diff --git a/openvidu-getaroom/web/index.html b/openvidu-getaroom/web/index.html
index 5c5018893..d96f87f2c 100644
--- a/openvidu-getaroom/web/index.html
+++ b/openvidu-getaroom/web/index.html
@@ -14,7 +14,7 @@
-
+
diff --git a/openvidu-getaroom/web/openvidu-browser-2.3.0.js b/openvidu-getaroom/web/openvidu-browser-2.3.0.js
deleted file mode 100644
index 83a78adcf..000000000
--- a/openvidu-getaroom/web/openvidu-browser-2.3.0.js
+++ /dev/null
@@ -1,7700 +0,0 @@
-(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 1)
- er = arguments[1];
- if (er instanceof Error) {
- throw er; // Unhandled 'error' event
- } else {
- // At least give some kind of context to the user
- var err = new Error('Unhandled "error" event. (' + er + ')');
- err.context = er;
- throw err;
- }
- return false;
- }
-
- handler = events[type];
-
- if (!handler)
- return false;
-
- var isFn = typeof handler === 'function';
- len = arguments.length;
- switch (len) {
- // fast cases
- case 1:
- emitNone(handler, isFn, this);
- break;
- case 2:
- emitOne(handler, isFn, this, arguments[1]);
- break;
- case 3:
- emitTwo(handler, isFn, this, arguments[1], arguments[2]);
- break;
- case 4:
- emitThree(handler, isFn, this, arguments[1], arguments[2], arguments[3]);
- break;
- // slower
- default:
- args = new Array(len - 1);
- for (i = 1; i < len; i++)
- args[i - 1] = arguments[i];
- emitMany(handler, isFn, this, args);
- }
-
- return true;
-};
-
-function _addListener(target, type, listener, prepend) {
- var m;
- var events;
- var existing;
-
- if (typeof listener !== 'function')
- throw new TypeError('"listener" argument must be a function');
-
- events = target._events;
- if (!events) {
- events = target._events = objectCreate(null);
- target._eventsCount = 0;
- } else {
- // To avoid recursion in the case that type === "newListener"! Before
- // adding it to the listeners, first emit "newListener".
- if (events.newListener) {
- target.emit('newListener', type,
- listener.listener ? listener.listener : listener);
-
- // Re-assign `events` because a newListener handler could have caused the
- // this._events to be assigned to a new object
- events = target._events;
- }
- existing = events[type];
- }
-
- if (!existing) {
- // Optimize the case of one listener. Don't need the extra array object.
- existing = events[type] = listener;
- ++target._eventsCount;
- } else {
- if (typeof existing === 'function') {
- // Adding the second element, need to change to array.
- existing = events[type] =
- prepend ? [listener, existing] : [existing, listener];
- } else {
- // If we've already got an array, just append.
- if (prepend) {
- existing.unshift(listener);
- } else {
- existing.push(listener);
- }
- }
-
- // Check for listener leak
- if (!existing.warned) {
- m = $getMaxListeners(target);
- if (m && m > 0 && existing.length > m) {
- existing.warned = true;
- var w = new Error('Possible EventEmitter memory leak detected. ' +
- existing.length + ' "' + String(type) + '" listeners ' +
- 'added. Use emitter.setMaxListeners() to ' +
- 'increase limit.');
- w.name = 'MaxListenersExceededWarning';
- w.emitter = target;
- w.type = type;
- w.count = existing.length;
- if (typeof console === 'object' && console.warn) {
- console.warn('%s: %s', w.name, w.message);
- }
- }
- }
- }
-
- return target;
-}
-
-EventEmitter.prototype.addListener = function addListener(type, listener) {
- return _addListener(this, type, listener, false);
-};
-
-EventEmitter.prototype.on = EventEmitter.prototype.addListener;
-
-EventEmitter.prototype.prependListener =
- function prependListener(type, listener) {
- return _addListener(this, type, listener, true);
- };
-
-function onceWrapper() {
- if (!this.fired) {
- this.target.removeListener(this.type, this.wrapFn);
- this.fired = true;
- switch (arguments.length) {
- case 0:
- return this.listener.call(this.target);
- case 1:
- return this.listener.call(this.target, arguments[0]);
- case 2:
- return this.listener.call(this.target, arguments[0], arguments[1]);
- case 3:
- return this.listener.call(this.target, arguments[0], arguments[1],
- arguments[2]);
- default:
- var args = new Array(arguments.length);
- for (var i = 0; i < args.length; ++i)
- args[i] = arguments[i];
- this.listener.apply(this.target, args);
- }
- }
-}
-
-function _onceWrap(target, type, listener) {
- var state = { fired: false, wrapFn: undefined, target: target, type: type, listener: listener };
- var wrapped = bind.call(onceWrapper, state);
- wrapped.listener = listener;
- state.wrapFn = wrapped;
- return wrapped;
-}
-
-EventEmitter.prototype.once = function once(type, listener) {
- if (typeof listener !== 'function')
- throw new TypeError('"listener" argument must be a function');
- this.on(type, _onceWrap(this, type, listener));
- return this;
-};
-
-EventEmitter.prototype.prependOnceListener =
- function prependOnceListener(type, listener) {
- if (typeof listener !== 'function')
- throw new TypeError('"listener" argument must be a function');
- this.prependListener(type, _onceWrap(this, type, listener));
- return this;
- };
-
-// Emits a 'removeListener' event if and only if the listener was removed.
-EventEmitter.prototype.removeListener =
- function removeListener(type, listener) {
- var list, events, position, i, originalListener;
-
- if (typeof listener !== 'function')
- throw new TypeError('"listener" argument must be a function');
-
- events = this._events;
- if (!events)
- return this;
-
- list = events[type];
- if (!list)
- return this;
-
- if (list === listener || list.listener === listener) {
- if (--this._eventsCount === 0)
- this._events = objectCreate(null);
- else {
- delete events[type];
- if (events.removeListener)
- this.emit('removeListener', type, list.listener || listener);
- }
- } else if (typeof list !== 'function') {
- position = -1;
-
- for (i = list.length - 1; i >= 0; i--) {
- if (list[i] === listener || list[i].listener === listener) {
- originalListener = list[i].listener;
- position = i;
- break;
- }
- }
-
- if (position < 0)
- return this;
-
- if (position === 0)
- list.shift();
- else
- spliceOne(list, position);
-
- if (list.length === 1)
- events[type] = list[0];
-
- if (events.removeListener)
- this.emit('removeListener', type, originalListener || listener);
- }
-
- return this;
- };
-
-EventEmitter.prototype.removeAllListeners =
- function removeAllListeners(type) {
- var listeners, events, i;
-
- events = this._events;
- if (!events)
- return this;
-
- // not listening for removeListener, no need to emit
- if (!events.removeListener) {
- if (arguments.length === 0) {
- this._events = objectCreate(null);
- this._eventsCount = 0;
- } else if (events[type]) {
- if (--this._eventsCount === 0)
- this._events = objectCreate(null);
- else
- delete events[type];
- }
- return this;
- }
-
- // emit removeListener for all listeners on all events
- if (arguments.length === 0) {
- var keys = objectKeys(events);
- var key;
- for (i = 0; i < keys.length; ++i) {
- key = keys[i];
- if (key === 'removeListener') continue;
- this.removeAllListeners(key);
- }
- this.removeAllListeners('removeListener');
- this._events = objectCreate(null);
- this._eventsCount = 0;
- return this;
- }
-
- listeners = events[type];
-
- if (typeof listeners === 'function') {
- this.removeListener(type, listeners);
- } else if (listeners) {
- // LIFO order
- for (i = listeners.length - 1; i >= 0; i--) {
- this.removeListener(type, listeners[i]);
- }
- }
-
- return this;
- };
-
-function _listeners(target, type, unwrap) {
- var events = target._events;
-
- if (!events)
- return [];
-
- var evlistener = events[type];
- if (!evlistener)
- return [];
-
- if (typeof evlistener === 'function')
- return unwrap ? [evlistener.listener || evlistener] : [evlistener];
-
- return unwrap ? unwrapListeners(evlistener) : arrayClone(evlistener, evlistener.length);
-}
-
-EventEmitter.prototype.listeners = function listeners(type) {
- return _listeners(this, type, true);
-};
-
-EventEmitter.prototype.rawListeners = function rawListeners(type) {
- return _listeners(this, type, false);
-};
-
-EventEmitter.listenerCount = function(emitter, type) {
- if (typeof emitter.listenerCount === 'function') {
- return emitter.listenerCount(type);
- } else {
- return listenerCount.call(emitter, type);
- }
-};
-
-EventEmitter.prototype.listenerCount = listenerCount;
-function listenerCount(type) {
- var events = this._events;
-
- if (events) {
- var evlistener = events[type];
-
- if (typeof evlistener === 'function') {
- return 1;
- } else if (evlistener) {
- return evlistener.length;
- }
- }
-
- return 0;
-}
-
-EventEmitter.prototype.eventNames = function eventNames() {
- return this._eventsCount > 0 ? Reflect.ownKeys(this._events) : [];
-};
-
-// About 1.5x faster than the two-arg version of Array#splice().
-function spliceOne(list, index) {
- for (var i = index, k = i + 1, n = list.length; k < n; i += 1, k += 1)
- list[i] = list[k];
- list.pop();
-}
-
-function arrayClone(arr, n) {
- var copy = new Array(n);
- for (var i = 0; i < n; ++i)
- copy[i] = arr[i];
- return copy;
-}
-
-function unwrapListeners(arr) {
- var ret = new Array(arr.length);
- for (var i = 0; i < ret.length; ++i) {
- ret[i] = arr[i].listener || arr[i];
- }
- return ret;
-}
-
-function objectCreatePolyfill(proto) {
- var F = function() {};
- F.prototype = proto;
- return new F;
-}
-function objectKeysPolyfill(obj) {
- var keys = [];
- for (var k in obj) if (Object.prototype.hasOwnProperty.call(obj, k)) {
- keys.push(k);
- }
- return k;
-}
-function functionBindPolyfill(context) {
- var fn = this;
- return function () {
- return fn.apply(context, arguments);
- };
-}
-
-},{}],2:[function(require,module,exports){
-/* jshint node: true */
-'use strict';
-
-var normalice = require('normalice');
-
-/**
- # freeice
-
- The `freeice` module is a simple way of getting random STUN or TURN server
- for your WebRTC application. The list of servers (just STUN at this stage)
- were sourced from this [gist](https://gist.github.com/zziuni/3741933).
-
- ## Example Use
-
- The following demonstrates how you can use `freeice` with
- [rtc-quickconnect](https://github.com/rtc-io/rtc-quickconnect):
-
- <<< examples/quickconnect.js
-
- As the `freeice` module generates ice servers in a list compliant with the
- WebRTC spec you will be able to use it with raw `RTCPeerConnection`
- constructors and other WebRTC libraries.
-
- ## Hey, don't use my STUN/TURN server!
-
- If for some reason your free STUN or TURN server ends up in the
- list of servers ([stun](https://github.com/DamonOehlman/freeice/blob/master/stun.json) or
- [turn](https://github.com/DamonOehlman/freeice/blob/master/turn.json))
- that is used in this module, you can feel
- free to open an issue on this repository and those servers will be removed
- within 24 hours (or sooner). This is the quickest and probably the most
- polite way to have something removed (and provides us some visibility
- if someone opens a pull request requesting that a server is added).
-
- ## Please add my server!
-
- If you have a server that you wish to add to the list, that's awesome! I'm
- sure I speak on behalf of a whole pile of WebRTC developers who say thanks.
- To get it into the list, feel free to either open a pull request or if you
- find that process a bit daunting then just create an issue requesting
- the addition of the server (make sure you provide all the details, and if
- you have a Terms of Service then including that in the PR/issue would be
- awesome).
-
- ## I know of a free server, can I add it?
-
- Sure, if you do your homework and make sure it is ok to use (I'm currently
- in the process of reviewing the terms of those STUN servers included from
- the original list). If it's ok to go, then please see the previous entry
- for how to add it.
-
- ## Current List of Servers
-
- * current as at the time of last `README.md` file generation
-
- ### STUN
-
- <<< stun.json
-
- ### TURN
-
- <<< turn.json
-
-**/
-
-var freeice = module.exports = function(opts) {
- // if a list of servers has been provided, then use it instead of defaults
- var servers = {
- stun: (opts || {}).stun || require('./stun.json'),
- turn: (opts || {}).turn || require('./turn.json')
- };
-
- var stunCount = (opts || {}).stunCount || 2;
- var turnCount = (opts || {}).turnCount || 0;
- var selected;
-
- function getServers(type, count) {
- var out = [];
- var input = [].concat(servers[type]);
- var idx;
-
- while (input.length && out.length < count) {
- idx = (Math.random() * input.length) | 0;
- out = out.concat(input.splice(idx, 1));
- }
-
- return out.map(function(url) {
- //If it's a not a string, don't try to "normalice" it otherwise using type:url will screw it up
- if ((typeof url !== 'string') && (! (url instanceof String))) {
- return url;
- } else {
- return normalice(type + ':' + url);
- }
- });
- }
-
- // add stun servers
- selected = [].concat(getServers('stun', stunCount));
-
- if (turnCount) {
- selected = selected.concat(getServers('turn', turnCount));
- }
-
- return selected;
-};
-
-},{"./stun.json":3,"./turn.json":4,"normalice":7}],3:[function(require,module,exports){
-module.exports=[
- "stun.l.google.com:19302",
- "stun1.l.google.com:19302",
- "stun2.l.google.com:19302",
- "stun3.l.google.com:19302",
- "stun4.l.google.com:19302",
- "stun.ekiga.net",
- "stun.ideasip.com",
- "stun.schlund.de",
- "stun.stunprotocol.org:3478",
- "stun.voiparound.com",
- "stun.voipbuster.com",
- "stun.voipstunt.com",
- "stun.voxgratia.org",
- "stun.services.mozilla.com"
-]
-
-},{}],4:[function(require,module,exports){
-module.exports=[]
-
-},{}],5:[function(require,module,exports){
-var WildEmitter = require('wildemitter');
-
-function getMaxVolume (analyser, fftBins) {
- var maxVolume = -Infinity;
- analyser.getFloatFrequencyData(fftBins);
-
- for(var i=4, ii=fftBins.length; i < ii; i++) {
- if (fftBins[i] > maxVolume && fftBins[i] < 0) {
- maxVolume = fftBins[i];
- }
- };
-
- return maxVolume;
-}
-
-
-var audioContextType;
-if (typeof window !== 'undefined') {
- audioContextType = window.AudioContext || window.webkitAudioContext;
-}
-// use a single audio context due to hardware limits
-var audioContext = null;
-module.exports = function(stream, options) {
- var harker = new WildEmitter();
-
-
- // make it not break in non-supported browsers
- if (!audioContextType) return harker;
-
- //Config
- var options = options || {},
- smoothing = (options.smoothing || 0.1),
- interval = (options.interval || 50),
- threshold = options.threshold,
- play = options.play,
- history = options.history || 10,
- running = true;
-
- //Setup Audio Context
- if (!audioContext) {
- audioContext = new audioContextType();
- }
- var sourceNode, fftBins, analyser;
-
- analyser = audioContext.createAnalyser();
- analyser.fftSize = 512;
- analyser.smoothingTimeConstant = smoothing;
- fftBins = new Float32Array(analyser.frequencyBinCount);
-
- if (stream.jquery) stream = stream[0];
- if (stream instanceof HTMLAudioElement || stream instanceof HTMLVideoElement) {
- //Audio Tag
- sourceNode = audioContext.createMediaElementSource(stream);
- if (typeof play === 'undefined') play = true;
- threshold = threshold || -50;
- } else {
- //WebRTC Stream
- sourceNode = audioContext.createMediaStreamSource(stream);
- threshold = threshold || -50;
- }
-
- sourceNode.connect(analyser);
- if (play) analyser.connect(audioContext.destination);
-
- harker.speaking = false;
-
- harker.suspend = function() {
- audioContext.suspend();
- }
- harker.resume = function() {
- audioContext.resume();
- }
- Object.defineProperty(harker, 'state', { get: function() {
- return audioContext.state;
- }});
- audioContext.onstatechange = function() {
- harker.emit('state_change', audioContext.state);
- }
-
- harker.setThreshold = function(t) {
- threshold = t;
- };
-
- harker.setInterval = function(i) {
- interval = i;
- };
-
- harker.stop = function() {
- running = false;
- harker.emit('volume_change', -100, threshold);
- if (harker.speaking) {
- harker.speaking = false;
- harker.emit('stopped_speaking');
- }
- analyser.disconnect();
- sourceNode.disconnect();
- };
- harker.speakingHistory = [];
- for (var i = 0; i < history; i++) {
- harker.speakingHistory.push(0);
- }
-
- // Poll the analyser node to determine if speaking
- // and emit events if changed
- var looper = function() {
- setTimeout(function() {
-
- //check if stop has been called
- if(!running) {
- return;
- }
-
- var currentVolume = getMaxVolume(analyser, fftBins);
-
- harker.emit('volume_change', currentVolume, threshold);
-
- var history = 0;
- if (currentVolume > threshold && !harker.speaking) {
- // trigger quickly, short history
- for (var i = harker.speakingHistory.length - 3; i < harker.speakingHistory.length; i++) {
- history += harker.speakingHistory[i];
- }
- if (history >= 2) {
- harker.speaking = true;
- harker.emit('speaking');
- }
- } else if (currentVolume < threshold && harker.speaking) {
- for (var i = 0; i < harker.speakingHistory.length; i++) {
- history += harker.speakingHistory[i];
- }
- if (history == 0) {
- harker.speaking = false;
- harker.emit('stopped_speaking');
- }
- }
- harker.speakingHistory.shift();
- harker.speakingHistory.push(0 + (currentVolume > threshold));
-
- looper();
- }, interval);
- };
- looper();
-
-
- return harker;
-}
-
-},{"wildemitter":14}],6:[function(require,module,exports){
-if (typeof Object.create === 'function') {
- // implementation from standard node.js 'util' module
- module.exports = function inherits(ctor, superCtor) {
- ctor.super_ = superCtor
- ctor.prototype = Object.create(superCtor.prototype, {
- constructor: {
- value: ctor,
- enumerable: false,
- writable: true,
- configurable: true
- }
- });
- };
-} else {
- // old school shim for old browsers
- module.exports = function inherits(ctor, superCtor) {
- ctor.super_ = superCtor
- var TempCtor = function () {}
- TempCtor.prototype = superCtor.prototype
- ctor.prototype = new TempCtor()
- ctor.prototype.constructor = ctor
- }
-}
-
-},{}],7:[function(require,module,exports){
-/**
- # normalice
-
- Normalize an ice server configuration object (or plain old string) into a format
- that is usable in all browsers supporting WebRTC. Primarily this module is designed
- to help with the transition of the `url` attribute of the configuration object to
- the `urls` attribute.
-
- ## Example Usage
-
- <<< examples/simple.js
-
-**/
-
-var protocols = [
- 'stun:',
- 'turn:'
-];
-
-module.exports = function(input) {
- var url = (input || {}).url || input;
- var protocol;
- var parts;
- var output = {};
-
- // if we don't have a string url, then allow the input to passthrough
- if (typeof url != 'string' && (! (url instanceof String))) {
- return input;
- }
-
- // trim the url string, and convert to an array
- url = url.trim();
-
- // if the protocol is not known, then passthrough
- protocol = protocols[protocols.indexOf(url.slice(0, 5))];
- if (! protocol) {
- return input;
- }
-
- // now let's attack the remaining url parts
- url = url.slice(5);
- parts = url.split('@');
-
- output.username = input.username;
- output.credential = input.credential;
- // if we have an authentication part, then set the credentials
- if (parts.length > 1) {
- url = parts[1];
- parts = parts[0].split(':');
-
- // add the output credential and username
- output.username = parts[0];
- output.credential = (input || {}).credential || parts[1] || '';
- }
-
- output.url = protocol + url;
- output.urls = [ output.url ];
-
- return output;
-};
-
-},{}],8:[function(require,module,exports){
-(function (global){
-/*!
- * Platform.js
- * Copyright 2014-2018 Benjamin Tan
- * Copyright 2011-2013 John-David Dalton
- * Available under MIT license
- */
-;(function() {
- 'use strict';
-
- /** Used to determine if values are of the language type `Object`. */
- var objectTypes = {
- 'function': true,
- 'object': true
- };
-
- /** Used as a reference to the global object. */
- var root = (objectTypes[typeof window] && window) || this;
-
- /** Backup possible global object. */
- var oldRoot = root;
-
- /** Detect free variable `exports`. */
- var freeExports = objectTypes[typeof exports] && exports;
-
- /** Detect free variable `module`. */
- var freeModule = objectTypes[typeof module] && module && !module.nodeType && module;
-
- /** Detect free variable `global` from Node.js or Browserified code and use it as `root`. */
- var freeGlobal = freeExports && freeModule && typeof global == 'object' && global;
- if (freeGlobal && (freeGlobal.global === freeGlobal || freeGlobal.window === freeGlobal || freeGlobal.self === freeGlobal)) {
- root = freeGlobal;
- }
-
- /**
- * Used as the maximum length of an array-like object.
- * See the [ES6 spec](http://people.mozilla.org/~jorendorff/es6-draft.html#sec-tolength)
- * for more details.
- */
- var maxSafeInteger = Math.pow(2, 53) - 1;
-
- /** Regular expression to detect Opera. */
- var reOpera = /\bOpera/;
-
- /** Possible global object. */
- var thisBinding = this;
-
- /** Used for native method references. */
- var objectProto = Object.prototype;
-
- /** Used to check for own properties of an object. */
- var hasOwnProperty = objectProto.hasOwnProperty;
-
- /** Used to resolve the internal `[[Class]]` of values. */
- var toString = objectProto.toString;
-
- /*--------------------------------------------------------------------------*/
-
- /**
- * Capitalizes a string value.
- *
- * @private
- * @param {string} string The string to capitalize.
- * @returns {string} The capitalized string.
- */
- function capitalize(string) {
- string = String(string);
- return string.charAt(0).toUpperCase() + string.slice(1);
- }
-
- /**
- * A utility function to clean up the OS name.
- *
- * @private
- * @param {string} os The OS name to clean up.
- * @param {string} [pattern] A `RegExp` pattern matching the OS name.
- * @param {string} [label] A label for the OS.
- */
- function cleanupOS(os, pattern, label) {
- // Platform tokens are defined at:
- // http://msdn.microsoft.com/en-us/library/ms537503(VS.85).aspx
- // http://web.archive.org/web/20081122053950/http://msdn.microsoft.com/en-us/library/ms537503(VS.85).aspx
- var data = {
- '10.0': '10',
- '6.4': '10 Technical Preview',
- '6.3': '8.1',
- '6.2': '8',
- '6.1': 'Server 2008 R2 / 7',
- '6.0': 'Server 2008 / Vista',
- '5.2': 'Server 2003 / XP 64-bit',
- '5.1': 'XP',
- '5.01': '2000 SP1',
- '5.0': '2000',
- '4.0': 'NT',
- '4.90': 'ME'
- };
- // Detect Windows version from platform tokens.
- if (pattern && label && /^Win/i.test(os) && !/^Windows Phone /i.test(os) &&
- (data = data[/[\d.]+$/.exec(os)])) {
- os = 'Windows ' + data;
- }
- // Correct character case and cleanup string.
- os = String(os);
-
- if (pattern && label) {
- os = os.replace(RegExp(pattern, 'i'), label);
- }
-
- os = format(
- os.replace(/ ce$/i, ' CE')
- .replace(/\bhpw/i, 'web')
- .replace(/\bMacintosh\b/, 'Mac OS')
- .replace(/_PowerPC\b/i, ' OS')
- .replace(/\b(OS X) [^ \d]+/i, '$1')
- .replace(/\bMac (OS X)\b/, '$1')
- .replace(/\/(\d)/, ' $1')
- .replace(/_/g, '.')
- .replace(/(?: BePC|[ .]*fc[ \d.]+)$/i, '')
- .replace(/\bx86\.64\b/gi, 'x86_64')
- .replace(/\b(Windows Phone) OS\b/, '$1')
- .replace(/\b(Chrome OS \w+) [\d.]+\b/, '$1')
- .split(' on ')[0]
- );
-
- return os;
- }
-
- /**
- * An iteration utility for arrays and objects.
- *
- * @private
- * @param {Array|Object} object The object to iterate over.
- * @param {Function} callback The function called per iteration.
- */
- function each(object, callback) {
- var index = -1,
- length = object ? object.length : 0;
-
- if (typeof length == 'number' && length > -1 && length <= maxSafeInteger) {
- while (++index < length) {
- callback(object[index], index, object);
- }
- } else {
- forOwn(object, callback);
- }
- }
-
- /**
- * Trim and conditionally capitalize string values.
- *
- * @private
- * @param {string} string The string to format.
- * @returns {string} The formatted string.
- */
- function format(string) {
- string = trim(string);
- return /^(?:webOS|i(?:OS|P))/.test(string)
- ? string
- : capitalize(string);
- }
-
- /**
- * Iterates over an object's own properties, executing the `callback` for each.
- *
- * @private
- * @param {Object} object The object to iterate over.
- * @param {Function} callback The function executed per own property.
- */
- function forOwn(object, callback) {
- for (var key in object) {
- if (hasOwnProperty.call(object, key)) {
- callback(object[key], key, object);
- }
- }
- }
-
- /**
- * Gets the internal `[[Class]]` of a value.
- *
- * @private
- * @param {*} value The value.
- * @returns {string} The `[[Class]]`.
- */
- function getClassOf(value) {
- return value == null
- ? capitalize(value)
- : toString.call(value).slice(8, -1);
- }
-
- /**
- * Host objects can return type values that are different from their actual
- * data type. The objects we are concerned with usually return non-primitive
- * types of "object", "function", or "unknown".
- *
- * @private
- * @param {*} object The owner of the property.
- * @param {string} property The property to check.
- * @returns {boolean} Returns `true` if the property value is a non-primitive, else `false`.
- */
- function isHostType(object, property) {
- var type = object != null ? typeof object[property] : 'number';
- return !/^(?:boolean|number|string|undefined)$/.test(type) &&
- (type == 'object' ? !!object[property] : true);
- }
-
- /**
- * Prepares a string for use in a `RegExp` by making hyphens and spaces optional.
- *
- * @private
- * @param {string} string The string to qualify.
- * @returns {string} The qualified string.
- */
- function qualify(string) {
- return String(string).replace(/([ -])(?!$)/g, '$1?');
- }
-
- /**
- * A bare-bones `Array#reduce` like utility function.
- *
- * @private
- * @param {Array} array The array to iterate over.
- * @param {Function} callback The function called per iteration.
- * @returns {*} The accumulated result.
- */
- function reduce(array, callback) {
- var accumulator = null;
- each(array, function(value, index) {
- accumulator = callback(accumulator, value, index, array);
- });
- return accumulator;
- }
-
- /**
- * Removes leading and trailing whitespace from a string.
- *
- * @private
- * @param {string} string The string to trim.
- * @returns {string} The trimmed string.
- */
- function trim(string) {
- return String(string).replace(/^ +| +$/g, '');
- }
-
- /*--------------------------------------------------------------------------*/
-
- /**
- * Creates a new platform object.
- *
- * @memberOf platform
- * @param {Object|string} [ua=navigator.userAgent] The user agent string or
- * context object.
- * @returns {Object} A platform object.
- */
- function parse(ua) {
-
- /** The environment context object. */
- var context = root;
-
- /** Used to flag when a custom context is provided. */
- var isCustomContext = ua && typeof ua == 'object' && getClassOf(ua) != 'String';
-
- // Juggle arguments.
- if (isCustomContext) {
- context = ua;
- ua = null;
- }
-
- /** Browser navigator object. */
- var nav = context.navigator || {};
-
- /** Browser user agent string. */
- var userAgent = nav.userAgent || '';
-
- ua || (ua = userAgent);
-
- /** Used to flag when `thisBinding` is the [ModuleScope]. */
- var isModuleScope = isCustomContext || thisBinding == oldRoot;
-
- /** Used to detect if browser is like Chrome. */
- var likeChrome = isCustomContext
- ? !!nav.likeChrome
- : /\bChrome\b/.test(ua) && !/internal|\n/i.test(toString.toString());
-
- /** Internal `[[Class]]` value shortcuts. */
- var objectClass = 'Object',
- airRuntimeClass = isCustomContext ? objectClass : 'ScriptBridgingProxyObject',
- enviroClass = isCustomContext ? objectClass : 'Environment',
- javaClass = (isCustomContext && context.java) ? 'JavaPackage' : getClassOf(context.java),
- phantomClass = isCustomContext ? objectClass : 'RuntimeObject';
-
- /** Detect Java environments. */
- var java = /\bJava/.test(javaClass) && context.java;
-
- /** Detect Rhino. */
- var rhino = java && getClassOf(context.environment) == enviroClass;
-
- /** A character to represent alpha. */
- var alpha = java ? 'a' : '\u03b1';
-
- /** A character to represent beta. */
- var beta = java ? 'b' : '\u03b2';
-
- /** Browser document object. */
- var doc = context.document || {};
-
- /**
- * Detect Opera browser (Presto-based).
- * http://www.howtocreate.co.uk/operaStuff/operaObject.html
- * http://dev.opera.com/articles/view/opera-mini-web-content-authoring-guidelines/#operamini
- */
- var opera = context.operamini || context.opera;
-
- /** Opera `[[Class]]`. */
- var operaClass = reOpera.test(operaClass = (isCustomContext && opera) ? opera['[[Class]]'] : getClassOf(opera))
- ? operaClass
- : (opera = null);
-
- /*------------------------------------------------------------------------*/
-
- /** Temporary variable used over the script's lifetime. */
- var data;
-
- /** The CPU architecture. */
- var arch = ua;
-
- /** Platform description array. */
- var description = [];
-
- /** Platform alpha/beta indicator. */
- var prerelease = null;
-
- /** A flag to indicate that environment features should be used to resolve the platform. */
- var useFeatures = ua == userAgent;
-
- /** The browser/environment version. */
- var version = useFeatures && opera && typeof opera.version == 'function' && opera.version();
-
- /** A flag to indicate if the OS ends with "/ Version" */
- var isSpecialCasedOS;
-
- /* Detectable layout engines (order is important). */
- var layout = getLayout([
- { 'label': 'EdgeHTML', 'pattern': 'Edge' },
- 'Trident',
- { 'label': 'WebKit', 'pattern': 'AppleWebKit' },
- 'iCab',
- 'Presto',
- 'NetFront',
- 'Tasman',
- 'KHTML',
- 'Gecko'
- ]);
-
- /* Detectable browser names (order is important). */
- var name = getName([
- 'Adobe AIR',
- 'Arora',
- 'Avant Browser',
- 'Breach',
- 'Camino',
- 'Electron',
- 'Epiphany',
- 'Fennec',
- 'Flock',
- 'Galeon',
- 'GreenBrowser',
- 'iCab',
- 'Iceweasel',
- 'K-Meleon',
- 'Konqueror',
- 'Lunascape',
- 'Maxthon',
- { 'label': 'Microsoft Edge', 'pattern': 'Edge' },
- 'Midori',
- 'Nook Browser',
- 'PaleMoon',
- 'PhantomJS',
- 'Raven',
- 'Rekonq',
- 'RockMelt',
- { 'label': 'Samsung Internet', 'pattern': 'SamsungBrowser' },
- 'SeaMonkey',
- { 'label': 'Silk', 'pattern': '(?:Cloud9|Silk-Accelerated)' },
- 'Sleipnir',
- 'SlimBrowser',
- { 'label': 'SRWare Iron', 'pattern': 'Iron' },
- 'Sunrise',
- 'Swiftfox',
- 'Waterfox',
- 'WebPositive',
- 'Opera Mini',
- { 'label': 'Opera Mini', 'pattern': 'OPiOS' },
- 'Opera',
- { 'label': 'Opera', 'pattern': 'OPR' },
- 'Chrome',
- { 'label': 'Chrome Mobile', 'pattern': '(?:CriOS|CrMo)' },
- { 'label': 'Firefox', 'pattern': '(?:Firefox|Minefield)' },
- { 'label': 'Firefox for iOS', 'pattern': 'FxiOS' },
- { 'label': 'IE', 'pattern': 'IEMobile' },
- { 'label': 'IE', 'pattern': 'MSIE' },
- 'Safari'
- ]);
-
- /* Detectable products (order is important). */
- var product = getProduct([
- { 'label': 'BlackBerry', 'pattern': 'BB10' },
- 'BlackBerry',
- { 'label': 'Galaxy S', 'pattern': 'GT-I9000' },
- { 'label': 'Galaxy S2', 'pattern': 'GT-I9100' },
- { 'label': 'Galaxy S3', 'pattern': 'GT-I9300' },
- { 'label': 'Galaxy S4', 'pattern': 'GT-I9500' },
- { 'label': 'Galaxy S5', 'pattern': 'SM-G900' },
- { 'label': 'Galaxy S6', 'pattern': 'SM-G920' },
- { 'label': 'Galaxy S6 Edge', 'pattern': 'SM-G925' },
- { 'label': 'Galaxy S7', 'pattern': 'SM-G930' },
- { 'label': 'Galaxy S7 Edge', 'pattern': 'SM-G935' },
- 'Google TV',
- 'Lumia',
- 'iPad',
- 'iPod',
- 'iPhone',
- 'Kindle',
- { 'label': 'Kindle Fire', 'pattern': '(?:Cloud9|Silk-Accelerated)' },
- 'Nexus',
- 'Nook',
- 'PlayBook',
- 'PlayStation Vita',
- 'PlayStation',
- 'TouchPad',
- 'Transformer',
- { 'label': 'Wii U', 'pattern': 'WiiU' },
- 'Wii',
- 'Xbox One',
- { 'label': 'Xbox 360', 'pattern': 'Xbox' },
- 'Xoom'
- ]);
-
- /* Detectable manufacturers. */
- var manufacturer = getManufacturer({
- 'Apple': { 'iPad': 1, 'iPhone': 1, 'iPod': 1 },
- 'Archos': {},
- 'Amazon': { 'Kindle': 1, 'Kindle Fire': 1 },
- 'Asus': { 'Transformer': 1 },
- 'Barnes & Noble': { 'Nook': 1 },
- 'BlackBerry': { 'PlayBook': 1 },
- 'Google': { 'Google TV': 1, 'Nexus': 1 },
- 'HP': { 'TouchPad': 1 },
- 'HTC': {},
- 'LG': {},
- 'Microsoft': { 'Xbox': 1, 'Xbox One': 1 },
- 'Motorola': { 'Xoom': 1 },
- 'Nintendo': { 'Wii U': 1, 'Wii': 1 },
- 'Nokia': { 'Lumia': 1 },
- 'Samsung': { 'Galaxy S': 1, 'Galaxy S2': 1, 'Galaxy S3': 1, 'Galaxy S4': 1 },
- 'Sony': { 'PlayStation': 1, 'PlayStation Vita': 1 }
- });
-
- /* Detectable operating systems (order is important). */
- var os = getOS([
- 'Windows Phone',
- 'Android',
- 'CentOS',
- { 'label': 'Chrome OS', 'pattern': 'CrOS' },
- 'Debian',
- 'Fedora',
- 'FreeBSD',
- 'Gentoo',
- 'Haiku',
- 'Kubuntu',
- 'Linux Mint',
- 'OpenBSD',
- 'Red Hat',
- 'SuSE',
- 'Ubuntu',
- 'Xubuntu',
- 'Cygwin',
- 'Symbian OS',
- 'hpwOS',
- 'webOS ',
- 'webOS',
- 'Tablet OS',
- 'Tizen',
- 'Linux',
- 'Mac OS X',
- 'Macintosh',
- 'Mac',
- 'Windows 98;',
- 'Windows '
- ]);
-
- /*------------------------------------------------------------------------*/
-
- /**
- * Picks the layout engine from an array of guesses.
- *
- * @private
- * @param {Array} guesses An array of guesses.
- * @returns {null|string} The detected layout engine.
- */
- function getLayout(guesses) {
- return reduce(guesses, function(result, guess) {
- return result || RegExp('\\b' + (
- guess.pattern || qualify(guess)
- ) + '\\b', 'i').exec(ua) && (guess.label || guess);
- });
- }
-
- /**
- * Picks the manufacturer from an array of guesses.
- *
- * @private
- * @param {Array} guesses An object of guesses.
- * @returns {null|string} The detected manufacturer.
- */
- function getManufacturer(guesses) {
- return reduce(guesses, function(result, value, key) {
- // Lookup the manufacturer by product or scan the UA for the manufacturer.
- return result || (
- value[product] ||
- value[/^[a-z]+(?: +[a-z]+\b)*/i.exec(product)] ||
- RegExp('\\b' + qualify(key) + '(?:\\b|\\w*\\d)', 'i').exec(ua)
- ) && key;
- });
- }
-
- /**
- * Picks the browser name from an array of guesses.
- *
- * @private
- * @param {Array} guesses An array of guesses.
- * @returns {null|string} The detected browser name.
- */
- function getName(guesses) {
- return reduce(guesses, function(result, guess) {
- return result || RegExp('\\b' + (
- guess.pattern || qualify(guess)
- ) + '\\b', 'i').exec(ua) && (guess.label || guess);
- });
- }
-
- /**
- * Picks the OS name from an array of guesses.
- *
- * @private
- * @param {Array} guesses An array of guesses.
- * @returns {null|string} The detected OS name.
- */
- function getOS(guesses) {
- return reduce(guesses, function(result, guess) {
- var pattern = guess.pattern || qualify(guess);
- if (!result && (result =
- RegExp('\\b' + pattern + '(?:/[\\d.]+|[ \\w.]*)', 'i').exec(ua)
- )) {
- result = cleanupOS(result, pattern, guess.label || guess);
- }
- return result;
- });
- }
-
- /**
- * Picks the product name from an array of guesses.
- *
- * @private
- * @param {Array} guesses An array of guesses.
- * @returns {null|string} The detected product name.
- */
- function getProduct(guesses) {
- return reduce(guesses, function(result, guess) {
- var pattern = guess.pattern || qualify(guess);
- if (!result && (result =
- RegExp('\\b' + pattern + ' *\\d+[.\\w_]*', 'i').exec(ua) ||
- RegExp('\\b' + pattern + ' *\\w+-[\\w]*', 'i').exec(ua) ||
- RegExp('\\b' + pattern + '(?:; *(?:[a-z]+[_-])?[a-z]+\\d+|[^ ();-]*)', 'i').exec(ua)
- )) {
- // Split by forward slash and append product version if needed.
- if ((result = String((guess.label && !RegExp(pattern, 'i').test(guess.label)) ? guess.label : result).split('/'))[1] && !/[\d.]+/.test(result[0])) {
- result[0] += ' ' + result[1];
- }
- // Correct character case and cleanup string.
- guess = guess.label || guess;
- result = format(result[0]
- .replace(RegExp(pattern, 'i'), guess)
- .replace(RegExp('; *(?:' + guess + '[_-])?', 'i'), ' ')
- .replace(RegExp('(' + guess + ')[-_.]?(\\w)', 'i'), '$1 $2'));
- }
- return result;
- });
- }
-
- /**
- * Resolves the version using an array of UA patterns.
- *
- * @private
- * @param {Array} patterns An array of UA patterns.
- * @returns {null|string} The detected version.
- */
- function getVersion(patterns) {
- return reduce(patterns, function(result, pattern) {
- return result || (RegExp(pattern +
- '(?:-[\\d.]+/|(?: for [\\w-]+)?[ /-])([\\d.]+[^ ();/_-]*)', 'i').exec(ua) || 0)[1] || null;
- });
- }
-
- /**
- * Returns `platform.description` when the platform object is coerced to a string.
- *
- * @name toString
- * @memberOf platform
- * @returns {string} Returns `platform.description` if available, else an empty string.
- */
- function toStringPlatform() {
- return this.description || '';
- }
-
- /*------------------------------------------------------------------------*/
-
- // Convert layout to an array so we can add extra details.
- layout && (layout = [layout]);
-
- // Detect product names that contain their manufacturer's name.
- if (manufacturer && !product) {
- product = getProduct([manufacturer]);
- }
- // Clean up Google TV.
- if ((data = /\bGoogle TV\b/.exec(product))) {
- product = data[0];
- }
- // Detect simulators.
- if (/\bSimulator\b/i.test(ua)) {
- product = (product ? product + ' ' : '') + 'Simulator';
- }
- // Detect Opera Mini 8+ running in Turbo/Uncompressed mode on iOS.
- if (name == 'Opera Mini' && /\bOPiOS\b/.test(ua)) {
- description.push('running in Turbo/Uncompressed mode');
- }
- // Detect IE Mobile 11.
- if (name == 'IE' && /\blike iPhone OS\b/.test(ua)) {
- data = parse(ua.replace(/like iPhone OS/, ''));
- manufacturer = data.manufacturer;
- product = data.product;
- }
- // Detect iOS.
- else if (/^iP/.test(product)) {
- name || (name = 'Safari');
- os = 'iOS' + ((data = / OS ([\d_]+)/i.exec(ua))
- ? ' ' + data[1].replace(/_/g, '.')
- : '');
- }
- // Detect Kubuntu.
- else if (name == 'Konqueror' && !/buntu/i.test(os)) {
- os = 'Kubuntu';
- }
- // Detect Android browsers.
- else if ((manufacturer && manufacturer != 'Google' &&
- ((/Chrome/.test(name) && !/\bMobile Safari\b/i.test(ua)) || /\bVita\b/.test(product))) ||
- (/\bAndroid\b/.test(os) && /^Chrome/.test(name) && /\bVersion\//i.test(ua))) {
- name = 'Android Browser';
- os = /\bAndroid\b/.test(os) ? os : 'Android';
- }
- // Detect Silk desktop/accelerated modes.
- else if (name == 'Silk') {
- if (!/\bMobi/i.test(ua)) {
- os = 'Android';
- description.unshift('desktop mode');
- }
- if (/Accelerated *= *true/i.test(ua)) {
- description.unshift('accelerated');
- }
- }
- // Detect PaleMoon identifying as Firefox.
- else if (name == 'PaleMoon' && (data = /\bFirefox\/([\d.]+)\b/.exec(ua))) {
- description.push('identifying as Firefox ' + data[1]);
- }
- // Detect Firefox OS and products running Firefox.
- else if (name == 'Firefox' && (data = /\b(Mobile|Tablet|TV)\b/i.exec(ua))) {
- os || (os = 'Firefox OS');
- product || (product = data[1]);
- }
- // Detect false positives for Firefox/Safari.
- else if (!name || (data = !/\bMinefield\b/i.test(ua) && /\b(?:Firefox|Safari)\b/.exec(name))) {
- // Escape the `/` for Firefox 1.
- if (name && !product && /[\/,]|^[^(]+?\)/.test(ua.slice(ua.indexOf(data + '/') + 8))) {
- // Clear name of false positives.
- name = null;
- }
- // Reassign a generic name.
- if ((data = product || manufacturer || os) &&
- (product || manufacturer || /\b(?:Android|Symbian OS|Tablet OS|webOS)\b/.test(os))) {
- name = /[a-z]+(?: Hat)?/i.exec(/\bAndroid\b/.test(os) ? os : data) + ' Browser';
- }
- }
- // Add Chrome version to description for Electron.
- else if (name == 'Electron' && (data = (/\bChrome\/([\d.]+)\b/.exec(ua) || 0)[1])) {
- description.push('Chromium ' + data);
- }
- // Detect non-Opera (Presto-based) versions (order is important).
- if (!version) {
- version = getVersion([
- '(?:Cloud9|CriOS|CrMo|Edge|FxiOS|IEMobile|Iron|Opera ?Mini|OPiOS|OPR|Raven|SamsungBrowser|Silk(?!/[\\d.]+$))',
- 'Version',
- qualify(name),
- '(?:Firefox|Minefield|NetFront)'
- ]);
- }
- // Detect stubborn layout engines.
- if ((data =
- layout == 'iCab' && parseFloat(version) > 3 && 'WebKit' ||
- /\bOpera\b/.test(name) && (/\bOPR\b/.test(ua) ? 'Blink' : 'Presto') ||
- /\b(?:Midori|Nook|Safari)\b/i.test(ua) && !/^(?:Trident|EdgeHTML)$/.test(layout) && 'WebKit' ||
- !layout && /\bMSIE\b/i.test(ua) && (os == 'Mac OS' ? 'Tasman' : 'Trident') ||
- layout == 'WebKit' && /\bPlayStation\b(?! Vita\b)/i.test(name) && 'NetFront'
- )) {
- layout = [data];
- }
- // Detect Windows Phone 7 desktop mode.
- if (name == 'IE' && (data = (/; *(?:XBLWP|ZuneWP)(\d+)/i.exec(ua) || 0)[1])) {
- name += ' Mobile';
- os = 'Windows Phone ' + (/\+$/.test(data) ? data : data + '.x');
- description.unshift('desktop mode');
- }
- // Detect Windows Phone 8.x desktop mode.
- else if (/\bWPDesktop\b/i.test(ua)) {
- name = 'IE Mobile';
- os = 'Windows Phone 8.x';
- description.unshift('desktop mode');
- version || (version = (/\brv:([\d.]+)/.exec(ua) || 0)[1]);
- }
- // Detect IE 11 identifying as other browsers.
- else if (name != 'IE' && layout == 'Trident' && (data = /\brv:([\d.]+)/.exec(ua))) {
- if (name) {
- description.push('identifying as ' + name + (version ? ' ' + version : ''));
- }
- name = 'IE';
- version = data[1];
- }
- // Leverage environment features.
- if (useFeatures) {
- // Detect server-side environments.
- // Rhino has a global function while others have a global object.
- if (isHostType(context, 'global')) {
- if (java) {
- data = java.lang.System;
- arch = data.getProperty('os.arch');
- os = os || data.getProperty('os.name') + ' ' + data.getProperty('os.version');
- }
- if (rhino) {
- try {
- version = context.require('ringo/engine').version.join('.');
- name = 'RingoJS';
- } catch(e) {
- if ((data = context.system) && data.global.system == context.system) {
- name = 'Narwhal';
- os || (os = data[0].os || null);
- }
- }
- if (!name) {
- name = 'Rhino';
- }
- }
- else if (
- typeof context.process == 'object' && !context.process.browser &&
- (data = context.process)
- ) {
- if (typeof data.versions == 'object') {
- if (typeof data.versions.electron == 'string') {
- description.push('Node ' + data.versions.node);
- name = 'Electron';
- version = data.versions.electron;
- } else if (typeof data.versions.nw == 'string') {
- description.push('Chromium ' + version, 'Node ' + data.versions.node);
- name = 'NW.js';
- version = data.versions.nw;
- }
- }
- if (!name) {
- name = 'Node.js';
- arch = data.arch;
- os = data.platform;
- version = /[\d.]+/.exec(data.version);
- version = version ? version[0] : null;
- }
- }
- }
- // Detect Adobe AIR.
- else if (getClassOf((data = context.runtime)) == airRuntimeClass) {
- name = 'Adobe AIR';
- os = data.flash.system.Capabilities.os;
- }
- // Detect PhantomJS.
- else if (getClassOf((data = context.phantom)) == phantomClass) {
- name = 'PhantomJS';
- version = (data = data.version || null) && (data.major + '.' + data.minor + '.' + data.patch);
- }
- // Detect IE compatibility modes.
- else if (typeof doc.documentMode == 'number' && (data = /\bTrident\/(\d+)/i.exec(ua))) {
- // We're in compatibility mode when the Trident version + 4 doesn't
- // equal the document mode.
- version = [version, doc.documentMode];
- if ((data = +data[1] + 4) != version[1]) {
- description.push('IE ' + version[1] + ' mode');
- layout && (layout[1] = '');
- version[1] = data;
- }
- version = name == 'IE' ? String(version[1].toFixed(1)) : version[0];
- }
- // Detect IE 11 masking as other browsers.
- else if (typeof doc.documentMode == 'number' && /^(?:Chrome|Firefox)\b/.test(name)) {
- description.push('masking as ' + name + ' ' + version);
- name = 'IE';
- version = '11.0';
- layout = ['Trident'];
- os = 'Windows';
- }
- os = os && format(os);
- }
- // Detect prerelease phases.
- if (version && (data =
- /(?:[ab]|dp|pre|[ab]\d+pre)(?:\d+\+?)?$/i.exec(version) ||
- /(?:alpha|beta)(?: ?\d)?/i.exec(ua + ';' + (useFeatures && nav.appMinorVersion)) ||
- /\bMinefield\b/i.test(ua) && 'a'
- )) {
- prerelease = /b/i.test(data) ? 'beta' : 'alpha';
- version = version.replace(RegExp(data + '\\+?$'), '') +
- (prerelease == 'beta' ? beta : alpha) + (/\d+\+?/.exec(data) || '');
- }
- // Detect Firefox Mobile.
- if (name == 'Fennec' || name == 'Firefox' && /\b(?:Android|Firefox OS)\b/.test(os)) {
- name = 'Firefox Mobile';
- }
- // Obscure Maxthon's unreliable version.
- else if (name == 'Maxthon' && version) {
- version = version.replace(/\.[\d.]+/, '.x');
- }
- // Detect Xbox 360 and Xbox One.
- else if (/\bXbox\b/i.test(product)) {
- if (product == 'Xbox 360') {
- os = null;
- }
- if (product == 'Xbox 360' && /\bIEMobile\b/.test(ua)) {
- description.unshift('mobile mode');
- }
- }
- // Add mobile postfix.
- else if ((/^(?:Chrome|IE|Opera)$/.test(name) || name && !product && !/Browser|Mobi/.test(name)) &&
- (os == 'Windows CE' || /Mobi/i.test(ua))) {
- name += ' Mobile';
- }
- // Detect IE platform preview.
- else if (name == 'IE' && useFeatures) {
- try {
- if (context.external === null) {
- description.unshift('platform preview');
- }
- } catch(e) {
- description.unshift('embedded');
- }
- }
- // Detect BlackBerry OS version.
- // http://docs.blackberry.com/en/developers/deliverables/18169/HTTP_headers_sent_by_BB_Browser_1234911_11.jsp
- else if ((/\bBlackBerry\b/.test(product) || /\bBB10\b/.test(ua)) && (data =
- (RegExp(product.replace(/ +/g, ' *') + '/([.\\d]+)', 'i').exec(ua) || 0)[1] ||
- version
- )) {
- data = [data, /BB10/.test(ua)];
- os = (data[1] ? (product = null, manufacturer = 'BlackBerry') : 'Device Software') + ' ' + data[0];
- version = null;
- }
- // Detect Opera identifying/masking itself as another browser.
- // http://www.opera.com/support/kb/view/843/
- else if (this != forOwn && product != 'Wii' && (
- (useFeatures && opera) ||
- (/Opera/.test(name) && /\b(?:MSIE|Firefox)\b/i.test(ua)) ||
- (name == 'Firefox' && /\bOS X (?:\d+\.){2,}/.test(os)) ||
- (name == 'IE' && (
- (os && !/^Win/.test(os) && version > 5.5) ||
- /\bWindows XP\b/.test(os) && version > 8 ||
- version == 8 && !/\bTrident\b/.test(ua)
- ))
- ) && !reOpera.test((data = parse.call(forOwn, ua.replace(reOpera, '') + ';'))) && data.name) {
- // When "identifying", the UA contains both Opera and the other browser's name.
- data = 'ing as ' + data.name + ((data = data.version) ? ' ' + data : '');
- if (reOpera.test(name)) {
- if (/\bIE\b/.test(data) && os == 'Mac OS') {
- os = null;
- }
- data = 'identify' + data;
- }
- // When "masking", the UA contains only the other browser's name.
- else {
- data = 'mask' + data;
- if (operaClass) {
- name = format(operaClass.replace(/([a-z])([A-Z])/g, '$1 $2'));
- } else {
- name = 'Opera';
- }
- if (/\bIE\b/.test(data)) {
- os = null;
- }
- if (!useFeatures) {
- version = null;
- }
- }
- layout = ['Presto'];
- description.push(data);
- }
- // Detect WebKit Nightly and approximate Chrome/Safari versions.
- if ((data = (/\bAppleWebKit\/([\d.]+\+?)/i.exec(ua) || 0)[1])) {
- // Correct build number for numeric comparison.
- // (e.g. "532.5" becomes "532.05")
- data = [parseFloat(data.replace(/\.(\d)$/, '.0$1')), data];
- // Nightly builds are postfixed with a "+".
- if (name == 'Safari' && data[1].slice(-1) == '+') {
- name = 'WebKit Nightly';
- prerelease = 'alpha';
- version = data[1].slice(0, -1);
- }
- // Clear incorrect browser versions.
- else if (version == data[1] ||
- version == (data[2] = (/\bSafari\/([\d.]+\+?)/i.exec(ua) || 0)[1])) {
- version = null;
- }
- // Use the full Chrome version when available.
- data[1] = (/\bChrome\/([\d.]+)/i.exec(ua) || 0)[1];
- // Detect Blink layout engine.
- if (data[0] == 537.36 && data[2] == 537.36 && parseFloat(data[1]) >= 28 && layout == 'WebKit') {
- layout = ['Blink'];
- }
- // Detect JavaScriptCore.
- // http://stackoverflow.com/questions/6768474/how-can-i-detect-which-javascript-engine-v8-or-jsc-is-used-at-runtime-in-androi
- if (!useFeatures || (!likeChrome && !data[1])) {
- layout && (layout[1] = 'like Safari');
- data = (data = data[0], data < 400 ? 1 : data < 500 ? 2 : data < 526 ? 3 : data < 533 ? 4 : data < 534 ? '4+' : data < 535 ? 5 : data < 537 ? 6 : data < 538 ? 7 : data < 601 ? 8 : '8');
- } else {
- layout && (layout[1] = 'like Chrome');
- data = data[1] || (data = data[0], data < 530 ? 1 : data < 532 ? 2 : data < 532.05 ? 3 : data < 533 ? 4 : data < 534.03 ? 5 : data < 534.07 ? 6 : data < 534.10 ? 7 : data < 534.13 ? 8 : data < 534.16 ? 9 : data < 534.24 ? 10 : data < 534.30 ? 11 : data < 535.01 ? 12 : data < 535.02 ? '13+' : data < 535.07 ? 15 : data < 535.11 ? 16 : data < 535.19 ? 17 : data < 536.05 ? 18 : data < 536.10 ? 19 : data < 537.01 ? 20 : data < 537.11 ? '21+' : data < 537.13 ? 23 : data < 537.18 ? 24 : data < 537.24 ? 25 : data < 537.36 ? 26 : layout != 'Blink' ? '27' : '28');
- }
- // Add the postfix of ".x" or "+" for approximate versions.
- layout && (layout[1] += ' ' + (data += typeof data == 'number' ? '.x' : /[.+]/.test(data) ? '' : '+'));
- // Obscure version for some Safari 1-2 releases.
- if (name == 'Safari' && (!version || parseInt(version) > 45)) {
- version = data;
- }
- }
- // Detect Opera desktop modes.
- if (name == 'Opera' && (data = /\bzbov|zvav$/.exec(os))) {
- name += ' ';
- description.unshift('desktop mode');
- if (data == 'zvav') {
- name += 'Mini';
- version = null;
- } else {
- name += 'Mobile';
- }
- os = os.replace(RegExp(' *' + data + '$'), '');
- }
- // Detect Chrome desktop mode.
- else if (name == 'Safari' && /\bChrome\b/.exec(layout && layout[1])) {
- description.unshift('desktop mode');
- name = 'Chrome Mobile';
- version = null;
-
- if (/\bOS X\b/.test(os)) {
- manufacturer = 'Apple';
- os = 'iOS 4.3+';
- } else {
- os = null;
- }
- }
- // Strip incorrect OS versions.
- if (version && version.indexOf((data = /[\d.]+$/.exec(os))) == 0 &&
- ua.indexOf('/' + data + '-') > -1) {
- os = trim(os.replace(data, ''));
- }
- // Add layout engine.
- if (layout && !/\b(?:Avant|Nook)\b/.test(name) && (
- /Browser|Lunascape|Maxthon/.test(name) ||
- name != 'Safari' && /^iOS/.test(os) && /\bSafari\b/.test(layout[1]) ||
- /^(?:Adobe|Arora|Breach|Midori|Opera|Phantom|Rekonq|Rock|Samsung Internet|Sleipnir|Web)/.test(name) && layout[1])) {
- // Don't add layout details to description if they are falsey.
- (data = layout[layout.length - 1]) && description.push(data);
- }
- // Combine contextual information.
- if (description.length) {
- description = ['(' + description.join('; ') + ')'];
- }
- // Append manufacturer to description.
- if (manufacturer && product && product.indexOf(manufacturer) < 0) {
- description.push('on ' + manufacturer);
- }
- // Append product to description.
- if (product) {
- description.push((/^on /.test(description[description.length - 1]) ? '' : 'on ') + product);
- }
- // Parse the OS into an object.
- if (os) {
- data = / ([\d.+]+)$/.exec(os);
- isSpecialCasedOS = data && os.charAt(os.length - data[0].length - 1) == '/';
- os = {
- 'architecture': 32,
- 'family': (data && !isSpecialCasedOS) ? os.replace(data[0], '') : os,
- 'version': data ? data[1] : null,
- 'toString': function() {
- var version = this.version;
- return this.family + ((version && !isSpecialCasedOS) ? ' ' + version : '') + (this.architecture == 64 ? ' 64-bit' : '');
- }
- };
- }
- // Add browser/OS architecture.
- if ((data = /\b(?:AMD|IA|Win|WOW|x86_|x)64\b/i.exec(arch)) && !/\bi686\b/i.test(arch)) {
- if (os) {
- os.architecture = 64;
- os.family = os.family.replace(RegExp(' *' + data), '');
- }
- if (
- name && (/\bWOW64\b/i.test(ua) ||
- (useFeatures && /\w(?:86|32)$/.test(nav.cpuClass || nav.platform) && !/\bWin64; x64\b/i.test(ua)))
- ) {
- description.unshift('32-bit');
- }
- }
- // Chrome 39 and above on OS X is always 64-bit.
- else if (
- os && /^OS X/.test(os.family) &&
- name == 'Chrome' && parseFloat(version) >= 39
- ) {
- os.architecture = 64;
- }
-
- ua || (ua = null);
-
- /*------------------------------------------------------------------------*/
-
- /**
- * The platform object.
- *
- * @name platform
- * @type Object
- */
- var platform = {};
-
- /**
- * The platform description.
- *
- * @memberOf platform
- * @type string|null
- */
- platform.description = ua;
-
- /**
- * The name of the browser's layout engine.
- *
- * The list of common layout engines include:
- * "Blink", "EdgeHTML", "Gecko", "Trident" and "WebKit"
- *
- * @memberOf platform
- * @type string|null
- */
- platform.layout = layout && layout[0];
-
- /**
- * The name of the product's manufacturer.
- *
- * The list of manufacturers include:
- * "Apple", "Archos", "Amazon", "Asus", "Barnes & Noble", "BlackBerry",
- * "Google", "HP", "HTC", "LG", "Microsoft", "Motorola", "Nintendo",
- * "Nokia", "Samsung" and "Sony"
- *
- * @memberOf platform
- * @type string|null
- */
- platform.manufacturer = manufacturer;
-
- /**
- * The name of the browser/environment.
- *
- * The list of common browser names include:
- * "Chrome", "Electron", "Firefox", "Firefox for iOS", "IE",
- * "Microsoft Edge", "PhantomJS", "Safari", "SeaMonkey", "Silk",
- * "Opera Mini" and "Opera"
- *
- * Mobile versions of some browsers have "Mobile" appended to their name:
- * eg. "Chrome Mobile", "Firefox Mobile", "IE Mobile" and "Opera Mobile"
- *
- * @memberOf platform
- * @type string|null
- */
- platform.name = name;
-
- /**
- * The alpha/beta release indicator.
- *
- * @memberOf platform
- * @type string|null
- */
- platform.prerelease = prerelease;
-
- /**
- * The name of the product hosting the browser.
- *
- * The list of common products include:
- *
- * "BlackBerry", "Galaxy S4", "Lumia", "iPad", "iPod", "iPhone", "Kindle",
- * "Kindle Fire", "Nexus", "Nook", "PlayBook", "TouchPad" and "Transformer"
- *
- * @memberOf platform
- * @type string|null
- */
- platform.product = product;
-
- /**
- * The browser's user agent string.
- *
- * @memberOf platform
- * @type string|null
- */
- platform.ua = ua;
-
- /**
- * The browser/environment version.
- *
- * @memberOf platform
- * @type string|null
- */
- platform.version = name && version;
-
- /**
- * The name of the operating system.
- *
- * @memberOf platform
- * @type Object
- */
- platform.os = os || {
-
- /**
- * The CPU architecture the OS is built for.
- *
- * @memberOf platform.os
- * @type number|null
- */
- 'architecture': null,
-
- /**
- * The family of the OS.
- *
- * Common values include:
- * "Windows", "Windows Server 2008 R2 / 7", "Windows Server 2008 / Vista",
- * "Windows XP", "OS X", "Ubuntu", "Debian", "Fedora", "Red Hat", "SuSE",
- * "Android", "iOS" and "Windows Phone"
- *
- * @memberOf platform.os
- * @type string|null
- */
- 'family': null,
-
- /**
- * The version of the OS.
- *
- * @memberOf platform.os
- * @type string|null
- */
- 'version': null,
-
- /**
- * Returns the OS string.
- *
- * @memberOf platform.os
- * @returns {string} The OS string.
- */
- 'toString': function() { return 'null'; }
- };
-
- platform.parse = parse;
- platform.toString = toStringPlatform;
-
- if (platform.version) {
- description.unshift(version);
- }
- if (platform.name) {
- description.unshift(name);
- }
- if (os && name && !(os == String(os).split(' ')[0] && (os == name.split(' ')[0] || product))) {
- description.push(product ? '(' + os + ')' : 'on ' + os);
- }
- if (description.length) {
- platform.description = description.join(' ');
- }
- return platform;
- }
-
- /*--------------------------------------------------------------------------*/
-
- // Export platform.
- var platform = parse();
-
- // Some AMD build optimizers, like r.js, check for condition patterns like the following:
- if (typeof define == 'function' && typeof define.amd == 'object' && define.amd) {
- // Expose platform on the global object to prevent errors when platform is
- // loaded by a script tag in the presence of an AMD loader.
- // See http://requirejs.org/docs/errors.html#mismatch for more details.
- root.platform = platform;
-
- // Define as an anonymous module so platform can be aliased through path mapping.
- define(function() {
- return platform;
- });
- }
- // Check for `exports` after `define` in case a build optimizer adds an `exports` object.
- else if (freeExports && freeModule) {
- // Export for CommonJS support.
- forOwn(platform, function(value, key) {
- freeExports[key] = value;
- });
- }
- else {
- // Export to the global object.
- root.platform = platform;
- }
-}.call(this));
-
-}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
-
-},{}],9:[function(require,module,exports){
-var v1 = require('./v1');
-var v4 = require('./v4');
-
-var uuid = v4;
-uuid.v1 = v1;
-uuid.v4 = v4;
-
-module.exports = uuid;
-
-},{"./v1":12,"./v4":13}],10:[function(require,module,exports){
-/**
- * Convert array of 16 byte values to UUID string format of the form:
- * XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
- */
-var byteToHex = [];
-for (var i = 0; i < 256; ++i) {
- byteToHex[i] = (i + 0x100).toString(16).substr(1);
-}
-
-function bytesToUuid(buf, offset) {
- var i = offset || 0;
- var bth = byteToHex;
- // join used to fix memory issue caused by concatenation: https://bugs.chromium.org/p/v8/issues/detail?id=3175#c4
- return ([bth[buf[i++]], bth[buf[i++]],
- bth[buf[i++]], bth[buf[i++]], '-',
- bth[buf[i++]], bth[buf[i++]], '-',
- bth[buf[i++]], bth[buf[i++]], '-',
- bth[buf[i++]], bth[buf[i++]], '-',
- bth[buf[i++]], bth[buf[i++]],
- bth[buf[i++]], bth[buf[i++]],
- bth[buf[i++]], bth[buf[i++]]]).join('');
-}
-
-module.exports = bytesToUuid;
-
-},{}],11:[function(require,module,exports){
-// Unique ID creation requires a high quality random # generator. In the
-// browser this is a little complicated due to unknown quality of Math.random()
-// and inconsistent support for the `crypto` API. We do the best we can via
-// feature-detection
-
-// getRandomValues needs to be invoked in a context where "this" is a Crypto
-// implementation. Also, find the complete implementation of crypto on IE11.
-var getRandomValues = (typeof(crypto) != 'undefined' && crypto.getRandomValues && crypto.getRandomValues.bind(crypto)) ||
- (typeof(msCrypto) != 'undefined' && typeof window.msCrypto.getRandomValues == 'function' && msCrypto.getRandomValues.bind(msCrypto));
-
-if (getRandomValues) {
- // WHATWG crypto RNG - http://wiki.whatwg.org/wiki/Crypto
- var rnds8 = new Uint8Array(16); // eslint-disable-line no-undef
-
- module.exports = function whatwgRNG() {
- getRandomValues(rnds8);
- return rnds8;
- };
-} else {
- // Math.random()-based (RNG)
- //
- // If all else fails, use Math.random(). It's fast, but is of unspecified
- // quality.
- var rnds = new Array(16);
-
- module.exports = function mathRNG() {
- for (var i = 0, r; i < 16; i++) {
- if ((i & 0x03) === 0) r = Math.random() * 0x100000000;
- rnds[i] = r >>> ((i & 0x03) << 3) & 0xff;
- }
-
- return rnds;
- };
-}
-
-},{}],12:[function(require,module,exports){
-var rng = require('./lib/rng');
-var bytesToUuid = require('./lib/bytesToUuid');
-
-// **`v1()` - Generate time-based UUID**
-//
-// Inspired by https://github.com/LiosK/UUID.js
-// and http://docs.python.org/library/uuid.html
-
-var _nodeId;
-var _clockseq;
-
-// Previous uuid creation time
-var _lastMSecs = 0;
-var _lastNSecs = 0;
-
-// See https://github.com/broofa/node-uuid for API details
-function v1(options, buf, offset) {
- var i = buf && offset || 0;
- var b = buf || [];
-
- options = options || {};
- var node = options.node || _nodeId;
- var clockseq = options.clockseq !== undefined ? options.clockseq : _clockseq;
-
- // node and clockseq need to be initialized to random values if they're not
- // specified. We do this lazily to minimize issues related to insufficient
- // system entropy. See #189
- if (node == null || clockseq == null) {
- var seedBytes = rng();
- if (node == null) {
- // Per 4.5, create and 48-bit node id, (47 random bits + multicast bit = 1)
- node = _nodeId = [
- seedBytes[0] | 0x01,
- seedBytes[1], seedBytes[2], seedBytes[3], seedBytes[4], seedBytes[5]
- ];
- }
- if (clockseq == null) {
- // Per 4.2.2, randomize (14 bit) clockseq
- clockseq = _clockseq = (seedBytes[6] << 8 | seedBytes[7]) & 0x3fff;
- }
- }
-
- // UUID timestamps are 100 nano-second units since the Gregorian epoch,
- // (1582-10-15 00:00). JSNumbers aren't precise enough for this, so
- // time is handled internally as 'msecs' (integer milliseconds) and 'nsecs'
- // (100-nanoseconds offset from msecs) since unix epoch, 1970-01-01 00:00.
- var msecs = options.msecs !== undefined ? options.msecs : new Date().getTime();
-
- // Per 4.2.1.2, use count of uuid's generated during the current clock
- // cycle to simulate higher resolution clock
- var nsecs = options.nsecs !== undefined ? options.nsecs : _lastNSecs + 1;
-
- // Time since last uuid creation (in msecs)
- var dt = (msecs - _lastMSecs) + (nsecs - _lastNSecs)/10000;
-
- // Per 4.2.1.2, Bump clockseq on clock regression
- if (dt < 0 && options.clockseq === undefined) {
- clockseq = clockseq + 1 & 0x3fff;
- }
-
- // Reset nsecs if clock regresses (new clockseq) or we've moved onto a new
- // time interval
- if ((dt < 0 || msecs > _lastMSecs) && options.nsecs === undefined) {
- nsecs = 0;
- }
-
- // Per 4.2.1.2 Throw error if too many uuids are requested
- if (nsecs >= 10000) {
- throw new Error('uuid.v1(): Can\'t create more than 10M uuids/sec');
- }
-
- _lastMSecs = msecs;
- _lastNSecs = nsecs;
- _clockseq = clockseq;
-
- // Per 4.1.4 - Convert from unix epoch to Gregorian epoch
- msecs += 12219292800000;
-
- // `time_low`
- var tl = ((msecs & 0xfffffff) * 10000 + nsecs) % 0x100000000;
- b[i++] = tl >>> 24 & 0xff;
- b[i++] = tl >>> 16 & 0xff;
- b[i++] = tl >>> 8 & 0xff;
- b[i++] = tl & 0xff;
-
- // `time_mid`
- var tmh = (msecs / 0x100000000 * 10000) & 0xfffffff;
- b[i++] = tmh >>> 8 & 0xff;
- b[i++] = tmh & 0xff;
-
- // `time_high_and_version`
- b[i++] = tmh >>> 24 & 0xf | 0x10; // include version
- b[i++] = tmh >>> 16 & 0xff;
-
- // `clock_seq_hi_and_reserved` (Per 4.2.2 - include variant)
- b[i++] = clockseq >>> 8 | 0x80;
-
- // `clock_seq_low`
- b[i++] = clockseq & 0xff;
-
- // `node`
- for (var n = 0; n < 6; ++n) {
- b[i + n] = node[n];
- }
-
- return buf ? buf : bytesToUuid(b);
-}
-
-module.exports = v1;
-
-},{"./lib/bytesToUuid":10,"./lib/rng":11}],13:[function(require,module,exports){
-var rng = require('./lib/rng');
-var bytesToUuid = require('./lib/bytesToUuid');
-
-function v4(options, buf, offset) {
- var i = buf && offset || 0;
-
- if (typeof(options) == 'string') {
- buf = options === 'binary' ? new Array(16) : null;
- options = null;
- }
- options = options || {};
-
- var rnds = options.random || (options.rng || rng)();
-
- // Per 4.4, set bits for version and `clock_seq_hi_and_reserved`
- rnds[6] = (rnds[6] & 0x0f) | 0x40;
- rnds[8] = (rnds[8] & 0x3f) | 0x80;
-
- // Copy bytes to buffer, if provided
- if (buf) {
- for (var ii = 0; ii < 16; ++ii) {
- buf[i + ii] = rnds[ii];
- }
- }
-
- return buf || bytesToUuid(rnds);
-}
-
-module.exports = v4;
-
-},{"./lib/bytesToUuid":10,"./lib/rng":11}],14:[function(require,module,exports){
-/*
-WildEmitter.js is a slim little event emitter by @henrikjoreteg largely based
-on @visionmedia's Emitter from UI Kit.
-
-Why? I wanted it standalone.
-
-I also wanted support for wildcard emitters like this:
-
-emitter.on('*', function (eventName, other, event, payloads) {
-
-});
-
-emitter.on('somenamespace*', function (eventName, payloads) {
-
-});
-
-Please note that callbacks triggered by wildcard registered events also get
-the event name as the first argument.
-*/
-
-module.exports = WildEmitter;
-
-function WildEmitter() { }
-
-WildEmitter.mixin = function (constructor) {
- var prototype = constructor.prototype || constructor;
-
- prototype.isWildEmitter= true;
-
- // Listen on the given `event` with `fn`. Store a group name if present.
- prototype.on = function (event, groupName, fn) {
- this.callbacks = this.callbacks || {};
- var hasGroup = (arguments.length === 3),
- group = hasGroup ? arguments[1] : undefined,
- func = hasGroup ? arguments[2] : arguments[1];
- func._groupName = group;
- (this.callbacks[event] = this.callbacks[event] || []).push(func);
- return this;
- };
-
- // Adds an `event` listener that will be invoked a single
- // time then automatically removed.
- prototype.once = function (event, groupName, fn) {
- var self = this,
- hasGroup = (arguments.length === 3),
- group = hasGroup ? arguments[1] : undefined,
- func = hasGroup ? arguments[2] : arguments[1];
- function on() {
- self.off(event, on);
- func.apply(this, arguments);
- }
- this.on(event, group, on);
- return this;
- };
-
- // Unbinds an entire group
- prototype.releaseGroup = function (groupName) {
- this.callbacks = this.callbacks || {};
- var item, i, len, handlers;
- for (item in this.callbacks) {
- handlers = this.callbacks[item];
- for (i = 0, len = handlers.length; i < len; i++) {
- if (handlers[i]._groupName === groupName) {
- //console.log('removing');
- // remove it and shorten the array we're looping through
- handlers.splice(i, 1);
- i--;
- len--;
- }
- }
- }
- return this;
- };
-
- // Remove the given callback for `event` or all
- // registered callbacks.
- prototype.off = function (event, fn) {
- this.callbacks = this.callbacks || {};
- var callbacks = this.callbacks[event],
- i;
-
- if (!callbacks) return this;
-
- // remove all handlers
- if (arguments.length === 1) {
- delete this.callbacks[event];
- return this;
- }
-
- // remove specific handler
- i = callbacks.indexOf(fn);
- callbacks.splice(i, 1);
- if (callbacks.length === 0) {
- delete this.callbacks[event];
- }
- return this;
- };
-
- /// Emit `event` with the given args.
- // also calls any `*` handlers
- prototype.emit = function (event) {
- this.callbacks = this.callbacks || {};
- var args = [].slice.call(arguments, 1),
- callbacks = this.callbacks[event],
- specialCallbacks = this.getWildcardCallbacks(event),
- i,
- len,
- item,
- listeners;
-
- if (callbacks) {
- listeners = callbacks.slice();
- for (i = 0, len = listeners.length; i < len; ++i) {
- if (!listeners[i]) {
- break;
- }
- listeners[i].apply(this, args);
- }
- }
-
- if (specialCallbacks) {
- len = specialCallbacks.length;
- listeners = specialCallbacks.slice();
- for (i = 0, len = listeners.length; i < len; ++i) {
- if (!listeners[i]) {
- break;
- }
- listeners[i].apply(this, [event].concat(args));
- }
- }
-
- return this;
- };
-
- // Helper for for finding special wildcard event handlers that match the event
- prototype.getWildcardCallbacks = function (eventName) {
- this.callbacks = this.callbacks || {};
- var item,
- split,
- result = [];
-
- for (item in this.callbacks) {
- split = item.split('*');
- if (item === '*' || (split.length === 2 && eventName.slice(0, split[0].length) === split[0])) {
- result = result.concat(this.callbacks[item]);
- }
- }
- return result;
- };
-
-};
-
-WildEmitter.mixin(WildEmitter);
-
-},{}],15:[function(require,module,exports){
-/*!
- * EventEmitter v5.2.5 - git.io/ee
- * Unlicense - http://unlicense.org/
- * Oliver Caldwell - http://oli.me.uk/
- * @preserve
- */
-
-;(function (exports) {
- 'use strict';
-
- /**
- * Class for managing events.
- * Can be extended to provide event functionality in other classes.
- *
- * @class EventEmitter Manages event registering and emitting.
- */
- function EventEmitter() {}
-
- // Shortcuts to improve speed and size
- var proto = EventEmitter.prototype;
- var originalGlobalValue = exports.EventEmitter;
-
- /**
- * Finds the index of the listener for the event in its storage array.
- *
- * @param {Function[]} listeners Array of listeners to search through.
- * @param {Function} listener Method to look for.
- * @return {Number} Index of the specified listener, -1 if not found
- * @api private
- */
- function indexOfListener(listeners, listener) {
- var i = listeners.length;
- while (i--) {
- if (listeners[i].listener === listener) {
- return i;
- }
- }
-
- return -1;
- }
-
- /**
- * Alias a method while keeping the context correct, to allow for overwriting of target method.
- *
- * @param {String} name The name of the target method.
- * @return {Function} The aliased method
- * @api private
- */
- function alias(name) {
- return function aliasClosure() {
- return this[name].apply(this, arguments);
- };
- }
-
- /**
- * Returns the listener array for the specified event.
- * Will initialise the event object and listener arrays if required.
- * Will return an object if you use a regex search. The object contains keys for each matched event. So /ba[rz]/ might return an object containing bar and baz. But only if you have either defined them with defineEvent or added some listeners to them.
- * Each property in the object response is an array of listener functions.
- *
- * @param {String|RegExp} evt Name of the event to return the listeners from.
- * @return {Function[]|Object} All listener functions for the event.
- */
- proto.getListeners = function getListeners(evt) {
- var events = this._getEvents();
- var response;
- var key;
-
- // Return a concatenated array of all matching events if
- // the selector is a regular expression.
- if (evt instanceof RegExp) {
- response = {};
- for (key in events) {
- if (events.hasOwnProperty(key) && evt.test(key)) {
- response[key] = events[key];
- }
- }
- }
- else {
- response = events[evt] || (events[evt] = []);
- }
-
- return response;
- };
-
- /**
- * Takes a list of listener objects and flattens it into a list of listener functions.
- *
- * @param {Object[]} listeners Raw listener objects.
- * @return {Function[]} Just the listener functions.
- */
- proto.flattenListeners = function flattenListeners(listeners) {
- var flatListeners = [];
- var i;
-
- for (i = 0; i < listeners.length; i += 1) {
- flatListeners.push(listeners[i].listener);
- }
-
- return flatListeners;
- };
-
- /**
- * Fetches the requested listeners via getListeners but will always return the results inside an object. This is mainly for internal use but others may find it useful.
- *
- * @param {String|RegExp} evt Name of the event to return the listeners from.
- * @return {Object} All listener functions for an event in an object.
- */
- proto.getListenersAsObject = function getListenersAsObject(evt) {
- var listeners = this.getListeners(evt);
- var response;
-
- if (listeners instanceof Array) {
- response = {};
- response[evt] = listeners;
- }
-
- return response || listeners;
- };
-
- function isValidListener (listener) {
- if (typeof listener === 'function' || listener instanceof RegExp) {
- return true
- } else if (listener && typeof listener === 'object') {
- return isValidListener(listener.listener)
- } else {
- return false
- }
- }
-
- /**
- * Adds a listener function to the specified event.
- * The listener will not be added if it is a duplicate.
- * If the listener returns true then it will be removed after it is called.
- * If you pass a regular expression as the event name then the listener will be added to all events that match it.
- *
- * @param {String|RegExp} evt Name of the event to attach the listener to.
- * @param {Function} listener Method to be called when the event is emitted. If the function returns true then it will be removed after calling.
- * @return {Object} Current instance of EventEmitter for chaining.
- */
- proto.addListener = function addListener(evt, listener) {
- if (!isValidListener(listener)) {
- throw new TypeError('listener must be a function');
- }
-
- var listeners = this.getListenersAsObject(evt);
- var listenerIsWrapped = typeof listener === 'object';
- var key;
-
- for (key in listeners) {
- if (listeners.hasOwnProperty(key) && indexOfListener(listeners[key], listener) === -1) {
- listeners[key].push(listenerIsWrapped ? listener : {
- listener: listener,
- once: false
- });
- }
- }
-
- return this;
- };
-
- /**
- * Alias of addListener
- */
- proto.on = alias('addListener');
-
- /**
- * Semi-alias of addListener. It will add a listener that will be
- * automatically removed after its first execution.
- *
- * @param {String|RegExp} evt Name of the event to attach the listener to.
- * @param {Function} listener Method to be called when the event is emitted. If the function returns true then it will be removed after calling.
- * @return {Object} Current instance of EventEmitter for chaining.
- */
- proto.addOnceListener = function addOnceListener(evt, listener) {
- return this.addListener(evt, {
- listener: listener,
- once: true
- });
- };
-
- /**
- * Alias of addOnceListener.
- */
- proto.once = alias('addOnceListener');
-
- /**
- * Defines an event name. This is required if you want to use a regex to add a listener to multiple events at once. If you don't do this then how do you expect it to know what event to add to? Should it just add to every possible match for a regex? No. That is scary and bad.
- * You need to tell it what event names should be matched by a regex.
- *
- * @param {String} evt Name of the event to create.
- * @return {Object} Current instance of EventEmitter for chaining.
- */
- proto.defineEvent = function defineEvent(evt) {
- this.getListeners(evt);
- return this;
- };
-
- /**
- * Uses defineEvent to define multiple events.
- *
- * @param {String[]} evts An array of event names to define.
- * @return {Object} Current instance of EventEmitter for chaining.
- */
- proto.defineEvents = function defineEvents(evts) {
- for (var i = 0; i < evts.length; i += 1) {
- this.defineEvent(evts[i]);
- }
- return this;
- };
-
- /**
- * Removes a listener function from the specified event.
- * When passed a regular expression as the event name, it will remove the listener from all events that match it.
- *
- * @param {String|RegExp} evt Name of the event to remove the listener from.
- * @param {Function} listener Method to remove from the event.
- * @return {Object} Current instance of EventEmitter for chaining.
- */
- proto.removeListener = function removeListener(evt, listener) {
- var listeners = this.getListenersAsObject(evt);
- var index;
- var key;
-
- for (key in listeners) {
- if (listeners.hasOwnProperty(key)) {
- index = indexOfListener(listeners[key], listener);
-
- if (index !== -1) {
- listeners[key].splice(index, 1);
- }
- }
- }
-
- return this;
- };
-
- /**
- * Alias of removeListener
- */
- proto.off = alias('removeListener');
-
- /**
- * Adds listeners in bulk using the manipulateListeners method.
- * If you pass an object as the first argument you can add to multiple events at once. The object should contain key value pairs of events and listeners or listener arrays. You can also pass it an event name and an array of listeners to be added.
- * You can also pass it a regular expression to add the array of listeners to all events that match it.
- * Yeah, this function does quite a bit. That's probably a bad thing.
- *
- * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to add to multiple events at once.
- * @param {Function[]} [listeners] An optional array of listener functions to add.
- * @return {Object} Current instance of EventEmitter for chaining.
- */
- proto.addListeners = function addListeners(evt, listeners) {
- // Pass through to manipulateListeners
- return this.manipulateListeners(false, evt, listeners);
- };
-
- /**
- * Removes listeners in bulk using the manipulateListeners method.
- * If you pass an object as the first argument you can remove from multiple events at once. The object should contain key value pairs of events and listeners or listener arrays.
- * You can also pass it an event name and an array of listeners to be removed.
- * You can also pass it a regular expression to remove the listeners from all events that match it.
- *
- * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to remove from multiple events at once.
- * @param {Function[]} [listeners] An optional array of listener functions to remove.
- * @return {Object} Current instance of EventEmitter for chaining.
- */
- proto.removeListeners = function removeListeners(evt, listeners) {
- // Pass through to manipulateListeners
- return this.manipulateListeners(true, evt, listeners);
- };
-
- /**
- * Edits listeners in bulk. The addListeners and removeListeners methods both use this to do their job. You should really use those instead, this is a little lower level.
- * The first argument will determine if the listeners are removed (true) or added (false).
- * If you pass an object as the second argument you can add/remove from multiple events at once. The object should contain key value pairs of events and listeners or listener arrays.
- * You can also pass it an event name and an array of listeners to be added/removed.
- * You can also pass it a regular expression to manipulate the listeners of all events that match it.
- *
- * @param {Boolean} remove True if you want to remove listeners, false if you want to add.
- * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to add/remove from multiple events at once.
- * @param {Function[]} [listeners] An optional array of listener functions to add/remove.
- * @return {Object} Current instance of EventEmitter for chaining.
- */
- proto.manipulateListeners = function manipulateListeners(remove, evt, listeners) {
- var i;
- var value;
- var single = remove ? this.removeListener : this.addListener;
- var multiple = remove ? this.removeListeners : this.addListeners;
-
- // If evt is an object then pass each of its properties to this method
- if (typeof evt === 'object' && !(evt instanceof RegExp)) {
- for (i in evt) {
- if (evt.hasOwnProperty(i) && (value = evt[i])) {
- // Pass the single listener straight through to the singular method
- if (typeof value === 'function') {
- single.call(this, i, value);
- }
- else {
- // Otherwise pass back to the multiple function
- multiple.call(this, i, value);
- }
- }
- }
- }
- else {
- // So evt must be a string
- // And listeners must be an array of listeners
- // Loop over it and pass each one to the multiple method
- i = listeners.length;
- while (i--) {
- single.call(this, evt, listeners[i]);
- }
- }
-
- return this;
- };
-
- /**
- * Removes all listeners from a specified event.
- * If you do not specify an event then all listeners will be removed.
- * That means every event will be emptied.
- * You can also pass a regex to remove all events that match it.
- *
- * @param {String|RegExp} [evt] Optional name of the event to remove all listeners for. Will remove from every event if not passed.
- * @return {Object} Current instance of EventEmitter for chaining.
- */
- proto.removeEvent = function removeEvent(evt) {
- var type = typeof evt;
- var events = this._getEvents();
- var key;
-
- // Remove different things depending on the state of evt
- if (type === 'string') {
- // Remove all listeners for the specified event
- delete events[evt];
- }
- else if (evt instanceof RegExp) {
- // Remove all events matching the regex.
- for (key in events) {
- if (events.hasOwnProperty(key) && evt.test(key)) {
- delete events[key];
- }
- }
- }
- else {
- // Remove all listeners in all events
- delete this._events;
- }
-
- return this;
- };
-
- /**
- * Alias of removeEvent.
- *
- * Added to mirror the node API.
- */
- proto.removeAllListeners = alias('removeEvent');
-
- /**
- * Emits an event of your choice.
- * When emitted, every listener attached to that event will be executed.
- * If you pass the optional argument array then those arguments will be passed to every listener upon execution.
- * Because it uses `apply`, your array of arguments will be passed as if you wrote them out separately.
- * So they will not arrive within the array on the other side, they will be separate.
- * You can also pass a regular expression to emit to all events that match it.
- *
- * @param {String|RegExp} evt Name of the event to emit and execute listeners for.
- * @param {Array} [args] Optional array of arguments to be passed to each listener.
- * @return {Object} Current instance of EventEmitter for chaining.
- */
- proto.emitEvent = function emitEvent(evt, args) {
- var listenersMap = this.getListenersAsObject(evt);
- var listeners;
- var listener;
- var i;
- var key;
- var response;
-
- for (key in listenersMap) {
- if (listenersMap.hasOwnProperty(key)) {
- listeners = listenersMap[key].slice(0);
-
- for (i = 0; i < listeners.length; i++) {
- // If the listener returns true then it shall be removed from the event
- // The function is executed either with a basic call or an apply if there is an args array
- listener = listeners[i];
-
- if (listener.once === true) {
- this.removeListener(evt, listener.listener);
- }
-
- response = listener.listener.apply(this, args || []);
-
- if (response === this._getOnceReturnValue()) {
- this.removeListener(evt, listener.listener);
- }
- }
- }
- }
-
- return this;
- };
-
- /**
- * Alias of emitEvent
- */
- proto.trigger = alias('emitEvent');
-
- /**
- * Subtly different from emitEvent in that it will pass its arguments on to the listeners, as opposed to taking a single array of arguments to pass on.
- * As with emitEvent, you can pass a regex in place of the event name to emit to all events that match it.
- *
- * @param {String|RegExp} evt Name of the event to emit and execute listeners for.
- * @param {...*} Optional additional arguments to be passed to each listener.
- * @return {Object} Current instance of EventEmitter for chaining.
- */
- proto.emit = function emit(evt) {
- var args = Array.prototype.slice.call(arguments, 1);
- return this.emitEvent(evt, args);
- };
-
- /**
- * Sets the current value to check against when executing listeners. If a
- * listeners return value matches the one set here then it will be removed
- * after execution. This value defaults to true.
- *
- * @param {*} value The new value to check for when executing listeners.
- * @return {Object} Current instance of EventEmitter for chaining.
- */
- proto.setOnceReturnValue = function setOnceReturnValue(value) {
- this._onceReturnValue = value;
- return this;
- };
-
- /**
- * Fetches the current value to check against when executing listeners. If
- * the listeners return value matches this one then it should be removed
- * automatically. It will return true by default.
- *
- * @return {*|Boolean} The current value to check for or the default, true.
- * @api private
- */
- proto._getOnceReturnValue = function _getOnceReturnValue() {
- if (this.hasOwnProperty('_onceReturnValue')) {
- return this._onceReturnValue;
- }
- else {
- return true;
- }
- };
-
- /**
- * Fetches the events object and creates one if required.
- *
- * @return {Object} The events storage object.
- * @api private
- */
- proto._getEvents = function _getEvents() {
- return this._events || (this._events = {});
- };
-
- /**
- * Reverts the global {@link EventEmitter} to its previous value and returns a reference to this version.
- *
- * @return {Function} Non conflicting EventEmitter class.
- */
- EventEmitter.noConflict = function noConflict() {
- exports.EventEmitter = originalGlobalValue;
- return EventEmitter;
- };
-
- // Expose the class either via AMD, CommonJS or the global object
- if (typeof define === 'function' && define.amd) {
- define(function () {
- return EventEmitter;
- });
- }
- else if (typeof module === 'object' && module.exports){
- module.exports = EventEmitter;
- }
- else {
- exports.EventEmitter = EventEmitter;
- }
-}(typeof window !== 'undefined' ? window : this || {}));
-
-},{}],16:[function(require,module,exports){
-"use strict";
-Object.defineProperty(exports, "__esModule", { value: true });
-var OpenVidu_1 = require("./OpenVidu/OpenVidu");
-if (window) {
- window['OpenVidu'] = OpenVidu_1.OpenVidu;
-}
-
-},{"./OpenVidu/OpenVidu":19}],17:[function(require,module,exports){
-"use strict";
-Object.defineProperty(exports, "__esModule", { value: true });
-var Stream_1 = require("./Stream");
-var Connection = (function () {
- function Connection(session, opts) {
- this.session = session;
- this.disposed = false;
- var msg = "'Connection' created ";
- if (!!opts) {
- msg += "(remote) with 'connectionId' [" + opts.id + ']';
- }
- else {
- msg += '(local)';
- }
- console.info(msg);
- this.options = opts;
- if (!!opts) {
- this.connectionId = opts.id;
- if (opts.metadata) {
- this.data = opts.metadata;
- }
- if (opts.streams) {
- this.initRemoteStreams(opts.streams);
- }
- }
- this.creationTime = new Date().getTime();
- }
- Connection.prototype.sendIceCandidate = function (candidate) {
- console.debug((!!this.stream.outboundStreamOpts ? 'Local' : 'Remote'), 'candidate for', this.connectionId, JSON.stringify(candidate));
- this.session.openvidu.sendRequest('onIceCandidate', {
- endpointName: this.connectionId,
- candidate: candidate.candidate,
- sdpMid: candidate.sdpMid,
- sdpMLineIndex: candidate.sdpMLineIndex
- }, function (error, response) {
- if (error) {
- console.error('Error sending ICE candidate: '
- + JSON.stringify(error));
- }
- });
- };
- Connection.prototype.initRemoteStreams = function (options) {
- var _this = this;
- options.forEach(function (opts) {
- var streamOptions = {
- id: opts.id,
- connection: _this,
- hasAudio: opts.hasAudio,
- hasVideo: opts.hasVideo,
- audioActive: opts.audioActive,
- videoActive: opts.videoActive,
- typeOfVideo: opts.typeOfVideo,
- frameRate: opts.frameRate,
- videoDimensions: !!opts.videoDimensions ? JSON.parse(opts.videoDimensions) : undefined
- };
- var stream = new Stream_1.Stream(_this.session, streamOptions);
- _this.addStream(stream);
- });
- console.info("Remote 'Connection' with 'connectionId' [" + this.connectionId + '] is now configured for receiving Streams with options: ', this.stream.inboundStreamOpts);
- };
- Connection.prototype.addStream = function (stream) {
- stream.connection = this;
- this.stream = stream;
- };
- Connection.prototype.removeStream = function (streamId) {
- delete this.stream;
- };
- Connection.prototype.dispose = function () {
- if (!!this.stream) {
- delete this.stream;
- }
- this.disposed = true;
- };
- return Connection;
-}());
-exports.Connection = Connection;
-
-},{"./Stream":22}],18:[function(require,module,exports){
-"use strict";
-Object.defineProperty(exports, "__esModule", { value: true });
-var LocalRecorderState_1 = require("../OpenViduInternal/Enums/LocalRecorderState");
-var LocalRecorder = (function () {
- function LocalRecorder(stream) {
- this.stream = stream;
- this.chunks = [];
- this.count = 0;
- this.connectionId = (!!this.stream.connection) ? this.stream.connection.connectionId : 'default-connection';
- this.id = this.stream.streamId + '_' + this.connectionId + '_localrecord';
- this.state = LocalRecorderState_1.LocalRecorderState.READY;
- }
- LocalRecorder.prototype.record = function () {
- var _this = this;
- return new Promise(function (resolve, reject) {
- try {
- if (typeof MediaRecorder === 'undefined') {
- console.error('MediaRecorder not supported on your browser. See compatibility in https://caniuse.com/#search=MediaRecorder');
- throw (Error('MediaRecorder not supported on your browser. See compatibility in https://caniuse.com/#search=MediaRecorder'));
- }
- if (_this.state !== LocalRecorderState_1.LocalRecorderState.READY) {
- throw (Error('\'LocalRecord.record()\' needs \'LocalRecord.state\' to be \'READY\' (current value: \'' + _this.state + '\'). Call \'LocalRecorder.clean()\' or init a new LocalRecorder before'));
- }
- console.log("Starting local recording of stream '" + _this.stream.streamId + "' of connection '" + _this.connectionId + "'");
- if (typeof MediaRecorder.isTypeSupported === 'function') {
- var options = void 0;
- if (MediaRecorder.isTypeSupported('video/webm;codecs=vp9')) {
- options = { mimeType: 'video/webm;codecs=vp9' };
- }
- else if (MediaRecorder.isTypeSupported('video/webm;codecs=h264')) {
- options = { mimeType: 'video/webm;codecs=h264' };
- }
- else if (MediaRecorder.isTypeSupported('video/webm;codecs=vp8')) {
- options = { mimeType: 'video/webm;codecs=vp8' };
- }
- console.log('Using mimeType ' + options.mimeType);
- _this.mediaRecorder = new MediaRecorder(_this.stream.getMediaStream(), options);
- }
- else {
- console.warn('isTypeSupported is not supported, using default codecs for browser');
- _this.mediaRecorder = new MediaRecorder(_this.stream.getMediaStream());
- }
- _this.mediaRecorder.start(10);
- }
- catch (err) {
- reject(err);
- }
- _this.mediaRecorder.ondataavailable = function (e) {
- _this.chunks.push(e.data);
- };
- _this.mediaRecorder.onerror = function (e) {
- console.error('MediaRecorder error: ', e);
- };
- _this.mediaRecorder.onstart = function () {
- console.log('MediaRecorder started (state=' + _this.mediaRecorder.state + ')');
- };
- _this.mediaRecorder.onstop = function () {
- _this.onStopDefault();
- };
- _this.mediaRecorder.onpause = function () {
- console.log('MediaRecorder paused (state=' + _this.mediaRecorder.state + ')');
- };
- _this.mediaRecorder.onresume = function () {
- console.log('MediaRecorder resumed (state=' + _this.mediaRecorder.state + ')');
- };
- _this.mediaRecorder.onwarning = function (e) {
- console.log('MediaRecorder warning: ' + e);
- };
- _this.state = LocalRecorderState_1.LocalRecorderState.RECORDING;
- resolve();
- });
- };
- LocalRecorder.prototype.stop = function () {
- var _this = this;
- return new Promise(function (resolve, reject) {
- try {
- if (_this.state === LocalRecorderState_1.LocalRecorderState.READY || _this.state === LocalRecorderState_1.LocalRecorderState.FINISHED) {
- throw (Error('\'LocalRecord.stop()\' needs \'LocalRecord.state\' to be \'RECORDING\' or \'PAUSED\' (current value: \'' + _this.state + '\'). Call \'LocalRecorder.start()\' before'));
- }
- _this.mediaRecorder.onstop = function () {
- _this.onStopDefault();
- resolve();
- };
- _this.mediaRecorder.stop();
- }
- catch (e) {
- reject(e);
- }
- });
- };
- LocalRecorder.prototype.pause = function () {
- var _this = this;
- return new Promise(function (resolve, reject) {
- try {
- if (_this.state !== LocalRecorderState_1.LocalRecorderState.RECORDING) {
- reject(Error('\'LocalRecord.pause()\' needs \'LocalRecord.state\' to be \'RECORDING\' (current value: \'' + _this.state + '\'). Call \'LocalRecorder.start()\' or \'LocalRecorder.resume()\' before'));
- }
- _this.mediaRecorder.pause();
- _this.state = LocalRecorderState_1.LocalRecorderState.PAUSED;
- }
- catch (error) {
- reject(error);
- }
- });
- };
- LocalRecorder.prototype.resume = function () {
- var _this = this;
- return new Promise(function (resolve, reject) {
- try {
- if (_this.state !== LocalRecorderState_1.LocalRecorderState.PAUSED) {
- throw (Error('\'LocalRecord.resume()\' needs \'LocalRecord.state\' to be \'PAUSED\' (current value: \'' + _this.state + '\'). Call \'LocalRecorder.pause()\' before'));
- }
- _this.mediaRecorder.resume();
- _this.state = LocalRecorderState_1.LocalRecorderState.RECORDING;
- }
- catch (error) {
- reject(error);
- }
- });
- };
- LocalRecorder.prototype.preview = function (parentElement) {
- if (this.state !== LocalRecorderState_1.LocalRecorderState.FINISHED) {
- throw (Error('\'LocalRecord.preview()\' needs \'LocalRecord.state\' to be \'FINISHED\' (current value: \'' + this.state + '\'). Call \'LocalRecorder.stop()\' before'));
- }
- this.videoPreview = document.createElement('video');
- this.videoPreview.id = this.id;
- this.videoPreview.autoplay = true;
- if (typeof parentElement === 'string') {
- this.htmlParentElementId = parentElement;
- var parentElementDom = document.getElementById(parentElement);
- if (parentElementDom) {
- this.videoPreview = parentElementDom.appendChild(this.videoPreview);
- }
- }
- else {
- this.htmlParentElementId = parentElement.id;
- this.videoPreview = parentElement.appendChild(this.videoPreview);
- }
- this.videoPreview.src = this.videoPreviewSrc;
- return this.videoPreview;
- };
- LocalRecorder.prototype.clean = function () {
- var _this = this;
- var f = function () {
- delete _this.blob;
- _this.chunks = [];
- _this.count = 0;
- delete _this.mediaRecorder;
- _this.state = LocalRecorderState_1.LocalRecorderState.READY;
- };
- if (this.state === LocalRecorderState_1.LocalRecorderState.RECORDING || this.state === LocalRecorderState_1.LocalRecorderState.PAUSED) {
- this.stop().then(function () { return f(); }).catch(function () { return f(); });
- }
- else {
- f();
- }
- };
- LocalRecorder.prototype.download = function () {
- if (this.state !== LocalRecorderState_1.LocalRecorderState.FINISHED) {
- throw (Error('\'LocalRecord.download()\' needs \'LocalRecord.state\' to be \'FINISHED\' (current value: \'' + this.state + '\'). Call \'LocalRecorder.stop()\' before'));
- }
- else {
- var a = document.createElement('a');
- a.style.display = 'none';
- document.body.appendChild(a);
- var url = window.URL.createObjectURL(this.blob);
- a.href = url;
- a.download = this.id + '.webm';
- a.click();
- window.URL.revokeObjectURL(url);
- document.body.removeChild(a);
- }
- };
- LocalRecorder.prototype.getBlob = function () {
- if (this.state !== LocalRecorderState_1.LocalRecorderState.FINISHED) {
- throw (Error('Call \'LocalRecord.stop()\' before getting Blob file'));
- }
- else {
- return this.blob;
- }
- };
- LocalRecorder.prototype.uploadAsBinary = function (endpoint, headers) {
- var _this = this;
- return new Promise(function (resolve, reject) {
- if (_this.state !== LocalRecorderState_1.LocalRecorderState.FINISHED) {
- reject(Error('\'LocalRecord.uploadAsBinary()\' needs \'LocalRecord.state\' to be \'FINISHED\' (current value: \'' + _this.state + '\'). Call \'LocalRecorder.stop()\' before'));
- }
- else {
- var http_1 = new XMLHttpRequest();
- http_1.open('POST', endpoint, true);
- if (typeof headers === 'object') {
- for (var _i = 0, _a = Object.keys(headers); _i < _a.length; _i++) {
- var key = _a[_i];
- http_1.setRequestHeader(key, headers[key]);
- }
- }
- http_1.onreadystatechange = function () {
- if (http_1.readyState === 4) {
- if (http_1.status.toString().charAt(0) === '2') {
- resolve(http_1.responseText);
- }
- else {
- reject(http_1.status);
- }
- }
- };
- http_1.send(_this.blob);
- }
- });
- };
- LocalRecorder.prototype.uploadAsMultipartfile = function (endpoint, headers) {
- var _this = this;
- return new Promise(function (resolve, reject) {
- if (_this.state !== LocalRecorderState_1.LocalRecorderState.FINISHED) {
- reject(Error('\'LocalRecord.uploadAsMultipartfile()\' needs \'LocalRecord.state\' to be \'FINISHED\' (current value: \'' + _this.state + '\'). Call \'LocalRecorder.stop()\' before'));
- }
- else {
- var http_2 = new XMLHttpRequest();
- http_2.open('POST', endpoint, true);
- if (typeof headers === 'object') {
- for (var _i = 0, _a = Object.keys(headers); _i < _a.length; _i++) {
- var key = _a[_i];
- http_2.setRequestHeader(key, headers[key]);
- }
- }
- var sendable = new FormData();
- sendable.append('file', _this.blob, _this.id + '.webm');
- http_2.onreadystatechange = function () {
- if (http_2.readyState === 4) {
- if (http_2.status.toString().charAt(0) === '2') {
- resolve(http_2.responseText);
- }
- else {
- reject(http_2.status);
- }
- }
- };
- http_2.send(sendable);
- }
- });
- };
- LocalRecorder.prototype.onStopDefault = function () {
- console.log('MediaRecorder stopped (state=' + this.mediaRecorder.state + ')');
- this.blob = new Blob(this.chunks, { type: 'video/webm' });
- this.chunks = [];
- this.videoPreviewSrc = window.URL.createObjectURL(this.blob);
- this.state = LocalRecorderState_1.LocalRecorderState.FINISHED;
- };
- return LocalRecorder;
-}());
-exports.LocalRecorder = LocalRecorder;
-
-},{"../OpenViduInternal/Enums/LocalRecorderState":25}],19:[function(require,module,exports){
-"use strict";
-Object.defineProperty(exports, "__esModule", { value: true });
-var LocalRecorder_1 = require("./LocalRecorder");
-var Publisher_1 = require("./Publisher");
-var Session_1 = require("./Session");
-var StreamPropertyChangedEvent_1 = require("../OpenViduInternal/Events/StreamPropertyChangedEvent");
-var OpenViduError_1 = require("../OpenViduInternal/Enums/OpenViduError");
-var VideoInsertMode_1 = require("../OpenViduInternal/Enums/VideoInsertMode");
-var screenSharingAuto = require("../OpenViduInternal/ScreenSharing/Screen-Capturing-Auto");
-var screenSharing = require("../OpenViduInternal/ScreenSharing/Screen-Capturing");
-var RpcBuilder = require("../OpenViduInternal/KurentoUtils/kurento-jsonrpc");
-var platform = require("platform");
-var OpenVidu = (function () {
- function OpenVidu() {
- var _this = this;
- this.publishers = [];
- this.secret = '';
- this.recorder = false;
- this.advancedConfiguration = {};
- console.info("'OpenVidu' initialized");
- if (platform.name.toLowerCase().indexOf('mobile') !== -1) {
- window.onorientationchange = function () {
- _this.publishers.forEach(function (publisher) {
- if (!!publisher.stream && !!publisher.stream.hasVideo && !!publisher.stream.streamManager.videos[0]) {
- var attempts_1 = 0;
- var oldWidth_1 = publisher.stream.videoDimensions.width;
- var oldHeight_1 = publisher.stream.videoDimensions.height;
- var firefoxSettings_1 = publisher.stream.getMediaStream().getVideoTracks()[0].getSettings();
- var newWidth_1 = (platform.name.toLowerCase().indexOf('firefox') !== -1) ? firefoxSettings_1.width : publisher.videoReference.videoWidth;
- var newHeight_1 = (platform.name.toLowerCase().indexOf('firefox') !== -1) ? firefoxSettings_1.height : publisher.videoReference.videoHeight;
- var repeatUntilChange_1 = setInterval(function () {
- firefoxSettings_1 = publisher.stream.getMediaStream().getVideoTracks()[0].getSettings();
- newWidth_1 = (platform.name.toLowerCase().indexOf('firefox') !== -1) ? firefoxSettings_1.width : publisher.videoReference.videoWidth;
- newHeight_1 = (platform.name.toLowerCase().indexOf('firefox') !== -1) ? firefoxSettings_1.height : publisher.videoReference.videoHeight;
- sendStreamPropertyChangedEvent_1(oldWidth_1, oldHeight_1, newWidth_1, newHeight_1);
- }, 100);
- var sendStreamPropertyChangedEvent_1 = function (oldWidth, oldHeight, newWidth, newHeight) {
- attempts_1++;
- if (attempts_1 > 4) {
- clearTimeout(repeatUntilChange_1);
- }
- if (newWidth !== oldWidth || newHeight !== oldHeight) {
- publisher.stream.videoDimensions = {
- width: newWidth || 0,
- height: newHeight || 0
- };
- _this.sendRequest('streamPropertyChanged', {
- streamId: publisher.stream.streamId,
- property: 'videoDimensions',
- newValue: JSON.stringify(publisher.stream.videoDimensions),
- reason: 'deviceRotated'
- }, function (error, response) {
- if (error) {
- console.error("Error sending 'streamPropertyChanged' event", error);
- }
- else {
- _this.session.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent_1.StreamPropertyChangedEvent(_this.session, publisher.stream, 'videoDimensions', publisher.stream.videoDimensions, { width: oldWidth, height: oldHeight }, 'deviceRotated')]);
- publisher.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent_1.StreamPropertyChangedEvent(publisher, publisher.stream, 'videoDimensions', publisher.stream.videoDimensions, { width: oldWidth, height: oldHeight }, 'deviceRotated')]);
- }
- });
- clearTimeout(repeatUntilChange_1);
- }
- };
- }
- });
- };
- }
- }
- OpenVidu.prototype.initSession = function () {
- this.session = new Session_1.Session(this);
- return this.session;
- };
- OpenVidu.prototype.initPublisher = function (targetElement, param2, param3) {
- var properties;
- if (!!param2 && (typeof param2 !== 'function')) {
- properties = param2;
- properties = {
- audioSource: (typeof properties.audioSource !== 'undefined') ? properties.audioSource : undefined,
- frameRate: this.isMediaStreamTrack(properties.videoSource) ? undefined : ((typeof properties.frameRate !== 'undefined') ? properties.frameRate : undefined),
- insertMode: (typeof properties.insertMode !== 'undefined') ? ((typeof properties.insertMode === 'string') ? VideoInsertMode_1.VideoInsertMode[properties.insertMode] : properties.insertMode) : VideoInsertMode_1.VideoInsertMode.APPEND,
- mirror: (typeof properties.mirror !== 'undefined') ? properties.mirror : true,
- publishAudio: (typeof properties.publishAudio !== 'undefined') ? properties.publishAudio : true,
- publishVideo: (typeof properties.publishVideo !== 'undefined') ? properties.publishVideo : true,
- resolution: this.isMediaStreamTrack(properties.videoSource) ? undefined : ((typeof properties.resolution !== 'undefined') ? properties.resolution : '640x480'),
- videoSource: (typeof properties.videoSource !== 'undefined') ? properties.videoSource : undefined
- };
- }
- else {
- properties = {
- insertMode: VideoInsertMode_1.VideoInsertMode.APPEND,
- mirror: true,
- publishAudio: true,
- publishVideo: true,
- resolution: '640x480'
- };
- }
- var publisher = new Publisher_1.Publisher(targetElement, properties, this);
- var completionHandler;
- if (!!param2 && (typeof param2 === 'function')) {
- completionHandler = param2;
- }
- else if (!!param3) {
- completionHandler = param3;
- }
- publisher.initialize()
- .then(function () {
- if (completionHandler !== undefined) {
- completionHandler(undefined);
- }
- publisher.emitEvent('accessAllowed', []);
- }).catch(function (error) {
- if (completionHandler !== undefined) {
- completionHandler(error);
- }
- publisher.emitEvent('accessDenied', []);
- });
- this.publishers.push(publisher);
- return publisher;
- };
- OpenVidu.prototype.initPublisherAsync = function (targetElement, properties) {
- var _this = this;
- return new Promise(function (resolve, reject) {
- var publisher;
- var callback = function (error) {
- if (!!error) {
- reject(error);
- }
- else {
- resolve(publisher);
- }
- };
- if (!!properties) {
- publisher = _this.initPublisher(targetElement, properties, callback);
- }
- else {
- publisher = _this.initPublisher(targetElement, callback);
- }
- });
- };
- OpenVidu.prototype.initLocalRecorder = function (stream) {
- return new LocalRecorder_1.LocalRecorder(stream);
- };
- OpenVidu.prototype.checkSystemRequirements = function () {
- var browser = platform.name;
- var version = platform.version;
- if ((browser !== 'Chrome') && (browser !== 'Chrome Mobile') &&
- (browser !== 'Firefox') && (browser !== 'Firefox Mobile') && (browser !== 'Firefox for iOS') &&
- (browser !== 'Opera') && (browser !== 'Opera Mobile') &&
- (browser !== 'Safari')) {
- return 0;
- }
- else {
- return 1;
- }
- };
- OpenVidu.prototype.getDevices = function () {
- return new Promise(function (resolve, reject) {
- navigator.mediaDevices.enumerateDevices().then(function (deviceInfos) {
- var devices = [];
- deviceInfos.forEach(function (deviceInfo) {
- if (deviceInfo.kind === 'audioinput' || deviceInfo.kind === 'videoinput') {
- devices.push({
- kind: deviceInfo.kind,
- deviceId: deviceInfo.deviceId,
- label: deviceInfo.label
- });
- }
- });
- resolve(devices);
- }).catch(function (error) {
- console.error('Error getting devices', error);
- reject(error);
- });
- });
- };
- OpenVidu.prototype.getUserMedia = function (options) {
- var _this = this;
- return new Promise(function (resolve, reject) {
- _this.generateMediaConstraints(options)
- .then(function (constraints) {
- navigator.mediaDevices.getUserMedia(constraints)
- .then(function (mediaStream) {
- resolve(mediaStream);
- })
- .catch(function (error) {
- var errorName;
- var errorMessage = error.toString();
- if (!(options.videoSource === 'screen')) {
- errorName = OpenViduError_1.OpenViduErrorName.DEVICE_ACCESS_DENIED;
- }
- else {
- errorName = OpenViduError_1.OpenViduErrorName.SCREEN_CAPTURE_DENIED;
- }
- reject(new OpenViduError_1.OpenViduError(errorName, errorMessage));
- });
- })
- .catch(function (error) {
- reject(error);
- });
- });
- };
- OpenVidu.prototype.enableProdMode = function () {
- console.log = function () { };
- console.debug = function () { };
- console.info = function () { };
- console.warn = function () { };
- };
- OpenVidu.prototype.setAdvancedConfiguration = function (configuration) {
- this.advancedConfiguration = configuration;
- };
- OpenVidu.prototype.generateMediaConstraints = function (publisherProperties) {
- var _this = this;
- return new Promise(function (resolve, reject) {
- var audio, video;
- if (publisherProperties.audioSource === null || publisherProperties.audioSource === false) {
- audio = false;
- }
- else if (publisherProperties.audioSource === undefined) {
- audio = true;
- }
- else {
- audio = publisherProperties.audioSource;
- }
- if (publisherProperties.videoSource === null || publisherProperties.videoSource === false) {
- video = false;
- }
- else {
- video = {
- height: {
- ideal: 480
- },
- width: {
- ideal: 640
- }
- };
- }
- var mediaConstraints = {
- audio: audio,
- video: video
- };
- if (typeof mediaConstraints.audio === 'string') {
- mediaConstraints.audio = { deviceId: { exact: mediaConstraints.audio } };
- }
- if (mediaConstraints.video) {
- if (!!publisherProperties.resolution) {
- var widthAndHeight = publisherProperties.resolution.toLowerCase().split('x');
- var width = Number(widthAndHeight[0]);
- var height = Number(widthAndHeight[1]);
- mediaConstraints.video.width.ideal = width;
- mediaConstraints.video.height.ideal = height;
- }
- if (!!publisherProperties.frameRate) {
- mediaConstraints.video.frameRate = { ideal: publisherProperties.frameRate };
- }
- if (!!publisherProperties.videoSource && typeof publisherProperties.videoSource === 'string') {
- if (publisherProperties.videoSource === 'screen') {
- if (platform.name !== 'Chrome' && platform.name.indexOf('Firefox') === -1) {
- var error = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_SHARING_NOT_SUPPORTED, 'You can only screen share in desktop Chrome and Firefox. Detected browser: ' + platform.name);
- console.error(error);
- reject(error);
- }
- else {
- if (!!_this.advancedConfiguration.screenShareChromeExtension && !(platform.name.indexOf('Firefox') !== -1)) {
- screenSharing.getScreenConstraints(function (error, screenConstraints) {
- if (!!error || !!screenConstraints.mandatory && screenConstraints.mandatory.chromeMediaSource === 'screen') {
- if (error === 'permission-denied' || error === 'PermissionDeniedError') {
- var error_1 = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_CAPTURE_DENIED, 'You must allow access to one window of your desktop');
- console.error(error_1);
- reject(error_1);
- }
- else {
- var extensionId = _this.advancedConfiguration.screenShareChromeExtension.split('/').pop().trim();
- screenSharing.getChromeExtensionStatus(extensionId, function (status) {
- if (status === 'installed-disabled') {
- var error_2 = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_EXTENSION_DISABLED, 'You must enable the screen extension');
- console.error(error_2);
- reject(error_2);
- }
- if (status === 'not-installed') {
- var error_3 = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_EXTENSION_NOT_INSTALLED, _this.advancedConfiguration.screenShareChromeExtension);
- console.error(error_3);
- reject(error_3);
- }
- });
- }
- }
- else {
- mediaConstraints.video = screenConstraints;
- resolve(mediaConstraints);
- }
- });
- }
- else {
- screenSharingAuto.getScreenId(function (error, sourceId, screenConstraints) {
- if (!!error) {
- if (error === 'not-installed') {
- var extensionUrl = !!_this.advancedConfiguration.screenShareChromeExtension ? _this.advancedConfiguration.screenShareChromeExtension :
- 'https://chrome.google.com/webstore/detail/openvidu-screensharing/lfcgfepafnobdloecchnfaclibenjold';
- var error_4 = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_EXTENSION_NOT_INSTALLED, extensionUrl);
- console.error(error_4);
- reject(error_4);
- }
- else if (error === 'installed-disabled') {
- var error_5 = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_EXTENSION_DISABLED, 'You must enable the screen extension');
- console.error(error_5);
- reject(error_5);
- }
- else if (error === 'permission-denied') {
- var error_6 = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_CAPTURE_DENIED, 'You must allow access to one window of your desktop');
- console.error(error_6);
- reject(error_6);
- }
- }
- else {
- mediaConstraints.video = screenConstraints.video;
- resolve(mediaConstraints);
- }
- });
- }
- publisherProperties.videoSource = 'screen';
- }
- }
- else {
- mediaConstraints.video['deviceId'] = { exact: publisherProperties.videoSource };
- resolve(mediaConstraints);
- }
- }
- else {
- resolve(mediaConstraints);
- }
- }
- else {
- resolve(mediaConstraints);
- }
- });
- };
- OpenVidu.prototype.startWs = function (onConnectSucces) {
- var config = {
- heartbeat: 5000,
- sendCloseMessage: false,
- ws: {
- uri: this.wsUri,
- useSockJS: false,
- onconnected: onConnectSucces,
- ondisconnect: this.disconnectCallback.bind(this),
- onreconnecting: this.reconnectingCallback.bind(this),
- onreconnected: this.reconnectedCallback.bind(this)
- },
- rpc: {
- requestTimeout: 10000,
- participantJoined: this.session.onParticipantJoined.bind(this.session),
- participantPublished: this.session.onParticipantPublished.bind(this.session),
- participantUnpublished: this.session.onParticipantUnpublished.bind(this.session),
- participantLeft: this.session.onParticipantLeft.bind(this.session),
- participantEvicted: this.session.onParticipantEvicted.bind(this.session),
- recordingStarted: this.session.onRecordingStarted.bind(this.session),
- recordingStopped: this.session.onRecordingStopped.bind(this.session),
- sendMessage: this.session.onNewMessage.bind(this.session),
- streamPropertyChanged: this.session.onStreamPropertyChanged.bind(this.session),
- iceCandidate: this.session.recvIceCandidate.bind(this.session),
- mediaError: this.session.onMediaError.bind(this.session)
- }
- };
- this.jsonRpcClient = new RpcBuilder.clients.JsonRpcClient(config);
- };
- OpenVidu.prototype.closeWs = function () {
- this.jsonRpcClient.close();
- };
- OpenVidu.prototype.sendRequest = function (method, params, callback) {
- if (params && params instanceof Function) {
- callback = params;
- params = {};
- }
- console.debug('Sending request: {method:"' + method + '", params: ' + JSON.stringify(params) + '}');
- this.jsonRpcClient.send(method, params, callback);
- };
- OpenVidu.prototype.isMediaStreamTrack = function (mediaSource) {
- var is = (!!mediaSource &&
- mediaSource.enabled !== undefined && typeof mediaSource.enabled === 'boolean' &&
- mediaSource.id !== undefined && typeof mediaSource.id === 'string' &&
- mediaSource.kind !== undefined && typeof mediaSource.kind === 'string' &&
- mediaSource.label !== undefined && typeof mediaSource.label === 'string' &&
- mediaSource.muted !== undefined && typeof mediaSource.muted === 'boolean' &&
- mediaSource.readyState !== undefined && typeof mediaSource.readyState === 'string');
- return is;
- };
- OpenVidu.prototype.getWsUri = function () {
- return this.wsUri;
- };
- OpenVidu.prototype.getSecret = function () {
- return this.secret;
- };
- OpenVidu.prototype.getRecorder = function () {
- return this.recorder;
- };
- OpenVidu.prototype.disconnectCallback = function () {
- console.warn('Websocket connection lost');
- if (this.isRoomAvailable()) {
- this.session.onLostConnection();
- }
- else {
- alert('Connection error. Please reload page.');
- }
- };
- OpenVidu.prototype.reconnectingCallback = function () {
- console.warn('Websocket connection lost (reconnecting)');
- if (this.isRoomAvailable()) {
- this.session.onLostConnection();
- }
- else {
- alert('Connection error. Please reload page.');
- }
- };
- OpenVidu.prototype.reconnectedCallback = function () {
- console.warn('Websocket reconnected');
- if (this.isRoomAvailable()) {
- this.session.onRecoveredConnection();
- }
- else {
- alert('Connection error. Please reload page.');
- }
- };
- OpenVidu.prototype.isRoomAvailable = function () {
- if (this.session !== undefined && this.session instanceof Session_1.Session) {
- return true;
- }
- else {
- console.warn('Session instance not found');
- return false;
- }
- };
- return OpenVidu;
-}());
-exports.OpenVidu = OpenVidu;
-
-},{"../OpenViduInternal/Enums/OpenViduError":26,"../OpenViduInternal/Enums/VideoInsertMode":27,"../OpenViduInternal/Events/StreamPropertyChangedEvent":36,"../OpenViduInternal/KurentoUtils/kurento-jsonrpc":43,"../OpenViduInternal/ScreenSharing/Screen-Capturing":48,"../OpenViduInternal/ScreenSharing/Screen-Capturing-Auto":47,"./LocalRecorder":18,"./Publisher":20,"./Session":21,"platform":8}],20:[function(require,module,exports){
-"use strict";
-var __extends = (this && this.__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 __());
- };
-})();
-Object.defineProperty(exports, "__esModule", { value: true });
-var Session_1 = require("./Session");
-var Stream_1 = require("./Stream");
-var StreamManager_1 = require("./StreamManager");
-var StreamEvent_1 = require("../OpenViduInternal/Events/StreamEvent");
-var StreamPropertyChangedEvent_1 = require("../OpenViduInternal/Events/StreamPropertyChangedEvent");
-var VideoElementEvent_1 = require("../OpenViduInternal/Events/VideoElementEvent");
-var OpenViduError_1 = require("../OpenViduInternal/Enums/OpenViduError");
-var platform = require("platform");
-var Publisher = (function (_super) {
- __extends(Publisher, _super);
- function Publisher(targEl, properties, openvidu) {
- var _this = _super.call(this, new Stream_1.Stream((!!openvidu.session) ? openvidu.session : new Session_1.Session(openvidu), { publisherProperties: properties, mediaConstraints: {} }), targEl) || this;
- _this.accessAllowed = false;
- _this.isSubscribedToRemote = false;
- _this.accessDenied = false;
- _this.properties = properties;
- _this.openvidu = openvidu;
- _this.stream.ee.on('local-stream-destroyed', function (reason) {
- _this.stream.isLocalStreamPublished = false;
- var streamEvent = new StreamEvent_1.StreamEvent(true, _this, 'streamDestroyed', _this.stream, reason);
- _this.emitEvent('streamDestroyed', [streamEvent]);
- streamEvent.callDefaultBehavior();
- });
- return _this;
- }
- Publisher.prototype.publishAudio = function (value) {
- var _this = this;
- if (this.stream.audioActive !== value) {
- this.stream.getMediaStream().getAudioTracks().forEach(function (track) {
- track.enabled = value;
- });
- this.session.openvidu.sendRequest('streamPropertyChanged', {
- streamId: this.stream.streamId,
- property: 'audioActive',
- newValue: value,
- reason: 'publishAudio'
- }, function (error, response) {
- if (error) {
- console.error("Error sending 'streamPropertyChanged' event", error);
- }
- else {
- _this.session.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent_1.StreamPropertyChangedEvent(_this.session, _this.stream, 'audioActive', value, !value, 'publishAudio')]);
- _this.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent_1.StreamPropertyChangedEvent(_this, _this.stream, 'audioActive', value, !value, 'publishAudio')]);
- }
- });
- this.stream.audioActive = value;
- console.info("'Publisher' has " + (value ? 'published' : 'unpublished') + ' its audio stream');
- }
- };
- Publisher.prototype.publishVideo = function (value) {
- var _this = this;
- if (this.stream.videoActive !== value) {
- this.stream.getMediaStream().getVideoTracks().forEach(function (track) {
- track.enabled = value;
- });
- this.session.openvidu.sendRequest('streamPropertyChanged', {
- streamId: this.stream.streamId,
- property: 'videoActive',
- newValue: value,
- reason: 'publishVideo'
- }, function (error, response) {
- if (error) {
- console.error("Error sending 'streamPropertyChanged' event", error);
- }
- else {
- _this.session.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent_1.StreamPropertyChangedEvent(_this.session, _this.stream, 'videoActive', value, !value, 'publishVideo')]);
- _this.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent_1.StreamPropertyChangedEvent(_this, _this.stream, 'videoActive', value, !value, 'publishVideo')]);
- }
- });
- this.stream.videoActive = value;
- console.info("'Publisher' has " + (value ? 'published' : 'unpublished') + ' its video stream');
- }
- };
- Publisher.prototype.subscribeToRemote = function (value) {
- value = (value !== undefined) ? value : true;
- this.isSubscribedToRemote = value;
- this.stream.subscribeToMyRemote(value);
- };
- Publisher.prototype.on = function (type, handler) {
- var _this = this;
- _super.prototype.on.call(this, type, handler);
- if (type === 'streamCreated') {
- if (!!this.stream && this.stream.isLocalStreamPublished) {
- this.emitEvent('streamCreated', [new StreamEvent_1.StreamEvent(false, this, 'streamCreated', this.stream, '')]);
- }
- else {
- this.stream.ee.on('stream-created-by-publisher', function () {
- _this.emitEvent('streamCreated', [new StreamEvent_1.StreamEvent(false, _this, 'streamCreated', _this.stream, '')]);
- });
- }
- }
- if (type === 'remoteVideoPlaying') {
- if (this.stream.displayMyRemote() && this.videos[0] && this.videos[0].video &&
- this.videos[0].video.currentTime > 0 &&
- this.videos[0].video.paused === false &&
- this.videos[0].video.ended === false &&
- this.videos[0].video.readyState === 4) {
- this.emitEvent('remoteVideoPlaying', [new VideoElementEvent_1.VideoElementEvent(this.videos[0].video, this, 'remoteVideoPlaying')]);
- }
- }
- if (type === 'accessAllowed') {
- if (this.accessAllowed) {
- this.emitEvent('accessAllowed', []);
- }
- }
- if (type === 'accessDenied') {
- if (this.accessDenied) {
- this.emitEvent('accessDenied', []);
- }
- }
- return this;
- };
- Publisher.prototype.once = function (type, handler) {
- var _this = this;
- _super.prototype.once.call(this, type, handler);
- if (type === 'streamCreated') {
- if (!!this.stream && this.stream.isLocalStreamPublished) {
- this.emitEvent('streamCreated', [new StreamEvent_1.StreamEvent(false, this, 'streamCreated', this.stream, '')]);
- }
- else {
- this.stream.ee.once('stream-created-by-publisher', function () {
- _this.emitEvent('streamCreated', [new StreamEvent_1.StreamEvent(false, _this, 'streamCreated', _this.stream, '')]);
- });
- }
- }
- if (type === 'remoteVideoPlaying') {
- if (this.stream.displayMyRemote() && this.videos[0] && this.videos[0].video &&
- this.videos[0].video.currentTime > 0 &&
- this.videos[0].video.paused === false &&
- this.videos[0].video.ended === false &&
- this.videos[0].video.readyState === 4) {
- this.emitEvent('remoteVideoPlaying', [new VideoElementEvent_1.VideoElementEvent(this.videos[0].video, this, 'remoteVideoPlaying')]);
- }
- }
- if (type === 'accessAllowed') {
- if (this.accessAllowed) {
- this.emitEvent('accessAllowed', []);
- }
- }
- if (type === 'accessDenied') {
- if (this.accessDenied) {
- this.emitEvent('accessDenied', []);
- }
- }
- return this;
- };
- Publisher.prototype.initialize = function () {
- var _this = this;
- return new Promise(function (resolve, reject) {
- var errorCallback = function (openViduError) {
- _this.accessDenied = true;
- _this.accessAllowed = false;
- reject(openViduError);
- };
- var successCallback = function (mediaStream) {
- _this.accessAllowed = true;
- _this.accessDenied = false;
- if (_this.openvidu.isMediaStreamTrack(_this.properties.audioSource)) {
- mediaStream.removeTrack(mediaStream.getAudioTracks()[0]);
- mediaStream.addTrack(_this.properties.audioSource);
- }
- if (_this.openvidu.isMediaStreamTrack(_this.properties.videoSource)) {
- mediaStream.removeTrack(mediaStream.getVideoTracks()[0]);
- mediaStream.addTrack(_this.properties.videoSource);
- }
- if (!!mediaStream.getAudioTracks()[0]) {
- mediaStream.getAudioTracks()[0].enabled = !!_this.stream.outboundStreamOpts.publisherProperties.publishAudio;
- }
- if (!!mediaStream.getVideoTracks()[0]) {
- mediaStream.getVideoTracks()[0].enabled = !!_this.stream.outboundStreamOpts.publisherProperties.publishVideo;
- }
- _this.videoReference = document.createElement('video');
- _this.videoReference.srcObject = mediaStream;
- _this.stream.setMediaStream(mediaStream);
- if (!_this.stream.displayMyRemote()) {
- _this.stream.updateMediaStreamInVideos();
- }
- if (!!_this.firstVideoElement) {
- _this.createVideoElement(_this.firstVideoElement.targetElement, _this.properties.insertMode);
- }
- delete _this.firstVideoElement;
- if (_this.stream.isSendVideo()) {
- if (!_this.stream.isSendScreen()) {
- var _a = mediaStream.getVideoTracks()[0].getSettings(), width = _a.width, height = _a.height;
- if (platform.name.toLowerCase().indexOf('mobile') !== -1 && (window.innerHeight > window.innerWidth)) {
- _this.stream.videoDimensions = {
- width: height || 0,
- height: width || 0
- };
- }
- else {
- _this.stream.videoDimensions = {
- width: width || 0,
- height: height || 0
- };
- }
- _this.stream.isLocalStreamReadyToPublish = true;
- _this.stream.ee.emitEvent('stream-ready-to-publish', []);
- }
- else {
- _this.videoReference.onloadedmetadata = function () {
- _this.stream.videoDimensions = {
- width: _this.videoReference.videoWidth,
- height: _this.videoReference.videoHeight
- };
- _this.screenShareResizeInterval = setInterval(function () {
- var firefoxSettings = mediaStream.getVideoTracks()[0].getSettings();
- var newWidth = (platform.name === 'Chrome') ? _this.videoReference.videoWidth : firefoxSettings.width;
- var newHeight = (platform.name === 'Chrome') ? _this.videoReference.videoHeight : firefoxSettings.height;
- if (_this.stream.isLocalStreamPublished &&
- (newWidth !== _this.stream.videoDimensions.width ||
- newHeight !== _this.stream.videoDimensions.height)) {
- var oldValue_1 = { width: _this.stream.videoDimensions.width, height: _this.stream.videoDimensions.height };
- _this.stream.videoDimensions = {
- width: newWidth || 0,
- height: newHeight || 0
- };
- _this.session.openvidu.sendRequest('streamPropertyChanged', {
- streamId: _this.stream.streamId,
- property: 'videoDimensions',
- newValue: JSON.stringify(_this.stream.videoDimensions),
- reason: 'screenResized'
- }, function (error, response) {
- if (error) {
- console.error("Error sending 'streamPropertyChanged' event", error);
- }
- else {
- _this.session.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent_1.StreamPropertyChangedEvent(_this.session, _this.stream, 'videoDimensions', _this.stream.videoDimensions, oldValue_1, 'screenResized')]);
- _this.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent_1.StreamPropertyChangedEvent(_this, _this.stream, 'videoDimensions', _this.stream.videoDimensions, oldValue_1, 'screenResized')]);
- }
- });
- }
- }, 500);
- _this.stream.isLocalStreamReadyToPublish = true;
- _this.stream.ee.emitEvent('stream-ready-to-publish', []);
- };
- }
- }
- else {
- _this.stream.isLocalStreamReadyToPublish = true;
- _this.stream.ee.emitEvent('stream-ready-to-publish', []);
- }
- resolve();
- };
- _this.openvidu.generateMediaConstraints(_this.properties)
- .then(function (constraints) {
- var outboundStreamOptions = {
- mediaConstraints: constraints,
- publisherProperties: _this.properties
- };
- _this.stream.setOutboundStreamOptions(outboundStreamOptions);
- var constraintsAux = {};
- var timeForDialogEvent = 1250;
- if (_this.stream.isSendVideo() || _this.stream.isSendAudio()) {
- var definedAudioConstraint_1 = ((constraints.audio === undefined) ? true : constraints.audio);
- constraintsAux.audio = _this.stream.isSendScreen() ? false : definedAudioConstraint_1;
- constraintsAux.video = constraints.video;
- var startTime_1 = Date.now();
- _this.setPermissionDialogTimer(timeForDialogEvent);
- navigator.mediaDevices.getUserMedia(constraintsAux)
- .then(function (mediaStream) {
- _this.clearPermissionDialogTimer(startTime_1, timeForDialogEvent);
- if (_this.stream.isSendScreen() && _this.stream.isSendAudio()) {
- constraintsAux.audio = definedAudioConstraint_1;
- constraintsAux.video = false;
- startTime_1 = Date.now();
- _this.setPermissionDialogTimer(timeForDialogEvent);
- navigator.mediaDevices.getUserMedia(constraintsAux)
- .then(function (audioOnlyStream) {
- _this.clearPermissionDialogTimer(startTime_1, timeForDialogEvent);
- mediaStream.addTrack(audioOnlyStream.getAudioTracks()[0]);
- successCallback(mediaStream);
- })
- .catch(function (error) {
- _this.clearPermissionDialogTimer(startTime_1, timeForDialogEvent);
- var errorName, errorMessage;
- switch (error.name.toLowerCase()) {
- case 'notfounderror':
- errorName = OpenViduError_1.OpenViduErrorName.INPUT_AUDIO_DEVICE_NOT_FOUND;
- errorMessage = error.toString();
- errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage));
- break;
- case 'notallowederror':
- errorName = OpenViduError_1.OpenViduErrorName.DEVICE_ACCESS_DENIED;
- errorMessage = error.toString();
- errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage));
- break;
- case 'overconstrainederror':
- if (error.constraint.toLowerCase() === 'deviceid') {
- errorName = OpenViduError_1.OpenViduErrorName.INPUT_AUDIO_DEVICE_NOT_FOUND;
- errorMessage = "Audio input device with deviceId '" + constraints.video.deviceId.exact + "' not found";
- }
- else {
- errorName = OpenViduError_1.OpenViduErrorName.PUBLISHER_PROPERTIES_ERROR;
- errorMessage = "Audio input device doesn't support the value passed for constraint '" + error.constraint + "'";
- }
- errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage));
- break;
- }
- });
- }
- else {
- successCallback(mediaStream);
- }
- })
- .catch(function (error) {
- _this.clearPermissionDialogTimer(startTime_1, timeForDialogEvent);
- var errorName, errorMessage;
- switch (error.name.toLowerCase()) {
- case 'notfounderror':
- navigator.mediaDevices.getUserMedia({
- audio: false,
- video: constraints.video
- })
- .then(function (mediaStream) {
- mediaStream.getVideoTracks().forEach(function (track) {
- track.stop();
- });
- errorName = OpenViduError_1.OpenViduErrorName.INPUT_AUDIO_DEVICE_NOT_FOUND;
- errorMessage = error.toString();
- errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage));
- }).catch(function (e) {
- errorName = OpenViduError_1.OpenViduErrorName.INPUT_VIDEO_DEVICE_NOT_FOUND;
- errorMessage = error.toString();
- errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage));
- });
- break;
- case 'notallowederror':
- errorName = _this.stream.isSendScreen() ? OpenViduError_1.OpenViduErrorName.SCREEN_CAPTURE_DENIED : OpenViduError_1.OpenViduErrorName.DEVICE_ACCESS_DENIED;
- errorMessage = error.toString();
- errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage));
- break;
- case 'overconstrainederror':
- navigator.mediaDevices.getUserMedia({
- audio: false,
- video: constraints.video
- })
- .then(function (mediaStream) {
- mediaStream.getVideoTracks().forEach(function (track) {
- track.stop();
- });
- if (error.constraint.toLowerCase() === 'deviceid') {
- errorName = OpenViduError_1.OpenViduErrorName.INPUT_AUDIO_DEVICE_NOT_FOUND;
- errorMessage = "Audio input device with deviceId '" + constraints.audio.deviceId.exact + "' not found";
- }
- else {
- errorName = OpenViduError_1.OpenViduErrorName.PUBLISHER_PROPERTIES_ERROR;
- errorMessage = "Audio input device doesn't support the value passed for constraint '" + error.constraint + "'";
- }
- errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage));
- }).catch(function (e) {
- if (error.constraint.toLowerCase() === 'deviceid') {
- errorName = OpenViduError_1.OpenViduErrorName.INPUT_VIDEO_DEVICE_NOT_FOUND;
- errorMessage = "Video input device with deviceId '" + constraints.video.deviceId.exact + "' not found";
- }
- else {
- errorName = OpenViduError_1.OpenViduErrorName.PUBLISHER_PROPERTIES_ERROR;
- errorMessage = "Video input device doesn't support the value passed for constraint '" + error.constraint + "'";
- }
- errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage));
- });
- break;
- }
- });
- }
- else {
- reject(new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.NO_INPUT_SOURCE_SET, "Properties 'audioSource' and 'videoSource' cannot be set to false or null at the same time when calling 'OpenVidu.initPublisher'"));
- }
- })
- .catch(function (error) {
- errorCallback(error);
- });
- });
- };
- Publisher.prototype.updateSession = function (session) {
- this.session = session;
- this.stream.session = session;
- };
- Publisher.prototype.reestablishStreamPlayingEvent = function () {
- if (this.ee.getListeners('streamPlaying').length > 0) {
- this.addPlayEventToFirstVideo();
- }
- };
- Publisher.prototype.setPermissionDialogTimer = function (waitTime) {
- var _this = this;
- this.permissionDialogTimeout = setTimeout(function () {
- _this.emitEvent('accessDialogOpened', []);
- }, waitTime);
- };
- Publisher.prototype.clearPermissionDialogTimer = function (startTime, waitTime) {
- clearTimeout(this.permissionDialogTimeout);
- if ((Date.now() - startTime) > waitTime) {
- this.emitEvent('accessDialogClosed', []);
- }
- };
- return Publisher;
-}(StreamManager_1.StreamManager));
-exports.Publisher = Publisher;
-
-},{"../OpenViduInternal/Enums/OpenViduError":26,"../OpenViduInternal/Events/StreamEvent":34,"../OpenViduInternal/Events/StreamPropertyChangedEvent":36,"../OpenViduInternal/Events/VideoElementEvent":37,"./Session":21,"./Stream":22,"./StreamManager":23,"platform":8}],21:[function(require,module,exports){
-"use strict";
-Object.defineProperty(exports, "__esModule", { value: true });
-var Connection_1 = require("./Connection");
-var Subscriber_1 = require("./Subscriber");
-var ConnectionEvent_1 = require("../OpenViduInternal/Events/ConnectionEvent");
-var RecordingEvent_1 = require("../OpenViduInternal/Events/RecordingEvent");
-var SessionDisconnectedEvent_1 = require("../OpenViduInternal/Events/SessionDisconnectedEvent");
-var SignalEvent_1 = require("../OpenViduInternal/Events/SignalEvent");
-var StreamEvent_1 = require("../OpenViduInternal/Events/StreamEvent");
-var StreamPropertyChangedEvent_1 = require("../OpenViduInternal/Events/StreamPropertyChangedEvent");
-var OpenViduError_1 = require("../OpenViduInternal/Enums/OpenViduError");
-var VideoInsertMode_1 = require("../OpenViduInternal/Enums/VideoInsertMode");
-var platform = require("platform");
-var EventEmitter = require("wolfy87-eventemitter");
-var Session = (function () {
- function Session(openvidu) {
- this.streamManagers = [];
- this.remoteStreamsCreated = {};
- this.remoteConnections = {};
- this.speakingEventsEnabled = false;
- this.ee = new EventEmitter();
- this.openvidu = openvidu;
- }
- Session.prototype.connect = function (token, metadata) {
- var _this = this;
- return new Promise(function (resolve, reject) {
- _this.processToken(token);
- if (_this.openvidu.checkSystemRequirements()) {
- _this.options = {
- sessionId: _this.sessionId,
- participantId: token,
- metadata: !!metadata ? _this.stringClientMetadata(metadata) : ''
- };
- _this.connectAux(token).then(function () {
- resolve();
- }).catch(function (error) {
- reject(error);
- });
- }
- else {
- reject(new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.BROWSER_NOT_SUPPORTED, 'Browser ' + platform.name + ' ' + platform.version + ' is not supported in OpenVidu'));
- }
- });
- };
- Session.prototype.disconnect = function () {
- this.leave(false, 'disconnect');
- };
- Session.prototype.subscribe = function (stream, targetElement, param3, param4) {
- var properties = {};
- if (!!param3 && typeof param3 !== 'function') {
- properties = {
- insertMode: (typeof param3.insertMode !== 'undefined') ? ((typeof param3.insertMode === 'string') ? VideoInsertMode_1.VideoInsertMode[param3.insertMode] : properties.insertMode) : VideoInsertMode_1.VideoInsertMode.APPEND,
- subscribeToAudio: (typeof param3.subscribeToAudio !== 'undefined') ? param3.subscribeToAudio : true,
- subscribeToVideo: (typeof param3.subscribeToVideo !== 'undefined') ? param3.subscribeToVideo : true
- };
- }
- else {
- properties = {
- insertMode: VideoInsertMode_1.VideoInsertMode.APPEND,
- subscribeToAudio: true,
- subscribeToVideo: true
- };
- }
- var completionHandler;
- if (!!param3 && (typeof param3 === 'function')) {
- completionHandler = param3;
- }
- else if (!!param4) {
- completionHandler = param4;
- }
- console.info('Subscribing to ' + stream.connection.connectionId);
- stream.subscribe()
- .then(function () {
- console.info('Subscribed correctly to ' + stream.connection.connectionId);
- if (completionHandler !== undefined) {
- completionHandler(undefined);
- }
- })
- .catch(function (error) {
- if (completionHandler !== undefined) {
- completionHandler(error);
- }
- });
- var subscriber = new Subscriber_1.Subscriber(stream, targetElement, properties);
- if (!!subscriber.targetElement) {
- stream.streamManager.createVideoElement(subscriber.targetElement, properties.insertMode);
- }
- return subscriber;
- };
- Session.prototype.subscribeAsync = function (stream, targetElement, properties) {
- var _this = this;
- return new Promise(function (resolve, reject) {
- var subscriber;
- var callback = function (error) {
- if (!!error) {
- reject(error);
- }
- else {
- resolve(subscriber);
- }
- };
- if (!!properties) {
- subscriber = _this.subscribe(stream, targetElement, properties, callback);
- }
- else {
- subscriber = _this.subscribe(stream, targetElement, callback);
- }
- });
- };
- Session.prototype.unsubscribe = function (subscriber) {
- var connectionId = subscriber.stream.connection.connectionId;
- console.info('Unsubscribing from ' + connectionId);
- this.openvidu.sendRequest('unsubscribeFromVideo', { sender: subscriber.stream.connection.connectionId }, function (error, response) {
- if (error) {
- console.error('Error unsubscribing from ' + connectionId, error);
- }
- else {
- console.info('Unsubscribed correctly from ' + connectionId);
- }
- subscriber.stream.disposeWebRtcPeer();
- subscriber.stream.disposeMediaStream();
- });
- subscriber.stream.streamManager.removeAllVideos();
- };
- Session.prototype.publish = function (publisher) {
- var _this = this;
- return new Promise(function (resolve, reject) {
- publisher.session = _this;
- publisher.stream.session = _this;
- if (!publisher.stream.publishedOnce) {
- _this.connection.addStream(publisher.stream);
- publisher.stream.publish()
- .then(function () {
- resolve();
- })
- .catch(function (error) {
- reject(error);
- });
- }
- else {
- publisher.initialize()
- .then(function () {
- _this.connection.addStream(publisher.stream);
- publisher.reestablishStreamPlayingEvent();
- publisher.stream.publish()
- .then(function () {
- resolve();
- })
- .catch(function (error) {
- reject(error);
- });
- }).catch(function (error) {
- reject(error);
- });
- }
- });
- };
- Session.prototype.unpublish = function (publisher) {
- var stream = publisher.stream;
- if (!stream.connection) {
- console.error('The associated Connection object of this Publisher is null', stream);
- return;
- }
- else if (stream.connection !== this.connection) {
- console.error('The associated Connection object of this Publisher is not your local Connection.' +
- "Only moderators can force unpublish on remote Streams via 'forceUnpublish' method", stream);
- return;
- }
- else {
- console.info('Unpublishing local media (' + stream.connection.connectionId + ')');
- this.openvidu.sendRequest('unpublishVideo', function (error, response) {
- if (error) {
- console.error(error);
- }
- else {
- console.info('Media unpublished correctly');
- }
- });
- stream.disposeWebRtcPeer();
- delete stream.connection.stream;
- var streamEvent = new StreamEvent_1.StreamEvent(true, publisher, 'streamDestroyed', publisher.stream, 'unpublish');
- publisher.emitEvent('streamDestroyed', [streamEvent]);
- streamEvent.callDefaultBehavior();
- }
- };
- Session.prototype.forceDisconnect = function (connection) {
- var _this = this;
- return new Promise(function (resolve, reject) {
- console.info('Forcing disconnect for connection ' + connection.connectionId);
- _this.openvidu.sendRequest('forceDisconnect', { connectionId: connection.connectionId }, function (error, response) {
- if (error) {
- console.error('Error forcing disconnect for Connection ' + connection.connectionId, error);
- if (error.code === 401) {
- reject(new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.OPENVIDU_PERMISSION_DENIED, "You don't have permissions to force a disconnection"));
- }
- else {
- reject(error);
- }
- }
- else {
- console.info('Forcing disconnect correctly for Connection ' + connection.connectionId);
- resolve();
- }
- });
- });
- };
- Session.prototype.forceUnpublish = function (stream) {
- var _this = this;
- return new Promise(function (resolve, reject) {
- console.info('Forcing unpublish for stream ' + stream.streamId);
- _this.openvidu.sendRequest('forceUnpublish', { streamId: stream.streamId }, function (error, response) {
- if (error) {
- console.error('Error forcing unpublish for Stream ' + stream.streamId, error);
- if (error.code === 401) {
- reject(new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.OPENVIDU_PERMISSION_DENIED, "You don't have permissions to force an unpublishing"));
- }
- else {
- reject(error);
- }
- }
- else {
- console.info('Forcing unpublish correctly for Stream ' + stream.streamId);
- resolve();
- }
- });
- });
- };
- Session.prototype.signal = function (signal) {
- var _this = this;
- return new Promise(function (resolve, reject) {
- var signalMessage = {};
- if (signal.to && signal.to.length > 0) {
- var connectionIds_1 = [];
- signal.to.forEach(function (connection) {
- connectionIds_1.push(connection.connectionId);
- });
- signalMessage['to'] = connectionIds_1;
- }
- else {
- signalMessage['to'] = [];
- }
- signalMessage['data'] = signal.data ? signal.data : '';
- signalMessage['type'] = signal.type ? signal.type : '';
- _this.openvidu.sendRequest('sendMessage', {
- message: JSON.stringify(signalMessage)
- }, function (error, response) {
- if (!!error) {
- reject(error);
- }
- else {
- resolve();
- }
- });
- });
- };
- Session.prototype.on = function (type, handler) {
- this.ee.on(type, function (event) {
- if (event) {
- console.info("Event '" + type + "' triggered by 'Session'", event);
- }
- else {
- console.info("Event '" + type + "' triggered by 'Session'");
- }
- handler(event);
- });
- if (type === 'publisherStartSpeaking' || type === 'publisherStopSpeaking') {
- this.speakingEventsEnabled = true;
- for (var connectionId in this.remoteConnections) {
- var str = this.remoteConnections[connectionId].stream;
- if (!!str && !str.speechEvent && str.hasAudio) {
- str.enableSpeakingEvents();
- }
- }
- }
- return this;
- };
- Session.prototype.once = function (type, handler) {
- this.ee.once(type, function (event) {
- if (event) {
- console.info("Event '" + type + "' triggered by 'Session'", event);
- }
- else {
- console.info("Event '" + type + "' triggered by 'Session'");
- }
- handler(event);
- });
- if (type === 'publisherStartSpeaking' || type === 'publisherStopSpeaking') {
- this.speakingEventsEnabled = true;
- for (var connectionId in this.remoteConnections) {
- var str = this.remoteConnections[connectionId].stream;
- if (!!str && !str.speechEvent && str.hasAudio) {
- str.enableOnceSpeakingEvents();
- }
- }
- }
- return this;
- };
- Session.prototype.off = function (type, handler) {
- if (!handler) {
- this.ee.removeAllListeners(type);
- }
- else {
- this.ee.off(type, handler);
- }
- if (type === 'publisherStartSpeaking' || type === 'publisherStopSpeaking') {
- this.speakingEventsEnabled = false;
- for (var connectionId in this.remoteConnections) {
- var str = this.remoteConnections[connectionId].stream;
- if (!!str && !!str.speechEvent) {
- str.disableSpeakingEvents();
- }
- }
- }
- return this;
- };
- Session.prototype.onParticipantJoined = function (response) {
- var _this = this;
- this.getConnection(response.id, '')
- .then(function (connection) {
- console.warn('Connection ' + response.id + ' already exists in connections list');
- })
- .catch(function (openViduError) {
- var connection = new Connection_1.Connection(_this, response);
- _this.remoteConnections[response.id] = connection;
- _this.ee.emitEvent('connectionCreated', [new ConnectionEvent_1.ConnectionEvent(false, _this, 'connectionCreated', connection, '')]);
- });
- };
- Session.prototype.onParticipantLeft = function (msg) {
- var _this = this;
- this.getRemoteConnection(msg.connectionId, 'Remote connection ' + msg.connectionId + " unknown when 'onParticipantLeft'. " +
- 'Existing remote connections: ' + JSON.stringify(Object.keys(this.remoteConnections)))
- .then(function (connection) {
- if (!!connection.stream) {
- var stream = connection.stream;
- var streamEvent = new StreamEvent_1.StreamEvent(true, _this, 'streamDestroyed', stream, msg.reason);
- _this.ee.emitEvent('streamDestroyed', [streamEvent]);
- streamEvent.callDefaultBehavior();
- delete _this.remoteStreamsCreated[stream.streamId];
- }
- delete _this.remoteConnections[connection.connectionId];
- _this.ee.emitEvent('connectionDestroyed', [new ConnectionEvent_1.ConnectionEvent(false, _this, 'connectionDestroyed', connection, msg.reason)]);
- })
- .catch(function (openViduError) {
- console.error(openViduError);
- });
- };
- Session.prototype.onParticipantPublished = function (response) {
- var _this = this;
- var afterConnectionFound = function (connection) {
- _this.remoteConnections[connection.connectionId] = connection;
- if (!_this.remoteStreamsCreated[connection.stream.streamId]) {
- _this.ee.emitEvent('streamCreated', [new StreamEvent_1.StreamEvent(false, _this, 'streamCreated', connection.stream, '')]);
- }
- _this.remoteStreamsCreated[connection.stream.streamId] = true;
- };
- var connection;
- this.getRemoteConnection(response.id, "Remote connection '" + response.id + "' unknown when 'onParticipantPublished'. " +
- 'Existing remote connections: ' + JSON.stringify(Object.keys(this.remoteConnections)))
- .then(function (con) {
- connection = con;
- response.metadata = con.data;
- connection.options = response;
- connection.initRemoteStreams(response.streams);
- afterConnectionFound(connection);
- })
- .catch(function (openViduError) {
- connection = new Connection_1.Connection(_this, response);
- afterConnectionFound(connection);
- });
- };
- Session.prototype.onParticipantUnpublished = function (msg) {
- var _this = this;
- if (msg.connectionId === this.connection.connectionId) {
- this.stopPublisherStream(msg.reason);
- }
- else {
- this.getRemoteConnection(msg.connectionId, "Remote connection '" + msg.connectionId + "' unknown when 'onParticipantUnpublished'. " +
- 'Existing remote connections: ' + JSON.stringify(Object.keys(this.remoteConnections)))
- .then(function (connection) {
- var streamEvent = new StreamEvent_1.StreamEvent(true, _this, 'streamDestroyed', connection.stream, msg.reason);
- _this.ee.emitEvent('streamDestroyed', [streamEvent]);
- streamEvent.callDefaultBehavior();
- var streamId = connection.stream.streamId;
- delete _this.remoteStreamsCreated[streamId];
- connection.removeStream(streamId);
- })
- .catch(function (openViduError) {
- console.error(openViduError);
- });
- }
- };
- Session.prototype.onParticipantEvicted = function (msg) {
- if (msg.connectionId === this.connection.connectionId) {
- if (!!this.sessionId && !this.connection.disposed) {
- this.leave(true, msg.reason);
- }
- }
- };
- Session.prototype.onNewMessage = function (msg) {
- var _this = this;
- console.info('New signal: ' + JSON.stringify(msg));
- this.getConnection(msg.from, "Connection '" + msg.from + "' unknow when 'onNewMessage'. Existing remote connections: "
- + JSON.stringify(Object.keys(this.remoteConnections)) + '. Existing local connection: ' + this.connection.connectionId)
- .then(function (connection) {
- _this.ee.emitEvent('signal', [new SignalEvent_1.SignalEvent(_this, msg.type, msg.data, connection)]);
- _this.ee.emitEvent('signal:' + msg.type, [new SignalEvent_1.SignalEvent(_this, msg.type, msg.data, connection)]);
- })
- .catch(function (openViduError) {
- console.error(openViduError);
- });
- };
- Session.prototype.onStreamPropertyChanged = function (msg) {
- var _this = this;
- this.getRemoteConnection(msg.connectionId, 'Remote connection ' + msg.connectionId + " unknown when 'onStreamPropertyChanged'. " +
- 'Existing remote connections: ' + JSON.stringify(Object.keys(this.remoteConnections)))
- .then(function (connection) {
- if (!!connection.stream && connection.stream.streamId === msg.streamId) {
- var stream = connection.stream;
- var oldValue = void 0;
- switch (msg.property) {
- case 'audioActive':
- oldValue = stream.audioActive;
- msg.newValue = msg.newValue === 'true';
- stream.audioActive = msg.newValue;
- break;
- case 'videoActive':
- oldValue = stream.videoActive;
- msg.newValue = msg.newValue === 'true';
- stream.videoActive = msg.newValue;
- break;
- case 'videoDimensions':
- oldValue = stream.videoDimensions;
- msg.newValue = JSON.parse(JSON.parse(msg.newValue));
- stream.videoDimensions = msg.newValue;
- break;
- }
- _this.ee.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent_1.StreamPropertyChangedEvent(_this, stream, msg.property, msg.newValue, oldValue, msg.reason)]);
- stream.streamManager.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent_1.StreamPropertyChangedEvent(stream.streamManager, stream, msg.property, msg.newValue, oldValue, msg.reason)]);
- }
- else {
- console.error("No stream with streamId '" + msg.streamId + "' found for connection '" + msg.connectionId + "' on 'streamPropertyChanged' event");
- }
- })
- .catch(function (openViduError) {
- console.error(openViduError);
- });
- };
- Session.prototype.recvIceCandidate = function (msg) {
- var candidate = {
- candidate: msg.candidate,
- sdpMid: msg.sdpMid,
- sdpMLineIndex: msg.sdpMLineIndex,
- toJSON: function () {
- return { candidate: msg.candidate };
- }
- };
- this.getConnection(msg.endpointName, 'Connection not found for endpoint ' + msg.endpointName + '. Ice candidate will be ignored: ' + candidate)
- .then(function (connection) {
- var stream = connection.stream;
- stream.getWebRtcPeer().addIceCandidate(candidate).catch(function (error) {
- console.error('Error adding candidate for ' + stream.streamId
- + ' stream of endpoint ' + msg.endpointName + ': ' + error);
- });
- })
- .catch(function (openViduError) {
- console.error(openViduError);
- });
- };
- Session.prototype.onSessionClosed = function (msg) {
- console.info('Session closed: ' + JSON.stringify(msg));
- var s = msg.sessionId;
- if (s !== undefined) {
- this.ee.emitEvent('session-closed', [{
- session: s
- }]);
- }
- else {
- console.warn('Session undefined on session closed', msg);
- }
- };
- Session.prototype.onLostConnection = function () {
- console.warn('Lost connection in Session ' + this.sessionId);
- if (!!this.sessionId && !this.connection.disposed) {
- this.leave(true, 'networkDisconnect');
- }
- };
- Session.prototype.onRecoveredConnection = function () {
- console.warn('Recovered connection in Session ' + this.sessionId);
- this.ee.emitEvent('connectionRecovered', []);
- };
- Session.prototype.onMediaError = function (params) {
- console.error('Media error: ' + JSON.stringify(params));
- var err = params.error;
- if (err) {
- this.ee.emitEvent('error-media', [{
- error: err
- }]);
- }
- else {
- console.warn('Received undefined media error. Params:', params);
- }
- };
- Session.prototype.onRecordingStarted = function (response) {
- this.ee.emitEvent('recordingStarted', [new RecordingEvent_1.RecordingEvent(this, 'recordingStarted', response.id, response.name)]);
- };
- Session.prototype.onRecordingStopped = function (response) {
- this.ee.emitEvent('recordingStopped', [new RecordingEvent_1.RecordingEvent(this, 'recordingStopped', response.id, response.name)]);
- };
- Session.prototype.emitEvent = function (type, eventArray) {
- this.ee.emitEvent(type, eventArray);
- };
- Session.prototype.leave = function (forced, reason) {
- var _this = this;
- forced = !!forced;
- console.info('Leaving Session (forced=' + forced + ')');
- if (!!this.connection) {
- if (!this.connection.disposed && !forced) {
- this.openvidu.sendRequest('leaveRoom', function (error, response) {
- if (error) {
- console.error(error);
- }
- _this.openvidu.closeWs();
- });
- }
- else {
- this.openvidu.closeWs();
- }
- this.stopPublisherStream(reason);
- if (!this.connection.disposed) {
- var sessionDisconnectEvent = new SessionDisconnectedEvent_1.SessionDisconnectedEvent(this, reason);
- this.ee.emitEvent('sessionDisconnected', [sessionDisconnectEvent]);
- sessionDisconnectEvent.callDefaultBehavior();
- }
- }
- else {
- console.warn('You were not connected to the session ' + this.sessionId);
- }
- };
- Session.prototype.connectAux = function (token) {
- var _this = this;
- return new Promise(function (resolve, reject) {
- _this.openvidu.startWs(function (error) {
- if (!!error) {
- reject(error);
- }
- else {
- var joinParams = {
- token: (!!token) ? token : '',
- session: _this.sessionId,
- metadata: !!_this.options.metadata ? _this.options.metadata : '',
- secret: _this.openvidu.getSecret(),
- recorder: _this.openvidu.getRecorder(),
- };
- _this.openvidu.sendRequest('joinRoom', joinParams, function (error, response) {
- if (!!error) {
- reject(error);
- }
- else {
- _this.capabilities = {
- subscribe: true,
- publish: _this.openvidu.role !== 'SUBSCRIBER',
- forceUnpublish: _this.openvidu.role === 'MODERATOR',
- forceDisconnect: _this.openvidu.role === 'MODERATOR'
- };
- _this.connection = new Connection_1.Connection(_this);
- _this.connection.connectionId = response.id;
- _this.connection.data = response.metadata;
- var events_1 = {
- connections: new Array(),
- streams: new Array()
- };
- var existingParticipants = response.value;
- existingParticipants.forEach(function (participant) {
- var connection = new Connection_1.Connection(_this, participant);
- _this.remoteConnections[connection.connectionId] = connection;
- events_1.connections.push(connection);
- if (!!connection.stream) {
- _this.remoteStreamsCreated[connection.stream.streamId] = true;
- events_1.streams.push(connection.stream);
- }
- });
- _this.ee.emitEvent('connectionCreated', [new ConnectionEvent_1.ConnectionEvent(false, _this, 'connectionCreated', _this.connection, '')]);
- events_1.connections.forEach(function (connection) {
- _this.ee.emitEvent('connectionCreated', [new ConnectionEvent_1.ConnectionEvent(false, _this, 'connectionCreated', connection, '')]);
- });
- events_1.streams.forEach(function (stream) {
- _this.ee.emitEvent('streamCreated', [new StreamEvent_1.StreamEvent(false, _this, 'streamCreated', stream, '')]);
- });
- resolve();
- }
- });
- }
- });
- });
- };
- Session.prototype.stopPublisherStream = function (reason) {
- if (!!this.connection.stream) {
- this.connection.stream.disposeWebRtcPeer();
- if (this.connection.stream.isLocalStreamPublished) {
- this.connection.stream.ee.emitEvent('local-stream-destroyed', [reason]);
- }
- }
- };
- Session.prototype.stringClientMetadata = function (metadata) {
- if (typeof metadata !== 'string') {
- return JSON.stringify(metadata);
- }
- else {
- return metadata;
- }
- };
- Session.prototype.getConnection = function (connectionId, errorMessage) {
- var _this = this;
- return new Promise(function (resolve, reject) {
- var connection = _this.remoteConnections[connectionId];
- if (!!connection) {
- resolve(connection);
- }
- else {
- if (_this.connection.connectionId === connectionId) {
- resolve(_this.connection);
- }
- else {
- reject(new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.GENERIC_ERROR, errorMessage));
- }
- }
- });
- };
- Session.prototype.getRemoteConnection = function (connectionId, errorMessage) {
- var _this = this;
- return new Promise(function (resolve, reject) {
- var connection = _this.remoteConnections[connectionId];
- if (!!connection) {
- resolve(connection);
- }
- else {
- reject(new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.GENERIC_ERROR, errorMessage));
- }
- });
- };
- Session.prototype.processToken = function (token) {
- var url = new URL(token);
- this.sessionId = url.searchParams.get('sessionId');
- var secret = url.searchParams.get('secret');
- var recorder = url.searchParams.get('recorder');
- var turnUsername = url.searchParams.get('turnUsername');
- var turnCredential = url.searchParams.get('turnCredential');
- var role = url.searchParams.get('role');
- if (!!secret) {
- this.openvidu.secret = secret;
- }
- if (!!recorder) {
- this.openvidu.recorder = true;
- }
- if (!!turnUsername && !!turnCredential) {
- var stunUrl = 'stun:' + url.hostname + ':3478';
- var turnUrl1 = 'turn:' + url.hostname + ':3478';
- var turnUrl2 = turnUrl1 + '?transport=tcp';
- this.openvidu.iceServers = [
- { urls: [stunUrl] },
- { urls: [turnUrl1, turnUrl2], username: turnUsername, credential: turnCredential }
- ];
- console.log('TURN temp credentials [' + turnUsername + ':' + turnCredential + ']');
- }
- if (!!role) {
- this.openvidu.role = role;
- }
- this.openvidu.wsUri = 'wss://' + url.host + '/openvidu';
- };
- return Session;
-}());
-exports.Session = Session;
-
-},{"../OpenViduInternal/Enums/OpenViduError":26,"../OpenViduInternal/Enums/VideoInsertMode":27,"../OpenViduInternal/Events/ConnectionEvent":28,"../OpenViduInternal/Events/RecordingEvent":31,"../OpenViduInternal/Events/SessionDisconnectedEvent":32,"../OpenViduInternal/Events/SignalEvent":33,"../OpenViduInternal/Events/StreamEvent":34,"../OpenViduInternal/Events/StreamPropertyChangedEvent":36,"./Connection":17,"./Subscriber":24,"platform":8,"wolfy87-eventemitter":15}],22:[function(require,module,exports){
-"use strict";
-Object.defineProperty(exports, "__esModule", { value: true });
-var WebRtcPeer_1 = require("../OpenViduInternal/WebRtcPeer/WebRtcPeer");
-var WebRtcStats_1 = require("../OpenViduInternal/WebRtcStats/WebRtcStats");
-var PublisherSpeakingEvent_1 = require("../OpenViduInternal/Events/PublisherSpeakingEvent");
-var EventEmitter = require("wolfy87-eventemitter");
-var hark = require("hark");
-var OpenViduError_1 = require("../OpenViduInternal/Enums/OpenViduError");
-var Stream = (function () {
- function Stream(session, options) {
- var _this = this;
- this.ee = new EventEmitter();
- this.isSubscribeToRemote = false;
- this.isLocalStreamReadyToPublish = false;
- this.isLocalStreamPublished = false;
- this.publishedOnce = false;
- this.session = session;
- if (options.hasOwnProperty('id')) {
- this.inboundStreamOpts = options;
- this.streamId = this.inboundStreamOpts.id;
- this.hasAudio = this.inboundStreamOpts.hasAudio;
- this.hasVideo = this.inboundStreamOpts.hasVideo;
- if (this.hasAudio) {
- this.audioActive = this.inboundStreamOpts.audioActive;
- }
- if (this.hasVideo) {
- this.videoActive = this.inboundStreamOpts.videoActive;
- this.typeOfVideo = (!this.inboundStreamOpts.typeOfVideo) ? undefined : this.inboundStreamOpts.typeOfVideo;
- this.frameRate = (this.inboundStreamOpts.frameRate === -1) ? undefined : this.inboundStreamOpts.frameRate;
- this.videoDimensions = this.inboundStreamOpts.videoDimensions;
- }
- }
- else {
- this.outboundStreamOpts = options;
- this.hasAudio = this.isSendAudio();
- this.hasVideo = this.isSendVideo();
- if (this.hasAudio) {
- this.audioActive = !!this.outboundStreamOpts.publisherProperties.publishAudio;
- }
- if (this.hasVideo) {
- this.videoActive = !!this.outboundStreamOpts.publisherProperties.publishVideo;
- this.frameRate = this.outboundStreamOpts.publisherProperties.frameRate;
- if (this.outboundStreamOpts.publisherProperties.videoSource instanceof MediaStreamTrack) {
- this.typeOfVideo = 'CUSTOM';
- }
- else {
- this.typeOfVideo = this.isSendScreen() ? 'SCREEN' : 'CAMERA';
- }
- }
- }
- this.ee.on('mediastream-updated', function () {
- _this.streamManager.updateMediaStream(_this.mediaStream);
- console.debug('Video srcObject [' + _this.mediaStream + '] updated in stream [' + _this.streamId + ']');
- });
- }
- Stream.prototype.getMediaStream = function () {
- return this.mediaStream;
- };
- Stream.prototype.setMediaStream = function (mediaStream) {
- this.mediaStream = mediaStream;
- };
- Stream.prototype.updateMediaStreamInVideos = function () {
- this.ee.emitEvent('mediastream-updated');
- };
- Stream.prototype.getWebRtcPeer = function () {
- return this.webRtcPeer;
- };
- Stream.prototype.getRTCPeerConnection = function () {
- return this.webRtcPeer.pc;
- };
- Stream.prototype.subscribeToMyRemote = function (value) {
- this.isSubscribeToRemote = value;
- };
- Stream.prototype.setOutboundStreamOptions = function (outboundStreamOpts) {
- this.outboundStreamOpts = outboundStreamOpts;
- };
- Stream.prototype.subscribe = function () {
- var _this = this;
- return new Promise(function (resolve, reject) {
- _this.initWebRtcPeerReceive()
- .then(function () {
- resolve();
- })
- .catch(function (error) {
- reject(error);
- });
- });
- };
- Stream.prototype.publish = function () {
- var _this = this;
- return new Promise(function (resolve, reject) {
- if (_this.isLocalStreamReadyToPublish) {
- _this.initWebRtcPeerSend()
- .then(function () {
- resolve();
- })
- .catch(function (error) {
- reject(error);
- });
- }
- else {
- _this.ee.once('stream-ready-to-publish', function () {
- _this.publish()
- .then(function () {
- resolve();
- })
- .catch(function (error) {
- reject(error);
- });
- });
- }
- });
- };
- Stream.prototype.disposeWebRtcPeer = function () {
- if (this.webRtcPeer) {
- this.webRtcPeer.dispose();
- }
- if (this.speechEvent) {
- this.speechEvent.stop();
- }
- this.stopWebRtcStats();
- console.info((!!this.outboundStreamOpts ? 'Outbound ' : 'Inbound ') + "WebRTCPeer from 'Stream' with id [" + this.streamId + '] is now closed');
- };
- Stream.prototype.disposeMediaStream = function () {
- if (this.mediaStream) {
- this.mediaStream.getAudioTracks().forEach(function (track) {
- track.stop();
- });
- this.mediaStream.getVideoTracks().forEach(function (track) {
- track.stop();
- });
- delete this.mediaStream;
- }
- console.info((!!this.outboundStreamOpts ? 'Local ' : 'Remote ') + "MediaStream from 'Stream' with id [" + this.streamId + '] is now disposed');
- };
- Stream.prototype.displayMyRemote = function () {
- return this.isSubscribeToRemote;
- };
- Stream.prototype.isSendAudio = function () {
- return (!!this.outboundStreamOpts &&
- this.outboundStreamOpts.publisherProperties.audioSource !== null &&
- this.outboundStreamOpts.publisherProperties.audioSource !== false);
- };
- Stream.prototype.isSendVideo = function () {
- return (!!this.outboundStreamOpts &&
- this.outboundStreamOpts.publisherProperties.videoSource !== null &&
- this.outboundStreamOpts.publisherProperties.videoSource !== false);
- };
- Stream.prototype.isSendScreen = function () {
- return (!!this.outboundStreamOpts &&
- this.outboundStreamOpts.publisherProperties.videoSource === 'screen');
- };
- Stream.prototype.setSpeechEventIfNotExists = function () {
- if (!this.speechEvent) {
- var harkOptions = this.session.openvidu.advancedConfiguration.publisherSpeakingEventsOptions || {};
- harkOptions.interval = (typeof harkOptions.interval === 'number') ? harkOptions.interval : 50;
- harkOptions.threshold = (typeof harkOptions.threshold === 'number') ? harkOptions.threshold : -50;
- this.speechEvent = hark(this.mediaStream, harkOptions);
- }
- };
- Stream.prototype.enableSpeakingEvents = function () {
- var _this = this;
- this.setSpeechEventIfNotExists();
- this.speechEvent.on('speaking', function () {
- _this.session.emitEvent('publisherStartSpeaking', [new PublisherSpeakingEvent_1.PublisherSpeakingEvent(_this.session, 'publisherStartSpeaking', _this.connection, _this.streamId)]);
- });
- this.speechEvent.on('stopped_speaking', function () {
- _this.session.emitEvent('publisherStopSpeaking', [new PublisherSpeakingEvent_1.PublisherSpeakingEvent(_this.session, 'publisherStopSpeaking', _this.connection, _this.streamId)]);
- });
- };
- Stream.prototype.enableOnceSpeakingEvents = function () {
- var _this = this;
- this.setSpeechEventIfNotExists();
- this.speechEvent.on('speaking', function () {
- _this.session.emitEvent('publisherStartSpeaking', [new PublisherSpeakingEvent_1.PublisherSpeakingEvent(_this.session, 'publisherStartSpeaking', _this.connection, _this.streamId)]);
- _this.disableSpeakingEvents();
- });
- this.speechEvent.on('stopped_speaking', function () {
- _this.session.emitEvent('publisherStopSpeaking', [new PublisherSpeakingEvent_1.PublisherSpeakingEvent(_this.session, 'publisherStopSpeaking', _this.connection, _this.streamId)]);
- _this.disableSpeakingEvents();
- });
- };
- Stream.prototype.disableSpeakingEvents = function () {
- this.speechEvent.stop();
- this.speechEvent = undefined;
- };
- Stream.prototype.isLocal = function () {
- return (!this.inboundStreamOpts && !!this.outboundStreamOpts);
- };
- Stream.prototype.getSelectedIceCandidate = function () {
- var _this = this;
- return new Promise(function (resolve, reject) {
- _this.webRtcStats.getSelectedIceCandidateInfo()
- .then(function (report) { return resolve(report); })
- .catch(function (error) { return reject(error); });
- });
- };
- Stream.prototype.getRemoteIceCandidateList = function () {
- return this.webRtcPeer.remoteCandidatesQueue;
- };
- Stream.prototype.getLocalIceCandidateList = function () {
- return this.webRtcPeer.localCandidatesQueue;
- };
- Stream.prototype.initWebRtcPeerSend = function () {
- var _this = this;
- return new Promise(function (resolve, reject) {
- var userMediaConstraints = {
- audio: _this.isSendAudio(),
- video: _this.isSendVideo()
- };
- var options = {
- mediaStream: _this.mediaStream,
- mediaConstraints: userMediaConstraints,
- onicecandidate: _this.connection.sendIceCandidate.bind(_this.connection),
- iceServers: _this.getIceServersConf(),
- simulcast: false
- };
- var successCallback = function (sdpOfferParam) {
- console.debug('Sending SDP offer to publish as '
- + _this.streamId, sdpOfferParam);
- var typeOfVideo = '';
- if (_this.isSendVideo()) {
- typeOfVideo = _this.outboundStreamOpts.publisherProperties.videoSource instanceof MediaStreamTrack ? 'CUSTOM' : (_this.isSendScreen() ? 'SCREEN' : 'CAMERA');
- }
- _this.session.openvidu.sendRequest('publishVideo', {
- sdpOffer: sdpOfferParam,
- doLoopback: _this.displayMyRemote() || false,
- hasAudio: _this.isSendAudio(),
- hasVideo: _this.isSendVideo(),
- audioActive: _this.audioActive,
- videoActive: _this.videoActive,
- typeOfVideo: typeOfVideo,
- frameRate: !!_this.frameRate ? _this.frameRate : -1,
- videoDimensions: JSON.stringify(_this.videoDimensions)
- }, function (error, response) {
- if (error) {
- if (error.code === 401) {
- reject(new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.OPENVIDU_PERMISSION_DENIED, "You don't have permissions to publish"));
- }
- else {
- reject('Error on publishVideo: ' + JSON.stringify(error));
- }
- }
- else {
- _this.webRtcPeer.processAnswer(response.sdpAnswer)
- .then(function () {
- _this.streamId = response.id;
- _this.isLocalStreamPublished = true;
- _this.publishedOnce = true;
- if (_this.displayMyRemote()) {
- _this.remotePeerSuccessfullyEstablished();
- }
- _this.ee.emitEvent('stream-created-by-publisher');
- _this.initWebRtcStats();
- resolve();
- })
- .catch(function (error) {
- reject(error);
- });
- console.info("'Publisher' successfully published to session");
- }
- });
- };
- if (_this.displayMyRemote()) {
- _this.webRtcPeer = new WebRtcPeer_1.WebRtcPeerSendrecv(options);
- }
- else {
- _this.webRtcPeer = new WebRtcPeer_1.WebRtcPeerSendonly(options);
- }
- _this.webRtcPeer.generateOffer().then(function (offer) {
- successCallback(offer);
- }).catch(function (error) {
- reject(new Error('(publish) SDP offer error: ' + JSON.stringify(error)));
- });
- });
- };
- Stream.prototype.initWebRtcPeerReceive = function () {
- var _this = this;
- return new Promise(function (resolve, reject) {
- var offerConstraints = {
- audio: _this.inboundStreamOpts.hasAudio,
- video: _this.inboundStreamOpts.hasVideo
- };
- console.debug("'Session.subscribe(Stream)' called. Constraints of generate SDP offer", offerConstraints);
- var options = {
- onicecandidate: _this.connection.sendIceCandidate.bind(_this.connection),
- mediaConstraints: offerConstraints,
- iceServers: _this.getIceServersConf(),
- simulcast: false
- };
- var successCallback = function (sdpOfferParam) {
- console.debug('Sending SDP offer to subscribe to '
- + _this.streamId, sdpOfferParam);
- _this.session.openvidu.sendRequest('receiveVideoFrom', {
- sender: _this.streamId,
- sdpOffer: sdpOfferParam
- }, function (error, response) {
- if (error) {
- reject(new Error('Error on recvVideoFrom: ' + JSON.stringify(error)));
- }
- else {
- _this.webRtcPeer.processAnswer(response.sdpAnswer).then(function () {
- _this.remotePeerSuccessfullyEstablished();
- _this.initWebRtcStats();
- resolve();
- }).catch(function (error) {
- reject(error);
- });
- }
- });
- };
- _this.webRtcPeer = new WebRtcPeer_1.WebRtcPeerRecvonly(options);
- _this.webRtcPeer.generateOffer()
- .then(function (offer) {
- successCallback(offer);
- })
- .catch(function (error) {
- reject(new Error('(subscribe) SDP offer error: ' + JSON.stringify(error)));
- });
- });
- };
- Stream.prototype.remotePeerSuccessfullyEstablished = function () {
- this.mediaStream = this.webRtcPeer.pc.getRemoteStreams()[0];
- console.debug('Peer remote stream', this.mediaStream);
- if (!!this.mediaStream) {
- this.ee.emitEvent('mediastream-updated');
- if (!this.displayMyRemote() && !!this.mediaStream.getAudioTracks()[0] && this.session.speakingEventsEnabled) {
- this.enableSpeakingEvents();
- }
- }
- };
- Stream.prototype.initWebRtcStats = function () {
- this.webRtcStats = new WebRtcStats_1.WebRtcStats(this);
- this.webRtcStats.initWebRtcStats();
- };
- Stream.prototype.stopWebRtcStats = function () {
- if (!!this.webRtcStats && this.webRtcStats.isEnabled()) {
- this.webRtcStats.stopWebRtcStats();
- }
- };
- Stream.prototype.getIceServersConf = function () {
- var returnValue;
- if (!!this.session.openvidu.advancedConfiguration.iceServers) {
- returnValue = this.session.openvidu.advancedConfiguration.iceServers === 'freeice' ?
- undefined :
- this.session.openvidu.advancedConfiguration.iceServers;
- }
- else if (this.session.openvidu.iceServers) {
- returnValue = this.session.openvidu.iceServers;
- }
- else {
- returnValue = undefined;
- }
- return returnValue;
- };
- return Stream;
-}());
-exports.Stream = Stream;
-
-},{"../OpenViduInternal/Enums/OpenViduError":26,"../OpenViduInternal/Events/PublisherSpeakingEvent":30,"../OpenViduInternal/WebRtcPeer/WebRtcPeer":49,"../OpenViduInternal/WebRtcStats/WebRtcStats":50,"hark":5,"wolfy87-eventemitter":15}],23:[function(require,module,exports){
-"use strict";
-Object.defineProperty(exports, "__esModule", { value: true });
-var StreamManagerEvent_1 = require("../OpenViduInternal/Events/StreamManagerEvent");
-var VideoElementEvent_1 = require("../OpenViduInternal/Events/VideoElementEvent");
-var VideoInsertMode_1 = require("../OpenViduInternal/Enums/VideoInsertMode");
-var EventEmitter = require("wolfy87-eventemitter");
-var StreamManager = (function () {
- function StreamManager(stream, targetElement) {
- var _this = this;
- this.videos = [];
- this.lazyLaunchVideoElementCreatedEvent = false;
- this.ee = new EventEmitter();
- this.stream = stream;
- this.stream.streamManager = this;
- this.remote = !this.stream.isLocal();
- if (!!targetElement) {
- var targEl = void 0;
- if (typeof targetElement === 'string') {
- targEl = document.getElementById(targetElement);
- }
- else if (targetElement instanceof HTMLElement) {
- targEl = targetElement;
- }
- if (!!targEl) {
- this.firstVideoElement = {
- targetElement: targEl,
- video: document.createElement('video'),
- id: ''
- };
- this.targetElement = targEl;
- this.element = targEl;
- }
- }
- this.canPlayListener = function () {
- if (_this.stream.isLocal()) {
- if (!_this.stream.displayMyRemote()) {
- console.info("Your local 'Stream' with id [" + _this.stream.streamId + '] video is now playing');
- _this.ee.emitEvent('videoPlaying', [new VideoElementEvent_1.VideoElementEvent(_this.videos[0].video, _this, 'videoPlaying')]);
- }
- else {
- console.info("Your own remote 'Stream' with id [" + _this.stream.streamId + '] video is now playing');
- _this.ee.emitEvent('remoteVideoPlaying', [new VideoElementEvent_1.VideoElementEvent(_this.videos[0].video, _this, 'remoteVideoPlaying')]);
- }
- }
- else {
- console.info("Remote 'Stream' with id [" + _this.stream.streamId + '] video is now playing');
- _this.ee.emitEvent('videoPlaying', [new VideoElementEvent_1.VideoElementEvent(_this.videos[0].video, _this, 'videoPlaying')]);
- }
- _this.ee.emitEvent('streamPlaying', [new StreamManagerEvent_1.StreamManagerEvent(_this)]);
- };
- }
- StreamManager.prototype.on = function (type, handler) {
- var _this = this;
- this.ee.on(type, function (event) {
- if (event) {
- console.info("Event '" + type + "' triggered by '" + (_this.remote ? 'Subscriber' : 'Publisher') + "'", event);
- }
- else {
- console.info("Event '" + type + "' triggered by '" + (_this.remote ? 'Subscriber' : 'Publisher') + "'");
- }
- handler(event);
- });
- if (type === 'videoElementCreated') {
- if (!!this.stream && this.lazyLaunchVideoElementCreatedEvent) {
- this.ee.emitEvent('videoElementCreated', [new VideoElementEvent_1.VideoElementEvent(this.videos[0].video, this, 'videoElementCreated')]);
- this.lazyLaunchVideoElementCreatedEvent = false;
- }
- }
- if (type === 'streamPlaying' || type === 'videoPlaying') {
- if (this.videos[0] && this.videos[0].video &&
- this.videos[0].video.currentTime > 0 &&
- this.videos[0].video.paused === false &&
- this.videos[0].video.ended === false &&
- this.videos[0].video.readyState === 4) {
- this.ee.emitEvent('streamPlaying', [new StreamManagerEvent_1.StreamManagerEvent(this)]);
- this.ee.emitEvent('videoPlaying', [new VideoElementEvent_1.VideoElementEvent(this.videos[0].video, this, 'videoPlaying')]);
- }
- }
- return this;
- };
- StreamManager.prototype.once = function (type, handler) {
- this.ee.once(type, function (event) {
- if (event) {
- console.info("Event '" + type + "' triggered once", event);
- }
- else {
- console.info("Event '" + type + "' triggered once");
- }
- handler(event);
- });
- if (type === 'videoElementCreated') {
- if (!!this.stream && this.lazyLaunchVideoElementCreatedEvent) {
- this.ee.emitEvent('videoElementCreated', [new VideoElementEvent_1.VideoElementEvent(this.videos[0].video, this, 'videoElementCreated')]);
- }
- }
- if (type === 'streamPlaying' || type === 'videoPlaying') {
- if (this.videos[0] && this.videos[0].video &&
- this.videos[0].video.currentTime > 0 &&
- this.videos[0].video.paused === false &&
- this.videos[0].video.ended === false &&
- this.videos[0].video.readyState === 4) {
- this.ee.emitEvent('streamPlaying', [new StreamManagerEvent_1.StreamManagerEvent(this)]);
- this.ee.emitEvent('videoPlaying', [new VideoElementEvent_1.VideoElementEvent(this.videos[0].video, this, 'videoPlaying')]);
- }
- }
- return this;
- };
- StreamManager.prototype.off = function (type, handler) {
- if (!handler) {
- this.ee.removeAllListeners(type);
- }
- else {
- this.ee.off(type, handler);
- }
- return this;
- };
- StreamManager.prototype.addVideoElement = function (video) {
- this.initializeVideoProperties(video);
- for (var _i = 0, _a = this.videos; _i < _a.length; _i++) {
- var v = _a[_i];
- if (v.video === video) {
- return 0;
- }
- }
- var returnNumber = 1;
- for (var _b = 0, _c = this.stream.session.streamManagers; _b < _c.length; _b++) {
- var streamManager = _c[_b];
- if (streamManager.disassociateVideo(video)) {
- returnNumber = -1;
- break;
- }
- }
- this.stream.session.streamManagers.forEach(function (streamManager) {
- streamManager.disassociateVideo(video);
- });
- this.pushNewStreamManagerVideo({
- video: video,
- id: video.id
- });
- console.info('New video element associated to ', this);
- return returnNumber;
- };
- StreamManager.prototype.createVideoElement = function (targetElement, insertMode) {
- var targEl;
- if (typeof targetElement === 'string') {
- targEl = document.getElementById(targEl);
- if (!targEl) {
- throw new Error("The provided 'targetElement' couldn't be resolved to any HTML element: " + targetElement);
- }
- }
- else if (targetElement instanceof HTMLElement) {
- targEl = targetElement;
- }
- else {
- throw new Error("The provided 'targetElement' couldn't be resolved to any HTML element: " + targetElement);
- }
- var video = document.createElement('video');
- this.initializeVideoProperties(video);
- var insMode = !!insertMode ? insertMode : VideoInsertMode_1.VideoInsertMode.APPEND;
- switch (insMode) {
- case VideoInsertMode_1.VideoInsertMode.AFTER:
- targEl.parentNode.insertBefore(video, targEl.nextSibling);
- break;
- case VideoInsertMode_1.VideoInsertMode.APPEND:
- targEl.appendChild(video);
- break;
- case VideoInsertMode_1.VideoInsertMode.BEFORE:
- targEl.parentNode.insertBefore(video, targEl);
- break;
- case VideoInsertMode_1.VideoInsertMode.PREPEND:
- targEl.insertBefore(video, targEl.childNodes[0]);
- break;
- case VideoInsertMode_1.VideoInsertMode.REPLACE:
- targEl.parentNode.replaceChild(video, targEl);
- break;
- default:
- insMode = VideoInsertMode_1.VideoInsertMode.APPEND;
- targEl.appendChild(video);
- break;
- }
- var v = {
- targetElement: targEl,
- video: video,
- insertMode: insMode,
- id: video.id
- };
- this.pushNewStreamManagerVideo(v);
- this.ee.emitEvent('videoElementCreated', [new VideoElementEvent_1.VideoElementEvent(v.video, this, 'videoElementCreated')]);
- this.lazyLaunchVideoElementCreatedEvent = !!this.firstVideoElement;
- return video;
- };
- StreamManager.prototype.initializeVideoProperties = function (video) {
- if (!(this.stream.isLocal() && this.stream.displayMyRemote())) {
- video.srcObject = this.stream.getMediaStream();
- }
- video.autoplay = true;
- video.controls = false;
- if (!video.id) {
- video.id = (this.remote ? 'remote-' : 'local-') + 'video-' + this.stream.streamId;
- if (!this.id && !!this.targetElement) {
- this.id = video.id;
- }
- }
- if (!this.remote && !this.stream.displayMyRemote()) {
- video.muted = true;
- if (this.stream.outboundStreamOpts.publisherProperties.mirror) {
- this.mirrorVideo(video);
- }
- }
- };
- StreamManager.prototype.removeAllVideos = function () {
- var _this = this;
- for (var i = this.stream.session.streamManagers.length - 1; i >= 0; --i) {
- if (this.stream.session.streamManagers[i] === this) {
- this.stream.session.streamManagers.splice(i, 1);
- }
- }
- this.videos.slice().reverse().forEach(function (streamManagerVideo, index, videos) {
- streamManagerVideo.video.removeEventListener('canplay', _this.canPlayListener);
- if (!!streamManagerVideo.targetElement) {
- streamManagerVideo.video.parentNode.removeChild(streamManagerVideo.video);
- _this.ee.emitEvent('videoElementDestroyed', [new VideoElementEvent_1.VideoElementEvent(streamManagerVideo.video, _this, 'videoElementDestroyed')]);
- _this.videos.splice(videos.length - 1 - index, 1);
- }
- else {
- streamManagerVideo.video.srcObject = null;
- }
- });
- };
- StreamManager.prototype.disassociateVideo = function (video) {
- var disassociated = false;
- for (var i = 0; i < this.videos.length; i++) {
- if (this.videos[i].video === video) {
- this.videos.splice(i, 1);
- disassociated = true;
- console.info('Video element disassociated from ', this);
- break;
- }
- }
- return disassociated;
- };
- StreamManager.prototype.addPlayEventToFirstVideo = function () {
- if ((!!this.videos[0]) && (!!this.videos[0].video) && (this.videos[0].video.oncanplay === null)) {
- this.videos[0].video.addEventListener('canplay', this.canPlayListener);
- }
- };
- StreamManager.prototype.updateMediaStream = function (mediaStream) {
- this.videos.forEach(function (streamManagerVideo) {
- streamManagerVideo.video.srcObject = mediaStream;
- });
- };
- StreamManager.prototype.emitEvent = function (type, eventArray) {
- this.ee.emitEvent(type, eventArray);
- };
- StreamManager.prototype.pushNewStreamManagerVideo = function (streamManagerVideo) {
- this.videos.push(streamManagerVideo);
- this.addPlayEventToFirstVideo();
- if (this.stream.session.streamManagers.indexOf(this) === -1) {
- this.stream.session.streamManagers.push(this);
- }
- };
- StreamManager.prototype.mirrorVideo = function (video) {
- video.style.transform = 'rotateY(180deg)';
- video.style.webkitTransform = 'rotateY(180deg)';
- };
- return StreamManager;
-}());
-exports.StreamManager = StreamManager;
-
-},{"../OpenViduInternal/Enums/VideoInsertMode":27,"../OpenViduInternal/Events/StreamManagerEvent":35,"../OpenViduInternal/Events/VideoElementEvent":37,"wolfy87-eventemitter":15}],24:[function(require,module,exports){
-"use strict";
-var __extends = (this && this.__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 __());
- };
-})();
-Object.defineProperty(exports, "__esModule", { value: true });
-var StreamManager_1 = require("./StreamManager");
-var Subscriber = (function (_super) {
- __extends(Subscriber, _super);
- function Subscriber(stream, targEl, properties) {
- var _this = _super.call(this, stream, targEl) || this;
- _this.element = _this.targetElement;
- _this.stream = stream;
- _this.properties = properties;
- return _this;
- }
- Subscriber.prototype.subscribeToAudio = function (value) {
- this.stream.getMediaStream().getAudioTracks().forEach(function (track) {
- track.enabled = value;
- });
- console.info("'Subscriber' has " + (value ? 'subscribed to' : 'unsubscribed from') + ' its audio stream');
- return this;
- };
- Subscriber.prototype.subscribeToVideo = function (value) {
- this.stream.getMediaStream().getVideoTracks().forEach(function (track) {
- track.enabled = value;
- });
- console.info("'Subscriber' has " + (value ? 'subscribed to' : 'unsubscribed from') + ' its video stream');
- return this;
- };
- return Subscriber;
-}(StreamManager_1.StreamManager));
-exports.Subscriber = Subscriber;
-
-},{"./StreamManager":23}],25:[function(require,module,exports){
-"use strict";
-Object.defineProperty(exports, "__esModule", { value: true });
-var LocalRecorderState;
-(function (LocalRecorderState) {
- LocalRecorderState["READY"] = "READY";
- LocalRecorderState["RECORDING"] = "RECORDING";
- LocalRecorderState["PAUSED"] = "PAUSED";
- LocalRecorderState["FINISHED"] = "FINISHED";
-})(LocalRecorderState = exports.LocalRecorderState || (exports.LocalRecorderState = {}));
-
-},{}],26:[function(require,module,exports){
-"use strict";
-Object.defineProperty(exports, "__esModule", { value: true });
-var OpenViduErrorName;
-(function (OpenViduErrorName) {
- OpenViduErrorName["BROWSER_NOT_SUPPORTED"] = "BROWSER_NOT_SUPPORTED";
- OpenViduErrorName["DEVICE_ACCESS_DENIED"] = "DEVICE_ACCESS_DENIED";
- OpenViduErrorName["SCREEN_CAPTURE_DENIED"] = "SCREEN_CAPTURE_DENIED";
- OpenViduErrorName["SCREEN_SHARING_NOT_SUPPORTED"] = "SCREEN_SHARING_NOT_SUPPORTED";
- OpenViduErrorName["SCREEN_EXTENSION_NOT_INSTALLED"] = "SCREEN_EXTENSION_NOT_INSTALLED";
- OpenViduErrorName["SCREEN_EXTENSION_DISABLED"] = "SCREEN_EXTENSION_DISABLED";
- OpenViduErrorName["INPUT_VIDEO_DEVICE_NOT_FOUND"] = "INPUT_VIDEO_DEVICE_NOT_FOUND";
- OpenViduErrorName["INPUT_AUDIO_DEVICE_NOT_FOUND"] = "INPUT_AUDIO_DEVICE_NOT_FOUND";
- OpenViduErrorName["NO_INPUT_SOURCE_SET"] = "NO_INPUT_SOURCE_SET";
- OpenViduErrorName["PUBLISHER_PROPERTIES_ERROR"] = "PUBLISHER_PROPERTIES_ERROR";
- OpenViduErrorName["OPENVIDU_PERMISSION_DENIED"] = "OPENVIDU_PERMISSION_DENIED";
- OpenViduErrorName["OPENVIDU_NOT_CONNECTED"] = "OPENVIDU_NOT_CONNECTED";
- OpenViduErrorName["GENERIC_ERROR"] = "GENERIC_ERROR";
-})(OpenViduErrorName = exports.OpenViduErrorName || (exports.OpenViduErrorName = {}));
-var OpenViduError = (function () {
- function OpenViduError(name, message) {
- this.name = name;
- this.message = message;
- }
- return OpenViduError;
-}());
-exports.OpenViduError = OpenViduError;
-
-},{}],27:[function(require,module,exports){
-"use strict";
-Object.defineProperty(exports, "__esModule", { value: true });
-var VideoInsertMode;
-(function (VideoInsertMode) {
- VideoInsertMode["AFTER"] = "AFTER";
- VideoInsertMode["APPEND"] = "APPEND";
- VideoInsertMode["BEFORE"] = "BEFORE";
- VideoInsertMode["PREPEND"] = "PREPEND";
- VideoInsertMode["REPLACE"] = "REPLACE";
-})(VideoInsertMode = exports.VideoInsertMode || (exports.VideoInsertMode = {}));
-
-},{}],28:[function(require,module,exports){
-"use strict";
-var __extends = (this && this.__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 __());
- };
-})();
-Object.defineProperty(exports, "__esModule", { value: true });
-var Event_1 = require("./Event");
-var ConnectionEvent = (function (_super) {
- __extends(ConnectionEvent, _super);
- function ConnectionEvent(cancelable, target, type, connection, reason) {
- var _this = _super.call(this, cancelable, target, type) || this;
- _this.connection = connection;
- _this.reason = reason;
- return _this;
- }
- ConnectionEvent.prototype.callDefaultBehavior = function () { };
- return ConnectionEvent;
-}(Event_1.Event));
-exports.ConnectionEvent = ConnectionEvent;
-
-},{"./Event":29}],29:[function(require,module,exports){
-"use strict";
-Object.defineProperty(exports, "__esModule", { value: true });
-var Event = (function () {
- function Event(cancelable, target, type) {
- this.hasBeenPrevented = false;
- this.cancelable = cancelable;
- this.target = target;
- this.type = type;
- }
- Event.prototype.isDefaultPrevented = function () {
- return this.hasBeenPrevented;
- };
- Event.prototype.preventDefault = function () {
- this.callDefaultBehavior = function () { };
- this.hasBeenPrevented = true;
- };
- return Event;
-}());
-exports.Event = Event;
-
-},{}],30:[function(require,module,exports){
-"use strict";
-var __extends = (this && this.__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 __());
- };
-})();
-Object.defineProperty(exports, "__esModule", { value: true });
-var Event_1 = require("./Event");
-var PublisherSpeakingEvent = (function (_super) {
- __extends(PublisherSpeakingEvent, _super);
- function PublisherSpeakingEvent(target, type, connection, streamId) {
- var _this = _super.call(this, false, target, type) || this;
- _this.type = type;
- _this.connection = connection;
- _this.streamId = streamId;
- return _this;
- }
- PublisherSpeakingEvent.prototype.callDefaultBehavior = function () { };
- return PublisherSpeakingEvent;
-}(Event_1.Event));
-exports.PublisherSpeakingEvent = PublisherSpeakingEvent;
-
-},{"./Event":29}],31:[function(require,module,exports){
-"use strict";
-var __extends = (this && this.__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 __());
- };
-})();
-Object.defineProperty(exports, "__esModule", { value: true });
-var Event_1 = require("./Event");
-var RecordingEvent = (function (_super) {
- __extends(RecordingEvent, _super);
- function RecordingEvent(target, type, id, name) {
- var _this = _super.call(this, false, target, type) || this;
- _this.id = id;
- if (name !== id) {
- _this.name = name;
- }
- return _this;
- }
- RecordingEvent.prototype.callDefaultBehavior = function () { };
- return RecordingEvent;
-}(Event_1.Event));
-exports.RecordingEvent = RecordingEvent;
-
-},{"./Event":29}],32:[function(require,module,exports){
-"use strict";
-var __extends = (this && this.__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 __());
- };
-})();
-Object.defineProperty(exports, "__esModule", { value: true });
-var Event_1 = require("./Event");
-var SessionDisconnectedEvent = (function (_super) {
- __extends(SessionDisconnectedEvent, _super);
- function SessionDisconnectedEvent(target, reason) {
- var _this = _super.call(this, true, target, 'sessionDisconnected') || this;
- _this.reason = reason;
- return _this;
- }
- SessionDisconnectedEvent.prototype.callDefaultBehavior = function () {
- console.info("Calling default behavior upon '" + this.type + "' event dispatched by 'Session'");
- var session = this.target;
- for (var connectionId in session.remoteConnections) {
- if (!!session.remoteConnections[connectionId].stream) {
- session.remoteConnections[connectionId].stream.disposeWebRtcPeer();
- session.remoteConnections[connectionId].stream.disposeMediaStream();
- if (session.remoteConnections[connectionId].stream.streamManager) {
- session.remoteConnections[connectionId].stream.streamManager.removeAllVideos();
- }
- delete session.remoteStreamsCreated[session.remoteConnections[connectionId].stream.streamId];
- session.remoteConnections[connectionId].dispose();
- }
- delete session.remoteConnections[connectionId];
- }
- };
- return SessionDisconnectedEvent;
-}(Event_1.Event));
-exports.SessionDisconnectedEvent = SessionDisconnectedEvent;
-
-},{"./Event":29}],33:[function(require,module,exports){
-"use strict";
-var __extends = (this && this.__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 __());
- };
-})();
-Object.defineProperty(exports, "__esModule", { value: true });
-var Event_1 = require("./Event");
-var SignalEvent = (function (_super) {
- __extends(SignalEvent, _super);
- function SignalEvent(target, type, data, from) {
- var _this = _super.call(this, false, target, type) || this;
- _this.type = type;
- _this.data = data;
- _this.from = from;
- return _this;
- }
- SignalEvent.prototype.callDefaultBehavior = function () { };
- return SignalEvent;
-}(Event_1.Event));
-exports.SignalEvent = SignalEvent;
-
-},{"./Event":29}],34:[function(require,module,exports){
-"use strict";
-var __extends = (this && this.__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 __());
- };
-})();
-Object.defineProperty(exports, "__esModule", { value: true });
-var Event_1 = require("./Event");
-var Publisher_1 = require("../../OpenVidu/Publisher");
-var Session_1 = require("../../OpenVidu/Session");
-var StreamEvent = (function (_super) {
- __extends(StreamEvent, _super);
- function StreamEvent(cancelable, target, type, stream, reason) {
- var _this = _super.call(this, cancelable, target, type) || this;
- _this.stream = stream;
- _this.reason = reason;
- return _this;
- }
- StreamEvent.prototype.callDefaultBehavior = function () {
- if (this.type === 'streamDestroyed') {
- if (this.target instanceof Session_1.Session) {
- console.info("Calling default behavior upon '" + this.type + "' event dispatched by 'Session'");
- this.stream.disposeWebRtcPeer();
- }
- else if (this.target instanceof Publisher_1.Publisher) {
- console.info("Calling default behavior upon '" + this.type + "' event dispatched by 'Publisher'");
- clearInterval(this.target.screenShareResizeInterval);
- this.stream.isLocalStreamReadyToPublish = false;
- var openviduPublishers = this.target.openvidu.publishers;
- for (var i = 0; i < openviduPublishers.length; i++) {
- if (openviduPublishers[i] === this.target) {
- openviduPublishers.splice(i, 1);
- break;
- }
- }
- }
- this.stream.disposeMediaStream();
- if (this.stream.streamManager)
- this.stream.streamManager.removeAllVideos();
- delete this.stream.session.remoteStreamsCreated[this.stream.streamId];
- var remoteConnection = this.stream.session.remoteConnections[this.stream.connection.connectionId];
- if (!!remoteConnection && !!remoteConnection.options) {
- var streamOptionsServer = remoteConnection.options.streams;
- for (var i = streamOptionsServer.length - 1; i >= 0; --i) {
- if (streamOptionsServer[i].id === this.stream.streamId) {
- streamOptionsServer.splice(i, 1);
- }
- }
- }
- }
- };
- return StreamEvent;
-}(Event_1.Event));
-exports.StreamEvent = StreamEvent;
-
-},{"../../OpenVidu/Publisher":20,"../../OpenVidu/Session":21,"./Event":29}],35:[function(require,module,exports){
-"use strict";
-var __extends = (this && this.__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 __());
- };
-})();
-Object.defineProperty(exports, "__esModule", { value: true });
-var Event_1 = require("./Event");
-var StreamManagerEvent = (function (_super) {
- __extends(StreamManagerEvent, _super);
- function StreamManagerEvent(target) {
- return _super.call(this, false, target, 'streamPlaying') || this;
- }
- StreamManagerEvent.prototype.callDefaultBehavior = function () { };
- return StreamManagerEvent;
-}(Event_1.Event));
-exports.StreamManagerEvent = StreamManagerEvent;
-
-},{"./Event":29}],36:[function(require,module,exports){
-"use strict";
-var __extends = (this && this.__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 __());
- };
-})();
-Object.defineProperty(exports, "__esModule", { value: true });
-var Event_1 = require("./Event");
-var StreamPropertyChangedEvent = (function (_super) {
- __extends(StreamPropertyChangedEvent, _super);
- function StreamPropertyChangedEvent(target, stream, changedProperty, newValue, oldValue, reason) {
- var _this = _super.call(this, false, target, 'streamPropertyChanged') || this;
- _this.stream = stream;
- _this.changedProperty = changedProperty;
- _this.newValue = newValue;
- _this.oldValue = oldValue;
- _this.reason = reason;
- return _this;
- }
- StreamPropertyChangedEvent.prototype.callDefaultBehavior = function () { };
- return StreamPropertyChangedEvent;
-}(Event_1.Event));
-exports.StreamPropertyChangedEvent = StreamPropertyChangedEvent;
-
-},{"./Event":29}],37:[function(require,module,exports){
-"use strict";
-var __extends = (this && this.__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 __());
- };
-})();
-Object.defineProperty(exports, "__esModule", { value: true });
-var Event_1 = require("./Event");
-var VideoElementEvent = (function (_super) {
- __extends(VideoElementEvent, _super);
- function VideoElementEvent(element, target, type) {
- var _this = _super.call(this, false, target, type) || this;
- _this.element = element;
- return _this;
- }
- VideoElementEvent.prototype.callDefaultBehavior = function () { };
- return VideoElementEvent;
-}(Event_1.Event));
-exports.VideoElementEvent = VideoElementEvent;
-
-},{"./Event":29}],38:[function(require,module,exports){
-function Mapper() {
- var sources = {};
- this.forEach = function (callback) {
- for (var key in sources) {
- var source = sources[key];
- for (var key2 in source)
- callback(source[key2]);
- }
- ;
- };
- this.get = function (id, source) {
- var ids = sources[source];
- if (ids == undefined)
- return undefined;
- return ids[id];
- };
- this.remove = function (id, source) {
- var ids = sources[source];
- if (ids == undefined)
- return;
- delete ids[id];
- for (var i in ids) {
- return false;
- }
- delete sources[source];
- };
- this.set = function (value, id, source) {
- if (value == undefined)
- return this.remove(id, source);
- var ids = sources[source];
- if (ids == undefined)
- sources[source] = ids = {};
- ids[id] = value;
- };
-}
-;
-Mapper.prototype.pop = function (id, source) {
- var value = this.get(id, source);
- if (value == undefined)
- return undefined;
- this.remove(id, source);
- return value;
-};
-module.exports = Mapper;
-
-},{}],39:[function(require,module,exports){
-var JsonRpcClient = require('./jsonrpcclient');
-exports.JsonRpcClient = JsonRpcClient;
-
-},{"./jsonrpcclient":40}],40:[function(require,module,exports){
-var RpcBuilder = require('../');
-var WebSocketWithReconnection = require('./transports/webSocketWithReconnection');
-Date.now = Date.now || function () {
- return +new Date;
-};
-var PING_INTERVAL = 5000;
-var RECONNECTING = 'RECONNECTING';
-var CONNECTED = 'CONNECTED';
-var DISCONNECTED = 'DISCONNECTED';
-var Logger = console;
-function JsonRpcClient(configuration) {
- var self = this;
- var wsConfig = configuration.ws;
- var notReconnectIfNumLessThan = -1;
- var pingNextNum = 0;
- var enabledPings = true;
- var pingPongStarted = false;
- var pingInterval;
- var status = DISCONNECTED;
- var onreconnecting = wsConfig.onreconnecting;
- var onreconnected = wsConfig.onreconnected;
- var onconnected = wsConfig.onconnected;
- var onerror = wsConfig.onerror;
- configuration.rpc.pull = function (params, request) {
- request.reply(null, "push");
- };
- wsConfig.onreconnecting = function () {
- Logger.debug("--------- ONRECONNECTING -----------");
- if (status === RECONNECTING) {
- Logger.error("Websocket already in RECONNECTING state when receiving a new ONRECONNECTING message. Ignoring it");
- return;
- }
- status = RECONNECTING;
- if (onreconnecting) {
- onreconnecting();
- }
- };
- wsConfig.onreconnected = function () {
- Logger.debug("--------- ONRECONNECTED -----------");
- if (status === CONNECTED) {
- Logger.error("Websocket already in CONNECTED state when receiving a new ONRECONNECTED message. Ignoring it");
- return;
- }
- status = CONNECTED;
- enabledPings = true;
- updateNotReconnectIfLessThan();
- usePing();
- if (onreconnected) {
- onreconnected();
- }
- };
- wsConfig.onconnected = function () {
- Logger.debug("--------- ONCONNECTED -----------");
- if (status === CONNECTED) {
- Logger.error("Websocket already in CONNECTED state when receiving a new ONCONNECTED message. Ignoring it");
- return;
- }
- status = CONNECTED;
- enabledPings = true;
- usePing();
- if (onconnected) {
- onconnected();
- }
- };
- wsConfig.onerror = function (error) {
- Logger.debug("--------- ONERROR -----------");
- status = DISCONNECTED;
- if (onerror) {
- onerror(error);
- }
- };
- var ws = new WebSocketWithReconnection(wsConfig);
- Logger.debug('Connecting websocket to URI: ' + wsConfig.uri);
- var rpcBuilderOptions = {
- request_timeout: configuration.rpc.requestTimeout,
- ping_request_timeout: configuration.rpc.heartbeatRequestTimeout
- };
- var rpc = new RpcBuilder(RpcBuilder.packers.JsonRPC, rpcBuilderOptions, ws, function (request) {
- Logger.debug('Received request: ' + JSON.stringify(request));
- try {
- var func = configuration.rpc[request.method];
- if (func === undefined) {
- Logger.error("Method " + request.method + " not registered in client");
- }
- else {
- func(request.params, request);
- }
- }
- catch (err) {
- Logger.error('Exception processing request: ' + JSON.stringify(request));
- Logger.error(err);
- }
- });
- this.send = function (method, params, callback) {
- if (method !== 'ping') {
- Logger.debug('Request: method:' + method + " params:" + JSON.stringify(params));
- }
- var requestTime = Date.now();
- rpc.encode(method, params, function (error, result) {
- if (error) {
- try {
- Logger.error("ERROR:" + error.message + " in Request: method:" +
- method + " params:" + JSON.stringify(params) + " request:" +
- error.request);
- if (error.data) {
- Logger.error("ERROR DATA:" + JSON.stringify(error.data));
- }
- }
- catch (e) { }
- error.requestTime = requestTime;
- }
- if (callback) {
- if (result != undefined && result.value !== 'pong') {
- Logger.debug('Response: ' + JSON.stringify(result));
- }
- callback(error, result);
- }
- });
- };
- function updateNotReconnectIfLessThan() {
- Logger.debug("notReconnectIfNumLessThan = " + pingNextNum + ' (old=' +
- notReconnectIfNumLessThan + ')');
- notReconnectIfNumLessThan = pingNextNum;
- }
- function sendPing() {
- if (enabledPings) {
- var params = null;
- if (pingNextNum == 0 || pingNextNum == notReconnectIfNumLessThan) {
- params = {
- interval: configuration.heartbeat || PING_INTERVAL
- };
- }
- pingNextNum++;
- self.send('ping', params, (function (pingNum) {
- return function (error, result) {
- if (error) {
- Logger.debug("Error in ping request #" + pingNum + " (" +
- error.message + ")");
- if (pingNum > notReconnectIfNumLessThan) {
- enabledPings = false;
- updateNotReconnectIfLessThan();
- Logger.debug("Server did not respond to ping message #" +
- pingNum + ". Reconnecting... ");
- ws.reconnectWs();
- }
- }
- };
- })(pingNextNum));
- }
- else {
- Logger.debug("Trying to send ping, but ping is not enabled");
- }
- }
- function usePing() {
- if (!pingPongStarted) {
- Logger.debug("Starting ping (if configured)");
- pingPongStarted = true;
- if (configuration.heartbeat != undefined) {
- pingInterval = setInterval(sendPing, configuration.heartbeat);
- sendPing();
- }
- }
- }
- this.close = function () {
- Logger.debug("Closing jsonRpcClient explicitly by client");
- if (pingInterval != undefined) {
- Logger.debug("Clearing ping interval");
- clearInterval(pingInterval);
- }
- pingPongStarted = false;
- enabledPings = false;
- if (configuration.sendCloseMessage) {
- Logger.debug("Sending close message");
- this.send('closeSession', null, function (error, result) {
- if (error) {
- Logger.error("Error sending close message: " + JSON.stringify(error));
- }
- ws.close();
- });
- }
- else {
- ws.close();
- }
- };
- this.forceClose = function (millis) {
- ws.forceClose(millis);
- };
- this.reconnect = function () {
- ws.reconnectWs();
- };
-}
-module.exports = JsonRpcClient;
-
-},{"../":43,"./transports/webSocketWithReconnection":42}],41:[function(require,module,exports){
-var WebSocketWithReconnection = require('./webSocketWithReconnection');
-exports.WebSocketWithReconnection = WebSocketWithReconnection;
-
-},{"./webSocketWithReconnection":42}],42:[function(require,module,exports){
-(function (global){
-"use strict";
-var BrowserWebSocket = global.WebSocket || global.MozWebSocket;
-var Logger = console;
-var MAX_RETRIES = 2000;
-var RETRY_TIME_MS = 3000;
-var CONNECTING = 0;
-var OPEN = 1;
-var CLOSING = 2;
-var CLOSED = 3;
-function WebSocketWithReconnection(config) {
- var closing = false;
- var registerMessageHandler;
- var wsUri = config.uri;
- var useSockJS = config.useSockJS;
- var reconnecting = false;
- var forcingDisconnection = false;
- var ws;
- if (useSockJS) {
- ws = new SockJS(wsUri);
- }
- else {
- ws = new WebSocket(wsUri);
- }
- ws.onopen = function () {
- logConnected(ws, wsUri);
- if (config.onconnected) {
- config.onconnected();
- }
- };
- ws.onerror = function (error) {
- Logger.error("Could not connect to " + wsUri + " (invoking onerror if defined)", error);
- if (config.onerror) {
- config.onerror(error);
- }
- };
- function logConnected(ws, wsUri) {
- try {
- Logger.debug("WebSocket connected to " + wsUri);
- }
- catch (e) {
- Logger.error(e);
- }
- }
- var reconnectionOnClose = function () {
- if (ws.readyState === CLOSED) {
- if (closing) {
- Logger.debug("Connection closed by user");
- }
- else {
- Logger.debug("Connection closed unexpectecly. Reconnecting...");
- reconnectToSameUri(MAX_RETRIES, 1);
- }
- }
- else {
- Logger.debug("Close callback from previous websocket. Ignoring it");
- }
- };
- ws.onclose = reconnectionOnClose;
- function reconnectToSameUri(maxRetries, numRetries) {
- Logger.debug("reconnectToSameUri (attempt #" + numRetries + ", max=" + maxRetries + ")");
- if (numRetries === 1) {
- if (reconnecting) {
- Logger.warn("Trying to reconnectToNewUri when reconnecting... Ignoring this reconnection.");
- return;
- }
- else {
- reconnecting = true;
- }
- if (config.onreconnecting) {
- config.onreconnecting();
- }
- }
- if (forcingDisconnection) {
- reconnectToNewUri(maxRetries, numRetries, wsUri);
- }
- else {
- if (config.newWsUriOnReconnection) {
- config.newWsUriOnReconnection(function (error, newWsUri) {
- if (error) {
- Logger.debug(error);
- setTimeout(function () {
- reconnectToSameUri(maxRetries, numRetries + 1);
- }, RETRY_TIME_MS);
- }
- else {
- reconnectToNewUri(maxRetries, numRetries, newWsUri);
- }
- });
- }
- else {
- reconnectToNewUri(maxRetries, numRetries, wsUri);
- }
- }
- }
- function reconnectToNewUri(maxRetries, numRetries, reconnectWsUri) {
- Logger.debug("Reconnection attempt #" + numRetries);
- ws.close();
- wsUri = reconnectWsUri || wsUri;
- var newWs;
- if (useSockJS) {
- newWs = new SockJS(wsUri);
- }
- else {
- newWs = new WebSocket(wsUri);
- }
- newWs.onopen = function () {
- Logger.debug("Reconnected after " + numRetries + " attempts...");
- logConnected(newWs, wsUri);
- reconnecting = false;
- registerMessageHandler();
- if (config.onreconnected()) {
- config.onreconnected();
- }
- newWs.onclose = reconnectionOnClose;
- };
- var onErrorOrClose = function (error) {
- Logger.warn("Reconnection error: ", error);
- if (numRetries === maxRetries) {
- if (config.ondisconnect) {
- config.ondisconnect();
- }
- }
- else {
- setTimeout(function () {
- reconnectToSameUri(maxRetries, numRetries + 1);
- }, RETRY_TIME_MS);
- }
- };
- newWs.onerror = onErrorOrClose;
- ws = newWs;
- }
- this.close = function () {
- closing = true;
- ws.close();
- };
- this.forceClose = function (millis) {
- Logger.debug("Testing: Force WebSocket close");
- if (millis) {
- Logger.debug("Testing: Change wsUri for " + millis + " millis to simulate net failure");
- var goodWsUri = wsUri;
- wsUri = "wss://21.234.12.34.4:443/";
- forcingDisconnection = true;
- setTimeout(function () {
- Logger.debug("Testing: Recover good wsUri " + goodWsUri);
- wsUri = goodWsUri;
- forcingDisconnection = false;
- }, millis);
- }
- ws.close();
- };
- this.reconnectWs = function () {
- Logger.debug("reconnectWs");
- reconnectToSameUri(MAX_RETRIES, 1, wsUri);
- };
- this.send = function (message) {
- ws.send(message);
- };
- this.addEventListener = function (type, callback) {
- registerMessageHandler = function () {
- ws.addEventListener(type, callback);
- };
- registerMessageHandler();
- };
-}
-module.exports = WebSocketWithReconnection;
-
-}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
-
-},{}],43:[function(require,module,exports){
-var defineProperty_IE8 = false;
-if (Object.defineProperty) {
- try {
- Object.defineProperty({}, "x", {});
- }
- catch (e) {
- defineProperty_IE8 = true;
- }
-}
-if (!Function.prototype.bind) {
- Function.prototype.bind = function (oThis) {
- if (typeof this !== 'function') {
- throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable');
- }
- var aArgs = Array.prototype.slice.call(arguments, 1), fToBind = this, fNOP = function () { }, fBound = function () {
- return fToBind.apply(this instanceof fNOP && oThis
- ? this
- : oThis, aArgs.concat(Array.prototype.slice.call(arguments)));
- };
- fNOP.prototype = this.prototype;
- fBound.prototype = new fNOP();
- return fBound;
- };
-}
-var EventEmitter = require('events').EventEmitter;
-var inherits = require('inherits');
-var packers = require('./packers');
-var Mapper = require('./Mapper');
-var BASE_TIMEOUT = 5000;
-function unifyResponseMethods(responseMethods) {
- if (!responseMethods)
- return {};
- for (var key in responseMethods) {
- var value = responseMethods[key];
- if (typeof value == 'string')
- responseMethods[key] =
- {
- response: value
- };
- }
- ;
- return responseMethods;
-}
-;
-function unifyTransport(transport) {
- if (!transport)
- return;
- if (transport instanceof Function)
- return { send: transport };
- if (transport.send instanceof Function)
- return transport;
- if (transport.postMessage instanceof Function) {
- transport.send = transport.postMessage;
- return transport;
- }
- if (transport.write instanceof Function) {
- transport.send = transport.write;
- return transport;
- }
- if (transport.onmessage !== undefined)
- return;
- if (transport.pause instanceof Function)
- return;
- throw new SyntaxError("Transport is not a function nor a valid object");
-}
-;
-function RpcNotification(method, params) {
- if (defineProperty_IE8) {
- this.method = method;
- this.params = params;
- }
- else {
- Object.defineProperty(this, 'method', { value: method, enumerable: true });
- Object.defineProperty(this, 'params', { value: params, enumerable: true });
- }
-}
-;
-function RpcBuilder(packer, options, transport, onRequest) {
- var self = this;
- if (!packer)
- throw new SyntaxError('Packer is not defined');
- if (!packer.pack || !packer.unpack)
- throw new SyntaxError('Packer is invalid');
- var responseMethods = unifyResponseMethods(packer.responseMethods);
- if (options instanceof Function) {
- if (transport != undefined)
- throw new SyntaxError("There can't be parameters after onRequest");
- onRequest = options;
- transport = undefined;
- options = undefined;
- }
- ;
- if (options && options.send instanceof Function) {
- if (transport && !(transport instanceof Function))
- throw new SyntaxError("Only a function can be after transport");
- onRequest = transport;
- transport = options;
- options = undefined;
- }
- ;
- if (transport instanceof Function) {
- if (onRequest != undefined)
- throw new SyntaxError("There can't be parameters after onRequest");
- onRequest = transport;
- transport = undefined;
- }
- ;
- if (transport && transport.send instanceof Function)
- if (onRequest && !(onRequest instanceof Function))
- throw new SyntaxError("Only a function can be after transport");
- options = options || {};
- EventEmitter.call(this);
- if (onRequest)
- this.on('request', onRequest);
- if (defineProperty_IE8)
- this.peerID = options.peerID;
- else
- Object.defineProperty(this, 'peerID', { value: options.peerID });
- var max_retries = options.max_retries || 0;
- function transportMessage(event) {
- self.decode(event.data || event);
- }
- ;
- this.getTransport = function () {
- return transport;
- };
- this.setTransport = function (value) {
- if (transport) {
- if (transport.removeEventListener)
- transport.removeEventListener('message', transportMessage);
- else if (transport.removeListener)
- transport.removeListener('data', transportMessage);
- }
- ;
- if (value) {
- if (value.addEventListener)
- value.addEventListener('message', transportMessage);
- else if (value.addListener)
- value.addListener('data', transportMessage);
- }
- ;
- transport = unifyTransport(value);
- };
- if (!defineProperty_IE8)
- Object.defineProperty(this, 'transport', {
- get: this.getTransport.bind(this),
- set: this.setTransport.bind(this)
- });
- this.setTransport(transport);
- var request_timeout = options.request_timeout || BASE_TIMEOUT;
- var ping_request_timeout = options.ping_request_timeout || request_timeout;
- var response_timeout = options.response_timeout || BASE_TIMEOUT;
- var duplicates_timeout = options.duplicates_timeout || BASE_TIMEOUT;
- var requestID = 0;
- var requests = new Mapper();
- var responses = new Mapper();
- var processedResponses = new Mapper();
- var message2Key = {};
- function storeResponse(message, id, dest) {
- var response = {
- message: message,
- timeout: setTimeout(function () {
- responses.remove(id, dest);
- }, response_timeout)
- };
- responses.set(response, id, dest);
- }
- ;
- function storeProcessedResponse(ack, from) {
- var timeout = setTimeout(function () {
- processedResponses.remove(ack, from);
- }, duplicates_timeout);
- processedResponses.set(timeout, ack, from);
- }
- ;
- function RpcRequest(method, params, id, from, transport) {
- RpcNotification.call(this, method, params);
- this.getTransport = function () {
- return transport;
- };
- this.setTransport = function (value) {
- transport = unifyTransport(value);
- };
- if (!defineProperty_IE8)
- Object.defineProperty(this, 'transport', {
- get: this.getTransport.bind(this),
- set: this.setTransport.bind(this)
- });
- var response = responses.get(id, from);
- if (!(transport || self.getTransport())) {
- if (defineProperty_IE8)
- this.duplicated = Boolean(response);
- else
- Object.defineProperty(this, 'duplicated', {
- value: Boolean(response)
- });
- }
- var responseMethod = responseMethods[method];
- this.pack = packer.pack.bind(packer, this, id);
- this.reply = function (error, result, transport) {
- if (error instanceof Function || error && error.send instanceof Function) {
- if (result != undefined)
- throw new SyntaxError("There can't be parameters after callback");
- transport = error;
- result = null;
- error = undefined;
- }
- else if (result instanceof Function
- || result && result.send instanceof Function) {
- if (transport != undefined)
- throw new SyntaxError("There can't be parameters after callback");
- transport = result;
- result = null;
- }
- ;
- transport = unifyTransport(transport);
- if (response)
- clearTimeout(response.timeout);
- if (from != undefined) {
- if (error)
- error.dest = from;
- if (result)
- result.dest = from;
- }
- ;
- var message;
- if (error || result != undefined) {
- if (self.peerID != undefined) {
- if (error)
- error.from = self.peerID;
- else
- result.from = self.peerID;
- }
- if (responseMethod) {
- if (responseMethod.error == undefined && error)
- message =
- {
- error: error
- };
- else {
- var method = error
- ? responseMethod.error
- : responseMethod.response;
- message =
- {
- method: method,
- params: error || result
- };
- }
- }
- else
- message =
- {
- error: error,
- result: result
- };
- message = packer.pack(message, id);
- }
- else if (response)
- message = response.message;
- else
- message = packer.pack({ result: null }, id);
- storeResponse(message, id, from);
- transport = transport || this.getTransport() || self.getTransport();
- if (transport)
- return transport.send(message);
- return message;
- };
- }
- ;
- inherits(RpcRequest, RpcNotification);
- function cancel(message) {
- var key = message2Key[message];
- if (!key)
- return;
- delete message2Key[message];
- var request = requests.pop(key.id, key.dest);
- if (!request)
- return;
- clearTimeout(request.timeout);
- storeProcessedResponse(key.id, key.dest);
- }
- ;
- this.cancel = function (message) {
- if (message)
- return cancel(message);
- for (var message in message2Key)
- cancel(message);
- };
- this.close = function () {
- var transport = this.getTransport();
- if (transport && transport.close)
- transport.close();
- this.cancel();
- processedResponses.forEach(clearTimeout);
- responses.forEach(function (response) {
- clearTimeout(response.timeout);
- });
- };
- this.encode = function (method, params, dest, transport, callback) {
- if (params instanceof Function) {
- if (dest != undefined)
- throw new SyntaxError("There can't be parameters after callback");
- callback = params;
- transport = undefined;
- dest = undefined;
- params = undefined;
- }
- else if (dest instanceof Function) {
- if (transport != undefined)
- throw new SyntaxError("There can't be parameters after callback");
- callback = dest;
- transport = undefined;
- dest = undefined;
- }
- else if (transport instanceof Function) {
- if (callback != undefined)
- throw new SyntaxError("There can't be parameters after callback");
- callback = transport;
- transport = undefined;
- }
- ;
- if (self.peerID != undefined) {
- params = params || {};
- params.from = self.peerID;
- }
- ;
- if (dest != undefined) {
- params = params || {};
- params.dest = dest;
- }
- ;
- var message = {
- method: method,
- params: params
- };
- if (callback) {
- var id = requestID++;
- var retried = 0;
- message = packer.pack(message, id);
- function dispatchCallback(error, result) {
- self.cancel(message);
- callback(error, result);
- }
- ;
- var request = {
- message: message,
- callback: dispatchCallback,
- responseMethods: responseMethods[method] || {}
- };
- var encode_transport = unifyTransport(transport);
- function sendRequest(transport) {
- var rt = (method === 'ping' ? ping_request_timeout : request_timeout);
- request.timeout = setTimeout(timeout, rt * Math.pow(2, retried++));
- message2Key[message] = { id: id, dest: dest };
- requests.set(request, id, dest);
- transport = transport || encode_transport || self.getTransport();
- if (transport)
- return transport.send(message);
- return message;
- }
- ;
- function retry(transport) {
- transport = unifyTransport(transport);
- console.warn(retried + ' retry for request message:', message);
- var timeout = processedResponses.pop(id, dest);
- clearTimeout(timeout);
- return sendRequest(transport);
- }
- ;
- function timeout() {
- if (retried < max_retries)
- return retry(transport);
- var error = new Error('Request has timed out');
- error.request = message;
- error.retry = retry;
- dispatchCallback(error);
- }
- ;
- return sendRequest(transport);
- }
- ;
- message = packer.pack(message);
- transport = transport || this.getTransport();
- if (transport)
- return transport.send(message);
- return message;
- };
- this.decode = function (message, transport) {
- if (!message)
- throw new TypeError("Message is not defined");
- try {
- message = packer.unpack(message);
- }
- catch (e) {
- return console.debug(e, message);
- }
- ;
- var id = message.id;
- var ack = message.ack;
- var method = message.method;
- var params = message.params || {};
- var from = params.from;
- var dest = params.dest;
- if (self.peerID != undefined && from == self.peerID)
- return;
- if (id == undefined && ack == undefined) {
- var notification = new RpcNotification(method, params);
- if (self.emit('request', notification))
- return;
- return notification;
- }
- ;
- function processRequest() {
- transport = unifyTransport(transport) || self.getTransport();
- if (transport) {
- var response = responses.get(id, from);
- if (response)
- return transport.send(response.message);
- }
- ;
- var idAck = (id != undefined) ? id : ack;
- var request = new RpcRequest(method, params, idAck, from, transport);
- if (self.emit('request', request))
- return;
- return request;
- }
- ;
- function processResponse(request, error, result) {
- request.callback(error, result);
- }
- ;
- function duplicatedResponse(timeout) {
- console.warn("Response already processed", message);
- clearTimeout(timeout);
- storeProcessedResponse(ack, from);
- }
- ;
- if (method) {
- if (dest == undefined || dest == self.peerID) {
- var request = requests.get(ack, from);
- if (request) {
- var responseMethods = request.responseMethods;
- if (method == responseMethods.error)
- return processResponse(request, params);
- if (method == responseMethods.response)
- return processResponse(request, null, params);
- return processRequest();
- }
- var processed = processedResponses.get(ack, from);
- if (processed)
- return duplicatedResponse(processed);
- }
- return processRequest();
- }
- ;
- var error = message.error;
- var result = message.result;
- if (error && error.dest && error.dest != self.peerID)
- return;
- if (result && result.dest && result.dest != self.peerID)
- return;
- var request = requests.get(ack, from);
- if (!request) {
- var processed = processedResponses.get(ack, from);
- if (processed)
- return duplicatedResponse(processed);
- return console.warn("No callback was defined for this message", message);
- }
- ;
- processResponse(request, error, result);
- };
-}
-;
-inherits(RpcBuilder, EventEmitter);
-RpcBuilder.RpcNotification = RpcNotification;
-module.exports = RpcBuilder;
-var clients = require('./clients');
-var transports = require('./clients/transports');
-RpcBuilder.clients = clients;
-RpcBuilder.clients.transports = transports;
-RpcBuilder.packers = packers;
-
-},{"./Mapper":38,"./clients":39,"./clients/transports":41,"./packers":46,"events":1,"inherits":6}],44:[function(require,module,exports){
-function pack(message, id) {
- var result = {
- jsonrpc: "2.0"
- };
- if (message.method) {
- result.method = message.method;
- if (message.params)
- result.params = message.params;
- if (id != undefined)
- result.id = id;
- }
- else if (id != undefined) {
- if (message.error) {
- if (message.result !== undefined)
- throw new TypeError("Both result and error are defined");
- result.error = message.error;
- }
- else if (message.result !== undefined)
- result.result = message.result;
- else
- throw new TypeError("No result or error is defined");
- result.id = id;
- }
- ;
- return JSON.stringify(result);
-}
-;
-function unpack(message) {
- var result = message;
- if (typeof message === 'string' || message instanceof String) {
- result = JSON.parse(message);
- }
- var version = result.jsonrpc;
- if (version !== '2.0')
- throw new TypeError("Invalid JsonRPC version '" + version + "': " + message);
- if (result.method == undefined) {
- if (result.id == undefined)
- throw new TypeError("Invalid message: " + message);
- var result_defined = result.result !== undefined;
- var error_defined = result.error !== undefined;
- if (result_defined && error_defined)
- throw new TypeError("Both result and error are defined: " + message);
- if (!result_defined && !error_defined)
- throw new TypeError("No result or error is defined: " + message);
- result.ack = result.id;
- delete result.id;
- }
- return result;
-}
-;
-exports.pack = pack;
-exports.unpack = unpack;
-
-},{}],45:[function(require,module,exports){
-function pack(message) {
- throw new TypeError("Not yet implemented");
-}
-;
-function unpack(message) {
- throw new TypeError("Not yet implemented");
-}
-;
-exports.pack = pack;
-exports.unpack = unpack;
-
-},{}],46:[function(require,module,exports){
-var JsonRPC = require('./JsonRPC');
-var XmlRPC = require('./XmlRPC');
-exports.JsonRPC = JsonRPC;
-exports.XmlRPC = XmlRPC;
-
-},{"./JsonRPC":44,"./XmlRPC":45}],47:[function(require,module,exports){
-window.getScreenId = function (callback, custom_parameter) {
- if (navigator.userAgent.indexOf('Edge') !== -1 && (!!navigator.msSaveOrOpenBlob || !!navigator.msSaveBlob)) {
- callback({
- video: true
- });
- return;
- }
- if (!!navigator.mozGetUserMedia) {
- callback(null, 'firefox', {
- video: {
- mozMediaSource: 'window',
- mediaSource: 'window'
- }
- });
- return;
- }
- window.addEventListener('message', onIFrameCallback);
- function onIFrameCallback(event) {
- if (!event.data)
- return;
- if (event.data.chromeMediaSourceId) {
- if (event.data.chromeMediaSourceId === 'PermissionDeniedError') {
- callback('permission-denied');
- }
- else {
- callback(null, event.data.chromeMediaSourceId, getScreenConstraints(null, event.data.chromeMediaSourceId, event.data.canRequestAudioTrack));
- }
- window.removeEventListener('message', onIFrameCallback);
- }
- if (event.data.chromeExtensionStatus) {
- callback(event.data.chromeExtensionStatus, null, getScreenConstraints(event.data.chromeExtensionStatus));
- window.removeEventListener('message', onIFrameCallback);
- }
- }
- if (!custom_parameter) {
- setTimeout(postGetSourceIdMessage, 100);
- }
- else {
- setTimeout(function () {
- postGetSourceIdMessage(custom_parameter);
- }, 100);
- }
-};
-function getScreenConstraints(error, sourceId, canRequestAudioTrack) {
- var screen_constraints = {
- audio: false,
- video: {
- mandatory: {
- chromeMediaSource: error ? 'screen' : 'desktop',
- maxWidth: window.screen.width > 1920 ? window.screen.width : 1920,
- maxHeight: window.screen.height > 1080 ? window.screen.height : 1080
- },
- optional: []
- }
- };
- if (!!canRequestAudioTrack) {
- screen_constraints.audio = {
- mandatory: {
- chromeMediaSource: error ? 'screen' : 'desktop',
- },
- optional: []
- };
- }
- if (sourceId) {
- screen_constraints.video.mandatory.chromeMediaSourceId = sourceId;
- if (screen_constraints.audio && screen_constraints.audio.mandatory) {
- screen_constraints.audio.mandatory.chromeMediaSourceId = sourceId;
- }
- }
- return screen_constraints;
-}
-function postGetSourceIdMessage(custom_parameter) {
- if (!iframe) {
- loadIFrame(function () {
- postGetSourceIdMessage(custom_parameter);
- });
- return;
- }
- if (!iframe.isLoaded) {
- setTimeout(function () {
- postGetSourceIdMessage(custom_parameter);
- }, 100);
- return;
- }
- if (!custom_parameter) {
- iframe.contentWindow.postMessage({
- captureSourceId: true
- }, '*');
- }
- else if (!!custom_parameter.forEach) {
- iframe.contentWindow.postMessage({
- captureCustomSourceId: custom_parameter
- }, '*');
- }
- else {
- iframe.contentWindow.postMessage({
- captureSourceIdWithAudio: true
- }, '*');
- }
-}
-var iframe;
-window.getScreenConstraints = function (callback) {
- loadIFrame(function () {
- getScreenId(function (error, sourceId, screen_constraints) {
- if (!screen_constraints) {
- screen_constraints = {
- video: true
- };
- }
- callback(error, screen_constraints.video);
- });
- });
-};
-function loadIFrame(loadCallback) {
- if (iframe) {
- loadCallback();
- return;
- }
- iframe = document.createElement('iframe');
- iframe.onload = function () {
- iframe.isLoaded = true;
- loadCallback();
- };
- iframe.src = 'https://openvidu.github.io/openvidu-screen-sharing-chrome-extension/';
- iframe.style.display = 'none';
- (document.body || document.documentElement).appendChild(iframe);
-}
-window.getChromeExtensionStatus = function (callback) {
- if (!!navigator.mozGetUserMedia) {
- callback('installed-enabled');
- return;
- }
- window.addEventListener('message', onIFrameCallback);
- function onIFrameCallback(event) {
- if (!event.data)
- return;
- if (event.data.chromeExtensionStatus) {
- callback(event.data.chromeExtensionStatus);
- window.removeEventListener('message', onIFrameCallback);
- }
- }
- setTimeout(postGetChromeExtensionStatusMessage, 100);
-};
-function postGetChromeExtensionStatusMessage() {
- if (!iframe) {
- loadIFrame(postGetChromeExtensionStatusMessage);
- return;
- }
- if (!iframe.isLoaded) {
- setTimeout(postGetChromeExtensionStatusMessage, 100);
- return;
- }
- iframe.contentWindow.postMessage({
- getChromeExtensionStatus: true
- }, '*');
-}
-exports.getScreenId = getScreenId;
-
-},{}],48:[function(require,module,exports){
-var chromeMediaSource = 'screen';
-var sourceId;
-var screenCallback;
-var isFirefox = typeof window.InstallTrigger !== 'undefined';
-var isOpera = !!window.opera || navigator.userAgent.indexOf(' OPR/') >= 0;
-var isChrome = !!window.chrome && !isOpera;
-window.addEventListener('message', function (event) {
- if (event.origin != window.location.origin) {
- return;
- }
- onMessageCallback(event.data);
-});
-function onMessageCallback(data) {
- if (data == 'PermissionDeniedError') {
- if (screenCallback)
- return screenCallback('PermissionDeniedError');
- else
- throw new Error('PermissionDeniedError');
- }
- if (data == 'rtcmulticonnection-extension-loaded') {
- chromeMediaSource = 'desktop';
- }
- if (data.sourceId && screenCallback) {
- screenCallback(sourceId = data.sourceId, data.canRequestAudioTrack === true);
- }
-}
-function isChromeExtensionAvailable(callback) {
- if (!callback)
- return;
- if (chromeMediaSource == 'desktop')
- return callback(true);
- window.postMessage('are-you-there', '*');
- setTimeout(function () {
- if (chromeMediaSource == 'screen') {
- callback(false);
- }
- else
- callback(true);
- }, 2000);
-}
-function getSourceId(callback) {
- if (!callback)
- throw '"callback" parameter is mandatory.';
- if (sourceId)
- return callback(sourceId);
- screenCallback = callback;
- window.postMessage('get-sourceId', '*');
-}
-function getCustomSourceId(arr, callback) {
- if (!arr || !arr.forEach)
- throw '"arr" parameter is mandatory and it must be an array.';
- if (!callback)
- throw '"callback" parameter is mandatory.';
- if (sourceId)
- return callback(sourceId);
- screenCallback = callback;
- window.postMessage({
- 'get-custom-sourceId': arr
- }, '*');
-}
-function getSourceIdWithAudio(callback) {
- if (!callback)
- throw '"callback" parameter is mandatory.';
- if (sourceId)
- return callback(sourceId);
- screenCallback = callback;
- window.postMessage('audio-plus-tab', '*');
-}
-function getChromeExtensionStatus(extensionid, callback) {
- if (isFirefox)
- return callback('not-chrome');
- if (arguments.length != 2) {
- callback = extensionid;
- extensionid = 'lfcgfepafnobdloecchnfaclibenjold';
- }
- var image = document.createElement('img');
- image.src = 'chrome-extension://' + extensionid + '/icon.png';
- image.onload = function () {
- chromeMediaSource = 'screen';
- window.postMessage('are-you-there', '*');
- setTimeout(function () {
- if (chromeMediaSource == 'screen') {
- callback('installed-disabled');
- }
- else
- callback('installed-enabled');
- }, 2000);
- };
- image.onerror = function () {
- callback('not-installed');
- };
-}
-function getScreenConstraintsWithAudio(callback) {
- getScreenConstraints(callback, true);
-}
-function getScreenConstraints(callback, captureSourceIdWithAudio) {
- sourceId = '';
- var firefoxScreenConstraints = {
- mozMediaSource: 'window',
- mediaSource: 'window'
- };
- if (isFirefox)
- return callback(null, firefoxScreenConstraints);
- var screen_constraints = {
- mandatory: {
- chromeMediaSource: chromeMediaSource,
- maxWidth: screen.width > 1920 ? screen.width : 1920,
- maxHeight: screen.height > 1080 ? screen.height : 1080
- },
- optional: []
- };
- if (chromeMediaSource == 'desktop' && !sourceId) {
- if (captureSourceIdWithAudio) {
- getSourceIdWithAudio(function (sourceId, canRequestAudioTrack) {
- screen_constraints.mandatory.chromeMediaSourceId = sourceId;
- if (canRequestAudioTrack) {
- screen_constraints.canRequestAudioTrack = true;
- }
- callback(sourceId == 'PermissionDeniedError' ? sourceId : null, screen_constraints);
- });
- }
- else {
- getSourceId(function (sourceId) {
- screen_constraints.mandatory.chromeMediaSourceId = sourceId;
- callback(sourceId == 'PermissionDeniedError' ? sourceId : null, screen_constraints);
- });
- }
- return;
- }
- if (chromeMediaSource == 'desktop') {
- screen_constraints.mandatory.chromeMediaSourceId = sourceId;
- }
- callback(null, screen_constraints);
-}
-exports.getScreenConstraints = getScreenConstraints;
-exports.getScreenConstraintsWithAudio = getScreenConstraintsWithAudio;
-exports.isChromeExtensionAvailable = isChromeExtensionAvailable;
-exports.getChromeExtensionStatus = getChromeExtensionStatus;
-exports.getSourceId = getSourceId;
-
-},{}],49:[function(require,module,exports){
-"use strict";
-var __extends = (this && this.__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 __());
- };
-})();
-Object.defineProperty(exports, "__esModule", { value: true });
-var freeice = require("freeice");
-var uuid = require("uuid");
-var platform = require("platform");
-var WebRtcPeer = (function () {
- function WebRtcPeer(configuration) {
- var _this = this;
- this.configuration = configuration;
- this.remoteCandidatesQueue = [];
- this.localCandidatesQueue = [];
- this.iceCandidateList = [];
- this.candidategatheringdone = false;
- this.configuration.iceServers = (!!this.configuration.iceServers && this.configuration.iceServers.length > 0) ? this.configuration.iceServers : freeice();
- this.pc = new RTCPeerConnection({ iceServers: this.configuration.iceServers });
- this.id = !!configuration.id ? configuration.id : uuid.v4();
- this.pc.onicecandidate = function (event) {
- var candidate = event.candidate;
- if (candidate) {
- _this.localCandidatesQueue.push({ candidate: candidate.candidate });
- _this.candidategatheringdone = false;
- _this.configuration.onicecandidate(event.candidate);
- }
- else if (!_this.candidategatheringdone) {
- _this.candidategatheringdone = true;
- }
- };
- this.pc.onsignalingstatechange = function () {
- if (_this.pc.signalingState === 'stable') {
- while (_this.iceCandidateList.length > 0) {
- _this.pc.addIceCandidate(_this.iceCandidateList.shift());
- }
- }
- };
- this.start();
- }
- WebRtcPeer.prototype.start = function () {
- var _this = this;
- return new Promise(function (resolve, reject) {
- if (_this.pc.signalingState === 'closed') {
- reject('The peer connection object is in "closed" state. This is most likely due to an invocation of the dispose method before accepting in the dialogue');
- }
- if (!!_this.configuration.mediaStream) {
- _this.pc.addStream(_this.configuration.mediaStream);
- }
- if (_this.configuration.mode === 'sendonly' &&
- (platform.name === 'Chrome' && platform.version.toString().substring(0, 2) === '39')) {
- _this.configuration.mode = 'sendrecv';
- }
- resolve();
- });
- };
- WebRtcPeer.prototype.dispose = function () {
- var _this = this;
- console.debug('Disposing WebRtcPeer');
- try {
- if (this.pc) {
- if (this.pc.signalingState === 'closed') {
- return;
- }
- this.remoteCandidatesQueue = [];
- this.localCandidatesQueue = [];
- this.pc.getLocalStreams().forEach(function (str) {
- _this.streamStop(str);
- });
- this.pc.close();
- }
- }
- catch (err) {
- console.warn('Exception disposing webrtc peer ' + err);
- }
- };
- WebRtcPeer.prototype.generateOffer = function () {
- var _this = this;
- return new Promise(function (resolve, reject) {
- var offerAudio, offerVideo = true;
- if (!!_this.configuration.mediaConstraints) {
- offerAudio = (typeof _this.configuration.mediaConstraints.audio === 'boolean') ?
- _this.configuration.mediaConstraints.audio : true;
- offerVideo = (typeof _this.configuration.mediaConstraints.video === 'boolean') ?
- _this.configuration.mediaConstraints.video : true;
- }
- var constraints = {
- offerToReceiveAudio: +(_this.configuration.mode !== 'sendonly' && offerAudio),
- offerToReceiveVideo: +(_this.configuration.mode !== 'sendonly' && offerVideo)
- };
- console.debug('RTCPeerConnection constraints: ' + JSON.stringify(constraints));
- _this.pc.createOffer(constraints).then(function (offer) {
- console.debug('Created SDP offer');
- return _this.pc.setLocalDescription(offer);
- }).then(function () {
- var localDescription = _this.pc.localDescription;
- if (!!localDescription) {
- console.debug('Local description set', localDescription.sdp);
- resolve(localDescription.sdp);
- }
- else {
- reject('Local description is not defined');
- }
- }).catch(function (error) { return reject(error); });
- });
- };
- WebRtcPeer.prototype.processOffer = function (sdpOffer) {
- var _this = this;
- return new Promise(function (resolve, reject) {
- var offer = {
- type: 'offer',
- sdp: sdpOffer
- };
- console.debug('SDP offer received, setting remote description');
- if (_this.pc.signalingState === 'closed') {
- reject('PeerConnection is closed');
- }
- _this.pc.setRemoteDescription(offer)
- .then(function () {
- return _this.pc.createAnswer();
- }).then(function (answer) {
- console.debug('Created SDP answer');
- return _this.pc.setLocalDescription(answer);
- }).then(function () {
- var localDescription = _this.pc.localDescription;
- if (!!localDescription) {
- console.debug('Local description set', localDescription.sdp);
- resolve(localDescription.sdp);
- }
- else {
- reject('Local description is not defined');
- }
- }).catch(function (error) { return reject(error); });
- });
- };
- WebRtcPeer.prototype.processAnswer = function (sdpAnswer) {
- var _this = this;
- return new Promise(function (resolve, reject) {
- var answer = {
- type: 'answer',
- sdp: sdpAnswer
- };
- console.debug('SDP answer received, setting remote description');
- if (_this.pc.signalingState === 'closed') {
- reject('RTCPeerConnection is closed');
- }
- _this.pc.setRemoteDescription(answer).then(function () { return resolve(); }).catch(function (error) { return reject(error); });
- });
- };
- WebRtcPeer.prototype.addIceCandidate = function (iceCandidate) {
- var _this = this;
- return new Promise(function (resolve, reject) {
- console.debug('Remote ICE candidate received', iceCandidate);
- _this.remoteCandidatesQueue.push(iceCandidate);
- switch (_this.pc.signalingState) {
- case 'closed':
- reject(new Error('PeerConnection object is closed'));
- break;
- case 'stable':
- if (!!_this.pc.remoteDescription) {
- _this.pc.addIceCandidate(iceCandidate).then(function () { return resolve(); }).catch(function (error) { return reject(error); });
- }
- break;
- default:
- _this.iceCandidateList.push(iceCandidate);
- resolve();
- }
- });
- };
- WebRtcPeer.prototype.streamStop = function (stream) {
- stream.getTracks().forEach(function (track) {
- track.stop();
- stream.removeTrack(track);
- });
- };
- return WebRtcPeer;
-}());
-exports.WebRtcPeer = WebRtcPeer;
-var WebRtcPeerRecvonly = (function (_super) {
- __extends(WebRtcPeerRecvonly, _super);
- function WebRtcPeerRecvonly(configuration) {
- var _this = this;
- configuration.mode = 'recvonly';
- _this = _super.call(this, configuration) || this;
- return _this;
- }
- return WebRtcPeerRecvonly;
-}(WebRtcPeer));
-exports.WebRtcPeerRecvonly = WebRtcPeerRecvonly;
-var WebRtcPeerSendonly = (function (_super) {
- __extends(WebRtcPeerSendonly, _super);
- function WebRtcPeerSendonly(configuration) {
- var _this = this;
- configuration.mode = 'sendonly';
- _this = _super.call(this, configuration) || this;
- return _this;
- }
- return WebRtcPeerSendonly;
-}(WebRtcPeer));
-exports.WebRtcPeerSendonly = WebRtcPeerSendonly;
-var WebRtcPeerSendrecv = (function (_super) {
- __extends(WebRtcPeerSendrecv, _super);
- function WebRtcPeerSendrecv(configuration) {
- var _this = this;
- configuration.mode = 'sendrecv';
- _this = _super.call(this, configuration) || this;
- return _this;
- }
- return WebRtcPeerSendrecv;
-}(WebRtcPeer));
-exports.WebRtcPeerSendrecv = WebRtcPeerSendrecv;
-
-},{"freeice":2,"platform":8,"uuid":9}],50:[function(require,module,exports){
-"use strict";
-Object.defineProperty(exports, "__esModule", { value: true });
-var platform = require("platform");
-var WebRtcStats = (function () {
- function WebRtcStats(stream) {
- this.stream = stream;
- this.webRtcStatsEnabled = false;
- this.statsInterval = 1;
- this.stats = {
- inbound: {
- audio: {
- bytesReceived: 0,
- packetsReceived: 0,
- packetsLost: 0
- },
- video: {
- bytesReceived: 0,
- packetsReceived: 0,
- packetsLost: 0,
- framesDecoded: 0,
- nackCount: 0
- }
- },
- outbound: {
- audio: {
- bytesSent: 0,
- packetsSent: 0,
- },
- video: {
- bytesSent: 0,
- packetsSent: 0,
- framesEncoded: 0,
- nackCount: 0
- }
- }
- };
- }
- WebRtcStats.prototype.isEnabled = function () {
- return this.webRtcStatsEnabled;
- };
- WebRtcStats.prototype.initWebRtcStats = function () {
- var _this = this;
- var elastestInstrumentation = localStorage.getItem('elastest-instrumentation');
- if (elastestInstrumentation) {
- console.warn('WebRtc stats enabled for stream ' + this.stream.streamId + ' of connection ' + this.stream.connection.connectionId);
- this.webRtcStatsEnabled = true;
- var instrumentation_1 = JSON.parse(elastestInstrumentation);
- this.statsInterval = instrumentation_1.webrtc.interval;
- console.warn('localStorage item: ' + JSON.stringify(instrumentation_1));
- this.webRtcStatsIntervalId = setInterval(function () {
- _this.sendStatsToHttpEndpoint(instrumentation_1);
- }, this.statsInterval * 1000);
- return;
- }
- console.debug('WebRtc stats not enabled');
- };
- WebRtcStats.prototype.stopWebRtcStats = function () {
- if (this.webRtcStatsEnabled) {
- clearInterval(this.webRtcStatsIntervalId);
- console.warn('WebRtc stats stopped for disposed stream ' + this.stream.streamId + ' of connection ' + this.stream.connection.connectionId);
- }
- };
- WebRtcStats.prototype.getSelectedIceCandidateInfo = function () {
- var _this = this;
- return new Promise(function (resolve, reject) {
- _this.getStatsAgnostic(_this.stream.getRTCPeerConnection(), function (stats) {
- if ((platform.name.indexOf('Chrome') !== -1) || (platform.name.indexOf('Opera') !== -1)) {
- var localCandidateId = void 0, remoteCandidateId = void 0, googCandidatePair = void 0;
- var localCandidates = {};
- var remoteCandidates = {};
- for (var key in stats) {
- var stat = stats[key];
- if (stat.type === 'localcandidate') {
- localCandidates[stat.id] = stat;
- }
- else if (stat.type === 'remotecandidate') {
- remoteCandidates[stat.id] = stat;
- }
- else if (stat.type === 'googCandidatePair' && (stat.googActiveConnection === 'true')) {
- googCandidatePair = stat;
- localCandidateId = stat.localCandidateId;
- remoteCandidateId = stat.remoteCandidateId;
- }
- }
- var finalLocalCandidate_1 = localCandidates[localCandidateId];
- if (!!finalLocalCandidate_1) {
- var candList = _this.stream.getLocalIceCandidateList();
- var cand = candList.filter(function (c) {
- return (!!c.candidate &&
- c.candidate.indexOf(finalLocalCandidate_1.ipAddress) >= 0 &&
- c.candidate.indexOf(finalLocalCandidate_1.portNumber) >= 0 &&
- c.candidate.indexOf(finalLocalCandidate_1.priority) >= 0);
- });
- finalLocalCandidate_1.raw = !!cand[0] ? cand[0].candidate : 'ERROR: Cannot find local candidate in list of sent ICE candidates';
- }
- else {
- finalLocalCandidate_1 = 'ERROR: No active local ICE candidate. Probably ICE-TCP is being used';
- }
- var finalRemoteCandidate_1 = remoteCandidates[remoteCandidateId];
- if (!!finalRemoteCandidate_1) {
- var candList = _this.stream.getRemoteIceCandidateList();
- var cand = candList.filter(function (c) {
- return (!!c.candidate &&
- c.candidate.indexOf(finalRemoteCandidate_1.ipAddress) >= 0 &&
- c.candidate.indexOf(finalRemoteCandidate_1.portNumber) >= 0 &&
- c.candidate.indexOf(finalRemoteCandidate_1.priority) >= 0);
- });
- finalRemoteCandidate_1.raw = !!cand[0] ? cand[0].candidate : 'ERROR: Cannot find remote candidate in list of received ICE candidates';
- }
- else {
- finalRemoteCandidate_1 = 'ERROR: No active remote ICE candidate. Probably ICE-TCP is being used';
- }
- resolve({
- googCandidatePair: googCandidatePair,
- localCandidate: finalLocalCandidate_1,
- remoteCandidate: finalRemoteCandidate_1
- });
- }
- else {
- reject('Selected ICE candidate info only available for Chrome');
- }
- }, function (error) {
- reject(error);
- });
- });
- };
- WebRtcStats.prototype.sendStatsToHttpEndpoint = function (instrumentation) {
- var _this = this;
- var sendPost = function (json) {
- var http = new XMLHttpRequest();
- var url = instrumentation.webrtc.httpEndpoint;
- http.open('POST', url, true);
- http.setRequestHeader('Content-type', 'application/json');
- http.onreadystatechange = function () {
- if (http.readyState === 4 && http.status === 200) {
- console.log('WebRtc stats successfully sent to ' + url + ' for stream ' + _this.stream.streamId + ' of connection ' + _this.stream.connection.connectionId);
- }
- };
- http.send(json);
- };
- var f = function (stats) {
- if (platform.name.indexOf('Firefox') !== -1) {
- stats.forEach(function (stat) {
- var json = {};
- if ((stat.type === 'inbound-rtp') &&
- (stat.nackCount !== null &&
- stat.isRemote === false &&
- stat.id.startsWith('inbound') &&
- stat.remoteId.startsWith('inbound'))) {
- var metricId = 'webrtc_inbound_' + stat.mediaType + '_' + stat.ssrc;
- var jit = stat.jitter * 1000;
- var metrics = {
- bytesReceived: (stat.bytesReceived - _this.stats.inbound[stat.mediaType].bytesReceived) / _this.statsInterval,
- jitter: jit,
- packetsReceived: (stat.packetsReceived - _this.stats.inbound[stat.mediaType].packetsReceived) / _this.statsInterval,
- packetsLost: (stat.packetsLost - _this.stats.inbound[stat.mediaType].packetsLost) / _this.statsInterval
- };
- var units = {
- bytesReceived: 'bytes',
- jitter: 'ms',
- packetsReceived: 'packets',
- packetsLost: 'packets'
- };
- if (stat.mediaType === 'video') {
- metrics['framesDecoded'] = (stat.framesDecoded - _this.stats.inbound.video.framesDecoded) / _this.statsInterval;
- metrics['nackCount'] = (stat.nackCount - _this.stats.inbound.video.nackCount) / _this.statsInterval;
- units['framesDecoded'] = 'frames';
- units['nackCount'] = 'packets';
- _this.stats.inbound.video.framesDecoded = stat.framesDecoded;
- _this.stats.inbound.video.nackCount = stat.nackCount;
- }
- _this.stats.inbound[stat.mediaType].bytesReceived = stat.bytesReceived;
- _this.stats.inbound[stat.mediaType].packetsReceived = stat.packetsReceived;
- _this.stats.inbound[stat.mediaType].packetsLost = stat.packetsLost;
- json = {
- '@timestamp': new Date(stat.timestamp).toISOString(),
- 'exec': instrumentation.exec,
- 'component': instrumentation.component,
- 'stream': 'webRtc',
- 'type': metricId,
- 'stream_type': 'composed_metrics',
- 'units': units
- };
- json[metricId] = metrics;
- sendPost(JSON.stringify(json));
- }
- else if ((stat.type === 'outbound-rtp') &&
- (stat.isRemote === false &&
- stat.id.toLowerCase().includes('outbound'))) {
- var metricId = 'webrtc_outbound_' + stat.mediaType + '_' + stat.ssrc;
- var metrics = {
- bytesSent: (stat.bytesSent - _this.stats.outbound[stat.mediaType].bytesSent) / _this.statsInterval,
- packetsSent: (stat.packetsSent - _this.stats.outbound[stat.mediaType].packetsSent) / _this.statsInterval
- };
- var units = {
- bytesSent: 'bytes',
- packetsSent: 'packets'
- };
- if (stat.mediaType === 'video') {
- metrics['framesEncoded'] = (stat.framesEncoded - _this.stats.outbound.video.framesEncoded) / _this.statsInterval;
- units['framesEncoded'] = 'frames';
- _this.stats.outbound.video.framesEncoded = stat.framesEncoded;
- }
- _this.stats.outbound[stat.mediaType].bytesSent = stat.bytesSent;
- _this.stats.outbound[stat.mediaType].packetsSent = stat.packetsSent;
- json = {
- '@timestamp': new Date(stat.timestamp).toISOString(),
- 'exec': instrumentation.exec,
- 'component': instrumentation.component,
- 'stream': 'webRtc',
- 'type': metricId,
- 'stream_type': 'composed_metrics',
- 'units': units
- };
- json[metricId] = metrics;
- sendPost(JSON.stringify(json));
- }
- });
- }
- else if ((platform.name.indexOf('Chrome') !== -1) || (platform.name.indexOf('Opera') !== -1)) {
- for (var _i = 0, _a = Object.keys(stats); _i < _a.length; _i++) {
- var key = _a[_i];
- var stat = stats[key];
- if (stat.type === 'ssrc') {
- var json = {};
- if ('bytesReceived' in stat && ((stat.mediaType === 'audio' && 'audioOutputLevel' in stat) ||
- (stat.mediaType === 'video' && 'qpSum' in stat))) {
- var metricId = 'webrtc_inbound_' + stat.mediaType + '_' + stat.ssrc;
- var metrics = {
- bytesReceived: (stat.bytesReceived - _this.stats.inbound[stat.mediaType].bytesReceived) / _this.statsInterval,
- jitter: stat.googJitterBufferMs,
- packetsReceived: (stat.packetsReceived - _this.stats.inbound[stat.mediaType].packetsReceived) / _this.statsInterval,
- packetsLost: (stat.packetsLost - _this.stats.inbound[stat.mediaType].packetsLost) / _this.statsInterval
- };
- var units = {
- bytesReceived: 'bytes',
- jitter: 'ms',
- packetsReceived: 'packets',
- packetsLost: 'packets'
- };
- if (stat.mediaType === 'video') {
- metrics['framesDecoded'] = (stat.framesDecoded - _this.stats.inbound.video.framesDecoded) / _this.statsInterval;
- metrics['nackCount'] = (stat.googNacksSent - _this.stats.inbound.video.nackCount) / _this.statsInterval;
- units['framesDecoded'] = 'frames';
- units['nackCount'] = 'packets';
- _this.stats.inbound.video.framesDecoded = stat.framesDecoded;
- _this.stats.inbound.video.nackCount = stat.googNacksSent;
- }
- _this.stats.inbound[stat.mediaType].bytesReceived = stat.bytesReceived;
- _this.stats.inbound[stat.mediaType].packetsReceived = stat.packetsReceived;
- _this.stats.inbound[stat.mediaType].packetsLost = stat.packetsLost;
- json = {
- '@timestamp': new Date(stat.timestamp).toISOString(),
- 'exec': instrumentation.exec,
- 'component': instrumentation.component,
- 'stream': 'webRtc',
- 'type': metricId,
- 'stream_type': 'composed_metrics',
- 'units': units
- };
- json[metricId] = metrics;
- sendPost(JSON.stringify(json));
- }
- else if ('bytesSent' in stat) {
- var metricId = 'webrtc_outbound_' + stat.mediaType + '_' + stat.ssrc;
- var metrics = {
- bytesSent: (stat.bytesSent - _this.stats.outbound[stat.mediaType].bytesSent) / _this.statsInterval,
- packetsSent: (stat.packetsSent - _this.stats.outbound[stat.mediaType].packetsSent) / _this.statsInterval
- };
- var units = {
- bytesSent: 'bytes',
- packetsSent: 'packets'
- };
- if (stat.mediaType === 'video') {
- metrics['framesEncoded'] = (stat.framesEncoded - _this.stats.outbound.video.framesEncoded) / _this.statsInterval;
- units['framesEncoded'] = 'frames';
- _this.stats.outbound.video.framesEncoded = stat.framesEncoded;
- }
- _this.stats.outbound[stat.mediaType].bytesSent = stat.bytesSent;
- _this.stats.outbound[stat.mediaType].packetsSent = stat.packetsSent;
- json = {
- '@timestamp': new Date(stat.timestamp).toISOString(),
- 'exec': instrumentation.exec,
- 'component': instrumentation.component,
- 'stream': 'webRtc',
- 'type': metricId,
- 'stream_type': 'composed_metrics',
- 'units': units
- };
- json[metricId] = metrics;
- sendPost(JSON.stringify(json));
- }
- }
- }
- }
- };
- this.getStatsAgnostic(this.stream.getRTCPeerConnection(), f, function (error) { console.log(error); });
- };
- WebRtcStats.prototype.standardizeReport = function (response) {
- console.log(response);
- var standardReport = {};
- if (platform.name.indexOf('Firefox') !== -1) {
- Object.keys(response).forEach(function (key) {
- console.log(response[key]);
- });
- return response;
- }
- response.result().forEach(function (report) {
- var standardStats = {
- id: report.id,
- timestamp: report.timestamp,
- type: report.type
- };
- report.names().forEach(function (name) {
- standardStats[name] = report.stat(name);
- });
- standardReport[standardStats.id] = standardStats;
- });
- return standardReport;
- };
- WebRtcStats.prototype.getStatsAgnostic = function (pc, successCb, failureCb) {
- var _this = this;
- if (platform.name.indexOf('Firefox') !== -1) {
- return pc.getStats(null).then(function (response) {
- var report = _this.standardizeReport(response);
- successCb(report);
- }).catch(failureCb);
- }
- else if ((platform.name.indexOf('Chrome') !== -1) || (platform.name.indexOf('Opera') !== -1)) {
- return pc.getStats(function (response) {
- var report = _this.standardizeReport(response);
- successCb(report);
- }, null, failureCb);
- }
- };
- return WebRtcStats;
-}());
-exports.WebRtcStats = WebRtcStats;
-
-},{"platform":8}]},{},[16])
-//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL25vZGVfbW9kdWxlcy9icm93c2VyLXBhY2svX3ByZWx1ZGUuanMiLCIuLi9ub2RlX21vZHVsZXMvZXZlbnRzL2V2ZW50cy5qcyIsIi4uL25vZGVfbW9kdWxlcy9mcmVlaWNlL2luZGV4LmpzIiwiLi4vbm9kZV9tb2R1bGVzL2ZyZWVpY2Uvc3R1bi5qc29uIiwiLi4vbm9kZV9tb2R1bGVzL2ZyZWVpY2UvdHVybi5qc29uIiwiLi4vbm9kZV9tb2R1bGVzL2hhcmsvaGFyay5qcyIsIi4uL25vZGVfbW9kdWxlcy9pbmhlcml0cy9pbmhlcml0c19icm93c2VyLmpzIiwiLi4vbm9kZV9tb2R1bGVzL25vcm1hbGljZS9pbmRleC5qcyIsIi4uL25vZGVfbW9kdWxlcy9wbGF0Zm9ybS9wbGF0Zm9ybS5qcyIsIi4uL25vZGVfbW9kdWxlcy91dWlkL2luZGV4LmpzIiwiLi4vbm9kZV9tb2R1bGVzL3V1aWQvbGliL2J5dGVzVG9VdWlkLmpzIiwiLi4vbm9kZV9tb2R1bGVzL3V1aWQvbGliL3JuZy1icm93c2VyLmpzIiwiLi4vbm9kZV9tb2R1bGVzL3V1aWQvdjEuanMiLCIuLi9ub2RlX21vZHVsZXMvdXVpZC92NC5qcyIsIi4uL25vZGVfbW9kdWxlcy93aWxkZW1pdHRlci93aWxkZW1pdHRlci5qcyIsIi4uL25vZGVfbW9kdWxlcy93b2xmeTg3LWV2ZW50ZW1pdHRlci9FdmVudEVtaXR0ZXIuanMiLCJNYWluLnRzIiwiT3BlblZpZHUvQ29ubmVjdGlvbi50cyIsIk9wZW5WaWR1L0xvY2FsUmVjb3JkZXIudHMiLCJPcGVuVmlkdS9PcGVuVmlkdS50cyIsIk9wZW5WaWR1L1B1Ymxpc2hlci50cyIsIk9wZW5WaWR1L1Nlc3Npb24udHMiLCJPcGVuVmlkdS9TdHJlYW0udHMiLCJPcGVuVmlkdS9TdHJlYW1NYW5hZ2VyLnRzIiwiT3BlblZpZHUvU3Vic2NyaWJlci50cyIsIk9wZW5WaWR1SW50ZXJuYWwvRW51bXMvTG9jYWxSZWNvcmRlclN0YXRlLnRzIiwiT3BlblZpZHVJbnRlcm5hbC9FbnVtcy9PcGVuVmlkdUVycm9yLnRzIiwiT3BlblZpZHVJbnRlcm5hbC9FbnVtcy9WaWRlb0luc2VydE1vZGUudHMiLCJPcGVuVmlkdUludGVybmFsL0V2ZW50cy9Db25uZWN0aW9uRXZlbnQudHMiLCJPcGVuVmlkdUludGVybmFsL0V2ZW50cy9FdmVudC50cyIsIk9wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1B1Ymxpc2hlclNwZWFraW5nRXZlbnQudHMiLCJPcGVuVmlkdUludGVybmFsL0V2ZW50cy9SZWNvcmRpbmdFdmVudC50cyIsIk9wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1Nlc3Npb25EaXNjb25uZWN0ZWRFdmVudC50cyIsIk9wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1NpZ25hbEV2ZW50LnRzIiwiT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvU3RyZWFtRXZlbnQudHMiLCJPcGVuVmlkdUludGVybmFsL0V2ZW50cy9TdHJlYW1NYW5hZ2VyRXZlbnQudHMiLCJPcGVuVmlkdUludGVybmFsL0V2ZW50cy9TdHJlYW1Qcm9wZXJ0eUNoYW5nZWRFdmVudC50cyIsIk9wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1ZpZGVvRWxlbWVudEV2ZW50LnRzIiwiT3BlblZpZHVJbnRlcm5hbC9LdXJlbnRvVXRpbHMva3VyZW50by1qc29ucnBjL01hcHBlci5qcyIsIk9wZW5WaWR1SW50ZXJuYWwvS3VyZW50b1V0aWxzL2t1cmVudG8tanNvbnJwYy9jbGllbnRzL2luZGV4LmpzIiwiT3BlblZpZHVJbnRlcm5hbC9LdXJlbnRvVXRpbHMva3VyZW50by1qc29ucnBjL2NsaWVudHMvanNvbnJwY2NsaWVudC5qcyIsIk9wZW5WaWR1SW50ZXJuYWwvS3VyZW50b1V0aWxzL2t1cmVudG8tanNvbnJwYy9jbGllbnRzL3RyYW5zcG9ydHMvaW5kZXguanMiLCJPcGVuVmlkdUludGVybmFsL0t1cmVudG9VdGlscy9rdXJlbnRvLWpzb25ycGMvY2xpZW50cy90cmFuc3BvcnRzL3dlYlNvY2tldFdpdGhSZWNvbm5lY3Rpb24uanMiLCJPcGVuVmlkdUludGVybmFsL0t1cmVudG9VdGlscy9rdXJlbnRvLWpzb25ycGMvaW5kZXguanMiLCJPcGVuVmlkdUludGVybmFsL0t1cmVudG9VdGlscy9rdXJlbnRvLWpzb25ycGMvcGFja2Vycy9Kc29uUlBDLmpzIiwiT3BlblZpZHVJbnRlcm5hbC9LdXJlbnRvVXRpbHMva3VyZW50by1qc29ucnBjL3BhY2tlcnMvWG1sUlBDLmpzIiwiT3BlblZpZHVJbnRlcm5hbC9LdXJlbnRvVXRpbHMva3VyZW50by1qc29ucnBjL3BhY2tlcnMvaW5kZXguanMiLCJPcGVuVmlkdUludGVybmFsL1NjcmVlblNoYXJpbmcvU2NyZWVuLUNhcHR1cmluZy1BdXRvLmpzIiwiT3BlblZpZHVJbnRlcm5hbC9TY3JlZW5TaGFyaW5nL1NjcmVlbi1DYXB0dXJpbmcuanMiLCJPcGVuVmlkdUludGVybmFsL1dlYlJ0Y1BlZXIvV2ViUnRjUGVlci50cyIsIk9wZW5WaWR1SW50ZXJuYWwvV2ViUnRjU3RhdHMvV2ViUnRjU3RhdHMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7QUNBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzNnQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDekdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDaEJBO0FBQ0E7O0FDREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2xKQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdkJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUM1REE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7O0FDanNDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDUkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDeEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbENBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDN0dBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM3QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDekpBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7O0FDdGVBLGdEQUErQztBQUUvQyxJQUFJLE1BQU0s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O1FBQWpELGlCQWNDO1FBYkcsSUFBSSxRQUFRLENBQUMsSUFBSyxDQUFDLE9BQU8sQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLENBQUMsRUFBRTtZQUUxQyxPQUFPLEVBQUUsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLENBQUMsSUFBSSxDQUFDLFVBQUEsUUFBUTtnQkFDbEMsSUFBTSxNQUFNLEdBQUcsS0FBSSxDQUFDLGlCQUFpQixDQUFDLFFBQVEsQ0FBQyxDQUFDO2dCQUNoRCxTQUFTLENBQUMsTUFBTSxDQUFDLENBQUM7WUFDdEIsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLFNBQVMsQ0FBQyxDQUFDO1NBQ3ZCO2FBQU0sSUFBSSxDQUFDLFFBQVEsQ0FBQyxJQUFLLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSyxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxFQUFFO1lBRTlGLE9BQU8sRUFBRSxDQUFDLFFBQVEsQ0FBQyxVQUFDLFFBQVE7Z0JBQ3hCLElBQU0sTUFBTSxHQUFHLEtBQUksQ0FBQyxpQkFBaUIsQ0FBQyxRQUFRLENBQUMsQ0FBQztnQkFDaEQsU0FBUyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1lBQ3RCLENBQUMsRUFBRSxJQUFJLEVBQUUsU0FBUyxDQUFDLENBQUM7U0FDdkI7SUFDTCxDQUFDO0lBRUwsa0JBQUM7QUFBRCxDQXJZQSxBQXFZQyxJQUFBO0FBcllZLGtDQUFXIiwiZmlsZSI6ImdlbmVyYXRlZC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzQ29udGVudCI6WyIoZnVuY3Rpb24oKXtmdW5jdGlvbiByKGUsbix0KXtmdW5jdGlvbiBvKGksZil7aWYoIW5baV0pe2lmKCFlW2ldKXt2YXIgYz1cImZ1bmN0aW9uXCI9PXR5cGVvZiByZXF1aXJlJiZyZXF1aXJlO2lmKCFmJiZjKXJldHVybiBjKGksITApO2lmKHUpcmV0dXJuIHUoaSwhMCk7dmFyIGE9bmV3IEVycm9yKFwiQ2Fubm90IGZpbmQgbW9kdWxlICdcIitpK1wiJ1wiKTt0aHJvdyBhLmNvZGU9XCJNT0RVTEVfTk9UX0ZPVU5EXCIsYX12YXIgcD1uW2ldPXtleHBvcnRzOnt9fTtlW2ldWzBdLmNhbGwocC5leHBvcnRzLGZ1bmN0aW9uKHIpe3ZhciBuPWVbaV1bMV1bcl07cmV0dXJuIG8obnx8cil9LHAscC5leHBvcnRzLHIsZSxuLHQpfXJldHVybiBuW2ldLmV4cG9ydHN9Zm9yKHZhciB1PVwiZnVuY3Rpb25cIj09dHlwZW9mIHJlcXVpcmUmJnJlcXVpcmUsaT0wO2k8dC5sZW5ndGg7aSsrKW8odFtpXSk7cmV0dXJuIG99cmV0dXJuIHJ9KSgpIiwiLy8gQ29weXJpZ2h0IEpveWVudCwgSW5jLiBhbmQgb3RoZXIgTm9kZSBjb250cmlidXRvcnMuXG4vL1xuLy8gUGVybWlzc2lvbiBpcyBoZXJlYnkgZ3JhbnRlZCwgZnJlZSBvZiBjaGFyZ2UsIHRvIGFueSBwZXJzb24gb2J0YWluaW5nIGFcbi8vIGNvcHkgb2YgdGhpcyBzb2Z0d2FyZSBhbmQgYXNzb2NpYXRlZCBkb2N1bWVudGF0aW9uIGZpbGVzICh0aGVcbi8vIFwiU29mdHdhcmVcIiksIHRvIGRlYWwgaW4gdGhlIFNvZnR3YXJlIHdpdGhvdXQgcmVzdHJpY3Rpb24sIGluY2x1ZGluZ1xuLy8gd2l0aG91dCBsaW1pdGF0aW9uIHRoZSByaWdodHMgdG8gdXNlLCBjb3B5LCBtb2RpZnksIG1lcmdlLCBwdWJsaXNoLFxuLy8gZGlzdHJpYnV0ZSwgc3VibGljZW5zZSwgYW5kL29yIHNlbGwgY29waWVzIG9mIHRoZSBTb2Z0d2FyZSwgYW5kIHRvIHBlcm1pdFxuLy8gcGVyc29ucyB0byB3aG9tIHRoZSBTb2Z0d2FyZSBpcyBmdXJuaXNoZWQgdG8gZG8gc28sIHN1YmplY3QgdG8gdGhlXG4vLyBmb2xsb3dpbmcgY29uZGl0aW9uczpcbi8vXG4vLyBUaGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSBhbmQgdGhpcyBwZXJtaXNzaW9uIG5vdGljZSBzaGFsbCBiZSBpbmNsdWRlZFxuLy8gaW4gYWxsIGNvcGllcyBvciBzdWJzdGFudGlhbCBwb3J0aW9ucyBvZiB0aGUgU29mdHdhcmUuXG4vL1xuLy8gVEhFIFNPRlRXQVJFIElTIFBST1ZJREVEIFwiQVMgSVNcIiwgV0lUSE9VVCBXQVJSQU5UWSBPRiBBTlkgS0lORCwgRVhQUkVTU1xuLy8gT1IgSU1QTElFRCwgSU5DTFVESU5HIEJVVCBOT1QgTElNSVRFRCBUTyBUSEUgV0FSUkFOVElFUyBPRlxuLy8gTUVSQ0hBTlRBQklMSVRZLCBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBTkQgTk9OSU5GUklOR0VNRU5ULiBJTlxuLy8gTk8gRVZFTlQgU0hBTEwgVEhFIEFVVEhPUlMgT1IgQ09QWVJJR0hUIEhPTERFUlMgQkUgTElBQkxFIEZPUiBBTlkgQ0xBSU0sXG4vLyBEQU1BR0VTIE9SIE9USEVSIExJQUJJTElUWSwgV0hFVEhFUiBJTiBBTiBBQ1RJT04gT0YgQ09OVFJBQ1QsIFRPUlQgT1Jcbi8vIE9USEVSV0lTRSwgQVJJU0lORyBGUk9NLCBPVVQgT0YgT1IgSU4gQ09OTkVDVElPTiBXSVRIIFRIRSBTT0ZUV0FSRSBPUiBUSEVcbi8vIFVTRSBPUiBPVEhFUiBERUFMSU5HUyBJTiBUSEUgU09GVFdBUkUuXG5cbnZhciBvYmplY3RDcmVhdGUgPSBPYmplY3QuY3JlYXRlIHx8IG9iamVjdENyZWF0ZVBvbHlmaWxsXG52YXIgb2JqZWN0S2V5cyA9IE9iamVjdC5rZXlzIHx8IG9iamVjdEtleXNQb2x5ZmlsbFxudmFyIGJpbmQgPSBGdW5jdGlvbi5wcm90b3R5cGUuYmluZCB8fCBmdW5jdGlvbkJpbmRQb2x5ZmlsbFxuXG5mdW5jdGlvbiBFdmVudEVtaXR0ZXIoKSB7XG4gIGlmICghdGhpcy5fZXZlbnRzIHx8ICFPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwodGhpcywgJ19ldmVudHMnKSkge1xuICAgIHRoaXMuX2V2ZW50cyA9IG9iamVjdENyZWF0ZShudWxsKTtcbiAgICB0aGlzLl9ldmVudHNDb3VudCA9IDA7XG4gIH1cblxuICB0aGlzLl9tYXhMaXN0ZW5lcnMgPSB0aGlzLl9tYXhMaXN0ZW5lcnMgfHwgdW5kZWZpbmVkO1xufVxubW9kdWxlLmV4cG9ydHMgPSBFdmVudEVtaXR0ZXI7XG5cbi8vIEJhY2t3YXJkcy1jb21wYXQgd2l0aCBub2RlIDAuMTAueFxuRXZlbnRFbWl0dGVyLkV2ZW50RW1pdHRlciA9IEV2ZW50RW1pdHRlcjtcblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5fZXZlbnRzID0gdW5kZWZpbmVkO1xuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5fbWF4TGlzdGVuZXJzID0gdW5kZWZpbmVkO1xuXG4vLyBCeSBkZWZhdWx0IEV2ZW50RW1pdHRlcnMgd2lsbCBwcmludCBhIHdhcm5pbmcgaWYgbW9yZSB0aGFuIDEwIGxpc3RlbmVycyBhcmVcbi8vIGFkZGVkIHRvIGl0LiBUaGlzIGlzIGEgdXNlZnVsIGRlZmF1bHQgd2hpY2ggaGVscHMgZmluZGluZyBtZW1vcnkgbGVha3MuXG52YXIgZGVmYXVsdE1heExpc3RlbmVycyA9IDEwO1xuXG52YXIgaGFzRGVmaW5lUHJvcGVydHk7XG50cnkge1xuICB2YXIgbyA9IHt9O1xuICBpZiAoT2JqZWN0LmRlZmluZVByb3BlcnR5KSBPYmplY3QuZGVmaW5lUHJvcGVydHkobywgJ3gnLCB7IHZhbHVlOiAwIH0pO1xuICBoYXNEZWZpbmVQcm9wZXJ0eSA9IG8ueCA9PT0gMDtcbn0gY2F0Y2ggKGVycikgeyBoYXNEZWZpbmVQcm9wZXJ0eSA9IGZhbHNlIH1cbmlmIChoYXNEZWZpbmVQcm9wZXJ0eSkge1xuICBPYmplY3QuZGVmaW5lUHJvcGVydHkoRXZlbnRFbWl0dGVyLCAnZGVmYXVsdE1heExpc3RlbmVycycsIHtcbiAgICBlbnVtZXJhYmxlOiB0cnVlLFxuICAgIGdldDogZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4gZGVmYXVsdE1heExpc3RlbmVycztcbiAgICB9LFxuICAgIHNldDogZnVuY3Rpb24oYXJnKSB7XG4gICAgICAvLyBjaGVjayB3aGV0aGVyIHRoZSBpbnB1dCBpcyBhIHBvc2l0aXZlIG51bWJlciAod2hvc2UgdmFsdWUgaXMgemVybyBvclxuICAgICAgLy8gZ3JlYXRlciBhbmQgbm90IGEgTmFOKS5cbiAgICAgIGlmICh0eXBlb2YgYXJnICE9PSAnbnVtYmVyJyB8fCBhcmcgPCAwIHx8IGFyZyAhPT0gYXJnKVxuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdcImRlZmF1bHRNYXhMaXN0ZW5lcnNcIiBtdXN0IGJlIGEgcG9zaXRpdmUgbnVtYmVyJyk7XG4gICAgICBkZWZhdWx0TWF4TGlzdGVuZXJzID0gYXJnO1xuICAgIH1cbiAgfSk7XG59IGVsc2Uge1xuICBFdmVudEVtaXR0ZXIuZGVmYXVsdE1heExpc3RlbmVycyA9IGRlZmF1bHRNYXhMaXN0ZW5lcnM7XG59XG5cbi8vIE9idmlvdXNseSBub3QgYWxsIEVtaXR0ZXJzIHNob3VsZCBiZSBsaW1pdGVkIHRvIDEwLiBUaGlzIGZ1bmN0aW9uIGFsbG93c1xuLy8gdGhhdCB0byBiZSBpbmNyZWFzZWQuIFNldCB0byB6ZXJvIGZvciB1bmxpbWl0ZWQuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLnNldE1heExpc3RlbmVycyA9IGZ1bmN0aW9uIHNldE1heExpc3RlbmVycyhuKSB7XG4gIGlmICh0eXBlb2YgbiAhPT0gJ251bWJlcicgfHwgbiA8IDAgfHwgaXNOYU4obikpXG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcignXCJuXCIgYXJndW1lbnQgbXVzdCBiZSBhIHBvc2l0aXZlIG51bWJlcicpO1xuICB0aGlzLl9tYXhMaXN0ZW5lcnMgPSBuO1xuICByZXR1cm4gdGhpcztcbn07XG5cbmZ1bmN0aW9uICRnZXRNYXhMaXN0ZW5lcnModGhhdCkge1xuICBpZiAodGhhdC5fbWF4TGlzdGVuZXJzID09PSB1bmRlZmluZWQpXG4gICAgcmV0dXJuIEV2ZW50RW1pdHRlci5kZWZhdWx0TWF4TGlzdGVuZXJzO1xuICByZXR1cm4gdGhhdC5fbWF4TGlzdGVuZXJzO1xufVxuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLmdldE1heExpc3RlbmVycyA9IGZ1bmN0aW9uIGdldE1heExpc3RlbmVycygpIHtcbiAgcmV0dXJuICRnZXRNYXhMaXN0ZW5lcnModGhpcyk7XG59O1xuXG4vLyBUaGVzZSBzdGFuZGFsb25lIGVtaXQqIGZ1bmN0aW9ucyBhcmUgdXNlZCB0byBvcHRpbWl6ZSBjYWxsaW5nIG9mIGV2ZW50XG4vLyBoYW5kbGVycyBmb3IgZmFzdCBjYXNlcyBiZWNhdXNlIGVtaXQoKSBpdHNlbGYgb2Z0ZW4gaGFzIGEgdmFyaWFibGUgbnVtYmVyIG9mXG4vLyBhcmd1bWVudHMgYW5kIGNhbiBiZSBkZW9wdGltaXplZCBiZWNhdXNlIG9mIHRoYXQuIFRoZXNlIGZ1bmN0aW9ucyBhbHdheXMgaGF2ZVxuLy8gdGhlIHNhbWUgbnVtYmVyIG9mIGFyZ3VtZW50cyBhbmQgdGh1cyBkbyBub3QgZ2V0IGRlb3B0aW1pemVkLCBzbyB0aGUgY29kZVxuLy8gaW5zaWRlIHRoZW0gY2FuIGV4ZWN1dGUgZmFzdGVyLlxuZnVuY3Rpb24gZW1pdE5vbmUoaGFuZGxlciwgaXNGbiwgc2VsZikge1xuICBpZiAoaXNGbilcbiAgICBoYW5kbGVyLmNhbGwoc2VsZik7XG4gIGVsc2Uge1xuICAgIHZhciBsZW4gPSBoYW5kbGVyLmxlbmd0aDtcbiAgICB2YXIgbGlzdGVuZXJzID0gYXJyYXlDbG9uZShoYW5kbGVyLCBsZW4pO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuOyArK2kpXG4gICAgICBsaXN0ZW5lcnNbaV0uY2FsbChzZWxmKTtcbiAgfVxufVxuZnVuY3Rpb24gZW1pdE9uZShoYW5kbGVyLCBpc0ZuLCBzZWxmLCBhcmcxKSB7XG4gIGlmIChpc0ZuKVxuICAgIGhhbmRsZXIuY2FsbChzZWxmLCBhcmcxKTtcbiAgZWxzZSB7XG4gICAgdmFyIGxlbiA9IGhhbmRsZXIubGVuZ3RoO1xuICAgIHZhciBsaXN0ZW5lcnMgPSBhcnJheUNsb25lKGhhbmRsZXIsIGxlbik7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW47ICsraSlcbiAgICAgIGxpc3RlbmVyc1tpXS5jYWxsKHNlbGYsIGFyZzEpO1xuICB9XG59XG5mdW5jdGlvbiBlbWl0VHdvKGhhbmRsZXIsIGlzRm4sIHNlbGYsIGFyZzEsIGFyZzIpIHtcbiAgaWYgKGlzRm4pXG4gICAgaGFuZGxlci5jYWxsKHNlbGYsIGFyZzEsIGFyZzIpO1xuICBlbHNlIHtcbiAgICB2YXIgbGVuID0gaGFuZGxlci5sZW5ndGg7XG4gICAgdmFyIGxpc3RlbmVycyA9IGFycmF5Q2xvbmUoaGFuZGxlciwgbGVuKTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgKytpKVxuICAgICAgbGlzdGVuZXJzW2ldLmNhbGwoc2VsZiwgYXJnMSwgYXJnMik7XG4gIH1cbn1cbmZ1bmN0aW9uIGVtaXRUaHJlZShoYW5kbGVyLCBpc0ZuLCBzZWxmLCBhcmcxLCBhcmcyLCBhcmczKSB7XG4gIGlmIChpc0ZuKVxuICAgIGhhbmRsZXIuY2FsbChzZWxmLCBhcmcxLCBhcmcyLCBhcmczKTtcbiAgZWxzZSB7XG4gICAgdmFyIGxlbiA9IGhhbmRsZXIubGVuZ3RoO1xuICAgIHZhciBsaXN0ZW5lcnMgPSBhcnJheUNsb25lKGhhbmRsZXIsIGxlbik7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW47ICsraSlcbiAgICAgIGxpc3RlbmVyc1tpXS5jYWxsKHNlbGYsIGFyZzEsIGFyZzIsIGFyZzMpO1xuICB9XG59XG5cbmZ1bmN0aW9uIGVtaXRNYW55KGhhbmRsZXIsIGlzRm4sIHNlbGYsIGFyZ3MpIHtcbiAgaWYgKGlzRm4pXG4gICAgaGFuZGxlci5hcHBseShzZWxmLCBhcmdzKTtcbiAgZWxzZSB7XG4gICAgdmFyIGxlbiA9IGhhbmRsZXIubGVuZ3RoO1xuICAgIHZhciBsaXN0ZW5lcnMgPSBhcnJheUNsb25lKGhhbmRsZXIsIGxlbik7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW47ICsraSlcbiAgICAgIGxpc3RlbmVyc1tpXS5hcHBseShzZWxmLCBhcmdzKTtcbiAgfVxufVxuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLmVtaXQgPSBmdW5jdGlvbiBlbWl0KHR5cGUpIHtcbiAgdmFyIGVyLCBoYW5kbGVyLCBsZW4sIGFyZ3MsIGksIGV2ZW50cztcbiAgdmFyIGRvRXJyb3IgPSAodHlwZSA9PT0gJ2Vycm9yJyk7XG5cbiAgZXZlbnRzID0gdGhpcy5fZXZlbnRzO1xuICBpZiAoZXZlbnRzKVxuICAgIGRvRXJyb3IgPSAoZG9FcnJvciAmJiBldmVudHMuZXJyb3IgPT0gbnVsbCk7XG4gIGVsc2UgaWYgKCFkb0Vycm9yKVxuICAgIHJldHVybiBmYWxzZTtcblxuICAvLyBJZiB0aGVyZSBpcyBubyAnZXJyb3InIGV2ZW50IGxpc3RlbmVyIHRoZW4gdGhyb3cuXG4gIGlmIChkb0Vycm9yKSB7XG4gICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPiAxKVxuICAgICAgZXIgPSBhcmd1bWVudHNbMV07XG4gICAgaWYgKGVyIGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICAgIHRocm93IGVyOyAvLyBVbmhhbmRsZWQgJ2Vycm9yJyBldmVudFxuICAgIH0gZWxzZSB7XG4gICAgICAvLyBBdCBsZWFzdCBnaXZlIHNvbWUga2luZCBvZiBjb250ZXh0IHRvIHRoZSB1c2VyXG4gICAgICB2YXIgZXJyID0gbmV3IEVycm9yKCdVbmhhbmRsZWQgXCJlcnJvclwiIGV2ZW50LiAoJyArIGVyICsgJyknKTtcbiAgICAgIGVyci5jb250ZXh0ID0gZXI7XG4gICAgICB0aHJvdyBlcnI7XG4gICAgfVxuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIGhhbmRsZXIgPSBldmVudHNbdHlwZV07XG5cbiAgaWYgKCFoYW5kbGVyKVxuICAgIHJldHVybiBmYWxzZTtcblxuICB2YXIgaXNGbiA9IHR5cGVvZiBoYW5kbGVyID09PSAnZnVuY3Rpb24nO1xuICBsZW4gPSBhcmd1bWVudHMubGVuZ3RoO1xuICBzd2l0Y2ggKGxlbikge1xuICAgICAgLy8gZmFzdCBjYXNlc1xuICAgIGNhc2UgMTpcbiAgICAgIGVtaXROb25lKGhhbmRsZXIsIGlzRm4sIHRoaXMpO1xuICAgICAgYnJlYWs7XG4gICAgY2FzZSAyOlxuICAgICAgZW1pdE9uZShoYW5kbGVyLCBpc0ZuLCB0aGlzLCBhcmd1bWVudHNbMV0pO1xuICAgICAgYnJlYWs7XG4gICAgY2FzZSAzOlxuICAgICAgZW1pdFR3byhoYW5kbGVyLCBpc0ZuLCB0aGlzLCBhcmd1bWVudHNbMV0sIGFyZ3VtZW50c1syXSk7XG4gICAgICBicmVhaztcbiAgICBjYXNlIDQ6XG4gICAgICBlbWl0VGhyZWUoaGFuZGxlciwgaXNGbiwgdGhpcywgYXJndW1lbnRzWzFdLCBhcmd1bWVudHNbMl0sIGFyZ3VtZW50c1szXSk7XG4gICAgICBicmVhaztcbiAgICAgIC8vIHNsb3dlclxuICAgIGRlZmF1bHQ6XG4gICAgICBhcmdzID0gbmV3IEFycmF5KGxlbiAtIDEpO1xuICAgICAgZm9yIChpID0gMTsgaSA8IGxlbjsgaSsrKVxuICAgICAgICBhcmdzW2kgLSAxXSA9IGFyZ3VtZW50c1tpXTtcbiAgICAgIGVtaXRNYW55KGhhbmRsZXIsIGlzRm4sIHRoaXMsIGFyZ3MpO1xuICB9XG5cbiAgcmV0dXJuIHRydWU7XG59O1xuXG5mdW5jdGlvbiBfYWRkTGlzdGVuZXIodGFyZ2V0LCB0eXBlLCBsaXN0ZW5lciwgcHJlcGVuZCkge1xuICB2YXIgbTtcbiAgdmFyIGV2ZW50cztcbiAgdmFyIGV4aXN0aW5nO1xuXG4gIGlmICh0eXBlb2YgbGlzdGVuZXIgIT09ICdmdW5jdGlvbicpXG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcignXCJsaXN0ZW5lclwiIGFyZ3VtZW50IG11c3QgYmUgYSBmdW5jdGlvbicpO1xuXG4gIGV2ZW50cyA9IHRhcmdldC5fZXZlbnRzO1xuICBpZiAoIWV2ZW50cykge1xuICAgIGV2ZW50cyA9IHRhcmdldC5fZXZlbnRzID0gb2JqZWN0Q3JlYXRlKG51bGwpO1xuICAgIHRhcmdldC5fZXZlbnRzQ291bnQgPSAwO1xuICB9IGVsc2Uge1xuICAgIC8vIFRvIGF2b2lkIHJlY3Vyc2lvbiBpbiB0aGUgY2FzZSB0aGF0IHR5cGUgPT09IFwibmV3TGlzdGVuZXJcIiEgQmVmb3JlXG4gICAgLy8gYWRkaW5nIGl0IHRvIHRoZSBsaXN0ZW5lcnMsIGZpcnN0IGVtaXQgXCJuZXdMaXN0ZW5lclwiLlxuICAgIGlmIChldmVudHMubmV3TGlzdGVuZXIpIHtcbiAgICAgIHRhcmdldC5lbWl0KCduZXdMaXN0ZW5lcicsIHR5cGUsXG4gICAgICAgICAgbGlzdGVuZXIubGlzdGVuZXIgPyBsaXN0ZW5lci5saXN0ZW5lciA6IGxpc3RlbmVyKTtcblxuICAgICAgLy8gUmUtYXNzaWduIGBldmVudHNgIGJlY2F1c2UgYSBuZXdMaXN0ZW5lciBoYW5kbGVyIGNvdWxkIGhhdmUgY2F1c2VkIHRoZVxuICAgICAgLy8gdGhpcy5fZXZlbnRzIHRvIGJlIGFzc2lnbmVkIHRvIGEgbmV3IG9iamVjdFxuICAgICAgZXZlbnRzID0gdGFyZ2V0Ll9ldmVudHM7XG4gICAgfVxuICAgIGV4aXN0aW5nID0gZXZlbnRzW3R5cGVdO1xuICB9XG5cbiAgaWYgKCFleGlzdGluZykge1xuICAgIC8vIE9wdGltaXplIHRoZSBjYXNlIG9mIG9uZSBsaXN0ZW5lci4gRG9uJ3QgbmVlZCB0aGUgZXh0cmEgYXJyYXkgb2JqZWN0LlxuICAgIGV4aXN0aW5nID0gZXZlbnRzW3R5cGVdID0gbGlzdGVuZXI7XG4gICAgKyt0YXJnZXQuX2V2ZW50c0NvdW50O1xuICB9IGVsc2Uge1xuICAgIGlmICh0eXBlb2YgZXhpc3RpbmcgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgIC8vIEFkZGluZyB0aGUgc2Vjb25kIGVsZW1lbnQsIG5lZWQgdG8gY2hhbmdlIHRvIGFycmF5LlxuICAgICAgZXhpc3RpbmcgPSBldmVudHNbdHlwZV0gPVxuICAgICAgICAgIHByZXBlbmQgPyBbbGlzdGVuZXIsIGV4aXN0aW5nXSA6IFtleGlzdGluZywgbGlzdGVuZXJdO1xuICAgIH0gZWxzZSB7XG4gICAgICAvLyBJZiB3ZSd2ZSBhbHJlYWR5IGdvdCBhbiBhcnJheSwganVzdCBhcHBlbmQuXG4gICAgICBpZiAocHJlcGVuZCkge1xuICAgICAgICBleGlzdGluZy51bnNoaWZ0KGxpc3RlbmVyKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGV4aXN0aW5nLnB1c2gobGlzdGVuZXIpO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIENoZWNrIGZvciBsaXN0ZW5lciBsZWFrXG4gICAgaWYgKCFleGlzdGluZy53YXJuZWQpIHtcbiAgICAgIG0gPSAkZ2V0TWF4TGlzdGVuZXJzKHRhcmdldCk7XG4gICAgICBpZiAobSAmJiBtID4gMCAmJiBleGlzdGluZy5sZW5ndGggPiBtKSB7XG4gICAgICAgIGV4aXN0aW5nLndhcm5lZCA9IHRydWU7XG4gICAgICAgIHZhciB3ID0gbmV3IEVycm9yKCdQb3NzaWJsZSBFdmVudEVtaXR0ZXIgbWVtb3J5IGxlYWsgZGV0ZWN0ZWQuICcgK1xuICAgICAgICAgICAgZXhpc3RpbmcubGVuZ3RoICsgJyBcIicgKyBTdHJpbmcodHlwZSkgKyAnXCIgbGlzdGVuZXJzICcgK1xuICAgICAgICAgICAgJ2FkZGVkLiBVc2UgZW1pdHRlci5zZXRNYXhMaXN0ZW5lcnMoKSB0byAnICtcbiAgICAgICAgICAgICdpbmNyZWFzZSBsaW1pdC4nKTtcbiAgICAgICAgdy5uYW1lID0gJ01heExpc3RlbmVyc0V4Y2VlZGVkV2FybmluZyc7XG4gICAgICAgIHcuZW1pdHRlciA9IHRhcmdldDtcbiAgICAgICAgdy50eXBlID0gdHlwZTtcbiAgICAgICAgdy5jb3VudCA9IGV4aXN0aW5nLmxlbmd0aDtcbiAgICAgICAgaWYgKHR5cGVvZiBjb25zb2xlID09PSAnb2JqZWN0JyAmJiBjb25zb2xlLndhcm4pIHtcbiAgICAgICAgICBjb25zb2xlLndhcm4oJyVzOiAlcycsIHcubmFtZSwgdy5tZXNzYWdlKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHJldHVybiB0YXJnZXQ7XG59XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUuYWRkTGlzdGVuZXIgPSBmdW5jdGlvbiBhZGRMaXN0ZW5lcih0eXBlLCBsaXN0ZW5lcikge1xuICByZXR1cm4gX2FkZExpc3RlbmVyKHRoaXMsIHR5cGUsIGxpc3RlbmVyLCBmYWxzZSk7XG59O1xuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLm9uID0gRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5hZGRMaXN0ZW5lcjtcblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5wcmVwZW5kTGlzdGVuZXIgPVxuICAgIGZ1bmN0aW9uIHByZXBlbmRMaXN0ZW5lcih0eXBlLCBsaXN0ZW5lcikge1xuICAgICAgcmV0dXJuIF9hZGRMaXN0ZW5lcih0aGlzLCB0eXBlLCBsaXN0ZW5lciwgdHJ1ZSk7XG4gICAgfTtcblxuZnVuY3Rpb24gb25jZVdyYXBwZXIoKSB7XG4gIGlmICghdGhpcy5maXJlZCkge1xuICAgIHRoaXMudGFyZ2V0LnJlbW92ZUxpc3RlbmVyKHRoaXMudHlwZSwgdGhpcy53cmFwRm4pO1xuICAgIHRoaXMuZmlyZWQgPSB0cnVlO1xuICAgIHN3aXRjaCAoYXJndW1lbnRzLmxlbmd0aCkge1xuICAgICAgY2FzZSAwOlxuICAgICAgICByZXR1cm4gdGhpcy5saXN0ZW5lci5jYWxsKHRoaXMudGFyZ2V0KTtcbiAgICAgIGNhc2UgMTpcbiAgICAgICAgcmV0dXJuIHRoaXMubGlzdGVuZXIuY2FsbCh0aGlzLnRhcmdldCwgYXJndW1lbnRzWzBdKTtcbiAgICAgIGNhc2UgMjpcbiAgICAgICAgcmV0dXJuIHRoaXMubGlzdGVuZXIuY2FsbCh0aGlzLnRhcmdldCwgYXJndW1lbnRzWzBdLCBhcmd1bWVudHNbMV0pO1xuICAgICAgY2FzZSAzOlxuICAgICAgICByZXR1cm4gdGhpcy5saXN0ZW5lci5jYWxsKHRoaXMudGFyZ2V0LCBhcmd1bWVudHNbMF0sIGFyZ3VtZW50c1sxXSxcbiAgICAgICAgICAgIGFyZ3VtZW50c1syXSk7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB2YXIgYXJncyA9IG5ldyBBcnJheShhcmd1bWVudHMubGVuZ3RoKTtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBhcmdzLmxlbmd0aDsgKytpKVxuICAgICAgICAgIGFyZ3NbaV0gPSBhcmd1bWVudHNbaV07XG4gICAgICAgIHRoaXMubGlzdGVuZXIuYXBwbHkodGhpcy50YXJnZXQsIGFyZ3MpO1xuICAgIH1cbiAgfVxufVxuXG5mdW5jdGlvbiBfb25jZVdyYXAodGFyZ2V0LCB0eXBlLCBsaXN0ZW5lcikge1xuICB2YXIgc3RhdGUgPSB7IGZpcmVkOiBmYWxzZSwgd3JhcEZuOiB1bmRlZmluZWQsIHRhcmdldDogdGFyZ2V0LCB0eXBlOiB0eXBlLCBsaXN0ZW5lcjogbGlzdGVuZXIgfTtcbiAgdmFyIHdyYXBwZWQgPSBiaW5kLmNhbGwob25jZVdyYXBwZXIsIHN0YXRlKTtcbiAgd3JhcHBlZC5saXN0ZW5lciA9IGxpc3RlbmVyO1xuICBzdGF0ZS53cmFwRm4gPSB3cmFwcGVkO1xuICByZXR1cm4gd3JhcHBlZDtcbn1cblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5vbmNlID0gZnVuY3Rpb24gb25jZSh0eXBlLCBsaXN0ZW5lcikge1xuICBpZiAodHlwZW9mIGxpc3RlbmVyICE9PSAnZnVuY3Rpb24nKVxuICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ1wibGlzdGVuZXJcIiBhcmd1bWVudCBtdXN0IGJlIGEgZnVuY3Rpb24nKTtcbiAgdGhpcy5vbih0eXBlLCBfb25jZVdyYXAodGhpcywgdHlwZSwgbGlzdGVuZXIpKTtcbiAgcmV0dXJuIHRoaXM7XG59O1xuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLnByZXBlbmRPbmNlTGlzdGVuZXIgPVxuICAgIGZ1bmN0aW9uIHByZXBlbmRPbmNlTGlzdGVuZXIodHlwZSwgbGlzdGVuZXIpIHtcbiAgICAgIGlmICh0eXBlb2YgbGlzdGVuZXIgIT09ICdmdW5jdGlvbicpXG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ1wibGlzdGVuZXJcIiBhcmd1bWVudCBtdXN0IGJlIGEgZnVuY3Rpb24nKTtcbiAgICAgIHRoaXMucHJlcGVuZExpc3RlbmVyKHR5cGUsIF9vbmNlV3JhcCh0aGlzLCB0eXBlLCBsaXN0ZW5lcikpO1xuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcblxuLy8gRW1pdHMgYSAncmVtb3ZlTGlzdGVuZXInIGV2ZW50IGlmIGFuZCBvbmx5IGlmIHRoZSBsaXN0ZW5lciB3YXMgcmVtb3ZlZC5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUucmVtb3ZlTGlzdGVuZXIgPVxuICAgIGZ1bmN0aW9uIHJlbW92ZUxpc3RlbmVyKHR5cGUsIGxpc3RlbmVyKSB7XG4gICAgICB2YXIgbGlzdCwgZXZlbnRzLCBwb3NpdGlvbiwgaSwgb3JpZ2luYWxMaXN0ZW5lcjtcblxuICAgICAgaWYgKHR5cGVvZiBsaXN0ZW5lciAhPT0gJ2Z1bmN0aW9uJylcbiAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignXCJsaXN0ZW5lclwiIGFyZ3VtZW50IG11c3QgYmUgYSBmdW5jdGlvbicpO1xuXG4gICAgICBldmVudHMgPSB0aGlzLl9ldmVudHM7XG4gICAgICBpZiAoIWV2ZW50cylcbiAgICAgICAgcmV0dXJuIHRoaXM7XG5cbiAgICAgIGxpc3QgPSBldmVudHNbdHlwZV07XG4gICAgICBpZiAoIWxpc3QpXG4gICAgICAgIHJldHVybiB0aGlzO1xuXG4gICAgICBpZiAobGlzdCA9PT0gbGlzdGVuZXIgfHwgbGlzdC5saXN0ZW5lciA9PT0gbGlzdGVuZXIpIHtcbiAgICAgICAgaWYgKC0tdGhpcy5fZXZlbnRzQ291bnQgPT09IDApXG4gICAgICAgICAgdGhpcy5fZXZlbnRzID0gb2JqZWN0Q3JlYXRlKG51bGwpO1xuICAgICAgICBlbHNlIHtcbiAgICAgICAgICBkZWxldGUgZXZlbnRzW3R5cGVdO1xuICAgICAgICAgIGlmIChldmVudHMucmVtb3ZlTGlzdGVuZXIpXG4gICAgICAgICAgICB0aGlzLmVtaXQoJ3JlbW92ZUxpc3RlbmVyJywgdHlwZSwgbGlzdC5saXN0ZW5lciB8fCBsaXN0ZW5lcik7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSBpZiAodHlwZW9mIGxpc3QgIT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgcG9zaXRpb24gPSAtMTtcblxuICAgICAgICBmb3IgKGkgPSBsaXN0Lmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgICAgICAgaWYgKGxpc3RbaV0gPT09IGxpc3RlbmVyIHx8IGxpc3RbaV0ubGlzdGVuZXIgPT09IGxpc3RlbmVyKSB7XG4gICAgICAgICAgICBvcmlnaW5hbExpc3RlbmVyID0gbGlzdFtpXS5saXN0ZW5lcjtcbiAgICAgICAgICAgIHBvc2l0aW9uID0gaTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChwb3NpdGlvbiA8IDApXG4gICAgICAgICAgcmV0dXJuIHRoaXM7XG5cbiAgICAgICAgaWYgKHBvc2l0aW9uID09PSAwKVxuICAgICAgICAgIGxpc3Quc2hpZnQoKTtcbiAgICAgICAgZWxzZVxuICAgICAgICAgIHNwbGljZU9uZShsaXN0LCBwb3NpdGlvbik7XG5cbiAgICAgICAgaWYgKGxpc3QubGVuZ3RoID09PSAxKVxuICAgICAgICAgIGV2ZW50c1t0eXBlXSA9IGxpc3RbMF07XG5cbiAgICAgICAgaWYgKGV2ZW50cy5yZW1vdmVMaXN0ZW5lcilcbiAgICAgICAgICB0aGlzLmVtaXQoJ3JlbW92ZUxpc3RlbmVyJywgdHlwZSwgb3JpZ2luYWxMaXN0ZW5lciB8fCBsaXN0ZW5lcik7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUucmVtb3ZlQWxsTGlzdGVuZXJzID1cbiAgICBmdW5jdGlvbiByZW1vdmVBbGxMaXN0ZW5lcnModHlwZSkge1xuICAgICAgdmFyIGxpc3RlbmVycywgZXZlbnRzLCBpO1xuXG4gICAgICBldmVudHMgPSB0aGlzLl9ldmVudHM7XG4gICAgICBpZiAoIWV2ZW50cylcbiAgICAgICAgcmV0dXJuIHRoaXM7XG5cbiAgICAgIC8vIG5vdCBsaXN0ZW5pbmcgZm9yIHJlbW92ZUxpc3RlbmVyLCBubyBuZWVkIHRvIGVtaXRcbiAgICAgIGlmICghZXZlbnRzLnJlbW92ZUxpc3RlbmVyKSB7XG4gICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgdGhpcy5fZXZlbnRzID0gb2JqZWN0Q3JlYXRlKG51bGwpO1xuICAgICAgICAgIHRoaXMuX2V2ZW50c0NvdW50ID0gMDtcbiAgICAgICAgfSBlbHNlIGlmIChldmVudHNbdHlwZV0pIHtcbiAgICAgICAgICBpZiAoLS10aGlzLl9ldmVudHNDb3VudCA9PT0gMClcbiAgICAgICAgICAgIHRoaXMuX2V2ZW50cyA9IG9iamVjdENyZWF0ZShudWxsKTtcbiAgICAgICAgICBlbHNlXG4gICAgICAgICAgICBkZWxldGUgZXZlbnRzW3R5cGVdO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgfVxuXG4gICAgICAvLyBlbWl0IHJlbW92ZUxpc3RlbmVyIGZvciBhbGwgbGlzdGVuZXJzIG9uIGFsbCBldmVudHNcbiAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgIHZhciBrZXlzID0gb2JqZWN0S2V5cyhldmVudHMpO1xuICAgICAgICB2YXIga2V5O1xuICAgICAgICBmb3IgKGkgPSAwOyBpIDwga2V5cy5sZW5ndGg7ICsraSkge1xuICAgICAgICAgIGtleSA9IGtleXNbaV07XG4gICAgICAgICAgaWYgKGtleSA9PT0gJ3JlbW92ZUxpc3RlbmVyJykgY29udGludWU7XG4gICAgICAgICAgdGhpcy5yZW1vdmVBbGxMaXN0ZW5lcnMoa2V5KTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnJlbW92ZUFsbExpc3RlbmVycygncmVtb3ZlTGlzdGVuZXInKTtcbiAgICAgICAgdGhpcy5fZXZlbnRzID0gb2JqZWN0Q3JlYXRlKG51bGwpO1xuICAgICAgICB0aGlzLl9ldmVudHNDb3VudCA9IDA7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgfVxuXG4gICAgICBsaXN0ZW5lcnMgPSBldmVudHNbdHlwZV07XG5cbiAgICAgIGlmICh0eXBlb2YgbGlzdGVuZXJzID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgIHRoaXMucmVtb3ZlTGlzdGVuZXIodHlwZSwgbGlzdGVuZXJzKTtcbiAgICAgIH0gZWxzZSBpZiAobGlzdGVuZXJzKSB7XG4gICAgICAgIC8vIExJRk8gb3JkZXJcbiAgICAgICAgZm9yIChpID0gbGlzdGVuZXJzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgICAgICAgdGhpcy5yZW1vdmVMaXN0ZW5lcih0eXBlLCBsaXN0ZW5lcnNbaV0pO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG5cbmZ1bmN0aW9uIF9saXN0ZW5lcnModGFyZ2V0LCB0eXBlLCB1bndyYXApIHtcbiAgdmFyIGV2ZW50cyA9IHRhcmdldC5fZXZlbnRzO1xuXG4gIGlmICghZXZlbnRzKVxuICAgIHJldHVybiBbXTtcblxuICB2YXIgZXZsaXN0ZW5lciA9IGV2ZW50c1t0eXBlXTtcbiAgaWYgKCFldmxpc3RlbmVyKVxuICAgIHJldHVybiBbXTtcblxuICBpZiAodHlwZW9mIGV2bGlzdGVuZXIgPT09ICdmdW5jdGlvbicpXG4gICAgcmV0dXJuIHVud3JhcCA/IFtldmxpc3RlbmVyLmxpc3RlbmVyIHx8IGV2bGlzdGVuZXJdIDogW2V2bGlzdGVuZXJdO1xuXG4gIHJldHVybiB1bndyYXAgPyB1bndyYXBMaXN0ZW5lcnMoZXZsaXN0ZW5lcikgOiBhcnJheUNsb25lKGV2bGlzdGVuZXIsIGV2bGlzdGVuZXIubGVuZ3RoKTtcbn1cblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5saXN0ZW5lcnMgPSBmdW5jdGlvbiBsaXN0ZW5lcnModHlwZSkge1xuICByZXR1cm4gX2xpc3RlbmVycyh0aGlzLCB0eXBlLCB0cnVlKTtcbn07XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUucmF3TGlzdGVuZXJzID0gZnVuY3Rpb24gcmF3TGlzdGVuZXJzKHR5cGUpIHtcbiAgcmV0dXJuIF9saXN0ZW5lcnModGhpcywgdHlwZSwgZmFsc2UpO1xufTtcblxuRXZlbnRFbWl0dGVyLmxpc3RlbmVyQ291bnQgPSBmdW5jdGlvbihlbWl0dGVyLCB0eXBlKSB7XG4gIGlmICh0eXBlb2YgZW1pdHRlci5saXN0ZW5lckNvdW50ID09PSAnZnVuY3Rpb24nKSB7XG4gICAgcmV0dXJuIGVtaXR0ZXIubGlzdGVuZXJDb3VudCh0eXBlKTtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gbGlzdGVuZXJDb3VudC5jYWxsKGVtaXR0ZXIsIHR5cGUpO1xuICB9XG59O1xuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLmxpc3RlbmVyQ291bnQgPSBsaXN0ZW5lckNvdW50O1xuZnVuY3Rpb24gbGlzdGVuZXJDb3VudCh0eXBlKSB7XG4gIHZhciBldmVudHMgPSB0aGlzLl9ldmVudHM7XG5cbiAgaWYgKGV2ZW50cykge1xuICAgIHZhciBldmxpc3RlbmVyID0gZXZlbnRzW3R5cGVdO1xuXG4gICAgaWYgKHR5cGVvZiBldmxpc3RlbmVyID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICByZXR1cm4gMTtcbiAgICB9IGVsc2UgaWYgKGV2bGlzdGVuZXIpIHtcbiAgICAgIHJldHVybiBldmxpc3RlbmVyLmxlbmd0aDtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gMDtcbn1cblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5ldmVudE5hbWVzID0gZnVuY3Rpb24gZXZlbnROYW1lcygpIHtcbiAgcmV0dXJuIHRoaXMuX2V2ZW50c0NvdW50ID4gMCA/IFJlZmxlY3Qub3duS2V5cyh0aGlzLl9ldmVudHMpIDogW107XG59O1xuXG4vLyBBYm91dCAxLjV4IGZhc3RlciB0aGFuIHRoZSB0d28tYXJnIHZlcnNpb24gb2YgQXJyYXkjc3BsaWNlKCkuXG5mdW5jdGlvbiBzcGxpY2VPbmUobGlzdCwgaW5kZXgpIHtcbiAgZm9yICh2YXIgaSA9IGluZGV4LCBrID0gaSArIDEsIG4gPSBsaXN0Lmxlbmd0aDsgayA8IG47IGkgKz0gMSwgayArPSAxKVxuICAgIGxpc3RbaV0gPSBsaXN0W2tdO1xuICBsaXN0LnBvcCgpO1xufVxuXG5mdW5jdGlvbiBhcnJheUNsb25lKGFyciwgbikge1xuICB2YXIgY29weSA9IG5ldyBBcnJheShuKTtcbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBuOyArK2kpXG4gICAgY29weVtpXSA9IGFycltpXTtcbiAgcmV0dXJuIGNvcHk7XG59XG5cbmZ1bmN0aW9uIHVud3JhcExpc3RlbmVycyhhcnIpIHtcbiAgdmFyIHJldCA9IG5ldyBBcnJheShhcnIubGVuZ3RoKTtcbiAgZm9yICh2YXIgaSA9IDA7IGkgPCByZXQubGVuZ3RoOyArK2kpIHtcbiAgICByZXRbaV0gPSBhcnJbaV0ubGlzdGVuZXIgfHwgYXJyW2ldO1xuICB9XG4gIHJldHVybiByZXQ7XG59XG5cbmZ1bmN0aW9uIG9iamVjdENyZWF0ZVBvbHlmaWxsKHByb3RvKSB7XG4gIHZhciBGID0gZnVuY3Rpb24oKSB7fTtcbiAgRi5wcm90b3R5cGUgPSBwcm90bztcbiAgcmV0dXJuIG5ldyBGO1xufVxuZnVuY3Rpb24gb2JqZWN0S2V5c1BvbHlmaWxsKG9iaikge1xuICB2YXIga2V5cyA9IFtdO1xuICBmb3IgKHZhciBrIGluIG9iaikgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChvYmosIGspKSB7XG4gICAga2V5cy5wdXNoKGspO1xuICB9XG4gIHJldHVybiBrO1xufVxuZnVuY3Rpb24gZnVuY3Rpb25CaW5kUG9seWZpbGwoY29udGV4dCkge1xuICB2YXIgZm4gPSB0aGlzO1xuICByZXR1cm4gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiBmbi5hcHBseShjb250ZXh0LCBhcmd1bWVudHMpO1xuICB9O1xufVxuIiwiLyoganNoaW50IG5vZGU6IHRydWUgKi9cbid1c2Ugc3RyaWN0JztcblxudmFyIG5vcm1hbGljZSA9IHJlcXVpcmUoJ25vcm1hbGljZScpO1xuXG4vKipcbiAgIyBmcmVlaWNlXG5cbiAgVGhlIGBmcmVlaWNlYCBtb2R1bGUgaXMgYSBzaW1wbGUgd2F5IG9mIGdldHRpbmcgcmFuZG9tIFNUVU4gb3IgVFVSTiBzZXJ2ZXJcbiAgZm9yIHlvdXIgV2ViUlRDIGFwcGxpY2F0aW9uLiAgVGhlIGxpc3Qgb2Ygc2VydmVycyAoanVzdCBTVFVOIGF0IHRoaXMgc3RhZ2UpXG4gIHdlcmUgc291cmNlZCBmcm9tIHRoaXMgW2dpc3RdKGh0dHBzOi8vZ2lzdC5naXRodWIuY29tL3p6aXVuaS8zNzQxOTMzKS5cblxuICAjIyBFeGFtcGxlIFVzZVxuXG4gIFRoZSBmb2xsb3dpbmcgZGVtb25zdHJhdGVzIGhvdyB5b3UgY2FuIHVzZSBgZnJlZWljZWAgd2l0aFxuICBbcnRjLXF1aWNrY29ubmVjdF0oaHR0cHM6Ly9naXRodWIuY29tL3J0Yy1pby9ydGMtcXVpY2tjb25uZWN0KTpcblxuICA8PDwgZXhhbXBsZXMvcXVpY2tjb25uZWN0LmpzXG5cbiAgQXMgdGhlIGBmcmVlaWNlYCBtb2R1bGUgZ2VuZXJhdGVzIGljZSBzZXJ2ZXJzIGluIGEgbGlzdCBjb21wbGlhbnQgd2l0aCB0aGVcbiAgV2ViUlRDIHNwZWMgeW91IHdpbGwgYmUgYWJsZSB0byB1c2UgaXQgd2l0aCByYXcgYFJUQ1BlZXJDb25uZWN0aW9uYFxuICBjb25zdHJ1Y3RvcnMgYW5kIG90aGVyIFdlYlJUQyBsaWJyYXJpZXMuXG5cbiAgIyMgSGV5LCBkb24ndCB1c2UgbXkgU1RVTi9UVVJOIHNlcnZlciFcblxuICBJZiBmb3Igc29tZSByZWFzb24geW91ciBmcmVlIFNUVU4gb3IgVFVSTiBzZXJ2ZXIgZW5kcyB1cCBpbiB0aGVcbiAgbGlzdCBvZiBzZXJ2ZXJzIChbc3R1bl0oaHR0cHM6Ly9naXRodWIuY29tL0RhbW9uT2VobG1hbi9mcmVlaWNlL2Jsb2IvbWFzdGVyL3N0dW4uanNvbikgb3JcbiAgW3R1cm5dKGh0dHBzOi8vZ2l0aHViLmNvbS9EYW1vbk9laGxtYW4vZnJlZWljZS9ibG9iL21hc3Rlci90dXJuLmpzb24pKVxuICB0aGF0IGlzIHVzZWQgaW4gdGhpcyBtb2R1bGUsIHlvdSBjYW4gZmVlbFxuICBmcmVlIHRvIG9wZW4gYW4gaXNzdWUgb24gdGhpcyByZXBvc2l0b3J5IGFuZCB0aG9zZSBzZXJ2ZXJzIHdpbGwgYmUgcmVtb3ZlZFxuICB3aXRoaW4gMjQgaG91cnMgKG9yIHNvb25lcikuICBUaGlzIGlzIHRoZSBxdWlja2VzdCBhbmQgcHJvYmFibHkgdGhlIG1vc3RcbiAgcG9saXRlIHdheSB0byBoYXZlIHNvbWV0aGluZyByZW1vdmVkIChhbmQgcHJvdmlkZXMgdXMgc29tZSB2aXNpYmlsaXR5XG4gIGlmIHNvbWVvbmUgb3BlbnMgYSBwdWxsIHJlcXVlc3QgcmVxdWVzdGluZyB0aGF0IGEgc2VydmVyIGlzIGFkZGVkKS5cblxuICAjIyBQbGVhc2UgYWRkIG15IHNlcnZlciFcblxuICBJZiB5b3UgaGF2ZSBhIHNlcnZlciB0aGF0IHlvdSB3aXNoIHRvIGFkZCB0byB0aGUgbGlzdCwgdGhhdCdzIGF3ZXNvbWUhIEknbVxuICBzdXJlIEkgc3BlYWsgb24gYmVoYWxmIG9mIGEgd2hvbGUgcGlsZSBvZiBXZWJSVEMgZGV2ZWxvcGVycyB3aG8gc2F5IHRoYW5rcy5cbiAgVG8gZ2V0IGl0IGludG8gdGhlIGxpc3QsIGZlZWwgZnJlZSB0byBlaXRoZXIgb3BlbiBhIHB1bGwgcmVxdWVzdCBvciBpZiB5b3VcbiAgZmluZCB0aGF0IHByb2Nlc3MgYSBiaXQgZGF1bnRpbmcgdGhlbiBqdXN0IGNyZWF0ZSBhbiBpc3N1ZSByZXF1ZXN0aW5nXG4gIHRoZSBhZGRpdGlvbiBvZiB0aGUgc2VydmVyIChtYWtlIHN1cmUgeW91IHByb3ZpZGUgYWxsIHRoZSBkZXRhaWxzLCBhbmQgaWZcbiAgeW91IGhhdmUgYSBUZXJtcyBvZiBTZXJ2aWNlIHRoZW4gaW5jbHVkaW5nIHRoYXQgaW4gdGhlIFBSL2lzc3VlIHdvdWxkIGJlXG4gIGF3ZXNvbWUpLlxuXG4gICMjIEkga25vdyBvZiBhIGZyZWUgc2VydmVyLCBjYW4gSSBhZGQgaXQ/XG5cbiAgU3VyZSwgaWYgeW91IGRvIHlvdXIgaG9tZXdvcmsgYW5kIG1ha2Ugc3VyZSBpdCBpcyBvayB0byB1c2UgKEknbSBjdXJyZW50bHlcbiAgaW4gdGhlIHByb2Nlc3Mgb2YgcmV2aWV3aW5nIHRoZSB0ZXJtcyBvZiB0aG9zZSBTVFVOIHNlcnZlcnMgaW5jbHVkZWQgZnJvbVxuICB0aGUgb3JpZ2luYWwgbGlzdCkuICBJZiBpdCdzIG9rIHRvIGdvLCB0aGVuIHBsZWFzZSBzZWUgdGhlIHByZXZpb3VzIGVudHJ5XG4gIGZvciBob3cgdG8gYWRkIGl0LlxuXG4gICMjIEN1cnJlbnQgTGlzdCBvZiBTZXJ2ZXJzXG5cbiAgKiBjdXJyZW50IGFzIGF0IHRoZSB0aW1lIG9mIGxhc3QgYFJFQURNRS5tZGAgZmlsZSBnZW5lcmF0aW9uXG5cbiAgIyMjIFNUVU5cblxuICA8PDwgc3R1bi5qc29uXG5cbiAgIyMjIFRVUk5cblxuICA8PDwgdHVybi5qc29uXG5cbioqL1xuXG52YXIgZnJlZWljZSA9IG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24ob3B0cykge1xuICAvLyBpZiBhIGxpc3Qgb2Ygc2VydmVycyBoYXMgYmVlbiBwcm92aWRlZCwgdGhlbiB1c2UgaXQgaW5zdGVhZCBvZiBkZWZhdWx0c1xuICB2YXIgc2VydmVycyA9IHtcbiAgICBzdHVuOiAob3B0cyB8fCB7fSkuc3R1biB8fCByZXF1aXJlKCcuL3N0dW4uanNvbicpLFxuICAgIHR1cm46IChvcHRzIHx8IHt9KS50dXJuIHx8IHJlcXVpcmUoJy4vdHVybi5qc29uJylcbiAgfTtcblxuICB2YXIgc3R1bkNvdW50ID0gKG9wdHMgfHwge30pLnN0dW5Db3VudCB8fCAyO1xuICB2YXIgdHVybkNvdW50ID0gKG9wdHMgfHwge30pLnR1cm5Db3VudCB8fCAwO1xuICB2YXIgc2VsZWN0ZWQ7XG5cbiAgZnVuY3Rpb24gZ2V0U2VydmVycyh0eXBlLCBjb3VudCkge1xuICAgIHZhciBvdXQgPSBbXTtcbiAgICB2YXIgaW5wdXQgPSBbXS5jb25jYXQoc2VydmVyc1t0eXBlXSk7XG4gICAgdmFyIGlkeDtcblxuICAgIHdoaWxlIChpbnB1dC5sZW5ndGggJiYgb3V0Lmxlbmd0aCA8IGNvdW50KSB7XG4gICAgICBpZHggPSAoTWF0aC5yYW5kb20oKSAqIGlucHV0Lmxlbmd0aCkgfCAwO1xuICAgICAgb3V0ID0gb3V0LmNvbmNhdChpbnB1dC5zcGxpY2UoaWR4LCAxKSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIG91dC5tYXAoZnVuY3Rpb24odXJsKSB7XG4gICAgICAgIC8vSWYgaXQncyBhIG5vdCBhIHN0cmluZywgZG9uJ3QgdHJ5IHRvIFwibm9ybWFsaWNlXCIgaXQgb3RoZXJ3aXNlIHVzaW5nIHR5cGU6dXJsIHdpbGwgc2NyZXcgaXQgdXBcbiAgICAgICAgaWYgKCh0eXBlb2YgdXJsICE9PSAnc3RyaW5nJykgJiYgKCEgKHVybCBpbnN0YW5jZW9mIFN0cmluZykpKSB7XG4gICAgICAgICAgICByZXR1cm4gdXJsO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIG5vcm1hbGljZSh0eXBlICsgJzonICsgdXJsKTtcbiAgICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgLy8gYWRkIHN0dW4gc2VydmVyc1xuICBzZWxlY3RlZCA9IFtdLmNvbmNhdChnZXRTZXJ2ZXJzKCdzdHVuJywgc3R1bkNvdW50KSk7XG5cbiAgaWYgKHR1cm5Db3VudCkge1xuICAgIHNlbGVjdGVkID0gc2VsZWN0ZWQuY29uY2F0KGdldFNlcnZlcnMoJ3R1cm4nLCB0dXJuQ291bnQpKTtcbiAgfVxuXG4gIHJldHVybiBzZWxlY3RlZDtcbn07XG4iLCJtb2R1bGUuZXhwb3J0cz1bXG4gIFwic3R1bi5sLmdvb2dsZS5jb206MTkzMDJcIixcbiAgXCJzdHVuMS5sLmdvb2dsZS5jb206MTkzMDJcIixcbiAgXCJzdHVuMi5sLmdvb2dsZS5jb206MTkzMDJcIixcbiAgXCJzdHVuMy5sLmdvb2dsZS5jb206MTkzMDJcIixcbiAgXCJzdHVuNC5sLmdvb2dsZS5jb206MTkzMDJcIixcbiAgXCJzdHVuLmVraWdhLm5ldFwiLFxuICBcInN0dW4uaWRlYXNpcC5jb21cIixcbiAgXCJzdHVuLnNjaGx1bmQuZGVcIixcbiAgXCJzdHVuLnN0dW5wcm90b2NvbC5vcmc6MzQ3OFwiLFxuICBcInN0dW4udm9pcGFyb3VuZC5jb21cIixcbiAgXCJzdHVuLnZvaXBidXN0ZXIuY29tXCIsXG4gIFwic3R1bi52b2lwc3R1bnQuY29tXCIsXG4gIFwic3R1bi52b3hncmF0aWEub3JnXCIsXG4gIFwic3R1bi5zZXJ2aWNlcy5tb3ppbGxhLmNvbVwiXG5dXG4iLCJtb2R1bGUuZXhwb3J0cz1bXVxuIiwidmFyIFdpbGRFbWl0dGVyID0gcmVxdWlyZSgnd2lsZGVtaXR0ZXInKTtcblxuZnVuY3Rpb24gZ2V0TWF4Vm9sdW1lIChhbmFseXNlciwgZmZ0Qmlucykge1xuICB2YXIgbWF4Vm9sdW1lID0gLUluZmluaXR5O1xuICBhbmFseXNlci5nZXRGbG9hdEZyZXF1ZW5jeURhdGEoZmZ0Qmlucyk7XG5cbiAgZm9yKHZhciBpPTQsIGlpPWZmdEJpbnMubGVuZ3RoOyBpIDwgaWk7IGkrKykge1xuICAgIGlmIChmZnRCaW5zW2ldID4gbWF4Vm9sdW1lICYmIGZmdEJpbnNbaV0gPCAwKSB7XG4gICAgICBtYXhWb2x1bWUgPSBmZnRCaW5zW2ldO1xuICAgIH1cbiAgfTtcblxuICByZXR1cm4gbWF4Vm9sdW1lO1xufVxuXG5cbnZhciBhdWRpb0NvbnRleHRUeXBlO1xuaWYgKHR5cGVvZiB3aW5kb3cgIT09ICd1bmRlZmluZWQnKSB7XG4gIGF1ZGlvQ29udGV4dFR5cGUgPSB3aW5kb3cuQXVkaW9Db250ZXh0IHx8IHdpbmRvdy53ZWJraXRBdWRpb0NvbnRleHQ7XG59XG4vLyB1c2UgYSBzaW5nbGUgYXVkaW8gY29udGV4dCBkdWUgdG8gaGFyZHdhcmUgbGltaXRzXG52YXIgYXVkaW9Db250ZXh0ID0gbnVsbDtcbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24oc3RyZWFtLCBvcHRpb25zKSB7XG4gIHZhciBoYXJrZXIgPSBuZXcgV2lsZEVtaXR0ZXIoKTtcblxuXG4gIC8vIG1ha2UgaXQgbm90IGJyZWFrIGluIG5vbi1zdXBwb3J0ZWQgYnJvd3NlcnNcbiAgaWYgKCFhdWRpb0NvbnRleHRUeXBlKSByZXR1cm4gaGFya2VyO1xuXG4gIC8vQ29uZmlnXG4gIHZhciBvcHRpb25zID0gb3B0aW9ucyB8fCB7fSxcbiAgICAgIHNtb290aGluZyA9IChvcHRpb25zLnNtb290aGluZyB8fCAwLjEpLFxuICAgICAgaW50ZXJ2YWwgPSAob3B0aW9ucy5pbnRlcnZhbCB8fCA1MCksXG4gICAgICB0aHJlc2hvbGQgPSBvcHRpb25zLnRocmVzaG9sZCxcbiAgICAgIHBsYXkgPSBvcHRpb25zLnBsYXksXG4gICAgICBoaXN0b3J5ID0gb3B0aW9ucy5oaXN0b3J5IHx8IDEwLFxuICAgICAgcnVubmluZyA9IHRydWU7XG5cbiAgLy9TZXR1cCBBdWRpbyBDb250ZXh0XG4gIGlmICghYXVkaW9Db250ZXh0KSB7XG4gICAgYXVkaW9Db250ZXh0ID0gbmV3IGF1ZGlvQ29udGV4dFR5cGUoKTtcbiAgfVxuICB2YXIgc291cmNlTm9kZSwgZmZ0QmlucywgYW5hbHlzZXI7XG5cbiAgYW5hbHlzZXIgPSBhdWRpb0NvbnRleHQuY3JlYXRlQW5hbHlzZXIoKTtcbiAgYW5hbHlzZXIuZmZ0U2l6ZSA9IDUxMjtcbiAgYW5hbHlzZXIuc21vb3RoaW5nVGltZUNvbnN0YW50ID0gc21vb3RoaW5nO1xuICBmZnRCaW5zID0gbmV3IEZsb2F0MzJBcnJheShhbmFseXNlci5mcmVxdWVuY3lCaW5Db3VudCk7XG5cbiAgaWYgKHN0cmVhbS5qcXVlcnkpIHN0cmVhbSA9IHN0cmVhbVswXTtcbiAgaWYgKHN0cmVhbSBpbnN0YW5jZW9mIEhUTUxBdWRpb0VsZW1lbnQgfHwgc3RyZWFtIGluc3RhbmNlb2YgSFRNTFZpZGVvRWxlbWVudCkge1xuICAgIC8vQXVkaW8gVGFnXG4gICAgc291cmNlTm9kZSA9IGF1ZGlvQ29udGV4dC5jcmVhdGVNZWRpYUVsZW1lbnRTb3VyY2Uoc3RyZWFtKTtcbiAgICBpZiAodHlwZW9mIHBsYXkgPT09ICd1bmRlZmluZWQnKSBwbGF5ID0gdHJ1ZTtcbiAgICB0aHJlc2hvbGQgPSB0aHJlc2hvbGQgfHwgLTUwO1xuICB9IGVsc2Uge1xuICAgIC8vV2ViUlRDIFN0cmVhbVxuICAgIHNvdXJjZU5vZGUgPSBhdWRpb0NvbnRleHQuY3JlYXRlTWVkaWFTdHJlYW1Tb3VyY2Uoc3RyZWFtKTtcbiAgICB0aHJlc2hvbGQgPSB0aHJlc2hvbGQgfHwgLTUwO1xuICB9XG5cbiAgc291cmNlTm9kZS5jb25uZWN0KGFuYWx5c2VyKTtcbiAgaWYgKHBsYXkpIGFuYWx5c2VyLmNvbm5lY3QoYXVkaW9Db250ZXh0LmRlc3RpbmF0aW9uKTtcblxuICBoYXJrZXIuc3BlYWtpbmcgPSBmYWxzZTtcblxuICBoYXJrZXIuc3VzcGVuZCA9IGZ1bmN0aW9uKCkge1xuICAgIGF1ZGlvQ29udGV4dC5zdXNwZW5kKCk7XG4gIH1cbiAgaGFya2VyLnJlc3VtZSA9IGZ1bmN0aW9uKCkge1xuICAgIGF1ZGlvQ29udGV4dC5yZXN1bWUoKTtcbiAgfVxuICBPYmplY3QuZGVmaW5lUHJvcGVydHkoaGFya2VyLCAnc3RhdGUnLCB7IGdldDogZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIGF1ZGlvQ29udGV4dC5zdGF0ZTtcbiAgfX0pO1xuICBhdWRpb0NvbnRleHQub25zdGF0ZWNoYW5nZSA9IGZ1bmN0aW9uKCkge1xuICAgIGhhcmtlci5lbWl0KCdzdGF0ZV9jaGFuZ2UnLCBhdWRpb0NvbnRleHQuc3RhdGUpO1xuICB9XG5cbiAgaGFya2VyLnNldFRocmVzaG9sZCA9IGZ1bmN0aW9uKHQpIHtcbiAgICB0aHJlc2hvbGQgPSB0O1xuICB9O1xuXG4gIGhhcmtlci5zZXRJbnRlcnZhbCA9IGZ1bmN0aW9uKGkpIHtcbiAgICBpbnRlcnZhbCA9IGk7XG4gIH07XG5cbiAgaGFya2VyLnN0b3AgPSBmdW5jdGlvbigpIHtcbiAgICBydW5uaW5nID0gZmFsc2U7XG4gICAgaGFya2VyLmVtaXQoJ3ZvbHVtZV9jaGFuZ2UnLCAtMTAwLCB0aHJlc2hvbGQpO1xuICAgIGlmIChoYXJrZXIuc3BlYWtpbmcpIHtcbiAgICAgIGhhcmtlci5zcGVha2luZyA9IGZhbHNlO1xuICAgICAgaGFya2VyLmVtaXQoJ3N0b3BwZWRfc3BlYWtpbmcnKTtcbiAgICB9XG4gICAgYW5hbHlzZXIuZGlzY29ubmVjdCgpO1xuICAgIHNvdXJjZU5vZGUuZGlzY29ubmVjdCgpO1xuICB9O1xuICBoYXJrZXIuc3BlYWtpbmdIaXN0b3J5ID0gW107XG4gIGZvciAodmFyIGkgPSAwOyBpIDwgaGlzdG9yeTsgaSsrKSB7XG4gICAgICBoYXJrZXIuc3BlYWtpbmdIaXN0b3J5LnB1c2goMCk7XG4gIH1cblxuICAvLyBQb2xsIHRoZSBhbmFseXNlciBub2RlIHRvIGRldGVybWluZSBpZiBzcGVha2luZ1xuICAvLyBhbmQgZW1pdCBldmVudHMgaWYgY2hhbmdlZFxuICB2YXIgbG9vcGVyID0gZnVuY3Rpb24oKSB7XG4gICAgc2V0VGltZW91dChmdW5jdGlvbigpIHtcblxuICAgICAgLy9jaGVjayBpZiBzdG9wIGhhcyBiZWVuIGNhbGxlZFxuICAgICAgaWYoIXJ1bm5pbmcpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICB2YXIgY3VycmVudFZvbHVtZSA9IGdldE1heFZvbHVtZShhbmFseXNlciwgZmZ0Qmlucyk7XG5cbiAgICAgIGhhcmtlci5lbWl0KCd2b2x1bWVfY2hhbmdlJywgY3VycmVudFZvbHVtZSwgdGhyZXNob2xkKTtcblxuICAgICAgdmFyIGhpc3RvcnkgPSAwO1xuICAgICAgaWYgKGN1cnJlbnRWb2x1bWUgPiB0aHJlc2hvbGQgJiYgIWhhcmtlci5zcGVha2luZykge1xuICAgICAgICAvLyB0cmlnZ2VyIHF1aWNrbHksIHNob3J0IGhpc3RvcnlcbiAgICAgICAgZm9yICh2YXIgaSA9IGhhcmtlci5zcGVha2luZ0hpc3RvcnkubGVuZ3RoIC0gMzsgaSA8IGhhcmtlci5zcGVha2luZ0hpc3RvcnkubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICBoaXN0b3J5ICs9IGhhcmtlci5zcGVha2luZ0hpc3RvcnlbaV07XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGhpc3RvcnkgPj0gMikge1xuICAgICAgICAgIGhhcmtlci5zcGVha2luZyA9IHRydWU7XG4gICAgICAgICAgaGFya2VyLmVtaXQoJ3NwZWFraW5nJyk7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSBpZiAoY3VycmVudFZvbHVtZSA8IHRocmVzaG9sZCAmJiBoYXJrZXIuc3BlYWtpbmcpIHtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBoYXJrZXIuc3BlYWtpbmdIaXN0b3J5Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgaGlzdG9yeSArPSBoYXJrZXIuc3BlYWtpbmdIaXN0b3J5W2ldO1xuICAgICAgICB9XG4gICAgICAgIGlmIChoaXN0b3J5ID09IDApIHtcbiAgICAgICAgICBoYXJrZXIuc3BlYWtpbmcgPSBmYWxzZTtcbiAgICAgICAgICBoYXJrZXIuZW1pdCgnc3RvcHBlZF9zcGVha2luZycpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBoYXJrZXIuc3BlYWtpbmdIaXN0b3J5LnNoaWZ0KCk7XG4gICAgICBoYXJrZXIuc3BlYWtpbmdIaXN0b3J5LnB1c2goMCArIChjdXJyZW50Vm9sdW1lID4gdGhyZXNob2xkKSk7XG5cbiAgICAgIGxvb3BlcigpO1xuICAgIH0sIGludGVydmFsKTtcbiAgfTtcbiAgbG9vcGVyKCk7XG5cblxuICByZXR1cm4gaGFya2VyO1xufVxuIiwiaWYgKHR5cGVvZiBPYmplY3QuY3JlYXRlID09PSAnZnVuY3Rpb24nKSB7XG4gIC8vIGltcGxlbWVudGF0aW9uIGZyb20gc3RhbmRhcmQgbm9kZS5qcyAndXRpbCcgbW9kdWxlXG4gIG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gaW5oZXJpdHMoY3Rvciwgc3VwZXJDdG9yKSB7XG4gICAgY3Rvci5zdXBlcl8gPSBzdXBlckN0b3JcbiAgICBjdG9yLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoc3VwZXJDdG9yLnByb3RvdHlwZSwge1xuICAgICAgY29uc3RydWN0b3I6IHtcbiAgICAgICAgdmFsdWU6IGN0b3IsXG4gICAgICAgIGVudW1lcmFibGU6IGZhbHNlLFxuICAgICAgICB3cml0YWJsZTogdHJ1ZSxcbiAgICAgICAgY29uZmlndXJhYmxlOiB0cnVlXG4gICAgICB9XG4gICAgfSk7XG4gIH07XG59IGVsc2Uge1xuICAvLyBvbGQgc2Nob29sIHNoaW0gZm9yIG9sZCBicm93c2Vyc1xuICBtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGluaGVyaXRzKGN0b3IsIHN1cGVyQ3Rvcikge1xuICAgIGN0b3Iuc3VwZXJfID0gc3VwZXJDdG9yXG4gICAgdmFyIFRlbXBDdG9yID0gZnVuY3Rpb24gKCkge31cbiAgICBUZW1wQ3Rvci5wcm90b3R5cGUgPSBzdXBlckN0b3IucHJvdG90eXBlXG4gICAgY3Rvci5wcm90b3R5cGUgPSBuZXcgVGVtcEN0b3IoKVxuICAgIGN0b3IucHJvdG90eXBlLmNvbnN0cnVjdG9yID0gY3RvclxuICB9XG59XG4iLCIvKipcbiAgIyBub3JtYWxpY2VcblxuICBOb3JtYWxpemUgYW4gaWNlIHNlcnZlciBjb25maWd1cmF0aW9uIG9iamVjdCAob3IgcGxhaW4gb2xkIHN0cmluZykgaW50byBhIGZvcm1hdFxuICB0aGF0IGlzIHVzYWJsZSBpbiBhbGwgYnJvd3NlcnMgc3VwcG9ydGluZyBXZWJSVEMuICBQcmltYXJpbHkgdGhpcyBtb2R1bGUgaXMgZGVzaWduZWRcbiAgdG8gaGVscCB3aXRoIHRoZSB0cmFuc2l0aW9uIG9mIHRoZSBgdXJsYCBhdHRyaWJ1dGUgb2YgdGhlIGNvbmZpZ3VyYXRpb24gb2JqZWN0IHRvXG4gIHRoZSBgdXJsc2AgYXR0cmlidXRlLlxuXG4gICMjIEV4YW1wbGUgVXNhZ2VcblxuICA8PDwgZXhhbXBsZXMvc2ltcGxlLmpzXG5cbioqL1xuXG52YXIgcHJvdG9jb2xzID0gW1xuICAnc3R1bjonLFxuICAndHVybjonXG5dO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKGlucHV0KSB7XG4gIHZhciB1cmwgPSAoaW5wdXQgfHwge30pLnVybCB8fCBpbnB1dDtcbiAgdmFyIHByb3RvY29sO1xuICB2YXIgcGFydHM7XG4gIHZhciBvdXRwdXQgPSB7fTtcblxuICAvLyBpZiB3ZSBkb24ndCBoYXZlIGEgc3RyaW5nIHVybCwgdGhlbiBhbGxvdyB0aGUgaW5wdXQgdG8gcGFzc3Rocm91Z2hcbiAgaWYgKHR5cGVvZiB1cmwgIT0gJ3N0cmluZycgJiYgKCEgKHVybCBpbnN0YW5jZW9mIFN0cmluZykpKSB7XG4gICAgcmV0dXJuIGlucHV0O1xuICB9XG5cbiAgLy8gdHJpbSB0aGUgdXJsIHN0cmluZywgYW5kIGNvbnZlcnQgdG8gYW4gYXJyYXlcbiAgdXJsID0gdXJsLnRyaW0oKTtcblxuICAvLyBpZiB0aGUgcHJvdG9jb2wgaXMgbm90IGtub3duLCB0aGVuIHBhc3N0aHJvdWdoXG4gIHByb3RvY29sID0gcHJvdG9jb2xzW3Byb3RvY29scy5pbmRleE9mKHVybC5zbGljZSgwLCA1KSldO1xuICBpZiAoISBwcm90b2NvbCkge1xuICAgIHJldHVybiBpbnB1dDtcbiAgfVxuXG4gIC8vIG5vdyBsZXQncyBhdHRhY2sgdGhlIHJlbWFpbmluZyB1cmwgcGFydHNcbiAgdXJsID0gdXJsLnNsaWNlKDUpO1xuICBwYXJ0cyA9IHVybC5zcGxpdCgnQCcpO1xuXG4gIG91dHB1dC51c2VybmFtZSA9IGlucHV0LnVzZXJuYW1lO1xuICBvdXRwdXQuY3JlZGVudGlhbCA9IGlucHV0LmNyZWRlbnRpYWw7XG4gIC8vIGlmIHdlIGhhdmUgYW4gYXV0aGVudGljYXRpb24gcGFydCwgdGhlbiBzZXQgdGhlIGNyZWRlbnRpYWxzXG4gIGlmIChwYXJ0cy5sZW5ndGggPiAxKSB7XG4gICAgdXJsID0gcGFydHNbMV07XG4gICAgcGFydHMgPSBwYXJ0c1swXS5zcGxpdCgnOicpO1xuXG4gICAgLy8gYWRkIHRoZSBvdXRwdXQgY3JlZGVudGlhbCBhbmQgdXNlcm5hbWVcbiAgICBvdXRwdXQudXNlcm5hbWUgPSBwYXJ0c1swXTtcbiAgICBvdXRwdXQuY3JlZGVudGlhbCA9IChpbnB1dCB8fCB7fSkuY3JlZGVudGlhbCB8fCBwYXJ0c1sxXSB8fCAnJztcbiAgfVxuXG4gIG91dHB1dC51cmwgPSBwcm90b2NvbCArIHVybDtcbiAgb3V0cHV0LnVybHMgPSBbIG91dHB1dC51cmwgXTtcblxuICByZXR1cm4gb3V0cHV0O1xufTtcbiIsIi8qIVxuICogUGxhdGZvcm0uanMgPGh0dHBzOi8vbXRocy5iZS9wbGF0Zm9ybT5cbiAqIENvcHlyaWdodCAyMDE0LTIwMTggQmVuamFtaW4gVGFuIDxodHRwczovL2Juam1udDRuLm5vdy5zaC8+XG4gKiBDb3B5cmlnaHQgMjAxMS0yMDEzIEpvaG4tRGF2aWQgRGFsdG9uIDxodHRwOi8vYWxseW91Y2FubGVldC5jb20vPlxuICogQXZhaWxhYmxlIHVuZGVyIE1JVCBsaWNlbnNlIDxodHRwczovL210aHMuYmUvbWl0PlxuICovXG47KGZ1bmN0aW9uKCkge1xuICAndXNlIHN0cmljdCc7XG5cbiAgLyoqIFVzZWQgdG8gZGV0ZXJtaW5lIGlmIHZhbHVlcyBhcmUgb2YgdGhlIGxhbmd1YWdlIHR5cGUgYE9iamVjdGAuICovXG4gIHZhciBvYmplY3RUeXBlcyA9IHtcbiAgICAnZnVuY3Rpb24nOiB0cnVlLFxuICAgICdvYmplY3QnOiB0cnVlXG4gIH07XG5cbiAgLyoqIFVzZWQgYXMgYSByZWZlcmVuY2UgdG8gdGhlIGdsb2JhbCBvYmplY3QuICovXG4gIHZhciByb290ID0gKG9iamVjdFR5cGVzW3R5cGVvZiB3aW5kb3ddICYmIHdpbmRvdykgfHwgdGhpcztcblxuICAvKiogQmFja3VwIHBvc3NpYmxlIGdsb2JhbCBvYmplY3QuICovXG4gIHZhciBvbGRSb290ID0gcm9vdDtcblxuICAvKiogRGV0ZWN0IGZyZWUgdmFyaWFibGUgYGV4cG9ydHNgLiAqL1xuICB2YXIgZnJlZUV4cG9ydHMgPSBvYmplY3RUeXBlc1t0eXBlb2YgZXhwb3J0c10gJiYgZXhwb3J0cztcblxuICAvKiogRGV0ZWN0IGZyZWUgdmFyaWFibGUgYG1vZHVsZWAuICovXG4gIHZhciBmcmVlTW9kdWxlID0gb2JqZWN0VHlwZXNbdHlwZW9mIG1vZHVsZV0gJiYgbW9kdWxlICYmICFtb2R1bGUubm9kZVR5cGUgJiYgbW9kdWxlO1xuXG4gIC8qKiBEZXRlY3QgZnJlZSB2YXJpYWJsZSBgZ2xvYmFsYCBmcm9tIE5vZGUuanMgb3IgQnJvd3NlcmlmaWVkIGNvZGUgYW5kIHVzZSBpdCBhcyBgcm9vdGAuICovXG4gIHZhciBmcmVlR2xvYmFsID0gZnJlZUV4cG9ydHMgJiYgZnJlZU1vZHVsZSAmJiB0eXBlb2YgZ2xvYmFsID09ICdvYmplY3QnICYmIGdsb2JhbDtcbiAgaWYgKGZyZWVHbG9iYWwgJiYgKGZyZWVHbG9iYWwuZ2xvYmFsID09PSBmcmVlR2xvYmFsIHx8IGZyZWVHbG9iYWwud2luZG93ID09PSBmcmVlR2xvYmFsIHx8IGZyZWVHbG9iYWwuc2VsZiA9PT0gZnJlZUdsb2JhbCkpIHtcbiAgICByb290ID0gZnJlZUdsb2JhbDtcbiAgfVxuXG4gIC8qKlxuICAgKiBVc2VkIGFzIHRoZSBtYXhpbXVtIGxlbmd0aCBvZiBhbiBhcnJheS1saWtlIG9iamVjdC5cbiAgICogU2VlIHRoZSBbRVM2IHNwZWNdKGh0dHA6Ly9wZW9wbGUubW96aWxsYS5vcmcvfmpvcmVuZG9yZmYvZXM2LWRyYWZ0Lmh0bWwjc2VjLXRvbGVuZ3RoKVxuICAgKiBmb3IgbW9yZSBkZXRhaWxzLlxuICAgKi9cbiAgdmFyIG1heFNhZmVJbnRlZ2VyID0gTWF0aC5wb3coMiwgNTMpIC0gMTtcblxuICAvKiogUmVndWxhciBleHByZXNzaW9uIHRvIGRldGVjdCBPcGVyYS4gKi9cbiAgdmFyIHJlT3BlcmEgPSAvXFxiT3BlcmEvO1xuXG4gIC8qKiBQb3NzaWJsZSBnbG9iYWwgb2JqZWN0LiAqL1xuICB2YXIgdGhpc0JpbmRpbmcgPSB0aGlzO1xuXG4gIC8qKiBVc2VkIGZvciBuYXRpdmUgbWV0aG9kIHJlZmVyZW5jZXMuICovXG4gIHZhciBvYmplY3RQcm90byA9IE9iamVjdC5wcm90b3R5cGU7XG5cbiAgLyoqIFVzZWQgdG8gY2hlY2sgZm9yIG93biBwcm9wZXJ0aWVzIG9mIGFuIG9iamVjdC4gKi9cbiAgdmFyIGhhc093blByb3BlcnR5ID0gb2JqZWN0UHJvdG8uaGFzT3duUHJvcGVydHk7XG5cbiAgLyoqIFVzZWQgdG8gcmVzb2x2ZSB0aGUgaW50ZXJuYWwgYFtbQ2xhc3NdXWAgb2YgdmFsdWVzLiAqL1xuICB2YXIgdG9TdHJpbmcgPSBvYmplY3RQcm90by50b1N0cmluZztcblxuICAvKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cblxuICAvKipcbiAgICogQ2FwaXRhbGl6ZXMgYSBzdHJpbmcgdmFsdWUuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBzdHJpbmcgVGhlIHN0cmluZyB0byBjYXBpdGFsaXplLlxuICAgKiBAcmV0dXJucyB7c3RyaW5nfSBUaGUgY2FwaXRhbGl6ZWQgc3RyaW5nLlxuICAgKi9cbiAgZnVuY3Rpb24gY2FwaXRhbGl6ZShzdHJpbmcpIHtcbiAgICBzdHJpbmcgPSBTdHJpbmcoc3RyaW5nKTtcbiAgICByZXR1cm4gc3RyaW5nLmNoYXJBdCgwKS50b1VwcGVyQ2FzZSgpICsgc3RyaW5nLnNsaWNlKDEpO1xuICB9XG5cbiAgLyoqXG4gICAqIEEgdXRpbGl0eSBmdW5jdGlvbiB0byBjbGVhbiB1cCB0aGUgT1MgbmFtZS5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtzdHJpbmd9IG9zIFRoZSBPUyBuYW1lIHRvIGNsZWFuIHVwLlxuICAgKiBAcGFyYW0ge3N0cmluZ30gW3BhdHRlcm5dIEEgYFJlZ0V4cGAgcGF0dGVybiBtYXRjaGluZyB0aGUgT1MgbmFtZS5cbiAgICogQHBhcmFtIHtzdHJpbmd9IFtsYWJlbF0gQSBsYWJlbCBmb3IgdGhlIE9TLlxuICAgKi9cbiAgZnVuY3Rpb24gY2xlYW51cE9TKG9zLCBwYXR0ZXJuLCBsYWJlbCkge1xuICAgIC8vIFBsYXRmb3JtIHRva2VucyBhcmUgZGVmaW5lZCBhdDpcbiAgICAvLyBodHRwOi8vbXNkbi5taWNyb3NvZnQuY29tL2VuLXVzL2xpYnJhcnkvbXM1Mzc1MDMoVlMuODUpLmFzcHhcbiAgICAvLyBodHRwOi8vd2ViLmFyY2hpdmUub3JnL3dlYi8yMDA4MTEyMjA1Mzk1MC9odHRwOi8vbXNkbi5taWNyb3NvZnQuY29tL2VuLXVzL2xpYnJhcnkvbXM1Mzc1MDMoVlMuODUpLmFzcHhcbiAgICB2YXIgZGF0YSA9IHtcbiAgICAgICcxMC4wJzogJzEwJyxcbiAgICAgICc2LjQnOiAgJzEwIFRlY2huaWNhbCBQcmV2aWV3JyxcbiAgICAgICc2LjMnOiAgJzguMScsXG4gICAgICAnNi4yJzogICc4JyxcbiAgICAgICc2LjEnOiAgJ1NlcnZlciAyMDA4IFIyIC8gNycsXG4gICAgICAnNi4wJzogICdTZXJ2ZXIgMjAwOCAvIFZpc3RhJyxcbiAgICAgICc1LjInOiAgJ1NlcnZlciAyMDAzIC8gWFAgNjQtYml0JyxcbiAgICAgICc1LjEnOiAgJ1hQJyxcbiAgICAgICc1LjAxJzogJzIwMDAgU1AxJyxcbiAgICAgICc1LjAnOiAgJzIwMDAnLFxuICAgICAgJzQuMCc6ICAnTlQnLFxuICAgICAgJzQuOTAnOiAnTUUnXG4gICAgfTtcbiAgICAvLyBEZXRlY3QgV2luZG93cyB2ZXJzaW9uIGZyb20gcGxhdGZvcm0gdG9rZW5zLlxuICAgIGlmIChwYXR0ZXJuICYmIGxhYmVsICYmIC9eV2luL2kudGVzdChvcykgJiYgIS9eV2luZG93cyBQaG9uZSAvaS50ZXN0KG9zKSAmJlxuICAgICAgICAoZGF0YSA9IGRhdGFbL1tcXGQuXSskLy5leGVjKG9zKV0pKSB7XG4gICAgICBvcyA9ICdXaW5kb3dzICcgKyBkYXRhO1xuICAgIH1cbiAgICAvLyBDb3JyZWN0IGNoYXJhY3RlciBjYXNlIGFuZCBjbGVhbnVwIHN0cmluZy5cbiAgICBvcyA9IFN0cmluZyhvcyk7XG5cbiAgICBpZiAocGF0dGVybiAmJiBsYWJlbCkge1xuICAgICAgb3MgPSBvcy5yZXBsYWNlKFJlZ0V4cChwYXR0ZXJuLCAnaScpLCBsYWJlbCk7XG4gICAgfVxuXG4gICAgb3MgPSBmb3JtYXQoXG4gICAgICBvcy5yZXBsYWNlKC8gY2UkL2ksICcgQ0UnKVxuICAgICAgICAucmVwbGFjZSgvXFxiaHB3L2ksICd3ZWInKVxuICAgICAgICAucmVwbGFjZSgvXFxiTWFjaW50b3NoXFxiLywgJ01hYyBPUycpXG4gICAgICAgIC5yZXBsYWNlKC9fUG93ZXJQQ1xcYi9pLCAnIE9TJylcbiAgICAgICAgLnJlcGxhY2UoL1xcYihPUyBYKSBbXiBcXGRdKy9pLCAnJDEnKVxuICAgICAgICAucmVwbGFjZSgvXFxiTWFjIChPUyBYKVxcYi8sICckMScpXG4gICAgICAgIC5yZXBsYWNlKC9cXC8oXFxkKS8sICcgJDEnKVxuICAgICAgICAucmVwbGFjZSgvXy9nLCAnLicpXG4gICAgICAgIC5yZXBsYWNlKC8oPzogQmVQQ3xbIC5dKmZjWyBcXGQuXSspJC9pLCAnJylcbiAgICAgICAgLnJlcGxhY2UoL1xcYng4NlxcLjY0XFxiL2dpLCAneDg2XzY0JylcbiAgICAgICAgLnJlcGxhY2UoL1xcYihXaW5kb3dzIFBob25lKSBPU1xcYi8sICckMScpXG4gICAgICAgIC5yZXBsYWNlKC9cXGIoQ2hyb21lIE9TIFxcdyspIFtcXGQuXStcXGIvLCAnJDEnKVxuICAgICAgICAuc3BsaXQoJyBvbiAnKVswXVxuICAgICk7XG5cbiAgICByZXR1cm4gb3M7XG4gIH1cblxuICAvKipcbiAgICogQW4gaXRlcmF0aW9uIHV0aWxpdHkgZm9yIGFycmF5cyBhbmQgb2JqZWN0cy5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtBcnJheXxPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIGl0ZXJhdGUgb3Zlci5cbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gY2FsbGJhY2sgVGhlIGZ1bmN0aW9uIGNhbGxlZCBwZXIgaXRlcmF0aW9uLlxuICAgKi9cbiAgZnVuY3Rpb24gZWFjaChvYmplY3QsIGNhbGxiYWNrKSB7XG4gICAgdmFyIGluZGV4ID0gLTEsXG4gICAgICAgIGxlbmd0aCA9IG9iamVjdCA/IG9iamVjdC5sZW5ndGggOiAwO1xuXG4gICAgaWYgKHR5cGVvZiBsZW5ndGggPT0gJ251bWJlcicgJiYgbGVuZ3RoID4gLTEgJiYgbGVuZ3RoIDw9IG1heFNhZmVJbnRlZ2VyKSB7XG4gICAgICB3aGlsZSAoKytpbmRleCA8IGxlbmd0aCkge1xuICAgICAgICBjYWxsYmFjayhvYmplY3RbaW5kZXhdLCBpbmRleCwgb2JqZWN0KTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgZm9yT3duKG9iamVjdCwgY2FsbGJhY2spO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBUcmltIGFuZCBjb25kaXRpb25hbGx5IGNhcGl0YWxpemUgc3RyaW5nIHZhbHVlcy5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtzdHJpbmd9IHN0cmluZyBUaGUgc3RyaW5nIHRvIGZvcm1hdC5cbiAgICogQHJldHVybnMge3N0cmluZ30gVGhlIGZvcm1hdHRlZCBzdHJpbmcuXG4gICAqL1xuICBmdW5jdGlvbiBmb3JtYXQoc3RyaW5nKSB7XG4gICAgc3RyaW5nID0gdHJpbShzdHJpbmcpO1xuICAgIHJldHVybiAvXig/OndlYk9TfGkoPzpPU3xQKSkvLnRlc3Qoc3RyaW5nKVxuICAgICAgPyBzdHJpbmdcbiAgICAgIDogY2FwaXRhbGl6ZShzdHJpbmcpO1xuICB9XG5cbiAgLyoqXG4gICAqIEl0ZXJhdGVzIG92ZXIgYW4gb2JqZWN0J3Mgb3duIHByb3BlcnRpZXMsIGV4ZWN1dGluZyB0aGUgYGNhbGxiYWNrYCBmb3IgZWFjaC5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIGl0ZXJhdGUgb3Zlci5cbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gY2FsbGJhY2sgVGhlIGZ1bmN0aW9uIGV4ZWN1dGVkIHBlciBvd24gcHJvcGVydHkuXG4gICAqL1xuICBmdW5jdGlvbiBmb3JPd24ob2JqZWN0LCBjYWxsYmFjaykge1xuICAgIGZvciAodmFyIGtleSBpbiBvYmplY3QpIHtcbiAgICAgIGlmIChoYXNPd25Qcm9wZXJ0eS5jYWxsKG9iamVjdCwga2V5KSkge1xuICAgICAgICBjYWxsYmFjayhvYmplY3Rba2V5XSwga2V5LCBvYmplY3QpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBHZXRzIHRoZSBpbnRlcm5hbCBgW1tDbGFzc11dYCBvZiBhIHZhbHVlLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZS5cbiAgICogQHJldHVybnMge3N0cmluZ30gVGhlIGBbW0NsYXNzXV1gLlxuICAgKi9cbiAgZnVuY3Rpb24gZ2V0Q2xhc3NPZih2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZSA9PSBudWxsXG4gICAgICA/IGNhcGl0YWxpemUodmFsdWUpXG4gICAgICA6IHRvU3RyaW5nLmNhbGwodmFsdWUpLnNsaWNlKDgsIC0xKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBIb3N0IG9iamVjdHMgY2FuIHJldHVybiB0eXBlIHZhbHVlcyB0aGF0IGFyZSBkaWZmZXJlbnQgZnJvbSB0aGVpciBhY3R1YWxcbiAgICogZGF0YSB0eXBlLiBUaGUgb2JqZWN0cyB3ZSBhcmUgY29uY2VybmVkIHdpdGggdXN1YWxseSByZXR1cm4gbm9uLXByaW1pdGl2ZVxuICAgKiB0eXBlcyBvZiBcIm9iamVjdFwiLCBcImZ1bmN0aW9uXCIsIG9yIFwidW5rbm93blwiLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0geyp9IG9iamVjdCBUaGUgb3duZXIgb2YgdGhlIHByb3BlcnR5LlxuICAgKiBAcGFyYW0ge3N0cmluZ30gcHJvcGVydHkgVGhlIHByb3BlcnR5IHRvIGNoZWNrLlxuICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgdGhlIHByb3BlcnR5IHZhbHVlIGlzIGEgbm9uLXByaW1pdGl2ZSwgZWxzZSBgZmFsc2VgLlxuICAgKi9cbiAgZnVuY3Rpb24gaXNIb3N0VHlwZShvYmplY3QsIHByb3BlcnR5KSB7XG4gICAgdmFyIHR5cGUgPSBvYmplY3QgIT0gbnVsbCA/IHR5cGVvZiBvYmplY3RbcHJvcGVydHldIDogJ251bWJlcic7XG4gICAgcmV0dXJuICEvXig/OmJvb2xlYW58bnVtYmVyfHN0cmluZ3x1bmRlZmluZWQpJC8udGVzdCh0eXBlKSAmJlxuICAgICAgKHR5cGUgPT0gJ29iamVjdCcgPyAhIW9iamVjdFtwcm9wZXJ0eV0gOiB0cnVlKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBQcmVwYXJlcyBhIHN0cmluZyBmb3IgdXNlIGluIGEgYFJlZ0V4cGAgYnkgbWFraW5nIGh5cGhlbnMgYW5kIHNwYWNlcyBvcHRpb25hbC5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtzdHJpbmd9IHN0cmluZyBUaGUgc3RyaW5nIHRvIHF1YWxpZnkuXG4gICAqIEByZXR1cm5zIHtzdHJpbmd9IFRoZSBxdWFsaWZpZWQgc3RyaW5nLlxuICAgKi9cbiAgZnVuY3Rpb24gcXVhbGlmeShzdHJpbmcpIHtcbiAgICByZXR1cm4gU3RyaW5nKHN0cmluZykucmVwbGFjZSgvKFsgLV0pKD8hJCkvZywgJyQxPycpO1xuICB9XG5cbiAgLyoqXG4gICAqIEEgYmFyZS1ib25lcyBgQXJyYXkjcmVkdWNlYCBsaWtlIHV0aWxpdHkgZnVuY3Rpb24uXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBpdGVyYXRlIG92ZXIuXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IGNhbGxiYWNrIFRoZSBmdW5jdGlvbiBjYWxsZWQgcGVyIGl0ZXJhdGlvbi5cbiAgICogQHJldHVybnMgeyp9IFRoZSBhY2N1bXVsYXRlZCByZXN1bHQuXG4gICAqL1xuICBmdW5jdGlvbiByZWR1Y2UoYXJyYXksIGNhbGxiYWNrKSB7XG4gICAgdmFyIGFjY3VtdWxhdG9yID0gbnVsbDtcbiAgICBlYWNoKGFycmF5LCBmdW5jdGlvbih2YWx1ZSwgaW5kZXgpIHtcbiAgICAgIGFjY3VtdWxhdG9yID0gY2FsbGJhY2soYWNjdW11bGF0b3IsIHZhbHVlLCBpbmRleCwgYXJyYXkpO1xuICAgIH0pO1xuICAgIHJldHVybiBhY2N1bXVsYXRvcjtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZW1vdmVzIGxlYWRpbmcgYW5kIHRyYWlsaW5nIHdoaXRlc3BhY2UgZnJvbSBhIHN0cmluZy5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtzdHJpbmd9IHN0cmluZyBUaGUgc3RyaW5nIHRvIHRyaW0uXG4gICAqIEByZXR1cm5zIHtzdHJpbmd9IFRoZSB0cmltbWVkIHN0cmluZy5cbiAgICovXG4gIGZ1bmN0aW9uIHRyaW0oc3RyaW5nKSB7XG4gICAgcmV0dXJuIFN0cmluZyhzdHJpbmcpLnJlcGxhY2UoL14gK3wgKyQvZywgJycpO1xuICB9XG5cbiAgLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG5cbiAgLyoqXG4gICAqIENyZWF0ZXMgYSBuZXcgcGxhdGZvcm0gb2JqZWN0LlxuICAgKlxuICAgKiBAbWVtYmVyT2YgcGxhdGZvcm1cbiAgICogQHBhcmFtIHtPYmplY3R8c3RyaW5nfSBbdWE9bmF2aWdhdG9yLnVzZXJBZ2VudF0gVGhlIHVzZXIgYWdlbnQgc3RyaW5nIG9yXG4gICAqICBjb250ZXh0IG9iamVjdC5cbiAgICogQHJldHVybnMge09iamVjdH0gQSBwbGF0Zm9ybSBvYmplY3QuXG4gICAqL1xuICBmdW5jdGlvbiBwYXJzZSh1YSkge1xuXG4gICAgLyoqIFRoZSBlbnZpcm9ubWVudCBjb250ZXh0IG9iamVjdC4gKi9cbiAgICB2YXIgY29udGV4dCA9IHJvb3Q7XG5cbiAgICAvKiogVXNlZCB0byBmbGFnIHdoZW4gYSBjdXN0b20gY29udGV4dCBpcyBwcm92aWRlZC4gKi9cbiAgICB2YXIgaXNDdXN0b21Db250ZXh0ID0gdWEgJiYgdHlwZW9mIHVhID09ICdvYmplY3QnICYmIGdldENsYXNzT2YodWEpICE9ICdTdHJpbmcnO1xuXG4gICAgLy8gSnVnZ2xlIGFyZ3VtZW50cy5cbiAgICBpZiAoaXNDdXN0b21Db250ZXh0KSB7XG4gICAgICBjb250ZXh0ID0gdWE7XG4gICAgICB1YSA9IG51bGw7XG4gICAgfVxuXG4gICAgLyoqIEJyb3dzZXIgbmF2aWdhdG9yIG9iamVjdC4gKi9cbiAgICB2YXIgbmF2ID0gY29udGV4dC5uYXZpZ2F0b3IgfHwge307XG5cbiAgICAvKiogQnJvd3NlciB1c2VyIGFnZW50IHN0cmluZy4gKi9cbiAgICB2YXIgdXNlckFnZW50ID0gbmF2LnVzZXJBZ2VudCB8fCAnJztcblxuICAgIHVhIHx8ICh1YSA9IHVzZXJBZ2VudCk7XG5cbiAgICAvKiogVXNlZCB0byBmbGFnIHdoZW4gYHRoaXNCaW5kaW5nYCBpcyB0aGUgW01vZHVsZVNjb3BlXS4gKi9cbiAgICB2YXIgaXNNb2R1bGVTY29wZSA9IGlzQ3VzdG9tQ29udGV4dCB8fCB0aGlzQmluZGluZyA9PSBvbGRSb290O1xuXG4gICAgLyoqIFVzZWQgdG8gZGV0ZWN0IGlmIGJyb3dzZXIgaXMgbGlrZSBDaHJvbWUuICovXG4gICAgdmFyIGxpa2VDaHJvbWUgPSBpc0N1c3RvbUNvbnRleHRcbiAgICAgID8gISFuYXYubGlrZUNocm9tZVxuICAgICAgOiAvXFxiQ2hyb21lXFxiLy50ZXN0KHVhKSAmJiAhL2ludGVybmFsfFxcbi9pLnRlc3QodG9TdHJpbmcudG9TdHJpbmcoKSk7XG5cbiAgICAvKiogSW50ZXJuYWwgYFtbQ2xhc3NdXWAgdmFsdWUgc2hvcnRjdXRzLiAqL1xuICAgIHZhciBvYmplY3RDbGFzcyA9ICdPYmplY3QnLFxuICAgICAgICBhaXJSdW50aW1lQ2xhc3MgPSBpc0N1c3RvbUNvbnRleHQgPyBvYmplY3RDbGFzcyA6ICdTY3JpcHRCcmlkZ2luZ1Byb3h5T2JqZWN0JyxcbiAgICAgICAgZW52aXJvQ2xhc3MgPSBpc0N1c3RvbUNvbnRleHQgPyBvYmplY3RDbGFzcyA6ICdFbnZpcm9ubWVudCcsXG4gICAgICAgIGphdmFDbGFzcyA9IChpc0N1c3RvbUNvbnRleHQgJiYgY29udGV4dC5qYXZhKSA/ICdKYXZhUGFja2FnZScgOiBnZXRDbGFzc09mKGNvbnRleHQuamF2YSksXG4gICAgICAgIHBoYW50b21DbGFzcyA9IGlzQ3VzdG9tQ29udGV4dCA/IG9iamVjdENsYXNzIDogJ1J1bnRpbWVPYmplY3QnO1xuXG4gICAgLyoqIERldGVjdCBKYXZhIGVudmlyb25tZW50cy4gKi9cbiAgICB2YXIgamF2YSA9IC9cXGJKYXZhLy50ZXN0KGphdmFDbGFzcykgJiYgY29udGV4dC5qYXZhO1xuXG4gICAgLyoqIERldGVjdCBSaGluby4gKi9cbiAgICB2YXIgcmhpbm8gPSBqYXZhICYmIGdldENsYXNzT2YoY29udGV4dC5lbnZpcm9ubWVudCkgPT0gZW52aXJvQ2xhc3M7XG5cbiAgICAvKiogQSBjaGFyYWN0ZXIgdG8gcmVwcmVzZW50IGFscGhhLiAqL1xuICAgIHZhciBhbHBoYSA9IGphdmEgPyAnYScgOiAnXFx1MDNiMSc7XG5cbiAgICAvKiogQSBjaGFyYWN0ZXIgdG8gcmVwcmVzZW50IGJldGEuICovXG4gICAgdmFyIGJldGEgPSBqYXZhID8gJ2InIDogJ1xcdTAzYjInO1xuXG4gICAgLyoqIEJyb3dzZXIgZG9jdW1lbnQgb2JqZWN0LiAqL1xuICAgIHZhciBkb2MgPSBjb250ZXh0LmRvY3VtZW50IHx8IHt9O1xuXG4gICAgLyoqXG4gICAgICogRGV0ZWN0IE9wZXJhIGJyb3dzZXIgKFByZXN0by1iYXNlZCkuXG4gICAgICogaHR0cDovL3d3dy5ob3d0b2NyZWF0ZS5jby51ay9vcGVyYVN0dWZmL29wZXJhT2JqZWN0Lmh0bWxcbiAgICAgKiBodHRwOi8vZGV2Lm9wZXJhLmNvbS9hcnRpY2xlcy92aWV3L29wZXJhLW1pbmktd2ViLWNvbnRlbnQtYXV0aG9yaW5nLWd1aWRlbGluZXMvI29wZXJhbWluaVxuICAgICAqL1xuICAgIHZhciBvcGVyYSA9IGNvbnRleHQub3BlcmFtaW5pIHx8IGNvbnRleHQub3BlcmE7XG5cbiAgICAvKiogT3BlcmEgYFtbQ2xhc3NdXWAuICovXG4gICAgdmFyIG9wZXJhQ2xhc3MgPSByZU9wZXJhLnRlc3Qob3BlcmFDbGFzcyA9IChpc0N1c3RvbUNvbnRleHQgJiYgb3BlcmEpID8gb3BlcmFbJ1tbQ2xhc3NdXSddIDogZ2V0Q2xhc3NPZihvcGVyYSkpXG4gICAgICA/IG9wZXJhQ2xhc3NcbiAgICAgIDogKG9wZXJhID0gbnVsbCk7XG5cbiAgICAvKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG5cbiAgICAvKiogVGVtcG9yYXJ5IHZhcmlhYmxlIHVzZWQgb3ZlciB0aGUgc2NyaXB0J3MgbGlmZXRpbWUuICovXG4gICAgdmFyIGRhdGE7XG5cbiAgICAvKiogVGhlIENQVSBhcmNoaXRlY3R1cmUuICovXG4gICAgdmFyIGFyY2ggPSB1YTtcblxuICAgIC8qKiBQbGF0Zm9ybSBkZXNjcmlwdGlvbiBhcnJheS4gKi9cbiAgICB2YXIgZGVzY3JpcHRpb24gPSBbXTtcblxuICAgIC8qKiBQbGF0Zm9ybSBhbHBoYS9iZXRhIGluZGljYXRvci4gKi9cbiAgICB2YXIgcHJlcmVsZWFzZSA9IG51bGw7XG5cbiAgICAvKiogQSBmbGFnIHRvIGluZGljYXRlIHRoYXQgZW52aXJvbm1lbnQgZmVhdHVyZXMgc2hvdWxkIGJlIHVzZWQgdG8gcmVzb2x2ZSB0aGUgcGxhdGZvcm0uICovXG4gICAgdmFyIHVzZUZlYXR1cmVzID0gdWEgPT0gdXNlckFnZW50O1xuXG4gICAgLyoqIFRoZSBicm93c2VyL2Vudmlyb25tZW50IHZlcnNpb24uICovXG4gICAgdmFyIHZlcnNpb24gPSB1c2VGZWF0dXJlcyAmJiBvcGVyYSAmJiB0eXBlb2Ygb3BlcmEudmVyc2lvbiA9PSAnZnVuY3Rpb24nICYmIG9wZXJhLnZlcnNpb24oKTtcblxuICAgIC8qKiBBIGZsYWcgdG8gaW5kaWNhdGUgaWYgdGhlIE9TIGVuZHMgd2l0aCBcIi8gVmVyc2lvblwiICovXG4gICAgdmFyIGlzU3BlY2lhbENhc2VkT1M7XG5cbiAgICAvKiBEZXRlY3RhYmxlIGxheW91dCBlbmdpbmVzIChvcmRlciBpcyBpbXBvcnRhbnQpLiAqL1xuICAgIHZhciBsYXlvdXQgPSBnZXRMYXlvdXQoW1xuICAgICAgeyAnbGFiZWwnOiAnRWRnZUhUTUwnLCAncGF0dGVybic6ICdFZGdlJyB9LFxuICAgICAgJ1RyaWRlbnQnLFxuICAgICAgeyAnbGFiZWwnOiAnV2ViS2l0JywgJ3BhdHRlcm4nOiAnQXBwbGVXZWJLaXQnIH0sXG4gICAgICAnaUNhYicsXG4gICAgICAnUHJlc3RvJyxcbiAgICAgICdOZXRGcm9udCcsXG4gICAgICAnVGFzbWFuJyxcbiAgICAgICdLSFRNTCcsXG4gICAgICAnR2Vja28nXG4gICAgXSk7XG5cbiAgICAvKiBEZXRlY3RhYmxlIGJyb3dzZXIgbmFtZXMgKG9yZGVyIGlzIGltcG9ydGFudCkuICovXG4gICAgdmFyIG5hbWUgPSBnZXROYW1lKFtcbiAgICAgICdBZG9iZSBBSVInLFxuICAgICAgJ0Fyb3JhJyxcbiAgICAgICdBdmFudCBCcm93c2VyJyxcbiAgICAgICdCcmVhY2gnLFxuICAgICAgJ0NhbWlubycsXG4gICAgICAnRWxlY3Ryb24nLFxuICAgICAgJ0VwaXBoYW55JyxcbiAgICAgICdGZW5uZWMnLFxuICAgICAgJ0Zsb2NrJyxcbiAgICAgICdHYWxlb24nLFxuICAgICAgJ0dyZWVuQnJvd3NlcicsXG4gICAgICAnaUNhYicsXG4gICAgICAnSWNld2Vhc2VsJyxcbiAgICAgICdLLU1lbGVvbicsXG4gICAgICAnS29ucXVlcm9yJyxcbiAgICAgICdMdW5hc2NhcGUnLFxuICAgICAgJ01heHRob24nLFxuICAgICAgeyAnbGFiZWwnOiAnTWljcm9zb2Z0IEVkZ2UnLCAncGF0dGVybic6ICdFZGdlJyB9LFxuICAgICAgJ01pZG9yaScsXG4gICAgICAnTm9vayBCcm93c2VyJyxcbiAgICAgICdQYWxlTW9vbicsXG4gICAgICAnUGhhbnRvbUpTJyxcbiAgICAgICdSYXZlbicsXG4gICAgICAnUmVrb25xJyxcbiAgICAgICdSb2NrTWVsdCcsXG4gICAgICB7ICdsYWJlbCc6ICdTYW1zdW5nIEludGVybmV0JywgJ3BhdHRlcm4nOiAnU2Ftc3VuZ0Jyb3dzZXInIH0sXG4gICAgICAnU2VhTW9ua2V5JyxcbiAgICAgIHsgJ2xhYmVsJzogJ1NpbGsnLCAncGF0dGVybic6ICcoPzpDbG91ZDl8U2lsay1BY2NlbGVyYXRlZCknIH0sXG4gICAgICAnU2xlaXBuaXInLFxuICAgICAgJ1NsaW1Ccm93c2VyJyxcbiAgICAgIHsgJ2xhYmVsJzogJ1NSV2FyZSBJcm9uJywgJ3BhdHRlcm4nOiAnSXJvbicgfSxcbiAgICAgICdTdW5yaXNlJyxcbiAgICAgICdTd2lmdGZveCcsXG4gICAgICAnV2F0ZXJmb3gnLFxuICAgICAgJ1dlYlBvc2l0aXZlJyxcbiAgICAgICdPcGVyYSBNaW5pJyxcbiAgICAgIHsgJ2xhYmVsJzogJ09wZXJhIE1pbmknLCAncGF0dGVybic6ICdPUGlPUycgfSxcbiAgICAgICdPcGVyYScsXG4gICAgICB7ICdsYWJlbCc6ICdPcGVyYScsICdwYXR0ZXJuJzogJ09QUicgfSxcbiAgICAgICdDaHJvbWUnLFxuICAgICAgeyAnbGFiZWwnOiAnQ2hyb21lIE1vYmlsZScsICdwYXR0ZXJuJzogJyg/OkNyaU9TfENyTW8pJyB9LFxuICAgICAgeyAnbGFiZWwnOiAnRmlyZWZveCcsICdwYXR0ZXJuJzogJyg/OkZpcmVmb3h8TWluZWZpZWxkKScgfSxcbiAgICAgIHsgJ2xhYmVsJzogJ0ZpcmVmb3ggZm9yIGlPUycsICdwYXR0ZXJuJzogJ0Z4aU9TJyB9LFxuICAgICAgeyAnbGFiZWwnOiAnSUUnLCAncGF0dGVybic6ICdJRU1vYmlsZScgfSxcbiAgICAgIHsgJ2xhYmVsJzogJ0lFJywgJ3BhdHRlcm4nOiAnTVNJRScgfSxcbiAgICAgICdTYWZhcmknXG4gICAgXSk7XG5cbiAgICAvKiBEZXRlY3RhYmxlIHByb2R1Y3RzIChvcmRlciBpcyBpbXBvcnRhbnQpLiAqL1xuICAgIHZhciBwcm9kdWN0ID0gZ2V0UHJvZHVjdChbXG4gICAgICB7ICdsYWJlbCc6ICdCbGFja0JlcnJ5JywgJ3BhdHRlcm4nOiAnQkIxMCcgfSxcbiAgICAgICdCbGFja0JlcnJ5JyxcbiAgICAgIHsgJ2xhYmVsJzogJ0dhbGF4eSBTJywgJ3BhdHRlcm4nOiAnR1QtSTkwMDAnIH0sXG4gICAgICB7ICdsYWJlbCc6ICdHYWxheHkgUzInLCAncGF0dGVybic6ICdHVC1JOTEwMCcgfSxcbiAgICAgIHsgJ2xhYmVsJzogJ0dhbGF4eSBTMycsICdwYXR0ZXJuJzogJ0dULUk5MzAwJyB9LFxuICAgICAgeyAnbGFiZWwnOiAnR2FsYXh5IFM0JywgJ3BhdHRlcm4nOiAnR1QtSTk1MDAnIH0sXG4gICAgICB7ICdsYWJlbCc6ICdHYWxheHkgUzUnLCAncGF0dGVybic6ICdTTS1HOTAwJyB9LFxuICAgICAgeyAnbGFiZWwnOiAnR2FsYXh5IFM2JywgJ3BhdHRlcm4nOiAnU00tRzkyMCcgfSxcbiAgICAgIHsgJ2xhYmVsJzogJ0dhbGF4eSBTNiBFZGdlJywgJ3BhdHRlcm4nOiAnU00tRzkyNScgfSxcbiAgICAgIHsgJ2xhYmVsJzogJ0dhbGF4eSBTNycsICdwYXR0ZXJuJzogJ1NNLUc5MzAnIH0sXG4gICAgICB7ICdsYWJlbCc6ICdHYWxheHkgUzcgRWRnZScsICdwYXR0ZXJuJzogJ1NNLUc5MzUnIH0sXG4gICAgICAnR29vZ2xlIFRWJyxcbiAgICAgICdMdW1pYScsXG4gICAgICAnaVBhZCcsXG4gICAgICAnaVBvZCcsXG4gICAgICAnaVBob25lJyxcbiAgICAgICdLaW5kbGUnLFxuICAgICAgeyAnbGFiZWwnOiAnS2luZGxlIEZpcmUnLCAncGF0dGVybic6ICcoPzpDbG91ZDl8U2lsay1BY2NlbGVyYXRlZCknIH0sXG4gICAgICAnTmV4dXMnLFxuICAgICAgJ05vb2snLFxuICAgICAgJ1BsYXlCb29rJyxcbiAgICAgICdQbGF5U3RhdGlvbiBWaXRhJyxcbiAgICAgICdQbGF5U3RhdGlvbicsXG4gICAgICAnVG91Y2hQYWQnLFxuICAgICAgJ1RyYW5zZm9ybWVyJyxcbiAgICAgIHsgJ2xhYmVsJzogJ1dpaSBVJywgJ3BhdHRlcm4nOiAnV2lpVScgfSxcbiAgICAgICdXaWknLFxuICAgICAgJ1hib3ggT25lJyxcbiAgICAgIHsgJ2xhYmVsJzogJ1hib3ggMzYwJywgJ3BhdHRlcm4nOiAnWGJveCcgfSxcbiAgICAgICdYb29tJ1xuICAgIF0pO1xuXG4gICAgLyogRGV0ZWN0YWJsZSBtYW51ZmFjdHVyZXJzLiAqL1xuICAgIHZhciBtYW51ZmFjdHVyZXIgPSBnZXRNYW51ZmFjdHVyZXIoe1xuICAgICAgJ0FwcGxlJzogeyAnaVBhZCc6IDEsICdpUGhvbmUnOiAxLCAnaVBvZCc6IDEgfSxcbiAgICAgICdBcmNob3MnOiB7fSxcbiAgICAgICdBbWF6b24nOiB7ICdLaW5kbGUnOiAxLCAnS2luZGxlIEZpcmUnOiAxIH0sXG4gICAgICAnQXN1cyc6IHsgJ1RyYW5zZm9ybWVyJzogMSB9LFxuICAgICAgJ0Jhcm5lcyAmIE5vYmxlJzogeyAnTm9vayc6IDEgfSxcbiAgICAgICdCbGFja0JlcnJ5JzogeyAnUGxheUJvb2snOiAxIH0sXG4gICAgICAnR29vZ2xlJzogeyAnR29vZ2xlIFRWJzogMSwgJ05leHVzJzogMSB9LFxuICAgICAgJ0hQJzogeyAnVG91Y2hQYWQnOiAxIH0sXG4gICAgICAnSFRDJzoge30sXG4gICAgICAnTEcnOiB7fSxcbiAgICAgICdNaWNyb3NvZnQnOiB7ICdYYm94JzogMSwgJ1hib3ggT25lJzogMSB9LFxuICAgICAgJ01vdG9yb2xhJzogeyAnWG9vbSc6IDEgfSxcbiAgICAgICdOaW50ZW5kbyc6IHsgJ1dpaSBVJzogMSwgICdXaWknOiAxIH0sXG4gICAgICAnTm9raWEnOiB7ICdMdW1pYSc6IDEgfSxcbiAgICAgICdTYW1zdW5nJzogeyAnR2FsYXh5IFMnOiAxLCAnR2FsYXh5IFMyJzogMSwgJ0dhbGF4eSBTMyc6IDEsICdHYWxheHkgUzQnOiAxIH0sXG4gICAgICAnU29ueSc6IHsgJ1BsYXlTdGF0aW9uJzogMSwgJ1BsYXlTdGF0aW9uIFZpdGEnOiAxIH1cbiAgICB9KTtcblxuICAgIC8qIERldGVjdGFibGUgb3BlcmF0aW5nIHN5c3RlbXMgKG9yZGVyIGlzIGltcG9ydGFudCkuICovXG4gICAgdmFyIG9zID0gZ2V0T1MoW1xuICAgICAgJ1dpbmRvd3MgUGhvbmUnLFxuICAgICAgJ0FuZHJvaWQnLFxuICAgICAgJ0NlbnRPUycsXG4gICAgICB7ICdsYWJlbCc6ICdDaHJvbWUgT1MnLCAncGF0dGVybic6ICdDck9TJyB9LFxuICAgICAgJ0RlYmlhbicsXG4gICAgICAnRmVkb3JhJyxcbiAgICAgICdGcmVlQlNEJyxcbiAgICAgICdHZW50b28nLFxuICAgICAgJ0hhaWt1JyxcbiAgICAgICdLdWJ1bnR1JyxcbiAgICAgICdMaW51eCBNaW50JyxcbiAgICAgICdPcGVuQlNEJyxcbiAgICAgICdSZWQgSGF0JyxcbiAgICAgICdTdVNFJyxcbiAgICAgICdVYnVudHUnLFxuICAgICAgJ1h1YnVudHUnLFxuICAgICAgJ0N5Z3dpbicsXG4gICAgICAnU3ltYmlhbiBPUycsXG4gICAgICAnaHB3T1MnLFxuICAgICAgJ3dlYk9TICcsXG4gICAgICAnd2ViT1MnLFxuICAgICAgJ1RhYmxldCBPUycsXG4gICAgICAnVGl6ZW4nLFxuICAgICAgJ0xpbnV4JyxcbiAgICAgICdNYWMgT1MgWCcsXG4gICAgICAnTWFjaW50b3NoJyxcbiAgICAgICdNYWMnLFxuICAgICAgJ1dpbmRvd3MgOTg7JyxcbiAgICAgICdXaW5kb3dzICdcbiAgICBdKTtcblxuICAgIC8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cblxuICAgIC8qKlxuICAgICAqIFBpY2tzIHRoZSBsYXlvdXQgZW5naW5lIGZyb20gYW4gYXJyYXkgb2YgZ3Vlc3Nlcy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtBcnJheX0gZ3Vlc3NlcyBBbiBhcnJheSBvZiBndWVzc2VzLlxuICAgICAqIEByZXR1cm5zIHtudWxsfHN0cmluZ30gVGhlIGRldGVjdGVkIGxheW91dCBlbmdpbmUuXG4gICAgICovXG4gICAgZnVuY3Rpb24gZ2V0TGF5b3V0KGd1ZXNzZXMpIHtcbiAgICAgIHJldHVybiByZWR1Y2UoZ3Vlc3NlcywgZnVuY3Rpb24ocmVzdWx0LCBndWVzcykge1xuICAgICAgICByZXR1cm4gcmVzdWx0IHx8IFJlZ0V4cCgnXFxcXGInICsgKFxuICAgICAgICAgIGd1ZXNzLnBhdHRlcm4gfHwgcXVhbGlmeShndWVzcylcbiAgICAgICAgKSArICdcXFxcYicsICdpJykuZXhlYyh1YSkgJiYgKGd1ZXNzLmxhYmVsIHx8IGd1ZXNzKTtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFBpY2tzIHRoZSBtYW51ZmFjdHVyZXIgZnJvbSBhbiBhcnJheSBvZiBndWVzc2VzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBndWVzc2VzIEFuIG9iamVjdCBvZiBndWVzc2VzLlxuICAgICAqIEByZXR1cm5zIHtudWxsfHN0cmluZ30gVGhlIGRldGVjdGVkIG1hbnVmYWN0dXJlci5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBnZXRNYW51ZmFjdHVyZXIoZ3Vlc3Nlcykge1xuICAgICAgcmV0dXJuIHJlZHVjZShndWVzc2VzLCBmdW5jdGlvbihyZXN1bHQsIHZhbHVlLCBrZXkpIHtcbiAgICAgICAgLy8gTG9va3VwIHRoZSBtYW51ZmFjdHVyZXIgYnkgcHJvZHVjdCBvciBzY2FuIHRoZSBVQSBmb3IgdGhlIG1hbnVmYWN0dXJlci5cbiAgICAgICAgcmV0dXJuIHJlc3VsdCB8fCAoXG4gICAgICAgICAgdmFsdWVbcHJvZHVjdF0gfHxcbiAgICAgICAgICB2YWx1ZVsvXlthLXpdKyg/OiArW2Etel0rXFxiKSovaS5leGVjKHByb2R1Y3QpXSB8fFxuICAgICAgICAgIFJlZ0V4cCgnXFxcXGInICsgcXVhbGlmeShrZXkpICsgJyg/OlxcXFxifFxcXFx3KlxcXFxkKScsICdpJykuZXhlYyh1YSlcbiAgICAgICAgKSAmJiBrZXk7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBQaWNrcyB0aGUgYnJvd3NlciBuYW1lIGZyb20gYW4gYXJyYXkgb2YgZ3Vlc3Nlcy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtBcnJheX0gZ3Vlc3NlcyBBbiBhcnJheSBvZiBndWVzc2VzLlxuICAgICAqIEByZXR1cm5zIHtudWxsfHN0cmluZ30gVGhlIGRldGVjdGVkIGJyb3dzZXIgbmFtZS5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBnZXROYW1lKGd1ZXNzZXMpIHtcbiAgICAgIHJldHVybiByZWR1Y2UoZ3Vlc3NlcywgZnVuY3Rpb24ocmVzdWx0LCBndWVzcykge1xuICAgICAgICByZXR1cm4gcmVzdWx0IHx8IFJlZ0V4cCgnXFxcXGInICsgKFxuICAgICAgICAgIGd1ZXNzLnBhdHRlcm4gfHwgcXVhbGlmeShndWVzcylcbiAgICAgICAgKSArICdcXFxcYicsICdpJykuZXhlYyh1YSkgJiYgKGd1ZXNzLmxhYmVsIHx8IGd1ZXNzKTtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFBpY2tzIHRoZSBPUyBuYW1lIGZyb20gYW4gYXJyYXkgb2YgZ3Vlc3Nlcy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtBcnJheX0gZ3Vlc3NlcyBBbiBhcnJheSBvZiBndWVzc2VzLlxuICAgICAqIEByZXR1cm5zIHtudWxsfHN0cmluZ30gVGhlIGRldGVjdGVkIE9TIG5hbWUuXG4gICAgICovXG4gICAgZnVuY3Rpb24gZ2V0T1MoZ3Vlc3Nlcykge1xuICAgICAgcmV0dXJuIHJlZHVjZShndWVzc2VzLCBmdW5jdGlvbihyZXN1bHQsIGd1ZXNzKSB7XG4gICAgICAgIHZhciBwYXR0ZXJuID0gZ3Vlc3MucGF0dGVybiB8fCBxdWFsaWZ5KGd1ZXNzKTtcbiAgICAgICAgaWYgKCFyZXN1bHQgJiYgKHJlc3VsdCA9XG4gICAgICAgICAgICAgIFJlZ0V4cCgnXFxcXGInICsgcGF0dGVybiArICcoPzovW1xcXFxkLl0rfFsgXFxcXHcuXSopJywgJ2knKS5leGVjKHVhKVxuICAgICAgICAgICAgKSkge1xuICAgICAgICAgIHJlc3VsdCA9IGNsZWFudXBPUyhyZXN1bHQsIHBhdHRlcm4sIGd1ZXNzLmxhYmVsIHx8IGd1ZXNzKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUGlja3MgdGhlIHByb2R1Y3QgbmFtZSBmcm9tIGFuIGFycmF5IG9mIGd1ZXNzZXMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGd1ZXNzZXMgQW4gYXJyYXkgb2YgZ3Vlc3Nlcy5cbiAgICAgKiBAcmV0dXJucyB7bnVsbHxzdHJpbmd9IFRoZSBkZXRlY3RlZCBwcm9kdWN0IG5hbWUuXG4gICAgICovXG4gICAgZnVuY3Rpb24gZ2V0UHJvZHVjdChndWVzc2VzKSB7XG4gICAgICByZXR1cm4gcmVkdWNlKGd1ZXNzZXMsIGZ1bmN0aW9uKHJlc3VsdCwgZ3Vlc3MpIHtcbiAgICAgICAgdmFyIHBhdHRlcm4gPSBndWVzcy5wYXR0ZXJuIHx8IHF1YWxpZnkoZ3Vlc3MpO1xuICAgICAgICBpZiAoIXJlc3VsdCAmJiAocmVzdWx0ID1cbiAgICAgICAgICAgICAgUmVnRXhwKCdcXFxcYicgKyBwYXR0ZXJuICsgJyAqXFxcXGQrWy5cXFxcd19dKicsICdpJykuZXhlYyh1YSkgfHxcbiAgICAgICAgICAgICAgUmVnRXhwKCdcXFxcYicgKyBwYXR0ZXJuICsgJyAqXFxcXHcrLVtcXFxcd10qJywgJ2knKS5leGVjKHVhKSB8fFxuICAgICAgICAgICAgICBSZWdFeHAoJ1xcXFxiJyArIHBhdHRlcm4gKyAnKD86OyAqKD86W2Etel0rW18tXSk/W2Etel0rXFxcXGQrfFteICgpOy1dKiknLCAnaScpLmV4ZWModWEpXG4gICAgICAgICAgICApKSB7XG4gICAgICAgICAgLy8gU3BsaXQgYnkgZm9yd2FyZCBzbGFzaCBhbmQgYXBwZW5kIHByb2R1Y3QgdmVyc2lvbiBpZiBuZWVkZWQuXG4gICAgICAgICAgaWYgKChyZXN1bHQgPSBTdHJpbmcoKGd1ZXNzLmxhYmVsICYmICFSZWdFeHAocGF0dGVybiwgJ2knKS50ZXN0KGd1ZXNzLmxhYmVsKSkgPyBndWVzcy5sYWJlbCA6IHJlc3VsdCkuc3BsaXQoJy8nKSlbMV0gJiYgIS9bXFxkLl0rLy50ZXN0KHJlc3VsdFswXSkpIHtcbiAgICAgICAgICAgIHJlc3VsdFswXSArPSAnICcgKyByZXN1bHRbMV07XG4gICAgICAgICAgfVxuICAgICAgICAgIC8vIENvcnJlY3QgY2hhcmFjdGVyIGNhc2UgYW5kIGNsZWFudXAgc3RyaW5nLlxuICAgICAgICAgIGd1ZXNzID0gZ3Vlc3MubGFiZWwgfHwgZ3Vlc3M7XG4gICAgICAgICAgcmVzdWx0ID0gZm9ybWF0KHJlc3VsdFswXVxuICAgICAgICAgICAgLnJlcGxhY2UoUmVnRXhwKHBhdHRlcm4sICdpJyksIGd1ZXNzKVxuICAgICAgICAgICAgLnJlcGxhY2UoUmVnRXhwKCc7ICooPzonICsgZ3Vlc3MgKyAnW18tXSk/JywgJ2knKSwgJyAnKVxuICAgICAgICAgICAgLnJlcGxhY2UoUmVnRXhwKCcoJyArIGd1ZXNzICsgJylbLV8uXT8oXFxcXHcpJywgJ2knKSwgJyQxICQyJykpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXNvbHZlcyB0aGUgdmVyc2lvbiB1c2luZyBhbiBhcnJheSBvZiBVQSBwYXR0ZXJucy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtBcnJheX0gcGF0dGVybnMgQW4gYXJyYXkgb2YgVUEgcGF0dGVybnMuXG4gICAgICogQHJldHVybnMge251bGx8c3RyaW5nfSBUaGUgZGV0ZWN0ZWQgdmVyc2lvbi5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBnZXRWZXJzaW9uKHBhdHRlcm5zKSB7XG4gICAgICByZXR1cm4gcmVkdWNlKHBhdHRlcm5zLCBmdW5jdGlvbihyZXN1bHQsIHBhdHRlcm4pIHtcbiAgICAgICAgcmV0dXJuIHJlc3VsdCB8fCAoUmVnRXhwKHBhdHRlcm4gK1xuICAgICAgICAgICcoPzotW1xcXFxkLl0rL3woPzogZm9yIFtcXFxcdy1dKyk/WyAvLV0pKFtcXFxcZC5dK1teICgpOy9fLV0qKScsICdpJykuZXhlYyh1YSkgfHwgMClbMV0gfHwgbnVsbDtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgYHBsYXRmb3JtLmRlc2NyaXB0aW9uYCB3aGVuIHRoZSBwbGF0Zm9ybSBvYmplY3QgaXMgY29lcmNlZCB0byBhIHN0cmluZy5cbiAgICAgKlxuICAgICAqIEBuYW1lIHRvU3RyaW5nXG4gICAgICogQG1lbWJlck9mIHBsYXRmb3JtXG4gICAgICogQHJldHVybnMge3N0cmluZ30gUmV0dXJucyBgcGxhdGZvcm0uZGVzY3JpcHRpb25gIGlmIGF2YWlsYWJsZSwgZWxzZSBhbiBlbXB0eSBzdHJpbmcuXG4gICAgICovXG4gICAgZnVuY3Rpb24gdG9TdHJpbmdQbGF0Zm9ybSgpIHtcbiAgICAgIHJldHVybiB0aGlzLmRlc2NyaXB0aW9uIHx8ICcnO1xuICAgIH1cblxuICAgIC8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cblxuICAgIC8vIENvbnZlcnQgbGF5b3V0IHRvIGFuIGFycmF5IHNvIHdlIGNhbiBhZGQgZXh0cmEgZGV0YWlscy5cbiAgICBsYXlvdXQgJiYgKGxheW91dCA9IFtsYXlvdXRdKTtcblxuICAgIC8vIERldGVjdCBwcm9kdWN0IG5hbWVzIHRoYXQgY29udGFpbiB0aGVpciBtYW51ZmFjdHVyZXIncyBuYW1lLlxuICAgIGlmIChtYW51ZmFjdHVyZXIgJiYgIXByb2R1Y3QpIHtcbiAgICAgIHByb2R1Y3QgPSBnZXRQcm9kdWN0KFttYW51ZmFjdHVyZXJdKTtcbiAgICB9XG4gICAgLy8gQ2xlYW4gdXAgR29vZ2xlIFRWLlxuICAgIGlmICgoZGF0YSA9IC9cXGJHb29nbGUgVFZcXGIvLmV4ZWMocHJvZHVjdCkpKSB7XG4gICAgICBwcm9kdWN0ID0gZGF0YVswXTtcbiAgICB9XG4gICAgLy8gRGV0ZWN0IHNpbXVsYXRvcnMuXG4gICAgaWYgKC9cXGJTaW11bGF0b3JcXGIvaS50ZXN0KHVhKSkge1xuICAgICAgcHJvZHVjdCA9IChwcm9kdWN0ID8gcHJvZHVjdCArICcgJyA6ICcnKSArICdTaW11bGF0b3InO1xuICAgIH1cbiAgICAvLyBEZXRlY3QgT3BlcmEgTWluaSA4KyBydW5uaW5nIGluIFR1cmJvL1VuY29tcHJlc3NlZCBtb2RlIG9uIGlPUy5cbiAgICBpZiAobmFtZSA9PSAnT3BlcmEgTWluaScgJiYgL1xcYk9QaU9TXFxiLy50ZXN0KHVhKSkge1xuICAgICAgZGVzY3JpcHRpb24ucHVzaCgncnVubmluZyBpbiBUdXJiby9VbmNvbXByZXNzZWQgbW9kZScpO1xuICAgIH1cbiAgICAvLyBEZXRlY3QgSUUgTW9iaWxlIDExLlxuICAgIGlmIChuYW1lID09ICdJRScgJiYgL1xcYmxpa2UgaVBob25lIE9TXFxiLy50ZXN0KHVhKSkge1xuICAgICAgZGF0YSA9IHBhcnNlKHVhLnJlcGxhY2UoL2xpa2UgaVBob25lIE9TLywgJycpKTtcbiAgICAgIG1hbnVmYWN0dXJlciA9IGRhdGEubWFudWZhY3R1cmVyO1xuICAgICAgcHJvZHVjdCA9IGRhdGEucHJvZHVjdDtcbiAgICB9XG4gICAgLy8gRGV0ZWN0IGlPUy5cbiAgICBlbHNlIGlmICgvXmlQLy50ZXN0KHByb2R1Y3QpKSB7XG4gICAgICBuYW1lIHx8IChuYW1lID0gJ1NhZmFyaScpO1xuICAgICAgb3MgPSAnaU9TJyArICgoZGF0YSA9IC8gT1MgKFtcXGRfXSspL2kuZXhlYyh1YSkpXG4gICAgICAgID8gJyAnICsgZGF0YVsxXS5yZXBsYWNlKC9fL2csICcuJylcbiAgICAgICAgOiAnJyk7XG4gICAgfVxuICAgIC8vIERldGVjdCBLdWJ1bnR1LlxuICAgIGVsc2UgaWYgKG5hbWUgPT0gJ0tvbnF1ZXJvcicgJiYgIS9idW50dS9pLnRlc3Qob3MpKSB7XG4gICAgICBvcyA9ICdLdWJ1bnR1JztcbiAgICB9XG4gICAgLy8gRGV0ZWN0IEFuZHJvaWQgYnJvd3NlcnMuXG4gICAgZWxzZSBpZiAoKG1hbnVmYWN0dXJlciAmJiBtYW51ZmFjdHVyZXIgIT0gJ0dvb2dsZScgJiZcbiAgICAgICAgKCgvQ2hyb21lLy50ZXN0KG5hbWUpICYmICEvXFxiTW9iaWxlIFNhZmFyaVxcYi9pLnRlc3QodWEpKSB8fCAvXFxiVml0YVxcYi8udGVzdChwcm9kdWN0KSkpIHx8XG4gICAgICAgICgvXFxiQW5kcm9pZFxcYi8udGVzdChvcykgJiYgL15DaHJvbWUvLnRlc3QobmFtZSkgJiYgL1xcYlZlcnNpb25cXC8vaS50ZXN0KHVhKSkpIHtcbiAgICAgIG5hbWUgPSAnQW5kcm9pZCBCcm93c2VyJztcbiAgICAgIG9zID0gL1xcYkFuZHJvaWRcXGIvLnRlc3Qob3MpID8gb3MgOiAnQW5kcm9pZCc7XG4gICAgfVxuICAgIC8vIERldGVjdCBTaWxrIGRlc2t0b3AvYWNjZWxlcmF0ZWQgbW9kZXMuXG4gICAgZWxzZSBpZiAobmFtZSA9PSAnU2lsaycpIHtcbiAgICAgIGlmICghL1xcYk1vYmkvaS50ZXN0KHVhKSkge1xuICAgICAgICBvcyA9ICdBbmRyb2lkJztcbiAgICAgICAgZGVzY3JpcHRpb24udW5zaGlmdCgnZGVza3RvcCBtb2RlJyk7XG4gICAgICB9XG4gICAgICBpZiAoL0FjY2VsZXJhdGVkICo9ICp0cnVlL2kudGVzdCh1YSkpIHtcbiAgICAgICAgZGVzY3JpcHRpb24udW5zaGlmdCgnYWNjZWxlcmF0ZWQnKTtcbiAgICAgIH1cbiAgICB9XG4gICAgLy8gRGV0ZWN0IFBhbGVNb29uIGlkZW50aWZ5aW5nIGFzIEZpcmVmb3guXG4gICAgZWxzZSBpZiAobmFtZSA9PSAnUGFsZU1vb24nICYmIChkYXRhID0gL1xcYkZpcmVmb3hcXC8oW1xcZC5dKylcXGIvLmV4ZWModWEpKSkge1xuICAgICAgZGVzY3JpcHRpb24ucHVzaCgnaWRlbnRpZnlpbmcgYXMgRmlyZWZveCAnICsgZGF0YVsxXSk7XG4gICAgfVxuICAgIC8vIERldGVjdCBGaXJlZm94IE9TIGFuZCBwcm9kdWN0cyBydW5uaW5nIEZpcmVmb3guXG4gICAgZWxzZSBpZiAobmFtZSA9PSAnRmlyZWZveCcgJiYgKGRhdGEgPSAvXFxiKE1vYmlsZXxUYWJsZXR8VFYpXFxiL2kuZXhlYyh1YSkpKSB7XG4gICAgICBvcyB8fCAob3MgPSAnRmlyZWZveCBPUycpO1xuICAgICAgcHJvZHVjdCB8fCAocHJvZHVjdCA9IGRhdGFbMV0pO1xuICAgIH1cbiAgICAvLyBEZXRlY3QgZmFsc2UgcG9zaXRpdmVzIGZvciBGaXJlZm94L1NhZmFyaS5cbiAgICBlbHNlIGlmICghbmFtZSB8fCAoZGF0YSA9ICEvXFxiTWluZWZpZWxkXFxiL2kudGVzdCh1YSkgJiYgL1xcYig/OkZpcmVmb3h8U2FmYXJpKVxcYi8uZXhlYyhuYW1lKSkpIHtcbiAgICAgIC8vIEVzY2FwZSB0aGUgYC9gIGZvciBGaXJlZm94IDEuXG4gICAgICBpZiAobmFtZSAmJiAhcHJvZHVjdCAmJiAvW1xcLyxdfF5bXihdKz9cXCkvLnRlc3QodWEuc2xpY2UodWEuaW5kZXhPZihkYXRhICsgJy8nKSArIDgpKSkge1xuICAgICAgICAvLyBDbGVhciBuYW1lIG9mIGZhbHNlIHBvc2l0aXZlcy5cbiAgICAgICAgbmFtZSA9IG51bGw7XG4gICAgICB9XG4gICAgICAvLyBSZWFzc2lnbiBhIGdlbmVyaWMgbmFtZS5cbiAgICAgIGlmICgoZGF0YSA9IHByb2R1Y3QgfHwgbWFudWZhY3R1cmVyIHx8IG9zKSAmJlxuICAgICAgICAgIChwcm9kdWN0IHx8IG1hbnVmYWN0dXJlciB8fCAvXFxiKD86QW5kcm9pZHxTeW1iaWFuIE9TfFRhYmxldCBPU3x3ZWJPUylcXGIvLnRlc3Qob3MpKSkge1xuICAgICAgICBuYW1lID0gL1thLXpdKyg/OiBIYXQpPy9pLmV4ZWMoL1xcYkFuZHJvaWRcXGIvLnRlc3Qob3MpID8gb3MgOiBkYXRhKSArICcgQnJvd3Nlcic7XG4gICAgICB9XG4gICAgfVxuICAgIC8vIEFkZCBDaHJvbWUgdmVyc2lvbiB0byBkZXNjcmlwdGlvbiBmb3IgRWxlY3Ryb24uXG4gICAgZWxzZSBpZiAobmFtZSA9PSAnRWxlY3Ryb24nICYmIChkYXRhID0gKC9cXGJDaHJvbWVcXC8oW1xcZC5dKylcXGIvLmV4ZWModWEpIHx8IDApWzFdKSkge1xuICAgICAgZGVzY3JpcHRpb24ucHVzaCgnQ2hyb21pdW0gJyArIGRhdGEpO1xuICAgIH1cbiAgICAvLyBEZXRlY3Qgbm9uLU9wZXJhIChQcmVzdG8tYmFzZWQpIHZlcnNpb25zIChvcmRlciBpcyBpbXBvcnRhbnQpLlxuICAgIGlmICghdmVyc2lvbikge1xuICAgICAgdmVyc2lvbiA9IGdldFZlcnNpb24oW1xuICAgICAgICAnKD86Q2xvdWQ5fENyaU9TfENyTW98RWRnZXxGeGlPU3xJRU1vYmlsZXxJcm9ufE9wZXJhID9NaW5pfE9QaU9TfE9QUnxSYXZlbnxTYW1zdW5nQnJvd3NlcnxTaWxrKD8hL1tcXFxcZC5dKyQpKScsXG4gICAgICAgICdWZXJzaW9uJyxcbiAgICAgICAgcXVhbGlmeShuYW1lKSxcbiAgICAgICAgJyg/OkZpcmVmb3h8TWluZWZpZWxkfE5ldEZyb250KSdcbiAgICAgIF0pO1xuICAgIH1cbiAgICAvLyBEZXRlY3Qgc3R1YmJvcm4gbGF5b3V0IGVuZ2luZXMuXG4gICAgaWYgKChkYXRhID1cbiAgICAgICAgICBsYXlvdXQgPT0gJ2lDYWInICYmIHBhcnNlRmxvYXQodmVyc2lvbikgPiAzICYmICdXZWJLaXQnIHx8XG4gICAgICAgICAgL1xcYk9wZXJhXFxiLy50ZXN0KG5hbWUpICYmICgvXFxiT1BSXFxiLy50ZXN0KHVhKSA/ICdCbGluaycgOiAnUHJlc3RvJykgfHxcbiAgICAgICAgICAvXFxiKD86TWlkb3JpfE5vb2t8U2FmYXJpKVxcYi9pLnRlc3QodWEpICYmICEvXig/OlRyaWRlbnR8RWRnZUhUTUwpJC8udGVzdChsYXlvdXQpICYmICdXZWJLaXQnIHx8XG4gICAgICAgICAgIWxheW91dCAmJiAvXFxiTVNJRVxcYi9pLnRlc3QodWEpICYmIChvcyA9PSAnTWFjIE9TJyA/ICdUYXNtYW4nIDogJ1RyaWRlbnQnKSB8fFxuICAgICAgICAgIGxheW91dCA9PSAnV2ViS2l0JyAmJiAvXFxiUGxheVN0YXRpb25cXGIoPyEgVml0YVxcYikvaS50ZXN0KG5hbWUpICYmICdOZXRGcm9udCdcbiAgICAgICAgKSkge1xuICAgICAgbGF5b3V0ID0gW2RhdGFdO1xuICAgIH1cbiAgICAvLyBEZXRlY3QgV2luZG93cyBQaG9uZSA3IGRlc2t0b3AgbW9kZS5cbiAgICBpZiAobmFtZSA9PSAnSUUnICYmIChkYXRhID0gKC87ICooPzpYQkxXUHxadW5lV1ApKFxcZCspL2kuZXhlYyh1YSkgfHwgMClbMV0pKSB7XG4gICAgICBuYW1lICs9ICcgTW9iaWxlJztcbiAgICAgIG9zID0gJ1dpbmRvd3MgUGhvbmUgJyArICgvXFwrJC8udGVzdChkYXRhKSA/IGRhdGEgOiBkYXRhICsgJy54Jyk7XG4gICAgICBkZXNjcmlwdGlvbi51bnNoaWZ0KCdkZXNrdG9wIG1vZGUnKTtcbiAgICB9XG4gICAgLy8gRGV0ZWN0IFdpbmRvd3MgUGhvbmUgOC54IGRlc2t0b3AgbW9kZS5cbiAgICBlbHNlIGlmICgvXFxiV1BEZXNrdG9wXFxiL2kudGVzdCh1YSkpIHtcbiAgICAgIG5hbWUgPSAnSUUgTW9iaWxlJztcbiAgICAgIG9zID0gJ1dpbmRvd3MgUGhvbmUgOC54JztcbiAgICAgIGRlc2NyaXB0aW9uLnVuc2hpZnQoJ2Rlc2t0b3AgbW9kZScpO1xuICAgICAgdmVyc2lvbiB8fCAodmVyc2lvbiA9ICgvXFxicnY6KFtcXGQuXSspLy5leGVjKHVhKSB8fCAwKVsxXSk7XG4gICAgfVxuICAgIC8vIERldGVjdCBJRSAxMSBpZGVudGlmeWluZyBhcyBvdGhlciBicm93c2Vycy5cbiAgICBlbHNlIGlmIChuYW1lICE9ICdJRScgJiYgbGF5b3V0ID09ICdUcmlkZW50JyAmJiAoZGF0YSA9IC9cXGJydjooW1xcZC5dKykvLmV4ZWModWEpKSkge1xuICAgICAgaWYgKG5hbWUpIHtcbiAgICAgICAgZGVzY3JpcHRpb24ucHVzaCgnaWRlbnRpZnlpbmcgYXMgJyArIG5hbWUgKyAodmVyc2lvbiA/ICcgJyArIHZlcnNpb24gOiAnJykpO1xuICAgICAgfVxuICAgICAgbmFtZSA9ICdJRSc7XG4gICAgICB2ZXJzaW9uID0gZGF0YVsxXTtcbiAgICB9XG4gICAgLy8gTGV2ZXJhZ2UgZW52aXJvbm1lbnQgZmVhdHVyZXMuXG4gICAgaWYgKHVzZUZlYXR1cmVzKSB7XG4gICAgICAvLyBEZXRlY3Qgc2VydmVyLXNpZGUgZW52aXJvbm1lbnRzLlxuICAgICAgLy8gUmhpbm8gaGFzIGEgZ2xvYmFsIGZ1bmN0aW9uIHdoaWxlIG90aGVycyBoYXZlIGEgZ2xvYmFsIG9iamVjdC5cbiAgICAgIGlmIChpc0hvc3RUeXBlKGNvbnRleHQsICdnbG9iYWwnKSkge1xuICAgICAgICBpZiAoamF2YSkge1xuICAgICAgICAgIGRhdGEgPSBqYXZhLmxhbmcuU3lzdGVtO1xuICAgICAgICAgIGFyY2ggPSBkYXRhLmdldFByb3BlcnR5KCdvcy5hcmNoJyk7XG4gICAgICAgICAgb3MgPSBvcyB8fCBkYXRhLmdldFByb3BlcnR5KCdvcy5uYW1lJykgKyAnICcgKyBkYXRhLmdldFByb3BlcnR5KCdvcy52ZXJzaW9uJyk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHJoaW5vKSB7XG4gICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIHZlcnNpb24gPSBjb250ZXh0LnJlcXVpcmUoJ3JpbmdvL2VuZ2luZScpLnZlcnNpb24uam9pbignLicpO1xuICAgICAgICAgICAgbmFtZSA9ICdSaW5nb0pTJztcbiAgICAgICAgICB9IGNhdGNoKGUpIHtcbiAgICAgICAgICAgIGlmICgoZGF0YSA9IGNvbnRleHQuc3lzdGVtKSAmJiBkYXRhLmdsb2JhbC5zeXN0ZW0gPT0gY29udGV4dC5zeXN0ZW0pIHtcbiAgICAgICAgICAgICAgbmFtZSA9ICdOYXJ3aGFsJztcbiAgICAgICAgICAgICAgb3MgfHwgKG9zID0gZGF0YVswXS5vcyB8fCBudWxsKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKCFuYW1lKSB7XG4gICAgICAgICAgICBuYW1lID0gJ1JoaW5vJztcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAoXG4gICAgICAgICAgdHlwZW9mIGNvbnRleHQucHJvY2VzcyA9PSAnb2JqZWN0JyAmJiAhY29udGV4dC5wcm9jZXNzLmJyb3dzZXIgJiZcbiAgICAgICAgICAoZGF0YSA9IGNvbnRleHQucHJvY2VzcylcbiAgICAgICAgKSB7XG4gICAgICAgICAgaWYgKHR5cGVvZiBkYXRhLnZlcnNpb25zID09ICdvYmplY3QnKSB7XG4gICAgICAgICAgICBpZiAodHlwZW9mIGRhdGEudmVyc2lvbnMuZWxlY3Ryb24gPT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgICAgZGVzY3JpcHRpb24ucHVzaCgnTm9kZSAnICsgZGF0YS52ZXJzaW9ucy5ub2RlKTtcbiAgICAgICAgICAgICAgbmFtZSA9ICdFbGVjdHJvbic7XG4gICAgICAgICAgICAgIHZlcnNpb24gPSBkYXRhLnZlcnNpb25zLmVsZWN0cm9uO1xuICAgICAgICAgICAgfSBlbHNlIGlmICh0eXBlb2YgZGF0YS52ZXJzaW9ucy5udyA9PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgICBkZXNjcmlwdGlvbi5wdXNoKCdDaHJvbWl1bSAnICsgdmVyc2lvbiwgJ05vZGUgJyArIGRhdGEudmVyc2lvbnMubm9kZSk7XG4gICAgICAgICAgICAgIG5hbWUgPSAnTlcuanMnO1xuICAgICAgICAgICAgICB2ZXJzaW9uID0gZGF0YS52ZXJzaW9ucy5udztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKCFuYW1lKSB7XG4gICAgICAgICAgICBuYW1lID0gJ05vZGUuanMnO1xuICAgICAgICAgICAgYXJjaCA9IGRhdGEuYXJjaDtcbiAgICAgICAgICAgIG9zID0gZGF0YS5wbGF0Zm9ybTtcbiAgICAgICAgICAgIHZlcnNpb24gPSAvW1xcZC5dKy8uZXhlYyhkYXRhLnZlcnNpb24pO1xuICAgICAgICAgICAgdmVyc2lvbiA9IHZlcnNpb24gPyB2ZXJzaW9uWzBdIDogbnVsbDtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIC8vIERldGVjdCBBZG9iZSBBSVIuXG4gICAgICBlbHNlIGlmIChnZXRDbGFzc09mKChkYXRhID0gY29udGV4dC5ydW50aW1lKSkgPT0gYWlyUnVudGltZUNsYXNzKSB7XG4gICAgICAgIG5hbWUgPSAnQWRvYmUgQUlSJztcbiAgICAgICAgb3MgPSBkYXRhLmZsYXNoLnN5c3RlbS5DYXBhYmlsaXRpZXMub3M7XG4gICAgICB9XG4gICAgICAvLyBEZXRlY3QgUGhhbnRvbUpTLlxuICAgICAgZWxzZSBpZiAoZ2V0Q2xhc3NPZigoZGF0YSA9IGNvbnRleHQucGhhbnRvbSkpID09IHBoYW50b21DbGFzcykge1xuICAgICAgICBuYW1lID0gJ1BoYW50b21KUyc7XG4gICAgICAgIHZlcnNpb24gPSAoZGF0YSA9IGRhdGEudmVyc2lvbiB8fCBudWxsKSAmJiAoZGF0YS5tYWpvciArICcuJyArIGRhdGEubWlub3IgKyAnLicgKyBkYXRhLnBhdGNoKTtcbiAgICAgIH1cbiAgICAgIC8vIERldGVjdCBJRSBjb21wYXRpYmlsaXR5IG1vZGVzLlxuICAgICAgZWxzZSBpZiAodHlwZW9mIGRvYy5kb2N1bWVudE1vZGUgPT0gJ251bWJlcicgJiYgKGRhdGEgPSAvXFxiVHJpZGVudFxcLyhcXGQrKS9pLmV4ZWModWEpKSkge1xuICAgICAgICAvLyBXZSdyZSBpbiBjb21wYXRpYmlsaXR5IG1vZGUgd2hlbiB0aGUgVHJpZGVudCB2ZXJzaW9uICsgNCBkb2Vzbid0XG4gICAgICAgIC8vIGVxdWFsIHRoZSBkb2N1bWVudCBtb2RlLlxuICAgICAgICB2ZXJzaW9uID0gW3ZlcnNpb24sIGRvYy5kb2N1bWVudE1vZGVdO1xuICAgICAgICBpZiAoKGRhdGEgPSArZGF0YVsxXSArIDQpICE9IHZlcnNpb25bMV0pIHtcbiAgICAgICAgICBkZXNjcmlwdGlvbi5wdXNoKCdJRSAnICsgdmVyc2lvblsxXSArICcgbW9kZScpO1xuICAgICAgICAgIGxheW91dCAmJiAobGF5b3V0WzFdID0gJycpO1xuICAgICAgICAgIHZlcnNpb25bMV0gPSBkYXRhO1xuICAgICAgICB9XG4gICAgICAgIHZlcnNpb24gPSBuYW1lID09ICdJRScgPyBTdHJpbmcodmVyc2lvblsxXS50b0ZpeGVkKDEpKSA6IHZlcnNpb25bMF07XG4gICAgICB9XG4gICAgICAvLyBEZXRlY3QgSUUgMTEgbWFza2luZyBhcyBvdGhlciBicm93c2Vycy5cbiAgICAgIGVsc2UgaWYgKHR5cGVvZiBkb2MuZG9jdW1lbnRNb2RlID09ICdudW1iZXInICYmIC9eKD86Q2hyb21lfEZpcmVmb3gpXFxiLy50ZXN0KG5hbWUpKSB7XG4gICAgICAgIGRlc2NyaXB0aW9uLnB1c2goJ21hc2tpbmcgYXMgJyArIG5hbWUgKyAnICcgKyB2ZXJzaW9uKTtcbiAgICAgICAgbmFtZSA9ICdJRSc7XG4gICAgICAgIHZlcnNpb24gPSAnMTEuMCc7XG4gICAgICAgIGxheW91dCA9IFsnVHJpZGVudCddO1xuICAgICAgICBvcyA9ICdXaW5kb3dzJztcbiAgICAgIH1cbiAgICAgIG9zID0gb3MgJiYgZm9ybWF0KG9zKTtcbiAgICB9XG4gICAgLy8gRGV0ZWN0IHByZXJlbGVhc2UgcGhhc2VzLlxuICAgIGlmICh2ZXJzaW9uICYmIChkYXRhID1cbiAgICAgICAgICAvKD86W2FiXXxkcHxwcmV8W2FiXVxcZCtwcmUpKD86XFxkK1xcKz8pPyQvaS5leGVjKHZlcnNpb24pIHx8XG4gICAgICAgICAgLyg/OmFscGhhfGJldGEpKD86ID9cXGQpPy9pLmV4ZWModWEgKyAnOycgKyAodXNlRmVhdHVyZXMgJiYgbmF2LmFwcE1pbm9yVmVyc2lvbikpIHx8XG4gICAgICAgICAgL1xcYk1pbmVmaWVsZFxcYi9pLnRlc3QodWEpICYmICdhJ1xuICAgICAgICApKSB7XG4gICAgICBwcmVyZWxlYXNlID0gL2IvaS50ZXN0KGRhdGEpID8gJ2JldGEnIDogJ2FscGhhJztcbiAgICAgIHZlcnNpb24gPSB2ZXJzaW9uLnJlcGxhY2UoUmVnRXhwKGRhdGEgKyAnXFxcXCs/JCcpLCAnJykgK1xuICAgICAgICAocHJlcmVsZWFzZSA9PSAnYmV0YScgPyBiZXRhIDogYWxwaGEpICsgKC9cXGQrXFwrPy8uZXhlYyhkYXRhKSB8fCAnJyk7XG4gICAgfVxuICAgIC8vIERldGVjdCBGaXJlZm94IE1vYmlsZS5cbiAgICBpZiAobmFtZSA9PSAnRmVubmVjJyB8fCBuYW1lID09ICdGaXJlZm94JyAmJiAvXFxiKD86QW5kcm9pZHxGaXJlZm94IE9TKVxcYi8udGVzdChvcykpIHtcbiAgICAgIG5hbWUgPSAnRmlyZWZveCBNb2JpbGUnO1xuICAgIH1cbiAgICAvLyBPYnNjdXJlIE1heHRob24ncyB1bnJlbGlhYmxlIHZlcnNpb24uXG4gICAgZWxzZSBpZiAobmFtZSA9PSAnTWF4dGhvbicgJiYgdmVyc2lvbikge1xuICAgICAgdmVyc2lvbiA9IHZlcnNpb24ucmVwbGFjZSgvXFwuW1xcZC5dKy8sICcueCcpO1xuICAgIH1cbiAgICAvLyBEZXRlY3QgWGJveCAzNjAgYW5kIFhib3ggT25lLlxuICAgIGVsc2UgaWYgKC9cXGJYYm94XFxiL2kudGVzdChwcm9kdWN0KSkge1xuICAgICAgaWYgKHByb2R1Y3QgPT0gJ1hib3ggMzYwJykge1xuICAgICAgICBvcyA9IG51bGw7XG4gICAgICB9XG4gICAgICBpZiAocHJvZHVjdCA9PSAnWGJveCAzNjAnICYmIC9cXGJJRU1vYmlsZVxcYi8udGVzdCh1YSkpIHtcbiAgICAgICAgZGVzY3JpcHRpb24udW5zaGlmdCgnbW9iaWxlIG1vZGUnKTtcbiAgICAgIH1cbiAgICB9XG4gICAgLy8gQWRkIG1vYmlsZSBwb3N0Zml4LlxuICAgIGVsc2UgaWYgKCgvXig/OkNocm9tZXxJRXxPcGVyYSkkLy50ZXN0KG5hbWUpIHx8IG5hbWUgJiYgIXByb2R1Y3QgJiYgIS9Ccm93c2VyfE1vYmkvLnRlc3QobmFtZSkpICYmXG4gICAgICAgIChvcyA9PSAnV2luZG93cyBDRScgfHwgL01vYmkvaS50ZXN0KHVhKSkpIHtcbiAgICAgIG5hbWUgKz0gJyBNb2JpbGUnO1xuICAgIH1cbiAgICAvLyBEZXRlY3QgSUUgcGxhdGZvcm0gcHJldmlldy5cbiAgICBlbHNlIGlmIChuYW1lID09ICdJRScgJiYgdXNlRmVhdHVyZXMpIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIGlmIChjb250ZXh0LmV4dGVybmFsID09PSBudWxsKSB7XG4gICAgICAgICAgZGVzY3JpcHRpb24udW5zaGlmdCgncGxhdGZvcm0gcHJldmlldycpO1xuICAgICAgICB9XG4gICAgICB9IGNhdGNoKGUpIHtcbiAgICAgICAgZGVzY3JpcHRpb24udW5zaGlmdCgnZW1iZWRkZWQnKTtcbiAgICAgIH1cbiAgICB9XG4gICAgLy8gRGV0ZWN0IEJsYWNrQmVycnkgT1MgdmVyc2lvbi5cbiAgICAvLyBodHRwOi8vZG9jcy5ibGFja2JlcnJ5LmNvbS9lbi9kZXZlbG9wZXJzL2RlbGl2ZXJhYmxlcy8xODE2OS9IVFRQX2hlYWRlcnNfc2VudF9ieV9CQl9Ccm93c2VyXzEyMzQ5MTFfMTEuanNwXG4gICAgZWxzZSBpZiAoKC9cXGJCbGFja0JlcnJ5XFxiLy50ZXN0KHByb2R1Y3QpIHx8IC9cXGJCQjEwXFxiLy50ZXN0KHVhKSkgJiYgKGRhdGEgPVxuICAgICAgICAgIChSZWdFeHAocHJvZHVjdC5yZXBsYWNlKC8gKy9nLCAnIConKSArICcvKFsuXFxcXGRdKyknLCAnaScpLmV4ZWModWEpIHx8IDApWzFdIHx8XG4gICAgICAgICAgdmVyc2lvblxuICAgICAgICApKSB7XG4gICAgICBkYXRhID0gW2RhdGEsIC9CQjEwLy50ZXN0KHVhKV07XG4gICAgICBvcyA9IChkYXRhWzFdID8gKHByb2R1Y3QgPSBudWxsLCBtYW51ZmFjdHVyZXIgPSAnQmxhY2tCZXJyeScpIDogJ0RldmljZSBTb2Z0d2FyZScpICsgJyAnICsgZGF0YVswXTtcbiAgICAgIHZlcnNpb24gPSBudWxsO1xuICAgIH1cbiAgICAvLyBEZXRlY3QgT3BlcmEgaWRlbnRpZnlpbmcvbWFza2luZyBpdHNlbGYgYXMgYW5vdGhlciBicm93c2VyLlxuICAgIC8vIGh0dHA6Ly93d3cub3BlcmEuY29tL3N1cHBvcnQva2Ivdmlldy84NDMvXG4gICAgZWxzZSBpZiAodGhpcyAhPSBmb3JPd24gJiYgcHJvZHVjdCAhPSAnV2lpJyAmJiAoXG4gICAgICAgICAgKHVzZUZlYXR1cmVzICYmIG9wZXJhKSB8fFxuICAgICAgICAgICgvT3BlcmEvLnRlc3QobmFtZSkgJiYgL1xcYig/Ok1TSUV8RmlyZWZveClcXGIvaS50ZXN0KHVhKSkgfHxcbiAgICAgICAgICAobmFtZSA9PSAnRmlyZWZveCcgJiYgL1xcYk9TIFggKD86XFxkK1xcLil7Mix9Ly50ZXN0KG9zKSkgfHxcbiAgICAgICAgICAobmFtZSA9PSAnSUUnICYmIChcbiAgICAgICAgICAgIChvcyAmJiAhL15XaW4vLnRlc3Qob3MpICYmIHZlcnNpb24gPiA1LjUpIHx8XG4gICAgICAgICAgICAvXFxiV2luZG93cyBYUFxcYi8udGVzdChvcykgJiYgdmVyc2lvbiA+IDggfHxcbiAgICAgICAgICAgIHZlcnNpb24gPT0gOCAmJiAhL1xcYlRyaWRlbnRcXGIvLnRlc3QodWEpXG4gICAgICAgICAgKSlcbiAgICAgICAgKSAmJiAhcmVPcGVyYS50ZXN0KChkYXRhID0gcGFyc2UuY2FsbChmb3JPd24sIHVhLnJlcGxhY2UocmVPcGVyYSwgJycpICsgJzsnKSkpICYmIGRhdGEubmFtZSkge1xuICAgICAgLy8gV2hlbiBcImlkZW50aWZ5aW5nXCIsIHRoZSBVQSBjb250YWlucyBib3RoIE9wZXJhIGFuZCB0aGUgb3RoZXIgYnJvd3NlcidzIG5hbWUuXG4gICAgICBkYXRhID0gJ2luZyBhcyAnICsgZGF0YS5uYW1lICsgKChkYXRhID0gZGF0YS52ZXJzaW9uKSA/ICcgJyArIGRhdGEgOiAnJyk7XG4gICAgICBpZiAocmVPcGVyYS50ZXN0KG5hbWUpKSB7XG4gICAgICAgIGlmICgvXFxiSUVcXGIvLnRlc3QoZGF0YSkgJiYgb3MgPT0gJ01hYyBPUycpIHtcbiAgICAgICAgICBvcyA9IG51bGw7XG4gICAgICAgIH1cbiAgICAgICAgZGF0YSA9ICdpZGVudGlmeScgKyBkYXRhO1xuICAgICAgfVxuICAgICAgLy8gV2hlbiBcIm1hc2tpbmdcIiwgdGhlIFVBIGNvbnRhaW5zIG9ubHkgdGhlIG90aGVyIGJyb3dzZXIncyBuYW1lLlxuICAgICAgZWxzZSB7XG4gICAgICAgIGRhdGEgPSAnbWFzaycgKyBkYXRhO1xuICAgICAgICBpZiAob3BlcmFDbGFzcykge1xuICAgICAgICAgIG5hbWUgPSBmb3JtYXQob3BlcmFDbGFzcy5yZXBsYWNlKC8oW2Etel0pKFtBLVpdKS9nLCAnJDEgJDInKSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgbmFtZSA9ICdPcGVyYSc7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKC9cXGJJRVxcYi8udGVzdChkYXRhKSkge1xuICAgICAgICAgIG9zID0gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIXVzZUZlYXR1cmVzKSB7XG4gICAgICAgICAgdmVyc2lvbiA9IG51bGw7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGxheW91dCA9IFsnUHJlc3RvJ107XG4gICAgICBkZXNjcmlwdGlvbi5wdXNoKGRhdGEpO1xuICAgIH1cbiAgICAvLyBEZXRlY3QgV2ViS2l0IE5pZ2h0bHkgYW5kIGFwcHJveGltYXRlIENocm9tZS9TYWZhcmkgdmVyc2lvbnMuXG4gICAgaWYgKChkYXRhID0gKC9cXGJBcHBsZVdlYktpdFxcLyhbXFxkLl0rXFwrPykvaS5leGVjKHVhKSB8fCAwKVsxXSkpIHtcbiAgICAgIC8vIENvcnJlY3QgYnVpbGQgbnVtYmVyIGZvciBudW1lcmljIGNvbXBhcmlzb24uXG4gICAgICAvLyAoZS5nLiBcIjUzMi41XCIgYmVjb21lcyBcIjUzMi4wNVwiKVxuICAgICAgZGF0YSA9IFtwYXJzZUZsb2F0KGRhdGEucmVwbGFjZSgvXFwuKFxcZCkkLywgJy4wJDEnKSksIGRhdGFdO1xuICAgICAgLy8gTmlnaHRseSBidWlsZHMgYXJlIHBvc3RmaXhlZCB3aXRoIGEgXCIrXCIuXG4gICAgICBpZiAobmFtZSA9PSAnU2FmYXJpJyAmJiBkYXRhWzFdLnNsaWNlKC0xKSA9PSAnKycpIHtcbiAgICAgICAgbmFtZSA9ICdXZWJLaXQgTmlnaHRseSc7XG4gICAgICAgIHByZXJlbGVhc2UgPSAnYWxwaGEnO1xuICAgICAgICB2ZXJzaW9uID0gZGF0YVsxXS5zbGljZSgwLCAtMSk7XG4gICAgICB9XG4gICAgICAvLyBDbGVhciBpbmNvcnJlY3QgYnJvd3NlciB2ZXJzaW9ucy5cbiAgICAgIGVsc2UgaWYgKHZlcnNpb24gPT0gZGF0YVsxXSB8fFxuICAgICAgICAgIHZlcnNpb24gPT0gKGRhdGFbMl0gPSAoL1xcYlNhZmFyaVxcLyhbXFxkLl0rXFwrPykvaS5leGVjKHVhKSB8fCAwKVsxXSkpIHtcbiAgICAgICAgdmVyc2lvbiA9IG51bGw7XG4gICAgICB9XG4gICAgICAvLyBVc2UgdGhlIGZ1bGwgQ2hyb21lIHZlcnNpb24gd2hlbiBhdmFpbGFibGUuXG4gICAgICBkYXRhWzFdID0gKC9cXGJDaHJvbWVcXC8oW1xcZC5dKykvaS5leGVjKHVhKSB8fCAwKVsxXTtcbiAgICAgIC8vIERldGVjdCBCbGluayBsYXlvdXQgZW5naW5lLlxuICAgICAgaWYgKGRhdGFbMF0gPT0gNTM3LjM2ICYmIGRhdGFbMl0gPT0gNTM3LjM2ICYmIHBhcnNlRmxvYXQoZGF0YVsxXSkgPj0gMjggJiYgbGF5b3V0ID09ICdXZWJLaXQnKSB7XG4gICAgICAgIGxheW91dCA9IFsnQmxpbmsnXTtcbiAgICAgIH1cbiAgICAgIC8vIERldGVjdCBKYXZhU2NyaXB0Q29yZS5cbiAgICAgIC8vIGh0dHA6Ly9zdGFja292ZXJmbG93LmNvbS9xdWVzdGlvbnMvNjc2ODQ3NC9ob3ctY2FuLWktZGV0ZWN0LXdoaWNoLWphdmFzY3JpcHQtZW5naW5lLXY4LW9yLWpzYy1pcy11c2VkLWF0LXJ1bnRpbWUtaW4tYW5kcm9pXG4gICAgICBpZiAoIXVzZUZlYXR1cmVzIHx8ICghbGlrZUNocm9tZSAmJiAhZGF0YVsxXSkpIHtcbiAgICAgICAgbGF5b3V0ICYmIChsYXlvdXRbMV0gPSAnbGlrZSBTYWZhcmknKTtcbiAgICAgICAgZGF0YSA9IChkYXRhID0gZGF0YVswXSwgZGF0YSA8IDQwMCA/IDEgOiBkYXRhIDwgNTAwID8gMiA6IGRhdGEgPCA1MjYgPyAzIDogZGF0YSA8IDUzMyA/IDQgOiBkYXRhIDwgNTM0ID8gJzQrJyA6IGRhdGEgPCA1MzUgPyA1IDogZGF0YSA8IDUzNyA/IDYgOiBkYXRhIDwgNTM4ID8gNyA6IGRhdGEgPCA2MDEgPyA4IDogJzgnKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGxheW91dCAmJiAobGF5b3V0WzFdID0gJ2xpa2UgQ2hyb21lJyk7XG4gICAgICAgIGRhdGEgPSBkYXRhWzFdIHx8IChkYXRhID0gZGF0YVswXSwgZGF0YSA8IDUzMCA/IDEgOiBkYXRhIDwgNTMyID8gMiA6IGRhdGEgPCA1MzIuMDUgPyAzIDogZGF0YSA8IDUzMyA/IDQgOiBkYXRhIDwgNTM0LjAzID8gNSA6IGRhdGEgPCA1MzQuMDcgPyA2IDogZGF0YSA8IDUzNC4xMCA/IDcgOiBkYXRhIDwgNTM0LjEzID8gOCA6IGRhdGEgPCA1MzQuMTYgPyA5IDogZGF0YSA8IDUzNC4yNCA/IDEwIDogZGF0YSA8IDUzNC4zMCA/IDExIDogZGF0YSA8IDUzNS4wMSA/IDEyIDogZGF0YSA8IDUzNS4wMiA/ICcxMysnIDogZGF0YSA8IDUzNS4wNyA/IDE1IDogZGF0YSA8IDUzNS4xMSA/IDE2IDogZGF0YSA8IDUzNS4xOSA/IDE3IDogZGF0YSA8IDUzNi4wNSA/IDE4IDogZGF0YSA8IDUzNi4xMCA/IDE5IDogZGF0YSA8IDUzNy4wMSA/IDIwIDogZGF0YSA8IDUzNy4xMSA/ICcyMSsnIDogZGF0YSA8IDUzNy4xMyA/IDIzIDogZGF0YSA8IDUzNy4xOCA/IDI0IDogZGF0YSA8IDUzNy4yNCA/IDI1IDogZGF0YSA8IDUzNy4zNiA/IDI2IDogbGF5b3V0ICE9ICdCbGluaycgPyAnMjcnIDogJzI4Jyk7XG4gICAgICB9XG4gICAgICAvLyBBZGQgdGhlIHBvc3RmaXggb2YgXCIueFwiIG9yIFwiK1wiIGZvciBhcHByb3hpbWF0ZSB2ZXJzaW9ucy5cbiAgICAgIGxheW91dCAmJiAobGF5b3V0WzFdICs9ICcgJyArIChkYXRhICs9IHR5cGVvZiBkYXRhID09ICdudW1iZXInID8gJy54JyA6IC9bLitdLy50ZXN0KGRhdGEpID8gJycgOiAnKycpKTtcbiAgICAgIC8vIE9ic2N1cmUgdmVyc2lvbiBmb3Igc29tZSBTYWZhcmkgMS0yIHJlbGVhc2VzLlxuICAgICAgaWYgKG5hbWUgPT0gJ1NhZmFyaScgJiYgKCF2ZXJzaW9uIHx8IHBhcnNlSW50KHZlcnNpb24pID4gNDUpKSB7XG4gICAgICAgIHZlcnNpb24gPSBkYXRhO1xuICAgICAgfVxuICAgIH1cbiAgICAvLyBEZXRlY3QgT3BlcmEgZGVza3RvcCBtb2Rlcy5cbiAgICBpZiAobmFtZSA9PSAnT3BlcmEnICYmICAoZGF0YSA9IC9cXGJ6Ym92fHp2YXYkLy5leGVjKG9zKSkpIHtcbiAgICAgIG5hbWUgKz0gJyAnO1xuICAgICAgZGVzY3JpcHRpb24udW5zaGlmdCgnZGVza3RvcCBtb2RlJyk7XG4gICAgICBpZiAoZGF0YSA9PSAnenZhdicpIHtcbiAgICAgICAgbmFtZSArPSAnTWluaSc7XG4gICAgICAgIHZlcnNpb24gPSBudWxsO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbmFtZSArPSAnTW9iaWxlJztcbiAgICAgIH1cbiAgICAgIG9zID0gb3MucmVwbGFjZShSZWdFeHAoJyAqJyArIGRhdGEgKyAnJCcpLCAnJyk7XG4gICAgfVxuICAgIC8vIERldGVjdCBDaHJvbWUgZGVza3RvcCBtb2RlLlxuICAgIGVsc2UgaWYgKG5hbWUgPT0gJ1NhZmFyaScgJiYgL1xcYkNocm9tZVxcYi8uZXhlYyhsYXlvdXQgJiYgbGF5b3V0WzFdKSkge1xuICAgICAgZGVzY3JpcHRpb24udW5zaGlmdCgnZGVza3RvcCBtb2RlJyk7XG4gICAgICBuYW1lID0gJ0Nocm9tZSBNb2JpbGUnO1xuICAgICAgdmVyc2lvbiA9IG51bGw7XG5cbiAgICAgIGlmICgvXFxiT1MgWFxcYi8udGVzdChvcykpIHtcbiAgICAgICAgbWFudWZhY3R1cmVyID0gJ0FwcGxlJztcbiAgICAgICAgb3MgPSAnaU9TIDQuMysnO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgb3MgPSBudWxsO1xuICAgICAgfVxuICAgIH1cbiAgICAvLyBTdHJpcCBpbmNvcnJlY3QgT1MgdmVyc2lvbnMuXG4gICAgaWYgKHZlcnNpb24gJiYgdmVyc2lvbi5pbmRleE9mKChkYXRhID0gL1tcXGQuXSskLy5leGVjKG9zKSkpID09IDAgJiZcbiAgICAgICAgdWEuaW5kZXhPZignLycgKyBkYXRhICsgJy0nKSA+IC0xKSB7XG4gICAgICBvcyA9IHRyaW0ob3MucmVwbGFjZShkYXRhLCAnJykpO1xuICAgIH1cbiAgICAvLyBBZGQgbGF5b3V0IGVuZ2luZS5cbiAgICBpZiAobGF5b3V0ICYmICEvXFxiKD86QXZhbnR8Tm9vaylcXGIvLnRlc3QobmFtZSkgJiYgKFxuICAgICAgICAvQnJvd3NlcnxMdW5hc2NhcGV8TWF4dGhvbi8udGVzdChuYW1lKSB8fFxuICAgICAgICBuYW1lICE9ICdTYWZhcmknICYmIC9eaU9TLy50ZXN0KG9zKSAmJiAvXFxiU2FmYXJpXFxiLy50ZXN0KGxheW91dFsxXSkgfHxcbiAgICAgICAgL14oPzpBZG9iZXxBcm9yYXxCcmVhY2h8TWlkb3JpfE9wZXJhfFBoYW50b218UmVrb25xfFJvY2t8U2Ftc3VuZyBJbnRlcm5ldHxTbGVpcG5pcnxXZWIpLy50ZXN0KG5hbWUpICYmIGxheW91dFsxXSkpIHtcbiAgICAgIC8vIERvbid0IGFkZCBsYXlvdXQgZGV0YWlscyB0byBkZXNjcmlwdGlvbiBpZiB0aGV5IGFyZSBmYWxzZXkuXG4gICAgICAoZGF0YSA9IGxheW91dFtsYXlvdXQubGVuZ3RoIC0gMV0pICYmIGRlc2NyaXB0aW9uLnB1c2goZGF0YSk7XG4gICAgfVxuICAgIC8vIENvbWJpbmUgY29udGV4dHVhbCBpbmZvcm1hdGlvbi5cbiAgICBpZiAoZGVzY3JpcHRpb24ubGVuZ3RoKSB7XG4gICAgICBkZXNjcmlwdGlvbiA9IFsnKCcgKyBkZXNjcmlwdGlvbi5qb2luKCc7ICcpICsgJyknXTtcbiAgICB9XG4gICAgLy8gQXBwZW5kIG1hbnVmYWN0dXJlciB0byBkZXNjcmlwdGlvbi5cbiAgICBpZiAobWFudWZhY3R1cmVyICYmIHByb2R1Y3QgJiYgcHJvZHVjdC5pbmRleE9mKG1hbnVmYWN0dXJlcikgPCAwKSB7XG4gICAgICBkZXNjcmlwdGlvbi5wdXNoKCdvbiAnICsgbWFudWZhY3R1cmVyKTtcbiAgICB9XG4gICAgLy8gQXBwZW5kIHByb2R1Y3QgdG8gZGVzY3JpcHRpb24uXG4gICAgaWYgKHByb2R1Y3QpIHtcbiAgICAgIGRlc2NyaXB0aW9uLnB1c2goKC9eb24gLy50ZXN0KGRlc2NyaXB0aW9uW2Rlc2NyaXB0aW9uLmxlbmd0aCAtIDFdKSA/ICcnIDogJ29uICcpICsgcHJvZHVjdCk7XG4gICAgfVxuICAgIC8vIFBhcnNlIHRoZSBPUyBpbnRvIGFuIG9iamVjdC5cbiAgICBpZiAob3MpIHtcbiAgICAgIGRhdGEgPSAvIChbXFxkLitdKykkLy5leGVjKG9zKTtcbiAgICAgIGlzU3BlY2lhbENhc2VkT1MgPSBkYXRhICYmIG9zLmNoYXJBdChvcy5sZW5ndGggLSBkYXRhWzBdLmxlbmd0aCAtIDEpID09ICcvJztcbiAgICAgIG9zID0ge1xuICAgICAgICAnYXJjaGl0ZWN0dXJlJzogMzIsXG4gICAgICAgICdmYW1pbHknOiAoZGF0YSAmJiAhaXNTcGVjaWFsQ2FzZWRPUykgPyBvcy5yZXBsYWNlKGRhdGFbMF0sICcnKSA6IG9zLFxuICAgICAgICAndmVyc2lvbic6IGRhdGEgPyBkYXRhWzFdIDogbnVsbCxcbiAgICAgICAgJ3RvU3RyaW5nJzogZnVuY3Rpb24oKSB7XG4gICAgICAgICAgdmFyIHZlcnNpb24gPSB0aGlzLnZlcnNpb247XG4gICAgICAgICAgcmV0dXJuIHRoaXMuZmFtaWx5ICsgKCh2ZXJzaW9uICYmICFpc1NwZWNpYWxDYXNlZE9TKSA/ICcgJyArIHZlcnNpb24gOiAnJykgKyAodGhpcy5hcmNoaXRlY3R1cmUgPT0gNjQgPyAnIDY0LWJpdCcgOiAnJyk7XG4gICAgICAgIH1cbiAgICAgIH07XG4gICAgfVxuICAgIC8vIEFkZCBicm93c2VyL09TIGFyY2hpdGVjdHVyZS5cbiAgICBpZiAoKGRhdGEgPSAvXFxiKD86QU1EfElBfFdpbnxXT1d8eDg2X3x4KTY0XFxiL2kuZXhlYyhhcmNoKSkgJiYgIS9cXGJpNjg2XFxiL2kudGVzdChhcmNoKSkge1xuICAgICAgaWYgKG9zKSB7XG4gICAgICAgIG9zLmFyY2hpdGVjdHVyZSA9IDY0O1xuICAgICAgICBvcy5mYW1pbHkgPSBvcy5mYW1pbHkucmVwbGFjZShSZWdFeHAoJyAqJyArIGRhdGEpLCAnJyk7XG4gICAgICB9XG4gICAgICBpZiAoXG4gICAgICAgICAgbmFtZSAmJiAoL1xcYldPVzY0XFxiL2kudGVzdCh1YSkgfHxcbiAgICAgICAgICAodXNlRmVhdHVyZXMgJiYgL1xcdyg/Ojg2fDMyKSQvLnRlc3QobmF2LmNwdUNsYXNzIHx8IG5hdi5wbGF0Zm9ybSkgJiYgIS9cXGJXaW42NDsgeDY0XFxiL2kudGVzdCh1YSkpKVxuICAgICAgKSB7XG4gICAgICAgIGRlc2NyaXB0aW9uLnVuc2hpZnQoJzMyLWJpdCcpO1xuICAgICAgfVxuICAgIH1cbiAgICAvLyBDaHJvbWUgMzkgYW5kIGFib3ZlIG9uIE9TIFggaXMgYWx3YXlzIDY0LWJpdC5cbiAgICBlbHNlIGlmIChcbiAgICAgICAgb3MgJiYgL15PUyBYLy50ZXN0KG9zLmZhbWlseSkgJiZcbiAgICAgICAgbmFtZSA9PSAnQ2hyb21lJyAmJiBwYXJzZUZsb2F0KHZlcnNpb24pID49IDM5XG4gICAgKSB7XG4gICAgICBvcy5hcmNoaXRlY3R1cmUgPSA2NDtcbiAgICB9XG5cbiAgICB1YSB8fCAodWEgPSBudWxsKTtcblxuICAgIC8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cblxuICAgIC8qKlxuICAgICAqIFRoZSBwbGF0Zm9ybSBvYmplY3QuXG4gICAgICpcbiAgICAgKiBAbmFtZSBwbGF0Zm9ybVxuICAgICAqIEB0eXBlIE9iamVjdFxuICAgICAqL1xuICAgIHZhciBwbGF0Zm9ybSA9IHt9O1xuXG4gICAgLyoqXG4gICAgICogVGhlIHBsYXRmb3JtIGRlc2NyaXB0aW9uLlxuICAgICAqXG4gICAgICogQG1lbWJlck9mIHBsYXRmb3JtXG4gICAgICogQHR5cGUgc3RyaW5nfG51bGxcbiAgICAgKi9cbiAgICBwbGF0Zm9ybS5kZXNjcmlwdGlvbiA9IHVhO1xuXG4gICAgLyoqXG4gICAgICogVGhlIG5hbWUgb2YgdGhlIGJyb3dzZXIncyBsYXlvdXQgZW5naW5lLlxuICAgICAqXG4gICAgICogVGhlIGxpc3Qgb2YgY29tbW9uIGxheW91dCBlbmdpbmVzIGluY2x1ZGU6XG4gICAgICogXCJCbGlua1wiLCBcIkVkZ2VIVE1MXCIsIFwiR2Vja29cIiwgXCJUcmlkZW50XCIgYW5kIFwiV2ViS2l0XCJcbiAgICAgKlxuICAgICAqIEBtZW1iZXJPZiBwbGF0Zm9ybVxuICAgICAqIEB0eXBlIHN0cmluZ3xudWxsXG4gICAgICovXG4gICAgcGxhdGZvcm0ubGF5b3V0ID0gbGF5b3V0ICYmIGxheW91dFswXTtcblxuICAgIC8qKlxuICAgICAqIFRoZSBuYW1lIG9mIHRoZSBwcm9kdWN0J3MgbWFudWZhY3R1cmVyLlxuICAgICAqXG4gICAgICogVGhlIGxpc3Qgb2YgbWFudWZhY3R1cmVycyBpbmNsdWRlOlxuICAgICAqIFwiQXBwbGVcIiwgXCJBcmNob3NcIiwgXCJBbWF6b25cIiwgXCJBc3VzXCIsIFwiQmFybmVzICYgTm9ibGVcIiwgXCJCbGFja0JlcnJ5XCIsXG4gICAgICogXCJHb29nbGVcIiwgXCJIUFwiLCBcIkhUQ1wiLCBcIkxHXCIsIFwiTWljcm9zb2Z0XCIsIFwiTW90b3JvbGFcIiwgXCJOaW50ZW5kb1wiLFxuICAgICAqIFwiTm9raWFcIiwgXCJTYW1zdW5nXCIgYW5kIFwiU29ueVwiXG4gICAgICpcbiAgICAgKiBAbWVtYmVyT2YgcGxhdGZvcm1cbiAgICAgKiBAdHlwZSBzdHJpbmd8bnVsbFxuICAgICAqL1xuICAgIHBsYXRmb3JtLm1hbnVmYWN0dXJlciA9IG1hbnVmYWN0dXJlcjtcblxuICAgIC8qKlxuICAgICAqIFRoZSBuYW1lIG9mIHRoZSBicm93c2VyL2Vudmlyb25tZW50LlxuICAgICAqXG4gICAgICogVGhlIGxpc3Qgb2YgY29tbW9uIGJyb3dzZXIgbmFtZXMgaW5jbHVkZTpcbiAgICAgKiBcIkNocm9tZVwiLCBcIkVsZWN0cm9uXCIsIFwiRmlyZWZveFwiLCBcIkZpcmVmb3ggZm9yIGlPU1wiLCBcIklFXCIsXG4gICAgICogXCJNaWNyb3NvZnQgRWRnZVwiLCBcIlBoYW50b21KU1wiLCBcIlNhZmFyaVwiLCBcIlNlYU1vbmtleVwiLCBcIlNpbGtcIixcbiAgICAgKiBcIk9wZXJhIE1pbmlcIiBhbmQgXCJPcGVyYVwiXG4gICAgICpcbiAgICAgKiBNb2JpbGUgdmVyc2lvbnMgb2Ygc29tZSBicm93c2VycyBoYXZlIFwiTW9iaWxlXCIgYXBwZW5kZWQgdG8gdGhlaXIgbmFtZTpcbiAgICAgKiBlZy4gXCJDaHJvbWUgTW9iaWxlXCIsIFwiRmlyZWZveCBNb2JpbGVcIiwgXCJJRSBNb2JpbGVcIiBhbmQgXCJPcGVyYSBNb2JpbGVcIlxuICAgICAqXG4gICAgICogQG1lbWJlck9mIHBsYXRmb3JtXG4gICAgICogQHR5cGUgc3RyaW5nfG51bGxcbiAgICAgKi9cbiAgICBwbGF0Zm9ybS5uYW1lID0gbmFtZTtcblxuICAgIC8qKlxuICAgICAqIFRoZSBhbHBoYS9iZXRhIHJlbGVhc2UgaW5kaWNhdG9yLlxuICAgICAqXG4gICAgICogQG1lbWJlck9mIHBsYXRmb3JtXG4gICAgICogQHR5cGUgc3RyaW5nfG51bGxcbiAgICAgKi9cbiAgICBwbGF0Zm9ybS5wcmVyZWxlYXNlID0gcHJlcmVsZWFzZTtcblxuICAgIC8qKlxuICAgICAqIFRoZSBuYW1lIG9mIHRoZSBwcm9kdWN0IGhvc3RpbmcgdGhlIGJyb3dzZXIuXG4gICAgICpcbiAgICAgKiBUaGUgbGlzdCBvZiBjb21tb24gcHJvZHVjdHMgaW5jbHVkZTpcbiAgICAgKlxuICAgICAqIFwiQmxhY2tCZXJyeVwiLCBcIkdhbGF4eSBTNFwiLCBcIkx1bWlhXCIsIFwiaVBhZFwiLCBcImlQb2RcIiwgXCJpUGhvbmVcIiwgXCJLaW5kbGVcIixcbiAgICAgKiBcIktpbmRsZSBGaXJlXCIsIFwiTmV4dXNcIiwgXCJOb29rXCIsIFwiUGxheUJvb2tcIiwgXCJUb3VjaFBhZFwiIGFuZCBcIlRyYW5zZm9ybWVyXCJcbiAgICAgKlxuICAgICAqIEBtZW1iZXJPZiBwbGF0Zm9ybVxuICAgICAqIEB0eXBlIHN0cmluZ3xudWxsXG4gICAgICovXG4gICAgcGxhdGZvcm0ucHJvZHVjdCA9IHByb2R1Y3Q7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYnJvd3NlcidzIHVzZXIgYWdlbnQgc3RyaW5nLlxuICAgICAqXG4gICAgICogQG1lbWJlck9mIHBsYXRmb3JtXG4gICAgICogQHR5cGUgc3RyaW5nfG51bGxcbiAgICAgKi9cbiAgICBwbGF0Zm9ybS51YSA9IHVhO1xuXG4gICAgLyoqXG4gICAgICogVGhlIGJyb3dzZXIvZW52aXJvbm1lbnQgdmVyc2lvbi5cbiAgICAgKlxuICAgICAqIEBtZW1iZXJPZiBwbGF0Zm9ybVxuICAgICAqIEB0eXBlIHN0cmluZ3xudWxsXG4gICAgICovXG4gICAgcGxhdGZvcm0udmVyc2lvbiA9IG5hbWUgJiYgdmVyc2lvbjtcblxuICAgIC8qKlxuICAgICAqIFRoZSBuYW1lIG9mIHRoZSBvcGVyYXRpbmcgc3lzdGVtLlxuICAgICAqXG4gICAgICogQG1lbWJlck9mIHBsYXRmb3JtXG4gICAgICogQHR5cGUgT2JqZWN0XG4gICAgICovXG4gICAgcGxhdGZvcm0ub3MgPSBvcyB8fCB7XG5cbiAgICAgIC8qKlxuICAgICAgICogVGhlIENQVSBhcmNoaXRlY3R1cmUgdGhlIE9TIGlzIGJ1aWx0IGZvci5cbiAgICAgICAqXG4gICAgICAgKiBAbWVtYmVyT2YgcGxhdGZvcm0ub3NcbiAgICAgICAqIEB0eXBlIG51bWJlcnxudWxsXG4gICAgICAgKi9cbiAgICAgICdhcmNoaXRlY3R1cmUnOiBudWxsLFxuXG4gICAgICAvKipcbiAgICAgICAqIFRoZSBmYW1pbHkgb2YgdGhlIE9TLlxuICAgICAgICpcbiAgICAgICAqIENvbW1vbiB2YWx1ZXMgaW5jbHVkZTpcbiAgICAgICAqIFwiV2luZG93c1wiLCBcIldpbmRvd3MgU2VydmVyIDIwMDggUjIgLyA3XCIsIFwiV2luZG93cyBTZXJ2ZXIgMjAwOCAvIFZpc3RhXCIsXG4gICAgICAgKiBcIldpbmRvd3MgWFBcIiwgXCJPUyBYXCIsIFwiVWJ1bnR1XCIsIFwiRGViaWFuXCIsIFwiRmVkb3JhXCIsIFwiUmVkIEhhdFwiLCBcIlN1U0VcIixcbiAgICAgICAqIFwiQW5kcm9pZFwiLCBcImlPU1wiIGFuZCBcIldpbmRvd3MgUGhvbmVcIlxuICAgICAgICpcbiAgICAgICAqIEBtZW1iZXJPZiBwbGF0Zm9ybS5vc1xuICAgICAgICogQHR5cGUgc3RyaW5nfG51bGxcbiAgICAgICAqL1xuICAgICAgJ2ZhbWlseSc6IG51bGwsXG5cbiAgICAgIC8qKlxuICAgICAgICogVGhlIHZlcnNpb24gb2YgdGhlIE9TLlxuICAgICAgICpcbiAgICAgICAqIEBtZW1iZXJPZiBwbGF0Zm9ybS5vc1xuICAgICAgICogQHR5cGUgc3RyaW5nfG51bGxcbiAgICAgICAqL1xuICAgICAgJ3ZlcnNpb24nOiBudWxsLFxuXG4gICAgICAvKipcbiAgICAgICAqIFJldHVybnMgdGhlIE9TIHN0cmluZy5cbiAgICAgICAqXG4gICAgICAgKiBAbWVtYmVyT2YgcGxhdGZvcm0ub3NcbiAgICAgICAqIEByZXR1cm5zIHtzdHJpbmd9IFRoZSBPUyBzdHJpbmcuXG4gICAgICAgKi9cbiAgICAgICd0b1N0cmluZyc6IGZ1bmN0aW9uKCkgeyByZXR1cm4gJ251bGwnOyB9XG4gICAgfTtcblxuICAgIHBsYXRmb3JtLnBhcnNlID0gcGFyc2U7XG4gICAgcGxhdGZvcm0udG9TdHJpbmcgPSB0b1N0cmluZ1BsYXRmb3JtO1xuXG4gICAgaWYgKHBsYXRmb3JtLnZlcnNpb24pIHtcbiAgICAgIGRlc2NyaXB0aW9uLnVuc2hpZnQodmVyc2lvbik7XG4gICAgfVxuICAgIGlmIChwbGF0Zm9ybS5uYW1lKSB7XG4gICAgICBkZXNjcmlwdGlvbi51bnNoaWZ0KG5hbWUpO1xuICAgIH1cbiAgICBpZiAob3MgJiYgbmFtZSAmJiAhKG9zID09IFN0cmluZyhvcykuc3BsaXQoJyAnKVswXSAmJiAob3MgPT0gbmFtZS5zcGxpdCgnICcpWzBdIHx8IHByb2R1Y3QpKSkge1xuICAgICAgZGVzY3JpcHRpb24ucHVzaChwcm9kdWN0ID8gJygnICsgb3MgKyAnKScgOiAnb24gJyArIG9zKTtcbiAgICB9XG4gICAgaWYgKGRlc2NyaXB0aW9uLmxlbmd0aCkge1xuICAgICAgcGxhdGZvcm0uZGVzY3JpcHRpb24gPSBkZXNjcmlwdGlvbi5qb2luKCcgJyk7XG4gICAgfVxuICAgIHJldHVybiBwbGF0Zm9ybTtcbiAgfVxuXG4gIC8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuXG4gIC8vIEV4cG9ydCBwbGF0Zm9ybS5cbiAgdmFyIHBsYXRmb3JtID0gcGFyc2UoKTtcblxuICAvLyBTb21lIEFNRCBidWlsZCBvcHRpbWl6ZXJzLCBsaWtlIHIuanMsIGNoZWNrIGZvciBjb25kaXRpb24gcGF0dGVybnMgbGlrZSB0aGUgZm9sbG93aW5nOlxuICBpZiAodHlwZW9mIGRlZmluZSA9PSAnZnVuY3Rpb24nICYmIHR5cGVvZiBkZWZpbmUuYW1kID09ICdvYmplY3QnICYmIGRlZmluZS5hbWQpIHtcbiAgICAvLyBFeHBvc2UgcGxhdGZvcm0gb24gdGhlIGdsb2JhbCBvYmplY3QgdG8gcHJldmVudCBlcnJvcnMgd2hlbiBwbGF0Zm9ybSBpc1xuICAgIC8vIGxvYWRlZCBieSBhIHNjcmlwdCB0YWcgaW4gdGhlIHByZXNlbmNlIG9mIGFuIEFNRCBsb2FkZXIuXG4gICAgLy8gU2VlIGh0dHA6Ly9yZXF1aXJlanMub3JnL2RvY3MvZXJyb3JzLmh0bWwjbWlzbWF0Y2ggZm9yIG1vcmUgZGV0YWlscy5cbiAgICByb290LnBsYXRmb3JtID0gcGxhdGZvcm07XG5cbiAgICAvLyBEZWZpbmUgYXMgYW4gYW5vbnltb3VzIG1vZHVsZSBzbyBwbGF0Zm9ybSBjYW4gYmUgYWxpYXNlZCB0aHJvdWdoIHBhdGggbWFwcGluZy5cbiAgICBkZWZpbmUoZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4gcGxhdGZvcm07XG4gICAgfSk7XG4gIH1cbiAgLy8gQ2hlY2sgZm9yIGBleHBvcnRzYCBhZnRlciBgZGVmaW5lYCBpbiBjYXNlIGEgYnVpbGQgb3B0aW1pemVyIGFkZHMgYW4gYGV4cG9ydHNgIG9iamVjdC5cbiAgZWxzZSBpZiAoZnJlZUV4cG9ydHMgJiYgZnJlZU1vZHVsZSkge1xuICAgIC8vIEV4cG9ydCBmb3IgQ29tbW9uSlMgc3VwcG9ydC5cbiAgICBmb3JPd24ocGxhdGZvcm0sIGZ1bmN0aW9uKHZhbHVlLCBrZXkpIHtcbiAgICAgIGZyZWVFeHBvcnRzW2tleV0gPSB2YWx1ZTtcbiAgICB9KTtcbiAgfVxuICBlbHNlIHtcbiAgICAvLyBFeHBvcnQgdG8gdGhlIGdsb2JhbCBvYmplY3QuXG4gICAgcm9vdC5wbGF0Zm9ybSA9IHBsYXRmb3JtO1xuICB9XG59LmNhbGwodGhpcykpO1xuIiwidmFyIHYxID0gcmVxdWlyZSgnLi92MScpO1xudmFyIHY0ID0gcmVxdWlyZSgnLi92NCcpO1xuXG52YXIgdXVpZCA9IHY0O1xudXVpZC52MSA9IHYxO1xudXVpZC52NCA9IHY0O1xuXG5tb2R1bGUuZXhwb3J0cyA9IHV1aWQ7XG4iLCIvKipcbiAqIENvbnZlcnQgYXJyYXkgb2YgMTYgYnl0ZSB2YWx1ZXMgdG8gVVVJRCBzdHJpbmcgZm9ybWF0IG9mIHRoZSBmb3JtOlxuICogWFhYWFhYWFgtWFhYWC1YWFhYLVhYWFgtWFhYWFhYWFhYWFhYXG4gKi9cbnZhciBieXRlVG9IZXggPSBbXTtcbmZvciAodmFyIGkgPSAwOyBpIDwgMjU2OyArK2kpIHtcbiAgYnl0ZVRvSGV4W2ldID0gKGkgKyAweDEwMCkudG9TdHJpbmcoMTYpLnN1YnN0cigxKTtcbn1cblxuZnVuY3Rpb24gYnl0ZXNUb1V1aWQoYnVmLCBvZmZzZXQpIHtcbiAgdmFyIGkgPSBvZmZzZXQgfHwgMDtcbiAgdmFyIGJ0aCA9IGJ5dGVUb0hleDtcbiAgLy8gam9pbiB1c2VkIHRvIGZpeCBtZW1vcnkgaXNzdWUgY2F1c2VkIGJ5IGNvbmNhdGVuYXRpb246IGh0dHBzOi8vYnVncy5jaHJvbWl1bS5vcmcvcC92OC9pc3N1ZXMvZGV0YWlsP2lkPTMxNzUjYzRcbiAgcmV0dXJuIChbYnRoW2J1ZltpKytdXSwgYnRoW2J1ZltpKytdXSwgXG5cdGJ0aFtidWZbaSsrXV0sIGJ0aFtidWZbaSsrXV0sICctJyxcblx0YnRoW2J1ZltpKytdXSwgYnRoW2J1ZltpKytdXSwgJy0nLFxuXHRidGhbYnVmW2krK11dLCBidGhbYnVmW2krK11dLCAnLScsXG5cdGJ0aFtidWZbaSsrXV0sIGJ0aFtidWZbaSsrXV0sICctJyxcblx0YnRoW2J1ZltpKytdXSwgYnRoW2J1ZltpKytdXSxcblx0YnRoW2J1ZltpKytdXSwgYnRoW2J1ZltpKytdXSxcblx0YnRoW2J1ZltpKytdXSwgYnRoW2J1ZltpKytdXV0pLmpvaW4oJycpO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGJ5dGVzVG9VdWlkO1xuIiwiLy8gVW5pcXVlIElEIGNyZWF0aW9uIHJlcXVpcmVzIGEgaGlnaCBxdWFsaXR5IHJhbmRvbSAjIGdlbmVyYXRvci4gIEluIHRoZVxuLy8gYnJvd3NlciB0aGlzIGlzIGEgbGl0dGxlIGNvbXBsaWNhdGVkIGR1ZSB0byB1bmtub3duIHF1YWxpdHkgb2YgTWF0aC5yYW5kb20oKVxuLy8gYW5kIGluY29uc2lzdGVudCBzdXBwb3J0IGZvciB0aGUgYGNyeXB0b2AgQVBJLiAgV2UgZG8gdGhlIGJlc3Qgd2UgY2FuIHZpYVxuLy8gZmVhdHVyZS1kZXRlY3Rpb25cblxuLy8gZ2V0UmFuZG9tVmFsdWVzIG5lZWRzIHRvIGJlIGludm9rZWQgaW4gYSBjb250ZXh0IHdoZXJlIFwidGhpc1wiIGlzIGEgQ3J5cHRvXG4vLyBpbXBsZW1lbnRhdGlvbi4gQWxzbywgZmluZCB0aGUgY29tcGxldGUgaW1wbGVtZW50YXRpb24gb2YgY3J5cHRvIG9uIElFMTEuXG52YXIgZ2V0UmFuZG9tVmFsdWVzID0gKHR5cGVvZihjcnlwdG8pICE9ICd1bmRlZmluZWQnICYmIGNyeXB0by5nZXRSYW5kb21WYWx1ZXMgJiYgY3J5cHRvLmdldFJhbmRvbVZhbHVlcy5iaW5kKGNyeXB0bykpIHx8XG4gICAgICAgICAgICAgICAgICAgICAgKHR5cGVvZihtc0NyeXB0bykgIT0gJ3VuZGVmaW5lZCcgJiYgdHlwZW9mIHdpbmRvdy5tc0NyeXB0by5nZXRSYW5kb21WYWx1ZXMgPT0gJ2Z1bmN0aW9uJyAmJiBtc0NyeXB0by5nZXRSYW5kb21WYWx1ZXMuYmluZChtc0NyeXB0bykpO1xuXG5pZiAoZ2V0UmFuZG9tVmFsdWVzKSB7XG4gIC8vIFdIQVRXRyBjcnlwdG8gUk5HIC0gaHR0cDovL3dpa2kud2hhdHdnLm9yZy93aWtpL0NyeXB0b1xuICB2YXIgcm5kczggPSBuZXcgVWludDhBcnJheSgxNik7IC8vIGVzbGludC1kaXNhYmxlLWxpbmUgbm8tdW5kZWZcblxuICBtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHdoYXR3Z1JORygpIHtcbiAgICBnZXRSYW5kb21WYWx1ZXMocm5kczgpO1xuICAgIHJldHVybiBybmRzODtcbiAgfTtcbn0gZWxzZSB7XG4gIC8vIE1hdGgucmFuZG9tKCktYmFzZWQgKFJORylcbiAgLy9cbiAgLy8gSWYgYWxsIGVsc2UgZmFpbHMsIHVzZSBNYXRoLnJhbmRvbSgpLiAgSXQncyBmYXN0LCBidXQgaXMgb2YgdW5zcGVjaWZpZWRcbiAgLy8gcXVhbGl0eS5cbiAgdmFyIHJuZHMgPSBuZXcgQXJyYXkoMTYpO1xuXG4gIG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gbWF0aFJORygpIHtcbiAgICBmb3IgKHZhciBpID0gMCwgcjsgaSA8IDE2OyBpKyspIHtcbiAgICAgIGlmICgoaSAmIDB4MDMpID09PSAwKSByID0gTWF0aC5yYW5kb20oKSAqIDB4MTAwMDAwMDAwO1xuICAgICAgcm5kc1tpXSA9IHIgPj4+ICgoaSAmIDB4MDMpIDw8IDMpICYgMHhmZjtcbiAgICB9XG5cbiAgICByZXR1cm4gcm5kcztcbiAgfTtcbn1cbiIsInZhciBybmcgPSByZXF1aXJlKCcuL2xpYi9ybmcnKTtcbnZhciBieXRlc1RvVXVpZCA9IHJlcXVpcmUoJy4vbGliL2J5dGVzVG9VdWlkJyk7XG5cbi8vICoqYHYxKClgIC0gR2VuZXJhdGUgdGltZS1iYXNlZCBVVUlEKipcbi8vXG4vLyBJbnNwaXJlZCBieSBodHRwczovL2dpdGh1Yi5jb20vTGlvc0svVVVJRC5qc1xuLy8gYW5kIGh0dHA6Ly9kb2NzLnB5dGhvbi5vcmcvbGlicmFyeS91dWlkLmh0bWxcblxudmFyIF9ub2RlSWQ7XG52YXIgX2Nsb2Nrc2VxO1xuXG4vLyBQcmV2aW91cyB1dWlkIGNyZWF0aW9uIHRpbWVcbnZhciBfbGFzdE1TZWNzID0gMDtcbnZhciBfbGFzdE5TZWNzID0gMDtcblxuLy8gU2VlIGh0dHBzOi8vZ2l0aHViLmNvbS9icm9vZmEvbm9kZS11dWlkIGZvciBBUEkgZGV0YWlsc1xuZnVuY3Rpb24gdjEob3B0aW9ucywgYnVmLCBvZmZzZXQpIHtcbiAgdmFyIGkgPSBidWYgJiYgb2Zmc2V0IHx8IDA7XG4gIHZhciBiID0gYnVmIHx8IFtdO1xuXG4gIG9wdGlvbnMgPSBvcHRpb25zIHx8IHt9O1xuICB2YXIgbm9kZSA9IG9wdGlvbnMubm9kZSB8fCBfbm9kZUlkO1xuICB2YXIgY2xvY2tzZXEgPSBvcHRpb25zLmNsb2Nrc2VxICE9PSB1bmRlZmluZWQgPyBvcHRpb25zLmNsb2Nrc2VxIDogX2Nsb2Nrc2VxO1xuXG4gIC8vIG5vZGUgYW5kIGNsb2Nrc2VxIG5lZWQgdG8gYmUgaW5pdGlhbGl6ZWQgdG8gcmFuZG9tIHZhbHVlcyBpZiB0aGV5J3JlIG5vdFxuICAvLyBzcGVjaWZpZWQuICBXZSBkbyB0aGlzIGxhemlseSB0byBtaW5pbWl6ZSBpc3N1ZXMgcmVsYXRlZCB0byBpbnN1ZmZpY2llbnRcbiAgLy8gc3lzdGVtIGVudHJvcHkuICBTZWUgIzE4OVxuICBpZiAobm9kZSA9PSBudWxsIHx8IGNsb2Nrc2VxID09IG51bGwpIHtcbiAgICB2YXIgc2VlZEJ5dGVzID0gcm5nKCk7XG4gICAgaWYgKG5vZGUgPT0gbnVsbCkge1xuICAgICAgLy8gUGVyIDQuNSwgY3JlYXRlIGFuZCA0OC1iaXQgbm9kZSBpZCwgKDQ3IHJhbmRvbSBiaXRzICsgbXVsdGljYXN0IGJpdCA9IDEpXG4gICAgICBub2RlID0gX25vZGVJZCA9IFtcbiAgICAgICAgc2VlZEJ5dGVzWzBdIHwgMHgwMSxcbiAgICAgICAgc2VlZEJ5dGVzWzFdLCBzZWVkQnl0ZXNbMl0sIHNlZWRCeXRlc1szXSwgc2VlZEJ5dGVzWzRdLCBzZWVkQnl0ZXNbNV1cbiAgICAgIF07XG4gICAgfVxuICAgIGlmIChjbG9ja3NlcSA9PSBudWxsKSB7XG4gICAgICAvLyBQZXIgNC4yLjIsIHJhbmRvbWl6ZSAoMTQgYml0KSBjbG9ja3NlcVxuICAgICAgY2xvY2tzZXEgPSBfY2xvY2tzZXEgPSAoc2VlZEJ5dGVzWzZdIDw8IDggfCBzZWVkQnl0ZXNbN10pICYgMHgzZmZmO1xuICAgIH1cbiAgfVxuXG4gIC8vIFVVSUQgdGltZXN0YW1wcyBhcmUgMTAwIG5hbm8tc2Vjb25kIHVuaXRzIHNpbmNlIHRoZSBHcmVnb3JpYW4gZXBvY2gsXG4gIC8vICgxNTgyLTEwLTE1IDAwOjAwKS4gIEpTTnVtYmVycyBhcmVuJ3QgcHJlY2lzZSBlbm91Z2ggZm9yIHRoaXMsIHNvXG4gIC8vIHRpbWUgaXMgaGFuZGxlZCBpbnRlcm5hbGx5IGFzICdtc2VjcycgKGludGVnZXIgbWlsbGlzZWNvbmRzKSBhbmQgJ25zZWNzJ1xuICAvLyAoMTAwLW5hbm9zZWNvbmRzIG9mZnNldCBmcm9tIG1zZWNzKSBzaW5jZSB1bml4IGVwb2NoLCAxOTcwLTAxLTAxIDAwOjAwLlxuICB2YXIgbXNlY3MgPSBvcHRpb25zLm1zZWNzICE9PSB1bmRlZmluZWQgPyBvcHRpb25zLm1zZWNzIDogbmV3IERhdGUoKS5nZXRUaW1lKCk7XG5cbiAgLy8gUGVyIDQuMi4xLjIsIHVzZSBjb3VudCBvZiB1dWlkJ3MgZ2VuZXJhdGVkIGR1cmluZyB0aGUgY3VycmVudCBjbG9ja1xuICAvLyBjeWNsZSB0byBzaW11bGF0ZSBoaWdoZXIgcmVzb2x1dGlvbiBjbG9ja1xuICB2YXIgbnNlY3MgPSBvcHRpb25zLm5zZWNzICE9PSB1bmRlZmluZWQgPyBvcHRpb25zLm5zZWNzIDogX2xhc3ROU2VjcyArIDE7XG5cbiAgLy8gVGltZSBzaW5jZSBsYXN0IHV1aWQgY3JlYXRpb24gKGluIG1zZWNzKVxuICB2YXIgZHQgPSAobXNlY3MgLSBfbGFzdE1TZWNzKSArIChuc2VjcyAtIF9sYXN0TlNlY3MpLzEwMDAwO1xuXG4gIC8vIFBlciA0LjIuMS4yLCBCdW1wIGNsb2Nrc2VxIG9uIGNsb2NrIHJlZ3Jlc3Npb25cbiAgaWYgKGR0IDwgMCAmJiBvcHRpb25zLmNsb2Nrc2VxID09PSB1bmRlZmluZWQpIHtcbiAgICBjbG9ja3NlcSA9IGNsb2Nrc2VxICsgMSAmIDB4M2ZmZjtcbiAgfVxuXG4gIC8vIFJlc2V0IG5zZWNzIGlmIGNsb2NrIHJlZ3Jlc3NlcyAobmV3IGNsb2Nrc2VxKSBvciB3ZSd2ZSBtb3ZlZCBvbnRvIGEgbmV3XG4gIC8vIHRpbWUgaW50ZXJ2YWxcbiAgaWYgKChkdCA8IDAgfHwgbXNlY3MgPiBfbGFzdE1TZWNzKSAmJiBvcHRpb25zLm5zZWNzID09PSB1bmRlZmluZWQpIHtcbiAgICBuc2VjcyA9IDA7XG4gIH1cblxuICAvLyBQZXIgNC4yLjEuMiBUaHJvdyBlcnJvciBpZiB0b28gbWFueSB1dWlkcyBhcmUgcmVxdWVzdGVkXG4gIGlmIChuc2VjcyA+PSAxMDAwMCkge1xuICAgIHRocm93IG5ldyBFcnJvcigndXVpZC52MSgpOiBDYW5cXCd0IGNyZWF0ZSBtb3JlIHRoYW4gMTBNIHV1aWRzL3NlYycpO1xuICB9XG5cbiAgX2xhc3RNU2VjcyA9IG1zZWNzO1xuICBfbGFzdE5TZWNzID0gbnNlY3M7XG4gIF9jbG9ja3NlcSA9IGNsb2Nrc2VxO1xuXG4gIC8vIFBlciA0LjEuNCAtIENvbnZlcnQgZnJvbSB1bml4IGVwb2NoIHRvIEdyZWdvcmlhbiBlcG9jaFxuICBtc2VjcyArPSAxMjIxOTI5MjgwMDAwMDtcblxuICAvLyBgdGltZV9sb3dgXG4gIHZhciB0bCA9ICgobXNlY3MgJiAweGZmZmZmZmYpICogMTAwMDAgKyBuc2VjcykgJSAweDEwMDAwMDAwMDtcbiAgYltpKytdID0gdGwgPj4+IDI0ICYgMHhmZjtcbiAgYltpKytdID0gdGwgPj4+IDE2ICYgMHhmZjtcbiAgYltpKytdID0gdGwgPj4+IDggJiAweGZmO1xuICBiW2krK10gPSB0bCAmIDB4ZmY7XG5cbiAgLy8gYHRpbWVfbWlkYFxuICB2YXIgdG1oID0gKG1zZWNzIC8gMHgxMDAwMDAwMDAgKiAxMDAwMCkgJiAweGZmZmZmZmY7XG4gIGJbaSsrXSA9IHRtaCA+Pj4gOCAmIDB4ZmY7XG4gIGJbaSsrXSA9IHRtaCAmIDB4ZmY7XG5cbiAgLy8gYHRpbWVfaGlnaF9hbmRfdmVyc2lvbmBcbiAgYltpKytdID0gdG1oID4+PiAyNCAmIDB4ZiB8IDB4MTA7IC8vIGluY2x1ZGUgdmVyc2lvblxuICBiW2krK10gPSB0bWggPj4+IDE2ICYgMHhmZjtcblxuICAvLyBgY2xvY2tfc2VxX2hpX2FuZF9yZXNlcnZlZGAgKFBlciA0LjIuMiAtIGluY2x1ZGUgdmFyaWFudClcbiAgYltpKytdID0gY2xvY2tzZXEgPj4+IDggfCAweDgwO1xuXG4gIC8vIGBjbG9ja19zZXFfbG93YFxuICBiW2krK10gPSBjbG9ja3NlcSAmIDB4ZmY7XG5cbiAgLy8gYG5vZGVgXG4gIGZvciAodmFyIG4gPSAwOyBuIDwgNjsgKytuKSB7XG4gICAgYltpICsgbl0gPSBub2RlW25dO1xuICB9XG5cbiAgcmV0dXJuIGJ1ZiA/IGJ1ZiA6IGJ5dGVzVG9VdWlkKGIpO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHYxO1xuIiwidmFyIHJuZyA9IHJlcXVpcmUoJy4vbGliL3JuZycpO1xudmFyIGJ5dGVzVG9VdWlkID0gcmVxdWlyZSgnLi9saWIvYnl0ZXNUb1V1aWQnKTtcblxuZnVuY3Rpb24gdjQob3B0aW9ucywgYnVmLCBvZmZzZXQpIHtcbiAgdmFyIGkgPSBidWYgJiYgb2Zmc2V0IHx8IDA7XG5cbiAgaWYgKHR5cGVvZihvcHRpb25zKSA9PSAnc3RyaW5nJykge1xuICAgIGJ1ZiA9IG9wdGlvbnMgPT09ICdiaW5hcnknID8gbmV3IEFycmF5KDE2KSA6IG51bGw7XG4gICAgb3B0aW9ucyA9IG51bGw7XG4gIH1cbiAgb3B0aW9ucyA9IG9wdGlvbnMgfHwge307XG5cbiAgdmFyIHJuZHMgPSBvcHRpb25zLnJhbmRvbSB8fCAob3B0aW9ucy5ybmcgfHwgcm5nKSgpO1xuXG4gIC8vIFBlciA0LjQsIHNldCBiaXRzIGZvciB2ZXJzaW9uIGFuZCBgY2xvY2tfc2VxX2hpX2FuZF9yZXNlcnZlZGBcbiAgcm5kc1s2XSA9IChybmRzWzZdICYgMHgwZikgfCAweDQwO1xuICBybmRzWzhdID0gKHJuZHNbOF0gJiAweDNmKSB8IDB4ODA7XG5cbiAgLy8gQ29weSBieXRlcyB0byBidWZmZXIsIGlmIHByb3ZpZGVkXG4gIGlmIChidWYpIHtcbiAgICBmb3IgKHZhciBpaSA9IDA7IGlpIDwgMTY7ICsraWkpIHtcbiAgICAgIGJ1ZltpICsgaWldID0gcm5kc1tpaV07XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGJ1ZiB8fCBieXRlc1RvVXVpZChybmRzKTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSB2NDtcbiIsIi8qXHJcbldpbGRFbWl0dGVyLmpzIGlzIGEgc2xpbSBsaXR0bGUgZXZlbnQgZW1pdHRlciBieSBAaGVucmlram9yZXRlZyBsYXJnZWx5IGJhc2VkXHJcbm9uIEB2aXNpb25tZWRpYSdzIEVtaXR0ZXIgZnJvbSBVSSBLaXQuXHJcblxyXG5XaHk/IEkgd2FudGVkIGl0IHN0YW5kYWxvbmUuXHJcblxyXG5JIGFsc28gd2FudGVkIHN1cHBvcnQgZm9yIHdpbGRjYXJkIGVtaXR0ZXJzIGxpa2UgdGhpczpcclxuXHJcbmVtaXR0ZXIub24oJyonLCBmdW5jdGlvbiAoZXZlbnROYW1lLCBvdGhlciwgZXZlbnQsIHBheWxvYWRzKSB7XHJcblxyXG59KTtcclxuXHJcbmVtaXR0ZXIub24oJ3NvbWVuYW1lc3BhY2UqJywgZnVuY3Rpb24gKGV2ZW50TmFtZSwgcGF5bG9hZHMpIHtcclxuXHJcbn0pO1xyXG5cclxuUGxlYXNlIG5vdGUgdGhhdCBjYWxsYmFja3MgdHJpZ2dlcmVkIGJ5IHdpbGRjYXJkIHJlZ2lzdGVyZWQgZXZlbnRzIGFsc28gZ2V0XHJcbnRoZSBldmVudCBuYW1lIGFzIHRoZSBmaXJzdCBhcmd1bWVudC5cclxuKi9cclxuXHJcbm1vZHVsZS5leHBvcnRzID0gV2lsZEVtaXR0ZXI7XHJcblxyXG5mdW5jdGlvbiBXaWxkRW1pdHRlcigpIHsgfVxyXG5cclxuV2lsZEVtaXR0ZXIubWl4aW4gPSBmdW5jdGlvbiAoY29uc3RydWN0b3IpIHtcclxuICAgIHZhciBwcm90b3R5cGUgPSBjb25zdHJ1Y3Rvci5wcm90b3R5cGUgfHwgY29uc3RydWN0b3I7XHJcblxyXG4gICAgcHJvdG90eXBlLmlzV2lsZEVtaXR0ZXI9IHRydWU7XHJcblxyXG4gICAgLy8gTGlzdGVuIG9uIHRoZSBnaXZlbiBgZXZlbnRgIHdpdGggYGZuYC4gU3RvcmUgYSBncm91cCBuYW1lIGlmIHByZXNlbnQuXHJcbiAgICBwcm90b3R5cGUub24gPSBmdW5jdGlvbiAoZXZlbnQsIGdyb3VwTmFtZSwgZm4pIHtcclxuICAgICAgICB0aGlzLmNhbGxiYWNrcyA9IHRoaXMuY2FsbGJhY2tzIHx8IHt9O1xyXG4gICAgICAgIHZhciBoYXNHcm91cCA9IChhcmd1bWVudHMubGVuZ3RoID09PSAzKSxcclxuICAgICAgICAgICAgZ3JvdXAgPSBoYXNHcm91cCA/IGFyZ3VtZW50c1sxXSA6IHVuZGVmaW5lZCxcclxuICAgICAgICAgICAgZnVuYyA9IGhhc0dyb3VwID8gYXJndW1lbnRzWzJdIDogYXJndW1lbnRzWzFdO1xyXG4gICAgICAgIGZ1bmMuX2dyb3VwTmFtZSA9IGdyb3VwO1xyXG4gICAgICAgICh0aGlzLmNhbGxiYWNrc1tldmVudF0gPSB0aGlzLmNhbGxiYWNrc1tldmVudF0gfHwgW10pLnB1c2goZnVuYyk7XHJcbiAgICAgICAgcmV0dXJuIHRoaXM7XHJcbiAgICB9O1xyXG5cclxuICAgIC8vIEFkZHMgYW4gYGV2ZW50YCBsaXN0ZW5lciB0aGF0IHdpbGwgYmUgaW52b2tlZCBhIHNpbmdsZVxyXG4gICAgLy8gdGltZSB0aGVuIGF1dG9tYXRpY2FsbHkgcmVtb3ZlZC5cclxuICAgIHByb3RvdHlwZS5vbmNlID0gZnVuY3Rpb24gKGV2ZW50LCBncm91cE5hbWUsIGZuKSB7XHJcbiAgICAgICAgdmFyIHNlbGYgPSB0aGlzLFxyXG4gICAgICAgICAgICBoYXNHcm91cCA9IChhcmd1bWVudHMubGVuZ3RoID09PSAzKSxcclxuICAgICAgICAgICAgZ3JvdXAgPSBoYXNHcm91cCA/IGFyZ3VtZW50c1sxXSA6IHVuZGVmaW5lZCxcclxuICAgICAgICAgICAgZnVuYyA9IGhhc0dyb3VwID8gYXJndW1lbnRzWzJdIDogYXJndW1lbnRzWzFdO1xyXG4gICAgICAgIGZ1bmN0aW9uIG9uKCkge1xyXG4gICAgICAgICAgICBzZWxmLm9mZihldmVudCwgb24pO1xyXG4gICAgICAgICAgICBmdW5jLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHRoaXMub24oZXZlbnQsIGdyb3VwLCBvbik7XHJcbiAgICAgICAgcmV0dXJuIHRoaXM7XHJcbiAgICB9O1xyXG5cclxuICAgIC8vIFVuYmluZHMgYW4gZW50aXJlIGdyb3VwXHJcbiAgICBwcm90b3R5cGUucmVsZWFzZUdyb3VwID0gZnVuY3Rpb24gKGdyb3VwTmFtZSkge1xyXG4gICAgICAgIHRoaXMuY2FsbGJhY2tzID0gdGhpcy5jYWxsYmFja3MgfHwge307XHJcbiAgICAgICAgdmFyIGl0ZW0sIGksIGxlbiwgaGFuZGxlcnM7XHJcbiAgICAgICAgZm9yIChpdGVtIGluIHRoaXMuY2FsbGJhY2tzKSB7XHJcbiAgICAgICAgICAgIGhhbmRsZXJzID0gdGhpcy5jYWxsYmFja3NbaXRlbV07XHJcbiAgICAgICAgICAgIGZvciAoaSA9IDAsIGxlbiA9IGhhbmRsZXJzLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XHJcbiAgICAgICAgICAgICAgICBpZiAoaGFuZGxlcnNbaV0uX2dyb3VwTmFtZSA9PT0gZ3JvdXBOYW1lKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgLy9jb25zb2xlLmxvZygncmVtb3ZpbmcnKTtcclxuICAgICAgICAgICAgICAgICAgICAvLyByZW1vdmUgaXQgYW5kIHNob3J0ZW4gdGhlIGFycmF5IHdlJ3JlIGxvb3BpbmcgdGhyb3VnaFxyXG4gICAgICAgICAgICAgICAgICAgIGhhbmRsZXJzLnNwbGljZShpLCAxKTtcclxuICAgICAgICAgICAgICAgICAgICBpLS07XHJcbiAgICAgICAgICAgICAgICAgICAgbGVuLS07XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgICAgcmV0dXJuIHRoaXM7XHJcbiAgICB9O1xyXG5cclxuICAgIC8vIFJlbW92ZSB0aGUgZ2l2ZW4gY2FsbGJhY2sgZm9yIGBldmVudGAgb3IgYWxsXHJcbiAgICAvLyByZWdpc3RlcmVkIGNhbGxiYWNrcy5cclxuICAgIHByb3RvdHlwZS5vZmYgPSBmdW5jdGlvbiAoZXZlbnQsIGZuKSB7XHJcbiAgICAgICAgdGhpcy5jYWxsYmFja3MgPSB0aGlzLmNhbGxiYWNrcyB8fCB7fTtcclxuICAgICAgICB2YXIgY2FsbGJhY2tzID0gdGhpcy5jYWxsYmFja3NbZXZlbnRdLFxyXG4gICAgICAgICAgICBpO1xyXG5cclxuICAgICAgICBpZiAoIWNhbGxiYWNrcykgcmV0dXJuIHRoaXM7XHJcblxyXG4gICAgICAgIC8vIHJlbW92ZSBhbGwgaGFuZGxlcnNcclxuICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMSkge1xyXG4gICAgICAgICAgICBkZWxldGUgdGhpcy5jYWxsYmFja3NbZXZlbnRdO1xyXG4gICAgICAgICAgICByZXR1cm4gdGhpcztcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC8vIHJlbW92ZSBzcGVjaWZpYyBoYW5kbGVyXHJcbiAgICAgICAgaSA9IGNhbGxiYWNrcy5pbmRleE9mKGZuKTtcclxuICAgICAgICBjYWxsYmFja3Muc3BsaWNlKGksIDEpO1xyXG4gICAgICAgIGlmIChjYWxsYmFja3MubGVuZ3RoID09PSAwKSB7XHJcbiAgICAgICAgICAgIGRlbGV0ZSB0aGlzLmNhbGxiYWNrc1tldmVudF07XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJldHVybiB0aGlzO1xyXG4gICAgfTtcclxuXHJcbiAgICAvLy8gRW1pdCBgZXZlbnRgIHdpdGggdGhlIGdpdmVuIGFyZ3MuXHJcbiAgICAvLyBhbHNvIGNhbGxzIGFueSBgKmAgaGFuZGxlcnNcclxuICAgIHByb3RvdHlwZS5lbWl0ID0gZnVuY3Rpb24gKGV2ZW50KSB7XHJcbiAgICAgICAgdGhpcy5jYWxsYmFja3MgPSB0aGlzLmNhbGxiYWNrcyB8fCB7fTtcclxuICAgICAgICB2YXIgYXJncyA9IFtdLnNsaWNlLmNhbGwoYXJndW1lbnRzLCAxKSxcclxuICAgICAgICAgICAgY2FsbGJhY2tzID0gdGhpcy5jYWxsYmFja3NbZXZlbnRdLFxyXG4gICAgICAgICAgICBzcGVjaWFsQ2FsbGJhY2tzID0gdGhpcy5nZXRXaWxkY2FyZENhbGxiYWNrcyhldmVudCksXHJcbiAgICAgICAgICAgIGksXHJcbiAgICAgICAgICAgIGxlbixcclxuICAgICAgICAgICAgaXRlbSxcclxuICAgICAgICAgICAgbGlzdGVuZXJzO1xyXG5cclxuICAgICAgICBpZiAoY2FsbGJhY2tzKSB7XHJcbiAgICAgICAgICAgIGxpc3RlbmVycyA9IGNhbGxiYWNrcy5zbGljZSgpO1xyXG4gICAgICAgICAgICBmb3IgKGkgPSAwLCBsZW4gPSBsaXN0ZW5lcnMubGVuZ3RoOyBpIDwgbGVuOyArK2kpIHtcclxuICAgICAgICAgICAgICAgIGlmICghbGlzdGVuZXJzW2ldKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICBsaXN0ZW5lcnNbaV0uYXBwbHkodGhpcywgYXJncyk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGlmIChzcGVjaWFsQ2FsbGJhY2tzKSB7XHJcbiAgICAgICAgICAgIGxlbiA9IHNwZWNpYWxDYWxsYmFja3MubGVuZ3RoO1xyXG4gICAgICAgICAgICBsaXN0ZW5lcnMgPSBzcGVjaWFsQ2FsbGJhY2tzLnNsaWNlKCk7XHJcbiAgICAgICAgICAgIGZvciAoaSA9IDAsIGxlbiA9IGxpc3RlbmVycy5sZW5ndGg7IGkgPCBsZW47ICsraSkge1xyXG4gICAgICAgICAgICAgICAgaWYgKCFsaXN0ZW5lcnNbaV0pIHtcclxuICAgICAgICAgICAgICAgICAgICBicmVhaztcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIGxpc3RlbmVyc1tpXS5hcHBseSh0aGlzLCBbZXZlbnRdLmNvbmNhdChhcmdzKSk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHJldHVybiB0aGlzO1xyXG4gICAgfTtcclxuXHJcbiAgICAvLyBIZWxwZXIgZm9yIGZvciBmaW5kaW5nIHNwZWNpYWwgd2lsZGNhcmQgZXZlbnQgaGFuZGxlcnMgdGhhdCBtYXRjaCB0aGUgZXZlbnRcclxuICAgIHByb3RvdHlwZS5nZXRXaWxkY2FyZENhbGxiYWNrcyA9IGZ1bmN0aW9uIChldmVudE5hbWUpIHtcclxuICAgICAgICB0aGlzLmNhbGxiYWNrcyA9IHRoaXMuY2FsbGJhY2tzIHx8IHt9O1xyXG4gICAgICAgIHZhciBpdGVtLFxyXG4gICAgICAgICAgICBzcGxpdCxcclxuICAgICAgICAgICAgcmVzdWx0ID0gW107XHJcblxyXG4gICAgICAgIGZvciAoaXRlbSBpbiB0aGlzLmNhbGxiYWNrcykge1xyXG4gICAgICAgICAgICBzcGxpdCA9IGl0ZW0uc3BsaXQoJyonKTtcclxuICAgICAgICAgICAgaWYgKGl0ZW0gPT09ICcqJyB8fCAoc3BsaXQubGVuZ3RoID09PSAyICYmIGV2ZW50TmFtZS5zbGljZSgwLCBzcGxpdFswXS5sZW5ndGgpID09PSBzcGxpdFswXSkpIHtcclxuICAgICAgICAgICAgICAgIHJlc3VsdCA9IHJlc3VsdC5jb25jYXQodGhpcy5jYWxsYmFja3NbaXRlbV0pO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJldHVybiByZXN1bHQ7XHJcbiAgICB9O1xyXG5cclxufTtcclxuXHJcbldpbGRFbWl0dGVyLm1peGluKFdpbGRFbWl0dGVyKTtcclxuIiwiLyohXG4gKiBFdmVudEVtaXR0ZXIgdjUuMi41IC0gZ2l0LmlvL2VlXG4gKiBVbmxpY2Vuc2UgLSBodHRwOi8vdW5saWNlbnNlLm9yZy9cbiAqIE9saXZlciBDYWxkd2VsbCAtIGh0dHA6Ly9vbGkubWUudWsvXG4gKiBAcHJlc2VydmVcbiAqL1xuXG47KGZ1bmN0aW9uIChleHBvcnRzKSB7XG4gICAgJ3VzZSBzdHJpY3QnO1xuXG4gICAgLyoqXG4gICAgICogQ2xhc3MgZm9yIG1hbmFnaW5nIGV2ZW50cy5cbiAgICAgKiBDYW4gYmUgZXh0ZW5kZWQgdG8gcHJvdmlkZSBldmVudCBmdW5jdGlvbmFsaXR5IGluIG90aGVyIGNsYXNzZXMuXG4gICAgICpcbiAgICAgKiBAY2xhc3MgRXZlbnRFbWl0dGVyIE1hbmFnZXMgZXZlbnQgcmVnaXN0ZXJpbmcgYW5kIGVtaXR0aW5nLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIEV2ZW50RW1pdHRlcigpIHt9XG5cbiAgICAvLyBTaG9ydGN1dHMgdG8gaW1wcm92ZSBzcGVlZCBhbmQgc2l6ZVxuICAgIHZhciBwcm90byA9IEV2ZW50RW1pdHRlci5wcm90b3R5cGU7XG4gICAgdmFyIG9yaWdpbmFsR2xvYmFsVmFsdWUgPSBleHBvcnRzLkV2ZW50RW1pdHRlcjtcblxuICAgIC8qKlxuICAgICAqIEZpbmRzIHRoZSBpbmRleCBvZiB0aGUgbGlzdGVuZXIgZm9yIHRoZSBldmVudCBpbiBpdHMgc3RvcmFnZSBhcnJheS5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb25bXX0gbGlzdGVuZXJzIEFycmF5IG9mIGxpc3RlbmVycyB0byBzZWFyY2ggdGhyb3VnaC5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBsaXN0ZW5lciBNZXRob2QgdG8gbG9vayBmb3IuXG4gICAgICogQHJldHVybiB7TnVtYmVyfSBJbmRleCBvZiB0aGUgc3BlY2lmaWVkIGxpc3RlbmVyLCAtMSBpZiBub3QgZm91bmRcbiAgICAgKiBAYXBpIHByaXZhdGVcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBpbmRleE9mTGlzdGVuZXIobGlzdGVuZXJzLCBsaXN0ZW5lcikge1xuICAgICAgICB2YXIgaSA9IGxpc3RlbmVycy5sZW5ndGg7XG4gICAgICAgIHdoaWxlIChpLS0pIHtcbiAgICAgICAgICAgIGlmIChsaXN0ZW5lcnNbaV0ubGlzdGVuZXIgPT09IGxpc3RlbmVyKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gLTE7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQWxpYXMgYSBtZXRob2Qgd2hpbGUga2VlcGluZyB0aGUgY29udGV4dCBjb3JyZWN0LCB0byBhbGxvdyBmb3Igb3ZlcndyaXRpbmcgb2YgdGFyZ2V0IG1ldGhvZC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfSBuYW1lIFRoZSBuYW1lIG9mIHRoZSB0YXJnZXQgbWV0aG9kLlxuICAgICAqIEByZXR1cm4ge0Z1bmN0aW9ufSBUaGUgYWxpYXNlZCBtZXRob2RcbiAgICAgKiBAYXBpIHByaXZhdGVcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBhbGlhcyhuYW1lKSB7XG4gICAgICAgIHJldHVybiBmdW5jdGlvbiBhbGlhc0Nsb3N1cmUoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpc1tuYW1lXS5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgICAgICB9O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgdGhlIGxpc3RlbmVyIGFycmF5IGZvciB0aGUgc3BlY2lmaWVkIGV2ZW50LlxuICAgICAqIFdpbGwgaW5pdGlhbGlzZSB0aGUgZXZlbnQgb2JqZWN0IGFuZCBsaXN0ZW5lciBhcnJheXMgaWYgcmVxdWlyZWQuXG4gICAgICogV2lsbCByZXR1cm4gYW4gb2JqZWN0IGlmIHlvdSB1c2UgYSByZWdleCBzZWFyY2guIFRoZSBvYmplY3QgY29udGFpbnMga2V5cyBmb3IgZWFjaCBtYXRjaGVkIGV2ZW50LiBTbyAvYmFbcnpdLyBtaWdodCByZXR1cm4gYW4gb2JqZWN0IGNvbnRhaW5pbmcgYmFyIGFuZCBiYXouIEJ1dCBvbmx5IGlmIHlvdSBoYXZlIGVpdGhlciBkZWZpbmVkIHRoZW0gd2l0aCBkZWZpbmVFdmVudCBvciBhZGRlZCBzb21lIGxpc3RlbmVycyB0byB0aGVtLlxuICAgICAqIEVhY2ggcHJvcGVydHkgaW4gdGhlIG9iamVjdCByZXNwb25zZSBpcyBhbiBhcnJheSBvZiBsaXN0ZW5lciBmdW5jdGlvbnMuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1N0cmluZ3xSZWdFeHB9IGV2dCBOYW1lIG9mIHRoZSBldmVudCB0byByZXR1cm4gdGhlIGxpc3RlbmVycyBmcm9tLlxuICAgICAqIEByZXR1cm4ge0Z1bmN0aW9uW118T2JqZWN0fSBBbGwgbGlzdGVuZXIgZnVuY3Rpb25zIGZvciB0aGUgZXZlbnQuXG4gICAgICovXG4gICAgcHJvdG8uZ2V0TGlzdGVuZXJzID0gZnVuY3Rpb24gZ2V0TGlzdGVuZXJzKGV2dCkge1xuICAgICAgICB2YXIgZXZlbnRzID0gdGhpcy5fZ2V0RXZlbnRzKCk7XG4gICAgICAgIHZhciByZXNwb25zZTtcbiAgICAgICAgdmFyIGtleTtcblxuICAgICAgICAvLyBSZXR1cm4gYSBjb25jYXRlbmF0ZWQgYXJyYXkgb2YgYWxsIG1hdGNoaW5nIGV2ZW50cyBpZlxuICAgICAgICAvLyB0aGUgc2VsZWN0b3IgaXMgYSByZWd1bGFyIGV4cHJlc3Npb24uXG4gICAgICAgIGlmIChldnQgaW5zdGFuY2VvZiBSZWdFeHApIHtcbiAgICAgICAgICAgIHJlc3BvbnNlID0ge307XG4gICAgICAgICAgICBmb3IgKGtleSBpbiBldmVudHMpIHtcbiAgICAgICAgICAgICAgICBpZiAoZXZlbnRzLmhhc093blByb3BlcnR5KGtleSkgJiYgZXZ0LnRlc3Qoa2V5KSkge1xuICAgICAgICAgICAgICAgICAgICByZXNwb25zZVtrZXldID0gZXZlbnRzW2tleV07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgcmVzcG9uc2UgPSBldmVudHNbZXZ0XSB8fCAoZXZlbnRzW2V2dF0gPSBbXSk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gcmVzcG9uc2U7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIFRha2VzIGEgbGlzdCBvZiBsaXN0ZW5lciBvYmplY3RzIGFuZCBmbGF0dGVucyBpdCBpbnRvIGEgbGlzdCBvZiBsaXN0ZW5lciBmdW5jdGlvbnMuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge09iamVjdFtdfSBsaXN0ZW5lcnMgUmF3IGxpc3RlbmVyIG9iamVjdHMuXG4gICAgICogQHJldHVybiB7RnVuY3Rpb25bXX0gSnVzdCB0aGUgbGlzdGVuZXIgZnVuY3Rpb25zLlxuICAgICAqL1xuICAgIHByb3RvLmZsYXR0ZW5MaXN0ZW5lcnMgPSBmdW5jdGlvbiBmbGF0dGVuTGlzdGVuZXJzKGxpc3RlbmVycykge1xuICAgICAgICB2YXIgZmxhdExpc3RlbmVycyA9IFtdO1xuICAgICAgICB2YXIgaTtcblxuICAgICAgICBmb3IgKGkgPSAwOyBpIDwgbGlzdGVuZXJzLmxlbmd0aDsgaSArPSAxKSB7XG4gICAgICAgICAgICBmbGF0TGlzdGVuZXJzLnB1c2gobGlzdGVuZXJzW2ldLmxpc3RlbmVyKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBmbGF0TGlzdGVuZXJzO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBGZXRjaGVzIHRoZSByZXF1ZXN0ZWQgbGlzdGVuZXJzIHZpYSBnZXRMaXN0ZW5lcnMgYnV0IHdpbGwgYWx3YXlzIHJldHVybiB0aGUgcmVzdWx0cyBpbnNpZGUgYW4gb2JqZWN0LiBUaGlzIGlzIG1haW5seSBmb3IgaW50ZXJuYWwgdXNlIGJ1dCBvdGhlcnMgbWF5IGZpbmQgaXQgdXNlZnVsLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtTdHJpbmd8UmVnRXhwfSBldnQgTmFtZSBvZiB0aGUgZXZlbnQgdG8gcmV0dXJuIHRoZSBsaXN0ZW5lcnMgZnJvbS5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEFsbCBsaXN0ZW5lciBmdW5jdGlvbnMgZm9yIGFuIGV2ZW50IGluIGFuIG9iamVjdC5cbiAgICAgKi9cbiAgICBwcm90by5nZXRMaXN0ZW5lcnNBc09iamVjdCA9IGZ1bmN0aW9uIGdldExpc3RlbmVyc0FzT2JqZWN0KGV2dCkge1xuICAgICAgICB2YXIgbGlzdGVuZXJzID0gdGhpcy5nZXRMaXN0ZW5lcnMoZXZ0KTtcbiAgICAgICAgdmFyIHJlc3BvbnNlO1xuXG4gICAgICAgIGlmIChsaXN0ZW5lcnMgaW5zdGFuY2VvZiBBcnJheSkge1xuICAgICAgICAgICAgcmVzcG9uc2UgPSB7fTtcbiAgICAgICAgICAgIHJlc3BvbnNlW2V2dF0gPSBsaXN0ZW5lcnM7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gcmVzcG9uc2UgfHwgbGlzdGVuZXJzO1xuICAgIH07XG5cbiAgICBmdW5jdGlvbiBpc1ZhbGlkTGlzdGVuZXIgKGxpc3RlbmVyKSB7XG4gICAgICAgIGlmICh0eXBlb2YgbGlzdGVuZXIgPT09ICdmdW5jdGlvbicgfHwgbGlzdGVuZXIgaW5zdGFuY2VvZiBSZWdFeHApIHtcbiAgICAgICAgICAgIHJldHVybiB0cnVlXG4gICAgICAgIH0gZWxzZSBpZiAobGlzdGVuZXIgJiYgdHlwZW9mIGxpc3RlbmVyID09PSAnb2JqZWN0Jykge1xuICAgICAgICAgICAgcmV0dXJuIGlzVmFsaWRMaXN0ZW5lcihsaXN0ZW5lci5saXN0ZW5lcilcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQWRkcyBhIGxpc3RlbmVyIGZ1bmN0aW9uIHRvIHRoZSBzcGVjaWZpZWQgZXZlbnQuXG4gICAgICogVGhlIGxpc3RlbmVyIHdpbGwgbm90IGJlIGFkZGVkIGlmIGl0IGlzIGEgZHVwbGljYXRlLlxuICAgICAqIElmIHRoZSBsaXN0ZW5lciByZXR1cm5zIHRydWUgdGhlbiBpdCB3aWxsIGJlIHJlbW92ZWQgYWZ0ZXIgaXQgaXMgY2FsbGVkLlxuICAgICAqIElmIHlvdSBwYXNzIGEgcmVndWxhciBleHByZXNzaW9uIGFzIHRoZSBldmVudCBuYW1lIHRoZW4gdGhlIGxpc3RlbmVyIHdpbGwgYmUgYWRkZWQgdG8gYWxsIGV2ZW50cyB0aGF0IG1hdGNoIGl0LlxuICAgICAqXG4gICAgICogQHBhcmFtIHtTdHJpbmd8UmVnRXhwfSBldnQgTmFtZSBvZiB0aGUgZXZlbnQgdG8gYXR0YWNoIHRoZSBsaXN0ZW5lciB0by5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBsaXN0ZW5lciBNZXRob2QgdG8gYmUgY2FsbGVkIHdoZW4gdGhlIGV2ZW50IGlzIGVtaXR0ZWQuIElmIHRoZSBmdW5jdGlvbiByZXR1cm5zIHRydWUgdGhlbiBpdCB3aWxsIGJlIHJlbW92ZWQgYWZ0ZXIgY2FsbGluZy5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEN1cnJlbnQgaW5zdGFuY2Ugb2YgRXZlbnRFbWl0dGVyIGZvciBjaGFpbmluZy5cbiAgICAgKi9cbiAgICBwcm90by5hZGRMaXN0ZW5lciA9IGZ1bmN0aW9uIGFkZExpc3RlbmVyKGV2dCwgbGlzdGVuZXIpIHtcbiAgICAgICAgaWYgKCFpc1ZhbGlkTGlzdGVuZXIobGlzdGVuZXIpKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdsaXN0ZW5lciBtdXN0IGJlIGEgZnVuY3Rpb24nKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBsaXN0ZW5lcnMgPSB0aGlzLmdldExpc3RlbmVyc0FzT2JqZWN0KGV2dCk7XG4gICAgICAgIHZhciBsaXN0ZW5lcklzV3JhcHBlZCA9IHR5cGVvZiBsaXN0ZW5lciA9PT0gJ29iamVjdCc7XG4gICAgICAgIHZhciBrZXk7XG5cbiAgICAgICAgZm9yIChrZXkgaW4gbGlzdGVuZXJzKSB7XG4gICAgICAgICAgICBpZiAobGlzdGVuZXJzLmhhc093blByb3BlcnR5KGtleSkgJiYgaW5kZXhPZkxpc3RlbmVyKGxpc3RlbmVyc1trZXldLCBsaXN0ZW5lcikgPT09IC0xKSB7XG4gICAgICAgICAgICAgICAgbGlzdGVuZXJzW2tleV0ucHVzaChsaXN0ZW5lcklzV3JhcHBlZCA/IGxpc3RlbmVyIDoge1xuICAgICAgICAgICAgICAgICAgICBsaXN0ZW5lcjogbGlzdGVuZXIsXG4gICAgICAgICAgICAgICAgICAgIG9uY2U6IGZhbHNlXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogQWxpYXMgb2YgYWRkTGlzdGVuZXJcbiAgICAgKi9cbiAgICBwcm90by5vbiA9IGFsaWFzKCdhZGRMaXN0ZW5lcicpO1xuXG4gICAgLyoqXG4gICAgICogU2VtaS1hbGlhcyBvZiBhZGRMaXN0ZW5lci4gSXQgd2lsbCBhZGQgYSBsaXN0ZW5lciB0aGF0IHdpbGwgYmVcbiAgICAgKiBhdXRvbWF0aWNhbGx5IHJlbW92ZWQgYWZ0ZXIgaXRzIGZpcnN0IGV4ZWN1dGlvbi5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfFJlZ0V4cH0gZXZ0IE5hbWUgb2YgdGhlIGV2ZW50IHRvIGF0dGFjaCB0aGUgbGlzdGVuZXIgdG8uXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gbGlzdGVuZXIgTWV0aG9kIHRvIGJlIGNhbGxlZCB3aGVuIHRoZSBldmVudCBpcyBlbWl0dGVkLiBJZiB0aGUgZnVuY3Rpb24gcmV0dXJucyB0cnVlIHRoZW4gaXQgd2lsbCBiZSByZW1vdmVkIGFmdGVyIGNhbGxpbmcuXG4gICAgICogQHJldHVybiB7T2JqZWN0fSBDdXJyZW50IGluc3RhbmNlIG9mIEV2ZW50RW1pdHRlciBmb3IgY2hhaW5pbmcuXG4gICAgICovXG4gICAgcHJvdG8uYWRkT25jZUxpc3RlbmVyID0gZnVuY3Rpb24gYWRkT25jZUxpc3RlbmVyKGV2dCwgbGlzdGVuZXIpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuYWRkTGlzdGVuZXIoZXZ0LCB7XG4gICAgICAgICAgICBsaXN0ZW5lcjogbGlzdGVuZXIsXG4gICAgICAgICAgICBvbmNlOiB0cnVlXG4gICAgICAgIH0pO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBBbGlhcyBvZiBhZGRPbmNlTGlzdGVuZXIuXG4gICAgICovXG4gICAgcHJvdG8ub25jZSA9IGFsaWFzKCdhZGRPbmNlTGlzdGVuZXInKTtcblxuICAgIC8qKlxuICAgICAqIERlZmluZXMgYW4gZXZlbnQgbmFtZS4gVGhpcyBpcyByZXF1aXJlZCBpZiB5b3Ugd2FudCB0byB1c2UgYSByZWdleCB0byBhZGQgYSBsaXN0ZW5lciB0byBtdWx0aXBsZSBldmVudHMgYXQgb25jZS4gSWYgeW91IGRvbid0IGRvIHRoaXMgdGhlbiBob3cgZG8geW91IGV4cGVjdCBpdCB0byBrbm93IHdoYXQgZXZlbnQgdG8gYWRkIHRvPyBTaG91bGQgaXQganVzdCBhZGQgdG8gZXZlcnkgcG9zc2libGUgbWF0Y2ggZm9yIGEgcmVnZXg/IE5vLiBUaGF0IGlzIHNjYXJ5IGFuZCBiYWQuXG4gICAgICogWW91IG5lZWQgdG8gdGVsbCBpdCB3aGF0IGV2ZW50IG5hbWVzIHNob3VsZCBiZSBtYXRjaGVkIGJ5IGEgcmVnZXguXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1N0cmluZ30gZXZ0IE5hbWUgb2YgdGhlIGV2ZW50IHRvIGNyZWF0ZS5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEN1cnJlbnQgaW5zdGFuY2Ugb2YgRXZlbnRFbWl0dGVyIGZvciBjaGFpbmluZy5cbiAgICAgKi9cbiAgICBwcm90by5kZWZpbmVFdmVudCA9IGZ1bmN0aW9uIGRlZmluZUV2ZW50KGV2dCkge1xuICAgICAgICB0aGlzLmdldExpc3RlbmVycyhldnQpO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogVXNlcyBkZWZpbmVFdmVudCB0byBkZWZpbmUgbXVsdGlwbGUgZXZlbnRzLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtTdHJpbmdbXX0gZXZ0cyBBbiBhcnJheSBvZiBldmVudCBuYW1lcyB0byBkZWZpbmUuXG4gICAgICogQHJldHVybiB7T2JqZWN0fSBDdXJyZW50IGluc3RhbmNlIG9mIEV2ZW50RW1pdHRlciBmb3IgY2hhaW5pbmcuXG4gICAgICovXG4gICAgcHJvdG8uZGVmaW5lRXZlbnRzID0gZnVuY3Rpb24gZGVmaW5lRXZlbnRzKGV2dHMpIHtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBldnRzLmxlbmd0aDsgaSArPSAxKSB7XG4gICAgICAgICAgICB0aGlzLmRlZmluZUV2ZW50KGV2dHNbaV0pO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBSZW1vdmVzIGEgbGlzdGVuZXIgZnVuY3Rpb24gZnJvbSB0aGUgc3BlY2lmaWVkIGV2ZW50LlxuICAgICAqIFdoZW4gcGFzc2VkIGEgcmVndWxhciBleHByZXNzaW9uIGFzIHRoZSBldmVudCBuYW1lLCBpdCB3aWxsIHJlbW92ZSB0aGUgbGlzdGVuZXIgZnJvbSBhbGwgZXZlbnRzIHRoYXQgbWF0Y2ggaXQuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1N0cmluZ3xSZWdFeHB9IGV2dCBOYW1lIG9mIHRoZSBldmVudCB0byByZW1vdmUgdGhlIGxpc3RlbmVyIGZyb20uXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gbGlzdGVuZXIgTWV0aG9kIHRvIHJlbW92ZSBmcm9tIHRoZSBldmVudC5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEN1cnJlbnQgaW5zdGFuY2Ugb2YgRXZlbnRFbWl0dGVyIGZvciBjaGFpbmluZy5cbiAgICAgKi9cbiAgICBwcm90by5yZW1vdmVMaXN0ZW5lciA9IGZ1bmN0aW9uIHJlbW92ZUxpc3RlbmVyKGV2dCwgbGlzdGVuZXIpIHtcbiAgICAgICAgdmFyIGxpc3RlbmVycyA9IHRoaXMuZ2V0TGlzdGVuZXJzQXNPYmplY3QoZXZ0KTtcbiAgICAgICAgdmFyIGluZGV4O1xuICAgICAgICB2YXIga2V5O1xuXG4gICAgICAgIGZvciAoa2V5IGluIGxpc3RlbmVycykge1xuICAgICAgICAgICAgaWYgKGxpc3RlbmVycy5oYXNPd25Qcm9wZXJ0eShrZXkpKSB7XG4gICAgICAgICAgICAgICAgaW5kZXggPSBpbmRleE9mTGlzdGVuZXIobGlzdGVuZXJzW2tleV0sIGxpc3RlbmVyKTtcblxuICAgICAgICAgICAgICAgIGlmIChpbmRleCAhPT0gLTEpIHtcbiAgICAgICAgICAgICAgICAgICAgbGlzdGVuZXJzW2tleV0uc3BsaWNlKGluZGV4LCAxKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogQWxpYXMgb2YgcmVtb3ZlTGlzdGVuZXJcbiAgICAgKi9cbiAgICBwcm90by5vZmYgPSBhbGlhcygncmVtb3ZlTGlzdGVuZXInKTtcblxuICAgIC8qKlxuICAgICAqIEFkZHMgbGlzdGVuZXJzIGluIGJ1bGsgdXNpbmcgdGhlIG1hbmlwdWxhdGVMaXN0ZW5lcnMgbWV0aG9kLlxuICAgICAqIElmIHlvdSBwYXNzIGFuIG9iamVjdCBhcyB0aGUgZmlyc3QgYXJndW1lbnQgeW91IGNhbiBhZGQgdG8gbXVsdGlwbGUgZXZlbnRzIGF0IG9uY2UuIFRoZSBvYmplY3Qgc2hvdWxkIGNvbnRhaW4ga2V5IHZhbHVlIHBhaXJzIG9mIGV2ZW50cyBhbmQgbGlzdGVuZXJzIG9yIGxpc3RlbmVyIGFycmF5cy4gWW91IGNhbiBhbHNvIHBhc3MgaXQgYW4gZXZlbnQgbmFtZSBhbmQgYW4gYXJyYXkgb2YgbGlzdGVuZXJzIHRvIGJlIGFkZGVkLlxuICAgICAqIFlvdSBjYW4gYWxzbyBwYXNzIGl0IGEgcmVndWxhciBleHByZXNzaW9uIHRvIGFkZCB0aGUgYXJyYXkgb2YgbGlzdGVuZXJzIHRvIGFsbCBldmVudHMgdGhhdCBtYXRjaCBpdC5cbiAgICAgKiBZZWFoLCB0aGlzIGZ1bmN0aW9uIGRvZXMgcXVpdGUgYSBiaXQuIFRoYXQncyBwcm9iYWJseSBhIGJhZCB0aGluZy5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfE9iamVjdHxSZWdFeHB9IGV2dCBBbiBldmVudCBuYW1lIGlmIHlvdSB3aWxsIHBhc3MgYW4gYXJyYXkgb2YgbGlzdGVuZXJzIG5leHQuIEFuIG9iamVjdCBpZiB5b3Ugd2lzaCB0byBhZGQgdG8gbXVsdGlwbGUgZXZlbnRzIGF0IG9uY2UuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbltdfSBbbGlzdGVuZXJzXSBBbiBvcHRpb25hbCBhcnJheSBvZiBsaXN0ZW5lciBmdW5jdGlvbnMgdG8gYWRkLlxuICAgICAqIEByZXR1cm4ge09iamVjdH0gQ3VycmVudCBpbnN0YW5jZSBvZiBFdmVudEVtaXR0ZXIgZm9yIGNoYWluaW5nLlxuICAgICAqL1xuICAgIHByb3RvLmFkZExpc3RlbmVycyA9IGZ1bmN0aW9uIGFkZExpc3RlbmVycyhldnQsIGxpc3RlbmVycykge1xuICAgICAgICAvLyBQYXNzIHRocm91Z2ggdG8gbWFuaXB1bGF0ZUxpc3RlbmVyc1xuICAgICAgICByZXR1cm4gdGhpcy5tYW5pcHVsYXRlTGlzdGVuZXJzKGZhbHNlLCBldnQsIGxpc3RlbmVycyk7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIFJlbW92ZXMgbGlzdGVuZXJzIGluIGJ1bGsgdXNpbmcgdGhlIG1hbmlwdWxhdGVMaXN0ZW5lcnMgbWV0aG9kLlxuICAgICAqIElmIHlvdSBwYXNzIGFuIG9iamVjdCBhcyB0aGUgZmlyc3QgYXJndW1lbnQgeW91IGNhbiByZW1vdmUgZnJvbSBtdWx0aXBsZSBldmVudHMgYXQgb25jZS4gVGhlIG9iamVjdCBzaG91bGQgY29udGFpbiBrZXkgdmFsdWUgcGFpcnMgb2YgZXZlbnRzIGFuZCBsaXN0ZW5lcnMgb3IgbGlzdGVuZXIgYXJyYXlzLlxuICAgICAqIFlvdSBjYW4gYWxzbyBwYXNzIGl0IGFuIGV2ZW50IG5hbWUgYW5kIGFuIGFycmF5IG9mIGxpc3RlbmVycyB0byBiZSByZW1vdmVkLlxuICAgICAqIFlvdSBjYW4gYWxzbyBwYXNzIGl0IGEgcmVndWxhciBleHByZXNzaW9uIHRvIHJlbW92ZSB0aGUgbGlzdGVuZXJzIGZyb20gYWxsIGV2ZW50cyB0aGF0IG1hdGNoIGl0LlxuICAgICAqXG4gICAgICogQHBhcmFtIHtTdHJpbmd8T2JqZWN0fFJlZ0V4cH0gZXZ0IEFuIGV2ZW50IG5hbWUgaWYgeW91IHdpbGwgcGFzcyBhbiBhcnJheSBvZiBsaXN0ZW5lcnMgbmV4dC4gQW4gb2JqZWN0IGlmIHlvdSB3aXNoIHRvIHJlbW92ZSBmcm9tIG11bHRpcGxlIGV2ZW50cyBhdCBvbmNlLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb25bXX0gW2xpc3RlbmVyc10gQW4gb3B0aW9uYWwgYXJyYXkgb2YgbGlzdGVuZXIgZnVuY3Rpb25zIHRvIHJlbW92ZS5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEN1cnJlbnQgaW5zdGFuY2Ugb2YgRXZlbnRFbWl0dGVyIGZvciBjaGFpbmluZy5cbiAgICAgKi9cbiAgICBwcm90by5yZW1vdmVMaXN0ZW5lcnMgPSBmdW5jdGlvbiByZW1vdmVMaXN0ZW5lcnMoZXZ0LCBsaXN0ZW5lcnMpIHtcbiAgICAgICAgLy8gUGFzcyB0aHJvdWdoIHRvIG1hbmlwdWxhdGVMaXN0ZW5lcnNcbiAgICAgICAgcmV0dXJuIHRoaXMubWFuaXB1bGF0ZUxpc3RlbmVycyh0cnVlLCBldnQsIGxpc3RlbmVycyk7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEVkaXRzIGxpc3RlbmVycyBpbiBidWxrLiBUaGUgYWRkTGlzdGVuZXJzIGFuZCByZW1vdmVMaXN0ZW5lcnMgbWV0aG9kcyBib3RoIHVzZSB0aGlzIHRvIGRvIHRoZWlyIGpvYi4gWW91IHNob3VsZCByZWFsbHkgdXNlIHRob3NlIGluc3RlYWQsIHRoaXMgaXMgYSBsaXR0bGUgbG93ZXIgbGV2ZWwuXG4gICAgICogVGhlIGZpcnN0IGFyZ3VtZW50IHdpbGwgZGV0ZXJtaW5lIGlmIHRoZSBsaXN0ZW5lcnMgYXJlIHJlbW92ZWQgKHRydWUpIG9yIGFkZGVkIChmYWxzZSkuXG4gICAgICogSWYgeW91IHBhc3MgYW4gb2JqZWN0IGFzIHRoZSBzZWNvbmQgYXJndW1lbnQgeW91IGNhbiBhZGQvcmVtb3ZlIGZyb20gbXVsdGlwbGUgZXZlbnRzIGF0IG9uY2UuIFRoZSBvYmplY3Qgc2hvdWxkIGNvbnRhaW4ga2V5IHZhbHVlIHBhaXJzIG9mIGV2ZW50cyBhbmQgbGlzdGVuZXJzIG9yIGxpc3RlbmVyIGFycmF5cy5cbiAgICAgKiBZb3UgY2FuIGFsc28gcGFzcyBpdCBhbiBldmVudCBuYW1lIGFuZCBhbiBhcnJheSBvZiBsaXN0ZW5lcnMgdG8gYmUgYWRkZWQvcmVtb3ZlZC5cbiAgICAgKiBZb3UgY2FuIGFsc28gcGFzcyBpdCBhIHJlZ3VsYXIgZXhwcmVzc2lvbiB0byBtYW5pcHVsYXRlIHRoZSBsaXN0ZW5lcnMgb2YgYWxsIGV2ZW50cyB0aGF0IG1hdGNoIGl0LlxuICAgICAqXG4gICAgICogQHBhcmFtIHtCb29sZWFufSByZW1vdmUgVHJ1ZSBpZiB5b3Ugd2FudCB0byByZW1vdmUgbGlzdGVuZXJzLCBmYWxzZSBpZiB5b3Ugd2FudCB0byBhZGQuXG4gICAgICogQHBhcmFtIHtTdHJpbmd8T2JqZWN0fFJlZ0V4cH0gZXZ0IEFuIGV2ZW50IG5hbWUgaWYgeW91IHdpbGwgcGFzcyBhbiBhcnJheSBvZiBsaXN0ZW5lcnMgbmV4dC4gQW4gb2JqZWN0IGlmIHlvdSB3aXNoIHRvIGFkZC9yZW1vdmUgZnJvbSBtdWx0aXBsZSBldmVudHMgYXQgb25jZS5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9uW119IFtsaXN0ZW5lcnNdIEFuIG9wdGlvbmFsIGFycmF5IG9mIGxpc3RlbmVyIGZ1bmN0aW9ucyB0byBhZGQvcmVtb3ZlLlxuICAgICAqIEByZXR1cm4ge09iamVjdH0gQ3VycmVudCBpbnN0YW5jZSBvZiBFdmVudEVtaXR0ZXIgZm9yIGNoYWluaW5nLlxuICAgICAqL1xuICAgIHByb3RvLm1hbmlwdWxhdGVMaXN0ZW5lcnMgPSBmdW5jdGlvbiBtYW5pcHVsYXRlTGlzdGVuZXJzKHJlbW92ZSwgZXZ0LCBsaXN0ZW5lcnMpIHtcbiAgICAgICAgdmFyIGk7XG4gICAgICAgIHZhciB2YWx1ZTtcbiAgICAgICAgdmFyIHNpbmdsZSA9IHJlbW92ZSA/IHRoaXMucmVtb3ZlTGlzdGVuZXIgOiB0aGlzLmFkZExpc3RlbmVyO1xuICAgICAgICB2YXIgbXVsdGlwbGUgPSByZW1vdmUgPyB0aGlzLnJlbW92ZUxpc3RlbmVycyA6IHRoaXMuYWRkTGlzdGVuZXJzO1xuXG4gICAgICAgIC8vIElmIGV2dCBpcyBhbiBvYmplY3QgdGhlbiBwYXNzIGVhY2ggb2YgaXRzIHByb3BlcnRpZXMgdG8gdGhpcyBtZXRob2RcbiAgICAgICAgaWYgKHR5cGVvZiBldnQgPT09ICdvYmplY3QnICYmICEoZXZ0IGluc3RhbmNlb2YgUmVnRXhwKSkge1xuICAgICAgICAgICAgZm9yIChpIGluIGV2dCkge1xuICAgICAgICAgICAgICAgIGlmIChldnQuaGFzT3duUHJvcGVydHkoaSkgJiYgKHZhbHVlID0gZXZ0W2ldKSkge1xuICAgICAgICAgICAgICAgICAgICAvLyBQYXNzIHRoZSBzaW5nbGUgbGlzdGVuZXIgc3RyYWlnaHQgdGhyb3VnaCB0byB0aGUgc2luZ3VsYXIgbWV0aG9kXG4gICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgdmFsdWUgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNpbmdsZS5jYWxsKHRoaXMsIGksIHZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIE90aGVyd2lzZSBwYXNzIGJhY2sgdG8gdGhlIG11bHRpcGxlIGZ1bmN0aW9uXG4gICAgICAgICAgICAgICAgICAgICAgICBtdWx0aXBsZS5jYWxsKHRoaXMsIGksIHZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIC8vIFNvIGV2dCBtdXN0IGJlIGEgc3RyaW5nXG4gICAgICAgICAgICAvLyBBbmQgbGlzdGVuZXJzIG11c3QgYmUgYW4gYXJyYXkgb2YgbGlzdGVuZXJzXG4gICAgICAgICAgICAvLyBMb29wIG92ZXIgaXQgYW5kIHBhc3MgZWFjaCBvbmUgdG8gdGhlIG11bHRpcGxlIG1ldGhvZFxuICAgICAgICAgICAgaSA9IGxpc3RlbmVycy5sZW5ndGg7XG4gICAgICAgICAgICB3aGlsZSAoaS0tKSB7XG4gICAgICAgICAgICAgICAgc2luZ2xlLmNhbGwodGhpcywgZXZ0LCBsaXN0ZW5lcnNbaV0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIFJlbW92ZXMgYWxsIGxpc3RlbmVycyBmcm9tIGEgc3BlY2lmaWVkIGV2ZW50LlxuICAgICAqIElmIHlvdSBkbyBub3Qgc3BlY2lmeSBhbiBldmVudCB0aGVuIGFsbCBsaXN0ZW5lcnMgd2lsbCBiZSByZW1vdmVkLlxuICAgICAqIFRoYXQgbWVhbnMgZXZlcnkgZXZlbnQgd2lsbCBiZSBlbXB0aWVkLlxuICAgICAqIFlvdSBjYW4gYWxzbyBwYXNzIGEgcmVnZXggdG8gcmVtb3ZlIGFsbCBldmVudHMgdGhhdCBtYXRjaCBpdC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfFJlZ0V4cH0gW2V2dF0gT3B0aW9uYWwgbmFtZSBvZiB0aGUgZXZlbnQgdG8gcmVtb3ZlIGFsbCBsaXN0ZW5lcnMgZm9yLiBXaWxsIHJlbW92ZSBmcm9tIGV2ZXJ5IGV2ZW50IGlmIG5vdCBwYXNzZWQuXG4gICAgICogQHJldHVybiB7T2JqZWN0fSBDdXJyZW50IGluc3RhbmNlIG9mIEV2ZW50RW1pdHRlciBmb3IgY2hhaW5pbmcuXG4gICAgICovXG4gICAgcHJvdG8ucmVtb3ZlRXZlbnQgPSBmdW5jdGlvbiByZW1vdmVFdmVudChldnQpIHtcbiAgICAgICAgdmFyIHR5cGUgPSB0eXBlb2YgZXZ0O1xuICAgICAgICB2YXIgZXZlbnRzID0gdGhpcy5fZ2V0RXZlbnRzKCk7XG4gICAgICAgIHZhciBrZXk7XG5cbiAgICAgICAgLy8gUmVtb3ZlIGRpZmZlcmVudCB0aGluZ3MgZGVwZW5kaW5nIG9uIHRoZSBzdGF0ZSBvZiBldnRcbiAgICAgICAgaWYgKHR5cGUgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAvLyBSZW1vdmUgYWxsIGxpc3RlbmVycyBmb3IgdGhlIHNwZWNpZmllZCBldmVudFxuICAgICAgICAgICAgZGVsZXRlIGV2ZW50c1tldnRdO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKGV2dCBpbnN0YW5jZW9mIFJlZ0V4cCkge1xuICAgICAgICAgICAgLy8gUmVtb3ZlIGFsbCBldmVudHMgbWF0Y2hpbmcgdGhlIHJlZ2V4LlxuICAgICAgICAgICAgZm9yIChrZXkgaW4gZXZlbnRzKSB7XG4gICAgICAgICAgICAgICAgaWYgKGV2ZW50cy5oYXNPd25Qcm9wZXJ0eShrZXkpICYmIGV2dC50ZXN0KGtleSkpIHtcbiAgICAgICAgICAgICAgICAgICAgZGVsZXRlIGV2ZW50c1trZXldO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIC8vIFJlbW92ZSBhbGwgbGlzdGVuZXJzIGluIGFsbCBldmVudHNcbiAgICAgICAgICAgIGRlbGV0ZSB0aGlzLl9ldmVudHM7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogQWxpYXMgb2YgcmVtb3ZlRXZlbnQuXG4gICAgICpcbiAgICAgKiBBZGRlZCB0byBtaXJyb3IgdGhlIG5vZGUgQVBJLlxuICAgICAqL1xuICAgIHByb3RvLnJlbW92ZUFsbExpc3RlbmVycyA9IGFsaWFzKCdyZW1vdmVFdmVudCcpO1xuXG4gICAgLyoqXG4gICAgICogRW1pdHMgYW4gZXZlbnQgb2YgeW91ciBjaG9pY2UuXG4gICAgICogV2hlbiBlbWl0dGVkLCBldmVyeSBsaXN0ZW5lciBhdHRhY2hlZCB0byB0aGF0IGV2ZW50IHdpbGwgYmUgZXhlY3V0ZWQuXG4gICAgICogSWYgeW91IHBhc3MgdGhlIG9wdGlvbmFsIGFyZ3VtZW50IGFycmF5IHRoZW4gdGhvc2UgYXJndW1lbnRzIHdpbGwgYmUgcGFzc2VkIHRvIGV2ZXJ5IGxpc3RlbmVyIHVwb24gZXhlY3V0aW9uLlxuICAgICAqIEJlY2F1c2UgaXQgdXNlcyBgYXBwbHlgLCB5b3VyIGFycmF5IG9mIGFyZ3VtZW50cyB3aWxsIGJlIHBhc3NlZCBhcyBpZiB5b3Ugd3JvdGUgdGhlbSBvdXQgc2VwYXJhdGVseS5cbiAgICAgKiBTbyB0aGV5IHdpbGwgbm90IGFycml2ZSB3aXRoaW4gdGhlIGFycmF5IG9uIHRoZSBvdGhlciBzaWRlLCB0aGV5IHdpbGwgYmUgc2VwYXJhdGUuXG4gICAgICogWW91IGNhbiBhbHNvIHBhc3MgYSByZWd1bGFyIGV4cHJlc3Npb24gdG8gZW1pdCB0byBhbGwgZXZlbnRzIHRoYXQgbWF0Y2ggaXQuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1N0cmluZ3xSZWdFeHB9IGV2dCBOYW1lIG9mIHRoZSBldmVudCB0byBlbWl0IGFuZCBleGVjdXRlIGxpc3RlbmVycyBmb3IuXG4gICAgICogQHBhcmFtIHtBcnJheX0gW2FyZ3NdIE9wdGlvbmFsIGFycmF5IG9mIGFyZ3VtZW50cyB0byBiZSBwYXNzZWQgdG8gZWFjaCBsaXN0ZW5lci5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEN1cnJlbnQgaW5zdGFuY2Ugb2YgRXZlbnRFbWl0dGVyIGZvciBjaGFpbmluZy5cbiAgICAgKi9cbiAgICBwcm90by5lbWl0RXZlbnQgPSBmdW5jdGlvbiBlbWl0RXZlbnQoZXZ0LCBhcmdzKSB7XG4gICAgICAgIHZhciBsaXN0ZW5lcnNNYXAgPSB0aGlzLmdldExpc3RlbmVyc0FzT2JqZWN0KGV2dCk7XG4gICAgICAgIHZhciBsaXN0ZW5lcnM7XG4gICAgICAgIHZhciBsaXN0ZW5lcjtcbiAgICAgICAgdmFyIGk7XG4gICAgICAgIHZhciBrZXk7XG4gICAgICAgIHZhciByZXNwb25zZTtcblxuICAgICAgICBmb3IgKGtleSBpbiBsaXN0ZW5lcnNNYXApIHtcbiAgICAgICAgICAgIGlmIChsaXN0ZW5lcnNNYXAuaGFzT3duUHJvcGVydHkoa2V5KSkge1xuICAgICAgICAgICAgICAgIGxpc3RlbmVycyA9IGxpc3RlbmVyc01hcFtrZXldLnNsaWNlKDApO1xuXG4gICAgICAgICAgICAgICAgZm9yIChpID0gMDsgaSA8IGxpc3RlbmVycy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAvLyBJZiB0aGUgbGlzdGVuZXIgcmV0dXJucyB0cnVlIHRoZW4gaXQgc2hhbGwgYmUgcmVtb3ZlZCBmcm9tIHRoZSBldmVudFxuICAgICAgICAgICAgICAgICAgICAvLyBUaGUgZnVuY3Rpb24gaXMgZXhlY3V0ZWQgZWl0aGVyIHdpdGggYSBiYXNpYyBjYWxsIG9yIGFuIGFwcGx5IGlmIHRoZXJlIGlzIGFuIGFyZ3MgYXJyYXlcbiAgICAgICAgICAgICAgICAgICAgbGlzdGVuZXIgPSBsaXN0ZW5lcnNbaV07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGxpc3RlbmVyLm9uY2UgPT09IHRydWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucmVtb3ZlTGlzdGVuZXIoZXZ0LCBsaXN0ZW5lci5saXN0ZW5lcik7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICByZXNwb25zZSA9IGxpc3RlbmVyLmxpc3RlbmVyLmFwcGx5KHRoaXMsIGFyZ3MgfHwgW10pO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChyZXNwb25zZSA9PT0gdGhpcy5fZ2V0T25jZVJldHVyblZhbHVlKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucmVtb3ZlTGlzdGVuZXIoZXZ0LCBsaXN0ZW5lci5saXN0ZW5lcik7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogQWxpYXMgb2YgZW1pdEV2ZW50XG4gICAgICovXG4gICAgcHJvdG8udHJpZ2dlciA9IGFsaWFzKCdlbWl0RXZlbnQnKTtcblxuICAgIC8qKlxuICAgICAqIFN1YnRseSBkaWZmZXJlbnQgZnJvbSBlbWl0RXZlbnQgaW4gdGhhdCBpdCB3aWxsIHBhc3MgaXRzIGFyZ3VtZW50cyBvbiB0byB0aGUgbGlzdGVuZXJzLCBhcyBvcHBvc2VkIHRvIHRha2luZyBhIHNpbmdsZSBhcnJheSBvZiBhcmd1bWVudHMgdG8gcGFzcyBvbi5cbiAgICAgKiBBcyB3aXRoIGVtaXRFdmVudCwgeW91IGNhbiBwYXNzIGEgcmVnZXggaW4gcGxhY2Ugb2YgdGhlIGV2ZW50IG5hbWUgdG8gZW1pdCB0byBhbGwgZXZlbnRzIHRoYXQgbWF0Y2ggaXQuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1N0cmluZ3xSZWdFeHB9IGV2dCBOYW1lIG9mIHRoZSBldmVudCB0byBlbWl0IGFuZCBleGVjdXRlIGxpc3RlbmVycyBmb3IuXG4gICAgICogQHBhcmFtIHsuLi4qfSBPcHRpb25hbCBhZGRpdGlvbmFsIGFyZ3VtZW50cyB0byBiZSBwYXNzZWQgdG8gZWFjaCBsaXN0ZW5lci5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEN1cnJlbnQgaW5zdGFuY2Ugb2YgRXZlbnRFbWl0dGVyIGZvciBjaGFpbmluZy5cbiAgICAgKi9cbiAgICBwcm90by5lbWl0ID0gZnVuY3Rpb24gZW1pdChldnQpIHtcbiAgICAgICAgdmFyIGFyZ3MgPSBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMsIDEpO1xuICAgICAgICByZXR1cm4gdGhpcy5lbWl0RXZlbnQoZXZ0LCBhcmdzKTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogU2V0cyB0aGUgY3VycmVudCB2YWx1ZSB0byBjaGVjayBhZ2FpbnN0IHdoZW4gZXhlY3V0aW5nIGxpc3RlbmVycy4gSWYgYVxuICAgICAqIGxpc3RlbmVycyByZXR1cm4gdmFsdWUgbWF0Y2hlcyB0aGUgb25lIHNldCBoZXJlIHRoZW4gaXQgd2lsbCBiZSByZW1vdmVkXG4gICAgICogYWZ0ZXIgZXhlY3V0aW9uLiBUaGlzIHZhbHVlIGRlZmF1bHRzIHRvIHRydWUuXG4gICAgICpcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSBuZXcgdmFsdWUgdG8gY2hlY2sgZm9yIHdoZW4gZXhlY3V0aW5nIGxpc3RlbmVycy5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEN1cnJlbnQgaW5zdGFuY2Ugb2YgRXZlbnRFbWl0dGVyIGZvciBjaGFpbmluZy5cbiAgICAgKi9cbiAgICBwcm90by5zZXRPbmNlUmV0dXJuVmFsdWUgPSBmdW5jdGlvbiBzZXRPbmNlUmV0dXJuVmFsdWUodmFsdWUpIHtcbiAgICAgICAgdGhpcy5fb25jZVJldHVyblZhbHVlID0gdmFsdWU7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBGZXRjaGVzIHRoZSBjdXJyZW50IHZhbHVlIHRvIGNoZWNrIGFnYWluc3Qgd2hlbiBleGVjdXRpbmcgbGlzdGVuZXJzLiBJZlxuICAgICAqIHRoZSBsaXN0ZW5lcnMgcmV0dXJuIHZhbHVlIG1hdGNoZXMgdGhpcyBvbmUgdGhlbiBpdCBzaG91bGQgYmUgcmVtb3ZlZFxuICAgICAqIGF1dG9tYXRpY2FsbHkuIEl0IHdpbGwgcmV0dXJuIHRydWUgYnkgZGVmYXVsdC5cbiAgICAgKlxuICAgICAqIEByZXR1cm4geyp8Qm9vbGVhbn0gVGhlIGN1cnJlbnQgdmFsdWUgdG8gY2hlY2sgZm9yIG9yIHRoZSBkZWZhdWx0LCB0cnVlLlxuICAgICAqIEBhcGkgcHJpdmF0ZVxuICAgICAqL1xuICAgIHByb3RvLl9nZXRPbmNlUmV0dXJuVmFsdWUgPSBmdW5jdGlvbiBfZ2V0T25jZVJldHVyblZhbHVlKCkge1xuICAgICAgICBpZiAodGhpcy5oYXNPd25Qcm9wZXJ0eSgnX29uY2VSZXR1cm5WYWx1ZScpKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5fb25jZVJldHVyblZhbHVlO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogRmV0Y2hlcyB0aGUgZXZlbnRzIG9iamVjdCBhbmQgY3JlYXRlcyBvbmUgaWYgcmVxdWlyZWQuXG4gICAgICpcbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IFRoZSBldmVudHMgc3RvcmFnZSBvYmplY3QuXG4gICAgICogQGFwaSBwcml2YXRlXG4gICAgICovXG4gICAgcHJvdG8uX2dldEV2ZW50cyA9IGZ1bmN0aW9uIF9nZXRFdmVudHMoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9ldmVudHMgfHwgKHRoaXMuX2V2ZW50cyA9IHt9KTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogUmV2ZXJ0cyB0aGUgZ2xvYmFsIHtAbGluayBFdmVudEVtaXR0ZXJ9IHRvIGl0cyBwcmV2aW91cyB2YWx1ZSBhbmQgcmV0dXJucyBhIHJlZmVyZW5jZSB0byB0aGlzIHZlcnNpb24uXG4gICAgICpcbiAgICAgKiBAcmV0dXJuIHtGdW5jdGlvbn0gTm9uIGNvbmZsaWN0aW5nIEV2ZW50RW1pdHRlciBjbGFzcy5cbiAgICAgKi9cbiAgICBFdmVudEVtaXR0ZXIubm9Db25mbGljdCA9IGZ1bmN0aW9uIG5vQ29uZmxpY3QoKSB7XG4gICAgICAgIGV4cG9ydHMuRXZlbnRFbWl0dGVyID0gb3JpZ2luYWxHbG9iYWxWYWx1ZTtcbiAgICAgICAgcmV0dXJuIEV2ZW50RW1pdHRlcjtcbiAgICB9O1xuXG4gICAgLy8gRXhwb3NlIHRoZSBjbGFzcyBlaXRoZXIgdmlhIEFNRCwgQ29tbW9uSlMgb3IgdGhlIGdsb2JhbCBvYmplY3RcbiAgICBpZiAodHlwZW9mIGRlZmluZSA9PT0gJ2Z1bmN0aW9uJyAmJiBkZWZpbmUuYW1kKSB7XG4gICAgICAgIGRlZmluZShmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gRXZlbnRFbWl0dGVyO1xuICAgICAgICB9KTtcbiAgICB9XG4gICAgZWxzZSBpZiAodHlwZW9mIG1vZHVsZSA9PT0gJ29iamVjdCcgJiYgbW9kdWxlLmV4cG9ydHMpe1xuICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IEV2ZW50RW1pdHRlcjtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIGV4cG9ydHMuRXZlbnRFbWl0dGVyID0gRXZlbnRFbWl0dGVyO1xuICAgIH1cbn0odHlwZW9mIHdpbmRvdyAhPT0gJ3VuZGVmaW5lZCcgPyB3aW5kb3cgOiB0aGlzIHx8IHt9KSk7XG4iLCJpbXBvcnQgeyBPcGVuVmlkdSB9IGZyb20gJy4vT3BlblZpZHUvT3BlblZpZHUnO1xuXG5pZiAod2luZG93KSB7XG4gICAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lOm5vLXN0cmluZy1saXRlcmFsXG4gICAgd2luZG93WydPcGVuVmlkdSddID0gT3BlblZpZHU7XG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBTZXNzaW9uIH0gZnJvbSAnLi9TZXNzaW9uJztcbmltcG9ydCB7IFN0cmVhbSB9IGZyb20gJy4vU3RyZWFtJztcbmltcG9ydCB7IENvbm5lY3Rpb25PcHRpb25zIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9JbnRlcmZhY2VzL1ByaXZhdGUvQ29ubmVjdGlvbk9wdGlvbnMnO1xuaW1wb3J0IHsgSW5ib3VuZFN0cmVhbU9wdGlvbnMgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHJpdmF0ZS9JbmJvdW5kU3RyZWFtT3B0aW9ucyc7XG5pbXBvcnQgeyBTdHJlYW1PcHRpb25zU2VydmVyIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9JbnRlcmZhY2VzL1ByaXZhdGUvU3RyZWFtT3B0aW9uc1NlcnZlcic7XG5cblxuLyoqXG4gKiBSZXByZXNlbnRzIGVhY2ggb25lIG9mIHRoZSB1c2VyJ3MgY29ubmVjdGlvbiB0byB0aGUgc2Vzc2lvbiAodGhlIGxvY2FsIG9uZSBhbmQgb3RoZXIgdXNlcidzIGNvbm5lY3Rpb25zKS5cbiAqIFRoZXJlZm9yZSBlYWNoIFtbU2Vzc2lvbl1dIGFuZCBbW1N0cmVhbV1dIG9iamVjdCBoYXMgYW4gYXR0cmlidXRlIG9mIHR5cGUgQ29ubmVjdGlvblxuICovXG5leHBvcnQgY2xhc3MgQ29ubmVjdGlvbiB7XG5cbiAgICAvKipcbiAgICAgKiBVbmlxdWUgaWRlbnRpZmllciBvZiB0aGUgY29ubmVjdGlvblxuICAgICAqL1xuICAgIGNvbm5lY3Rpb25JZDogc3RyaW5nO1xuXG4gICAgLyoqXG4gICAgICogVGltZSB3aGVuIHRoaXMgY29ubmVjdGlvbiB3YXMgY3JlYXRlZCAoVVRDIG1pbGxpc2Vjb25kcylcbiAgICAgKi9cbiAgICBjcmVhdGlvblRpbWU6IG51bWJlcjtcblxuICAgIC8qKlxuICAgICAqIERhdGEgYXNzb2NpYXRlZCB0byB0aGlzIGNvbm5lY3Rpb24gKGFuZCB0aGVyZWZvcmUgdG8gY2VydGFpbiB1c2VyKS4gVGhpcyBpcyBhbiBpbXBvcnRhbnQgZmllbGQ6XG4gICAgICogaXQgYWxsb3dzIHlvdSB0byBicm9hZGNhc3QgYWxsIHRoZSBpbmZvcm1hdGlvbiB5b3Ugd2FudCBmb3IgZWFjaCB1c2VyIChhIHVzZXJuYW1lLCBmb3IgZXhhbXBsZSlcbiAgICAgKi9cbiAgICBkYXRhOiBzdHJpbmc7XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgc3RyZWFtOiBTdHJlYW07XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgb3B0aW9uczogQ29ubmVjdGlvbk9wdGlvbnMgfCB1bmRlZmluZWQ7XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgZGlzcG9zZWQgPSBmYWxzZTtcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3Rvcihwcml2YXRlIHNlc3Npb246IFNlc3Npb24sIG9wdHM/OiBDb25uZWN0aW9uT3B0aW9ucykge1xuXG4gICAgICAgIGxldCBtc2cgPSBcIidDb25uZWN0aW9uJyBjcmVhdGVkIFwiO1xuICAgICAgICBpZiAoISFvcHRzKSB7XG4gICAgICAgICAgICBtc2cgKz0gXCIocmVtb3RlKSB3aXRoICdjb25uZWN0aW9uSWQnIFtcIiArIG9wdHMuaWQgKyAnXSc7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBtc2cgKz0gJyhsb2NhbCknO1xuICAgICAgICB9XG4gICAgICAgIGNvbnNvbGUuaW5mbyhtc2cpO1xuXG4gICAgICAgIHRoaXMub3B0aW9ucyA9IG9wdHM7XG5cbiAgICAgICAgaWYgKCEhb3B0cykge1xuICAgICAgICAgICAgLy8gQ29ubmVjdGlvbiBpcyByZW1vdGVcbiAgICAgICAgICAgIHRoaXMuY29ubmVjdGlvbklkID0gb3B0cy5pZDtcbiAgICAgICAgICAgIGlmIChvcHRzLm1ldGFkYXRhKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5kYXRhID0gb3B0cy5tZXRhZGF0YTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChvcHRzLnN0cmVhbXMpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmluaXRSZW1vdGVTdHJlYW1zKG9wdHMuc3RyZWFtcyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLmNyZWF0aW9uVGltZSA9IG5ldyBEYXRlKCkuZ2V0VGltZSgpO1xuICAgIH1cblxuXG4gICAgLyogSGlkZGVuIG1ldGhvZHMgKi9cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBzZW5kSWNlQ2FuZGlkYXRlKGNhbmRpZGF0ZTogUlRDSWNlQ2FuZGlkYXRlKTogdm9pZCB7XG5cbiAgICAgICAgY29uc29sZS5kZWJ1ZygoISF0aGlzLnN0cmVhbS5vdXRib3VuZFN0cmVhbU9wdHMgPyAnTG9jYWwnIDogJ1JlbW90ZScpLCAnY2FuZGlkYXRlIGZvcicsXG4gICAgICAgICAgICB0aGlzLmNvbm5lY3Rpb25JZCwgSlNPTi5zdHJpbmdpZnkoY2FuZGlkYXRlKSk7XG5cbiAgICAgICAgdGhpcy5zZXNzaW9uLm9wZW52aWR1LnNlbmRSZXF1ZXN0KCdvbkljZUNhbmRpZGF0ZScsIHtcbiAgICAgICAgICAgIGVuZHBvaW50TmFtZTogdGhpcy5jb25uZWN0aW9uSWQsXG4gICAgICAgICAgICBjYW5kaWRhdGU6IGNhbmRpZGF0ZS5jYW5kaWRhdGUsXG4gICAgICAgICAgICBzZHBNaWQ6IGNhbmRpZGF0ZS5zZHBNaWQsXG4gICAgICAgICAgICBzZHBNTGluZUluZGV4OiBjYW5kaWRhdGUuc2RwTUxpbmVJbmRleFxuICAgICAgICB9LCAoZXJyb3IsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICBpZiAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKCdFcnJvciBzZW5kaW5nIElDRSBjYW5kaWRhdGU6ICdcbiAgICAgICAgICAgICAgICAgICAgKyBKU09OLnN0cmluZ2lmeShlcnJvcikpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgaW5pdFJlbW90ZVN0cmVhbXMob3B0aW9uczogU3RyZWFtT3B0aW9uc1NlcnZlcltdKTogdm9pZCB7XG5cbiAgICAgICAgLy8gVGhpcyBpcyByZWFkeSBmb3Igc3VwcG9ydGluZyBtdWx0aXBsZSBzdHJlYW1zIHBlciBDb25uZWN0aW9uIG9iamVjdC4gUmlnaHQgbm93IHRoZSBsb29wIHdpbGwgYWx3YXlzIHJ1biBqdXN0IG9uY2VcbiAgICAgICAgLy8gdGhpcy5zdHJlYW0gc2hvdWxkIGFsc28gYmUgcmVwbGFjZWQgYnkgYSBjb2xsZWN0aW9uIG9mIHN0cmVhbXMgdG8gc3VwcG9ydCBtdWx0aXBsZSBzdHJlYW1zIHBlciBDb25uZWN0aW9uXG4gICAgICAgIG9wdGlvbnMuZm9yRWFjaChvcHRzID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHN0cmVhbU9wdGlvbnM6IEluYm91bmRTdHJlYW1PcHRpb25zID0ge1xuICAgICAgICAgICAgICAgIGlkOiBvcHRzLmlkLFxuICAgICAgICAgICAgICAgIGNvbm5lY3Rpb246IHRoaXMsXG4gICAgICAgICAgICAgICAgaGFzQXVkaW86IG9wdHMuaGFzQXVkaW8sXG4gICAgICAgICAgICAgICAgaGFzVmlkZW86IG9wdHMuaGFzVmlkZW8sXG4gICAgICAgICAgICAgICAgYXVkaW9BY3RpdmU6IG9wdHMuYXVkaW9BY3RpdmUsXG4gICAgICAgICAgICAgICAgdmlkZW9BY3RpdmU6IG9wdHMudmlkZW9BY3RpdmUsXG4gICAgICAgICAgICAgICAgdHlwZU9mVmlkZW86IG9wdHMudHlwZU9mVmlkZW8sXG4gICAgICAgICAgICAgICAgZnJhbWVSYXRlOiBvcHRzLmZyYW1lUmF0ZSxcbiAgICAgICAgICAgICAgICB2aWRlb0RpbWVuc2lvbnM6ICEhb3B0cy52aWRlb0RpbWVuc2lvbnMgPyBKU09OLnBhcnNlKG9wdHMudmlkZW9EaW1lbnNpb25zKSA6IHVuZGVmaW5lZFxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGNvbnN0IHN0cmVhbSA9IG5ldyBTdHJlYW0odGhpcy5zZXNzaW9uLCBzdHJlYW1PcHRpb25zKTtcblxuICAgICAgICAgICAgdGhpcy5hZGRTdHJlYW0oc3RyZWFtKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgY29uc29sZS5pbmZvKFwiUmVtb3RlICdDb25uZWN0aW9uJyB3aXRoICdjb25uZWN0aW9uSWQnIFtcIiArIHRoaXMuY29ubmVjdGlvbklkICsgJ10gaXMgbm93IGNvbmZpZ3VyZWQgZm9yIHJlY2VpdmluZyBTdHJlYW1zIHdpdGggb3B0aW9uczogJywgdGhpcy5zdHJlYW0uaW5ib3VuZFN0cmVhbU9wdHMpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBhZGRTdHJlYW0oc3RyZWFtOiBTdHJlYW0pOiB2b2lkIHtcbiAgICAgICAgc3RyZWFtLmNvbm5lY3Rpb24gPSB0aGlzO1xuICAgICAgICB0aGlzLnN0cmVhbSA9IHN0cmVhbTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgcmVtb3ZlU3RyZWFtKHN0cmVhbUlkOiBzdHJpbmcpOiB2b2lkIHtcbiAgICAgICAgZGVsZXRlIHRoaXMuc3RyZWFtO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBkaXNwb3NlKCk6IHZvaWQge1xuICAgICAgICBpZiAoISF0aGlzLnN0cmVhbSkge1xuICAgICAgICAgICAgZGVsZXRlIHRoaXMuc3RyZWFtO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuZGlzcG9zZWQgPSB0cnVlO1xuICAgIH1cblxufSIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTctMjAxOCBPcGVuVmlkdSAoaHR0cHM6Ly9vcGVudmlkdS5pby8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuaW1wb3J0IHsgU3RyZWFtIH0gZnJvbSAnLi9TdHJlYW0nO1xuaW1wb3J0IHsgTG9jYWxSZWNvcmRlclN0YXRlIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FbnVtcy9Mb2NhbFJlY29yZGVyU3RhdGUnO1xuXG4vKipcbiAqIEBoaWRkZW5cbiAqL1xuZGVjbGFyZSB2YXIgTWVkaWFSZWNvcmRlcjogYW55O1xuXG5cbi8qKlxuICogRWFzeSByZWNvcmRpbmcgb2YgW1tTdHJlYW1dXSBvYmplY3RzIHN0cmFpZ2h0YXdheSBmcm9tIHRoZSBicm93c2VyLlxuICpcbiAqID4gV0FSTklORzogUGVyZm9ybWluZyBicm93c2VyIGxvY2FsIHJlY29yZGluZyBvZiAqKnJlbW90ZSBzdHJlYW1zKiogbWF5IGNhdXNlIHNvbWUgdHJvdWJsZXMuIEEgbG9uZyB3YWl0aW5nIHRpbWUgbWF5IGJlIHJlcXVpcmVkIGFmdGVyIGNhbGxpbmcgX0xvY2FsUmVjb3JkZXIuc3RvcCgpXyBpbiB0aGlzIGNhc2VcbiAqL1xuZXhwb3J0IGNsYXNzIExvY2FsUmVjb3JkZXIge1xuXG4gICAgc3RhdGU6IExvY2FsUmVjb3JkZXJTdGF0ZTtcblxuICAgIHByaXZhdGUgY29ubmVjdGlvbklkOiBzdHJpbmc7XG4gICAgcHJpdmF0ZSBtZWRpYVJlY29yZGVyOiBhbnk7XG4gICAgcHJpdmF0ZSBjaHVua3M6IGFueVtdID0gW107XG4gICAgcHJpdmF0ZSBibG9iOiBCbG9iO1xuICAgIHByaXZhdGUgY291bnQgPSAwO1xuICAgIHByaXZhdGUgaWQ6IHN0cmluZztcbiAgICBwcml2YXRlIHZpZGVvUHJldmlld1NyYzogc3RyaW5nO1xuICAgIHByaXZhdGUgaHRtbFBhcmVudEVsZW1lbnRJZDogc3RyaW5nO1xuICAgIHByaXZhdGUgdmlkZW9QcmV2aWV3OiBIVE1MVmlkZW9FbGVtZW50O1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHByaXZhdGUgc3RyZWFtOiBTdHJlYW0pIHtcbiAgICAgICAgdGhpcy5jb25uZWN0aW9uSWQgPSAoISF0aGlzLnN0cmVhbS5jb25uZWN0aW9uKSA/IHRoaXMuc3RyZWFtLmNvbm5lY3Rpb24uY29ubmVjdGlvbklkIDogJ2RlZmF1bHQtY29ubmVjdGlvbic7XG4gICAgICAgIHRoaXMuaWQgPSB0aGlzLnN0cmVhbS5zdHJlYW1JZCArICdfJyArIHRoaXMuY29ubmVjdGlvbklkICsgJ19sb2NhbHJlY29yZCc7XG4gICAgICAgIHRoaXMuc3RhdGUgPSBMb2NhbFJlY29yZGVyU3RhdGUuUkVBRFk7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBTdGFydHMgdGhlIHJlY29yZGluZyBvZiB0aGUgU3RyZWFtLiBbW3N0YXRlXV0gcHJvcGVydHkgbXVzdCBiZSBgUkVBRFlgLiBBZnRlciBtZXRob2Qgc3VjY2VlZHMgaXMgc2V0IHRvIGBSRUNPUkRJTkdgXG4gICAgICogQHJldHVybnMgQSBQcm9taXNlICh0byB3aGljaCB5b3UgY2FuIG9wdGlvbmFsbHkgc3Vic2NyaWJlIHRvKSB0aGF0IGlzIHJlc29sdmVkIGlmIHRoZSByZWNvcmRpbmcgc3VjY2Vzc2Z1bGx5IHN0YXJ0ZWQgYW5kIHJlamVjdGVkIHdpdGggYW4gRXJyb3Igb2JqZWN0IGlmIG5vdFxuICAgICAqL1xuICAgIHJlY29yZCgpOiBQcm9taXNlPGFueT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuXG4gICAgICAgICAgICB0cnkge1xuXG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBNZWRpYVJlY29yZGVyID09PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKCdNZWRpYVJlY29yZGVyIG5vdCBzdXBwb3J0ZWQgb24geW91ciBicm93c2VyLiBTZWUgY29tcGF0aWJpbGl0eSBpbiBodHRwczovL2Nhbml1c2UuY29tLyNzZWFyY2g9TWVkaWFSZWNvcmRlcicpO1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyAoRXJyb3IoJ01lZGlhUmVjb3JkZXIgbm90IHN1cHBvcnRlZCBvbiB5b3VyIGJyb3dzZXIuIFNlZSBjb21wYXRpYmlsaXR5IGluIGh0dHBzOi8vY2FuaXVzZS5jb20vI3NlYXJjaD1NZWRpYVJlY29yZGVyJykpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAodGhpcy5zdGF0ZSAhPT0gTG9jYWxSZWNvcmRlclN0YXRlLlJFQURZKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IChFcnJvcignXFwnTG9jYWxSZWNvcmQucmVjb3JkKClcXCcgbmVlZHMgXFwnTG9jYWxSZWNvcmQuc3RhdGVcXCcgdG8gYmUgXFwnUkVBRFlcXCcgKGN1cnJlbnQgdmFsdWU6IFxcJycgKyB0aGlzLnN0YXRlICsgJ1xcJykuIENhbGwgXFwnTG9jYWxSZWNvcmRlci5jbGVhbigpXFwnIG9yIGluaXQgYSBuZXcgTG9jYWxSZWNvcmRlciBiZWZvcmUnKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKFwiU3RhcnRpbmcgbG9jYWwgcmVjb3JkaW5nIG9mIHN0cmVhbSAnXCIgKyB0aGlzLnN0cmVhbS5zdHJlYW1JZCArIFwiJyBvZiBjb25uZWN0aW9uICdcIiArIHRoaXMuY29ubmVjdGlvbklkICsgXCInXCIpO1xuXG5cbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIE1lZGlhUmVjb3JkZXIuaXNUeXBlU3VwcG9ydGVkID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICAgICAgICAgIGxldCBvcHRpb25zO1xuICAgICAgICAgICAgICAgICAgICBpZiAoTWVkaWFSZWNvcmRlci5pc1R5cGVTdXBwb3J0ZWQoJ3ZpZGVvL3dlYm07Y29kZWNzPXZwOScpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBvcHRpb25zID0geyBtaW1lVHlwZTogJ3ZpZGVvL3dlYm07Y29kZWNzPXZwOScgfTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChNZWRpYVJlY29yZGVyLmlzVHlwZVN1cHBvcnRlZCgndmlkZW8vd2VibTtjb2RlY3M9aDI2NCcpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBvcHRpb25zID0geyBtaW1lVHlwZTogJ3ZpZGVvL3dlYm07Y29kZWNzPWgyNjQnIH07XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoTWVkaWFSZWNvcmRlci5pc1R5cGVTdXBwb3J0ZWQoJ3ZpZGVvL3dlYm07Y29kZWNzPXZwOCcpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBvcHRpb25zID0geyBtaW1lVHlwZTogJ3ZpZGVvL3dlYm07Y29kZWNzPXZwOCcgfTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmxvZygnVXNpbmcgbWltZVR5cGUgJyArIG9wdGlvbnMubWltZVR5cGUpO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLm1lZGlhUmVjb3JkZXIgPSBuZXcgTWVkaWFSZWNvcmRlcih0aGlzLnN0cmVhbS5nZXRNZWRpYVN0cmVhbSgpLCBvcHRpb25zKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLndhcm4oJ2lzVHlwZVN1cHBvcnRlZCBpcyBub3Qgc3VwcG9ydGVkLCB1c2luZyBkZWZhdWx0IGNvZGVjcyBmb3IgYnJvd3NlcicpO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLm1lZGlhUmVjb3JkZXIgPSBuZXcgTWVkaWFSZWNvcmRlcih0aGlzLnN0cmVhbS5nZXRNZWRpYVN0cmVhbSgpKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB0aGlzLm1lZGlhUmVjb3JkZXIuc3RhcnQoMTApO1xuXG4gICAgICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAgICAgICByZWplY3QoZXJyKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5tZWRpYVJlY29yZGVyLm9uZGF0YWF2YWlsYWJsZSA9IChlKSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5jaHVua3MucHVzaChlLmRhdGEpO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgdGhpcy5tZWRpYVJlY29yZGVyLm9uZXJyb3IgPSAoZSkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ01lZGlhUmVjb3JkZXIgZXJyb3I6ICcsIGUpO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgdGhpcy5tZWRpYVJlY29yZGVyLm9uc3RhcnQgPSAoKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5sb2coJ01lZGlhUmVjb3JkZXIgc3RhcnRlZCAoc3RhdGU9JyArIHRoaXMubWVkaWFSZWNvcmRlci5zdGF0ZSArICcpJyk7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICB0aGlzLm1lZGlhUmVjb3JkZXIub25zdG9wID0gKCkgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMub25TdG9wRGVmYXVsdCgpO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgdGhpcy5tZWRpYVJlY29yZGVyLm9ucGF1c2UgPSAoKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5sb2coJ01lZGlhUmVjb3JkZXIgcGF1c2VkIChzdGF0ZT0nICsgdGhpcy5tZWRpYVJlY29yZGVyLnN0YXRlICsgJyknKTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIHRoaXMubWVkaWFSZWNvcmRlci5vbnJlc3VtZSA9ICgpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmxvZygnTWVkaWFSZWNvcmRlciByZXN1bWVkIChzdGF0ZT0nICsgdGhpcy5tZWRpYVJlY29yZGVyLnN0YXRlICsgJyknKTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIHRoaXMubWVkaWFSZWNvcmRlci5vbndhcm5pbmcgPSAoZSkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKCdNZWRpYVJlY29yZGVyIHdhcm5pbmc6ICcgKyBlKTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIHRoaXMuc3RhdGUgPSBMb2NhbFJlY29yZGVyU3RhdGUuUkVDT1JESU5HO1xuICAgICAgICAgICAgcmVzb2x2ZSgpO1xuXG4gICAgICAgIH0pO1xuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogRW5kcyB0aGUgcmVjb3JkaW5nIG9mIHRoZSBTdHJlYW0uIFtbc3RhdGVdXSBwcm9wZXJ0eSBtdXN0IGJlIGBSRUNPUkRJTkdgIG9yIGBQQVVTRURgLiBBZnRlciBtZXRob2Qgc3VjY2VlZHMgaXMgc2V0IHRvIGBGSU5JU0hFRGBcbiAgICAgKiBAcmV0dXJucyBBIFByb21pc2UgKHRvIHdoaWNoIHlvdSBjYW4gb3B0aW9uYWxseSBzdWJzY3JpYmUgdG8pIHRoYXQgaXMgcmVzb2x2ZWQgaWYgdGhlIHJlY29yZGluZyBzdWNjZXNzZnVsbHkgc3RvcHBlZCBhbmQgcmVqZWN0ZWQgd2l0aCBhbiBFcnJvciBvYmplY3QgaWYgbm90XG4gICAgICovXG4gICAgc3RvcCgpOiBQcm9taXNlPGFueT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5zdGF0ZSA9PT0gTG9jYWxSZWNvcmRlclN0YXRlLlJFQURZIHx8IHRoaXMuc3RhdGUgPT09IExvY2FsUmVjb3JkZXJTdGF0ZS5GSU5JU0hFRCkge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyAoRXJyb3IoJ1xcJ0xvY2FsUmVjb3JkLnN0b3AoKVxcJyBuZWVkcyBcXCdMb2NhbFJlY29yZC5zdGF0ZVxcJyB0byBiZSBcXCdSRUNPUkRJTkdcXCcgb3IgXFwnUEFVU0VEXFwnIChjdXJyZW50IHZhbHVlOiBcXCcnICsgdGhpcy5zdGF0ZSArICdcXCcpLiBDYWxsIFxcJ0xvY2FsUmVjb3JkZXIuc3RhcnQoKVxcJyBiZWZvcmUnKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRoaXMubWVkaWFSZWNvcmRlci5vbnN0b3AgPSAoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMub25TdG9wRGVmYXVsdCgpO1xuICAgICAgICAgICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB0aGlzLm1lZGlhUmVjb3JkZXIuc3RvcCgpO1xuICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICAgIHJlamVjdChlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBQYXVzZXMgdGhlIHJlY29yZGluZyBvZiB0aGUgU3RyZWFtLiBbW3N0YXRlXV0gcHJvcGVydHkgbXVzdCBiZSBgUkVDT1JESU5HYC4gQWZ0ZXIgbWV0aG9kIHN1Y2NlZWRzIGlzIHNldCB0byBgUEFVU0VEYFxuICAgICAqIEByZXR1cm5zIEEgUHJvbWlzZSAodG8gd2hpY2ggeW91IGNhbiBvcHRpb25hbGx5IHN1YnNjcmliZSB0bykgdGhhdCBpcyByZXNvbHZlZCBpZiB0aGUgcmVjb3JkaW5nIHdhcyBzdWNjZXNzZnVsbHkgcGF1c2VkIGFuZCByZWplY3RlZCB3aXRoIGFuIEVycm9yIG9iamVjdCBpZiBub3RcbiAgICAgKi9cbiAgICBwYXVzZSgpOiBQcm9taXNlPGFueT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5zdGF0ZSAhPT0gTG9jYWxSZWNvcmRlclN0YXRlLlJFQ09SRElORykge1xuICAgICAgICAgICAgICAgICAgICByZWplY3QoRXJyb3IoJ1xcJ0xvY2FsUmVjb3JkLnBhdXNlKClcXCcgbmVlZHMgXFwnTG9jYWxSZWNvcmQuc3RhdGVcXCcgdG8gYmUgXFwnUkVDT1JESU5HXFwnIChjdXJyZW50IHZhbHVlOiBcXCcnICsgdGhpcy5zdGF0ZSArICdcXCcpLiBDYWxsIFxcJ0xvY2FsUmVjb3JkZXIuc3RhcnQoKVxcJyBvciBcXCdMb2NhbFJlY29yZGVyLnJlc3VtZSgpXFwnIGJlZm9yZScpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhpcy5tZWRpYVJlY29yZGVyLnBhdXNlKCk7XG4gICAgICAgICAgICAgICAgdGhpcy5zdGF0ZSA9IExvY2FsUmVjb3JkZXJTdGF0ZS5QQVVTRUQ7XG4gICAgICAgICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlc3VtZXMgdGhlIHJlY29yZGluZyBvZiB0aGUgU3RyZWFtLiBbW3N0YXRlXV0gcHJvcGVydHkgbXVzdCBiZSBgUEFVU0VEYC4gQWZ0ZXIgbWV0aG9kIHN1Y2NlZWRzIGlzIHNldCB0byBgUkVDT1JESU5HYFxuICAgICAqIEByZXR1cm5zIEEgUHJvbWlzZSAodG8gd2hpY2ggeW91IGNhbiBvcHRpb25hbGx5IHN1YnNjcmliZSB0bykgdGhhdCBpcyByZXNvbHZlZCBpZiB0aGUgcmVjb3JkaW5nIHdhcyBzdWNjZXNzZnVsbHkgcmVzdW1lZCBhbmQgcmVqZWN0ZWQgd2l0aCBhbiBFcnJvciBvYmplY3QgaWYgbm90XG4gICAgICovXG4gICAgcmVzdW1lKCk6IFByb21pc2U8YW55PiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLnN0YXRlICE9PSBMb2NhbFJlY29yZGVyU3RhdGUuUEFVU0VEKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IChFcnJvcignXFwnTG9jYWxSZWNvcmQucmVzdW1lKClcXCcgbmVlZHMgXFwnTG9jYWxSZWNvcmQuc3RhdGVcXCcgdG8gYmUgXFwnUEFVU0VEXFwnIChjdXJyZW50IHZhbHVlOiBcXCcnICsgdGhpcy5zdGF0ZSArICdcXCcpLiBDYWxsIFxcJ0xvY2FsUmVjb3JkZXIucGF1c2UoKVxcJyBiZWZvcmUnKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRoaXMubWVkaWFSZWNvcmRlci5yZXN1bWUoKTtcbiAgICAgICAgICAgICAgICB0aGlzLnN0YXRlID0gTG9jYWxSZWNvcmRlclN0YXRlLlJFQ09SRElORztcbiAgICAgICAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBQcmV2aWV3cyB0aGUgcmVjb3JkaW5nLCBhcHBlbmRpbmcgYSBuZXcgSFRNTFZpZGVvRWxlbWVudCB0byBlbGVtZW50IHdpdGggaWQgYHBhcmVudElkYC4gW1tzdGF0ZV1dIHByb3BlcnR5IG11c3QgYmUgYEZJTklTSEVEYFxuICAgICAqL1xuICAgIHByZXZpZXcocGFyZW50RWxlbWVudCk6IEhUTUxWaWRlb0VsZW1lbnQge1xuXG4gICAgICAgIGlmICh0aGlzLnN0YXRlICE9PSBMb2NhbFJlY29yZGVyU3RhdGUuRklOSVNIRUQpIHtcbiAgICAgICAgICAgIHRocm93IChFcnJvcignXFwnTG9jYWxSZWNvcmQucHJldmlldygpXFwnIG5lZWRzIFxcJ0xvY2FsUmVjb3JkLnN0YXRlXFwnIHRvIGJlIFxcJ0ZJTklTSEVEXFwnIChjdXJyZW50IHZhbHVlOiBcXCcnICsgdGhpcy5zdGF0ZSArICdcXCcpLiBDYWxsIFxcJ0xvY2FsUmVjb3JkZXIuc3RvcCgpXFwnIGJlZm9yZScpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMudmlkZW9QcmV2aWV3ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgndmlkZW8nKTtcblxuICAgICAgICB0aGlzLnZpZGVvUHJldmlldy5pZCA9IHRoaXMuaWQ7XG4gICAgICAgIHRoaXMudmlkZW9QcmV2aWV3LmF1dG9wbGF5ID0gdHJ1ZTtcblxuICAgICAgICBpZiAodHlwZW9mIHBhcmVudEVsZW1lbnQgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICB0aGlzLmh0bWxQYXJlbnRFbGVtZW50SWQgPSBwYXJlbnRFbGVtZW50O1xuXG4gICAgICAgICAgICBjb25zdCBwYXJlbnRFbGVtZW50RG9tID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQocGFyZW50RWxlbWVudCk7XG4gICAgICAgICAgICBpZiAocGFyZW50RWxlbWVudERvbSkge1xuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9QcmV2aWV3ID0gcGFyZW50RWxlbWVudERvbS5hcHBlbmRDaGlsZCh0aGlzLnZpZGVvUHJldmlldyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLmh0bWxQYXJlbnRFbGVtZW50SWQgPSBwYXJlbnRFbGVtZW50LmlkO1xuICAgICAgICAgICAgdGhpcy52aWRlb1ByZXZpZXcgPSBwYXJlbnRFbGVtZW50LmFwcGVuZENoaWxkKHRoaXMudmlkZW9QcmV2aWV3KTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMudmlkZW9QcmV2aWV3LnNyYyA9IHRoaXMudmlkZW9QcmV2aWV3U3JjO1xuXG4gICAgICAgIHJldHVybiB0aGlzLnZpZGVvUHJldmlldztcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIEdyYWNlZnVsbHkgc3RvcHMgYW5kIGNsZWFucyB0aGUgY3VycmVudCByZWNvcmRpbmcgKFdBUk5JTkc6IGl0IGlzIGNvbXBsZXRlbHkgZGlzbWlzc2VkKS4gU2V0cyBbW3N0YXRlXV0gdG8gYFJFQURZYCBzbyB0aGUgcmVjb3JkaW5nIGNhbiBzdGFydCBhZ2FpblxuICAgICAqL1xuICAgIGNsZWFuKCk6IHZvaWQge1xuICAgICAgICBjb25zdCBmID0gKCkgPT4ge1xuICAgICAgICAgICAgZGVsZXRlIHRoaXMuYmxvYjtcbiAgICAgICAgICAgIHRoaXMuY2h1bmtzID0gW107XG4gICAgICAgICAgICB0aGlzLmNvdW50ID0gMDtcbiAgICAgICAgICAgIGRlbGV0ZSB0aGlzLm1lZGlhUmVjb3JkZXI7XG4gICAgICAgICAgICB0aGlzLnN0YXRlID0gTG9jYWxSZWNvcmRlclN0YXRlLlJFQURZO1xuICAgICAgICB9O1xuICAgICAgICBpZiAodGhpcy5zdGF0ZSA9PT0gTG9jYWxSZWNvcmRlclN0YXRlLlJFQ09SRElORyB8fCB0aGlzLnN0YXRlID09PSBMb2NhbFJlY29yZGVyU3RhdGUuUEFVU0VEKSB7XG4gICAgICAgICAgICB0aGlzLnN0b3AoKS50aGVuKCgpID0+IGYoKSkuY2F0Y2goKCkgPT4gZigpKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGYoKTtcbiAgICAgICAgfVxuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogRG93bmxvYWRzIHRoZSByZWNvcmRlZCB2aWRlbyB0aHJvdWdoIHRoZSBicm93c2VyLiBbW3N0YXRlXV0gcHJvcGVydHkgbXVzdCBiZSBgRklOSVNIRURgXG4gICAgICovXG4gICAgZG93bmxvYWQoKTogdm9pZCB7XG4gICAgICAgIGlmICh0aGlzLnN0YXRlICE9PSBMb2NhbFJlY29yZGVyU3RhdGUuRklOSVNIRUQpIHtcbiAgICAgICAgICAgIHRocm93IChFcnJvcignXFwnTG9jYWxSZWNvcmQuZG93bmxvYWQoKVxcJyBuZWVkcyBcXCdMb2NhbFJlY29yZC5zdGF0ZVxcJyB0byBiZSBcXCdGSU5JU0hFRFxcJyAoY3VycmVudCB2YWx1ZTogXFwnJyArIHRoaXMuc3RhdGUgKyAnXFwnKS4gQ2FsbCBcXCdMb2NhbFJlY29yZGVyLnN0b3AoKVxcJyBiZWZvcmUnKSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjb25zdCBhOiBIVE1MQW5jaG9yRWxlbWVudCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2EnKTtcbiAgICAgICAgICAgIGEuc3R5bGUuZGlzcGxheSA9ICdub25lJztcbiAgICAgICAgICAgIGRvY3VtZW50LmJvZHkuYXBwZW5kQ2hpbGQoYSk7XG5cbiAgICAgICAgICAgIGNvbnN0IHVybCA9IHdpbmRvdy5VUkwuY3JlYXRlT2JqZWN0VVJMKHRoaXMuYmxvYik7XG4gICAgICAgICAgICBhLmhyZWYgPSB1cmw7XG4gICAgICAgICAgICBhLmRvd25sb2FkID0gdGhpcy5pZCArICcud2VibSc7XG4gICAgICAgICAgICBhLmNsaWNrKCk7XG4gICAgICAgICAgICB3aW5kb3cuVVJMLnJldm9rZU9iamVjdFVSTCh1cmwpO1xuXG4gICAgICAgICAgICBkb2N1bWVudC5ib2R5LnJlbW92ZUNoaWxkKGEpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0cyB0aGUgcmF3IEJsb2IgZmlsZS4gTWV0aG9kcyBwcmV2aWV3LCBkb3dubG9hZCwgdXBsb2FkQXNCaW5hcnkgYW5kIHVwbG9hZEFzTXVsdGlwYXJ0ZmlsZSB1c2UgdGhpcyBzYW1lIGZpbGUgdG8gcGVyZm9ybSB0aGVpciBzcGVjaWZpYyBhY3Rpb25zLiBbW3N0YXRlXV0gcHJvcGVydHkgbXVzdCBiZSBgRklOSVNIRURgXG4gICAgICovXG4gICAgZ2V0QmxvYigpOiBCbG9iIHtcbiAgICAgICAgaWYgKHRoaXMuc3RhdGUgIT09IExvY2FsUmVjb3JkZXJTdGF0ZS5GSU5JU0hFRCkge1xuICAgICAgICAgICAgdGhyb3cgKEVycm9yKCdDYWxsIFxcJ0xvY2FsUmVjb3JkLnN0b3AoKVxcJyBiZWZvcmUgZ2V0dGluZyBCbG9iIGZpbGUnKSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5ibG9iO1xuICAgICAgICB9XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBVcGxvYWRzIHRoZSByZWNvcmRlZCB2aWRlbyBhcyBhIGJpbmFyeSBmaWxlIHBlcmZvcm1pbmcgYW4gSFRUUC9QT1NUIG9wZXJhdGlvbiB0byBVUkwgYGVuZHBvaW50YC4gW1tzdGF0ZV1dIHByb3BlcnR5IG11c3QgYmUgYEZJTklTSEVEYC4gT3B0aW9uYWwgSFRUUCBoZWFkZXJzIGNhbiBiZSBwYXNzZWQgYXMgc2Vjb25kIHBhcmFtZXRlci4gRm9yIGV4YW1wbGU6XG4gICAgICogYGBgXG4gICAgICogdmFyIGhlYWRlcnMgPSB7XG4gICAgICogIFwiQ29va2llXCI6IFwiJFZlcnNpb249MTsgU2tpbj1uZXc7XCIsXG4gICAgICogIFwiQXV0aG9yaXphdGlvblwiOlwiQmFzaWMgUVd4aFpHcGJqcHVJSE5sY3RaUT09XCJcbiAgICAgKiB9XG4gICAgICogYGBgXG4gICAgICogQHJldHVybnMgQSBQcm9taXNlICh0byB3aGljaCB5b3UgY2FuIG9wdGlvbmFsbHkgc3Vic2NyaWJlIHRvKSB0aGF0IGlzIHJlc29sdmVkIHdpdGggdGhlIGBodHRwLnJlc3BvbnNlVGV4dGAgZnJvbSBzZXJ2ZXIgaWYgdGhlIG9wZXJhdGlvbiB3YXMgc3VjY2Vzc2Z1bCBhbmQgcmVqZWN0ZWQgd2l0aCB0aGUgZmFpbGVkIGBodHRwLnN0YXR1c2AgaWYgbm90XG4gICAgICovXG4gICAgdXBsb2FkQXNCaW5hcnkoZW5kcG9pbnQ6IHN0cmluZywgaGVhZGVycz86IGFueSk6IFByb21pc2U8YW55PiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICBpZiAodGhpcy5zdGF0ZSAhPT0gTG9jYWxSZWNvcmRlclN0YXRlLkZJTklTSEVEKSB7XG4gICAgICAgICAgICAgICAgcmVqZWN0KEVycm9yKCdcXCdMb2NhbFJlY29yZC51cGxvYWRBc0JpbmFyeSgpXFwnIG5lZWRzIFxcJ0xvY2FsUmVjb3JkLnN0YXRlXFwnIHRvIGJlIFxcJ0ZJTklTSEVEXFwnIChjdXJyZW50IHZhbHVlOiBcXCcnICsgdGhpcy5zdGF0ZSArICdcXCcpLiBDYWxsIFxcJ0xvY2FsUmVjb3JkZXIuc3RvcCgpXFwnIGJlZm9yZScpKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY29uc3QgaHR0cCA9IG5ldyBYTUxIdHRwUmVxdWVzdCgpO1xuICAgICAgICAgICAgICAgIGh0dHAub3BlbignUE9TVCcsIGVuZHBvaW50LCB0cnVlKTtcblxuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgaGVhZGVycyA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgICAgICAgICAgICAgZm9yIChjb25zdCBrZXkgb2YgT2JqZWN0LmtleXMoaGVhZGVycykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGh0dHAuc2V0UmVxdWVzdEhlYWRlcihrZXksIGhlYWRlcnNba2V5XSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBodHRwLm9ucmVhZHlzdGF0ZWNoYW5nZSA9ICgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGh0dHAucmVhZHlTdGF0ZSA9PT0gNCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGh0dHAuc3RhdHVzLnRvU3RyaW5nKCkuY2hhckF0KDApID09PSAnMicpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBTdWNjZXNzIHJlc3BvbnNlIGZyb20gc2VydmVyIChIVFRQIHN0YXR1cyBzdGFuZGFyZDogMlhYIGlzIHN1Y2Nlc3MpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZShodHRwLnJlc3BvbnNlVGV4dCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChodHRwLnN0YXR1cyk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIGh0dHAuc2VuZCh0aGlzLmJsb2IpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFVwbG9hZHMgdGhlIHJlY29yZGVkIHZpZGVvIGFzIGEgbXVsdGlwYXJ0IGZpbGUgcGVyZm9ybWluZyBhbiBIVFRQL1BPU1Qgb3BlcmF0aW9uIHRvIFVSTCBgZW5kcG9pbnRgLiBbW3N0YXRlXV0gcHJvcGVydHkgbXVzdCBiZSBgRklOSVNIRURgLiBPcHRpb25hbCBIVFRQIGhlYWRlcnMgY2FuIGJlIHBhc3NlZCBhcyBzZWNvbmQgcGFyYW1ldGVyLiBGb3IgZXhhbXBsZTpcbiAgICAgKiBgYGBcbiAgICAgKiB2YXIgaGVhZGVycyA9IHtcbiAgICAgKiAgXCJDb29raWVcIjogXCIkVmVyc2lvbj0xOyBTa2luPW5ldztcIixcbiAgICAgKiAgXCJBdXRob3JpemF0aW9uXCI6XCJCYXNpYyBRV3hoWkdwYmpwdUlITmxjdFpRPT1cIlxuICAgICAqIH1cbiAgICAgKiBgYGBcbiAgICAgKiBAcmV0dXJucyBBIFByb21pc2UgKHRvIHdoaWNoIHlvdSBjYW4gb3B0aW9uYWxseSBzdWJzY3JpYmUgdG8pIHRoYXQgaXMgcmVzb2x2ZWQgd2l0aCB0aGUgYGh0dHAucmVzcG9uc2VUZXh0YCBmcm9tIHNlcnZlciBpZiB0aGUgb3BlcmF0aW9uIHdhcyBzdWNjZXNzZnVsIGFuZCByZWplY3RlZCB3aXRoIHRoZSBmYWlsZWQgYGh0dHAuc3RhdHVzYCBpZiBub3Q6XG4gICAgICovXG4gICAgdXBsb2FkQXNNdWx0aXBhcnRmaWxlKGVuZHBvaW50OiBzdHJpbmcsIGhlYWRlcnM/OiBhbnkpOiBQcm9taXNlPGFueT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgaWYgKHRoaXMuc3RhdGUgIT09IExvY2FsUmVjb3JkZXJTdGF0ZS5GSU5JU0hFRCkge1xuICAgICAgICAgICAgICAgIHJlamVjdChFcnJvcignXFwnTG9jYWxSZWNvcmQudXBsb2FkQXNNdWx0aXBhcnRmaWxlKClcXCcgbmVlZHMgXFwnTG9jYWxSZWNvcmQuc3RhdGVcXCcgdG8gYmUgXFwnRklOSVNIRURcXCcgKGN1cnJlbnQgdmFsdWU6IFxcJycgKyB0aGlzLnN0YXRlICsgJ1xcJykuIENhbGwgXFwnTG9jYWxSZWNvcmRlci5zdG9wKClcXCcgYmVmb3JlJykpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBjb25zdCBodHRwID0gbmV3IFhNTEh0dHBSZXF1ZXN0KCk7XG4gICAgICAgICAgICAgICAgaHR0cC5vcGVuKCdQT1NUJywgZW5kcG9pbnQsIHRydWUpO1xuXG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBoZWFkZXJzID09PSAnb2JqZWN0Jykge1xuICAgICAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IGtleSBvZiBPYmplY3Qua2V5cyhoZWFkZXJzKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaHR0cC5zZXRSZXF1ZXN0SGVhZGVyKGtleSwgaGVhZGVyc1trZXldKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGNvbnN0IHNlbmRhYmxlID0gbmV3IEZvcm1EYXRhKCk7XG4gICAgICAgICAgICAgICAgc2VuZGFibGUuYXBwZW5kKCdmaWxlJywgdGhpcy5ibG9iLCB0aGlzLmlkICsgJy53ZWJtJyk7XG5cbiAgICAgICAgICAgICAgICBodHRwLm9ucmVhZHlzdGF0ZWNoYW5nZSA9ICgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGh0dHAucmVhZHlTdGF0ZSA9PT0gNCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGh0dHAuc3RhdHVzLnRvU3RyaW5nKCkuY2hhckF0KDApID09PSAnMicpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBTdWNjZXNzIHJlc3BvbnNlIGZyb20gc2VydmVyIChIVFRQIHN0YXR1cyBzdGFuZGFyZDogMlhYIGlzIHN1Y2Nlc3MpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZShodHRwLnJlc3BvbnNlVGV4dCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChodHRwLnN0YXR1cyk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICAgICAgaHR0cC5zZW5kKHNlbmRhYmxlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG5cbiAgICAvKiBQcml2YXRlIG1ldGhvZHMgKi9cblxuICAgIHByaXZhdGUgb25TdG9wRGVmYXVsdCgpOiB2b2lkIHtcbiAgICAgICAgY29uc29sZS5sb2coJ01lZGlhUmVjb3JkZXIgc3RvcHBlZCAgKHN0YXRlPScgKyB0aGlzLm1lZGlhUmVjb3JkZXIuc3RhdGUgKyAnKScpO1xuXG4gICAgICAgIHRoaXMuYmxvYiA9IG5ldyBCbG9iKHRoaXMuY2h1bmtzLCB7IHR5cGU6ICd2aWRlby93ZWJtJyB9KTtcbiAgICAgICAgdGhpcy5jaHVua3MgPSBbXTtcblxuICAgICAgICB0aGlzLnZpZGVvUHJldmlld1NyYyA9IHdpbmRvdy5VUkwuY3JlYXRlT2JqZWN0VVJMKHRoaXMuYmxvYik7XG5cbiAgICAgICAgdGhpcy5zdGF0ZSA9IExvY2FsUmVjb3JkZXJTdGF0ZS5GSU5JU0hFRDtcbiAgICB9XG5cbn1cbiIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTctMjAxOCBPcGVuVmlkdSAoaHR0cHM6Ly9vcGVudmlkdS5pby8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuaW1wb3J0IHsgTG9jYWxSZWNvcmRlciB9IGZyb20gJy4vTG9jYWxSZWNvcmRlcic7XG5pbXBvcnQgeyBQdWJsaXNoZXIgfSBmcm9tICcuL1B1Ymxpc2hlcic7XG5pbXBvcnQgeyBTZXNzaW9uIH0gZnJvbSAnLi9TZXNzaW9uJztcbmltcG9ydCB7IFN0cmVhbSB9IGZyb20gJy4vU3RyZWFtJztcbmltcG9ydCB7IFN0cmVhbVByb3BlcnR5Q2hhbmdlZEV2ZW50IH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvU3RyZWFtUHJvcGVydHlDaGFuZ2VkRXZlbnQnO1xuaW1wb3J0IHsgRGV2aWNlIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9JbnRlcmZhY2VzL1B1YmxpYy9EZXZpY2UnO1xuaW1wb3J0IHsgT3BlblZpZHVBZHZhbmNlZENvbmZpZ3VyYXRpb24gfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHVibGljL09wZW5WaWR1QWR2YW5jZWRDb25maWd1cmF0aW9uJztcbmltcG9ydCB7IFB1Ymxpc2hlclByb3BlcnRpZXMgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHVibGljL1B1Ymxpc2hlclByb3BlcnRpZXMnO1xuaW1wb3J0IHsgT3BlblZpZHVFcnJvciwgT3BlblZpZHVFcnJvck5hbWUgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0VudW1zL09wZW5WaWR1RXJyb3InO1xuaW1wb3J0IHsgVmlkZW9JbnNlcnRNb2RlIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FbnVtcy9WaWRlb0luc2VydE1vZGUnO1xuXG5pbXBvcnQgKiBhcyBzY3JlZW5TaGFyaW5nQXV0byBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL1NjcmVlblNoYXJpbmcvU2NyZWVuLUNhcHR1cmluZy1BdXRvJztcbmltcG9ydCAqIGFzIHNjcmVlblNoYXJpbmcgZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9TY3JlZW5TaGFyaW5nL1NjcmVlbi1DYXB0dXJpbmcnO1xuXG5pbXBvcnQgUnBjQnVpbGRlciA9IHJlcXVpcmUoJy4uL09wZW5WaWR1SW50ZXJuYWwvS3VyZW50b1V0aWxzL2t1cmVudG8tanNvbnJwYycpO1xuaW1wb3J0IHBsYXRmb3JtID0gcmVxdWlyZSgncGxhdGZvcm0nKTtcblxuXG4vKipcbiAqIEVudHJ5cG9pbnQgb2YgT3BlblZpZHUgQnJvd3NlciBsaWJyYXJ5LlxuICogVXNlIGl0IHRvIGluaXRpYWxpemUgb2JqZWN0cyBvZiB0eXBlIFtbU2Vzc2lvbl1dLCBbW1B1Ymxpc2hlcl1dIGFuZCBbW0xvY2FsUmVjb3JkZXJdXVxuICovXG5leHBvcnQgY2xhc3MgT3BlblZpZHUge1xuXG4gIHByaXZhdGUganNvblJwY0NsaWVudDogYW55O1xuXG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICBzZXNzaW9uOiBTZXNzaW9uO1xuICAvKipcbiAgICogQGhpZGRlblxuICAgKi9cbiAgcHVibGlzaGVyczogUHVibGlzaGVyW10gPSBbXTtcbiAgLyoqXG4gICAqIEBoaWRkZW5cbiAgICovXG4gIHdzVXJpOiBzdHJpbmc7XG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICBzZWNyZXQgPSAnJztcbiAgLyoqXG4gICAqIEBoaWRkZW5cbiAgICovXG4gIHJlY29yZGVyID0gZmFsc2U7XG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICBpY2VTZXJ2ZXJzOiBSVENJY2VTZXJ2ZXJbXTtcbiAgLyoqXG4gICAqIEBoaWRkZW5cbiAgICovXG4gIHJvbGU6IHN0cmluZztcbiAgLyoqXG4gICAqIEBoaWRkZW5cbiAgICovXG4gIGFkdmFuY2VkQ29uZmlndXJhdGlvbjogT3BlblZpZHVBZHZhbmNlZENvbmZpZ3VyYXRpb24gPSB7fTtcblxuICBjb25zdHJ1Y3RvcigpIHtcbiAgICBjb25zb2xlLmluZm8oXCInT3BlblZpZHUnIGluaXRpYWxpemVkXCIpO1xuXG4gICAgaWYgKHBsYXRmb3JtLm5hbWUhIS50b0xvd2VyQ2FzZSgpLmluZGV4T2YoJ21vYmlsZScpICE9PSAtMSkge1xuICAgICAgLy8gTGlzdGVuIHRvIG9yaWVudGF0aW9uY2hhbmdlIG9ubHkgb24gbW9iaWxlIGJyb3dzZXJzXG4gICAgICAoPGFueT53aW5kb3cpLm9ub3JpZW50YXRpb25jaGFuZ2UgPSAoKSA9PiB7XG4gICAgICAgIHRoaXMucHVibGlzaGVycy5mb3JFYWNoKHB1Ymxpc2hlciA9PiB7XG4gICAgICAgICAgaWYgKCEhcHVibGlzaGVyLnN0cmVhbSAmJiAhIXB1Ymxpc2hlci5zdHJlYW0uaGFzVmlkZW8gJiYgISFwdWJsaXNoZXIuc3RyZWFtLnN0cmVhbU1hbmFnZXIudmlkZW9zWzBdKSB7XG5cbiAgICAgICAgICAgIGxldCBhdHRlbXB0cyA9IDA7XG5cbiAgICAgICAgICAgIGNvbnN0IG9sZFdpZHRoID0gcHVibGlzaGVyLnN0cmVhbS52aWRlb0RpbWVuc2lvbnMud2lkdGg7XG4gICAgICAgICAgICBjb25zdCBvbGRIZWlnaHQgPSBwdWJsaXNoZXIuc3RyZWFtLnZpZGVvRGltZW5zaW9ucy5oZWlnaHQ7XG4gICAgICAgICAgICAvLyBOZXcgcmVzb2x1dGlvbiBnb3QgZnJvbSBkaWZmZXJlbnQgcGxhY2VzIGZvciBDaHJvbWUgYW5kIEZpcmVmb3guIENocm9tZSBuZWVkcyBhIHZpZGVvV2lkdGggYW5kIHZpZGVvSGVpZ2h0IG9mIGEgdmlkZW9FbGVtZW50LlxuICAgICAgICAgICAgLy8gRmlyZWZveCBuZWVkcyBnZXRTZXR0aW5ncyBmcm9tIHRoZSB2aWRlb1RyYWNrXG4gICAgICAgICAgICBsZXQgZmlyZWZveFNldHRpbmdzID0gcHVibGlzaGVyLnN0cmVhbS5nZXRNZWRpYVN0cmVhbSgpLmdldFZpZGVvVHJhY2tzKClbMF0uZ2V0U2V0dGluZ3MoKTtcbiAgICAgICAgICAgIGxldCBuZXdXaWR0aCA9IChwbGF0Zm9ybS5uYW1lISEudG9Mb3dlckNhc2UoKS5pbmRleE9mKCdmaXJlZm94JykgIT09IC0xKSA/IGZpcmVmb3hTZXR0aW5ncy53aWR0aCA6IHB1Ymxpc2hlci52aWRlb1JlZmVyZW5jZS52aWRlb1dpZHRoO1xuICAgICAgICAgICAgbGV0IG5ld0hlaWdodCA9IChwbGF0Zm9ybS5uYW1lISEudG9Mb3dlckNhc2UoKS5pbmRleE9mKCdmaXJlZm94JykgIT09IC0xKSA/IGZpcmVmb3hTZXR0aW5ncy5oZWlnaHQgOiBwdWJsaXNoZXIudmlkZW9SZWZlcmVuY2UudmlkZW9IZWlnaHQ7XG5cbiAgICAgICAgICAgIGNvbnN0IHJlcGVhdFVudGlsQ2hhbmdlID0gc2V0SW50ZXJ2YWwoKCkgPT4ge1xuICAgICAgICAgICAgICBmaXJlZm94U2V0dGluZ3MgPSBwdWJsaXNoZXIuc3RyZWFtLmdldE1lZGlhU3RyZWFtKCkuZ2V0VmlkZW9UcmFja3MoKVswXS5nZXRTZXR0aW5ncygpO1xuICAgICAgICAgICAgICBuZXdXaWR0aCA9IChwbGF0Zm9ybS5uYW1lISEudG9Mb3dlckNhc2UoKS5pbmRleE9mKCdmaXJlZm94JykgIT09IC0xKSA/IGZpcmVmb3hTZXR0aW5ncy53aWR0aCA6IHB1Ymxpc2hlci52aWRlb1JlZmVyZW5jZS52aWRlb1dpZHRoO1xuICAgICAgICAgICAgICBuZXdIZWlnaHQgPSAocGxhdGZvcm0ubmFtZSEhLnRvTG93ZXJDYXNlKCkuaW5kZXhPZignZmlyZWZveCcpICE9PSAtMSkgPyBmaXJlZm94U2V0dGluZ3MuaGVpZ2h0IDogcHVibGlzaGVyLnZpZGVvUmVmZXJlbmNlLnZpZGVvSGVpZ2h0O1xuICAgICAgICAgICAgICBzZW5kU3RyZWFtUHJvcGVydHlDaGFuZ2VkRXZlbnQob2xkV2lkdGgsIG9sZEhlaWdodCwgbmV3V2lkdGgsIG5ld0hlaWdodCk7XG4gICAgICAgICAgICB9LCAxMDApO1xuXG4gICAgICAgICAgICBjb25zdCBzZW5kU3RyZWFtUHJvcGVydHlDaGFuZ2VkRXZlbnQgPSAob2xkV2lkdGgsIG9sZEhlaWdodCwgbmV3V2lkdGgsIG5ld0hlaWdodCkgPT4ge1xuICAgICAgICAgICAgICBhdHRlbXB0cysrO1xuICAgICAgICAgICAgICBpZiAoYXR0ZW1wdHMgPiA0KSB7XG4gICAgICAgICAgICAgICAgY2xlYXJUaW1lb3V0KHJlcGVhdFVudGlsQ2hhbmdlKTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICBpZiAobmV3V2lkdGggIT09IG9sZFdpZHRoIHx8IG5ld0hlaWdodCAhPT0gb2xkSGVpZ2h0KSB7XG4gICAgICAgICAgICAgICAgcHVibGlzaGVyLnN0cmVhbS52aWRlb0RpbWVuc2lvbnMgPSB7XG4gICAgICAgICAgICAgICAgICB3aWR0aDogbmV3V2lkdGggfHwgMCxcbiAgICAgICAgICAgICAgICAgIGhlaWdodDogbmV3SGVpZ2h0IHx8IDBcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIHRoaXMuc2VuZFJlcXVlc3QoXG4gICAgICAgICAgICAgICAgICAnc3RyZWFtUHJvcGVydHlDaGFuZ2VkJyxcbiAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgc3RyZWFtSWQ6IHB1Ymxpc2hlci5zdHJlYW0uc3RyZWFtSWQsXG4gICAgICAgICAgICAgICAgICAgIHByb3BlcnR5OiAndmlkZW9EaW1lbnNpb25zJyxcbiAgICAgICAgICAgICAgICAgICAgbmV3VmFsdWU6IEpTT04uc3RyaW5naWZ5KHB1Ymxpc2hlci5zdHJlYW0udmlkZW9EaW1lbnNpb25zKSxcbiAgICAgICAgICAgICAgICAgICAgcmVhc29uOiAnZGV2aWNlUm90YXRlZCdcbiAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAoZXJyb3IsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoXCJFcnJvciBzZW5kaW5nICdzdHJlYW1Qcm9wZXJ0eUNoYW5nZWQnIGV2ZW50XCIsIGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICB0aGlzLnNlc3Npb24uZW1pdEV2ZW50KCdzdHJlYW1Qcm9wZXJ0eUNoYW5nZWQnLCBbbmV3IFN0cmVhbVByb3BlcnR5Q2hhbmdlZEV2ZW50KHRoaXMuc2Vzc2lvbiwgcHVibGlzaGVyLnN0cmVhbSwgJ3ZpZGVvRGltZW5zaW9ucycsIHB1Ymxpc2hlci5zdHJlYW0udmlkZW9EaW1lbnNpb25zLCB7IHdpZHRoOiBvbGRXaWR0aCwgaGVpZ2h0OiBvbGRIZWlnaHQgfSwgJ2RldmljZVJvdGF0ZWQnKV0pO1xuICAgICAgICAgICAgICAgICAgICAgIHB1Ymxpc2hlci5lbWl0RXZlbnQoJ3N0cmVhbVByb3BlcnR5Q2hhbmdlZCcsIFtuZXcgU3RyZWFtUHJvcGVydHlDaGFuZ2VkRXZlbnQocHVibGlzaGVyLCBwdWJsaXNoZXIuc3RyZWFtLCAndmlkZW9EaW1lbnNpb25zJywgcHVibGlzaGVyLnN0cmVhbS52aWRlb0RpbWVuc2lvbnMsIHsgd2lkdGg6IG9sZFdpZHRoLCBoZWlnaHQ6IG9sZEhlaWdodCB9LCAnZGV2aWNlUm90YXRlZCcpXSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIGNsZWFyVGltZW91dChyZXBlYXRVbnRpbENoYW5nZSk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH07XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgIH07XG4gICAgfVxuICB9XG5cblxuICAvKipcbiAgICogUmV0dXJucyBuZXcgc2Vzc2lvblxuICAgKi9cbiAgaW5pdFNlc3Npb24oKTogU2Vzc2lvbiB7XG4gICAgdGhpcy5zZXNzaW9uID0gbmV3IFNlc3Npb24odGhpcyk7XG4gICAgcmV0dXJuIHRoaXMuc2Vzc2lvbjtcbiAgfVxuXG5cbiAgaW5pdFB1Ymxpc2hlcih0YXJnZXRFbGVtZW50OiBzdHJpbmcgfCBIVE1MRWxlbWVudCk6IFB1Ymxpc2hlcjtcbiAgaW5pdFB1Ymxpc2hlcih0YXJnZXRFbGVtZW50OiBzdHJpbmcgfCBIVE1MRWxlbWVudCwgcHJvcGVydGllczogUHVibGlzaGVyUHJvcGVydGllcyk6IFB1Ymxpc2hlcjtcbiAgaW5pdFB1Ymxpc2hlcih0YXJnZXRFbGVtZW50OiBzdHJpbmcgfCBIVE1MRWxlbWVudCwgY29tcGxldGlvbkhhbmRsZXI6IChlcnJvcjogRXJyb3IgfCB1bmRlZmluZWQpID0+IHZvaWQpOiBQdWJsaXNoZXI7XG4gIGluaXRQdWJsaXNoZXIodGFyZ2V0RWxlbWVudDogc3RyaW5nIHwgSFRNTEVsZW1lbnQsIHByb3BlcnRpZXM6IFB1Ymxpc2hlclByb3BlcnRpZXMsIGNvbXBsZXRpb25IYW5kbGVyOiAoZXJyb3I6IEVycm9yIHwgdW5kZWZpbmVkKSA9PiB2b2lkKTogUHVibGlzaGVyO1xuXG4gIC8qKlxuICAgKiBSZXR1cm5zIGEgbmV3IHB1Ymxpc2hlclxuICAgKlxuICAgKiAjIyMjIEV2ZW50cyBkaXNwYXRjaGVkXG4gICAqXG4gICAqIFRoZSBbW1B1Ymxpc2hlcl1dIG9iamVjdCB3aWxsIGRpc3BhdGNoIGFuIGBhY2Nlc3NEaWFsb2dPcGVuZWRgIGV2ZW50LCBvbmx5IGlmIHRoZSBwb3AtdXAgc2hvd24gYnkgdGhlIGJyb3dzZXIgdG8gcmVxdWVzdCBwZXJtaXNzaW9ucyBmb3IgdGhlIGNhbWVyYSBpcyBvcGVuZWQuIFlvdSBjYW4gdXNlIHRoaXMgZXZlbnQgdG8gYWxlcnQgdGhlIHVzZXIgYWJvdXQgZ3JhbnRpbmcgcGVybWlzc2lvbnNcbiAgICogZm9yIHlvdXIgd2Vic2l0ZS4gQW4gYGFjY2Vzc0RpYWxvZ0Nsb3NlZGAgZXZlbnQgd2lsbCBhbHNvIGJlIGRpc3BhdGNoZWQgYWZ0ZXIgdXNlciBjbGlja3Mgb24gXCJBbGxvd1wiIG9yIFwiQmxvY2tcIiBpbiB0aGUgcG9wLXVwLlxuICAgKlxuICAgKiBUaGUgW1tQdWJsaXNoZXJdXSBvYmplY3Qgd2lsbCBkaXNwYXRjaCBhbiBgYWNjZXNzQWxsb3dlZGAgb3IgYGFjY2Vzc0RlbmllZGAgZXZlbnQgb25jZSBpdCBoYXMgYmVlbiBncmFudGVkIGFjY2VzcyB0byB0aGUgcmVxdWVzdGVkIGlucHV0IGRldmljZXMgb3Igbm90LlxuICAgKlxuICAgKiBUaGUgW1tQdWJsaXNoZXJdXSBvYmplY3Qgd2lsbCBkaXNwYXRjaCBhIGB2aWRlb0VsZW1lbnRDcmVhdGVkYCBldmVudCBvbmNlIGEgSFRNTCB2aWRlbyBlbGVtZW50IGhhcyBiZWVuIGFkZGVkIHRvIERPTSAob25seSBpZiB5b3VcbiAgICogW2xldCBPcGVuVmlkdSB0YWtlIGNhcmUgb2YgdGhlIHZpZGVvIHBsYXllcnNdKC9kb2NzL2hvdy1kby1pL21hbmFnZS12aWRlb3MvI2xldC1vcGVudmlkdS10YWtlLWNhcmUtb2YtdGhlLXZpZGVvLXBsYXllcnMpKS4gU2VlIFtbVmlkZW9FbGVtZW50RXZlbnRdXSB0byBsZWFybiBtb3JlLlxuICAgKlxuICAgKiBUaGUgW1tQdWJsaXNoZXJdXSBvYmplY3Qgd2lsbCBkaXNwYXRjaCBhIGBzdHJlYW1QbGF5aW5nYCBldmVudCBvbmNlIHRoZSBsb2NhbCBzdHJlYW1zIHN0YXJ0cyBwbGF5aW5nLiBTZWUgW1tTdHJlYW1NYW5hZ2VyRXZlbnRdXSB0byBsZWFybiBtb3JlLlxuICAgKlxuICAgKiBAcGFyYW0gdGFyZ2V0RWxlbWVudCAgSFRNTCBET00gZWxlbWVudCAob3IgaXRzIGBpZGAgYXR0cmlidXRlKSBpbiB3aGljaCB0aGUgdmlkZW8gZWxlbWVudCBvZiB0aGUgUHVibGlzaGVyIHdpbGwgYmUgaW5zZXJ0ZWQgKHNlZSBbW1B1Ymxpc2hlclByb3BlcnRpZXMuaW5zZXJ0TW9kZV1dKS4gSWYgKm51bGwqIG9yICp1bmRlZmluZWQqIG5vIGRlZmF1bHQgdmlkZW8gd2lsbCBiZSBjcmVhdGVkIGZvciB0aGlzIFB1Ymxpc2hlci5cbiAgICogWW91IGNhbiBhbHdheXMgY2FsbCBtZXRob2QgW1tQdWJsaXNoZXIuYWRkVmlkZW9FbGVtZW50XV0gb3IgW1tQdWJsaXNoZXIuY3JlYXRlVmlkZW9FbGVtZW50XV0gdG8gbWFuYWdlIHRoZSB2aWRlbyBlbGVtZW50cyBvbiB5b3VyIG93biAoc2VlIFtNYW5hZ2UgdmlkZW8gcGxheWVyc10oL2RvY3MvaG93LWRvLWkvbWFuYWdlLXZpZGVvcykgc2VjdGlvbilcbiAgICogQHBhcmFtIGNvbXBsZXRpb25IYW5kbGVyIGBlcnJvcmAgcGFyYW1ldGVyIGlzIG51bGwgaWYgYGluaXRQdWJsaXNoZXJgIHN1Y2NlZWRzLCBhbmQgaXMgZGVmaW5lZCBpZiBpdCBmYWlscy5cbiAgICogICAgICAgICAgICAgICAgICAgICAgICAgIGBjb21wbGV0aW9uSGFuZGxlcmAgZnVuY3Rpb24gaXMgY2FsbGVkIGJlZm9yZSB0aGUgUHVibGlzaGVyIGRpc3BhdGNoZXMgYW4gYGFjY2Vzc0FsbG93ZWRgIG9yIGFuIGBhY2Nlc3NEZW5pZWRgIGV2ZW50XG4gICAqL1xuICBpbml0UHVibGlzaGVyKHRhcmdldEVsZW1lbnQ6IHN0cmluZyB8IEhUTUxFbGVtZW50LCBwYXJhbTI/LCBwYXJhbTM/KTogUHVibGlzaGVyIHtcblxuICAgIGxldCBwcm9wZXJ0aWVzOiBQdWJsaXNoZXJQcm9wZXJ0aWVzO1xuXG4gICAgaWYgKCEhcGFyYW0yICYmICh0eXBlb2YgcGFyYW0yICE9PSAnZnVuY3Rpb24nKSkge1xuXG4gICAgICAvLyBNYXRjaGVzICdpbml0UHVibGlzaGVyKHRhcmdldEVsZW1lbnQsIHByb3BlcnRpZXMpJyBvciAnaW5pdFB1Ymxpc2hlcih0YXJnZXRFbGVtZW50LCBwcm9wZXJ0aWVzLCBjb21wbGV0aW9uSGFuZGxlciknXG5cbiAgICAgIHByb3BlcnRpZXMgPSAoPFB1Ymxpc2hlclByb3BlcnRpZXM+cGFyYW0yKTtcblxuICAgICAgcHJvcGVydGllcyA9IHtcbiAgICAgICAgYXVkaW9Tb3VyY2U6ICh0eXBlb2YgcHJvcGVydGllcy5hdWRpb1NvdXJjZSAhPT0gJ3VuZGVmaW5lZCcpID8gcHJvcGVydGllcy5hdWRpb1NvdXJjZSA6IHVuZGVmaW5lZCxcbiAgICAgICAgZnJhbWVSYXRlOiB0aGlzLmlzTWVkaWFTdHJlYW1UcmFjayhwcm9wZXJ0aWVzLnZpZGVvU291cmNlKSA/IHVuZGVmaW5lZCA6ICgodHlwZW9mIHByb3BlcnRpZXMuZnJhbWVSYXRlICE9PSAndW5kZWZpbmVkJykgPyBwcm9wZXJ0aWVzLmZyYW1lUmF0ZSA6IHVuZGVmaW5lZCksXG4gICAgICAgIGluc2VydE1vZGU6ICh0eXBlb2YgcHJvcGVydGllcy5pbnNlcnRNb2RlICE9PSAndW5kZWZpbmVkJykgPyAoKHR5cGVvZiBwcm9wZXJ0aWVzLmluc2VydE1vZGUgPT09ICdzdHJpbmcnKSA/IFZpZGVvSW5zZXJ0TW9kZVtwcm9wZXJ0aWVzLmluc2VydE1vZGVdIDogcHJvcGVydGllcy5pbnNlcnRNb2RlKSA6IFZpZGVvSW5zZXJ0TW9kZS5BUFBFTkQsXG4gICAgICAgIG1pcnJvcjogKHR5cGVvZiBwcm9wZXJ0aWVzLm1pcnJvciAhPT0gJ3VuZGVmaW5lZCcpID8gcHJvcGVydGllcy5taXJyb3IgOiB0cnVlLFxuICAgICAgICBwdWJsaXNoQXVkaW86ICh0eXBlb2YgcHJvcGVydGllcy5wdWJsaXNoQXVkaW8gIT09ICd1bmRlZmluZWQnKSA/IHByb3BlcnRpZXMucHVibGlzaEF1ZGlvIDogdHJ1ZSxcbiAgICAgICAgcHVibGlzaFZpZGVvOiAodHlwZW9mIHByb3BlcnRpZXMucHVibGlzaFZpZGVvICE9PSAndW5kZWZpbmVkJykgPyBwcm9wZXJ0aWVzLnB1Ymxpc2hWaWRlbyA6IHRydWUsXG4gICAgICAgIHJlc29sdXRpb246IHRoaXMuaXNNZWRpYVN0cmVhbVRyYWNrKHByb3BlcnRpZXMudmlkZW9Tb3VyY2UpID8gdW5kZWZpbmVkIDogKCh0eXBlb2YgcHJvcGVydGllcy5yZXNvbHV0aW9uICE9PSAndW5kZWZpbmVkJykgPyBwcm9wZXJ0aWVzLnJlc29sdXRpb24gOiAnNjQweDQ4MCcpLFxuICAgICAgICB2aWRlb1NvdXJjZTogKHR5cGVvZiBwcm9wZXJ0aWVzLnZpZGVvU291cmNlICE9PSAndW5kZWZpbmVkJykgPyBwcm9wZXJ0aWVzLnZpZGVvU291cmNlIDogdW5kZWZpbmVkXG4gICAgICB9O1xuICAgIH0gZWxzZSB7XG5cbiAgICAgIC8vIE1hdGNoZXMgJ2luaXRQdWJsaXNoZXIodGFyZ2V0RWxlbWVudCknIG9yICdpbml0UHVibGlzaGVyKHRhcmdldEVsZW1lbnQsIGNvbXBsZXRpb25IYW5kbGVyKSdcblxuICAgICAgcHJvcGVydGllcyA9IHtcbiAgICAgICAgaW5zZXJ0TW9kZTogVmlkZW9JbnNlcnRNb2RlLkFQUEVORCxcbiAgICAgICAgbWlycm9yOiB0cnVlLFxuICAgICAgICBwdWJsaXNoQXVkaW86IHRydWUsXG4gICAgICAgIHB1Ymxpc2hWaWRlbzogdHJ1ZSxcbiAgICAgICAgcmVzb2x1dGlvbjogJzY0MHg0ODAnXG4gICAgICB9O1xuICAgIH1cblxuICAgIGNvbnN0IHB1Ymxpc2hlcjogUHVibGlzaGVyID0gbmV3IFB1Ymxpc2hlcih0YXJnZXRFbGVtZW50LCBwcm9wZXJ0aWVzLCB0aGlzKTtcblxuICAgIGxldCBjb21wbGV0aW9uSGFuZGxlcjogKGVycm9yOiBFcnJvciB8IHVuZGVmaW5lZCkgPT4gdm9pZDtcbiAgICBpZiAoISFwYXJhbTIgJiYgKHR5cGVvZiBwYXJhbTIgPT09ICdmdW5jdGlvbicpKSB7XG4gICAgICBjb21wbGV0aW9uSGFuZGxlciA9IHBhcmFtMjtcbiAgICB9IGVsc2UgaWYgKCEhcGFyYW0zKSB7XG4gICAgICBjb21wbGV0aW9uSGFuZGxlciA9IHBhcmFtMztcbiAgICB9XG5cbiAgICBwdWJsaXNoZXIuaW5pdGlhbGl6ZSgpXG4gICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgIGlmIChjb21wbGV0aW9uSGFuZGxlciAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgY29tcGxldGlvbkhhbmRsZXIodW5kZWZpbmVkKTtcbiAgICAgICAgfVxuICAgICAgICBwdWJsaXNoZXIuZW1pdEV2ZW50KCdhY2Nlc3NBbGxvd2VkJywgW10pO1xuICAgICAgfSkuY2F0Y2goKGVycm9yKSA9PiB7XG4gICAgICAgIGlmIChjb21wbGV0aW9uSGFuZGxlciAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgY29tcGxldGlvbkhhbmRsZXIoZXJyb3IpO1xuICAgICAgICB9XG4gICAgICAgIHB1Ymxpc2hlci5lbWl0RXZlbnQoJ2FjY2Vzc0RlbmllZCcsIFtdKTtcbiAgICAgIH0pO1xuXG4gICAgdGhpcy5wdWJsaXNoZXJzLnB1c2gocHVibGlzaGVyKTtcbiAgICByZXR1cm4gcHVibGlzaGVyO1xuICB9XG5cblxuICAvKipcbiAgICogUHJvbWlzaWZpZWQgdmVyc2lvbiBvZiBbW09wZW5WaWR1LmluaXRQdWJsaXNoZXJdXVxuICAgKlxuICAgKiA+IFdBUk5JTkc6IGV2ZW50cyBgYWNjZXNzRGlhbG9nT3BlbmVkYCBhbmQgYGFjY2Vzc0RpYWxvZ0Nsb3NlZGAgd2lsbCBub3QgYmUgZGlzcGF0Y2hlZCBpZiB1c2luZyB0aGlzIG1ldGhvZCBpbnN0ZWFkIG9mIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dXG4gICAqL1xuICBpbml0UHVibGlzaGVyQXN5bmModGFyZ2V0RWxlbWVudDogc3RyaW5nIHwgSFRNTEVsZW1lbnQpOiBQcm9taXNlPFB1Ymxpc2hlcj47XG4gIGluaXRQdWJsaXNoZXJBc3luYyh0YXJnZXRFbGVtZW50OiBzdHJpbmcgfCBIVE1MRWxlbWVudCwgcHJvcGVydGllczogUHVibGlzaGVyUHJvcGVydGllcyk6IFByb21pc2U8UHVibGlzaGVyPjtcblxuICBpbml0UHVibGlzaGVyQXN5bmModGFyZ2V0RWxlbWVudDogc3RyaW5nIHwgSFRNTEVsZW1lbnQsIHByb3BlcnRpZXM/OiBQdWJsaXNoZXJQcm9wZXJ0aWVzKTogUHJvbWlzZTxQdWJsaXNoZXI+IHtcbiAgICByZXR1cm4gbmV3IFByb21pc2U8UHVibGlzaGVyPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG5cbiAgICAgIGxldCBwdWJsaXNoZXI6IFB1Ymxpc2hlcjtcblxuICAgICAgY29uc3QgY2FsbGJhY2sgPSAoZXJyb3I6IEVycm9yKSA9PiB7XG4gICAgICAgIGlmICghIWVycm9yKSB7XG4gICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICByZXNvbHZlKHB1Ymxpc2hlcik7XG4gICAgICAgIH1cbiAgICAgIH07XG5cbiAgICAgIGlmICghIXByb3BlcnRpZXMpIHtcbiAgICAgICAgcHVibGlzaGVyID0gdGhpcy5pbml0UHVibGlzaGVyKHRhcmdldEVsZW1lbnQsIHByb3BlcnRpZXMsIGNhbGxiYWNrKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHB1Ymxpc2hlciA9IHRoaXMuaW5pdFB1Ymxpc2hlcih0YXJnZXRFbGVtZW50LCBjYWxsYmFjayk7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIGEgbmV3IGxvY2FsIHJlY29yZGVyIGZvciByZWNvcmRpbmcgc3RyZWFtcyBzdHJhaWdodCBhd2F5IGZyb20gdGhlIGJyb3dzZXJcbiAgICogQHBhcmFtIHN0cmVhbSAgU3RyZWFtIHRvIHJlY29yZFxuICAgKi9cbiAgaW5pdExvY2FsUmVjb3JkZXIoc3RyZWFtOiBTdHJlYW0pOiBMb2NhbFJlY29yZGVyIHtcbiAgICByZXR1cm4gbmV3IExvY2FsUmVjb3JkZXIoc3RyZWFtKTtcbiAgfVxuXG5cbiAgLyoqXG4gICAqIENoZWNrcyBpZiB0aGUgYnJvd3NlciBzdXBwb3J0cyBPcGVuVmlkdVxuICAgKiBAcmV0dXJucyAxIGlmIHRoZSBicm93c2VyIHN1cHBvcnRzIE9wZW5WaWR1LCAwIG90aGVyd2lzZVxuICAgKi9cbiAgY2hlY2tTeXN0ZW1SZXF1aXJlbWVudHMoKTogbnVtYmVyIHtcbiAgICBjb25zdCBicm93c2VyID0gcGxhdGZvcm0ubmFtZTtcbiAgICBjb25zdCB2ZXJzaW9uID0gcGxhdGZvcm0udmVyc2lvbjtcblxuICAgIGlmICgoYnJvd3NlciAhPT0gJ0Nocm9tZScpICYmIChicm93c2VyICE9PSAnQ2hyb21lIE1vYmlsZScpICYmXG4gICAgICAoYnJvd3NlciAhPT0gJ0ZpcmVmb3gnKSAmJiAoYnJvd3NlciAhPT0gJ0ZpcmVmb3ggTW9iaWxlJykgJiYgKGJyb3dzZXIgIT09ICdGaXJlZm94IGZvciBpT1MnKSAmJlxuICAgICAgKGJyb3dzZXIgIT09ICdPcGVyYScpICYmIChicm93c2VyICE9PSAnT3BlcmEgTW9iaWxlJykgJiZcbiAgICAgIChicm93c2VyICE9PSAnU2FmYXJpJykpIHtcbiAgICAgIHJldHVybiAwO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gMTtcbiAgICB9XG4gIH1cblxuXG4gIC8qKlxuICAgKiBDb2xsZWN0cyBpbmZvcm1hdGlvbiBhYm91dCB0aGUgbWVkaWEgaW5wdXQgZGV2aWNlcyBhdmFpbGFibGUgb24gdGhlIHN5c3RlbS4gWW91IGNhbiBwYXNzIHByb3BlcnR5IGBkZXZpY2VJZGAgb2YgYSBbW0RldmljZV1dIG9iamVjdCBhcyB2YWx1ZSBvZiBgYXVkaW9Tb3VyY2VgIG9yIGB2aWRlb1NvdXJjZWAgcHJvcGVydGllcyBpbiBbW2luaXRQdWJsaXNoZXJdXSBtZXRob2RcbiAgICovXG4gIGdldERldmljZXMoKTogUHJvbWlzZTxEZXZpY2VbXT4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZTxEZXZpY2VbXT4oKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgbmF2aWdhdG9yLm1lZGlhRGV2aWNlcy5lbnVtZXJhdGVEZXZpY2VzKCkudGhlbigoZGV2aWNlSW5mb3MpID0+IHtcbiAgICAgICAgY29uc3QgZGV2aWNlczogRGV2aWNlW10gPSBbXTtcbiAgICAgICAgZGV2aWNlSW5mb3MuZm9yRWFjaChkZXZpY2VJbmZvID0+IHtcbiAgICAgICAgICBpZiAoZGV2aWNlSW5mby5raW5kID09PSAnYXVkaW9pbnB1dCcgfHwgZGV2aWNlSW5mby5raW5kID09PSAndmlkZW9pbnB1dCcpIHtcbiAgICAgICAgICAgIGRldmljZXMucHVzaCh7XG4gICAgICAgICAgICAgIGtpbmQ6IGRldmljZUluZm8ua2luZCxcbiAgICAgICAgICAgICAgZGV2aWNlSWQ6IGRldmljZUluZm8uZGV2aWNlSWQsXG4gICAgICAgICAgICAgIGxhYmVsOiBkZXZpY2VJbmZvLmxhYmVsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICByZXNvbHZlKGRldmljZXMpO1xuICAgICAgfSkuY2F0Y2goKGVycm9yKSA9PiB7XG4gICAgICAgIGNvbnNvbGUuZXJyb3IoJ0Vycm9yIGdldHRpbmcgZGV2aWNlcycsIGVycm9yKTtcbiAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9XG5cblxuICAvKipcbiAgICogR2V0IGEgTWVkaWFTdHJlYW0gb2JqZWN0IHRoYXQgeW91IGNhbiBjdXN0b21pemUgYmVmb3JlIGNhbGxpbmcgW1tpbml0UHVibGlzaGVyXV0gKHBhc3MgX01lZGlhU3RyZWFtVHJhY2tfIHByb3BlcnR5IG9mIHRoZSBfTWVkaWFTdHJlYW1fIHZhbHVlIHJlc29sdmVkIGJ5IHRoZSBQcm9taXNlIGFzIGBhdWRpb1NvdXJjZWAgb3IgYHZpZGVvU291cmNlYCBwcm9wZXJ0aWVzIGluIFtbaW5pdFB1Ymxpc2hlcl1dKVxuICAgKlxuICAgKiBQYXJhbWV0ZXIgYG9wdGlvbnNgIGlzIHRoZSBzYW1lIGFzIGluIFtbaW5pdFB1Ymxpc2hlcl1dIHNlY29uZCBwYXJhbWV0ZXIgKG9mIHR5cGUgW1tQdWJsaXNoZXJQcm9wZXJ0aWVzXV0pLCBidXQgb25seSB0aGUgZm9sbG93aW5nIHByb3BlcnRpZXMgd2lsbCBiZSBhcHBsaWVkOiBgYXVkaW9Tb3VyY2VgLCBgdmlkZW9Tb3VyY2VgLCBgZnJhbWVSYXRlYCwgYHJlc29sdXRpb25gXG4gICAqXG4gICAqIFRvIGN1c3RvbWl6ZSB0aGUgUHVibGlzaGVyJ3MgdmlkZW8sIHRoZSBBUEkgZm9yIEhUTUxDYW52YXNFbGVtZW50IGlzIHZlcnkgdXNlZnVsLiBGb3IgZXhhbXBsZSwgdG8gZ2V0IGEgYmxhY2stYW5kLXdoaXRlIHZpZGVvIGF0IDEwIGZwcyBhbmQgSEQgcmVzb2x1dGlvbiB3aXRoIG5vIHNvdW5kOlxuICAgKiBgYGBcbiAgICogdmFyIE9WID0gbmV3IE9wZW5WaWR1KCk7XG4gICAqIHZhciBGUkFNRV9SQVRFID0gMTA7XG4gICAqXG4gICAqIE9WLmdldFVzZXJNZWRpYSh7XG4gICAqICAgIGF1ZGlvU291cmNlOiBmYWxzZTtcbiAgICogICAgdmlkZW9Tb3VyY2U6IHVuZGVmaW5lZCxcbiAgICogICAgcmVzb2x1dGlvbjogJzEyODB4NzIwJyxcbiAgICogICAgZnJhbWVSYXRlOiBGUkFNRV9SQVRFXG4gICAqIH0pXG4gICAqIC50aGVuKG1lZGlhU3RyZWFtID0+IHtcbiAgICpcbiAgICogICAgdmFyIHZpZGVvVHJhY2sgPSBtZWRpYVN0cmVhbS5nZXRWaWRlb1RyYWNrcygpWzBdO1xuICAgKiAgICB2YXIgdmlkZW8gPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCd2aWRlbycpO1xuICAgKiAgICB2aWRlby5zcmNPYmplY3QgPSBuZXcgTWVkaWFTdHJlYW0oW3ZpZGVvVHJhY2tdKTtcbiAgICpcbiAgICogICAgdmFyIGNhbnZhcyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2NhbnZhcycpO1xuICAgKiAgICB2YXIgY3R4ID0gY2FudmFzLmdldENvbnRleHQoJzJkJyk7XG4gICAqICAgIGN0eC5maWx0ZXIgPSAnZ3JheXNjYWxlKDEwMCUpJztcbiAgICpcbiAgICogICAgdmlkZW8uYWRkRXZlbnRMaXN0ZW5lcigncGxheScsICgpID0+IHtcbiAgICogICAgICB2YXIgbG9vcCA9ICgpID0+IHtcbiAgICogICAgICAgIGlmICghdmlkZW8ucGF1c2VkICYmICF2aWRlby5lbmRlZCkge1xuICAgKiAgICAgICAgICBjdHguZHJhd0ltYWdlKHZpZGVvLCAwLCAwLCAzMDAsIDE3MCk7XG4gICAqICAgICAgICAgIHNldFRpbWVvdXQobG9vcCwgMTAwMC8gRlJBTUVfUkFURSk7IC8vIERyYXdpbmcgYXQgMTAgZnBzXG4gICAqICAgICAgICB9XG4gICAqICAgICAgfTtcbiAgICogICAgICBsb29wKCk7XG4gICAqICAgIH0pO1xuICAgKiAgICB2aWRlby5wbGF5KCk7XG4gICAqXG4gICAqICAgIHZhciBncmF5VmlkZW9UcmFjayA9IGNhbnZhcy5jYXB0dXJlU3RyZWFtKEZSQU1FX1JBVEUpLmdldFZpZGVvVHJhY2tzKClbMF07XG4gICAqICAgIHZhciBwdWJsaXNoZXIgPSB0aGlzLk9WLmluaXRQdWJsaXNoZXIoXG4gICAqICAgICAgbXlIdG1sVGFyZ2V0LFxuICAgKiAgICAgIHtcbiAgICogICAgICAgIGF1ZGlvU291cmNlOiBmYWxzZSxcbiAgICogICAgICAgIHZpZGVvU291cmNlOiBncmF5VmlkZW9UcmFja1xuICAgKiAgICAgIH0pO1xuICAgKiB9KTtcbiAgICogYGBgXG4gICAqL1xuICBnZXRVc2VyTWVkaWEob3B0aW9uczogUHVibGlzaGVyUHJvcGVydGllcyk6IFByb21pc2U8TWVkaWFTdHJlYW0+IHtcbiAgICByZXR1cm4gbmV3IFByb21pc2U8TWVkaWFTdHJlYW0+KChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIHRoaXMuZ2VuZXJhdGVNZWRpYUNvbnN0cmFpbnRzKG9wdGlvbnMpXG4gICAgICAgIC50aGVuKGNvbnN0cmFpbnRzID0+IHtcbiAgICAgICAgICBuYXZpZ2F0b3IubWVkaWFEZXZpY2VzLmdldFVzZXJNZWRpYShjb25zdHJhaW50cylcbiAgICAgICAgICAgIC50aGVuKG1lZGlhU3RyZWFtID0+IHtcbiAgICAgICAgICAgICAgcmVzb2x2ZShtZWRpYVN0cmVhbSk7XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICAgICAgbGV0IGVycm9yTmFtZTogT3BlblZpZHVFcnJvck5hbWU7XG4gICAgICAgICAgICAgIGNvbnN0IGVycm9yTWVzc2FnZSA9IGVycm9yLnRvU3RyaW5nKCk7XG4gICAgICAgICAgICAgIGlmICghKG9wdGlvbnMudmlkZW9Tb3VyY2UgPT09ICdzY3JlZW4nKSkge1xuICAgICAgICAgICAgICAgIGVycm9yTmFtZSA9IE9wZW5WaWR1RXJyb3JOYW1lLkRFVklDRV9BQ0NFU1NfREVOSUVEO1xuICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGVycm9yTmFtZSA9IE9wZW5WaWR1RXJyb3JOYW1lLlNDUkVFTl9DQVBUVVJFX0RFTklFRDtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICByZWplY3QobmV3IE9wZW5WaWR1RXJyb3IoZXJyb3JOYW1lLCBlcnJvck1lc3NhZ2UpKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KVxuICAgICAgICAuY2F0Y2goKGVycm9yOiBPcGVuVmlkdUVycm9yKSA9PiB7XG4gICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgfSk7XG4gICAgfSk7XG4gIH1cblxuXG4gIC8qIHRzbGludDpkaXNhYmxlOm5vLWVtcHR5ICovXG4gIC8qKlxuICAgKiBEaXNhYmxlIGFsbCBsb2dnaW5nIGV4Y2VwdCBlcnJvciBsZXZlbFxuICAgKi9cbiAgZW5hYmxlUHJvZE1vZGUoKTogdm9pZCB7XG4gICAgY29uc29sZS5sb2cgPSAoKSA9PiB7IH07XG4gICAgY29uc29sZS5kZWJ1ZyA9ICgpID0+IHsgfTtcbiAgICBjb25zb2xlLmluZm8gPSAoKSA9PiB7IH07XG4gICAgY29uc29sZS53YXJuID0gKCkgPT4geyB9O1xuICB9XG4gIC8qIHRzbGludDplbmFibGU6bm8tZW1wdHkgKi9cblxuXG4gIC8qKlxuICAgKiBTZXQgT3BlblZpZHUgYWR2YW5jZWQgY29uZmlndXJhdGlvbiBvcHRpb25zLiBDdXJyZW50bHkgYGNvbmZpZ3VyYXRpb25gIGlzIGFuIG9iamVjdCB3aXRoIHRoZSBmb2xsb3dpbmcgb3B0aW9uYWwgcHJvcGVydGllcyAoc2VlIFtbT3BlblZpZHVBZHZhbmNlZENvbmZpZ3VyYXRpb25dXSBmb3IgbW9yZSBkZXRhaWxzKTpcbiAgICogLSBgaWNlU2VydmVyc2A6IHNldCBjdXN0b20gU1RVTi9UVVJOIHNlcnZlcnMgdG8gYmUgdXNlZCBieSBPcGVuVmlkdSBCcm93c2VyXG4gICAqIC0gYHNjcmVlblNoYXJlQ2hyb21lRXh0ZW5zaW9uYDogdXJsIHRvIGEgY3VzdG9tIHNjcmVlbiBzaGFyZSBleHRlbnNpb24gZm9yIENocm9tZSB0byBiZSB1c2VkIGluc3RlYWQgb2YgdGhlIGRlZmF1bHQgb25lLCBiYXNlZCBvbiBvdXJzIFtodHRwczovL2dpdGh1Yi5jb20vT3BlblZpZHUvb3BlbnZpZHUtc2NyZWVuLXNoYXJpbmctY2hyb21lLWV4dGVuc2lvbl0oaHR0cHM6Ly9naXRodWIuY29tL09wZW5WaWR1L29wZW52aWR1LXNjcmVlbi1zaGFyaW5nLWNocm9tZS1leHRlbnNpb24pXG4gICAqIC0gYHB1Ymxpc2hlclNwZWFraW5nRXZlbnRzT3B0aW9uc2A6IGN1c3RvbSBjb25maWd1cmF0aW9uIGZvciB0aGUgW1tQdWJsaXNoZXJTcGVha2luZ0V2ZW50XV0gZmVhdHVyZVxuICAgKi9cbiAgc2V0QWR2YW5jZWRDb25maWd1cmF0aW9uKGNvbmZpZ3VyYXRpb246IE9wZW5WaWR1QWR2YW5jZWRDb25maWd1cmF0aW9uKTogdm9pZCB7XG4gICAgdGhpcy5hZHZhbmNlZENvbmZpZ3VyYXRpb24gPSBjb25maWd1cmF0aW9uO1xuICB9XG5cblxuICAvKiBIaWRkZW4gbWV0aG9kcyAqL1xuXG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICBnZW5lcmF0ZU1lZGlhQ29uc3RyYWludHMocHVibGlzaGVyUHJvcGVydGllczogUHVibGlzaGVyUHJvcGVydGllcyk6IFByb21pc2U8TWVkaWFTdHJlYW1Db25zdHJhaW50cz4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZTxNZWRpYVN0cmVhbUNvbnN0cmFpbnRzPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICBsZXQgYXVkaW8sIHZpZGVvO1xuXG4gICAgICBpZiAocHVibGlzaGVyUHJvcGVydGllcy5hdWRpb1NvdXJjZSA9PT0gbnVsbCB8fCBwdWJsaXNoZXJQcm9wZXJ0aWVzLmF1ZGlvU291cmNlID09PSBmYWxzZSkge1xuICAgICAgICBhdWRpbyA9IGZhbHNlO1xuICAgICAgfSBlbHNlIGlmIChwdWJsaXNoZXJQcm9wZXJ0aWVzLmF1ZGlvU291cmNlID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgYXVkaW8gPSB0cnVlO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgYXVkaW8gPSBwdWJsaXNoZXJQcm9wZXJ0aWVzLmF1ZGlvU291cmNlO1xuICAgICAgfVxuXG4gICAgICBpZiAocHVibGlzaGVyUHJvcGVydGllcy52aWRlb1NvdXJjZSA9PT0gbnVsbCB8fCBwdWJsaXNoZXJQcm9wZXJ0aWVzLnZpZGVvU291cmNlID09PSBmYWxzZSkge1xuICAgICAgICB2aWRlbyA9IGZhbHNlO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdmlkZW8gPSB7XG4gICAgICAgICAgaGVpZ2h0OiB7XG4gICAgICAgICAgICBpZGVhbDogNDgwXG4gICAgICAgICAgfSxcbiAgICAgICAgICB3aWR0aDoge1xuICAgICAgICAgICAgaWRlYWw6IDY0MFxuICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgbWVkaWFDb25zdHJhaW50czogTWVkaWFTdHJlYW1Db25zdHJhaW50cyA9IHtcbiAgICAgICAgYXVkaW8sXG4gICAgICAgIHZpZGVvXG4gICAgICB9O1xuXG4gICAgICBpZiAodHlwZW9mIG1lZGlhQ29uc3RyYWludHMuYXVkaW8gPT09ICdzdHJpbmcnKSB7XG4gICAgICAgIG1lZGlhQ29uc3RyYWludHMuYXVkaW8gPSB7IGRldmljZUlkOiB7IGV4YWN0OiBtZWRpYUNvbnN0cmFpbnRzLmF1ZGlvIH0gfTtcbiAgICAgIH1cblxuICAgICAgaWYgKG1lZGlhQ29uc3RyYWludHMudmlkZW8pIHtcblxuICAgICAgICBpZiAoISFwdWJsaXNoZXJQcm9wZXJ0aWVzLnJlc29sdXRpb24pIHtcbiAgICAgICAgICBjb25zdCB3aWR0aEFuZEhlaWdodCA9IHB1Ymxpc2hlclByb3BlcnRpZXMucmVzb2x1dGlvbi50b0xvd2VyQ2FzZSgpLnNwbGl0KCd4Jyk7XG4gICAgICAgICAgY29uc3Qgd2lkdGggPSBOdW1iZXIod2lkdGhBbmRIZWlnaHRbMF0pO1xuICAgICAgICAgIGNvbnN0IGhlaWdodCA9IE51bWJlcih3aWR0aEFuZEhlaWdodFsxXSk7XG4gICAgICAgICAgKG1lZGlhQ29uc3RyYWludHMudmlkZW8gYXMgYW55KS53aWR0aC5pZGVhbCA9IHdpZHRoO1xuICAgICAgICAgIChtZWRpYUNvbnN0cmFpbnRzLnZpZGVvIGFzIGFueSkuaGVpZ2h0LmlkZWFsID0gaGVpZ2h0O1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCEhcHVibGlzaGVyUHJvcGVydGllcy5mcmFtZVJhdGUpIHtcbiAgICAgICAgICAobWVkaWFDb25zdHJhaW50cy52aWRlbyBhcyBhbnkpLmZyYW1lUmF0ZSA9IHsgaWRlYWw6IHB1Ymxpc2hlclByb3BlcnRpZXMuZnJhbWVSYXRlIH07XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoISFwdWJsaXNoZXJQcm9wZXJ0aWVzLnZpZGVvU291cmNlICYmIHR5cGVvZiBwdWJsaXNoZXJQcm9wZXJ0aWVzLnZpZGVvU291cmNlID09PSAnc3RyaW5nJykge1xuXG4gICAgICAgICAgaWYgKHB1Ymxpc2hlclByb3BlcnRpZXMudmlkZW9Tb3VyY2UgPT09ICdzY3JlZW4nKSB7XG5cbiAgICAgICAgICAgIGlmIChwbGF0Zm9ybS5uYW1lICE9PSAnQ2hyb21lJyAmJiBwbGF0Zm9ybS5uYW1lIS5pbmRleE9mKCdGaXJlZm94JykgPT09IC0xKSB7XG4gICAgICAgICAgICAgIGNvbnN0IGVycm9yID0gbmV3IE9wZW5WaWR1RXJyb3IoT3BlblZpZHVFcnJvck5hbWUuU0NSRUVOX1NIQVJJTkdfTk9UX1NVUFBPUlRFRCwgJ1lvdSBjYW4gb25seSBzY3JlZW4gc2hhcmUgaW4gZGVza3RvcCBDaHJvbWUgYW5kIEZpcmVmb3guIERldGVjdGVkIGJyb3dzZXI6ICcgKyBwbGF0Zm9ybS5uYW1lKTtcbiAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihlcnJvcik7XG4gICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICB9IGVsc2Uge1xuXG4gICAgICAgICAgICAgIGlmICghIXRoaXMuYWR2YW5jZWRDb25maWd1cmF0aW9uLnNjcmVlblNoYXJlQ2hyb21lRXh0ZW5zaW9uICYmICEocGxhdGZvcm0ubmFtZSEuaW5kZXhPZignRmlyZWZveCcpICE9PSAtMSkpIHtcblxuICAgICAgICAgICAgICAgIC8vIEN1c3RvbSBzY3JlZW4gc2hhcmluZyBleHRlbnNpb24gZm9yIENocm9tZVxuXG4gICAgICAgICAgICAgICAgc2NyZWVuU2hhcmluZy5nZXRTY3JlZW5Db25zdHJhaW50cygoZXJyb3IsIHNjcmVlbkNvbnN0cmFpbnRzKSA9PiB7XG4gICAgICAgICAgICAgICAgICBpZiAoISFlcnJvciB8fCAhIXNjcmVlbkNvbnN0cmFpbnRzLm1hbmRhdG9yeSAmJiBzY3JlZW5Db25zdHJhaW50cy5tYW5kYXRvcnkuY2hyb21lTWVkaWFTb3VyY2UgPT09ICdzY3JlZW4nKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnJvciA9PT0gJ3Blcm1pc3Npb24tZGVuaWVkJyB8fCBlcnJvciA9PT0gJ1Blcm1pc3Npb25EZW5pZWRFcnJvcicpIHtcbiAgICAgICAgICAgICAgICAgICAgICBjb25zdCBlcnJvciA9IG5ldyBPcGVuVmlkdUVycm9yKE9wZW5WaWR1RXJyb3JOYW1lLlNDUkVFTl9DQVBUVVJFX0RFTklFRCwgJ1lvdSBtdXN0IGFsbG93IGFjY2VzcyB0byBvbmUgd2luZG93IG9mIHlvdXIgZGVza3RvcCcpO1xuICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgY29uc3QgZXh0ZW5zaW9uSWQgPSB0aGlzLmFkdmFuY2VkQ29uZmlndXJhdGlvbi5zY3JlZW5TaGFyZUNocm9tZUV4dGVuc2lvbiEuc3BsaXQoJy8nKS5wb3AoKSEhLnRyaW0oKTtcbiAgICAgICAgICAgICAgICAgICAgICBzY3JlZW5TaGFyaW5nLmdldENocm9tZUV4dGVuc2lvblN0YXR1cyhleHRlbnNpb25JZCwgKHN0YXR1cykgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHN0YXR1cyA9PT0gJ2luc3RhbGxlZC1kaXNhYmxlZCcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZXJyb3IgPSBuZXcgT3BlblZpZHVFcnJvcihPcGVuVmlkdUVycm9yTmFtZS5TQ1JFRU5fRVhURU5TSU9OX0RJU0FCTEVELCAnWW91IG11c3QgZW5hYmxlIHRoZSBzY3JlZW4gZXh0ZW5zaW9uJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHN0YXR1cyA9PT0gJ25vdC1pbnN0YWxsZWQnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGVycm9yID0gbmV3IE9wZW5WaWR1RXJyb3IoT3BlblZpZHVFcnJvck5hbWUuU0NSRUVOX0VYVEVOU0lPTl9OT1RfSU5TVEFMTEVELCAoPHN0cmluZz50aGlzLmFkdmFuY2VkQ29uZmlndXJhdGlvbi5zY3JlZW5TaGFyZUNocm9tZUV4dGVuc2lvbikpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgbWVkaWFDb25zdHJhaW50cy52aWRlbyA9IHNjcmVlbkNvbnN0cmFpbnRzO1xuICAgICAgICAgICAgICAgICAgICByZXNvbHZlKG1lZGlhQ29uc3RyYWludHMpO1xuICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICB9IGVsc2Uge1xuXG4gICAgICAgICAgICAgICAgLy8gRGVmYXVsdCBzY3JlZW4gc2hhcmluZyBleHRlbnNpb24gZm9yIENocm9tZVxuXG4gICAgICAgICAgICAgICAgc2NyZWVuU2hhcmluZ0F1dG8uZ2V0U2NyZWVuSWQoKGVycm9yLCBzb3VyY2VJZCwgc2NyZWVuQ29uc3RyYWludHMpID0+IHtcbiAgICAgICAgICAgICAgICAgIGlmICghIWVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnJvciA9PT0gJ25vdC1pbnN0YWxsZWQnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgY29uc3QgZXh0ZW5zaW9uVXJsID0gISF0aGlzLmFkdmFuY2VkQ29uZmlndXJhdGlvbi5zY3JlZW5TaGFyZUNocm9tZUV4dGVuc2lvbiA/IHRoaXMuYWR2YW5jZWRDb25maWd1cmF0aW9uLnNjcmVlblNoYXJlQ2hyb21lRXh0ZW5zaW9uIDpcbiAgICAgICAgICAgICAgICAgICAgICAgICdodHRwczovL2Nocm9tZS5nb29nbGUuY29tL3dlYnN0b3JlL2RldGFpbC9vcGVudmlkdS1zY3JlZW5zaGFyaW5nL2xmY2dmZXBhZm5vYmRsb2VjY2huZmFjbGliZW5qb2xkJztcbiAgICAgICAgICAgICAgICAgICAgICBjb25zdCBlcnJvciA9IG5ldyBPcGVuVmlkdUVycm9yKE9wZW5WaWR1RXJyb3JOYW1lLlNDUkVFTl9FWFRFTlNJT05fTk9UX0lOU1RBTExFRCwgZXh0ZW5zaW9uVXJsKTtcbiAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGVycm9yID09PSAnaW5zdGFsbGVkLWRpc2FibGVkJykge1xuICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGVycm9yID0gbmV3IE9wZW5WaWR1RXJyb3IoT3BlblZpZHVFcnJvck5hbWUuU0NSRUVOX0VYVEVOU0lPTl9ESVNBQkxFRCwgJ1lvdSBtdXN0IGVuYWJsZSB0aGUgc2NyZWVuIGV4dGVuc2lvbicpO1xuICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoZXJyb3IgPT09ICdwZXJtaXNzaW9uLWRlbmllZCcpIHtcbiAgICAgICAgICAgICAgICAgICAgICBjb25zdCBlcnJvciA9IG5ldyBPcGVuVmlkdUVycm9yKE9wZW5WaWR1RXJyb3JOYW1lLlNDUkVFTl9DQVBUVVJFX0RFTklFRCwgJ1lvdSBtdXN0IGFsbG93IGFjY2VzcyB0byBvbmUgd2luZG93IG9mIHlvdXIgZGVza3RvcCcpO1xuICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIG1lZGlhQ29uc3RyYWludHMudmlkZW8gPSBzY3JlZW5Db25zdHJhaW50cy52aWRlbztcbiAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZShtZWRpYUNvbnN0cmFpbnRzKTtcbiAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgIHB1Ymxpc2hlclByb3BlcnRpZXMudmlkZW9Tb3VyY2UgPSAnc2NyZWVuJztcblxuICAgICAgICAgICAgfVxuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6bm8tc3RyaW5nLWxpdGVyYWxcbiAgICAgICAgICAgIG1lZGlhQ29uc3RyYWludHMudmlkZW9bJ2RldmljZUlkJ10gPSB7IGV4YWN0OiBwdWJsaXNoZXJQcm9wZXJ0aWVzLnZpZGVvU291cmNlIH07XG4gICAgICAgICAgICByZXNvbHZlKG1lZGlhQ29uc3RyYWludHMpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICByZXNvbHZlKG1lZGlhQ29uc3RyYWludHMpO1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXNvbHZlKG1lZGlhQ29uc3RyYWludHMpO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIEBoaWRkZW5cbiAgICovXG4gIHN0YXJ0V3Mob25Db25uZWN0U3VjY2VzOiAoZXJyb3I6IEVycm9yKSA9PiB2b2lkKTogdm9pZCB7XG4gICAgY29uc3QgY29uZmlnID0ge1xuICAgICAgaGVhcnRiZWF0OiA1MDAwLFxuICAgICAgc2VuZENsb3NlTWVzc2FnZTogZmFsc2UsXG4gICAgICB3czoge1xuICAgICAgICB1cmk6IHRoaXMud3NVcmksXG4gICAgICAgIHVzZVNvY2tKUzogZmFsc2UsXG4gICAgICAgIG9uY29ubmVjdGVkOiBvbkNvbm5lY3RTdWNjZXMsXG4gICAgICAgIG9uZGlzY29ubmVjdDogdGhpcy5kaXNjb25uZWN0Q2FsbGJhY2suYmluZCh0aGlzKSxcbiAgICAgICAgb25yZWNvbm5lY3Rpbmc6IHRoaXMucmVjb25uZWN0aW5nQ2FsbGJhY2suYmluZCh0aGlzKSxcbiAgICAgICAgb25yZWNvbm5lY3RlZDogdGhpcy5yZWNvbm5lY3RlZENhbGxiYWNrLmJpbmQodGhpcylcbiAgICAgIH0sXG4gICAgICBycGM6IHtcbiAgICAgICAgcmVxdWVzdFRpbWVvdXQ6IDEwMDAwLFxuICAgICAgICBwYXJ0aWNpcGFudEpvaW5lZDogdGhpcy5zZXNzaW9uLm9uUGFydGljaXBhbnRKb2luZWQuYmluZCh0aGlzLnNlc3Npb24pLFxuICAgICAgICBwYXJ0aWNpcGFudFB1Ymxpc2hlZDogdGhpcy5zZXNzaW9uLm9uUGFydGljaXBhbnRQdWJsaXNoZWQuYmluZCh0aGlzLnNlc3Npb24pLFxuICAgICAgICBwYXJ0aWNpcGFudFVucHVibGlzaGVkOiB0aGlzLnNlc3Npb24ub25QYXJ0aWNpcGFudFVucHVibGlzaGVkLmJpbmQodGhpcy5zZXNzaW9uKSxcbiAgICAgICAgcGFydGljaXBhbnRMZWZ0OiB0aGlzLnNlc3Npb24ub25QYXJ0aWNpcGFudExlZnQuYmluZCh0aGlzLnNlc3Npb24pLFxuICAgICAgICBwYXJ0aWNpcGFudEV2aWN0ZWQ6IHRoaXMuc2Vzc2lvbi5vblBhcnRpY2lwYW50RXZpY3RlZC5iaW5kKHRoaXMuc2Vzc2lvbiksXG4gICAgICAgIHJlY29yZGluZ1N0YXJ0ZWQ6IHRoaXMuc2Vzc2lvbi5vblJlY29yZGluZ1N0YXJ0ZWQuYmluZCh0aGlzLnNlc3Npb24pLFxuICAgICAgICByZWNvcmRpbmdTdG9wcGVkOiB0aGlzLnNlc3Npb24ub25SZWNvcmRpbmdTdG9wcGVkLmJpbmQodGhpcy5zZXNzaW9uKSxcbiAgICAgICAgc2VuZE1lc3NhZ2U6IHRoaXMuc2Vzc2lvbi5vbk5ld01lc3NhZ2UuYmluZCh0aGlzLnNlc3Npb24pLFxuICAgICAgICBzdHJlYW1Qcm9wZXJ0eUNoYW5nZWQ6IHRoaXMuc2Vzc2lvbi5vblN0cmVhbVByb3BlcnR5Q2hhbmdlZC5iaW5kKHRoaXMuc2Vzc2lvbiksXG4gICAgICAgIGljZUNhbmRpZGF0ZTogdGhpcy5zZXNzaW9uLnJlY3ZJY2VDYW5kaWRhdGUuYmluZCh0aGlzLnNlc3Npb24pLFxuICAgICAgICBtZWRpYUVycm9yOiB0aGlzLnNlc3Npb24ub25NZWRpYUVycm9yLmJpbmQodGhpcy5zZXNzaW9uKVxuICAgICAgfVxuICAgIH07XG4gICAgdGhpcy5qc29uUnBjQ2xpZW50ID0gbmV3IFJwY0J1aWxkZXIuY2xpZW50cy5Kc29uUnBjQ2xpZW50KGNvbmZpZyk7XG4gIH1cblxuICAvKipcbiAgICogQGhpZGRlblxuICAgKi9cbiAgY2xvc2VXcygpOiB2b2lkIHtcbiAgICB0aGlzLmpzb25ScGNDbGllbnQuY2xvc2UoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICBzZW5kUmVxdWVzdChtZXRob2Q6IHN0cmluZywgcGFyYW1zOiBhbnksIGNhbGxiYWNrPyk6IHZvaWQge1xuICAgIGlmIChwYXJhbXMgJiYgcGFyYW1zIGluc3RhbmNlb2YgRnVuY3Rpb24pIHtcbiAgICAgIGNhbGxiYWNrID0gcGFyYW1zO1xuICAgICAgcGFyYW1zID0ge307XG4gICAgfVxuICAgIGNvbnNvbGUuZGVidWcoJ1NlbmRpbmcgcmVxdWVzdDoge21ldGhvZDpcIicgKyBtZXRob2QgKyAnXCIsIHBhcmFtczogJyArIEpTT04uc3RyaW5naWZ5KHBhcmFtcykgKyAnfScpO1xuICAgIHRoaXMuanNvblJwY0NsaWVudC5zZW5kKG1ldGhvZCwgcGFyYW1zLCBjYWxsYmFjayk7XG4gIH1cblxuICAvKipcbiAgICogQGhpZGRlblxuICAgKi9cbiAgaXNNZWRpYVN0cmVhbVRyYWNrKG1lZGlhU291cmNlOiBhbnkpOiBib29sZWFuIHtcbiAgICBjb25zdCBpcyA9ICghIW1lZGlhU291cmNlICYmXG4gICAgICBtZWRpYVNvdXJjZS5lbmFibGVkICE9PSB1bmRlZmluZWQgJiYgdHlwZW9mIG1lZGlhU291cmNlLmVuYWJsZWQgPT09ICdib29sZWFuJyAmJlxuICAgICAgbWVkaWFTb3VyY2UuaWQgIT09IHVuZGVmaW5lZCAmJiB0eXBlb2YgbWVkaWFTb3VyY2UuaWQgPT09ICdzdHJpbmcnICYmXG4gICAgICBtZWRpYVNvdXJjZS5raW5kICE9PSB1bmRlZmluZWQgJiYgdHlwZW9mIG1lZGlhU291cmNlLmtpbmQgPT09ICdzdHJpbmcnICYmXG4gICAgICBtZWRpYVNvdXJjZS5sYWJlbCAhPT0gdW5kZWZpbmVkICYmIHR5cGVvZiBtZWRpYVNvdXJjZS5sYWJlbCA9PT0gJ3N0cmluZycgJiZcbiAgICAgIG1lZGlhU291cmNlLm11dGVkICE9PSB1bmRlZmluZWQgJiYgdHlwZW9mIG1lZGlhU291cmNlLm11dGVkID09PSAnYm9vbGVhbicgJiZcbiAgICAgIG1lZGlhU291cmNlLnJlYWR5U3RhdGUgIT09IHVuZGVmaW5lZCAmJiB0eXBlb2YgbWVkaWFTb3VyY2UucmVhZHlTdGF0ZSA9PT0gJ3N0cmluZycpO1xuICAgIHJldHVybiBpcztcbiAgfVxuXG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICBnZXRXc1VyaSgpOiBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLndzVXJpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBoaWRkZW5cbiAgICovXG4gIGdldFNlY3JldCgpOiBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLnNlY3JldDtcbiAgfVxuXG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICBnZXRSZWNvcmRlcigpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5yZWNvcmRlcjtcbiAgfVxuXG5cbiAgLyogUHJpdmF0ZSBtZXRob2RzICovXG5cbiAgcHJpdmF0ZSBkaXNjb25uZWN0Q2FsbGJhY2soKTogdm9pZCB7XG4gICAgY29uc29sZS53YXJuKCdXZWJzb2NrZXQgY29ubmVjdGlvbiBsb3N0Jyk7XG4gICAgaWYgKHRoaXMuaXNSb29tQXZhaWxhYmxlKCkpIHtcbiAgICAgIHRoaXMuc2Vzc2lvbi5vbkxvc3RDb25uZWN0aW9uKCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGFsZXJ0KCdDb25uZWN0aW9uIGVycm9yLiBQbGVhc2UgcmVsb2FkIHBhZ2UuJyk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSByZWNvbm5lY3RpbmdDYWxsYmFjaygpOiB2b2lkIHtcbiAgICBjb25zb2xlLndhcm4oJ1dlYnNvY2tldCBjb25uZWN0aW9uIGxvc3QgKHJlY29ubmVjdGluZyknKTtcbiAgICBpZiAodGhpcy5pc1Jvb21BdmFpbGFibGUoKSkge1xuICAgICAgdGhpcy5zZXNzaW9uLm9uTG9zdENvbm5lY3Rpb24oKTtcbiAgICB9IGVsc2Uge1xuICAgICAgYWxlcnQoJ0Nvbm5lY3Rpb24gZXJyb3IuIFBsZWFzZSByZWxvYWQgcGFnZS4nKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIHJlY29ubmVjdGVkQ2FsbGJhY2soKTogdm9pZCB7XG4gICAgY29uc29sZS53YXJuKCdXZWJzb2NrZXQgcmVjb25uZWN0ZWQnKTtcbiAgICBpZiAodGhpcy5pc1Jvb21BdmFpbGFibGUoKSkge1xuICAgICAgdGhpcy5zZXNzaW9uLm9uUmVjb3ZlcmVkQ29ubmVjdGlvbigpO1xuICAgIH0gZWxzZSB7XG4gICAgICBhbGVydCgnQ29ubmVjdGlvbiBlcnJvci4gUGxlYXNlIHJlbG9hZCBwYWdlLicpO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgaXNSb29tQXZhaWxhYmxlKCk6IGJvb2xlYW4ge1xuICAgIGlmICh0aGlzLnNlc3Npb24gIT09IHVuZGVmaW5lZCAmJiB0aGlzLnNlc3Npb24gaW5zdGFuY2VvZiBTZXNzaW9uKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9IGVsc2Uge1xuICAgICAgY29uc29sZS53YXJuKCdTZXNzaW9uIGluc3RhbmNlIG5vdCBmb3VuZCcpO1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfVxuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBPcGVuVmlkdSB9IGZyb20gJy4vT3BlblZpZHUnO1xuaW1wb3J0IHsgU2Vzc2lvbiB9IGZyb20gJy4vU2Vzc2lvbic7XG5pbXBvcnQgeyBTdHJlYW0gfSBmcm9tICcuL1N0cmVhbSc7XG5pbXBvcnQgeyBTdHJlYW1NYW5hZ2VyIH0gZnJvbSAnLi9TdHJlYW1NYW5hZ2VyJztcbmltcG9ydCB7IEV2ZW50RGlzcGF0Y2hlciB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvSW50ZXJmYWNlcy9QdWJsaWMvRXZlbnREaXNwYXRjaGVyJztcbmltcG9ydCB7IFB1Ymxpc2hlclByb3BlcnRpZXMgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHVibGljL1B1Ymxpc2hlclByb3BlcnRpZXMnO1xuaW1wb3J0IHsgRXZlbnQgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0V2ZW50cy9FdmVudCc7XG5pbXBvcnQgeyBTdHJlYW1FdmVudCB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1N0cmVhbUV2ZW50JztcbmltcG9ydCB7IFN0cmVhbVByb3BlcnR5Q2hhbmdlZEV2ZW50IH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvU3RyZWFtUHJvcGVydHlDaGFuZ2VkRXZlbnQnO1xuaW1wb3J0IHsgVmlkZW9FbGVtZW50RXZlbnQgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0V2ZW50cy9WaWRlb0VsZW1lbnRFdmVudCc7XG5pbXBvcnQgeyBPcGVuVmlkdUVycm9yLCBPcGVuVmlkdUVycm9yTmFtZSB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRW51bXMvT3BlblZpZHVFcnJvcic7XG5pbXBvcnQgeyBWaWRlb0luc2VydE1vZGUgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0VudW1zL1ZpZGVvSW5zZXJ0TW9kZSc7XG5cbmltcG9ydCBwbGF0Zm9ybSA9IHJlcXVpcmUoJ3BsYXRmb3JtJyk7XG5cblxuLyoqXG4gKiBQYWNrcyBsb2NhbCBtZWRpYSBzdHJlYW1zLiBQYXJ0aWNpcGFudHMgY2FuIHB1Ymxpc2ggaXQgdG8gYSBzZXNzaW9uLiBJbml0aWFsaXplZCB3aXRoIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dIG1ldGhvZFxuICovXG5leHBvcnQgY2xhc3MgUHVibGlzaGVyIGV4dGVuZHMgU3RyZWFtTWFuYWdlciB7XG5cbiAgICAvKipcbiAgICAgKiBXaGV0aGVyIHRoZSBQdWJsaXNoZXIgaGFzIGJlZW4gZ3JhbnRlZCBhY2Nlc3MgdG8gdGhlIHJlcXVlc3RlZCBpbnB1dCBkZXZpY2VzIG9yIG5vdFxuICAgICAqL1xuICAgIGFjY2Vzc0FsbG93ZWQgPSBmYWxzZTtcblxuICAgIC8qKlxuICAgICAqIFdoZXRoZXIgeW91IGhhdmUgY2FsbGVkIFtbUHVibGlzaGVyLnN1YnNjcmliZVRvUmVtb3RlXV0gd2l0aCB2YWx1ZSBgdHJ1ZWAgb3IgYGZhbHNlYCAoKmZhbHNlKiBieSBkZWZhdWx0KVxuICAgICAqL1xuICAgIGlzU3Vic2NyaWJlZFRvUmVtb3RlID0gZmFsc2U7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgW1tTZXNzaW9uXV0gdG8gd2hpY2ggdGhlIFB1Ymxpc2hlciBiZWxvbmdzXG4gICAgICovXG4gICAgc2Vzc2lvbjogU2Vzc2lvbjsgLy8gSW5pdGlhbGl6ZWQgYnkgU2Vzc2lvbi5wdWJsaXNoKFB1Ymxpc2hlcilcblxuICAgIHByaXZhdGUgYWNjZXNzRGVuaWVkID0gZmFsc2U7XG4gICAgcHJpdmF0ZSBwcm9wZXJ0aWVzOiBQdWJsaXNoZXJQcm9wZXJ0aWVzO1xuICAgIHByaXZhdGUgcGVybWlzc2lvbkRpYWxvZ1RpbWVvdXQ6IE5vZGVKUy5UaW1lcjtcblxuICAgIC8qKlxuICAgICAqIGhpZGRlblxuICAgICAqL1xuICAgIG9wZW52aWR1OiBPcGVuVmlkdTtcbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgdmlkZW9SZWZlcmVuY2U6IEhUTUxWaWRlb0VsZW1lbnQ7XG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHNjcmVlblNoYXJlUmVzaXplSW50ZXJ2YWw6IE5vZGVKUy5UaW1lcjtcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3Rvcih0YXJnRWw6IHN0cmluZyB8IEhUTUxFbGVtZW50LCBwcm9wZXJ0aWVzOiBQdWJsaXNoZXJQcm9wZXJ0aWVzLCBvcGVudmlkdTogT3BlblZpZHUpIHtcbiAgICAgICAgc3VwZXIobmV3IFN0cmVhbSgoISFvcGVudmlkdS5zZXNzaW9uKSA/IG9wZW52aWR1LnNlc3Npb24gOiBuZXcgU2Vzc2lvbihvcGVudmlkdSksIHsgcHVibGlzaGVyUHJvcGVydGllczogcHJvcGVydGllcywgbWVkaWFDb25zdHJhaW50czoge30gfSksIHRhcmdFbCk7XG4gICAgICAgIHRoaXMucHJvcGVydGllcyA9IHByb3BlcnRpZXM7XG4gICAgICAgIHRoaXMub3BlbnZpZHUgPSBvcGVudmlkdTtcblxuICAgICAgICB0aGlzLnN0cmVhbS5lZS5vbignbG9jYWwtc3RyZWFtLWRlc3Ryb3llZCcsIChyZWFzb246IHN0cmluZykgPT4ge1xuICAgICAgICAgICAgdGhpcy5zdHJlYW0uaXNMb2NhbFN0cmVhbVB1Ymxpc2hlZCA9IGZhbHNlO1xuICAgICAgICAgICAgY29uc3Qgc3RyZWFtRXZlbnQgPSBuZXcgU3RyZWFtRXZlbnQodHJ1ZSwgdGhpcywgJ3N0cmVhbURlc3Ryb3llZCcsIHRoaXMuc3RyZWFtLCByZWFzb24pO1xuICAgICAgICAgICAgdGhpcy5lbWl0RXZlbnQoJ3N0cmVhbURlc3Ryb3llZCcsIFtzdHJlYW1FdmVudF0pO1xuICAgICAgICAgICAgc3RyZWFtRXZlbnQuY2FsbERlZmF1bHRCZWhhdmlvcigpO1xuICAgICAgICB9KTtcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFB1Ymxpc2ggb3IgdW5wdWJsaXNoIHRoZSBhdWRpbyBzdHJlYW0gKGlmIGF2YWlsYWJsZSkuIENhbGxpbmcgdGhpcyBtZXRob2QgdHdpY2UgaW4gYSByb3cgcGFzc2luZyBzYW1lIHZhbHVlIHdpbGwgaGF2ZSBubyBlZmZlY3RcbiAgICAgKlxuICAgICAqICMjIyMgRXZlbnRzIGRpc3BhdGNoZWRcbiAgICAgKlxuICAgICAqIFRoZSBbW1Nlc3Npb25dXSBvYmplY3Qgb2YgdGhlIGxvY2FsIHBhcnRpY2lwYW50IHdpbGwgZGlzcGF0Y2ggYSBgc3RyZWFtUHJvcGVydHlDaGFuZ2VkYCBldmVudCB3aXRoIGBjaGFuZ2VkUHJvcGVydHlgIHNldCB0byBgXCJhdWRpb0FjdGl2ZVwiYCBhbmQgYHJlYXNvbmAgc2V0IHRvIGBcInB1Ymxpc2hBdWRpb1wiYFxuICAgICAqIFRoZSBbW1B1Ymxpc2hlcl1dIG9iamVjdCBvZiB0aGUgbG9jYWwgcGFydGljaXBhbnQgd2lsbCBhbHNvIGRpc3BhdGNoIHRoZSBleGFjdCBzYW1lIGV2ZW50XG4gICAgICpcbiAgICAgKiBUaGUgW1tTZXNzaW9uXV0gb2JqZWN0IG9mIGV2ZXJ5IG90aGVyIHBhcnRpY2lwYW50IGNvbm5lY3RlZCB0byB0aGUgc2Vzc2lvbiB3aWxsIGRpc3BhdGNoIGEgYHN0cmVhbVByb3BlcnR5Q2hhbmdlZGAgZXZlbnQgd2l0aCBgY2hhbmdlZFByb3BlcnR5YCBzZXQgdG8gYFwiYXVkaW9BY3RpdmVcImAgYW5kIGByZWFzb25gIHNldCB0byBgXCJwdWJsaXNoQXVkaW9cImBcbiAgICAgKiBUaGUgcmVzcGVjdGl2ZSBbW1N1YnNjcmliZXJdXSBvYmplY3Qgb2YgZXZlcnkgb3RoZXIgcGFydGljaXBhbnQgcmVjZWl2aW5nIHRoaXMgUHVibGlzaGVyJ3Mgc3RyZWFtIHdpbGwgYWxzbyBkaXNwYXRjaCB0aGUgZXhhY3Qgc2FtZSBldmVudFxuICAgICAqXG4gICAgICogU2VlIFtbU3RyZWFtUHJvcGVydHlDaGFuZ2VkRXZlbnRdXSB0byBsZWFybiBtb3JlLlxuICAgICAqXG4gICAgICogQHBhcmFtIHZhbHVlIGB0cnVlYCB0byBwdWJsaXNoIHRoZSBhdWRpbyBzdHJlYW0sIGBmYWxzZWAgdG8gdW5wdWJsaXNoIGl0XG4gICAgICovXG4gICAgcHVibGlzaEF1ZGlvKHZhbHVlOiBib29sZWFuKTogdm9pZCB7XG4gICAgICAgIGlmICh0aGlzLnN0cmVhbS5hdWRpb0FjdGl2ZSAhPT0gdmFsdWUpIHtcbiAgICAgICAgICAgIHRoaXMuc3RyZWFtLmdldE1lZGlhU3RyZWFtKCkuZ2V0QXVkaW9UcmFja3MoKS5mb3JFYWNoKCh0cmFjaykgPT4ge1xuICAgICAgICAgICAgICAgIHRyYWNrLmVuYWJsZWQgPSB2YWx1ZTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgdGhpcy5zZXNzaW9uLm9wZW52aWR1LnNlbmRSZXF1ZXN0KFxuICAgICAgICAgICAgICAgICdzdHJlYW1Qcm9wZXJ0eUNoYW5nZWQnLFxuICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgc3RyZWFtSWQ6IHRoaXMuc3RyZWFtLnN0cmVhbUlkLFxuICAgICAgICAgICAgICAgICAgICBwcm9wZXJ0eTogJ2F1ZGlvQWN0aXZlJyxcbiAgICAgICAgICAgICAgICAgICAgbmV3VmFsdWU6IHZhbHVlLFxuICAgICAgICAgICAgICAgICAgICByZWFzb246ICdwdWJsaXNoQXVkaW8nXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAoZXJyb3IsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihcIkVycm9yIHNlbmRpbmcgJ3N0cmVhbVByb3BlcnR5Q2hhbmdlZCcgZXZlbnRcIiwgZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXNzaW9uLmVtaXRFdmVudCgnc3RyZWFtUHJvcGVydHlDaGFuZ2VkJywgW25ldyBTdHJlYW1Qcm9wZXJ0eUNoYW5nZWRFdmVudCh0aGlzLnNlc3Npb24sIHRoaXMuc3RyZWFtLCAnYXVkaW9BY3RpdmUnLCB2YWx1ZSwgIXZhbHVlLCAncHVibGlzaEF1ZGlvJyldKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZW1pdEV2ZW50KCdzdHJlYW1Qcm9wZXJ0eUNoYW5nZWQnLCBbbmV3IFN0cmVhbVByb3BlcnR5Q2hhbmdlZEV2ZW50KHRoaXMsIHRoaXMuc3RyZWFtLCAnYXVkaW9BY3RpdmUnLCB2YWx1ZSwgIXZhbHVlLCAncHVibGlzaEF1ZGlvJyldKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgdGhpcy5zdHJlYW0uYXVkaW9BY3RpdmUgPSB2YWx1ZTtcbiAgICAgICAgICAgIGNvbnNvbGUuaW5mbyhcIidQdWJsaXNoZXInIGhhcyBcIiArICh2YWx1ZSA/ICdwdWJsaXNoZWQnIDogJ3VucHVibGlzaGVkJykgKyAnIGl0cyBhdWRpbyBzdHJlYW0nKTtcbiAgICAgICAgfVxuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogUHVibGlzaCBvciB1bnB1Ymxpc2ggdGhlIHZpZGVvIHN0cmVhbSAoaWYgYXZhaWxhYmxlKS4gQ2FsbGluZyB0aGlzIG1ldGhvZCB0d2ljZSBpbiBhIHJvdyBwYXNzaW5nIHNhbWUgdmFsdWUgd2lsbCBoYXZlIG5vIGVmZmVjdFxuICAgICAqXG4gICAgICogIyMjIyBFdmVudHMgZGlzcGF0Y2hlZFxuICAgICAqXG4gICAgICogVGhlIFtbU2Vzc2lvbl1dIG9iamVjdCBvZiB0aGUgbG9jYWwgcGFydGljaXBhbnQgd2lsbCBkaXNwYXRjaCBhIGBzdHJlYW1Qcm9wZXJ0eUNoYW5nZWRgIGV2ZW50IHdpdGggYGNoYW5nZWRQcm9wZXJ0eWAgc2V0IHRvIGBcInZpZGVvQWN0aXZlXCJgIGFuZCBgcmVhc29uYCBzZXQgdG8gYFwicHVibGlzaFZpZGVvXCJgXG4gICAgICogVGhlIFtbUHVibGlzaGVyXV0gb2JqZWN0IG9mIHRoZSBsb2NhbCBwYXJ0aWNpcGFudCB3aWxsIGFsc28gZGlzcGF0Y2ggdGhlIGV4YWN0IHNhbWUgZXZlbnRcbiAgICAgKlxuICAgICAqIFRoZSBbW1Nlc3Npb25dXSBvYmplY3Qgb2YgZXZlcnkgb3RoZXIgcGFydGljaXBhbnQgY29ubmVjdGVkIHRvIHRoZSBzZXNzaW9uIHdpbGwgZGlzcGF0Y2ggYSBgc3RyZWFtUHJvcGVydHlDaGFuZ2VkYCBldmVudCB3aXRoIGBjaGFuZ2VkUHJvcGVydHlgIHNldCB0byBgXCJ2aWRlb0FjdGl2ZVwiYCBhbmQgYHJlYXNvbmAgc2V0IHRvIGBcInB1Ymxpc2hWaWRlb1wiYFxuICAgICAqIFRoZSByZXNwZWN0aXZlIFtbU3Vic2NyaWJlcl1dIG9iamVjdCBvZiBldmVyeSBvdGhlciBwYXJ0aWNpcGFudCByZWNlaXZpbmcgdGhpcyBQdWJsaXNoZXIncyBzdHJlYW0gd2lsbCBhbHNvIGRpc3BhdGNoIHRoZSBleGFjdCBzYW1lIGV2ZW50XG4gICAgICpcbiAgICAgKiBTZWUgW1tTdHJlYW1Qcm9wZXJ0eUNoYW5nZWRFdmVudF1dIHRvIGxlYXJuIG1vcmUuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gdmFsdWUgYHRydWVgIHRvIHB1Ymxpc2ggdGhlIHZpZGVvIHN0cmVhbSwgYGZhbHNlYCB0byB1bnB1Ymxpc2ggaXRcbiAgICAgKi9cbiAgICBwdWJsaXNoVmlkZW8odmFsdWU6IGJvb2xlYW4pOiB2b2lkIHtcbiAgICAgICAgaWYgKHRoaXMuc3RyZWFtLnZpZGVvQWN0aXZlICE9PSB2YWx1ZSkge1xuICAgICAgICAgICAgdGhpcy5zdHJlYW0uZ2V0TWVkaWFTdHJlYW0oKS5nZXRWaWRlb1RyYWNrcygpLmZvckVhY2goKHRyYWNrKSA9PiB7XG4gICAgICAgICAgICAgICAgdHJhY2suZW5hYmxlZCA9IHZhbHVlO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB0aGlzLnNlc3Npb24ub3BlbnZpZHUuc2VuZFJlcXVlc3QoXG4gICAgICAgICAgICAgICAgJ3N0cmVhbVByb3BlcnR5Q2hhbmdlZCcsXG4gICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICBzdHJlYW1JZDogdGhpcy5zdHJlYW0uc3RyZWFtSWQsXG4gICAgICAgICAgICAgICAgICAgIHByb3BlcnR5OiAndmlkZW9BY3RpdmUnLFxuICAgICAgICAgICAgICAgICAgICBuZXdWYWx1ZTogdmFsdWUsXG4gICAgICAgICAgICAgICAgICAgIHJlYXNvbjogJ3B1Ymxpc2hWaWRlbydcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIChlcnJvciwgcmVzcG9uc2UpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKFwiRXJyb3Igc2VuZGluZyAnc3RyZWFtUHJvcGVydHlDaGFuZ2VkJyBldmVudFwiLCBlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnNlc3Npb24uZW1pdEV2ZW50KCdzdHJlYW1Qcm9wZXJ0eUNoYW5nZWQnLCBbbmV3IFN0cmVhbVByb3BlcnR5Q2hhbmdlZEV2ZW50KHRoaXMuc2Vzc2lvbiwgdGhpcy5zdHJlYW0sICd2aWRlb0FjdGl2ZScsIHZhbHVlLCAhdmFsdWUsICdwdWJsaXNoVmlkZW8nKV0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5lbWl0RXZlbnQoJ3N0cmVhbVByb3BlcnR5Q2hhbmdlZCcsIFtuZXcgU3RyZWFtUHJvcGVydHlDaGFuZ2VkRXZlbnQodGhpcywgdGhpcy5zdHJlYW0sICd2aWRlb0FjdGl2ZScsIHZhbHVlLCAhdmFsdWUsICdwdWJsaXNoVmlkZW8nKV0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB0aGlzLnN0cmVhbS52aWRlb0FjdGl2ZSA9IHZhbHVlO1xuICAgICAgICAgICAgY29uc29sZS5pbmZvKFwiJ1B1Ymxpc2hlcicgaGFzIFwiICsgKHZhbHVlID8gJ3B1Ymxpc2hlZCcgOiAndW5wdWJsaXNoZWQnKSArICcgaXRzIHZpZGVvIHN0cmVhbScpO1xuICAgICAgICB9XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBDYWxsIHRoaXMgbWV0aG9kIGJlZm9yZSBbW1Nlc3Npb24ucHVibGlzaF1dIGlmIHlvdSBwcmVmZXIgdG8gc3Vic2NyaWJlIHRvIHlvdXIgUHVibGlzaGVyJ3MgcmVtb3RlIHN0cmVhbSBpbnN0ZWFkIG9mIHVzaW5nIHRoZSBsb2NhbCBzdHJlYW0sIGFzIGFueSBvdGhlciB1c2VyIHdvdWxkIGRvLlxuICAgICAqL1xuICAgIHN1YnNjcmliZVRvUmVtb3RlKHZhbHVlPzogYm9vbGVhbik6IHZvaWQge1xuICAgICAgICB2YWx1ZSA9ICh2YWx1ZSAhPT0gdW5kZWZpbmVkKSA/IHZhbHVlIDogdHJ1ZTtcbiAgICAgICAgdGhpcy5pc1N1YnNjcmliZWRUb1JlbW90ZSA9IHZhbHVlO1xuICAgICAgICB0aGlzLnN0cmVhbS5zdWJzY3JpYmVUb015UmVtb3RlKHZhbHVlKTtcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFNlZSBbW0V2ZW50RGlzcGF0Y2hlci5vbl1dXG4gICAgICovXG4gICAgb24odHlwZTogc3RyaW5nLCBoYW5kbGVyOiAoZXZlbnQ6IEV2ZW50KSA9PiB2b2lkKTogRXZlbnREaXNwYXRjaGVyIHtcbiAgICAgICAgc3VwZXIub24odHlwZSwgaGFuZGxlcik7XG4gICAgICAgIGlmICh0eXBlID09PSAnc3RyZWFtQ3JlYXRlZCcpIHtcbiAgICAgICAgICAgIGlmICghIXRoaXMuc3RyZWFtICYmIHRoaXMuc3RyZWFtLmlzTG9jYWxTdHJlYW1QdWJsaXNoZWQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVtaXRFdmVudCgnc3RyZWFtQ3JlYXRlZCcsIFtuZXcgU3RyZWFtRXZlbnQoZmFsc2UsIHRoaXMsICdzdHJlYW1DcmVhdGVkJywgdGhpcy5zdHJlYW0sICcnKV0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbS5lZS5vbignc3RyZWFtLWNyZWF0ZWQtYnktcHVibGlzaGVyJywgKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmVtaXRFdmVudCgnc3RyZWFtQ3JlYXRlZCcsIFtuZXcgU3RyZWFtRXZlbnQoZmFsc2UsIHRoaXMsICdzdHJlYW1DcmVhdGVkJywgdGhpcy5zdHJlYW0sICcnKV0pO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmICh0eXBlID09PSAncmVtb3RlVmlkZW9QbGF5aW5nJykge1xuICAgICAgICAgICAgaWYgKHRoaXMuc3RyZWFtLmRpc3BsYXlNeVJlbW90ZSgpICYmIHRoaXMudmlkZW9zWzBdICYmIHRoaXMudmlkZW9zWzBdLnZpZGVvICYmXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8uY3VycmVudFRpbWUgPiAwICYmXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8ucGF1c2VkID09PSBmYWxzZSAmJlxuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9zWzBdLnZpZGVvLmVuZGVkID09PSBmYWxzZSAmJlxuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9zWzBdLnZpZGVvLnJlYWR5U3RhdGUgPT09IDQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVtaXRFdmVudCgncmVtb3RlVmlkZW9QbGF5aW5nJywgW25ldyBWaWRlb0VsZW1lbnRFdmVudCh0aGlzLnZpZGVvc1swXS52aWRlbywgdGhpcywgJ3JlbW90ZVZpZGVvUGxheWluZycpXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHR5cGUgPT09ICdhY2Nlc3NBbGxvd2VkJykge1xuICAgICAgICAgICAgaWYgKHRoaXMuYWNjZXNzQWxsb3dlZCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZW1pdEV2ZW50KCdhY2Nlc3NBbGxvd2VkJywgW10pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmICh0eXBlID09PSAnYWNjZXNzRGVuaWVkJykge1xuICAgICAgICAgICAgaWYgKHRoaXMuYWNjZXNzRGVuaWVkKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5lbWl0RXZlbnQoJ2FjY2Vzc0RlbmllZCcsIFtdKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFNlZSBbW0V2ZW50RGlzcGF0Y2hlci5vbmNlXV1cbiAgICAgKi9cbiAgICBvbmNlKHR5cGU6IHN0cmluZywgaGFuZGxlcjogKGV2ZW50OiBFdmVudCkgPT4gdm9pZCk6IFB1Ymxpc2hlciB7XG4gICAgICAgIHN1cGVyLm9uY2UodHlwZSwgaGFuZGxlcik7XG4gICAgICAgIGlmICh0eXBlID09PSAnc3RyZWFtQ3JlYXRlZCcpIHtcbiAgICAgICAgICAgIGlmICghIXRoaXMuc3RyZWFtICYmIHRoaXMuc3RyZWFtLmlzTG9jYWxTdHJlYW1QdWJsaXNoZWQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVtaXRFdmVudCgnc3RyZWFtQ3JlYXRlZCcsIFtuZXcgU3RyZWFtRXZlbnQoZmFsc2UsIHRoaXMsICdzdHJlYW1DcmVhdGVkJywgdGhpcy5zdHJlYW0sICcnKV0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbS5lZS5vbmNlKCdzdHJlYW0tY3JlYXRlZC1ieS1wdWJsaXNoZXInLCAoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZW1pdEV2ZW50KCdzdHJlYW1DcmVhdGVkJywgW25ldyBTdHJlYW1FdmVudChmYWxzZSwgdGhpcywgJ3N0cmVhbUNyZWF0ZWQnLCB0aGlzLnN0cmVhbSwgJycpXSk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHR5cGUgPT09ICdyZW1vdGVWaWRlb1BsYXlpbmcnKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5zdHJlYW0uZGlzcGxheU15UmVtb3RlKCkgJiYgdGhpcy52aWRlb3NbMF0gJiYgdGhpcy52aWRlb3NbMF0udmlkZW8gJiZcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvc1swXS52aWRlby5jdXJyZW50VGltZSA+IDAgJiZcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvc1swXS52aWRlby5wYXVzZWQgPT09IGZhbHNlICYmXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8uZW5kZWQgPT09IGZhbHNlICYmXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8ucmVhZHlTdGF0ZSA9PT0gNCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZW1pdEV2ZW50KCdyZW1vdGVWaWRlb1BsYXlpbmcnLCBbbmV3IFZpZGVvRWxlbWVudEV2ZW50KHRoaXMudmlkZW9zWzBdLnZpZGVvLCB0aGlzLCAncmVtb3RlVmlkZW9QbGF5aW5nJyldKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAodHlwZSA9PT0gJ2FjY2Vzc0FsbG93ZWQnKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5hY2Nlc3NBbGxvd2VkKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5lbWl0RXZlbnQoJ2FjY2Vzc0FsbG93ZWQnLCBbXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHR5cGUgPT09ICdhY2Nlc3NEZW5pZWQnKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5hY2Nlc3NEZW5pZWQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVtaXRFdmVudCgnYWNjZXNzRGVuaWVkJywgW10pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuXG4gICAgLyogSGlkZGVuIG1ldGhvZHMgKi9cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBpbml0aWFsaXplKCk6IFByb21pc2U8YW55PiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG5cbiAgICAgICAgICAgIGNvbnN0IGVycm9yQ2FsbGJhY2sgPSAob3BlblZpZHVFcnJvcjogT3BlblZpZHVFcnJvcikgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuYWNjZXNzRGVuaWVkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB0aGlzLmFjY2Vzc0FsbG93ZWQgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICByZWplY3Qob3BlblZpZHVFcnJvcik7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICBjb25zdCBzdWNjZXNzQ2FsbGJhY2sgPSAobWVkaWFTdHJlYW06IE1lZGlhU3RyZWFtKSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5hY2Nlc3NBbGxvd2VkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB0aGlzLmFjY2Vzc0RlbmllZCA9IGZhbHNlO1xuXG4gICAgICAgICAgICAgICAgaWYgKHRoaXMub3BlbnZpZHUuaXNNZWRpYVN0cmVhbVRyYWNrKHRoaXMucHJvcGVydGllcy5hdWRpb1NvdXJjZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgbWVkaWFTdHJlYW0ucmVtb3ZlVHJhY2sobWVkaWFTdHJlYW0uZ2V0QXVkaW9UcmFja3MoKVswXSk7XG4gICAgICAgICAgICAgICAgICAgIG1lZGlhU3RyZWFtLmFkZFRyYWNrKCg8TWVkaWFTdHJlYW1UcmFjaz50aGlzLnByb3BlcnRpZXMuYXVkaW9Tb3VyY2UpKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAodGhpcy5vcGVudmlkdS5pc01lZGlhU3RyZWFtVHJhY2sodGhpcy5wcm9wZXJ0aWVzLnZpZGVvU291cmNlKSkge1xuICAgICAgICAgICAgICAgICAgICBtZWRpYVN0cmVhbS5yZW1vdmVUcmFjayhtZWRpYVN0cmVhbS5nZXRWaWRlb1RyYWNrcygpWzBdKTtcbiAgICAgICAgICAgICAgICAgICAgbWVkaWFTdHJlYW0uYWRkVHJhY2soKDxNZWRpYVN0cmVhbVRyYWNrPnRoaXMucHJvcGVydGllcy52aWRlb1NvdXJjZSkpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIEFwcGx5IFB1Ymxpc2hlclByb3BlcnRpZXMucHVibGlzaEF1ZGlvIGFuZCBQdWJsaXNoZXJQcm9wZXJ0aWVzLnB1Ymxpc2hWaWRlb1xuICAgICAgICAgICAgICAgIGlmICghIW1lZGlhU3RyZWFtLmdldEF1ZGlvVHJhY2tzKClbMF0pIHtcbiAgICAgICAgICAgICAgICAgICAgbWVkaWFTdHJlYW0uZ2V0QXVkaW9UcmFja3MoKVswXS5lbmFibGVkID0gISF0aGlzLnN0cmVhbS5vdXRib3VuZFN0cmVhbU9wdHMucHVibGlzaGVyUHJvcGVydGllcy5wdWJsaXNoQXVkaW87XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmICghIW1lZGlhU3RyZWFtLmdldFZpZGVvVHJhY2tzKClbMF0pIHtcbiAgICAgICAgICAgICAgICAgICAgbWVkaWFTdHJlYW0uZ2V0VmlkZW9UcmFja3MoKVswXS5lbmFibGVkID0gISF0aGlzLnN0cmVhbS5vdXRib3VuZFN0cmVhbU9wdHMucHVibGlzaGVyUHJvcGVydGllcy5wdWJsaXNoVmlkZW87XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb1JlZmVyZW5jZSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3ZpZGVvJyk7XG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb1JlZmVyZW5jZS5zcmNPYmplY3QgPSBtZWRpYVN0cmVhbTtcblxuICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtLnNldE1lZGlhU3RyZWFtKG1lZGlhU3RyZWFtKTtcbiAgICAgICAgICAgICAgICBpZiAoIXRoaXMuc3RyZWFtLmRpc3BsYXlNeVJlbW90ZSgpKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIFdoZW4gd2UgYXJlIHN1YnNjcmliZWQgdG8gb3VyIHJlbW90ZSB3ZSBkb24ndCBzdGlsbCBzZXQgdGhlIE1lZGlhU3RyZWFtIG9iamVjdCBpbiB0aGUgdmlkZW8gZWxlbWVudHMgdG9cbiAgICAgICAgICAgICAgICAgICAgLy8gYXZvaWQgZWFybHkgJ3N0cmVhbVBsYXlpbmcnIGV2ZW50XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtLnVwZGF0ZU1lZGlhU3RyZWFtSW5WaWRlb3MoKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoISF0aGlzLmZpcnN0VmlkZW9FbGVtZW50KSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuY3JlYXRlVmlkZW9FbGVtZW50KHRoaXMuZmlyc3RWaWRlb0VsZW1lbnQudGFyZ2V0RWxlbWVudCwgPFZpZGVvSW5zZXJ0TW9kZT50aGlzLnByb3BlcnRpZXMuaW5zZXJ0TW9kZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGRlbGV0ZSB0aGlzLmZpcnN0VmlkZW9FbGVtZW50O1xuXG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuc3RyZWFtLmlzU2VuZFZpZGVvKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCF0aGlzLnN0cmVhbS5pc1NlbmRTY3JlZW4oKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gV2l0aCBubyBzY3JlZW4gc2hhcmUsIHZpZGVvIGRpbWVuc2lvbiBjYW4gYmUgc2V0IGRpcmVjdGx5IGZyb20gTWVkaWFTdHJlYW0gKGdldFNldHRpbmdzKVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gT3JpZW50YXRpb24gbXVzdCBiZSBjaGVja2VkIGZvciBtb2JpbGUgZGV2aWNlcyAod2lkdGggYW5kIGhlaWdodCBhcmUgcmV2ZXJzZWQpXG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB7IHdpZHRoLCBoZWlnaHQgfSA9IG1lZGlhU3RyZWFtLmdldFZpZGVvVHJhY2tzKClbMF0uZ2V0U2V0dGluZ3MoKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHBsYXRmb3JtLm5hbWUhIS50b0xvd2VyQ2FzZSgpLmluZGV4T2YoJ21vYmlsZScpICE9PSAtMSAmJiAod2luZG93LmlubmVySGVpZ2h0ID4gd2luZG93LmlubmVyV2lkdGgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gTW9iaWxlIHBvcnRyYWl0IG1vZGVcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbS52aWRlb0RpbWVuc2lvbnMgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdpZHRoOiBoZWlnaHQgfHwgMCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaGVpZ2h0OiB3aWR0aCB8fCAwXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdHJlYW0udmlkZW9EaW1lbnNpb25zID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3aWR0aDogd2lkdGggfHwgMCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaGVpZ2h0OiBoZWlnaHQgfHwgMFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbS5pc0xvY2FsU3RyZWFtUmVhZHlUb1B1Ymxpc2ggPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdHJlYW0uZWUuZW1pdEV2ZW50KCdzdHJlYW0tcmVhZHktdG8tcHVibGlzaCcsIFtdKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIFdpdGggc2NyZWVuIHNoYXJlLCB2aWRlbyBkaW1lbnNpb24gbXVzdCBiZSBnb3QgZnJvbSBhIHZpZGVvIGVsZW1lbnQgKG9ubG9hZGVkbWV0YWRhdGEgZXZlbnQpXG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnZpZGVvUmVmZXJlbmNlLm9ubG9hZGVkbWV0YWRhdGEgPSAoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdHJlYW0udmlkZW9EaW1lbnNpb25zID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3aWR0aDogdGhpcy52aWRlb1JlZmVyZW5jZS52aWRlb1dpZHRoLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBoZWlnaHQ6IHRoaXMudmlkZW9SZWZlcmVuY2UudmlkZW9IZWlnaHRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc2NyZWVuU2hhcmVSZXNpemVJbnRlcnZhbCA9IHNldEludGVydmFsKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZmlyZWZveFNldHRpbmdzID0gbWVkaWFTdHJlYW0uZ2V0VmlkZW9UcmFja3MoKVswXS5nZXRTZXR0aW5ncygpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBuZXdXaWR0aCA9IChwbGF0Zm9ybS5uYW1lID09PSAnQ2hyb21lJykgPyB0aGlzLnZpZGVvUmVmZXJlbmNlLnZpZGVvV2lkdGggOiBmaXJlZm94U2V0dGluZ3Mud2lkdGg7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG5ld0hlaWdodCA9IChwbGF0Zm9ybS5uYW1lID09PSAnQ2hyb21lJykgPyB0aGlzLnZpZGVvUmVmZXJlbmNlLnZpZGVvSGVpZ2h0IDogZmlyZWZveFNldHRpbmdzLmhlaWdodDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuc3RyZWFtLmlzTG9jYWxTdHJlYW1QdWJsaXNoZWQgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChuZXdXaWR0aCAhPT0gdGhpcy5zdHJlYW0udmlkZW9EaW1lbnNpb25zLndpZHRoIHx8XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3SGVpZ2h0ICE9PSB0aGlzLnN0cmVhbS52aWRlb0RpbWVuc2lvbnMuaGVpZ2h0KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3Qgb2xkVmFsdWUgPSB7IHdpZHRoOiB0aGlzLnN0cmVhbS52aWRlb0RpbWVuc2lvbnMud2lkdGgsIGhlaWdodDogdGhpcy5zdHJlYW0udmlkZW9EaW1lbnNpb25zLmhlaWdodCB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdHJlYW0udmlkZW9EaW1lbnNpb25zID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdpZHRoOiBuZXdXaWR0aCB8fCAwLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhlaWdodDogbmV3SGVpZ2h0IHx8IDBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnNlc3Npb24ub3BlbnZpZHUuc2VuZFJlcXVlc3QoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ3N0cmVhbVByb3BlcnR5Q2hhbmdlZCcsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJlYW1JZDogdGhpcy5zdHJlYW0uc3RyZWFtSWQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByb3BlcnR5OiAndmlkZW9EaW1lbnNpb25zJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3VmFsdWU6IEpTT04uc3RyaW5naWZ5KHRoaXMuc3RyZWFtLnZpZGVvRGltZW5zaW9ucyksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlYXNvbjogJ3NjcmVlblJlc2l6ZWQnXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoZXJyb3IsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihcIkVycm9yIHNlbmRpbmcgJ3N0cmVhbVByb3BlcnR5Q2hhbmdlZCcgZXZlbnRcIiwgZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXNzaW9uLmVtaXRFdmVudCgnc3RyZWFtUHJvcGVydHlDaGFuZ2VkJywgW25ldyBTdHJlYW1Qcm9wZXJ0eUNoYW5nZWRFdmVudCh0aGlzLnNlc3Npb24sIHRoaXMuc3RyZWFtLCAndmlkZW9EaW1lbnNpb25zJywgdGhpcy5zdHJlYW0udmlkZW9EaW1lbnNpb25zLCBvbGRWYWx1ZSwgJ3NjcmVlblJlc2l6ZWQnKV0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5lbWl0RXZlbnQoJ3N0cmVhbVByb3BlcnR5Q2hhbmdlZCcsIFtuZXcgU3RyZWFtUHJvcGVydHlDaGFuZ2VkRXZlbnQodGhpcywgdGhpcy5zdHJlYW0sICd2aWRlb0RpbWVuc2lvbnMnLCB0aGlzLnN0cmVhbS52aWRlb0RpbWVuc2lvbnMsIG9sZFZhbHVlLCAnc2NyZWVuUmVzaXplZCcpXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0sIDUwMCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdHJlYW0uaXNMb2NhbFN0cmVhbVJlYWR5VG9QdWJsaXNoID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbS5lZS5lbWl0RXZlbnQoJ3N0cmVhbS1yZWFkeS10by1wdWJsaXNoJywgW10pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtLmlzTG9jYWxTdHJlYW1SZWFkeVRvUHVibGlzaCA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtLmVlLmVtaXRFdmVudCgnc3RyZWFtLXJlYWR5LXRvLXB1Ymxpc2gnLCBbXSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIHRoaXMub3BlbnZpZHUuZ2VuZXJhdGVNZWRpYUNvbnN0cmFpbnRzKHRoaXMucHJvcGVydGllcylcbiAgICAgICAgICAgICAgICAudGhlbihjb25zdHJhaW50cyA9PiB7XG5cbiAgICAgICAgICAgICAgICAgICAgY29uc3Qgb3V0Ym91bmRTdHJlYW1PcHRpb25zID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgbWVkaWFDb25zdHJhaW50czogY29uc3RyYWludHMsXG4gICAgICAgICAgICAgICAgICAgICAgICBwdWJsaXNoZXJQcm9wZXJ0aWVzOiB0aGlzLnByb3BlcnRpZXNcbiAgICAgICAgICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbS5zZXRPdXRib3VuZFN0cmVhbU9wdGlvbnMob3V0Ym91bmRTdHJlYW1PcHRpb25zKTtcblxuICAgICAgICAgICAgICAgICAgICBjb25zdCBjb25zdHJhaW50c0F1eDogTWVkaWFTdHJlYW1Db25zdHJhaW50cyA9IHt9O1xuICAgICAgICAgICAgICAgICAgICBjb25zdCB0aW1lRm9yRGlhbG9nRXZlbnQgPSAxMjUwO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLnN0cmVhbS5pc1NlbmRWaWRlbygpIHx8IHRoaXMuc3RyZWFtLmlzU2VuZEF1ZGlvKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGRlZmluZWRBdWRpb0NvbnN0cmFpbnQgPSAoKGNvbnN0cmFpbnRzLmF1ZGlvID09PSB1bmRlZmluZWQpID8gdHJ1ZSA6IGNvbnN0cmFpbnRzLmF1ZGlvKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0cmFpbnRzQXV4LmF1ZGlvID0gdGhpcy5zdHJlYW0uaXNTZW5kU2NyZWVuKCkgPyBmYWxzZSA6IGRlZmluZWRBdWRpb0NvbnN0cmFpbnQ7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdHJhaW50c0F1eC52aWRlbyA9IGNvbnN0cmFpbnRzLnZpZGVvO1xuICAgICAgICAgICAgICAgICAgICAgICAgbGV0IHN0YXJ0VGltZSA9IERhdGUubm93KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnNldFBlcm1pc3Npb25EaWFsb2dUaW1lcih0aW1lRm9yRGlhbG9nRXZlbnQpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBuYXZpZ2F0b3IubWVkaWFEZXZpY2VzLmdldFVzZXJNZWRpYShjb25zdHJhaW50c0F1eClcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAudGhlbihtZWRpYVN0cmVhbSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY2xlYXJQZXJtaXNzaW9uRGlhbG9nVGltZXIoc3RhcnRUaW1lLCB0aW1lRm9yRGlhbG9nRXZlbnQpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLnN0cmVhbS5pc1NlbmRTY3JlZW4oKSAmJiB0aGlzLnN0cmVhbS5pc1NlbmRBdWRpbygpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBXaGVuIGdldHRpbmcgZGVza3RvcCBhcyB1c2VyIG1lZGlhIGF1ZGlvIGNvbnN0cmFpbnQgbXVzdCBiZSBmYWxzZS4gTm93IHdlIGNhbiBhc2sgZm9yIGl0IGlmIHJlcXVpcmVkXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdHJhaW50c0F1eC5hdWRpbyA9IGRlZmluZWRBdWRpb0NvbnN0cmFpbnQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdHJhaW50c0F1eC52aWRlbyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhcnRUaW1lID0gRGF0ZS5ub3coKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc2V0UGVybWlzc2lvbkRpYWxvZ1RpbWVyKHRpbWVGb3JEaWFsb2dFdmVudCk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hdmlnYXRvci5tZWRpYURldmljZXMuZ2V0VXNlck1lZGlhKGNvbnN0cmFpbnRzQXV4KVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC50aGVuKGF1ZGlvT25seVN0cmVhbSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY2xlYXJQZXJtaXNzaW9uRGlhbG9nVGltZXIoc3RhcnRUaW1lLCB0aW1lRm9yRGlhbG9nRXZlbnQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZWRpYVN0cmVhbS5hZGRUcmFjayhhdWRpb09ubHlTdHJlYW0uZ2V0QXVkaW9UcmFja3MoKVswXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN1Y2Nlc3NDYWxsYmFjayhtZWRpYVN0cmVhbSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNsZWFyUGVybWlzc2lvbkRpYWxvZ1RpbWVyKHN0YXJ0VGltZSwgdGltZUZvckRpYWxvZ0V2ZW50KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGVycm9yTmFtZSwgZXJyb3JNZXNzYWdlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzd2l0Y2ggKGVycm9yLm5hbWUudG9Mb3dlckNhc2UoKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAnbm90Zm91bmRlcnJvcic6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JOYW1lID0gT3BlblZpZHVFcnJvck5hbWUuSU5QVVRfQVVESU9fREVWSUNFX05PVF9GT1VORDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck1lc3NhZ2UgPSBlcnJvci50b1N0cmluZygpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yQ2FsbGJhY2sobmV3IE9wZW5WaWR1RXJyb3IoZXJyb3JOYW1lLCBlcnJvck1lc3NhZ2UpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJ25vdGFsbG93ZWRlcnJvcic6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JOYW1lID0gT3BlblZpZHVFcnJvck5hbWUuREVWSUNFX0FDQ0VTU19ERU5JRUQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JNZXNzYWdlID0gZXJyb3IudG9TdHJpbmcoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvckNhbGxiYWNrKG5ldyBPcGVuVmlkdUVycm9yKGVycm9yTmFtZSwgZXJyb3JNZXNzYWdlKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlICdvdmVyY29uc3RyYWluZWRlcnJvcic6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yLmNvbnN0cmFpbnQudG9Mb3dlckNhc2UoKSA9PT0gJ2RldmljZWlkJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck5hbWUgPSBPcGVuVmlkdUVycm9yTmFtZS5JTlBVVF9BVURJT19ERVZJQ0VfTk9UX0ZPVU5EO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck1lc3NhZ2UgPSBcIkF1ZGlvIGlucHV0IGRldmljZSB3aXRoIGRldmljZUlkICdcIiArICg8Q29uc3RyYWluRE9NU3RyaW5nUGFyYW1ldGVycz4oPE1lZGlhVHJhY2tDb25zdHJhaW50cz5jb25zdHJhaW50cy52aWRlbykuZGV2aWNlSWQhISkuZXhhY3QgKyBcIicgbm90IGZvdW5kXCI7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JOYW1lID0gT3BlblZpZHVFcnJvck5hbWUuUFVCTElTSEVSX1BST1BFUlRJRVNfRVJST1I7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yTWVzc2FnZSA9IFwiQXVkaW8gaW5wdXQgZGV2aWNlIGRvZXNuJ3Qgc3VwcG9ydCB0aGUgdmFsdWUgcGFzc2VkIGZvciBjb25zdHJhaW50ICdcIiArIGVycm9yLmNvbnN0cmFpbnQgKyBcIidcIjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JDYWxsYmFjayhuZXcgT3BlblZpZHVFcnJvcihlcnJvck5hbWUsIGVycm9yTWVzc2FnZSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdWNjZXNzQ2FsbGJhY2sobWVkaWFTdHJlYW0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNsZWFyUGVybWlzc2lvbkRpYWxvZ1RpbWVyKHN0YXJ0VGltZSwgdGltZUZvckRpYWxvZ0V2ZW50KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGVycm9yTmFtZSwgZXJyb3JNZXNzYWdlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzd2l0Y2ggKGVycm9yLm5hbWUudG9Mb3dlckNhc2UoKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAnbm90Zm91bmRlcnJvcic6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmF2aWdhdG9yLm1lZGlhRGV2aWNlcy5nZXRVc2VyTWVkaWEoe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhdWRpbzogZmFsc2UsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZpZGVvOiBjb25zdHJhaW50cy52aWRlb1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC50aGVuKG1lZGlhU3RyZWFtID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1lZGlhU3RyZWFtLmdldFZpZGVvVHJhY2tzKCkuZm9yRWFjaCgodHJhY2spID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cmFjay5zdG9wKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yTmFtZSA9IE9wZW5WaWR1RXJyb3JOYW1lLklOUFVUX0FVRElPX0RFVklDRV9OT1RfRk9VTkQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck1lc3NhZ2UgPSBlcnJvci50b1N0cmluZygpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JDYWxsYmFjayhuZXcgT3BlblZpZHVFcnJvcihlcnJvck5hbWUsIGVycm9yTWVzc2FnZSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KS5jYXRjaChlID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yTmFtZSA9IE9wZW5WaWR1RXJyb3JOYW1lLklOUFVUX1ZJREVPX0RFVklDRV9OT1RfRk9VTkQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck1lc3NhZ2UgPSBlcnJvci50b1N0cmluZygpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JDYWxsYmFjayhuZXcgT3BlblZpZHVFcnJvcihlcnJvck5hbWUsIGVycm9yTWVzc2FnZSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJ25vdGFsbG93ZWRlcnJvcic6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JOYW1lID0gdGhpcy5zdHJlYW0uaXNTZW5kU2NyZWVuKCkgPyBPcGVuVmlkdUVycm9yTmFtZS5TQ1JFRU5fQ0FQVFVSRV9ERU5JRUQgOiBPcGVuVmlkdUVycm9yTmFtZS5ERVZJQ0VfQUNDRVNTX0RFTklFRDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck1lc3NhZ2UgPSBlcnJvci50b1N0cmluZygpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yQ2FsbGJhY2sobmV3IE9wZW5WaWR1RXJyb3IoZXJyb3JOYW1lLCBlcnJvck1lc3NhZ2UpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJ292ZXJjb25zdHJhaW5lZGVycm9yJzpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYXZpZ2F0b3IubWVkaWFEZXZpY2VzLmdldFVzZXJNZWRpYSh7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGF1ZGlvOiBmYWxzZSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmlkZW86IGNvbnN0cmFpbnRzLnZpZGVvXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLnRoZW4obWVkaWFTdHJlYW0gPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWVkaWFTdHJlYW0uZ2V0VmlkZW9UcmFja3MoKS5mb3JFYWNoKCh0cmFjaykgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRyYWNrLnN0b3AoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yLmNvbnN0cmFpbnQudG9Mb3dlckNhc2UoKSA9PT0gJ2RldmljZWlkJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yTmFtZSA9IE9wZW5WaWR1RXJyb3JOYW1lLklOUFVUX0FVRElPX0RFVklDRV9OT1RfRk9VTkQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JNZXNzYWdlID0gXCJBdWRpbyBpbnB1dCBkZXZpY2Ugd2l0aCBkZXZpY2VJZCAnXCIgKyAoPENvbnN0cmFpbkRPTVN0cmluZ1BhcmFtZXRlcnM+KDxNZWRpYVRyYWNrQ29uc3RyYWludHM+Y29uc3RyYWludHMuYXVkaW8pLmRldmljZUlkISEpLmV4YWN0ICsgXCInIG5vdCBmb3VuZFwiO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck5hbWUgPSBPcGVuVmlkdUVycm9yTmFtZS5QVUJMSVNIRVJfUFJPUEVSVElFU19FUlJPUjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck1lc3NhZ2UgPSBcIkF1ZGlvIGlucHV0IGRldmljZSBkb2Vzbid0IHN1cHBvcnQgdGhlIHZhbHVlIHBhc3NlZCBmb3IgY29uc3RyYWludCAnXCIgKyBlcnJvci5jb25zdHJhaW50ICsgXCInXCI7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvckNhbGxiYWNrKG5ldyBPcGVuVmlkdUVycm9yKGVycm9yTmFtZSwgZXJyb3JNZXNzYWdlKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pLmNhdGNoKGUgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yLmNvbnN0cmFpbnQudG9Mb3dlckNhc2UoKSA9PT0gJ2RldmljZWlkJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yTmFtZSA9IE9wZW5WaWR1RXJyb3JOYW1lLklOUFVUX1ZJREVPX0RFVklDRV9OT1RfRk9VTkQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JNZXNzYWdlID0gXCJWaWRlbyBpbnB1dCBkZXZpY2Ugd2l0aCBkZXZpY2VJZCAnXCIgKyAoPENvbnN0cmFpbkRPTVN0cmluZ1BhcmFtZXRlcnM+KDxNZWRpYVRyYWNrQ29uc3RyYWludHM+Y29uc3RyYWludHMudmlkZW8pLmRldmljZUlkISEpLmV4YWN0ICsgXCInIG5vdCBmb3VuZFwiO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck5hbWUgPSBPcGVuVmlkdUVycm9yTmFtZS5QVUJMSVNIRVJfUFJPUEVSVElFU19FUlJPUjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck1lc3NhZ2UgPSBcIlZpZGVvIGlucHV0IGRldmljZSBkb2Vzbid0IHN1cHBvcnQgdGhlIHZhbHVlIHBhc3NlZCBmb3IgY29uc3RyYWludCAnXCIgKyBlcnJvci5jb25zdHJhaW50ICsgXCInXCI7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvckNhbGxiYWNrKG5ldyBPcGVuVmlkdUVycm9yKGVycm9yTmFtZSwgZXJyb3JNZXNzYWdlKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZWplY3QobmV3IE9wZW5WaWR1RXJyb3IoT3BlblZpZHVFcnJvck5hbWUuTk9fSU5QVVRfU09VUkNFX1NFVCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBcIlByb3BlcnRpZXMgJ2F1ZGlvU291cmNlJyBhbmQgJ3ZpZGVvU291cmNlJyBjYW5ub3QgYmUgc2V0IHRvIGZhbHNlIG9yIG51bGwgYXQgdGhlIHNhbWUgdGltZSB3aGVuIGNhbGxpbmcgJ09wZW5WaWR1LmluaXRQdWJsaXNoZXInXCIpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgLmNhdGNoKChlcnJvcjogT3BlblZpZHVFcnJvcikgPT4ge1xuICAgICAgICAgICAgICAgICAgICBlcnJvckNhbGxiYWNrKGVycm9yKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHVwZGF0ZVNlc3Npb24oc2Vzc2lvbjogU2Vzc2lvbik6IHZvaWQge1xuICAgICAgICB0aGlzLnNlc3Npb24gPSBzZXNzaW9uO1xuICAgICAgICB0aGlzLnN0cmVhbS5zZXNzaW9uID0gc2Vzc2lvbjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgcmVlc3RhYmxpc2hTdHJlYW1QbGF5aW5nRXZlbnQoKSB7XG4gICAgICAgIGlmICh0aGlzLmVlLmdldExpc3RlbmVycygnc3RyZWFtUGxheWluZycpLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgIHRoaXMuYWRkUGxheUV2ZW50VG9GaXJzdFZpZGVvKCk7XG4gICAgICAgIH1cbiAgICB9XG5cblxuICAgIC8qIFByaXZhdGUgbWV0aG9kcyAqL1xuXG4gICAgcHJpdmF0ZSBzZXRQZXJtaXNzaW9uRGlhbG9nVGltZXIod2FpdFRpbWU6IG51bWJlcik6IHZvaWQge1xuICAgICAgICB0aGlzLnBlcm1pc3Npb25EaWFsb2dUaW1lb3V0ID0gc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgICAgICB0aGlzLmVtaXRFdmVudCgnYWNjZXNzRGlhbG9nT3BlbmVkJywgW10pO1xuICAgICAgICB9LCB3YWl0VGltZSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBjbGVhclBlcm1pc3Npb25EaWFsb2dUaW1lcihzdGFydFRpbWU6IG51bWJlciwgd2FpdFRpbWU6IG51bWJlcik6IHZvaWQge1xuICAgICAgICBjbGVhclRpbWVvdXQodGhpcy5wZXJtaXNzaW9uRGlhbG9nVGltZW91dCk7XG4gICAgICAgIGlmICgoRGF0ZS5ub3coKSAtIHN0YXJ0VGltZSkgPiB3YWl0VGltZSkge1xuICAgICAgICAgICAgLy8gUGVybWlzc2lvbiBkaWFsb2cgd2FzIHNob3duIGFuZCBub3cgaXMgY2xvc2VkXG4gICAgICAgICAgICB0aGlzLmVtaXRFdmVudCgnYWNjZXNzRGlhbG9nQ2xvc2VkJywgW10pO1xuICAgICAgICB9XG4gICAgfVxuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBDb25uZWN0aW9uIH0gZnJvbSAnLi9Db25uZWN0aW9uJztcbmltcG9ydCB7IE9wZW5WaWR1IH0gZnJvbSAnLi9PcGVuVmlkdSc7XG5pbXBvcnQgeyBQdWJsaXNoZXIgfSBmcm9tICcuL1B1Ymxpc2hlcic7XG5pbXBvcnQgeyBTdHJlYW0gfSBmcm9tICcuL1N0cmVhbSc7XG5pbXBvcnQgeyBTdHJlYW1NYW5hZ2VyIH0gZnJvbSAnLi9TdHJlYW1NYW5hZ2VyJztcbmltcG9ydCB7IFN1YnNjcmliZXIgfSBmcm9tICcuL1N1YnNjcmliZXInO1xuaW1wb3J0IHsgQ2FwYWJpbGl0aWVzIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9JbnRlcmZhY2VzL1B1YmxpYy9DYXBhYmlsaXRpZXMnO1xuaW1wb3J0IHsgRXZlbnREaXNwYXRjaGVyIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9JbnRlcmZhY2VzL1B1YmxpYy9FdmVudERpc3BhdGNoZXInO1xuaW1wb3J0IHsgU2lnbmFsT3B0aW9ucyB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvSW50ZXJmYWNlcy9QdWJsaWMvU2lnbmFsT3B0aW9ucyc7XG5pbXBvcnQgeyBTdWJzY3JpYmVyUHJvcGVydGllcyB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvSW50ZXJmYWNlcy9QdWJsaWMvU3Vic2NyaWJlclByb3BlcnRpZXMnO1xuaW1wb3J0IHsgQ29ubmVjdGlvbk9wdGlvbnMgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHJpdmF0ZS9Db25uZWN0aW9uT3B0aW9ucyc7XG5pbXBvcnQgeyBPYmpNYXAgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHJpdmF0ZS9PYmpNYXAnO1xuaW1wb3J0IHsgU2Vzc2lvbk9wdGlvbnMgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHJpdmF0ZS9TZXNzaW9uT3B0aW9ucyc7XG5pbXBvcnQgeyBDb25uZWN0aW9uRXZlbnQgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0V2ZW50cy9Db25uZWN0aW9uRXZlbnQnO1xuaW1wb3J0IHsgUHVibGlzaGVyU3BlYWtpbmdFdmVudCB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1B1Ymxpc2hlclNwZWFraW5nRXZlbnQnO1xuaW1wb3J0IHsgUmVjb3JkaW5nRXZlbnQgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0V2ZW50cy9SZWNvcmRpbmdFdmVudCc7XG5pbXBvcnQgeyBTZXNzaW9uRGlzY29ubmVjdGVkRXZlbnQgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0V2ZW50cy9TZXNzaW9uRGlzY29ubmVjdGVkRXZlbnQnO1xuaW1wb3J0IHsgU2lnbmFsRXZlbnQgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0V2ZW50cy9TaWduYWxFdmVudCc7XG5pbXBvcnQgeyBTdHJlYW1FdmVudCB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1N0cmVhbUV2ZW50JztcbmltcG9ydCB7IFN0cmVhbVByb3BlcnR5Q2hhbmdlZEV2ZW50IH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvU3RyZWFtUHJvcGVydHlDaGFuZ2VkRXZlbnQnO1xuaW1wb3J0IHsgT3BlblZpZHVFcnJvciwgT3BlblZpZHVFcnJvck5hbWUgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0VudW1zL09wZW5WaWR1RXJyb3InO1xuaW1wb3J0IHsgVmlkZW9JbnNlcnRNb2RlIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FbnVtcy9WaWRlb0luc2VydE1vZGUnO1xuXG5pbXBvcnQgcGxhdGZvcm0gPSByZXF1aXJlKCdwbGF0Zm9ybScpO1xuaW1wb3J0IEV2ZW50RW1pdHRlciA9IHJlcXVpcmUoJ3dvbGZ5ODctZXZlbnRlbWl0dGVyJyk7XG5cblxuLyoqXG4gKiBSZXByZXNlbnRzIGEgdmlkZW8gY2FsbC4gSXQgY2FuIGFsc28gYmUgc2VlbiBhcyBhIHZpZGVvY29uZmVyZW5jZSByb29tIHdoZXJlIG11bHRpcGxlIHVzZXJzIGNhbiBjb25uZWN0LlxuICogUGFydGljaXBhbnRzIHdobyBwdWJsaXNoIHRoZWlyIHZpZGVvcyB0byBhIHNlc3Npb24gY2FuIGJlIHNlZW4gYnkgdGhlIHJlc3Qgb2YgdXNlcnMgY29ubmVjdGVkIHRvIHRoYXQgc3BlY2lmaWMgc2Vzc2lvbi5cbiAqIEluaXRpYWxpemVkIHdpdGggW1tPcGVuVmlkdS5pbml0U2Vzc2lvbl1dIG1ldGhvZFxuICovXG5leHBvcnQgY2xhc3MgU2Vzc2lvbiBpbXBsZW1lbnRzIEV2ZW50RGlzcGF0Y2hlciB7XG5cbiAgICAvKipcbiAgICAgKiBMb2NhbCBjb25uZWN0aW9uIHRvIHRoZSBTZXNzaW9uLiBUaGlzIG9iamVjdCBpcyBkZWZpbmVkIG9ubHkgYWZ0ZXIgW1tTZXNzaW9uLmNvbm5lY3RdXSBoYXMgYmVlbiBzdWNjZXNzZnVsbHkgZXhlY3V0ZWQsIGFuZCBjYW4gYmUgcmV0cmlldmVkIHN1YnNjcmliaW5nIHRvIGBjb25uZWN0aW9uQ3JlYXRlZGAgZXZlbnRcbiAgICAgKi9cbiAgICBjb25uZWN0aW9uOiBDb25uZWN0aW9uO1xuXG4gICAgLyoqXG4gICAgICogVW5pcXVlIGlkZW50aWZpZXIgb2YgdGhlIFNlc3Npb25cbiAgICAgKi9cbiAgICBzZXNzaW9uSWQ6IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIENvbGxlY3Rpb24gb2YgYWxsIFN0cmVhbU1hbmFnZXJzIG9mIHRoaXMgU2Vzc2lvbiAoW1tQdWJsaXNoZXJdXSBhbmQgW1tTdWJzY3JpYmVyXV0pXG4gICAgICovXG4gICAgc3RyZWFtTWFuYWdlcnM6IFN0cmVhbU1hbmFnZXJbXSA9IFtdO1xuXG4gICAgLyoqXG4gICAgICogT2JqZWN0IGRlZmluaW5nIHRoZSBtZXRob2RzIHRoYXQgdGhlIGNsaWVudCBpcyBhYmxlIHRvIGNhbGwuIFRoZXNlIGFyZSBkZWZpbmVkIGJ5IHRoZSByb2xlIG9mIHRoZSB0b2tlbiB1c2VkIHRvIGNvbm5lY3QgdG8gdGhlIFNlc3Npb24uXG4gICAgICogVGhpcyBvYmplY3QgaXMgb25seSBkZWZpbmVkIGFmdGVyIFtbU2Vzc2lvbi5jb25uZWN0XV0gaGFzIGJlZW4gc3VjY2Vzc2Z1bGx5IHJlc29sdmVkXG4gICAgICovXG4gICAgY2FwYWJpbGl0aWVzOiBDYXBhYmlsaXRpZXM7XG5cbiAgICAvLyBUaGlzIG1hcCBpcyBvbmx5IHVzZWQgdG8gYXZvaWQgcmFjZSBjb25kaXRpb24gYmV0d2VlbiAnam9pblJvb20nIHJlc3BvbnNlIGFuZCAnb25QYXJ0aWNpcGFudFB1Ymxpc2hlZCcgbm90aWZpY2F0aW9uXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHJlbW90ZVN0cmVhbXNDcmVhdGVkOiBPYmpNYXA8Ym9vbGVhbj4gPSB7fTtcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICByZW1vdGVDb25uZWN0aW9uczogT2JqTWFwPENvbm5lY3Rpb24+ID0ge307XG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIG9wZW52aWR1OiBPcGVuVmlkdTtcbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgb3B0aW9uczogU2Vzc2lvbk9wdGlvbnM7XG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHNwZWFraW5nRXZlbnRzRW5hYmxlZCA9IGZhbHNlO1xuXG4gICAgcHJpdmF0ZSBlZSA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3RvcihvcGVudmlkdTogT3BlblZpZHUpIHtcbiAgICAgICAgdGhpcy5vcGVudmlkdSA9IG9wZW52aWR1O1xuICAgIH1cblxuICAgIGNvbm5lY3QodG9rZW46IHN0cmluZyk6IFByb21pc2U8YW55PjtcbiAgICBjb25uZWN0KHRva2VuOiBzdHJpbmcsIG1ldGFkYXRhOiBhbnkpOiBQcm9taXNlPGFueT47XG5cbiAgICAvKipcbiAgICAgKiBDb25uZWN0cyB0byB0aGUgc2Vzc2lvbiB1c2luZyBgdG9rZW5gLiBQYXJhbWV0ZXIgYG1ldGFkYXRhYCBhbGxvd3MgeW91IHRvIHBhc3MgZXh0cmEgZGF0YSB0byBzaGFyZSB3aXRoIG90aGVyIHVzZXJzIHdoZW5cbiAgICAgKiB0aGV5IHJlY2VpdmUgYHN0cmVhbUNyZWF0ZWRgIGV2ZW50LiBUaGUgc3RydWN0dXJlIG9mIGBtZXRhZGF0YWAgc3RyaW5nIGlzIHVwIHRvIHlvdSAobWF5YmUgc29tZSBzdGFuZGFyaXplZCBmb3JtYXRcbiAgICAgKiBhcyBKU09OIG9yIFhNTCBpcyBhIGdvb2QgaWRlYSksIHRoZSBvbmx5IHJlc3RyaWN0aW9uIGlzIGEgbWF4aW11bSBsZW5ndGggb2YgMTAwMDAgY2hhcnMuXG4gICAgICpcbiAgICAgKiBUaGlzIG1ldGFkYXRhIGlzIG5vdCBjb25zaWRlcmVkIHNlY3VyZSwgYXMgaXQgaXMgZ2VuZXJhdGVkIGluIHRoZSBjbGllbnQgc2lkZS4gVG8gcGFzcyBzZWN1cml6ZWQgZGF0YSwgYWRkIGl0IGFzIGEgcGFyYW1ldGVyIGluIHRoZVxuICAgICAqIHRva2VuIGdlbmVyYXRpb24gb3BlcmF0aW9uICh0aHJvdWdoIHRoZSBBUEkgUkVTVCwgb3BlbnZpZHUtamF2YS1jbGllbnQgb3Igb3BlbnZpZHUtbm9kZS1jbGllbnQpLlxuICAgICAqXG4gICAgICogT25seSBhZnRlciB0aGUgcmV0dXJuZWQgUHJvbWlzZSBpcyBzdWNjZXNzZnVsbHkgcmVzb2x2ZWQgW1tTZXNzaW9uLmNvbm5lY3Rpb25dXSBvYmplY3Qgd2lsbCBiZSBhdmFpbGFibGUgYW5kIHByb3Blcmx5IGRlZmluZWQuXG4gICAgICpcbiAgICAgKiAjIyMjIEV2ZW50cyBkaXNwYXRjaGVkXG4gICAgICpcbiAgICAgKiBUaGUgW1tTZXNzaW9uXV0gb2JqZWN0IG9mIHRoZSBsb2NhbCBwYXJ0aWNpcGFudCB3aWxsIGZpcnN0IGRpc3BhdGNoIG9uZSBvciBtb3JlIGBjb25uZWN0aW9uQ3JlYXRlZGAgZXZlbnRzIHVwb24gc3VjY2Vzc2Z1bCB0ZXJtaW5hdGlvbiBvZiB0aGlzIG1ldGhvZDpcbiAgICAgKiAtIEZpcnN0IG9uZSBmb3IgeW91ciBvd24gbG9jYWwgQ29ubmVjdGlvbiBvYmplY3QsIHNvIHlvdSBjYW4gcmV0cmlldmUgW1tTZXNzaW9uLmNvbm5lY3Rpb25dXSBwcm9wZXJ0eS5cbiAgICAgKiAtIFRoZW4gb25lIGZvciBlYWNoIHJlbW90ZSBDb25uZWN0aW9uIHByZXZpb3VzbHkgY29ubmVjdGVkIHRvIHRoZSBTZXNzaW9uLCBpZiBhbnkuIEFueSBvdGhlciByZW1vdGUgdXNlciBjb25uZWN0aW5nIHRvIHRoZSBTZXNzaW9uIGFmdGVyIHlvdSBoYXZlXG4gICAgICogc3VjY2Vzc2Z1bGx5IGNvbm5lY3RlZCB3aWxsIGFsc28gZGlzcGF0Y2ggYSBgY29ubmVjdGlvbkNyZWF0ZWRgIGV2ZW50IHdoZW4gdGhleSBkbyBzby5cbiAgICAgKlxuICAgICAqIFRoZSBbW1Nlc3Npb25dXSBvYmplY3Qgb2YgdGhlIGxvY2FsIHBhcnRpY2lwYW50IHdpbGwgYWxzbyBkaXNwYXRjaCBhIGBzdHJlYW1DcmVhdGVkYCBldmVudCBmb3IgZWFjaCByZW1vdGUgYWN0aXZlIFtbUHVibGlzaGVyXV0gdGhhdCB3YXMgYWxyZWFkeSBzdHJlYW1pbmdcbiAgICAgKiB3aGVuIGNvbm5lY3RpbmcsIGp1c3QgYWZ0ZXIgZGlzcGF0Y2hpbmcgYWxsIHJlbW90ZSBgY29ubmVjdGlvbkNyZWF0ZWRgIGV2ZW50cy5cbiAgICAgKlxuICAgICAqIFRoZSBbW1Nlc3Npb25dXSBvYmplY3Qgb2YgZXZlcnkgb3RoZXIgcGFydGljaXBhbnQgY29ubmVjdGVkIHRvIHRoZSBzZXNzaW9uIHdpbGwgZGlzcGF0Y2ggYSBgY29ubmVjdGlvbkNyZWF0ZWRgIGV2ZW50LlxuICAgICAqXG4gICAgICogU2VlIFtbQ29ubmVjdGlvbkV2ZW50XV0gYW5kIFtbU3RyZWFtRXZlbnRdXSB0byBsZWFybiBtb3JlLlxuICAgICAqXG4gICAgICogQHJldHVybnMgQSBQcm9taXNlIHRvIHdoaWNoIHlvdSBtdXN0IHN1YnNjcmliZSB0aGF0IGlzIHJlc29sdmVkIGlmIHRoZSB0aGUgY29ubmVjdGlvbiB0byB0aGUgU2Vzc2lvbiB3YXMgc3VjY2Vzc2Z1bCBhbmQgcmVqZWN0ZWQgd2l0aCBhbiBFcnJvciBvYmplY3QgaWYgbm90XG4gICAgICpcbiAgICAgKi9cbiAgICBjb25uZWN0KHRva2VuOiBzdHJpbmcsIG1ldGFkYXRhPzogYW55KTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcblxuICAgICAgICAgICAgdGhpcy5wcm9jZXNzVG9rZW4odG9rZW4pO1xuXG4gICAgICAgICAgICBpZiAodGhpcy5vcGVudmlkdS5jaGVja1N5c3RlbVJlcXVpcmVtZW50cygpKSB7XG4gICAgICAgICAgICAgICAgLy8gRWFybHkgY29uZmlndXJhdGlvbiB0byBkZWFjdGl2YXRlIGF1dG9tYXRpYyBzdWJzY3JpcHRpb24gdG8gc3RyZWFtc1xuICAgICAgICAgICAgICAgIHRoaXMub3B0aW9ucyA9IHtcbiAgICAgICAgICAgICAgICAgICAgc2Vzc2lvbklkOiB0aGlzLnNlc3Npb25JZCxcbiAgICAgICAgICAgICAgICAgICAgcGFydGljaXBhbnRJZDogdG9rZW4sXG4gICAgICAgICAgICAgICAgICAgIG1ldGFkYXRhOiAhIW1ldGFkYXRhID8gdGhpcy5zdHJpbmdDbGllbnRNZXRhZGF0YShtZXRhZGF0YSkgOiAnJ1xuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgdGhpcy5jb25uZWN0QXV4KHRva2VuKS50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgICAgICAgIH0pLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmVqZWN0KG5ldyBPcGVuVmlkdUVycm9yKE9wZW5WaWR1RXJyb3JOYW1lLkJST1dTRVJfTk9UX1NVUFBPUlRFRCwgJ0Jyb3dzZXIgJyArIHBsYXRmb3JtLm5hbWUgKyAnICcgKyBwbGF0Zm9ybS52ZXJzaW9uICsgJyBpcyBub3Qgc3VwcG9ydGVkIGluIE9wZW5WaWR1JykpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBMZWF2ZXMgdGhlIHNlc3Npb24sIGRlc3Ryb3lpbmcgYWxsIHN0cmVhbXMgYW5kIGRlbGV0aW5nIHRoZSB1c2VyIGFzIGEgcGFydGljaXBhbnQuXG4gICAgICpcbiAgICAgKiAjIyMjIEV2ZW50cyBkaXNwYXRjaGVkXG4gICAgICpcbiAgICAgKiBUaGUgW1tTZXNzaW9uXV0gb2JqZWN0IG9mIHRoZSBsb2NhbCBwYXJ0aWNpcGFudCB3aWxsIGRpc3BhdGNoIGEgYHNlc3Npb25EaXNjb25uZWN0ZWRgIGV2ZW50LlxuICAgICAqIFRoaXMgZXZlbnQgd2lsbCBhdXRvbWF0aWNhbGx5IHVuc3Vic2NyaWJlIHRoZSBsZWF2aW5nIHBhcnRpY2lwYW50IGZyb20gZXZlcnkgU3Vic2NyaWJlciBvYmplY3Qgb2YgdGhlIHNlc3Npb24gKHRoaXMgaW5jbHVkZXMgY2xvc2luZyB0aGUgV2ViUlRDUGVlciBjb25uZWN0aW9uIGFuZCBkaXNwb3NpbmcgYWxsIE1lZGlhU3RyZWFtVHJhY2tzKVxuICAgICAqIGFuZCBhbHNvIGRlbGV0ZXMgYW55IEhUTUwgdmlkZW8gZWxlbWVudCBhc3NvY2lhdGVkIHRvIGVhY2ggU3Vic2NyaWJlciAob25seSB0aG9zZSBbY3JlYXRlZCBieSBPcGVuVmlkdSBCcm93c2VyXSgvZG9jcy9ob3ctZG8taS9tYW5hZ2UtdmlkZW9zLyNsZXQtb3BlbnZpZHUtdGFrZS1jYXJlLW9mLXRoZS12aWRlby1wbGF5ZXJzKSkuXG4gICAgICogRm9yIGV2ZXJ5IHZpZGVvIHJlbW92ZWQsIGVhY2ggU3Vic2NyaWJlciBvYmplY3Qgd2lsbCBkaXNwYXRjaCBhIGB2aWRlb0VsZW1lbnREZXN0cm95ZWRgIGV2ZW50LlxuICAgICAqIENhbGwgYGV2ZW50LnByZXZlbnREZWZhdWx0KClgIHVwb24gZXZlbnQgYHNlc3Npb25EaXNjb25uZWN0ZWRgIHRvIGF2b2lkIHRoaXMgYmVoYXZpb3IgYW5kIHRha2UgY2FyZSBvZiBkaXNwb3NpbmcgYW5kIGNsZWFuaW5nIGFsbCB0aGUgU3Vic2NyaWJlciBvYmplY3RzIHlvdXJzZWxmLlxuICAgICAqIFNlZSBbW1Nlc3Npb25EaXNjb25uZWN0ZWRFdmVudF1dIGFuZCBbW1ZpZGVvRWxlbWVudEV2ZW50XV0gdG8gbGVhcm4gbW9yZSB0byBsZWFybiBtb3JlLlxuICAgICAqXG4gICAgICogVGhlIFtbUHVibGlzaGVyXV0gb2JqZWN0IG9mIHRoZSBsb2NhbCBwYXJ0aWNpcGFudCB3aWxsIGRpc3BhdGNoIGEgYHN0cmVhbURlc3Ryb3llZGAgZXZlbnQgaWYgdGhlcmUgaXMgYSBbW1B1Ymxpc2hlcl1dIG9iamVjdCBwdWJsaXNoaW5nIHRvIHRoZSBzZXNzaW9uLlxuICAgICAqIFRoaXMgZXZlbnQgd2lsbCBhdXRvbWF0aWNhbGx5IHN0b3AgYWxsIG1lZGlhIHRyYWNrcyBhbmQgZGVsZXRlIGFueSBIVE1MIHZpZGVvIGVsZW1lbnQgYXNzb2NpYXRlZCB0byBpdCAob25seSB0aG9zZSBbY3JlYXRlZCBieSBPcGVuVmlkdSBCcm93c2VyXSgvZG9jcy9ob3ctZG8taS9tYW5hZ2UtdmlkZW9zLyNsZXQtb3BlbnZpZHUtdGFrZS1jYXJlLW9mLXRoZS12aWRlby1wbGF5ZXJzKSkuXG4gICAgICogRm9yIGV2ZXJ5IHZpZGVvIHJlbW92ZWQsIHRoZSBQdWJsaXNoZXIgb2JqZWN0IHdpbGwgZGlzcGF0Y2ggYSBgdmlkZW9FbGVtZW50RGVzdHJveWVkYCBldmVudC5cbiAgICAgKiBDYWxsIGBldmVudC5wcmV2ZW50RGVmYXVsdCgpYCB1cG9uIGV2ZW50IGBzdHJlYW1EZXN0cm95ZWRgIGlmIHlvdSB3YW50IHRvIGNsZWFuIHRoZSBQdWJsaXNoZXIgb2JqZWN0IG9uIHlvdXIgb3duIG9yIHJlLXB1Ymxpc2ggaXQgaW4gYSBkaWZmZXJlbnQgU2Vzc2lvbiAodG8gZG8gc28gaXQgaXMgYSBtYW5kYXRvcnkgcmVxdWlyZW1lbnQgdG8gY2FsbCBgU2Vzc2lvbi51bnB1Ymxpc2goKWBcbiAgICAgKiBvci9hbmQgYFNlc3Npb24uZGlzY29ubmVjdCgpYCBpbiB0aGUgcHJldmlvdXMgc2Vzc2lvbikuIFNlZSBbW1N0cmVhbUV2ZW50XV0gYW5kIFtbVmlkZW9FbGVtZW50RXZlbnRdXSB0byBsZWFybiBtb3JlLlxuICAgICAqXG4gICAgICogVGhlIFtbU2Vzc2lvbl1dIG9iamVjdCBvZiBldmVyeSBvdGhlciBwYXJ0aWNpcGFudCBjb25uZWN0ZWQgdG8gdGhlIHNlc3Npb24gd2lsbCBkaXNwYXRjaCBhIGBzdHJlYW1EZXN0cm95ZWRgIGV2ZW50IGlmIHRoZSBkaXNjb25uZWN0ZWQgcGFydGljaXBhbnQgd2FzIHB1Ymxpc2hpbmcuXG4gICAgICogVGhpcyBldmVudCB3aWxsIGF1dG9tYXRpY2FsbHkgdW5zdWJzY3JpYmUgdGhlIFN1YnNjcmliZXIgb2JqZWN0IGZyb20gdGhlIHNlc3Npb24gKHRoaXMgaW5jbHVkZXMgY2xvc2luZyB0aGUgV2ViUlRDUGVlciBjb25uZWN0aW9uIGFuZCBkaXNwb3NpbmcgYWxsIE1lZGlhU3RyZWFtVHJhY2tzKVxuICAgICAqIGFuZCBhbHNvIGRlbGV0ZXMgYW55IEhUTUwgdmlkZW8gZWxlbWVudCBhc3NvY2lhdGVkIHRvIHRoYXQgU3Vic2NyaWJlciAob25seSB0aG9zZSBbY3JlYXRlZCBieSBPcGVuVmlkdSBCcm93c2VyXSgvZG9jcy9ob3ctZG8taS9tYW5hZ2UtdmlkZW9zLyNsZXQtb3BlbnZpZHUtdGFrZS1jYXJlLW9mLXRoZS12aWRlby1wbGF5ZXJzKSkuXG4gICAgICogRm9yIGV2ZXJ5IHZpZGVvIHJlbW92ZWQsIHRoZSBTdWJzY3JpYmVyIG9iamVjdCB3aWxsIGRpc3BhdGNoIGEgYHZpZGVvRWxlbWVudERlc3Ryb3llZGAgZXZlbnQuXG4gICAgICogQ2FsbCBgZXZlbnQucHJldmVudERlZmF1bHQoKWAgdXBvbiBldmVudCBgc3RyZWFtRGVzdHJveWVkYCB0byBhdm9pZCB0aGlzIGRlZmF1bHQgYmVoYXZpb3IgYW5kIHRha2UgY2FyZSBvZiBkaXNwb3NpbmcgYW5kIGNsZWFuaW5nIHRoZSBTdWJzY3JpYmVyIG9iamVjdCB5b3Vyc2VsZi5cbiAgICAgKiBTZWUgW1tTdHJlYW1FdmVudF1dIGFuZCBbW1ZpZGVvRWxlbWVudEV2ZW50XV0gdG8gbGVhcm4gbW9yZS5cbiAgICAgKlxuICAgICAqIFRoZSBbW1Nlc3Npb25dXSBvYmplY3Qgb2YgZXZlcnkgb3RoZXIgcGFydGljaXBhbnQgY29ubmVjdGVkIHRvIHRoZSBzZXNzaW9uIHdpbGwgZGlzcGF0Y2ggYSBgY29ubmVjdGlvbkRlc3Ryb3llZGAgZXZlbnQgaW4gYW55IGNhc2UuIFNlZSBbW0Nvbm5lY3Rpb25FdmVudF1dIHRvIGxlYXJuIG1vcmUuXG4gICAgICovXG4gICAgZGlzY29ubmVjdCgpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5sZWF2ZShmYWxzZSwgJ2Rpc2Nvbm5lY3QnKTtcbiAgICB9XG5cbiAgICBzdWJzY3JpYmUoc3RyZWFtOiBTdHJlYW0sIHRhcmdldEVsZW1lbnQ6IHN0cmluZyB8IEhUTUxFbGVtZW50KTogU3Vic2NyaWJlcjtcbiAgICBzdWJzY3JpYmUoc3RyZWFtOiBTdHJlYW0sIHRhcmdldEVsZW1lbnQ6IHN0cmluZyB8IEhUTUxFbGVtZW50LCBwcm9wZXJ0aWVzOiBTdWJzY3JpYmVyUHJvcGVydGllcyk6IFN1YnNjcmliZXI7XG4gICAgc3Vic2NyaWJlKHN0cmVhbTogU3RyZWFtLCB0YXJnZXRFbGVtZW50OiBzdHJpbmcgfCBIVE1MRWxlbWVudCwgY29tcGxldGlvbkhhbmRsZXI6IChlcnJvcjogRXJyb3IgfCB1bmRlZmluZWQpID0+IHZvaWQpOiBTdWJzY3JpYmVyO1xuICAgIHN1YnNjcmliZShzdHJlYW06IFN0cmVhbSwgdGFyZ2V0RWxlbWVudDogc3RyaW5nIHwgSFRNTEVsZW1lbnQsIHByb3BlcnRpZXM6IFN1YnNjcmliZXJQcm9wZXJ0aWVzLCBjb21wbGV0aW9uSGFuZGxlcjogKGVycm9yOiBFcnJvciB8IHVuZGVmaW5lZCkgPT4gdm9pZCk6IFN1YnNjcmliZXI7XG5cbiAgICAvKipcbiAgICAgKiBTdWJzY3JpYmVzIHRvIGEgYHN0cmVhbWAsIGFkZGluZyBhIG5ldyBIVE1MIHZpZGVvIGVsZW1lbnQgdG8gRE9NIHdpdGggYHN1YnNjcmliZXJQcm9wZXJ0aWVzYCBzZXR0aW5ncy4gVGhpcyBtZXRob2QgaXMgdXN1YWxseSBjYWxsZWQgaW4gdGhlIGNhbGxiYWNrIG9mIGBzdHJlYW1DcmVhdGVkYCBldmVudC5cbiAgICAgKlxuICAgICAqICMjIyMgRXZlbnRzIGRpc3BhdGNoZWRcbiAgICAgKlxuICAgICAqIFRoZSBbW1N1YnNjcmliZXJdXSBvYmplY3Qgd2lsbCBkaXNwYXRjaCBhIGB2aWRlb0VsZW1lbnRDcmVhdGVkYCBldmVudCBvbmNlIHRoZSBIVE1MIHZpZGVvIGVsZW1lbnQgaGFzIGJlZW4gYWRkZWQgdG8gRE9NIChvbmx5IGlmIHlvdVxuICAgICAqIFtsZXQgT3BlblZpZHUgdGFrZSBjYXJlIG9mIHRoZSB2aWRlbyBwbGF5ZXJzXSgvZG9jcy9ob3ctZG8taS9tYW5hZ2UtdmlkZW9zLyNsZXQtb3BlbnZpZHUtdGFrZS1jYXJlLW9mLXRoZS12aWRlby1wbGF5ZXJzKSkuIFNlZSBbW1ZpZGVvRWxlbWVudEV2ZW50XV0gdG8gbGVhcm4gbW9yZS5cbiAgICAgKlxuICAgICAqIFRoZSBbW1N1YnNjcmliZXJdXSBvYmplY3Qgd2lsbCBkaXNwYXRjaCBhIGBzdHJlYW1QbGF5aW5nYCBldmVudCBvbmNlIHRoZSByZW1vdGUgc3RyZWFtIHN0YXJ0cyBwbGF5aW5nLiBTZWUgW1tTdHJlYW1NYW5hZ2VyRXZlbnRdXSB0byBsZWFybiBtb3JlLlxuICAgICAqXG4gICAgICogQHBhcmFtIHN0cmVhbSBTdHJlYW0gb2JqZWN0IHRvIHN1YnNjcmliZSB0b1xuICAgICAqIEBwYXJhbSB0YXJnZXRFbGVtZW50IEhUTUwgRE9NIGVsZW1lbnQgKG9yIGl0cyBgaWRgIGF0dHJpYnV0ZSkgaW4gd2hpY2ggdGhlIHZpZGVvIGVsZW1lbnQgb2YgdGhlIFN1YnNjcmliZXIgd2lsbCBiZSBpbnNlcnRlZCAoc2VlIFtbU3Vic2NyaWJlclByb3BlcnRpZXMuaW5zZXJ0TW9kZV1dKS4gSWYgKm51bGwqIG9yICp1bmRlZmluZWQqIG5vIGRlZmF1bHQgdmlkZW8gd2lsbCBiZSBjcmVhdGVkIGZvciB0aGlzIFN1YnNjcmliZXIuXG4gICAgICogWW91IGNhbiBhbHdheXMgY2FsbCBtZXRob2QgW1tTdWJzY3JpYmVyLmFkZFZpZGVvRWxlbWVudF1dIG9yIFtbU3Vic2NyaWJlci5jcmVhdGVWaWRlb0VsZW1lbnRdXSB0byBtYW5hZ2UgdGhlIHZpZGVvIGVsZW1lbnRzIG9uIHlvdXIgb3duIChzZWUgW01hbmFnZSB2aWRlbyBwbGF5ZXJzXSgvZG9jcy9ob3ctZG8taS9tYW5hZ2UtdmlkZW9zKSBzZWN0aW9uKVxuICAgICAqIEBwYXJhbSBjb21wbGV0aW9uSGFuZGxlciBgZXJyb3JgIHBhcmFtZXRlciBpcyBudWxsIGlmIGBzdWJzY3JpYmVgIHN1Y2NlZWRzLCBhbmQgaXMgZGVmaW5lZCBpZiBpdCBmYWlscy5cbiAgICAgKi9cbiAgICBzdWJzY3JpYmUoc3RyZWFtOiBTdHJlYW0sIHRhcmdldEVsZW1lbnQ6IHN0cmluZyB8IEhUTUxFbGVtZW50LCBwYXJhbTM/OiAoKGVycm9yOiBFcnJvciB8IHVuZGVmaW5lZCkgPT4gdm9pZCkgfCBTdWJzY3JpYmVyUHJvcGVydGllcywgcGFyYW00PzogKChlcnJvcjogRXJyb3IgfCB1bmRlZmluZWQpID0+IHZvaWQpKTogU3Vic2NyaWJlciB7XG4gICAgICAgIGxldCBwcm9wZXJ0aWVzOiBTdWJzY3JpYmVyUHJvcGVydGllcyA9IHt9O1xuICAgICAgICBpZiAoISFwYXJhbTMgJiYgdHlwZW9mIHBhcmFtMyAhPT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgcHJvcGVydGllcyA9IHtcbiAgICAgICAgICAgICAgICBpbnNlcnRNb2RlOiAodHlwZW9mIHBhcmFtMy5pbnNlcnRNb2RlICE9PSAndW5kZWZpbmVkJykgPyAoKHR5cGVvZiBwYXJhbTMuaW5zZXJ0TW9kZSA9PT0gJ3N0cmluZycpID8gVmlkZW9JbnNlcnRNb2RlW3BhcmFtMy5pbnNlcnRNb2RlXSA6IHByb3BlcnRpZXMuaW5zZXJ0TW9kZSkgOiBWaWRlb0luc2VydE1vZGUuQVBQRU5ELFxuICAgICAgICAgICAgICAgIHN1YnNjcmliZVRvQXVkaW86ICh0eXBlb2YgcGFyYW0zLnN1YnNjcmliZVRvQXVkaW8gIT09ICd1bmRlZmluZWQnKSA/IHBhcmFtMy5zdWJzY3JpYmVUb0F1ZGlvIDogdHJ1ZSxcbiAgICAgICAgICAgICAgICBzdWJzY3JpYmVUb1ZpZGVvOiAodHlwZW9mIHBhcmFtMy5zdWJzY3JpYmVUb1ZpZGVvICE9PSAndW5kZWZpbmVkJykgPyBwYXJhbTMuc3Vic2NyaWJlVG9WaWRlbyA6IHRydWVcbiAgICAgICAgICAgIH07XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBwcm9wZXJ0aWVzID0ge1xuICAgICAgICAgICAgICAgIGluc2VydE1vZGU6IFZpZGVvSW5zZXJ0TW9kZS5BUFBFTkQsXG4gICAgICAgICAgICAgICAgc3Vic2NyaWJlVG9BdWRpbzogdHJ1ZSxcbiAgICAgICAgICAgICAgICBzdWJzY3JpYmVUb1ZpZGVvOiB0cnVlXG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG5cbiAgICAgICAgbGV0IGNvbXBsZXRpb25IYW5kbGVyOiAoZXJyb3I6IEVycm9yIHwgdW5kZWZpbmVkKSA9PiB2b2lkO1xuICAgICAgICBpZiAoISFwYXJhbTMgJiYgKHR5cGVvZiBwYXJhbTMgPT09ICdmdW5jdGlvbicpKSB7XG4gICAgICAgICAgICBjb21wbGV0aW9uSGFuZGxlciA9IHBhcmFtMztcbiAgICAgICAgfSBlbHNlIGlmICghIXBhcmFtNCkge1xuICAgICAgICAgICAgY29tcGxldGlvbkhhbmRsZXIgPSBwYXJhbTQ7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zb2xlLmluZm8oJ1N1YnNjcmliaW5nIHRvICcgKyBzdHJlYW0uY29ubmVjdGlvbi5jb25uZWN0aW9uSWQpO1xuXG4gICAgICAgIHN0cmVhbS5zdWJzY3JpYmUoKVxuICAgICAgICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbygnU3Vic2NyaWJlZCBjb3JyZWN0bHkgdG8gJyArIHN0cmVhbS5jb25uZWN0aW9uLmNvbm5lY3Rpb25JZCk7XG4gICAgICAgICAgICAgICAgaWYgKGNvbXBsZXRpb25IYW5kbGVyICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgY29tcGxldGlvbkhhbmRsZXIodW5kZWZpbmVkKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICAgICAgICBpZiAoY29tcGxldGlvbkhhbmRsZXIgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICBjb21wbGV0aW9uSGFuZGxlcihlcnJvcik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIGNvbnN0IHN1YnNjcmliZXIgPSBuZXcgU3Vic2NyaWJlcihzdHJlYW0sIHRhcmdldEVsZW1lbnQsIHByb3BlcnRpZXMpO1xuICAgICAgICBpZiAoISFzdWJzY3JpYmVyLnRhcmdldEVsZW1lbnQpIHtcbiAgICAgICAgICAgIHN0cmVhbS5zdHJlYW1NYW5hZ2VyLmNyZWF0ZVZpZGVvRWxlbWVudChzdWJzY3JpYmVyLnRhcmdldEVsZW1lbnQsIDxWaWRlb0luc2VydE1vZGU+cHJvcGVydGllcy5pbnNlcnRNb2RlKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gc3Vic2NyaWJlcjtcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFByb21pc2lmaWVkIHZlcnNpb24gb2YgW1tTZXNzaW9uLnN1YnNjcmliZV1dXG4gICAgICovXG4gICAgc3Vic2NyaWJlQXN5bmMoc3RyZWFtOiBTdHJlYW0sIHRhcmdldEVsZW1lbnQ6IHN0cmluZyB8IEhUTUxFbGVtZW50KTogUHJvbWlzZTxTdWJzY3JpYmVyPjtcbiAgICBzdWJzY3JpYmVBc3luYyhzdHJlYW06IFN0cmVhbSwgdGFyZ2V0RWxlbWVudDogc3RyaW5nIHwgSFRNTEVsZW1lbnQsIHByb3BlcnRpZXM6IFN1YnNjcmliZXJQcm9wZXJ0aWVzKTogUHJvbWlzZTxTdWJzY3JpYmVyPjtcblxuICAgIHN1YnNjcmliZUFzeW5jKHN0cmVhbTogU3RyZWFtLCB0YXJnZXRFbGVtZW50OiBzdHJpbmcgfCBIVE1MRWxlbWVudCwgcHJvcGVydGllcz86IFN1YnNjcmliZXJQcm9wZXJ0aWVzKTogUHJvbWlzZTxTdWJzY3JpYmVyPiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZTxTdWJzY3JpYmVyPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG5cbiAgICAgICAgICAgIGxldCBzdWJzY3JpYmVyOiBTdWJzY3JpYmVyO1xuXG4gICAgICAgICAgICBjb25zdCBjYWxsYmFjayA9IChlcnJvcjogRXJyb3IpID0+IHtcbiAgICAgICAgICAgICAgICBpZiAoISFlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc29sdmUoc3Vic2NyaWJlcik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgaWYgKCEhcHJvcGVydGllcykge1xuICAgICAgICAgICAgICAgIHN1YnNjcmliZXIgPSB0aGlzLnN1YnNjcmliZShzdHJlYW0sIHRhcmdldEVsZW1lbnQsIHByb3BlcnRpZXMsIGNhbGxiYWNrKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgc3Vic2NyaWJlciA9IHRoaXMuc3Vic2NyaWJlKHN0cmVhbSwgdGFyZ2V0RWxlbWVudCwgY2FsbGJhY2spO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgIH0pO1xuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogVW5zdWJzY3JpYmVzIGZyb20gYHN1YnNjcmliZXJgLCBhdXRvbWF0aWNhbGx5IHJlbW92aW5nIGl0cyBhc3NvY2lhdGVkIEhUTUwgdmlkZW8gZWxlbWVudHMuXG4gICAgICpcbiAgICAgKiAjIyMjIEV2ZW50cyBkaXNwYXRjaGVkXG4gICAgICpcbiAgICAgKiBUaGUgW1tTdWJzY3JpYmVyXV0gb2JqZWN0IHdpbGwgZGlzcGF0Y2ggYSBgdmlkZW9FbGVtZW50RGVzdHJveWVkYCBldmVudCBmb3IgZWFjaCB2aWRlbyBhc3NvY2lhdGVkIHRvIGl0IHRoYXQgd2FzIHJlbW92ZWQgZnJvbSBET00uXG4gICAgICogT25seSB2aWRlb3MgW2NyZWF0ZWQgYnkgT3BlblZpZHUgQnJvd3Nlcl0oL2RvY3MvaG93LWRvLWkvbWFuYWdlLXZpZGVvcy8jbGV0LW9wZW52aWR1LXRha2UtY2FyZS1vZi10aGUtdmlkZW8tcGxheWVycykpIHdpbGwgYmUgYXV0b21hdGljYWxseSByZW1vdmVkXG4gICAgICpcbiAgICAgKiBTZWUgW1tWaWRlb0VsZW1lbnRFdmVudF1dIHRvIGxlYXJuIG1vcmVcbiAgICAgKi9cbiAgICB1bnN1YnNjcmliZShzdWJzY3JpYmVyOiBTdWJzY3JpYmVyKTogdm9pZCB7XG4gICAgICAgIGNvbnN0IGNvbm5lY3Rpb25JZCA9IHN1YnNjcmliZXIuc3RyZWFtLmNvbm5lY3Rpb24uY29ubmVjdGlvbklkO1xuXG4gICAgICAgIGNvbnNvbGUuaW5mbygnVW5zdWJzY3JpYmluZyBmcm9tICcgKyBjb25uZWN0aW9uSWQpO1xuXG4gICAgICAgIHRoaXMub3BlbnZpZHUuc2VuZFJlcXVlc3QoXG4gICAgICAgICAgICAndW5zdWJzY3JpYmVGcm9tVmlkZW8nLFxuICAgICAgICAgICAgeyBzZW5kZXI6IHN1YnNjcmliZXIuc3RyZWFtLmNvbm5lY3Rpb24uY29ubmVjdGlvbklkIH0sXG4gICAgICAgICAgICAoZXJyb3IsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ0Vycm9yIHVuc3Vic2NyaWJpbmcgZnJvbSAnICsgY29ubmVjdGlvbklkLCBlcnJvcik7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS5pbmZvKCdVbnN1YnNjcmliZWQgY29ycmVjdGx5IGZyb20gJyArIGNvbm5lY3Rpb25JZCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHN1YnNjcmliZXIuc3RyZWFtLmRpc3Bvc2VXZWJSdGNQZWVyKCk7XG4gICAgICAgICAgICAgICAgc3Vic2NyaWJlci5zdHJlYW0uZGlzcG9zZU1lZGlhU3RyZWFtKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICk7XG4gICAgICAgIHN1YnNjcmliZXIuc3RyZWFtLnN0cmVhbU1hbmFnZXIucmVtb3ZlQWxsVmlkZW9zKCk7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBQdWJsaXNoZXMgdG8gdGhlIFNlc3Npb24gdGhlIFB1Ymxpc2hlciBvYmplY3RcbiAgICAgKlxuICAgICAqICMjIyMgRXZlbnRzIGRpc3BhdGNoZWRcbiAgICAgKlxuICAgICAqIFRoZSBsb2NhbCBbW1B1Ymxpc2hlcl1dIG9iamVjdCB3aWxsIGRpc3BhdGNoIGEgYHN0cmVhbUNyZWF0ZWRgIGV2ZW50IHVwb24gc3VjY2Vzc2Z1bCB0ZXJtaW5hdGlvbiBvZiB0aGlzIG1ldGhvZC4gU2VlIFtbU3RyZWFtRXZlbnRdXSB0byBsZWFybiBtb3JlLlxuICAgICAqXG4gICAgICogVGhlIGxvY2FsIFtbUHVibGlzaGVyXV0gb2JqZWN0IHdpbGwgZGlzcGF0Y2ggYSBgc3RyZWFtUGxheWluZ2Agb25jZSB0aGUgbWVkaWEgc3RyZWFtIHN0YXJ0cyBwbGF5aW5nLiBTZWUgW1tTdHJlYW1NYW5hZ2VyRXZlbnRdXSB0byBsZWFybiBtb3JlLlxuICAgICAqXG4gICAgICogVGhlIFtbU2Vzc2lvbl1dIG9iamVjdCBvZiBldmVyeSBvdGhlciBwYXJ0aWNpcGFudCBjb25uZWN0ZWQgdG8gdGhlIHNlc3Npb24gd2lsbCBkaXNwYXRjaCBhIGBzdHJlYW1DcmVhdGVkYCBldmVudCBzbyB0aGV5IGNhbiBzdWJzY3JpYmUgdG8gaXQuIFNlZSBbW1N0cmVhbUV2ZW50XV0gdG8gbGVhcm4gbW9yZS5cbiAgICAgKlxuICAgICAqIEByZXR1cm5zIEEgUHJvbWlzZSAodG8gd2hpY2ggeW91IGNhbiBvcHRpb25hbGx5IHN1YnNjcmliZSB0bykgdGhhdCBpcyByZXNvbHZlZCBvbmx5IGFmdGVyIHRoZSBwdWJsaXNoZXIgd2FzIHN1Y2Nlc3NmdWxseSBwdWJsaXNoZWQgYW5kIHJlamVjdGVkIHdpdGggYW4gRXJyb3Igb2JqZWN0IGlmIG5vdFxuICAgICAqL1xuICAgIHB1Ymxpc2gocHVibGlzaGVyOiBQdWJsaXNoZXIpOiBQcm9taXNlPGFueT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgcHVibGlzaGVyLnNlc3Npb24gPSB0aGlzO1xuICAgICAgICAgICAgcHVibGlzaGVyLnN0cmVhbS5zZXNzaW9uID0gdGhpcztcblxuICAgICAgICAgICAgaWYgKCFwdWJsaXNoZXIuc3RyZWFtLnB1Ymxpc2hlZE9uY2UpIHtcbiAgICAgICAgICAgICAgICAvLyAnU2Vzc2lvbi51bnB1Ymxpc2goUHVibGlzaGVyKScgaGFzIE5PVCBiZWVuIGNhbGxlZFxuICAgICAgICAgICAgICAgIHRoaXMuY29ubmVjdGlvbi5hZGRTdHJlYW0ocHVibGlzaGVyLnN0cmVhbSk7XG4gICAgICAgICAgICAgICAgcHVibGlzaGVyLnN0cmVhbS5wdWJsaXNoKClcbiAgICAgICAgICAgICAgICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIC8vICdTZXNzaW9uLnVucHVibGlzaChQdWJsaXNoZXIpJyBoYXMgYmVlbiBjYWxsZWQuIE11c3QgaW5pdGlhbGl6ZSBhZ2FpbiBQdWJsaXNoZXJcbiAgICAgICAgICAgICAgICBwdWJsaXNoZXIuaW5pdGlhbGl6ZSgpXG4gICAgICAgICAgICAgICAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY29ubmVjdGlvbi5hZGRTdHJlYW0ocHVibGlzaGVyLnN0cmVhbSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBwdWJsaXNoZXIucmVlc3RhYmxpc2hTdHJlYW1QbGF5aW5nRXZlbnQoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHB1Ymxpc2hlci5zdHJlYW0ucHVibGlzaCgpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICB9KS5jYXRjaCgoZXJyb3IpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFVucHVibGlzaGVzIGZyb20gdGhlIFNlc3Npb24gdGhlIFB1Ymxpc2hlciBvYmplY3QuXG4gICAgICpcbiAgICAgKiAjIyMjIEV2ZW50cyBkaXNwYXRjaGVkXG4gICAgICpcbiAgICAgKiBUaGUgW1tQdWJsaXNoZXJdXSBvYmplY3Qgb2YgdGhlIGxvY2FsIHBhcnRpY2lwYW50IHdpbGwgZGlzcGF0Y2ggYSBgc3RyZWFtRGVzdHJveWVkYCBldmVudC5cbiAgICAgKiBUaGlzIGV2ZW50IHdpbGwgYXV0b21hdGljYWxseSBzdG9wIGFsbCBtZWRpYSB0cmFja3MgYW5kIGRlbGV0ZSBhbnkgSFRNTCB2aWRlbyBlbGVtZW50IGFzc29jaWF0ZWQgdG8gdGhpcyBQdWJsaXNoZXJcbiAgICAgKiAob25seSB0aG9zZSB2aWRlb3MgW2NyZWF0ZWQgYnkgT3BlblZpZHUgQnJvd3Nlcl0oL2RvY3MvaG93LWRvLWkvbWFuYWdlLXZpZGVvcy8jbGV0LW9wZW52aWR1LXRha2UtY2FyZS1vZi10aGUtdmlkZW8tcGxheWVycykpLlxuICAgICAqIEZvciBldmVyeSB2aWRlbyByZW1vdmVkLCB0aGUgUHVibGlzaGVyIG9iamVjdCB3aWxsIGRpc3BhdGNoIGEgYHZpZGVvRWxlbWVudERlc3Ryb3llZGAgZXZlbnQuXG4gICAgICogQ2FsbCBgZXZlbnQucHJldmVudERlZmF1bHQoKWAgdXBvbiBldmVudCBgc3RyZWFtRGVzdHJveWVkYCBpZiB5b3Ugd2FudCB0byBjbGVhbiB0aGUgUHVibGlzaGVyIG9iamVjdCBvbiB5b3VyIG93biBvciByZS1wdWJsaXNoIGl0IGluIGEgZGlmZmVyZW50IFNlc3Npb24uXG4gICAgICpcbiAgICAgKiBUaGUgW1tTZXNzaW9uXV0gb2JqZWN0IG9mIGV2ZXJ5IG90aGVyIHBhcnRpY2lwYW50IGNvbm5lY3RlZCB0byB0aGUgc2Vzc2lvbiB3aWxsIGRpc3BhdGNoIGEgYHN0cmVhbURlc3Ryb3llZGAgZXZlbnQuXG4gICAgICogVGhpcyBldmVudCB3aWxsIGF1dG9tYXRpY2FsbHkgdW5zdWJzY3JpYmUgdGhlIFN1YnNjcmliZXIgb2JqZWN0IGZyb20gdGhlIHNlc3Npb24gKHRoaXMgaW5jbHVkZXMgY2xvc2luZyB0aGUgV2ViUlRDUGVlciBjb25uZWN0aW9uIGFuZCBkaXNwb3NpbmcgYWxsIE1lZGlhU3RyZWFtVHJhY2tzKSBhbmRcbiAgICAgKiBkZWxldGUgYW55IEhUTUwgdmlkZW8gZWxlbWVudCBhc3NvY2lhdGVkIHRvIGl0IChvbmx5IHRob3NlIFtjcmVhdGVkIGJ5IE9wZW5WaWR1IEJyb3dzZXJdKC9kb2NzL2hvdy1kby1pL21hbmFnZS12aWRlb3MvI2xldC1vcGVudmlkdS10YWtlLWNhcmUtb2YtdGhlLXZpZGVvLXBsYXllcnMpKS5cbiAgICAgKiBGb3IgZXZlcnkgdmlkZW8gcmVtb3ZlZCwgdGhlIFN1YnNjcmliZXIgb2JqZWN0IHdpbGwgZGlzcGF0Y2ggYSBgdmlkZW9FbGVtZW50RGVzdHJveWVkYCBldmVudC5cbiAgICAgKiBDYWxsIGBldmVudC5wcmV2ZW50RGVmYXVsdCgpYCB1cG9uIGV2ZW50IGBzdHJlYW1EZXN0cm95ZWRgIHRvIGF2b2lkIHRoaXMgZGVmYXVsdCBiZWhhdmlvciBhbmQgdGFrZSBjYXJlIG9mIGRpc3Bvc2luZyBhbmQgY2xlYW5pbmcgdGhlIFN1YnNjcmliZXIgb2JqZWN0IG9uIHlvdXIgb3duLlxuICAgICAqXG4gICAgICogU2VlIFtbU3RyZWFtRXZlbnRdXSBhbmQgW1tWaWRlb0VsZW1lbnRFdmVudF1dIHRvIGxlYXJuIG1vcmUuXG4gICAgICovXG4gICAgdW5wdWJsaXNoKHB1Ymxpc2hlcjogUHVibGlzaGVyKTogdm9pZCB7XG5cbiAgICAgICAgY29uc3Qgc3RyZWFtID0gcHVibGlzaGVyLnN0cmVhbTtcblxuICAgICAgICBpZiAoIXN0cmVhbS5jb25uZWN0aW9uKSB7XG4gICAgICAgICAgICBjb25zb2xlLmVycm9yKCdUaGUgYXNzb2NpYXRlZCBDb25uZWN0aW9uIG9iamVjdCBvZiB0aGlzIFB1Ymxpc2hlciBpcyBudWxsJywgc3RyZWFtKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfSBlbHNlIGlmIChzdHJlYW0uY29ubmVjdGlvbiAhPT0gdGhpcy5jb25uZWN0aW9uKSB7XG4gICAgICAgICAgICBjb25zb2xlLmVycm9yKCdUaGUgYXNzb2NpYXRlZCBDb25uZWN0aW9uIG9iamVjdCBvZiB0aGlzIFB1Ymxpc2hlciBpcyBub3QgeW91ciBsb2NhbCBDb25uZWN0aW9uLicgK1xuICAgICAgICAgICAgICAgIFwiT25seSBtb2RlcmF0b3JzIGNhbiBmb3JjZSB1bnB1Ymxpc2ggb24gcmVtb3RlIFN0cmVhbXMgdmlhICdmb3JjZVVucHVibGlzaCcgbWV0aG9kXCIsIHN0cmVhbSk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH0gZWxzZSB7XG5cbiAgICAgICAgICAgIGNvbnNvbGUuaW5mbygnVW5wdWJsaXNoaW5nIGxvY2FsIG1lZGlhICgnICsgc3RyZWFtLmNvbm5lY3Rpb24uY29ubmVjdGlvbklkICsgJyknKTtcblxuICAgICAgICAgICAgdGhpcy5vcGVudmlkdS5zZW5kUmVxdWVzdCgndW5wdWJsaXNoVmlkZW8nLCAoZXJyb3IsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoZXJyb3IpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbygnTWVkaWEgdW5wdWJsaXNoZWQgY29ycmVjdGx5Jyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIHN0cmVhbS5kaXNwb3NlV2ViUnRjUGVlcigpO1xuICAgICAgICAgICAgZGVsZXRlIHN0cmVhbS5jb25uZWN0aW9uLnN0cmVhbTtcblxuICAgICAgICAgICAgY29uc3Qgc3RyZWFtRXZlbnQgPSBuZXcgU3RyZWFtRXZlbnQodHJ1ZSwgcHVibGlzaGVyLCAnc3RyZWFtRGVzdHJveWVkJywgcHVibGlzaGVyLnN0cmVhbSwgJ3VucHVibGlzaCcpO1xuICAgICAgICAgICAgcHVibGlzaGVyLmVtaXRFdmVudCgnc3RyZWFtRGVzdHJveWVkJywgW3N0cmVhbUV2ZW50XSk7XG4gICAgICAgICAgICBzdHJlYW1FdmVudC5jYWxsRGVmYXVsdEJlaGF2aW9yKCk7XG4gICAgICAgIH1cbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIEZvcmNlcyBzb21lIHVzZXIgdG8gbGVhdmUgdGhlIHNlc3Npb25cbiAgICAgKlxuICAgICAqICMjIyMgRXZlbnRzIGRpc3BhdGNoZWRcbiAgICAgKlxuICAgICAqIFRoZSBiZWhhdmlvciBpcyB0aGUgc2FtZSBhcyB3aGVuIHNvbWUgdXNlciBjYWxscyBbW1Nlc3Npb24uZGlzY29ubmVjdF1dLCBidXQgYHJlYXNvbmAgcHJvcGVydHkgaW4gYWxsIGV2ZW50cyB3aWxsIGJlIGBcImZvcmNlRGlzY29ubmVjdEJ5VXNlclwiYC5cbiAgICAgKlxuICAgICAqIFRoZSBbW1Nlc3Npb25dXSBvYmplY3Qgb2YgZXZlcnkgcGFydGljaXBhbnQgd2lsbCBkaXNwYXRjaCBhIGBzdHJlYW1EZXN0cm95ZWRgIGV2ZW50IGlmIHRoZSBldmljdGVkIHVzZXIgd2FzIHB1Ymxpc2hpbmcgYSBzdHJlYW0sIHdpdGggcHJvcGVydHkgYHJlYXNvbmAgc2V0IHRvIGBcImZvcmNlRGlzY29ubmVjdEJ5VXNlclwiYC5cbiAgICAgKiBUaGUgW1tTZXNzaW9uXV0gb2JqZWN0IG9mIGV2ZXJ5IHBhcnRpY2lwYW50IGV4Y2VwdCB0aGUgZXZpY3RlZCBvbmUgd2lsbCBkaXNwYXRjaCBhIGBjb25uZWN0aW9uRGVzdHJveWVkYCBldmVudCBmb3IgdGhlIGV2aWN0ZWQgdXNlciwgd2l0aCBwcm9wZXJ0eSBgcmVhc29uYCBzZXQgdG8gYFwiZm9yY2VEaXNjb25uZWN0QnlVc2VyXCJgLlxuICAgICAqXG4gICAgICogSWYgYW55LCB0aGUgW1tQdWJsaXNoZXJdXSBvYmplY3Qgb2YgdGhlIGV2aWN0ZWQgcGFydGljaXBhbnQgd2lsbCBhbHNvIGRpc3BhdGNoIGEgYHN0cmVhbURlc3Ryb3llZGAgZXZlbnQgd2l0aCBwcm9wZXJ0eSBgcmVhc29uYCBzZXQgdG8gYFwiZm9yY2VEaXNjb25uZWN0QnlVc2VyXCJgLlxuICAgICAqIFRoZSBbW1Nlc3Npb25dXSBvYmplY3Qgb2YgdGhlIGV2aWN0ZWQgcGFydGljaXBhbnQgd2lsbCBkaXNwYXRjaCBhIGBzZXNzaW9uRGlzY29ubmVjdGVkYCBldmVudCB3aXRoIHByb3BlcnR5IGByZWFzb25gIHNldCB0byBgXCJmb3JjZURpc2Nvbm5lY3RCeVVzZXJcImAuXG4gICAgICpcbiAgICAgKiBTZWUgW1tTdHJlYW1FdmVudF1dLCBbW0Nvbm5lY3Rpb25FdmVudF1dIGFuZCBbW1Nlc3Npb25EaXNjb25uZWN0ZWRFdmVudF1dIHRvIGxlYXJuIG1vcmUuXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyBBIFByb21pc2UgKHRvIHdoaWNoIHlvdSBjYW4gb3B0aW9uYWxseSBzdWJzY3JpYmUgdG8pIHRoYXQgaXMgcmVzb2x2ZWQgb25seSBhZnRlciB0aGUgcGFydGljaXBhbnQgaGFzIGJlZW4gc3VjY2Vzc2Z1bGx5IGV2aWN0ZWQgZnJvbSB0aGUgc2Vzc2lvbiBhbmQgcmVqZWN0ZWQgd2l0aCBhbiBFcnJvciBvYmplY3QgaWYgbm90XG4gICAgICovXG4gICAgZm9yY2VEaXNjb25uZWN0KGNvbm5lY3Rpb246IENvbm5lY3Rpb24pOiBQcm9taXNlPGFueT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgY29uc29sZS5pbmZvKCdGb3JjaW5nIGRpc2Nvbm5lY3QgZm9yIGNvbm5lY3Rpb24gJyArIGNvbm5lY3Rpb24uY29ubmVjdGlvbklkKTtcbiAgICAgICAgICAgIHRoaXMub3BlbnZpZHUuc2VuZFJlcXVlc3QoXG4gICAgICAgICAgICAgICAgJ2ZvcmNlRGlzY29ubmVjdCcsXG4gICAgICAgICAgICAgICAgeyBjb25uZWN0aW9uSWQ6IGNvbm5lY3Rpb24uY29ubmVjdGlvbklkIH0sXG4gICAgICAgICAgICAgICAgKGVycm9yLCByZXNwb25zZSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBpZiAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ0Vycm9yIGZvcmNpbmcgZGlzY29ubmVjdCBmb3IgQ29ubmVjdGlvbiAnICsgY29ubmVjdGlvbi5jb25uZWN0aW9uSWQsIGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChlcnJvci5jb2RlID09PSA0MDEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWplY3QobmV3IE9wZW5WaWR1RXJyb3IoT3BlblZpZHVFcnJvck5hbWUuT1BFTlZJRFVfUEVSTUlTU0lPTl9ERU5JRUQsIFwiWW91IGRvbid0IGhhdmUgcGVybWlzc2lvbnMgdG8gZm9yY2UgYSBkaXNjb25uZWN0aW9uXCIpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbygnRm9yY2luZyBkaXNjb25uZWN0IGNvcnJlY3RseSBmb3IgQ29ubmVjdGlvbiAnICsgY29ubmVjdGlvbi5jb25uZWN0aW9uSWQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBGb3JjZXMgc29tZSB1c2VyIHRvIHVucHVibGlzaCBhIFN0cmVhbVxuICAgICAqXG4gICAgICogIyMjIyBFdmVudHMgZGlzcGF0Y2hlZFxuICAgICAqXG4gICAgICogVGhlIGJlaGF2aW9yIGlzIHRoZSBzYW1lIGFzIHdoZW4gc29tZSB1c2VyIGNhbGxzIFtbU2Vzc2lvbi51bnB1Ymxpc2hdXSwgYnV0IGByZWFzb25gIHByb3BlcnR5IGluIGFsbCBldmVudHMgd2lsbCBiZSBgXCJmb3JjZVVucHVibGlzaEJ5VXNlclwiYFxuICAgICAqXG4gICAgICogVGhlIFtbU2Vzc2lvbl1dIG9iamVjdCBvZiBldmVyeSBwYXJ0aWNpcGFudCB3aWxsIGRpc3BhdGNoIGEgYHN0cmVhbURlc3Ryb3llZGAgZXZlbnQgd2l0aCBwcm9wZXJ0eSBgcmVhc29uYCBzZXQgdG8gYFwiZm9yY2VEaXNjb25uZWN0QnlVc2VyXCJgXG4gICAgICpcbiAgICAgKiBUaGUgW1tQdWJsaXNoZXJdXSBvYmplY3Qgb2YgdGhlIGFmZmVjdGVkIHBhcnRpY2lwYW50IHdpbGwgYWxzbyBkaXNwYXRjaCBhIGBzdHJlYW1EZXN0cm95ZWRgIGV2ZW50IHdpdGggcHJvcGVydHkgYHJlYXNvbmAgc2V0IHRvIGBcImZvcmNlRGlzY29ubmVjdEJ5VXNlclwiYFxuICAgICAqXG4gICAgICogU2VlIFtbU3RyZWFtRXZlbnRdXSB0byBsZWFybiBtb3JlLlxuICAgICAqXG4gICAgICogQHJldHVybnMgQSBQcm9taXNlICh0byB3aGljaCB5b3UgY2FuIG9wdGlvbmFsbHkgc3Vic2NyaWJlIHRvKSB0aGF0IGlzIHJlc29sdmVkIG9ubHkgYWZ0ZXIgdGhlIHJlbW90ZSBTdHJlYW0gaGFzIGJlZW4gc3VjY2Vzc2Z1bGx5IHVucHVibGlzaGVkIGZyb20gdGhlIHNlc3Npb24gYW5kIHJlamVjdGVkIHdpdGggYW4gRXJyb3Igb2JqZWN0IGlmIG5vdFxuICAgICAqL1xuICAgIGZvcmNlVW5wdWJsaXNoKHN0cmVhbTogU3RyZWFtKTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIGNvbnNvbGUuaW5mbygnRm9yY2luZyB1bnB1Ymxpc2ggZm9yIHN0cmVhbSAnICsgc3RyZWFtLnN0cmVhbUlkKTtcbiAgICAgICAgICAgIHRoaXMub3BlbnZpZHUuc2VuZFJlcXVlc3QoXG4gICAgICAgICAgICAgICAgJ2ZvcmNlVW5wdWJsaXNoJyxcbiAgICAgICAgICAgICAgICB7IHN0cmVhbUlkOiBzdHJlYW0uc3RyZWFtSWQgfSxcbiAgICAgICAgICAgICAgICAoZXJyb3IsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcignRXJyb3IgZm9yY2luZyB1bnB1Ymxpc2ggZm9yIFN0cmVhbSAnICsgc3RyZWFtLnN0cmVhbUlkLCBlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZXJyb3IuY29kZSA9PT0gNDAxKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KG5ldyBPcGVuVmlkdUVycm9yKE9wZW5WaWR1RXJyb3JOYW1lLk9QRU5WSURVX1BFUk1JU1NJT05fREVOSUVELCBcIllvdSBkb24ndCBoYXZlIHBlcm1pc3Npb25zIHRvIGZvcmNlIGFuIHVucHVibGlzaGluZ1wiKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oJ0ZvcmNpbmcgdW5wdWJsaXNoIGNvcnJlY3RseSBmb3IgU3RyZWFtICcgKyBzdHJlYW0uc3RyZWFtSWQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBTZW5kcyBvbmUgc2lnbmFsLiBgc2lnbmFsYCBvYmplY3QgaGFzIHRoZSBmb2xsb3dpbmcgb3B0aW9uYWwgcHJvcGVydGllczpcbiAgICAgKiBgYGBqc29uXG4gICAgICoge2RhdGE6c3RyaW5nLCB0bzpDb25uZWN0aW9uW10sIHR5cGU6c3RyaW5nfVxuICAgICAqIGBgYFxuICAgICAqIEFsbCB1c2VycyBzdWJzY3JpYmVkIHRvIHRoYXQgc2lnbmFsIChgc2Vzc2lvbi5vbignc2lnbmFsOnR5cGUnLCAuLi4pYCBvciBgc2Vzc2lvbi5vbignc2lnbmFsJywgLi4uKWAgZm9yIGFsbCBzaWduYWxzKSBhbmQgd2hvc2UgQ29ubmVjdGlvbiBvYmplY3RzIGFyZSBpbiBgdG9gIGFycmF5IHdpbGwgcmVjZWl2ZSBpdC4gVGhlaXIgbG9jYWxcbiAgICAgKiBTZXNzaW9uIG9iamVjdHMgd2lsbCBkaXNwYXRjaCBhIGBzaWduYWxgIG9yIGBzaWduYWw6dHlwZWAgZXZlbnQuIFNlZSBbW1NpZ25hbEV2ZW50XV0gdG8gbGVhcm4gbW9yZS5cbiAgICAgKlxuICAgICAqIEByZXR1cm5zIEEgUHJvbWlzZSAodG8gd2hpY2ggeW91IGNhbiBvcHRpb25hbGx5IHN1YnNjcmliZSB0bykgdGhhdCBpcyByZXNvbHZlZCBpZiB0aGUgbWVzc2FnZSBzdWNjZXNzZnVsbHkgcmVhY2hlZCBvcGVudmlkdS1zZXJ2ZXIgYW5kIHJlamVjdGVkIHdpdGggYW4gRXJyb3Igb2JqZWN0IGlmIG5vdC4gX1RoaXMgZG9lc24ndFxuICAgICAqIG1lYW4gdGhhdCBvcGVudmlkdS1zZXJ2ZXIgY291bGQgcmVzZW5kIHRoZSBtZXNzYWdlIHRvIGFsbCB0aGUgbGlzdGVkIHJlY2VpdmVycy5fXG4gICAgICovXG4gICAgLyogdHNsaW50OmRpc2FibGU6bm8tc3RyaW5nLWxpdGVyYWwgKi9cbiAgICBzaWduYWwoc2lnbmFsOiBTaWduYWxPcHRpb25zKTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcblxuICAgICAgICAgICAgY29uc3Qgc2lnbmFsTWVzc2FnZSA9IHt9O1xuXG4gICAgICAgICAgICBpZiAoc2lnbmFsLnRvICYmIHNpZ25hbC50by5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgY29ubmVjdGlvbklkczogc3RyaW5nW10gPSBbXTtcblxuICAgICAgICAgICAgICAgIHNpZ25hbC50by5mb3JFYWNoKGNvbm5lY3Rpb24gPT4ge1xuICAgICAgICAgICAgICAgICAgICBjb25uZWN0aW9uSWRzLnB1c2goY29ubmVjdGlvbi5jb25uZWN0aW9uSWQpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIHNpZ25hbE1lc3NhZ2VbJ3RvJ10gPSBjb25uZWN0aW9uSWRzO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBzaWduYWxNZXNzYWdlWyd0byddID0gW107XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHNpZ25hbE1lc3NhZ2VbJ2RhdGEnXSA9IHNpZ25hbC5kYXRhID8gc2lnbmFsLmRhdGEgOiAnJztcbiAgICAgICAgICAgIHNpZ25hbE1lc3NhZ2VbJ3R5cGUnXSA9IHNpZ25hbC50eXBlID8gc2lnbmFsLnR5cGUgOiAnJztcblxuICAgICAgICAgICAgdGhpcy5vcGVudmlkdS5zZW5kUmVxdWVzdCgnc2VuZE1lc3NhZ2UnLCB7XG4gICAgICAgICAgICAgICAgbWVzc2FnZTogSlNPTi5zdHJpbmdpZnkoc2lnbmFsTWVzc2FnZSlcbiAgICAgICAgICAgIH0sIChlcnJvciwgcmVzcG9uc2UpID0+IHtcbiAgICAgICAgICAgICAgICBpZiAoISFlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgfVxuICAgIC8qIHRzbGludDplbmFibGU6bm8tc3RyaW5nLWxpdGVyYWwgKi9cblxuXG4gICAgLyoqXG4gICAgICogU2VlIFtbRXZlbnREaXNwYXRjaGVyLm9uXV1cbiAgICAgKi9cbiAgICBvbih0eXBlOiBzdHJpbmcsIGhhbmRsZXI6IChldmVudDogU2Vzc2lvbkRpc2Nvbm5lY3RlZEV2ZW50IHwgU2lnbmFsRXZlbnQgfCBTdHJlYW1FdmVudCB8IENvbm5lY3Rpb25FdmVudCB8IFB1Ymxpc2hlclNwZWFraW5nRXZlbnQgfCBSZWNvcmRpbmdFdmVudCkgPT4gdm9pZCk6IEV2ZW50RGlzcGF0Y2hlciB7XG5cbiAgICAgICAgdGhpcy5lZS5vbih0eXBlLCBldmVudCA9PiB7XG4gICAgICAgICAgICBpZiAoZXZlbnQpIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oXCJFdmVudCAnXCIgKyB0eXBlICsgXCInIHRyaWdnZXJlZCBieSAnU2Vzc2lvbidcIiwgZXZlbnQpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oXCJFdmVudCAnXCIgKyB0eXBlICsgXCInIHRyaWdnZXJlZCBieSAnU2Vzc2lvbidcIik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBoYW5kbGVyKGV2ZW50KTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgaWYgKHR5cGUgPT09ICdwdWJsaXNoZXJTdGFydFNwZWFraW5nJyB8fCB0eXBlID09PSAncHVibGlzaGVyU3RvcFNwZWFraW5nJykge1xuICAgICAgICAgICAgdGhpcy5zcGVha2luZ0V2ZW50c0VuYWJsZWQgPSB0cnVlO1xuICAgICAgICAgICAgLy8gSWYgdGhlcmUgYXJlIGFscmVhZHkgYXZhaWxhYmxlIHJlbW90ZSBzdHJlYW1zLCBlbmFibGUgaGFyayAnc3BlYWtpbmcnIGV2ZW50IGluIGFsbCBvZiB0aGVtXG4gICAgICAgICAgICBmb3IgKGNvbnN0IGNvbm5lY3Rpb25JZCBpbiB0aGlzLnJlbW90ZUNvbm5lY3Rpb25zKSB7XG4gICAgICAgICAgICAgICAgY29uc3Qgc3RyID0gdGhpcy5yZW1vdGVDb25uZWN0aW9uc1tjb25uZWN0aW9uSWRdLnN0cmVhbTtcbiAgICAgICAgICAgICAgICBpZiAoISFzdHIgJiYgIXN0ci5zcGVlY2hFdmVudCAmJiBzdHIuaGFzQXVkaW8pIHtcbiAgICAgICAgICAgICAgICAgICAgc3RyLmVuYWJsZVNwZWFraW5nRXZlbnRzKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBTZWUgW1tFdmVudERpc3BhdGNoZXIub25jZV1dXG4gICAgICovXG4gICAgb25jZSh0eXBlOiBzdHJpbmcsIGhhbmRsZXI6IChldmVudDogU2Vzc2lvbkRpc2Nvbm5lY3RlZEV2ZW50IHwgU2lnbmFsRXZlbnQgfCBTdHJlYW1FdmVudCB8IENvbm5lY3Rpb25FdmVudCB8IFB1Ymxpc2hlclNwZWFraW5nRXZlbnQgfCBSZWNvcmRpbmdFdmVudCkgPT4gdm9pZCk6IFNlc3Npb24ge1xuICAgICAgICB0aGlzLmVlLm9uY2UodHlwZSwgZXZlbnQgPT4ge1xuICAgICAgICAgICAgaWYgKGV2ZW50KSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5pbmZvKFwiRXZlbnQgJ1wiICsgdHlwZSArIFwiJyB0cmlnZ2VyZWQgYnkgJ1Nlc3Npb24nXCIsIGV2ZW50KTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5pbmZvKFwiRXZlbnQgJ1wiICsgdHlwZSArIFwiJyB0cmlnZ2VyZWQgYnkgJ1Nlc3Npb24nXCIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaGFuZGxlcihldmVudCk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGlmICh0eXBlID09PSAncHVibGlzaGVyU3RhcnRTcGVha2luZycgfHwgdHlwZSA9PT0gJ3B1Ymxpc2hlclN0b3BTcGVha2luZycpIHtcbiAgICAgICAgICAgIHRoaXMuc3BlYWtpbmdFdmVudHNFbmFibGVkID0gdHJ1ZTtcblxuICAgICAgICAgICAgLy8gSWYgdGhlcmUgYXJlIGFscmVhZHkgYXZhaWxhYmxlIHJlbW90ZSBzdHJlYW1zLCBlbmFibGUgaGFyayBpbiBhbGwgb2YgdGhlbVxuICAgICAgICAgICAgZm9yIChjb25zdCBjb25uZWN0aW9uSWQgaW4gdGhpcy5yZW1vdGVDb25uZWN0aW9ucykge1xuICAgICAgICAgICAgICAgIGNvbnN0IHN0ciA9IHRoaXMucmVtb3RlQ29ubmVjdGlvbnNbY29ubmVjdGlvbklkXS5zdHJlYW07XG4gICAgICAgICAgICAgICAgaWYgKCEhc3RyICYmICFzdHIuc3BlZWNoRXZlbnQgJiYgc3RyLmhhc0F1ZGlvKSB7XG4gICAgICAgICAgICAgICAgICAgIHN0ci5lbmFibGVPbmNlU3BlYWtpbmdFdmVudHMoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFNlZSBbW0V2ZW50RGlzcGF0Y2hlci5vZmZdXVxuICAgICAqL1xuICAgIG9mZih0eXBlOiBzdHJpbmcsIGhhbmRsZXI/OiAoZXZlbnQ6IFNlc3Npb25EaXNjb25uZWN0ZWRFdmVudCB8IFNpZ25hbEV2ZW50IHwgU3RyZWFtRXZlbnQgfCBDb25uZWN0aW9uRXZlbnQgfCBQdWJsaXNoZXJTcGVha2luZ0V2ZW50IHwgUmVjb3JkaW5nRXZlbnQpID0+IHZvaWQpOiBTZXNzaW9uIHtcblxuICAgICAgICBpZiAoIWhhbmRsZXIpIHtcbiAgICAgICAgICAgIHRoaXMuZWUucmVtb3ZlQWxsTGlzdGVuZXJzKHR5cGUpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5lZS5vZmYodHlwZSwgaGFuZGxlcik7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodHlwZSA9PT0gJ3B1Ymxpc2hlclN0YXJ0U3BlYWtpbmcnIHx8IHR5cGUgPT09ICdwdWJsaXNoZXJTdG9wU3BlYWtpbmcnKSB7XG4gICAgICAgICAgICB0aGlzLnNwZWFraW5nRXZlbnRzRW5hYmxlZCA9IGZhbHNlO1xuXG4gICAgICAgICAgICAvLyBJZiB0aGVyZSBhcmUgYWxyZWFkeSBhdmFpbGFibGUgcmVtb3RlIHN0cmVhbXMsIGRpc2FibGFlIGhhcmsgaW4gYWxsIG9mIHRoZW1cbiAgICAgICAgICAgIGZvciAoY29uc3QgY29ubmVjdGlvbklkIGluIHRoaXMucmVtb3RlQ29ubmVjdGlvbnMpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBzdHIgPSB0aGlzLnJlbW90ZUNvbm5lY3Rpb25zW2Nvbm5lY3Rpb25JZF0uc3RyZWFtO1xuICAgICAgICAgICAgICAgIGlmICghIXN0ciAmJiAhIXN0ci5zcGVlY2hFdmVudCkge1xuICAgICAgICAgICAgICAgICAgICBzdHIuZGlzYWJsZVNwZWFraW5nRXZlbnRzKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuXG4gICAgLyogSGlkZGVuIG1ldGhvZHMgKi9cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvblBhcnRpY2lwYW50Sm9pbmVkKHJlc3BvbnNlOiBDb25uZWN0aW9uT3B0aW9ucyk6IHZvaWQge1xuICAgICAgICAvLyBDb25uZWN0aW9uIHNob3VsZG4ndCBleGlzdFxuICAgICAgICB0aGlzLmdldENvbm5lY3Rpb24ocmVzcG9uc2UuaWQsICcnKVxuXG4gICAgICAgICAgICAudGhlbihjb25uZWN0aW9uID0+IHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLndhcm4oJ0Nvbm5lY3Rpb24gJyArIHJlc3BvbnNlLmlkICsgJyBhbHJlYWR5IGV4aXN0cyBpbiBjb25uZWN0aW9ucyBsaXN0Jyk7XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLmNhdGNoKG9wZW5WaWR1RXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IGNvbm5lY3Rpb24gPSBuZXcgQ29ubmVjdGlvbih0aGlzLCByZXNwb25zZSk7XG4gICAgICAgICAgICAgICAgdGhpcy5yZW1vdGVDb25uZWN0aW9uc1tyZXNwb25zZS5pZF0gPSBjb25uZWN0aW9uO1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdjb25uZWN0aW9uQ3JlYXRlZCcsIFtuZXcgQ29ubmVjdGlvbkV2ZW50KGZhbHNlLCB0aGlzLCAnY29ubmVjdGlvbkNyZWF0ZWQnLCBjb25uZWN0aW9uLCAnJyldKTtcbiAgICAgICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvblBhcnRpY2lwYW50TGVmdChtc2cpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5nZXRSZW1vdGVDb25uZWN0aW9uKG1zZy5jb25uZWN0aW9uSWQsICdSZW1vdGUgY29ubmVjdGlvbiAnICsgbXNnLmNvbm5lY3Rpb25JZCArIFwiIHVua25vd24gd2hlbiAnb25QYXJ0aWNpcGFudExlZnQnLiBcIiArXG4gICAgICAgICAgICAnRXhpc3RpbmcgcmVtb3RlIGNvbm5lY3Rpb25zOiAnICsgSlNPTi5zdHJpbmdpZnkoT2JqZWN0LmtleXModGhpcy5yZW1vdGVDb25uZWN0aW9ucykpKVxuXG4gICAgICAgICAgICAudGhlbihjb25uZWN0aW9uID0+IHtcbiAgICAgICAgICAgICAgICBpZiAoISFjb25uZWN0aW9uLnN0cmVhbSkge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBzdHJlYW0gPSBjb25uZWN0aW9uLnN0cmVhbTtcblxuICAgICAgICAgICAgICAgICAgICBjb25zdCBzdHJlYW1FdmVudCA9IG5ldyBTdHJlYW1FdmVudCh0cnVlLCB0aGlzLCAnc3RyZWFtRGVzdHJveWVkJywgc3RyZWFtLCBtc2cucmVhc29uKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3N0cmVhbURlc3Ryb3llZCcsIFtzdHJlYW1FdmVudF0pO1xuICAgICAgICAgICAgICAgICAgICBzdHJlYW1FdmVudC5jYWxsRGVmYXVsdEJlaGF2aW9yKCk7XG5cbiAgICAgICAgICAgICAgICAgICAgZGVsZXRlIHRoaXMucmVtb3RlU3RyZWFtc0NyZWF0ZWRbc3RyZWFtLnN0cmVhbUlkXTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZGVsZXRlIHRoaXMucmVtb3RlQ29ubmVjdGlvbnNbY29ubmVjdGlvbi5jb25uZWN0aW9uSWRdO1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdjb25uZWN0aW9uRGVzdHJveWVkJywgW25ldyBDb25uZWN0aW9uRXZlbnQoZmFsc2UsIHRoaXMsICdjb25uZWN0aW9uRGVzdHJveWVkJywgY29ubmVjdGlvbiwgbXNnLnJlYXNvbildKTtcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAuY2F0Y2gob3BlblZpZHVFcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihvcGVuVmlkdUVycm9yKTtcbiAgICAgICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvblBhcnRpY2lwYW50UHVibGlzaGVkKHJlc3BvbnNlOiBDb25uZWN0aW9uT3B0aW9ucyk6IHZvaWQge1xuXG4gICAgICAgIGNvbnN0IGFmdGVyQ29ubmVjdGlvbkZvdW5kID0gKGNvbm5lY3Rpb24pID0+IHtcbiAgICAgICAgICAgIHRoaXMucmVtb3RlQ29ubmVjdGlvbnNbY29ubmVjdGlvbi5jb25uZWN0aW9uSWRdID0gY29ubmVjdGlvbjtcblxuICAgICAgICAgICAgaWYgKCF0aGlzLnJlbW90ZVN0cmVhbXNDcmVhdGVkW2Nvbm5lY3Rpb24uc3RyZWFtLnN0cmVhbUlkXSkge1xuICAgICAgICAgICAgICAgIC8vIEF2b2lkIHJhY2UgY29uZGl0aW9uIGJldHdlZW4gc3RyZWFtLnN1YnNjcmliZSgpIGluIFwib25QYXJ0aWNpcGFudFB1Ymxpc2hlZFwiIGFuZCBpbiBcImpvaW5Sb29tXCIgcnBjIGNhbGxiYWNrXG4gICAgICAgICAgICAgICAgLy8gVGhpcyBjb25kaXRpb24gaXMgZmFsc2UgaWYgb3BlbnZpZHUtc2VydmVyIHNlbmRzIFwicGFydGljaXBhbnRQdWJsaXNoZWRcIiBldmVudCB0byBhIHN1YnNjcmliZXIgcGFydGljaXBhbnQgdGhhdCBoYXNcbiAgICAgICAgICAgICAgICAvLyBhbHJlYWR5IHN1YnNjcmliZWQgdG8gY2VydGFpbiBzdHJlYW0gaW4gdGhlIGNhbGxiYWNrIG9mIFwiam9pblJvb21cIiBtZXRob2RcblxuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdzdHJlYW1DcmVhdGVkJywgW25ldyBTdHJlYW1FdmVudChmYWxzZSwgdGhpcywgJ3N0cmVhbUNyZWF0ZWQnLCBjb25uZWN0aW9uLnN0cmVhbSwgJycpXSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMucmVtb3RlU3RyZWFtc0NyZWF0ZWRbY29ubmVjdGlvbi5zdHJlYW0uc3RyZWFtSWRdID0gdHJ1ZTtcbiAgICAgICAgfTtcblxuICAgICAgICAvLyBHZXQgdGhlIGV4aXN0aW5nIENvbm5lY3Rpb24gY3JlYXRlZCBvbiAnb25QYXJ0aWNpcGFudEpvaW5lZCcgZm9yXG4gICAgICAgIC8vIGV4aXN0aW5nIHBhcnRpY2lwYW50cyBvciBjcmVhdGUgYSBuZXcgb25lIGZvciBuZXcgcGFydGljaXBhbnRzXG4gICAgICAgIGxldCBjb25uZWN0aW9uOiBDb25uZWN0aW9uO1xuICAgICAgICB0aGlzLmdldFJlbW90ZUNvbm5lY3Rpb24ocmVzcG9uc2UuaWQsIFwiUmVtb3RlIGNvbm5lY3Rpb24gJ1wiICsgcmVzcG9uc2UuaWQgKyBcIicgdW5rbm93biB3aGVuICdvblBhcnRpY2lwYW50UHVibGlzaGVkJy4gXCIgK1xuICAgICAgICAgICAgJ0V4aXN0aW5nIHJlbW90ZSBjb25uZWN0aW9uczogJyArIEpTT04uc3RyaW5naWZ5KE9iamVjdC5rZXlzKHRoaXMucmVtb3RlQ29ubmVjdGlvbnMpKSlcblxuICAgICAgICAgICAgLnRoZW4oY29uID0+IHtcbiAgICAgICAgICAgICAgICAvLyBVcGRhdGUgZXhpc3RpbmcgQ29ubmVjdGlvblxuICAgICAgICAgICAgICAgIGNvbm5lY3Rpb24gPSBjb247XG4gICAgICAgICAgICAgICAgcmVzcG9uc2UubWV0YWRhdGEgPSBjb24uZGF0YTtcbiAgICAgICAgICAgICAgICBjb25uZWN0aW9uLm9wdGlvbnMgPSByZXNwb25zZTtcbiAgICAgICAgICAgICAgICBjb25uZWN0aW9uLmluaXRSZW1vdGVTdHJlYW1zKHJlc3BvbnNlLnN0cmVhbXMpO1xuICAgICAgICAgICAgICAgIGFmdGVyQ29ubmVjdGlvbkZvdW5kKGNvbm5lY3Rpb24pO1xuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIC5jYXRjaChvcGVuVmlkdUVycm9yID0+IHtcbiAgICAgICAgICAgICAgICAvLyBDcmVhdGUgbmV3IENvbm5lY3Rpb25cbiAgICAgICAgICAgICAgICBjb25uZWN0aW9uID0gbmV3IENvbm5lY3Rpb24odGhpcywgcmVzcG9uc2UpO1xuICAgICAgICAgICAgICAgIGFmdGVyQ29ubmVjdGlvbkZvdW5kKGNvbm5lY3Rpb24pO1xuICAgICAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIG9uUGFydGljaXBhbnRVbnB1Ymxpc2hlZChtc2cpOiB2b2lkIHtcbiAgICAgICAgaWYgKG1zZy5jb25uZWN0aW9uSWQgPT09IHRoaXMuY29ubmVjdGlvbi5jb25uZWN0aW9uSWQpIHtcbiAgICAgICAgICAgIC8vIFlvdXIgc3RyZWFtIGhhcyBiZWVuIGZvcmNlZGx5IHVucHVibGlzaGVkIGZyb20gdGhlIHNlc3Npb25cbiAgICAgICAgICAgIHRoaXMuc3RvcFB1Ymxpc2hlclN0cmVhbShtc2cucmVhc29uKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuZ2V0UmVtb3RlQ29ubmVjdGlvbihtc2cuY29ubmVjdGlvbklkLCBcIlJlbW90ZSBjb25uZWN0aW9uICdcIiArIG1zZy5jb25uZWN0aW9uSWQgKyBcIicgdW5rbm93biB3aGVuICdvblBhcnRpY2lwYW50VW5wdWJsaXNoZWQnLiBcIiArXG4gICAgICAgICAgICAgICAgJ0V4aXN0aW5nIHJlbW90ZSBjb25uZWN0aW9uczogJyArIEpTT04uc3RyaW5naWZ5KE9iamVjdC5rZXlzKHRoaXMucmVtb3RlQ29ubmVjdGlvbnMpKSlcblxuICAgICAgICAgICAgICAgIC50aGVuKGNvbm5lY3Rpb24gPT4ge1xuXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHN0cmVhbUV2ZW50ID0gbmV3IFN0cmVhbUV2ZW50KHRydWUsIHRoaXMsICdzdHJlYW1EZXN0cm95ZWQnLCBjb25uZWN0aW9uLnN0cmVhbSwgbXNnLnJlYXNvbik7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdzdHJlYW1EZXN0cm95ZWQnLCBbc3RyZWFtRXZlbnRdKTtcbiAgICAgICAgICAgICAgICAgICAgc3RyZWFtRXZlbnQuY2FsbERlZmF1bHRCZWhhdmlvcigpO1xuXG4gICAgICAgICAgICAgICAgICAgIC8vIERlbGV0aW5nIHRoZSByZW1vdGUgc3RyZWFtXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHN0cmVhbUlkOiBzdHJpbmcgPSBjb25uZWN0aW9uLnN0cmVhbS5zdHJlYW1JZDtcbiAgICAgICAgICAgICAgICAgICAgZGVsZXRlIHRoaXMucmVtb3RlU3RyZWFtc0NyZWF0ZWRbc3RyZWFtSWRdO1xuICAgICAgICAgICAgICAgICAgICBjb25uZWN0aW9uLnJlbW92ZVN0cmVhbShzdHJlYW1JZCk7XG4gICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAuY2F0Y2gob3BlblZpZHVFcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3Iob3BlblZpZHVFcnJvcik7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgb25QYXJ0aWNpcGFudEV2aWN0ZWQobXNnKTogdm9pZCB7XG4gICAgICAgIGlmIChtc2cuY29ubmVjdGlvbklkID09PSB0aGlzLmNvbm5lY3Rpb24uY29ubmVjdGlvbklkKSB7XG4gICAgICAgICAgICAvLyBZb3UgaGF2ZSBiZWVuIGV2aWN0ZWQgZnJvbSB0aGUgc2Vzc2lvblxuICAgICAgICAgICAgaWYgKCEhdGhpcy5zZXNzaW9uSWQgJiYgIXRoaXMuY29ubmVjdGlvbi5kaXNwb3NlZCkge1xuICAgICAgICAgICAgICAgIHRoaXMubGVhdmUodHJ1ZSwgbXNnLnJlYXNvbik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgb25OZXdNZXNzYWdlKG1zZyk6IHZvaWQge1xuXG4gICAgICAgIGNvbnNvbGUuaW5mbygnTmV3IHNpZ25hbDogJyArIEpTT04uc3RyaW5naWZ5KG1zZykpO1xuXG4gICAgICAgIHRoaXMuZ2V0Q29ubmVjdGlvbihtc2cuZnJvbSwgXCJDb25uZWN0aW9uICdcIiArIG1zZy5mcm9tICsgXCInIHVua25vdyB3aGVuICdvbk5ld01lc3NhZ2UnLiBFeGlzdGluZyByZW1vdGUgY29ubmVjdGlvbnM6IFwiXG4gICAgICAgICAgICArIEpTT04uc3RyaW5naWZ5KE9iamVjdC5rZXlzKHRoaXMucmVtb3RlQ29ubmVjdGlvbnMpKSArICcuIEV4aXN0aW5nIGxvY2FsIGNvbm5lY3Rpb246ICcgKyB0aGlzLmNvbm5lY3Rpb24uY29ubmVjdGlvbklkKVxuXG4gICAgICAgICAgICAudGhlbihjb25uZWN0aW9uID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnc2lnbmFsJywgW25ldyBTaWduYWxFdmVudCh0aGlzLCBtc2cudHlwZSwgbXNnLmRhdGEsIGNvbm5lY3Rpb24pXSk7XG4gICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3NpZ25hbDonICsgbXNnLnR5cGUsIFtuZXcgU2lnbmFsRXZlbnQodGhpcywgbXNnLnR5cGUsIG1zZy5kYXRhLCBjb25uZWN0aW9uKV0pO1xuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIC5jYXRjaChvcGVuVmlkdUVycm9yID0+IHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKG9wZW5WaWR1RXJyb3IpO1xuICAgICAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIG9uU3RyZWFtUHJvcGVydHlDaGFuZ2VkKG1zZyk6IHZvaWQge1xuICAgICAgICB0aGlzLmdldFJlbW90ZUNvbm5lY3Rpb24obXNnLmNvbm5lY3Rpb25JZCwgJ1JlbW90ZSBjb25uZWN0aW9uICcgKyBtc2cuY29ubmVjdGlvbklkICsgXCIgdW5rbm93biB3aGVuICdvblN0cmVhbVByb3BlcnR5Q2hhbmdlZCcuIFwiICtcbiAgICAgICAgICAgICdFeGlzdGluZyByZW1vdGUgY29ubmVjdGlvbnM6ICcgKyBKU09OLnN0cmluZ2lmeShPYmplY3Qua2V5cyh0aGlzLnJlbW90ZUNvbm5lY3Rpb25zKSkpXG5cbiAgICAgICAgICAgIC50aGVuKGNvbm5lY3Rpb24gPT4ge1xuICAgICAgICAgICAgICAgIGlmICghIWNvbm5lY3Rpb24uc3RyZWFtICYmIGNvbm5lY3Rpb24uc3RyZWFtLnN0cmVhbUlkID09PSBtc2cuc3RyZWFtSWQpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3Qgc3RyZWFtID0gY29ubmVjdGlvbi5zdHJlYW07XG4gICAgICAgICAgICAgICAgICAgIGxldCBvbGRWYWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgc3dpdGNoIChtc2cucHJvcGVydHkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJ2F1ZGlvQWN0aXZlJzpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvbGRWYWx1ZSA9IHN0cmVhbS5hdWRpb0FjdGl2ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtc2cubmV3VmFsdWUgPSBtc2cubmV3VmFsdWUgPT09ICd0cnVlJztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJlYW0uYXVkaW9BY3RpdmUgPSBtc2cubmV3VmFsdWU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlICd2aWRlb0FjdGl2ZSc6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgb2xkVmFsdWUgPSBzdHJlYW0udmlkZW9BY3RpdmU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbXNnLm5ld1ZhbHVlID0gbXNnLm5ld1ZhbHVlID09PSAndHJ1ZSc7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyZWFtLnZpZGVvQWN0aXZlID0gbXNnLm5ld1ZhbHVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAndmlkZW9EaW1lbnNpb25zJzpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvbGRWYWx1ZSA9IHN0cmVhbS52aWRlb0RpbWVuc2lvbnM7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbXNnLm5ld1ZhbHVlID0gSlNPTi5wYXJzZShKU09OLnBhcnNlKG1zZy5uZXdWYWx1ZSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cmVhbS52aWRlb0RpbWVuc2lvbnMgPSBtc2cubmV3VmFsdWU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnc3RyZWFtUHJvcGVydHlDaGFuZ2VkJywgW25ldyBTdHJlYW1Qcm9wZXJ0eUNoYW5nZWRFdmVudCh0aGlzLCBzdHJlYW0sIG1zZy5wcm9wZXJ0eSwgbXNnLm5ld1ZhbHVlLCBvbGRWYWx1ZSwgbXNnLnJlYXNvbildKTtcbiAgICAgICAgICAgICAgICAgICAgc3RyZWFtLnN0cmVhbU1hbmFnZXIuZW1pdEV2ZW50KCdzdHJlYW1Qcm9wZXJ0eUNoYW5nZWQnLCBbbmV3IFN0cmVhbVByb3BlcnR5Q2hhbmdlZEV2ZW50KHN0cmVhbS5zdHJlYW1NYW5hZ2VyLCBzdHJlYW0sIG1zZy5wcm9wZXJ0eSwgbXNnLm5ld1ZhbHVlLCBvbGRWYWx1ZSwgbXNnLnJlYXNvbildKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKFwiTm8gc3RyZWFtIHdpdGggc3RyZWFtSWQgJ1wiICsgbXNnLnN0cmVhbUlkICsgXCInIGZvdW5kIGZvciBjb25uZWN0aW9uICdcIiArIG1zZy5jb25uZWN0aW9uSWQgKyBcIicgb24gJ3N0cmVhbVByb3BlcnR5Q2hhbmdlZCcgZXZlbnRcIik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIC5jYXRjaChvcGVuVmlkdUVycm9yID0+IHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKG9wZW5WaWR1RXJyb3IpO1xuICAgICAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHJlY3ZJY2VDYW5kaWRhdGUobXNnKTogdm9pZCB7XG4gICAgICAgIGNvbnN0IGNhbmRpZGF0ZSA9IHtcbiAgICAgICAgICAgIGNhbmRpZGF0ZTogbXNnLmNhbmRpZGF0ZSxcbiAgICAgICAgICAgIHNkcE1pZDogbXNnLnNkcE1pZCxcbiAgICAgICAgICAgIHNkcE1MaW5lSW5kZXg6IG1zZy5zZHBNTGluZUluZGV4LFxuICAgICAgICAgICAgdG9KU09OOiAoKSA9PiB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHsgY2FuZGlkYXRlOiBtc2cuY2FuZGlkYXRlIH07XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuZ2V0Q29ubmVjdGlvbihtc2cuZW5kcG9pbnROYW1lLCAnQ29ubmVjdGlvbiBub3QgZm91bmQgZm9yIGVuZHBvaW50ICcgKyBtc2cuZW5kcG9pbnROYW1lICsgJy4gSWNlIGNhbmRpZGF0ZSB3aWxsIGJlIGlnbm9yZWQ6ICcgKyBjYW5kaWRhdGUpXG4gICAgICAgICAgICAudGhlbihjb25uZWN0aW9uID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCBzdHJlYW0gPSBjb25uZWN0aW9uLnN0cmVhbTtcbiAgICAgICAgICAgICAgICBzdHJlYW0uZ2V0V2ViUnRjUGVlcigpLmFkZEljZUNhbmRpZGF0ZShjYW5kaWRhdGUpLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcignRXJyb3IgYWRkaW5nIGNhbmRpZGF0ZSBmb3IgJyArIHN0cmVhbS5zdHJlYW1JZFxuICAgICAgICAgICAgICAgICAgICAgICAgKyAnIHN0cmVhbSBvZiBlbmRwb2ludCAnICsgbXNnLmVuZHBvaW50TmFtZSArICc6ICcgKyBlcnJvcik7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLmNhdGNoKG9wZW5WaWR1RXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3Iob3BlblZpZHVFcnJvcik7XG4gICAgICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgb25TZXNzaW9uQ2xvc2VkKG1zZyk6IHZvaWQge1xuICAgICAgICBjb25zb2xlLmluZm8oJ1Nlc3Npb24gY2xvc2VkOiAnICsgSlNPTi5zdHJpbmdpZnkobXNnKSk7XG4gICAgICAgIGNvbnN0IHMgPSBtc2cuc2Vzc2lvbklkO1xuICAgICAgICBpZiAocyAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnc2Vzc2lvbi1jbG9zZWQnLCBbe1xuICAgICAgICAgICAgICAgIHNlc3Npb246IHNcbiAgICAgICAgICAgIH1dKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvbnNvbGUud2FybignU2Vzc2lvbiB1bmRlZmluZWQgb24gc2Vzc2lvbiBjbG9zZWQnLCBtc2cpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIG9uTG9zdENvbm5lY3Rpb24oKTogdm9pZCB7XG5cbiAgICAgICAgLyppZiAoIXRoaXMuY29ubmVjdGlvbikge1xuXG4gICAgICAgICAgICBjb25zb2xlLndhcm4oJ05vdCBjb25uZWN0ZWQgdG8gc2Vzc2lvbjogaWYgeW91IGFyZSBub3QgZGVidWdnaW5nLCB0aGlzIGlzIHByb2JhYmx5IGEgY2VydGlmaWNhdGUgZXJyb3InKTtcblxuICAgICAgICAgICAgY29uc3QgdXJsID0gJ2h0dHBzOi8vJyArIHRoaXMub3BlbnZpZHUuZ2V0V3NVcmkoKS5zcGxpdCgnd3NzOi8vJylbMV0uc3BsaXQoJy9vcGVudmlkdScpWzBdO1xuICAgICAgICAgICAgaWYgKHdpbmRvdy5jb25maXJtKCdJZiB5b3UgYXJlIG5vdCBkZWJ1Z2dpbmcsIHRoaXMgaXMgcHJvYmFibHkgYSBjZXJ0aWZpY2F0ZSBlcnJvciBhdCBcXFwiJyArIHVybCArICdcXFwiXFxuXFxuQ2xpY2sgT0sgdG8gbmF2aWdhdGUgYW5kIGFjY2VwdCBpdCcpKSB7XG4gICAgICAgICAgICAgICAgbG9jYXRpb24uYXNzaWduKHVybCArICcvYWNjZXB0LWNlcnRpZmljYXRlJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH0qL1xuXG4gICAgICAgIGNvbnNvbGUud2FybignTG9zdCBjb25uZWN0aW9uIGluIFNlc3Npb24gJyArIHRoaXMuc2Vzc2lvbklkKTtcbiAgICAgICAgaWYgKCEhdGhpcy5zZXNzaW9uSWQgJiYgIXRoaXMuY29ubmVjdGlvbi5kaXNwb3NlZCkge1xuICAgICAgICAgICAgdGhpcy5sZWF2ZSh0cnVlLCAnbmV0d29ya0Rpc2Nvbm5lY3QnKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvblJlY292ZXJlZENvbm5lY3Rpb24oKTogdm9pZCB7XG4gICAgICAgIGNvbnNvbGUud2FybignUmVjb3ZlcmVkIGNvbm5lY3Rpb24gaW4gU2Vzc2lvbiAnICsgdGhpcy5zZXNzaW9uSWQpO1xuICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnY29ubmVjdGlvblJlY292ZXJlZCcsIFtdKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgb25NZWRpYUVycm9yKHBhcmFtcyk6IHZvaWQge1xuXG4gICAgICAgIGNvbnNvbGUuZXJyb3IoJ01lZGlhIGVycm9yOiAnICsgSlNPTi5zdHJpbmdpZnkocGFyYW1zKSk7XG4gICAgICAgIGNvbnN0IGVyciA9IHBhcmFtcy5lcnJvcjtcbiAgICAgICAgaWYgKGVycikge1xuICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ2Vycm9yLW1lZGlhJywgW3tcbiAgICAgICAgICAgICAgICBlcnJvcjogZXJyXG4gICAgICAgICAgICB9XSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjb25zb2xlLndhcm4oJ1JlY2VpdmVkIHVuZGVmaW5lZCBtZWRpYSBlcnJvci4gUGFyYW1zOicsIHBhcmFtcyk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgb25SZWNvcmRpbmdTdGFydGVkKHJlc3BvbnNlKTogdm9pZCB7XG4gICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdyZWNvcmRpbmdTdGFydGVkJywgW25ldyBSZWNvcmRpbmdFdmVudCh0aGlzLCAncmVjb3JkaW5nU3RhcnRlZCcsIHJlc3BvbnNlLmlkLCByZXNwb25zZS5uYW1lKV0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvblJlY29yZGluZ1N0b3BwZWQocmVzcG9uc2UpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3JlY29yZGluZ1N0b3BwZWQnLCBbbmV3IFJlY29yZGluZ0V2ZW50KHRoaXMsICdyZWNvcmRpbmdTdG9wcGVkJywgcmVzcG9uc2UuaWQsIHJlc3BvbnNlLm5hbWUpXSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGVtaXRFdmVudCh0eXBlOiBzdHJpbmcsIGV2ZW50QXJyYXk6IGFueVtdKTogdm9pZCB7XG4gICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KHR5cGUsIGV2ZW50QXJyYXkpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBsZWF2ZShmb3JjZWQ6IGJvb2xlYW4sIHJlYXNvbjogc3RyaW5nKTogdm9pZCB7XG5cbiAgICAgICAgZm9yY2VkID0gISFmb3JjZWQ7XG4gICAgICAgIGNvbnNvbGUuaW5mbygnTGVhdmluZyBTZXNzaW9uIChmb3JjZWQ9JyArIGZvcmNlZCArICcpJyk7XG5cbiAgICAgICAgaWYgKCEhdGhpcy5jb25uZWN0aW9uKSB7XG4gICAgICAgICAgICBpZiAoIXRoaXMuY29ubmVjdGlvbi5kaXNwb3NlZCAmJiAhZm9yY2VkKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5vcGVudmlkdS5zZW5kUmVxdWVzdCgnbGVhdmVSb29tJywgKGVycm9yLCByZXNwb25zZSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBpZiAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHRoaXMub3BlbnZpZHUuY2xvc2VXcygpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLm9wZW52aWR1LmNsb3NlV3MoKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5zdG9wUHVibGlzaGVyU3RyZWFtKHJlYXNvbik7XG5cbiAgICAgICAgICAgIGlmICghdGhpcy5jb25uZWN0aW9uLmRpc3Bvc2VkKSB7XG4gICAgICAgICAgICAgICAgLy8gTWFrZSBTZXNzaW9uIG9iamVjdCBkaXNwYXRjaCAnc2Vzc2lvbkRpc2Nvbm5lY3RlZCcgZXZlbnQgKGlmIGl0IGlzIG5vdCBhbHJlYWR5IGRpc3Bvc2VkKVxuICAgICAgICAgICAgICAgIGNvbnN0IHNlc3Npb25EaXNjb25uZWN0RXZlbnQgPSBuZXcgU2Vzc2lvbkRpc2Nvbm5lY3RlZEV2ZW50KHRoaXMsIHJlYXNvbik7XG4gICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3Nlc3Npb25EaXNjb25uZWN0ZWQnLCBbc2Vzc2lvbkRpc2Nvbm5lY3RFdmVudF0pO1xuICAgICAgICAgICAgICAgIHNlc3Npb25EaXNjb25uZWN0RXZlbnQuY2FsbERlZmF1bHRCZWhhdmlvcigpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY29uc29sZS53YXJuKCdZb3Ugd2VyZSBub3QgY29ubmVjdGVkIHRvIHRoZSBzZXNzaW9uICcgKyB0aGlzLnNlc3Npb25JZCk7XG4gICAgICAgIH1cbiAgICB9XG5cblxuICAgIC8qIFByaXZhdGUgbWV0aG9kcyAqL1xuXG4gICAgcHJpdmF0ZSBjb25uZWN0QXV4KHRva2VuOiBzdHJpbmcpOiBQcm9taXNlPGFueT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5vcGVudmlkdS5zdGFydFdzKChlcnJvcikgPT4ge1xuICAgICAgICAgICAgICAgIGlmICghIWVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcblxuICAgICAgICAgICAgICAgICAgICBjb25zdCBqb2luUGFyYW1zID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgdG9rZW46ICghIXRva2VuKSA/IHRva2VuIDogJycsXG4gICAgICAgICAgICAgICAgICAgICAgICBzZXNzaW9uOiB0aGlzLnNlc3Npb25JZCxcbiAgICAgICAgICAgICAgICAgICAgICAgIG1ldGFkYXRhOiAhIXRoaXMub3B0aW9ucy5tZXRhZGF0YSA/IHRoaXMub3B0aW9ucy5tZXRhZGF0YSA6ICcnLFxuICAgICAgICAgICAgICAgICAgICAgICAgc2VjcmV0OiB0aGlzLm9wZW52aWR1LmdldFNlY3JldCgpLFxuICAgICAgICAgICAgICAgICAgICAgICAgcmVjb3JkZXI6IHRoaXMub3BlbnZpZHUuZ2V0UmVjb3JkZXIoKSxcbiAgICAgICAgICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgICAgICAgICB0aGlzLm9wZW52aWR1LnNlbmRSZXF1ZXN0KCdqb2luUm9vbScsIGpvaW5QYXJhbXMsIChlcnJvciwgcmVzcG9uc2UpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghIWVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBJbml0aWFsaXplIGNhcGFiaWxpdGllcyBvYmplY3Qgd2l0aCB0aGUgcm9sZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY2FwYWJpbGl0aWVzID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdWJzY3JpYmU6IHRydWUsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHB1Ymxpc2g6IHRoaXMub3BlbnZpZHUucm9sZSAhPT0gJ1NVQlNDUklCRVInLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3JjZVVucHVibGlzaDogdGhpcy5vcGVudmlkdS5yb2xlID09PSAnTU9ERVJBVE9SJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yY2VEaXNjb25uZWN0OiB0aGlzLm9wZW52aWR1LnJvbGUgPT09ICdNT0RFUkFUT1InXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEluaXRpYWxpemUgbG9jYWwgQ29ubmVjdGlvbiBvYmplY3Qgd2l0aCB2YWx1ZXMgcmV0dXJuZWQgYnkgb3BlbnZpZHUtc2VydmVyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jb25uZWN0aW9uID0gbmV3IENvbm5lY3Rpb24odGhpcyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jb25uZWN0aW9uLmNvbm5lY3Rpb25JZCA9IHJlc3BvbnNlLmlkO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY29ubmVjdGlvbi5kYXRhID0gcmVzcG9uc2UubWV0YWRhdGE7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBJbml0aWFsaXplIHJlbW90ZSBDb25uZWN0aW9ucyB3aXRoIHZhbHVlIHJldHVybmVkIGJ5IG9wZW52aWR1LXNlcnZlclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGV2ZW50cyA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29ubmVjdGlvbnM6IG5ldyBBcnJheTxDb25uZWN0aW9uPigpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJlYW1zOiBuZXcgQXJyYXk8U3RyZWFtPigpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBleGlzdGluZ1BhcnRpY2lwYW50czogQ29ubmVjdGlvbk9wdGlvbnNbXSA9IHJlc3BvbnNlLnZhbHVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV4aXN0aW5nUGFydGljaXBhbnRzLmZvckVhY2gocGFydGljaXBhbnQgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBjb25uZWN0aW9uID0gbmV3IENvbm5lY3Rpb24odGhpcywgcGFydGljaXBhbnQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnJlbW90ZUNvbm5lY3Rpb25zW2Nvbm5lY3Rpb24uY29ubmVjdGlvbklkXSA9IGNvbm5lY3Rpb247XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV2ZW50cy5jb25uZWN0aW9ucy5wdXNoKGNvbm5lY3Rpb24pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoISFjb25uZWN0aW9uLnN0cmVhbSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5yZW1vdGVTdHJlYW1zQ3JlYXRlZFtjb25uZWN0aW9uLnN0cmVhbS5zdHJlYW1JZF0gPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXZlbnRzLnN0cmVhbXMucHVzaChjb25uZWN0aW9uLnN0cmVhbSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIE93biAnY29ubmVjdGlvbkNyZWF0ZWQnIGV2ZW50XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ2Nvbm5lY3Rpb25DcmVhdGVkJywgW25ldyBDb25uZWN0aW9uRXZlbnQoZmFsc2UsIHRoaXMsICdjb25uZWN0aW9uQ3JlYXRlZCcsIHRoaXMuY29ubmVjdGlvbiwgJycpXSk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBPbmUgJ2Nvbm5lY3Rpb25DcmVhdGVkJyBldmVudCBmb3IgZWFjaCBleGlzdGluZyBjb25uZWN0aW9uIGluIHRoZSBzZXNzaW9uXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZXZlbnRzLmNvbm5lY3Rpb25zLmZvckVhY2goY29ubmVjdGlvbiA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdjb25uZWN0aW9uQ3JlYXRlZCcsIFtuZXcgQ29ubmVjdGlvbkV2ZW50KGZhbHNlLCB0aGlzLCAnY29ubmVjdGlvbkNyZWF0ZWQnLCBjb25uZWN0aW9uLCAnJyldKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIE9uZSAnc3RyZWFtQ3JlYXRlZCcgZXZlbnQgZm9yIGVhY2ggYWN0aXZlIHN0cmVhbSBpbiB0aGUgc2Vzc2lvblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV2ZW50cy5zdHJlYW1zLmZvckVhY2goc3RyZWFtID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3N0cmVhbUNyZWF0ZWQnLCBbbmV3IFN0cmVhbUV2ZW50KGZhbHNlLCB0aGlzLCAnc3RyZWFtQ3JlYXRlZCcsIHN0cmVhbSwgJycpXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBwcml2YXRlIHN0b3BQdWJsaXNoZXJTdHJlYW0ocmVhc29uOiBzdHJpbmcpIHtcbiAgICAgICAgaWYgKCEhdGhpcy5jb25uZWN0aW9uLnN0cmVhbSkge1xuICAgICAgICAgICAgLy8gRGlzcG9zZSBQdWJsaXNoZXIncyAgbG9jYWwgc3RyZWFtXG4gICAgICAgICAgICB0aGlzLmNvbm5lY3Rpb24uc3RyZWFtLmRpc3Bvc2VXZWJSdGNQZWVyKCk7XG4gICAgICAgICAgICBpZiAodGhpcy5jb25uZWN0aW9uLnN0cmVhbS5pc0xvY2FsU3RyZWFtUHVibGlzaGVkKSB7XG4gICAgICAgICAgICAgICAgLy8gTWFrZSBQdWJsaXNoZXIgb2JqZWN0IGRpc3BhdGNoICdzdHJlYW1EZXN0cm95ZWQnIGV2ZW50IGlmIHRoZSBTdHJlYW0gd2FzIHB1Ymxpc2hlZFxuICAgICAgICAgICAgICAgIHRoaXMuY29ubmVjdGlvbi5zdHJlYW0uZWUuZW1pdEV2ZW50KCdsb2NhbC1zdHJlYW0tZGVzdHJveWVkJywgW3JlYXNvbl0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBzdHJpbmdDbGllbnRNZXRhZGF0YShtZXRhZGF0YTogYW55KTogc3RyaW5nIHtcbiAgICAgICAgaWYgKHR5cGVvZiBtZXRhZGF0YSAhPT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgIHJldHVybiBKU09OLnN0cmluZ2lmeShtZXRhZGF0YSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gbWV0YWRhdGE7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIGdldENvbm5lY3Rpb24oY29ubmVjdGlvbklkOiBzdHJpbmcsIGVycm9yTWVzc2FnZTogc3RyaW5nKTogUHJvbWlzZTxDb25uZWN0aW9uPiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZTxDb25uZWN0aW9uPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICBjb25zdCBjb25uZWN0aW9uID0gdGhpcy5yZW1vdGVDb25uZWN0aW9uc1tjb25uZWN0aW9uSWRdO1xuICAgICAgICAgICAgaWYgKCEhY29ubmVjdGlvbikge1xuICAgICAgICAgICAgICAgIC8vIFJlc29sdmUgcmVtb3RlIGNvbm5lY3Rpb25cbiAgICAgICAgICAgICAgICByZXNvbHZlKGNvbm5lY3Rpb24pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5jb25uZWN0aW9uLmNvbm5lY3Rpb25JZCA9PT0gY29ubmVjdGlvbklkKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIFJlc29sdmUgbG9jYWwgY29ubmVjdGlvblxuICAgICAgICAgICAgICAgICAgICByZXNvbHZlKHRoaXMuY29ubmVjdGlvbik7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gQ29ubmVjdGlvbiBub3QgZm91bmQuIFJlamVjdCB3aXRoIE9wZW5WaWR1RXJyb3JcbiAgICAgICAgICAgICAgICAgICAgcmVqZWN0KG5ldyBPcGVuVmlkdUVycm9yKE9wZW5WaWR1RXJyb3JOYW1lLkdFTkVSSUNfRVJST1IsIGVycm9yTWVzc2FnZSkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBnZXRSZW1vdGVDb25uZWN0aW9uKGNvbm5lY3Rpb25JZDogc3RyaW5nLCBlcnJvck1lc3NhZ2U6IHN0cmluZyk6IFByb21pc2U8Q29ubmVjdGlvbj4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2U8Q29ubmVjdGlvbj4oKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgY29uc3QgY29ubmVjdGlvbiA9IHRoaXMucmVtb3RlQ29ubmVjdGlvbnNbY29ubmVjdGlvbklkXTtcbiAgICAgICAgICAgIGlmICghIWNvbm5lY3Rpb24pIHtcbiAgICAgICAgICAgICAgICAvLyBSZXNvbHZlIHJlbW90ZSBjb25uZWN0aW9uXG4gICAgICAgICAgICAgICAgcmVzb2x2ZShjb25uZWN0aW9uKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgLy8gUmVtb3RlIGNvbm5lY3Rpb24gbm90IGZvdW5kLiBSZWplY3Qgd2l0aCBPcGVuVmlkdUVycm9yXG4gICAgICAgICAgICAgICAgcmVqZWN0KG5ldyBPcGVuVmlkdUVycm9yKE9wZW5WaWR1RXJyb3JOYW1lLkdFTkVSSUNfRVJST1IsIGVycm9yTWVzc2FnZSkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBwcml2YXRlIHByb2Nlc3NUb2tlbih0b2tlbjogc3RyaW5nKTogdm9pZCB7XG4gICAgICAgIGNvbnN0IHVybCA9IG5ldyBVUkwodG9rZW4pO1xuICAgICAgICB0aGlzLnNlc3Npb25JZCA9IDxzdHJpbmc+dXJsLnNlYXJjaFBhcmFtcy5nZXQoJ3Nlc3Npb25JZCcpO1xuICAgICAgICBjb25zdCBzZWNyZXQgPSB1cmwuc2VhcmNoUGFyYW1zLmdldCgnc2VjcmV0Jyk7XG4gICAgICAgIGNvbnN0IHJlY29yZGVyID0gdXJsLnNlYXJjaFBhcmFtcy5nZXQoJ3JlY29yZGVyJyk7XG4gICAgICAgIGNvbnN0IHR1cm5Vc2VybmFtZSA9IHVybC5zZWFyY2hQYXJhbXMuZ2V0KCd0dXJuVXNlcm5hbWUnKTtcbiAgICAgICAgY29uc3QgdHVybkNyZWRlbnRpYWwgPSB1cmwuc2VhcmNoUGFyYW1zLmdldCgndHVybkNyZWRlbnRpYWwnKTtcbiAgICAgICAgY29uc3Qgcm9sZSA9IHVybC5zZWFyY2hQYXJhbXMuZ2V0KCdyb2xlJyk7XG5cbiAgICAgICAgaWYgKCEhc2VjcmV0KSB7XG4gICAgICAgICAgICB0aGlzLm9wZW52aWR1LnNlY3JldCA9IHNlY3JldDtcbiAgICAgICAgfVxuICAgICAgICBpZiAoISFyZWNvcmRlcikge1xuICAgICAgICAgICAgdGhpcy5vcGVudmlkdS5yZWNvcmRlciA9IHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCEhdHVyblVzZXJuYW1lICYmICEhdHVybkNyZWRlbnRpYWwpIHtcbiAgICAgICAgICAgIGNvbnN0IHN0dW5VcmwgPSAnc3R1bjonICsgdXJsLmhvc3RuYW1lICsgJzozNDc4JztcbiAgICAgICAgICAgIGNvbnN0IHR1cm5VcmwxID0gJ3R1cm46JyArIHVybC5ob3N0bmFtZSArICc6MzQ3OCc7XG4gICAgICAgICAgICBjb25zdCB0dXJuVXJsMiA9IHR1cm5VcmwxICsgJz90cmFuc3BvcnQ9dGNwJztcbiAgICAgICAgICAgIHRoaXMub3BlbnZpZHUuaWNlU2VydmVycyA9IFtcbiAgICAgICAgICAgICAgICB7IHVybHM6IFtzdHVuVXJsXSB9LFxuICAgICAgICAgICAgICAgIHsgdXJsczogW3R1cm5VcmwxLCB0dXJuVXJsMl0sIHVzZXJuYW1lOiB0dXJuVXNlcm5hbWUsIGNyZWRlbnRpYWw6IHR1cm5DcmVkZW50aWFsIH1cbiAgICAgICAgICAgIF07XG4gICAgICAgICAgICBjb25zb2xlLmxvZygnVFVSTiB0ZW1wIGNyZWRlbnRpYWxzIFsnICsgdHVyblVzZXJuYW1lICsgJzonICsgdHVybkNyZWRlbnRpYWwgKyAnXScpO1xuICAgICAgICB9XG4gICAgICAgIGlmICghIXJvbGUpIHtcbiAgICAgICAgICAgIHRoaXMub3BlbnZpZHUucm9sZSA9IHJvbGU7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLm9wZW52aWR1LndzVXJpID0gJ3dzczovLycgKyB1cmwuaG9zdCArICcvb3BlbnZpZHUnO1xuICAgIH1cblxufSIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTctMjAxOCBPcGVuVmlkdSAoaHR0cHM6Ly9vcGVudmlkdS5pby8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuaW1wb3J0IHsgQ29ubmVjdGlvbiB9IGZyb20gJy4vQ29ubmVjdGlvbic7XG5pbXBvcnQgeyBTZXNzaW9uIH0gZnJvbSAnLi9TZXNzaW9uJztcbmltcG9ydCB7IFN0cmVhbU1hbmFnZXIgfSBmcm9tICcuL1N0cmVhbU1hbmFnZXInO1xuaW1wb3J0IHsgSW5ib3VuZFN0cmVhbU9wdGlvbnMgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHJpdmF0ZS9JbmJvdW5kU3RyZWFtT3B0aW9ucyc7XG5pbXBvcnQgeyBPdXRib3VuZFN0cmVhbU9wdGlvbnMgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHJpdmF0ZS9PdXRib3VuZFN0cmVhbU9wdGlvbnMnO1xuaW1wb3J0IHsgV2ViUnRjUGVlciwgV2ViUnRjUGVlclNlbmRvbmx5LCBXZWJSdGNQZWVyUmVjdm9ubHksIFdlYlJ0Y1BlZXJTZW5kcmVjdiB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvV2ViUnRjUGVlci9XZWJSdGNQZWVyJztcbmltcG9ydCB7IFdlYlJ0Y1N0YXRzIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9XZWJSdGNTdGF0cy9XZWJSdGNTdGF0cyc7XG5pbXBvcnQgeyBQdWJsaXNoZXJTcGVha2luZ0V2ZW50IH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvUHVibGlzaGVyU3BlYWtpbmdFdmVudCc7XG5cbmltcG9ydCBFdmVudEVtaXR0ZXIgPSByZXF1aXJlKCd3b2xmeTg3LWV2ZW50ZW1pdHRlcicpO1xuaW1wb3J0IGhhcmsgPSByZXF1aXJlKCdoYXJrJyk7XG5pbXBvcnQgeyBPcGVuVmlkdUVycm9yLCBPcGVuVmlkdUVycm9yTmFtZSB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRW51bXMvT3BlblZpZHVFcnJvcic7XG5cblxuLyoqXG4gKiBSZXByZXNlbnRzIGVhY2ggb25lIG9mIHRoZSBtZWRpYSBzdHJlYW1zIGF2YWlsYWJsZSBpbiBPcGVuVmlkdSBTZXJ2ZXIgZm9yIGNlcnRhaW4gc2Vzc2lvbi5cbiAqIEVhY2ggW1tQdWJsaXNoZXJdXSBhbmQgW1tTdWJzY3JpYmVyXV0gaGFzIGFuIGF0dHJpYnV0ZSBvZiB0eXBlIFN0cmVhbSwgYXMgdGhleSBnaXZlIGFjY2Vzc1xuICogdG8gb25lIG9mIHRoZW0gKHNlbmRpbmcgYW5kIHJlY2VpdmluZyBpdCwgcmVzcGVjdGl2ZWx5KVxuICovXG5leHBvcnQgY2xhc3MgU3RyZWFtIHtcblxuICAgIC8qKlxuICAgICAqIFRoZSBDb25uZWN0aW9uIG9iamVjdCB0aGF0IGlzIHB1Ymxpc2hpbmcgdGhlIHN0cmVhbVxuICAgICAqL1xuICAgIGNvbm5lY3Rpb246IENvbm5lY3Rpb247XG5cbiAgICAvKipcbiAgICAgKiBGcmFtZSByYXRlIG9mIHRoZSB2aWRlbyBpbiBmcmFtZXMgcGVyIHNlY29uZC4gVGhpcyBwcm9wZXJ0eSBpcyBvbmx5IGRlZmluZWQgaWYgdGhlIFtbUHVibGlzaGVyXV0gb2ZcbiAgICAgKiB0aGUgc3RyZWFtIHdhcyBpbml0aWFsaXplZCBwYXNzaW5nIGEgX2ZyYW1lUmF0ZV8gcHJvcGVydHkgb24gW1tPcGVuVmlkdS5pbml0UHVibGlzaGVyXV0gbWV0aG9kXG4gICAgICovXG4gICAgZnJhbWVSYXRlPzogbnVtYmVyO1xuXG4gICAgLyoqXG4gICAgICogV2hldGhlciB0aGUgc3RyZWFtIGhhcyBhIHZpZGVvIHRyYWNrIG9yIG5vdFxuICAgICAqL1xuICAgIGhhc1ZpZGVvOiBib29sZWFuO1xuXG4gICAgLyoqXG4gICAgICogV2hldGhlciB0aGUgc3RyZWFtIGhhcyBhbiBhdWRpbyB0cmFjayBvciBub3RcbiAgICAgKi9cbiAgICBoYXNBdWRpbzogYm9vbGVhbjtcblxuICAgIC8qKlxuICAgICAqIFdoZXRoZXIgdGhlIHN0cmVhbSBoYXMgdGhlIHZpZGVvIHRyYWNrIG11dGVkIG9yIHVubXV0ZWQuIElmIFtbaGFzVmlkZW9dXSBpcyBmYWxzZSwgdGhpcyBwcm9wZXJ0eSBpcyB1bmRlZmluZWQuXG4gICAgICpcbiAgICAgKiBUaGlzIHByb3BlcnR5IG1heSBjaGFuZ2UgaWYgdGhlIFB1Ymxpc2hlciBwdWJsaXNoaW5nIHRoZSBzdHJlYW0gY2FsbHMgW1tQdWJsaXNoZXIucHVibGlzaFZpZGVvXV0uIFdoZW5ldmVyIHRoaXMgaGFwcGVucyBhIFtbU3RyZWFtUHJvcGVydHlDaGFuZ2VkRXZlbnRdXSB3aWxsIGJlIGRpc3BhdGNoZWRcbiAgICAgKiBieSB0aGUgU2Vzc2lvbiBvYmplY3QgYXMgd2VsbCBhcyBieSB0aGUgYWZmZWN0ZWQgU3Vic2NyaWJlci9QdWJsaXNoZXIgb2JqZWN0XG4gICAgICovXG4gICAgdmlkZW9BY3RpdmU6IGJvb2xlYW47XG5cbiAgICAvKipcbiAgICAgKiBXaGV0aGVyIHRoZSBzdHJlYW0gaGFzIHRoZSBhdWRpbyB0cmFjayBtdXRlZCBvciB1bm11dGVkLiBJZiBbW2hhc0F1ZGlvXV0gaXMgZmFsc2UsIHRoaXMgcHJvcGVydHkgaXMgdW5kZWZpbmVkXG4gICAgICpcbiAgICAgKiBUaGlzIHByb3BlcnR5IG1heSBjaGFuZ2UgaWYgdGhlIFB1Ymxpc2hlciBwdWJsaXNoaW5nIHRoZSBzdHJlYW0gY2FsbHMgW1tQdWJsaXNoZXIucHVibGlzaEF1ZGlvXV0uIFdoZW5ldmVyIHRoaXMgaGFwcGVucyBhIFtbU3RyZWFtUHJvcGVydHlDaGFuZ2VkRXZlbnRdXSB3aWxsIGJlIGRpc3BhdGNoZWRcbiAgICAgKiBieSB0aGUgU2Vzc2lvbiBvYmplY3QgYXMgd2VsbCBhcyBieSB0aGUgYWZmZWN0ZWQgU3Vic2NyaWJlci9QdWJsaXNoZXIgb2JqZWN0XG4gICAgICovXG4gICAgYXVkaW9BY3RpdmU6IGJvb2xlYW47XG5cbiAgICAvKipcbiAgICAgKiBVbmlxdWUgaWRlbnRpZmllciBvZiB0aGUgc3RyZWFtXG4gICAgICovXG4gICAgc3RyZWFtSWQ6IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIGBcIkNBTUVSQVwiYCwgYFwiU0NSRUVOXCJgIG9yIGBcIkNVU1RPTVwiYCAodGhlIGxhdHRlciB3aGVuIFtbUHVibGlzaGVyUHJvcGVydGllcy52aWRlb1NvdXJjZV1dIGlzIGEgTWVkaWFTdHJlYW1UcmFjayB3aGVuIGNhbGxpbmcgW1tPcGVuVmlkdS5pbml0UHVibGlzaGVyXV0pLlxuICAgICAqIElmIFtbaGFzVmlkZW9dXSBpcyBmYWxzZSwgdGhpcyBwcm9wZXJ0eSBpcyB1bmRlZmluZWRcbiAgICAgKi9cbiAgICB0eXBlT2ZWaWRlbz86IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIFN0cmVhbU1hbmFnZXIgb2JqZWN0IChbW1B1Ymxpc2hlcl1dIG9yIFtbU3Vic2NyaWJlcl1dKSBpbiBjaGFyZ2Ugb2YgZGlzcGxheWluZyB0aGlzIHN0cmVhbSBpbiB0aGUgRE9NXG4gICAgICovXG4gICAgc3RyZWFtTWFuYWdlcjogU3RyZWFtTWFuYWdlcjtcblxuICAgIC8qKlxuICAgICAqIFdpZHRoIGFuZCBoZWlnaHQgaW4gcGl4ZWxzIG9mIHRoZSBlbmNvZGVkIHZpZGVvIHN0cmVhbS4gSWYgW1toYXNWaWRlb11dIGlzIGZhbHNlLCB0aGlzIHByb3BlcnR5IGlzIHVuZGVmaW5lZFxuICAgICAqXG4gICAgICogVGhpcyBwcm9wZXJ0eSBtYXkgY2hhbmdlIGlmIHRoZSBQdWJsaXNoZXIgdGhhdCBpcyBwdWJsaXNoaW5nOlxuICAgICAqIC0gSWYgaXQgaXMgYSBtb2JpbGUgZGV2aWNlLCB3aGVuZXZlciB0aGUgdXNlciByb3RhdGVzIHRoZSBkZXZpY2UuXG4gICAgICogLSBJZiBpdCBpcyBzY3JlZW4tc2hhcmluZywgd2hlbmV2ZXIgdGhlIHVzZXIgY2hhbmdlcyB0aGUgc2l6ZSBvZiB0aGUgY2FwdHVyZWQgd2luZG93LlxuICAgICAqXG4gICAgICogV2hlbmV2ZXIgdGhpcyBoYXBwZW5zIGEgW1tTdHJlYW1Qcm9wZXJ0eUNoYW5nZWRFdmVudF1dIHdpbGwgYmUgZGlzcGF0Y2hlZCBieSB0aGUgU2Vzc2lvbiBvYmplY3QgYXMgd2VsbCBhcyBieSB0aGUgYWZmZWN0ZWQgU3Vic2NyaWJlci9QdWJsaXNoZXIgb2JqZWN0XG4gICAgICovXG4gICAgdmlkZW9EaW1lbnNpb25zOiB7IHdpZHRoOiBudW1iZXIsIGhlaWdodDogbnVtYmVyIH07XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgZWUgPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG5cbiAgICBwcml2YXRlIHdlYlJ0Y1BlZXI6IFdlYlJ0Y1BlZXI7XG4gICAgcHJpdmF0ZSBtZWRpYVN0cmVhbTogTWVkaWFTdHJlYW07XG4gICAgcHJpdmF0ZSB3ZWJSdGNTdGF0czogV2ViUnRjU3RhdHM7XG5cbiAgICBwcml2YXRlIGlzU3Vic2NyaWJlVG9SZW1vdGUgPSBmYWxzZTtcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBpc0xvY2FsU3RyZWFtUmVhZHlUb1B1Ymxpc2ggPSBmYWxzZTtcbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgaXNMb2NhbFN0cmVhbVB1Ymxpc2hlZCA9IGZhbHNlO1xuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBwdWJsaXNoZWRPbmNlID0gZmFsc2U7XG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHNlc3Npb246IFNlc3Npb247XG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGluYm91bmRTdHJlYW1PcHRzOiBJbmJvdW5kU3RyZWFtT3B0aW9ucztcbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgb3V0Ym91bmRTdHJlYW1PcHRzOiBPdXRib3VuZFN0cmVhbU9wdGlvbnM7XG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHNwZWVjaEV2ZW50OiBhbnk7XG5cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3RvcihzZXNzaW9uOiBTZXNzaW9uLCBvcHRpb25zOiBJbmJvdW5kU3RyZWFtT3B0aW9ucyB8IE91dGJvdW5kU3RyZWFtT3B0aW9ucyB8IHt9KSB7XG5cbiAgICAgICAgdGhpcy5zZXNzaW9uID0gc2Vzc2lvbjtcblxuICAgICAgICBpZiAob3B0aW9ucy5oYXNPd25Qcm9wZXJ0eSgnaWQnKSkge1xuICAgICAgICAgICAgLy8gSW5ib3VuZFN0cmVhbU9wdGlvbnM6IHN0cmVhbSBiZWxvbmdzIHRvIGEgU3Vic2NyaWJlclxuICAgICAgICAgICAgdGhpcy5pbmJvdW5kU3RyZWFtT3B0cyA9IDxJbmJvdW5kU3RyZWFtT3B0aW9ucz5vcHRpb25zO1xuICAgICAgICAgICAgdGhpcy5zdHJlYW1JZCA9IHRoaXMuaW5ib3VuZFN0cmVhbU9wdHMuaWQ7XG4gICAgICAgICAgICB0aGlzLmhhc0F1ZGlvID0gdGhpcy5pbmJvdW5kU3RyZWFtT3B0cy5oYXNBdWRpbztcbiAgICAgICAgICAgIHRoaXMuaGFzVmlkZW8gPSB0aGlzLmluYm91bmRTdHJlYW1PcHRzLmhhc1ZpZGVvO1xuICAgICAgICAgICAgaWYgKHRoaXMuaGFzQXVkaW8pIHtcbiAgICAgICAgICAgICAgICB0aGlzLmF1ZGlvQWN0aXZlID0gdGhpcy5pbmJvdW5kU3RyZWFtT3B0cy5hdWRpb0FjdGl2ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0aGlzLmhhc1ZpZGVvKSB7XG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb0FjdGl2ZSA9IHRoaXMuaW5ib3VuZFN0cmVhbU9wdHMudmlkZW9BY3RpdmU7XG4gICAgICAgICAgICAgICAgdGhpcy50eXBlT2ZWaWRlbyA9ICghdGhpcy5pbmJvdW5kU3RyZWFtT3B0cy50eXBlT2ZWaWRlbykgPyB1bmRlZmluZWQgOiB0aGlzLmluYm91bmRTdHJlYW1PcHRzLnR5cGVPZlZpZGVvO1xuICAgICAgICAgICAgICAgIHRoaXMuZnJhbWVSYXRlID0gKHRoaXMuaW5ib3VuZFN0cmVhbU9wdHMuZnJhbWVSYXRlID09PSAtMSkgPyB1bmRlZmluZWQgOiB0aGlzLmluYm91bmRTdHJlYW1PcHRzLmZyYW1lUmF0ZTtcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvRGltZW5zaW9ucyA9IHRoaXMuaW5ib3VuZFN0cmVhbU9wdHMudmlkZW9EaW1lbnNpb25zO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gT3V0Ym91bmRTdHJlYW1PcHRpb25zOiBzdHJlYW0gYmVsb25ncyB0byBhIFB1Ymxpc2hlclxuICAgICAgICAgICAgdGhpcy5vdXRib3VuZFN0cmVhbU9wdHMgPSA8T3V0Ym91bmRTdHJlYW1PcHRpb25zPm9wdGlvbnM7XG5cbiAgICAgICAgICAgIHRoaXMuaGFzQXVkaW8gPSB0aGlzLmlzU2VuZEF1ZGlvKCk7XG4gICAgICAgICAgICB0aGlzLmhhc1ZpZGVvID0gdGhpcy5pc1NlbmRWaWRlbygpO1xuXG4gICAgICAgICAgICBpZiAodGhpcy5oYXNBdWRpbykge1xuICAgICAgICAgICAgICAgIHRoaXMuYXVkaW9BY3RpdmUgPSAhIXRoaXMub3V0Ym91bmRTdHJlYW1PcHRzLnB1Ymxpc2hlclByb3BlcnRpZXMucHVibGlzaEF1ZGlvO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRoaXMuaGFzVmlkZW8pIHtcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvQWN0aXZlID0gISF0aGlzLm91dGJvdW5kU3RyZWFtT3B0cy5wdWJsaXNoZXJQcm9wZXJ0aWVzLnB1Ymxpc2hWaWRlbztcbiAgICAgICAgICAgICAgICB0aGlzLmZyYW1lUmF0ZSA9IHRoaXMub3V0Ym91bmRTdHJlYW1PcHRzLnB1Ymxpc2hlclByb3BlcnRpZXMuZnJhbWVSYXRlO1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLm91dGJvdW5kU3RyZWFtT3B0cy5wdWJsaXNoZXJQcm9wZXJ0aWVzLnZpZGVvU291cmNlIGluc3RhbmNlb2YgTWVkaWFTdHJlYW1UcmFjaykge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnR5cGVPZlZpZGVvID0gJ0NVU1RPTSc7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy50eXBlT2ZWaWRlbyA9IHRoaXMuaXNTZW5kU2NyZWVuKCkgPyAnU0NSRUVOJyA6ICdDQU1FUkEnO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuZWUub24oJ21lZGlhc3RyZWFtLXVwZGF0ZWQnLCAoKSA9PiB7XG4gICAgICAgICAgICB0aGlzLnN0cmVhbU1hbmFnZXIudXBkYXRlTWVkaWFTdHJlYW0odGhpcy5tZWRpYVN0cmVhbSk7XG4gICAgICAgICAgICBjb25zb2xlLmRlYnVnKCdWaWRlbyBzcmNPYmplY3QgWycgKyB0aGlzLm1lZGlhU3RyZWFtICsgJ10gdXBkYXRlZCBpbiBzdHJlYW0gWycgKyB0aGlzLnN0cmVhbUlkICsgJ10nKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG5cbiAgICAvKiBIaWRkZW4gbWV0aG9kcyAqL1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGdldE1lZGlhU3RyZWFtKCk6IE1lZGlhU3RyZWFtIHtcbiAgICAgICAgcmV0dXJuIHRoaXMubWVkaWFTdHJlYW07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHNldE1lZGlhU3RyZWFtKG1lZGlhU3RyZWFtOiBNZWRpYVN0cmVhbSk6IHZvaWQge1xuICAgICAgICB0aGlzLm1lZGlhU3RyZWFtID0gbWVkaWFTdHJlYW07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHVwZGF0ZU1lZGlhU3RyZWFtSW5WaWRlb3MoKSB7XG4gICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdtZWRpYXN0cmVhbS11cGRhdGVkJyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGdldFdlYlJ0Y1BlZXIoKTogV2ViUnRjUGVlciB7XG4gICAgICAgIHJldHVybiB0aGlzLndlYlJ0Y1BlZXI7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGdldFJUQ1BlZXJDb25uZWN0aW9uKCk6IFJUQ1BlZXJDb25uZWN0aW9uIHtcbiAgICAgICAgcmV0dXJuIHRoaXMud2ViUnRjUGVlci5wYztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgc3Vic2NyaWJlVG9NeVJlbW90ZSh2YWx1ZTogYm9vbGVhbik6IHZvaWQge1xuICAgICAgICB0aGlzLmlzU3Vic2NyaWJlVG9SZW1vdGUgPSB2YWx1ZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgc2V0T3V0Ym91bmRTdHJlYW1PcHRpb25zKG91dGJvdW5kU3RyZWFtT3B0czogT3V0Ym91bmRTdHJlYW1PcHRpb25zKTogdm9pZCB7XG4gICAgICAgIHRoaXMub3V0Ym91bmRTdHJlYW1PcHRzID0gb3V0Ym91bmRTdHJlYW1PcHRzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBzdWJzY3JpYmUoKTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIHRoaXMuaW5pdFdlYlJ0Y1BlZXJSZWNlaXZlKClcbiAgICAgICAgICAgICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBwdWJsaXNoKCk6IFByb21pc2U8YW55PiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICBpZiAodGhpcy5pc0xvY2FsU3RyZWFtUmVhZHlUb1B1Ymxpc2gpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmluaXRXZWJSdGNQZWVyU2VuZCgpXG4gICAgICAgICAgICAgICAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLm9uY2UoJ3N0cmVhbS1yZWFkeS10by1wdWJsaXNoJywgKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnB1Ymxpc2goKVxuICAgICAgICAgICAgICAgICAgICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgICAgICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGRpc3Bvc2VXZWJSdGNQZWVyKCk6IHZvaWQge1xuICAgICAgICBpZiAodGhpcy53ZWJSdGNQZWVyKSB7XG4gICAgICAgICAgICB0aGlzLndlYlJ0Y1BlZXIuZGlzcG9zZSgpO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLnNwZWVjaEV2ZW50KSB7XG4gICAgICAgICAgICB0aGlzLnNwZWVjaEV2ZW50LnN0b3AoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuc3RvcFdlYlJ0Y1N0YXRzKCk7XG5cbiAgICAgICAgY29uc29sZS5pbmZvKCghIXRoaXMub3V0Ym91bmRTdHJlYW1PcHRzID8gJ091dGJvdW5kICcgOiAnSW5ib3VuZCAnKSArIFwiV2ViUlRDUGVlciBmcm9tICdTdHJlYW0nIHdpdGggaWQgW1wiICsgdGhpcy5zdHJlYW1JZCArICddIGlzIG5vdyBjbG9zZWQnKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgZGlzcG9zZU1lZGlhU3RyZWFtKCk6IHZvaWQge1xuICAgICAgICBpZiAodGhpcy5tZWRpYVN0cmVhbSkge1xuICAgICAgICAgICAgdGhpcy5tZWRpYVN0cmVhbS5nZXRBdWRpb1RyYWNrcygpLmZvckVhY2goKHRyYWNrKSA9PiB7XG4gICAgICAgICAgICAgICAgdHJhY2suc3RvcCgpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB0aGlzLm1lZGlhU3RyZWFtLmdldFZpZGVvVHJhY2tzKCkuZm9yRWFjaCgodHJhY2spID0+IHtcbiAgICAgICAgICAgICAgICB0cmFjay5zdG9wKCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGRlbGV0ZSB0aGlzLm1lZGlhU3RyZWFtO1xuICAgICAgICB9XG4gICAgICAgIGNvbnNvbGUuaW5mbygoISF0aGlzLm91dGJvdW5kU3RyZWFtT3B0cyA/ICdMb2NhbCAnIDogJ1JlbW90ZSAnKSArIFwiTWVkaWFTdHJlYW0gZnJvbSAnU3RyZWFtJyB3aXRoIGlkIFtcIiArIHRoaXMuc3RyZWFtSWQgKyAnXSBpcyBub3cgZGlzcG9zZWQnKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgZGlzcGxheU15UmVtb3RlKCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gdGhpcy5pc1N1YnNjcmliZVRvUmVtb3RlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBpc1NlbmRBdWRpbygpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuICghIXRoaXMub3V0Ym91bmRTdHJlYW1PcHRzICYmXG4gICAgICAgICAgICB0aGlzLm91dGJvdW5kU3RyZWFtT3B0cy5wdWJsaXNoZXJQcm9wZXJ0aWVzLmF1ZGlvU291cmNlICE9PSBudWxsICYmXG4gICAgICAgICAgICB0aGlzLm91dGJvdW5kU3RyZWFtT3B0cy5wdWJsaXNoZXJQcm9wZXJ0aWVzLmF1ZGlvU291cmNlICE9PSBmYWxzZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGlzU2VuZFZpZGVvKCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gKCEhdGhpcy5vdXRib3VuZFN0cmVhbU9wdHMgJiZcbiAgICAgICAgICAgIHRoaXMub3V0Ym91bmRTdHJlYW1PcHRzLnB1Ymxpc2hlclByb3BlcnRpZXMudmlkZW9Tb3VyY2UgIT09IG51bGwgJiZcbiAgICAgICAgICAgIHRoaXMub3V0Ym91bmRTdHJlYW1PcHRzLnB1Ymxpc2hlclByb3BlcnRpZXMudmlkZW9Tb3VyY2UgIT09IGZhbHNlKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgaXNTZW5kU2NyZWVuKCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gKCEhdGhpcy5vdXRib3VuZFN0cmVhbU9wdHMgJiZcbiAgICAgICAgICAgIHRoaXMub3V0Ym91bmRTdHJlYW1PcHRzLnB1Ymxpc2hlclByb3BlcnRpZXMudmlkZW9Tb3VyY2UgPT09ICdzY3JlZW4nKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgc2V0U3BlZWNoRXZlbnRJZk5vdEV4aXN0cygpOiB2b2lkIHtcbiAgICAgICAgaWYgKCF0aGlzLnNwZWVjaEV2ZW50KSB7XG4gICAgICAgICAgICBjb25zdCBoYXJrT3B0aW9ucyA9IHRoaXMuc2Vzc2lvbi5vcGVudmlkdS5hZHZhbmNlZENvbmZpZ3VyYXRpb24ucHVibGlzaGVyU3BlYWtpbmdFdmVudHNPcHRpb25zIHx8IHt9O1xuICAgICAgICAgICAgaGFya09wdGlvbnMuaW50ZXJ2YWwgPSAodHlwZW9mIGhhcmtPcHRpb25zLmludGVydmFsID09PSAnbnVtYmVyJykgPyBoYXJrT3B0aW9ucy5pbnRlcnZhbCA6IDUwO1xuICAgICAgICAgICAgaGFya09wdGlvbnMudGhyZXNob2xkID0gKHR5cGVvZiBoYXJrT3B0aW9ucy50aHJlc2hvbGQgPT09ICdudW1iZXInKSA/IGhhcmtPcHRpb25zLnRocmVzaG9sZCA6IC01MDtcblxuICAgICAgICAgICAgdGhpcy5zcGVlY2hFdmVudCA9IGhhcmsodGhpcy5tZWRpYVN0cmVhbSwgaGFya09wdGlvbnMpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGVuYWJsZVNwZWFraW5nRXZlbnRzKCk6IHZvaWQge1xuICAgICAgICB0aGlzLnNldFNwZWVjaEV2ZW50SWZOb3RFeGlzdHMoKTtcbiAgICAgICAgdGhpcy5zcGVlY2hFdmVudC5vbignc3BlYWtpbmcnLCAoKSA9PiB7XG4gICAgICAgICAgICB0aGlzLnNlc3Npb24uZW1pdEV2ZW50KCdwdWJsaXNoZXJTdGFydFNwZWFraW5nJywgW25ldyBQdWJsaXNoZXJTcGVha2luZ0V2ZW50KHRoaXMuc2Vzc2lvbiwgJ3B1Ymxpc2hlclN0YXJ0U3BlYWtpbmcnLCB0aGlzLmNvbm5lY3Rpb24sIHRoaXMuc3RyZWFtSWQpXSk7XG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLnNwZWVjaEV2ZW50Lm9uKCdzdG9wcGVkX3NwZWFraW5nJywgKCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5zZXNzaW9uLmVtaXRFdmVudCgncHVibGlzaGVyU3RvcFNwZWFraW5nJywgW25ldyBQdWJsaXNoZXJTcGVha2luZ0V2ZW50KHRoaXMuc2Vzc2lvbiwgJ3B1Ymxpc2hlclN0b3BTcGVha2luZycsIHRoaXMuY29ubmVjdGlvbiwgdGhpcy5zdHJlYW1JZCldKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGVuYWJsZU9uY2VTcGVha2luZ0V2ZW50cygpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5zZXRTcGVlY2hFdmVudElmTm90RXhpc3RzKCk7XG4gICAgICAgIHRoaXMuc3BlZWNoRXZlbnQub24oJ3NwZWFraW5nJywgKCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5zZXNzaW9uLmVtaXRFdmVudCgncHVibGlzaGVyU3RhcnRTcGVha2luZycsIFtuZXcgUHVibGlzaGVyU3BlYWtpbmdFdmVudCh0aGlzLnNlc3Npb24sICdwdWJsaXNoZXJTdGFydFNwZWFraW5nJywgdGhpcy5jb25uZWN0aW9uLCB0aGlzLnN0cmVhbUlkKV0pO1xuICAgICAgICAgICAgdGhpcy5kaXNhYmxlU3BlYWtpbmdFdmVudHMoKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMuc3BlZWNoRXZlbnQub24oJ3N0b3BwZWRfc3BlYWtpbmcnLCAoKSA9PiB7XG4gICAgICAgICAgICB0aGlzLnNlc3Npb24uZW1pdEV2ZW50KCdwdWJsaXNoZXJTdG9wU3BlYWtpbmcnLCBbbmV3IFB1Ymxpc2hlclNwZWFraW5nRXZlbnQodGhpcy5zZXNzaW9uLCAncHVibGlzaGVyU3RvcFNwZWFraW5nJywgdGhpcy5jb25uZWN0aW9uLCB0aGlzLnN0cmVhbUlkKV0pO1xuICAgICAgICAgICAgdGhpcy5kaXNhYmxlU3BlYWtpbmdFdmVudHMoKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGRpc2FibGVTcGVha2luZ0V2ZW50cygpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5zcGVlY2hFdmVudC5zdG9wKCk7XG4gICAgICAgIHRoaXMuc3BlZWNoRXZlbnQgPSB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGlzTG9jYWwoKTogYm9vbGVhbiB7XG4gICAgICAgIC8vIGluYm91bmQgb3B0aW9ucyB1bmRlZmluZWQgYW5kIG91dGJvdW5kIG9wdGlvbnMgZGVmaW5lZFxuICAgICAgICByZXR1cm4gKCF0aGlzLmluYm91bmRTdHJlYW1PcHRzICYmICEhdGhpcy5vdXRib3VuZFN0cmVhbU9wdHMpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBnZXRTZWxlY3RlZEljZUNhbmRpZGF0ZSgpOiBQcm9taXNlPGFueT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgdGhpcy53ZWJSdGNTdGF0cy5nZXRTZWxlY3RlZEljZUNhbmRpZGF0ZUluZm8oKVxuICAgICAgICAgICAgICAgIC50aGVuKHJlcG9ydCA9PiByZXNvbHZlKHJlcG9ydCkpXG4gICAgICAgICAgICAgICAgLmNhdGNoKGVycm9yID0+IHJlamVjdChlcnJvcikpO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgZ2V0UmVtb3RlSWNlQ2FuZGlkYXRlTGlzdCgpOiBSVENJY2VDYW5kaWRhdGVbXSB7XG4gICAgICAgIHJldHVybiB0aGlzLndlYlJ0Y1BlZXIucmVtb3RlQ2FuZGlkYXRlc1F1ZXVlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBnZXRMb2NhbEljZUNhbmRpZGF0ZUxpc3QoKTogUlRDSWNlQ2FuZGlkYXRlW10ge1xuICAgICAgICByZXR1cm4gdGhpcy53ZWJSdGNQZWVyLmxvY2FsQ2FuZGlkYXRlc1F1ZXVlO1xuICAgIH1cblxuICAgIC8qIFByaXZhdGUgbWV0aG9kcyAqL1xuXG4gICAgcHJpdmF0ZSBpbml0V2ViUnRjUGVlclNlbmQoKTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcblxuICAgICAgICAgICAgY29uc3QgdXNlck1lZGlhQ29uc3RyYWludHMgPSB7XG4gICAgICAgICAgICAgICAgYXVkaW86IHRoaXMuaXNTZW5kQXVkaW8oKSxcbiAgICAgICAgICAgICAgICB2aWRlbzogdGhpcy5pc1NlbmRWaWRlbygpXG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICBjb25zdCBvcHRpb25zID0ge1xuICAgICAgICAgICAgICAgIG1lZGlhU3RyZWFtOiB0aGlzLm1lZGlhU3RyZWFtLFxuICAgICAgICAgICAgICAgIG1lZGlhQ29uc3RyYWludHM6IHVzZXJNZWRpYUNvbnN0cmFpbnRzLFxuICAgICAgICAgICAgICAgIG9uaWNlY2FuZGlkYXRlOiB0aGlzLmNvbm5lY3Rpb24uc2VuZEljZUNhbmRpZGF0ZS5iaW5kKHRoaXMuY29ubmVjdGlvbiksXG4gICAgICAgICAgICAgICAgaWNlU2VydmVyczogdGhpcy5nZXRJY2VTZXJ2ZXJzQ29uZigpLFxuICAgICAgICAgICAgICAgIHNpbXVsY2FzdDogZmFsc2VcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIGNvbnN0IHN1Y2Nlc3NDYWxsYmFjayA9IChzZHBPZmZlclBhcmFtKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5kZWJ1ZygnU2VuZGluZyBTRFAgb2ZmZXIgdG8gcHVibGlzaCBhcyAnXG4gICAgICAgICAgICAgICAgICAgICsgdGhpcy5zdHJlYW1JZCwgc2RwT2ZmZXJQYXJhbSk7XG5cbiAgICAgICAgICAgICAgICBsZXQgdHlwZU9mVmlkZW8gPSAnJztcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5pc1NlbmRWaWRlbygpKSB7XG4gICAgICAgICAgICAgICAgICAgIHR5cGVPZlZpZGVvID0gdGhpcy5vdXRib3VuZFN0cmVhbU9wdHMucHVibGlzaGVyUHJvcGVydGllcy52aWRlb1NvdXJjZSBpbnN0YW5jZW9mIE1lZGlhU3RyZWFtVHJhY2sgPyAnQ1VTVE9NJyA6ICh0aGlzLmlzU2VuZFNjcmVlbigpID8gJ1NDUkVFTicgOiAnQ0FNRVJBJyk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdGhpcy5zZXNzaW9uLm9wZW52aWR1LnNlbmRSZXF1ZXN0KCdwdWJsaXNoVmlkZW8nLCB7XG4gICAgICAgICAgICAgICAgICAgIHNkcE9mZmVyOiBzZHBPZmZlclBhcmFtLFxuICAgICAgICAgICAgICAgICAgICBkb0xvb3BiYWNrOiB0aGlzLmRpc3BsYXlNeVJlbW90ZSgpIHx8IGZhbHNlLFxuICAgICAgICAgICAgICAgICAgICBoYXNBdWRpbzogdGhpcy5pc1NlbmRBdWRpbygpLFxuICAgICAgICAgICAgICAgICAgICBoYXNWaWRlbzogdGhpcy5pc1NlbmRWaWRlbygpLFxuICAgICAgICAgICAgICAgICAgICBhdWRpb0FjdGl2ZTogdGhpcy5hdWRpb0FjdGl2ZSxcbiAgICAgICAgICAgICAgICAgICAgdmlkZW9BY3RpdmU6IHRoaXMudmlkZW9BY3RpdmUsXG4gICAgICAgICAgICAgICAgICAgIHR5cGVPZlZpZGVvLFxuICAgICAgICAgICAgICAgICAgICBmcmFtZVJhdGU6ICEhdGhpcy5mcmFtZVJhdGUgPyB0aGlzLmZyYW1lUmF0ZSA6IC0xLFxuICAgICAgICAgICAgICAgICAgICB2aWRlb0RpbWVuc2lvbnM6IEpTT04uc3RyaW5naWZ5KHRoaXMudmlkZW9EaW1lbnNpb25zKVxuICAgICAgICAgICAgICAgIH0sIChlcnJvciwgcmVzcG9uc2UpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZXJyb3IuY29kZSA9PT0gNDAxKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KG5ldyBPcGVuVmlkdUVycm9yKE9wZW5WaWR1RXJyb3JOYW1lLk9QRU5WSURVX1BFUk1JU1NJT05fREVOSUVELCBcIllvdSBkb24ndCBoYXZlIHBlcm1pc3Npb25zIHRvIHB1Ymxpc2hcIikpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWplY3QoJ0Vycm9yIG9uIHB1Ymxpc2hWaWRlbzogJyArIEpTT04uc3RyaW5naWZ5KGVycm9yKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLndlYlJ0Y1BlZXIucHJvY2Vzc0Fuc3dlcihyZXNwb25zZS5zZHBBbnN3ZXIpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbUlkID0gcmVzcG9uc2UuaWQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuaXNMb2NhbFN0cmVhbVB1Ymxpc2hlZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucHVibGlzaGVkT25jZSA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLmRpc3BsYXlNeVJlbW90ZSgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnJlbW90ZVBlZXJTdWNjZXNzZnVsbHlFc3RhYmxpc2hlZCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdzdHJlYW0tY3JlYXRlZC1ieS1wdWJsaXNoZXInKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5pbml0V2ViUnRjU3RhdHMoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbyhcIidQdWJsaXNoZXInIHN1Y2Nlc3NmdWxseSBwdWJsaXNoZWQgdG8gc2Vzc2lvblwiKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgaWYgKHRoaXMuZGlzcGxheU15UmVtb3RlKCkpIHtcbiAgICAgICAgICAgICAgICB0aGlzLndlYlJ0Y1BlZXIgPSBuZXcgV2ViUnRjUGVlclNlbmRyZWN2KG9wdGlvbnMpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLndlYlJ0Y1BlZXIgPSBuZXcgV2ViUnRjUGVlclNlbmRvbmx5KG9wdGlvbnMpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy53ZWJSdGNQZWVyLmdlbmVyYXRlT2ZmZXIoKS50aGVuKG9mZmVyID0+IHtcbiAgICAgICAgICAgICAgICBzdWNjZXNzQ2FsbGJhY2sob2ZmZXIpO1xuICAgICAgICAgICAgfSkuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgIHJlamVjdChuZXcgRXJyb3IoJyhwdWJsaXNoKSBTRFAgb2ZmZXIgZXJyb3I6ICcgKyBKU09OLnN0cmluZ2lmeShlcnJvcikpKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGluaXRXZWJSdGNQZWVyUmVjZWl2ZSgpOiBQcm9taXNlPGFueT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuXG4gICAgICAgICAgICBjb25zdCBvZmZlckNvbnN0cmFpbnRzID0ge1xuICAgICAgICAgICAgICAgIGF1ZGlvOiB0aGlzLmluYm91bmRTdHJlYW1PcHRzLmhhc0F1ZGlvLFxuICAgICAgICAgICAgICAgIHZpZGVvOiB0aGlzLmluYm91bmRTdHJlYW1PcHRzLmhhc1ZpZGVvXG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgY29uc29sZS5kZWJ1ZyhcIidTZXNzaW9uLnN1YnNjcmliZShTdHJlYW0pJyBjYWxsZWQuIENvbnN0cmFpbnRzIG9mIGdlbmVyYXRlIFNEUCBvZmZlclwiLFxuICAgICAgICAgICAgICAgIG9mZmVyQ29uc3RyYWludHMpO1xuICAgICAgICAgICAgY29uc3Qgb3B0aW9ucyA9IHtcbiAgICAgICAgICAgICAgICBvbmljZWNhbmRpZGF0ZTogdGhpcy5jb25uZWN0aW9uLnNlbmRJY2VDYW5kaWRhdGUuYmluZCh0aGlzLmNvbm5lY3Rpb24pLFxuICAgICAgICAgICAgICAgIG1lZGlhQ29uc3RyYWludHM6IG9mZmVyQ29uc3RyYWludHMsXG4gICAgICAgICAgICAgICAgaWNlU2VydmVyczogdGhpcy5nZXRJY2VTZXJ2ZXJzQ29uZigpLFxuICAgICAgICAgICAgICAgIHNpbXVsY2FzdDogZmFsc2VcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIGNvbnN0IHN1Y2Nlc3NDYWxsYmFjayA9IChzZHBPZmZlclBhcmFtKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5kZWJ1ZygnU2VuZGluZyBTRFAgb2ZmZXIgdG8gc3Vic2NyaWJlIHRvICdcbiAgICAgICAgICAgICAgICAgICAgKyB0aGlzLnN0cmVhbUlkLCBzZHBPZmZlclBhcmFtKTtcbiAgICAgICAgICAgICAgICB0aGlzLnNlc3Npb24ub3BlbnZpZHUuc2VuZFJlcXVlc3QoJ3JlY2VpdmVWaWRlb0Zyb20nLCB7XG4gICAgICAgICAgICAgICAgICAgIHNlbmRlcjogdGhpcy5zdHJlYW1JZCxcbiAgICAgICAgICAgICAgICAgICAgc2RwT2ZmZXI6IHNkcE9mZmVyUGFyYW1cbiAgICAgICAgICAgICAgICB9LCAoZXJyb3IsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KG5ldyBFcnJvcignRXJyb3Igb24gcmVjdlZpZGVvRnJvbTogJyArIEpTT04uc3RyaW5naWZ5KGVycm9yKSkpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy53ZWJSdGNQZWVyLnByb2Nlc3NBbnN3ZXIocmVzcG9uc2Uuc2RwQW5zd2VyKS50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnJlbW90ZVBlZXJTdWNjZXNzZnVsbHlFc3RhYmxpc2hlZCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuaW5pdFdlYlJ0Y1N0YXRzKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSkuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgdGhpcy53ZWJSdGNQZWVyID0gbmV3IFdlYlJ0Y1BlZXJSZWN2b25seShvcHRpb25zKTtcbiAgICAgICAgICAgIHRoaXMud2ViUnRjUGVlci5nZW5lcmF0ZU9mZmVyKClcbiAgICAgICAgICAgICAgICAudGhlbihvZmZlciA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHN1Y2Nlc3NDYWxsYmFjayhvZmZlcik7XG4gICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgICAgICByZWplY3QobmV3IEVycm9yKCcoc3Vic2NyaWJlKSBTRFAgb2ZmZXIgZXJyb3I6ICcgKyBKU09OLnN0cmluZ2lmeShlcnJvcikpKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSByZW1vdGVQZWVyU3VjY2Vzc2Z1bGx5RXN0YWJsaXNoZWQoKTogdm9pZCB7XG4gICAgICAgIHRoaXMubWVkaWFTdHJlYW0gPSB0aGlzLndlYlJ0Y1BlZXIucGMuZ2V0UmVtb3RlU3RyZWFtcygpWzBdO1xuICAgICAgICBjb25zb2xlLmRlYnVnKCdQZWVyIHJlbW90ZSBzdHJlYW0nLCB0aGlzLm1lZGlhU3RyZWFtKTtcblxuICAgICAgICBpZiAoISF0aGlzLm1lZGlhU3RyZWFtKSB7XG4gICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnbWVkaWFzdHJlYW0tdXBkYXRlZCcpO1xuICAgICAgICAgICAgaWYgKCF0aGlzLmRpc3BsYXlNeVJlbW90ZSgpICYmICEhdGhpcy5tZWRpYVN0cmVhbS5nZXRBdWRpb1RyYWNrcygpWzBdICYmIHRoaXMuc2Vzc2lvbi5zcGVha2luZ0V2ZW50c0VuYWJsZWQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVuYWJsZVNwZWFraW5nRXZlbnRzKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIGluaXRXZWJSdGNTdGF0cygpOiB2b2lkIHtcbiAgICAgICAgdGhpcy53ZWJSdGNTdGF0cyA9IG5ldyBXZWJSdGNTdGF0cyh0aGlzKTtcbiAgICAgICAgdGhpcy53ZWJSdGNTdGF0cy5pbml0V2ViUnRjU3RhdHMoKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIHN0b3BXZWJSdGNTdGF0cygpOiB2b2lkIHtcbiAgICAgICAgaWYgKCEhdGhpcy53ZWJSdGNTdGF0cyAmJiB0aGlzLndlYlJ0Y1N0YXRzLmlzRW5hYmxlZCgpKSB7XG4gICAgICAgICAgICB0aGlzLndlYlJ0Y1N0YXRzLnN0b3BXZWJSdGNTdGF0cygpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBnZXRJY2VTZXJ2ZXJzQ29uZigpOiBSVENJY2VTZXJ2ZXJbXSB8IHVuZGVmaW5lZCB7XG4gICAgICAgIGxldCByZXR1cm5WYWx1ZTtcbiAgICAgICAgaWYgKCEhdGhpcy5zZXNzaW9uLm9wZW52aWR1LmFkdmFuY2VkQ29uZmlndXJhdGlvbi5pY2VTZXJ2ZXJzKSB7XG4gICAgICAgICAgICByZXR1cm5WYWx1ZSA9IHRoaXMuc2Vzc2lvbi5vcGVudmlkdS5hZHZhbmNlZENvbmZpZ3VyYXRpb24uaWNlU2VydmVycyA9PT0gJ2ZyZWVpY2UnID9cbiAgICAgICAgICAgICAgICB1bmRlZmluZWQgOlxuICAgICAgICAgICAgICAgIHRoaXMuc2Vzc2lvbi5vcGVudmlkdS5hZHZhbmNlZENvbmZpZ3VyYXRpb24uaWNlU2VydmVycztcbiAgICAgICAgfSBlbHNlIGlmICh0aGlzLnNlc3Npb24ub3BlbnZpZHUuaWNlU2VydmVycykge1xuICAgICAgICAgICAgcmV0dXJuVmFsdWUgPSB0aGlzLnNlc3Npb24ub3BlbnZpZHUuaWNlU2VydmVycztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVyblZhbHVlID0gdW5kZWZpbmVkO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZXR1cm5WYWx1ZTtcbiAgICB9XG5cbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IFN0cmVhbSB9IGZyb20gJy4vU3RyZWFtJztcbmltcG9ydCB7IEV2ZW50RGlzcGF0Y2hlciB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvSW50ZXJmYWNlcy9QdWJsaWMvRXZlbnREaXNwYXRjaGVyJztcbmltcG9ydCB7IFN0cmVhbU1hbmFnZXJWaWRlbyB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvSW50ZXJmYWNlcy9QdWJsaWMvU3RyZWFtTWFuYWdlclZpZGVvJztcbmltcG9ydCB7IEV2ZW50IH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvRXZlbnQnO1xuaW1wb3J0IHsgU3RyZWFtTWFuYWdlckV2ZW50IH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvU3RyZWFtTWFuYWdlckV2ZW50JztcbmltcG9ydCB7IFZpZGVvRWxlbWVudEV2ZW50IH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvVmlkZW9FbGVtZW50RXZlbnQnO1xuaW1wb3J0IHsgVmlkZW9JbnNlcnRNb2RlIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FbnVtcy9WaWRlb0luc2VydE1vZGUnO1xuXG5pbXBvcnQgRXZlbnRFbWl0dGVyID0gcmVxdWlyZSgnd29sZnk4Ny1ldmVudGVtaXR0ZXInKTtcblxuXG4vKipcbiAqIEludGVyZmFjZSBpbiBjaGFyZ2Ugb2YgZGlzcGxheWluZyB0aGUgbWVkaWEgc3RyZWFtcyBpbiB0aGUgSFRNTCBET00uIFRoaXMgd3JhcHMgYW55IFtbUHVibGlzaGVyXV0gYW5kIFtbU3Vic2NyaWJlcl1dIG9iamVjdC5cbiAqIFlvdSBjYW4gaW5zZXJ0IGFzIG1hbnkgdmlkZW8gcGxheWVycyBmbyB0aGUgc2FtZSBTdHJlYW0gYXMgeW91IHdhbnQgYnkgY2FsbGluZyBbW1N0cmVhbU1hbmFnZXIuYWRkVmlkZW9FbGVtZW50XV0gb3JcbiAqIFtbU3RyZWFtTWFuYWdlci5jcmVhdGVWaWRlb0VsZW1lbnRdXS5cbiAqXG4gKiBUaGUgdXNlIG9mIFN0cmVhbU1hbmFnZXIgd3JhcHBlciBpcyBwYXJ0aWN1bGFybHkgdXNlZnVsIHdoZW4geW91IGRvbid0IG5lZWQgdG8gZGlmZmVyZW50aWF0ZSBiZXR3ZWVuIFB1Ymxpc2hlciBvciBTdWJzY3JpYmVyIHN0cmVhbXMgb3IganVzdFxuICogd2FudCB0byBkaXJlY3RseSBtYW5hZ2UgeW91ciBvd24gdmlkZW8gZWxlbWVudHMgKGV2ZW4gbW9yZSB0aGFuIG9uZSB2aWRlbyBlbGVtZW50IHBlciBTdHJlYW0pLiBUaGlzIHNjZW5hcmlvIGlzIHByZXR0eSBjb21tb24gaW5cbiAqIGRlY2xhcmF0aXZlLCBNVkMgZnJvbnRlbmQgZnJhbWV3b3JrcyBzdWNoIGFzIEFuZ3VsYXIsIFJlYWN0IG9yIFZ1ZS5qc1xuICovXG5leHBvcnQgY2xhc3MgU3RyZWFtTWFuYWdlciBpbXBsZW1lbnRzIEV2ZW50RGlzcGF0Y2hlciB7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgU3RyZWFtIHJlcHJlc2VudGVkIGluIHRoZSBET00gYnkgdGhlIFB1Ymxpc2hlci9TdWJzY3JpYmVyXG4gICAgICovXG4gICAgc3RyZWFtOiBTdHJlYW07XG5cbiAgICAvKipcbiAgICAgKiBBbGwgdGhlIHZpZGVvcyBkaXNwbGF5aW5nIHRoZSBTdHJlYW0gb2YgdGhpcyBQdWJsaXNoZXIvU3Vic2NyaWJlclxuICAgICAqL1xuICAgIHZpZGVvczogU3RyZWFtTWFuYWdlclZpZGVvW10gPSBbXTtcblxuICAgIC8qKlxuICAgICAqIFdoZXRoZXIgdGhlIFN0cmVhbSByZXByZXNlbnRlZCBpbiB0aGUgRE9NIGlzIGxvY2FsIG9yIHJlbW90ZVxuICAgICAqIC0gYGZhbHNlYCBmb3IgW1tQdWJsaXNoZXJdXVxuICAgICAqIC0gYHRydWVgIGZvciBbW1N1YnNjcmliZXJdXVxuICAgICAqL1xuICAgIHJlbW90ZTogYm9vbGVhbjtcblxuICAgIC8qKlxuICAgICAqIFRoZSBET00gSFRNTEVsZW1lbnQgYXNzaWduZWQgYXMgdGFyZ2V0IGVsZW1lbnQgd2hlbiBjcmVhdGluZyB0aGUgdmlkZW8gZm9yIHRoZSBQdWJsaXNoZXIvU3Vic2NyaWJlci4gVGhpcyBwcm9wZXJ0eSBpcyBvbmx5IGRlZmluZWQgaWY6XG4gICAgICogLSBbW1B1Ymxpc2hlcl1dIGhhcyBiZWVuIGluaXRpYWxpemVkIGJ5IGNhbGxpbmcgbWV0aG9kIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dIHdpdGggYSB2YWxpZCBgdGFyZ2V0RWxlbWVudGAgcGFyYW1ldGVyXG4gICAgICogLSBbW1N1YnNjcmliZXJdXSBoYXMgYmVlbiBpbml0aWFsaXplZCBieSBjYWxsaW5nIG1ldGhvZCBbW1Nlc3Npb24uc3Vic2NyaWJlXV0gd2l0aCBhIHZhbGlkIGB0YXJnZXRFbGVtZW50YCBwYXJhbWV0ZXJcbiAgICAgKi9cbiAgICB0YXJnZXRFbGVtZW50OiBIVE1MRWxlbWVudDtcblxuICAgIC8qKlxuICAgICAqIGBpZGAgYXR0cmlidXRlIG9mIHRoZSBET00gdmlkZW8gZWxlbWVudCBkaXNwbGF5aW5nIHRoZSBQdWJsaXNoZXIvU3Vic2NyaWJlcidzIHN0cmVhbS4gVGhpcyBwcm9wZXJ0eSBpcyBvbmx5IGRlZmluZWQgaWY6XG4gICAgICogLSBbW1B1Ymxpc2hlcl1dIGhhcyBiZWVuIGluaXRpYWxpemVkIGJ5IGNhbGxpbmcgbWV0aG9kIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dIHdpdGggYSB2YWxpZCBgdGFyZ2V0RWxlbWVudGAgcGFyYW1ldGVyXG4gICAgICogLSBbW1N1YnNjcmliZXJdXSBoYXMgYmVlbiBpbml0aWFsaXplZCBieSBjYWxsaW5nIG1ldGhvZCBbW1Nlc3Npb24uc3Vic2NyaWJlXV0gd2l0aCBhIHZhbGlkIGB0YXJnZXRFbGVtZW50YCBwYXJhbWV0ZXJcbiAgICAgKi9cbiAgICBpZDogc3RyaW5nO1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGZpcnN0VmlkZW9FbGVtZW50OiBTdHJlYW1NYW5hZ2VyVmlkZW87XG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGxhenlMYXVuY2hWaWRlb0VsZW1lbnRDcmVhdGVkRXZlbnQgPSBmYWxzZTtcbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgZWxlbWVudDogSFRNTEVsZW1lbnQ7XG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHByb3RlY3RlZCBlZSA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgcHJvdGVjdGVkIGNhblBsYXlMaXN0ZW5lcjogRXZlbnRMaXN0ZW5lck9yRXZlbnRMaXN0ZW5lck9iamVjdDtcblxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHN0cmVhbTogU3RyZWFtLCB0YXJnZXRFbGVtZW50PzogSFRNTEVsZW1lbnQgfCBzdHJpbmcpIHtcbiAgICAgICAgdGhpcy5zdHJlYW0gPSBzdHJlYW07XG4gICAgICAgIHRoaXMuc3RyZWFtLnN0cmVhbU1hbmFnZXIgPSB0aGlzO1xuICAgICAgICB0aGlzLnJlbW90ZSA9ICF0aGlzLnN0cmVhbS5pc0xvY2FsKCk7XG5cbiAgICAgICAgaWYgKCEhdGFyZ2V0RWxlbWVudCkge1xuICAgICAgICAgICAgbGV0IHRhcmdFbDtcbiAgICAgICAgICAgIGlmICh0eXBlb2YgdGFyZ2V0RWxlbWVudCA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgICAgICB0YXJnRWwgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCh0YXJnZXRFbGVtZW50KTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAodGFyZ2V0RWxlbWVudCBpbnN0YW5jZW9mIEhUTUxFbGVtZW50KSB7XG4gICAgICAgICAgICAgICAgdGFyZ0VsID0gdGFyZ2V0RWxlbWVudDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKCEhdGFyZ0VsKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5maXJzdFZpZGVvRWxlbWVudCA9IHtcbiAgICAgICAgICAgICAgICAgICAgdGFyZ2V0RWxlbWVudDogdGFyZ0VsLFxuICAgICAgICAgICAgICAgICAgICB2aWRlbzogZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgndmlkZW8nKSxcbiAgICAgICAgICAgICAgICAgICAgaWQ6ICcnXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB0aGlzLnRhcmdldEVsZW1lbnQgPSB0YXJnRWw7XG4gICAgICAgICAgICAgICAgdGhpcy5lbGVtZW50ID0gdGFyZ0VsO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHRoaXMuY2FuUGxheUxpc3RlbmVyID0gKCkgPT4ge1xuICAgICAgICAgICAgaWYgKHRoaXMuc3RyZWFtLmlzTG9jYWwoKSkge1xuICAgICAgICAgICAgICAgIGlmICghdGhpcy5zdHJlYW0uZGlzcGxheU15UmVtb3RlKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS5pbmZvKFwiWW91ciBsb2NhbCAnU3RyZWFtJyB3aXRoIGlkIFtcIiArIHRoaXMuc3RyZWFtLnN0cmVhbUlkICsgJ10gdmlkZW8gaXMgbm93IHBsYXlpbmcnKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3ZpZGVvUGxheWluZycsIFtuZXcgVmlkZW9FbGVtZW50RXZlbnQodGhpcy52aWRlb3NbMF0udmlkZW8sIHRoaXMsICd2aWRlb1BsYXlpbmcnKV0pO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbyhcIllvdXIgb3duIHJlbW90ZSAnU3RyZWFtJyB3aXRoIGlkIFtcIiArIHRoaXMuc3RyZWFtLnN0cmVhbUlkICsgJ10gdmlkZW8gaXMgbm93IHBsYXlpbmcnKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3JlbW90ZVZpZGVvUGxheWluZycsIFtuZXcgVmlkZW9FbGVtZW50RXZlbnQodGhpcy52aWRlb3NbMF0udmlkZW8sIHRoaXMsICdyZW1vdGVWaWRlb1BsYXlpbmcnKV0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5pbmZvKFwiUmVtb3RlICdTdHJlYW0nIHdpdGggaWQgW1wiICsgdGhpcy5zdHJlYW0uc3RyZWFtSWQgKyAnXSB2aWRlbyBpcyBub3cgcGxheWluZycpO1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCd2aWRlb1BsYXlpbmcnLCBbbmV3IFZpZGVvRWxlbWVudEV2ZW50KHRoaXMudmlkZW9zWzBdLnZpZGVvLCB0aGlzLCAndmlkZW9QbGF5aW5nJyldKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdzdHJlYW1QbGF5aW5nJywgW25ldyBTdHJlYW1NYW5hZ2VyRXZlbnQodGhpcyldKTtcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZWUgW1tFdmVudERpc3BhdGNoZXIub25dXVxuICAgICAqL1xuICAgIG9uKHR5cGU6IHN0cmluZywgaGFuZGxlcjogKGV2ZW50OiBFdmVudCkgPT4gdm9pZCk6IEV2ZW50RGlzcGF0Y2hlciB7XG4gICAgICAgIHRoaXMuZWUub24odHlwZSwgZXZlbnQgPT4ge1xuICAgICAgICAgICAgaWYgKGV2ZW50KSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5pbmZvKFwiRXZlbnQgJ1wiICsgdHlwZSArIFwiJyB0cmlnZ2VyZWQgYnkgJ1wiICsgKHRoaXMucmVtb3RlID8gJ1N1YnNjcmliZXInIDogJ1B1Ymxpc2hlcicpICsgXCInXCIsIGV2ZW50KTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5pbmZvKFwiRXZlbnQgJ1wiICsgdHlwZSArIFwiJyB0cmlnZ2VyZWQgYnkgJ1wiICsgKHRoaXMucmVtb3RlID8gJ1N1YnNjcmliZXInIDogJ1B1Ymxpc2hlcicpICsgXCInXCIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaGFuZGxlcihldmVudCk7XG4gICAgICAgIH0pO1xuICAgICAgICBpZiAodHlwZSA9PT0gJ3ZpZGVvRWxlbWVudENyZWF0ZWQnKSB7XG4gICAgICAgICAgICBpZiAoISF0aGlzLnN0cmVhbSAmJiB0aGlzLmxhenlMYXVuY2hWaWRlb0VsZW1lbnRDcmVhdGVkRXZlbnQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgndmlkZW9FbGVtZW50Q3JlYXRlZCcsIFtuZXcgVmlkZW9FbGVtZW50RXZlbnQodGhpcy52aWRlb3NbMF0udmlkZW8sIHRoaXMsICd2aWRlb0VsZW1lbnRDcmVhdGVkJyldKTtcbiAgICAgICAgICAgICAgICB0aGlzLmxhenlMYXVuY2hWaWRlb0VsZW1lbnRDcmVhdGVkRXZlbnQgPSBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAodHlwZSA9PT0gJ3N0cmVhbVBsYXlpbmcnIHx8IHR5cGUgPT09ICd2aWRlb1BsYXlpbmcnKSB7XG4gICAgICAgICAgICBpZiAodGhpcy52aWRlb3NbMF0gJiYgdGhpcy52aWRlb3NbMF0udmlkZW8gJiZcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvc1swXS52aWRlby5jdXJyZW50VGltZSA+IDAgJiZcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvc1swXS52aWRlby5wYXVzZWQgPT09IGZhbHNlICYmXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8uZW5kZWQgPT09IGZhbHNlICYmXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8ucmVhZHlTdGF0ZSA9PT0gNCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdzdHJlYW1QbGF5aW5nJywgW25ldyBTdHJlYW1NYW5hZ2VyRXZlbnQodGhpcyldKTtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgndmlkZW9QbGF5aW5nJywgW25ldyBWaWRlb0VsZW1lbnRFdmVudCh0aGlzLnZpZGVvc1swXS52aWRlbywgdGhpcywgJ3ZpZGVvUGxheWluZycpXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2VlIFtbRXZlbnREaXNwYXRjaGVyLm9uY2VdXVxuICAgICAqL1xuICAgIG9uY2UodHlwZTogc3RyaW5nLCBoYW5kbGVyOiAoZXZlbnQ6IEV2ZW50KSA9PiB2b2lkKTogU3RyZWFtTWFuYWdlciB7XG4gICAgICAgIHRoaXMuZWUub25jZSh0eXBlLCBldmVudCA9PiB7XG4gICAgICAgICAgICBpZiAoZXZlbnQpIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oXCJFdmVudCAnXCIgKyB0eXBlICsgXCInIHRyaWdnZXJlZCBvbmNlXCIsIGV2ZW50KTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5pbmZvKFwiRXZlbnQgJ1wiICsgdHlwZSArIFwiJyB0cmlnZ2VyZWQgb25jZVwiKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGhhbmRsZXIoZXZlbnQpO1xuICAgICAgICB9KTtcbiAgICAgICAgaWYgKHR5cGUgPT09ICd2aWRlb0VsZW1lbnRDcmVhdGVkJykge1xuICAgICAgICAgICAgaWYgKCEhdGhpcy5zdHJlYW0gJiYgdGhpcy5sYXp5TGF1bmNoVmlkZW9FbGVtZW50Q3JlYXRlZEV2ZW50KSB7XG4gICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3ZpZGVvRWxlbWVudENyZWF0ZWQnLCBbbmV3IFZpZGVvRWxlbWVudEV2ZW50KHRoaXMudmlkZW9zWzBdLnZpZGVvLCB0aGlzLCAndmlkZW9FbGVtZW50Q3JlYXRlZCcpXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHR5cGUgPT09ICdzdHJlYW1QbGF5aW5nJyB8fCB0eXBlID09PSAndmlkZW9QbGF5aW5nJykge1xuICAgICAgICAgICAgaWYgKHRoaXMudmlkZW9zWzBdICYmIHRoaXMudmlkZW9zWzBdLnZpZGVvICYmXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8uY3VycmVudFRpbWUgPiAwICYmXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8ucGF1c2VkID09PSBmYWxzZSAmJlxuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9zWzBdLnZpZGVvLmVuZGVkID09PSBmYWxzZSAmJlxuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9zWzBdLnZpZGVvLnJlYWR5U3RhdGUgPT09IDQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnc3RyZWFtUGxheWluZycsIFtuZXcgU3RyZWFtTWFuYWdlckV2ZW50KHRoaXMpXSk7XG4gICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3ZpZGVvUGxheWluZycsIFtuZXcgVmlkZW9FbGVtZW50RXZlbnQodGhpcy52aWRlb3NbMF0udmlkZW8sIHRoaXMsICd2aWRlb1BsYXlpbmcnKV0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNlZSBbW0V2ZW50RGlzcGF0Y2hlci5vZmZdXVxuICAgICAqL1xuICAgIG9mZih0eXBlOiBzdHJpbmcsIGhhbmRsZXI/OiAoZXZlbnQ6IEV2ZW50KSA9PiB2b2lkKTogU3RyZWFtTWFuYWdlciB7XG4gICAgICAgIGlmICghaGFuZGxlcikge1xuICAgICAgICAgICAgdGhpcy5lZS5yZW1vdmVBbGxMaXN0ZW5lcnModHlwZSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLmVlLm9mZih0eXBlLCBoYW5kbGVyKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBNYWtlcyBgdmlkZW9gIGVsZW1lbnQgcGFyYW1ldGVyIGRpc3BsYXkgdGhpcyBbW3N0cmVhbV1dLiBUaGlzIGlzIHVzZWZ1bCB3aGVuIHlvdSBhcmVcbiAgICAgKiBbbWFuYWdpbmcgdGhlIHZpZGVvIGVsZW1lbnRzIG9uIHlvdXIgb3duXSgvZG9jcy9ob3ctZG8taS9tYW5hZ2UtdmlkZW9zLyN5b3UtdGFrZS1jYXJlLW9mLXRoZS12aWRlby1wbGF5ZXJzKVxuICAgICAqXG4gICAgICogQ2FsbGluZyB0aGlzIG1ldGhvZCB3aXRoIGEgdmlkZW8gYWxyZWFkeSBhZGRlZCB0byBvdGhlciBQdWJsaXNoZXIvU3Vic2NyaWJlciB3aWxsIGNhdXNlIHRoZSB2aWRlbyBlbGVtZW50IHRvIGJlXG4gICAgICogZGlzYXNzb2NpYXRlZCBmcm9tIHRoYXQgcHJldmlvdXMgUHVibGlzaGVyL1N1YnNjcmliZXIgYW5kIHRvIGJlIGFzc29jaWF0ZWQgdG8gdGhpcyBvbmUuXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyAxIGlmIHRoZSB2aWRlbyB3YXNuJ3QgYXNzb2NpYXRlZCB0byBhbnkgb3RoZXIgUHVibGlzaGVyL1N1YnNjcmliZXIgYW5kIGhhcyBiZWVuIHN1Y2Nlc3NmdWxseSBhZGRlZCB0byB0aGlzIG9uZS5cbiAgICAgKiAwIGlmIHRoZSB2aWRlbyB3YXMgYWxyZWFkeSBhZGRlZCB0byB0aGlzIFB1Ymxpc2hlci9TdWJzY3JpYmVyLiAtMSBpZiB0aGUgdmlkZW8gd2FzIHByZXZpb3VzbHkgYXNzb2NpYXRlZCB0byBhbnkgb3RoZXJcbiAgICAgKiBQdWJsaXNoZXIvU3Vic2NyaWJlciBhbmQgaGFzIGJlZW4gc3VjY2Vzc2Z1bGx5IGRpc2Fzc29jaWF0ZWQgZnJvbSB0aGF0IG9uZSBhbmQgcHJvcGVybHkgYWRkZWQgdG8gdGhpcyBvbmUuXG4gICAgICovXG4gICAgYWRkVmlkZW9FbGVtZW50KHZpZGVvOiBIVE1MVmlkZW9FbGVtZW50KTogbnVtYmVyIHtcblxuICAgICAgICB0aGlzLmluaXRpYWxpemVWaWRlb1Byb3BlcnRpZXModmlkZW8pO1xuXG4gICAgICAgIC8vIElmIHRoZSB2aWRlbyBlbGVtZW50IGlzIGFscmVhZHkgcGFydCBvZiB0aGlzIFN0cmVhbU1hbmFnZXIgZG8gbm90aGluZ1xuICAgICAgICBmb3IgKGNvbnN0IHYgb2YgdGhpcy52aWRlb3MpIHtcbiAgICAgICAgICAgIGlmICh2LnZpZGVvID09PSB2aWRlbykge1xuICAgICAgICAgICAgICAgIHJldHVybiAwO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgbGV0IHJldHVybk51bWJlciA9IDE7XG5cbiAgICAgICAgZm9yIChjb25zdCBzdHJlYW1NYW5hZ2VyIG9mIHRoaXMuc3RyZWFtLnNlc3Npb24uc3RyZWFtTWFuYWdlcnMpIHtcbiAgICAgICAgICAgIGlmIChzdHJlYW1NYW5hZ2VyLmRpc2Fzc29jaWF0ZVZpZGVvKHZpZGVvKSkge1xuICAgICAgICAgICAgICAgIHJldHVybk51bWJlciA9IC0xO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5zdHJlYW0uc2Vzc2lvbi5zdHJlYW1NYW5hZ2Vycy5mb3JFYWNoKHN0cmVhbU1hbmFnZXIgPT4ge1xuICAgICAgICAgICAgc3RyZWFtTWFuYWdlci5kaXNhc3NvY2lhdGVWaWRlbyh2aWRlbyk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHRoaXMucHVzaE5ld1N0cmVhbU1hbmFnZXJWaWRlbyh7XG4gICAgICAgICAgICB2aWRlbyxcbiAgICAgICAgICAgIGlkOiB2aWRlby5pZFxuICAgICAgICB9KTtcblxuICAgICAgICBjb25zb2xlLmluZm8oJ05ldyB2aWRlbyBlbGVtZW50IGFzc29jaWF0ZWQgdG8gJywgdGhpcyk7XG5cbiAgICAgICAgcmV0dXJuIHJldHVybk51bWJlcjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgbmV3IHZpZGVvIGVsZW1lbnQgZGlzcGxheWluZyB0aGlzIFtbc3RyZWFtXV0uIFRoaXMgYWxsb3dzIHlvdSB0byBoYXZlIG11bHRpcGxlIHZpZGVvIGVsZW1lbnRzIGRpc3BsYXlpbmcgdGhlIHNhbWUgbWVkaWEgc3RyZWFtLlxuICAgICAqXG4gICAgICogIyMjIyBFdmVudHMgZGlzcGF0Y2hlZFxuICAgICAqXG4gICAgICogVGhlIFB1Ymxpc2hlci9TdWJzY3JpYmVyIG9iamVjdCB3aWxsIGRpc3BhdGNoIGEgYHZpZGVvRWxlbWVudENyZWF0ZWRgIGV2ZW50IG9uY2UgdGhlIEhUTUwgdmlkZW8gZWxlbWVudCBoYXMgYmVlbiBhZGRlZCB0byBET00uIFNlZSBbW1ZpZGVvRWxlbWVudEV2ZW50XV1cbiAgICAgKlxuICAgICAqIEBwYXJhbSB0YXJnZXRFbGVtZW50IEhUTUwgRE9NIGVsZW1lbnQgKG9yIGl0cyBgaWRgIGF0dHJpYnV0ZSkgaW4gd2hpY2ggdGhlIHZpZGVvIGVsZW1lbnQgb2YgdGhlIFB1Ymxpc2hlci9TdWJzY3JpYmVyIHdpbGwgYmUgaW5zZXJ0ZWRcbiAgICAgKiBAcGFyYW0gaW5zZXJ0TW9kZSBIb3cgdGhlIHZpZGVvIGVsZW1lbnQgd2lsbCBiZSBpbnNlcnRlZCBhY2NvcmRpbmdseSB0byBgdGFyZ2V0RWxlbWV0YFxuICAgICAqL1xuICAgIGNyZWF0ZVZpZGVvRWxlbWVudCh0YXJnZXRFbGVtZW50Pzogc3RyaW5nIHwgSFRNTEVsZW1lbnQsIGluc2VydE1vZGU/OiBWaWRlb0luc2VydE1vZGUpOiBIVE1MVmlkZW9FbGVtZW50IHtcbiAgICAgICAgbGV0IHRhcmdFbDtcbiAgICAgICAgaWYgKHR5cGVvZiB0YXJnZXRFbGVtZW50ID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgdGFyZ0VsID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQodGFyZ0VsKTtcbiAgICAgICAgICAgIGlmICghdGFyZ0VsKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiVGhlIHByb3ZpZGVkICd0YXJnZXRFbGVtZW50JyBjb3VsZG4ndCBiZSByZXNvbHZlZCB0byBhbnkgSFRNTCBlbGVtZW50OiBcIiArIHRhcmdldEVsZW1lbnQpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2UgaWYgKHRhcmdldEVsZW1lbnQgaW5zdGFuY2VvZiBIVE1MRWxlbWVudCkge1xuICAgICAgICAgICAgdGFyZ0VsID0gdGFyZ2V0RWxlbWVudDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIlRoZSBwcm92aWRlZCAndGFyZ2V0RWxlbWVudCcgY291bGRuJ3QgYmUgcmVzb2x2ZWQgdG8gYW55IEhUTUwgZWxlbWVudDogXCIgKyB0YXJnZXRFbGVtZW50KTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHZpZGVvID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgndmlkZW8nKTtcbiAgICAgICAgdGhpcy5pbml0aWFsaXplVmlkZW9Qcm9wZXJ0aWVzKHZpZGVvKTtcblxuICAgICAgICBsZXQgaW5zTW9kZSA9ICEhaW5zZXJ0TW9kZSA/IGluc2VydE1vZGUgOiBWaWRlb0luc2VydE1vZGUuQVBQRU5EO1xuICAgICAgICBzd2l0Y2ggKGluc01vZGUpIHtcbiAgICAgICAgICAgIGNhc2UgVmlkZW9JbnNlcnRNb2RlLkFGVEVSOlxuICAgICAgICAgICAgICAgIHRhcmdFbC5wYXJlbnROb2RlISEuaW5zZXJ0QmVmb3JlKHZpZGVvLCB0YXJnRWwubmV4dFNpYmxpbmcpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBWaWRlb0luc2VydE1vZGUuQVBQRU5EOlxuICAgICAgICAgICAgICAgIHRhcmdFbC5hcHBlbmRDaGlsZCh2aWRlbyk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIFZpZGVvSW5zZXJ0TW9kZS5CRUZPUkU6XG4gICAgICAgICAgICAgICAgdGFyZ0VsLnBhcmVudE5vZGUhIS5pbnNlcnRCZWZvcmUodmlkZW8sIHRhcmdFbCk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIFZpZGVvSW5zZXJ0TW9kZS5QUkVQRU5EOlxuICAgICAgICAgICAgICAgIHRhcmdFbC5pbnNlcnRCZWZvcmUodmlkZW8sIHRhcmdFbC5jaGlsZE5vZGVzWzBdKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgVmlkZW9JbnNlcnRNb2RlLlJFUExBQ0U6XG4gICAgICAgICAgICAgICAgdGFyZ0VsLnBhcmVudE5vZGUhIS5yZXBsYWNlQ2hpbGQodmlkZW8sIHRhcmdFbCk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgIGluc01vZGUgPSBWaWRlb0luc2VydE1vZGUuQVBQRU5EO1xuICAgICAgICAgICAgICAgIHRhcmdFbC5hcHBlbmRDaGlsZCh2aWRlbyk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCB2OiBTdHJlYW1NYW5hZ2VyVmlkZW8gPSB7XG4gICAgICAgICAgICB0YXJnZXRFbGVtZW50OiB0YXJnRWwsXG4gICAgICAgICAgICB2aWRlbyxcbiAgICAgICAgICAgIGluc2VydE1vZGU6IGluc01vZGUsXG4gICAgICAgICAgICBpZDogdmlkZW8uaWRcbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5wdXNoTmV3U3RyZWFtTWFuYWdlclZpZGVvKHYpO1xuXG4gICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCd2aWRlb0VsZW1lbnRDcmVhdGVkJywgW25ldyBWaWRlb0VsZW1lbnRFdmVudCh2LnZpZGVvLCB0aGlzLCAndmlkZW9FbGVtZW50Q3JlYXRlZCcpXSk7XG5cbiAgICAgICAgdGhpcy5sYXp5TGF1bmNoVmlkZW9FbGVtZW50Q3JlYXRlZEV2ZW50ID0gISF0aGlzLmZpcnN0VmlkZW9FbGVtZW50O1xuXG4gICAgICAgIHJldHVybiB2aWRlbztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgaW5pdGlhbGl6ZVZpZGVvUHJvcGVydGllcyh2aWRlbzogSFRNTFZpZGVvRWxlbWVudCk6IHZvaWQge1xuICAgICAgICBpZiAoISh0aGlzLnN0cmVhbS5pc0xvY2FsKCkgJiYgdGhpcy5zdHJlYW0uZGlzcGxheU15UmVtb3RlKCkpKSB7XG4gICAgICAgICAgICAvLyBBdm9pZCBzZXR0aW5nIHRoZSBNZWRpYVN0cmVhbSBpbnRvIHRoZSBzcmNPYmplY3QgaWYgcmVtb3RlIHN1YnNjcmlwdGlvbiBiZWZvcmUgcHVibGlzaGluZ1xuICAgICAgICAgICAgdmlkZW8uc3JjT2JqZWN0ID0gdGhpcy5zdHJlYW0uZ2V0TWVkaWFTdHJlYW0oKTtcbiAgICAgICAgfVxuICAgICAgICB2aWRlby5hdXRvcGxheSA9IHRydWU7XG4gICAgICAgIHZpZGVvLmNvbnRyb2xzID0gZmFsc2U7XG4gICAgICAgIGlmICghdmlkZW8uaWQpIHtcbiAgICAgICAgICAgIHZpZGVvLmlkID0gKHRoaXMucmVtb3RlID8gJ3JlbW90ZS0nIDogJ2xvY2FsLScpICsgJ3ZpZGVvLScgKyB0aGlzLnN0cmVhbS5zdHJlYW1JZDtcbiAgICAgICAgICAgIC8vIERFUFJFQ0FURUQgcHJvcGVydHk6IGFzc2lnbiBvbmNlIHRoZSBwcm9wZXJ0eSBpZCBpZiB0aGUgdXNlciBwcm92aWRlZCBhIHZhbGlkIHRhcmdldEVsZW1lbnRcbiAgICAgICAgICAgIGlmICghdGhpcy5pZCAmJiAhIXRoaXMudGFyZ2V0RWxlbWVudCkge1xuICAgICAgICAgICAgICAgIHRoaXMuaWQgPSB2aWRlby5pZDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAoIXRoaXMucmVtb3RlICYmICF0aGlzLnN0cmVhbS5kaXNwbGF5TXlSZW1vdGUoKSkge1xuICAgICAgICAgICAgdmlkZW8ubXV0ZWQgPSB0cnVlO1xuICAgICAgICAgICAgaWYgKHRoaXMuc3RyZWFtLm91dGJvdW5kU3RyZWFtT3B0cy5wdWJsaXNoZXJQcm9wZXJ0aWVzLm1pcnJvcikge1xuICAgICAgICAgICAgICAgIHRoaXMubWlycm9yVmlkZW8odmlkZW8pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHJlbW92ZUFsbFZpZGVvcygpOiB2b2lkIHtcbiAgICAgICAgZm9yIChsZXQgaSA9IHRoaXMuc3RyZWFtLnNlc3Npb24uc3RyZWFtTWFuYWdlcnMubGVuZ3RoIC0gMTsgaSA+PSAwOyAtLWkpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLnN0cmVhbS5zZXNzaW9uLnN0cmVhbU1hbmFnZXJzW2ldID09PSB0aGlzKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5zdHJlYW0uc2Vzc2lvbi5zdHJlYW1NYW5hZ2Vycy5zcGxpY2UoaSwgMSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLnZpZGVvcy5zbGljZSgpLnJldmVyc2UoKS5mb3JFYWNoKChzdHJlYW1NYW5hZ2VyVmlkZW8sIGluZGV4LCB2aWRlb3MpID0+IHtcbiAgICAgICAgICAgIC8vIFJlbW92ZSBvbmNhbnBsYXkgZXZlbnQgbGlzdGVuZXIgKG9ubHkgT3BlblZpZHUgYnJvd3NlciBvbmUsIG5vdCB0aGUgdXNlciBvbmVzKVxuICAgICAgICAgICAgc3RyZWFtTWFuYWdlclZpZGVvLnZpZGVvLnJlbW92ZUV2ZW50TGlzdGVuZXIoJ2NhbnBsYXknLCB0aGlzLmNhblBsYXlMaXN0ZW5lcik7XG4gICAgICAgICAgICBpZiAoISFzdHJlYW1NYW5hZ2VyVmlkZW8udGFyZ2V0RWxlbWVudCkge1xuICAgICAgICAgICAgICAgIC8vIE9ubHkgcmVtb3ZlIHZpZGVvcyBjcmVhdGVkIGJ5IE9wZW5WaWR1IEJyb3dzZXIgKHRob3NlIGdlbmVyYXRlZCBieSBwYXNzaW5nIGEgdmFsaWQgdGFyZ2V0RWxlbWVudCBpbiBPcGVuVmlkdS5pbml0UHVibGlzaGVyIGFuZCBTZXNzaW9uLnN1YnNjcmliZVxuICAgICAgICAgICAgICAgIC8vIG9yIHRob3NlIGNyZWF0ZWQgYnkgU3RyZWFtTWFuYWdlci5jcmVhdGVWaWRlb0VsZW1lbnQpLiBUaGVzZSBhcmUgYWxzbyB0aGUgdmlkZW9zIHRoYXQgdHJpZ2dlcmVkIGEgdmlkZW9FbGVtZW50Q3JlYXRlZCBldmVudFxuICAgICAgICAgICAgICAgIHN0cmVhbU1hbmFnZXJWaWRlby52aWRlby5wYXJlbnROb2RlIS5yZW1vdmVDaGlsZChzdHJlYW1NYW5hZ2VyVmlkZW8udmlkZW8pO1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCd2aWRlb0VsZW1lbnREZXN0cm95ZWQnLCBbbmV3IFZpZGVvRWxlbWVudEV2ZW50KHN0cmVhbU1hbmFnZXJWaWRlby52aWRlbywgdGhpcywgJ3ZpZGVvRWxlbWVudERlc3Ryb3llZCcpXSk7XG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3Muc3BsaWNlKHZpZGVvcy5sZW5ndGggLSAxIC0gaW5kZXgsIDEpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAvLyBSZW1vdmUgc3JjT2JqZWN0IGluIGFsbCB2aWRlb3MgbWFuYWdlZCBieSB0aGUgdXNlclxuICAgICAgICAgICAgICAgIHN0cmVhbU1hbmFnZXJWaWRlby52aWRlby5zcmNPYmplY3QgPSBudWxsO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgZGlzYXNzb2NpYXRlVmlkZW8odmlkZW86IEhUTUxWaWRlb0VsZW1lbnQpOiBib29sZWFuIHtcbiAgICAgICAgbGV0IGRpc2Fzc29jaWF0ZWQgPSBmYWxzZTtcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLnZpZGVvcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgaWYgKHRoaXMudmlkZW9zW2ldLnZpZGVvID09PSB2aWRlbykge1xuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9zLnNwbGljZShpLCAxKTtcbiAgICAgICAgICAgICAgICBkaXNhc3NvY2lhdGVkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oJ1ZpZGVvIGVsZW1lbnQgZGlzYXNzb2NpYXRlZCBmcm9tICcsIHRoaXMpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBkaXNhc3NvY2lhdGVkO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBhZGRQbGF5RXZlbnRUb0ZpcnN0VmlkZW8oKSB7XG4gICAgICAgIGlmICgoISF0aGlzLnZpZGVvc1swXSkgJiYgKCEhdGhpcy52aWRlb3NbMF0udmlkZW8pICYmICh0aGlzLnZpZGVvc1swXS52aWRlby5vbmNhbnBsYXkgPT09IG51bGwpKSB7XG4gICAgICAgICAgICB0aGlzLnZpZGVvc1swXS52aWRlby5hZGRFdmVudExpc3RlbmVyKCdjYW5wbGF5JywgdGhpcy5jYW5QbGF5TGlzdGVuZXIpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHVwZGF0ZU1lZGlhU3RyZWFtKG1lZGlhU3RyZWFtOiBNZWRpYVN0cmVhbSkge1xuICAgICAgICB0aGlzLnZpZGVvcy5mb3JFYWNoKHN0cmVhbU1hbmFnZXJWaWRlbyA9PiB7XG4gICAgICAgICAgICBzdHJlYW1NYW5hZ2VyVmlkZW8udmlkZW8uc3JjT2JqZWN0ID0gbWVkaWFTdHJlYW07XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBlbWl0RXZlbnQodHlwZTogc3RyaW5nLCBldmVudEFycmF5OiBhbnlbXSk6IHZvaWQge1xuICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCh0eXBlLCBldmVudEFycmF5KTtcbiAgICB9XG5cbiAgICBwcml2YXRlIHB1c2hOZXdTdHJlYW1NYW5hZ2VyVmlkZW8oc3RyZWFtTWFuYWdlclZpZGVvOiBTdHJlYW1NYW5hZ2VyVmlkZW8pIHtcbiAgICAgICAgdGhpcy52aWRlb3MucHVzaChzdHJlYW1NYW5hZ2VyVmlkZW8pO1xuICAgICAgICB0aGlzLmFkZFBsYXlFdmVudFRvRmlyc3RWaWRlbygpO1xuICAgICAgICBpZiAodGhpcy5zdHJlYW0uc2Vzc2lvbi5zdHJlYW1NYW5hZ2Vycy5pbmRleE9mKHRoaXMpID09PSAtMSkge1xuICAgICAgICAgICAgdGhpcy5zdHJlYW0uc2Vzc2lvbi5zdHJlYW1NYW5hZ2Vycy5wdXNoKHRoaXMpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBtaXJyb3JWaWRlbyh2aWRlbyk6IHZvaWQge1xuICAgICAgICB2aWRlby5zdHlsZS50cmFuc2Zvcm0gPSAncm90YXRlWSgxODBkZWcpJztcbiAgICAgICAgdmlkZW8uc3R5bGUud2Via2l0VHJhbnNmb3JtID0gJ3JvdGF0ZVkoMTgwZGVnKSc7XG4gICAgfVxuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBTdHJlYW0gfSBmcm9tICcuL1N0cmVhbSc7XG5pbXBvcnQgeyBTdHJlYW1NYW5hZ2VyIH0gZnJvbSAnLi9TdHJlYW1NYW5hZ2VyJztcbmltcG9ydCB7IFN1YnNjcmliZXJQcm9wZXJ0aWVzIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9JbnRlcmZhY2VzL1B1YmxpYy9TdWJzY3JpYmVyUHJvcGVydGllcyc7XG5cblxuLyoqXG4gKiBQYWNrcyByZW1vdGUgbWVkaWEgc3RyZWFtcy4gUGFydGljaXBhbnRzIGF1dG9tYXRpY2FsbHkgcmVjZWl2ZSB0aGVtIHdoZW4gb3RoZXJzIHB1Ymxpc2ggdGhlaXIgc3RyZWFtcy4gSW5pdGlhbGl6ZWQgd2l0aCBbW1Nlc3Npb24uc3Vic2NyaWJlXV0gbWV0aG9kXG4gKi9cbmV4cG9ydCBjbGFzcyBTdWJzY3JpYmVyIGV4dGVuZHMgU3RyZWFtTWFuYWdlciB7XG5cbiAgICBwcml2YXRlIHByb3BlcnRpZXM6IFN1YnNjcmliZXJQcm9wZXJ0aWVzO1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHN0cmVhbTogU3RyZWFtLCB0YXJnRWw6IHN0cmluZyB8IEhUTUxFbGVtZW50LCBwcm9wZXJ0aWVzOiBTdWJzY3JpYmVyUHJvcGVydGllcykge1xuICAgICAgICBzdXBlcihzdHJlYW0sIHRhcmdFbCk7XG4gICAgICAgIHRoaXMuZWxlbWVudCA9IHRoaXMudGFyZ2V0RWxlbWVudDtcbiAgICAgICAgdGhpcy5zdHJlYW0gPSBzdHJlYW07XG4gICAgICAgIHRoaXMucHJvcGVydGllcyA9IHByb3BlcnRpZXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU3Vic2NyaWJlIG9yIHVuc3Vic2NyaWJlIGZyb20gdGhlIGF1ZGlvIHN0cmVhbSAoaWYgYXZhaWxhYmxlKS4gQ2FsbGluZyB0aGlzIG1ldGhvZCB0d2ljZSBpbiBhIHJvdyBwYXNzaW5nIHNhbWUgdmFsdWUgd2lsbCBoYXZlIG5vIGVmZmVjdFxuICAgICAqIEBwYXJhbSB2YWx1ZSBgdHJ1ZWAgdG8gc3Vic2NyaWJlIHRvIHRoZSBhdWRpbyBzdHJlYW0sIGBmYWxzZWAgdG8gdW5zdWJzY3JpYmUgZnJvbSBpdFxuICAgICAqL1xuICAgIHN1YnNjcmliZVRvQXVkaW8odmFsdWU6IGJvb2xlYW4pOiBTdWJzY3JpYmVyIHtcbiAgICAgICAgdGhpcy5zdHJlYW0uZ2V0TWVkaWFTdHJlYW0oKS5nZXRBdWRpb1RyYWNrcygpLmZvckVhY2goKHRyYWNrKSA9PiB7XG4gICAgICAgICAgICB0cmFjay5lbmFibGVkID0gdmFsdWU7XG4gICAgICAgIH0pO1xuICAgICAgICBjb25zb2xlLmluZm8oXCInU3Vic2NyaWJlcicgaGFzIFwiICsgKHZhbHVlID8gJ3N1YnNjcmliZWQgdG8nIDogJ3Vuc3Vic2NyaWJlZCBmcm9tJykgKyAnIGl0cyBhdWRpbyBzdHJlYW0nKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU3Vic2NyaWJlIG9yIHVuc3Vic2NyaWJlIGZyb20gdGhlIHZpZGVvIHN0cmVhbSAoaWYgYXZhaWxhYmxlKS4gQ2FsbGluZyB0aGlzIG1ldGhvZCB0d2ljZSBpbiBhIHJvdyBwYXNzaW5nIHNhbWUgdmFsdWUgd2lsbCBoYXZlIG5vIGVmZmVjdFxuICAgICAqIEBwYXJhbSB2YWx1ZSBgdHJ1ZWAgdG8gc3Vic2NyaWJlIHRvIHRoZSB2aWRlbyBzdHJlYW0sIGBmYWxzZWAgdG8gdW5zdWJzY3JpYmUgZnJvbSBpdFxuICAgICAqL1xuICAgIHN1YnNjcmliZVRvVmlkZW8odmFsdWU6IGJvb2xlYW4pOiBTdWJzY3JpYmVyIHtcbiAgICAgICAgdGhpcy5zdHJlYW0uZ2V0TWVkaWFTdHJlYW0oKS5nZXRWaWRlb1RyYWNrcygpLmZvckVhY2goKHRyYWNrKSA9PiB7XG4gICAgICAgICAgICB0cmFjay5lbmFibGVkID0gdmFsdWU7XG4gICAgICAgIH0pO1xuICAgICAgICBjb25zb2xlLmluZm8oXCInU3Vic2NyaWJlcicgaGFzIFwiICsgKHZhbHVlID8gJ3N1YnNjcmliZWQgdG8nIDogJ3Vuc3Vic2NyaWJlZCBmcm9tJykgKyAnIGl0cyB2aWRlbyBzdHJlYW0nKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5leHBvcnQgZW51bSBMb2NhbFJlY29yZGVyU3RhdGUge1xuICAgIFJFQURZID0gJ1JFQURZJyxcbiAgICBSRUNPUkRJTkcgPSAnUkVDT1JESU5HJyxcbiAgICBQQVVTRUQgPSAnUEFVU0VEJyxcbiAgICBGSU5JU0hFRCA9ICdGSU5JU0hFRCdcbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbi8qKlxuICogRGVmaW5lcyBwcm9wZXJ0eSBbW09wZW5WaWR1RXJyb3IubmFtZV1dXG4gKi9cbmV4cG9ydCBlbnVtIE9wZW5WaWR1RXJyb3JOYW1lIHtcblxuICAgIC8qKlxuICAgICAqIEJyb3dzZXIgaXMgbm90IHN1cHBvcnRlZCBieSBPcGVuVmlkdS5cbiAgICAgKiBSZXR1cm5lZCB1cG9uIHVuc3VjY2Vzc2Z1bCBbW1Nlc3Npb24uY29ubmVjdF1dXG4gICAgICovXG4gICAgQlJPV1NFUl9OT1RfU1VQUE9SVEVEID0gJ0JST1dTRVJfTk9UX1NVUFBPUlRFRCcsXG5cbiAgICAvKipcbiAgICAgKiBUaGUgdXNlciBoYXNuJ3QgZ3JhbnRlZCBwZXJtaXNzaW9ucyB0byB0aGUgcmVxdWlyZWQgaW5wdXQgZGV2aWNlIHdoZW4gdGhlIGJyb3dzZXIgYXNrZWQgZm9yIHRoZW0uXG4gICAgICogUmV0dXJuZWQgdXBvbiB1bnN1Y2Nlc3NmdWwgW1tPcGVuVmlkdS5pbml0UHVibGlzaGVyXV0gb3IgW1tPcGVuVmlkdS5nZXRVc2VyTWVkaWFdXVxuICAgICAqL1xuICAgIERFVklDRV9BQ0NFU1NfREVOSUVEID0gJ0RFVklDRV9BQ0NFU1NfREVOSUVEJyxcblxuICAgIC8qKlxuICAgICAqIFRoZSB1c2VyIGhhc24ndCBncmFudGVkIHBlcm1pc3Npb25zIHRvIGNhcHR1cmUgc29tZSBkZXNrdG9wIHNjcmVlbiB3aGVuIHRoZSBicm93c2VyIGFza2VkIGZvciB0aGVtLlxuICAgICAqIFJldHVybmVkIHVwb24gdW5zdWNjZXNzZnVsIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dIG9yIFtbT3BlblZpZHUuZ2V0VXNlck1lZGlhXV1cbiAgICAgKi9cbiAgICBTQ1JFRU5fQ0FQVFVSRV9ERU5JRUQgPSAnU0NSRUVOX0NBUFRVUkVfREVOSUVEJyxcblxuICAgIC8qKlxuICAgICAqIEJyb3dzZXIgZG9lcyBub3Qgc3VwcG9ydCBzY3JlZW4gc2hhcmluZy5cbiAgICAgKiBSZXR1cm5lZCB1cG9uIHVuc3VjY2Vzc2Z1bCBbW09wZW5WaWR1LmluaXRQdWJsaXNoZXJdXVxuICAgICAqL1xuICAgIFNDUkVFTl9TSEFSSU5HX05PVF9TVVBQT1JURUQgPSAnU0NSRUVOX1NIQVJJTkdfTk9UX1NVUFBPUlRFRCcsXG5cbiAgICAvKipcbiAgICAgKiBPbmx5IGZvciBDaHJvbWUsIHRoZXJlJ3Mgbm8gc2NyZWVuIHNoYXJpbmcgZXh0ZW5zaW9uIGluc3RhbGxlZFxuICAgICAqIFJldHVybmVkIHVwb24gdW5zdWNjZXNzZnVsIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dXG4gICAgICovXG4gICAgU0NSRUVOX0VYVEVOU0lPTl9OT1RfSU5TVEFMTEVEID0gJ1NDUkVFTl9FWFRFTlNJT05fTk9UX0lOU1RBTExFRCcsXG5cbiAgICAvKipcbiAgICAgKiBPbmx5IGZvciBDaHJvbWUsIHRoZSBzY3JlZW4gc2hhcmluZyBleHRlbnNpb24gaXMgaW5zdGFsbGVkIGJ1dCBpcyBkaXNhYmxlZFxuICAgICAqIFJldHVybmVkIHVwb24gdW5zdWNjZXNzZnVsIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dXG4gICAgICovXG4gICAgU0NSRUVOX0VYVEVOU0lPTl9ESVNBQkxFRCA9ICdTQ1JFRU5fRVhURU5TSU9OX0RJU0FCTEVEJyxcblxuICAgIC8qKlxuICAgICAqIE5vIHZpZGVvIGlucHV0IGRldmljZSBmb3VuZCB3aXRoIHRoZSBwcm92aWRlZCBkZXZpY2VJZCAocHJvcGVydHkgW1tQdWJsaXNoZXJQcm9wZXJ0aWVzLnZpZGVvU291cmNlXV0pXG4gICAgICogUmV0dXJuZWQgdXBvbiB1bnN1Y2Nlc3NmdWwgW1tPcGVuVmlkdS5pbml0UHVibGlzaGVyXV1cbiAgICAgKi9cbiAgICBJTlBVVF9WSURFT19ERVZJQ0VfTk9UX0ZPVU5EID0gJ0lOUFVUX1ZJREVPX0RFVklDRV9OT1RfRk9VTkQnLFxuXG4gICAgLyoqXG4gICAgICogTm8gYXVkaW8gaW5wdXQgZGV2aWNlIGZvdW5kIHdpdGggdGhlIHByb3ZpZGVkIGRldmljZUlkIChwcm9wZXJ0eSBbW1B1Ymxpc2hlclByb3BlcnRpZXMuYXVkaW9Tb3VyY2VdXSlcbiAgICAgKiBSZXR1cm5lZCB1cG9uIHVuc3VjY2Vzc2Z1bCBbW09wZW5WaWR1LmluaXRQdWJsaXNoZXJdXVxuICAgICAqL1xuICAgIElOUFVUX0FVRElPX0RFVklDRV9OT1RfRk9VTkQgPSAnSU5QVVRfQVVESU9fREVWSUNFX05PVF9GT1VORCcsXG5cbiAgICAvKipcbiAgICAgKiBNZXRob2QgW1tPcGVuVmlkdS5pbml0UHVibGlzaGVyXV0gaGFzIGJlZW4gY2FsbGVkIHdpdGggcHJvcGVydGllcyBgdmlkZW9Tb3VyY2VgIGFuZCBgYXVkaW9Tb3VyY2VgIG9mXG4gICAgICogW1tQdWJsaXNoZXJQcm9wZXJ0aWVzXV0gcGFyYW1ldGVyIGJvdGggc2V0IHRvICpmYWxzZSogb3IgKm51bGwqXG4gICAgICovXG4gICAgTk9fSU5QVVRfU09VUkNFX1NFVCA9ICdOT19JTlBVVF9TT1VSQ0VfU0VUJyxcblxuICAgIC8qKlxuICAgICAqIFNvbWUgbWVkaWEgcHJvcGVydHkgb2YgW1tQdWJsaXNoZXJQcm9wZXJ0aWVzXV0gc3VjaCBhcyBgZnJhbWVSYXRlYCBvciBgcmVzb2x1dGlvbmAgaXMgbm90IHN1cHBvcnRlZFxuICAgICAqIGJ5IHRoZSBpbnB1dCBkZXZpY2VzICh3aGVuZXZlciBpdCBpcyBwb3NzaWJsZSB0aGV5IGFyZSBhdXRvbWF0aWNhbGx5IGFkanVzdGVkIHRvIHRoZSBtb3N0IHNpbWlsYXIgdmFsdWUpLlxuICAgICAqIFJldHVybmVkIHVwb24gdW5zdWNjZXNzZnVsIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dXG4gICAgICovXG4gICAgUFVCTElTSEVSX1BST1BFUlRJRVNfRVJST1IgPSAnUFVCTElTSEVSX1BST1BFUlRJRVNfRVJST1InLFxuXG4gICAgLyoqXG4gICAgICogVGhlIGNsaWVudCB0cmllZCB0byBjYWxsIGEgbWV0aG9kIHdpdGhvdXQgdGhlIHJlcXVpcmVkIHBlcm1pc3Npb25zLiBUaGlzIGNhbiBvY2N1ciBmb3IgbWV0aG9kcyBbW1Nlc3Npb24ucHVibGlzaF1dLFxuICAgICAqIFtbU2Vzc2lvbi5mb3JjZVVucHVibGlzaF1dIGFuZCBbW1Nlc3Npb24uZm9yY2VEaXNjb25uZWN0XV1cbiAgICAgKi9cbiAgICBPUEVOVklEVV9QRVJNSVNTSU9OX0RFTklFRCA9ICdPUEVOVklEVV9QRVJNSVNTSU9OX0RFTklFRCcsXG5cbiAgICAvKipcbiAgICAgKiBfTm90IGluIHVzZSB5ZXRfXG4gICAgICovXG4gICAgT1BFTlZJRFVfTk9UX0NPTk5FQ1RFRCA9ICdPUEVOVklEVV9OT1RfQ09OTkVDVEVEJyxcblxuICAgIC8qKlxuICAgICAqIF9Ob3QgaW4gdXNlIHlldF9cbiAgICAgKi9cbiAgICBHRU5FUklDX0VSUk9SID0gJ0dFTkVSSUNfRVJST1InXG59XG5cbi8qKlxuICogU2ltcGxlIG9iamVjdCB0byBpZGVudGlmeSBydW50aW1lIGVycm9ycyBvbiB0aGUgY2xpZW50IHNpZGVcbiAqL1xuZXhwb3J0IGNsYXNzIE9wZW5WaWR1RXJyb3Ige1xuXG4gICAgbmFtZTogT3BlblZpZHVFcnJvck5hbWU7XG4gICAgbWVzc2FnZTogc3RyaW5nO1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKG5hbWU6IE9wZW5WaWR1RXJyb3JOYW1lLCBtZXNzYWdlOiBzdHJpbmcpIHtcbiAgICAgICAgdGhpcy5uYW1lID0gbmFtZTtcbiAgICAgICAgdGhpcy5tZXNzYWdlID0gbWVzc2FnZTtcbiAgICB9XG5cbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbi8qKlxuICogSG93IHRoZSB2aWRlbyB3aWxsIGJlIGluc2VydGVkIGluIHRoZSBET00gZm9yIFB1Ymxpc2hlcnMgYW5kIFN1YnNjcmliZXJzLiBTZWUgW1tQdWJsaXNoZXJQcm9wZXJ0aWVzLmluc2VydE1vZGVdXSBhbmQgW1tTdWJzY3JpYmVyUHJvcGVydGllcy5pbnNlcnRNb2RlXV1cbiAqL1xuZXhwb3J0IGVudW0gVmlkZW9JbnNlcnRNb2RlIHtcblxuICAgIC8qKlxuICAgICAqIFZpZGVvIGluc2VydGVkIGFmdGVyIHRoZSB0YXJnZXQgZWxlbWVudCAoYXMgbmV4dCBzaWJsaW5nKVxuICAgICAqL1xuICAgIEFGVEVSID0gJ0FGVEVSJyxcbiAgICAvKipcbiAgICAgKiBWaWRlbyBpbnNlcnRlZCBhcyBsYXN0IGNoaWxkIG9mIHRoZSB0YXJnZXQgZWxlbWVudFxuICAgICAqL1xuICAgIEFQUEVORCA9ICdBUFBFTkQnLFxuICAgIC8qKlxuICAgICAqIFZpZGVvIGluc2VydGVkIGJlZm9yZSB0aGUgdGFyZ2V0IGVsZW1lbnQgKGFzIHByZXZpb3VzIHNpYmxpbmcpXG4gICAgICovXG4gICAgQkVGT1JFID0gJ0JFRk9SRScsXG4gICAgLyoqXG4gICAgICogVmlkZW8gaW5zZXJ0ZWQgYXMgZmlyc3QgY2hpbGQgb2YgdGhlIHRhcmdldCBlbGVtZW50XG4gICAgICovXG4gICAgUFJFUEVORCA9ICdQUkVQRU5EJyxcbiAgICAvKipcbiAgICAgKiBWaWRlbyByZXBsYWNlcyB0YXJnZXQgZWxlbWVudFxuICAgICAqL1xuICAgIFJFUExBQ0UgPSAnUkVQTEFDRSdcblxufSIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTctMjAxOCBPcGVuVmlkdSAoaHR0cHM6Ly9vcGVudmlkdS5pby8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuaW1wb3J0IHsgRXZlbnQgfSBmcm9tICcuL0V2ZW50JztcbmltcG9ydCB7IENvbm5lY3Rpb24gfSBmcm9tICcuLi8uLi9PcGVuVmlkdS9Db25uZWN0aW9uJztcbmltcG9ydCB7IFNlc3Npb24gfSBmcm9tICcuLi8uLi9PcGVuVmlkdS9TZXNzaW9uJztcblxuXG4vKipcbiAqIERlZmluZXMgdGhlIGZvbGxvd2luZyBldmVudHM6XG4gKiAtIGBjb25uZWN0aW9uQ3JlYXRlZGA6IGRpc3BhdGNoZWQgYnkgW1tTZXNzaW9uXV1cbiAqIC0gYGNvbm5lY3Rpb25EZXN0cm95ZWRgOiBkaXNwYXRjaGVkIGJ5IFtbU2Vzc2lvbl1dXG4gKi9cbmV4cG9ydCBjbGFzcyBDb25uZWN0aW9uRXZlbnQgZXh0ZW5kcyBFdmVudCB7XG5cbiAgICAvKipcbiAgICAgKiBDb25uZWN0aW9uIG9iamVjdCB0aGF0IHdhcyBjcmVhdGVkIG9yIGRlc3Ryb3llZFxuICAgICAqL1xuICAgIGNvbm5lY3Rpb246IENvbm5lY3Rpb247XG5cbiAgICAvKipcbiAgICAgKiBGb3IgJ2Nvbm5lY3Rpb25EZXN0cm95ZWQnIGV2ZW50OlxuICAgICAqIC0gXCJkaXNjb25uZWN0XCI6IHRoZSByZW1vdGUgdXNlciBoYXMgY2FsbGVkIGBTZXNzaW9uLmRpc2Nvbm5lY3QoKWBcbiAgICAgKiAtIFwiZm9yY2VEaXNjb25uZWN0QnlVc2VyXCI6IHRoZSByZW1vdGUgdXNlciBoYXMgYmVlbiBldmljdGVkIGZyb20gdGhlIFNlc3Npb24gYnkgb3RoZXIgdXNlciBjYWxsaW5nIGBTZXNzaW9uLmZvcmNlRGlzY29ubmVjdCgpYFxuICAgICAqIC0gXCJmb3JjZURpc2Nvbm5lY3RCeVNlcnZlclwiOiB0aGUgcmVtb3RlIHVzZXIgaGFzIGJlZW4gZXZpY3RlZCBmcm9tIHRoZSBTZXNzaW9uIGJ5IHRoZSBhcHBsaWNhdGlvblxuICAgICAqIC0gXCJzZXNzaW9uQ2xvc2VkQnlTZXJ2ZXJcIjogdGhlIFNlc3Npb24gaGFzIGJlZW4gY2xvc2VkIGJ5IHRoZSBhcHBsaWNhdGlvblxuICAgICAqIC0gXCJuZXR3b3JrRGlzY29ubmVjdFwiOiB0aGUgcmVtb3RlIHVzZXIgbmV0d29yayBjb25uZWN0aW9uIGhhcyBkcm9wcGVkXG4gICAgICpcbiAgICAgKiBGb3IgJ2Nvbm5lY3Rpb25DcmVhdGVkJyBlbXB0eSBzdHJpbmdcbiAgICAgKi9cbiAgICByZWFzb246IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3RvcihjYW5jZWxhYmxlOiBib29sZWFuLCB0YXJnZXQ6IFNlc3Npb24sIHR5cGU6IHN0cmluZywgY29ubmVjdGlvbjogQ29ubmVjdGlvbiwgcmVhc29uOiBzdHJpbmcpIHtcbiAgICAgICAgc3VwZXIoY2FuY2VsYWJsZSwgdGFyZ2V0LCB0eXBlKTtcbiAgICAgICAgdGhpcy5jb25uZWN0aW9uID0gY29ubmVjdGlvbjtcbiAgICAgICAgdGhpcy5yZWFzb24gPSByZWFzb247XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZTpuby1lbXB0eVxuICAgIGNhbGxEZWZhdWx0QmVoYXZpb3IoKSB7IH1cblxufSIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTctMjAxOCBPcGVuVmlkdSAoaHR0cHM6Ly9vcGVudmlkdS5pby8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuaW1wb3J0IHsgU3RyZWFtTWFuYWdlciB9IGZyb20gJy4uLy4uL09wZW5WaWR1L1N0cmVhbU1hbmFnZXInO1xuaW1wb3J0IHsgU2Vzc2lvbiB9IGZyb20gJy4uLy4uL09wZW5WaWR1L1Nlc3Npb24nO1xuXG5leHBvcnQgYWJzdHJhY3QgY2xhc3MgRXZlbnQge1xuXG4gICAgLyoqXG4gICAgICogV2hldGhlciB0aGUgZXZlbnQgaGFzIGEgZGVmYXVsdCBiZWhhdmlvciB0aGF0IG1heSBiZSBwcmV2ZW50ZWQgYnkgY2FsbGluZyBbW0V2ZW50LnByZXZlbnREZWZhdWx0XV1cbiAgICAgKi9cbiAgICBjYW5jZWxhYmxlOiBib29sZWFuO1xuXG4gICAgLyoqXG4gICAgICogVGhlIG9iamVjdCB0aGF0IGRpc3BhdGNoZWQgdGhlIGV2ZW50XG4gICAgICovXG4gICAgdGFyZ2V0OiBTZXNzaW9uIHwgU3RyZWFtTWFuYWdlcjtcblxuICAgIC8qKlxuICAgICAqIFRoZSB0eXBlIG9mIGV2ZW50LiBUaGlzIGlzIHRoZSBzYW1lIHN0cmluZyB5b3UgcGFzcyBhcyBmaXJzdCBwYXJhbWV0ZXIgd2hlbiBjYWxsaW5nIG1ldGhvZCBgb24oKWAgb2YgYW55IG9iamVjdCBpbXBsZW1lbnRpbmcgW1tFdmVudERpc3BhdGNoZXJdXSBpbnRlcmZhY2VcbiAgICAgKi9cbiAgICB0eXBlOiBzdHJpbmc7XG5cbiAgICBwcml2YXRlIGhhc0JlZW5QcmV2ZW50ZWQgPSBmYWxzZTtcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3RvcihjYW5jZWxhYmxlOiBib29sZWFuLCB0YXJnZXQ6IFNlc3Npb24gfCBTdHJlYW1NYW5hZ2VyLCB0eXBlOiBzdHJpbmcpIHtcbiAgICAgICAgdGhpcy5jYW5jZWxhYmxlID0gY2FuY2VsYWJsZTtcbiAgICAgICAgdGhpcy50YXJnZXQgPSB0YXJnZXQ7XG4gICAgICAgIHRoaXMudHlwZSA9IHR5cGU7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogV2hldGhlciB0aGUgZGVmYXVsdCBiZWFoaXZvdXIgb2YgdGhlIGV2ZW50IGhhcyBiZWVuIHByZXZlbnRlZCBvciBub3QuIENhbGwgW1tFdmVudC5wcmV2ZW50RGVmYXVsdF1dIHRvIHByZXZlbnQgaXRcbiAgICAgKi9cbiAgICBpc0RlZmF1bHRQcmV2ZW50ZWQoKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiB0aGlzLmhhc0JlZW5QcmV2ZW50ZWQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUHJldmVudHMgdGhlIGRlZmF1bHQgYmVoYXZpb3Igb2YgdGhlIGV2ZW50LiBUaGUgZm9sbG93aW5nIGV2ZW50cyBoYXZlIGEgZGVmYXVsdCBiZWhhdmlvcjpcbiAgICAgKlxuICAgICAqIC0gYHNlc3Npb25EaXNjb25uZWN0ZWRgOiBkaXNwYXRjaGVkIGJ5IFtbU2Vzc2lvbl1dIG9iamVjdCwgYXV0b21hdGljYWxseSB1bnN1YnNjcmliZXMgdGhlIGxlYXZpbmcgcGFydGljaXBhbnQgZnJvbSBldmVyeSBTdWJzY3JpYmVyIG9iamVjdCBvZiB0aGUgc2Vzc2lvbiAodGhpcyBpbmNsdWRlcyBjbG9zaW5nIHRoZSBXZWJSVENQZWVyIGNvbm5lY3Rpb24gYW5kIGRpc3Bvc2luZyBhbGwgTWVkaWFTdHJlYW1UcmFja3MpXG4gICAgICogYW5kIGFsc28gZGVsZXRlcyBhbnkgSFRNTCB2aWRlbyBlbGVtZW50IGFzc29jaWF0ZWQgdG8gZWFjaCBTdWJzY3JpYmVyIChvbmx5IHRob3NlIGNyZWF0ZWQgYnkgT3BlblZpZHUgQnJvd3NlciwgZWl0aGVyIGJ5IHBhc3NpbmcgYSB2YWxpZCBwYXJhbWV0ZXIgYXMgYHRhcmdldEVsZW1lbnRgIGluIG1ldGhvZCBbW1Nlc3Npb24uc3Vic2NyaWJlXV0gb3JcbiAgICAgKiBieSBjYWxsaW5nIFtbU3Vic2NyaWJlci5jcmVhdGVWaWRlb0VsZW1lbnRdXSkuIEZvciBldmVyeSB2aWRlbyByZW1vdmVkLCBlYWNoIFN1YnNjcmliZXIgb2JqZWN0IHdpbGwgYWxzbyBkaXNwYXRjaCBhIGB2aWRlb0VsZW1lbnREZXN0cm95ZWRgIGV2ZW50LlxuICAgICAqXG4gICAgICogLSBgc3RyZWFtRGVzdHJveWVkYDpcbiAgICAgKiAgIC0gSWYgZGlzcGF0Y2hlZCBieSBhIFtbUHVibGlzaGVyXV0gKCp5b3UqIGhhdmUgdW5wdWJsaXNoZWQpOiBhdXRvbWF0aWNhbGx5IHN0b3BzIGFsbCBtZWRpYSB0cmFja3MgYW5kIGRlbGV0ZXMgYW55IEhUTUwgdmlkZW8gZWxlbWVudCBhc3NvY2lhdGVkIHRvIGl0IChvbmx5IHRob3NlIGNyZWF0ZWQgYnkgT3BlblZpZHUgQnJvd3NlciwgZWl0aGVyIGJ5IHBhc3NpbmcgYSB2YWxpZCBwYXJhbWV0ZXIgYXMgYHRhcmdldEVsZW1lbnRgXG4gICAgICogaW4gbWV0aG9kIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dIG9yIGJ5IGNhbGxpbmcgW1tQdWJsaXNoZXIuY3JlYXRlVmlkZW9FbGVtZW50XV0pLiBGb3IgZXZlcnkgdmlkZW8gcmVtb3ZlZCwgdGhlIFB1Ymxpc2hlciBvYmplY3Qgd2lsbCBhbHNvIGRpc3BhdGNoIGEgYHZpZGVvRWxlbWVudERlc3Ryb3llZGAgZXZlbnQuXG4gICAgICogICAtIElmIGRpc3BhdGNoZWQgYnkgW1tTZXNzaW9uXV0gKCpvdGhlciB1c2VyKiBoYXMgdW5wdWJsaXNoZWQpOiBhdXRvbWF0aWNhbGx5IHVuc3Vic2NyaWJlcyB0aGUgcHJvcGVyIFN1YnNjcmliZXIgb2JqZWN0IGZyb20gdGhlIHNlc3Npb24gKHRoaXMgaW5jbHVkZXMgY2xvc2luZyB0aGUgV2ViUlRDUGVlciBjb25uZWN0aW9uIGFuZCBkaXNwb3NpbmcgYWxsIE1lZGlhU3RyZWFtVHJhY2tzKVxuICAgICAqIGFuZCBhbHNvIGRlbGV0ZXMgYW55IEhUTUwgdmlkZW8gZWxlbWVudCBhc3NvY2lhdGVkIHRvIHRoYXQgU3Vic2NyaWJlciAob25seSB0aG9zZSBjcmVhdGVkIGJ5IE9wZW5WaWR1IEJyb3dzZXIsIGVpdGhlciBieSBwYXNzaW5nIGEgdmFsaWQgcGFyYW1ldGVyIGFzIGB0YXJnZXRFbGVtZW50YCBpbiBtZXRob2QgW1tTZXNzaW9uLnN1YnNjcmliZV1dIG9yXG4gICAgICogYnkgY2FsbGluZyBbW1N1YnNjcmliZXIuY3JlYXRlVmlkZW9FbGVtZW50XV0pLiBGb3IgZXZlcnkgdmlkZW8gcmVtb3ZlZCwgdGhlIFN1YnNjcmliZXIgb2JqZWN0IHdpbGwgYWxzbyBkaXNwYXRjaCBhIGB2aWRlb0VsZW1lbnREZXN0cm95ZWRgIGV2ZW50LlxuICAgICAqL1xuICAgIHByZXZlbnREZWZhdWx0KCkge1xuICAgICAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6bm8tZW1wdHlcbiAgICAgICAgdGhpcy5jYWxsRGVmYXVsdEJlaGF2aW9yID0gKCkgPT4geyB9O1xuICAgICAgICB0aGlzLmhhc0JlZW5QcmV2ZW50ZWQgPSB0cnVlO1xuICAgIH1cblxuICAgIHByb3RlY3RlZCBhYnN0cmFjdCBjYWxsRGVmYXVsdEJlaGF2aW9yKCk7XG5cbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IEV2ZW50IH0gZnJvbSAnLi9FdmVudCc7XG5pbXBvcnQgeyBDb25uZWN0aW9uIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvQ29ubmVjdGlvbic7XG5pbXBvcnQgeyBTZXNzaW9uIH0gZnJvbSAnLi4vLi4nO1xuXG5cbi8qKlxuICogRGVmaW5lcyB0aGUgZm9sbG93aW5nIGV2ZW50czpcbiAqIC0gYHB1Ymxpc2hlclN0YXJ0U3BlYWtpbmdgOiBkaXNwYXRjaGVkIGJ5IFtbU2Vzc2lvbl1dXG4gKiAtIGBwdWJsaXNoZXJTdG9wU3BlYWtpbmdgOiBkaXNwYXRjaGVkIGJ5IFtbU2Vzc2lvbl1dXG4gKlxuICogTW9yZSBpbmZvcm1hdGlvbjpcbiAqIC0gVGhpcyBldmVudHMgd2lsbCBvbmx5IGJlIHRyaWdnZXJlZCBmb3IgKipyZW1vdGUgc3RyZWFtcyB0aGF0IGhhdmUgYXVkaW8gdHJhY2tzKipcbiAqIC0gQm90aCBldmVudHMgc2hhcmUgdGhlIHNhbWUgbGlmZWN5Y2xlLiBUaGF0IG1lYW5zIHRoYXQgeW91IGNhbiBzdWJzY3JpYmUgdG8gb25seSBvbmUgb2YgdGhlbSBpZiB5b3Ugd2FudCwgYnV0IGlmIHlvdSBjYWxsIGBTZXNzaW9uLm9mZigncHVibGlzaGVyU3RvcFNwZWFraW5nJylgLFxuICoga2VlcCBpbiBtaW5kIHRoYXQgdGhpcyB3aWxsIGFsc28gaW50ZXJuYWxseSByZW1vdmUgYW55ICdwdWJsaXNoZXJTdGFydFNwZWFraW5nJyBldmVudFxuICogLSBZb3UgY2FuIGZ1cnRoZXIgY29uZmlndXJlIGhvdyB0aGUgZXZlbnRzIGFyZSBkaXNwYXRjaGVkIGJ5IHNldHRpbmcgcHJvcGVydHkgYHB1Ymxpc2hlclNwZWFraW5nRXZlbnRzT3B0aW9uc2AgaW4gdGhlIGNhbGwgb2YgW1tPcGVuVmlkdS5zZXRBZHZhbmNlZENvbmZpZ3VyYXRpb25dXVxuICovXG5leHBvcnQgY2xhc3MgUHVibGlzaGVyU3BlYWtpbmdFdmVudCBleHRlbmRzIEV2ZW50IHtcblxuICAgIC8qKlxuICAgICAqIFRoZSBjbGllbnQgdGhhdCBzdGFydGVkIG9yIHN0b3BwZWQgc3BlYWtpbmdcbiAgICAgKi9cbiAgICBjb25uZWN0aW9uOiBDb25uZWN0aW9uO1xuXG4gICAgLyoqXG4gICAgICogVGhlIHN0cmVhbUlkIG9mIHRoZSBTdHJlYW0gYWZmZWN0ZWQgYnkgdGhlIHNwZWFraW5nIGV2ZW50XG4gICAgICovXG4gICAgc3RyZWFtSWQ6IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3Rvcih0YXJnZXQ6IFNlc3Npb24sIHR5cGU6IHN0cmluZywgY29ubmVjdGlvbjogQ29ubmVjdGlvbiwgc3RyZWFtSWQ6IHN0cmluZykge1xuICAgICAgICBzdXBlcihmYWxzZSwgdGFyZ2V0LCB0eXBlKTtcbiAgICAgICAgdGhpcy50eXBlID0gdHlwZTtcbiAgICAgICAgdGhpcy5jb25uZWN0aW9uID0gY29ubmVjdGlvbjtcbiAgICAgICAgdGhpcy5zdHJlYW1JZCA9IHN0cmVhbUlkO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6bm8tZW1wdHlcbiAgICBjYWxsRGVmYXVsdEJlaGF2aW9yKCkgeyB9XG5cbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IEV2ZW50IH0gZnJvbSAnLi9FdmVudCc7XG5pbXBvcnQgeyBTZXNzaW9uIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvU2Vzc2lvbic7XG5cblxuLyoqXG4gKiBEZWZpbmVzIHRoZSBmb2xsb3dpbmcgZXZlbnRzOlxuICogLSBgcmVjb3JkaW5nU3RhcnRlZGA6IGRpc3BhdGNoZWQgYnkgW1tTZXNzaW9uXV1cbiAqIC0gYHJlY29yZGluZ1N0b3BwZWRgOiBkaXNwYXRjaGVkIGJ5IFtbU2Vzc2lvbl1dXG4gKi9cbmV4cG9ydCBjbGFzcyBSZWNvcmRpbmdFdmVudCBleHRlbmRzIEV2ZW50IHtcblxuICAgIC8qKlxuICAgICAqIFRoZSByZWNvcmRpbmcgSUQgZ2VuZXJhdGVkIGluIG9wZW52aWR1LXNlcnZlclxuICAgICAqL1xuICAgIGlkOiBzdHJpbmc7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgcmVjb3JkaW5nIG5hbWUgeW91IHN1cHBsaWVkIHRvIG9wZW52aWR1LXNlcnZlci4gRm9yIGV4YW1wbGUsIHRvIG5hbWUgeW91ciByZWNvcmRpbmcgZmlsZSBNWV9SRUNPUkRJTkc6XG4gICAgICogLSBXaXRoICoqQVBJIFJFU1QqKjogUE9TVCB0byBgL2FwaS9yZWNvcmRpbmdzL3N0YXJ0YCBwYXNzaW5nIEpTT04gYm9keSBge1wic2Vzc2lvblwiOlwic2Vzc2lvbklkXCIsXCJuYW1lXCI6XCJNWV9SRUNPUkRJTkdcIn1gXG4gICAgICogLSBXaXRoICoqb3BlbnZpZHUtamF2YS1jbGllbnQqKjogYE9wZW5WaWR1LnN0YXJ0UmVjb3JkaW5nKHNlc3Npb25JZCwgXCJNWV9SRUNPUkRJTkdcIilgIG9yIGBPcGVuVmlkdS5zdGFydFJlY29yZGluZyhzZXNzaW9uSWQsIG5ldyBSZWNvcmRpbmdQcm9wZXJ0aWVzLkJ1aWxkZXIoKS5uYW1lKFwiTVlfUkVDT1JESU5HXCIpLmJ1aWxkKCkpYFxuICAgICAqIC0gV2l0aCAqKm9wZW52aWR1LW5vZGUtY2xpZW50Kio6IGBPcGVuVmlkdS5zdGFydFJlY29yZGluZyhzZXNzaW9uSWQsIFwiTVlfUkVDT1JESU5HXCIpYCBvciBgT3BlblZpZHUuc3RhcnRSZWNvcmRpbmcoc2Vzc2lvbklkLCB7bmFtZTogXCJNWV9SRUNPUkRJTkdcIn0pYFxuICAgICAqXG4gICAgICogSWYgbm8gbmFtZSBpcyBzdXBwbGllZCwgdGhpcyBwcm9wZXJ0eSB3aWxsIGJlIHVuZGVmaW5lZCBhbmQgdGhlIHJlY29yZGVkIGZpbGUgd2lsbCBiZSBuYW1lZCBhZnRlciBwcm9wZXJ0eSBbW2lkXV1cbiAgICAgKi9cbiAgICBuYW1lPzogc3RyaW5nO1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHRhcmdldDogU2Vzc2lvbiwgdHlwZTogc3RyaW5nLCBpZDogc3RyaW5nLCBuYW1lOiBzdHJpbmcpIHtcbiAgICAgICAgc3VwZXIoZmFsc2UsIHRhcmdldCwgdHlwZSk7XG4gICAgICAgIHRoaXMuaWQgPSBpZDtcbiAgICAgICAgaWYgKG5hbWUgIT09IGlkKSB7XG4gICAgICAgICAgICB0aGlzLm5hbWUgPSBuYW1lO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZTpuby1lbXB0eVxuICAgIGNhbGxEZWZhdWx0QmVoYXZpb3IoKSB7IH1cblxufSIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTctMjAxOCBPcGVuVmlkdSAoaHR0cHM6Ly9vcGVudmlkdS5pby8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuaW1wb3J0IHsgRXZlbnQgfSBmcm9tICcuL0V2ZW50JztcbmltcG9ydCB7IFNlc3Npb24gfSBmcm9tICcuLi8uLi9PcGVuVmlkdS9TZXNzaW9uJztcblxuXG4vKipcbiAqIERlZmluZXMgZXZlbnQgYHNlc3Npb25EaXNjb25uZWN0ZWRgIGRpc3BhdGNoZWQgYnkgW1tTZXNzaW9uXV1cbiAqL1xuZXhwb3J0IGNsYXNzIFNlc3Npb25EaXNjb25uZWN0ZWRFdmVudCBleHRlbmRzIEV2ZW50IHtcblxuICAgIC8qKlxuICAgICAqIC0gXCJkaXNjb25uZWN0XCI6IHlvdSBoYXZlIGNhbGxlZCBgU2Vzc2lvbi5kaXNjb25uZWN0KClgXG4gICAgICogLSBcImZvcmNlRGlzY29ubmVjdEJ5VXNlclwiOiB5b3UgaGF2ZSBiZWVuIGV2aWN0ZWQgZnJvbSB0aGUgU2Vzc2lvbiBieSBvdGhlciB1c2VyIGNhbGxpbmcgYFNlc3Npb24uZm9yY2VEaXNjb25uZWN0KClgXG4gICAgICogLSBcImZvcmNlRGlzY29ubmVjdEJ5U2VydmVyXCI6IHlvdSBoYXZlIGJlZW4gZXZpY3RlZCBmcm9tIHRoZSBTZXNzaW9uIGJ5IHRoZSBhcHBsaWNhdGlvblxuICAgICAqIC0gXCJzZXNzaW9uQ2xvc2VkQnlTZXJ2ZXJcIjogdGhlIFNlc3Npb24gaGFzIGJlZW4gY2xvc2VkIGJ5IHRoZSBhcHBsaWNhdGlvblxuICAgICAqIC0gXCJuZXR3b3JrRGlzY29ubmVjdFwiOiB5b3VyIG5ldHdvcmsgY29ubmVjdGlvbiBoYXMgZHJvcHBlZFxuICAgICAqL1xuICAgIHJlYXNvbjogc3RyaW5nO1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHRhcmdldDogU2Vzc2lvbiwgcmVhc29uOiBzdHJpbmcpIHtcbiAgICAgICAgc3VwZXIodHJ1ZSwgdGFyZ2V0LCAnc2Vzc2lvbkRpc2Nvbm5lY3RlZCcpO1xuICAgICAgICB0aGlzLnJlYXNvbiA9IHJlYXNvbjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgY2FsbERlZmF1bHRCZWhhdmlvcigpIHtcblxuICAgICAgICBjb25zb2xlLmluZm8oXCJDYWxsaW5nIGRlZmF1bHQgYmVoYXZpb3IgdXBvbiAnXCIgKyB0aGlzLnR5cGUgKyBcIicgZXZlbnQgZGlzcGF0Y2hlZCBieSAnU2Vzc2lvbidcIik7XG5cbiAgICAgICAgY29uc3Qgc2Vzc2lvbiA9IDxTZXNzaW9uPnRoaXMudGFyZ2V0O1xuXG4gICAgICAgIC8vIERpc3Bvc2UgYW5kIGRlbGV0ZSBhbGwgcmVtb3RlIENvbm5lY3Rpb25zXG4gICAgICAgIGZvciAoY29uc3QgY29ubmVjdGlvbklkIGluIHNlc3Npb24ucmVtb3RlQ29ubmVjdGlvbnMpIHtcbiAgICAgICAgICAgIGlmICghIXNlc3Npb24ucmVtb3RlQ29ubmVjdGlvbnNbY29ubmVjdGlvbklkXS5zdHJlYW0pIHtcbiAgICAgICAgICAgICAgICBzZXNzaW9uLnJlbW90ZUNvbm5lY3Rpb25zW2Nvbm5lY3Rpb25JZF0uc3RyZWFtLmRpc3Bvc2VXZWJSdGNQZWVyKCk7XG4gICAgICAgICAgICAgICAgc2Vzc2lvbi5yZW1vdGVDb25uZWN0aW9uc1tjb25uZWN0aW9uSWRdLnN0cmVhbS5kaXNwb3NlTWVkaWFTdHJlYW0oKTtcbiAgICAgICAgICAgICAgICBpZiAoc2Vzc2lvbi5yZW1vdGVDb25uZWN0aW9uc1tjb25uZWN0aW9uSWRdLnN0cmVhbS5zdHJlYW1NYW5hZ2VyKSB7XG4gICAgICAgICAgICAgICAgICAgIHNlc3Npb24ucmVtb3RlQ29ubmVjdGlvbnNbY29ubmVjdGlvbklkXS5zdHJlYW0uc3RyZWFtTWFuYWdlci5yZW1vdmVBbGxWaWRlb3MoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZGVsZXRlIHNlc3Npb24ucmVtb3RlU3RyZWFtc0NyZWF0ZWRbc2Vzc2lvbi5yZW1vdGVDb25uZWN0aW9uc1tjb25uZWN0aW9uSWRdLnN0cmVhbS5zdHJlYW1JZF07XG4gICAgICAgICAgICAgICAgc2Vzc2lvbi5yZW1vdGVDb25uZWN0aW9uc1tjb25uZWN0aW9uSWRdLmRpc3Bvc2UoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGRlbGV0ZSBzZXNzaW9uLnJlbW90ZUNvbm5lY3Rpb25zW2Nvbm5lY3Rpb25JZF07XG4gICAgICAgIH1cbiAgICB9XG5cbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IEV2ZW50IH0gZnJvbSAnLi9FdmVudCc7XG5pbXBvcnQgeyBDb25uZWN0aW9uIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvQ29ubmVjdGlvbic7XG5pbXBvcnQgeyBTZXNzaW9uIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvU2Vzc2lvbic7XG5cblxuLyoqXG4gKiBEZWZpbmVzIHRoZSBmb2xsb3dpbmcgZXZlbnRzOlxuICogLSBgc2lnbmFsYDogZGlzcGF0Y2hlZCBieSBbW1Nlc3Npb25dXVxuICogLSBgc2lnbmFsOlRZUEVgOiBkaXNwYXRjaGVkIGJ5IFtbU2Vzc2lvbl1dXG4gKi9cbmV4cG9ydCBjbGFzcyBTaWduYWxFdmVudCBleHRlbmRzIEV2ZW50IHtcblxuICAgIC8qKlxuICAgICAqIFRoZSB0eXBlIG9mIHNpZ25hbCAoY2FuIGJlIGVtcHR5KS5cbiAgICAgKlxuICAgICAqIFRoZSBjbGllbnQgbXVzdCBiZSBzdWJzY3JpYmVkIHRvIGBTZXNzaW9uLm9uKCdzaWduYWw6dHlwZScsIGZ1bmN0aW9uKHNpZ25hbEV2ZW50KSB7Li4ufSlgIHRvIHJlY2VpdmUgdGhpcyBvYmplY3QgaW4gdGhlIGNhbGxiYWNrLlxuICAgICAqXG4gICAgICogU3Vic2NyaWJpbmcgdG8gYFNlc3Npb24ub24oJ3NpZ25hbCcsIGZ1bmN0aW9uKHNpZ25hbEV2ZW50KSB7Li4ufSlgIHdpbGwgdHJpZ2dlciBhbGwgdHlwZXMgb2Ygc2lnbmFscy5cbiAgICAgKi9cbiAgICB0eXBlOiBzdHJpbmc7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgbWVzc2FnZSBvZiB0aGUgc2lnbmFsIChjYW4gYmUgZW10cHkpXG4gICAgICovXG4gICAgZGF0YTogc3RyaW5nO1xuXG4gICAgLyoqXG4gICAgICogVGhlIGNsaWVudCB0aGF0IHNlbnQgdGhlIHNpZ25hbFxuICAgICAqL1xuICAgIGZyb206IENvbm5lY3Rpb247XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgY29uc3RydWN0b3IodGFyZ2V0OiBTZXNzaW9uLCB0eXBlOiBzdHJpbmcsIGRhdGE6IHN0cmluZywgZnJvbTogQ29ubmVjdGlvbikge1xuICAgICAgICBzdXBlcihmYWxzZSwgdGFyZ2V0LCB0eXBlKTtcbiAgICAgICAgdGhpcy50eXBlID0gdHlwZTtcbiAgICAgICAgdGhpcy5kYXRhID0gZGF0YTtcbiAgICAgICAgdGhpcy5mcm9tID0gZnJvbTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lOm5vLWVtcHR5XG4gICAgY2FsbERlZmF1bHRCZWhhdmlvcigpIHsgfVxuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBFdmVudCB9IGZyb20gJy4vRXZlbnQnO1xuaW1wb3J0IHsgUHVibGlzaGVyIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvUHVibGlzaGVyJztcbmltcG9ydCB7IFNlc3Npb24gfSBmcm9tICcuLi8uLi9PcGVuVmlkdS9TZXNzaW9uJztcbmltcG9ydCB7IFN0cmVhbSB9IGZyb20gJy4uLy4uL09wZW5WaWR1L1N0cmVhbSc7XG5cblxuLyoqXG4gKiBEZWZpbmVzIHRoZSBmb2xsb3dpbmcgZXZlbnRzOlxuICogLSBgc3RyZWFtQ3JlYXRlZGA6IGRpc3BhdGNoZWQgYnkgW1tTZXNzaW9uXV0gYW5kIFtbUHVibGlzaGVyXV1cbiAqIC0gYHN0cmVhbURlc3Ryb3llZGA6IGRpc3BhdGNoZWQgYnkgW1tTZXNzaW9uXV0gYW5kIFtbUHVibGlzaGVyXV1cbiAqL1xuZXhwb3J0IGNsYXNzIFN0cmVhbUV2ZW50IGV4dGVuZHMgRXZlbnQge1xuXG4gICAgLyoqXG4gICAgICogU3RyZWFtIG9iamVjdCB0aGF0IHdhcyBjcmVhdGVkIG9yIGRlc3Ryb3llZFxuICAgICAqL1xuICAgIHN0cmVhbTogU3RyZWFtO1xuXG4gICAgLyoqXG4gICAgICogRm9yICdzdHJlYW1EZXN0cm95ZWQnIGV2ZW50OlxuICAgICAqIC0gXCJ1bnB1Ymxpc2hcIjogbWV0aG9kIGBTZXNzaW9uLnVucHVibGlzaCgpYCBoYXMgYmVlbiBjYWxsZWRcbiAgICAgKiAtIFwiZGlzY29ubmVjdFwiOiBtZXRob2QgYFNlc3Npb24uZGlzY29ubmVjdCgpYCBoYXMgYmVlbiBjYWxsZWRcbiAgICAgKiAtIFwiZm9yY2VVbnB1Ymxpc2hCeVVzZXJcIjogc29tZSB1c2VyIGhhcyBjYWxsZWQgYFNlc3Npb24uZm9yY2VVbnB1Ymxpc2goKWAgb3ZlciB0aGUgU3RyZWFtXG4gICAgICogLSBcImZvcmNlRGlzY29ubmVjdEJ5VXNlclwiOiBzb21lIHVzZXIgaGFzIGNhbGxlZCBgU2Vzc2lvbi5mb3JjZURpc2Nvbm5lY3QoKWAgb3ZlciB0aGUgU3RyZWFtXG4gICAgICogLSBcImZvcmNlVW5wdWJsaXNoQnlTZXJ2ZXJcIjogdGhlIHVzZXIncyBzdHJlYW0gaGFzIGJlZW4gdW5wdWJsaXNoZWQgZnJvbSB0aGUgU2Vzc2lvbiBieSB0aGUgYXBwbGljYXRpb25cbiAgICAgKiAtIFwiZm9yY2VEaXNjb25uZWN0QnlTZXJ2ZXJcIjogdGhlIHVzZXIgaGFzIGJlZW4gZXZpY3RlZCBmcm9tIHRoZSBTZXNzaW9uIGJ5IHRoZSBhcHBsaWNhdGlvblxuICAgICAqIC0gXCJzZXNzaW9uQ2xvc2VkQnlTZXJ2ZXJcIjogdGhlIFNlc3Npb24gaGFzIGJlZW4gY2xvc2VkIGJ5IHRoZSBhcHBsaWNhdGlvblxuICAgICAqIC0gXCJuZXR3b3JrRGlzY29ubmVjdFwiOiB0aGUgdXNlcidzIG5ldHdvcmsgY29ubmVjdGlvbiBoYXMgZHJvcHBlZFxuICAgICAqXG4gICAgICogRm9yICdzdHJlYW1DcmVhdGVkJyBlbXB0eSBzdHJpbmdcbiAgICAgKi9cbiAgICByZWFzb246IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3RvcihjYW5jZWxhYmxlOiBib29sZWFuLCB0YXJnZXQ6IFNlc3Npb24gfCBQdWJsaXNoZXIsIHR5cGU6IHN0cmluZywgc3RyZWFtOiBTdHJlYW0sIHJlYXNvbjogc3RyaW5nKSB7XG4gICAgICAgIHN1cGVyKGNhbmNlbGFibGUsIHRhcmdldCwgdHlwZSk7XG4gICAgICAgIHRoaXMuc3RyZWFtID0gc3RyZWFtO1xuICAgICAgICB0aGlzLnJlYXNvbiA9IHJlYXNvbjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgY2FsbERlZmF1bHRCZWhhdmlvcigpIHtcbiAgICAgICAgaWYgKHRoaXMudHlwZSA9PT0gJ3N0cmVhbURlc3Ryb3llZCcpIHtcblxuICAgICAgICAgICAgaWYgKHRoaXMudGFyZ2V0IGluc3RhbmNlb2YgU2Vzc2lvbikge1xuICAgICAgICAgICAgICAgIC8vIFJlbW90ZSBTdHJlYW1cbiAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oXCJDYWxsaW5nIGRlZmF1bHQgYmVoYXZpb3IgdXBvbiAnXCIgKyB0aGlzLnR5cGUgKyBcIicgZXZlbnQgZGlzcGF0Y2hlZCBieSAnU2Vzc2lvbidcIik7XG4gICAgICAgICAgICAgICAgdGhpcy5zdHJlYW0uZGlzcG9zZVdlYlJ0Y1BlZXIoKTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAodGhpcy50YXJnZXQgaW5zdGFuY2VvZiBQdWJsaXNoZXIpIHtcbiAgICAgICAgICAgICAgICAvLyBMb2NhbCBTdHJlYW1cbiAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oXCJDYWxsaW5nIGRlZmF1bHQgYmVoYXZpb3IgdXBvbiAnXCIgKyB0aGlzLnR5cGUgKyBcIicgZXZlbnQgZGlzcGF0Y2hlZCBieSAnUHVibGlzaGVyJ1wiKTtcbiAgICAgICAgICAgICAgICBjbGVhckludGVydmFsKCg8UHVibGlzaGVyPnRoaXMudGFyZ2V0KS5zY3JlZW5TaGFyZVJlc2l6ZUludGVydmFsKTtcbiAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbS5pc0xvY2FsU3RyZWFtUmVhZHlUb1B1Ymxpc2ggPSBmYWxzZTtcblxuICAgICAgICAgICAgICAgIC8vIERlbGV0ZSBQdWJsaXNoZXIgb2JqZWN0IGZyb20gT3BlblZpZHUgcHVibGlzaGVycyBhcnJheVxuICAgICAgICAgICAgICAgIGNvbnN0IG9wZW52aWR1UHVibGlzaGVycyA9ICg8UHVibGlzaGVyPnRoaXMudGFyZ2V0KS5vcGVudmlkdS5wdWJsaXNoZXJzO1xuICAgICAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgb3BlbnZpZHVQdWJsaXNoZXJzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChvcGVudmlkdVB1Ymxpc2hlcnNbaV0gPT09ICg8UHVibGlzaGVyPnRoaXMudGFyZ2V0KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgb3BlbnZpZHVQdWJsaXNoZXJzLnNwbGljZShpLCAxKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBEaXNwb3NlIHRoZSBNZWRpYVN0cmVhbSBsb2NhbCBvYmplY3RcbiAgICAgICAgICAgIHRoaXMuc3RyZWFtLmRpc3Bvc2VNZWRpYVN0cmVhbSgpO1xuXG4gICAgICAgICAgICAvLyBSZW1vdmUgZnJvbSBET00gYWxsIHZpZGVvIGVsZW1lbnRzIGFzc29jaWF0ZWQgdG8gdGhpcyBTdHJlYW0sIGlmIHRoZXJlJ3MgYSBTdHJlYW1NYW5hZ2VyIGRlZmluZWRcbiAgICAgICAgICAgIC8vIChtZXRob2QgU2Vzc2lvbi5zdWJzY3JpYmUgbXVzdCBoYXZlIGJlZW4gY2FsbGVkKVxuICAgICAgICAgICAgaWYgKHRoaXMuc3RyZWFtLnN0cmVhbU1hbmFnZXIpIHRoaXMuc3RyZWFtLnN0cmVhbU1hbmFnZXIucmVtb3ZlQWxsVmlkZW9zKCk7XG5cbiAgICAgICAgICAgIC8vIERlbGV0ZSBzdHJlYW0gZnJvbSBTZXNzaW9uLnJlbW90ZVN0cmVhbXNDcmVhdGVkIG1hcFxuICAgICAgICAgICAgZGVsZXRlIHRoaXMuc3RyZWFtLnNlc3Npb24ucmVtb3RlU3RyZWFtc0NyZWF0ZWRbdGhpcy5zdHJlYW0uc3RyZWFtSWRdO1xuXG4gICAgICAgICAgICAvLyBEZWxldGUgU3RyZWFtT3B0aW9uc1NlcnZlciBmcm9tIHJlbW90ZSBDb25uZWN0aW9uXG4gICAgICAgICAgICBjb25zdCByZW1vdGVDb25uZWN0aW9uID0gdGhpcy5zdHJlYW0uc2Vzc2lvbi5yZW1vdGVDb25uZWN0aW9uc1t0aGlzLnN0cmVhbS5jb25uZWN0aW9uLmNvbm5lY3Rpb25JZF07XG4gICAgICAgICAgICBpZiAoISFyZW1vdGVDb25uZWN0aW9uICYmICEhcmVtb3RlQ29ubmVjdGlvbi5vcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgY29uc3Qgc3RyZWFtT3B0aW9uc1NlcnZlciA9IHJlbW90ZUNvbm5lY3Rpb24ub3B0aW9ucy5zdHJlYW1zO1xuICAgICAgICAgICAgICAgIGZvciAobGV0IGkgPSBzdHJlYW1PcHRpb25zU2VydmVyLmxlbmd0aCAtIDE7IGkgPj0gMDsgLS1pKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChzdHJlYW1PcHRpb25zU2VydmVyW2ldLmlkID09PSB0aGlzLnN0cmVhbS5zdHJlYW1JZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgc3RyZWFtT3B0aW9uc1NlcnZlci5zcGxpY2UoaSwgMSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgfVxuICAgIH1cblxufSIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTctMjAxOCBPcGVuVmlkdSAoaHR0cHM6Ly9vcGVudmlkdS5pby8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuaW1wb3J0IHsgRXZlbnQgfSBmcm9tICcuL0V2ZW50JztcbmltcG9ydCB7IFN0cmVhbU1hbmFnZXIgfSBmcm9tICcuLi8uLi9PcGVuVmlkdS9TdHJlYW1NYW5hZ2VyJztcblxuLyoqXG4gKiBEZWZpbmVzIHRoZSBmb2xsb3dpbmcgZXZlbnRzOlxuICogLSBgc3RyZWFtUGxheWluZ2A6IGRpc3BhdGNoZWQgYnkgW1tTdHJlYW1NYW5hZ2VyXV0gKFtbUHVibGlzaGVyXV0gYW5kIFtbU3Vic2NyaWJlcl1dKVxuICovXG5leHBvcnQgY2xhc3MgU3RyZWFtTWFuYWdlckV2ZW50IGV4dGVuZHMgRXZlbnQge1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHRhcmdldDogU3RyZWFtTWFuYWdlcikge1xuICAgICAgICBzdXBlcihmYWxzZSwgdGFyZ2V0LCAnc3RyZWFtUGxheWluZycpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6bm8tZW1wdHlcbiAgICBjYWxsRGVmYXVsdEJlaGF2aW9yKCkgeyB9XG5cbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IEV2ZW50IH0gZnJvbSAnLi9FdmVudCc7XG5pbXBvcnQgeyBTZXNzaW9uIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvU2Vzc2lvbic7XG5pbXBvcnQgeyBTdHJlYW0gfSBmcm9tICcuLi8uLi9PcGVuVmlkdS9TdHJlYW0nO1xuaW1wb3J0IHsgU3RyZWFtTWFuYWdlciB9IGZyb20gJy4uLy4uL09wZW5WaWR1L1N0cmVhbU1hbmFnZXInO1xuXG4vKipcbiAqIERlZmluZXMgZXZlbnQgYHN0cmVhbVByb3BlcnR5Q2hhbmdlZGAgZGlzcGF0Y2hlZCBieSBbW1Nlc3Npb25dXSBhcyB3ZWxsIGFzIGJ5IFtbU3RyZWFtTWFuYWdlcl1dIChbW1B1Ymxpc2hlcl1dIGFuZCBbW1N1YnNjcmliZXJdXSkuXG4gKiBUaGlzIGV2ZW50IGlzIGZpcmVkIHdoZW4gYW55IHJlbW90ZSBzdHJlYW0gKG93bmVkIGJ5IGEgU3Vic2NyaWJlcikgb3IgbG9jYWwgc3RyZWFtIChvd25lZCBieSBhIFB1Ymxpc2hlcikgdW5kZXJnb2VzXG4gKiBhbnkgY2hhbmdlIGluIGFueSBvZiBpdHMgbXV0YWJsZSBwcm9wZXJ0aWVzIChzZWUgW1tjaGFuZ2VkUHJvcGVydHldXSkuXG4gKi9cbmV4cG9ydCBjbGFzcyBTdHJlYW1Qcm9wZXJ0eUNoYW5nZWRFdmVudCBleHRlbmRzIEV2ZW50IHtcblxuICAgIC8qKlxuICAgICAqIFRoZSBTdHJlYW0gd2hvc2UgcHJvcGVydHkgaGFzIGNoYW5nZWQuIFlvdSBjYW4gYWx3YXlzIGlkZW50aWZ5IHRoZSB1c2VyIHB1Ymxpc2hpbmcgdGhlIGNoYW5nZWQgc3RyZWFtIGJ5IGNvbnN1bHRpbmcgcHJvcGVydHkgW1tTdHJlYW0uY29ubmVjdGlvbl1dXG4gICAgICovXG4gICAgc3RyZWFtOiBTdHJlYW07XG5cbiAgICAvKipcbiAgICAgKiBUaGUgcHJvcGVydHkgb2YgdGhlIHN0cmVhbSB0aGF0IGNoYW5nZWQuIFRoaXMgdmFsdWUgaXMgZWl0aGVyIGBcInZpZGVvQWN0aXZlXCJgLCBgXCJhdWRpb0FjdGl2ZVwiYCBvciBgXCJ2aWRlb0RpbWVuc2lvbnNcImBcbiAgICAgKi9cbiAgICBjaGFuZ2VkUHJvcGVydHk6IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIENhdXNlIG9mIHRoZSBjaGFuZ2Ugb24gdGhlIHN0cmVhbSdzIHByb3BlcnR5OlxuICAgICAqIC0gRm9yIGB2aWRlb0FjdGl2ZWA6IGBcInB1Ymxpc2hWaWRlb1wiYFxuICAgICAqIC0gRm9yIGBhdWRpb0FjdGl2ZWA6IGBcInB1Ymxpc2hBdWRpb1wiYFxuICAgICAqIC0gRm9yIGB2aWRlb0RpbWVuc2lvbnNgOiBgXCJkZXZpY2VSb3RhdGVkXCJgIG9yIGBcInNjcmVlblJlc2l6ZWRcImBcbiAgICAgKi9cbiAgICByZWFzb246IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIE5ldyB2YWx1ZSBvZiB0aGUgcHJvcGVydHkgKGFmdGVyIGNoYW5nZSwgY3VycmVudCB2YWx1ZSlcbiAgICAgKi9cbiAgICBuZXdWYWx1ZTogT2JqZWN0O1xuXG4gICAgLyoqXG4gICAgICogUHJldmlvdXMgdmFsdWUgb2YgdGhlIHByb3BlcnR5IChiZWZvcmUgY2hhbmdlKVxuICAgICAqL1xuICAgIG9sZFZhbHVlOiBPYmplY3Q7XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgY29uc3RydWN0b3IodGFyZ2V0OiBTZXNzaW9uIHwgU3RyZWFtTWFuYWdlciwgc3RyZWFtOiBTdHJlYW0sIGNoYW5nZWRQcm9wZXJ0eTogc3RyaW5nLCBuZXdWYWx1ZTogT2JqZWN0LCBvbGRWYWx1ZTogT2JqZWN0LCByZWFzb246IHN0cmluZykge1xuICAgICAgICBzdXBlcihmYWxzZSwgdGFyZ2V0LCAnc3RyZWFtUHJvcGVydHlDaGFuZ2VkJyk7XG4gICAgICAgIHRoaXMuc3RyZWFtID0gc3RyZWFtO1xuICAgICAgICB0aGlzLmNoYW5nZWRQcm9wZXJ0eSA9IGNoYW5nZWRQcm9wZXJ0eTtcbiAgICAgICAgdGhpcy5uZXdWYWx1ZSA9IG5ld1ZhbHVlO1xuICAgICAgICB0aGlzLm9sZFZhbHVlID0gb2xkVmFsdWU7XG4gICAgICAgIHRoaXMucmVhc29uID0gcmVhc29uO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6bm8tZW1wdHlcbiAgICBjYWxsRGVmYXVsdEJlaGF2aW9yKCkgeyB9XG5cbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IEV2ZW50IH0gZnJvbSAnLi9FdmVudCc7XG5pbXBvcnQgeyBTdHJlYW1NYW5hZ2VyIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvU3RyZWFtTWFuYWdlcic7XG5cblxuLyoqXG4gKiBEZWZpbmVzIHRoZSBmb2xsb3dpbmcgZXZlbnRzOlxuICogLSBgdmlkZW9FbGVtZW50Q3JlYXRlZGA6IGRpc3BhdGNoZWQgYnkgW1tQdWJsaXNoZXJdXSBhbmQgW1tTdWJzY3JpYmVyXV0gd2hlbmV2ZXIgYSBuZXcgSFRNTCB2aWRlbyBlbGVtZW50IGhhcyBiZWVuIGluc2VydGVkIGludG8gRE9NIGJ5IE9wZW5WaWR1IEJyb3dzZXIgbGlicmFyeS4gU2VlXG4gKiBbTWFuYWdlIHZpZGVvIHBsYXllcnNdKC9kb2NzL2hvdy1kby1pL21hbmFnZS12aWRlb3MpIHNlY3Rpb24uXG4gKiAtIGB2aWRlb0VsZW1lbnREZXN0cm95ZWRgOiBkaXNwYXRjaGVkIGJ5IFtbUHVibGlzaGVyXV0gYW5kIFtbU3Vic2NyaWJlcl1dIHdoZW5ldmVyIGFuIEhUTUwgdmlkZW8gZWxlbWVudCBoYXMgYmVlbiByZW1vdmVkIGZyb20gRE9NIGJ5IE9wZW5WaWR1IEJyb3dzZXIgbGlicmFyeS5cbiAqL1xuZXhwb3J0IGNsYXNzIFZpZGVvRWxlbWVudEV2ZW50IGV4dGVuZHMgRXZlbnQge1xuXG4gICAgLyoqXG4gICAgICogVmlkZW8gZWxlbWVudCB0aGF0IHdhcyBjcmVhdGVkIG9yIGRlc3Ryb3llZFxuICAgICAqL1xuICAgIGVsZW1lbnQ6IEhUTUxWaWRlb0VsZW1lbnQ7XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgY29uc3RydWN0b3IoZWxlbWVudDogSFRNTFZpZGVvRWxlbWVudCwgdGFyZ2V0OiBTdHJlYW1NYW5hZ2VyLCB0eXBlOiBzdHJpbmcpIHtcbiAgICAgICAgc3VwZXIoZmFsc2UsIHRhcmdldCwgdHlwZSk7XG4gICAgICAgIHRoaXMuZWxlbWVudCA9IGVsZW1lbnQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZTpuby1lbXB0eVxuICAgIGNhbGxEZWZhdWx0QmVoYXZpb3IoKSB7IH1cblxufSIsImZ1bmN0aW9uIE1hcHBlcigpXG57XG4gIHZhciBzb3VyY2VzID0ge307XG5cblxuICB0aGlzLmZvckVhY2ggPSBmdW5jdGlvbihjYWxsYmFjaylcbiAge1xuICAgIGZvcih2YXIga2V5IGluIHNvdXJjZXMpXG4gICAge1xuICAgICAgdmFyIHNvdXJjZSA9IHNvdXJjZXNba2V5XTtcblxuICAgICAgZm9yKHZhciBrZXkyIGluIHNvdXJjZSlcbiAgICAgICAgY2FsbGJhY2soc291cmNlW2tleTJdKTtcbiAgICB9O1xuICB9O1xuXG4gIHRoaXMuZ2V0ID0gZnVuY3Rpb24oaWQsIHNvdXJjZSlcbiAge1xuICAgIHZhciBpZHMgPSBzb3VyY2VzW3NvdXJjZV07XG4gICAgaWYoaWRzID09IHVuZGVmaW5lZClcbiAgICAgIHJldHVybiB1bmRlZmluZWQ7XG5cbiAgICByZXR1cm4gaWRzW2lkXTtcbiAgfTtcblxuICB0aGlzLnJlbW92ZSA9IGZ1bmN0aW9uKGlkLCBzb3VyY2UpXG4gIHtcbiAgICB2YXIgaWRzID0gc291cmNlc1tzb3VyY2VdO1xuICAgIGlmKGlkcyA9PSB1bmRlZmluZWQpXG4gICAgICByZXR1cm47XG5cbiAgICBkZWxldGUgaWRzW2lkXTtcblxuICAgIC8vIENoZWNrIGl0J3MgZW1wdHlcbiAgICBmb3IodmFyIGkgaW4gaWRzKXtyZXR1cm4gZmFsc2V9XG5cbiAgICBkZWxldGUgc291cmNlc1tzb3VyY2VdO1xuICB9O1xuXG4gIHRoaXMuc2V0ID0gZnVuY3Rpb24odmFsdWUsIGlkLCBzb3VyY2UpXG4gIHtcbiAgICBpZih2YWx1ZSA9PSB1bmRlZmluZWQpXG4gICAgICByZXR1cm4gdGhpcy5yZW1vdmUoaWQsIHNvdXJjZSk7XG5cbiAgICB2YXIgaWRzID0gc291cmNlc1tzb3VyY2VdO1xuICAgIGlmKGlkcyA9PSB1bmRlZmluZWQpXG4gICAgICBzb3VyY2VzW3NvdXJjZV0gPSBpZHMgPSB7fTtcblxuICAgIGlkc1tpZF0gPSB2YWx1ZTtcbiAgfTtcbn07XG5cblxuTWFwcGVyLnByb3RvdHlwZS5wb3AgPSBmdW5jdGlvbihpZCwgc291cmNlKVxue1xuICB2YXIgdmFsdWUgPSB0aGlzLmdldChpZCwgc291cmNlKTtcbiAgaWYodmFsdWUgPT0gdW5kZWZpbmVkKVxuICAgIHJldHVybiB1bmRlZmluZWQ7XG5cbiAgdGhpcy5yZW1vdmUoaWQsIHNvdXJjZSk7XG5cbiAgcmV0dXJuIHZhbHVlO1xufTtcblxuXG5tb2R1bGUuZXhwb3J0cyA9IE1hcHBlcjtcbiIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTQgS3VyZW50byAoaHR0cDovL2t1cmVudG8ub3JnLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG52YXIgSnNvblJwY0NsaWVudCAgPSByZXF1aXJlKCcuL2pzb25ycGNjbGllbnQnKTtcblxuXG5leHBvcnRzLkpzb25ScGNDbGllbnQgID0gSnNvblJwY0NsaWVudDsiLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE0IEt1cmVudG8gKGh0dHA6Ly9rdXJlbnRvLm9yZy8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxudmFyIFJwY0J1aWxkZXIgPSByZXF1aXJlKCcuLi8nKTtcbnZhciBXZWJTb2NrZXRXaXRoUmVjb25uZWN0aW9uID0gcmVxdWlyZSgnLi90cmFuc3BvcnRzL3dlYlNvY2tldFdpdGhSZWNvbm5lY3Rpb24nKTtcblxuRGF0ZS5ub3cgPSBEYXRlLm5vdyB8fCBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gK25ldyBEYXRlO1xufTtcblxudmFyIFBJTkdfSU5URVJWQUwgPSA1MDAwO1xuXG52YXIgUkVDT05ORUNUSU5HID0gJ1JFQ09OTkVDVElORyc7XG52YXIgQ09OTkVDVEVEID0gJ0NPTk5FQ1RFRCc7XG52YXIgRElTQ09OTkVDVEVEID0gJ0RJU0NPTk5FQ1RFRCc7XG5cbnZhciBMb2dnZXIgPSBjb25zb2xlO1xuXG4vKipcbiAqXG4gKiBoZWFydGJlYXQ6IGludGVydmFsIGluIG1zIGZvciBlYWNoIGhlYXJ0YmVhdCBtZXNzYWdlLFxuICogc2VuZENsb3NlTWVzc2FnZSA6IHRydWUgLyBmYWxzZSwgYmVmb3JlIGNsb3NpbmcgdGhlIGNvbm5lY3Rpb24sIGl0IHNlbmRzIGEgY2xvc2VTZXNzaW9uIG1lc3NhZ2VcbiAqIDxwcmU+XG4gKiB3cyA6IHtcbiAqIFx0dXJpIDogVVJJIHRvIGNvbm50ZWN0IHRvLFxuICogIHVzZVNvY2tKUyA6IHRydWUgKHVzZSBTb2NrSlMpIC8gZmFsc2UgKHVzZSBXZWJTb2NrZXQpIGJ5IGRlZmF1bHQsXG4gKiBcdG9uY29ubmVjdGVkIDogY2FsbGJhY2sgbWV0aG9kIHRvIGludm9rZSB3aGVuIGNvbm5lY3Rpb24gaXMgc3VjY2Vzc2Z1bCxcbiAqIFx0b25kaXNjb25uZWN0IDogY2FsbGJhY2sgbWV0aG9kIHRvIGludm9rZSB3aGVuIHRoZSBjb25uZWN0aW9uIGlzIGxvc3QsXG4gKiBcdG9ucmVjb25uZWN0aW5nIDogY2FsbGJhY2sgbWV0aG9kIHRvIGludm9rZSB3aGVuIHRoZSBjbGllbnQgaXMgcmVjb25uZWN0aW5nLFxuICogXHRvbnJlY29ubmVjdGVkIDogY2FsbGJhY2sgbWV0aG9kIHRvIGludm9rZSB3aGVuIHRoZSBjbGllbnQgc3VjY2Vzc2Z1bGx5IHJlY29ubmVjdHMsXG4gKiBcdG9uZXJyb3IgOiBjYWxsYmFjayBtZXRob2QgdG8gaW52b2tlIHdoZW4gdGhlcmUgaXMgYW4gZXJyb3JcbiAqIH0sXG4gKiBycGMgOiB7XG4gKiBcdHJlcXVlc3RUaW1lb3V0IDogdGltZW91dCBmb3IgYSByZXF1ZXN0LFxuICogXHRzZXNzaW9uU3RhdHVzQ2hhbmdlZDogY2FsbGJhY2sgbWV0aG9kIGZvciBjaGFuZ2VzIGluIHNlc3Npb24gc3RhdHVzLFxuICogXHRtZWRpYVJlbmVnb3RpYXRpb246IG1lZGlhUmVuZWdvdGlhdGlvblxuICogfVxuICogPC9wcmU+XG4gKi9cbmZ1bmN0aW9uIEpzb25ScGNDbGllbnQoY29uZmlndXJhdGlvbikge1xuXG4gICAgdmFyIHNlbGYgPSB0aGlzO1xuXG4gICAgdmFyIHdzQ29uZmlnID0gY29uZmlndXJhdGlvbi53cztcblxuICAgIHZhciBub3RSZWNvbm5lY3RJZk51bUxlc3NUaGFuID0gLTE7XG5cbiAgICB2YXIgcGluZ05leHROdW0gPSAwO1xuICAgIHZhciBlbmFibGVkUGluZ3MgPSB0cnVlO1xuICAgIHZhciBwaW5nUG9uZ1N0YXJ0ZWQgPSBmYWxzZTtcbiAgICB2YXIgcGluZ0ludGVydmFsO1xuXG4gICAgdmFyIHN0YXR1cyA9IERJU0NPTk5FQ1RFRDtcblxuICAgIHZhciBvbnJlY29ubmVjdGluZyA9IHdzQ29uZmlnLm9ucmVjb25uZWN0aW5nO1xuICAgIHZhciBvbnJlY29ubmVjdGVkID0gd3NDb25maWcub25yZWNvbm5lY3RlZDtcbiAgICB2YXIgb25jb25uZWN0ZWQgPSB3c0NvbmZpZy5vbmNvbm5lY3RlZDtcbiAgICB2YXIgb25lcnJvciA9IHdzQ29uZmlnLm9uZXJyb3I7XG5cbiAgICBjb25maWd1cmF0aW9uLnJwYy5wdWxsID0gZnVuY3Rpb24ocGFyYW1zLCByZXF1ZXN0KSB7XG4gICAgICAgIHJlcXVlc3QucmVwbHkobnVsbCwgXCJwdXNoXCIpO1xuICAgIH1cblxuICAgIHdzQ29uZmlnLm9ucmVjb25uZWN0aW5nID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIExvZ2dlci5kZWJ1ZyhcIi0tLS0tLS0tLSBPTlJFQ09OTkVDVElORyAtLS0tLS0tLS0tLVwiKTtcbiAgICAgICAgaWYgKHN0YXR1cyA9PT0gUkVDT05ORUNUSU5HKSB7XG4gICAgICAgICAgICBMb2dnZXIuZXJyb3IoXCJXZWJzb2NrZXQgYWxyZWFkeSBpbiBSRUNPTk5FQ1RJTkcgc3RhdGUgd2hlbiByZWNlaXZpbmcgYSBuZXcgT05SRUNPTk5FQ1RJTkcgbWVzc2FnZS4gSWdub3JpbmcgaXRcIik7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBzdGF0dXMgPSBSRUNPTk5FQ1RJTkc7XG4gICAgICAgIGlmIChvbnJlY29ubmVjdGluZykge1xuICAgICAgICAgICAgb25yZWNvbm5lY3RpbmcoKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHdzQ29uZmlnLm9ucmVjb25uZWN0ZWQgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgTG9nZ2VyLmRlYnVnKFwiLS0tLS0tLS0tIE9OUkVDT05ORUNURUQgLS0tLS0tLS0tLS1cIik7XG4gICAgICAgIGlmIChzdGF0dXMgPT09IENPTk5FQ1RFRCkge1xuICAgICAgICAgICAgTG9nZ2VyLmVycm9yKFwiV2Vic29ja2V0IGFscmVhZHkgaW4gQ09OTkVDVEVEIHN0YXRlIHdoZW4gcmVjZWl2aW5nIGEgbmV3IE9OUkVDT05ORUNURUQgbWVzc2FnZS4gSWdub3JpbmcgaXRcIik7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgc3RhdHVzID0gQ09OTkVDVEVEO1xuXG4gICAgICAgIGVuYWJsZWRQaW5ncyA9IHRydWU7XG4gICAgICAgIHVwZGF0ZU5vdFJlY29ubmVjdElmTGVzc1RoYW4oKTtcbiAgICAgICAgdXNlUGluZygpO1xuXG4gICAgICAgIGlmIChvbnJlY29ubmVjdGVkKSB7XG4gICAgICAgICAgICBvbnJlY29ubmVjdGVkKCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB3c0NvbmZpZy5vbmNvbm5lY3RlZCA9IGZ1bmN0aW9uKCkge1xuICAgICAgICBMb2dnZXIuZGVidWcoXCItLS0tLS0tLS0gT05DT05ORUNURUQgLS0tLS0tLS0tLS1cIik7XG4gICAgICAgIGlmIChzdGF0dXMgPT09IENPTk5FQ1RFRCkge1xuICAgICAgICAgICAgTG9nZ2VyLmVycm9yKFwiV2Vic29ja2V0IGFscmVhZHkgaW4gQ09OTkVDVEVEIHN0YXRlIHdoZW4gcmVjZWl2aW5nIGEgbmV3IE9OQ09OTkVDVEVEIG1lc3NhZ2UuIElnbm9yaW5nIGl0XCIpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHN0YXR1cyA9IENPTk5FQ1RFRDtcblxuICAgICAgICBlbmFibGVkUGluZ3MgPSB0cnVlO1xuICAgICAgICB1c2VQaW5nKCk7XG5cbiAgICAgICAgaWYgKG9uY29ubmVjdGVkKSB7XG4gICAgICAgICAgICBvbmNvbm5lY3RlZCgpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgd3NDb25maWcub25lcnJvciA9IGZ1bmN0aW9uKGVycm9yKSB7XG4gICAgICAgIExvZ2dlci5kZWJ1ZyhcIi0tLS0tLS0tLSBPTkVSUk9SIC0tLS0tLS0tLS0tXCIpO1xuXG4gICAgICAgIHN0YXR1cyA9IERJU0NPTk5FQ1RFRDtcblxuICAgICAgICBpZiAob25lcnJvcikge1xuICAgICAgICAgICAgb25lcnJvcihlcnJvcik7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB2YXIgd3MgPSBuZXcgV2ViU29ja2V0V2l0aFJlY29ubmVjdGlvbih3c0NvbmZpZyk7XG5cbiAgICBMb2dnZXIuZGVidWcoJ0Nvbm5lY3Rpbmcgd2Vic29ja2V0IHRvIFVSSTogJyArIHdzQ29uZmlnLnVyaSk7XG5cbiAgICB2YXIgcnBjQnVpbGRlck9wdGlvbnMgPSB7XG4gICAgICAgIHJlcXVlc3RfdGltZW91dDogY29uZmlndXJhdGlvbi5ycGMucmVxdWVzdFRpbWVvdXQsXG4gICAgICAgIHBpbmdfcmVxdWVzdF90aW1lb3V0OiBjb25maWd1cmF0aW9uLnJwYy5oZWFydGJlYXRSZXF1ZXN0VGltZW91dFxuICAgIH07XG5cbiAgICB2YXIgcnBjID0gbmV3IFJwY0J1aWxkZXIoUnBjQnVpbGRlci5wYWNrZXJzLkpzb25SUEMsIHJwY0J1aWxkZXJPcHRpb25zLCB3cyxcbiAgICAgICAgZnVuY3Rpb24ocmVxdWVzdCkge1xuXG4gICAgICAgICAgICBMb2dnZXIuZGVidWcoJ1JlY2VpdmVkIHJlcXVlc3Q6ICcgKyBKU09OLnN0cmluZ2lmeShyZXF1ZXN0KSk7XG5cbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgdmFyIGZ1bmMgPSBjb25maWd1cmF0aW9uLnJwY1tyZXF1ZXN0Lm1ldGhvZF07XG5cbiAgICAgICAgICAgICAgICBpZiAoZnVuYyA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgIExvZ2dlci5lcnJvcihcIk1ldGhvZCBcIiArIHJlcXVlc3QubWV0aG9kICsgXCIgbm90IHJlZ2lzdGVyZWQgaW4gY2xpZW50XCIpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGZ1bmMocmVxdWVzdC5wYXJhbXMsIHJlcXVlc3QpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgICAgIExvZ2dlci5lcnJvcignRXhjZXB0aW9uIHByb2Nlc3NpbmcgcmVxdWVzdDogJyArIEpTT04uc3RyaW5naWZ5KHJlcXVlc3QpKTtcbiAgICAgICAgICAgICAgICBMb2dnZXIuZXJyb3IoZXJyKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG5cbiAgICB0aGlzLnNlbmQgPSBmdW5jdGlvbihtZXRob2QsIHBhcmFtcywgY2FsbGJhY2spIHtcbiAgICAgICAgaWYgKG1ldGhvZCAhPT0gJ3BpbmcnKSB7XG4gICAgICAgICAgICBMb2dnZXIuZGVidWcoJ1JlcXVlc3Q6IG1ldGhvZDonICsgbWV0aG9kICsgXCIgcGFyYW1zOlwiICsgSlNPTi5zdHJpbmdpZnkocGFyYW1zKSk7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgcmVxdWVzdFRpbWUgPSBEYXRlLm5vdygpO1xuXG4gICAgICAgIHJwYy5lbmNvZGUobWV0aG9kLCBwYXJhbXMsIGZ1bmN0aW9uKGVycm9yLCByZXN1bHQpIHtcbiAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgIExvZ2dlci5lcnJvcihcIkVSUk9SOlwiICsgZXJyb3IubWVzc2FnZSArIFwiIGluIFJlcXVlc3Q6IG1ldGhvZDpcIiArXG4gICAgICAgICAgICAgICAgICAgICAgICBtZXRob2QgKyBcIiBwYXJhbXM6XCIgKyBKU09OLnN0cmluZ2lmeShwYXJhbXMpICsgXCIgcmVxdWVzdDpcIiArXG4gICAgICAgICAgICAgICAgICAgICAgICBlcnJvci5yZXF1ZXN0KTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yLmRhdGEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIExvZ2dlci5lcnJvcihcIkVSUk9SIERBVEE6XCIgKyBKU09OLnN0cmluZ2lmeShlcnJvci5kYXRhKSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGNhdGNoIChlKSB7fVxuICAgICAgICAgICAgICAgIGVycm9yLnJlcXVlc3RUaW1lID0gcmVxdWVzdFRpbWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoY2FsbGJhY2spIHtcbiAgICAgICAgICAgICAgICBpZiAocmVzdWx0ICE9IHVuZGVmaW5lZCAmJiByZXN1bHQudmFsdWUgIT09ICdwb25nJykge1xuICAgICAgICAgICAgICAgICAgICBMb2dnZXIuZGVidWcoJ1Jlc3BvbnNlOiAnICsgSlNPTi5zdHJpbmdpZnkocmVzdWx0KSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNhbGxiYWNrKGVycm9yLCByZXN1bHQpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiB1cGRhdGVOb3RSZWNvbm5lY3RJZkxlc3NUaGFuKCkge1xuICAgICAgICBMb2dnZXIuZGVidWcoXCJub3RSZWNvbm5lY3RJZk51bUxlc3NUaGFuID0gXCIgKyBwaW5nTmV4dE51bSArICcgKG9sZD0nICtcbiAgICAgICAgICAgIG5vdFJlY29ubmVjdElmTnVtTGVzc1RoYW4gKyAnKScpO1xuICAgICAgICBub3RSZWNvbm5lY3RJZk51bUxlc3NUaGFuID0gcGluZ05leHROdW07XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gc2VuZFBpbmcoKSB7XG4gICAgICAgIGlmIChlbmFibGVkUGluZ3MpIHtcbiAgICAgICAgICAgIHZhciBwYXJhbXMgPSBudWxsO1xuICAgICAgICAgICAgaWYgKHBpbmdOZXh0TnVtID09IDAgfHwgcGluZ05leHROdW0gPT0gbm90UmVjb25uZWN0SWZOdW1MZXNzVGhhbikge1xuICAgICAgICAgICAgICAgIHBhcmFtcyA9IHtcbiAgICAgICAgICAgICAgICAgICAgaW50ZXJ2YWw6IGNvbmZpZ3VyYXRpb24uaGVhcnRiZWF0IHx8IFBJTkdfSU5URVJWQUxcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcGluZ05leHROdW0rKztcblxuICAgICAgICAgICAgc2VsZi5zZW5kKCdwaW5nJywgcGFyYW1zLCAoZnVuY3Rpb24ocGluZ051bSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmdW5jdGlvbihlcnJvciwgcmVzdWx0KSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFwiRXJyb3IgaW4gcGluZyByZXF1ZXN0ICNcIiArIHBpbmdOdW0gKyBcIiAoXCIgK1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yLm1lc3NhZ2UgKyBcIilcIik7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocGluZ051bSA+IG5vdFJlY29ubmVjdElmTnVtTGVzc1RoYW4pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbmFibGVkUGluZ3MgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB1cGRhdGVOb3RSZWNvbm5lY3RJZkxlc3NUaGFuKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFwiU2VydmVyIGRpZCBub3QgcmVzcG9uZCB0byBwaW5nIG1lc3NhZ2UgI1wiICtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGluZ051bSArIFwiLiBSZWNvbm5lY3RpbmcuLi4gXCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdzLnJlY29ubmVjdFdzKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KShwaW5nTmV4dE51bSkpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFwiVHJ5aW5nIHRvIHNlbmQgcGluZywgYnV0IHBpbmcgaXMgbm90IGVuYWJsZWRcIik7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKlxuICAgICogSWYgY29uZmlndXJhdGlvbi5oZWFyYmVhdCBoYXMgYW55IHZhbHVlLCB0aGUgcGluZy1wb25nIHdpbGwgd29yayB3aXRoIHRoZSBpbnRlcnZhbFxuICAgICogb2YgY29uZmlndXJhdGlvbi5oZWFyYmVhdFxuICAgICovXG4gICAgZnVuY3Rpb24gdXNlUGluZygpIHtcbiAgICAgICAgaWYgKCFwaW5nUG9uZ1N0YXJ0ZWQpIHtcbiAgICAgICAgICAgIExvZ2dlci5kZWJ1ZyhcIlN0YXJ0aW5nIHBpbmcgKGlmIGNvbmZpZ3VyZWQpXCIpXG4gICAgICAgICAgICBwaW5nUG9uZ1N0YXJ0ZWQgPSB0cnVlO1xuXG4gICAgICAgICAgICBpZiAoY29uZmlndXJhdGlvbi5oZWFydGJlYXQgIT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgcGluZ0ludGVydmFsID0gc2V0SW50ZXJ2YWwoc2VuZFBpbmcsIGNvbmZpZ3VyYXRpb24uaGVhcnRiZWF0KTtcbiAgICAgICAgICAgICAgICBzZW5kUGluZygpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgdGhpcy5jbG9zZSA9IGZ1bmN0aW9uKCkge1xuICAgICAgICBMb2dnZXIuZGVidWcoXCJDbG9zaW5nIGpzb25ScGNDbGllbnQgZXhwbGljaXRseSBieSBjbGllbnRcIik7XG5cbiAgICAgICAgaWYgKHBpbmdJbnRlcnZhbCAhPSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIExvZ2dlci5kZWJ1ZyhcIkNsZWFyaW5nIHBpbmcgaW50ZXJ2YWxcIik7XG4gICAgICAgICAgICBjbGVhckludGVydmFsKHBpbmdJbnRlcnZhbCk7XG4gICAgICAgIH1cbiAgICAgICAgcGluZ1BvbmdTdGFydGVkID0gZmFsc2U7XG4gICAgICAgIGVuYWJsZWRQaW5ncyA9IGZhbHNlO1xuXG4gICAgICAgIGlmIChjb25maWd1cmF0aW9uLnNlbmRDbG9zZU1lc3NhZ2UpIHtcbiAgICAgICAgICAgIExvZ2dlci5kZWJ1ZyhcIlNlbmRpbmcgY2xvc2UgbWVzc2FnZVwiKVxuICAgICAgICAgICAgdGhpcy5zZW5kKCdjbG9zZVNlc3Npb24nLCBudWxsLCBmdW5jdGlvbihlcnJvciwgcmVzdWx0KSB7XG4gICAgICAgICAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgIExvZ2dlci5lcnJvcihcIkVycm9yIHNlbmRpbmcgY2xvc2UgbWVzc2FnZTogXCIgKyBKU09OLnN0cmluZ2lmeShlcnJvcikpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB3cy5jbG9zZSgpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0gZWxzZSB7XG5cdFx0XHR3cy5jbG9zZSgpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gVGhpcyBtZXRob2QgaXMgb25seSBmb3IgdGVzdGluZ1xuICAgIHRoaXMuZm9yY2VDbG9zZSA9IGZ1bmN0aW9uKG1pbGxpcykge1xuICAgICAgICB3cy5mb3JjZUNsb3NlKG1pbGxpcyk7XG4gICAgfVxuXG4gICAgdGhpcy5yZWNvbm5lY3QgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgd3MucmVjb25uZWN0V3MoKTtcbiAgICB9XG59XG5cblxubW9kdWxlLmV4cG9ydHMgPSBKc29uUnBjQ2xpZW50O1xuIiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNCBLdXJlbnRvIChodHRwOi8va3VyZW50by5vcmcvKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbnZhciBXZWJTb2NrZXRXaXRoUmVjb25uZWN0aW9uICA9IHJlcXVpcmUoJy4vd2ViU29ja2V0V2l0aFJlY29ubmVjdGlvbicpO1xuXG5cbmV4cG9ydHMuV2ViU29ja2V0V2l0aFJlY29ubmVjdGlvbiAgPSBXZWJTb2NrZXRXaXRoUmVjb25uZWN0aW9uOyIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTMtMjAxNSBLdXJlbnRvIChodHRwOi8va3VyZW50by5vcmcvKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuXCJ1c2Ugc3RyaWN0XCI7XG5cbnZhciBCcm93c2VyV2ViU29ja2V0ID0gZ2xvYmFsLldlYlNvY2tldCB8fCBnbG9iYWwuTW96V2ViU29ja2V0O1xuXG52YXIgTG9nZ2VyID0gY29uc29sZTtcblxuLyoqXG4gKiBHZXQgZWl0aGVyIHRoZSBgV2ViU29ja2V0YCBvciBgTW96V2ViU29ja2V0YCBnbG9iYWxzXG4gKiBpbiB0aGUgYnJvd3NlciBvciB0cnkgdG8gcmVzb2x2ZSBXZWJTb2NrZXQtY29tcGF0aWJsZVxuICogaW50ZXJmYWNlIGV4cG9zZWQgYnkgYHdzYCBmb3IgTm9kZS1saWtlIGVudmlyb25tZW50LlxuICovXG5cbi8qdmFyIFdlYlNvY2tldCA9IEJyb3dzZXJXZWJTb2NrZXQ7XG5pZiAoIVdlYlNvY2tldCAmJiB0eXBlb2Ygd2luZG93ID09PSAndW5kZWZpbmVkJykge1xuICAgIHRyeSB7XG4gICAgICAgIFdlYlNvY2tldCA9IHJlcXVpcmUoJ3dzJyk7XG4gICAgfSBjYXRjaCAoZSkgeyB9XG59Ki9cblxuLy92YXIgU29ja0pTID0gcmVxdWlyZSgnc29ja2pzLWNsaWVudCcpO1xuXG52YXIgTUFYX1JFVFJJRVMgPSAyMDAwOyAvLyBGb3JldmVyLi4uXG52YXIgUkVUUllfVElNRV9NUyA9IDMwMDA7IC8vIEZJWE1FOiBJbXBsZW1lbnQgZXhwb25lbnRpYWwgd2FpdCB0aW1lcy4uLlxuXG52YXIgQ09OTkVDVElORyA9IDA7XG52YXIgT1BFTiA9IDE7XG52YXIgQ0xPU0lORyA9IDI7XG52YXIgQ0xPU0VEID0gMztcblxuLypcbmNvbmZpZyA9IHtcblx0XHR1cmkgOiB3c1VyaSxcblx0XHR1c2VTb2NrSlMgOiB0cnVlICh1c2UgU29ja0pTKSAvIGZhbHNlICh1c2UgV2ViU29ja2V0KSBieSBkZWZhdWx0LFxuXHRcdG9uY29ubmVjdGVkIDogY2FsbGJhY2sgbWV0aG9kIHRvIGludm9rZSB3aGVuIGNvbm5lY3Rpb24gaXMgc3VjY2Vzc2Z1bCxcblx0XHRvbmRpc2Nvbm5lY3QgOiBjYWxsYmFjayBtZXRob2QgdG8gaW52b2tlIHdoZW4gdGhlIGNvbm5lY3Rpb24gaXMgbG9zdCxcblx0XHRvbnJlY29ubmVjdGluZyA6IGNhbGxiYWNrIG1ldGhvZCB0byBpbnZva2Ugd2hlbiB0aGUgY2xpZW50IGlzIHJlY29ubmVjdGluZyxcblx0XHRvbnJlY29ubmVjdGVkIDogY2FsbGJhY2sgbWV0aG9kIHRvIGludm9rZSB3aGVuIHRoZSBjbGllbnQgc3VjY2Vzc2Z1bGx5IHJlY29ubmVjdHMsXG5cdH07XG4qL1xuZnVuY3Rpb24gV2ViU29ja2V0V2l0aFJlY29ubmVjdGlvbihjb25maWcpIHtcblxuICAgIHZhciBjbG9zaW5nID0gZmFsc2U7XG4gICAgdmFyIHJlZ2lzdGVyTWVzc2FnZUhhbmRsZXI7XG4gICAgdmFyIHdzVXJpID0gY29uZmlnLnVyaTtcbiAgICB2YXIgdXNlU29ja0pTID0gY29uZmlnLnVzZVNvY2tKUztcbiAgICB2YXIgcmVjb25uZWN0aW5nID0gZmFsc2U7XG5cbiAgICB2YXIgZm9yY2luZ0Rpc2Nvbm5lY3Rpb24gPSBmYWxzZTtcblxuICAgIHZhciB3cztcblxuICAgIGlmICh1c2VTb2NrSlMpIHtcbiAgICAgICAgd3MgPSBuZXcgU29ja0pTKHdzVXJpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICB3cyA9IG5ldyBXZWJTb2NrZXQod3NVcmkpO1xuICAgIH1cblxuICAgIHdzLm9ub3BlbiA9IGZ1bmN0aW9uKCkge1xuICAgICAgICBsb2dDb25uZWN0ZWQod3MsIHdzVXJpKTtcbiAgICAgICAgaWYgKGNvbmZpZy5vbmNvbm5lY3RlZCkge1xuICAgICAgICAgICAgY29uZmlnLm9uY29ubmVjdGVkKCk7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgd3Mub25lcnJvciA9IGZ1bmN0aW9uKGVycm9yKSB7XG4gICAgICAgIExvZ2dlci5lcnJvcihcIkNvdWxkIG5vdCBjb25uZWN0IHRvIFwiICsgd3NVcmkgKyBcIiAoaW52b2tpbmcgb25lcnJvciBpZiBkZWZpbmVkKVwiLCBlcnJvcik7XG4gICAgICAgIGlmIChjb25maWcub25lcnJvcikge1xuICAgICAgICAgICAgY29uZmlnLm9uZXJyb3IoZXJyb3IpO1xuICAgICAgICB9XG4gICAgfTtcblxuICAgIGZ1bmN0aW9uIGxvZ0Nvbm5lY3RlZCh3cywgd3NVcmkpIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIExvZ2dlci5kZWJ1ZyhcIldlYlNvY2tldCBjb25uZWN0ZWQgdG8gXCIgKyB3c1VyaSk7XG4gICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgIExvZ2dlci5lcnJvcihlKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHZhciByZWNvbm5lY3Rpb25PbkNsb3NlID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIGlmICh3cy5yZWFkeVN0YXRlID09PSBDTE9TRUQpIHtcbiAgICAgICAgICAgIGlmIChjbG9zaW5nKSB7XG4gICAgICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFwiQ29ubmVjdGlvbiBjbG9zZWQgYnkgdXNlclwiKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFwiQ29ubmVjdGlvbiBjbG9zZWQgdW5leHBlY3RlY2x5LiBSZWNvbm5lY3RpbmcuLi5cIik7XG4gICAgICAgICAgICAgICAgcmVjb25uZWN0VG9TYW1lVXJpKE1BWF9SRVRSSUVTLCAxKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIExvZ2dlci5kZWJ1ZyhcIkNsb3NlIGNhbGxiYWNrIGZyb20gcHJldmlvdXMgd2Vic29ja2V0LiBJZ25vcmluZyBpdFwiKTtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICB3cy5vbmNsb3NlID0gcmVjb25uZWN0aW9uT25DbG9zZTtcblxuICAgIGZ1bmN0aW9uIHJlY29ubmVjdFRvU2FtZVVyaShtYXhSZXRyaWVzLCBudW1SZXRyaWVzKSB7XG4gICAgICAgIExvZ2dlci5kZWJ1ZyhcInJlY29ubmVjdFRvU2FtZVVyaSAoYXR0ZW1wdCAjXCIgKyBudW1SZXRyaWVzICsgXCIsIG1heD1cIiArIG1heFJldHJpZXMgKyBcIilcIik7XG5cbiAgICAgICAgaWYgKG51bVJldHJpZXMgPT09IDEpIHtcbiAgICAgICAgICAgIGlmIChyZWNvbm5lY3RpbmcpIHtcbiAgICAgICAgICAgICAgICBMb2dnZXIud2FybihcIlRyeWluZyB0byByZWNvbm5lY3RUb05ld1VyaSB3aGVuIHJlY29ubmVjdGluZy4uLiBJZ25vcmluZyB0aGlzIHJlY29ubmVjdGlvbi5cIilcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJlY29ubmVjdGluZyA9IHRydWU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChjb25maWcub25yZWNvbm5lY3RpbmcpIHtcbiAgICAgICAgICAgICAgICBjb25maWcub25yZWNvbm5lY3RpbmcoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChmb3JjaW5nRGlzY29ubmVjdGlvbikge1xuICAgICAgICAgICAgcmVjb25uZWN0VG9OZXdVcmkobWF4UmV0cmllcywgbnVtUmV0cmllcywgd3NVcmkpO1xuXG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBpZiAoY29uZmlnLm5ld1dzVXJpT25SZWNvbm5lY3Rpb24pIHtcbiAgICAgICAgICAgICAgICBjb25maWcubmV3V3NVcmlPblJlY29ubmVjdGlvbihmdW5jdGlvbihlcnJvciwgbmV3V3NVcmkpIHtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIExvZ2dlci5kZWJ1ZyhlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlY29ubmVjdFRvU2FtZVVyaShtYXhSZXRyaWVzLCBudW1SZXRyaWVzICsgMSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9LCBSRVRSWV9USU1FX01TKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlY29ubmVjdFRvTmV3VXJpKG1heFJldHJpZXMsIG51bVJldHJpZXMsIG5ld1dzVXJpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJlY29ubmVjdFRvTmV3VXJpKG1heFJldHJpZXMsIG51bVJldHJpZXMsIHdzVXJpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIFRPRE8gVGVzdCByZXRyaWVzLiBIb3cgdG8gZm9yY2Ugbm90IGNvbm5lY3Rpb24/XG4gICAgZnVuY3Rpb24gcmVjb25uZWN0VG9OZXdVcmkobWF4UmV0cmllcywgbnVtUmV0cmllcywgcmVjb25uZWN0V3NVcmkpIHtcbiAgICAgICAgTG9nZ2VyLmRlYnVnKFwiUmVjb25uZWN0aW9uIGF0dGVtcHQgI1wiICsgbnVtUmV0cmllcyk7XG5cbiAgICAgICAgd3MuY2xvc2UoKTtcblxuICAgICAgICB3c1VyaSA9IHJlY29ubmVjdFdzVXJpIHx8IHdzVXJpO1xuXG4gICAgICAgIHZhciBuZXdXcztcbiAgICAgICAgaWYgKHVzZVNvY2tKUykge1xuICAgICAgICAgICAgbmV3V3MgPSBuZXcgU29ja0pTKHdzVXJpKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIG5ld1dzID0gbmV3IFdlYlNvY2tldCh3c1VyaSk7XG4gICAgICAgIH1cblxuICAgICAgICBuZXdXcy5vbm9wZW4gPSBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIExvZ2dlci5kZWJ1ZyhcIlJlY29ubmVjdGVkIGFmdGVyIFwiICsgbnVtUmV0cmllcyArIFwiIGF0dGVtcHRzLi4uXCIpO1xuICAgICAgICAgICAgbG9nQ29ubmVjdGVkKG5ld1dzLCB3c1VyaSk7XG4gICAgICAgICAgICByZWNvbm5lY3RpbmcgPSBmYWxzZTtcbiAgICAgICAgICAgIHJlZ2lzdGVyTWVzc2FnZUhhbmRsZXIoKTtcbiAgICAgICAgICAgIGlmIChjb25maWcub25yZWNvbm5lY3RlZCgpKSB7XG4gICAgICAgICAgICAgICAgY29uZmlnLm9ucmVjb25uZWN0ZWQoKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgbmV3V3Mub25jbG9zZSA9IHJlY29ubmVjdGlvbk9uQ2xvc2U7XG4gICAgICAgIH07XG5cbiAgICAgICAgdmFyIG9uRXJyb3JPckNsb3NlID0gZnVuY3Rpb24oZXJyb3IpIHtcbiAgICAgICAgICAgIExvZ2dlci53YXJuKFwiUmVjb25uZWN0aW9uIGVycm9yOiBcIiwgZXJyb3IpO1xuXG4gICAgICAgICAgICBpZiAobnVtUmV0cmllcyA9PT0gbWF4UmV0cmllcykge1xuICAgICAgICAgICAgICAgIGlmIChjb25maWcub25kaXNjb25uZWN0KSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbmZpZy5vbmRpc2Nvbm5lY3QoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlY29ubmVjdFRvU2FtZVVyaShtYXhSZXRyaWVzLCBudW1SZXRyaWVzICsgMSk7XG4gICAgICAgICAgICAgICAgfSwgUkVUUllfVElNRV9NUyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG5cbiAgICAgICAgbmV3V3Mub25lcnJvciA9IG9uRXJyb3JPckNsb3NlO1xuXG4gICAgICAgIHdzID0gbmV3V3M7XG4gICAgfVxuXG4gICAgdGhpcy5jbG9zZSA9IGZ1bmN0aW9uKCkge1xuICAgICAgICBjbG9zaW5nID0gdHJ1ZTtcbiAgICAgICAgd3MuY2xvc2UoKTtcbiAgICB9O1xuXG5cbiAgICAvLyBUaGlzIG1ldGhvZCBpcyBvbmx5IGZvciB0ZXN0aW5nXG4gICAgdGhpcy5mb3JjZUNsb3NlID0gZnVuY3Rpb24obWlsbGlzKSB7XG4gICAgICAgIExvZ2dlci5kZWJ1ZyhcIlRlc3Rpbmc6IEZvcmNlIFdlYlNvY2tldCBjbG9zZVwiKTtcblxuICAgICAgICBpZiAobWlsbGlzKSB7XG4gICAgICAgICAgICBMb2dnZXIuZGVidWcoXCJUZXN0aW5nOiBDaGFuZ2Ugd3NVcmkgZm9yIFwiICsgbWlsbGlzICsgXCIgbWlsbGlzIHRvIHNpbXVsYXRlIG5ldCBmYWlsdXJlXCIpO1xuICAgICAgICAgICAgdmFyIGdvb2RXc1VyaSA9IHdzVXJpO1xuICAgICAgICAgICAgd3NVcmkgPSBcIndzczovLzIxLjIzNC4xMi4zNC40OjQ0My9cIjtcblxuICAgICAgICAgICAgZm9yY2luZ0Rpc2Nvbm5lY3Rpb24gPSB0cnVlO1xuXG4gICAgICAgICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgIExvZ2dlci5kZWJ1ZyhcIlRlc3Rpbmc6IFJlY292ZXIgZ29vZCB3c1VyaSBcIiArIGdvb2RXc1VyaSk7XG4gICAgICAgICAgICAgICAgd3NVcmkgPSBnb29kV3NVcmk7XG5cbiAgICAgICAgICAgICAgICBmb3JjaW5nRGlzY29ubmVjdGlvbiA9IGZhbHNlO1xuXG4gICAgICAgICAgICB9LCBtaWxsaXMpO1xuICAgICAgICB9XG5cbiAgICAgICAgd3MuY2xvc2UoKTtcbiAgICB9O1xuXG4gICAgdGhpcy5yZWNvbm5lY3RXcyA9IGZ1bmN0aW9uKCkge1xuICAgICAgICBMb2dnZXIuZGVidWcoXCJyZWNvbm5lY3RXc1wiKTtcbiAgICAgICAgcmVjb25uZWN0VG9TYW1lVXJpKE1BWF9SRVRSSUVTLCAxLCB3c1VyaSk7XG4gICAgfTtcblxuICAgIHRoaXMuc2VuZCA9IGZ1bmN0aW9uKG1lc3NhZ2UpIHtcbiAgICAgICAgd3Muc2VuZChtZXNzYWdlKTtcbiAgICB9O1xuXG4gICAgdGhpcy5hZGRFdmVudExpc3RlbmVyID0gZnVuY3Rpb24odHlwZSwgY2FsbGJhY2spIHtcbiAgICAgICAgcmVnaXN0ZXJNZXNzYWdlSGFuZGxlciA9IGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgd3MuYWRkRXZlbnRMaXN0ZW5lcih0eXBlLCBjYWxsYmFjayk7XG4gICAgICAgIH07XG5cbiAgICAgICAgcmVnaXN0ZXJNZXNzYWdlSGFuZGxlcigpO1xuICAgIH07XG59XG5cbm1vZHVsZS5leHBvcnRzID0gV2ViU29ja2V0V2l0aFJlY29ubmVjdGlvbjtcbiIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTQgS3VyZW50byAoaHR0cDovL2t1cmVudG8ub3JnLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5cbnZhciBkZWZpbmVQcm9wZXJ0eV9JRTggPSBmYWxzZVxuaWYoT2JqZWN0LmRlZmluZVByb3BlcnR5KVxue1xuICB0cnlcbiAge1xuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh7fSwgXCJ4XCIsIHt9KTtcbiAgfVxuICBjYXRjaChlKVxuICB7XG4gICAgZGVmaW5lUHJvcGVydHlfSUU4ID0gdHJ1ZVxuICB9XG59XG5cbi8vIGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0phdmFTY3JpcHQvUmVmZXJlbmNlL0dsb2JhbF9PYmplY3RzL0Z1bmN0aW9uL2JpbmRcbmlmICghRnVuY3Rpb24ucHJvdG90eXBlLmJpbmQpIHtcbiAgRnVuY3Rpb24ucHJvdG90eXBlLmJpbmQgPSBmdW5jdGlvbihvVGhpcykge1xuICAgIGlmICh0eXBlb2YgdGhpcyAhPT0gJ2Z1bmN0aW9uJykge1xuICAgICAgLy8gY2xvc2VzdCB0aGluZyBwb3NzaWJsZSB0byB0aGUgRUNNQVNjcmlwdCA1XG4gICAgICAvLyBpbnRlcm5hbCBJc0NhbGxhYmxlIGZ1bmN0aW9uXG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdGdW5jdGlvbi5wcm90b3R5cGUuYmluZCAtIHdoYXQgaXMgdHJ5aW5nIHRvIGJlIGJvdW5kIGlzIG5vdCBjYWxsYWJsZScpO1xuICAgIH1cblxuICAgIHZhciBhQXJncyAgID0gQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzLCAxKSxcbiAgICAgICAgZlRvQmluZCA9IHRoaXMsXG4gICAgICAgIGZOT1AgICAgPSBmdW5jdGlvbigpIHt9LFxuICAgICAgICBmQm91bmQgID0gZnVuY3Rpb24oKSB7XG4gICAgICAgICAgcmV0dXJuIGZUb0JpbmQuYXBwbHkodGhpcyBpbnN0YW5jZW9mIGZOT1AgJiYgb1RoaXNcbiAgICAgICAgICAgICAgICAgPyB0aGlzXG4gICAgICAgICAgICAgICAgIDogb1RoaXMsXG4gICAgICAgICAgICAgICAgIGFBcmdzLmNvbmNhdChBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMpKSk7XG4gICAgICAgIH07XG5cbiAgICBmTk9QLnByb3RvdHlwZSA9IHRoaXMucHJvdG90eXBlO1xuICAgIGZCb3VuZC5wcm90b3R5cGUgPSBuZXcgZk5PUCgpO1xuXG4gICAgcmV0dXJuIGZCb3VuZDtcbiAgfTtcbn1cblxuXG52YXIgRXZlbnRFbWl0dGVyID0gcmVxdWlyZSgnZXZlbnRzJykuRXZlbnRFbWl0dGVyO1xuXG52YXIgaW5oZXJpdHMgPSByZXF1aXJlKCdpbmhlcml0cycpO1xuXG52YXIgcGFja2VycyA9IHJlcXVpcmUoJy4vcGFja2VycycpO1xudmFyIE1hcHBlciA9IHJlcXVpcmUoJy4vTWFwcGVyJyk7XG5cblxudmFyIEJBU0VfVElNRU9VVCA9IDUwMDA7XG5cblxuZnVuY3Rpb24gdW5pZnlSZXNwb25zZU1ldGhvZHMocmVzcG9uc2VNZXRob2RzKVxue1xuICBpZighcmVzcG9uc2VNZXRob2RzKSByZXR1cm4ge307XG5cbiAgZm9yKHZhciBrZXkgaW4gcmVzcG9uc2VNZXRob2RzKVxuICB7XG4gICAgdmFyIHZhbHVlID0gcmVzcG9uc2VNZXRob2RzW2tleV07XG5cbiAgICBpZih0eXBlb2YgdmFsdWUgPT0gJ3N0cmluZycpXG4gICAgICByZXNwb25zZU1ldGhvZHNba2V5XSA9XG4gICAgICB7XG4gICAgICAgIHJlc3BvbnNlOiB2YWx1ZVxuICAgICAgfVxuICB9O1xuXG4gIHJldHVybiByZXNwb25zZU1ldGhvZHM7XG59O1xuXG5mdW5jdGlvbiB1bmlmeVRyYW5zcG9ydCh0cmFuc3BvcnQpXG57XG4gIGlmKCF0cmFuc3BvcnQpIHJldHVybjtcblxuICAvLyBUcmFuc3BvcnQgYXMgYSBmdW5jdGlvblxuICBpZih0cmFuc3BvcnQgaW5zdGFuY2VvZiBGdW5jdGlvbilcbiAgICByZXR1cm4ge3NlbmQ6IHRyYW5zcG9ydH07XG5cbiAgLy8gV2ViU29ja2V0ICYgRGF0YUNoYW5uZWxcbiAgaWYodHJhbnNwb3J0LnNlbmQgaW5zdGFuY2VvZiBGdW5jdGlvbilcbiAgICByZXR1cm4gdHJhbnNwb3J0O1xuXG4gIC8vIE1lc3NhZ2UgQVBJIChJbnRlci13aW5kb3cgJiBXZWJXb3JrZXIpXG4gIGlmKHRyYW5zcG9ydC5wb3N0TWVzc2FnZSBpbnN0YW5jZW9mIEZ1bmN0aW9uKVxuICB7XG4gICAgdHJhbnNwb3J0LnNlbmQgPSB0cmFuc3BvcnQucG9zdE1lc3NhZ2U7XG4gICAgcmV0dXJuIHRyYW5zcG9ydDtcbiAgfVxuXG4gIC8vIFN0cmVhbSBBUElcbiAgaWYodHJhbnNwb3J0LndyaXRlIGluc3RhbmNlb2YgRnVuY3Rpb24pXG4gIHtcbiAgICB0cmFuc3BvcnQuc2VuZCA9IHRyYW5zcG9ydC53cml0ZTtcbiAgICByZXR1cm4gdHJhbnNwb3J0O1xuICB9XG5cbiAgLy8gVHJhbnNwb3J0cyB0aGF0IG9ubHkgY2FuIHJlY2VpdmUgbWVzc2FnZXMsIGJ1dCBub3Qgc2VuZFxuICBpZih0cmFuc3BvcnQub25tZXNzYWdlICE9PSB1bmRlZmluZWQpIHJldHVybjtcbiAgaWYodHJhbnNwb3J0LnBhdXNlIGluc3RhbmNlb2YgRnVuY3Rpb24pIHJldHVybjtcblxuICB0aHJvdyBuZXcgU3ludGF4RXJyb3IoXCJUcmFuc3BvcnQgaXMgbm90IGEgZnVuY3Rpb24gbm9yIGEgdmFsaWQgb2JqZWN0XCIpO1xufTtcblxuXG4vKipcbiAqIFJlcHJlc2VudGF0aW9uIG9mIGEgUlBDIG5vdGlmaWNhdGlvblxuICpcbiAqIEBjbGFzc1xuICpcbiAqIEBjb25zdHJ1Y3RvclxuICpcbiAqIEBwYXJhbSB7U3RyaW5nfSBtZXRob2QgLW1ldGhvZCBvZiB0aGUgbm90aWZpY2F0aW9uXG4gKiBAcGFyYW0gcGFyYW1zIC0gcGFyYW1ldGVycyBvZiB0aGUgbm90aWZpY2F0aW9uXG4gKi9cbmZ1bmN0aW9uIFJwY05vdGlmaWNhdGlvbihtZXRob2QsIHBhcmFtcylcbntcbiAgaWYoZGVmaW5lUHJvcGVydHlfSUU4KVxuICB7XG4gICAgdGhpcy5tZXRob2QgPSBtZXRob2RcbiAgICB0aGlzLnBhcmFtcyA9IHBhcmFtc1xuICB9XG4gIGVsc2VcbiAge1xuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0aGlzLCAnbWV0aG9kJywge3ZhbHVlOiBtZXRob2QsIGVudW1lcmFibGU6IHRydWV9KTtcbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkodGhpcywgJ3BhcmFtcycsIHt2YWx1ZTogcGFyYW1zLCBlbnVtZXJhYmxlOiB0cnVlfSk7XG4gIH1cbn07XG5cblxuLyoqXG4gKiBAY2xhc3NcbiAqXG4gKiBAY29uc3RydWN0b3JcbiAqXG4gKiBAcGFyYW0ge29iamVjdH0gcGFja2VyXG4gKlxuICogQHBhcmFtIHtvYmplY3R9IFtvcHRpb25zXVxuICpcbiAqIEBwYXJhbSB7b2JqZWN0fSBbdHJhbnNwb3J0XVxuICpcbiAqIEBwYXJhbSB7RnVuY3Rpb259IFtvblJlcXVlc3RdXG4gKi9cbmZ1bmN0aW9uIFJwY0J1aWxkZXIocGFja2VyLCBvcHRpb25zLCB0cmFuc3BvcnQsIG9uUmVxdWVzdClcbntcbiAgdmFyIHNlbGYgPSB0aGlzO1xuXG4gIGlmKCFwYWNrZXIpXG4gICAgdGhyb3cgbmV3IFN5bnRheEVycm9yKCdQYWNrZXIgaXMgbm90IGRlZmluZWQnKTtcblxuICBpZighcGFja2VyLnBhY2sgfHwgIXBhY2tlci51bnBhY2spXG4gICAgdGhyb3cgbmV3IFN5bnRheEVycm9yKCdQYWNrZXIgaXMgaW52YWxpZCcpO1xuXG4gIHZhciByZXNwb25zZU1ldGhvZHMgPSB1bmlmeVJlc3BvbnNlTWV0aG9kcyhwYWNrZXIucmVzcG9uc2VNZXRob2RzKTtcblxuXG4gIGlmKG9wdGlvbnMgaW5zdGFuY2VvZiBGdW5jdGlvbilcbiAge1xuICAgIGlmKHRyYW5zcG9ydCAhPSB1bmRlZmluZWQpXG4gICAgICB0aHJvdyBuZXcgU3ludGF4RXJyb3IoXCJUaGVyZSBjYW4ndCBiZSBwYXJhbWV0ZXJzIGFmdGVyIG9uUmVxdWVzdFwiKTtcblxuICAgIG9uUmVxdWVzdCA9IG9wdGlvbnM7XG4gICAgdHJhbnNwb3J0ID0gdW5kZWZpbmVkO1xuICAgIG9wdGlvbnMgICA9IHVuZGVmaW5lZDtcbiAgfTtcblxuICBpZihvcHRpb25zICYmIG9wdGlvbnMuc2VuZCBpbnN0YW5jZW9mIEZ1bmN0aW9uKVxuICB7XG4gICAgaWYodHJhbnNwb3J0ICYmICEodHJhbnNwb3J0IGluc3RhbmNlb2YgRnVuY3Rpb24pKVxuICAgICAgdGhyb3cgbmV3IFN5bnRheEVycm9yKFwiT25seSBhIGZ1bmN0aW9uIGNhbiBiZSBhZnRlciB0cmFuc3BvcnRcIik7XG5cbiAgICBvblJlcXVlc3QgPSB0cmFuc3BvcnQ7XG4gICAgdHJhbnNwb3J0ID0gb3B0aW9ucztcbiAgICBvcHRpb25zICAgPSB1bmRlZmluZWQ7XG4gIH07XG5cbiAgaWYodHJhbnNwb3J0IGluc3RhbmNlb2YgRnVuY3Rpb24pXG4gIHtcbiAgICBpZihvblJlcXVlc3QgIT0gdW5kZWZpbmVkKVxuICAgICAgdGhyb3cgbmV3IFN5bnRheEVycm9yKFwiVGhlcmUgY2FuJ3QgYmUgcGFyYW1ldGVycyBhZnRlciBvblJlcXVlc3RcIik7XG5cbiAgICBvblJlcXVlc3QgPSB0cmFuc3BvcnQ7XG4gICAgdHJhbnNwb3J0ID0gdW5kZWZpbmVkO1xuICB9O1xuXG4gIGlmKHRyYW5zcG9ydCAmJiB0cmFuc3BvcnQuc2VuZCBpbnN0YW5jZW9mIEZ1bmN0aW9uKVxuICAgIGlmKG9uUmVxdWVzdCAmJiAhKG9uUmVxdWVzdCBpbnN0YW5jZW9mIEZ1bmN0aW9uKSlcbiAgICAgIHRocm93IG5ldyBTeW50YXhFcnJvcihcIk9ubHkgYSBmdW5jdGlvbiBjYW4gYmUgYWZ0ZXIgdHJhbnNwb3J0XCIpO1xuXG4gIG9wdGlvbnMgPSBvcHRpb25zIHx8IHt9O1xuXG5cbiAgRXZlbnRFbWl0dGVyLmNhbGwodGhpcyk7XG5cbiAgaWYob25SZXF1ZXN0KVxuICAgIHRoaXMub24oJ3JlcXVlc3QnLCBvblJlcXVlc3QpO1xuXG5cbiAgaWYoZGVmaW5lUHJvcGVydHlfSUU4KVxuICAgIHRoaXMucGVlcklEID0gb3B0aW9ucy5wZWVySURcbiAgZWxzZVxuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0aGlzLCAncGVlcklEJywge3ZhbHVlOiBvcHRpb25zLnBlZXJJRH0pO1xuXG4gIHZhciBtYXhfcmV0cmllcyA9IG9wdGlvbnMubWF4X3JldHJpZXMgfHwgMDtcblxuXG4gIGZ1bmN0aW9uIHRyYW5zcG9ydE1lc3NhZ2UoZXZlbnQpXG4gIHtcbiAgICBzZWxmLmRlY29kZShldmVudC5kYXRhIHx8IGV2ZW50KTtcbiAgfTtcblxuICB0aGlzLmdldFRyYW5zcG9ydCA9IGZ1bmN0aW9uKClcbiAge1xuICAgIHJldHVybiB0cmFuc3BvcnQ7XG4gIH1cbiAgdGhpcy5zZXRUcmFuc3BvcnQgPSBmdW5jdGlvbih2YWx1ZSlcbiAge1xuICAgIC8vIFJlbW92ZSBsaXN0ZW5lciBmcm9tIG9sZCB0cmFuc3BvcnRcbiAgICBpZih0cmFuc3BvcnQpXG4gICAge1xuICAgICAgLy8gVzNDIHRyYW5zcG9ydHNcbiAgICAgIGlmKHRyYW5zcG9ydC5yZW1vdmVFdmVudExpc3RlbmVyKVxuICAgICAgICB0cmFuc3BvcnQucmVtb3ZlRXZlbnRMaXN0ZW5lcignbWVzc2FnZScsIHRyYW5zcG9ydE1lc3NhZ2UpO1xuXG4gICAgICAvLyBOb2RlLmpzIFN0cmVhbXMgQVBJXG4gICAgICBlbHNlIGlmKHRyYW5zcG9ydC5yZW1vdmVMaXN0ZW5lcilcbiAgICAgICAgdHJhbnNwb3J0LnJlbW92ZUxpc3RlbmVyKCdkYXRhJywgdHJhbnNwb3J0TWVzc2FnZSk7XG4gICAgfTtcblxuICAgIC8vIFNldCBsaXN0ZW5lciBvbiBuZXcgdHJhbnNwb3J0XG4gICAgaWYodmFsdWUpXG4gICAge1xuICAgICAgLy8gVzNDIHRyYW5zcG9ydHNcbiAgICAgIGlmKHZhbHVlLmFkZEV2ZW50TGlzdGVuZXIpXG4gICAgICAgIHZhbHVlLmFkZEV2ZW50TGlzdGVuZXIoJ21lc3NhZ2UnLCB0cmFuc3BvcnRNZXNzYWdlKTtcblxuICAgICAgLy8gTm9kZS5qcyBTdHJlYW1zIEFQSVxuICAgICAgZWxzZSBpZih2YWx1ZS5hZGRMaXN0ZW5lcilcbiAgICAgICAgdmFsdWUuYWRkTGlzdGVuZXIoJ2RhdGEnLCB0cmFuc3BvcnRNZXNzYWdlKTtcbiAgICB9O1xuXG4gICAgdHJhbnNwb3J0ID0gdW5pZnlUcmFuc3BvcnQodmFsdWUpO1xuICB9XG5cbiAgaWYoIWRlZmluZVByb3BlcnR5X0lFOClcbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkodGhpcywgJ3RyYW5zcG9ydCcsXG4gICAge1xuICAgICAgZ2V0OiB0aGlzLmdldFRyYW5zcG9ydC5iaW5kKHRoaXMpLFxuICAgICAgc2V0OiB0aGlzLnNldFRyYW5zcG9ydC5iaW5kKHRoaXMpXG4gICAgfSlcblxuICB0aGlzLnNldFRyYW5zcG9ydCh0cmFuc3BvcnQpO1xuXG5cbiAgdmFyIHJlcXVlc3RfdGltZW91dCAgICAgID0gb3B0aW9ucy5yZXF1ZXN0X3RpbWVvdXQgICAgICB8fCBCQVNFX1RJTUVPVVQ7XG4gIHZhciBwaW5nX3JlcXVlc3RfdGltZW91dCA9IG9wdGlvbnMucGluZ19yZXF1ZXN0X3RpbWVvdXQgfHwgcmVxdWVzdF90aW1lb3V0O1xuICB2YXIgcmVzcG9uc2VfdGltZW91dCAgICAgPSBvcHRpb25zLnJlc3BvbnNlX3RpbWVvdXQgICAgIHx8IEJBU0VfVElNRU9VVDtcbiAgdmFyIGR1cGxpY2F0ZXNfdGltZW91dCAgID0gb3B0aW9ucy5kdXBsaWNhdGVzX3RpbWVvdXQgICB8fCBCQVNFX1RJTUVPVVQ7XG5cblxuICB2YXIgcmVxdWVzdElEID0gMDtcblxuICB2YXIgcmVxdWVzdHMgID0gbmV3IE1hcHBlcigpO1xuICB2YXIgcmVzcG9uc2VzID0gbmV3IE1hcHBlcigpO1xuICB2YXIgcHJvY2Vzc2VkUmVzcG9uc2VzID0gbmV3IE1hcHBlcigpO1xuXG4gIHZhciBtZXNzYWdlMktleSA9IHt9O1xuXG5cbiAgLyoqXG4gICAqIFN0b3JlIHRoZSByZXNwb25zZSB0byBwcmV2ZW50IHRvIHByb2Nlc3MgZHVwbGljYXRlIHJlcXVlc3QgbGF0ZXJcbiAgICovXG4gIGZ1bmN0aW9uIHN0b3JlUmVzcG9uc2UobWVzc2FnZSwgaWQsIGRlc3QpXG4gIHtcbiAgICB2YXIgcmVzcG9uc2UgPVxuICAgIHtcbiAgICAgIG1lc3NhZ2U6IG1lc3NhZ2UsXG4gICAgICAvKiogVGltZW91dCB0byBhdXRvLWNsZWFuIG9sZCByZXNwb25zZXMgKi9cbiAgICAgIHRpbWVvdXQ6IHNldFRpbWVvdXQoZnVuY3Rpb24oKVxuICAgICAge1xuICAgICAgICByZXNwb25zZXMucmVtb3ZlKGlkLCBkZXN0KTtcbiAgICAgIH0sXG4gICAgICByZXNwb25zZV90aW1lb3V0KVxuICAgIH07XG5cbiAgICByZXNwb25zZXMuc2V0KHJlc3BvbnNlLCBpZCwgZGVzdCk7XG4gIH07XG5cbiAgLyoqXG4gICAqIFN0b3JlIHRoZSByZXNwb25zZSB0byBpZ25vcmUgZHVwbGljYXRlZCBtZXNzYWdlcyBsYXRlclxuICAgKi9cbiAgZnVuY3Rpb24gc3RvcmVQcm9jZXNzZWRSZXNwb25zZShhY2ssIGZyb20pXG4gIHtcbiAgICB2YXIgdGltZW91dCA9IHNldFRpbWVvdXQoZnVuY3Rpb24oKVxuICAgIHtcbiAgICAgIHByb2Nlc3NlZFJlc3BvbnNlcy5yZW1vdmUoYWNrLCBmcm9tKTtcbiAgICB9LFxuICAgIGR1cGxpY2F0ZXNfdGltZW91dCk7XG5cbiAgICBwcm9jZXNzZWRSZXNwb25zZXMuc2V0KHRpbWVvdXQsIGFjaywgZnJvbSk7XG4gIH07XG5cblxuICAvKipcbiAgICogUmVwcmVzZW50YXRpb24gb2YgYSBSUEMgcmVxdWVzdFxuICAgKlxuICAgKiBAY2xhc3NcbiAgICogQGV4dGVuZHMgUnBjTm90aWZpY2F0aW9uXG4gICAqXG4gICAqIEBjb25zdHJ1Y3RvclxuICAgKlxuICAgKiBAcGFyYW0ge1N0cmluZ30gbWV0aG9kIC1tZXRob2Qgb2YgdGhlIG5vdGlmaWNhdGlvblxuICAgKiBAcGFyYW0gcGFyYW1zIC0gcGFyYW1ldGVycyBvZiB0aGUgbm90aWZpY2F0aW9uXG4gICAqIEBwYXJhbSB7SW50ZWdlcn0gaWQgLSBpZGVudGlmaWVyIG9mIHRoZSByZXF1ZXN0XG4gICAqIEBwYXJhbSBbZnJvbV0gLSBzb3VyY2Ugb2YgdGhlIG5vdGlmaWNhdGlvblxuICAgKi9cbiAgZnVuY3Rpb24gUnBjUmVxdWVzdChtZXRob2QsIHBhcmFtcywgaWQsIGZyb20sIHRyYW5zcG9ydClcbiAge1xuICAgIFJwY05vdGlmaWNhdGlvbi5jYWxsKHRoaXMsIG1ldGhvZCwgcGFyYW1zKTtcblxuICAgIHRoaXMuZ2V0VHJhbnNwb3J0ID0gZnVuY3Rpb24oKVxuICAgIHtcbiAgICAgIHJldHVybiB0cmFuc3BvcnQ7XG4gICAgfVxuICAgIHRoaXMuc2V0VHJhbnNwb3J0ID0gZnVuY3Rpb24odmFsdWUpXG4gICAge1xuICAgICAgdHJhbnNwb3J0ID0gdW5pZnlUcmFuc3BvcnQodmFsdWUpO1xuICAgIH1cblxuICAgIGlmKCFkZWZpbmVQcm9wZXJ0eV9JRTgpXG4gICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkodGhpcywgJ3RyYW5zcG9ydCcsXG4gICAgICB7XG4gICAgICAgIGdldDogdGhpcy5nZXRUcmFuc3BvcnQuYmluZCh0aGlzKSxcbiAgICAgICAgc2V0OiB0aGlzLnNldFRyYW5zcG9ydC5iaW5kKHRoaXMpXG4gICAgICB9KVxuXG4gICAgdmFyIHJlc3BvbnNlID0gcmVzcG9uc2VzLmdldChpZCwgZnJvbSk7XG5cbiAgICAvKipcbiAgICAgKiBAY29uc3RhbnQge0Jvb2xlYW59IGR1cGxpY2F0ZWRcbiAgICAgKi9cbiAgICBpZighKHRyYW5zcG9ydCB8fCBzZWxmLmdldFRyYW5zcG9ydCgpKSlcbiAgICB7XG4gICAgICBpZihkZWZpbmVQcm9wZXJ0eV9JRTgpXG4gICAgICAgIHRoaXMuZHVwbGljYXRlZCA9IEJvb2xlYW4ocmVzcG9uc2UpXG4gICAgICBlbHNlXG4gICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0aGlzLCAnZHVwbGljYXRlZCcsXG4gICAgICAgIHtcbiAgICAgICAgICB2YWx1ZTogQm9vbGVhbihyZXNwb25zZSlcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgdmFyIHJlc3BvbnNlTWV0aG9kID0gcmVzcG9uc2VNZXRob2RzW21ldGhvZF07XG5cbiAgICB0aGlzLnBhY2sgPSBwYWNrZXIucGFjay5iaW5kKHBhY2tlciwgdGhpcywgaWQpXG5cbiAgICAvKipcbiAgICAgKiBHZW5lcmF0ZSBhIHJlc3BvbnNlIHRvIHRoaXMgcmVxdWVzdFxuICAgICAqXG4gICAgICogQHBhcmFtIHtFcnJvcn0gW2Vycm9yXVxuICAgICAqIEBwYXJhbSB7Kn0gW3Jlc3VsdF1cbiAgICAgKlxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9XG4gICAgICovXG4gICAgdGhpcy5yZXBseSA9IGZ1bmN0aW9uKGVycm9yLCByZXN1bHQsIHRyYW5zcG9ydClcbiAgICB7XG4gICAgICAvLyBGaXggb3B0aW9uYWwgcGFyYW1ldGVyc1xuICAgICAgaWYoZXJyb3IgaW5zdGFuY2VvZiBGdW5jdGlvbiB8fCBlcnJvciAmJiBlcnJvci5zZW5kIGluc3RhbmNlb2YgRnVuY3Rpb24pXG4gICAgICB7XG4gICAgICAgIGlmKHJlc3VsdCAhPSB1bmRlZmluZWQpXG4gICAgICAgICAgdGhyb3cgbmV3IFN5bnRheEVycm9yKFwiVGhlcmUgY2FuJ3QgYmUgcGFyYW1ldGVycyBhZnRlciBjYWxsYmFja1wiKTtcblxuICAgICAgICB0cmFuc3BvcnQgPSBlcnJvcjtcbiAgICAgICAgcmVzdWx0ID0gbnVsbDtcbiAgICAgICAgZXJyb3IgPSB1bmRlZmluZWQ7XG4gICAgICB9XG5cbiAgICAgIGVsc2UgaWYocmVzdWx0IGluc3RhbmNlb2YgRnVuY3Rpb25cbiAgICAgIHx8IHJlc3VsdCAmJiByZXN1bHQuc2VuZCBpbnN0YW5jZW9mIEZ1bmN0aW9uKVxuICAgICAge1xuICAgICAgICBpZih0cmFuc3BvcnQgIT0gdW5kZWZpbmVkKVxuICAgICAgICAgIHRocm93IG5ldyBTeW50YXhFcnJvcihcIlRoZXJlIGNhbid0IGJlIHBhcmFtZXRlcnMgYWZ0ZXIgY2FsbGJhY2tcIik7XG5cbiAgICAgICAgdHJhbnNwb3J0ID0gcmVzdWx0O1xuICAgICAgICByZXN1bHQgPSBudWxsO1xuICAgICAgfTtcblxuICAgICAgdHJhbnNwb3J0ID0gdW5pZnlUcmFuc3BvcnQodHJhbnNwb3J0KTtcblxuICAgICAgLy8gRHVwbGljYXRlZCByZXF1ZXN0LCByZW1vdmUgb2xkIHJlc3BvbnNlIHRpbWVvdXRcbiAgICAgIGlmKHJlc3BvbnNlKVxuICAgICAgICBjbGVhclRpbWVvdXQocmVzcG9uc2UudGltZW91dCk7XG5cbiAgICAgIGlmKGZyb20gIT0gdW5kZWZpbmVkKVxuICAgICAge1xuICAgICAgICBpZihlcnJvcilcbiAgICAgICAgICBlcnJvci5kZXN0ID0gZnJvbTtcblxuICAgICAgICBpZihyZXN1bHQpXG4gICAgICAgICAgcmVzdWx0LmRlc3QgPSBmcm9tO1xuICAgICAgfTtcblxuICAgICAgdmFyIG1lc3NhZ2U7XG5cbiAgICAgIC8vIE5ldyByZXF1ZXN0IG9yIG92ZXJyaWRlbiBvbmUsIGNyZWF0ZSBuZXcgcmVzcG9uc2Ugd2l0aCBwcm92aWRlZCBkYXRhXG4gICAgICBpZihlcnJvciB8fCByZXN1bHQgIT0gdW5kZWZpbmVkKVxuICAgICAge1xuICAgICAgICBpZihzZWxmLnBlZXJJRCAhPSB1bmRlZmluZWQpXG4gICAgICAgIHtcbiAgICAgICAgICBpZihlcnJvcilcbiAgICAgICAgICAgIGVycm9yLmZyb20gPSBzZWxmLnBlZXJJRDtcbiAgICAgICAgICBlbHNlXG4gICAgICAgICAgICByZXN1bHQuZnJvbSA9IHNlbGYucGVlcklEO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gUHJvdG9jb2wgaW5kaWNhdGVzIHRoYXQgcmVzcG9uc2VzIGhhcyBvd24gcmVxdWVzdCBtZXRob2RzXG4gICAgICAgIGlmKHJlc3BvbnNlTWV0aG9kKVxuICAgICAgICB7XG4gICAgICAgICAgaWYocmVzcG9uc2VNZXRob2QuZXJyb3IgPT0gdW5kZWZpbmVkICYmIGVycm9yKVxuICAgICAgICAgICAgbWVzc2FnZSA9XG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIGVycm9yOiBlcnJvclxuICAgICAgICAgICAgfTtcblxuICAgICAgICAgIGVsc2VcbiAgICAgICAgICB7XG4gICAgICAgICAgICB2YXIgbWV0aG9kID0gZXJyb3JcbiAgICAgICAgICAgICAgICAgICAgICAgPyByZXNwb25zZU1ldGhvZC5lcnJvclxuICAgICAgICAgICAgICAgICAgICAgICA6IHJlc3BvbnNlTWV0aG9kLnJlc3BvbnNlO1xuXG4gICAgICAgICAgICBtZXNzYWdlID1cbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgbWV0aG9kOiBtZXRob2QsXG4gICAgICAgICAgICAgIHBhcmFtczogZXJyb3IgfHwgcmVzdWx0XG4gICAgICAgICAgICB9O1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlXG4gICAgICAgICAgbWVzc2FnZSA9XG4gICAgICAgICAge1xuICAgICAgICAgICAgZXJyb3I6ICBlcnJvcixcbiAgICAgICAgICAgIHJlc3VsdDogcmVzdWx0XG4gICAgICAgICAgfTtcblxuICAgICAgICBtZXNzYWdlID0gcGFja2VyLnBhY2sobWVzc2FnZSwgaWQpO1xuICAgICAgfVxuXG4gICAgICAvLyBEdXBsaWNhdGUgJiBub3Qtb3ZlcnJpZGVuIHJlcXVlc3QsIHJlLXNlbmQgb2xkIHJlc3BvbnNlXG4gICAgICBlbHNlIGlmKHJlc3BvbnNlKVxuICAgICAgICBtZXNzYWdlID0gcmVzcG9uc2UubWVzc2FnZTtcblxuICAgICAgLy8gTmV3IGVtcHR5IHJlcGx5LCByZXNwb25zZSBudWxsIHZhbHVlXG4gICAgICBlbHNlXG4gICAgICAgIG1lc3NhZ2UgPSBwYWNrZXIucGFjayh7cmVzdWx0OiBudWxsfSwgaWQpO1xuXG4gICAgICAvLyBTdG9yZSB0aGUgcmVzcG9uc2UgdG8gcHJldmVudCB0byBwcm9jZXNzIGEgZHVwbGljYXRlZCByZXF1ZXN0IGxhdGVyXG4gICAgICBzdG9yZVJlc3BvbnNlKG1lc3NhZ2UsIGlkLCBmcm9tKTtcblxuICAgICAgLy8gUmV0dXJuIHRoZSBzdG9yZWQgcmVzcG9uc2Ugc28gaXQgY2FuIGJlIGRpcmVjdGx5IHNlbmQgYmFja1xuICAgICAgdHJhbnNwb3J0ID0gdHJhbnNwb3J0IHx8IHRoaXMuZ2V0VHJhbnNwb3J0KCkgfHwgc2VsZi5nZXRUcmFuc3BvcnQoKTtcblxuICAgICAgaWYodHJhbnNwb3J0KVxuICAgICAgICByZXR1cm4gdHJhbnNwb3J0LnNlbmQobWVzc2FnZSk7XG5cbiAgICAgIHJldHVybiBtZXNzYWdlO1xuICAgIH1cbiAgfTtcbiAgaW5oZXJpdHMoUnBjUmVxdWVzdCwgUnBjTm90aWZpY2F0aW9uKTtcblxuXG4gIGZ1bmN0aW9uIGNhbmNlbChtZXNzYWdlKVxuICB7XG4gICAgdmFyIGtleSA9IG1lc3NhZ2UyS2V5W21lc3NhZ2VdO1xuICAgIGlmKCFrZXkpIHJldHVybjtcblxuICAgIGRlbGV0ZSBtZXNzYWdlMktleVttZXNzYWdlXTtcblxuICAgIHZhciByZXF1ZXN0ID0gcmVxdWVzdHMucG9wKGtleS5pZCwga2V5LmRlc3QpO1xuICAgIGlmKCFyZXF1ZXN0KSByZXR1cm47XG5cbiAgICBjbGVhclRpbWVvdXQocmVxdWVzdC50aW1lb3V0KTtcblxuICAgIC8vIFN0YXJ0IGR1cGxpY2F0ZWQgcmVzcG9uc2VzIHRpbWVvdXRcbiAgICBzdG9yZVByb2Nlc3NlZFJlc3BvbnNlKGtleS5pZCwga2V5LmRlc3QpO1xuICB9O1xuXG4gIC8qKlxuICAgKiBBbGxvdyB0byBjYW5jZWwgYSByZXF1ZXN0IGFuZCBkb24ndCB3YWl0IGZvciBhIHJlc3BvbnNlXG4gICAqXG4gICAqIElmIGBtZXNzYWdlYCBpcyBub3QgZ2l2ZW4sIGNhbmNlbCBhbGwgdGhlIHJlcXVlc3RcbiAgICovXG4gIHRoaXMuY2FuY2VsID0gZnVuY3Rpb24obWVzc2FnZSlcbiAge1xuICAgIGlmKG1lc3NhZ2UpIHJldHVybiBjYW5jZWwobWVzc2FnZSk7XG5cbiAgICBmb3IodmFyIG1lc3NhZ2UgaW4gbWVzc2FnZTJLZXkpXG4gICAgICBjYW5jZWwobWVzc2FnZSk7XG4gIH07XG5cblxuICB0aGlzLmNsb3NlID0gZnVuY3Rpb24oKVxuICB7XG4gICAgLy8gUHJldmVudCB0byByZWNlaXZlIG5ldyBtZXNzYWdlc1xuICAgIHZhciB0cmFuc3BvcnQgPSB0aGlzLmdldFRyYW5zcG9ydCgpO1xuICAgIGlmKHRyYW5zcG9ydCAmJiB0cmFuc3BvcnQuY2xvc2UpXG4gICAgICAgdHJhbnNwb3J0LmNsb3NlKCk7XG5cbiAgICAvLyBSZXF1ZXN0ICYgcHJvY2Vzc2VkIHJlc3BvbnNlc1xuICAgIHRoaXMuY2FuY2VsKCk7XG5cbiAgICBwcm9jZXNzZWRSZXNwb25zZXMuZm9yRWFjaChjbGVhclRpbWVvdXQpO1xuXG4gICAgLy8gUmVzcG9uc2VzXG4gICAgcmVzcG9uc2VzLmZvckVhY2goZnVuY3Rpb24ocmVzcG9uc2UpXG4gICAge1xuICAgICAgY2xlYXJUaW1lb3V0KHJlc3BvbnNlLnRpbWVvdXQpO1xuICAgIH0pO1xuICB9O1xuXG5cbiAgLyoqXG4gICAqIEdlbmVyYXRlcyBhbmQgZW5jb2RlIGEgSnNvblJQQyAyLjAgbWVzc2FnZVxuICAgKlxuICAgKiBAcGFyYW0ge1N0cmluZ30gbWV0aG9kIC1tZXRob2Qgb2YgdGhlIG5vdGlmaWNhdGlvblxuICAgKiBAcGFyYW0gcGFyYW1zIC0gcGFyYW1ldGVycyBvZiB0aGUgbm90aWZpY2F0aW9uXG4gICAqIEBwYXJhbSBbZGVzdF0gLSBkZXN0aW5hdGlvbiBvZiB0aGUgbm90aWZpY2F0aW9uXG4gICAqIEBwYXJhbSB7b2JqZWN0fSBbdHJhbnNwb3J0XSAtIHRyYW5zcG9ydCB3aGVyZSB0byBzZW5kIHRoZSBtZXNzYWdlXG4gICAqIEBwYXJhbSBbY2FsbGJhY2tdIC0gZnVuY3Rpb24gY2FsbGVkIHdoZW4gYSByZXNwb25zZSB0byB0aGlzIHJlcXVlc3QgaXNcbiAgICogICByZWNlaXZlZC4gSWYgbm90IGRlZmluZWQsIGEgbm90aWZpY2F0aW9uIHdpbGwgYmUgc2VuZCBpbnN0ZWFkXG4gICAqXG4gICAqIEByZXR1cm5zIHtzdHJpbmd9IEEgcmF3IEpzb25SUEMgMi4wIHJlcXVlc3Qgb3Igbm90aWZpY2F0aW9uIHN0cmluZ1xuICAgKi9cbiAgdGhpcy5lbmNvZGUgPSBmdW5jdGlvbihtZXRob2QsIHBhcmFtcywgZGVzdCwgdHJhbnNwb3J0LCBjYWxsYmFjaylcbiAge1xuICAgIC8vIEZpeCBvcHRpb25hbCBwYXJhbWV0ZXJzXG4gICAgaWYocGFyYW1zIGluc3RhbmNlb2YgRnVuY3Rpb24pXG4gICAge1xuICAgICAgaWYoZGVzdCAhPSB1bmRlZmluZWQpXG4gICAgICAgIHRocm93IG5ldyBTeW50YXhFcnJvcihcIlRoZXJlIGNhbid0IGJlIHBhcmFtZXRlcnMgYWZ0ZXIgY2FsbGJhY2tcIik7XG5cbiAgICAgIGNhbGxiYWNrICA9IHBhcmFtcztcbiAgICAgIHRyYW5zcG9ydCA9IHVuZGVmaW5lZDtcbiAgICAgIGRlc3QgICAgICA9IHVuZGVmaW5lZDtcbiAgICAgIHBhcmFtcyAgICA9IHVuZGVmaW5lZDtcbiAgICB9XG5cbiAgICBlbHNlIGlmKGRlc3QgaW5zdGFuY2VvZiBGdW5jdGlvbilcbiAgICB7XG4gICAgICBpZih0cmFuc3BvcnQgIT0gdW5kZWZpbmVkKVxuICAgICAgICB0aHJvdyBuZXcgU3ludGF4RXJyb3IoXCJUaGVyZSBjYW4ndCBiZSBwYXJhbWV0ZXJzIGFmdGVyIGNhbGxiYWNrXCIpO1xuXG4gICAgICBjYWxsYmFjayAgPSBkZXN0O1xuICAgICAgdHJhbnNwb3J0ID0gdW5kZWZpbmVkO1xuICAgICAgZGVzdCAgICAgID0gdW5kZWZpbmVkO1xuICAgIH1cblxuICAgIGVsc2UgaWYodHJhbnNwb3J0IGluc3RhbmNlb2YgRnVuY3Rpb24pXG4gICAge1xuICAgICAgaWYoY2FsbGJhY2sgIT0gdW5kZWZpbmVkKVxuICAgICAgICB0aHJvdyBuZXcgU3ludGF4RXJyb3IoXCJUaGVyZSBjYW4ndCBiZSBwYXJhbWV0ZXJzIGFmdGVyIGNhbGxiYWNrXCIpO1xuXG4gICAgICBjYWxsYmFjayAgPSB0cmFuc3BvcnQ7XG4gICAgICB0cmFuc3BvcnQgPSB1bmRlZmluZWQ7XG4gICAgfTtcblxuICAgIGlmKHNlbGYucGVlcklEICE9IHVuZGVmaW5lZClcbiAgICB7XG4gICAgICBwYXJhbXMgPSBwYXJhbXMgfHwge307XG5cbiAgICAgIHBhcmFtcy5mcm9tID0gc2VsZi5wZWVySUQ7XG4gICAgfTtcblxuICAgIGlmKGRlc3QgIT0gdW5kZWZpbmVkKVxuICAgIHtcbiAgICAgIHBhcmFtcyA9IHBhcmFtcyB8fCB7fTtcblxuICAgICAgcGFyYW1zLmRlc3QgPSBkZXN0O1xuICAgIH07XG5cbiAgICAvLyBFbmNvZGUgbWVzc2FnZVxuICAgIHZhciBtZXNzYWdlID1cbiAgICB7XG4gICAgICBtZXRob2Q6IG1ldGhvZCxcbiAgICAgIHBhcmFtczogcGFyYW1zXG4gICAgfTtcblxuICAgIGlmKGNhbGxiYWNrKVxuICAgIHtcbiAgICAgIHZhciBpZCA9IHJlcXVlc3RJRCsrO1xuICAgICAgdmFyIHJldHJpZWQgPSAwO1xuXG4gICAgICBtZXNzYWdlID0gcGFja2VyLnBhY2sobWVzc2FnZSwgaWQpO1xuXG4gICAgICBmdW5jdGlvbiBkaXNwYXRjaENhbGxiYWNrKGVycm9yLCByZXN1bHQpXG4gICAgICB7XG4gICAgICAgIHNlbGYuY2FuY2VsKG1lc3NhZ2UpO1xuXG4gICAgICAgIGNhbGxiYWNrKGVycm9yLCByZXN1bHQpO1xuICAgICAgfTtcblxuICAgICAgdmFyIHJlcXVlc3QgPVxuICAgICAge1xuICAgICAgICBtZXNzYWdlOiAgICAgICAgIG1lc3NhZ2UsXG4gICAgICAgIGNhbGxiYWNrOiAgICAgICAgZGlzcGF0Y2hDYWxsYmFjayxcbiAgICAgICAgcmVzcG9uc2VNZXRob2RzOiByZXNwb25zZU1ldGhvZHNbbWV0aG9kXSB8fCB7fVxuICAgICAgfTtcblxuICAgICAgdmFyIGVuY29kZV90cmFuc3BvcnQgPSB1bmlmeVRyYW5zcG9ydCh0cmFuc3BvcnQpO1xuXG4gICAgICBmdW5jdGlvbiBzZW5kUmVxdWVzdCh0cmFuc3BvcnQpXG4gICAgICB7XG4gICAgICAgIHZhciBydCA9IChtZXRob2QgPT09ICdwaW5nJyA/IHBpbmdfcmVxdWVzdF90aW1lb3V0IDogcmVxdWVzdF90aW1lb3V0KTtcbiAgICAgICAgcmVxdWVzdC50aW1lb3V0ID0gc2V0VGltZW91dCh0aW1lb3V0LCBydCpNYXRoLnBvdygyLCByZXRyaWVkKyspKTtcbiAgICAgICAgbWVzc2FnZTJLZXlbbWVzc2FnZV0gPSB7aWQ6IGlkLCBkZXN0OiBkZXN0fTtcbiAgICAgICAgcmVxdWVzdHMuc2V0KHJlcXVlc3QsIGlkLCBkZXN0KTtcblxuICAgICAgICB0cmFuc3BvcnQgPSB0cmFuc3BvcnQgfHwgZW5jb2RlX3RyYW5zcG9ydCB8fCBzZWxmLmdldFRyYW5zcG9ydCgpO1xuICAgICAgICBpZih0cmFuc3BvcnQpXG4gICAgICAgICAgcmV0dXJuIHRyYW5zcG9ydC5zZW5kKG1lc3NhZ2UpO1xuXG4gICAgICAgIHJldHVybiBtZXNzYWdlO1xuICAgICAgfTtcblxuICAgICAgZnVuY3Rpb24gcmV0cnkodHJhbnNwb3J0KVxuICAgICAge1xuICAgICAgICB0cmFuc3BvcnQgPSB1bmlmeVRyYW5zcG9ydCh0cmFuc3BvcnQpO1xuXG4gICAgICAgIGNvbnNvbGUud2FybihyZXRyaWVkKycgcmV0cnkgZm9yIHJlcXVlc3QgbWVzc2FnZTonLG1lc3NhZ2UpO1xuXG4gICAgICAgIHZhciB0aW1lb3V0ID0gcHJvY2Vzc2VkUmVzcG9uc2VzLnBvcChpZCwgZGVzdCk7XG4gICAgICAgIGNsZWFyVGltZW91dCh0aW1lb3V0KTtcblxuICAgICAgICByZXR1cm4gc2VuZFJlcXVlc3QodHJhbnNwb3J0KTtcbiAgICAgIH07XG5cbiAgICAgIGZ1bmN0aW9uIHRpbWVvdXQoKVxuICAgICAge1xuICAgICAgICBpZihyZXRyaWVkIDwgbWF4X3JldHJpZXMpXG4gICAgICAgICAgcmV0dXJuIHJldHJ5KHRyYW5zcG9ydCk7XG5cbiAgICAgICAgdmFyIGVycm9yID0gbmV3IEVycm9yKCdSZXF1ZXN0IGhhcyB0aW1lZCBvdXQnKTtcbiAgICAgICAgICAgIGVycm9yLnJlcXVlc3QgPSBtZXNzYWdlO1xuXG4gICAgICAgIGVycm9yLnJldHJ5ID0gcmV0cnk7XG5cbiAgICAgICAgZGlzcGF0Y2hDYWxsYmFjayhlcnJvcilcbiAgICAgIH07XG5cbiAgICAgIHJldHVybiBzZW5kUmVxdWVzdCh0cmFuc3BvcnQpO1xuICAgIH07XG5cbiAgICAvLyBSZXR1cm4gdGhlIHBhY2tlZCBtZXNzYWdlXG4gICAgbWVzc2FnZSA9IHBhY2tlci5wYWNrKG1lc3NhZ2UpO1xuXG4gICAgdHJhbnNwb3J0ID0gdHJhbnNwb3J0IHx8IHRoaXMuZ2V0VHJhbnNwb3J0KCk7XG4gICAgaWYodHJhbnNwb3J0KVxuICAgICAgcmV0dXJuIHRyYW5zcG9ydC5zZW5kKG1lc3NhZ2UpO1xuXG4gICAgcmV0dXJuIG1lc3NhZ2U7XG4gIH07XG5cbiAgLyoqXG4gICAqIERlY29kZSBhbmQgcHJvY2VzcyBhIEpzb25SUEMgMi4wIG1lc3NhZ2VcbiAgICpcbiAgICogQHBhcmFtIHtzdHJpbmd9IG1lc3NhZ2UgLSBzdHJpbmcgd2l0aCB0aGUgY29udGVudCBvZiB0aGUgbWVzc2FnZVxuICAgKlxuICAgKiBAcmV0dXJucyB7UnBjTm90aWZpY2F0aW9ufFJwY1JlcXVlc3R8dW5kZWZpbmVkfSAtIHRoZSByZXByZXNlbnRhdGlvbiBvZiB0aGVcbiAgICogICBub3RpZmljYXRpb24gb3IgdGhlIHJlcXVlc3QuIElmIGEgcmVzcG9uc2Ugd2FzIHByb2Nlc3NlZCwgaXQgd2lsbCByZXR1cm5cbiAgICogICBgdW5kZWZpbmVkYCB0byBub3RpZnkgdGhhdCBpdCB3YXMgcHJvY2Vzc2VkXG4gICAqXG4gICAqIEB0aHJvd3Mge1R5cGVFcnJvcn0gLSBNZXNzYWdlIGlzIG5vdCBkZWZpbmVkXG4gICAqL1xuICB0aGlzLmRlY29kZSA9IGZ1bmN0aW9uKG1lc3NhZ2UsIHRyYW5zcG9ydClcbiAge1xuICAgIGlmKCFtZXNzYWdlKVxuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIk1lc3NhZ2UgaXMgbm90IGRlZmluZWRcIik7XG5cbiAgICB0cnlcbiAgICB7XG4gICAgICBtZXNzYWdlID0gcGFja2VyLnVucGFjayhtZXNzYWdlKTtcbiAgICB9XG4gICAgY2F0Y2goZSlcbiAgICB7XG4gICAgICAvLyBJZ25vcmUgaW52YWxpZCBtZXNzYWdlc1xuICAgICAgcmV0dXJuIGNvbnNvbGUuZGVidWcoZSwgbWVzc2FnZSk7XG4gICAgfTtcblxuICAgIHZhciBpZCAgICAgPSBtZXNzYWdlLmlkO1xuICAgIHZhciBhY2sgICAgPSBtZXNzYWdlLmFjaztcbiAgICB2YXIgbWV0aG9kID0gbWVzc2FnZS5tZXRob2Q7XG4gICAgdmFyIHBhcmFtcyA9IG1lc3NhZ2UucGFyYW1zIHx8IHt9O1xuXG4gICAgdmFyIGZyb20gPSBwYXJhbXMuZnJvbTtcbiAgICB2YXIgZGVzdCA9IHBhcmFtcy5kZXN0O1xuXG4gICAgLy8gSWdub3JlIG1lc3NhZ2VzIHNlbmQgYnkgdXNcbiAgICBpZihzZWxmLnBlZXJJRCAhPSB1bmRlZmluZWQgJiYgZnJvbSA9PSBzZWxmLnBlZXJJRCkgcmV0dXJuO1xuXG4gICAgLy8gTm90aWZpY2F0aW9uXG4gICAgaWYoaWQgPT0gdW5kZWZpbmVkICYmIGFjayA9PSB1bmRlZmluZWQpXG4gICAge1xuICAgICAgdmFyIG5vdGlmaWNhdGlvbiA9IG5ldyBScGNOb3RpZmljYXRpb24obWV0aG9kLCBwYXJhbXMpO1xuXG4gICAgICBpZihzZWxmLmVtaXQoJ3JlcXVlc3QnLCBub3RpZmljYXRpb24pKSByZXR1cm47XG4gICAgICByZXR1cm4gbm90aWZpY2F0aW9uO1xuICAgIH07XG5cblxuICAgIGZ1bmN0aW9uIHByb2Nlc3NSZXF1ZXN0KClcbiAgICB7XG4gICAgICAvLyBJZiB3ZSBoYXZlIGEgdHJhbnNwb3J0IGFuZCBpdCdzIGEgZHVwbGljYXRlZCByZXF1ZXN0LCByZXBseSBpbm1lZGlhdGx5XG4gICAgICB0cmFuc3BvcnQgPSB1bmlmeVRyYW5zcG9ydCh0cmFuc3BvcnQpIHx8IHNlbGYuZ2V0VHJhbnNwb3J0KCk7XG4gICAgICBpZih0cmFuc3BvcnQpXG4gICAgICB7XG4gICAgICAgIHZhciByZXNwb25zZSA9IHJlc3BvbnNlcy5nZXQoaWQsIGZyb20pO1xuICAgICAgICBpZihyZXNwb25zZSlcbiAgICAgICAgICByZXR1cm4gdHJhbnNwb3J0LnNlbmQocmVzcG9uc2UubWVzc2FnZSk7XG4gICAgICB9O1xuXG4gICAgICB2YXIgaWRBY2sgPSAoaWQgIT0gdW5kZWZpbmVkKSA/IGlkIDogYWNrO1xuICAgICAgdmFyIHJlcXVlc3QgPSBuZXcgUnBjUmVxdWVzdChtZXRob2QsIHBhcmFtcywgaWRBY2ssIGZyb20sIHRyYW5zcG9ydCk7XG5cbiAgICAgIGlmKHNlbGYuZW1pdCgncmVxdWVzdCcsIHJlcXVlc3QpKSByZXR1cm47XG4gICAgICByZXR1cm4gcmVxdWVzdDtcbiAgICB9O1xuXG4gICAgZnVuY3Rpb24gcHJvY2Vzc1Jlc3BvbnNlKHJlcXVlc3QsIGVycm9yLCByZXN1bHQpXG4gICAge1xuICAgICAgcmVxdWVzdC5jYWxsYmFjayhlcnJvciwgcmVzdWx0KTtcbiAgICB9O1xuXG4gICAgZnVuY3Rpb24gZHVwbGljYXRlZFJlc3BvbnNlKHRpbWVvdXQpXG4gICAge1xuICAgICAgY29uc29sZS53YXJuKFwiUmVzcG9uc2UgYWxyZWFkeSBwcm9jZXNzZWRcIiwgbWVzc2FnZSk7XG5cbiAgICAgIC8vIFVwZGF0ZSBkdXBsaWNhdGVkIHJlc3BvbnNlcyB0aW1lb3V0XG4gICAgICBjbGVhclRpbWVvdXQodGltZW91dCk7XG4gICAgICBzdG9yZVByb2Nlc3NlZFJlc3BvbnNlKGFjaywgZnJvbSk7XG4gICAgfTtcblxuXG4gICAgLy8gUmVxdWVzdCwgb3IgcmVzcG9uc2Ugd2l0aCBvd24gbWV0aG9kXG4gICAgaWYobWV0aG9kKVxuICAgIHtcbiAgICAgIC8vIENoZWNrIGlmIGl0J3MgYSByZXNwb25zZSB3aXRoIG93biBtZXRob2RcbiAgICAgIGlmKGRlc3QgPT0gdW5kZWZpbmVkIHx8IGRlc3QgPT0gc2VsZi5wZWVySUQpXG4gICAgICB7XG4gICAgICAgIHZhciByZXF1ZXN0ID0gcmVxdWVzdHMuZ2V0KGFjaywgZnJvbSk7XG4gICAgICAgIGlmKHJlcXVlc3QpXG4gICAgICAgIHtcbiAgICAgICAgICB2YXIgcmVzcG9uc2VNZXRob2RzID0gcmVxdWVzdC5yZXNwb25zZU1ldGhvZHM7XG5cbiAgICAgICAgICBpZihtZXRob2QgPT0gcmVzcG9uc2VNZXRob2RzLmVycm9yKVxuICAgICAgICAgICAgcmV0dXJuIHByb2Nlc3NSZXNwb25zZShyZXF1ZXN0LCBwYXJhbXMpO1xuXG4gICAgICAgICAgaWYobWV0aG9kID09IHJlc3BvbnNlTWV0aG9kcy5yZXNwb25zZSlcbiAgICAgICAgICAgIHJldHVybiBwcm9jZXNzUmVzcG9uc2UocmVxdWVzdCwgbnVsbCwgcGFyYW1zKTtcblxuICAgICAgICAgIHJldHVybiBwcm9jZXNzUmVxdWVzdCgpO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIHByb2Nlc3NlZCA9IHByb2Nlc3NlZFJlc3BvbnNlcy5nZXQoYWNrLCBmcm9tKTtcbiAgICAgICAgaWYocHJvY2Vzc2VkKVxuICAgICAgICAgIHJldHVybiBkdXBsaWNhdGVkUmVzcG9uc2UocHJvY2Vzc2VkKTtcbiAgICAgIH1cblxuICAgICAgLy8gUmVxdWVzdFxuICAgICAgcmV0dXJuIHByb2Nlc3NSZXF1ZXN0KCk7XG4gICAgfTtcblxuICAgIHZhciBlcnJvciAgPSBtZXNzYWdlLmVycm9yO1xuICAgIHZhciByZXN1bHQgPSBtZXNzYWdlLnJlc3VsdDtcblxuICAgIC8vIElnbm9yZSByZXNwb25zZXMgbm90IHNlbmQgdG8gdXNcbiAgICBpZihlcnJvciAgJiYgZXJyb3IuZGVzdCAgJiYgZXJyb3IuZGVzdCAgIT0gc2VsZi5wZWVySUQpIHJldHVybjtcbiAgICBpZihyZXN1bHQgJiYgcmVzdWx0LmRlc3QgJiYgcmVzdWx0LmRlc3QgIT0gc2VsZi5wZWVySUQpIHJldHVybjtcblxuICAgIC8vIFJlc3BvbnNlXG4gICAgdmFyIHJlcXVlc3QgPSByZXF1ZXN0cy5nZXQoYWNrLCBmcm9tKTtcbiAgICBpZighcmVxdWVzdClcbiAgICB7XG4gICAgICB2YXIgcHJvY2Vzc2VkID0gcHJvY2Vzc2VkUmVzcG9uc2VzLmdldChhY2ssIGZyb20pO1xuICAgICAgaWYocHJvY2Vzc2VkKVxuICAgICAgICByZXR1cm4gZHVwbGljYXRlZFJlc3BvbnNlKHByb2Nlc3NlZCk7XG5cbiAgICAgIHJldHVybiBjb25zb2xlLndhcm4oXCJObyBjYWxsYmFjayB3YXMgZGVmaW5lZCBmb3IgdGhpcyBtZXNzYWdlXCIsIG1lc3NhZ2UpO1xuICAgIH07XG5cbiAgICAvLyBQcm9jZXNzIHJlc3BvbnNlXG4gICAgcHJvY2Vzc1Jlc3BvbnNlKHJlcXVlc3QsIGVycm9yLCByZXN1bHQpO1xuICB9O1xufTtcbmluaGVyaXRzKFJwY0J1aWxkZXIsIEV2ZW50RW1pdHRlcik7XG5cblxuUnBjQnVpbGRlci5ScGNOb3RpZmljYXRpb24gPSBScGNOb3RpZmljYXRpb247XG5cblxubW9kdWxlLmV4cG9ydHMgPSBScGNCdWlsZGVyO1xuXG52YXIgY2xpZW50cyA9IHJlcXVpcmUoJy4vY2xpZW50cycpO1xudmFyIHRyYW5zcG9ydHMgPSByZXF1aXJlKCcuL2NsaWVudHMvdHJhbnNwb3J0cycpO1xuXG5ScGNCdWlsZGVyLmNsaWVudHMgPSBjbGllbnRzO1xuUnBjQnVpbGRlci5jbGllbnRzLnRyYW5zcG9ydHMgPSB0cmFuc3BvcnRzO1xuUnBjQnVpbGRlci5wYWNrZXJzID0gcGFja2VycztcbiIsIi8qKlxuICogSnNvblJQQyAyLjAgcGFja2VyXG4gKi9cblxuLyoqXG4gKiBQYWNrIGEgSnNvblJQQyAyLjAgbWVzc2FnZVxuICpcbiAqIEBwYXJhbSB7T2JqZWN0fSBtZXNzYWdlIC0gb2JqZWN0IHRvIGJlIHBhY2thZ2VkLiBJdCByZXF1aXJlcyB0byBoYXZlIGFsbCB0aGVcbiAqICAgZmllbGRzIG5lZWRlZCBieSB0aGUgSnNvblJQQyAyLjAgbWVzc2FnZSB0aGF0IGl0J3MgZ29pbmcgdG8gYmUgZ2VuZXJhdGVkXG4gKlxuICogQHJldHVybiB7U3RyaW5nfSAtIHRoZSBzdHJpbmdpZmllZCBKc29uUlBDIDIuMCBtZXNzYWdlXG4gKi9cbmZ1bmN0aW9uIHBhY2sobWVzc2FnZSwgaWQpXG57XG4gIHZhciByZXN1bHQgPVxuICB7XG4gICAganNvbnJwYzogXCIyLjBcIlxuICB9O1xuXG4gIC8vIFJlcXVlc3RcbiAgaWYobWVzc2FnZS5tZXRob2QpXG4gIHtcbiAgICByZXN1bHQubWV0aG9kID0gbWVzc2FnZS5tZXRob2Q7XG5cbiAgICBpZihtZXNzYWdlLnBhcmFtcylcbiAgICAgIHJlc3VsdC5wYXJhbXMgPSBtZXNzYWdlLnBhcmFtcztcblxuICAgIC8vIFJlcXVlc3QgaXMgYSBub3RpZmljYXRpb25cbiAgICBpZihpZCAhPSB1bmRlZmluZWQpXG4gICAgICByZXN1bHQuaWQgPSBpZDtcbiAgfVxuXG4gIC8vIFJlc3BvbnNlXG4gIGVsc2UgaWYoaWQgIT0gdW5kZWZpbmVkKVxuICB7XG4gICAgaWYobWVzc2FnZS5lcnJvcilcbiAgICB7XG4gICAgICBpZihtZXNzYWdlLnJlc3VsdCAhPT0gdW5kZWZpbmVkKVxuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQm90aCByZXN1bHQgYW5kIGVycm9yIGFyZSBkZWZpbmVkXCIpO1xuXG4gICAgICByZXN1bHQuZXJyb3IgPSBtZXNzYWdlLmVycm9yO1xuICAgIH1cbiAgICBlbHNlIGlmKG1lc3NhZ2UucmVzdWx0ICE9PSB1bmRlZmluZWQpXG4gICAgICByZXN1bHQucmVzdWx0ID0gbWVzc2FnZS5yZXN1bHQ7XG4gICAgZWxzZVxuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIk5vIHJlc3VsdCBvciBlcnJvciBpcyBkZWZpbmVkXCIpO1xuXG4gICAgcmVzdWx0LmlkID0gaWQ7XG4gIH07XG5cbiAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KHJlc3VsdCk7XG59O1xuXG4vKipcbiAqIFVucGFjayBhIEpzb25SUEMgMi4wIG1lc3NhZ2VcbiAqXG4gKiBAcGFyYW0ge1N0cmluZ30gbWVzc2FnZSAtIHN0cmluZyB3aXRoIHRoZSBjb250ZW50IG9mIHRoZSBKc29uUlBDIDIuMCBtZXNzYWdlXG4gKlxuICogQHRocm93cyB7VHlwZUVycm9yfSAtIEludmFsaWQgSnNvblJQQyB2ZXJzaW9uXG4gKlxuICogQHJldHVybiB7T2JqZWN0fSAtIG9iamVjdCBmaWxsZWQgd2l0aCB0aGUgSnNvblJQQyAyLjAgbWVzc2FnZSBjb250ZW50XG4gKi9cbmZ1bmN0aW9uIHVucGFjayhtZXNzYWdlKVxue1xuICB2YXIgcmVzdWx0ID0gbWVzc2FnZTtcblxuICBpZih0eXBlb2YgbWVzc2FnZSA9PT0gJ3N0cmluZycgfHwgbWVzc2FnZSBpbnN0YW5jZW9mIFN0cmluZykge1xuICAgIHJlc3VsdCA9IEpTT04ucGFyc2UobWVzc2FnZSk7XG4gIH1cblxuICAvLyBDaGVjayBpZiBpdCdzIGEgdmFsaWQgbWVzc2FnZVxuXG4gIHZhciB2ZXJzaW9uID0gcmVzdWx0Lmpzb25ycGM7XG4gIGlmKHZlcnNpb24gIT09ICcyLjAnKVxuICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJJbnZhbGlkIEpzb25SUEMgdmVyc2lvbiAnXCIgKyB2ZXJzaW9uICsgXCInOiBcIiArIG1lc3NhZ2UpO1xuXG4gIC8vIFJlc3BvbnNlXG4gIGlmKHJlc3VsdC5tZXRob2QgPT0gdW5kZWZpbmVkKVxuICB7XG4gICAgaWYocmVzdWx0LmlkID09IHVuZGVmaW5lZClcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJJbnZhbGlkIG1lc3NhZ2U6IFwiK21lc3NhZ2UpO1xuXG4gICAgdmFyIHJlc3VsdF9kZWZpbmVkID0gcmVzdWx0LnJlc3VsdCAhPT0gdW5kZWZpbmVkO1xuICAgIHZhciBlcnJvcl9kZWZpbmVkICA9IHJlc3VsdC5lcnJvciAgIT09IHVuZGVmaW5lZDtcblxuICAgIC8vIENoZWNrIG9ubHkgcmVzdWx0IG9yIGVycm9yIGlzIGRlZmluZWQsIG5vdCBib3RoIG9yIG5vbmVcbiAgICBpZihyZXN1bHRfZGVmaW5lZCAmJiBlcnJvcl9kZWZpbmVkKVxuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkJvdGggcmVzdWx0IGFuZCBlcnJvciBhcmUgZGVmaW5lZDogXCIrbWVzc2FnZSk7XG5cbiAgICBpZighcmVzdWx0X2RlZmluZWQgJiYgIWVycm9yX2RlZmluZWQpXG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiTm8gcmVzdWx0IG9yIGVycm9yIGlzIGRlZmluZWQ6IFwiK21lc3NhZ2UpO1xuXG4gICAgcmVzdWx0LmFjayA9IHJlc3VsdC5pZDtcbiAgICBkZWxldGUgcmVzdWx0LmlkO1xuICB9XG5cbiAgLy8gUmV0dXJuIHVucGFja2VkIG1lc3NhZ2VcbiAgcmV0dXJuIHJlc3VsdDtcbn07XG5cblxuZXhwb3J0cy5wYWNrICAgPSBwYWNrO1xuZXhwb3J0cy51bnBhY2sgPSB1bnBhY2s7XG4iLCJmdW5jdGlvbiBwYWNrKG1lc3NhZ2UpXG57XG4gIHRocm93IG5ldyBUeXBlRXJyb3IoXCJOb3QgeWV0IGltcGxlbWVudGVkXCIpO1xufTtcblxuZnVuY3Rpb24gdW5wYWNrKG1lc3NhZ2UpXG57XG4gIHRocm93IG5ldyBUeXBlRXJyb3IoXCJOb3QgeWV0IGltcGxlbWVudGVkXCIpO1xufTtcblxuXG5leHBvcnRzLnBhY2sgICA9IHBhY2s7XG5leHBvcnRzLnVucGFjayA9IHVucGFjaztcbiIsInZhciBKc29uUlBDID0gcmVxdWlyZSgnLi9Kc29uUlBDJyk7XG52YXIgWG1sUlBDICA9IHJlcXVpcmUoJy4vWG1sUlBDJyk7XG5cblxuZXhwb3J0cy5Kc29uUlBDID0gSnNvblJQQztcbmV4cG9ydHMuWG1sUlBDICA9IFhtbFJQQztcbiIsIi8vIExhc3QgdGltZSB1cGRhdGVkIG9uIEp1bmUgMDgsIDIwMThcblxuLy8gTGF0ZXN0IGZpbGUgY2FuIGJlIGZvdW5kIGhlcmU6IGh0dHBzOi8vY2RuLndlYnJ0Yy1leHBlcmltZW50LmNvbS9nZXRTY3JlZW5JZC5qc1xuXG4vLyBNdWF6IEtoYW4gICAgICAgICAtIHd3dy5NdWF6S2hhbi5jb21cbi8vIE1JVCBMaWNlbnNlICAgICAgIC0gd3d3LldlYlJUQy1FeHBlcmltZW50LmNvbS9saWNlbmNlXG4vLyBEb2N1bWVudGF0aW9uICAgICAtIGh0dHBzOi8vZ2l0aHViLmNvbS9tdWF6LWtoYW4vZ2V0U2NyZWVuSWQuXG5cbi8vIF9fX19fX19fX19fX19fXG4vLyBnZXRTY3JlZW5JZC5qc1xuXG4vKlxuZ2V0U2NyZWVuSWQoZnVuY3Rpb24gKGVycm9yLCBzb3VyY2VJZCwgc2NyZWVuX2NvbnN0cmFpbnRzKSB7XG4gICAgLy8gZXJyb3IgICAgPT0gbnVsbCB8fCAncGVybWlzc2lvbi1kZW5pZWQnIHx8ICdub3QtaW5zdGFsbGVkJyB8fCAnaW5zdGFsbGVkLWRpc2FibGVkJyB8fCAnbm90LWNocm9tZSdcbiAgICAvLyBzb3VyY2VJZCA9PSBudWxsIHx8ICdzdHJpbmcnIHx8ICdmaXJlZm94J1xuICAgIFxuICAgIGlmKG1pY3Jvc29mdEVkZ2UpIHtcbiAgICAgICAgbmF2aWdhdG9yLmdldERpc3BsYXlNZWRpYShzY3JlZW5fY29uc3RyYWludHMpLnRoZW4ob25TdWNjZXNzLCBvbkZhaWx1cmUpO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgbmF2aWdhdG9yLm1lZGlhRGV2aWNlcy5nZXRVc2VyTWVkaWEoc2NyZWVuX2NvbnN0cmFpbnRzKS50aGVuKG9uU3VjY2VzcyljYXRjaChvbkZhaWx1cmUpO1xuICAgIH1cbn0sICdwYXNzIHNlY29uZCBwYXJhbWV0ZXIgb25seSBpZiB5b3Ugd2FudCBzeXN0ZW0gYXVkaW8nKTtcbiovXG5cbndpbmRvdy5nZXRTY3JlZW5JZCA9IGZ1bmN0aW9uIChjYWxsYmFjaywgY3VzdG9tX3BhcmFtZXRlcikge1xuICAgIGlmIChuYXZpZ2F0b3IudXNlckFnZW50LmluZGV4T2YoJ0VkZ2UnKSAhPT0gLTEgJiYgKCEhbmF2aWdhdG9yLm1zU2F2ZU9yT3BlbkJsb2IgfHwgISFuYXZpZ2F0b3IubXNTYXZlQmxvYikpIHtcbiAgICAgICAgLy8gbWljcm9zb2Z0IGVkZ2UgPT4gbmF2aWdhdG9yLmdldERpc3BsYXlNZWRpYShzY3JlZW5fY29uc3RyYWludHMpLnRoZW4ob25TdWNjZXNzLCBvbkZhaWx1cmUpO1xuICAgICAgICBjYWxsYmFjayh7XG4gICAgICAgICAgICB2aWRlbzogdHJ1ZVxuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8vIGZvciBGaXJlZm94OlxuICAgIC8vIHNvdXJjZUlkID09ICdmaXJlZm94J1xuICAgIC8vIHNjcmVlbl9jb25zdHJhaW50cyA9IHsuLi59XG4gICAgaWYgKCEhbmF2aWdhdG9yLm1vekdldFVzZXJNZWRpYSkge1xuICAgICAgICBjYWxsYmFjayhudWxsLCAnZmlyZWZveCcsIHtcbiAgICAgICAgICAgIHZpZGVvOiB7XG4gICAgICAgICAgICAgICAgbW96TWVkaWFTb3VyY2U6ICd3aW5kb3cnLFxuICAgICAgICAgICAgICAgIG1lZGlhU291cmNlOiAnd2luZG93J1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdtZXNzYWdlJywgb25JRnJhbWVDYWxsYmFjayk7XG5cbiAgICBmdW5jdGlvbiBvbklGcmFtZUNhbGxiYWNrKGV2ZW50KSB7XG4gICAgICAgIGlmICghZXZlbnQuZGF0YSkgcmV0dXJuO1xuXG4gICAgICAgIGlmIChldmVudC5kYXRhLmNocm9tZU1lZGlhU291cmNlSWQpIHtcbiAgICAgICAgICAgIGlmIChldmVudC5kYXRhLmNocm9tZU1lZGlhU291cmNlSWQgPT09ICdQZXJtaXNzaW9uRGVuaWVkRXJyb3InKSB7XG4gICAgICAgICAgICAgICAgY2FsbGJhY2soJ3Blcm1pc3Npb24tZGVuaWVkJyk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGNhbGxiYWNrKG51bGwsIGV2ZW50LmRhdGEuY2hyb21lTWVkaWFTb3VyY2VJZCwgZ2V0U2NyZWVuQ29uc3RyYWludHMobnVsbCwgZXZlbnQuZGF0YS5jaHJvbWVNZWRpYVNvdXJjZUlkLCBldmVudC5kYXRhLmNhblJlcXVlc3RBdWRpb1RyYWNrKSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIHRoaXMgZXZlbnQgbGlzdGVuZXIgaXMgbm8gbW9yZSBuZWVkZWRcbiAgICAgICAgICAgIHdpbmRvdy5yZW1vdmVFdmVudExpc3RlbmVyKCdtZXNzYWdlJywgb25JRnJhbWVDYWxsYmFjayk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoZXZlbnQuZGF0YS5jaHJvbWVFeHRlbnNpb25TdGF0dXMpIHtcbiAgICAgICAgICAgIGNhbGxiYWNrKGV2ZW50LmRhdGEuY2hyb21lRXh0ZW5zaW9uU3RhdHVzLCBudWxsLCBnZXRTY3JlZW5Db25zdHJhaW50cyhldmVudC5kYXRhLmNocm9tZUV4dGVuc2lvblN0YXR1cykpO1xuXG4gICAgICAgICAgICAvLyB0aGlzIGV2ZW50IGxpc3RlbmVyIGlzIG5vIG1vcmUgbmVlZGVkXG4gICAgICAgICAgICB3aW5kb3cucmVtb3ZlRXZlbnRMaXN0ZW5lcignbWVzc2FnZScsIG9uSUZyYW1lQ2FsbGJhY2spO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgaWYgKCFjdXN0b21fcGFyYW1ldGVyKSB7XG4gICAgICAgIHNldFRpbWVvdXQocG9zdEdldFNvdXJjZUlkTWVzc2FnZSwgMTAwKTtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcG9zdEdldFNvdXJjZUlkTWVzc2FnZShjdXN0b21fcGFyYW1ldGVyKTtcbiAgICAgICAgfSwgMTAwKTtcbiAgICB9XG59O1xuXG5mdW5jdGlvbiBnZXRTY3JlZW5Db25zdHJhaW50cyhlcnJvciwgc291cmNlSWQsIGNhblJlcXVlc3RBdWRpb1RyYWNrKSB7XG4gICAgdmFyIHNjcmVlbl9jb25zdHJhaW50cyA9IHtcbiAgICAgICAgYXVkaW86IGZhbHNlLFxuICAgICAgICB2aWRlbzoge1xuICAgICAgICAgICAgbWFuZGF0b3J5OiB7XG4gICAgICAgICAgICAgICAgY2hyb21lTWVkaWFTb3VyY2U6IGVycm9yID8gJ3NjcmVlbicgOiAnZGVza3RvcCcsXG4gICAgICAgICAgICAgICAgbWF4V2lkdGg6IHdpbmRvdy5zY3JlZW4ud2lkdGggPiAxOTIwID8gd2luZG93LnNjcmVlbi53aWR0aCA6IDE5MjAsXG4gICAgICAgICAgICAgICAgbWF4SGVpZ2h0OiB3aW5kb3cuc2NyZWVuLmhlaWdodCA+IDEwODAgPyB3aW5kb3cuc2NyZWVuLmhlaWdodCA6IDEwODBcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBvcHRpb25hbDogW11cbiAgICAgICAgfVxuICAgIH07XG5cbiAgICBpZiAoISFjYW5SZXF1ZXN0QXVkaW9UcmFjaykge1xuICAgICAgICBzY3JlZW5fY29uc3RyYWludHMuYXVkaW8gPSB7XG4gICAgICAgICAgICBtYW5kYXRvcnk6IHtcbiAgICAgICAgICAgICAgICBjaHJvbWVNZWRpYVNvdXJjZTogZXJyb3IgPyAnc2NyZWVuJyA6ICdkZXNrdG9wJyxcbiAgICAgICAgICAgICAgICAvLyBlY2hvQ2FuY2VsbGF0aW9uOiB0cnVlXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgb3B0aW9uYWw6IFtdXG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgaWYgKHNvdXJjZUlkKSB7XG4gICAgICAgIHNjcmVlbl9jb25zdHJhaW50cy52aWRlby5tYW5kYXRvcnkuY2hyb21lTWVkaWFTb3VyY2VJZCA9IHNvdXJjZUlkO1xuXG4gICAgICAgIGlmIChzY3JlZW5fY29uc3RyYWludHMuYXVkaW8gJiYgc2NyZWVuX2NvbnN0cmFpbnRzLmF1ZGlvLm1hbmRhdG9yeSkge1xuICAgICAgICAgICAgc2NyZWVuX2NvbnN0cmFpbnRzLmF1ZGlvLm1hbmRhdG9yeS5jaHJvbWVNZWRpYVNvdXJjZUlkID0gc291cmNlSWQ7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gc2NyZWVuX2NvbnN0cmFpbnRzO1xufVxuXG5mdW5jdGlvbiBwb3N0R2V0U291cmNlSWRNZXNzYWdlKGN1c3RvbV9wYXJhbWV0ZXIpIHtcbiAgICBpZiAoIWlmcmFtZSkge1xuICAgICAgICBsb2FkSUZyYW1lKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHBvc3RHZXRTb3VyY2VJZE1lc3NhZ2UoY3VzdG9tX3BhcmFtZXRlcik7XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYgKCFpZnJhbWUuaXNMb2FkZWQpIHtcbiAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBwb3N0R2V0U291cmNlSWRNZXNzYWdlKGN1c3RvbV9wYXJhbWV0ZXIpO1xuICAgICAgICB9LCAxMDApO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYgKCFjdXN0b21fcGFyYW1ldGVyKSB7XG4gICAgICAgIGlmcmFtZS5jb250ZW50V2luZG93LnBvc3RNZXNzYWdlKHtcbiAgICAgICAgICAgIGNhcHR1cmVTb3VyY2VJZDogdHJ1ZVxuICAgICAgICB9LCAnKicpO1xuICAgIH1cbiAgICBlbHNlIGlmICghIWN1c3RvbV9wYXJhbWV0ZXIuZm9yRWFjaCkge1xuICAgICAgICBpZnJhbWUuY29udGVudFdpbmRvdy5wb3N0TWVzc2FnZSh7XG4gICAgICAgICAgICBjYXB0dXJlQ3VzdG9tU291cmNlSWQ6IGN1c3RvbV9wYXJhbWV0ZXJcbiAgICAgICAgfSwgJyonKTtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIGlmcmFtZS5jb250ZW50V2luZG93LnBvc3RNZXNzYWdlKHtcbiAgICAgICAgICAgIGNhcHR1cmVTb3VyY2VJZFdpdGhBdWRpbzogdHJ1ZVxuICAgICAgICB9LCAnKicpO1xuICAgIH1cbn1cblxudmFyIGlmcmFtZTtcblxuLy8gdGhpcyBmdW5jdGlvbiBpcyB1c2VkIGluIFJUQ011bHRpQ29ubmVjdGlvbiB2M1xud2luZG93LmdldFNjcmVlbkNvbnN0cmFpbnRzID0gZnVuY3Rpb24gKGNhbGxiYWNrKSB7XG4gICAgbG9hZElGcmFtZShmdW5jdGlvbiAoKSB7XG4gICAgICAgIGdldFNjcmVlbklkKGZ1bmN0aW9uIChlcnJvciwgc291cmNlSWQsIHNjcmVlbl9jb25zdHJhaW50cykge1xuICAgICAgICAgICAgaWYgKCFzY3JlZW5fY29uc3RyYWludHMpIHtcbiAgICAgICAgICAgICAgICBzY3JlZW5fY29uc3RyYWludHMgPSB7XG4gICAgICAgICAgICAgICAgICAgIHZpZGVvOiB0cnVlXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgY2FsbGJhY2soZXJyb3IsIHNjcmVlbl9jb25zdHJhaW50cy52aWRlbyk7XG4gICAgICAgIH0pO1xuICAgIH0pO1xufTtcblxuZnVuY3Rpb24gbG9hZElGcmFtZShsb2FkQ2FsbGJhY2spIHtcbiAgICBpZiAoaWZyYW1lKSB7XG4gICAgICAgIGxvYWRDYWxsYmFjaygpO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWZyYW1lID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnaWZyYW1lJyk7XG4gICAgaWZyYW1lLm9ubG9hZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWZyYW1lLmlzTG9hZGVkID0gdHJ1ZTtcbiAgICAgICAgbG9hZENhbGxiYWNrKCk7XG4gICAgfTtcbiAgICBpZnJhbWUuc3JjID0gJ2h0dHBzOi8vb3BlbnZpZHUuZ2l0aHViLmlvL29wZW52aWR1LXNjcmVlbi1zaGFyaW5nLWNocm9tZS1leHRlbnNpb24vJztcbiAgICBpZnJhbWUuc3R5bGUuZGlzcGxheSA9ICdub25lJztcbiAgICAoZG9jdW1lbnQuYm9keSB8fCBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQpLmFwcGVuZENoaWxkKGlmcmFtZSk7XG59XG5cbndpbmRvdy5nZXRDaHJvbWVFeHRlbnNpb25TdGF0dXMgPSBmdW5jdGlvbiAoY2FsbGJhY2spIHtcbiAgICAvLyBmb3IgRmlyZWZveDpcbiAgICBpZiAoISFuYXZpZ2F0b3IubW96R2V0VXNlck1lZGlhKSB7XG4gICAgICAgIGNhbGxiYWNrKCdpbnN0YWxsZWQtZW5hYmxlZCcpO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ21lc3NhZ2UnLCBvbklGcmFtZUNhbGxiYWNrKTtcblxuICAgIGZ1bmN0aW9uIG9uSUZyYW1lQ2FsbGJhY2soZXZlbnQpIHtcbiAgICAgICAgaWYgKCFldmVudC5kYXRhKSByZXR1cm47XG5cbiAgICAgICAgaWYgKGV2ZW50LmRhdGEuY2hyb21lRXh0ZW5zaW9uU3RhdHVzKSB7XG4gICAgICAgICAgICBjYWxsYmFjayhldmVudC5kYXRhLmNocm9tZUV4dGVuc2lvblN0YXR1cyk7XG5cbiAgICAgICAgICAgIC8vIHRoaXMgZXZlbnQgbGlzdGVuZXIgaXMgbm8gbW9yZSBuZWVkZWRcbiAgICAgICAgICAgIHdpbmRvdy5yZW1vdmVFdmVudExpc3RlbmVyKCdtZXNzYWdlJywgb25JRnJhbWVDYWxsYmFjayk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBzZXRUaW1lb3V0KHBvc3RHZXRDaHJvbWVFeHRlbnNpb25TdGF0dXNNZXNzYWdlLCAxMDApO1xufTtcblxuZnVuY3Rpb24gcG9zdEdldENocm9tZUV4dGVuc2lvblN0YXR1c01lc3NhZ2UoKSB7XG4gICAgaWYgKCFpZnJhbWUpIHtcbiAgICAgICAgbG9hZElGcmFtZShwb3N0R2V0Q2hyb21lRXh0ZW5zaW9uU3RhdHVzTWVzc2FnZSk7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAoIWlmcmFtZS5pc0xvYWRlZCkge1xuICAgICAgICBzZXRUaW1lb3V0KHBvc3RHZXRDaHJvbWVFeHRlbnNpb25TdGF0dXNNZXNzYWdlLCAxMDApO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWZyYW1lLmNvbnRlbnRXaW5kb3cucG9zdE1lc3NhZ2Uoe1xuICAgICAgICBnZXRDaHJvbWVFeHRlbnNpb25TdGF0dXM6IHRydWVcbiAgICB9LCAnKicpO1xufVxuXG5leHBvcnRzLmdldFNjcmVlbklkID0gZ2V0U2NyZWVuSWQ7IiwiLy8gZ2xvYmFsIHZhcmlhYmxlc1xudmFyIGNocm9tZU1lZGlhU291cmNlID0gJ3NjcmVlbic7XG52YXIgc291cmNlSWQ7XG52YXIgc2NyZWVuQ2FsbGJhY2s7XG52YXIgaXNGaXJlZm94ID0gdHlwZW9mIHdpbmRvdy5JbnN0YWxsVHJpZ2dlciAhPT0gJ3VuZGVmaW5lZCc7XG52YXIgaXNPcGVyYSA9ICEhd2luZG93Lm9wZXJhIHx8IG5hdmlnYXRvci51c2VyQWdlbnQuaW5kZXhPZignIE9QUi8nKSA+PSAwO1xudmFyIGlzQ2hyb21lID0gISF3aW5kb3cuY2hyb21lICYmICFpc09wZXJhO1xuXG53aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcignbWVzc2FnZScsIGZ1bmN0aW9uIChldmVudCkge1xuICAgIGlmIChldmVudC5vcmlnaW4gIT0gd2luZG93LmxvY2F0aW9uLm9yaWdpbikge1xuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIG9uTWVzc2FnZUNhbGxiYWNrKGV2ZW50LmRhdGEpO1xufSk7XG5cbi8vIGFuZCB0aGUgZnVuY3Rpb24gdGhhdCBoYW5kbGVzIHJlY2VpdmVkIG1lc3NhZ2VzXG5mdW5jdGlvbiBvbk1lc3NhZ2VDYWxsYmFjayhkYXRhKSB7XG4gICAgLy8gXCJjYW5jZWxcIiBidXR0b24gaXMgY2xpY2tlZFxuICAgIGlmIChkYXRhID09ICdQZXJtaXNzaW9uRGVuaWVkRXJyb3InKSB7XG4gICAgICAgIGlmIChzY3JlZW5DYWxsYmFjaylcbiAgICAgICAgICAgIHJldHVybiBzY3JlZW5DYWxsYmFjaygnUGVybWlzc2lvbkRlbmllZEVycm9yJyk7XG4gICAgICAgIGVsc2VcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignUGVybWlzc2lvbkRlbmllZEVycm9yJyk7XG4gICAgfVxuICAgIC8vIGV4dGVuc2lvbiBub3RpZmllZCBoaXMgcHJlc2VuY2VcbiAgICBpZiAoZGF0YSA9PSAncnRjbXVsdGljb25uZWN0aW9uLWV4dGVuc2lvbi1sb2FkZWQnKSB7XG4gICAgICAgIGNocm9tZU1lZGlhU291cmNlID0gJ2Rlc2t0b3AnO1xuICAgIH1cbiAgICAvLyBleHRlbnNpb24gc2hhcmVkIHRlbXAgc291cmNlSWRcbiAgICBpZiAoZGF0YS5zb3VyY2VJZCAmJiBzY3JlZW5DYWxsYmFjaykge1xuICAgICAgICBzY3JlZW5DYWxsYmFjayhzb3VyY2VJZCA9IGRhdGEuc291cmNlSWQsIGRhdGEuY2FuUmVxdWVzdEF1ZGlvVHJhY2sgPT09IHRydWUpO1xuICAgIH1cbn1cblxuLy8gdGhpcyBtZXRob2QgY2FuIGJlIHVzZWQgdG8gY2hlY2sgaWYgY2hyb21lIGV4dGVuc2lvbiBpcyBpbnN0YWxsZWQgJiBlbmFibGVkLlxuZnVuY3Rpb24gaXNDaHJvbWVFeHRlbnNpb25BdmFpbGFibGUoY2FsbGJhY2spIHtcbiAgICBpZiAoIWNhbGxiYWNrKSByZXR1cm47XG4gICAgaWYgKGNocm9tZU1lZGlhU291cmNlID09ICdkZXNrdG9wJykgcmV0dXJuIGNhbGxiYWNrKHRydWUpO1xuXG4gICAgLy8gYXNrIGV4dGVuc2lvbiBpZiBpdCBpcyBhdmFpbGFibGVcbiAgICB3aW5kb3cucG9zdE1lc3NhZ2UoJ2FyZS15b3UtdGhlcmUnLCAnKicpO1xuICAgIHNldFRpbWVvdXQoZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAoY2hyb21lTWVkaWFTb3VyY2UgPT0gJ3NjcmVlbicpIHtcbiAgICAgICAgICAgIGNhbGxiYWNrKGZhbHNlKTtcbiAgICAgICAgfSBlbHNlIGNhbGxiYWNrKHRydWUpO1xuICAgIH0sIDIwMDApO1xufVxuXG4vLyB0aGlzIGZ1bmN0aW9uIGNhbiBiZSB1c2VkIHRvIGdldCBcInNvdXJjZS1pZFwiIGZyb20gdGhlIGV4dGVuc2lvblxuZnVuY3Rpb24gZ2V0U291cmNlSWQoY2FsbGJhY2spIHtcbiAgICBpZiAoIWNhbGxiYWNrKVxuICAgICAgICB0aHJvdyAnXCJjYWxsYmFja1wiIHBhcmFtZXRlciBpcyBtYW5kYXRvcnkuJztcbiAgICBpZiAoc291cmNlSWQpXG4gICAgICAgIHJldHVybiBjYWxsYmFjayhzb3VyY2VJZCk7XG4gICAgc2NyZWVuQ2FsbGJhY2sgPSBjYWxsYmFjaztcbiAgICB3aW5kb3cucG9zdE1lc3NhZ2UoJ2dldC1zb3VyY2VJZCcsICcqJyk7XG59XG5cbi8vIHRoaXMgZnVuY3Rpb24gY2FuIGJlIHVzZWQgdG8gZ2V0IFwic291cmNlLWlkXCIgZnJvbSB0aGUgZXh0ZW5zaW9uXG5mdW5jdGlvbiBnZXRDdXN0b21Tb3VyY2VJZChhcnIsIGNhbGxiYWNrKSB7XG4gICAgaWYgKCFhcnIgfHwgIWFyci5mb3JFYWNoKSB0aHJvdyAnXCJhcnJcIiBwYXJhbWV0ZXIgaXMgbWFuZGF0b3J5IGFuZCBpdCBtdXN0IGJlIGFuIGFycmF5Lic7XG4gICAgaWYgKCFjYWxsYmFjaykgdGhyb3cgJ1wiY2FsbGJhY2tcIiBwYXJhbWV0ZXIgaXMgbWFuZGF0b3J5Lic7XG5cbiAgICBpZiAoc291cmNlSWQpIHJldHVybiBjYWxsYmFjayhzb3VyY2VJZCk7XG5cbiAgICBzY3JlZW5DYWxsYmFjayA9IGNhbGxiYWNrO1xuICAgIHdpbmRvdy5wb3N0TWVzc2FnZSh7XG4gICAgICAgICdnZXQtY3VzdG9tLXNvdXJjZUlkJzogYXJyXG4gICAgfSwgJyonKTtcbn1cblxuLy8gdGhpcyBmdW5jdGlvbiBjYW4gYmUgdXNlZCB0byBnZXQgXCJzb3VyY2UtaWRcIiBmcm9tIHRoZSBleHRlbnNpb25cbmZ1bmN0aW9uIGdldFNvdXJjZUlkV2l0aEF1ZGlvKGNhbGxiYWNrKSB7XG4gICAgaWYgKCFjYWxsYmFjaykgdGhyb3cgJ1wiY2FsbGJhY2tcIiBwYXJhbWV0ZXIgaXMgbWFuZGF0b3J5Lic7XG4gICAgaWYgKHNvdXJjZUlkKSByZXR1cm4gY2FsbGJhY2soc291cmNlSWQpO1xuXG4gICAgc2NyZWVuQ2FsbGJhY2sgPSBjYWxsYmFjaztcbiAgICB3aW5kb3cucG9zdE1lc3NhZ2UoJ2F1ZGlvLXBsdXMtdGFiJywgJyonKTtcbn1cblxuZnVuY3Rpb24gZ2V0Q2hyb21lRXh0ZW5zaW9uU3RhdHVzKGV4dGVuc2lvbmlkLCBjYWxsYmFjaykge1xuICAgIGlmIChpc0ZpcmVmb3gpXG4gICAgICAgIHJldHVybiBjYWxsYmFjaygnbm90LWNocm9tZScpO1xuICAgIGlmIChhcmd1bWVudHMubGVuZ3RoICE9IDIpIHtcbiAgICAgICAgY2FsbGJhY2sgPSBleHRlbnNpb25pZDtcbiAgICAgICAgZXh0ZW5zaW9uaWQgPSAnbGZjZ2ZlcGFmbm9iZGxvZWNjaG5mYWNsaWJlbmpvbGQnOyAvLyBkZWZhdWx0IGV4dGVuc2lvbi1pZFxuICAgIH1cbiAgICB2YXIgaW1hZ2UgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdpbWcnKTtcbiAgICBpbWFnZS5zcmMgPSAnY2hyb21lLWV4dGVuc2lvbjovLycgKyBleHRlbnNpb25pZCArICcvaWNvbi5wbmcnO1xuICAgIGltYWdlLm9ubG9hZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgY2hyb21lTWVkaWFTb3VyY2UgPSAnc2NyZWVuJztcbiAgICAgICAgd2luZG93LnBvc3RNZXNzYWdlKCdhcmUteW91LXRoZXJlJywgJyonKTtcbiAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBpZiAoY2hyb21lTWVkaWFTb3VyY2UgPT0gJ3NjcmVlbicpIHtcbiAgICAgICAgICAgICAgICBjYWxsYmFjaygnaW5zdGFsbGVkLWRpc2FibGVkJyk7XG4gICAgICAgICAgICB9IGVsc2VcbiAgICAgICAgICAgICAgICBjYWxsYmFjaygnaW5zdGFsbGVkLWVuYWJsZWQnKTtcbiAgICAgICAgfSwgMjAwMCk7XG4gICAgfTtcbiAgICBpbWFnZS5vbmVycm9yID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBjYWxsYmFjaygnbm90LWluc3RhbGxlZCcpO1xuICAgIH07XG59XG5cbmZ1bmN0aW9uIGdldFNjcmVlbkNvbnN0cmFpbnRzV2l0aEF1ZGlvKGNhbGxiYWNrKSB7XG4gICAgZ2V0U2NyZWVuQ29uc3RyYWludHMoY2FsbGJhY2ssIHRydWUpO1xufVxuXG4vLyB0aGlzIGZ1bmN0aW9uIGV4cGxhaW5zIGhvdyB0byB1c2UgYWJvdmUgbWV0aG9kcy9vYmplY3RzXG5mdW5jdGlvbiBnZXRTY3JlZW5Db25zdHJhaW50cyhjYWxsYmFjaywgY2FwdHVyZVNvdXJjZUlkV2l0aEF1ZGlvKSB7XG4gICAgc291cmNlSWQgPSAnJztcbiAgICB2YXIgZmlyZWZveFNjcmVlbkNvbnN0cmFpbnRzID0ge1xuICAgICAgICBtb3pNZWRpYVNvdXJjZTogJ3dpbmRvdycsXG4gICAgICAgIG1lZGlhU291cmNlOiAnd2luZG93J1xuICAgIH07XG4gICAgaWYgKGlzRmlyZWZveClcbiAgICAgICAgcmV0dXJuIGNhbGxiYWNrKG51bGwsIGZpcmVmb3hTY3JlZW5Db25zdHJhaW50cyk7XG4gICAgLy8gdGhpcyBzdGF0ZW1lbnQgZGVmaW5lcyBnZXRVc2VyTWVkaWEgY29uc3RyYWludHNcbiAgICAvLyB0aGF0IHdpbGwgYmUgdXNlZCB0byBjYXB0dXJlIGNvbnRlbnQgb2Ygc2NyZWVuXG4gICAgdmFyIHNjcmVlbl9jb25zdHJhaW50cyA9IHtcbiAgICAgICAgbWFuZGF0b3J5OiB7XG4gICAgICAgICAgICBjaHJvbWVNZWRpYVNvdXJjZTogY2hyb21lTWVkaWFTb3VyY2UsXG4gICAgICAgICAgICBtYXhXaWR0aDogc2NyZWVuLndpZHRoID4gMTkyMCA/IHNjcmVlbi53aWR0aCA6IDE5MjAsXG4gICAgICAgICAgICBtYXhIZWlnaHQ6IHNjcmVlbi5oZWlnaHQgPiAxMDgwID8gc2NyZWVuLmhlaWdodCA6IDEwODBcbiAgICAgICAgfSxcbiAgICAgICAgb3B0aW9uYWw6IFtdXG4gICAgfTtcbiAgICAvLyB0aGlzIHN0YXRlbWVudCB2ZXJpZmllcyBjaHJvbWUgZXh0ZW5zaW9uIGF2YWlsYWJpbGl0eVxuICAgIC8vIGlmIGluc3RhbGxlZCBhbmQgYXZhaWxhYmxlIHRoZW4gaXQgd2lsbCBpbnZva2UgZXh0ZW5zaW9uIEFQSVxuICAgIC8vIG90aGVyd2lzZSBpdCB3aWxsIGZhbGxiYWNrIHRvIGNvbW1hbmQtbGluZSBiYXNlZCBzY3JlZW4gY2FwdHVyaW5nIEFQSVxuICAgIGlmIChjaHJvbWVNZWRpYVNvdXJjZSA9PSAnZGVza3RvcCcgJiYgIXNvdXJjZUlkKSB7XG4gICAgICAgIGlmIChjYXB0dXJlU291cmNlSWRXaXRoQXVkaW8pIHtcbiAgICAgICAgICAgIGdldFNvdXJjZUlkV2l0aEF1ZGlvKGZ1bmN0aW9uIChzb3VyY2VJZCwgY2FuUmVxdWVzdEF1ZGlvVHJhY2spIHtcbiAgICAgICAgICAgICAgICBzY3JlZW5fY29uc3RyYWludHMubWFuZGF0b3J5LmNocm9tZU1lZGlhU291cmNlSWQgPSBzb3VyY2VJZDtcblxuICAgICAgICAgICAgICAgIGlmIChjYW5SZXF1ZXN0QXVkaW9UcmFjaykge1xuICAgICAgICAgICAgICAgICAgICBzY3JlZW5fY29uc3RyYWludHMuY2FuUmVxdWVzdEF1ZGlvVHJhY2sgPSB0cnVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjYWxsYmFjayhzb3VyY2VJZCA9PSAnUGVybWlzc2lvbkRlbmllZEVycm9yJyA/IHNvdXJjZUlkIDogbnVsbCwgc2NyZWVuX2NvbnN0cmFpbnRzKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgZ2V0U291cmNlSWQoZnVuY3Rpb24gKHNvdXJjZUlkKSB7XG4gICAgICAgICAgICAgICAgc2NyZWVuX2NvbnN0cmFpbnRzLm1hbmRhdG9yeS5jaHJvbWVNZWRpYVNvdXJjZUlkID0gc291cmNlSWQ7XG4gICAgICAgICAgICAgICAgY2FsbGJhY2soc291cmNlSWQgPT0gJ1Blcm1pc3Npb25EZW5pZWRFcnJvcicgPyBzb3VyY2VJZCA6IG51bGwsIHNjcmVlbl9jb25zdHJhaW50cyk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gdGhpcyBzdGF0ZW1lbnQgc2V0cyBnZXRzICdzb3VyY2VJZFwiIGFuZCBzZXRzIFwiY2hyb21lTWVkaWFTb3VyY2VJZFwiIFxuICAgIGlmIChjaHJvbWVNZWRpYVNvdXJjZSA9PSAnZGVza3RvcCcpIHtcbiAgICAgICAgc2NyZWVuX2NvbnN0cmFpbnRzLm1hbmRhdG9yeS5jaHJvbWVNZWRpYVNvdXJjZUlkID0gc291cmNlSWQ7XG4gICAgfVxuXG4gICAgLy8gbm93IGludm9raW5nIG5hdGl2ZSBnZXRVc2VyTWVkaWEgQVBJXG4gICAgY2FsbGJhY2sobnVsbCwgc2NyZWVuX2NvbnN0cmFpbnRzKTtcbn1cblxuZXhwb3J0cy5nZXRTY3JlZW5Db25zdHJhaW50cyA9IGdldFNjcmVlbkNvbnN0cmFpbnRzO1xuZXhwb3J0cy5nZXRTY3JlZW5Db25zdHJhaW50c1dpdGhBdWRpbyA9IGdldFNjcmVlbkNvbnN0cmFpbnRzV2l0aEF1ZGlvO1xuZXhwb3J0cy5pc0Nocm9tZUV4dGVuc2lvbkF2YWlsYWJsZSA9IGlzQ2hyb21lRXh0ZW5zaW9uQXZhaWxhYmxlO1xuZXhwb3J0cy5nZXRDaHJvbWVFeHRlbnNpb25TdGF0dXMgPSBnZXRDaHJvbWVFeHRlbnNpb25TdGF0dXM7XG5leHBvcnRzLmdldFNvdXJjZUlkID0gZ2V0U291cmNlSWQ7IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgZnJlZWljZSA9IHJlcXVpcmUoJ2ZyZWVpY2UnKTtcbmltcG9ydCB1dWlkID0gcmVxdWlyZSgndXVpZCcpO1xuaW1wb3J0IHBsYXRmb3JtID0gcmVxdWlyZSgncGxhdGZvcm0nKTtcblxuXG5leHBvcnQgaW50ZXJmYWNlIFdlYlJ0Y1BlZXJDb25maWd1cmF0aW9uIHtcbiAgICBtZWRpYUNvbnN0cmFpbnRzOiB7XG4gICAgICAgIGF1ZGlvOiBib29sZWFuLFxuICAgICAgICB2aWRlbzogYm9vbGVhblxuICAgIH07XG4gICAgc2ltdWxjYXN0OiBib29sZWFuO1xuICAgIG9uaWNlY2FuZGlkYXRlOiAoZXZlbnQpID0+IHZvaWQ7XG4gICAgaWNlU2VydmVyczogUlRDSWNlU2VydmVyW10gfCB1bmRlZmluZWQ7XG4gICAgbWVkaWFTdHJlYW0/OiBNZWRpYVN0cmVhbTtcbiAgICBtb2RlPzogc3RyaW5nOyAvLyBzZW5kb25seSwgcmVjb25seSwgc2VuZHJlY3ZcbiAgICBpZD86IHN0cmluZztcbn1cblxuZXhwb3J0IGNsYXNzIFdlYlJ0Y1BlZXIge1xuXG4gICAgcGM6IFJUQ1BlZXJDb25uZWN0aW9uO1xuICAgIGlkOiBzdHJpbmc7XG4gICAgcmVtb3RlQ2FuZGlkYXRlc1F1ZXVlOiBSVENJY2VDYW5kaWRhdGVbXSA9IFtdO1xuICAgIGxvY2FsQ2FuZGlkYXRlc1F1ZXVlOiBSVENJY2VDYW5kaWRhdGVbXSA9IFtdO1xuXG4gICAgaWNlQ2FuZGlkYXRlTGlzdDogUlRDSWNlQ2FuZGlkYXRlW10gPSBbXTtcblxuICAgIHByaXZhdGUgY2FuZGlkYXRlZ2F0aGVyaW5nZG9uZSA9IGZhbHNlO1xuXG4gICAgY29uc3RydWN0b3IocHJpdmF0ZSBjb25maWd1cmF0aW9uOiBXZWJSdGNQZWVyQ29uZmlndXJhdGlvbikge1xuICAgICAgICB0aGlzLmNvbmZpZ3VyYXRpb24uaWNlU2VydmVycyA9ICghIXRoaXMuY29uZmlndXJhdGlvbi5pY2VTZXJ2ZXJzICYmIHRoaXMuY29uZmlndXJhdGlvbi5pY2VTZXJ2ZXJzLmxlbmd0aCA+IDApID8gdGhpcy5jb25maWd1cmF0aW9uLmljZVNlcnZlcnMgOiBmcmVlaWNlKCk7XG5cbiAgICAgICAgdGhpcy5wYyA9IG5ldyBSVENQZWVyQ29ubmVjdGlvbih7IGljZVNlcnZlcnM6IHRoaXMuY29uZmlndXJhdGlvbi5pY2VTZXJ2ZXJzIH0pO1xuICAgICAgICB0aGlzLmlkID0gISFjb25maWd1cmF0aW9uLmlkID8gY29uZmlndXJhdGlvbi5pZCA6IHV1aWQudjQoKTtcblxuICAgICAgICB0aGlzLnBjLm9uaWNlY2FuZGlkYXRlID0gZXZlbnQgPT4ge1xuICAgICAgICAgICAgY29uc3QgY2FuZGlkYXRlOiBSVENJY2VDYW5kaWRhdGUgPSBldmVudC5jYW5kaWRhdGU7XG4gICAgICAgICAgICBpZiAoY2FuZGlkYXRlKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5sb2NhbENhbmRpZGF0ZXNRdWV1ZS5wdXNoKDxSVENJY2VDYW5kaWRhdGU+eyBjYW5kaWRhdGU6IGNhbmRpZGF0ZS5jYW5kaWRhdGUgfSk7XG4gICAgICAgICAgICAgICAgdGhpcy5jYW5kaWRhdGVnYXRoZXJpbmdkb25lID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgdGhpcy5jb25maWd1cmF0aW9uLm9uaWNlY2FuZGlkYXRlKGV2ZW50LmNhbmRpZGF0ZSk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKCF0aGlzLmNhbmRpZGF0ZWdhdGhlcmluZ2RvbmUpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmNhbmRpZGF0ZWdhdGhlcmluZ2RvbmUgPSB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuXG4gICAgICAgIHRoaXMucGMub25zaWduYWxpbmdzdGF0ZWNoYW5nZSA9ICgpID0+IHtcbiAgICAgICAgICAgIGlmICh0aGlzLnBjLnNpZ25hbGluZ1N0YXRlID09PSAnc3RhYmxlJykge1xuICAgICAgICAgICAgICAgIHdoaWxlICh0aGlzLmljZUNhbmRpZGF0ZUxpc3QubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnBjLmFkZEljZUNhbmRpZGF0ZSg8UlRDSWNlQ2FuZGlkYXRlPnRoaXMuaWNlQ2FuZGlkYXRlTGlzdC5zaGlmdCgpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG5cbiAgICAgICAgdGhpcy5zdGFydCgpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoaXMgZnVuY3Rpb24gY3JlYXRlcyB0aGUgUlRDUGVlckNvbm5lY3Rpb24gb2JqZWN0IHRha2luZyBpbnRvIGFjY291bnQgdGhlXG4gICAgICogcHJvcGVydGllcyByZWNlaXZlZCBpbiB0aGUgY29uc3RydWN0b3IuIEl0IHN0YXJ0cyB0aGUgU0RQIG5lZ290aWF0aW9uXG4gICAgICogcHJvY2VzczogZ2VuZXJhdGVzIHRoZSBTRFAgb2ZmZXIgYW5kIGludm9rZXMgdGhlIG9uc2Rwb2ZmZXIgY2FsbGJhY2suIFRoaXNcbiAgICAgKiBjYWxsYmFjayBpcyBleHBlY3RlZCB0byBzZW5kIHRoZSBTRFAgb2ZmZXIsIGluIG9yZGVyIHRvIG9idGFpbiBhbiBTRFBcbiAgICAgKiBhbnN3ZXIgZnJvbSBhbm90aGVyIHBlZXIuXG4gICAgICovXG4gICAgc3RhcnQoKTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIGlmICh0aGlzLnBjLnNpZ25hbGluZ1N0YXRlID09PSAnY2xvc2VkJykge1xuICAgICAgICAgICAgICAgIHJlamVjdCgnVGhlIHBlZXIgY29ubmVjdGlvbiBvYmplY3QgaXMgaW4gXCJjbG9zZWRcIiBzdGF0ZS4gVGhpcyBpcyBtb3N0IGxpa2VseSBkdWUgdG8gYW4gaW52b2NhdGlvbiBvZiB0aGUgZGlzcG9zZSBtZXRob2QgYmVmb3JlIGFjY2VwdGluZyBpbiB0aGUgZGlhbG9ndWUnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICghIXRoaXMuY29uZmlndXJhdGlvbi5tZWRpYVN0cmVhbSkge1xuICAgICAgICAgICAgICAgIHRoaXMucGMuYWRkU3RyZWFtKHRoaXMuY29uZmlndXJhdGlvbi5tZWRpYVN0cmVhbSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIFtIYWNrXSBodHRwczovL2NvZGUuZ29vZ2xlLmNvbS9wL2Nocm9taXVtL2lzc3Vlcy9kZXRhaWw/aWQ9NDQzNTU4XG4gICAgICAgICAgICBpZiAodGhpcy5jb25maWd1cmF0aW9uLm1vZGUgPT09ICdzZW5kb25seScgJiZcbiAgICAgICAgICAgICAgICAocGxhdGZvcm0ubmFtZSA9PT0gJ0Nocm9tZScgJiYgcGxhdGZvcm0udmVyc2lvbiEudG9TdHJpbmcoKS5zdWJzdHJpbmcoMCwgMikgPT09ICczOScpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5jb25maWd1cmF0aW9uLm1vZGUgPSAnc2VuZHJlY3YnO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoaXMgbWV0aG9kIGZyZWVzIHRoZSByZXNvdXJjZXMgdXNlZCBieSBXZWJSdGNQZWVyXG4gICAgICovXG4gICAgZGlzcG9zZSgpIHtcbiAgICAgICAgY29uc29sZS5kZWJ1ZygnRGlzcG9zaW5nIFdlYlJ0Y1BlZXInKTtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGlmICh0aGlzLnBjKSB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMucGMuc2lnbmFsaW5nU3RhdGUgPT09ICdjbG9zZWQnKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhpcy5yZW1vdGVDYW5kaWRhdGVzUXVldWUgPSBbXTtcbiAgICAgICAgICAgICAgICB0aGlzLmxvY2FsQ2FuZGlkYXRlc1F1ZXVlID0gW107XG5cbiAgICAgICAgICAgICAgICB0aGlzLnBjLmdldExvY2FsU3RyZWFtcygpLmZvckVhY2goc3RyID0+IHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5zdHJlYW1TdG9wKHN0cik7XG4gICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICAvLyBGSVhNRSBUaGlzIGlzIG5vdCB5ZXQgaW1wbGVtZW50ZWQgaW4gZmlyZWZveFxuICAgICAgICAgICAgICAgIC8vIGlmKHZpZGVvU3RyZWFtKSBwYy5yZW1vdmVTdHJlYW0odmlkZW9TdHJlYW0pO1xuICAgICAgICAgICAgICAgIC8vIGlmKGF1ZGlvU3RyZWFtKSBwYy5yZW1vdmVTdHJlYW0oYXVkaW9TdHJlYW0pO1xuXG4gICAgICAgICAgICAgICAgdGhpcy5wYy5jbG9zZSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAgIGNvbnNvbGUud2FybignRXhjZXB0aW9uIGRpc3Bvc2luZyB3ZWJydGMgcGVlciAnICsgZXJyKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIDEpIEZ1bmN0aW9uIHRoYXQgY3JlYXRlcyBhbiBvZmZlciwgc2V0cyBpdCBhcyBsb2NhbCBkZXNjcmlwdGlvbiBhbmQgcmV0dXJucyB0aGUgb2ZmZXIgcGFyYW1cbiAgICAgKiB0byBzZW5kIHRvIE9wZW5WaWR1IFNlcnZlciAod2lsbCBiZSB0aGUgcmVtb3RlIGRlc2NyaXB0aW9uIG9mIG90aGVyIHBlZXIpXG4gICAgICovXG4gICAgZ2VuZXJhdGVPZmZlcigpOiBQcm9taXNlPHN0cmluZz4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgbGV0IG9mZmVyQXVkaW8sIG9mZmVyVmlkZW8gPSB0cnVlO1xuXG4gICAgICAgICAgICAvLyBDb25zdHJhaW50cyBtdXN0IGhhdmUgYm90aCBibG9ja3NcbiAgICAgICAgICAgIGlmICghIXRoaXMuY29uZmlndXJhdGlvbi5tZWRpYUNvbnN0cmFpbnRzKSB7XG4gICAgICAgICAgICAgICAgb2ZmZXJBdWRpbyA9ICh0eXBlb2YgdGhpcy5jb25maWd1cmF0aW9uLm1lZGlhQ29uc3RyYWludHMuYXVkaW8gPT09ICdib29sZWFuJykgP1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbmZpZ3VyYXRpb24ubWVkaWFDb25zdHJhaW50cy5hdWRpbyA6IHRydWU7XG4gICAgICAgICAgICAgICAgb2ZmZXJWaWRlbyA9ICh0eXBlb2YgdGhpcy5jb25maWd1cmF0aW9uLm1lZGlhQ29uc3RyYWludHMudmlkZW8gPT09ICdib29sZWFuJykgP1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbmZpZ3VyYXRpb24ubWVkaWFDb25zdHJhaW50cy52aWRlbyA6IHRydWU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGNvbnN0IGNvbnN0cmFpbnRzOiBSVENPZmZlck9wdGlvbnMgPSB7XG4gICAgICAgICAgICAgICAgb2ZmZXJUb1JlY2VpdmVBdWRpbzogKyAodGhpcy5jb25maWd1cmF0aW9uLm1vZGUgIT09ICdzZW5kb25seScgJiYgb2ZmZXJBdWRpbyksXG4gICAgICAgICAgICAgICAgb2ZmZXJUb1JlY2VpdmVWaWRlbzogKyAodGhpcy5jb25maWd1cmF0aW9uLm1vZGUgIT09ICdzZW5kb25seScgJiYgb2ZmZXJWaWRlbylcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIGNvbnNvbGUuZGVidWcoJ1JUQ1BlZXJDb25uZWN0aW9uIGNvbnN0cmFpbnRzOiAnICsgSlNPTi5zdHJpbmdpZnkoY29uc3RyYWludHMpKTtcblxuICAgICAgICAgICAgdGhpcy5wYy5jcmVhdGVPZmZlcihjb25zdHJhaW50cykudGhlbihvZmZlciA9PiB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5kZWJ1ZygnQ3JlYXRlZCBTRFAgb2ZmZXInKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5wYy5zZXRMb2NhbERlc2NyaXB0aW9uKG9mZmVyKTtcbiAgICAgICAgICAgIH0pLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IGxvY2FsRGVzY3JpcHRpb24gPSB0aGlzLnBjLmxvY2FsRGVzY3JpcHRpb247XG4gICAgICAgICAgICAgICAgaWYgKCEhbG9jYWxEZXNjcmlwdGlvbikge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmRlYnVnKCdMb2NhbCBkZXNjcmlwdGlvbiBzZXQnLCBsb2NhbERlc2NyaXB0aW9uLnNkcCk7XG4gICAgICAgICAgICAgICAgICAgIHJlc29sdmUoPHN0cmluZz5sb2NhbERlc2NyaXB0aW9uLnNkcCk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcmVqZWN0KCdMb2NhbCBkZXNjcmlwdGlvbiBpcyBub3QgZGVmaW5lZCcpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pLmNhdGNoKGVycm9yID0+IHJlamVjdChlcnJvcikpO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiAyKSBGdW5jdGlvbiB0byBpbnZva2Ugd2hlbiBhIFNEUCBvZmZlciBpcyByZWNlaXZlZC4gU2V0cyBpdCBhcyByZW1vdGUgZGVzY3JpcHRpb24sXG4gICAgICogZ2VuZXJhdGVzIGFuZCBhbnN3ZXIgYW5kIHJldHVybnMgaXQgdG8gc2VuZCBpdCB0byBPcGVuVmlkdSBTZXJ2ZXJcbiAgICAgKi9cbiAgICBwcm9jZXNzT2ZmZXIoc2RwT2ZmZXI6IHN0cmluZyk6IFByb21pc2U8Q29uc3RyYWluRE9NU3RyaW5nPiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICBjb25zdCBvZmZlcjogUlRDU2Vzc2lvbkRlc2NyaXB0aW9uSW5pdCA9IHtcbiAgICAgICAgICAgICAgICB0eXBlOiAnb2ZmZXInLFxuICAgICAgICAgICAgICAgIHNkcDogc2RwT2ZmZXJcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIGNvbnNvbGUuZGVidWcoJ1NEUCBvZmZlciByZWNlaXZlZCwgc2V0dGluZyByZW1vdGUgZGVzY3JpcHRpb24nKTtcblxuICAgICAgICAgICAgaWYgKHRoaXMucGMuc2lnbmFsaW5nU3RhdGUgPT09ICdjbG9zZWQnKSB7XG4gICAgICAgICAgICAgICAgcmVqZWN0KCdQZWVyQ29ubmVjdGlvbiBpcyBjbG9zZWQnKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5wYy5zZXRSZW1vdGVEZXNjcmlwdGlvbihvZmZlcilcbiAgICAgICAgICAgICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLnBjLmNyZWF0ZUFuc3dlcigpO1xuICAgICAgICAgICAgICAgIH0pLnRoZW4oYW5zd2VyID0+IHtcbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS5kZWJ1ZygnQ3JlYXRlZCBTRFAgYW5zd2VyJyk7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLnBjLnNldExvY2FsRGVzY3JpcHRpb24oYW5zd2VyKTtcbiAgICAgICAgICAgICAgICB9KS50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgbG9jYWxEZXNjcmlwdGlvbiA9IHRoaXMucGMubG9jYWxEZXNjcmlwdGlvbjtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCEhbG9jYWxEZXNjcmlwdGlvbikge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5kZWJ1ZygnTG9jYWwgZGVzY3JpcHRpb24gc2V0JywgbG9jYWxEZXNjcmlwdGlvbi5zZHApO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSg8c3RyaW5nPmxvY2FsRGVzY3JpcHRpb24uc2RwKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdCgnTG9jYWwgZGVzY3JpcHRpb24gaXMgbm90IGRlZmluZWQnKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pLmNhdGNoKGVycm9yID0+IHJlamVjdChlcnJvcikpO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiAzKSBGdW5jdGlvbiBpbnZva2VkIHdoZW4gYSBTRFAgYW5zd2VyIGlzIHJlY2VpdmVkLiBGaW5hbCBzdGVwIGluIFNEUCBuZWdvdGlhdGlvbiwgdGhlIHBlZXJcbiAgICAgKiBqdXN0IG5lZWRzIHRvIHNldCB0aGUgYW5zd2VyIGFzIGl0cyByZW1vdGUgZGVzY3JpcHRpb25cbiAgICAgKi9cbiAgICBwcm9jZXNzQW5zd2VyKHNkcEFuc3dlcjogc3RyaW5nKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcblxuICAgICAgICAgICAgY29uc3QgYW5zd2VyOiBSVENTZXNzaW9uRGVzY3JpcHRpb25Jbml0ID0ge1xuICAgICAgICAgICAgICAgIHR5cGU6ICdhbnN3ZXInLFxuICAgICAgICAgICAgICAgIHNkcDogc2RwQW5zd2VyXG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICBjb25zb2xlLmRlYnVnKCdTRFAgYW5zd2VyIHJlY2VpdmVkLCBzZXR0aW5nIHJlbW90ZSBkZXNjcmlwdGlvbicpO1xuXG4gICAgICAgICAgICBpZiAodGhpcy5wYy5zaWduYWxpbmdTdGF0ZSA9PT0gJ2Nsb3NlZCcpIHtcbiAgICAgICAgICAgICAgICByZWplY3QoJ1JUQ1BlZXJDb25uZWN0aW9uIGlzIGNsb3NlZCcpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLnBjLnNldFJlbW90ZURlc2NyaXB0aW9uKGFuc3dlcikudGhlbigoKSA9PiByZXNvbHZlKCkpLmNhdGNoKGVycm9yID0+IHJlamVjdChlcnJvcikpO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDYWxsYmFjayBmdW5jdGlvbiBpbnZva2VkIHdoZW4gYW4gSUNFIGNhbmRpZGF0ZSBpcyByZWNlaXZlZFxuICAgICAqL1xuICAgIGFkZEljZUNhbmRpZGF0ZShpY2VDYW5kaWRhdGU6IFJUQ0ljZUNhbmRpZGF0ZSk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgY29uc29sZS5kZWJ1ZygnUmVtb3RlIElDRSBjYW5kaWRhdGUgcmVjZWl2ZWQnLCBpY2VDYW5kaWRhdGUpO1xuICAgICAgICAgICAgdGhpcy5yZW1vdGVDYW5kaWRhdGVzUXVldWUucHVzaChpY2VDYW5kaWRhdGUpO1xuICAgICAgICAgICAgc3dpdGNoICh0aGlzLnBjLnNpZ25hbGluZ1N0YXRlKSB7XG4gICAgICAgICAgICAgICAgY2FzZSAnY2xvc2VkJzpcbiAgICAgICAgICAgICAgICAgICAgcmVqZWN0KG5ldyBFcnJvcignUGVlckNvbm5lY3Rpb24gb2JqZWN0IGlzIGNsb3NlZCcpKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAnc3RhYmxlJzpcbiAgICAgICAgICAgICAgICAgICAgaWYgKCEhdGhpcy5wYy5yZW1vdGVEZXNjcmlwdGlvbikge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5wYy5hZGRJY2VDYW5kaWRhdGUoaWNlQ2FuZGlkYXRlKS50aGVuKCgpID0+IHJlc29sdmUoKSkuY2F0Y2goZXJyb3IgPT4gcmVqZWN0KGVycm9yKSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5pY2VDYW5kaWRhdGVMaXN0LnB1c2goaWNlQ2FuZGlkYXRlKTtcbiAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBwcml2YXRlIHN0cmVhbVN0b3Aoc3RyZWFtOiBNZWRpYVN0cmVhbSk6IHZvaWQge1xuICAgICAgICBzdHJlYW0uZ2V0VHJhY2tzKCkuZm9yRWFjaCh0cmFjayA9PiB7XG4gICAgICAgICAgICB0cmFjay5zdG9wKCk7XG4gICAgICAgICAgICBzdHJlYW0ucmVtb3ZlVHJhY2sodHJhY2spO1xuICAgICAgICB9KTtcbiAgICB9XG59XG5cblxuZXhwb3J0IGNsYXNzIFdlYlJ0Y1BlZXJSZWN2b25seSBleHRlbmRzIFdlYlJ0Y1BlZXIge1xuICAgIGNvbnN0cnVjdG9yKGNvbmZpZ3VyYXRpb246IFdlYlJ0Y1BlZXJDb25maWd1cmF0aW9uKSB7XG4gICAgICAgIGNvbmZpZ3VyYXRpb24ubW9kZSA9ICdyZWN2b25seSc7XG4gICAgICAgIHN1cGVyKGNvbmZpZ3VyYXRpb24pO1xuICAgIH1cbn1cblxuZXhwb3J0IGNsYXNzIFdlYlJ0Y1BlZXJTZW5kb25seSBleHRlbmRzIFdlYlJ0Y1BlZXIge1xuICAgIGNvbnN0cnVjdG9yKGNvbmZpZ3VyYXRpb246IFdlYlJ0Y1BlZXJDb25maWd1cmF0aW9uKSB7XG4gICAgICAgIGNvbmZpZ3VyYXRpb24ubW9kZSA9ICdzZW5kb25seSc7XG4gICAgICAgIHN1cGVyKGNvbmZpZ3VyYXRpb24pO1xuICAgIH1cbn1cblxuZXhwb3J0IGNsYXNzIFdlYlJ0Y1BlZXJTZW5kcmVjdiBleHRlbmRzIFdlYlJ0Y1BlZXIge1xuICAgIGNvbnN0cnVjdG9yKGNvbmZpZ3VyYXRpb246IFdlYlJ0Y1BlZXJDb25maWd1cmF0aW9uKSB7XG4gICAgICAgIGNvbmZpZ3VyYXRpb24ubW9kZSA9ICdzZW5kcmVjdic7XG4gICAgICAgIHN1cGVyKGNvbmZpZ3VyYXRpb24pO1xuICAgIH1cbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbi8vIHRzbGludDpkaXNhYmxlOm5vLXN0cmluZy1saXRlcmFsXG5cbmltcG9ydCB7IFN0cmVhbSB9IGZyb20gJy4uLy4uL09wZW5WaWR1L1N0cmVhbSc7XG5pbXBvcnQgcGxhdGZvcm0gPSByZXF1aXJlKCdwbGF0Zm9ybScpO1xuXG5leHBvcnQgY2xhc3MgV2ViUnRjU3RhdHMge1xuXG4gICAgcHJpdmF0ZSB3ZWJSdGNTdGF0c0VuYWJsZWQgPSBmYWxzZTtcbiAgICBwcml2YXRlIHdlYlJ0Y1N0YXRzSW50ZXJ2YWxJZDogTm9kZUpTLlRpbWVyO1xuICAgIHByaXZhdGUgc3RhdHNJbnRlcnZhbCA9IDE7XG4gICAgcHJpdmF0ZSBzdGF0czogYW55ID0ge1xuICAgICAgICBpbmJvdW5kOiB7XG4gICAgICAgICAgICBhdWRpbzoge1xuICAgICAgICAgICAgICAgIGJ5dGVzUmVjZWl2ZWQ6IDAsXG4gICAgICAgICAgICAgICAgcGFja2V0c1JlY2VpdmVkOiAwLFxuICAgICAgICAgICAgICAgIHBhY2tldHNMb3N0OiAwXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgdmlkZW86IHtcbiAgICAgICAgICAgICAgICBieXRlc1JlY2VpdmVkOiAwLFxuICAgICAgICAgICAgICAgIHBhY2tldHNSZWNlaXZlZDogMCxcbiAgICAgICAgICAgICAgICBwYWNrZXRzTG9zdDogMCxcbiAgICAgICAgICAgICAgICBmcmFtZXNEZWNvZGVkOiAwLFxuICAgICAgICAgICAgICAgIG5hY2tDb3VudDogMFxuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBvdXRib3VuZDoge1xuICAgICAgICAgICAgYXVkaW86IHtcbiAgICAgICAgICAgICAgICBieXRlc1NlbnQ6IDAsXG4gICAgICAgICAgICAgICAgcGFja2V0c1NlbnQ6IDAsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgdmlkZW86IHtcbiAgICAgICAgICAgICAgICBieXRlc1NlbnQ6IDAsXG4gICAgICAgICAgICAgICAgcGFja2V0c1NlbnQ6IDAsXG4gICAgICAgICAgICAgICAgZnJhbWVzRW5jb2RlZDogMCxcbiAgICAgICAgICAgICAgICBuYWNrQ291bnQ6IDBcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH07XG5cbiAgICBjb25zdHJ1Y3Rvcihwcml2YXRlIHN0cmVhbTogU3RyZWFtKSB7IH1cblxuICAgIHB1YmxpYyBpc0VuYWJsZWQoKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiB0aGlzLndlYlJ0Y1N0YXRzRW5hYmxlZDtcbiAgICB9XG5cbiAgICBwdWJsaWMgaW5pdFdlYlJ0Y1N0YXRzKCk6IHZvaWQge1xuXG4gICAgICAgIGNvbnN0IGVsYXN0ZXN0SW5zdHJ1bWVudGF0aW9uID0gbG9jYWxTdG9yYWdlLmdldEl0ZW0oJ2VsYXN0ZXN0LWluc3RydW1lbnRhdGlvbicpO1xuXG4gICAgICAgIGlmIChlbGFzdGVzdEluc3RydW1lbnRhdGlvbikge1xuICAgICAgICAgICAgLy8gRWxhc1Rlc3QgaW5zdHJ1bWVudGF0aW9uIG9iamVjdCBmb3VuZCBpbiBsb2NhbCBzdG9yYWdlXG5cbiAgICAgICAgICAgIGNvbnNvbGUud2FybignV2ViUnRjIHN0YXRzIGVuYWJsZWQgZm9yIHN0cmVhbSAnICsgdGhpcy5zdHJlYW0uc3RyZWFtSWQgKyAnIG9mIGNvbm5lY3Rpb24gJyArIHRoaXMuc3RyZWFtLmNvbm5lY3Rpb24uY29ubmVjdGlvbklkKTtcblxuICAgICAgICAgICAgdGhpcy53ZWJSdGNTdGF0c0VuYWJsZWQgPSB0cnVlO1xuXG4gICAgICAgICAgICBjb25zdCBpbnN0cnVtZW50YXRpb24gPSBKU09OLnBhcnNlKGVsYXN0ZXN0SW5zdHJ1bWVudGF0aW9uKTtcbiAgICAgICAgICAgIHRoaXMuc3RhdHNJbnRlcnZhbCA9IGluc3RydW1lbnRhdGlvbi53ZWJydGMuaW50ZXJ2YWw7ICAvLyBJbnRlcnZhbCBpbiBzZWNvbmRzXG5cbiAgICAgICAgICAgIGNvbnNvbGUud2FybignbG9jYWxTdG9yYWdlIGl0ZW06ICcgKyBKU09OLnN0cmluZ2lmeShpbnN0cnVtZW50YXRpb24pKTtcblxuICAgICAgICAgICAgdGhpcy53ZWJSdGNTdGF0c0ludGVydmFsSWQgPSBzZXRJbnRlcnZhbCgoKSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5zZW5kU3RhdHNUb0h0dHBFbmRwb2ludChpbnN0cnVtZW50YXRpb24pO1xuICAgICAgICAgICAgfSwgdGhpcy5zdGF0c0ludGVydmFsICogMTAwMCk7XG5cbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnNvbGUuZGVidWcoJ1dlYlJ0YyBzdGF0cyBub3QgZW5hYmxlZCcpO1xuICAgIH1cblxuICAgIHB1YmxpYyBzdG9wV2ViUnRjU3RhdHMoKSB7XG4gICAgICAgIGlmICh0aGlzLndlYlJ0Y1N0YXRzRW5hYmxlZCkge1xuICAgICAgICAgICAgY2xlYXJJbnRlcnZhbCh0aGlzLndlYlJ0Y1N0YXRzSW50ZXJ2YWxJZCk7XG4gICAgICAgICAgICBjb25zb2xlLndhcm4oJ1dlYlJ0YyBzdGF0cyBzdG9wcGVkIGZvciBkaXNwb3NlZCBzdHJlYW0gJyArIHRoaXMuc3RyZWFtLnN0cmVhbUlkICsgJyBvZiBjb25uZWN0aW9uICcgKyB0aGlzLnN0cmVhbS5jb25uZWN0aW9uLmNvbm5lY3Rpb25JZCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwdWJsaWMgZ2V0U2VsZWN0ZWRJY2VDYW5kaWRhdGVJbmZvKCk6IFByb21pc2U8YW55PiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICB0aGlzLmdldFN0YXRzQWdub3N0aWModGhpcy5zdHJlYW0uZ2V0UlRDUGVlckNvbm5lY3Rpb24oKSxcbiAgICAgICAgICAgICAgICAoc3RhdHMpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKChwbGF0Zm9ybS5uYW1lIS5pbmRleE9mKCdDaHJvbWUnKSAhPT0gLTEpIHx8IChwbGF0Zm9ybS5uYW1lIS5pbmRleE9mKCdPcGVyYScpICE9PSAtMSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBsb2NhbENhbmRpZGF0ZUlkLCByZW1vdGVDYW5kaWRhdGVJZCwgZ29vZ0NhbmRpZGF0ZVBhaXI7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBsb2NhbENhbmRpZGF0ZXMgPSB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHJlbW90ZUNhbmRpZGF0ZXMgPSB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAoY29uc3Qga2V5IGluIHN0YXRzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3Qgc3RhdCA9IHN0YXRzW2tleV07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHN0YXQudHlwZSA9PT0gJ2xvY2FsY2FuZGlkYXRlJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsb2NhbENhbmRpZGF0ZXNbc3RhdC5pZF0gPSBzdGF0O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoc3RhdC50eXBlID09PSAncmVtb3RlY2FuZGlkYXRlJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZW1vdGVDYW5kaWRhdGVzW3N0YXQuaWRdID0gc3RhdDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHN0YXQudHlwZSA9PT0gJ2dvb2dDYW5kaWRhdGVQYWlyJyAmJiAoc3RhdC5nb29nQWN0aXZlQ29ubmVjdGlvbiA9PT0gJ3RydWUnKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnb29nQ2FuZGlkYXRlUGFpciA9IHN0YXQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxvY2FsQ2FuZGlkYXRlSWQgPSBzdGF0LmxvY2FsQ2FuZGlkYXRlSWQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlbW90ZUNhbmRpZGF0ZUlkID0gc3RhdC5yZW1vdGVDYW5kaWRhdGVJZDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBsZXQgZmluYWxMb2NhbENhbmRpZGF0ZSA9IGxvY2FsQ2FuZGlkYXRlc1tsb2NhbENhbmRpZGF0ZUlkXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghIWZpbmFsTG9jYWxDYW5kaWRhdGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBjYW5kTGlzdCA9IHRoaXMuc3RyZWFtLmdldExvY2FsSWNlQ2FuZGlkYXRlTGlzdCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGNhbmQgPSBjYW5kTGlzdC5maWx0ZXIoKGM6IFJUQ0ljZUNhbmRpZGF0ZSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gKCEhYy5jYW5kaWRhdGUgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuY2FuZGlkYXRlLmluZGV4T2YoZmluYWxMb2NhbENhbmRpZGF0ZS5pcEFkZHJlc3MpID49IDAgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuY2FuZGlkYXRlLmluZGV4T2YoZmluYWxMb2NhbENhbmRpZGF0ZS5wb3J0TnVtYmVyKSA+PSAwICYmXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjLmNhbmRpZGF0ZS5pbmRleE9mKGZpbmFsTG9jYWxDYW5kaWRhdGUucHJpb3JpdHkpID49IDApO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbmFsTG9jYWxDYW5kaWRhdGUucmF3ID0gISFjYW5kWzBdID8gY2FuZFswXS5jYW5kaWRhdGUgOiAnRVJST1I6IENhbm5vdCBmaW5kIGxvY2FsIGNhbmRpZGF0ZSBpbiBsaXN0IG9mIHNlbnQgSUNFIGNhbmRpZGF0ZXMnO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaW5hbExvY2FsQ2FuZGlkYXRlID0gJ0VSUk9SOiBObyBhY3RpdmUgbG9jYWwgSUNFIGNhbmRpZGF0ZS4gUHJvYmFibHkgSUNFLVRDUCBpcyBiZWluZyB1c2VkJztcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGZpbmFsUmVtb3RlQ2FuZGlkYXRlID0gcmVtb3RlQ2FuZGlkYXRlc1tyZW1vdGVDYW5kaWRhdGVJZF07XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoISFmaW5hbFJlbW90ZUNhbmRpZGF0ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGNhbmRMaXN0ID0gdGhpcy5zdHJlYW0uZ2V0UmVtb3RlSWNlQ2FuZGlkYXRlTGlzdCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGNhbmQgPSBjYW5kTGlzdC5maWx0ZXIoKGM6IFJUQ0ljZUNhbmRpZGF0ZSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gKCEhYy5jYW5kaWRhdGUgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuY2FuZGlkYXRlLmluZGV4T2YoZmluYWxSZW1vdGVDYW5kaWRhdGUuaXBBZGRyZXNzKSA+PSAwICYmXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjLmNhbmRpZGF0ZS5pbmRleE9mKGZpbmFsUmVtb3RlQ2FuZGlkYXRlLnBvcnROdW1iZXIpID49IDAgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuY2FuZGlkYXRlLmluZGV4T2YoZmluYWxSZW1vdGVDYW5kaWRhdGUucHJpb3JpdHkpID49IDApO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbmFsUmVtb3RlQ2FuZGlkYXRlLnJhdyA9ICEhY2FuZFswXSA/IGNhbmRbMF0uY2FuZGlkYXRlIDogJ0VSUk9SOiBDYW5ub3QgZmluZCByZW1vdGUgY2FuZGlkYXRlIGluIGxpc3Qgb2YgcmVjZWl2ZWQgSUNFIGNhbmRpZGF0ZXMnO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaW5hbFJlbW90ZUNhbmRpZGF0ZSA9ICdFUlJPUjogTm8gYWN0aXZlIHJlbW90ZSBJQ0UgY2FuZGlkYXRlLiBQcm9iYWJseSBJQ0UtVENQIGlzIGJlaW5nIHVzZWQnO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICByZXNvbHZlKHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBnb29nQ2FuZGlkYXRlUGFpcixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsb2NhbENhbmRpZGF0ZTogZmluYWxMb2NhbENhbmRpZGF0ZSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZW1vdGVDYW5kaWRhdGU6IGZpbmFsUmVtb3RlQ2FuZGlkYXRlXG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdCgnU2VsZWN0ZWQgSUNFIGNhbmRpZGF0ZSBpbmZvIG9ubHkgYXZhaWxhYmxlIGZvciBDaHJvbWUnKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgKGVycm9yKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIHByaXZhdGUgc2VuZFN0YXRzVG9IdHRwRW5kcG9pbnQoaW5zdHJ1bWVudGF0aW9uKTogdm9pZCB7XG5cbiAgICAgICAgY29uc3Qgc2VuZFBvc3QgPSAoanNvbikgPT4ge1xuICAgICAgICAgICAgY29uc3QgaHR0cDogWE1MSHR0cFJlcXVlc3QgPSBuZXcgWE1MSHR0cFJlcXVlc3QoKTtcbiAgICAgICAgICAgIGNvbnN0IHVybDogc3RyaW5nID0gaW5zdHJ1bWVudGF0aW9uLndlYnJ0Yy5odHRwRW5kcG9pbnQ7XG4gICAgICAgICAgICBodHRwLm9wZW4oJ1BPU1QnLCB1cmwsIHRydWUpO1xuXG4gICAgICAgICAgICBodHRwLnNldFJlcXVlc3RIZWFkZXIoJ0NvbnRlbnQtdHlwZScsICdhcHBsaWNhdGlvbi9qc29uJyk7XG5cbiAgICAgICAgICAgIGh0dHAub25yZWFkeXN0YXRlY2hhbmdlID0gKCkgPT4geyAvLyBDYWxsIGEgZnVuY3Rpb24gd2hlbiB0aGUgc3RhdGUgY2hhbmdlcy5cbiAgICAgICAgICAgICAgICBpZiAoaHR0cC5yZWFkeVN0YXRlID09PSA0ICYmIGh0dHAuc3RhdHVzID09PSAyMDApIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS5sb2coJ1dlYlJ0YyBzdGF0cyBzdWNjZXNzZnVsbHkgc2VudCB0byAnICsgdXJsICsgJyBmb3Igc3RyZWFtICcgKyB0aGlzLnN0cmVhbS5zdHJlYW1JZCArICcgb2YgY29ubmVjdGlvbiAnICsgdGhpcy5zdHJlYW0uY29ubmVjdGlvbi5jb25uZWN0aW9uSWQpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBodHRwLnNlbmQoanNvbik7XG4gICAgICAgIH07XG5cbiAgICAgICAgY29uc3QgZiA9IChzdGF0cykgPT4ge1xuXG4gICAgICAgICAgICBpZiAocGxhdGZvcm0ubmFtZSEuaW5kZXhPZignRmlyZWZveCcpICE9PSAtMSkge1xuICAgICAgICAgICAgICAgIHN0YXRzLmZvckVhY2goKHN0YXQpID0+IHtcblxuICAgICAgICAgICAgICAgICAgICBsZXQganNvbiA9IHt9O1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICgoc3RhdC50eXBlID09PSAnaW5ib3VuZC1ydHAnKSAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEF2b2lkIGZpcmVmb3ggZW1wdHkgb3V0Ym91bmQtcnRwIHN0YXRpc3RpY3NcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGF0Lm5hY2tDb3VudCAhPT0gbnVsbCAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0YXQuaXNSZW1vdGUgPT09IGZhbHNlICYmXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhdC5pZC5zdGFydHNXaXRoKCdpbmJvdW5kJykgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGF0LnJlbW90ZUlkLnN0YXJ0c1dpdGgoJ2luYm91bmQnKVxuICAgICAgICAgICAgICAgICAgICAgICAgKSkge1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBtZXRyaWNJZCA9ICd3ZWJydGNfaW5ib3VuZF8nICsgc3RhdC5tZWRpYVR5cGUgKyAnXycgKyBzdGF0LnNzcmM7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBqaXQgPSBzdGF0LmppdHRlciAqIDEwMDA7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG1ldHJpY3MgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnl0ZXNSZWNlaXZlZDogKHN0YXQuYnl0ZXNSZWNlaXZlZCAtIHRoaXMuc3RhdHMuaW5ib3VuZFtzdGF0Lm1lZGlhVHlwZV0uYnl0ZXNSZWNlaXZlZCkgLyB0aGlzLnN0YXRzSW50ZXJ2YWwsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaml0dGVyOiBqaXQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFja2V0c1JlY2VpdmVkOiAoc3RhdC5wYWNrZXRzUmVjZWl2ZWQgLSB0aGlzLnN0YXRzLmluYm91bmRbc3RhdC5tZWRpYVR5cGVdLnBhY2tldHNSZWNlaXZlZCkgLyB0aGlzLnN0YXRzSW50ZXJ2YWwsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFja2V0c0xvc3Q6IChzdGF0LnBhY2tldHNMb3N0IC0gdGhpcy5zdGF0cy5pbmJvdW5kW3N0YXQubWVkaWFUeXBlXS5wYWNrZXRzTG9zdCkgLyB0aGlzLnN0YXRzSW50ZXJ2YWxcbiAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB1bml0cyA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBieXRlc1JlY2VpdmVkOiAnYnl0ZXMnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGppdHRlcjogJ21zJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYWNrZXRzUmVjZWl2ZWQ6ICdwYWNrZXRzJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYWNrZXRzTG9zdDogJ3BhY2tldHMnXG4gICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHN0YXQubWVkaWFUeXBlID09PSAndmlkZW8nKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbWV0cmljc1snZnJhbWVzRGVjb2RlZCddID0gKHN0YXQuZnJhbWVzRGVjb2RlZCAtIHRoaXMuc3RhdHMuaW5ib3VuZC52aWRlby5mcmFtZXNEZWNvZGVkKSAvIHRoaXMuc3RhdHNJbnRlcnZhbDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXRyaWNzWyduYWNrQ291bnQnXSA9IChzdGF0Lm5hY2tDb3VudCAtIHRoaXMuc3RhdHMuaW5ib3VuZC52aWRlby5uYWNrQ291bnQpIC8gdGhpcy5zdGF0c0ludGVydmFsO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVuaXRzWydmcmFtZXNEZWNvZGVkJ10gPSAnZnJhbWVzJztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB1bml0c1snbmFja0NvdW50J10gPSAncGFja2V0cyc7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXRzLmluYm91bmQudmlkZW8uZnJhbWVzRGVjb2RlZCA9IHN0YXQuZnJhbWVzRGVjb2RlZDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXRzLmluYm91bmQudmlkZW8ubmFja0NvdW50ID0gc3RhdC5uYWNrQ291bnQ7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdHMuaW5ib3VuZFtzdGF0Lm1lZGlhVHlwZV0uYnl0ZXNSZWNlaXZlZCA9IHN0YXQuYnl0ZXNSZWNlaXZlZDtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdHMuaW5ib3VuZFtzdGF0Lm1lZGlhVHlwZV0ucGFja2V0c1JlY2VpdmVkID0gc3RhdC5wYWNrZXRzUmVjZWl2ZWQ7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXRzLmluYm91bmRbc3RhdC5tZWRpYVR5cGVdLnBhY2tldHNMb3N0ID0gc3RhdC5wYWNrZXRzTG9zdDtcblxuICAgICAgICAgICAgICAgICAgICAgICAganNvbiA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAnQHRpbWVzdGFtcCc6IG5ldyBEYXRlKHN0YXQudGltZXN0YW1wKS50b0lTT1N0cmluZygpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICdleGVjJzogaW5zdHJ1bWVudGF0aW9uLmV4ZWMsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJ2NvbXBvbmVudCc6IGluc3RydW1lbnRhdGlvbi5jb21wb25lbnQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJ3N0cmVhbSc6ICd3ZWJSdGMnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICd0eXBlJzogbWV0cmljSWQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJ3N0cmVhbV90eXBlJzogJ2NvbXBvc2VkX21ldHJpY3MnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICd1bml0cyc6IHVuaXRzXG4gICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAganNvblttZXRyaWNJZF0gPSBtZXRyaWNzO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBzZW5kUG9zdChKU09OLnN0cmluZ2lmeShqc29uKSk7XG5cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICgoc3RhdC50eXBlID09PSAnb3V0Ym91bmQtcnRwJykgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgIChcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBBdm9pZCBmaXJlZm94IGVtcHR5IGluYm91bmQtcnRwIHN0YXRpc3RpY3NcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGF0LmlzUmVtb3RlID09PSBmYWxzZSAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0YXQuaWQudG9Mb3dlckNhc2UoKS5pbmNsdWRlcygnb3V0Ym91bmQnKVxuICAgICAgICAgICAgICAgICAgICAgICAgKSkge1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBtZXRyaWNJZCA9ICd3ZWJydGNfb3V0Ym91bmRfJyArIHN0YXQubWVkaWFUeXBlICsgJ18nICsgc3RhdC5zc3JjO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBtZXRyaWNzID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ5dGVzU2VudDogKHN0YXQuYnl0ZXNTZW50IC0gdGhpcy5zdGF0cy5vdXRib3VuZFtzdGF0Lm1lZGlhVHlwZV0uYnl0ZXNTZW50KSAvIHRoaXMuc3RhdHNJbnRlcnZhbCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYWNrZXRzU2VudDogKHN0YXQucGFja2V0c1NlbnQgLSB0aGlzLnN0YXRzLm91dGJvdW5kW3N0YXQubWVkaWFUeXBlXS5wYWNrZXRzU2VudCkgLyB0aGlzLnN0YXRzSW50ZXJ2YWxcbiAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB1bml0cyA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBieXRlc1NlbnQ6ICdieXRlcycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFja2V0c1NlbnQ6ICdwYWNrZXRzJ1xuICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzdGF0Lm1lZGlhVHlwZSA9PT0gJ3ZpZGVvJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1ldHJpY3NbJ2ZyYW1lc0VuY29kZWQnXSA9IChzdGF0LmZyYW1lc0VuY29kZWQgLSB0aGlzLnN0YXRzLm91dGJvdW5kLnZpZGVvLmZyYW1lc0VuY29kZWQpIC8gdGhpcy5zdGF0c0ludGVydmFsO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVuaXRzWydmcmFtZXNFbmNvZGVkJ10gPSAnZnJhbWVzJztcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdHMub3V0Ym91bmQudmlkZW8uZnJhbWVzRW5jb2RlZCA9IHN0YXQuZnJhbWVzRW5jb2RlZDtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0cy5vdXRib3VuZFtzdGF0Lm1lZGlhVHlwZV0uYnl0ZXNTZW50ID0gc3RhdC5ieXRlc1NlbnQ7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXRzLm91dGJvdW5kW3N0YXQubWVkaWFUeXBlXS5wYWNrZXRzU2VudCA9IHN0YXQucGFja2V0c1NlbnQ7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGpzb24gPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJ0B0aW1lc3RhbXAnOiBuZXcgRGF0ZShzdGF0LnRpbWVzdGFtcCkudG9JU09TdHJpbmcoKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAnZXhlYyc6IGluc3RydW1lbnRhdGlvbi5leGVjLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICdjb21wb25lbnQnOiBpbnN0cnVtZW50YXRpb24uY29tcG9uZW50LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICdzdHJlYW0nOiAnd2ViUnRjJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAndHlwZSc6IG1ldHJpY0lkLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICdzdHJlYW1fdHlwZSc6ICdjb21wb3NlZF9tZXRyaWNzJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAndW5pdHMnOiB1bml0c1xuICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGpzb25bbWV0cmljSWRdID0gbWV0cmljcztcblxuICAgICAgICAgICAgICAgICAgICAgICAgc2VuZFBvc3QoSlNPTi5zdHJpbmdpZnkoanNvbikpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKChwbGF0Zm9ybS5uYW1lIS5pbmRleE9mKCdDaHJvbWUnKSAhPT0gLTEpIHx8IChwbGF0Zm9ybS5uYW1lIS5pbmRleE9mKCdPcGVyYScpICE9PSAtMSkpIHtcbiAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IGtleSBvZiBPYmplY3Qua2V5cyhzdGF0cykpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3Qgc3RhdCA9IHN0YXRzW2tleV07XG4gICAgICAgICAgICAgICAgICAgIGlmIChzdGF0LnR5cGUgPT09ICdzc3JjJykge1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBsZXQganNvbiA9IHt9O1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoJ2J5dGVzUmVjZWl2ZWQnIGluIHN0YXQgJiYgKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIChzdGF0Lm1lZGlhVHlwZSA9PT0gJ2F1ZGlvJyAmJiAnYXVkaW9PdXRwdXRMZXZlbCcgaW4gc3RhdCkgfHxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAoc3RhdC5tZWRpYVR5cGUgPT09ICd2aWRlbycgJiYgJ3FwU3VtJyBpbiBzdGF0KVxuICAgICAgICAgICAgICAgICAgICAgICAgKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGluYm91bmQtcnRwXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgbWV0cmljSWQgPSAnd2VicnRjX2luYm91bmRfJyArIHN0YXQubWVkaWFUeXBlICsgJ18nICsgc3RhdC5zc3JjO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgbWV0cmljcyA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnl0ZXNSZWNlaXZlZDogKHN0YXQuYnl0ZXNSZWNlaXZlZCAtIHRoaXMuc3RhdHMuaW5ib3VuZFtzdGF0Lm1lZGlhVHlwZV0uYnl0ZXNSZWNlaXZlZCkgLyB0aGlzLnN0YXRzSW50ZXJ2YWwsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGppdHRlcjogc3RhdC5nb29nSml0dGVyQnVmZmVyTXMsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhY2tldHNSZWNlaXZlZDogKHN0YXQucGFja2V0c1JlY2VpdmVkIC0gdGhpcy5zdGF0cy5pbmJvdW5kW3N0YXQubWVkaWFUeXBlXS5wYWNrZXRzUmVjZWl2ZWQpIC8gdGhpcy5zdGF0c0ludGVydmFsLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYWNrZXRzTG9zdDogKHN0YXQucGFja2V0c0xvc3QgLSB0aGlzLnN0YXRzLmluYm91bmRbc3RhdC5tZWRpYVR5cGVdLnBhY2tldHNMb3N0KSAvIHRoaXMuc3RhdHNJbnRlcnZhbFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgdW5pdHMgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ5dGVzUmVjZWl2ZWQ6ICdieXRlcycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGppdHRlcjogJ21zJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFja2V0c1JlY2VpdmVkOiAncGFja2V0cycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhY2tldHNMb3N0OiAncGFja2V0cydcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzdGF0Lm1lZGlhVHlwZSA9PT0gJ3ZpZGVvJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXRyaWNzWydmcmFtZXNEZWNvZGVkJ10gPSAoc3RhdC5mcmFtZXNEZWNvZGVkIC0gdGhpcy5zdGF0cy5pbmJvdW5kLnZpZGVvLmZyYW1lc0RlY29kZWQpIC8gdGhpcy5zdGF0c0ludGVydmFsO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXRyaWNzWyduYWNrQ291bnQnXSA9IChzdGF0Lmdvb2dOYWNrc1NlbnQgLSB0aGlzLnN0YXRzLmluYm91bmQudmlkZW8ubmFja0NvdW50KSAvIHRoaXMuc3RhdHNJbnRlcnZhbDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdW5pdHNbJ2ZyYW1lc0RlY29kZWQnXSA9ICdmcmFtZXMnO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1bml0c1snbmFja0NvdW50J10gPSAncGFja2V0cyc7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0cy5pbmJvdW5kLnZpZGVvLmZyYW1lc0RlY29kZWQgPSBzdGF0LmZyYW1lc0RlY29kZWQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdHMuaW5ib3VuZC52aWRlby5uYWNrQ291bnQgPSBzdGF0Lmdvb2dOYWNrc1NlbnQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0cy5pbmJvdW5kW3N0YXQubWVkaWFUeXBlXS5ieXRlc1JlY2VpdmVkID0gc3RhdC5ieXRlc1JlY2VpdmVkO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdHMuaW5ib3VuZFtzdGF0Lm1lZGlhVHlwZV0ucGFja2V0c1JlY2VpdmVkID0gc3RhdC5wYWNrZXRzUmVjZWl2ZWQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0cy5pbmJvdW5kW3N0YXQubWVkaWFUeXBlXS5wYWNrZXRzTG9zdCA9IHN0YXQucGFja2V0c0xvc3Q7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBqc29uID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnQHRpbWVzdGFtcCc6IG5ldyBEYXRlKHN0YXQudGltZXN0YW1wKS50b0lTT1N0cmluZygpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnZXhlYyc6IGluc3RydW1lbnRhdGlvbi5leGVjLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnY29tcG9uZW50JzogaW5zdHJ1bWVudGF0aW9uLmNvbXBvbmVudCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ3N0cmVhbSc6ICd3ZWJSdGMnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAndHlwZSc6IG1ldHJpY0lkLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnc3RyZWFtX3R5cGUnOiAnY29tcG9zZWRfbWV0cmljcycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICd1bml0cyc6IHVuaXRzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBqc29uW21ldHJpY0lkXSA9IG1ldHJpY3M7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZW5kUG9zdChKU09OLnN0cmluZ2lmeShqc29uKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKCdieXRlc1NlbnQnIGluIHN0YXQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBvdXRib3VuZC1ydHBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBtZXRyaWNJZCA9ICd3ZWJydGNfb3V0Ym91bmRfJyArIHN0YXQubWVkaWFUeXBlICsgJ18nICsgc3RhdC5zc3JjO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgbWV0cmljcyA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnl0ZXNTZW50OiAoc3RhdC5ieXRlc1NlbnQgLSB0aGlzLnN0YXRzLm91dGJvdW5kW3N0YXQubWVkaWFUeXBlXS5ieXRlc1NlbnQpIC8gdGhpcy5zdGF0c0ludGVydmFsLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYWNrZXRzU2VudDogKHN0YXQucGFja2V0c1NlbnQgLSB0aGlzLnN0YXRzLm91dGJvdW5kW3N0YXQubWVkaWFUeXBlXS5wYWNrZXRzU2VudCkgLyB0aGlzLnN0YXRzSW50ZXJ2YWxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHVuaXRzID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBieXRlc1NlbnQ6ICdieXRlcycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhY2tldHNTZW50OiAncGFja2V0cydcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzdGF0Lm1lZGlhVHlwZSA9PT0gJ3ZpZGVvJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXRyaWNzWydmcmFtZXNFbmNvZGVkJ10gPSAoc3RhdC5mcmFtZXNFbmNvZGVkIC0gdGhpcy5zdGF0cy5vdXRib3VuZC52aWRlby5mcmFtZXNFbmNvZGVkKSAvIHRoaXMuc3RhdHNJbnRlcnZhbDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdW5pdHNbJ2ZyYW1lc0VuY29kZWQnXSA9ICdmcmFtZXMnO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdHMub3V0Ym91bmQudmlkZW8uZnJhbWVzRW5jb2RlZCA9IHN0YXQuZnJhbWVzRW5jb2RlZDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXRzLm91dGJvdW5kW3N0YXQubWVkaWFUeXBlXS5ieXRlc1NlbnQgPSBzdGF0LmJ5dGVzU2VudDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXRzLm91dGJvdW5kW3N0YXQubWVkaWFUeXBlXS5wYWNrZXRzU2VudCA9IHN0YXQucGFja2V0c1NlbnQ7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBqc29uID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnQHRpbWVzdGFtcCc6IG5ldyBEYXRlKHN0YXQudGltZXN0YW1wKS50b0lTT1N0cmluZygpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnZXhlYyc6IGluc3RydW1lbnRhdGlvbi5leGVjLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnY29tcG9uZW50JzogaW5zdHJ1bWVudGF0aW9uLmNvbXBvbmVudCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ3N0cmVhbSc6ICd3ZWJSdGMnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAndHlwZSc6IG1ldHJpY0lkLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnc3RyZWFtX3R5cGUnOiAnY29tcG9zZWRfbWV0cmljcycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICd1bml0cyc6IHVuaXRzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBqc29uW21ldHJpY0lkXSA9IG1ldHJpY3M7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZW5kUG9zdChKU09OLnN0cmluZ2lmeShqc29uKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG5cbiAgICAgICAgdGhpcy5nZXRTdGF0c0Fnbm9zdGljKHRoaXMuc3RyZWFtLmdldFJUQ1BlZXJDb25uZWN0aW9uKCksIGYsIChlcnJvcikgPT4geyBjb25zb2xlLmxvZyhlcnJvcik7IH0pO1xuICAgIH1cblxuICAgIHByaXZhdGUgc3RhbmRhcmRpemVSZXBvcnQocmVzcG9uc2UpIHtcbiAgICAgICAgY29uc29sZS5sb2cocmVzcG9uc2UpO1xuICAgICAgICBjb25zdCBzdGFuZGFyZFJlcG9ydCA9IHt9O1xuXG4gICAgICAgIGlmIChwbGF0Zm9ybS5uYW1lIS5pbmRleE9mKCdGaXJlZm94JykgIT09IC0xKSB7XG4gICAgICAgICAgICBPYmplY3Qua2V5cyhyZXNwb25zZSkuZm9yRWFjaChrZXkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKHJlc3BvbnNlW2tleV0pO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICByZXR1cm4gcmVzcG9uc2U7XG4gICAgICAgIH1cblxuICAgICAgICByZXNwb25zZS5yZXN1bHQoKS5mb3JFYWNoKHJlcG9ydCA9PiB7XG4gICAgICAgICAgICBjb25zdCBzdGFuZGFyZFN0YXRzID0ge1xuICAgICAgICAgICAgICAgIGlkOiByZXBvcnQuaWQsXG4gICAgICAgICAgICAgICAgdGltZXN0YW1wOiByZXBvcnQudGltZXN0YW1wLFxuICAgICAgICAgICAgICAgIHR5cGU6IHJlcG9ydC50eXBlXG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgcmVwb3J0Lm5hbWVzKCkuZm9yRWFjaCgobmFtZSkgPT4ge1xuICAgICAgICAgICAgICAgIHN0YW5kYXJkU3RhdHNbbmFtZV0gPSByZXBvcnQuc3RhdChuYW1lKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgc3RhbmRhcmRSZXBvcnRbc3RhbmRhcmRTdGF0cy5pZF0gPSBzdGFuZGFyZFN0YXRzO1xuICAgICAgICB9KTtcblxuICAgICAgICByZXR1cm4gc3RhbmRhcmRSZXBvcnQ7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBnZXRTdGF0c0Fnbm9zdGljKHBjLCBzdWNjZXNzQ2IsIGZhaWx1cmVDYikge1xuICAgICAgICBpZiAocGxhdGZvcm0ubmFtZSEuaW5kZXhPZignRmlyZWZveCcpICE9PSAtMSkge1xuICAgICAgICAgICAgLy8gZ2V0U3RhdHMgdGFrZXMgYXJncyBpbiBkaWZmZXJlbnQgb3JkZXIgaW4gQ2hyb21lIGFuZCBGaXJlZm94XG4gICAgICAgICAgICByZXR1cm4gcGMuZ2V0U3RhdHMobnVsbCkudGhlbihyZXNwb25zZSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3QgcmVwb3J0ID0gdGhpcy5zdGFuZGFyZGl6ZVJlcG9ydChyZXNwb25zZSk7XG4gICAgICAgICAgICAgICAgc3VjY2Vzc0NiKHJlcG9ydCk7XG4gICAgICAgICAgICB9KS5jYXRjaChmYWlsdXJlQ2IpO1xuICAgICAgICB9IGVsc2UgaWYgKChwbGF0Zm9ybS5uYW1lIS5pbmRleE9mKCdDaHJvbWUnKSAhPT0gLTEpIHx8IChwbGF0Zm9ybS5uYW1lIS5pbmRleE9mKCdPcGVyYScpICE9PSAtMSkpIHtcbiAgICAgICAgICAgIC8vIEluIENocm9tZSwgdGhlIGZpcnN0IHR3byBhcmd1bWVudHMgYXJlIHJldmVyc2VkXG4gICAgICAgICAgICByZXR1cm4gcGMuZ2V0U3RhdHMoKHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3QgcmVwb3J0ID0gdGhpcy5zdGFuZGFyZGl6ZVJlcG9ydChyZXNwb25zZSk7XG4gICAgICAgICAgICAgICAgc3VjY2Vzc0NiKHJlcG9ydCk7XG4gICAgICAgICAgICB9LCBudWxsLCBmYWlsdXJlQ2IpO1xuICAgICAgICB9XG4gICAgfVxuXG59Il19
diff --git a/openvidu-getaroom/web/openvidu-browser-2.4.0.js b/openvidu-getaroom/web/openvidu-browser-2.4.0.js
new file mode 100644
index 000000000..61298c941
--- /dev/null
+++ b/openvidu-getaroom/web/openvidu-browser-2.4.0.js
@@ -0,0 +1,7696 @@
+(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 1)
+ er = arguments[1];
+ if (er instanceof Error) {
+ throw er; // Unhandled 'error' event
+ } else {
+ // At least give some kind of context to the user
+ var err = new Error('Unhandled "error" event. (' + er + ')');
+ err.context = er;
+ throw err;
+ }
+ return false;
+ }
+
+ handler = events[type];
+
+ if (!handler)
+ return false;
+
+ var isFn = typeof handler === 'function';
+ len = arguments.length;
+ switch (len) {
+ // fast cases
+ case 1:
+ emitNone(handler, isFn, this);
+ break;
+ case 2:
+ emitOne(handler, isFn, this, arguments[1]);
+ break;
+ case 3:
+ emitTwo(handler, isFn, this, arguments[1], arguments[2]);
+ break;
+ case 4:
+ emitThree(handler, isFn, this, arguments[1], arguments[2], arguments[3]);
+ break;
+ // slower
+ default:
+ args = new Array(len - 1);
+ for (i = 1; i < len; i++)
+ args[i - 1] = arguments[i];
+ emitMany(handler, isFn, this, args);
+ }
+
+ return true;
+};
+
+function _addListener(target, type, listener, prepend) {
+ var m;
+ var events;
+ var existing;
+
+ if (typeof listener !== 'function')
+ throw new TypeError('"listener" argument must be a function');
+
+ events = target._events;
+ if (!events) {
+ events = target._events = objectCreate(null);
+ target._eventsCount = 0;
+ } else {
+ // To avoid recursion in the case that type === "newListener"! Before
+ // adding it to the listeners, first emit "newListener".
+ if (events.newListener) {
+ target.emit('newListener', type,
+ listener.listener ? listener.listener : listener);
+
+ // Re-assign `events` because a newListener handler could have caused the
+ // this._events to be assigned to a new object
+ events = target._events;
+ }
+ existing = events[type];
+ }
+
+ if (!existing) {
+ // Optimize the case of one listener. Don't need the extra array object.
+ existing = events[type] = listener;
+ ++target._eventsCount;
+ } else {
+ if (typeof existing === 'function') {
+ // Adding the second element, need to change to array.
+ existing = events[type] =
+ prepend ? [listener, existing] : [existing, listener];
+ } else {
+ // If we've already got an array, just append.
+ if (prepend) {
+ existing.unshift(listener);
+ } else {
+ existing.push(listener);
+ }
+ }
+
+ // Check for listener leak
+ if (!existing.warned) {
+ m = $getMaxListeners(target);
+ if (m && m > 0 && existing.length > m) {
+ existing.warned = true;
+ var w = new Error('Possible EventEmitter memory leak detected. ' +
+ existing.length + ' "' + String(type) + '" listeners ' +
+ 'added. Use emitter.setMaxListeners() to ' +
+ 'increase limit.');
+ w.name = 'MaxListenersExceededWarning';
+ w.emitter = target;
+ w.type = type;
+ w.count = existing.length;
+ if (typeof console === 'object' && console.warn) {
+ console.warn('%s: %s', w.name, w.message);
+ }
+ }
+ }
+ }
+
+ return target;
+}
+
+EventEmitter.prototype.addListener = function addListener(type, listener) {
+ return _addListener(this, type, listener, false);
+};
+
+EventEmitter.prototype.on = EventEmitter.prototype.addListener;
+
+EventEmitter.prototype.prependListener =
+ function prependListener(type, listener) {
+ return _addListener(this, type, listener, true);
+ };
+
+function onceWrapper() {
+ if (!this.fired) {
+ this.target.removeListener(this.type, this.wrapFn);
+ this.fired = true;
+ switch (arguments.length) {
+ case 0:
+ return this.listener.call(this.target);
+ case 1:
+ return this.listener.call(this.target, arguments[0]);
+ case 2:
+ return this.listener.call(this.target, arguments[0], arguments[1]);
+ case 3:
+ return this.listener.call(this.target, arguments[0], arguments[1],
+ arguments[2]);
+ default:
+ var args = new Array(arguments.length);
+ for (var i = 0; i < args.length; ++i)
+ args[i] = arguments[i];
+ this.listener.apply(this.target, args);
+ }
+ }
+}
+
+function _onceWrap(target, type, listener) {
+ var state = { fired: false, wrapFn: undefined, target: target, type: type, listener: listener };
+ var wrapped = bind.call(onceWrapper, state);
+ wrapped.listener = listener;
+ state.wrapFn = wrapped;
+ return wrapped;
+}
+
+EventEmitter.prototype.once = function once(type, listener) {
+ if (typeof listener !== 'function')
+ throw new TypeError('"listener" argument must be a function');
+ this.on(type, _onceWrap(this, type, listener));
+ return this;
+};
+
+EventEmitter.prototype.prependOnceListener =
+ function prependOnceListener(type, listener) {
+ if (typeof listener !== 'function')
+ throw new TypeError('"listener" argument must be a function');
+ this.prependListener(type, _onceWrap(this, type, listener));
+ return this;
+ };
+
+// Emits a 'removeListener' event if and only if the listener was removed.
+EventEmitter.prototype.removeListener =
+ function removeListener(type, listener) {
+ var list, events, position, i, originalListener;
+
+ if (typeof listener !== 'function')
+ throw new TypeError('"listener" argument must be a function');
+
+ events = this._events;
+ if (!events)
+ return this;
+
+ list = events[type];
+ if (!list)
+ return this;
+
+ if (list === listener || list.listener === listener) {
+ if (--this._eventsCount === 0)
+ this._events = objectCreate(null);
+ else {
+ delete events[type];
+ if (events.removeListener)
+ this.emit('removeListener', type, list.listener || listener);
+ }
+ } else if (typeof list !== 'function') {
+ position = -1;
+
+ for (i = list.length - 1; i >= 0; i--) {
+ if (list[i] === listener || list[i].listener === listener) {
+ originalListener = list[i].listener;
+ position = i;
+ break;
+ }
+ }
+
+ if (position < 0)
+ return this;
+
+ if (position === 0)
+ list.shift();
+ else
+ spliceOne(list, position);
+
+ if (list.length === 1)
+ events[type] = list[0];
+
+ if (events.removeListener)
+ this.emit('removeListener', type, originalListener || listener);
+ }
+
+ return this;
+ };
+
+EventEmitter.prototype.removeAllListeners =
+ function removeAllListeners(type) {
+ var listeners, events, i;
+
+ events = this._events;
+ if (!events)
+ return this;
+
+ // not listening for removeListener, no need to emit
+ if (!events.removeListener) {
+ if (arguments.length === 0) {
+ this._events = objectCreate(null);
+ this._eventsCount = 0;
+ } else if (events[type]) {
+ if (--this._eventsCount === 0)
+ this._events = objectCreate(null);
+ else
+ delete events[type];
+ }
+ return this;
+ }
+
+ // emit removeListener for all listeners on all events
+ if (arguments.length === 0) {
+ var keys = objectKeys(events);
+ var key;
+ for (i = 0; i < keys.length; ++i) {
+ key = keys[i];
+ if (key === 'removeListener') continue;
+ this.removeAllListeners(key);
+ }
+ this.removeAllListeners('removeListener');
+ this._events = objectCreate(null);
+ this._eventsCount = 0;
+ return this;
+ }
+
+ listeners = events[type];
+
+ if (typeof listeners === 'function') {
+ this.removeListener(type, listeners);
+ } else if (listeners) {
+ // LIFO order
+ for (i = listeners.length - 1; i >= 0; i--) {
+ this.removeListener(type, listeners[i]);
+ }
+ }
+
+ return this;
+ };
+
+function _listeners(target, type, unwrap) {
+ var events = target._events;
+
+ if (!events)
+ return [];
+
+ var evlistener = events[type];
+ if (!evlistener)
+ return [];
+
+ if (typeof evlistener === 'function')
+ return unwrap ? [evlistener.listener || evlistener] : [evlistener];
+
+ return unwrap ? unwrapListeners(evlistener) : arrayClone(evlistener, evlistener.length);
+}
+
+EventEmitter.prototype.listeners = function listeners(type) {
+ return _listeners(this, type, true);
+};
+
+EventEmitter.prototype.rawListeners = function rawListeners(type) {
+ return _listeners(this, type, false);
+};
+
+EventEmitter.listenerCount = function(emitter, type) {
+ if (typeof emitter.listenerCount === 'function') {
+ return emitter.listenerCount(type);
+ } else {
+ return listenerCount.call(emitter, type);
+ }
+};
+
+EventEmitter.prototype.listenerCount = listenerCount;
+function listenerCount(type) {
+ var events = this._events;
+
+ if (events) {
+ var evlistener = events[type];
+
+ if (typeof evlistener === 'function') {
+ return 1;
+ } else if (evlistener) {
+ return evlistener.length;
+ }
+ }
+
+ return 0;
+}
+
+EventEmitter.prototype.eventNames = function eventNames() {
+ return this._eventsCount > 0 ? Reflect.ownKeys(this._events) : [];
+};
+
+// About 1.5x faster than the two-arg version of Array#splice().
+function spliceOne(list, index) {
+ for (var i = index, k = i + 1, n = list.length; k < n; i += 1, k += 1)
+ list[i] = list[k];
+ list.pop();
+}
+
+function arrayClone(arr, n) {
+ var copy = new Array(n);
+ for (var i = 0; i < n; ++i)
+ copy[i] = arr[i];
+ return copy;
+}
+
+function unwrapListeners(arr) {
+ var ret = new Array(arr.length);
+ for (var i = 0; i < ret.length; ++i) {
+ ret[i] = arr[i].listener || arr[i];
+ }
+ return ret;
+}
+
+function objectCreatePolyfill(proto) {
+ var F = function() {};
+ F.prototype = proto;
+ return new F;
+}
+function objectKeysPolyfill(obj) {
+ var keys = [];
+ for (var k in obj) if (Object.prototype.hasOwnProperty.call(obj, k)) {
+ keys.push(k);
+ }
+ return k;
+}
+function functionBindPolyfill(context) {
+ var fn = this;
+ return function () {
+ return fn.apply(context, arguments);
+ };
+}
+
+},{}],2:[function(require,module,exports){
+/* jshint node: true */
+'use strict';
+
+var normalice = require('normalice');
+
+/**
+ # freeice
+
+ The `freeice` module is a simple way of getting random STUN or TURN server
+ for your WebRTC application. The list of servers (just STUN at this stage)
+ were sourced from this [gist](https://gist.github.com/zziuni/3741933).
+
+ ## Example Use
+
+ The following demonstrates how you can use `freeice` with
+ [rtc-quickconnect](https://github.com/rtc-io/rtc-quickconnect):
+
+ <<< examples/quickconnect.js
+
+ As the `freeice` module generates ice servers in a list compliant with the
+ WebRTC spec you will be able to use it with raw `RTCPeerConnection`
+ constructors and other WebRTC libraries.
+
+ ## Hey, don't use my STUN/TURN server!
+
+ If for some reason your free STUN or TURN server ends up in the
+ list of servers ([stun](https://github.com/DamonOehlman/freeice/blob/master/stun.json) or
+ [turn](https://github.com/DamonOehlman/freeice/blob/master/turn.json))
+ that is used in this module, you can feel
+ free to open an issue on this repository and those servers will be removed
+ within 24 hours (or sooner). This is the quickest and probably the most
+ polite way to have something removed (and provides us some visibility
+ if someone opens a pull request requesting that a server is added).
+
+ ## Please add my server!
+
+ If you have a server that you wish to add to the list, that's awesome! I'm
+ sure I speak on behalf of a whole pile of WebRTC developers who say thanks.
+ To get it into the list, feel free to either open a pull request or if you
+ find that process a bit daunting then just create an issue requesting
+ the addition of the server (make sure you provide all the details, and if
+ you have a Terms of Service then including that in the PR/issue would be
+ awesome).
+
+ ## I know of a free server, can I add it?
+
+ Sure, if you do your homework and make sure it is ok to use (I'm currently
+ in the process of reviewing the terms of those STUN servers included from
+ the original list). If it's ok to go, then please see the previous entry
+ for how to add it.
+
+ ## Current List of Servers
+
+ * current as at the time of last `README.md` file generation
+
+ ### STUN
+
+ <<< stun.json
+
+ ### TURN
+
+ <<< turn.json
+
+**/
+
+var freeice = module.exports = function(opts) {
+ // if a list of servers has been provided, then use it instead of defaults
+ var servers = {
+ stun: (opts || {}).stun || require('./stun.json'),
+ turn: (opts || {}).turn || require('./turn.json')
+ };
+
+ var stunCount = (opts || {}).stunCount || 2;
+ var turnCount = (opts || {}).turnCount || 0;
+ var selected;
+
+ function getServers(type, count) {
+ var out = [];
+ var input = [].concat(servers[type]);
+ var idx;
+
+ while (input.length && out.length < count) {
+ idx = (Math.random() * input.length) | 0;
+ out = out.concat(input.splice(idx, 1));
+ }
+
+ return out.map(function(url) {
+ //If it's a not a string, don't try to "normalice" it otherwise using type:url will screw it up
+ if ((typeof url !== 'string') && (! (url instanceof String))) {
+ return url;
+ } else {
+ return normalice(type + ':' + url);
+ }
+ });
+ }
+
+ // add stun servers
+ selected = [].concat(getServers('stun', stunCount));
+
+ if (turnCount) {
+ selected = selected.concat(getServers('turn', turnCount));
+ }
+
+ return selected;
+};
+
+},{"./stun.json":3,"./turn.json":4,"normalice":7}],3:[function(require,module,exports){
+module.exports=[
+ "stun.l.google.com:19302",
+ "stun1.l.google.com:19302",
+ "stun2.l.google.com:19302",
+ "stun3.l.google.com:19302",
+ "stun4.l.google.com:19302",
+ "stun.ekiga.net",
+ "stun.ideasip.com",
+ "stun.schlund.de",
+ "stun.stunprotocol.org:3478",
+ "stun.voiparound.com",
+ "stun.voipbuster.com",
+ "stun.voipstunt.com",
+ "stun.voxgratia.org",
+ "stun.services.mozilla.com"
+]
+
+},{}],4:[function(require,module,exports){
+module.exports=[]
+
+},{}],5:[function(require,module,exports){
+var WildEmitter = require('wildemitter');
+
+function getMaxVolume (analyser, fftBins) {
+ var maxVolume = -Infinity;
+ analyser.getFloatFrequencyData(fftBins);
+
+ for(var i=4, ii=fftBins.length; i < ii; i++) {
+ if (fftBins[i] > maxVolume && fftBins[i] < 0) {
+ maxVolume = fftBins[i];
+ }
+ };
+
+ return maxVolume;
+}
+
+
+var audioContextType;
+if (typeof window !== 'undefined') {
+ audioContextType = window.AudioContext || window.webkitAudioContext;
+}
+// use a single audio context due to hardware limits
+var audioContext = null;
+module.exports = function(stream, options) {
+ var harker = new WildEmitter();
+
+
+ // make it not break in non-supported browsers
+ if (!audioContextType) return harker;
+
+ //Config
+ var options = options || {},
+ smoothing = (options.smoothing || 0.1),
+ interval = (options.interval || 50),
+ threshold = options.threshold,
+ play = options.play,
+ history = options.history || 10,
+ running = true;
+
+ //Setup Audio Context
+ if (!audioContext) {
+ audioContext = new audioContextType();
+ }
+ var sourceNode, fftBins, analyser;
+
+ analyser = audioContext.createAnalyser();
+ analyser.fftSize = 512;
+ analyser.smoothingTimeConstant = smoothing;
+ fftBins = new Float32Array(analyser.frequencyBinCount);
+
+ if (stream.jquery) stream = stream[0];
+ if (stream instanceof HTMLAudioElement || stream instanceof HTMLVideoElement) {
+ //Audio Tag
+ sourceNode = audioContext.createMediaElementSource(stream);
+ if (typeof play === 'undefined') play = true;
+ threshold = threshold || -50;
+ } else {
+ //WebRTC Stream
+ sourceNode = audioContext.createMediaStreamSource(stream);
+ threshold = threshold || -50;
+ }
+
+ sourceNode.connect(analyser);
+ if (play) analyser.connect(audioContext.destination);
+
+ harker.speaking = false;
+
+ harker.suspend = function() {
+ audioContext.suspend();
+ }
+ harker.resume = function() {
+ audioContext.resume();
+ }
+ Object.defineProperty(harker, 'state', { get: function() {
+ return audioContext.state;
+ }});
+ audioContext.onstatechange = function() {
+ harker.emit('state_change', audioContext.state);
+ }
+
+ harker.setThreshold = function(t) {
+ threshold = t;
+ };
+
+ harker.setInterval = function(i) {
+ interval = i;
+ };
+
+ harker.stop = function() {
+ running = false;
+ harker.emit('volume_change', -100, threshold);
+ if (harker.speaking) {
+ harker.speaking = false;
+ harker.emit('stopped_speaking');
+ }
+ analyser.disconnect();
+ sourceNode.disconnect();
+ };
+ harker.speakingHistory = [];
+ for (var i = 0; i < history; i++) {
+ harker.speakingHistory.push(0);
+ }
+
+ // Poll the analyser node to determine if speaking
+ // and emit events if changed
+ var looper = function() {
+ setTimeout(function() {
+
+ //check if stop has been called
+ if(!running) {
+ return;
+ }
+
+ var currentVolume = getMaxVolume(analyser, fftBins);
+
+ harker.emit('volume_change', currentVolume, threshold);
+
+ var history = 0;
+ if (currentVolume > threshold && !harker.speaking) {
+ // trigger quickly, short history
+ for (var i = harker.speakingHistory.length - 3; i < harker.speakingHistory.length; i++) {
+ history += harker.speakingHistory[i];
+ }
+ if (history >= 2) {
+ harker.speaking = true;
+ harker.emit('speaking');
+ }
+ } else if (currentVolume < threshold && harker.speaking) {
+ for (var i = 0; i < harker.speakingHistory.length; i++) {
+ history += harker.speakingHistory[i];
+ }
+ if (history == 0) {
+ harker.speaking = false;
+ harker.emit('stopped_speaking');
+ }
+ }
+ harker.speakingHistory.shift();
+ harker.speakingHistory.push(0 + (currentVolume > threshold));
+
+ looper();
+ }, interval);
+ };
+ looper();
+
+
+ return harker;
+}
+
+},{"wildemitter":14}],6:[function(require,module,exports){
+if (typeof Object.create === 'function') {
+ // implementation from standard node.js 'util' module
+ module.exports = function inherits(ctor, superCtor) {
+ ctor.super_ = superCtor
+ ctor.prototype = Object.create(superCtor.prototype, {
+ constructor: {
+ value: ctor,
+ enumerable: false,
+ writable: true,
+ configurable: true
+ }
+ });
+ };
+} else {
+ // old school shim for old browsers
+ module.exports = function inherits(ctor, superCtor) {
+ ctor.super_ = superCtor
+ var TempCtor = function () {}
+ TempCtor.prototype = superCtor.prototype
+ ctor.prototype = new TempCtor()
+ ctor.prototype.constructor = ctor
+ }
+}
+
+},{}],7:[function(require,module,exports){
+/**
+ # normalice
+
+ Normalize an ice server configuration object (or plain old string) into a format
+ that is usable in all browsers supporting WebRTC. Primarily this module is designed
+ to help with the transition of the `url` attribute of the configuration object to
+ the `urls` attribute.
+
+ ## Example Usage
+
+ <<< examples/simple.js
+
+**/
+
+var protocols = [
+ 'stun:',
+ 'turn:'
+];
+
+module.exports = function(input) {
+ var url = (input || {}).url || input;
+ var protocol;
+ var parts;
+ var output = {};
+
+ // if we don't have a string url, then allow the input to passthrough
+ if (typeof url != 'string' && (! (url instanceof String))) {
+ return input;
+ }
+
+ // trim the url string, and convert to an array
+ url = url.trim();
+
+ // if the protocol is not known, then passthrough
+ protocol = protocols[protocols.indexOf(url.slice(0, 5))];
+ if (! protocol) {
+ return input;
+ }
+
+ // now let's attack the remaining url parts
+ url = url.slice(5);
+ parts = url.split('@');
+
+ output.username = input.username;
+ output.credential = input.credential;
+ // if we have an authentication part, then set the credentials
+ if (parts.length > 1) {
+ url = parts[1];
+ parts = parts[0].split(':');
+
+ // add the output credential and username
+ output.username = parts[0];
+ output.credential = (input || {}).credential || parts[1] || '';
+ }
+
+ output.url = protocol + url;
+ output.urls = [ output.url ];
+
+ return output;
+};
+
+},{}],8:[function(require,module,exports){
+(function (global){
+/*!
+ * Platform.js
+ * Copyright 2014-2018 Benjamin Tan
+ * Copyright 2011-2013 John-David Dalton
+ * Available under MIT license
+ */
+;(function() {
+ 'use strict';
+
+ /** Used to determine if values are of the language type `Object`. */
+ var objectTypes = {
+ 'function': true,
+ 'object': true
+ };
+
+ /** Used as a reference to the global object. */
+ var root = (objectTypes[typeof window] && window) || this;
+
+ /** Backup possible global object. */
+ var oldRoot = root;
+
+ /** Detect free variable `exports`. */
+ var freeExports = objectTypes[typeof exports] && exports;
+
+ /** Detect free variable `module`. */
+ var freeModule = objectTypes[typeof module] && module && !module.nodeType && module;
+
+ /** Detect free variable `global` from Node.js or Browserified code and use it as `root`. */
+ var freeGlobal = freeExports && freeModule && typeof global == 'object' && global;
+ if (freeGlobal && (freeGlobal.global === freeGlobal || freeGlobal.window === freeGlobal || freeGlobal.self === freeGlobal)) {
+ root = freeGlobal;
+ }
+
+ /**
+ * Used as the maximum length of an array-like object.
+ * See the [ES6 spec](http://people.mozilla.org/~jorendorff/es6-draft.html#sec-tolength)
+ * for more details.
+ */
+ var maxSafeInteger = Math.pow(2, 53) - 1;
+
+ /** Regular expression to detect Opera. */
+ var reOpera = /\bOpera/;
+
+ /** Possible global object. */
+ var thisBinding = this;
+
+ /** Used for native method references. */
+ var objectProto = Object.prototype;
+
+ /** Used to check for own properties of an object. */
+ var hasOwnProperty = objectProto.hasOwnProperty;
+
+ /** Used to resolve the internal `[[Class]]` of values. */
+ var toString = objectProto.toString;
+
+ /*--------------------------------------------------------------------------*/
+
+ /**
+ * Capitalizes a string value.
+ *
+ * @private
+ * @param {string} string The string to capitalize.
+ * @returns {string} The capitalized string.
+ */
+ function capitalize(string) {
+ string = String(string);
+ return string.charAt(0).toUpperCase() + string.slice(1);
+ }
+
+ /**
+ * A utility function to clean up the OS name.
+ *
+ * @private
+ * @param {string} os The OS name to clean up.
+ * @param {string} [pattern] A `RegExp` pattern matching the OS name.
+ * @param {string} [label] A label for the OS.
+ */
+ function cleanupOS(os, pattern, label) {
+ // Platform tokens are defined at:
+ // http://msdn.microsoft.com/en-us/library/ms537503(VS.85).aspx
+ // http://web.archive.org/web/20081122053950/http://msdn.microsoft.com/en-us/library/ms537503(VS.85).aspx
+ var data = {
+ '10.0': '10',
+ '6.4': '10 Technical Preview',
+ '6.3': '8.1',
+ '6.2': '8',
+ '6.1': 'Server 2008 R2 / 7',
+ '6.0': 'Server 2008 / Vista',
+ '5.2': 'Server 2003 / XP 64-bit',
+ '5.1': 'XP',
+ '5.01': '2000 SP1',
+ '5.0': '2000',
+ '4.0': 'NT',
+ '4.90': 'ME'
+ };
+ // Detect Windows version from platform tokens.
+ if (pattern && label && /^Win/i.test(os) && !/^Windows Phone /i.test(os) &&
+ (data = data[/[\d.]+$/.exec(os)])) {
+ os = 'Windows ' + data;
+ }
+ // Correct character case and cleanup string.
+ os = String(os);
+
+ if (pattern && label) {
+ os = os.replace(RegExp(pattern, 'i'), label);
+ }
+
+ os = format(
+ os.replace(/ ce$/i, ' CE')
+ .replace(/\bhpw/i, 'web')
+ .replace(/\bMacintosh\b/, 'Mac OS')
+ .replace(/_PowerPC\b/i, ' OS')
+ .replace(/\b(OS X) [^ \d]+/i, '$1')
+ .replace(/\bMac (OS X)\b/, '$1')
+ .replace(/\/(\d)/, ' $1')
+ .replace(/_/g, '.')
+ .replace(/(?: BePC|[ .]*fc[ \d.]+)$/i, '')
+ .replace(/\bx86\.64\b/gi, 'x86_64')
+ .replace(/\b(Windows Phone) OS\b/, '$1')
+ .replace(/\b(Chrome OS \w+) [\d.]+\b/, '$1')
+ .split(' on ')[0]
+ );
+
+ return os;
+ }
+
+ /**
+ * An iteration utility for arrays and objects.
+ *
+ * @private
+ * @param {Array|Object} object The object to iterate over.
+ * @param {Function} callback The function called per iteration.
+ */
+ function each(object, callback) {
+ var index = -1,
+ length = object ? object.length : 0;
+
+ if (typeof length == 'number' && length > -1 && length <= maxSafeInteger) {
+ while (++index < length) {
+ callback(object[index], index, object);
+ }
+ } else {
+ forOwn(object, callback);
+ }
+ }
+
+ /**
+ * Trim and conditionally capitalize string values.
+ *
+ * @private
+ * @param {string} string The string to format.
+ * @returns {string} The formatted string.
+ */
+ function format(string) {
+ string = trim(string);
+ return /^(?:webOS|i(?:OS|P))/.test(string)
+ ? string
+ : capitalize(string);
+ }
+
+ /**
+ * Iterates over an object's own properties, executing the `callback` for each.
+ *
+ * @private
+ * @param {Object} object The object to iterate over.
+ * @param {Function} callback The function executed per own property.
+ */
+ function forOwn(object, callback) {
+ for (var key in object) {
+ if (hasOwnProperty.call(object, key)) {
+ callback(object[key], key, object);
+ }
+ }
+ }
+
+ /**
+ * Gets the internal `[[Class]]` of a value.
+ *
+ * @private
+ * @param {*} value The value.
+ * @returns {string} The `[[Class]]`.
+ */
+ function getClassOf(value) {
+ return value == null
+ ? capitalize(value)
+ : toString.call(value).slice(8, -1);
+ }
+
+ /**
+ * Host objects can return type values that are different from their actual
+ * data type. The objects we are concerned with usually return non-primitive
+ * types of "object", "function", or "unknown".
+ *
+ * @private
+ * @param {*} object The owner of the property.
+ * @param {string} property The property to check.
+ * @returns {boolean} Returns `true` if the property value is a non-primitive, else `false`.
+ */
+ function isHostType(object, property) {
+ var type = object != null ? typeof object[property] : 'number';
+ return !/^(?:boolean|number|string|undefined)$/.test(type) &&
+ (type == 'object' ? !!object[property] : true);
+ }
+
+ /**
+ * Prepares a string for use in a `RegExp` by making hyphens and spaces optional.
+ *
+ * @private
+ * @param {string} string The string to qualify.
+ * @returns {string} The qualified string.
+ */
+ function qualify(string) {
+ return String(string).replace(/([ -])(?!$)/g, '$1?');
+ }
+
+ /**
+ * A bare-bones `Array#reduce` like utility function.
+ *
+ * @private
+ * @param {Array} array The array to iterate over.
+ * @param {Function} callback The function called per iteration.
+ * @returns {*} The accumulated result.
+ */
+ function reduce(array, callback) {
+ var accumulator = null;
+ each(array, function(value, index) {
+ accumulator = callback(accumulator, value, index, array);
+ });
+ return accumulator;
+ }
+
+ /**
+ * Removes leading and trailing whitespace from a string.
+ *
+ * @private
+ * @param {string} string The string to trim.
+ * @returns {string} The trimmed string.
+ */
+ function trim(string) {
+ return String(string).replace(/^ +| +$/g, '');
+ }
+
+ /*--------------------------------------------------------------------------*/
+
+ /**
+ * Creates a new platform object.
+ *
+ * @memberOf platform
+ * @param {Object|string} [ua=navigator.userAgent] The user agent string or
+ * context object.
+ * @returns {Object} A platform object.
+ */
+ function parse(ua) {
+
+ /** The environment context object. */
+ var context = root;
+
+ /** Used to flag when a custom context is provided. */
+ var isCustomContext = ua && typeof ua == 'object' && getClassOf(ua) != 'String';
+
+ // Juggle arguments.
+ if (isCustomContext) {
+ context = ua;
+ ua = null;
+ }
+
+ /** Browser navigator object. */
+ var nav = context.navigator || {};
+
+ /** Browser user agent string. */
+ var userAgent = nav.userAgent || '';
+
+ ua || (ua = userAgent);
+
+ /** Used to flag when `thisBinding` is the [ModuleScope]. */
+ var isModuleScope = isCustomContext || thisBinding == oldRoot;
+
+ /** Used to detect if browser is like Chrome. */
+ var likeChrome = isCustomContext
+ ? !!nav.likeChrome
+ : /\bChrome\b/.test(ua) && !/internal|\n/i.test(toString.toString());
+
+ /** Internal `[[Class]]` value shortcuts. */
+ var objectClass = 'Object',
+ airRuntimeClass = isCustomContext ? objectClass : 'ScriptBridgingProxyObject',
+ enviroClass = isCustomContext ? objectClass : 'Environment',
+ javaClass = (isCustomContext && context.java) ? 'JavaPackage' : getClassOf(context.java),
+ phantomClass = isCustomContext ? objectClass : 'RuntimeObject';
+
+ /** Detect Java environments. */
+ var java = /\bJava/.test(javaClass) && context.java;
+
+ /** Detect Rhino. */
+ var rhino = java && getClassOf(context.environment) == enviroClass;
+
+ /** A character to represent alpha. */
+ var alpha = java ? 'a' : '\u03b1';
+
+ /** A character to represent beta. */
+ var beta = java ? 'b' : '\u03b2';
+
+ /** Browser document object. */
+ var doc = context.document || {};
+
+ /**
+ * Detect Opera browser (Presto-based).
+ * http://www.howtocreate.co.uk/operaStuff/operaObject.html
+ * http://dev.opera.com/articles/view/opera-mini-web-content-authoring-guidelines/#operamini
+ */
+ var opera = context.operamini || context.opera;
+
+ /** Opera `[[Class]]`. */
+ var operaClass = reOpera.test(operaClass = (isCustomContext && opera) ? opera['[[Class]]'] : getClassOf(opera))
+ ? operaClass
+ : (opera = null);
+
+ /*------------------------------------------------------------------------*/
+
+ /** Temporary variable used over the script's lifetime. */
+ var data;
+
+ /** The CPU architecture. */
+ var arch = ua;
+
+ /** Platform description array. */
+ var description = [];
+
+ /** Platform alpha/beta indicator. */
+ var prerelease = null;
+
+ /** A flag to indicate that environment features should be used to resolve the platform. */
+ var useFeatures = ua == userAgent;
+
+ /** The browser/environment version. */
+ var version = useFeatures && opera && typeof opera.version == 'function' && opera.version();
+
+ /** A flag to indicate if the OS ends with "/ Version" */
+ var isSpecialCasedOS;
+
+ /* Detectable layout engines (order is important). */
+ var layout = getLayout([
+ { 'label': 'EdgeHTML', 'pattern': 'Edge' },
+ 'Trident',
+ { 'label': 'WebKit', 'pattern': 'AppleWebKit' },
+ 'iCab',
+ 'Presto',
+ 'NetFront',
+ 'Tasman',
+ 'KHTML',
+ 'Gecko'
+ ]);
+
+ /* Detectable browser names (order is important). */
+ var name = getName([
+ 'Adobe AIR',
+ 'Arora',
+ 'Avant Browser',
+ 'Breach',
+ 'Camino',
+ 'Electron',
+ 'Epiphany',
+ 'Fennec',
+ 'Flock',
+ 'Galeon',
+ 'GreenBrowser',
+ 'iCab',
+ 'Iceweasel',
+ 'K-Meleon',
+ 'Konqueror',
+ 'Lunascape',
+ 'Maxthon',
+ { 'label': 'Microsoft Edge', 'pattern': 'Edge' },
+ 'Midori',
+ 'Nook Browser',
+ 'PaleMoon',
+ 'PhantomJS',
+ 'Raven',
+ 'Rekonq',
+ 'RockMelt',
+ { 'label': 'Samsung Internet', 'pattern': 'SamsungBrowser' },
+ 'SeaMonkey',
+ { 'label': 'Silk', 'pattern': '(?:Cloud9|Silk-Accelerated)' },
+ 'Sleipnir',
+ 'SlimBrowser',
+ { 'label': 'SRWare Iron', 'pattern': 'Iron' },
+ 'Sunrise',
+ 'Swiftfox',
+ 'Waterfox',
+ 'WebPositive',
+ 'Opera Mini',
+ { 'label': 'Opera Mini', 'pattern': 'OPiOS' },
+ 'Opera',
+ { 'label': 'Opera', 'pattern': 'OPR' },
+ 'Chrome',
+ { 'label': 'Chrome Mobile', 'pattern': '(?:CriOS|CrMo)' },
+ { 'label': 'Firefox', 'pattern': '(?:Firefox|Minefield)' },
+ { 'label': 'Firefox for iOS', 'pattern': 'FxiOS' },
+ { 'label': 'IE', 'pattern': 'IEMobile' },
+ { 'label': 'IE', 'pattern': 'MSIE' },
+ 'Safari'
+ ]);
+
+ /* Detectable products (order is important). */
+ var product = getProduct([
+ { 'label': 'BlackBerry', 'pattern': 'BB10' },
+ 'BlackBerry',
+ { 'label': 'Galaxy S', 'pattern': 'GT-I9000' },
+ { 'label': 'Galaxy S2', 'pattern': 'GT-I9100' },
+ { 'label': 'Galaxy S3', 'pattern': 'GT-I9300' },
+ { 'label': 'Galaxy S4', 'pattern': 'GT-I9500' },
+ { 'label': 'Galaxy S5', 'pattern': 'SM-G900' },
+ { 'label': 'Galaxy S6', 'pattern': 'SM-G920' },
+ { 'label': 'Galaxy S6 Edge', 'pattern': 'SM-G925' },
+ { 'label': 'Galaxy S7', 'pattern': 'SM-G930' },
+ { 'label': 'Galaxy S7 Edge', 'pattern': 'SM-G935' },
+ 'Google TV',
+ 'Lumia',
+ 'iPad',
+ 'iPod',
+ 'iPhone',
+ 'Kindle',
+ { 'label': 'Kindle Fire', 'pattern': '(?:Cloud9|Silk-Accelerated)' },
+ 'Nexus',
+ 'Nook',
+ 'PlayBook',
+ 'PlayStation Vita',
+ 'PlayStation',
+ 'TouchPad',
+ 'Transformer',
+ { 'label': 'Wii U', 'pattern': 'WiiU' },
+ 'Wii',
+ 'Xbox One',
+ { 'label': 'Xbox 360', 'pattern': 'Xbox' },
+ 'Xoom'
+ ]);
+
+ /* Detectable manufacturers. */
+ var manufacturer = getManufacturer({
+ 'Apple': { 'iPad': 1, 'iPhone': 1, 'iPod': 1 },
+ 'Archos': {},
+ 'Amazon': { 'Kindle': 1, 'Kindle Fire': 1 },
+ 'Asus': { 'Transformer': 1 },
+ 'Barnes & Noble': { 'Nook': 1 },
+ 'BlackBerry': { 'PlayBook': 1 },
+ 'Google': { 'Google TV': 1, 'Nexus': 1 },
+ 'HP': { 'TouchPad': 1 },
+ 'HTC': {},
+ 'LG': {},
+ 'Microsoft': { 'Xbox': 1, 'Xbox One': 1 },
+ 'Motorola': { 'Xoom': 1 },
+ 'Nintendo': { 'Wii U': 1, 'Wii': 1 },
+ 'Nokia': { 'Lumia': 1 },
+ 'Samsung': { 'Galaxy S': 1, 'Galaxy S2': 1, 'Galaxy S3': 1, 'Galaxy S4': 1 },
+ 'Sony': { 'PlayStation': 1, 'PlayStation Vita': 1 }
+ });
+
+ /* Detectable operating systems (order is important). */
+ var os = getOS([
+ 'Windows Phone',
+ 'Android',
+ 'CentOS',
+ { 'label': 'Chrome OS', 'pattern': 'CrOS' },
+ 'Debian',
+ 'Fedora',
+ 'FreeBSD',
+ 'Gentoo',
+ 'Haiku',
+ 'Kubuntu',
+ 'Linux Mint',
+ 'OpenBSD',
+ 'Red Hat',
+ 'SuSE',
+ 'Ubuntu',
+ 'Xubuntu',
+ 'Cygwin',
+ 'Symbian OS',
+ 'hpwOS',
+ 'webOS ',
+ 'webOS',
+ 'Tablet OS',
+ 'Tizen',
+ 'Linux',
+ 'Mac OS X',
+ 'Macintosh',
+ 'Mac',
+ 'Windows 98;',
+ 'Windows '
+ ]);
+
+ /*------------------------------------------------------------------------*/
+
+ /**
+ * Picks the layout engine from an array of guesses.
+ *
+ * @private
+ * @param {Array} guesses An array of guesses.
+ * @returns {null|string} The detected layout engine.
+ */
+ function getLayout(guesses) {
+ return reduce(guesses, function(result, guess) {
+ return result || RegExp('\\b' + (
+ guess.pattern || qualify(guess)
+ ) + '\\b', 'i').exec(ua) && (guess.label || guess);
+ });
+ }
+
+ /**
+ * Picks the manufacturer from an array of guesses.
+ *
+ * @private
+ * @param {Array} guesses An object of guesses.
+ * @returns {null|string} The detected manufacturer.
+ */
+ function getManufacturer(guesses) {
+ return reduce(guesses, function(result, value, key) {
+ // Lookup the manufacturer by product or scan the UA for the manufacturer.
+ return result || (
+ value[product] ||
+ value[/^[a-z]+(?: +[a-z]+\b)*/i.exec(product)] ||
+ RegExp('\\b' + qualify(key) + '(?:\\b|\\w*\\d)', 'i').exec(ua)
+ ) && key;
+ });
+ }
+
+ /**
+ * Picks the browser name from an array of guesses.
+ *
+ * @private
+ * @param {Array} guesses An array of guesses.
+ * @returns {null|string} The detected browser name.
+ */
+ function getName(guesses) {
+ return reduce(guesses, function(result, guess) {
+ return result || RegExp('\\b' + (
+ guess.pattern || qualify(guess)
+ ) + '\\b', 'i').exec(ua) && (guess.label || guess);
+ });
+ }
+
+ /**
+ * Picks the OS name from an array of guesses.
+ *
+ * @private
+ * @param {Array} guesses An array of guesses.
+ * @returns {null|string} The detected OS name.
+ */
+ function getOS(guesses) {
+ return reduce(guesses, function(result, guess) {
+ var pattern = guess.pattern || qualify(guess);
+ if (!result && (result =
+ RegExp('\\b' + pattern + '(?:/[\\d.]+|[ \\w.]*)', 'i').exec(ua)
+ )) {
+ result = cleanupOS(result, pattern, guess.label || guess);
+ }
+ return result;
+ });
+ }
+
+ /**
+ * Picks the product name from an array of guesses.
+ *
+ * @private
+ * @param {Array} guesses An array of guesses.
+ * @returns {null|string} The detected product name.
+ */
+ function getProduct(guesses) {
+ return reduce(guesses, function(result, guess) {
+ var pattern = guess.pattern || qualify(guess);
+ if (!result && (result =
+ RegExp('\\b' + pattern + ' *\\d+[.\\w_]*', 'i').exec(ua) ||
+ RegExp('\\b' + pattern + ' *\\w+-[\\w]*', 'i').exec(ua) ||
+ RegExp('\\b' + pattern + '(?:; *(?:[a-z]+[_-])?[a-z]+\\d+|[^ ();-]*)', 'i').exec(ua)
+ )) {
+ // Split by forward slash and append product version if needed.
+ if ((result = String((guess.label && !RegExp(pattern, 'i').test(guess.label)) ? guess.label : result).split('/'))[1] && !/[\d.]+/.test(result[0])) {
+ result[0] += ' ' + result[1];
+ }
+ // Correct character case and cleanup string.
+ guess = guess.label || guess;
+ result = format(result[0]
+ .replace(RegExp(pattern, 'i'), guess)
+ .replace(RegExp('; *(?:' + guess + '[_-])?', 'i'), ' ')
+ .replace(RegExp('(' + guess + ')[-_.]?(\\w)', 'i'), '$1 $2'));
+ }
+ return result;
+ });
+ }
+
+ /**
+ * Resolves the version using an array of UA patterns.
+ *
+ * @private
+ * @param {Array} patterns An array of UA patterns.
+ * @returns {null|string} The detected version.
+ */
+ function getVersion(patterns) {
+ return reduce(patterns, function(result, pattern) {
+ return result || (RegExp(pattern +
+ '(?:-[\\d.]+/|(?: for [\\w-]+)?[ /-])([\\d.]+[^ ();/_-]*)', 'i').exec(ua) || 0)[1] || null;
+ });
+ }
+
+ /**
+ * Returns `platform.description` when the platform object is coerced to a string.
+ *
+ * @name toString
+ * @memberOf platform
+ * @returns {string} Returns `platform.description` if available, else an empty string.
+ */
+ function toStringPlatform() {
+ return this.description || '';
+ }
+
+ /*------------------------------------------------------------------------*/
+
+ // Convert layout to an array so we can add extra details.
+ layout && (layout = [layout]);
+
+ // Detect product names that contain their manufacturer's name.
+ if (manufacturer && !product) {
+ product = getProduct([manufacturer]);
+ }
+ // Clean up Google TV.
+ if ((data = /\bGoogle TV\b/.exec(product))) {
+ product = data[0];
+ }
+ // Detect simulators.
+ if (/\bSimulator\b/i.test(ua)) {
+ product = (product ? product + ' ' : '') + 'Simulator';
+ }
+ // Detect Opera Mini 8+ running in Turbo/Uncompressed mode on iOS.
+ if (name == 'Opera Mini' && /\bOPiOS\b/.test(ua)) {
+ description.push('running in Turbo/Uncompressed mode');
+ }
+ // Detect IE Mobile 11.
+ if (name == 'IE' && /\blike iPhone OS\b/.test(ua)) {
+ data = parse(ua.replace(/like iPhone OS/, ''));
+ manufacturer = data.manufacturer;
+ product = data.product;
+ }
+ // Detect iOS.
+ else if (/^iP/.test(product)) {
+ name || (name = 'Safari');
+ os = 'iOS' + ((data = / OS ([\d_]+)/i.exec(ua))
+ ? ' ' + data[1].replace(/_/g, '.')
+ : '');
+ }
+ // Detect Kubuntu.
+ else if (name == 'Konqueror' && !/buntu/i.test(os)) {
+ os = 'Kubuntu';
+ }
+ // Detect Android browsers.
+ else if ((manufacturer && manufacturer != 'Google' &&
+ ((/Chrome/.test(name) && !/\bMobile Safari\b/i.test(ua)) || /\bVita\b/.test(product))) ||
+ (/\bAndroid\b/.test(os) && /^Chrome/.test(name) && /\bVersion\//i.test(ua))) {
+ name = 'Android Browser';
+ os = /\bAndroid\b/.test(os) ? os : 'Android';
+ }
+ // Detect Silk desktop/accelerated modes.
+ else if (name == 'Silk') {
+ if (!/\bMobi/i.test(ua)) {
+ os = 'Android';
+ description.unshift('desktop mode');
+ }
+ if (/Accelerated *= *true/i.test(ua)) {
+ description.unshift('accelerated');
+ }
+ }
+ // Detect PaleMoon identifying as Firefox.
+ else if (name == 'PaleMoon' && (data = /\bFirefox\/([\d.]+)\b/.exec(ua))) {
+ description.push('identifying as Firefox ' + data[1]);
+ }
+ // Detect Firefox OS and products running Firefox.
+ else if (name == 'Firefox' && (data = /\b(Mobile|Tablet|TV)\b/i.exec(ua))) {
+ os || (os = 'Firefox OS');
+ product || (product = data[1]);
+ }
+ // Detect false positives for Firefox/Safari.
+ else if (!name || (data = !/\bMinefield\b/i.test(ua) && /\b(?:Firefox|Safari)\b/.exec(name))) {
+ // Escape the `/` for Firefox 1.
+ if (name && !product && /[\/,]|^[^(]+?\)/.test(ua.slice(ua.indexOf(data + '/') + 8))) {
+ // Clear name of false positives.
+ name = null;
+ }
+ // Reassign a generic name.
+ if ((data = product || manufacturer || os) &&
+ (product || manufacturer || /\b(?:Android|Symbian OS|Tablet OS|webOS)\b/.test(os))) {
+ name = /[a-z]+(?: Hat)?/i.exec(/\bAndroid\b/.test(os) ? os : data) + ' Browser';
+ }
+ }
+ // Add Chrome version to description for Electron.
+ else if (name == 'Electron' && (data = (/\bChrome\/([\d.]+)\b/.exec(ua) || 0)[1])) {
+ description.push('Chromium ' + data);
+ }
+ // Detect non-Opera (Presto-based) versions (order is important).
+ if (!version) {
+ version = getVersion([
+ '(?:Cloud9|CriOS|CrMo|Edge|FxiOS|IEMobile|Iron|Opera ?Mini|OPiOS|OPR|Raven|SamsungBrowser|Silk(?!/[\\d.]+$))',
+ 'Version',
+ qualify(name),
+ '(?:Firefox|Minefield|NetFront)'
+ ]);
+ }
+ // Detect stubborn layout engines.
+ if ((data =
+ layout == 'iCab' && parseFloat(version) > 3 && 'WebKit' ||
+ /\bOpera\b/.test(name) && (/\bOPR\b/.test(ua) ? 'Blink' : 'Presto') ||
+ /\b(?:Midori|Nook|Safari)\b/i.test(ua) && !/^(?:Trident|EdgeHTML)$/.test(layout) && 'WebKit' ||
+ !layout && /\bMSIE\b/i.test(ua) && (os == 'Mac OS' ? 'Tasman' : 'Trident') ||
+ layout == 'WebKit' && /\bPlayStation\b(?! Vita\b)/i.test(name) && 'NetFront'
+ )) {
+ layout = [data];
+ }
+ // Detect Windows Phone 7 desktop mode.
+ if (name == 'IE' && (data = (/; *(?:XBLWP|ZuneWP)(\d+)/i.exec(ua) || 0)[1])) {
+ name += ' Mobile';
+ os = 'Windows Phone ' + (/\+$/.test(data) ? data : data + '.x');
+ description.unshift('desktop mode');
+ }
+ // Detect Windows Phone 8.x desktop mode.
+ else if (/\bWPDesktop\b/i.test(ua)) {
+ name = 'IE Mobile';
+ os = 'Windows Phone 8.x';
+ description.unshift('desktop mode');
+ version || (version = (/\brv:([\d.]+)/.exec(ua) || 0)[1]);
+ }
+ // Detect IE 11 identifying as other browsers.
+ else if (name != 'IE' && layout == 'Trident' && (data = /\brv:([\d.]+)/.exec(ua))) {
+ if (name) {
+ description.push('identifying as ' + name + (version ? ' ' + version : ''));
+ }
+ name = 'IE';
+ version = data[1];
+ }
+ // Leverage environment features.
+ if (useFeatures) {
+ // Detect server-side environments.
+ // Rhino has a global function while others have a global object.
+ if (isHostType(context, 'global')) {
+ if (java) {
+ data = java.lang.System;
+ arch = data.getProperty('os.arch');
+ os = os || data.getProperty('os.name') + ' ' + data.getProperty('os.version');
+ }
+ if (rhino) {
+ try {
+ version = context.require('ringo/engine').version.join('.');
+ name = 'RingoJS';
+ } catch(e) {
+ if ((data = context.system) && data.global.system == context.system) {
+ name = 'Narwhal';
+ os || (os = data[0].os || null);
+ }
+ }
+ if (!name) {
+ name = 'Rhino';
+ }
+ }
+ else if (
+ typeof context.process == 'object' && !context.process.browser &&
+ (data = context.process)
+ ) {
+ if (typeof data.versions == 'object') {
+ if (typeof data.versions.electron == 'string') {
+ description.push('Node ' + data.versions.node);
+ name = 'Electron';
+ version = data.versions.electron;
+ } else if (typeof data.versions.nw == 'string') {
+ description.push('Chromium ' + version, 'Node ' + data.versions.node);
+ name = 'NW.js';
+ version = data.versions.nw;
+ }
+ }
+ if (!name) {
+ name = 'Node.js';
+ arch = data.arch;
+ os = data.platform;
+ version = /[\d.]+/.exec(data.version);
+ version = version ? version[0] : null;
+ }
+ }
+ }
+ // Detect Adobe AIR.
+ else if (getClassOf((data = context.runtime)) == airRuntimeClass) {
+ name = 'Adobe AIR';
+ os = data.flash.system.Capabilities.os;
+ }
+ // Detect PhantomJS.
+ else if (getClassOf((data = context.phantom)) == phantomClass) {
+ name = 'PhantomJS';
+ version = (data = data.version || null) && (data.major + '.' + data.minor + '.' + data.patch);
+ }
+ // Detect IE compatibility modes.
+ else if (typeof doc.documentMode == 'number' && (data = /\bTrident\/(\d+)/i.exec(ua))) {
+ // We're in compatibility mode when the Trident version + 4 doesn't
+ // equal the document mode.
+ version = [version, doc.documentMode];
+ if ((data = +data[1] + 4) != version[1]) {
+ description.push('IE ' + version[1] + ' mode');
+ layout && (layout[1] = '');
+ version[1] = data;
+ }
+ version = name == 'IE' ? String(version[1].toFixed(1)) : version[0];
+ }
+ // Detect IE 11 masking as other browsers.
+ else if (typeof doc.documentMode == 'number' && /^(?:Chrome|Firefox)\b/.test(name)) {
+ description.push('masking as ' + name + ' ' + version);
+ name = 'IE';
+ version = '11.0';
+ layout = ['Trident'];
+ os = 'Windows';
+ }
+ os = os && format(os);
+ }
+ // Detect prerelease phases.
+ if (version && (data =
+ /(?:[ab]|dp|pre|[ab]\d+pre)(?:\d+\+?)?$/i.exec(version) ||
+ /(?:alpha|beta)(?: ?\d)?/i.exec(ua + ';' + (useFeatures && nav.appMinorVersion)) ||
+ /\bMinefield\b/i.test(ua) && 'a'
+ )) {
+ prerelease = /b/i.test(data) ? 'beta' : 'alpha';
+ version = version.replace(RegExp(data + '\\+?$'), '') +
+ (prerelease == 'beta' ? beta : alpha) + (/\d+\+?/.exec(data) || '');
+ }
+ // Detect Firefox Mobile.
+ if (name == 'Fennec' || name == 'Firefox' && /\b(?:Android|Firefox OS)\b/.test(os)) {
+ name = 'Firefox Mobile';
+ }
+ // Obscure Maxthon's unreliable version.
+ else if (name == 'Maxthon' && version) {
+ version = version.replace(/\.[\d.]+/, '.x');
+ }
+ // Detect Xbox 360 and Xbox One.
+ else if (/\bXbox\b/i.test(product)) {
+ if (product == 'Xbox 360') {
+ os = null;
+ }
+ if (product == 'Xbox 360' && /\bIEMobile\b/.test(ua)) {
+ description.unshift('mobile mode');
+ }
+ }
+ // Add mobile postfix.
+ else if ((/^(?:Chrome|IE|Opera)$/.test(name) || name && !product && !/Browser|Mobi/.test(name)) &&
+ (os == 'Windows CE' || /Mobi/i.test(ua))) {
+ name += ' Mobile';
+ }
+ // Detect IE platform preview.
+ else if (name == 'IE' && useFeatures) {
+ try {
+ if (context.external === null) {
+ description.unshift('platform preview');
+ }
+ } catch(e) {
+ description.unshift('embedded');
+ }
+ }
+ // Detect BlackBerry OS version.
+ // http://docs.blackberry.com/en/developers/deliverables/18169/HTTP_headers_sent_by_BB_Browser_1234911_11.jsp
+ else if ((/\bBlackBerry\b/.test(product) || /\bBB10\b/.test(ua)) && (data =
+ (RegExp(product.replace(/ +/g, ' *') + '/([.\\d]+)', 'i').exec(ua) || 0)[1] ||
+ version
+ )) {
+ data = [data, /BB10/.test(ua)];
+ os = (data[1] ? (product = null, manufacturer = 'BlackBerry') : 'Device Software') + ' ' + data[0];
+ version = null;
+ }
+ // Detect Opera identifying/masking itself as another browser.
+ // http://www.opera.com/support/kb/view/843/
+ else if (this != forOwn && product != 'Wii' && (
+ (useFeatures && opera) ||
+ (/Opera/.test(name) && /\b(?:MSIE|Firefox)\b/i.test(ua)) ||
+ (name == 'Firefox' && /\bOS X (?:\d+\.){2,}/.test(os)) ||
+ (name == 'IE' && (
+ (os && !/^Win/.test(os) && version > 5.5) ||
+ /\bWindows XP\b/.test(os) && version > 8 ||
+ version == 8 && !/\bTrident\b/.test(ua)
+ ))
+ ) && !reOpera.test((data = parse.call(forOwn, ua.replace(reOpera, '') + ';'))) && data.name) {
+ // When "identifying", the UA contains both Opera and the other browser's name.
+ data = 'ing as ' + data.name + ((data = data.version) ? ' ' + data : '');
+ if (reOpera.test(name)) {
+ if (/\bIE\b/.test(data) && os == 'Mac OS') {
+ os = null;
+ }
+ data = 'identify' + data;
+ }
+ // When "masking", the UA contains only the other browser's name.
+ else {
+ data = 'mask' + data;
+ if (operaClass) {
+ name = format(operaClass.replace(/([a-z])([A-Z])/g, '$1 $2'));
+ } else {
+ name = 'Opera';
+ }
+ if (/\bIE\b/.test(data)) {
+ os = null;
+ }
+ if (!useFeatures) {
+ version = null;
+ }
+ }
+ layout = ['Presto'];
+ description.push(data);
+ }
+ // Detect WebKit Nightly and approximate Chrome/Safari versions.
+ if ((data = (/\bAppleWebKit\/([\d.]+\+?)/i.exec(ua) || 0)[1])) {
+ // Correct build number for numeric comparison.
+ // (e.g. "532.5" becomes "532.05")
+ data = [parseFloat(data.replace(/\.(\d)$/, '.0$1')), data];
+ // Nightly builds are postfixed with a "+".
+ if (name == 'Safari' && data[1].slice(-1) == '+') {
+ name = 'WebKit Nightly';
+ prerelease = 'alpha';
+ version = data[1].slice(0, -1);
+ }
+ // Clear incorrect browser versions.
+ else if (version == data[1] ||
+ version == (data[2] = (/\bSafari\/([\d.]+\+?)/i.exec(ua) || 0)[1])) {
+ version = null;
+ }
+ // Use the full Chrome version when available.
+ data[1] = (/\bChrome\/([\d.]+)/i.exec(ua) || 0)[1];
+ // Detect Blink layout engine.
+ if (data[0] == 537.36 && data[2] == 537.36 && parseFloat(data[1]) >= 28 && layout == 'WebKit') {
+ layout = ['Blink'];
+ }
+ // Detect JavaScriptCore.
+ // http://stackoverflow.com/questions/6768474/how-can-i-detect-which-javascript-engine-v8-or-jsc-is-used-at-runtime-in-androi
+ if (!useFeatures || (!likeChrome && !data[1])) {
+ layout && (layout[1] = 'like Safari');
+ data = (data = data[0], data < 400 ? 1 : data < 500 ? 2 : data < 526 ? 3 : data < 533 ? 4 : data < 534 ? '4+' : data < 535 ? 5 : data < 537 ? 6 : data < 538 ? 7 : data < 601 ? 8 : '8');
+ } else {
+ layout && (layout[1] = 'like Chrome');
+ data = data[1] || (data = data[0], data < 530 ? 1 : data < 532 ? 2 : data < 532.05 ? 3 : data < 533 ? 4 : data < 534.03 ? 5 : data < 534.07 ? 6 : data < 534.10 ? 7 : data < 534.13 ? 8 : data < 534.16 ? 9 : data < 534.24 ? 10 : data < 534.30 ? 11 : data < 535.01 ? 12 : data < 535.02 ? '13+' : data < 535.07 ? 15 : data < 535.11 ? 16 : data < 535.19 ? 17 : data < 536.05 ? 18 : data < 536.10 ? 19 : data < 537.01 ? 20 : data < 537.11 ? '21+' : data < 537.13 ? 23 : data < 537.18 ? 24 : data < 537.24 ? 25 : data < 537.36 ? 26 : layout != 'Blink' ? '27' : '28');
+ }
+ // Add the postfix of ".x" or "+" for approximate versions.
+ layout && (layout[1] += ' ' + (data += typeof data == 'number' ? '.x' : /[.+]/.test(data) ? '' : '+'));
+ // Obscure version for some Safari 1-2 releases.
+ if (name == 'Safari' && (!version || parseInt(version) > 45)) {
+ version = data;
+ }
+ }
+ // Detect Opera desktop modes.
+ if (name == 'Opera' && (data = /\bzbov|zvav$/.exec(os))) {
+ name += ' ';
+ description.unshift('desktop mode');
+ if (data == 'zvav') {
+ name += 'Mini';
+ version = null;
+ } else {
+ name += 'Mobile';
+ }
+ os = os.replace(RegExp(' *' + data + '$'), '');
+ }
+ // Detect Chrome desktop mode.
+ else if (name == 'Safari' && /\bChrome\b/.exec(layout && layout[1])) {
+ description.unshift('desktop mode');
+ name = 'Chrome Mobile';
+ version = null;
+
+ if (/\bOS X\b/.test(os)) {
+ manufacturer = 'Apple';
+ os = 'iOS 4.3+';
+ } else {
+ os = null;
+ }
+ }
+ // Strip incorrect OS versions.
+ if (version && version.indexOf((data = /[\d.]+$/.exec(os))) == 0 &&
+ ua.indexOf('/' + data + '-') > -1) {
+ os = trim(os.replace(data, ''));
+ }
+ // Add layout engine.
+ if (layout && !/\b(?:Avant|Nook)\b/.test(name) && (
+ /Browser|Lunascape|Maxthon/.test(name) ||
+ name != 'Safari' && /^iOS/.test(os) && /\bSafari\b/.test(layout[1]) ||
+ /^(?:Adobe|Arora|Breach|Midori|Opera|Phantom|Rekonq|Rock|Samsung Internet|Sleipnir|Web)/.test(name) && layout[1])) {
+ // Don't add layout details to description if they are falsey.
+ (data = layout[layout.length - 1]) && description.push(data);
+ }
+ // Combine contextual information.
+ if (description.length) {
+ description = ['(' + description.join('; ') + ')'];
+ }
+ // Append manufacturer to description.
+ if (manufacturer && product && product.indexOf(manufacturer) < 0) {
+ description.push('on ' + manufacturer);
+ }
+ // Append product to description.
+ if (product) {
+ description.push((/^on /.test(description[description.length - 1]) ? '' : 'on ') + product);
+ }
+ // Parse the OS into an object.
+ if (os) {
+ data = / ([\d.+]+)$/.exec(os);
+ isSpecialCasedOS = data && os.charAt(os.length - data[0].length - 1) == '/';
+ os = {
+ 'architecture': 32,
+ 'family': (data && !isSpecialCasedOS) ? os.replace(data[0], '') : os,
+ 'version': data ? data[1] : null,
+ 'toString': function() {
+ var version = this.version;
+ return this.family + ((version && !isSpecialCasedOS) ? ' ' + version : '') + (this.architecture == 64 ? ' 64-bit' : '');
+ }
+ };
+ }
+ // Add browser/OS architecture.
+ if ((data = /\b(?:AMD|IA|Win|WOW|x86_|x)64\b/i.exec(arch)) && !/\bi686\b/i.test(arch)) {
+ if (os) {
+ os.architecture = 64;
+ os.family = os.family.replace(RegExp(' *' + data), '');
+ }
+ if (
+ name && (/\bWOW64\b/i.test(ua) ||
+ (useFeatures && /\w(?:86|32)$/.test(nav.cpuClass || nav.platform) && !/\bWin64; x64\b/i.test(ua)))
+ ) {
+ description.unshift('32-bit');
+ }
+ }
+ // Chrome 39 and above on OS X is always 64-bit.
+ else if (
+ os && /^OS X/.test(os.family) &&
+ name == 'Chrome' && parseFloat(version) >= 39
+ ) {
+ os.architecture = 64;
+ }
+
+ ua || (ua = null);
+
+ /*------------------------------------------------------------------------*/
+
+ /**
+ * The platform object.
+ *
+ * @name platform
+ * @type Object
+ */
+ var platform = {};
+
+ /**
+ * The platform description.
+ *
+ * @memberOf platform
+ * @type string|null
+ */
+ platform.description = ua;
+
+ /**
+ * The name of the browser's layout engine.
+ *
+ * The list of common layout engines include:
+ * "Blink", "EdgeHTML", "Gecko", "Trident" and "WebKit"
+ *
+ * @memberOf platform
+ * @type string|null
+ */
+ platform.layout = layout && layout[0];
+
+ /**
+ * The name of the product's manufacturer.
+ *
+ * The list of manufacturers include:
+ * "Apple", "Archos", "Amazon", "Asus", "Barnes & Noble", "BlackBerry",
+ * "Google", "HP", "HTC", "LG", "Microsoft", "Motorola", "Nintendo",
+ * "Nokia", "Samsung" and "Sony"
+ *
+ * @memberOf platform
+ * @type string|null
+ */
+ platform.manufacturer = manufacturer;
+
+ /**
+ * The name of the browser/environment.
+ *
+ * The list of common browser names include:
+ * "Chrome", "Electron", "Firefox", "Firefox for iOS", "IE",
+ * "Microsoft Edge", "PhantomJS", "Safari", "SeaMonkey", "Silk",
+ * "Opera Mini" and "Opera"
+ *
+ * Mobile versions of some browsers have "Mobile" appended to their name:
+ * eg. "Chrome Mobile", "Firefox Mobile", "IE Mobile" and "Opera Mobile"
+ *
+ * @memberOf platform
+ * @type string|null
+ */
+ platform.name = name;
+
+ /**
+ * The alpha/beta release indicator.
+ *
+ * @memberOf platform
+ * @type string|null
+ */
+ platform.prerelease = prerelease;
+
+ /**
+ * The name of the product hosting the browser.
+ *
+ * The list of common products include:
+ *
+ * "BlackBerry", "Galaxy S4", "Lumia", "iPad", "iPod", "iPhone", "Kindle",
+ * "Kindle Fire", "Nexus", "Nook", "PlayBook", "TouchPad" and "Transformer"
+ *
+ * @memberOf platform
+ * @type string|null
+ */
+ platform.product = product;
+
+ /**
+ * The browser's user agent string.
+ *
+ * @memberOf platform
+ * @type string|null
+ */
+ platform.ua = ua;
+
+ /**
+ * The browser/environment version.
+ *
+ * @memberOf platform
+ * @type string|null
+ */
+ platform.version = name && version;
+
+ /**
+ * The name of the operating system.
+ *
+ * @memberOf platform
+ * @type Object
+ */
+ platform.os = os || {
+
+ /**
+ * The CPU architecture the OS is built for.
+ *
+ * @memberOf platform.os
+ * @type number|null
+ */
+ 'architecture': null,
+
+ /**
+ * The family of the OS.
+ *
+ * Common values include:
+ * "Windows", "Windows Server 2008 R2 / 7", "Windows Server 2008 / Vista",
+ * "Windows XP", "OS X", "Ubuntu", "Debian", "Fedora", "Red Hat", "SuSE",
+ * "Android", "iOS" and "Windows Phone"
+ *
+ * @memberOf platform.os
+ * @type string|null
+ */
+ 'family': null,
+
+ /**
+ * The version of the OS.
+ *
+ * @memberOf platform.os
+ * @type string|null
+ */
+ 'version': null,
+
+ /**
+ * Returns the OS string.
+ *
+ * @memberOf platform.os
+ * @returns {string} The OS string.
+ */
+ 'toString': function() { return 'null'; }
+ };
+
+ platform.parse = parse;
+ platform.toString = toStringPlatform;
+
+ if (platform.version) {
+ description.unshift(version);
+ }
+ if (platform.name) {
+ description.unshift(name);
+ }
+ if (os && name && !(os == String(os).split(' ')[0] && (os == name.split(' ')[0] || product))) {
+ description.push(product ? '(' + os + ')' : 'on ' + os);
+ }
+ if (description.length) {
+ platform.description = description.join(' ');
+ }
+ return platform;
+ }
+
+ /*--------------------------------------------------------------------------*/
+
+ // Export platform.
+ var platform = parse();
+
+ // Some AMD build optimizers, like r.js, check for condition patterns like the following:
+ if (typeof define == 'function' && typeof define.amd == 'object' && define.amd) {
+ // Expose platform on the global object to prevent errors when platform is
+ // loaded by a script tag in the presence of an AMD loader.
+ // See http://requirejs.org/docs/errors.html#mismatch for more details.
+ root.platform = platform;
+
+ // Define as an anonymous module so platform can be aliased through path mapping.
+ define(function() {
+ return platform;
+ });
+ }
+ // Check for `exports` after `define` in case a build optimizer adds an `exports` object.
+ else if (freeExports && freeModule) {
+ // Export for CommonJS support.
+ forOwn(platform, function(value, key) {
+ freeExports[key] = value;
+ });
+ }
+ else {
+ // Export to the global object.
+ root.platform = platform;
+ }
+}.call(this));
+
+}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
+
+},{}],9:[function(require,module,exports){
+var v1 = require('./v1');
+var v4 = require('./v4');
+
+var uuid = v4;
+uuid.v1 = v1;
+uuid.v4 = v4;
+
+module.exports = uuid;
+
+},{"./v1":12,"./v4":13}],10:[function(require,module,exports){
+/**
+ * Convert array of 16 byte values to UUID string format of the form:
+ * XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
+ */
+var byteToHex = [];
+for (var i = 0; i < 256; ++i) {
+ byteToHex[i] = (i + 0x100).toString(16).substr(1);
+}
+
+function bytesToUuid(buf, offset) {
+ var i = offset || 0;
+ var bth = byteToHex;
+ // join used to fix memory issue caused by concatenation: https://bugs.chromium.org/p/v8/issues/detail?id=3175#c4
+ return ([bth[buf[i++]], bth[buf[i++]],
+ bth[buf[i++]], bth[buf[i++]], '-',
+ bth[buf[i++]], bth[buf[i++]], '-',
+ bth[buf[i++]], bth[buf[i++]], '-',
+ bth[buf[i++]], bth[buf[i++]], '-',
+ bth[buf[i++]], bth[buf[i++]],
+ bth[buf[i++]], bth[buf[i++]],
+ bth[buf[i++]], bth[buf[i++]]]).join('');
+}
+
+module.exports = bytesToUuid;
+
+},{}],11:[function(require,module,exports){
+// Unique ID creation requires a high quality random # generator. In the
+// browser this is a little complicated due to unknown quality of Math.random()
+// and inconsistent support for the `crypto` API. We do the best we can via
+// feature-detection
+
+// getRandomValues needs to be invoked in a context where "this" is a Crypto
+// implementation. Also, find the complete implementation of crypto on IE11.
+var getRandomValues = (typeof(crypto) != 'undefined' && crypto.getRandomValues && crypto.getRandomValues.bind(crypto)) ||
+ (typeof(msCrypto) != 'undefined' && typeof window.msCrypto.getRandomValues == 'function' && msCrypto.getRandomValues.bind(msCrypto));
+
+if (getRandomValues) {
+ // WHATWG crypto RNG - http://wiki.whatwg.org/wiki/Crypto
+ var rnds8 = new Uint8Array(16); // eslint-disable-line no-undef
+
+ module.exports = function whatwgRNG() {
+ getRandomValues(rnds8);
+ return rnds8;
+ };
+} else {
+ // Math.random()-based (RNG)
+ //
+ // If all else fails, use Math.random(). It's fast, but is of unspecified
+ // quality.
+ var rnds = new Array(16);
+
+ module.exports = function mathRNG() {
+ for (var i = 0, r; i < 16; i++) {
+ if ((i & 0x03) === 0) r = Math.random() * 0x100000000;
+ rnds[i] = r >>> ((i & 0x03) << 3) & 0xff;
+ }
+
+ return rnds;
+ };
+}
+
+},{}],12:[function(require,module,exports){
+var rng = require('./lib/rng');
+var bytesToUuid = require('./lib/bytesToUuid');
+
+// **`v1()` - Generate time-based UUID**
+//
+// Inspired by https://github.com/LiosK/UUID.js
+// and http://docs.python.org/library/uuid.html
+
+var _nodeId;
+var _clockseq;
+
+// Previous uuid creation time
+var _lastMSecs = 0;
+var _lastNSecs = 0;
+
+// See https://github.com/broofa/node-uuid for API details
+function v1(options, buf, offset) {
+ var i = buf && offset || 0;
+ var b = buf || [];
+
+ options = options || {};
+ var node = options.node || _nodeId;
+ var clockseq = options.clockseq !== undefined ? options.clockseq : _clockseq;
+
+ // node and clockseq need to be initialized to random values if they're not
+ // specified. We do this lazily to minimize issues related to insufficient
+ // system entropy. See #189
+ if (node == null || clockseq == null) {
+ var seedBytes = rng();
+ if (node == null) {
+ // Per 4.5, create and 48-bit node id, (47 random bits + multicast bit = 1)
+ node = _nodeId = [
+ seedBytes[0] | 0x01,
+ seedBytes[1], seedBytes[2], seedBytes[3], seedBytes[4], seedBytes[5]
+ ];
+ }
+ if (clockseq == null) {
+ // Per 4.2.2, randomize (14 bit) clockseq
+ clockseq = _clockseq = (seedBytes[6] << 8 | seedBytes[7]) & 0x3fff;
+ }
+ }
+
+ // UUID timestamps are 100 nano-second units since the Gregorian epoch,
+ // (1582-10-15 00:00). JSNumbers aren't precise enough for this, so
+ // time is handled internally as 'msecs' (integer milliseconds) and 'nsecs'
+ // (100-nanoseconds offset from msecs) since unix epoch, 1970-01-01 00:00.
+ var msecs = options.msecs !== undefined ? options.msecs : new Date().getTime();
+
+ // Per 4.2.1.2, use count of uuid's generated during the current clock
+ // cycle to simulate higher resolution clock
+ var nsecs = options.nsecs !== undefined ? options.nsecs : _lastNSecs + 1;
+
+ // Time since last uuid creation (in msecs)
+ var dt = (msecs - _lastMSecs) + (nsecs - _lastNSecs)/10000;
+
+ // Per 4.2.1.2, Bump clockseq on clock regression
+ if (dt < 0 && options.clockseq === undefined) {
+ clockseq = clockseq + 1 & 0x3fff;
+ }
+
+ // Reset nsecs if clock regresses (new clockseq) or we've moved onto a new
+ // time interval
+ if ((dt < 0 || msecs > _lastMSecs) && options.nsecs === undefined) {
+ nsecs = 0;
+ }
+
+ // Per 4.2.1.2 Throw error if too many uuids are requested
+ if (nsecs >= 10000) {
+ throw new Error('uuid.v1(): Can\'t create more than 10M uuids/sec');
+ }
+
+ _lastMSecs = msecs;
+ _lastNSecs = nsecs;
+ _clockseq = clockseq;
+
+ // Per 4.1.4 - Convert from unix epoch to Gregorian epoch
+ msecs += 12219292800000;
+
+ // `time_low`
+ var tl = ((msecs & 0xfffffff) * 10000 + nsecs) % 0x100000000;
+ b[i++] = tl >>> 24 & 0xff;
+ b[i++] = tl >>> 16 & 0xff;
+ b[i++] = tl >>> 8 & 0xff;
+ b[i++] = tl & 0xff;
+
+ // `time_mid`
+ var tmh = (msecs / 0x100000000 * 10000) & 0xfffffff;
+ b[i++] = tmh >>> 8 & 0xff;
+ b[i++] = tmh & 0xff;
+
+ // `time_high_and_version`
+ b[i++] = tmh >>> 24 & 0xf | 0x10; // include version
+ b[i++] = tmh >>> 16 & 0xff;
+
+ // `clock_seq_hi_and_reserved` (Per 4.2.2 - include variant)
+ b[i++] = clockseq >>> 8 | 0x80;
+
+ // `clock_seq_low`
+ b[i++] = clockseq & 0xff;
+
+ // `node`
+ for (var n = 0; n < 6; ++n) {
+ b[i + n] = node[n];
+ }
+
+ return buf ? buf : bytesToUuid(b);
+}
+
+module.exports = v1;
+
+},{"./lib/bytesToUuid":10,"./lib/rng":11}],13:[function(require,module,exports){
+var rng = require('./lib/rng');
+var bytesToUuid = require('./lib/bytesToUuid');
+
+function v4(options, buf, offset) {
+ var i = buf && offset || 0;
+
+ if (typeof(options) == 'string') {
+ buf = options === 'binary' ? new Array(16) : null;
+ options = null;
+ }
+ options = options || {};
+
+ var rnds = options.random || (options.rng || rng)();
+
+ // Per 4.4, set bits for version and `clock_seq_hi_and_reserved`
+ rnds[6] = (rnds[6] & 0x0f) | 0x40;
+ rnds[8] = (rnds[8] & 0x3f) | 0x80;
+
+ // Copy bytes to buffer, if provided
+ if (buf) {
+ for (var ii = 0; ii < 16; ++ii) {
+ buf[i + ii] = rnds[ii];
+ }
+ }
+
+ return buf || bytesToUuid(rnds);
+}
+
+module.exports = v4;
+
+},{"./lib/bytesToUuid":10,"./lib/rng":11}],14:[function(require,module,exports){
+/*
+WildEmitter.js is a slim little event emitter by @henrikjoreteg largely based
+on @visionmedia's Emitter from UI Kit.
+
+Why? I wanted it standalone.
+
+I also wanted support for wildcard emitters like this:
+
+emitter.on('*', function (eventName, other, event, payloads) {
+
+});
+
+emitter.on('somenamespace*', function (eventName, payloads) {
+
+});
+
+Please note that callbacks triggered by wildcard registered events also get
+the event name as the first argument.
+*/
+
+module.exports = WildEmitter;
+
+function WildEmitter() { }
+
+WildEmitter.mixin = function (constructor) {
+ var prototype = constructor.prototype || constructor;
+
+ prototype.isWildEmitter= true;
+
+ // Listen on the given `event` with `fn`. Store a group name if present.
+ prototype.on = function (event, groupName, fn) {
+ this.callbacks = this.callbacks || {};
+ var hasGroup = (arguments.length === 3),
+ group = hasGroup ? arguments[1] : undefined,
+ func = hasGroup ? arguments[2] : arguments[1];
+ func._groupName = group;
+ (this.callbacks[event] = this.callbacks[event] || []).push(func);
+ return this;
+ };
+
+ // Adds an `event` listener that will be invoked a single
+ // time then automatically removed.
+ prototype.once = function (event, groupName, fn) {
+ var self = this,
+ hasGroup = (arguments.length === 3),
+ group = hasGroup ? arguments[1] : undefined,
+ func = hasGroup ? arguments[2] : arguments[1];
+ function on() {
+ self.off(event, on);
+ func.apply(this, arguments);
+ }
+ this.on(event, group, on);
+ return this;
+ };
+
+ // Unbinds an entire group
+ prototype.releaseGroup = function (groupName) {
+ this.callbacks = this.callbacks || {};
+ var item, i, len, handlers;
+ for (item in this.callbacks) {
+ handlers = this.callbacks[item];
+ for (i = 0, len = handlers.length; i < len; i++) {
+ if (handlers[i]._groupName === groupName) {
+ //console.log('removing');
+ // remove it and shorten the array we're looping through
+ handlers.splice(i, 1);
+ i--;
+ len--;
+ }
+ }
+ }
+ return this;
+ };
+
+ // Remove the given callback for `event` or all
+ // registered callbacks.
+ prototype.off = function (event, fn) {
+ this.callbacks = this.callbacks || {};
+ var callbacks = this.callbacks[event],
+ i;
+
+ if (!callbacks) return this;
+
+ // remove all handlers
+ if (arguments.length === 1) {
+ delete this.callbacks[event];
+ return this;
+ }
+
+ // remove specific handler
+ i = callbacks.indexOf(fn);
+ callbacks.splice(i, 1);
+ if (callbacks.length === 0) {
+ delete this.callbacks[event];
+ }
+ return this;
+ };
+
+ /// Emit `event` with the given args.
+ // also calls any `*` handlers
+ prototype.emit = function (event) {
+ this.callbacks = this.callbacks || {};
+ var args = [].slice.call(arguments, 1),
+ callbacks = this.callbacks[event],
+ specialCallbacks = this.getWildcardCallbacks(event),
+ i,
+ len,
+ item,
+ listeners;
+
+ if (callbacks) {
+ listeners = callbacks.slice();
+ for (i = 0, len = listeners.length; i < len; ++i) {
+ if (!listeners[i]) {
+ break;
+ }
+ listeners[i].apply(this, args);
+ }
+ }
+
+ if (specialCallbacks) {
+ len = specialCallbacks.length;
+ listeners = specialCallbacks.slice();
+ for (i = 0, len = listeners.length; i < len; ++i) {
+ if (!listeners[i]) {
+ break;
+ }
+ listeners[i].apply(this, [event].concat(args));
+ }
+ }
+
+ return this;
+ };
+
+ // Helper for for finding special wildcard event handlers that match the event
+ prototype.getWildcardCallbacks = function (eventName) {
+ this.callbacks = this.callbacks || {};
+ var item,
+ split,
+ result = [];
+
+ for (item in this.callbacks) {
+ split = item.split('*');
+ if (item === '*' || (split.length === 2 && eventName.slice(0, split[0].length) === split[0])) {
+ result = result.concat(this.callbacks[item]);
+ }
+ }
+ return result;
+ };
+
+};
+
+WildEmitter.mixin(WildEmitter);
+
+},{}],15:[function(require,module,exports){
+/*!
+ * EventEmitter v5.2.5 - git.io/ee
+ * Unlicense - http://unlicense.org/
+ * Oliver Caldwell - http://oli.me.uk/
+ * @preserve
+ */
+
+;(function (exports) {
+ 'use strict';
+
+ /**
+ * Class for managing events.
+ * Can be extended to provide event functionality in other classes.
+ *
+ * @class EventEmitter Manages event registering and emitting.
+ */
+ function EventEmitter() {}
+
+ // Shortcuts to improve speed and size
+ var proto = EventEmitter.prototype;
+ var originalGlobalValue = exports.EventEmitter;
+
+ /**
+ * Finds the index of the listener for the event in its storage array.
+ *
+ * @param {Function[]} listeners Array of listeners to search through.
+ * @param {Function} listener Method to look for.
+ * @return {Number} Index of the specified listener, -1 if not found
+ * @api private
+ */
+ function indexOfListener(listeners, listener) {
+ var i = listeners.length;
+ while (i--) {
+ if (listeners[i].listener === listener) {
+ return i;
+ }
+ }
+
+ return -1;
+ }
+
+ /**
+ * Alias a method while keeping the context correct, to allow for overwriting of target method.
+ *
+ * @param {String} name The name of the target method.
+ * @return {Function} The aliased method
+ * @api private
+ */
+ function alias(name) {
+ return function aliasClosure() {
+ return this[name].apply(this, arguments);
+ };
+ }
+
+ /**
+ * Returns the listener array for the specified event.
+ * Will initialise the event object and listener arrays if required.
+ * Will return an object if you use a regex search. The object contains keys for each matched event. So /ba[rz]/ might return an object containing bar and baz. But only if you have either defined them with defineEvent or added some listeners to them.
+ * Each property in the object response is an array of listener functions.
+ *
+ * @param {String|RegExp} evt Name of the event to return the listeners from.
+ * @return {Function[]|Object} All listener functions for the event.
+ */
+ proto.getListeners = function getListeners(evt) {
+ var events = this._getEvents();
+ var response;
+ var key;
+
+ // Return a concatenated array of all matching events if
+ // the selector is a regular expression.
+ if (evt instanceof RegExp) {
+ response = {};
+ for (key in events) {
+ if (events.hasOwnProperty(key) && evt.test(key)) {
+ response[key] = events[key];
+ }
+ }
+ }
+ else {
+ response = events[evt] || (events[evt] = []);
+ }
+
+ return response;
+ };
+
+ /**
+ * Takes a list of listener objects and flattens it into a list of listener functions.
+ *
+ * @param {Object[]} listeners Raw listener objects.
+ * @return {Function[]} Just the listener functions.
+ */
+ proto.flattenListeners = function flattenListeners(listeners) {
+ var flatListeners = [];
+ var i;
+
+ for (i = 0; i < listeners.length; i += 1) {
+ flatListeners.push(listeners[i].listener);
+ }
+
+ return flatListeners;
+ };
+
+ /**
+ * Fetches the requested listeners via getListeners but will always return the results inside an object. This is mainly for internal use but others may find it useful.
+ *
+ * @param {String|RegExp} evt Name of the event to return the listeners from.
+ * @return {Object} All listener functions for an event in an object.
+ */
+ proto.getListenersAsObject = function getListenersAsObject(evt) {
+ var listeners = this.getListeners(evt);
+ var response;
+
+ if (listeners instanceof Array) {
+ response = {};
+ response[evt] = listeners;
+ }
+
+ return response || listeners;
+ };
+
+ function isValidListener (listener) {
+ if (typeof listener === 'function' || listener instanceof RegExp) {
+ return true
+ } else if (listener && typeof listener === 'object') {
+ return isValidListener(listener.listener)
+ } else {
+ return false
+ }
+ }
+
+ /**
+ * Adds a listener function to the specified event.
+ * The listener will not be added if it is a duplicate.
+ * If the listener returns true then it will be removed after it is called.
+ * If you pass a regular expression as the event name then the listener will be added to all events that match it.
+ *
+ * @param {String|RegExp} evt Name of the event to attach the listener to.
+ * @param {Function} listener Method to be called when the event is emitted. If the function returns true then it will be removed after calling.
+ * @return {Object} Current instance of EventEmitter for chaining.
+ */
+ proto.addListener = function addListener(evt, listener) {
+ if (!isValidListener(listener)) {
+ throw new TypeError('listener must be a function');
+ }
+
+ var listeners = this.getListenersAsObject(evt);
+ var listenerIsWrapped = typeof listener === 'object';
+ var key;
+
+ for (key in listeners) {
+ if (listeners.hasOwnProperty(key) && indexOfListener(listeners[key], listener) === -1) {
+ listeners[key].push(listenerIsWrapped ? listener : {
+ listener: listener,
+ once: false
+ });
+ }
+ }
+
+ return this;
+ };
+
+ /**
+ * Alias of addListener
+ */
+ proto.on = alias('addListener');
+
+ /**
+ * Semi-alias of addListener. It will add a listener that will be
+ * automatically removed after its first execution.
+ *
+ * @param {String|RegExp} evt Name of the event to attach the listener to.
+ * @param {Function} listener Method to be called when the event is emitted. If the function returns true then it will be removed after calling.
+ * @return {Object} Current instance of EventEmitter for chaining.
+ */
+ proto.addOnceListener = function addOnceListener(evt, listener) {
+ return this.addListener(evt, {
+ listener: listener,
+ once: true
+ });
+ };
+
+ /**
+ * Alias of addOnceListener.
+ */
+ proto.once = alias('addOnceListener');
+
+ /**
+ * Defines an event name. This is required if you want to use a regex to add a listener to multiple events at once. If you don't do this then how do you expect it to know what event to add to? Should it just add to every possible match for a regex? No. That is scary and bad.
+ * You need to tell it what event names should be matched by a regex.
+ *
+ * @param {String} evt Name of the event to create.
+ * @return {Object} Current instance of EventEmitter for chaining.
+ */
+ proto.defineEvent = function defineEvent(evt) {
+ this.getListeners(evt);
+ return this;
+ };
+
+ /**
+ * Uses defineEvent to define multiple events.
+ *
+ * @param {String[]} evts An array of event names to define.
+ * @return {Object} Current instance of EventEmitter for chaining.
+ */
+ proto.defineEvents = function defineEvents(evts) {
+ for (var i = 0; i < evts.length; i += 1) {
+ this.defineEvent(evts[i]);
+ }
+ return this;
+ };
+
+ /**
+ * Removes a listener function from the specified event.
+ * When passed a regular expression as the event name, it will remove the listener from all events that match it.
+ *
+ * @param {String|RegExp} evt Name of the event to remove the listener from.
+ * @param {Function} listener Method to remove from the event.
+ * @return {Object} Current instance of EventEmitter for chaining.
+ */
+ proto.removeListener = function removeListener(evt, listener) {
+ var listeners = this.getListenersAsObject(evt);
+ var index;
+ var key;
+
+ for (key in listeners) {
+ if (listeners.hasOwnProperty(key)) {
+ index = indexOfListener(listeners[key], listener);
+
+ if (index !== -1) {
+ listeners[key].splice(index, 1);
+ }
+ }
+ }
+
+ return this;
+ };
+
+ /**
+ * Alias of removeListener
+ */
+ proto.off = alias('removeListener');
+
+ /**
+ * Adds listeners in bulk using the manipulateListeners method.
+ * If you pass an object as the first argument you can add to multiple events at once. The object should contain key value pairs of events and listeners or listener arrays. You can also pass it an event name and an array of listeners to be added.
+ * You can also pass it a regular expression to add the array of listeners to all events that match it.
+ * Yeah, this function does quite a bit. That's probably a bad thing.
+ *
+ * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to add to multiple events at once.
+ * @param {Function[]} [listeners] An optional array of listener functions to add.
+ * @return {Object} Current instance of EventEmitter for chaining.
+ */
+ proto.addListeners = function addListeners(evt, listeners) {
+ // Pass through to manipulateListeners
+ return this.manipulateListeners(false, evt, listeners);
+ };
+
+ /**
+ * Removes listeners in bulk using the manipulateListeners method.
+ * If you pass an object as the first argument you can remove from multiple events at once. The object should contain key value pairs of events and listeners or listener arrays.
+ * You can also pass it an event name and an array of listeners to be removed.
+ * You can also pass it a regular expression to remove the listeners from all events that match it.
+ *
+ * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to remove from multiple events at once.
+ * @param {Function[]} [listeners] An optional array of listener functions to remove.
+ * @return {Object} Current instance of EventEmitter for chaining.
+ */
+ proto.removeListeners = function removeListeners(evt, listeners) {
+ // Pass through to manipulateListeners
+ return this.manipulateListeners(true, evt, listeners);
+ };
+
+ /**
+ * Edits listeners in bulk. The addListeners and removeListeners methods both use this to do their job. You should really use those instead, this is a little lower level.
+ * The first argument will determine if the listeners are removed (true) or added (false).
+ * If you pass an object as the second argument you can add/remove from multiple events at once. The object should contain key value pairs of events and listeners or listener arrays.
+ * You can also pass it an event name and an array of listeners to be added/removed.
+ * You can also pass it a regular expression to manipulate the listeners of all events that match it.
+ *
+ * @param {Boolean} remove True if you want to remove listeners, false if you want to add.
+ * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to add/remove from multiple events at once.
+ * @param {Function[]} [listeners] An optional array of listener functions to add/remove.
+ * @return {Object} Current instance of EventEmitter for chaining.
+ */
+ proto.manipulateListeners = function manipulateListeners(remove, evt, listeners) {
+ var i;
+ var value;
+ var single = remove ? this.removeListener : this.addListener;
+ var multiple = remove ? this.removeListeners : this.addListeners;
+
+ // If evt is an object then pass each of its properties to this method
+ if (typeof evt === 'object' && !(evt instanceof RegExp)) {
+ for (i in evt) {
+ if (evt.hasOwnProperty(i) && (value = evt[i])) {
+ // Pass the single listener straight through to the singular method
+ if (typeof value === 'function') {
+ single.call(this, i, value);
+ }
+ else {
+ // Otherwise pass back to the multiple function
+ multiple.call(this, i, value);
+ }
+ }
+ }
+ }
+ else {
+ // So evt must be a string
+ // And listeners must be an array of listeners
+ // Loop over it and pass each one to the multiple method
+ i = listeners.length;
+ while (i--) {
+ single.call(this, evt, listeners[i]);
+ }
+ }
+
+ return this;
+ };
+
+ /**
+ * Removes all listeners from a specified event.
+ * If you do not specify an event then all listeners will be removed.
+ * That means every event will be emptied.
+ * You can also pass a regex to remove all events that match it.
+ *
+ * @param {String|RegExp} [evt] Optional name of the event to remove all listeners for. Will remove from every event if not passed.
+ * @return {Object} Current instance of EventEmitter for chaining.
+ */
+ proto.removeEvent = function removeEvent(evt) {
+ var type = typeof evt;
+ var events = this._getEvents();
+ var key;
+
+ // Remove different things depending on the state of evt
+ if (type === 'string') {
+ // Remove all listeners for the specified event
+ delete events[evt];
+ }
+ else if (evt instanceof RegExp) {
+ // Remove all events matching the regex.
+ for (key in events) {
+ if (events.hasOwnProperty(key) && evt.test(key)) {
+ delete events[key];
+ }
+ }
+ }
+ else {
+ // Remove all listeners in all events
+ delete this._events;
+ }
+
+ return this;
+ };
+
+ /**
+ * Alias of removeEvent.
+ *
+ * Added to mirror the node API.
+ */
+ proto.removeAllListeners = alias('removeEvent');
+
+ /**
+ * Emits an event of your choice.
+ * When emitted, every listener attached to that event will be executed.
+ * If you pass the optional argument array then those arguments will be passed to every listener upon execution.
+ * Because it uses `apply`, your array of arguments will be passed as if you wrote them out separately.
+ * So they will not arrive within the array on the other side, they will be separate.
+ * You can also pass a regular expression to emit to all events that match it.
+ *
+ * @param {String|RegExp} evt Name of the event to emit and execute listeners for.
+ * @param {Array} [args] Optional array of arguments to be passed to each listener.
+ * @return {Object} Current instance of EventEmitter for chaining.
+ */
+ proto.emitEvent = function emitEvent(evt, args) {
+ var listenersMap = this.getListenersAsObject(evt);
+ var listeners;
+ var listener;
+ var i;
+ var key;
+ var response;
+
+ for (key in listenersMap) {
+ if (listenersMap.hasOwnProperty(key)) {
+ listeners = listenersMap[key].slice(0);
+
+ for (i = 0; i < listeners.length; i++) {
+ // If the listener returns true then it shall be removed from the event
+ // The function is executed either with a basic call or an apply if there is an args array
+ listener = listeners[i];
+
+ if (listener.once === true) {
+ this.removeListener(evt, listener.listener);
+ }
+
+ response = listener.listener.apply(this, args || []);
+
+ if (response === this._getOnceReturnValue()) {
+ this.removeListener(evt, listener.listener);
+ }
+ }
+ }
+ }
+
+ return this;
+ };
+
+ /**
+ * Alias of emitEvent
+ */
+ proto.trigger = alias('emitEvent');
+
+ /**
+ * Subtly different from emitEvent in that it will pass its arguments on to the listeners, as opposed to taking a single array of arguments to pass on.
+ * As with emitEvent, you can pass a regex in place of the event name to emit to all events that match it.
+ *
+ * @param {String|RegExp} evt Name of the event to emit and execute listeners for.
+ * @param {...*} Optional additional arguments to be passed to each listener.
+ * @return {Object} Current instance of EventEmitter for chaining.
+ */
+ proto.emit = function emit(evt) {
+ var args = Array.prototype.slice.call(arguments, 1);
+ return this.emitEvent(evt, args);
+ };
+
+ /**
+ * Sets the current value to check against when executing listeners. If a
+ * listeners return value matches the one set here then it will be removed
+ * after execution. This value defaults to true.
+ *
+ * @param {*} value The new value to check for when executing listeners.
+ * @return {Object} Current instance of EventEmitter for chaining.
+ */
+ proto.setOnceReturnValue = function setOnceReturnValue(value) {
+ this._onceReturnValue = value;
+ return this;
+ };
+
+ /**
+ * Fetches the current value to check against when executing listeners. If
+ * the listeners return value matches this one then it should be removed
+ * automatically. It will return true by default.
+ *
+ * @return {*|Boolean} The current value to check for or the default, true.
+ * @api private
+ */
+ proto._getOnceReturnValue = function _getOnceReturnValue() {
+ if (this.hasOwnProperty('_onceReturnValue')) {
+ return this._onceReturnValue;
+ }
+ else {
+ return true;
+ }
+ };
+
+ /**
+ * Fetches the events object and creates one if required.
+ *
+ * @return {Object} The events storage object.
+ * @api private
+ */
+ proto._getEvents = function _getEvents() {
+ return this._events || (this._events = {});
+ };
+
+ /**
+ * Reverts the global {@link EventEmitter} to its previous value and returns a reference to this version.
+ *
+ * @return {Function} Non conflicting EventEmitter class.
+ */
+ EventEmitter.noConflict = function noConflict() {
+ exports.EventEmitter = originalGlobalValue;
+ return EventEmitter;
+ };
+
+ // Expose the class either via AMD, CommonJS or the global object
+ if (typeof define === 'function' && define.amd) {
+ define(function () {
+ return EventEmitter;
+ });
+ }
+ else if (typeof module === 'object' && module.exports){
+ module.exports = EventEmitter;
+ }
+ else {
+ exports.EventEmitter = EventEmitter;
+ }
+}(typeof window !== 'undefined' ? window : this || {}));
+
+},{}],16:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+var OpenVidu_1 = require("./OpenVidu/OpenVidu");
+if (window) {
+ window['OpenVidu'] = OpenVidu_1.OpenVidu;
+}
+
+},{"./OpenVidu/OpenVidu":19}],17:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+var Stream_1 = require("./Stream");
+var Connection = (function () {
+ function Connection(session, opts) {
+ this.session = session;
+ this.disposed = false;
+ var msg = "'Connection' created ";
+ if (!!opts) {
+ msg += "(remote) with 'connectionId' [" + opts.id + ']';
+ }
+ else {
+ msg += '(local)';
+ }
+ console.info(msg);
+ this.options = opts;
+ if (!!opts) {
+ this.connectionId = opts.id;
+ if (opts.metadata) {
+ this.data = opts.metadata;
+ }
+ if (opts.streams) {
+ this.initRemoteStreams(opts.streams);
+ }
+ }
+ this.creationTime = new Date().getTime();
+ }
+ Connection.prototype.sendIceCandidate = function (candidate) {
+ console.debug((!!this.stream.outboundStreamOpts ? 'Local' : 'Remote'), 'candidate for', this.connectionId, JSON.stringify(candidate));
+ this.session.openvidu.sendRequest('onIceCandidate', {
+ endpointName: this.connectionId,
+ candidate: candidate.candidate,
+ sdpMid: candidate.sdpMid,
+ sdpMLineIndex: candidate.sdpMLineIndex
+ }, function (error, response) {
+ if (error) {
+ console.error('Error sending ICE candidate: '
+ + JSON.stringify(error));
+ }
+ });
+ };
+ Connection.prototype.initRemoteStreams = function (options) {
+ var _this = this;
+ options.forEach(function (opts) {
+ var streamOptions = {
+ id: opts.id,
+ connection: _this,
+ hasAudio: opts.hasAudio,
+ hasVideo: opts.hasVideo,
+ audioActive: opts.audioActive,
+ videoActive: opts.videoActive,
+ typeOfVideo: opts.typeOfVideo,
+ frameRate: opts.frameRate,
+ videoDimensions: !!opts.videoDimensions ? JSON.parse(opts.videoDimensions) : undefined
+ };
+ var stream = new Stream_1.Stream(_this.session, streamOptions);
+ _this.addStream(stream);
+ });
+ console.info("Remote 'Connection' with 'connectionId' [" + this.connectionId + '] is now configured for receiving Streams with options: ', this.stream.inboundStreamOpts);
+ };
+ Connection.prototype.addStream = function (stream) {
+ stream.connection = this;
+ this.stream = stream;
+ };
+ Connection.prototype.removeStream = function (streamId) {
+ delete this.stream;
+ };
+ Connection.prototype.dispose = function () {
+ if (!!this.stream) {
+ delete this.stream;
+ }
+ this.disposed = true;
+ };
+ return Connection;
+}());
+exports.Connection = Connection;
+
+},{"./Stream":22}],18:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+var LocalRecorderState_1 = require("../OpenViduInternal/Enums/LocalRecorderState");
+var LocalRecorder = (function () {
+ function LocalRecorder(stream) {
+ this.stream = stream;
+ this.chunks = [];
+ this.count = 0;
+ this.connectionId = (!!this.stream.connection) ? this.stream.connection.connectionId : 'default-connection';
+ this.id = this.stream.streamId + '_' + this.connectionId + '_localrecord';
+ this.state = LocalRecorderState_1.LocalRecorderState.READY;
+ }
+ LocalRecorder.prototype.record = function () {
+ var _this = this;
+ return new Promise(function (resolve, reject) {
+ try {
+ if (typeof MediaRecorder === 'undefined') {
+ console.error('MediaRecorder not supported on your browser. See compatibility in https://caniuse.com/#search=MediaRecorder');
+ throw (Error('MediaRecorder not supported on your browser. See compatibility in https://caniuse.com/#search=MediaRecorder'));
+ }
+ if (_this.state !== LocalRecorderState_1.LocalRecorderState.READY) {
+ throw (Error('\'LocalRecord.record()\' needs \'LocalRecord.state\' to be \'READY\' (current value: \'' + _this.state + '\'). Call \'LocalRecorder.clean()\' or init a new LocalRecorder before'));
+ }
+ console.log("Starting local recording of stream '" + _this.stream.streamId + "' of connection '" + _this.connectionId + "'");
+ if (typeof MediaRecorder.isTypeSupported === 'function') {
+ var options = void 0;
+ if (MediaRecorder.isTypeSupported('video/webm;codecs=vp9')) {
+ options = { mimeType: 'video/webm;codecs=vp9' };
+ }
+ else if (MediaRecorder.isTypeSupported('video/webm;codecs=h264')) {
+ options = { mimeType: 'video/webm;codecs=h264' };
+ }
+ else if (MediaRecorder.isTypeSupported('video/webm;codecs=vp8')) {
+ options = { mimeType: 'video/webm;codecs=vp8' };
+ }
+ console.log('Using mimeType ' + options.mimeType);
+ _this.mediaRecorder = new MediaRecorder(_this.stream.getMediaStream(), options);
+ }
+ else {
+ console.warn('isTypeSupported is not supported, using default codecs for browser');
+ _this.mediaRecorder = new MediaRecorder(_this.stream.getMediaStream());
+ }
+ _this.mediaRecorder.start(10);
+ }
+ catch (err) {
+ reject(err);
+ }
+ _this.mediaRecorder.ondataavailable = function (e) {
+ _this.chunks.push(e.data);
+ };
+ _this.mediaRecorder.onerror = function (e) {
+ console.error('MediaRecorder error: ', e);
+ };
+ _this.mediaRecorder.onstart = function () {
+ console.log('MediaRecorder started (state=' + _this.mediaRecorder.state + ')');
+ };
+ _this.mediaRecorder.onstop = function () {
+ _this.onStopDefault();
+ };
+ _this.mediaRecorder.onpause = function () {
+ console.log('MediaRecorder paused (state=' + _this.mediaRecorder.state + ')');
+ };
+ _this.mediaRecorder.onresume = function () {
+ console.log('MediaRecorder resumed (state=' + _this.mediaRecorder.state + ')');
+ };
+ _this.mediaRecorder.onwarning = function (e) {
+ console.log('MediaRecorder warning: ' + e);
+ };
+ _this.state = LocalRecorderState_1.LocalRecorderState.RECORDING;
+ resolve();
+ });
+ };
+ LocalRecorder.prototype.stop = function () {
+ var _this = this;
+ return new Promise(function (resolve, reject) {
+ try {
+ if (_this.state === LocalRecorderState_1.LocalRecorderState.READY || _this.state === LocalRecorderState_1.LocalRecorderState.FINISHED) {
+ throw (Error('\'LocalRecord.stop()\' needs \'LocalRecord.state\' to be \'RECORDING\' or \'PAUSED\' (current value: \'' + _this.state + '\'). Call \'LocalRecorder.start()\' before'));
+ }
+ _this.mediaRecorder.onstop = function () {
+ _this.onStopDefault();
+ resolve();
+ };
+ _this.mediaRecorder.stop();
+ }
+ catch (e) {
+ reject(e);
+ }
+ });
+ };
+ LocalRecorder.prototype.pause = function () {
+ var _this = this;
+ return new Promise(function (resolve, reject) {
+ try {
+ if (_this.state !== LocalRecorderState_1.LocalRecorderState.RECORDING) {
+ reject(Error('\'LocalRecord.pause()\' needs \'LocalRecord.state\' to be \'RECORDING\' (current value: \'' + _this.state + '\'). Call \'LocalRecorder.start()\' or \'LocalRecorder.resume()\' before'));
+ }
+ _this.mediaRecorder.pause();
+ _this.state = LocalRecorderState_1.LocalRecorderState.PAUSED;
+ }
+ catch (error) {
+ reject(error);
+ }
+ });
+ };
+ LocalRecorder.prototype.resume = function () {
+ var _this = this;
+ return new Promise(function (resolve, reject) {
+ try {
+ if (_this.state !== LocalRecorderState_1.LocalRecorderState.PAUSED) {
+ throw (Error('\'LocalRecord.resume()\' needs \'LocalRecord.state\' to be \'PAUSED\' (current value: \'' + _this.state + '\'). Call \'LocalRecorder.pause()\' before'));
+ }
+ _this.mediaRecorder.resume();
+ _this.state = LocalRecorderState_1.LocalRecorderState.RECORDING;
+ }
+ catch (error) {
+ reject(error);
+ }
+ });
+ };
+ LocalRecorder.prototype.preview = function (parentElement) {
+ if (this.state !== LocalRecorderState_1.LocalRecorderState.FINISHED) {
+ throw (Error('\'LocalRecord.preview()\' needs \'LocalRecord.state\' to be \'FINISHED\' (current value: \'' + this.state + '\'). Call \'LocalRecorder.stop()\' before'));
+ }
+ this.videoPreview = document.createElement('video');
+ this.videoPreview.id = this.id;
+ this.videoPreview.autoplay = true;
+ if (typeof parentElement === 'string') {
+ this.htmlParentElementId = parentElement;
+ var parentElementDom = document.getElementById(parentElement);
+ if (parentElementDom) {
+ this.videoPreview = parentElementDom.appendChild(this.videoPreview);
+ }
+ }
+ else {
+ this.htmlParentElementId = parentElement.id;
+ this.videoPreview = parentElement.appendChild(this.videoPreview);
+ }
+ this.videoPreview.src = this.videoPreviewSrc;
+ return this.videoPreview;
+ };
+ LocalRecorder.prototype.clean = function () {
+ var _this = this;
+ var f = function () {
+ delete _this.blob;
+ _this.chunks = [];
+ _this.count = 0;
+ delete _this.mediaRecorder;
+ _this.state = LocalRecorderState_1.LocalRecorderState.READY;
+ };
+ if (this.state === LocalRecorderState_1.LocalRecorderState.RECORDING || this.state === LocalRecorderState_1.LocalRecorderState.PAUSED) {
+ this.stop().then(function () { return f(); }).catch(function () { return f(); });
+ }
+ else {
+ f();
+ }
+ };
+ LocalRecorder.prototype.download = function () {
+ if (this.state !== LocalRecorderState_1.LocalRecorderState.FINISHED) {
+ throw (Error('\'LocalRecord.download()\' needs \'LocalRecord.state\' to be \'FINISHED\' (current value: \'' + this.state + '\'). Call \'LocalRecorder.stop()\' before'));
+ }
+ else {
+ var a = document.createElement('a');
+ a.style.display = 'none';
+ document.body.appendChild(a);
+ var url = window.URL.createObjectURL(this.blob);
+ a.href = url;
+ a.download = this.id + '.webm';
+ a.click();
+ window.URL.revokeObjectURL(url);
+ document.body.removeChild(a);
+ }
+ };
+ LocalRecorder.prototype.getBlob = function () {
+ if (this.state !== LocalRecorderState_1.LocalRecorderState.FINISHED) {
+ throw (Error('Call \'LocalRecord.stop()\' before getting Blob file'));
+ }
+ else {
+ return this.blob;
+ }
+ };
+ LocalRecorder.prototype.uploadAsBinary = function (endpoint, headers) {
+ var _this = this;
+ return new Promise(function (resolve, reject) {
+ if (_this.state !== LocalRecorderState_1.LocalRecorderState.FINISHED) {
+ reject(Error('\'LocalRecord.uploadAsBinary()\' needs \'LocalRecord.state\' to be \'FINISHED\' (current value: \'' + _this.state + '\'). Call \'LocalRecorder.stop()\' before'));
+ }
+ else {
+ var http_1 = new XMLHttpRequest();
+ http_1.open('POST', endpoint, true);
+ if (typeof headers === 'object') {
+ for (var _i = 0, _a = Object.keys(headers); _i < _a.length; _i++) {
+ var key = _a[_i];
+ http_1.setRequestHeader(key, headers[key]);
+ }
+ }
+ http_1.onreadystatechange = function () {
+ if (http_1.readyState === 4) {
+ if (http_1.status.toString().charAt(0) === '2') {
+ resolve(http_1.responseText);
+ }
+ else {
+ reject(http_1.status);
+ }
+ }
+ };
+ http_1.send(_this.blob);
+ }
+ });
+ };
+ LocalRecorder.prototype.uploadAsMultipartfile = function (endpoint, headers) {
+ var _this = this;
+ return new Promise(function (resolve, reject) {
+ if (_this.state !== LocalRecorderState_1.LocalRecorderState.FINISHED) {
+ reject(Error('\'LocalRecord.uploadAsMultipartfile()\' needs \'LocalRecord.state\' to be \'FINISHED\' (current value: \'' + _this.state + '\'). Call \'LocalRecorder.stop()\' before'));
+ }
+ else {
+ var http_2 = new XMLHttpRequest();
+ http_2.open('POST', endpoint, true);
+ if (typeof headers === 'object') {
+ for (var _i = 0, _a = Object.keys(headers); _i < _a.length; _i++) {
+ var key = _a[_i];
+ http_2.setRequestHeader(key, headers[key]);
+ }
+ }
+ var sendable = new FormData();
+ sendable.append('file', _this.blob, _this.id + '.webm');
+ http_2.onreadystatechange = function () {
+ if (http_2.readyState === 4) {
+ if (http_2.status.toString().charAt(0) === '2') {
+ resolve(http_2.responseText);
+ }
+ else {
+ reject(http_2.status);
+ }
+ }
+ };
+ http_2.send(sendable);
+ }
+ });
+ };
+ LocalRecorder.prototype.onStopDefault = function () {
+ console.log('MediaRecorder stopped (state=' + this.mediaRecorder.state + ')');
+ this.blob = new Blob(this.chunks, { type: 'video/webm' });
+ this.chunks = [];
+ this.videoPreviewSrc = window.URL.createObjectURL(this.blob);
+ this.state = LocalRecorderState_1.LocalRecorderState.FINISHED;
+ };
+ return LocalRecorder;
+}());
+exports.LocalRecorder = LocalRecorder;
+
+},{"../OpenViduInternal/Enums/LocalRecorderState":25}],19:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+var LocalRecorder_1 = require("./LocalRecorder");
+var Publisher_1 = require("./Publisher");
+var Session_1 = require("./Session");
+var StreamPropertyChangedEvent_1 = require("../OpenViduInternal/Events/StreamPropertyChangedEvent");
+var OpenViduError_1 = require("../OpenViduInternal/Enums/OpenViduError");
+var VideoInsertMode_1 = require("../OpenViduInternal/Enums/VideoInsertMode");
+var screenSharingAuto = require("../OpenViduInternal/ScreenSharing/Screen-Capturing-Auto");
+var screenSharing = require("../OpenViduInternal/ScreenSharing/Screen-Capturing");
+var RpcBuilder = require("../OpenViduInternal/KurentoUtils/kurento-jsonrpc");
+var platform = require("platform");
+var OpenVidu = (function () {
+ function OpenVidu() {
+ var _this = this;
+ this.publishers = [];
+ this.secret = '';
+ this.recorder = false;
+ this.advancedConfiguration = {};
+ console.info("'OpenVidu' initialized");
+ if (platform.name.toLowerCase().indexOf('mobile') !== -1) {
+ window.onorientationchange = function () {
+ _this.publishers.forEach(function (publisher) {
+ if (!!publisher.stream && !!publisher.stream.hasVideo && !!publisher.stream.streamManager.videos[0]) {
+ var attempts_1 = 0;
+ var oldWidth_1 = publisher.stream.videoDimensions.width;
+ var oldHeight_1 = publisher.stream.videoDimensions.height;
+ var firefoxSettings_1 = publisher.stream.getMediaStream().getVideoTracks()[0].getSettings();
+ var newWidth_1 = (platform.name.toLowerCase().indexOf('firefox') !== -1) ? firefoxSettings_1.width : publisher.videoReference.videoWidth;
+ var newHeight_1 = (platform.name.toLowerCase().indexOf('firefox') !== -1) ? firefoxSettings_1.height : publisher.videoReference.videoHeight;
+ var repeatUntilChange_1 = setInterval(function () {
+ firefoxSettings_1 = publisher.stream.getMediaStream().getVideoTracks()[0].getSettings();
+ newWidth_1 = (platform.name.toLowerCase().indexOf('firefox') !== -1) ? firefoxSettings_1.width : publisher.videoReference.videoWidth;
+ newHeight_1 = (platform.name.toLowerCase().indexOf('firefox') !== -1) ? firefoxSettings_1.height : publisher.videoReference.videoHeight;
+ sendStreamPropertyChangedEvent_1(oldWidth_1, oldHeight_1, newWidth_1, newHeight_1);
+ }, 100);
+ var sendStreamPropertyChangedEvent_1 = function (oldWidth, oldHeight, newWidth, newHeight) {
+ attempts_1++;
+ if (attempts_1 > 4) {
+ clearTimeout(repeatUntilChange_1);
+ }
+ if (newWidth !== oldWidth || newHeight !== oldHeight) {
+ publisher.stream.videoDimensions = {
+ width: newWidth || 0,
+ height: newHeight || 0
+ };
+ _this.sendRequest('streamPropertyChanged', {
+ streamId: publisher.stream.streamId,
+ property: 'videoDimensions',
+ newValue: JSON.stringify(publisher.stream.videoDimensions),
+ reason: 'deviceRotated'
+ }, function (error, response) {
+ if (error) {
+ console.error("Error sending 'streamPropertyChanged' event", error);
+ }
+ else {
+ _this.session.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent_1.StreamPropertyChangedEvent(_this.session, publisher.stream, 'videoDimensions', publisher.stream.videoDimensions, { width: oldWidth, height: oldHeight }, 'deviceRotated')]);
+ publisher.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent_1.StreamPropertyChangedEvent(publisher, publisher.stream, 'videoDimensions', publisher.stream.videoDimensions, { width: oldWidth, height: oldHeight }, 'deviceRotated')]);
+ }
+ });
+ clearTimeout(repeatUntilChange_1);
+ }
+ };
+ }
+ });
+ };
+ }
+ }
+ OpenVidu.prototype.initSession = function () {
+ this.session = new Session_1.Session(this);
+ return this.session;
+ };
+ OpenVidu.prototype.initPublisher = function (targetElement, param2, param3) {
+ var properties;
+ if (!!param2 && (typeof param2 !== 'function')) {
+ properties = param2;
+ properties = {
+ audioSource: (typeof properties.audioSource !== 'undefined') ? properties.audioSource : undefined,
+ frameRate: this.isMediaStreamTrack(properties.videoSource) ? undefined : ((typeof properties.frameRate !== 'undefined') ? properties.frameRate : undefined),
+ insertMode: (typeof properties.insertMode !== 'undefined') ? ((typeof properties.insertMode === 'string') ? VideoInsertMode_1.VideoInsertMode[properties.insertMode] : properties.insertMode) : VideoInsertMode_1.VideoInsertMode.APPEND,
+ mirror: (typeof properties.mirror !== 'undefined') ? properties.mirror : true,
+ publishAudio: (typeof properties.publishAudio !== 'undefined') ? properties.publishAudio : true,
+ publishVideo: (typeof properties.publishVideo !== 'undefined') ? properties.publishVideo : true,
+ resolution: this.isMediaStreamTrack(properties.videoSource) ? undefined : ((typeof properties.resolution !== 'undefined') ? properties.resolution : '640x480'),
+ videoSource: (typeof properties.videoSource !== 'undefined') ? properties.videoSource : undefined
+ };
+ }
+ else {
+ properties = {
+ insertMode: VideoInsertMode_1.VideoInsertMode.APPEND,
+ mirror: true,
+ publishAudio: true,
+ publishVideo: true,
+ resolution: '640x480'
+ };
+ }
+ var publisher = new Publisher_1.Publisher(targetElement, properties, this);
+ var completionHandler;
+ if (!!param2 && (typeof param2 === 'function')) {
+ completionHandler = param2;
+ }
+ else if (!!param3) {
+ completionHandler = param3;
+ }
+ publisher.initialize()
+ .then(function () {
+ if (completionHandler !== undefined) {
+ completionHandler(undefined);
+ }
+ publisher.emitEvent('accessAllowed', []);
+ }).catch(function (error) {
+ if (completionHandler !== undefined) {
+ completionHandler(error);
+ }
+ publisher.emitEvent('accessDenied', []);
+ });
+ this.publishers.push(publisher);
+ return publisher;
+ };
+ OpenVidu.prototype.initPublisherAsync = function (targetElement, properties) {
+ var _this = this;
+ return new Promise(function (resolve, reject) {
+ var publisher;
+ var callback = function (error) {
+ if (!!error) {
+ reject(error);
+ }
+ else {
+ resolve(publisher);
+ }
+ };
+ if (!!properties) {
+ publisher = _this.initPublisher(targetElement, properties, callback);
+ }
+ else {
+ publisher = _this.initPublisher(targetElement, callback);
+ }
+ });
+ };
+ OpenVidu.prototype.initLocalRecorder = function (stream) {
+ return new LocalRecorder_1.LocalRecorder(stream);
+ };
+ OpenVidu.prototype.checkSystemRequirements = function () {
+ var browser = platform.name;
+ var version = platform.version;
+ if ((browser !== 'Chrome') && (browser !== 'Chrome Mobile') &&
+ (browser !== 'Firefox') && (browser !== 'Firefox Mobile') && (browser !== 'Firefox for iOS') &&
+ (browser !== 'Opera') && (browser !== 'Opera Mobile') &&
+ (browser !== 'Safari')) {
+ return 0;
+ }
+ else {
+ return 1;
+ }
+ };
+ OpenVidu.prototype.getDevices = function () {
+ return new Promise(function (resolve, reject) {
+ navigator.mediaDevices.enumerateDevices().then(function (deviceInfos) {
+ var devices = [];
+ deviceInfos.forEach(function (deviceInfo) {
+ if (deviceInfo.kind === 'audioinput' || deviceInfo.kind === 'videoinput') {
+ devices.push({
+ kind: deviceInfo.kind,
+ deviceId: deviceInfo.deviceId,
+ label: deviceInfo.label
+ });
+ }
+ });
+ resolve(devices);
+ }).catch(function (error) {
+ console.error('Error getting devices', error);
+ reject(error);
+ });
+ });
+ };
+ OpenVidu.prototype.getUserMedia = function (options) {
+ var _this = this;
+ return new Promise(function (resolve, reject) {
+ _this.generateMediaConstraints(options)
+ .then(function (constraints) {
+ navigator.mediaDevices.getUserMedia(constraints)
+ .then(function (mediaStream) {
+ resolve(mediaStream);
+ })
+ .catch(function (error) {
+ var errorName;
+ var errorMessage = error.toString();
+ if (!(options.videoSource === 'screen')) {
+ errorName = OpenViduError_1.OpenViduErrorName.DEVICE_ACCESS_DENIED;
+ }
+ else {
+ errorName = OpenViduError_1.OpenViduErrorName.SCREEN_CAPTURE_DENIED;
+ }
+ reject(new OpenViduError_1.OpenViduError(errorName, errorMessage));
+ });
+ })
+ .catch(function (error) {
+ reject(error);
+ });
+ });
+ };
+ OpenVidu.prototype.enableProdMode = function () {
+ console.log = function () { };
+ console.debug = function () { };
+ console.info = function () { };
+ console.warn = function () { };
+ };
+ OpenVidu.prototype.setAdvancedConfiguration = function (configuration) {
+ this.advancedConfiguration = configuration;
+ };
+ OpenVidu.prototype.generateMediaConstraints = function (publisherProperties) {
+ var _this = this;
+ return new Promise(function (resolve, reject) {
+ var audio, video;
+ if (publisherProperties.audioSource === null || publisherProperties.audioSource === false) {
+ audio = false;
+ }
+ else if (publisherProperties.audioSource === undefined) {
+ audio = true;
+ }
+ else {
+ audio = publisherProperties.audioSource;
+ }
+ if (publisherProperties.videoSource === null || publisherProperties.videoSource === false) {
+ video = false;
+ }
+ else {
+ video = {
+ height: {
+ ideal: 480
+ },
+ width: {
+ ideal: 640
+ }
+ };
+ }
+ var mediaConstraints = {
+ audio: audio,
+ video: video
+ };
+ if (typeof mediaConstraints.audio === 'string') {
+ mediaConstraints.audio = { deviceId: { exact: mediaConstraints.audio } };
+ }
+ if (mediaConstraints.video) {
+ if (!!publisherProperties.resolution) {
+ var widthAndHeight = publisherProperties.resolution.toLowerCase().split('x');
+ var width = Number(widthAndHeight[0]);
+ var height = Number(widthAndHeight[1]);
+ mediaConstraints.video.width.ideal = width;
+ mediaConstraints.video.height.ideal = height;
+ }
+ if (!!publisherProperties.frameRate) {
+ mediaConstraints.video.frameRate = { ideal: publisherProperties.frameRate };
+ }
+ if (!!publisherProperties.videoSource && typeof publisherProperties.videoSource === 'string') {
+ if (publisherProperties.videoSource === 'screen') {
+ if (platform.name !== 'Chrome' && platform.name.indexOf('Firefox') === -1) {
+ var error = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_SHARING_NOT_SUPPORTED, 'You can only screen share in desktop Chrome and Firefox. Detected browser: ' + platform.name);
+ console.error(error);
+ reject(error);
+ }
+ else {
+ if (!!_this.advancedConfiguration.screenShareChromeExtension && !(platform.name.indexOf('Firefox') !== -1)) {
+ screenSharing.getScreenConstraints(function (error, screenConstraints) {
+ if (!!error || !!screenConstraints.mandatory && screenConstraints.mandatory.chromeMediaSource === 'screen') {
+ if (error === 'permission-denied' || error === 'PermissionDeniedError') {
+ var error_1 = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_CAPTURE_DENIED, 'You must allow access to one window of your desktop');
+ console.error(error_1);
+ reject(error_1);
+ }
+ else {
+ var extensionId = _this.advancedConfiguration.screenShareChromeExtension.split('/').pop().trim();
+ screenSharing.getChromeExtensionStatus(extensionId, function (status) {
+ if (status === 'installed-disabled') {
+ var error_2 = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_EXTENSION_DISABLED, 'You must enable the screen extension');
+ console.error(error_2);
+ reject(error_2);
+ }
+ if (status === 'not-installed') {
+ var error_3 = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_EXTENSION_NOT_INSTALLED, _this.advancedConfiguration.screenShareChromeExtension);
+ console.error(error_3);
+ reject(error_3);
+ }
+ });
+ }
+ }
+ else {
+ mediaConstraints.video = screenConstraints;
+ resolve(mediaConstraints);
+ }
+ });
+ }
+ else {
+ screenSharingAuto.getScreenId(function (error, sourceId, screenConstraints) {
+ if (!!error) {
+ if (error === 'not-installed') {
+ var extensionUrl = !!_this.advancedConfiguration.screenShareChromeExtension ? _this.advancedConfiguration.screenShareChromeExtension :
+ 'https://chrome.google.com/webstore/detail/openvidu-screensharing/lfcgfepafnobdloecchnfaclibenjold';
+ var error_4 = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_EXTENSION_NOT_INSTALLED, extensionUrl);
+ console.error(error_4);
+ reject(error_4);
+ }
+ else if (error === 'installed-disabled') {
+ var error_5 = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_EXTENSION_DISABLED, 'You must enable the screen extension');
+ console.error(error_5);
+ reject(error_5);
+ }
+ else if (error === 'permission-denied') {
+ var error_6 = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_CAPTURE_DENIED, 'You must allow access to one window of your desktop');
+ console.error(error_6);
+ reject(error_6);
+ }
+ }
+ else {
+ mediaConstraints.video = screenConstraints.video;
+ resolve(mediaConstraints);
+ }
+ });
+ }
+ publisherProperties.videoSource = 'screen';
+ }
+ }
+ else {
+ mediaConstraints.video['deviceId'] = { exact: publisherProperties.videoSource };
+ resolve(mediaConstraints);
+ }
+ }
+ else {
+ resolve(mediaConstraints);
+ }
+ }
+ else {
+ resolve(mediaConstraints);
+ }
+ });
+ };
+ OpenVidu.prototype.startWs = function (onConnectSucces) {
+ var config = {
+ heartbeat: 5000,
+ sendCloseMessage: false,
+ ws: {
+ uri: this.wsUri,
+ useSockJS: false,
+ onconnected: onConnectSucces,
+ ondisconnect: this.disconnectCallback.bind(this),
+ onreconnecting: this.reconnectingCallback.bind(this),
+ onreconnected: this.reconnectedCallback.bind(this)
+ },
+ rpc: {
+ requestTimeout: 10000,
+ participantJoined: this.session.onParticipantJoined.bind(this.session),
+ participantPublished: this.session.onParticipantPublished.bind(this.session),
+ participantUnpublished: this.session.onParticipantUnpublished.bind(this.session),
+ participantLeft: this.session.onParticipantLeft.bind(this.session),
+ participantEvicted: this.session.onParticipantEvicted.bind(this.session),
+ recordingStarted: this.session.onRecordingStarted.bind(this.session),
+ recordingStopped: this.session.onRecordingStopped.bind(this.session),
+ sendMessage: this.session.onNewMessage.bind(this.session),
+ streamPropertyChanged: this.session.onStreamPropertyChanged.bind(this.session),
+ iceCandidate: this.session.recvIceCandidate.bind(this.session),
+ mediaError: this.session.onMediaError.bind(this.session)
+ }
+ };
+ this.jsonRpcClient = new RpcBuilder.clients.JsonRpcClient(config);
+ };
+ OpenVidu.prototype.closeWs = function () {
+ this.jsonRpcClient.close();
+ };
+ OpenVidu.prototype.sendRequest = function (method, params, callback) {
+ if (params && params instanceof Function) {
+ callback = params;
+ params = {};
+ }
+ console.debug('Sending request: {method:"' + method + '", params: ' + JSON.stringify(params) + '}');
+ this.jsonRpcClient.send(method, params, callback);
+ };
+ OpenVidu.prototype.isMediaStreamTrack = function (mediaSource) {
+ var is = (!!mediaSource &&
+ mediaSource.enabled !== undefined && typeof mediaSource.enabled === 'boolean' &&
+ mediaSource.id !== undefined && typeof mediaSource.id === 'string' &&
+ mediaSource.kind !== undefined && typeof mediaSource.kind === 'string' &&
+ mediaSource.label !== undefined && typeof mediaSource.label === 'string' &&
+ mediaSource.muted !== undefined && typeof mediaSource.muted === 'boolean' &&
+ mediaSource.readyState !== undefined && typeof mediaSource.readyState === 'string');
+ return is;
+ };
+ OpenVidu.prototype.getWsUri = function () {
+ return this.wsUri;
+ };
+ OpenVidu.prototype.getSecret = function () {
+ return this.secret;
+ };
+ OpenVidu.prototype.getRecorder = function () {
+ return this.recorder;
+ };
+ OpenVidu.prototype.disconnectCallback = function () {
+ console.warn('Websocket connection lost');
+ if (this.isRoomAvailable()) {
+ this.session.onLostConnection();
+ }
+ else {
+ alert('Connection error. Please reload page.');
+ }
+ };
+ OpenVidu.prototype.reconnectingCallback = function () {
+ console.warn('Websocket connection lost (reconnecting)');
+ if (this.isRoomAvailable()) {
+ this.session.onLostConnection();
+ }
+ else {
+ alert('Connection error. Please reload page.');
+ }
+ };
+ OpenVidu.prototype.reconnectedCallback = function () {
+ console.warn('Websocket reconnected');
+ if (this.isRoomAvailable()) {
+ this.session.onRecoveredConnection();
+ }
+ else {
+ alert('Connection error. Please reload page.');
+ }
+ };
+ OpenVidu.prototype.isRoomAvailable = function () {
+ if (this.session !== undefined && this.session instanceof Session_1.Session) {
+ return true;
+ }
+ else {
+ console.warn('Session instance not found');
+ return false;
+ }
+ };
+ return OpenVidu;
+}());
+exports.OpenVidu = OpenVidu;
+
+},{"../OpenViduInternal/Enums/OpenViduError":26,"../OpenViduInternal/Enums/VideoInsertMode":27,"../OpenViduInternal/Events/StreamPropertyChangedEvent":36,"../OpenViduInternal/KurentoUtils/kurento-jsonrpc":43,"../OpenViduInternal/ScreenSharing/Screen-Capturing":48,"../OpenViduInternal/ScreenSharing/Screen-Capturing-Auto":47,"./LocalRecorder":18,"./Publisher":20,"./Session":21,"platform":8}],20:[function(require,module,exports){
+"use strict";
+var __extends = (this && this.__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 __());
+ };
+})();
+Object.defineProperty(exports, "__esModule", { value: true });
+var Session_1 = require("./Session");
+var Stream_1 = require("./Stream");
+var StreamManager_1 = require("./StreamManager");
+var StreamEvent_1 = require("../OpenViduInternal/Events/StreamEvent");
+var StreamPropertyChangedEvent_1 = require("../OpenViduInternal/Events/StreamPropertyChangedEvent");
+var VideoElementEvent_1 = require("../OpenViduInternal/Events/VideoElementEvent");
+var OpenViduError_1 = require("../OpenViduInternal/Enums/OpenViduError");
+var platform = require("platform");
+var Publisher = (function (_super) {
+ __extends(Publisher, _super);
+ function Publisher(targEl, properties, openvidu) {
+ var _this = _super.call(this, new Stream_1.Stream((!!openvidu.session) ? openvidu.session : new Session_1.Session(openvidu), { publisherProperties: properties, mediaConstraints: {} }), targEl) || this;
+ _this.accessAllowed = false;
+ _this.isSubscribedToRemote = false;
+ _this.accessDenied = false;
+ _this.properties = properties;
+ _this.openvidu = openvidu;
+ _this.stream.ee.on('local-stream-destroyed', function (reason) {
+ _this.stream.isLocalStreamPublished = false;
+ var streamEvent = new StreamEvent_1.StreamEvent(true, _this, 'streamDestroyed', _this.stream, reason);
+ _this.emitEvent('streamDestroyed', [streamEvent]);
+ streamEvent.callDefaultBehavior();
+ });
+ return _this;
+ }
+ Publisher.prototype.publishAudio = function (value) {
+ var _this = this;
+ if (this.stream.audioActive !== value) {
+ this.stream.getMediaStream().getAudioTracks().forEach(function (track) {
+ track.enabled = value;
+ });
+ this.session.openvidu.sendRequest('streamPropertyChanged', {
+ streamId: this.stream.streamId,
+ property: 'audioActive',
+ newValue: value,
+ reason: 'publishAudio'
+ }, function (error, response) {
+ if (error) {
+ console.error("Error sending 'streamPropertyChanged' event", error);
+ }
+ else {
+ _this.session.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent_1.StreamPropertyChangedEvent(_this.session, _this.stream, 'audioActive', value, !value, 'publishAudio')]);
+ _this.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent_1.StreamPropertyChangedEvent(_this, _this.stream, 'audioActive', value, !value, 'publishAudio')]);
+ }
+ });
+ this.stream.audioActive = value;
+ console.info("'Publisher' has " + (value ? 'published' : 'unpublished') + ' its audio stream');
+ }
+ };
+ Publisher.prototype.publishVideo = function (value) {
+ var _this = this;
+ if (this.stream.videoActive !== value) {
+ this.stream.getMediaStream().getVideoTracks().forEach(function (track) {
+ track.enabled = value;
+ });
+ this.session.openvidu.sendRequest('streamPropertyChanged', {
+ streamId: this.stream.streamId,
+ property: 'videoActive',
+ newValue: value,
+ reason: 'publishVideo'
+ }, function (error, response) {
+ if (error) {
+ console.error("Error sending 'streamPropertyChanged' event", error);
+ }
+ else {
+ _this.session.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent_1.StreamPropertyChangedEvent(_this.session, _this.stream, 'videoActive', value, !value, 'publishVideo')]);
+ _this.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent_1.StreamPropertyChangedEvent(_this, _this.stream, 'videoActive', value, !value, 'publishVideo')]);
+ }
+ });
+ this.stream.videoActive = value;
+ console.info("'Publisher' has " + (value ? 'published' : 'unpublished') + ' its video stream');
+ }
+ };
+ Publisher.prototype.subscribeToRemote = function (value) {
+ value = (value !== undefined) ? value : true;
+ this.isSubscribedToRemote = value;
+ this.stream.subscribeToMyRemote(value);
+ };
+ Publisher.prototype.on = function (type, handler) {
+ var _this = this;
+ _super.prototype.on.call(this, type, handler);
+ if (type === 'streamCreated') {
+ if (!!this.stream && this.stream.isLocalStreamPublished) {
+ this.emitEvent('streamCreated', [new StreamEvent_1.StreamEvent(false, this, 'streamCreated', this.stream, '')]);
+ }
+ else {
+ this.stream.ee.on('stream-created-by-publisher', function () {
+ _this.emitEvent('streamCreated', [new StreamEvent_1.StreamEvent(false, _this, 'streamCreated', _this.stream, '')]);
+ });
+ }
+ }
+ if (type === 'remoteVideoPlaying') {
+ if (this.stream.displayMyRemote() && this.videos[0] && this.videos[0].video &&
+ this.videos[0].video.currentTime > 0 &&
+ this.videos[0].video.paused === false &&
+ this.videos[0].video.ended === false &&
+ this.videos[0].video.readyState === 4) {
+ this.emitEvent('remoteVideoPlaying', [new VideoElementEvent_1.VideoElementEvent(this.videos[0].video, this, 'remoteVideoPlaying')]);
+ }
+ }
+ if (type === 'accessAllowed') {
+ if (this.accessAllowed) {
+ this.emitEvent('accessAllowed', []);
+ }
+ }
+ if (type === 'accessDenied') {
+ if (this.accessDenied) {
+ this.emitEvent('accessDenied', []);
+ }
+ }
+ return this;
+ };
+ Publisher.prototype.once = function (type, handler) {
+ var _this = this;
+ _super.prototype.once.call(this, type, handler);
+ if (type === 'streamCreated') {
+ if (!!this.stream && this.stream.isLocalStreamPublished) {
+ this.emitEvent('streamCreated', [new StreamEvent_1.StreamEvent(false, this, 'streamCreated', this.stream, '')]);
+ }
+ else {
+ this.stream.ee.once('stream-created-by-publisher', function () {
+ _this.emitEvent('streamCreated', [new StreamEvent_1.StreamEvent(false, _this, 'streamCreated', _this.stream, '')]);
+ });
+ }
+ }
+ if (type === 'remoteVideoPlaying') {
+ if (this.stream.displayMyRemote() && this.videos[0] && this.videos[0].video &&
+ this.videos[0].video.currentTime > 0 &&
+ this.videos[0].video.paused === false &&
+ this.videos[0].video.ended === false &&
+ this.videos[0].video.readyState === 4) {
+ this.emitEvent('remoteVideoPlaying', [new VideoElementEvent_1.VideoElementEvent(this.videos[0].video, this, 'remoteVideoPlaying')]);
+ }
+ }
+ if (type === 'accessAllowed') {
+ if (this.accessAllowed) {
+ this.emitEvent('accessAllowed', []);
+ }
+ }
+ if (type === 'accessDenied') {
+ if (this.accessDenied) {
+ this.emitEvent('accessDenied', []);
+ }
+ }
+ return this;
+ };
+ Publisher.prototype.initialize = function () {
+ var _this = this;
+ return new Promise(function (resolve, reject) {
+ var errorCallback = function (openViduError) {
+ _this.accessDenied = true;
+ _this.accessAllowed = false;
+ reject(openViduError);
+ };
+ var successCallback = function (mediaStream) {
+ _this.accessAllowed = true;
+ _this.accessDenied = false;
+ if (_this.openvidu.isMediaStreamTrack(_this.properties.audioSource)) {
+ mediaStream.removeTrack(mediaStream.getAudioTracks()[0]);
+ mediaStream.addTrack(_this.properties.audioSource);
+ }
+ if (_this.openvidu.isMediaStreamTrack(_this.properties.videoSource)) {
+ mediaStream.removeTrack(mediaStream.getVideoTracks()[0]);
+ mediaStream.addTrack(_this.properties.videoSource);
+ }
+ if (!!mediaStream.getAudioTracks()[0]) {
+ var enabled = (_this.stream.audioActive !== undefined && _this.stream.audioActive !== null) ? _this.stream.audioActive : !!_this.stream.outboundStreamOpts.publisherProperties.publishAudio;
+ mediaStream.getAudioTracks()[0].enabled = enabled;
+ }
+ if (!!mediaStream.getVideoTracks()[0]) {
+ var enabled = (_this.stream.videoActive !== undefined && _this.stream.videoActive !== null) ? _this.stream.videoActive : !!_this.stream.outboundStreamOpts.publisherProperties.publishVideo;
+ mediaStream.getVideoTracks()[0].enabled = enabled;
+ }
+ _this.videoReference = document.createElement('video');
+ _this.videoReference.srcObject = mediaStream;
+ _this.stream.setMediaStream(mediaStream);
+ if (!_this.stream.displayMyRemote()) {
+ _this.stream.updateMediaStreamInVideos();
+ }
+ if (!!_this.firstVideoElement) {
+ _this.createVideoElement(_this.firstVideoElement.targetElement, _this.properties.insertMode);
+ }
+ delete _this.firstVideoElement;
+ if (_this.stream.isSendVideo()) {
+ if (!_this.stream.isSendScreen()) {
+ var _a = mediaStream.getVideoTracks()[0].getSettings(), width = _a.width, height = _a.height;
+ if (platform.name.toLowerCase().indexOf('mobile') !== -1 && (window.innerHeight > window.innerWidth)) {
+ _this.stream.videoDimensions = {
+ width: height || 0,
+ height: width || 0
+ };
+ }
+ else {
+ _this.stream.videoDimensions = {
+ width: width || 0,
+ height: height || 0
+ };
+ }
+ _this.stream.isLocalStreamReadyToPublish = true;
+ _this.stream.ee.emitEvent('stream-ready-to-publish', []);
+ }
+ else {
+ _this.videoReference.onloadedmetadata = function () {
+ _this.stream.videoDimensions = {
+ width: _this.videoReference.videoWidth,
+ height: _this.videoReference.videoHeight
+ };
+ _this.screenShareResizeInterval = setInterval(function () {
+ var firefoxSettings = mediaStream.getVideoTracks()[0].getSettings();
+ var newWidth = (platform.name === 'Chrome') ? _this.videoReference.videoWidth : firefoxSettings.width;
+ var newHeight = (platform.name === 'Chrome') ? _this.videoReference.videoHeight : firefoxSettings.height;
+ if (_this.stream.isLocalStreamPublished &&
+ (newWidth !== _this.stream.videoDimensions.width ||
+ newHeight !== _this.stream.videoDimensions.height)) {
+ var oldValue_1 = { width: _this.stream.videoDimensions.width, height: _this.stream.videoDimensions.height };
+ _this.stream.videoDimensions = {
+ width: newWidth || 0,
+ height: newHeight || 0
+ };
+ _this.session.openvidu.sendRequest('streamPropertyChanged', {
+ streamId: _this.stream.streamId,
+ property: 'videoDimensions',
+ newValue: JSON.stringify(_this.stream.videoDimensions),
+ reason: 'screenResized'
+ }, function (error, response) {
+ if (error) {
+ console.error("Error sending 'streamPropertyChanged' event", error);
+ }
+ else {
+ _this.session.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent_1.StreamPropertyChangedEvent(_this.session, _this.stream, 'videoDimensions', _this.stream.videoDimensions, oldValue_1, 'screenResized')]);
+ _this.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent_1.StreamPropertyChangedEvent(_this, _this.stream, 'videoDimensions', _this.stream.videoDimensions, oldValue_1, 'screenResized')]);
+ }
+ });
+ }
+ }, 500);
+ _this.stream.isLocalStreamReadyToPublish = true;
+ _this.stream.ee.emitEvent('stream-ready-to-publish', []);
+ };
+ }
+ }
+ else {
+ _this.stream.isLocalStreamReadyToPublish = true;
+ _this.stream.ee.emitEvent('stream-ready-to-publish', []);
+ }
+ resolve();
+ };
+ _this.openvidu.generateMediaConstraints(_this.properties)
+ .then(function (constraints) {
+ var outboundStreamOptions = {
+ mediaConstraints: constraints,
+ publisherProperties: _this.properties
+ };
+ _this.stream.setOutboundStreamOptions(outboundStreamOptions);
+ var constraintsAux = {};
+ var timeForDialogEvent = 1250;
+ if (_this.stream.isSendVideo() || _this.stream.isSendAudio()) {
+ var definedAudioConstraint_1 = ((constraints.audio === undefined) ? true : constraints.audio);
+ constraintsAux.audio = _this.stream.isSendScreen() ? false : definedAudioConstraint_1;
+ constraintsAux.video = constraints.video;
+ var startTime_1 = Date.now();
+ _this.setPermissionDialogTimer(timeForDialogEvent);
+ navigator.mediaDevices.getUserMedia(constraintsAux)
+ .then(function (mediaStream) {
+ _this.clearPermissionDialogTimer(startTime_1, timeForDialogEvent);
+ if (_this.stream.isSendScreen() && _this.stream.isSendAudio()) {
+ constraintsAux.audio = definedAudioConstraint_1;
+ constraintsAux.video = false;
+ startTime_1 = Date.now();
+ _this.setPermissionDialogTimer(timeForDialogEvent);
+ navigator.mediaDevices.getUserMedia(constraintsAux)
+ .then(function (audioOnlyStream) {
+ _this.clearPermissionDialogTimer(startTime_1, timeForDialogEvent);
+ mediaStream.addTrack(audioOnlyStream.getAudioTracks()[0]);
+ successCallback(mediaStream);
+ })
+ .catch(function (error) {
+ _this.clearPermissionDialogTimer(startTime_1, timeForDialogEvent);
+ var errorName, errorMessage;
+ switch (error.name.toLowerCase()) {
+ case 'notfounderror':
+ errorName = OpenViduError_1.OpenViduErrorName.INPUT_AUDIO_DEVICE_NOT_FOUND;
+ errorMessage = error.toString();
+ errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage));
+ break;
+ case 'notallowederror':
+ errorName = OpenViduError_1.OpenViduErrorName.DEVICE_ACCESS_DENIED;
+ errorMessage = error.toString();
+ errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage));
+ break;
+ case 'overconstrainederror':
+ if (error.constraint.toLowerCase() === 'deviceid') {
+ errorName = OpenViduError_1.OpenViduErrorName.INPUT_AUDIO_DEVICE_NOT_FOUND;
+ errorMessage = "Audio input device with deviceId '" + constraints.video.deviceId.exact + "' not found";
+ }
+ else {
+ errorName = OpenViduError_1.OpenViduErrorName.PUBLISHER_PROPERTIES_ERROR;
+ errorMessage = "Audio input device doesn't support the value passed for constraint '" + error.constraint + "'";
+ }
+ errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage));
+ break;
+ }
+ });
+ }
+ else {
+ successCallback(mediaStream);
+ }
+ })
+ .catch(function (error) {
+ _this.clearPermissionDialogTimer(startTime_1, timeForDialogEvent);
+ var errorName, errorMessage;
+ switch (error.name.toLowerCase()) {
+ case 'notfounderror':
+ navigator.mediaDevices.getUserMedia({
+ audio: false,
+ video: constraints.video
+ })
+ .then(function (mediaStream) {
+ mediaStream.getVideoTracks().forEach(function (track) {
+ track.stop();
+ });
+ errorName = OpenViduError_1.OpenViduErrorName.INPUT_AUDIO_DEVICE_NOT_FOUND;
+ errorMessage = error.toString();
+ errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage));
+ }).catch(function (e) {
+ errorName = OpenViduError_1.OpenViduErrorName.INPUT_VIDEO_DEVICE_NOT_FOUND;
+ errorMessage = error.toString();
+ errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage));
+ });
+ break;
+ case 'notallowederror':
+ errorName = _this.stream.isSendScreen() ? OpenViduError_1.OpenViduErrorName.SCREEN_CAPTURE_DENIED : OpenViduError_1.OpenViduErrorName.DEVICE_ACCESS_DENIED;
+ errorMessage = error.toString();
+ errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage));
+ break;
+ case 'overconstrainederror':
+ navigator.mediaDevices.getUserMedia({
+ audio: false,
+ video: constraints.video
+ })
+ .then(function (mediaStream) {
+ mediaStream.getVideoTracks().forEach(function (track) {
+ track.stop();
+ });
+ if (error.constraint.toLowerCase() === 'deviceid') {
+ errorName = OpenViduError_1.OpenViduErrorName.INPUT_AUDIO_DEVICE_NOT_FOUND;
+ errorMessage = "Audio input device with deviceId '" + constraints.audio.deviceId.exact + "' not found";
+ }
+ else {
+ errorName = OpenViduError_1.OpenViduErrorName.PUBLISHER_PROPERTIES_ERROR;
+ errorMessage = "Audio input device doesn't support the value passed for constraint '" + error.constraint + "'";
+ }
+ errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage));
+ }).catch(function (e) {
+ if (error.constraint.toLowerCase() === 'deviceid') {
+ errorName = OpenViduError_1.OpenViduErrorName.INPUT_VIDEO_DEVICE_NOT_FOUND;
+ errorMessage = "Video input device with deviceId '" + constraints.video.deviceId.exact + "' not found";
+ }
+ else {
+ errorName = OpenViduError_1.OpenViduErrorName.PUBLISHER_PROPERTIES_ERROR;
+ errorMessage = "Video input device doesn't support the value passed for constraint '" + error.constraint + "'";
+ }
+ errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage));
+ });
+ break;
+ }
+ });
+ }
+ else {
+ reject(new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.NO_INPUT_SOURCE_SET, "Properties 'audioSource' and 'videoSource' cannot be set to false or null at the same time when calling 'OpenVidu.initPublisher'"));
+ }
+ })
+ .catch(function (error) {
+ errorCallback(error);
+ });
+ });
+ };
+ Publisher.prototype.reestablishStreamPlayingEvent = function () {
+ if (this.ee.getListeners('streamPlaying').length > 0) {
+ this.addPlayEventToFirstVideo();
+ }
+ };
+ Publisher.prototype.setPermissionDialogTimer = function (waitTime) {
+ var _this = this;
+ this.permissionDialogTimeout = setTimeout(function () {
+ _this.emitEvent('accessDialogOpened', []);
+ }, waitTime);
+ };
+ Publisher.prototype.clearPermissionDialogTimer = function (startTime, waitTime) {
+ clearTimeout(this.permissionDialogTimeout);
+ if ((Date.now() - startTime) > waitTime) {
+ this.emitEvent('accessDialogClosed', []);
+ }
+ };
+ return Publisher;
+}(StreamManager_1.StreamManager));
+exports.Publisher = Publisher;
+
+},{"../OpenViduInternal/Enums/OpenViduError":26,"../OpenViduInternal/Events/StreamEvent":34,"../OpenViduInternal/Events/StreamPropertyChangedEvent":36,"../OpenViduInternal/Events/VideoElementEvent":37,"./Session":21,"./Stream":22,"./StreamManager":23,"platform":8}],21:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+var Connection_1 = require("./Connection");
+var Subscriber_1 = require("./Subscriber");
+var ConnectionEvent_1 = require("../OpenViduInternal/Events/ConnectionEvent");
+var RecordingEvent_1 = require("../OpenViduInternal/Events/RecordingEvent");
+var SessionDisconnectedEvent_1 = require("../OpenViduInternal/Events/SessionDisconnectedEvent");
+var SignalEvent_1 = require("../OpenViduInternal/Events/SignalEvent");
+var StreamEvent_1 = require("../OpenViduInternal/Events/StreamEvent");
+var StreamPropertyChangedEvent_1 = require("../OpenViduInternal/Events/StreamPropertyChangedEvent");
+var OpenViduError_1 = require("../OpenViduInternal/Enums/OpenViduError");
+var VideoInsertMode_1 = require("../OpenViduInternal/Enums/VideoInsertMode");
+var platform = require("platform");
+var EventEmitter = require("wolfy87-eventemitter");
+var Session = (function () {
+ function Session(openvidu) {
+ this.streamManagers = [];
+ this.remoteStreamsCreated = {};
+ this.remoteConnections = {};
+ this.speakingEventsEnabled = false;
+ this.ee = new EventEmitter();
+ this.openvidu = openvidu;
+ }
+ Session.prototype.connect = function (token, metadata) {
+ var _this = this;
+ return new Promise(function (resolve, reject) {
+ _this.processToken(token);
+ if (_this.openvidu.checkSystemRequirements()) {
+ _this.options = {
+ sessionId: _this.sessionId,
+ participantId: token,
+ metadata: !!metadata ? _this.stringClientMetadata(metadata) : ''
+ };
+ _this.connectAux(token).then(function () {
+ resolve();
+ }).catch(function (error) {
+ reject(error);
+ });
+ }
+ else {
+ reject(new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.BROWSER_NOT_SUPPORTED, 'Browser ' + platform.name + ' ' + platform.version + ' is not supported in OpenVidu'));
+ }
+ });
+ };
+ Session.prototype.disconnect = function () {
+ this.leave(false, 'disconnect');
+ };
+ Session.prototype.subscribe = function (stream, targetElement, param3, param4) {
+ var properties = {};
+ if (!!param3 && typeof param3 !== 'function') {
+ properties = {
+ insertMode: (typeof param3.insertMode !== 'undefined') ? ((typeof param3.insertMode === 'string') ? VideoInsertMode_1.VideoInsertMode[param3.insertMode] : properties.insertMode) : VideoInsertMode_1.VideoInsertMode.APPEND,
+ subscribeToAudio: (typeof param3.subscribeToAudio !== 'undefined') ? param3.subscribeToAudio : true,
+ subscribeToVideo: (typeof param3.subscribeToVideo !== 'undefined') ? param3.subscribeToVideo : true
+ };
+ }
+ else {
+ properties = {
+ insertMode: VideoInsertMode_1.VideoInsertMode.APPEND,
+ subscribeToAudio: true,
+ subscribeToVideo: true
+ };
+ }
+ var completionHandler;
+ if (!!param3 && (typeof param3 === 'function')) {
+ completionHandler = param3;
+ }
+ else if (!!param4) {
+ completionHandler = param4;
+ }
+ console.info('Subscribing to ' + stream.connection.connectionId);
+ stream.subscribe()
+ .then(function () {
+ console.info('Subscribed correctly to ' + stream.connection.connectionId);
+ if (completionHandler !== undefined) {
+ completionHandler(undefined);
+ }
+ })
+ .catch(function (error) {
+ if (completionHandler !== undefined) {
+ completionHandler(error);
+ }
+ });
+ var subscriber = new Subscriber_1.Subscriber(stream, targetElement, properties);
+ if (!!subscriber.targetElement) {
+ stream.streamManager.createVideoElement(subscriber.targetElement, properties.insertMode);
+ }
+ return subscriber;
+ };
+ Session.prototype.subscribeAsync = function (stream, targetElement, properties) {
+ var _this = this;
+ return new Promise(function (resolve, reject) {
+ var subscriber;
+ var callback = function (error) {
+ if (!!error) {
+ reject(error);
+ }
+ else {
+ resolve(subscriber);
+ }
+ };
+ if (!!properties) {
+ subscriber = _this.subscribe(stream, targetElement, properties, callback);
+ }
+ else {
+ subscriber = _this.subscribe(stream, targetElement, callback);
+ }
+ });
+ };
+ Session.prototype.unsubscribe = function (subscriber) {
+ var connectionId = subscriber.stream.connection.connectionId;
+ console.info('Unsubscribing from ' + connectionId);
+ this.openvidu.sendRequest('unsubscribeFromVideo', { sender: subscriber.stream.connection.connectionId }, function (error, response) {
+ if (error) {
+ console.error('Error unsubscribing from ' + connectionId, error);
+ }
+ else {
+ console.info('Unsubscribed correctly from ' + connectionId);
+ }
+ subscriber.stream.disposeWebRtcPeer();
+ subscriber.stream.disposeMediaStream();
+ });
+ subscriber.stream.streamManager.removeAllVideos();
+ };
+ Session.prototype.publish = function (publisher) {
+ var _this = this;
+ return new Promise(function (resolve, reject) {
+ publisher.session = _this;
+ publisher.stream.session = _this;
+ if (!publisher.stream.publishedOnce) {
+ _this.connection.addStream(publisher.stream);
+ publisher.stream.publish()
+ .then(function () {
+ resolve();
+ })
+ .catch(function (error) {
+ reject(error);
+ });
+ }
+ else {
+ publisher.initialize()
+ .then(function () {
+ _this.connection.addStream(publisher.stream);
+ publisher.reestablishStreamPlayingEvent();
+ publisher.stream.publish()
+ .then(function () {
+ resolve();
+ })
+ .catch(function (error) {
+ reject(error);
+ });
+ }).catch(function (error) {
+ reject(error);
+ });
+ }
+ });
+ };
+ Session.prototype.unpublish = function (publisher) {
+ var stream = publisher.stream;
+ if (!stream.connection) {
+ console.error('The associated Connection object of this Publisher is null', stream);
+ return;
+ }
+ else if (stream.connection !== this.connection) {
+ console.error('The associated Connection object of this Publisher is not your local Connection.' +
+ "Only moderators can force unpublish on remote Streams via 'forceUnpublish' method", stream);
+ return;
+ }
+ else {
+ console.info('Unpublishing local media (' + stream.connection.connectionId + ')');
+ this.openvidu.sendRequest('unpublishVideo', function (error, response) {
+ if (error) {
+ console.error(error);
+ }
+ else {
+ console.info('Media unpublished correctly');
+ }
+ });
+ stream.disposeWebRtcPeer();
+ delete stream.connection.stream;
+ var streamEvent = new StreamEvent_1.StreamEvent(true, publisher, 'streamDestroyed', publisher.stream, 'unpublish');
+ publisher.emitEvent('streamDestroyed', [streamEvent]);
+ streamEvent.callDefaultBehavior();
+ }
+ };
+ Session.prototype.forceDisconnect = function (connection) {
+ var _this = this;
+ return new Promise(function (resolve, reject) {
+ console.info('Forcing disconnect for connection ' + connection.connectionId);
+ _this.openvidu.sendRequest('forceDisconnect', { connectionId: connection.connectionId }, function (error, response) {
+ if (error) {
+ console.error('Error forcing disconnect for Connection ' + connection.connectionId, error);
+ if (error.code === 401) {
+ reject(new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.OPENVIDU_PERMISSION_DENIED, "You don't have permissions to force a disconnection"));
+ }
+ else {
+ reject(error);
+ }
+ }
+ else {
+ console.info('Forcing disconnect correctly for Connection ' + connection.connectionId);
+ resolve();
+ }
+ });
+ });
+ };
+ Session.prototype.forceUnpublish = function (stream) {
+ var _this = this;
+ return new Promise(function (resolve, reject) {
+ console.info('Forcing unpublish for stream ' + stream.streamId);
+ _this.openvidu.sendRequest('forceUnpublish', { streamId: stream.streamId }, function (error, response) {
+ if (error) {
+ console.error('Error forcing unpublish for Stream ' + stream.streamId, error);
+ if (error.code === 401) {
+ reject(new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.OPENVIDU_PERMISSION_DENIED, "You don't have permissions to force an unpublishing"));
+ }
+ else {
+ reject(error);
+ }
+ }
+ else {
+ console.info('Forcing unpublish correctly for Stream ' + stream.streamId);
+ resolve();
+ }
+ });
+ });
+ };
+ Session.prototype.signal = function (signal) {
+ var _this = this;
+ return new Promise(function (resolve, reject) {
+ var signalMessage = {};
+ if (signal.to && signal.to.length > 0) {
+ var connectionIds_1 = [];
+ signal.to.forEach(function (connection) {
+ connectionIds_1.push(connection.connectionId);
+ });
+ signalMessage['to'] = connectionIds_1;
+ }
+ else {
+ signalMessage['to'] = [];
+ }
+ signalMessage['data'] = signal.data ? signal.data : '';
+ signalMessage['type'] = signal.type ? signal.type : '';
+ _this.openvidu.sendRequest('sendMessage', {
+ message: JSON.stringify(signalMessage)
+ }, function (error, response) {
+ if (!!error) {
+ reject(error);
+ }
+ else {
+ resolve();
+ }
+ });
+ });
+ };
+ Session.prototype.on = function (type, handler) {
+ this.ee.on(type, function (event) {
+ if (event) {
+ console.info("Event '" + type + "' triggered by 'Session'", event);
+ }
+ else {
+ console.info("Event '" + type + "' triggered by 'Session'");
+ }
+ handler(event);
+ });
+ if (type === 'publisherStartSpeaking' || type === 'publisherStopSpeaking') {
+ this.speakingEventsEnabled = true;
+ for (var connectionId in this.remoteConnections) {
+ var str = this.remoteConnections[connectionId].stream;
+ if (!!str && !str.speechEvent && str.hasAudio) {
+ str.enableSpeakingEvents();
+ }
+ }
+ }
+ return this;
+ };
+ Session.prototype.once = function (type, handler) {
+ this.ee.once(type, function (event) {
+ if (event) {
+ console.info("Event '" + type + "' triggered by 'Session'", event);
+ }
+ else {
+ console.info("Event '" + type + "' triggered by 'Session'");
+ }
+ handler(event);
+ });
+ if (type === 'publisherStartSpeaking' || type === 'publisherStopSpeaking') {
+ this.speakingEventsEnabled = true;
+ for (var connectionId in this.remoteConnections) {
+ var str = this.remoteConnections[connectionId].stream;
+ if (!!str && !str.speechEvent && str.hasAudio) {
+ str.enableOnceSpeakingEvents();
+ }
+ }
+ }
+ return this;
+ };
+ Session.prototype.off = function (type, handler) {
+ if (!handler) {
+ this.ee.removeAllListeners(type);
+ }
+ else {
+ this.ee.off(type, handler);
+ }
+ if (type === 'publisherStartSpeaking' || type === 'publisherStopSpeaking') {
+ this.speakingEventsEnabled = false;
+ for (var connectionId in this.remoteConnections) {
+ var str = this.remoteConnections[connectionId].stream;
+ if (!!str && !!str.speechEvent) {
+ str.disableSpeakingEvents();
+ }
+ }
+ }
+ return this;
+ };
+ Session.prototype.onParticipantJoined = function (response) {
+ var _this = this;
+ this.getConnection(response.id, '')
+ .then(function (connection) {
+ console.warn('Connection ' + response.id + ' already exists in connections list');
+ })
+ .catch(function (openViduError) {
+ var connection = new Connection_1.Connection(_this, response);
+ _this.remoteConnections[response.id] = connection;
+ _this.ee.emitEvent('connectionCreated', [new ConnectionEvent_1.ConnectionEvent(false, _this, 'connectionCreated', connection, '')]);
+ });
+ };
+ Session.prototype.onParticipantLeft = function (msg) {
+ var _this = this;
+ this.getRemoteConnection(msg.connectionId, 'Remote connection ' + msg.connectionId + " unknown when 'onParticipantLeft'. " +
+ 'Existing remote connections: ' + JSON.stringify(Object.keys(this.remoteConnections)))
+ .then(function (connection) {
+ if (!!connection.stream) {
+ var stream = connection.stream;
+ var streamEvent = new StreamEvent_1.StreamEvent(true, _this, 'streamDestroyed', stream, msg.reason);
+ _this.ee.emitEvent('streamDestroyed', [streamEvent]);
+ streamEvent.callDefaultBehavior();
+ delete _this.remoteStreamsCreated[stream.streamId];
+ }
+ delete _this.remoteConnections[connection.connectionId];
+ _this.ee.emitEvent('connectionDestroyed', [new ConnectionEvent_1.ConnectionEvent(false, _this, 'connectionDestroyed', connection, msg.reason)]);
+ })
+ .catch(function (openViduError) {
+ console.error(openViduError);
+ });
+ };
+ Session.prototype.onParticipantPublished = function (response) {
+ var _this = this;
+ var afterConnectionFound = function (connection) {
+ _this.remoteConnections[connection.connectionId] = connection;
+ if (!_this.remoteStreamsCreated[connection.stream.streamId]) {
+ _this.ee.emitEvent('streamCreated', [new StreamEvent_1.StreamEvent(false, _this, 'streamCreated', connection.stream, '')]);
+ }
+ _this.remoteStreamsCreated[connection.stream.streamId] = true;
+ };
+ var connection;
+ this.getRemoteConnection(response.id, "Remote connection '" + response.id + "' unknown when 'onParticipantPublished'. " +
+ 'Existing remote connections: ' + JSON.stringify(Object.keys(this.remoteConnections)))
+ .then(function (con) {
+ connection = con;
+ response.metadata = con.data;
+ connection.options = response;
+ connection.initRemoteStreams(response.streams);
+ afterConnectionFound(connection);
+ })
+ .catch(function (openViduError) {
+ connection = new Connection_1.Connection(_this, response);
+ afterConnectionFound(connection);
+ });
+ };
+ Session.prototype.onParticipantUnpublished = function (msg) {
+ var _this = this;
+ if (msg.connectionId === this.connection.connectionId) {
+ this.stopPublisherStream(msg.reason);
+ }
+ else {
+ this.getRemoteConnection(msg.connectionId, "Remote connection '" + msg.connectionId + "' unknown when 'onParticipantUnpublished'. " +
+ 'Existing remote connections: ' + JSON.stringify(Object.keys(this.remoteConnections)))
+ .then(function (connection) {
+ var streamEvent = new StreamEvent_1.StreamEvent(true, _this, 'streamDestroyed', connection.stream, msg.reason);
+ _this.ee.emitEvent('streamDestroyed', [streamEvent]);
+ streamEvent.callDefaultBehavior();
+ var streamId = connection.stream.streamId;
+ delete _this.remoteStreamsCreated[streamId];
+ connection.removeStream(streamId);
+ })
+ .catch(function (openViduError) {
+ console.error(openViduError);
+ });
+ }
+ };
+ Session.prototype.onParticipantEvicted = function (msg) {
+ if (msg.connectionId === this.connection.connectionId) {
+ if (!!this.sessionId && !this.connection.disposed) {
+ this.leave(true, msg.reason);
+ }
+ }
+ };
+ Session.prototype.onNewMessage = function (msg) {
+ var _this = this;
+ console.info('New signal: ' + JSON.stringify(msg));
+ this.getConnection(msg.from, "Connection '" + msg.from + "' unknow when 'onNewMessage'. Existing remote connections: "
+ + JSON.stringify(Object.keys(this.remoteConnections)) + '. Existing local connection: ' + this.connection.connectionId)
+ .then(function (connection) {
+ _this.ee.emitEvent('signal', [new SignalEvent_1.SignalEvent(_this, msg.type, msg.data, connection)]);
+ _this.ee.emitEvent('signal:' + msg.type, [new SignalEvent_1.SignalEvent(_this, msg.type, msg.data, connection)]);
+ })
+ .catch(function (openViduError) {
+ console.error(openViduError);
+ });
+ };
+ Session.prototype.onStreamPropertyChanged = function (msg) {
+ var _this = this;
+ this.getRemoteConnection(msg.connectionId, 'Remote connection ' + msg.connectionId + " unknown when 'onStreamPropertyChanged'. " +
+ 'Existing remote connections: ' + JSON.stringify(Object.keys(this.remoteConnections)))
+ .then(function (connection) {
+ if (!!connection.stream && connection.stream.streamId === msg.streamId) {
+ var stream = connection.stream;
+ var oldValue = void 0;
+ switch (msg.property) {
+ case 'audioActive':
+ oldValue = stream.audioActive;
+ msg.newValue = msg.newValue === 'true';
+ stream.audioActive = msg.newValue;
+ break;
+ case 'videoActive':
+ oldValue = stream.videoActive;
+ msg.newValue = msg.newValue === 'true';
+ stream.videoActive = msg.newValue;
+ break;
+ case 'videoDimensions':
+ oldValue = stream.videoDimensions;
+ msg.newValue = JSON.parse(JSON.parse(msg.newValue));
+ stream.videoDimensions = msg.newValue;
+ break;
+ }
+ _this.ee.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent_1.StreamPropertyChangedEvent(_this, stream, msg.property, msg.newValue, oldValue, msg.reason)]);
+ stream.streamManager.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent_1.StreamPropertyChangedEvent(stream.streamManager, stream, msg.property, msg.newValue, oldValue, msg.reason)]);
+ }
+ else {
+ console.error("No stream with streamId '" + msg.streamId + "' found for connection '" + msg.connectionId + "' on 'streamPropertyChanged' event");
+ }
+ })
+ .catch(function (openViduError) {
+ console.error(openViduError);
+ });
+ };
+ Session.prototype.recvIceCandidate = function (msg) {
+ var candidate = {
+ candidate: msg.candidate,
+ sdpMid: msg.sdpMid,
+ sdpMLineIndex: msg.sdpMLineIndex,
+ toJSON: function () {
+ return { candidate: msg.candidate };
+ }
+ };
+ this.getConnection(msg.endpointName, 'Connection not found for endpoint ' + msg.endpointName + '. Ice candidate will be ignored: ' + candidate)
+ .then(function (connection) {
+ var stream = connection.stream;
+ stream.getWebRtcPeer().addIceCandidate(candidate).catch(function (error) {
+ console.error('Error adding candidate for ' + stream.streamId
+ + ' stream of endpoint ' + msg.endpointName + ': ' + error);
+ });
+ })
+ .catch(function (openViduError) {
+ console.error(openViduError);
+ });
+ };
+ Session.prototype.onSessionClosed = function (msg) {
+ console.info('Session closed: ' + JSON.stringify(msg));
+ var s = msg.sessionId;
+ if (s !== undefined) {
+ this.ee.emitEvent('session-closed', [{
+ session: s
+ }]);
+ }
+ else {
+ console.warn('Session undefined on session closed', msg);
+ }
+ };
+ Session.prototype.onLostConnection = function () {
+ console.warn('Lost connection in Session ' + this.sessionId);
+ if (!!this.sessionId && !this.connection.disposed) {
+ this.leave(true, 'networkDisconnect');
+ }
+ };
+ Session.prototype.onRecoveredConnection = function () {
+ console.warn('Recovered connection in Session ' + this.sessionId);
+ this.ee.emitEvent('connectionRecovered', []);
+ };
+ Session.prototype.onMediaError = function (params) {
+ console.error('Media error: ' + JSON.stringify(params));
+ var err = params.error;
+ if (err) {
+ this.ee.emitEvent('error-media', [{
+ error: err
+ }]);
+ }
+ else {
+ console.warn('Received undefined media error. Params:', params);
+ }
+ };
+ Session.prototype.onRecordingStarted = function (response) {
+ this.ee.emitEvent('recordingStarted', [new RecordingEvent_1.RecordingEvent(this, 'recordingStarted', response.id, response.name)]);
+ };
+ Session.prototype.onRecordingStopped = function (response) {
+ this.ee.emitEvent('recordingStopped', [new RecordingEvent_1.RecordingEvent(this, 'recordingStopped', response.id, response.name)]);
+ };
+ Session.prototype.emitEvent = function (type, eventArray) {
+ this.ee.emitEvent(type, eventArray);
+ };
+ Session.prototype.leave = function (forced, reason) {
+ var _this = this;
+ forced = !!forced;
+ console.info('Leaving Session (forced=' + forced + ')');
+ if (!!this.connection) {
+ if (!this.connection.disposed && !forced) {
+ this.openvidu.sendRequest('leaveRoom', function (error, response) {
+ if (error) {
+ console.error(error);
+ }
+ _this.openvidu.closeWs();
+ });
+ }
+ else {
+ this.openvidu.closeWs();
+ }
+ this.stopPublisherStream(reason);
+ if (!this.connection.disposed) {
+ var sessionDisconnectEvent = new SessionDisconnectedEvent_1.SessionDisconnectedEvent(this, reason);
+ this.ee.emitEvent('sessionDisconnected', [sessionDisconnectEvent]);
+ sessionDisconnectEvent.callDefaultBehavior();
+ }
+ }
+ else {
+ console.warn('You were not connected to the session ' + this.sessionId);
+ }
+ };
+ Session.prototype.connectAux = function (token) {
+ var _this = this;
+ return new Promise(function (resolve, reject) {
+ _this.openvidu.startWs(function (error) {
+ if (!!error) {
+ reject(error);
+ }
+ else {
+ var joinParams = {
+ token: (!!token) ? token : '',
+ session: _this.sessionId,
+ metadata: !!_this.options.metadata ? _this.options.metadata : '',
+ secret: _this.openvidu.getSecret(),
+ recorder: _this.openvidu.getRecorder(),
+ };
+ _this.openvidu.sendRequest('joinRoom', joinParams, function (error, response) {
+ if (!!error) {
+ reject(error);
+ }
+ else {
+ _this.capabilities = {
+ subscribe: true,
+ publish: _this.openvidu.role !== 'SUBSCRIBER',
+ forceUnpublish: _this.openvidu.role === 'MODERATOR',
+ forceDisconnect: _this.openvidu.role === 'MODERATOR'
+ };
+ _this.connection = new Connection_1.Connection(_this);
+ _this.connection.connectionId = response.id;
+ _this.connection.data = response.metadata;
+ var events_1 = {
+ connections: new Array(),
+ streams: new Array()
+ };
+ var existingParticipants = response.value;
+ existingParticipants.forEach(function (participant) {
+ var connection = new Connection_1.Connection(_this, participant);
+ _this.remoteConnections[connection.connectionId] = connection;
+ events_1.connections.push(connection);
+ if (!!connection.stream) {
+ _this.remoteStreamsCreated[connection.stream.streamId] = true;
+ events_1.streams.push(connection.stream);
+ }
+ });
+ _this.ee.emitEvent('connectionCreated', [new ConnectionEvent_1.ConnectionEvent(false, _this, 'connectionCreated', _this.connection, '')]);
+ events_1.connections.forEach(function (connection) {
+ _this.ee.emitEvent('connectionCreated', [new ConnectionEvent_1.ConnectionEvent(false, _this, 'connectionCreated', connection, '')]);
+ });
+ events_1.streams.forEach(function (stream) {
+ _this.ee.emitEvent('streamCreated', [new StreamEvent_1.StreamEvent(false, _this, 'streamCreated', stream, '')]);
+ });
+ resolve();
+ }
+ });
+ }
+ });
+ });
+ };
+ Session.prototype.stopPublisherStream = function (reason) {
+ if (!!this.connection.stream) {
+ this.connection.stream.disposeWebRtcPeer();
+ if (this.connection.stream.isLocalStreamPublished) {
+ this.connection.stream.ee.emitEvent('local-stream-destroyed', [reason]);
+ }
+ }
+ };
+ Session.prototype.stringClientMetadata = function (metadata) {
+ if (typeof metadata !== 'string') {
+ return JSON.stringify(metadata);
+ }
+ else {
+ return metadata;
+ }
+ };
+ Session.prototype.getConnection = function (connectionId, errorMessage) {
+ var _this = this;
+ return new Promise(function (resolve, reject) {
+ var connection = _this.remoteConnections[connectionId];
+ if (!!connection) {
+ resolve(connection);
+ }
+ else {
+ if (_this.connection.connectionId === connectionId) {
+ resolve(_this.connection);
+ }
+ else {
+ reject(new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.GENERIC_ERROR, errorMessage));
+ }
+ }
+ });
+ };
+ Session.prototype.getRemoteConnection = function (connectionId, errorMessage) {
+ var _this = this;
+ return new Promise(function (resolve, reject) {
+ var connection = _this.remoteConnections[connectionId];
+ if (!!connection) {
+ resolve(connection);
+ }
+ else {
+ reject(new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.GENERIC_ERROR, errorMessage));
+ }
+ });
+ };
+ Session.prototype.processToken = function (token) {
+ var url = new URL(token);
+ this.sessionId = url.searchParams.get('sessionId');
+ var secret = url.searchParams.get('secret');
+ var recorder = url.searchParams.get('recorder');
+ var turnUsername = url.searchParams.get('turnUsername');
+ var turnCredential = url.searchParams.get('turnCredential');
+ var role = url.searchParams.get('role');
+ if (!!secret) {
+ this.openvidu.secret = secret;
+ }
+ if (!!recorder) {
+ this.openvidu.recorder = true;
+ }
+ if (!!turnUsername && !!turnCredential) {
+ var stunUrl = 'stun:' + url.hostname + ':3478';
+ var turnUrl1 = 'turn:' + url.hostname + ':3478';
+ var turnUrl2 = turnUrl1 + '?transport=tcp';
+ this.openvidu.iceServers = [
+ { urls: [stunUrl] },
+ { urls: [turnUrl1, turnUrl2], username: turnUsername, credential: turnCredential }
+ ];
+ console.log('TURN temp credentials [' + turnUsername + ':' + turnCredential + ']');
+ }
+ if (!!role) {
+ this.openvidu.role = role;
+ }
+ this.openvidu.wsUri = 'wss://' + url.host + '/openvidu';
+ };
+ return Session;
+}());
+exports.Session = Session;
+
+},{"../OpenViduInternal/Enums/OpenViduError":26,"../OpenViduInternal/Enums/VideoInsertMode":27,"../OpenViduInternal/Events/ConnectionEvent":28,"../OpenViduInternal/Events/RecordingEvent":31,"../OpenViduInternal/Events/SessionDisconnectedEvent":32,"../OpenViduInternal/Events/SignalEvent":33,"../OpenViduInternal/Events/StreamEvent":34,"../OpenViduInternal/Events/StreamPropertyChangedEvent":36,"./Connection":17,"./Subscriber":24,"platform":8,"wolfy87-eventemitter":15}],22:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+var WebRtcPeer_1 = require("../OpenViduInternal/WebRtcPeer/WebRtcPeer");
+var WebRtcStats_1 = require("../OpenViduInternal/WebRtcStats/WebRtcStats");
+var PublisherSpeakingEvent_1 = require("../OpenViduInternal/Events/PublisherSpeakingEvent");
+var EventEmitter = require("wolfy87-eventemitter");
+var hark = require("hark");
+var OpenViduError_1 = require("../OpenViduInternal/Enums/OpenViduError");
+var Stream = (function () {
+ function Stream(session, options) {
+ var _this = this;
+ this.ee = new EventEmitter();
+ this.isSubscribeToRemote = false;
+ this.isLocalStreamReadyToPublish = false;
+ this.isLocalStreamPublished = false;
+ this.publishedOnce = false;
+ this.session = session;
+ if (options.hasOwnProperty('id')) {
+ this.inboundStreamOpts = options;
+ this.streamId = this.inboundStreamOpts.id;
+ this.hasAudio = this.inboundStreamOpts.hasAudio;
+ this.hasVideo = this.inboundStreamOpts.hasVideo;
+ if (this.hasAudio) {
+ this.audioActive = this.inboundStreamOpts.audioActive;
+ }
+ if (this.hasVideo) {
+ this.videoActive = this.inboundStreamOpts.videoActive;
+ this.typeOfVideo = (!this.inboundStreamOpts.typeOfVideo) ? undefined : this.inboundStreamOpts.typeOfVideo;
+ this.frameRate = (this.inboundStreamOpts.frameRate === -1) ? undefined : this.inboundStreamOpts.frameRate;
+ this.videoDimensions = this.inboundStreamOpts.videoDimensions;
+ }
+ }
+ else {
+ this.outboundStreamOpts = options;
+ this.hasAudio = this.isSendAudio();
+ this.hasVideo = this.isSendVideo();
+ if (this.hasAudio) {
+ this.audioActive = !!this.outboundStreamOpts.publisherProperties.publishAudio;
+ }
+ if (this.hasVideo) {
+ this.videoActive = !!this.outboundStreamOpts.publisherProperties.publishVideo;
+ this.frameRate = this.outboundStreamOpts.publisherProperties.frameRate;
+ if (this.outboundStreamOpts.publisherProperties.videoSource instanceof MediaStreamTrack) {
+ this.typeOfVideo = 'CUSTOM';
+ }
+ else {
+ this.typeOfVideo = this.isSendScreen() ? 'SCREEN' : 'CAMERA';
+ }
+ }
+ }
+ this.ee.on('mediastream-updated', function () {
+ _this.streamManager.updateMediaStream(_this.mediaStream);
+ console.debug('Video srcObject [' + _this.mediaStream + '] updated in stream [' + _this.streamId + ']');
+ });
+ }
+ Stream.prototype.getMediaStream = function () {
+ return this.mediaStream;
+ };
+ Stream.prototype.setMediaStream = function (mediaStream) {
+ this.mediaStream = mediaStream;
+ };
+ Stream.prototype.updateMediaStreamInVideos = function () {
+ this.ee.emitEvent('mediastream-updated');
+ };
+ Stream.prototype.getWebRtcPeer = function () {
+ return this.webRtcPeer;
+ };
+ Stream.prototype.getRTCPeerConnection = function () {
+ return this.webRtcPeer.pc;
+ };
+ Stream.prototype.subscribeToMyRemote = function (value) {
+ this.isSubscribeToRemote = value;
+ };
+ Stream.prototype.setOutboundStreamOptions = function (outboundStreamOpts) {
+ this.outboundStreamOpts = outboundStreamOpts;
+ };
+ Stream.prototype.subscribe = function () {
+ var _this = this;
+ return new Promise(function (resolve, reject) {
+ _this.initWebRtcPeerReceive()
+ .then(function () {
+ resolve();
+ })
+ .catch(function (error) {
+ reject(error);
+ });
+ });
+ };
+ Stream.prototype.publish = function () {
+ var _this = this;
+ return new Promise(function (resolve, reject) {
+ if (_this.isLocalStreamReadyToPublish) {
+ _this.initWebRtcPeerSend()
+ .then(function () {
+ resolve();
+ })
+ .catch(function (error) {
+ reject(error);
+ });
+ }
+ else {
+ _this.ee.once('stream-ready-to-publish', function () {
+ _this.publish()
+ .then(function () {
+ resolve();
+ })
+ .catch(function (error) {
+ reject(error);
+ });
+ });
+ }
+ });
+ };
+ Stream.prototype.disposeWebRtcPeer = function () {
+ if (this.webRtcPeer) {
+ this.webRtcPeer.dispose();
+ }
+ if (this.speechEvent) {
+ this.speechEvent.stop();
+ }
+ this.stopWebRtcStats();
+ console.info((!!this.outboundStreamOpts ? 'Outbound ' : 'Inbound ') + "WebRTCPeer from 'Stream' with id [" + this.streamId + '] is now closed');
+ };
+ Stream.prototype.disposeMediaStream = function () {
+ if (this.mediaStream) {
+ this.mediaStream.getAudioTracks().forEach(function (track) {
+ track.stop();
+ });
+ this.mediaStream.getVideoTracks().forEach(function (track) {
+ track.stop();
+ });
+ delete this.mediaStream;
+ }
+ console.info((!!this.outboundStreamOpts ? 'Local ' : 'Remote ') + "MediaStream from 'Stream' with id [" + this.streamId + '] is now disposed');
+ };
+ Stream.prototype.displayMyRemote = function () {
+ return this.isSubscribeToRemote;
+ };
+ Stream.prototype.isSendAudio = function () {
+ return (!!this.outboundStreamOpts &&
+ this.outboundStreamOpts.publisherProperties.audioSource !== null &&
+ this.outboundStreamOpts.publisherProperties.audioSource !== false);
+ };
+ Stream.prototype.isSendVideo = function () {
+ return (!!this.outboundStreamOpts &&
+ this.outboundStreamOpts.publisherProperties.videoSource !== null &&
+ this.outboundStreamOpts.publisherProperties.videoSource !== false);
+ };
+ Stream.prototype.isSendScreen = function () {
+ return (!!this.outboundStreamOpts &&
+ this.outboundStreamOpts.publisherProperties.videoSource === 'screen');
+ };
+ Stream.prototype.setSpeechEventIfNotExists = function () {
+ if (!this.speechEvent) {
+ var harkOptions = this.session.openvidu.advancedConfiguration.publisherSpeakingEventsOptions || {};
+ harkOptions.interval = (typeof harkOptions.interval === 'number') ? harkOptions.interval : 50;
+ harkOptions.threshold = (typeof harkOptions.threshold === 'number') ? harkOptions.threshold : -50;
+ this.speechEvent = hark(this.mediaStream, harkOptions);
+ }
+ };
+ Stream.prototype.enableSpeakingEvents = function () {
+ var _this = this;
+ this.setSpeechEventIfNotExists();
+ this.speechEvent.on('speaking', function () {
+ _this.session.emitEvent('publisherStartSpeaking', [new PublisherSpeakingEvent_1.PublisherSpeakingEvent(_this.session, 'publisherStartSpeaking', _this.connection, _this.streamId)]);
+ });
+ this.speechEvent.on('stopped_speaking', function () {
+ _this.session.emitEvent('publisherStopSpeaking', [new PublisherSpeakingEvent_1.PublisherSpeakingEvent(_this.session, 'publisherStopSpeaking', _this.connection, _this.streamId)]);
+ });
+ };
+ Stream.prototype.enableOnceSpeakingEvents = function () {
+ var _this = this;
+ this.setSpeechEventIfNotExists();
+ this.speechEvent.on('speaking', function () {
+ _this.session.emitEvent('publisherStartSpeaking', [new PublisherSpeakingEvent_1.PublisherSpeakingEvent(_this.session, 'publisherStartSpeaking', _this.connection, _this.streamId)]);
+ _this.disableSpeakingEvents();
+ });
+ this.speechEvent.on('stopped_speaking', function () {
+ _this.session.emitEvent('publisherStopSpeaking', [new PublisherSpeakingEvent_1.PublisherSpeakingEvent(_this.session, 'publisherStopSpeaking', _this.connection, _this.streamId)]);
+ _this.disableSpeakingEvents();
+ });
+ };
+ Stream.prototype.disableSpeakingEvents = function () {
+ this.speechEvent.stop();
+ this.speechEvent = undefined;
+ };
+ Stream.prototype.isLocal = function () {
+ return (!this.inboundStreamOpts && !!this.outboundStreamOpts);
+ };
+ Stream.prototype.getSelectedIceCandidate = function () {
+ var _this = this;
+ return new Promise(function (resolve, reject) {
+ _this.webRtcStats.getSelectedIceCandidateInfo()
+ .then(function (report) { return resolve(report); })
+ .catch(function (error) { return reject(error); });
+ });
+ };
+ Stream.prototype.getRemoteIceCandidateList = function () {
+ return this.webRtcPeer.remoteCandidatesQueue;
+ };
+ Stream.prototype.getLocalIceCandidateList = function () {
+ return this.webRtcPeer.localCandidatesQueue;
+ };
+ Stream.prototype.initWebRtcPeerSend = function () {
+ var _this = this;
+ return new Promise(function (resolve, reject) {
+ var userMediaConstraints = {
+ audio: _this.isSendAudio(),
+ video: _this.isSendVideo()
+ };
+ var options = {
+ mediaStream: _this.mediaStream,
+ mediaConstraints: userMediaConstraints,
+ onicecandidate: _this.connection.sendIceCandidate.bind(_this.connection),
+ iceServers: _this.getIceServersConf(),
+ simulcast: false
+ };
+ var successCallback = function (sdpOfferParam) {
+ console.debug('Sending SDP offer to publish as '
+ + _this.streamId, sdpOfferParam);
+ var typeOfVideo = '';
+ if (_this.isSendVideo()) {
+ typeOfVideo = _this.outboundStreamOpts.publisherProperties.videoSource instanceof MediaStreamTrack ? 'CUSTOM' : (_this.isSendScreen() ? 'SCREEN' : 'CAMERA');
+ }
+ _this.session.openvidu.sendRequest('publishVideo', {
+ sdpOffer: sdpOfferParam,
+ doLoopback: _this.displayMyRemote() || false,
+ hasAudio: _this.isSendAudio(),
+ hasVideo: _this.isSendVideo(),
+ audioActive: _this.audioActive,
+ videoActive: _this.videoActive,
+ typeOfVideo: typeOfVideo,
+ frameRate: !!_this.frameRate ? _this.frameRate : -1,
+ videoDimensions: JSON.stringify(_this.videoDimensions)
+ }, function (error, response) {
+ if (error) {
+ if (error.code === 401) {
+ reject(new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.OPENVIDU_PERMISSION_DENIED, "You don't have permissions to publish"));
+ }
+ else {
+ reject('Error on publishVideo: ' + JSON.stringify(error));
+ }
+ }
+ else {
+ _this.webRtcPeer.processAnswer(response.sdpAnswer)
+ .then(function () {
+ _this.streamId = response.id;
+ _this.isLocalStreamPublished = true;
+ _this.publishedOnce = true;
+ if (_this.displayMyRemote()) {
+ _this.remotePeerSuccessfullyEstablished();
+ }
+ _this.ee.emitEvent('stream-created-by-publisher');
+ _this.initWebRtcStats();
+ resolve();
+ })
+ .catch(function (error) {
+ reject(error);
+ });
+ console.info("'Publisher' successfully published to session");
+ }
+ });
+ };
+ if (_this.displayMyRemote()) {
+ _this.webRtcPeer = new WebRtcPeer_1.WebRtcPeerSendrecv(options);
+ }
+ else {
+ _this.webRtcPeer = new WebRtcPeer_1.WebRtcPeerSendonly(options);
+ }
+ _this.webRtcPeer.generateOffer().then(function (offer) {
+ successCallback(offer);
+ }).catch(function (error) {
+ reject(new Error('(publish) SDP offer error: ' + JSON.stringify(error)));
+ });
+ });
+ };
+ Stream.prototype.initWebRtcPeerReceive = function () {
+ var _this = this;
+ return new Promise(function (resolve, reject) {
+ var offerConstraints = {
+ audio: _this.inboundStreamOpts.hasAudio,
+ video: _this.inboundStreamOpts.hasVideo
+ };
+ console.debug("'Session.subscribe(Stream)' called. Constraints of generate SDP offer", offerConstraints);
+ var options = {
+ onicecandidate: _this.connection.sendIceCandidate.bind(_this.connection),
+ mediaConstraints: offerConstraints,
+ iceServers: _this.getIceServersConf(),
+ simulcast: false
+ };
+ var successCallback = function (sdpOfferParam) {
+ console.debug('Sending SDP offer to subscribe to '
+ + _this.streamId, sdpOfferParam);
+ _this.session.openvidu.sendRequest('receiveVideoFrom', {
+ sender: _this.streamId,
+ sdpOffer: sdpOfferParam
+ }, function (error, response) {
+ if (error) {
+ reject(new Error('Error on recvVideoFrom: ' + JSON.stringify(error)));
+ }
+ else {
+ _this.webRtcPeer.processAnswer(response.sdpAnswer).then(function () {
+ _this.remotePeerSuccessfullyEstablished();
+ _this.initWebRtcStats();
+ resolve();
+ }).catch(function (error) {
+ reject(error);
+ });
+ }
+ });
+ };
+ _this.webRtcPeer = new WebRtcPeer_1.WebRtcPeerRecvonly(options);
+ _this.webRtcPeer.generateOffer()
+ .then(function (offer) {
+ successCallback(offer);
+ })
+ .catch(function (error) {
+ reject(new Error('(subscribe) SDP offer error: ' + JSON.stringify(error)));
+ });
+ });
+ };
+ Stream.prototype.remotePeerSuccessfullyEstablished = function () {
+ this.mediaStream = this.webRtcPeer.pc.getRemoteStreams()[0];
+ console.debug('Peer remote stream', this.mediaStream);
+ if (!!this.mediaStream) {
+ this.ee.emitEvent('mediastream-updated');
+ if (!this.displayMyRemote() && !!this.mediaStream.getAudioTracks()[0] && this.session.speakingEventsEnabled) {
+ this.enableSpeakingEvents();
+ }
+ }
+ };
+ Stream.prototype.initWebRtcStats = function () {
+ this.webRtcStats = new WebRtcStats_1.WebRtcStats(this);
+ this.webRtcStats.initWebRtcStats();
+ };
+ Stream.prototype.stopWebRtcStats = function () {
+ if (!!this.webRtcStats && this.webRtcStats.isEnabled()) {
+ this.webRtcStats.stopWebRtcStats();
+ }
+ };
+ Stream.prototype.getIceServersConf = function () {
+ var returnValue;
+ if (!!this.session.openvidu.advancedConfiguration.iceServers) {
+ returnValue = this.session.openvidu.advancedConfiguration.iceServers === 'freeice' ?
+ undefined :
+ this.session.openvidu.advancedConfiguration.iceServers;
+ }
+ else if (this.session.openvidu.iceServers) {
+ returnValue = this.session.openvidu.iceServers;
+ }
+ else {
+ returnValue = undefined;
+ }
+ return returnValue;
+ };
+ return Stream;
+}());
+exports.Stream = Stream;
+
+},{"../OpenViduInternal/Enums/OpenViduError":26,"../OpenViduInternal/Events/PublisherSpeakingEvent":30,"../OpenViduInternal/WebRtcPeer/WebRtcPeer":49,"../OpenViduInternal/WebRtcStats/WebRtcStats":50,"hark":5,"wolfy87-eventemitter":15}],23:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+var StreamManagerEvent_1 = require("../OpenViduInternal/Events/StreamManagerEvent");
+var VideoElementEvent_1 = require("../OpenViduInternal/Events/VideoElementEvent");
+var VideoInsertMode_1 = require("../OpenViduInternal/Enums/VideoInsertMode");
+var EventEmitter = require("wolfy87-eventemitter");
+var StreamManager = (function () {
+ function StreamManager(stream, targetElement) {
+ var _this = this;
+ this.videos = [];
+ this.lazyLaunchVideoElementCreatedEvent = false;
+ this.ee = new EventEmitter();
+ this.stream = stream;
+ this.stream.streamManager = this;
+ this.remote = !this.stream.isLocal();
+ if (!!targetElement) {
+ var targEl = void 0;
+ if (typeof targetElement === 'string') {
+ targEl = document.getElementById(targetElement);
+ }
+ else if (targetElement instanceof HTMLElement) {
+ targEl = targetElement;
+ }
+ if (!!targEl) {
+ this.firstVideoElement = {
+ targetElement: targEl,
+ video: document.createElement('video'),
+ id: ''
+ };
+ this.targetElement = targEl;
+ this.element = targEl;
+ }
+ }
+ this.canPlayListener = function () {
+ if (_this.stream.isLocal()) {
+ if (!_this.stream.displayMyRemote()) {
+ console.info("Your local 'Stream' with id [" + _this.stream.streamId + '] video is now playing');
+ _this.ee.emitEvent('videoPlaying', [new VideoElementEvent_1.VideoElementEvent(_this.videos[0].video, _this, 'videoPlaying')]);
+ }
+ else {
+ console.info("Your own remote 'Stream' with id [" + _this.stream.streamId + '] video is now playing');
+ _this.ee.emitEvent('remoteVideoPlaying', [new VideoElementEvent_1.VideoElementEvent(_this.videos[0].video, _this, 'remoteVideoPlaying')]);
+ }
+ }
+ else {
+ console.info("Remote 'Stream' with id [" + _this.stream.streamId + '] video is now playing');
+ _this.ee.emitEvent('videoPlaying', [new VideoElementEvent_1.VideoElementEvent(_this.videos[0].video, _this, 'videoPlaying')]);
+ }
+ _this.ee.emitEvent('streamPlaying', [new StreamManagerEvent_1.StreamManagerEvent(_this)]);
+ };
+ }
+ StreamManager.prototype.on = function (type, handler) {
+ var _this = this;
+ this.ee.on(type, function (event) {
+ if (event) {
+ console.info("Event '" + type + "' triggered by '" + (_this.remote ? 'Subscriber' : 'Publisher') + "'", event);
+ }
+ else {
+ console.info("Event '" + type + "' triggered by '" + (_this.remote ? 'Subscriber' : 'Publisher') + "'");
+ }
+ handler(event);
+ });
+ if (type === 'videoElementCreated') {
+ if (!!this.stream && this.lazyLaunchVideoElementCreatedEvent) {
+ this.ee.emitEvent('videoElementCreated', [new VideoElementEvent_1.VideoElementEvent(this.videos[0].video, this, 'videoElementCreated')]);
+ this.lazyLaunchVideoElementCreatedEvent = false;
+ }
+ }
+ if (type === 'streamPlaying' || type === 'videoPlaying') {
+ if (this.videos[0] && this.videos[0].video &&
+ this.videos[0].video.currentTime > 0 &&
+ this.videos[0].video.paused === false &&
+ this.videos[0].video.ended === false &&
+ this.videos[0].video.readyState === 4) {
+ this.ee.emitEvent('streamPlaying', [new StreamManagerEvent_1.StreamManagerEvent(this)]);
+ this.ee.emitEvent('videoPlaying', [new VideoElementEvent_1.VideoElementEvent(this.videos[0].video, this, 'videoPlaying')]);
+ }
+ }
+ return this;
+ };
+ StreamManager.prototype.once = function (type, handler) {
+ this.ee.once(type, function (event) {
+ if (event) {
+ console.info("Event '" + type + "' triggered once", event);
+ }
+ else {
+ console.info("Event '" + type + "' triggered once");
+ }
+ handler(event);
+ });
+ if (type === 'videoElementCreated') {
+ if (!!this.stream && this.lazyLaunchVideoElementCreatedEvent) {
+ this.ee.emitEvent('videoElementCreated', [new VideoElementEvent_1.VideoElementEvent(this.videos[0].video, this, 'videoElementCreated')]);
+ }
+ }
+ if (type === 'streamPlaying' || type === 'videoPlaying') {
+ if (this.videos[0] && this.videos[0].video &&
+ this.videos[0].video.currentTime > 0 &&
+ this.videos[0].video.paused === false &&
+ this.videos[0].video.ended === false &&
+ this.videos[0].video.readyState === 4) {
+ this.ee.emitEvent('streamPlaying', [new StreamManagerEvent_1.StreamManagerEvent(this)]);
+ this.ee.emitEvent('videoPlaying', [new VideoElementEvent_1.VideoElementEvent(this.videos[0].video, this, 'videoPlaying')]);
+ }
+ }
+ return this;
+ };
+ StreamManager.prototype.off = function (type, handler) {
+ if (!handler) {
+ this.ee.removeAllListeners(type);
+ }
+ else {
+ this.ee.off(type, handler);
+ }
+ return this;
+ };
+ StreamManager.prototype.addVideoElement = function (video) {
+ this.initializeVideoProperties(video);
+ for (var _i = 0, _a = this.videos; _i < _a.length; _i++) {
+ var v = _a[_i];
+ if (v.video === video) {
+ return 0;
+ }
+ }
+ var returnNumber = 1;
+ for (var _b = 0, _c = this.stream.session.streamManagers; _b < _c.length; _b++) {
+ var streamManager = _c[_b];
+ if (streamManager.disassociateVideo(video)) {
+ returnNumber = -1;
+ break;
+ }
+ }
+ this.stream.session.streamManagers.forEach(function (streamManager) {
+ streamManager.disassociateVideo(video);
+ });
+ this.pushNewStreamManagerVideo({
+ video: video,
+ id: video.id
+ });
+ console.info('New video element associated to ', this);
+ return returnNumber;
+ };
+ StreamManager.prototype.createVideoElement = function (targetElement, insertMode) {
+ var targEl;
+ if (typeof targetElement === 'string') {
+ targEl = document.getElementById(targEl);
+ if (!targEl) {
+ throw new Error("The provided 'targetElement' couldn't be resolved to any HTML element: " + targetElement);
+ }
+ }
+ else if (targetElement instanceof HTMLElement) {
+ targEl = targetElement;
+ }
+ else {
+ throw new Error("The provided 'targetElement' couldn't be resolved to any HTML element: " + targetElement);
+ }
+ var video = document.createElement('video');
+ this.initializeVideoProperties(video);
+ var insMode = !!insertMode ? insertMode : VideoInsertMode_1.VideoInsertMode.APPEND;
+ switch (insMode) {
+ case VideoInsertMode_1.VideoInsertMode.AFTER:
+ targEl.parentNode.insertBefore(video, targEl.nextSibling);
+ break;
+ case VideoInsertMode_1.VideoInsertMode.APPEND:
+ targEl.appendChild(video);
+ break;
+ case VideoInsertMode_1.VideoInsertMode.BEFORE:
+ targEl.parentNode.insertBefore(video, targEl);
+ break;
+ case VideoInsertMode_1.VideoInsertMode.PREPEND:
+ targEl.insertBefore(video, targEl.childNodes[0]);
+ break;
+ case VideoInsertMode_1.VideoInsertMode.REPLACE:
+ targEl.parentNode.replaceChild(video, targEl);
+ break;
+ default:
+ insMode = VideoInsertMode_1.VideoInsertMode.APPEND;
+ targEl.appendChild(video);
+ break;
+ }
+ var v = {
+ targetElement: targEl,
+ video: video,
+ insertMode: insMode,
+ id: video.id
+ };
+ this.pushNewStreamManagerVideo(v);
+ this.ee.emitEvent('videoElementCreated', [new VideoElementEvent_1.VideoElementEvent(v.video, this, 'videoElementCreated')]);
+ this.lazyLaunchVideoElementCreatedEvent = !!this.firstVideoElement;
+ return video;
+ };
+ StreamManager.prototype.initializeVideoProperties = function (video) {
+ if (!(this.stream.isLocal() && this.stream.displayMyRemote())) {
+ video.srcObject = this.stream.getMediaStream();
+ }
+ video.autoplay = true;
+ video.controls = false;
+ if (!video.id) {
+ video.id = (this.remote ? 'remote-' : 'local-') + 'video-' + this.stream.streamId;
+ if (!this.id && !!this.targetElement) {
+ this.id = video.id;
+ }
+ }
+ if (!this.remote && !this.stream.displayMyRemote()) {
+ video.muted = true;
+ if (this.stream.outboundStreamOpts.publisherProperties.mirror) {
+ this.mirrorVideo(video);
+ }
+ }
+ };
+ StreamManager.prototype.removeAllVideos = function () {
+ var _this = this;
+ for (var i = this.stream.session.streamManagers.length - 1; i >= 0; --i) {
+ if (this.stream.session.streamManagers[i] === this) {
+ this.stream.session.streamManagers.splice(i, 1);
+ }
+ }
+ this.videos.forEach(function (streamManagerVideo) {
+ streamManagerVideo.video.removeEventListener('canplay', _this.canPlayListener);
+ if (!!streamManagerVideo.targetElement) {
+ streamManagerVideo.video.parentNode.removeChild(streamManagerVideo.video);
+ _this.ee.emitEvent('videoElementDestroyed', [new VideoElementEvent_1.VideoElementEvent(streamManagerVideo.video, _this, 'videoElementDestroyed')]);
+ }
+ streamManagerVideo.video.srcObject = null;
+ _this.videos.filter(function (v) { return !v.targetElement; });
+ });
+ };
+ StreamManager.prototype.disassociateVideo = function (video) {
+ var disassociated = false;
+ for (var i = 0; i < this.videos.length; i++) {
+ if (this.videos[i].video === video) {
+ this.videos.splice(i, 1);
+ disassociated = true;
+ console.info('Video element disassociated from ', this);
+ break;
+ }
+ }
+ return disassociated;
+ };
+ StreamManager.prototype.addPlayEventToFirstVideo = function () {
+ if ((!!this.videos[0]) && (!!this.videos[0].video) && (this.videos[0].video.oncanplay === null)) {
+ this.videos[0].video.addEventListener('canplay', this.canPlayListener);
+ }
+ };
+ StreamManager.prototype.updateMediaStream = function (mediaStream) {
+ this.videos.forEach(function (streamManagerVideo) {
+ streamManagerVideo.video.srcObject = mediaStream;
+ });
+ };
+ StreamManager.prototype.emitEvent = function (type, eventArray) {
+ this.ee.emitEvent(type, eventArray);
+ };
+ StreamManager.prototype.pushNewStreamManagerVideo = function (streamManagerVideo) {
+ this.videos.push(streamManagerVideo);
+ this.addPlayEventToFirstVideo();
+ if (this.stream.session.streamManagers.indexOf(this) === -1) {
+ this.stream.session.streamManagers.push(this);
+ }
+ };
+ StreamManager.prototype.mirrorVideo = function (video) {
+ video.style.transform = 'rotateY(180deg)';
+ video.style.webkitTransform = 'rotateY(180deg)';
+ };
+ return StreamManager;
+}());
+exports.StreamManager = StreamManager;
+
+},{"../OpenViduInternal/Enums/VideoInsertMode":27,"../OpenViduInternal/Events/StreamManagerEvent":35,"../OpenViduInternal/Events/VideoElementEvent":37,"wolfy87-eventemitter":15}],24:[function(require,module,exports){
+"use strict";
+var __extends = (this && this.__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 __());
+ };
+})();
+Object.defineProperty(exports, "__esModule", { value: true });
+var StreamManager_1 = require("./StreamManager");
+var Subscriber = (function (_super) {
+ __extends(Subscriber, _super);
+ function Subscriber(stream, targEl, properties) {
+ var _this = _super.call(this, stream, targEl) || this;
+ _this.element = _this.targetElement;
+ _this.stream = stream;
+ _this.properties = properties;
+ return _this;
+ }
+ Subscriber.prototype.subscribeToAudio = function (value) {
+ this.stream.getMediaStream().getAudioTracks().forEach(function (track) {
+ track.enabled = value;
+ });
+ console.info("'Subscriber' has " + (value ? 'subscribed to' : 'unsubscribed from') + ' its audio stream');
+ return this;
+ };
+ Subscriber.prototype.subscribeToVideo = function (value) {
+ this.stream.getMediaStream().getVideoTracks().forEach(function (track) {
+ track.enabled = value;
+ });
+ console.info("'Subscriber' has " + (value ? 'subscribed to' : 'unsubscribed from') + ' its video stream');
+ return this;
+ };
+ return Subscriber;
+}(StreamManager_1.StreamManager));
+exports.Subscriber = Subscriber;
+
+},{"./StreamManager":23}],25:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+var LocalRecorderState;
+(function (LocalRecorderState) {
+ LocalRecorderState["READY"] = "READY";
+ LocalRecorderState["RECORDING"] = "RECORDING";
+ LocalRecorderState["PAUSED"] = "PAUSED";
+ LocalRecorderState["FINISHED"] = "FINISHED";
+})(LocalRecorderState = exports.LocalRecorderState || (exports.LocalRecorderState = {}));
+
+},{}],26:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+var OpenViduErrorName;
+(function (OpenViduErrorName) {
+ OpenViduErrorName["BROWSER_NOT_SUPPORTED"] = "BROWSER_NOT_SUPPORTED";
+ OpenViduErrorName["DEVICE_ACCESS_DENIED"] = "DEVICE_ACCESS_DENIED";
+ OpenViduErrorName["SCREEN_CAPTURE_DENIED"] = "SCREEN_CAPTURE_DENIED";
+ OpenViduErrorName["SCREEN_SHARING_NOT_SUPPORTED"] = "SCREEN_SHARING_NOT_SUPPORTED";
+ OpenViduErrorName["SCREEN_EXTENSION_NOT_INSTALLED"] = "SCREEN_EXTENSION_NOT_INSTALLED";
+ OpenViduErrorName["SCREEN_EXTENSION_DISABLED"] = "SCREEN_EXTENSION_DISABLED";
+ OpenViduErrorName["INPUT_VIDEO_DEVICE_NOT_FOUND"] = "INPUT_VIDEO_DEVICE_NOT_FOUND";
+ OpenViduErrorName["INPUT_AUDIO_DEVICE_NOT_FOUND"] = "INPUT_AUDIO_DEVICE_NOT_FOUND";
+ OpenViduErrorName["NO_INPUT_SOURCE_SET"] = "NO_INPUT_SOURCE_SET";
+ OpenViduErrorName["PUBLISHER_PROPERTIES_ERROR"] = "PUBLISHER_PROPERTIES_ERROR";
+ OpenViduErrorName["OPENVIDU_PERMISSION_DENIED"] = "OPENVIDU_PERMISSION_DENIED";
+ OpenViduErrorName["OPENVIDU_NOT_CONNECTED"] = "OPENVIDU_NOT_CONNECTED";
+ OpenViduErrorName["GENERIC_ERROR"] = "GENERIC_ERROR";
+})(OpenViduErrorName = exports.OpenViduErrorName || (exports.OpenViduErrorName = {}));
+var OpenViduError = (function () {
+ function OpenViduError(name, message) {
+ this.name = name;
+ this.message = message;
+ }
+ return OpenViduError;
+}());
+exports.OpenViduError = OpenViduError;
+
+},{}],27:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+var VideoInsertMode;
+(function (VideoInsertMode) {
+ VideoInsertMode["AFTER"] = "AFTER";
+ VideoInsertMode["APPEND"] = "APPEND";
+ VideoInsertMode["BEFORE"] = "BEFORE";
+ VideoInsertMode["PREPEND"] = "PREPEND";
+ VideoInsertMode["REPLACE"] = "REPLACE";
+})(VideoInsertMode = exports.VideoInsertMode || (exports.VideoInsertMode = {}));
+
+},{}],28:[function(require,module,exports){
+"use strict";
+var __extends = (this && this.__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 __());
+ };
+})();
+Object.defineProperty(exports, "__esModule", { value: true });
+var Event_1 = require("./Event");
+var ConnectionEvent = (function (_super) {
+ __extends(ConnectionEvent, _super);
+ function ConnectionEvent(cancelable, target, type, connection, reason) {
+ var _this = _super.call(this, cancelable, target, type) || this;
+ _this.connection = connection;
+ _this.reason = reason;
+ return _this;
+ }
+ ConnectionEvent.prototype.callDefaultBehavior = function () { };
+ return ConnectionEvent;
+}(Event_1.Event));
+exports.ConnectionEvent = ConnectionEvent;
+
+},{"./Event":29}],29:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+var Event = (function () {
+ function Event(cancelable, target, type) {
+ this.hasBeenPrevented = false;
+ this.cancelable = cancelable;
+ this.target = target;
+ this.type = type;
+ }
+ Event.prototype.isDefaultPrevented = function () {
+ return this.hasBeenPrevented;
+ };
+ Event.prototype.preventDefault = function () {
+ this.callDefaultBehavior = function () { };
+ this.hasBeenPrevented = true;
+ };
+ return Event;
+}());
+exports.Event = Event;
+
+},{}],30:[function(require,module,exports){
+"use strict";
+var __extends = (this && this.__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 __());
+ };
+})();
+Object.defineProperty(exports, "__esModule", { value: true });
+var Event_1 = require("./Event");
+var PublisherSpeakingEvent = (function (_super) {
+ __extends(PublisherSpeakingEvent, _super);
+ function PublisherSpeakingEvent(target, type, connection, streamId) {
+ var _this = _super.call(this, false, target, type) || this;
+ _this.type = type;
+ _this.connection = connection;
+ _this.streamId = streamId;
+ return _this;
+ }
+ PublisherSpeakingEvent.prototype.callDefaultBehavior = function () { };
+ return PublisherSpeakingEvent;
+}(Event_1.Event));
+exports.PublisherSpeakingEvent = PublisherSpeakingEvent;
+
+},{"./Event":29}],31:[function(require,module,exports){
+"use strict";
+var __extends = (this && this.__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 __());
+ };
+})();
+Object.defineProperty(exports, "__esModule", { value: true });
+var Event_1 = require("./Event");
+var RecordingEvent = (function (_super) {
+ __extends(RecordingEvent, _super);
+ function RecordingEvent(target, type, id, name) {
+ var _this = _super.call(this, false, target, type) || this;
+ _this.id = id;
+ if (name !== id) {
+ _this.name = name;
+ }
+ return _this;
+ }
+ RecordingEvent.prototype.callDefaultBehavior = function () { };
+ return RecordingEvent;
+}(Event_1.Event));
+exports.RecordingEvent = RecordingEvent;
+
+},{"./Event":29}],32:[function(require,module,exports){
+"use strict";
+var __extends = (this && this.__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 __());
+ };
+})();
+Object.defineProperty(exports, "__esModule", { value: true });
+var Event_1 = require("./Event");
+var SessionDisconnectedEvent = (function (_super) {
+ __extends(SessionDisconnectedEvent, _super);
+ function SessionDisconnectedEvent(target, reason) {
+ var _this = _super.call(this, true, target, 'sessionDisconnected') || this;
+ _this.reason = reason;
+ return _this;
+ }
+ SessionDisconnectedEvent.prototype.callDefaultBehavior = function () {
+ console.info("Calling default behavior upon '" + this.type + "' event dispatched by 'Session'");
+ var session = this.target;
+ for (var connectionId in session.remoteConnections) {
+ if (!!session.remoteConnections[connectionId].stream) {
+ session.remoteConnections[connectionId].stream.disposeWebRtcPeer();
+ session.remoteConnections[connectionId].stream.disposeMediaStream();
+ if (session.remoteConnections[connectionId].stream.streamManager) {
+ session.remoteConnections[connectionId].stream.streamManager.removeAllVideos();
+ }
+ delete session.remoteStreamsCreated[session.remoteConnections[connectionId].stream.streamId];
+ session.remoteConnections[connectionId].dispose();
+ }
+ delete session.remoteConnections[connectionId];
+ }
+ };
+ return SessionDisconnectedEvent;
+}(Event_1.Event));
+exports.SessionDisconnectedEvent = SessionDisconnectedEvent;
+
+},{"./Event":29}],33:[function(require,module,exports){
+"use strict";
+var __extends = (this && this.__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 __());
+ };
+})();
+Object.defineProperty(exports, "__esModule", { value: true });
+var Event_1 = require("./Event");
+var SignalEvent = (function (_super) {
+ __extends(SignalEvent, _super);
+ function SignalEvent(target, type, data, from) {
+ var _this = _super.call(this, false, target, type) || this;
+ _this.type = type;
+ _this.data = data;
+ _this.from = from;
+ return _this;
+ }
+ SignalEvent.prototype.callDefaultBehavior = function () { };
+ return SignalEvent;
+}(Event_1.Event));
+exports.SignalEvent = SignalEvent;
+
+},{"./Event":29}],34:[function(require,module,exports){
+"use strict";
+var __extends = (this && this.__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 __());
+ };
+})();
+Object.defineProperty(exports, "__esModule", { value: true });
+var Event_1 = require("./Event");
+var Publisher_1 = require("../../OpenVidu/Publisher");
+var Session_1 = require("../../OpenVidu/Session");
+var StreamEvent = (function (_super) {
+ __extends(StreamEvent, _super);
+ function StreamEvent(cancelable, target, type, stream, reason) {
+ var _this = _super.call(this, cancelable, target, type) || this;
+ _this.stream = stream;
+ _this.reason = reason;
+ return _this;
+ }
+ StreamEvent.prototype.callDefaultBehavior = function () {
+ if (this.type === 'streamDestroyed') {
+ if (this.target instanceof Session_1.Session) {
+ console.info("Calling default behavior upon '" + this.type + "' event dispatched by 'Session'");
+ this.stream.disposeWebRtcPeer();
+ }
+ else if (this.target instanceof Publisher_1.Publisher) {
+ console.info("Calling default behavior upon '" + this.type + "' event dispatched by 'Publisher'");
+ clearInterval(this.target.screenShareResizeInterval);
+ this.stream.isLocalStreamReadyToPublish = false;
+ var openviduPublishers = this.target.openvidu.publishers;
+ for (var i = 0; i < openviduPublishers.length; i++) {
+ if (openviduPublishers[i] === this.target) {
+ openviduPublishers.splice(i, 1);
+ break;
+ }
+ }
+ }
+ this.stream.disposeMediaStream();
+ if (this.stream.streamManager)
+ this.stream.streamManager.removeAllVideos();
+ delete this.stream.session.remoteStreamsCreated[this.stream.streamId];
+ var remoteConnection = this.stream.session.remoteConnections[this.stream.connection.connectionId];
+ if (!!remoteConnection && !!remoteConnection.options) {
+ var streamOptionsServer = remoteConnection.options.streams;
+ for (var i = streamOptionsServer.length - 1; i >= 0; --i) {
+ if (streamOptionsServer[i].id === this.stream.streamId) {
+ streamOptionsServer.splice(i, 1);
+ }
+ }
+ }
+ }
+ };
+ return StreamEvent;
+}(Event_1.Event));
+exports.StreamEvent = StreamEvent;
+
+},{"../../OpenVidu/Publisher":20,"../../OpenVidu/Session":21,"./Event":29}],35:[function(require,module,exports){
+"use strict";
+var __extends = (this && this.__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 __());
+ };
+})();
+Object.defineProperty(exports, "__esModule", { value: true });
+var Event_1 = require("./Event");
+var StreamManagerEvent = (function (_super) {
+ __extends(StreamManagerEvent, _super);
+ function StreamManagerEvent(target) {
+ return _super.call(this, false, target, 'streamPlaying') || this;
+ }
+ StreamManagerEvent.prototype.callDefaultBehavior = function () { };
+ return StreamManagerEvent;
+}(Event_1.Event));
+exports.StreamManagerEvent = StreamManagerEvent;
+
+},{"./Event":29}],36:[function(require,module,exports){
+"use strict";
+var __extends = (this && this.__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 __());
+ };
+})();
+Object.defineProperty(exports, "__esModule", { value: true });
+var Event_1 = require("./Event");
+var StreamPropertyChangedEvent = (function (_super) {
+ __extends(StreamPropertyChangedEvent, _super);
+ function StreamPropertyChangedEvent(target, stream, changedProperty, newValue, oldValue, reason) {
+ var _this = _super.call(this, false, target, 'streamPropertyChanged') || this;
+ _this.stream = stream;
+ _this.changedProperty = changedProperty;
+ _this.newValue = newValue;
+ _this.oldValue = oldValue;
+ _this.reason = reason;
+ return _this;
+ }
+ StreamPropertyChangedEvent.prototype.callDefaultBehavior = function () { };
+ return StreamPropertyChangedEvent;
+}(Event_1.Event));
+exports.StreamPropertyChangedEvent = StreamPropertyChangedEvent;
+
+},{"./Event":29}],37:[function(require,module,exports){
+"use strict";
+var __extends = (this && this.__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 __());
+ };
+})();
+Object.defineProperty(exports, "__esModule", { value: true });
+var Event_1 = require("./Event");
+var VideoElementEvent = (function (_super) {
+ __extends(VideoElementEvent, _super);
+ function VideoElementEvent(element, target, type) {
+ var _this = _super.call(this, false, target, type) || this;
+ _this.element = element;
+ return _this;
+ }
+ VideoElementEvent.prototype.callDefaultBehavior = function () { };
+ return VideoElementEvent;
+}(Event_1.Event));
+exports.VideoElementEvent = VideoElementEvent;
+
+},{"./Event":29}],38:[function(require,module,exports){
+function Mapper() {
+ var sources = {};
+ this.forEach = function (callback) {
+ for (var key in sources) {
+ var source = sources[key];
+ for (var key2 in source)
+ callback(source[key2]);
+ }
+ ;
+ };
+ this.get = function (id, source) {
+ var ids = sources[source];
+ if (ids == undefined)
+ return undefined;
+ return ids[id];
+ };
+ this.remove = function (id, source) {
+ var ids = sources[source];
+ if (ids == undefined)
+ return;
+ delete ids[id];
+ for (var i in ids) {
+ return false;
+ }
+ delete sources[source];
+ };
+ this.set = function (value, id, source) {
+ if (value == undefined)
+ return this.remove(id, source);
+ var ids = sources[source];
+ if (ids == undefined)
+ sources[source] = ids = {};
+ ids[id] = value;
+ };
+}
+;
+Mapper.prototype.pop = function (id, source) {
+ var value = this.get(id, source);
+ if (value == undefined)
+ return undefined;
+ this.remove(id, source);
+ return value;
+};
+module.exports = Mapper;
+
+},{}],39:[function(require,module,exports){
+var JsonRpcClient = require('./jsonrpcclient');
+exports.JsonRpcClient = JsonRpcClient;
+
+},{"./jsonrpcclient":40}],40:[function(require,module,exports){
+var RpcBuilder = require('../');
+var WebSocketWithReconnection = require('./transports/webSocketWithReconnection');
+Date.now = Date.now || function () {
+ return +new Date;
+};
+var PING_INTERVAL = 5000;
+var RECONNECTING = 'RECONNECTING';
+var CONNECTED = 'CONNECTED';
+var DISCONNECTED = 'DISCONNECTED';
+var Logger = console;
+function JsonRpcClient(configuration) {
+ var self = this;
+ var wsConfig = configuration.ws;
+ var notReconnectIfNumLessThan = -1;
+ var pingNextNum = 0;
+ var enabledPings = true;
+ var pingPongStarted = false;
+ var pingInterval;
+ var status = DISCONNECTED;
+ var onreconnecting = wsConfig.onreconnecting;
+ var onreconnected = wsConfig.onreconnected;
+ var onconnected = wsConfig.onconnected;
+ var onerror = wsConfig.onerror;
+ configuration.rpc.pull = function (params, request) {
+ request.reply(null, "push");
+ };
+ wsConfig.onreconnecting = function () {
+ Logger.debug("--------- ONRECONNECTING -----------");
+ if (status === RECONNECTING) {
+ Logger.error("Websocket already in RECONNECTING state when receiving a new ONRECONNECTING message. Ignoring it");
+ return;
+ }
+ status = RECONNECTING;
+ if (onreconnecting) {
+ onreconnecting();
+ }
+ };
+ wsConfig.onreconnected = function () {
+ Logger.debug("--------- ONRECONNECTED -----------");
+ if (status === CONNECTED) {
+ Logger.error("Websocket already in CONNECTED state when receiving a new ONRECONNECTED message. Ignoring it");
+ return;
+ }
+ status = CONNECTED;
+ enabledPings = true;
+ updateNotReconnectIfLessThan();
+ usePing();
+ if (onreconnected) {
+ onreconnected();
+ }
+ };
+ wsConfig.onconnected = function () {
+ Logger.debug("--------- ONCONNECTED -----------");
+ if (status === CONNECTED) {
+ Logger.error("Websocket already in CONNECTED state when receiving a new ONCONNECTED message. Ignoring it");
+ return;
+ }
+ status = CONNECTED;
+ enabledPings = true;
+ usePing();
+ if (onconnected) {
+ onconnected();
+ }
+ };
+ wsConfig.onerror = function (error) {
+ Logger.debug("--------- ONERROR -----------");
+ status = DISCONNECTED;
+ if (onerror) {
+ onerror(error);
+ }
+ };
+ var ws = new WebSocketWithReconnection(wsConfig);
+ Logger.debug('Connecting websocket to URI: ' + wsConfig.uri);
+ var rpcBuilderOptions = {
+ request_timeout: configuration.rpc.requestTimeout,
+ ping_request_timeout: configuration.rpc.heartbeatRequestTimeout
+ };
+ var rpc = new RpcBuilder(RpcBuilder.packers.JsonRPC, rpcBuilderOptions, ws, function (request) {
+ Logger.debug('Received request: ' + JSON.stringify(request));
+ try {
+ var func = configuration.rpc[request.method];
+ if (func === undefined) {
+ Logger.error("Method " + request.method + " not registered in client");
+ }
+ else {
+ func(request.params, request);
+ }
+ }
+ catch (err) {
+ Logger.error('Exception processing request: ' + JSON.stringify(request));
+ Logger.error(err);
+ }
+ });
+ this.send = function (method, params, callback) {
+ if (method !== 'ping') {
+ Logger.debug('Request: method:' + method + " params:" + JSON.stringify(params));
+ }
+ var requestTime = Date.now();
+ rpc.encode(method, params, function (error, result) {
+ if (error) {
+ try {
+ Logger.error("ERROR:" + error.message + " in Request: method:" +
+ method + " params:" + JSON.stringify(params) + " request:" +
+ error.request);
+ if (error.data) {
+ Logger.error("ERROR DATA:" + JSON.stringify(error.data));
+ }
+ }
+ catch (e) { }
+ error.requestTime = requestTime;
+ }
+ if (callback) {
+ if (result != undefined && result.value !== 'pong') {
+ Logger.debug('Response: ' + JSON.stringify(result));
+ }
+ callback(error, result);
+ }
+ });
+ };
+ function updateNotReconnectIfLessThan() {
+ Logger.debug("notReconnectIfNumLessThan = " + pingNextNum + ' (old=' +
+ notReconnectIfNumLessThan + ')');
+ notReconnectIfNumLessThan = pingNextNum;
+ }
+ function sendPing() {
+ if (enabledPings) {
+ var params = null;
+ if (pingNextNum == 0 || pingNextNum == notReconnectIfNumLessThan) {
+ params = {
+ interval: configuration.heartbeat || PING_INTERVAL
+ };
+ }
+ pingNextNum++;
+ self.send('ping', params, (function (pingNum) {
+ return function (error, result) {
+ if (error) {
+ Logger.debug("Error in ping request #" + pingNum + " (" +
+ error.message + ")");
+ if (pingNum > notReconnectIfNumLessThan) {
+ enabledPings = false;
+ updateNotReconnectIfLessThan();
+ Logger.debug("Server did not respond to ping message #" +
+ pingNum + ". Reconnecting... ");
+ ws.reconnectWs();
+ }
+ }
+ };
+ })(pingNextNum));
+ }
+ else {
+ Logger.debug("Trying to send ping, but ping is not enabled");
+ }
+ }
+ function usePing() {
+ if (!pingPongStarted) {
+ Logger.debug("Starting ping (if configured)");
+ pingPongStarted = true;
+ if (configuration.heartbeat != undefined) {
+ pingInterval = setInterval(sendPing, configuration.heartbeat);
+ sendPing();
+ }
+ }
+ }
+ this.close = function () {
+ Logger.debug("Closing jsonRpcClient explicitly by client");
+ if (pingInterval != undefined) {
+ Logger.debug("Clearing ping interval");
+ clearInterval(pingInterval);
+ }
+ pingPongStarted = false;
+ enabledPings = false;
+ if (configuration.sendCloseMessage) {
+ Logger.debug("Sending close message");
+ this.send('closeSession', null, function (error, result) {
+ if (error) {
+ Logger.error("Error sending close message: " + JSON.stringify(error));
+ }
+ ws.close();
+ });
+ }
+ else {
+ ws.close();
+ }
+ };
+ this.forceClose = function (millis) {
+ ws.forceClose(millis);
+ };
+ this.reconnect = function () {
+ ws.reconnectWs();
+ };
+}
+module.exports = JsonRpcClient;
+
+},{"../":43,"./transports/webSocketWithReconnection":42}],41:[function(require,module,exports){
+var WebSocketWithReconnection = require('./webSocketWithReconnection');
+exports.WebSocketWithReconnection = WebSocketWithReconnection;
+
+},{"./webSocketWithReconnection":42}],42:[function(require,module,exports){
+(function (global){
+"use strict";
+var BrowserWebSocket = global.WebSocket || global.MozWebSocket;
+var Logger = console;
+var MAX_RETRIES = 2000;
+var RETRY_TIME_MS = 3000;
+var CONNECTING = 0;
+var OPEN = 1;
+var CLOSING = 2;
+var CLOSED = 3;
+function WebSocketWithReconnection(config) {
+ var closing = false;
+ var registerMessageHandler;
+ var wsUri = config.uri;
+ var useSockJS = config.useSockJS;
+ var reconnecting = false;
+ var forcingDisconnection = false;
+ var ws;
+ if (useSockJS) {
+ ws = new SockJS(wsUri);
+ }
+ else {
+ ws = new WebSocket(wsUri);
+ }
+ ws.onopen = function () {
+ logConnected(ws, wsUri);
+ if (config.onconnected) {
+ config.onconnected();
+ }
+ };
+ ws.onerror = function (error) {
+ Logger.error("Could not connect to " + wsUri + " (invoking onerror if defined)", error);
+ if (config.onerror) {
+ config.onerror(error);
+ }
+ };
+ function logConnected(ws, wsUri) {
+ try {
+ Logger.debug("WebSocket connected to " + wsUri);
+ }
+ catch (e) {
+ Logger.error(e);
+ }
+ }
+ var reconnectionOnClose = function () {
+ if (ws.readyState === CLOSED) {
+ if (closing) {
+ Logger.debug("Connection closed by user");
+ }
+ else {
+ Logger.debug("Connection closed unexpectecly. Reconnecting...");
+ reconnectToSameUri(MAX_RETRIES, 1);
+ }
+ }
+ else {
+ Logger.debug("Close callback from previous websocket. Ignoring it");
+ }
+ };
+ ws.onclose = reconnectionOnClose;
+ function reconnectToSameUri(maxRetries, numRetries) {
+ Logger.debug("reconnectToSameUri (attempt #" + numRetries + ", max=" + maxRetries + ")");
+ if (numRetries === 1) {
+ if (reconnecting) {
+ Logger.warn("Trying to reconnectToNewUri when reconnecting... Ignoring this reconnection.");
+ return;
+ }
+ else {
+ reconnecting = true;
+ }
+ if (config.onreconnecting) {
+ config.onreconnecting();
+ }
+ }
+ if (forcingDisconnection) {
+ reconnectToNewUri(maxRetries, numRetries, wsUri);
+ }
+ else {
+ if (config.newWsUriOnReconnection) {
+ config.newWsUriOnReconnection(function (error, newWsUri) {
+ if (error) {
+ Logger.debug(error);
+ setTimeout(function () {
+ reconnectToSameUri(maxRetries, numRetries + 1);
+ }, RETRY_TIME_MS);
+ }
+ else {
+ reconnectToNewUri(maxRetries, numRetries, newWsUri);
+ }
+ });
+ }
+ else {
+ reconnectToNewUri(maxRetries, numRetries, wsUri);
+ }
+ }
+ }
+ function reconnectToNewUri(maxRetries, numRetries, reconnectWsUri) {
+ Logger.debug("Reconnection attempt #" + numRetries);
+ ws.close();
+ wsUri = reconnectWsUri || wsUri;
+ var newWs;
+ if (useSockJS) {
+ newWs = new SockJS(wsUri);
+ }
+ else {
+ newWs = new WebSocket(wsUri);
+ }
+ newWs.onopen = function () {
+ Logger.debug("Reconnected after " + numRetries + " attempts...");
+ logConnected(newWs, wsUri);
+ reconnecting = false;
+ registerMessageHandler();
+ if (config.onreconnected()) {
+ config.onreconnected();
+ }
+ newWs.onclose = reconnectionOnClose;
+ };
+ var onErrorOrClose = function (error) {
+ Logger.warn("Reconnection error: ", error);
+ if (numRetries === maxRetries) {
+ if (config.ondisconnect) {
+ config.ondisconnect();
+ }
+ }
+ else {
+ setTimeout(function () {
+ reconnectToSameUri(maxRetries, numRetries + 1);
+ }, RETRY_TIME_MS);
+ }
+ };
+ newWs.onerror = onErrorOrClose;
+ ws = newWs;
+ }
+ this.close = function () {
+ closing = true;
+ ws.close();
+ };
+ this.forceClose = function (millis) {
+ Logger.debug("Testing: Force WebSocket close");
+ if (millis) {
+ Logger.debug("Testing: Change wsUri for " + millis + " millis to simulate net failure");
+ var goodWsUri = wsUri;
+ wsUri = "wss://21.234.12.34.4:443/";
+ forcingDisconnection = true;
+ setTimeout(function () {
+ Logger.debug("Testing: Recover good wsUri " + goodWsUri);
+ wsUri = goodWsUri;
+ forcingDisconnection = false;
+ }, millis);
+ }
+ ws.close();
+ };
+ this.reconnectWs = function () {
+ Logger.debug("reconnectWs");
+ reconnectToSameUri(MAX_RETRIES, 1);
+ };
+ this.send = function (message) {
+ ws.send(message);
+ };
+ this.addEventListener = function (type, callback) {
+ registerMessageHandler = function () {
+ ws.addEventListener(type, callback);
+ };
+ registerMessageHandler();
+ };
+}
+module.exports = WebSocketWithReconnection;
+
+}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
+
+},{}],43:[function(require,module,exports){
+var defineProperty_IE8 = false;
+if (Object.defineProperty) {
+ try {
+ Object.defineProperty({}, "x", {});
+ }
+ catch (e) {
+ defineProperty_IE8 = true;
+ }
+}
+if (!Function.prototype.bind) {
+ Function.prototype.bind = function (oThis) {
+ if (typeof this !== 'function') {
+ throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable');
+ }
+ var aArgs = Array.prototype.slice.call(arguments, 1), fToBind = this, fNOP = function () { }, fBound = function () {
+ return fToBind.apply(this instanceof fNOP && oThis
+ ? this
+ : oThis, aArgs.concat(Array.prototype.slice.call(arguments)));
+ };
+ fNOP.prototype = this.prototype;
+ fBound.prototype = new fNOP();
+ return fBound;
+ };
+}
+var EventEmitter = require('events').EventEmitter;
+var inherits = require('inherits');
+var packers = require('./packers');
+var Mapper = require('./Mapper');
+var BASE_TIMEOUT = 5000;
+function unifyResponseMethods(responseMethods) {
+ if (!responseMethods)
+ return {};
+ for (var key in responseMethods) {
+ var value = responseMethods[key];
+ if (typeof value == 'string')
+ responseMethods[key] =
+ {
+ response: value
+ };
+ }
+ ;
+ return responseMethods;
+}
+;
+function unifyTransport(transport) {
+ if (!transport)
+ return;
+ if (transport instanceof Function)
+ return { send: transport };
+ if (transport.send instanceof Function)
+ return transport;
+ if (transport.postMessage instanceof Function) {
+ transport.send = transport.postMessage;
+ return transport;
+ }
+ if (transport.write instanceof Function) {
+ transport.send = transport.write;
+ return transport;
+ }
+ if (transport.onmessage !== undefined)
+ return;
+ if (transport.pause instanceof Function)
+ return;
+ throw new SyntaxError("Transport is not a function nor a valid object");
+}
+;
+function RpcNotification(method, params) {
+ if (defineProperty_IE8) {
+ this.method = method;
+ this.params = params;
+ }
+ else {
+ Object.defineProperty(this, 'method', { value: method, enumerable: true });
+ Object.defineProperty(this, 'params', { value: params, enumerable: true });
+ }
+}
+;
+function RpcBuilder(packer, options, transport, onRequest) {
+ var self = this;
+ if (!packer)
+ throw new SyntaxError('Packer is not defined');
+ if (!packer.pack || !packer.unpack)
+ throw new SyntaxError('Packer is invalid');
+ var responseMethods = unifyResponseMethods(packer.responseMethods);
+ if (options instanceof Function) {
+ if (transport != undefined)
+ throw new SyntaxError("There can't be parameters after onRequest");
+ onRequest = options;
+ transport = undefined;
+ options = undefined;
+ }
+ ;
+ if (options && options.send instanceof Function) {
+ if (transport && !(transport instanceof Function))
+ throw new SyntaxError("Only a function can be after transport");
+ onRequest = transport;
+ transport = options;
+ options = undefined;
+ }
+ ;
+ if (transport instanceof Function) {
+ if (onRequest != undefined)
+ throw new SyntaxError("There can't be parameters after onRequest");
+ onRequest = transport;
+ transport = undefined;
+ }
+ ;
+ if (transport && transport.send instanceof Function)
+ if (onRequest && !(onRequest instanceof Function))
+ throw new SyntaxError("Only a function can be after transport");
+ options = options || {};
+ EventEmitter.call(this);
+ if (onRequest)
+ this.on('request', onRequest);
+ if (defineProperty_IE8)
+ this.peerID = options.peerID;
+ else
+ Object.defineProperty(this, 'peerID', { value: options.peerID });
+ var max_retries = options.max_retries || 0;
+ function transportMessage(event) {
+ self.decode(event.data || event);
+ }
+ ;
+ this.getTransport = function () {
+ return transport;
+ };
+ this.setTransport = function (value) {
+ if (transport) {
+ if (transport.removeEventListener)
+ transport.removeEventListener('message', transportMessage);
+ else if (transport.removeListener)
+ transport.removeListener('data', transportMessage);
+ }
+ ;
+ if (value) {
+ if (value.addEventListener)
+ value.addEventListener('message', transportMessage);
+ else if (value.addListener)
+ value.addListener('data', transportMessage);
+ }
+ ;
+ transport = unifyTransport(value);
+ };
+ if (!defineProperty_IE8)
+ Object.defineProperty(this, 'transport', {
+ get: this.getTransport.bind(this),
+ set: this.setTransport.bind(this)
+ });
+ this.setTransport(transport);
+ var request_timeout = options.request_timeout || BASE_TIMEOUT;
+ var ping_request_timeout = options.ping_request_timeout || request_timeout;
+ var response_timeout = options.response_timeout || BASE_TIMEOUT;
+ var duplicates_timeout = options.duplicates_timeout || BASE_TIMEOUT;
+ var requestID = 0;
+ var requests = new Mapper();
+ var responses = new Mapper();
+ var processedResponses = new Mapper();
+ var message2Key = {};
+ function storeResponse(message, id, dest) {
+ var response = {
+ message: message,
+ timeout: setTimeout(function () {
+ responses.remove(id, dest);
+ }, response_timeout)
+ };
+ responses.set(response, id, dest);
+ }
+ ;
+ function storeProcessedResponse(ack, from) {
+ var timeout = setTimeout(function () {
+ processedResponses.remove(ack, from);
+ }, duplicates_timeout);
+ processedResponses.set(timeout, ack, from);
+ }
+ ;
+ function RpcRequest(method, params, id, from, transport) {
+ RpcNotification.call(this, method, params);
+ this.getTransport = function () {
+ return transport;
+ };
+ this.setTransport = function (value) {
+ transport = unifyTransport(value);
+ };
+ if (!defineProperty_IE8)
+ Object.defineProperty(this, 'transport', {
+ get: this.getTransport.bind(this),
+ set: this.setTransport.bind(this)
+ });
+ var response = responses.get(id, from);
+ if (!(transport || self.getTransport())) {
+ if (defineProperty_IE8)
+ this.duplicated = Boolean(response);
+ else
+ Object.defineProperty(this, 'duplicated', {
+ value: Boolean(response)
+ });
+ }
+ var responseMethod = responseMethods[method];
+ this.pack = packer.pack.bind(packer, this, id);
+ this.reply = function (error, result, transport) {
+ if (error instanceof Function || error && error.send instanceof Function) {
+ if (result != undefined)
+ throw new SyntaxError("There can't be parameters after callback");
+ transport = error;
+ result = null;
+ error = undefined;
+ }
+ else if (result instanceof Function
+ || result && result.send instanceof Function) {
+ if (transport != undefined)
+ throw new SyntaxError("There can't be parameters after callback");
+ transport = result;
+ result = null;
+ }
+ ;
+ transport = unifyTransport(transport);
+ if (response)
+ clearTimeout(response.timeout);
+ if (from != undefined) {
+ if (error)
+ error.dest = from;
+ if (result)
+ result.dest = from;
+ }
+ ;
+ var message;
+ if (error || result != undefined) {
+ if (self.peerID != undefined) {
+ if (error)
+ error.from = self.peerID;
+ else
+ result.from = self.peerID;
+ }
+ if (responseMethod) {
+ if (responseMethod.error == undefined && error)
+ message =
+ {
+ error: error
+ };
+ else {
+ var method = error
+ ? responseMethod.error
+ : responseMethod.response;
+ message =
+ {
+ method: method,
+ params: error || result
+ };
+ }
+ }
+ else
+ message =
+ {
+ error: error,
+ result: result
+ };
+ message = packer.pack(message, id);
+ }
+ else if (response)
+ message = response.message;
+ else
+ message = packer.pack({ result: null }, id);
+ storeResponse(message, id, from);
+ transport = transport || this.getTransport() || self.getTransport();
+ if (transport)
+ return transport.send(message);
+ return message;
+ };
+ }
+ ;
+ inherits(RpcRequest, RpcNotification);
+ function cancel(message) {
+ var key = message2Key[message];
+ if (!key)
+ return;
+ delete message2Key[message];
+ var request = requests.pop(key.id, key.dest);
+ if (!request)
+ return;
+ clearTimeout(request.timeout);
+ storeProcessedResponse(key.id, key.dest);
+ }
+ ;
+ this.cancel = function (message) {
+ if (message)
+ return cancel(message);
+ for (var message in message2Key)
+ cancel(message);
+ };
+ this.close = function () {
+ var transport = this.getTransport();
+ if (transport && transport.close)
+ transport.close();
+ this.cancel();
+ processedResponses.forEach(clearTimeout);
+ responses.forEach(function (response) {
+ clearTimeout(response.timeout);
+ });
+ };
+ this.encode = function (method, params, dest, transport, callback) {
+ if (params instanceof Function) {
+ if (dest != undefined)
+ throw new SyntaxError("There can't be parameters after callback");
+ callback = params;
+ transport = undefined;
+ dest = undefined;
+ params = undefined;
+ }
+ else if (dest instanceof Function) {
+ if (transport != undefined)
+ throw new SyntaxError("There can't be parameters after callback");
+ callback = dest;
+ transport = undefined;
+ dest = undefined;
+ }
+ else if (transport instanceof Function) {
+ if (callback != undefined)
+ throw new SyntaxError("There can't be parameters after callback");
+ callback = transport;
+ transport = undefined;
+ }
+ ;
+ if (self.peerID != undefined) {
+ params = params || {};
+ params.from = self.peerID;
+ }
+ ;
+ if (dest != undefined) {
+ params = params || {};
+ params.dest = dest;
+ }
+ ;
+ var message = {
+ method: method,
+ params: params
+ };
+ if (callback) {
+ var id = requestID++;
+ var retried = 0;
+ message = packer.pack(message, id);
+ function dispatchCallback(error, result) {
+ self.cancel(message);
+ callback(error, result);
+ }
+ ;
+ var request = {
+ message: message,
+ callback: dispatchCallback,
+ responseMethods: responseMethods[method] || {}
+ };
+ var encode_transport = unifyTransport(transport);
+ function sendRequest(transport) {
+ var rt = (method === 'ping' ? ping_request_timeout : request_timeout);
+ request.timeout = setTimeout(timeout, rt * Math.pow(2, retried++));
+ message2Key[message] = { id: id, dest: dest };
+ requests.set(request, id, dest);
+ transport = transport || encode_transport || self.getTransport();
+ if (transport)
+ return transport.send(message);
+ return message;
+ }
+ ;
+ function retry(transport) {
+ transport = unifyTransport(transport);
+ console.warn(retried + ' retry for request message:', message);
+ var timeout = processedResponses.pop(id, dest);
+ clearTimeout(timeout);
+ return sendRequest(transport);
+ }
+ ;
+ function timeout() {
+ if (retried < max_retries)
+ return retry(transport);
+ var error = new Error('Request has timed out');
+ error.request = message;
+ error.retry = retry;
+ dispatchCallback(error);
+ }
+ ;
+ return sendRequest(transport);
+ }
+ ;
+ message = packer.pack(message);
+ transport = transport || this.getTransport();
+ if (transport)
+ return transport.send(message);
+ return message;
+ };
+ this.decode = function (message, transport) {
+ if (!message)
+ throw new TypeError("Message is not defined");
+ try {
+ message = packer.unpack(message);
+ }
+ catch (e) {
+ return console.debug(e, message);
+ }
+ ;
+ var id = message.id;
+ var ack = message.ack;
+ var method = message.method;
+ var params = message.params || {};
+ var from = params.from;
+ var dest = params.dest;
+ if (self.peerID != undefined && from == self.peerID)
+ return;
+ if (id == undefined && ack == undefined) {
+ var notification = new RpcNotification(method, params);
+ if (self.emit('request', notification))
+ return;
+ return notification;
+ }
+ ;
+ function processRequest() {
+ transport = unifyTransport(transport) || self.getTransport();
+ if (transport) {
+ var response = responses.get(id, from);
+ if (response)
+ return transport.send(response.message);
+ }
+ ;
+ var idAck = (id != undefined) ? id : ack;
+ var request = new RpcRequest(method, params, idAck, from, transport);
+ if (self.emit('request', request))
+ return;
+ return request;
+ }
+ ;
+ function processResponse(request, error, result) {
+ request.callback(error, result);
+ }
+ ;
+ function duplicatedResponse(timeout) {
+ console.warn("Response already processed", message);
+ clearTimeout(timeout);
+ storeProcessedResponse(ack, from);
+ }
+ ;
+ if (method) {
+ if (dest == undefined || dest == self.peerID) {
+ var request = requests.get(ack, from);
+ if (request) {
+ var responseMethods = request.responseMethods;
+ if (method == responseMethods.error)
+ return processResponse(request, params);
+ if (method == responseMethods.response)
+ return processResponse(request, null, params);
+ return processRequest();
+ }
+ var processed = processedResponses.get(ack, from);
+ if (processed)
+ return duplicatedResponse(processed);
+ }
+ return processRequest();
+ }
+ ;
+ var error = message.error;
+ var result = message.result;
+ if (error && error.dest && error.dest != self.peerID)
+ return;
+ if (result && result.dest && result.dest != self.peerID)
+ return;
+ var request = requests.get(ack, from);
+ if (!request) {
+ var processed = processedResponses.get(ack, from);
+ if (processed)
+ return duplicatedResponse(processed);
+ return console.warn("No callback was defined for this message", message);
+ }
+ ;
+ processResponse(request, error, result);
+ };
+}
+;
+inherits(RpcBuilder, EventEmitter);
+RpcBuilder.RpcNotification = RpcNotification;
+module.exports = RpcBuilder;
+var clients = require('./clients');
+var transports = require('./clients/transports');
+RpcBuilder.clients = clients;
+RpcBuilder.clients.transports = transports;
+RpcBuilder.packers = packers;
+
+},{"./Mapper":38,"./clients":39,"./clients/transports":41,"./packers":46,"events":1,"inherits":6}],44:[function(require,module,exports){
+function pack(message, id) {
+ var result = {
+ jsonrpc: "2.0"
+ };
+ if (message.method) {
+ result.method = message.method;
+ if (message.params)
+ result.params = message.params;
+ if (id != undefined)
+ result.id = id;
+ }
+ else if (id != undefined) {
+ if (message.error) {
+ if (message.result !== undefined)
+ throw new TypeError("Both result and error are defined");
+ result.error = message.error;
+ }
+ else if (message.result !== undefined)
+ result.result = message.result;
+ else
+ throw new TypeError("No result or error is defined");
+ result.id = id;
+ }
+ ;
+ return JSON.stringify(result);
+}
+;
+function unpack(message) {
+ var result = message;
+ if (typeof message === 'string' || message instanceof String) {
+ result = JSON.parse(message);
+ }
+ var version = result.jsonrpc;
+ if (version !== '2.0')
+ throw new TypeError("Invalid JsonRPC version '" + version + "': " + message);
+ if (result.method == undefined) {
+ if (result.id == undefined)
+ throw new TypeError("Invalid message: " + message);
+ var result_defined = result.result !== undefined;
+ var error_defined = result.error !== undefined;
+ if (result_defined && error_defined)
+ throw new TypeError("Both result and error are defined: " + message);
+ if (!result_defined && !error_defined)
+ throw new TypeError("No result or error is defined: " + message);
+ result.ack = result.id;
+ delete result.id;
+ }
+ return result;
+}
+;
+exports.pack = pack;
+exports.unpack = unpack;
+
+},{}],45:[function(require,module,exports){
+function pack(message) {
+ throw new TypeError("Not yet implemented");
+}
+;
+function unpack(message) {
+ throw new TypeError("Not yet implemented");
+}
+;
+exports.pack = pack;
+exports.unpack = unpack;
+
+},{}],46:[function(require,module,exports){
+var JsonRPC = require('./JsonRPC');
+var XmlRPC = require('./XmlRPC');
+exports.JsonRPC = JsonRPC;
+exports.XmlRPC = XmlRPC;
+
+},{"./JsonRPC":44,"./XmlRPC":45}],47:[function(require,module,exports){
+window.getScreenId = function (callback, custom_parameter) {
+ if (navigator.userAgent.indexOf('Edge') !== -1 && (!!navigator.msSaveOrOpenBlob || !!navigator.msSaveBlob)) {
+ callback({
+ video: true
+ });
+ return;
+ }
+ if (!!navigator.mozGetUserMedia) {
+ callback(null, 'firefox', {
+ video: {
+ mozMediaSource: 'window',
+ mediaSource: 'window'
+ }
+ });
+ return;
+ }
+ window.addEventListener('message', onIFrameCallback);
+ function onIFrameCallback(event) {
+ if (!event.data)
+ return;
+ if (event.data.chromeMediaSourceId) {
+ if (event.data.chromeMediaSourceId === 'PermissionDeniedError') {
+ callback('permission-denied');
+ }
+ else {
+ callback(null, event.data.chromeMediaSourceId, getScreenConstraints(null, event.data.chromeMediaSourceId, event.data.canRequestAudioTrack));
+ }
+ window.removeEventListener('message', onIFrameCallback);
+ }
+ if (event.data.chromeExtensionStatus) {
+ callback(event.data.chromeExtensionStatus, null, getScreenConstraints(event.data.chromeExtensionStatus));
+ window.removeEventListener('message', onIFrameCallback);
+ }
+ }
+ if (!custom_parameter) {
+ setTimeout(postGetSourceIdMessage, 100);
+ }
+ else {
+ setTimeout(function () {
+ postGetSourceIdMessage(custom_parameter);
+ }, 100);
+ }
+};
+function getScreenConstraints(error, sourceId, canRequestAudioTrack) {
+ var screen_constraints = {
+ audio: false,
+ video: {
+ mandatory: {
+ chromeMediaSource: error ? 'screen' : 'desktop',
+ maxWidth: window.screen.width > 1920 ? window.screen.width : 1920,
+ maxHeight: window.screen.height > 1080 ? window.screen.height : 1080
+ },
+ optional: []
+ }
+ };
+ if (!!canRequestAudioTrack) {
+ screen_constraints.audio = {
+ mandatory: {
+ chromeMediaSource: error ? 'screen' : 'desktop',
+ },
+ optional: []
+ };
+ }
+ if (sourceId) {
+ screen_constraints.video.mandatory.chromeMediaSourceId = sourceId;
+ if (screen_constraints.audio && screen_constraints.audio.mandatory) {
+ screen_constraints.audio.mandatory.chromeMediaSourceId = sourceId;
+ }
+ }
+ return screen_constraints;
+}
+function postGetSourceIdMessage(custom_parameter) {
+ if (!iframe) {
+ loadIFrame(function () {
+ postGetSourceIdMessage(custom_parameter);
+ });
+ return;
+ }
+ if (!iframe.isLoaded) {
+ setTimeout(function () {
+ postGetSourceIdMessage(custom_parameter);
+ }, 100);
+ return;
+ }
+ if (!custom_parameter) {
+ iframe.contentWindow.postMessage({
+ captureSourceId: true
+ }, '*');
+ }
+ else if (!!custom_parameter.forEach) {
+ iframe.contentWindow.postMessage({
+ captureCustomSourceId: custom_parameter
+ }, '*');
+ }
+ else {
+ iframe.contentWindow.postMessage({
+ captureSourceIdWithAudio: true
+ }, '*');
+ }
+}
+var iframe;
+window.getScreenConstraints = function (callback) {
+ loadIFrame(function () {
+ getScreenId(function (error, sourceId, screen_constraints) {
+ if (!screen_constraints) {
+ screen_constraints = {
+ video: true
+ };
+ }
+ callback(error, screen_constraints.video);
+ });
+ });
+};
+function loadIFrame(loadCallback) {
+ if (iframe) {
+ loadCallback();
+ return;
+ }
+ iframe = document.createElement('iframe');
+ iframe.onload = function () {
+ iframe.isLoaded = true;
+ loadCallback();
+ };
+ iframe.src = 'https://openvidu.github.io/openvidu-screen-sharing-chrome-extension/';
+ iframe.style.display = 'none';
+ (document.body || document.documentElement).appendChild(iframe);
+}
+window.getChromeExtensionStatus = function (callback) {
+ if (!!navigator.mozGetUserMedia) {
+ callback('installed-enabled');
+ return;
+ }
+ window.addEventListener('message', onIFrameCallback);
+ function onIFrameCallback(event) {
+ if (!event.data)
+ return;
+ if (event.data.chromeExtensionStatus) {
+ callback(event.data.chromeExtensionStatus);
+ window.removeEventListener('message', onIFrameCallback);
+ }
+ }
+ setTimeout(postGetChromeExtensionStatusMessage, 100);
+};
+function postGetChromeExtensionStatusMessage() {
+ if (!iframe) {
+ loadIFrame(postGetChromeExtensionStatusMessage);
+ return;
+ }
+ if (!iframe.isLoaded) {
+ setTimeout(postGetChromeExtensionStatusMessage, 100);
+ return;
+ }
+ iframe.contentWindow.postMessage({
+ getChromeExtensionStatus: true
+ }, '*');
+}
+exports.getScreenId = getScreenId;
+
+},{}],48:[function(require,module,exports){
+var chromeMediaSource = 'screen';
+var sourceId;
+var screenCallback;
+var isFirefox = typeof window.InstallTrigger !== 'undefined';
+var isOpera = !!window.opera || navigator.userAgent.indexOf(' OPR/') >= 0;
+var isChrome = !!window.chrome && !isOpera;
+window.addEventListener('message', function (event) {
+ if (event.origin != window.location.origin) {
+ return;
+ }
+ onMessageCallback(event.data);
+});
+function onMessageCallback(data) {
+ if (data == 'PermissionDeniedError') {
+ if (screenCallback)
+ return screenCallback('PermissionDeniedError');
+ else
+ throw new Error('PermissionDeniedError');
+ }
+ if (data == 'rtcmulticonnection-extension-loaded') {
+ chromeMediaSource = 'desktop';
+ }
+ if (data.sourceId && screenCallback) {
+ screenCallback(sourceId = data.sourceId, data.canRequestAudioTrack === true);
+ }
+}
+function isChromeExtensionAvailable(callback) {
+ if (!callback)
+ return;
+ if (chromeMediaSource == 'desktop')
+ return callback(true);
+ window.postMessage('are-you-there', '*');
+ setTimeout(function () {
+ if (chromeMediaSource == 'screen') {
+ callback(false);
+ }
+ else
+ callback(true);
+ }, 2000);
+}
+function getSourceId(callback) {
+ if (!callback)
+ throw '"callback" parameter is mandatory.';
+ if (sourceId)
+ return callback(sourceId);
+ screenCallback = callback;
+ window.postMessage('get-sourceId', '*');
+}
+function getCustomSourceId(arr, callback) {
+ if (!arr || !arr.forEach)
+ throw '"arr" parameter is mandatory and it must be an array.';
+ if (!callback)
+ throw '"callback" parameter is mandatory.';
+ if (sourceId)
+ return callback(sourceId);
+ screenCallback = callback;
+ window.postMessage({
+ 'get-custom-sourceId': arr
+ }, '*');
+}
+function getSourceIdWithAudio(callback) {
+ if (!callback)
+ throw '"callback" parameter is mandatory.';
+ if (sourceId)
+ return callback(sourceId);
+ screenCallback = callback;
+ window.postMessage('audio-plus-tab', '*');
+}
+function getChromeExtensionStatus(extensionid, callback) {
+ if (isFirefox)
+ return callback('not-chrome');
+ if (arguments.length != 2) {
+ callback = extensionid;
+ extensionid = 'lfcgfepafnobdloecchnfaclibenjold';
+ }
+ var image = document.createElement('img');
+ image.src = 'chrome-extension://' + extensionid + '/icon.png';
+ image.onload = function () {
+ chromeMediaSource = 'screen';
+ window.postMessage('are-you-there', '*');
+ setTimeout(function () {
+ if (chromeMediaSource == 'screen') {
+ callback('installed-disabled');
+ }
+ else
+ callback('installed-enabled');
+ }, 2000);
+ };
+ image.onerror = function () {
+ callback('not-installed');
+ };
+}
+function getScreenConstraintsWithAudio(callback) {
+ getScreenConstraints(callback, true);
+}
+function getScreenConstraints(callback, captureSourceIdWithAudio) {
+ sourceId = '';
+ var firefoxScreenConstraints = {
+ mozMediaSource: 'window',
+ mediaSource: 'window'
+ };
+ if (isFirefox)
+ return callback(null, firefoxScreenConstraints);
+ var screen_constraints = {
+ mandatory: {
+ chromeMediaSource: chromeMediaSource,
+ maxWidth: screen.width > 1920 ? screen.width : 1920,
+ maxHeight: screen.height > 1080 ? screen.height : 1080
+ },
+ optional: []
+ };
+ if (chromeMediaSource == 'desktop' && !sourceId) {
+ if (captureSourceIdWithAudio) {
+ getSourceIdWithAudio(function (sourceId, canRequestAudioTrack) {
+ screen_constraints.mandatory.chromeMediaSourceId = sourceId;
+ if (canRequestAudioTrack) {
+ screen_constraints.canRequestAudioTrack = true;
+ }
+ callback(sourceId == 'PermissionDeniedError' ? sourceId : null, screen_constraints);
+ });
+ }
+ else {
+ getSourceId(function (sourceId) {
+ screen_constraints.mandatory.chromeMediaSourceId = sourceId;
+ callback(sourceId == 'PermissionDeniedError' ? sourceId : null, screen_constraints);
+ });
+ }
+ return;
+ }
+ if (chromeMediaSource == 'desktop') {
+ screen_constraints.mandatory.chromeMediaSourceId = sourceId;
+ }
+ callback(null, screen_constraints);
+}
+exports.getScreenConstraints = getScreenConstraints;
+exports.getScreenConstraintsWithAudio = getScreenConstraintsWithAudio;
+exports.isChromeExtensionAvailable = isChromeExtensionAvailable;
+exports.getChromeExtensionStatus = getChromeExtensionStatus;
+exports.getSourceId = getSourceId;
+
+},{}],49:[function(require,module,exports){
+"use strict";
+var __extends = (this && this.__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 __());
+ };
+})();
+Object.defineProperty(exports, "__esModule", { value: true });
+var freeice = require("freeice");
+var uuid = require("uuid");
+var platform = require("platform");
+var WebRtcPeer = (function () {
+ function WebRtcPeer(configuration) {
+ var _this = this;
+ this.configuration = configuration;
+ this.remoteCandidatesQueue = [];
+ this.localCandidatesQueue = [];
+ this.iceCandidateList = [];
+ this.candidategatheringdone = false;
+ this.configuration.iceServers = (!!this.configuration.iceServers && this.configuration.iceServers.length > 0) ? this.configuration.iceServers : freeice();
+ this.pc = new RTCPeerConnection({ iceServers: this.configuration.iceServers });
+ this.id = !!configuration.id ? configuration.id : uuid.v4();
+ this.pc.onicecandidate = function (event) {
+ var candidate = event.candidate;
+ if (candidate) {
+ _this.localCandidatesQueue.push({ candidate: candidate.candidate });
+ _this.candidategatheringdone = false;
+ _this.configuration.onicecandidate(event.candidate);
+ }
+ else if (!_this.candidategatheringdone) {
+ _this.candidategatheringdone = true;
+ }
+ };
+ this.pc.onsignalingstatechange = function () {
+ if (_this.pc.signalingState === 'stable') {
+ while (_this.iceCandidateList.length > 0) {
+ _this.pc.addIceCandidate(_this.iceCandidateList.shift());
+ }
+ }
+ };
+ this.start();
+ }
+ WebRtcPeer.prototype.start = function () {
+ var _this = this;
+ return new Promise(function (resolve, reject) {
+ if (_this.pc.signalingState === 'closed') {
+ reject('The peer connection object is in "closed" state. This is most likely due to an invocation of the dispose method before accepting in the dialogue');
+ }
+ if (!!_this.configuration.mediaStream) {
+ _this.pc.addStream(_this.configuration.mediaStream);
+ }
+ if (_this.configuration.mode === 'sendonly' &&
+ (platform.name === 'Chrome' && platform.version.toString().substring(0, 2) === '39')) {
+ _this.configuration.mode = 'sendrecv';
+ }
+ resolve();
+ });
+ };
+ WebRtcPeer.prototype.dispose = function () {
+ var _this = this;
+ console.debug('Disposing WebRtcPeer');
+ try {
+ if (this.pc) {
+ if (this.pc.signalingState === 'closed') {
+ return;
+ }
+ this.remoteCandidatesQueue = [];
+ this.localCandidatesQueue = [];
+ this.pc.getLocalStreams().forEach(function (str) {
+ _this.streamStop(str);
+ });
+ this.pc.close();
+ }
+ }
+ catch (err) {
+ console.warn('Exception disposing webrtc peer ' + err);
+ }
+ };
+ WebRtcPeer.prototype.generateOffer = function () {
+ var _this = this;
+ return new Promise(function (resolve, reject) {
+ var offerAudio, offerVideo = true;
+ if (!!_this.configuration.mediaConstraints) {
+ offerAudio = (typeof _this.configuration.mediaConstraints.audio === 'boolean') ?
+ _this.configuration.mediaConstraints.audio : true;
+ offerVideo = (typeof _this.configuration.mediaConstraints.video === 'boolean') ?
+ _this.configuration.mediaConstraints.video : true;
+ }
+ var constraints = {
+ offerToReceiveAudio: +(_this.configuration.mode !== 'sendonly' && offerAudio),
+ offerToReceiveVideo: +(_this.configuration.mode !== 'sendonly' && offerVideo)
+ };
+ console.debug('RTCPeerConnection constraints: ' + JSON.stringify(constraints));
+ _this.pc.createOffer(constraints).then(function (offer) {
+ console.debug('Created SDP offer');
+ return _this.pc.setLocalDescription(offer);
+ }).then(function () {
+ var localDescription = _this.pc.localDescription;
+ if (!!localDescription) {
+ console.debug('Local description set', localDescription.sdp);
+ resolve(localDescription.sdp);
+ }
+ else {
+ reject('Local description is not defined');
+ }
+ }).catch(function (error) { return reject(error); });
+ });
+ };
+ WebRtcPeer.prototype.processOffer = function (sdpOffer) {
+ var _this = this;
+ return new Promise(function (resolve, reject) {
+ var offer = {
+ type: 'offer',
+ sdp: sdpOffer
+ };
+ console.debug('SDP offer received, setting remote description');
+ if (_this.pc.signalingState === 'closed') {
+ reject('PeerConnection is closed');
+ }
+ _this.pc.setRemoteDescription(offer)
+ .then(function () {
+ return _this.pc.createAnswer();
+ }).then(function (answer) {
+ console.debug('Created SDP answer');
+ return _this.pc.setLocalDescription(answer);
+ }).then(function () {
+ var localDescription = _this.pc.localDescription;
+ if (!!localDescription) {
+ console.debug('Local description set', localDescription.sdp);
+ resolve(localDescription.sdp);
+ }
+ else {
+ reject('Local description is not defined');
+ }
+ }).catch(function (error) { return reject(error); });
+ });
+ };
+ WebRtcPeer.prototype.processAnswer = function (sdpAnswer) {
+ var _this = this;
+ return new Promise(function (resolve, reject) {
+ var answer = {
+ type: 'answer',
+ sdp: sdpAnswer
+ };
+ console.debug('SDP answer received, setting remote description');
+ if (_this.pc.signalingState === 'closed') {
+ reject('RTCPeerConnection is closed');
+ }
+ _this.pc.setRemoteDescription(answer).then(function () { return resolve(); }).catch(function (error) { return reject(error); });
+ });
+ };
+ WebRtcPeer.prototype.addIceCandidate = function (iceCandidate) {
+ var _this = this;
+ return new Promise(function (resolve, reject) {
+ console.debug('Remote ICE candidate received', iceCandidate);
+ _this.remoteCandidatesQueue.push(iceCandidate);
+ switch (_this.pc.signalingState) {
+ case 'closed':
+ reject(new Error('PeerConnection object is closed'));
+ break;
+ case 'stable':
+ if (!!_this.pc.remoteDescription) {
+ _this.pc.addIceCandidate(iceCandidate).then(function () { return resolve(); }).catch(function (error) { return reject(error); });
+ }
+ break;
+ default:
+ _this.iceCandidateList.push(iceCandidate);
+ resolve();
+ }
+ });
+ };
+ WebRtcPeer.prototype.streamStop = function (stream) {
+ stream.getTracks().forEach(function (track) {
+ track.stop();
+ stream.removeTrack(track);
+ });
+ };
+ return WebRtcPeer;
+}());
+exports.WebRtcPeer = WebRtcPeer;
+var WebRtcPeerRecvonly = (function (_super) {
+ __extends(WebRtcPeerRecvonly, _super);
+ function WebRtcPeerRecvonly(configuration) {
+ var _this = this;
+ configuration.mode = 'recvonly';
+ _this = _super.call(this, configuration) || this;
+ return _this;
+ }
+ return WebRtcPeerRecvonly;
+}(WebRtcPeer));
+exports.WebRtcPeerRecvonly = WebRtcPeerRecvonly;
+var WebRtcPeerSendonly = (function (_super) {
+ __extends(WebRtcPeerSendonly, _super);
+ function WebRtcPeerSendonly(configuration) {
+ var _this = this;
+ configuration.mode = 'sendonly';
+ _this = _super.call(this, configuration) || this;
+ return _this;
+ }
+ return WebRtcPeerSendonly;
+}(WebRtcPeer));
+exports.WebRtcPeerSendonly = WebRtcPeerSendonly;
+var WebRtcPeerSendrecv = (function (_super) {
+ __extends(WebRtcPeerSendrecv, _super);
+ function WebRtcPeerSendrecv(configuration) {
+ var _this = this;
+ configuration.mode = 'sendrecv';
+ _this = _super.call(this, configuration) || this;
+ return _this;
+ }
+ return WebRtcPeerSendrecv;
+}(WebRtcPeer));
+exports.WebRtcPeerSendrecv = WebRtcPeerSendrecv;
+
+},{"freeice":2,"platform":8,"uuid":9}],50:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+var platform = require("platform");
+var WebRtcStats = (function () {
+ function WebRtcStats(stream) {
+ this.stream = stream;
+ this.webRtcStatsEnabled = false;
+ this.statsInterval = 1;
+ this.stats = {
+ inbound: {
+ audio: {
+ bytesReceived: 0,
+ packetsReceived: 0,
+ packetsLost: 0
+ },
+ video: {
+ bytesReceived: 0,
+ packetsReceived: 0,
+ packetsLost: 0,
+ framesDecoded: 0,
+ nackCount: 0
+ }
+ },
+ outbound: {
+ audio: {
+ bytesSent: 0,
+ packetsSent: 0,
+ },
+ video: {
+ bytesSent: 0,
+ packetsSent: 0,
+ framesEncoded: 0,
+ nackCount: 0
+ }
+ }
+ };
+ }
+ WebRtcStats.prototype.isEnabled = function () {
+ return this.webRtcStatsEnabled;
+ };
+ WebRtcStats.prototype.initWebRtcStats = function () {
+ var _this = this;
+ var elastestInstrumentation = localStorage.getItem('elastest-instrumentation');
+ if (elastestInstrumentation) {
+ console.warn('WebRtc stats enabled for stream ' + this.stream.streamId + ' of connection ' + this.stream.connection.connectionId);
+ this.webRtcStatsEnabled = true;
+ var instrumentation_1 = JSON.parse(elastestInstrumentation);
+ this.statsInterval = instrumentation_1.webrtc.interval;
+ console.warn('localStorage item: ' + JSON.stringify(instrumentation_1));
+ this.webRtcStatsIntervalId = setInterval(function () {
+ _this.sendStatsToHttpEndpoint(instrumentation_1);
+ }, this.statsInterval * 1000);
+ return;
+ }
+ console.debug('WebRtc stats not enabled');
+ };
+ WebRtcStats.prototype.stopWebRtcStats = function () {
+ if (this.webRtcStatsEnabled) {
+ clearInterval(this.webRtcStatsIntervalId);
+ console.warn('WebRtc stats stopped for disposed stream ' + this.stream.streamId + ' of connection ' + this.stream.connection.connectionId);
+ }
+ };
+ WebRtcStats.prototype.getSelectedIceCandidateInfo = function () {
+ var _this = this;
+ return new Promise(function (resolve, reject) {
+ _this.getStatsAgnostic(_this.stream.getRTCPeerConnection(), function (stats) {
+ if ((platform.name.indexOf('Chrome') !== -1) || (platform.name.indexOf('Opera') !== -1)) {
+ var localCandidateId = void 0, remoteCandidateId = void 0, googCandidatePair = void 0;
+ var localCandidates = {};
+ var remoteCandidates = {};
+ for (var key in stats) {
+ var stat = stats[key];
+ if (stat.type === 'localcandidate') {
+ localCandidates[stat.id] = stat;
+ }
+ else if (stat.type === 'remotecandidate') {
+ remoteCandidates[stat.id] = stat;
+ }
+ else if (stat.type === 'googCandidatePair' && (stat.googActiveConnection === 'true')) {
+ googCandidatePair = stat;
+ localCandidateId = stat.localCandidateId;
+ remoteCandidateId = stat.remoteCandidateId;
+ }
+ }
+ var finalLocalCandidate_1 = localCandidates[localCandidateId];
+ if (!!finalLocalCandidate_1) {
+ var candList = _this.stream.getLocalIceCandidateList();
+ var cand = candList.filter(function (c) {
+ return (!!c.candidate &&
+ c.candidate.indexOf(finalLocalCandidate_1.ipAddress) >= 0 &&
+ c.candidate.indexOf(finalLocalCandidate_1.portNumber) >= 0 &&
+ c.candidate.indexOf(finalLocalCandidate_1.priority) >= 0);
+ });
+ finalLocalCandidate_1.raw = !!cand[0] ? cand[0].candidate : 'ERROR: Cannot find local candidate in list of sent ICE candidates';
+ }
+ else {
+ finalLocalCandidate_1 = 'ERROR: No active local ICE candidate. Probably ICE-TCP is being used';
+ }
+ var finalRemoteCandidate_1 = remoteCandidates[remoteCandidateId];
+ if (!!finalRemoteCandidate_1) {
+ var candList = _this.stream.getRemoteIceCandidateList();
+ var cand = candList.filter(function (c) {
+ return (!!c.candidate &&
+ c.candidate.indexOf(finalRemoteCandidate_1.ipAddress) >= 0 &&
+ c.candidate.indexOf(finalRemoteCandidate_1.portNumber) >= 0 &&
+ c.candidate.indexOf(finalRemoteCandidate_1.priority) >= 0);
+ });
+ finalRemoteCandidate_1.raw = !!cand[0] ? cand[0].candidate : 'ERROR: Cannot find remote candidate in list of received ICE candidates';
+ }
+ else {
+ finalRemoteCandidate_1 = 'ERROR: No active remote ICE candidate. Probably ICE-TCP is being used';
+ }
+ resolve({
+ googCandidatePair: googCandidatePair,
+ localCandidate: finalLocalCandidate_1,
+ remoteCandidate: finalRemoteCandidate_1
+ });
+ }
+ else {
+ reject('Selected ICE candidate info only available for Chrome');
+ }
+ }, function (error) {
+ reject(error);
+ });
+ });
+ };
+ WebRtcStats.prototype.sendStatsToHttpEndpoint = function (instrumentation) {
+ var _this = this;
+ var sendPost = function (json) {
+ var http = new XMLHttpRequest();
+ var url = instrumentation.webrtc.httpEndpoint;
+ http.open('POST', url, true);
+ http.setRequestHeader('Content-type', 'application/json');
+ http.onreadystatechange = function () {
+ if (http.readyState === 4 && http.status === 200) {
+ console.log('WebRtc stats successfully sent to ' + url + ' for stream ' + _this.stream.streamId + ' of connection ' + _this.stream.connection.connectionId);
+ }
+ };
+ http.send(json);
+ };
+ var f = function (stats) {
+ if (platform.name.indexOf('Firefox') !== -1) {
+ stats.forEach(function (stat) {
+ var json = {};
+ if ((stat.type === 'inbound-rtp') &&
+ (stat.nackCount !== null &&
+ stat.isRemote === false &&
+ stat.id.startsWith('inbound') &&
+ stat.remoteId.startsWith('inbound'))) {
+ var metricId = 'webrtc_inbound_' + stat.mediaType + '_' + stat.ssrc;
+ var jit = stat.jitter * 1000;
+ var metrics = {
+ bytesReceived: (stat.bytesReceived - _this.stats.inbound[stat.mediaType].bytesReceived) / _this.statsInterval,
+ jitter: jit,
+ packetsReceived: (stat.packetsReceived - _this.stats.inbound[stat.mediaType].packetsReceived) / _this.statsInterval,
+ packetsLost: (stat.packetsLost - _this.stats.inbound[stat.mediaType].packetsLost) / _this.statsInterval
+ };
+ var units = {
+ bytesReceived: 'bytes',
+ jitter: 'ms',
+ packetsReceived: 'packets',
+ packetsLost: 'packets'
+ };
+ if (stat.mediaType === 'video') {
+ metrics['framesDecoded'] = (stat.framesDecoded - _this.stats.inbound.video.framesDecoded) / _this.statsInterval;
+ metrics['nackCount'] = (stat.nackCount - _this.stats.inbound.video.nackCount) / _this.statsInterval;
+ units['framesDecoded'] = 'frames';
+ units['nackCount'] = 'packets';
+ _this.stats.inbound.video.framesDecoded = stat.framesDecoded;
+ _this.stats.inbound.video.nackCount = stat.nackCount;
+ }
+ _this.stats.inbound[stat.mediaType].bytesReceived = stat.bytesReceived;
+ _this.stats.inbound[stat.mediaType].packetsReceived = stat.packetsReceived;
+ _this.stats.inbound[stat.mediaType].packetsLost = stat.packetsLost;
+ json = {
+ '@timestamp': new Date(stat.timestamp).toISOString(),
+ 'exec': instrumentation.exec,
+ 'component': instrumentation.component,
+ 'stream': 'webRtc',
+ 'type': metricId,
+ 'stream_type': 'composed_metrics',
+ 'units': units
+ };
+ json[metricId] = metrics;
+ sendPost(JSON.stringify(json));
+ }
+ else if ((stat.type === 'outbound-rtp') &&
+ (stat.isRemote === false &&
+ stat.id.toLowerCase().includes('outbound'))) {
+ var metricId = 'webrtc_outbound_' + stat.mediaType + '_' + stat.ssrc;
+ var metrics = {
+ bytesSent: (stat.bytesSent - _this.stats.outbound[stat.mediaType].bytesSent) / _this.statsInterval,
+ packetsSent: (stat.packetsSent - _this.stats.outbound[stat.mediaType].packetsSent) / _this.statsInterval
+ };
+ var units = {
+ bytesSent: 'bytes',
+ packetsSent: 'packets'
+ };
+ if (stat.mediaType === 'video') {
+ metrics['framesEncoded'] = (stat.framesEncoded - _this.stats.outbound.video.framesEncoded) / _this.statsInterval;
+ units['framesEncoded'] = 'frames';
+ _this.stats.outbound.video.framesEncoded = stat.framesEncoded;
+ }
+ _this.stats.outbound[stat.mediaType].bytesSent = stat.bytesSent;
+ _this.stats.outbound[stat.mediaType].packetsSent = stat.packetsSent;
+ json = {
+ '@timestamp': new Date(stat.timestamp).toISOString(),
+ 'exec': instrumentation.exec,
+ 'component': instrumentation.component,
+ 'stream': 'webRtc',
+ 'type': metricId,
+ 'stream_type': 'composed_metrics',
+ 'units': units
+ };
+ json[metricId] = metrics;
+ sendPost(JSON.stringify(json));
+ }
+ });
+ }
+ else if ((platform.name.indexOf('Chrome') !== -1) || (platform.name.indexOf('Opera') !== -1)) {
+ for (var _i = 0, _a = Object.keys(stats); _i < _a.length; _i++) {
+ var key = _a[_i];
+ var stat = stats[key];
+ if (stat.type === 'ssrc') {
+ var json = {};
+ if ('bytesReceived' in stat && ((stat.mediaType === 'audio' && 'audioOutputLevel' in stat) ||
+ (stat.mediaType === 'video' && 'qpSum' in stat))) {
+ var metricId = 'webrtc_inbound_' + stat.mediaType + '_' + stat.ssrc;
+ var metrics = {
+ bytesReceived: (stat.bytesReceived - _this.stats.inbound[stat.mediaType].bytesReceived) / _this.statsInterval,
+ jitter: stat.googJitterBufferMs,
+ packetsReceived: (stat.packetsReceived - _this.stats.inbound[stat.mediaType].packetsReceived) / _this.statsInterval,
+ packetsLost: (stat.packetsLost - _this.stats.inbound[stat.mediaType].packetsLost) / _this.statsInterval
+ };
+ var units = {
+ bytesReceived: 'bytes',
+ jitter: 'ms',
+ packetsReceived: 'packets',
+ packetsLost: 'packets'
+ };
+ if (stat.mediaType === 'video') {
+ metrics['framesDecoded'] = (stat.framesDecoded - _this.stats.inbound.video.framesDecoded) / _this.statsInterval;
+ metrics['nackCount'] = (stat.googNacksSent - _this.stats.inbound.video.nackCount) / _this.statsInterval;
+ units['framesDecoded'] = 'frames';
+ units['nackCount'] = 'packets';
+ _this.stats.inbound.video.framesDecoded = stat.framesDecoded;
+ _this.stats.inbound.video.nackCount = stat.googNacksSent;
+ }
+ _this.stats.inbound[stat.mediaType].bytesReceived = stat.bytesReceived;
+ _this.stats.inbound[stat.mediaType].packetsReceived = stat.packetsReceived;
+ _this.stats.inbound[stat.mediaType].packetsLost = stat.packetsLost;
+ json = {
+ '@timestamp': new Date(stat.timestamp).toISOString(),
+ 'exec': instrumentation.exec,
+ 'component': instrumentation.component,
+ 'stream': 'webRtc',
+ 'type': metricId,
+ 'stream_type': 'composed_metrics',
+ 'units': units
+ };
+ json[metricId] = metrics;
+ sendPost(JSON.stringify(json));
+ }
+ else if ('bytesSent' in stat) {
+ var metricId = 'webrtc_outbound_' + stat.mediaType + '_' + stat.ssrc;
+ var metrics = {
+ bytesSent: (stat.bytesSent - _this.stats.outbound[stat.mediaType].bytesSent) / _this.statsInterval,
+ packetsSent: (stat.packetsSent - _this.stats.outbound[stat.mediaType].packetsSent) / _this.statsInterval
+ };
+ var units = {
+ bytesSent: 'bytes',
+ packetsSent: 'packets'
+ };
+ if (stat.mediaType === 'video') {
+ metrics['framesEncoded'] = (stat.framesEncoded - _this.stats.outbound.video.framesEncoded) / _this.statsInterval;
+ units['framesEncoded'] = 'frames';
+ _this.stats.outbound.video.framesEncoded = stat.framesEncoded;
+ }
+ _this.stats.outbound[stat.mediaType].bytesSent = stat.bytesSent;
+ _this.stats.outbound[stat.mediaType].packetsSent = stat.packetsSent;
+ json = {
+ '@timestamp': new Date(stat.timestamp).toISOString(),
+ 'exec': instrumentation.exec,
+ 'component': instrumentation.component,
+ 'stream': 'webRtc',
+ 'type': metricId,
+ 'stream_type': 'composed_metrics',
+ 'units': units
+ };
+ json[metricId] = metrics;
+ sendPost(JSON.stringify(json));
+ }
+ }
+ }
+ }
+ };
+ this.getStatsAgnostic(this.stream.getRTCPeerConnection(), f, function (error) { console.log(error); });
+ };
+ WebRtcStats.prototype.standardizeReport = function (response) {
+ console.log(response);
+ var standardReport = {};
+ if (platform.name.indexOf('Firefox') !== -1) {
+ Object.keys(response).forEach(function (key) {
+ console.log(response[key]);
+ });
+ return response;
+ }
+ response.result().forEach(function (report) {
+ var standardStats = {
+ id: report.id,
+ timestamp: report.timestamp,
+ type: report.type
+ };
+ report.names().forEach(function (name) {
+ standardStats[name] = report.stat(name);
+ });
+ standardReport[standardStats.id] = standardStats;
+ });
+ return standardReport;
+ };
+ WebRtcStats.prototype.getStatsAgnostic = function (pc, successCb, failureCb) {
+ var _this = this;
+ if (platform.name.indexOf('Firefox') !== -1) {
+ return pc.getStats(null).then(function (response) {
+ var report = _this.standardizeReport(response);
+ successCb(report);
+ }).catch(failureCb);
+ }
+ else if ((platform.name.indexOf('Chrome') !== -1) || (platform.name.indexOf('Opera') !== -1)) {
+ return pc.getStats(function (response) {
+ var report = _this.standardizeReport(response);
+ successCb(report);
+ }, null, failureCb);
+ }
+ };
+ return WebRtcStats;
+}());
+exports.WebRtcStats = WebRtcStats;
+
+},{"platform":8}]},{},[16])
+//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL25vZGVfbW9kdWxlcy9icm93c2VyLXBhY2svX3ByZWx1ZGUuanMiLCIuLi9ub2RlX21vZHVsZXMvZXZlbnRzL2V2ZW50cy5qcyIsIi4uL25vZGVfbW9kdWxlcy9mcmVlaWNlL2luZGV4LmpzIiwiLi4vbm9kZV9tb2R1bGVzL2ZyZWVpY2Uvc3R1bi5qc29uIiwiLi4vbm9kZV9tb2R1bGVzL2ZyZWVpY2UvdHVybi5qc29uIiwiLi4vbm9kZV9tb2R1bGVzL2hhcmsvaGFyay5qcyIsIi4uL25vZGVfbW9kdWxlcy9pbmhlcml0cy9pbmhlcml0c19icm93c2VyLmpzIiwiLi4vbm9kZV9tb2R1bGVzL25vcm1hbGljZS9pbmRleC5qcyIsIi4uL25vZGVfbW9kdWxlcy9wbGF0Zm9ybS9wbGF0Zm9ybS5qcyIsIi4uL25vZGVfbW9kdWxlcy91dWlkL2luZGV4LmpzIiwiLi4vbm9kZV9tb2R1bGVzL3V1aWQvbGliL2J5dGVzVG9VdWlkLmpzIiwiLi4vbm9kZV9tb2R1bGVzL3V1aWQvbGliL3JuZy1icm93c2VyLmpzIiwiLi4vbm9kZV9tb2R1bGVzL3V1aWQvdjEuanMiLCIuLi9ub2RlX21vZHVsZXMvdXVpZC92NC5qcyIsIi4uL25vZGVfbW9kdWxlcy93aWxkZW1pdHRlci93aWxkZW1pdHRlci5qcyIsIi4uL25vZGVfbW9kdWxlcy93b2xmeTg3LWV2ZW50ZW1pdHRlci9FdmVudEVtaXR0ZXIuanMiLCJNYWluLnRzIiwiT3BlblZpZHUvQ29ubmVjdGlvbi50cyIsIk9wZW5WaWR1L0xvY2FsUmVjb3JkZXIudHMiLCJPcGVuVmlkdS9PcGVuVmlkdS50cyIsIk9wZW5WaWR1L1B1Ymxpc2hlci50cyIsIk9wZW5WaWR1L1Nlc3Npb24udHMiLCJPcGVuVmlkdS9TdHJlYW0udHMiLCJPcGVuVmlkdS9TdHJlYW1NYW5hZ2VyLnRzIiwiT3BlblZpZHUvU3Vic2NyaWJlci50cyIsIk9wZW5WaWR1SW50ZXJuYWwvRW51bXMvTG9jYWxSZWNvcmRlclN0YXRlLnRzIiwiT3BlblZpZHVJbnRlcm5hbC9FbnVtcy9PcGVuVmlkdUVycm9yLnRzIiwiT3BlblZpZHVJbnRlcm5hbC9FbnVtcy9WaWRlb0luc2VydE1vZGUudHMiLCJPcGVuVmlkdUludGVybmFsL0V2ZW50cy9Db25uZWN0aW9uRXZlbnQudHMiLCJPcGVuVmlkdUludGVybmFsL0V2ZW50cy9FdmVudC50cyIsIk9wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1B1Ymxpc2hlclNwZWFraW5nRXZlbnQudHMiLCJPcGVuVmlkdUludGVybmFsL0V2ZW50cy9SZWNvcmRpbmdFdmVudC50cyIsIk9wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1Nlc3Npb25EaXNjb25uZWN0ZWRFdmVudC50cyIsIk9wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1NpZ25hbEV2ZW50LnRzIiwiT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvU3RyZWFtRXZlbnQudHMiLCJPcGVuVmlkdUludGVybmFsL0V2ZW50cy9TdHJlYW1NYW5hZ2VyRXZlbnQudHMiLCJPcGVuVmlkdUludGVybmFsL0V2ZW50cy9TdHJlYW1Qcm9wZXJ0eUNoYW5nZWRFdmVudC50cyIsIk9wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1ZpZGVvRWxlbWVudEV2ZW50LnRzIiwiT3BlblZpZHVJbnRlcm5hbC9LdXJlbnRvVXRpbHMva3VyZW50by1qc29ucnBjL01hcHBlci5qcyIsIk9wZW5WaWR1SW50ZXJuYWwvS3VyZW50b1V0aWxzL2t1cmVudG8tanNvbnJwYy9jbGllbnRzL2luZGV4LmpzIiwiT3BlblZpZHVJbnRlcm5hbC9LdXJlbnRvVXRpbHMva3VyZW50by1qc29ucnBjL2NsaWVudHMvanNvbnJwY2NsaWVudC5qcyIsIk9wZW5WaWR1SW50ZXJuYWwvS3VyZW50b1V0aWxzL2t1cmVudG8tanNvbnJwYy9jbGllbnRzL3RyYW5zcG9ydHMvaW5kZXguanMiLCJPcGVuVmlkdUludGVybmFsL0t1cmVudG9VdGlscy9rdXJlbnRvLWpzb25ycGMvY2xpZW50cy90cmFuc3BvcnRzL3dlYlNvY2tldFdpdGhSZWNvbm5lY3Rpb24uanMiLCJPcGVuVmlkdUludGVybmFsL0t1cmVudG9VdGlscy9rdXJlbnRvLWpzb25ycGMvaW5kZXguanMiLCJPcGVuVmlkdUludGVybmFsL0t1cmVudG9VdGlscy9rdXJlbnRvLWpzb25ycGMvcGFja2Vycy9Kc29uUlBDLmpzIiwiT3BlblZpZHVJbnRlcm5hbC9LdXJlbnRvVXRpbHMva3VyZW50by1qc29ucnBjL3BhY2tlcnMvWG1sUlBDLmpzIiwiT3BlblZpZHVJbnRlcm5hbC9LdXJlbnRvVXRpbHMva3VyZW50by1qc29ucnBjL3BhY2tlcnMvaW5kZXguanMiLCJPcGVuVmlkdUludGVybmFsL1NjcmVlblNoYXJpbmcvU2NyZWVuLUNhcHR1cmluZy1BdXRvLmpzIiwiT3BlblZpZHVJbnRlcm5hbC9TY3JlZW5TaGFyaW5nL1NjcmVlbi1DYXB0dXJpbmcuanMiLCJPcGVuVmlkdUludGVybmFsL1dlYlJ0Y1BlZXIvV2ViUnRjUGVlci50cyIsIk9wZW5WaWR1SW50ZXJuYWwvV2ViUnRjU3RhdHMvV2ViUnRjU3RhdHMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7QUNBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzNnQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDekdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDaEJBO0FBQ0E7O0FDREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2xKQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdkJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUM1REE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7O0FDanNDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDUkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDeEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbENBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDN0dBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM3QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDekpBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7O0FDdGVBLGdEQUErQztBQUUvQyxJQUFJLE1BQU0s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bigpe2Z1bmN0aW9uIHIoZSxuLHQpe2Z1bmN0aW9uIG8oaSxmKXtpZighbltpXSl7aWYoIWVbaV0pe3ZhciBjPVwiZnVuY3Rpb25cIj09dHlwZW9mIHJlcXVpcmUmJnJlcXVpcmU7aWYoIWYmJmMpcmV0dXJuIGMoaSwhMCk7aWYodSlyZXR1cm4gdShpLCEwKTt2YXIgYT1uZXcgRXJyb3IoXCJDYW5ub3QgZmluZCBtb2R1bGUgJ1wiK2krXCInXCIpO3Rocm93IGEuY29kZT1cIk1PRFVMRV9OT1RfRk9VTkRcIixhfXZhciBwPW5baV09e2V4cG9ydHM6e319O2VbaV1bMF0uY2FsbChwLmV4cG9ydHMsZnVuY3Rpb24ocil7dmFyIG49ZVtpXVsxXVtyXTtyZXR1cm4gbyhufHxyKX0scCxwLmV4cG9ydHMscixlLG4sdCl9cmV0dXJuIG5baV0uZXhwb3J0c31mb3IodmFyIHU9XCJmdW5jdGlvblwiPT10eXBlb2YgcmVxdWlyZSYmcmVxdWlyZSxpPTA7aTx0Lmxlbmd0aDtpKyspbyh0W2ldKTtyZXR1cm4gb31yZXR1cm4gcn0pKCkiLCIvLyBDb3B5cmlnaHQgSm95ZW50LCBJbmMuIGFuZCBvdGhlciBOb2RlIGNvbnRyaWJ1dG9ycy5cbi8vXG4vLyBQZXJtaXNzaW9uIGlzIGhlcmVieSBncmFudGVkLCBmcmVlIG9mIGNoYXJnZSwgdG8gYW55IHBlcnNvbiBvYnRhaW5pbmcgYVxuLy8gY29weSBvZiB0aGlzIHNvZnR3YXJlIGFuZCBhc3NvY2lhdGVkIGRvY3VtZW50YXRpb24gZmlsZXMgKHRoZVxuLy8gXCJTb2Z0d2FyZVwiKSwgdG8gZGVhbCBpbiB0aGUgU29mdHdhcmUgd2l0aG91dCByZXN0cmljdGlvbiwgaW5jbHVkaW5nXG4vLyB3aXRob3V0IGxpbWl0YXRpb24gdGhlIHJpZ2h0cyB0byB1c2UsIGNvcHksIG1vZGlmeSwgbWVyZ2UsIHB1Ymxpc2gsXG4vLyBkaXN0cmlidXRlLCBzdWJsaWNlbnNlLCBhbmQvb3Igc2VsbCBjb3BpZXMgb2YgdGhlIFNvZnR3YXJlLCBhbmQgdG8gcGVybWl0XG4vLyBwZXJzb25zIHRvIHdob20gdGhlIFNvZnR3YXJlIGlzIGZ1cm5pc2hlZCB0byBkbyBzbywgc3ViamVjdCB0byB0aGVcbi8vIGZvbGxvd2luZyBjb25kaXRpb25zOlxuLy9cbi8vIFRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlIGFuZCB0aGlzIHBlcm1pc3Npb24gbm90aWNlIHNoYWxsIGJlIGluY2x1ZGVkXG4vLyBpbiBhbGwgY29waWVzIG9yIHN1YnN0YW50aWFsIHBvcnRpb25zIG9mIHRoZSBTb2Z0d2FyZS5cbi8vXG4vLyBUSEUgU09GVFdBUkUgSVMgUFJPVklERUQgXCJBUyBJU1wiLCBXSVRIT1VUIFdBUlJBTlRZIE9GIEFOWSBLSU5ELCBFWFBSRVNTXG4vLyBPUiBJTVBMSUVELCBJTkNMVURJTkcgQlVUIE5PVCBMSU1JVEVEIFRPIFRIRSBXQVJSQU5USUVTIE9GXG4vLyBNRVJDSEFOVEFCSUxJVFksIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFORCBOT05JTkZSSU5HRU1FTlQuIElOXG4vLyBOTyBFVkVOVCBTSEFMTCBUSEUgQVVUSE9SUyBPUiBDT1BZUklHSFQgSE9MREVSUyBCRSBMSUFCTEUgRk9SIEFOWSBDTEFJTSxcbi8vIERBTUFHRVMgT1IgT1RIRVIgTElBQklMSVRZLCBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgVE9SVCBPUlxuLy8gT1RIRVJXSVNFLCBBUklTSU5HIEZST00sIE9VVCBPRiBPUiBJTiBDT05ORUNUSU9OIFdJVEggVEhFIFNPRlRXQVJFIE9SIFRIRVxuLy8gVVNFIE9SIE9USEVSIERFQUxJTkdTIElOIFRIRSBTT0ZUV0FSRS5cblxudmFyIG9iamVjdENyZWF0ZSA9IE9iamVjdC5jcmVhdGUgfHwgb2JqZWN0Q3JlYXRlUG9seWZpbGxcbnZhciBvYmplY3RLZXlzID0gT2JqZWN0LmtleXMgfHwgb2JqZWN0S2V5c1BvbHlmaWxsXG52YXIgYmluZCA9IEZ1bmN0aW9uLnByb3RvdHlwZS5iaW5kIHx8IGZ1bmN0aW9uQmluZFBvbHlmaWxsXG5cbmZ1bmN0aW9uIEV2ZW50RW1pdHRlcigpIHtcbiAgaWYgKCF0aGlzLl9ldmVudHMgfHwgIU9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbCh0aGlzLCAnX2V2ZW50cycpKSB7XG4gICAgdGhpcy5fZXZlbnRzID0gb2JqZWN0Q3JlYXRlKG51bGwpO1xuICAgIHRoaXMuX2V2ZW50c0NvdW50ID0gMDtcbiAgfVxuXG4gIHRoaXMuX21heExpc3RlbmVycyA9IHRoaXMuX21heExpc3RlbmVycyB8fCB1bmRlZmluZWQ7XG59XG5tb2R1bGUuZXhwb3J0cyA9IEV2ZW50RW1pdHRlcjtcblxuLy8gQmFja3dhcmRzLWNvbXBhdCB3aXRoIG5vZGUgMC4xMC54XG5FdmVudEVtaXR0ZXIuRXZlbnRFbWl0dGVyID0gRXZlbnRFbWl0dGVyO1xuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLl9ldmVudHMgPSB1bmRlZmluZWQ7XG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLl9tYXhMaXN0ZW5lcnMgPSB1bmRlZmluZWQ7XG5cbi8vIEJ5IGRlZmF1bHQgRXZlbnRFbWl0dGVycyB3aWxsIHByaW50IGEgd2FybmluZyBpZiBtb3JlIHRoYW4gMTAgbGlzdGVuZXJzIGFyZVxuLy8gYWRkZWQgdG8gaXQuIFRoaXMgaXMgYSB1c2VmdWwgZGVmYXVsdCB3aGljaCBoZWxwcyBmaW5kaW5nIG1lbW9yeSBsZWFrcy5cbnZhciBkZWZhdWx0TWF4TGlzdGVuZXJzID0gMTA7XG5cbnZhciBoYXNEZWZpbmVQcm9wZXJ0eTtcbnRyeSB7XG4gIHZhciBvID0ge307XG4gIGlmIChPYmplY3QuZGVmaW5lUHJvcGVydHkpIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShvLCAneCcsIHsgdmFsdWU6IDAgfSk7XG4gIGhhc0RlZmluZVByb3BlcnR5ID0gby54ID09PSAwO1xufSBjYXRjaCAoZXJyKSB7IGhhc0RlZmluZVByb3BlcnR5ID0gZmFsc2UgfVxuaWYgKGhhc0RlZmluZVByb3BlcnR5KSB7XG4gIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShFdmVudEVtaXR0ZXIsICdkZWZhdWx0TWF4TGlzdGVuZXJzJywge1xuICAgIGVudW1lcmFibGU6IHRydWUsXG4gICAgZ2V0OiBmdW5jdGlvbigpIHtcbiAgICAgIHJldHVybiBkZWZhdWx0TWF4TGlzdGVuZXJzO1xuICAgIH0sXG4gICAgc2V0OiBmdW5jdGlvbihhcmcpIHtcbiAgICAgIC8vIGNoZWNrIHdoZXRoZXIgdGhlIGlucHV0IGlzIGEgcG9zaXRpdmUgbnVtYmVyICh3aG9zZSB2YWx1ZSBpcyB6ZXJvIG9yXG4gICAgICAvLyBncmVhdGVyIGFuZCBub3QgYSBOYU4pLlxuICAgICAgaWYgKHR5cGVvZiBhcmcgIT09ICdudW1iZXInIHx8IGFyZyA8IDAgfHwgYXJnICE9PSBhcmcpXG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ1wiZGVmYXVsdE1heExpc3RlbmVyc1wiIG11c3QgYmUgYSBwb3NpdGl2ZSBudW1iZXInKTtcbiAgICAgIGRlZmF1bHRNYXhMaXN0ZW5lcnMgPSBhcmc7XG4gICAgfVxuICB9KTtcbn0gZWxzZSB7XG4gIEV2ZW50RW1pdHRlci5kZWZhdWx0TWF4TGlzdGVuZXJzID0gZGVmYXVsdE1heExpc3RlbmVycztcbn1cblxuLy8gT2J2aW91c2x5IG5vdCBhbGwgRW1pdHRlcnMgc2hvdWxkIGJlIGxpbWl0ZWQgdG8gMTAuIFRoaXMgZnVuY3Rpb24gYWxsb3dzXG4vLyB0aGF0IHRvIGJlIGluY3JlYXNlZC4gU2V0IHRvIHplcm8gZm9yIHVubGltaXRlZC5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUuc2V0TWF4TGlzdGVuZXJzID0gZnVuY3Rpb24gc2V0TWF4TGlzdGVuZXJzKG4pIHtcbiAgaWYgKHR5cGVvZiBuICE9PSAnbnVtYmVyJyB8fCBuIDwgMCB8fCBpc05hTihuKSlcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdcIm5cIiBhcmd1bWVudCBtdXN0IGJlIGEgcG9zaXRpdmUgbnVtYmVyJyk7XG4gIHRoaXMuX21heExpc3RlbmVycyA9IG47XG4gIHJldHVybiB0aGlzO1xufTtcblxuZnVuY3Rpb24gJGdldE1heExpc3RlbmVycyh0aGF0KSB7XG4gIGlmICh0aGF0Ll9tYXhMaXN0ZW5lcnMgPT09IHVuZGVmaW5lZClcbiAgICByZXR1cm4gRXZlbnRFbWl0dGVyLmRlZmF1bHRNYXhMaXN0ZW5lcnM7XG4gIHJldHVybiB0aGF0Ll9tYXhMaXN0ZW5lcnM7XG59XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUuZ2V0TWF4TGlzdGVuZXJzID0gZnVuY3Rpb24gZ2V0TWF4TGlzdGVuZXJzKCkge1xuICByZXR1cm4gJGdldE1heExpc3RlbmVycyh0aGlzKTtcbn07XG5cbi8vIFRoZXNlIHN0YW5kYWxvbmUgZW1pdCogZnVuY3Rpb25zIGFyZSB1c2VkIHRvIG9wdGltaXplIGNhbGxpbmcgb2YgZXZlbnRcbi8vIGhhbmRsZXJzIGZvciBmYXN0IGNhc2VzIGJlY2F1c2UgZW1pdCgpIGl0c2VsZiBvZnRlbiBoYXMgYSB2YXJpYWJsZSBudW1iZXIgb2Zcbi8vIGFyZ3VtZW50cyBhbmQgY2FuIGJlIGRlb3B0aW1pemVkIGJlY2F1c2Ugb2YgdGhhdC4gVGhlc2UgZnVuY3Rpb25zIGFsd2F5cyBoYXZlXG4vLyB0aGUgc2FtZSBudW1iZXIgb2YgYXJndW1lbnRzIGFuZCB0aHVzIGRvIG5vdCBnZXQgZGVvcHRpbWl6ZWQsIHNvIHRoZSBjb2RlXG4vLyBpbnNpZGUgdGhlbSBjYW4gZXhlY3V0ZSBmYXN0ZXIuXG5mdW5jdGlvbiBlbWl0Tm9uZShoYW5kbGVyLCBpc0ZuLCBzZWxmKSB7XG4gIGlmIChpc0ZuKVxuICAgIGhhbmRsZXIuY2FsbChzZWxmKTtcbiAgZWxzZSB7XG4gICAgdmFyIGxlbiA9IGhhbmRsZXIubGVuZ3RoO1xuICAgIHZhciBsaXN0ZW5lcnMgPSBhcnJheUNsb25lKGhhbmRsZXIsIGxlbik7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW47ICsraSlcbiAgICAgIGxpc3RlbmVyc1tpXS5jYWxsKHNlbGYpO1xuICB9XG59XG5mdW5jdGlvbiBlbWl0T25lKGhhbmRsZXIsIGlzRm4sIHNlbGYsIGFyZzEpIHtcbiAgaWYgKGlzRm4pXG4gICAgaGFuZGxlci5jYWxsKHNlbGYsIGFyZzEpO1xuICBlbHNlIHtcbiAgICB2YXIgbGVuID0gaGFuZGxlci5sZW5ndGg7XG4gICAgdmFyIGxpc3RlbmVycyA9IGFycmF5Q2xvbmUoaGFuZGxlciwgbGVuKTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgKytpKVxuICAgICAgbGlzdGVuZXJzW2ldLmNhbGwoc2VsZiwgYXJnMSk7XG4gIH1cbn1cbmZ1bmN0aW9uIGVtaXRUd28oaGFuZGxlciwgaXNGbiwgc2VsZiwgYXJnMSwgYXJnMikge1xuICBpZiAoaXNGbilcbiAgICBoYW5kbGVyLmNhbGwoc2VsZiwgYXJnMSwgYXJnMik7XG4gIGVsc2Uge1xuICAgIHZhciBsZW4gPSBoYW5kbGVyLmxlbmd0aDtcbiAgICB2YXIgbGlzdGVuZXJzID0gYXJyYXlDbG9uZShoYW5kbGVyLCBsZW4pO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuOyArK2kpXG4gICAgICBsaXN0ZW5lcnNbaV0uY2FsbChzZWxmLCBhcmcxLCBhcmcyKTtcbiAgfVxufVxuZnVuY3Rpb24gZW1pdFRocmVlKGhhbmRsZXIsIGlzRm4sIHNlbGYsIGFyZzEsIGFyZzIsIGFyZzMpIHtcbiAgaWYgKGlzRm4pXG4gICAgaGFuZGxlci5jYWxsKHNlbGYsIGFyZzEsIGFyZzIsIGFyZzMpO1xuICBlbHNlIHtcbiAgICB2YXIgbGVuID0gaGFuZGxlci5sZW5ndGg7XG4gICAgdmFyIGxpc3RlbmVycyA9IGFycmF5Q2xvbmUoaGFuZGxlciwgbGVuKTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgKytpKVxuICAgICAgbGlzdGVuZXJzW2ldLmNhbGwoc2VsZiwgYXJnMSwgYXJnMiwgYXJnMyk7XG4gIH1cbn1cblxuZnVuY3Rpb24gZW1pdE1hbnkoaGFuZGxlciwgaXNGbiwgc2VsZiwgYXJncykge1xuICBpZiAoaXNGbilcbiAgICBoYW5kbGVyLmFwcGx5KHNlbGYsIGFyZ3MpO1xuICBlbHNlIHtcbiAgICB2YXIgbGVuID0gaGFuZGxlci5sZW5ndGg7XG4gICAgdmFyIGxpc3RlbmVycyA9IGFycmF5Q2xvbmUoaGFuZGxlciwgbGVuKTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgKytpKVxuICAgICAgbGlzdGVuZXJzW2ldLmFwcGx5KHNlbGYsIGFyZ3MpO1xuICB9XG59XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUuZW1pdCA9IGZ1bmN0aW9uIGVtaXQodHlwZSkge1xuICB2YXIgZXIsIGhhbmRsZXIsIGxlbiwgYXJncywgaSwgZXZlbnRzO1xuICB2YXIgZG9FcnJvciA9ICh0eXBlID09PSAnZXJyb3InKTtcblxuICBldmVudHMgPSB0aGlzLl9ldmVudHM7XG4gIGlmIChldmVudHMpXG4gICAgZG9FcnJvciA9IChkb0Vycm9yICYmIGV2ZW50cy5lcnJvciA9PSBudWxsKTtcbiAgZWxzZSBpZiAoIWRvRXJyb3IpXG4gICAgcmV0dXJuIGZhbHNlO1xuXG4gIC8vIElmIHRoZXJlIGlzIG5vICdlcnJvcicgZXZlbnQgbGlzdGVuZXIgdGhlbiB0aHJvdy5cbiAgaWYgKGRvRXJyb3IpIHtcbiAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA+IDEpXG4gICAgICBlciA9IGFyZ3VtZW50c1sxXTtcbiAgICBpZiAoZXIgaW5zdGFuY2VvZiBFcnJvcikge1xuICAgICAgdGhyb3cgZXI7IC8vIFVuaGFuZGxlZCAnZXJyb3InIGV2ZW50XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIEF0IGxlYXN0IGdpdmUgc29tZSBraW5kIG9mIGNvbnRleHQgdG8gdGhlIHVzZXJcbiAgICAgIHZhciBlcnIgPSBuZXcgRXJyb3IoJ1VuaGFuZGxlZCBcImVycm9yXCIgZXZlbnQuICgnICsgZXIgKyAnKScpO1xuICAgICAgZXJyLmNvbnRleHQgPSBlcjtcbiAgICAgIHRocm93IGVycjtcbiAgICB9XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgaGFuZGxlciA9IGV2ZW50c1t0eXBlXTtcblxuICBpZiAoIWhhbmRsZXIpXG4gICAgcmV0dXJuIGZhbHNlO1xuXG4gIHZhciBpc0ZuID0gdHlwZW9mIGhhbmRsZXIgPT09ICdmdW5jdGlvbic7XG4gIGxlbiA9IGFyZ3VtZW50cy5sZW5ndGg7XG4gIHN3aXRjaCAobGVuKSB7XG4gICAgICAvLyBmYXN0IGNhc2VzXG4gICAgY2FzZSAxOlxuICAgICAgZW1pdE5vbmUoaGFuZGxlciwgaXNGbiwgdGhpcyk7XG4gICAgICBicmVhaztcbiAgICBjYXNlIDI6XG4gICAgICBlbWl0T25lKGhhbmRsZXIsIGlzRm4sIHRoaXMsIGFyZ3VtZW50c1sxXSk7XG4gICAgICBicmVhaztcbiAgICBjYXNlIDM6XG4gICAgICBlbWl0VHdvKGhhbmRsZXIsIGlzRm4sIHRoaXMsIGFyZ3VtZW50c1sxXSwgYXJndW1lbnRzWzJdKTtcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgNDpcbiAgICAgIGVtaXRUaHJlZShoYW5kbGVyLCBpc0ZuLCB0aGlzLCBhcmd1bWVudHNbMV0sIGFyZ3VtZW50c1syXSwgYXJndW1lbnRzWzNdKTtcbiAgICAgIGJyZWFrO1xuICAgICAgLy8gc2xvd2VyXG4gICAgZGVmYXVsdDpcbiAgICAgIGFyZ3MgPSBuZXcgQXJyYXkobGVuIC0gMSk7XG4gICAgICBmb3IgKGkgPSAxOyBpIDwgbGVuOyBpKyspXG4gICAgICAgIGFyZ3NbaSAtIDFdID0gYXJndW1lbnRzW2ldO1xuICAgICAgZW1pdE1hbnkoaGFuZGxlciwgaXNGbiwgdGhpcywgYXJncyk7XG4gIH1cblxuICByZXR1cm4gdHJ1ZTtcbn07XG5cbmZ1bmN0aW9uIF9hZGRMaXN0ZW5lcih0YXJnZXQsIHR5cGUsIGxpc3RlbmVyLCBwcmVwZW5kKSB7XG4gIHZhciBtO1xuICB2YXIgZXZlbnRzO1xuICB2YXIgZXhpc3Rpbmc7XG5cbiAgaWYgKHR5cGVvZiBsaXN0ZW5lciAhPT0gJ2Z1bmN0aW9uJylcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdcImxpc3RlbmVyXCIgYXJndW1lbnQgbXVzdCBiZSBhIGZ1bmN0aW9uJyk7XG5cbiAgZXZlbnRzID0gdGFyZ2V0Ll9ldmVudHM7XG4gIGlmICghZXZlbnRzKSB7XG4gICAgZXZlbnRzID0gdGFyZ2V0Ll9ldmVudHMgPSBvYmplY3RDcmVhdGUobnVsbCk7XG4gICAgdGFyZ2V0Ll9ldmVudHNDb3VudCA9IDA7XG4gIH0gZWxzZSB7XG4gICAgLy8gVG8gYXZvaWQgcmVjdXJzaW9uIGluIHRoZSBjYXNlIHRoYXQgdHlwZSA9PT0gXCJuZXdMaXN0ZW5lclwiISBCZWZvcmVcbiAgICAvLyBhZGRpbmcgaXQgdG8gdGhlIGxpc3RlbmVycywgZmlyc3QgZW1pdCBcIm5ld0xpc3RlbmVyXCIuXG4gICAgaWYgKGV2ZW50cy5uZXdMaXN0ZW5lcikge1xuICAgICAgdGFyZ2V0LmVtaXQoJ25ld0xpc3RlbmVyJywgdHlwZSxcbiAgICAgICAgICBsaXN0ZW5lci5saXN0ZW5lciA/IGxpc3RlbmVyLmxpc3RlbmVyIDogbGlzdGVuZXIpO1xuXG4gICAgICAvLyBSZS1hc3NpZ24gYGV2ZW50c2AgYmVjYXVzZSBhIG5ld0xpc3RlbmVyIGhhbmRsZXIgY291bGQgaGF2ZSBjYXVzZWQgdGhlXG4gICAgICAvLyB0aGlzLl9ldmVudHMgdG8gYmUgYXNzaWduZWQgdG8gYSBuZXcgb2JqZWN0XG4gICAgICBldmVudHMgPSB0YXJnZXQuX2V2ZW50cztcbiAgICB9XG4gICAgZXhpc3RpbmcgPSBldmVudHNbdHlwZV07XG4gIH1cblxuICBpZiAoIWV4aXN0aW5nKSB7XG4gICAgLy8gT3B0aW1pemUgdGhlIGNhc2Ugb2Ygb25lIGxpc3RlbmVyLiBEb24ndCBuZWVkIHRoZSBleHRyYSBhcnJheSBvYmplY3QuXG4gICAgZXhpc3RpbmcgPSBldmVudHNbdHlwZV0gPSBsaXN0ZW5lcjtcbiAgICArK3RhcmdldC5fZXZlbnRzQ291bnQ7XG4gIH0gZWxzZSB7XG4gICAgaWYgKHR5cGVvZiBleGlzdGluZyA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgLy8gQWRkaW5nIHRoZSBzZWNvbmQgZWxlbWVudCwgbmVlZCB0byBjaGFuZ2UgdG8gYXJyYXkuXG4gICAgICBleGlzdGluZyA9IGV2ZW50c1t0eXBlXSA9XG4gICAgICAgICAgcHJlcGVuZCA/IFtsaXN0ZW5lciwgZXhpc3RpbmddIDogW2V4aXN0aW5nLCBsaXN0ZW5lcl07XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIElmIHdlJ3ZlIGFscmVhZHkgZ290IGFuIGFycmF5LCBqdXN0IGFwcGVuZC5cbiAgICAgIGlmIChwcmVwZW5kKSB7XG4gICAgICAgIGV4aXN0aW5nLnVuc2hpZnQobGlzdGVuZXIpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgZXhpc3RpbmcucHVzaChsaXN0ZW5lcik7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gQ2hlY2sgZm9yIGxpc3RlbmVyIGxlYWtcbiAgICBpZiAoIWV4aXN0aW5nLndhcm5lZCkge1xuICAgICAgbSA9ICRnZXRNYXhMaXN0ZW5lcnModGFyZ2V0KTtcbiAgICAgIGlmIChtICYmIG0gPiAwICYmIGV4aXN0aW5nLmxlbmd0aCA+IG0pIHtcbiAgICAgICAgZXhpc3Rpbmcud2FybmVkID0gdHJ1ZTtcbiAgICAgICAgdmFyIHcgPSBuZXcgRXJyb3IoJ1Bvc3NpYmxlIEV2ZW50RW1pdHRlciBtZW1vcnkgbGVhayBkZXRlY3RlZC4gJyArXG4gICAgICAgICAgICBleGlzdGluZy5sZW5ndGggKyAnIFwiJyArIFN0cmluZyh0eXBlKSArICdcIiBsaXN0ZW5lcnMgJyArXG4gICAgICAgICAgICAnYWRkZWQuIFVzZSBlbWl0dGVyLnNldE1heExpc3RlbmVycygpIHRvICcgK1xuICAgICAgICAgICAgJ2luY3JlYXNlIGxpbWl0LicpO1xuICAgICAgICB3Lm5hbWUgPSAnTWF4TGlzdGVuZXJzRXhjZWVkZWRXYXJuaW5nJztcbiAgICAgICAgdy5lbWl0dGVyID0gdGFyZ2V0O1xuICAgICAgICB3LnR5cGUgPSB0eXBlO1xuICAgICAgICB3LmNvdW50ID0gZXhpc3RpbmcubGVuZ3RoO1xuICAgICAgICBpZiAodHlwZW9mIGNvbnNvbGUgPT09ICdvYmplY3QnICYmIGNvbnNvbGUud2Fybikge1xuICAgICAgICAgIGNvbnNvbGUud2FybignJXM6ICVzJywgdy5uYW1lLCB3Lm1lc3NhZ2UpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHRhcmdldDtcbn1cblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5hZGRMaXN0ZW5lciA9IGZ1bmN0aW9uIGFkZExpc3RlbmVyKHR5cGUsIGxpc3RlbmVyKSB7XG4gIHJldHVybiBfYWRkTGlzdGVuZXIodGhpcywgdHlwZSwgbGlzdGVuZXIsIGZhbHNlKTtcbn07XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUub24gPSBFdmVudEVtaXR0ZXIucHJvdG90eXBlLmFkZExpc3RlbmVyO1xuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLnByZXBlbmRMaXN0ZW5lciA9XG4gICAgZnVuY3Rpb24gcHJlcGVuZExpc3RlbmVyKHR5cGUsIGxpc3RlbmVyKSB7XG4gICAgICByZXR1cm4gX2FkZExpc3RlbmVyKHRoaXMsIHR5cGUsIGxpc3RlbmVyLCB0cnVlKTtcbiAgICB9O1xuXG5mdW5jdGlvbiBvbmNlV3JhcHBlcigpIHtcbiAgaWYgKCF0aGlzLmZpcmVkKSB7XG4gICAgdGhpcy50YXJnZXQucmVtb3ZlTGlzdGVuZXIodGhpcy50eXBlLCB0aGlzLndyYXBGbik7XG4gICAgdGhpcy5maXJlZCA9IHRydWU7XG4gICAgc3dpdGNoIChhcmd1bWVudHMubGVuZ3RoKSB7XG4gICAgICBjYXNlIDA6XG4gICAgICAgIHJldHVybiB0aGlzLmxpc3RlbmVyLmNhbGwodGhpcy50YXJnZXQpO1xuICAgICAgY2FzZSAxOlxuICAgICAgICByZXR1cm4gdGhpcy5saXN0ZW5lci5jYWxsKHRoaXMudGFyZ2V0LCBhcmd1bWVudHNbMF0pO1xuICAgICAgY2FzZSAyOlxuICAgICAgICByZXR1cm4gdGhpcy5saXN0ZW5lci5jYWxsKHRoaXMudGFyZ2V0LCBhcmd1bWVudHNbMF0sIGFyZ3VtZW50c1sxXSk7XG4gICAgICBjYXNlIDM6XG4gICAgICAgIHJldHVybiB0aGlzLmxpc3RlbmVyLmNhbGwodGhpcy50YXJnZXQsIGFyZ3VtZW50c1swXSwgYXJndW1lbnRzWzFdLFxuICAgICAgICAgICAgYXJndW1lbnRzWzJdKTtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHZhciBhcmdzID0gbmV3IEFycmF5KGFyZ3VtZW50cy5sZW5ndGgpO1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGFyZ3MubGVuZ3RoOyArK2kpXG4gICAgICAgICAgYXJnc1tpXSA9IGFyZ3VtZW50c1tpXTtcbiAgICAgICAgdGhpcy5saXN0ZW5lci5hcHBseSh0aGlzLnRhcmdldCwgYXJncyk7XG4gICAgfVxuICB9XG59XG5cbmZ1bmN0aW9uIF9vbmNlV3JhcCh0YXJnZXQsIHR5cGUsIGxpc3RlbmVyKSB7XG4gIHZhciBzdGF0ZSA9IHsgZmlyZWQ6IGZhbHNlLCB3cmFwRm46IHVuZGVmaW5lZCwgdGFyZ2V0OiB0YXJnZXQsIHR5cGU6IHR5cGUsIGxpc3RlbmVyOiBsaXN0ZW5lciB9O1xuICB2YXIgd3JhcHBlZCA9IGJpbmQuY2FsbChvbmNlV3JhcHBlciwgc3RhdGUpO1xuICB3cmFwcGVkLmxpc3RlbmVyID0gbGlzdGVuZXI7XG4gIHN0YXRlLndyYXBGbiA9IHdyYXBwZWQ7XG4gIHJldHVybiB3cmFwcGVkO1xufVxuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLm9uY2UgPSBmdW5jdGlvbiBvbmNlKHR5cGUsIGxpc3RlbmVyKSB7XG4gIGlmICh0eXBlb2YgbGlzdGVuZXIgIT09ICdmdW5jdGlvbicpXG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcignXCJsaXN0ZW5lclwiIGFyZ3VtZW50IG11c3QgYmUgYSBmdW5jdGlvbicpO1xuICB0aGlzLm9uKHR5cGUsIF9vbmNlV3JhcCh0aGlzLCB0eXBlLCBsaXN0ZW5lcikpO1xuICByZXR1cm4gdGhpcztcbn07XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUucHJlcGVuZE9uY2VMaXN0ZW5lciA9XG4gICAgZnVuY3Rpb24gcHJlcGVuZE9uY2VMaXN0ZW5lcih0eXBlLCBsaXN0ZW5lcikge1xuICAgICAgaWYgKHR5cGVvZiBsaXN0ZW5lciAhPT0gJ2Z1bmN0aW9uJylcbiAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignXCJsaXN0ZW5lclwiIGFyZ3VtZW50IG11c3QgYmUgYSBmdW5jdGlvbicpO1xuICAgICAgdGhpcy5wcmVwZW5kTGlzdGVuZXIodHlwZSwgX29uY2VXcmFwKHRoaXMsIHR5cGUsIGxpc3RlbmVyKSk7XG4gICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuXG4vLyBFbWl0cyBhICdyZW1vdmVMaXN0ZW5lcicgZXZlbnQgaWYgYW5kIG9ubHkgaWYgdGhlIGxpc3RlbmVyIHdhcyByZW1vdmVkLlxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5yZW1vdmVMaXN0ZW5lciA9XG4gICAgZnVuY3Rpb24gcmVtb3ZlTGlzdGVuZXIodHlwZSwgbGlzdGVuZXIpIHtcbiAgICAgIHZhciBsaXN0LCBldmVudHMsIHBvc2l0aW9uLCBpLCBvcmlnaW5hbExpc3RlbmVyO1xuXG4gICAgICBpZiAodHlwZW9mIGxpc3RlbmVyICE9PSAnZnVuY3Rpb24nKVxuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdcImxpc3RlbmVyXCIgYXJndW1lbnQgbXVzdCBiZSBhIGZ1bmN0aW9uJyk7XG5cbiAgICAgIGV2ZW50cyA9IHRoaXMuX2V2ZW50cztcbiAgICAgIGlmICghZXZlbnRzKVxuICAgICAgICByZXR1cm4gdGhpcztcblxuICAgICAgbGlzdCA9IGV2ZW50c1t0eXBlXTtcbiAgICAgIGlmICghbGlzdClcbiAgICAgICAgcmV0dXJuIHRoaXM7XG5cbiAgICAgIGlmIChsaXN0ID09PSBsaXN0ZW5lciB8fCBsaXN0Lmxpc3RlbmVyID09PSBsaXN0ZW5lcikge1xuICAgICAgICBpZiAoLS10aGlzLl9ldmVudHNDb3VudCA9PT0gMClcbiAgICAgICAgICB0aGlzLl9ldmVudHMgPSBvYmplY3RDcmVhdGUobnVsbCk7XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgIGRlbGV0ZSBldmVudHNbdHlwZV07XG4gICAgICAgICAgaWYgKGV2ZW50cy5yZW1vdmVMaXN0ZW5lcilcbiAgICAgICAgICAgIHRoaXMuZW1pdCgncmVtb3ZlTGlzdGVuZXInLCB0eXBlLCBsaXN0Lmxpc3RlbmVyIHx8IGxpc3RlbmVyKTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIGlmICh0eXBlb2YgbGlzdCAhPT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICBwb3NpdGlvbiA9IC0xO1xuXG4gICAgICAgIGZvciAoaSA9IGxpc3QubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgICAgICBpZiAobGlzdFtpXSA9PT0gbGlzdGVuZXIgfHwgbGlzdFtpXS5saXN0ZW5lciA9PT0gbGlzdGVuZXIpIHtcbiAgICAgICAgICAgIG9yaWdpbmFsTGlzdGVuZXIgPSBsaXN0W2ldLmxpc3RlbmVyO1xuICAgICAgICAgICAgcG9zaXRpb24gPSBpO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHBvc2l0aW9uIDwgMClcbiAgICAgICAgICByZXR1cm4gdGhpcztcblxuICAgICAgICBpZiAocG9zaXRpb24gPT09IDApXG4gICAgICAgICAgbGlzdC5zaGlmdCgpO1xuICAgICAgICBlbHNlXG4gICAgICAgICAgc3BsaWNlT25lKGxpc3QsIHBvc2l0aW9uKTtcblxuICAgICAgICBpZiAobGlzdC5sZW5ndGggPT09IDEpXG4gICAgICAgICAgZXZlbnRzW3R5cGVdID0gbGlzdFswXTtcblxuICAgICAgICBpZiAoZXZlbnRzLnJlbW92ZUxpc3RlbmVyKVxuICAgICAgICAgIHRoaXMuZW1pdCgncmVtb3ZlTGlzdGVuZXInLCB0eXBlLCBvcmlnaW5hbExpc3RlbmVyIHx8IGxpc3RlbmVyKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5yZW1vdmVBbGxMaXN0ZW5lcnMgPVxuICAgIGZ1bmN0aW9uIHJlbW92ZUFsbExpc3RlbmVycyh0eXBlKSB7XG4gICAgICB2YXIgbGlzdGVuZXJzLCBldmVudHMsIGk7XG5cbiAgICAgIGV2ZW50cyA9IHRoaXMuX2V2ZW50cztcbiAgICAgIGlmICghZXZlbnRzKVxuICAgICAgICByZXR1cm4gdGhpcztcblxuICAgICAgLy8gbm90IGxpc3RlbmluZyBmb3IgcmVtb3ZlTGlzdGVuZXIsIG5vIG5lZWQgdG8gZW1pdFxuICAgICAgaWYgKCFldmVudHMucmVtb3ZlTGlzdGVuZXIpIHtcbiAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICB0aGlzLl9ldmVudHMgPSBvYmplY3RDcmVhdGUobnVsbCk7XG4gICAgICAgICAgdGhpcy5fZXZlbnRzQ291bnQgPSAwO1xuICAgICAgICB9IGVsc2UgaWYgKGV2ZW50c1t0eXBlXSkge1xuICAgICAgICAgIGlmICgtLXRoaXMuX2V2ZW50c0NvdW50ID09PSAwKVxuICAgICAgICAgICAgdGhpcy5fZXZlbnRzID0gb2JqZWN0Q3JlYXRlKG51bGwpO1xuICAgICAgICAgIGVsc2VcbiAgICAgICAgICAgIGRlbGV0ZSBldmVudHNbdHlwZV07XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICB9XG5cbiAgICAgIC8vIGVtaXQgcmVtb3ZlTGlzdGVuZXIgZm9yIGFsbCBsaXN0ZW5lcnMgb24gYWxsIGV2ZW50c1xuICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgdmFyIGtleXMgPSBvYmplY3RLZXlzKGV2ZW50cyk7XG4gICAgICAgIHZhciBrZXk7XG4gICAgICAgIGZvciAoaSA9IDA7IGkgPCBrZXlzLmxlbmd0aDsgKytpKSB7XG4gICAgICAgICAga2V5ID0ga2V5c1tpXTtcbiAgICAgICAgICBpZiAoa2V5ID09PSAncmVtb3ZlTGlzdGVuZXInKSBjb250aW51ZTtcbiAgICAgICAgICB0aGlzLnJlbW92ZUFsbExpc3RlbmVycyhrZXkpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMucmVtb3ZlQWxsTGlzdGVuZXJzKCdyZW1vdmVMaXN0ZW5lcicpO1xuICAgICAgICB0aGlzLl9ldmVudHMgPSBvYmplY3RDcmVhdGUobnVsbCk7XG4gICAgICAgIHRoaXMuX2V2ZW50c0NvdW50ID0gMDtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICB9XG5cbiAgICAgIGxpc3RlbmVycyA9IGV2ZW50c1t0eXBlXTtcblxuICAgICAgaWYgKHR5cGVvZiBsaXN0ZW5lcnMgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgdGhpcy5yZW1vdmVMaXN0ZW5lcih0eXBlLCBsaXN0ZW5lcnMpO1xuICAgICAgfSBlbHNlIGlmIChsaXN0ZW5lcnMpIHtcbiAgICAgICAgLy8gTElGTyBvcmRlclxuICAgICAgICBmb3IgKGkgPSBsaXN0ZW5lcnMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgICAgICB0aGlzLnJlbW92ZUxpc3RlbmVyKHR5cGUsIGxpc3RlbmVyc1tpXSk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcblxuZnVuY3Rpb24gX2xpc3RlbmVycyh0YXJnZXQsIHR5cGUsIHVud3JhcCkge1xuICB2YXIgZXZlbnRzID0gdGFyZ2V0Ll9ldmVudHM7XG5cbiAgaWYgKCFldmVudHMpXG4gICAgcmV0dXJuIFtdO1xuXG4gIHZhciBldmxpc3RlbmVyID0gZXZlbnRzW3R5cGVdO1xuICBpZiAoIWV2bGlzdGVuZXIpXG4gICAgcmV0dXJuIFtdO1xuXG4gIGlmICh0eXBlb2YgZXZsaXN0ZW5lciA9PT0gJ2Z1bmN0aW9uJylcbiAgICByZXR1cm4gdW53cmFwID8gW2V2bGlzdGVuZXIubGlzdGVuZXIgfHwgZXZsaXN0ZW5lcl0gOiBbZXZsaXN0ZW5lcl07XG5cbiAgcmV0dXJuIHVud3JhcCA/IHVud3JhcExpc3RlbmVycyhldmxpc3RlbmVyKSA6IGFycmF5Q2xvbmUoZXZsaXN0ZW5lciwgZXZsaXN0ZW5lci5sZW5ndGgpO1xufVxuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLmxpc3RlbmVycyA9IGZ1bmN0aW9uIGxpc3RlbmVycyh0eXBlKSB7XG4gIHJldHVybiBfbGlzdGVuZXJzKHRoaXMsIHR5cGUsIHRydWUpO1xufTtcblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5yYXdMaXN0ZW5lcnMgPSBmdW5jdGlvbiByYXdMaXN0ZW5lcnModHlwZSkge1xuICByZXR1cm4gX2xpc3RlbmVycyh0aGlzLCB0eXBlLCBmYWxzZSk7XG59O1xuXG5FdmVudEVtaXR0ZXIubGlzdGVuZXJDb3VudCA9IGZ1bmN0aW9uKGVtaXR0ZXIsIHR5cGUpIHtcbiAgaWYgKHR5cGVvZiBlbWl0dGVyLmxpc3RlbmVyQ291bnQgPT09ICdmdW5jdGlvbicpIHtcbiAgICByZXR1cm4gZW1pdHRlci5saXN0ZW5lckNvdW50KHR5cGUpO1xuICB9IGVsc2Uge1xuICAgIHJldHVybiBsaXN0ZW5lckNvdW50LmNhbGwoZW1pdHRlciwgdHlwZSk7XG4gIH1cbn07XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUubGlzdGVuZXJDb3VudCA9IGxpc3RlbmVyQ291bnQ7XG5mdW5jdGlvbiBsaXN0ZW5lckNvdW50KHR5cGUpIHtcbiAgdmFyIGV2ZW50cyA9IHRoaXMuX2V2ZW50cztcblxuICBpZiAoZXZlbnRzKSB7XG4gICAgdmFyIGV2bGlzdGVuZXIgPSBldmVudHNbdHlwZV07XG5cbiAgICBpZiAodHlwZW9mIGV2bGlzdGVuZXIgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgIHJldHVybiAxO1xuICAgIH0gZWxzZSBpZiAoZXZsaXN0ZW5lcikge1xuICAgICAgcmV0dXJuIGV2bGlzdGVuZXIubGVuZ3RoO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiAwO1xufVxuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLmV2ZW50TmFtZXMgPSBmdW5jdGlvbiBldmVudE5hbWVzKCkge1xuICByZXR1cm4gdGhpcy5fZXZlbnRzQ291bnQgPiAwID8gUmVmbGVjdC5vd25LZXlzKHRoaXMuX2V2ZW50cykgOiBbXTtcbn07XG5cbi8vIEFib3V0IDEuNXggZmFzdGVyIHRoYW4gdGhlIHR3by1hcmcgdmVyc2lvbiBvZiBBcnJheSNzcGxpY2UoKS5cbmZ1bmN0aW9uIHNwbGljZU9uZShsaXN0LCBpbmRleCkge1xuICBmb3IgKHZhciBpID0gaW5kZXgsIGsgPSBpICsgMSwgbiA9IGxpc3QubGVuZ3RoOyBrIDwgbjsgaSArPSAxLCBrICs9IDEpXG4gICAgbGlzdFtpXSA9IGxpc3Rba107XG4gIGxpc3QucG9wKCk7XG59XG5cbmZ1bmN0aW9uIGFycmF5Q2xvbmUoYXJyLCBuKSB7XG4gIHZhciBjb3B5ID0gbmV3IEFycmF5KG4pO1xuICBmb3IgKHZhciBpID0gMDsgaSA8IG47ICsraSlcbiAgICBjb3B5W2ldID0gYXJyW2ldO1xuICByZXR1cm4gY29weTtcbn1cblxuZnVuY3Rpb24gdW53cmFwTGlzdGVuZXJzKGFycikge1xuICB2YXIgcmV0ID0gbmV3IEFycmF5KGFyci5sZW5ndGgpO1xuICBmb3IgKHZhciBpID0gMDsgaSA8IHJldC5sZW5ndGg7ICsraSkge1xuICAgIHJldFtpXSA9IGFycltpXS5saXN0ZW5lciB8fCBhcnJbaV07XG4gIH1cbiAgcmV0dXJuIHJldDtcbn1cblxuZnVuY3Rpb24gb2JqZWN0Q3JlYXRlUG9seWZpbGwocHJvdG8pIHtcbiAgdmFyIEYgPSBmdW5jdGlvbigpIHt9O1xuICBGLnByb3RvdHlwZSA9IHByb3RvO1xuICByZXR1cm4gbmV3IEY7XG59XG5mdW5jdGlvbiBvYmplY3RLZXlzUG9seWZpbGwob2JqKSB7XG4gIHZhciBrZXlzID0gW107XG4gIGZvciAodmFyIGsgaW4gb2JqKSBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKG9iaiwgaykpIHtcbiAgICBrZXlzLnB1c2goayk7XG4gIH1cbiAgcmV0dXJuIGs7XG59XG5mdW5jdGlvbiBmdW5jdGlvbkJpbmRQb2x5ZmlsbChjb250ZXh0KSB7XG4gIHZhciBmbiA9IHRoaXM7XG4gIHJldHVybiBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIGZuLmFwcGx5KGNvbnRleHQsIGFyZ3VtZW50cyk7XG4gIH07XG59XG4iLCIvKiBqc2hpbnQgbm9kZTogdHJ1ZSAqL1xuJ3VzZSBzdHJpY3QnO1xuXG52YXIgbm9ybWFsaWNlID0gcmVxdWlyZSgnbm9ybWFsaWNlJyk7XG5cbi8qKlxuICAjIGZyZWVpY2VcblxuICBUaGUgYGZyZWVpY2VgIG1vZHVsZSBpcyBhIHNpbXBsZSB3YXkgb2YgZ2V0dGluZyByYW5kb20gU1RVTiBvciBUVVJOIHNlcnZlclxuICBmb3IgeW91ciBXZWJSVEMgYXBwbGljYXRpb24uICBUaGUgbGlzdCBvZiBzZXJ2ZXJzIChqdXN0IFNUVU4gYXQgdGhpcyBzdGFnZSlcbiAgd2VyZSBzb3VyY2VkIGZyb20gdGhpcyBbZ2lzdF0oaHR0cHM6Ly9naXN0LmdpdGh1Yi5jb20venppdW5pLzM3NDE5MzMpLlxuXG4gICMjIEV4YW1wbGUgVXNlXG5cbiAgVGhlIGZvbGxvd2luZyBkZW1vbnN0cmF0ZXMgaG93IHlvdSBjYW4gdXNlIGBmcmVlaWNlYCB3aXRoXG4gIFtydGMtcXVpY2tjb25uZWN0XShodHRwczovL2dpdGh1Yi5jb20vcnRjLWlvL3J0Yy1xdWlja2Nvbm5lY3QpOlxuXG4gIDw8PCBleGFtcGxlcy9xdWlja2Nvbm5lY3QuanNcblxuICBBcyB0aGUgYGZyZWVpY2VgIG1vZHVsZSBnZW5lcmF0ZXMgaWNlIHNlcnZlcnMgaW4gYSBsaXN0IGNvbXBsaWFudCB3aXRoIHRoZVxuICBXZWJSVEMgc3BlYyB5b3Ugd2lsbCBiZSBhYmxlIHRvIHVzZSBpdCB3aXRoIHJhdyBgUlRDUGVlckNvbm5lY3Rpb25gXG4gIGNvbnN0cnVjdG9ycyBhbmQgb3RoZXIgV2ViUlRDIGxpYnJhcmllcy5cblxuICAjIyBIZXksIGRvbid0IHVzZSBteSBTVFVOL1RVUk4gc2VydmVyIVxuXG4gIElmIGZvciBzb21lIHJlYXNvbiB5b3VyIGZyZWUgU1RVTiBvciBUVVJOIHNlcnZlciBlbmRzIHVwIGluIHRoZVxuICBsaXN0IG9mIHNlcnZlcnMgKFtzdHVuXShodHRwczovL2dpdGh1Yi5jb20vRGFtb25PZWhsbWFuL2ZyZWVpY2UvYmxvYi9tYXN0ZXIvc3R1bi5qc29uKSBvclxuICBbdHVybl0oaHR0cHM6Ly9naXRodWIuY29tL0RhbW9uT2VobG1hbi9mcmVlaWNlL2Jsb2IvbWFzdGVyL3R1cm4uanNvbikpXG4gIHRoYXQgaXMgdXNlZCBpbiB0aGlzIG1vZHVsZSwgeW91IGNhbiBmZWVsXG4gIGZyZWUgdG8gb3BlbiBhbiBpc3N1ZSBvbiB0aGlzIHJlcG9zaXRvcnkgYW5kIHRob3NlIHNlcnZlcnMgd2lsbCBiZSByZW1vdmVkXG4gIHdpdGhpbiAyNCBob3VycyAob3Igc29vbmVyKS4gIFRoaXMgaXMgdGhlIHF1aWNrZXN0IGFuZCBwcm9iYWJseSB0aGUgbW9zdFxuICBwb2xpdGUgd2F5IHRvIGhhdmUgc29tZXRoaW5nIHJlbW92ZWQgKGFuZCBwcm92aWRlcyB1cyBzb21lIHZpc2liaWxpdHlcbiAgaWYgc29tZW9uZSBvcGVucyBhIHB1bGwgcmVxdWVzdCByZXF1ZXN0aW5nIHRoYXQgYSBzZXJ2ZXIgaXMgYWRkZWQpLlxuXG4gICMjIFBsZWFzZSBhZGQgbXkgc2VydmVyIVxuXG4gIElmIHlvdSBoYXZlIGEgc2VydmVyIHRoYXQgeW91IHdpc2ggdG8gYWRkIHRvIHRoZSBsaXN0LCB0aGF0J3MgYXdlc29tZSEgSSdtXG4gIHN1cmUgSSBzcGVhayBvbiBiZWhhbGYgb2YgYSB3aG9sZSBwaWxlIG9mIFdlYlJUQyBkZXZlbG9wZXJzIHdobyBzYXkgdGhhbmtzLlxuICBUbyBnZXQgaXQgaW50byB0aGUgbGlzdCwgZmVlbCBmcmVlIHRvIGVpdGhlciBvcGVuIGEgcHVsbCByZXF1ZXN0IG9yIGlmIHlvdVxuICBmaW5kIHRoYXQgcHJvY2VzcyBhIGJpdCBkYXVudGluZyB0aGVuIGp1c3QgY3JlYXRlIGFuIGlzc3VlIHJlcXVlc3RpbmdcbiAgdGhlIGFkZGl0aW9uIG9mIHRoZSBzZXJ2ZXIgKG1ha2Ugc3VyZSB5b3UgcHJvdmlkZSBhbGwgdGhlIGRldGFpbHMsIGFuZCBpZlxuICB5b3UgaGF2ZSBhIFRlcm1zIG9mIFNlcnZpY2UgdGhlbiBpbmNsdWRpbmcgdGhhdCBpbiB0aGUgUFIvaXNzdWUgd291bGQgYmVcbiAgYXdlc29tZSkuXG5cbiAgIyMgSSBrbm93IG9mIGEgZnJlZSBzZXJ2ZXIsIGNhbiBJIGFkZCBpdD9cblxuICBTdXJlLCBpZiB5b3UgZG8geW91ciBob21ld29yayBhbmQgbWFrZSBzdXJlIGl0IGlzIG9rIHRvIHVzZSAoSSdtIGN1cnJlbnRseVxuICBpbiB0aGUgcHJvY2VzcyBvZiByZXZpZXdpbmcgdGhlIHRlcm1zIG9mIHRob3NlIFNUVU4gc2VydmVycyBpbmNsdWRlZCBmcm9tXG4gIHRoZSBvcmlnaW5hbCBsaXN0KS4gIElmIGl0J3Mgb2sgdG8gZ28sIHRoZW4gcGxlYXNlIHNlZSB0aGUgcHJldmlvdXMgZW50cnlcbiAgZm9yIGhvdyB0byBhZGQgaXQuXG5cbiAgIyMgQ3VycmVudCBMaXN0IG9mIFNlcnZlcnNcblxuICAqIGN1cnJlbnQgYXMgYXQgdGhlIHRpbWUgb2YgbGFzdCBgUkVBRE1FLm1kYCBmaWxlIGdlbmVyYXRpb25cblxuICAjIyMgU1RVTlxuXG4gIDw8PCBzdHVuLmpzb25cblxuICAjIyMgVFVSTlxuXG4gIDw8PCB0dXJuLmpzb25cblxuKiovXG5cbnZhciBmcmVlaWNlID0gbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihvcHRzKSB7XG4gIC8vIGlmIGEgbGlzdCBvZiBzZXJ2ZXJzIGhhcyBiZWVuIHByb3ZpZGVkLCB0aGVuIHVzZSBpdCBpbnN0ZWFkIG9mIGRlZmF1bHRzXG4gIHZhciBzZXJ2ZXJzID0ge1xuICAgIHN0dW46IChvcHRzIHx8IHt9KS5zdHVuIHx8IHJlcXVpcmUoJy4vc3R1bi5qc29uJyksXG4gICAgdHVybjogKG9wdHMgfHwge30pLnR1cm4gfHwgcmVxdWlyZSgnLi90dXJuLmpzb24nKVxuICB9O1xuXG4gIHZhciBzdHVuQ291bnQgPSAob3B0cyB8fCB7fSkuc3R1bkNvdW50IHx8IDI7XG4gIHZhciB0dXJuQ291bnQgPSAob3B0cyB8fCB7fSkudHVybkNvdW50IHx8IDA7XG4gIHZhciBzZWxlY3RlZDtcblxuICBmdW5jdGlvbiBnZXRTZXJ2ZXJzKHR5cGUsIGNvdW50KSB7XG4gICAgdmFyIG91dCA9IFtdO1xuICAgIHZhciBpbnB1dCA9IFtdLmNvbmNhdChzZXJ2ZXJzW3R5cGVdKTtcbiAgICB2YXIgaWR4O1xuXG4gICAgd2hpbGUgKGlucHV0Lmxlbmd0aCAmJiBvdXQubGVuZ3RoIDwgY291bnQpIHtcbiAgICAgIGlkeCA9IChNYXRoLnJhbmRvbSgpICogaW5wdXQubGVuZ3RoKSB8IDA7XG4gICAgICBvdXQgPSBvdXQuY29uY2F0KGlucHV0LnNwbGljZShpZHgsIDEpKTtcbiAgICB9XG5cbiAgICByZXR1cm4gb3V0Lm1hcChmdW5jdGlvbih1cmwpIHtcbiAgICAgICAgLy9JZiBpdCdzIGEgbm90IGEgc3RyaW5nLCBkb24ndCB0cnkgdG8gXCJub3JtYWxpY2VcIiBpdCBvdGhlcndpc2UgdXNpbmcgdHlwZTp1cmwgd2lsbCBzY3JldyBpdCB1cFxuICAgICAgICBpZiAoKHR5cGVvZiB1cmwgIT09ICdzdHJpbmcnKSAmJiAoISAodXJsIGluc3RhbmNlb2YgU3RyaW5nKSkpIHtcbiAgICAgICAgICAgIHJldHVybiB1cmw7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gbm9ybWFsaWNlKHR5cGUgKyAnOicgKyB1cmwpO1xuICAgICAgICB9XG4gICAgfSk7XG4gIH1cblxuICAvLyBhZGQgc3R1biBzZXJ2ZXJzXG4gIHNlbGVjdGVkID0gW10uY29uY2F0KGdldFNlcnZlcnMoJ3N0dW4nLCBzdHVuQ291bnQpKTtcblxuICBpZiAodHVybkNvdW50KSB7XG4gICAgc2VsZWN0ZWQgPSBzZWxlY3RlZC5jb25jYXQoZ2V0U2VydmVycygndHVybicsIHR1cm5Db3VudCkpO1xuICB9XG5cbiAgcmV0dXJuIHNlbGVjdGVkO1xufTtcbiIsIm1vZHVsZS5leHBvcnRzPVtcbiAgXCJzdHVuLmwuZ29vZ2xlLmNvbToxOTMwMlwiLFxuICBcInN0dW4xLmwuZ29vZ2xlLmNvbToxOTMwMlwiLFxuICBcInN0dW4yLmwuZ29vZ2xlLmNvbToxOTMwMlwiLFxuICBcInN0dW4zLmwuZ29vZ2xlLmNvbToxOTMwMlwiLFxuICBcInN0dW40LmwuZ29vZ2xlLmNvbToxOTMwMlwiLFxuICBcInN0dW4uZWtpZ2EubmV0XCIsXG4gIFwic3R1bi5pZGVhc2lwLmNvbVwiLFxuICBcInN0dW4uc2NobHVuZC5kZVwiLFxuICBcInN0dW4uc3R1bnByb3RvY29sLm9yZzozNDc4XCIsXG4gIFwic3R1bi52b2lwYXJvdW5kLmNvbVwiLFxuICBcInN0dW4udm9pcGJ1c3Rlci5jb21cIixcbiAgXCJzdHVuLnZvaXBzdHVudC5jb21cIixcbiAgXCJzdHVuLnZveGdyYXRpYS5vcmdcIixcbiAgXCJzdHVuLnNlcnZpY2VzLm1vemlsbGEuY29tXCJcbl1cbiIsIm1vZHVsZS5leHBvcnRzPVtdXG4iLCJ2YXIgV2lsZEVtaXR0ZXIgPSByZXF1aXJlKCd3aWxkZW1pdHRlcicpO1xuXG5mdW5jdGlvbiBnZXRNYXhWb2x1bWUgKGFuYWx5c2VyLCBmZnRCaW5zKSB7XG4gIHZhciBtYXhWb2x1bWUgPSAtSW5maW5pdHk7XG4gIGFuYWx5c2VyLmdldEZsb2F0RnJlcXVlbmN5RGF0YShmZnRCaW5zKTtcblxuICBmb3IodmFyIGk9NCwgaWk9ZmZ0Qmlucy5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7XG4gICAgaWYgKGZmdEJpbnNbaV0gPiBtYXhWb2x1bWUgJiYgZmZ0Qmluc1tpXSA8IDApIHtcbiAgICAgIG1heFZvbHVtZSA9IGZmdEJpbnNbaV07XG4gICAgfVxuICB9O1xuXG4gIHJldHVybiBtYXhWb2x1bWU7XG59XG5cblxudmFyIGF1ZGlvQ29udGV4dFR5cGU7XG5pZiAodHlwZW9mIHdpbmRvdyAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgYXVkaW9Db250ZXh0VHlwZSA9IHdpbmRvdy5BdWRpb0NvbnRleHQgfHwgd2luZG93LndlYmtpdEF1ZGlvQ29udGV4dDtcbn1cbi8vIHVzZSBhIHNpbmdsZSBhdWRpbyBjb250ZXh0IGR1ZSB0byBoYXJkd2FyZSBsaW1pdHNcbnZhciBhdWRpb0NvbnRleHQgPSBudWxsO1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihzdHJlYW0sIG9wdGlvbnMpIHtcbiAgdmFyIGhhcmtlciA9IG5ldyBXaWxkRW1pdHRlcigpO1xuXG5cbiAgLy8gbWFrZSBpdCBub3QgYnJlYWsgaW4gbm9uLXN1cHBvcnRlZCBicm93c2Vyc1xuICBpZiAoIWF1ZGlvQ29udGV4dFR5cGUpIHJldHVybiBoYXJrZXI7XG5cbiAgLy9Db25maWdcbiAgdmFyIG9wdGlvbnMgPSBvcHRpb25zIHx8IHt9LFxuICAgICAgc21vb3RoaW5nID0gKG9wdGlvbnMuc21vb3RoaW5nIHx8IDAuMSksXG4gICAgICBpbnRlcnZhbCA9IChvcHRpb25zLmludGVydmFsIHx8IDUwKSxcbiAgICAgIHRocmVzaG9sZCA9IG9wdGlvbnMudGhyZXNob2xkLFxuICAgICAgcGxheSA9IG9wdGlvbnMucGxheSxcbiAgICAgIGhpc3RvcnkgPSBvcHRpb25zLmhpc3RvcnkgfHwgMTAsXG4gICAgICBydW5uaW5nID0gdHJ1ZTtcblxuICAvL1NldHVwIEF1ZGlvIENvbnRleHRcbiAgaWYgKCFhdWRpb0NvbnRleHQpIHtcbiAgICBhdWRpb0NvbnRleHQgPSBuZXcgYXVkaW9Db250ZXh0VHlwZSgpO1xuICB9XG4gIHZhciBzb3VyY2VOb2RlLCBmZnRCaW5zLCBhbmFseXNlcjtcblxuICBhbmFseXNlciA9IGF1ZGlvQ29udGV4dC5jcmVhdGVBbmFseXNlcigpO1xuICBhbmFseXNlci5mZnRTaXplID0gNTEyO1xuICBhbmFseXNlci5zbW9vdGhpbmdUaW1lQ29uc3RhbnQgPSBzbW9vdGhpbmc7XG4gIGZmdEJpbnMgPSBuZXcgRmxvYXQzMkFycmF5KGFuYWx5c2VyLmZyZXF1ZW5jeUJpbkNvdW50KTtcblxuICBpZiAoc3RyZWFtLmpxdWVyeSkgc3RyZWFtID0gc3RyZWFtWzBdO1xuICBpZiAoc3RyZWFtIGluc3RhbmNlb2YgSFRNTEF1ZGlvRWxlbWVudCB8fCBzdHJlYW0gaW5zdGFuY2VvZiBIVE1MVmlkZW9FbGVtZW50KSB7XG4gICAgLy9BdWRpbyBUYWdcbiAgICBzb3VyY2VOb2RlID0gYXVkaW9Db250ZXh0LmNyZWF0ZU1lZGlhRWxlbWVudFNvdXJjZShzdHJlYW0pO1xuICAgIGlmICh0eXBlb2YgcGxheSA9PT0gJ3VuZGVmaW5lZCcpIHBsYXkgPSB0cnVlO1xuICAgIHRocmVzaG9sZCA9IHRocmVzaG9sZCB8fCAtNTA7XG4gIH0gZWxzZSB7XG4gICAgLy9XZWJSVEMgU3RyZWFtXG4gICAgc291cmNlTm9kZSA9IGF1ZGlvQ29udGV4dC5jcmVhdGVNZWRpYVN0cmVhbVNvdXJjZShzdHJlYW0pO1xuICAgIHRocmVzaG9sZCA9IHRocmVzaG9sZCB8fCAtNTA7XG4gIH1cblxuICBzb3VyY2VOb2RlLmNvbm5lY3QoYW5hbHlzZXIpO1xuICBpZiAocGxheSkgYW5hbHlzZXIuY29ubmVjdChhdWRpb0NvbnRleHQuZGVzdGluYXRpb24pO1xuXG4gIGhhcmtlci5zcGVha2luZyA9IGZhbHNlO1xuXG4gIGhhcmtlci5zdXNwZW5kID0gZnVuY3Rpb24oKSB7XG4gICAgYXVkaW9Db250ZXh0LnN1c3BlbmQoKTtcbiAgfVxuICBoYXJrZXIucmVzdW1lID0gZnVuY3Rpb24oKSB7XG4gICAgYXVkaW9Db250ZXh0LnJlc3VtZSgpO1xuICB9XG4gIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShoYXJrZXIsICdzdGF0ZScsIHsgZ2V0OiBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gYXVkaW9Db250ZXh0LnN0YXRlO1xuICB9fSk7XG4gIGF1ZGlvQ29udGV4dC5vbnN0YXRlY2hhbmdlID0gZnVuY3Rpb24oKSB7XG4gICAgaGFya2VyLmVtaXQoJ3N0YXRlX2NoYW5nZScsIGF1ZGlvQ29udGV4dC5zdGF0ZSk7XG4gIH1cblxuICBoYXJrZXIuc2V0VGhyZXNob2xkID0gZnVuY3Rpb24odCkge1xuICAgIHRocmVzaG9sZCA9IHQ7XG4gIH07XG5cbiAgaGFya2VyLnNldEludGVydmFsID0gZnVuY3Rpb24oaSkge1xuICAgIGludGVydmFsID0gaTtcbiAgfTtcblxuICBoYXJrZXIuc3RvcCA9IGZ1bmN0aW9uKCkge1xuICAgIHJ1bm5pbmcgPSBmYWxzZTtcbiAgICBoYXJrZXIuZW1pdCgndm9sdW1lX2NoYW5nZScsIC0xMDAsIHRocmVzaG9sZCk7XG4gICAgaWYgKGhhcmtlci5zcGVha2luZykge1xuICAgICAgaGFya2VyLnNwZWFraW5nID0gZmFsc2U7XG4gICAgICBoYXJrZXIuZW1pdCgnc3RvcHBlZF9zcGVha2luZycpO1xuICAgIH1cbiAgICBhbmFseXNlci5kaXNjb25uZWN0KCk7XG4gICAgc291cmNlTm9kZS5kaXNjb25uZWN0KCk7XG4gIH07XG4gIGhhcmtlci5zcGVha2luZ0hpc3RvcnkgPSBbXTtcbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBoaXN0b3J5OyBpKyspIHtcbiAgICAgIGhhcmtlci5zcGVha2luZ0hpc3RvcnkucHVzaCgwKTtcbiAgfVxuXG4gIC8vIFBvbGwgdGhlIGFuYWx5c2VyIG5vZGUgdG8gZGV0ZXJtaW5lIGlmIHNwZWFraW5nXG4gIC8vIGFuZCBlbWl0IGV2ZW50cyBpZiBjaGFuZ2VkXG4gIHZhciBsb29wZXIgPSBmdW5jdGlvbigpIHtcbiAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uKCkge1xuXG4gICAgICAvL2NoZWNrIGlmIHN0b3AgaGFzIGJlZW4gY2FsbGVkXG4gICAgICBpZighcnVubmluZykge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIHZhciBjdXJyZW50Vm9sdW1lID0gZ2V0TWF4Vm9sdW1lKGFuYWx5c2VyLCBmZnRCaW5zKTtcblxuICAgICAgaGFya2VyLmVtaXQoJ3ZvbHVtZV9jaGFuZ2UnLCBjdXJyZW50Vm9sdW1lLCB0aHJlc2hvbGQpO1xuXG4gICAgICB2YXIgaGlzdG9yeSA9IDA7XG4gICAgICBpZiAoY3VycmVudFZvbHVtZSA+IHRocmVzaG9sZCAmJiAhaGFya2VyLnNwZWFraW5nKSB7XG4gICAgICAgIC8vIHRyaWdnZXIgcXVpY2tseSwgc2hvcnQgaGlzdG9yeVxuICAgICAgICBmb3IgKHZhciBpID0gaGFya2VyLnNwZWFraW5nSGlzdG9yeS5sZW5ndGggLSAzOyBpIDwgaGFya2VyLnNwZWFraW5nSGlzdG9yeS5sZW5ndGg7IGkrKykge1xuICAgICAgICAgIGhpc3RvcnkgKz0gaGFya2VyLnNwZWFraW5nSGlzdG9yeVtpXTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoaGlzdG9yeSA+PSAyKSB7XG4gICAgICAgICAgaGFya2VyLnNwZWFraW5nID0gdHJ1ZTtcbiAgICAgICAgICBoYXJrZXIuZW1pdCgnc3BlYWtpbmcnKTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIGlmIChjdXJyZW50Vm9sdW1lIDwgdGhyZXNob2xkICYmIGhhcmtlci5zcGVha2luZykge1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGhhcmtlci5zcGVha2luZ0hpc3RvcnkubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICBoaXN0b3J5ICs9IGhhcmtlci5zcGVha2luZ0hpc3RvcnlbaV07XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGhpc3RvcnkgPT0gMCkge1xuICAgICAgICAgIGhhcmtlci5zcGVha2luZyA9IGZhbHNlO1xuICAgICAgICAgIGhhcmtlci5lbWl0KCdzdG9wcGVkX3NwZWFraW5nJyk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGhhcmtlci5zcGVha2luZ0hpc3Rvcnkuc2hpZnQoKTtcbiAgICAgIGhhcmtlci5zcGVha2luZ0hpc3RvcnkucHVzaCgwICsgKGN1cnJlbnRWb2x1bWUgPiB0aHJlc2hvbGQpKTtcblxuICAgICAgbG9vcGVyKCk7XG4gICAgfSwgaW50ZXJ2YWwpO1xuICB9O1xuICBsb29wZXIoKTtcblxuXG4gIHJldHVybiBoYXJrZXI7XG59XG4iLCJpZiAodHlwZW9mIE9iamVjdC5jcmVhdGUgPT09ICdmdW5jdGlvbicpIHtcbiAgLy8gaW1wbGVtZW50YXRpb24gZnJvbSBzdGFuZGFyZCBub2RlLmpzICd1dGlsJyBtb2R1bGVcbiAgbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBpbmhlcml0cyhjdG9yLCBzdXBlckN0b3IpIHtcbiAgICBjdG9yLnN1cGVyXyA9IHN1cGVyQ3RvclxuICAgIGN0b3IucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShzdXBlckN0b3IucHJvdG90eXBlLCB7XG4gICAgICBjb25zdHJ1Y3Rvcjoge1xuICAgICAgICB2YWx1ZTogY3RvcixcbiAgICAgICAgZW51bWVyYWJsZTogZmFsc2UsXG4gICAgICAgIHdyaXRhYmxlOiB0cnVlLFxuICAgICAgICBjb25maWd1cmFibGU6IHRydWVcbiAgICAgIH1cbiAgICB9KTtcbiAgfTtcbn0gZWxzZSB7XG4gIC8vIG9sZCBzY2hvb2wgc2hpbSBmb3Igb2xkIGJyb3dzZXJzXG4gIG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gaW5oZXJpdHMoY3Rvciwgc3VwZXJDdG9yKSB7XG4gICAgY3Rvci5zdXBlcl8gPSBzdXBlckN0b3JcbiAgICB2YXIgVGVtcEN0b3IgPSBmdW5jdGlvbiAoKSB7fVxuICAgIFRlbXBDdG9yLnByb3RvdHlwZSA9IHN1cGVyQ3Rvci5wcm90b3R5cGVcbiAgICBjdG9yLnByb3RvdHlwZSA9IG5ldyBUZW1wQ3RvcigpXG4gICAgY3Rvci5wcm90b3R5cGUuY29uc3RydWN0b3IgPSBjdG9yXG4gIH1cbn1cbiIsIi8qKlxuICAjIG5vcm1hbGljZVxuXG4gIE5vcm1hbGl6ZSBhbiBpY2Ugc2VydmVyIGNvbmZpZ3VyYXRpb24gb2JqZWN0IChvciBwbGFpbiBvbGQgc3RyaW5nKSBpbnRvIGEgZm9ybWF0XG4gIHRoYXQgaXMgdXNhYmxlIGluIGFsbCBicm93c2VycyBzdXBwb3J0aW5nIFdlYlJUQy4gIFByaW1hcmlseSB0aGlzIG1vZHVsZSBpcyBkZXNpZ25lZFxuICB0byBoZWxwIHdpdGggdGhlIHRyYW5zaXRpb24gb2YgdGhlIGB1cmxgIGF0dHJpYnV0ZSBvZiB0aGUgY29uZmlndXJhdGlvbiBvYmplY3QgdG9cbiAgdGhlIGB1cmxzYCBhdHRyaWJ1dGUuXG5cbiAgIyMgRXhhbXBsZSBVc2FnZVxuXG4gIDw8PCBleGFtcGxlcy9zaW1wbGUuanNcblxuKiovXG5cbnZhciBwcm90b2NvbHMgPSBbXG4gICdzdHVuOicsXG4gICd0dXJuOidcbl07XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24oaW5wdXQpIHtcbiAgdmFyIHVybCA9IChpbnB1dCB8fCB7fSkudXJsIHx8IGlucHV0O1xuICB2YXIgcHJvdG9jb2w7XG4gIHZhciBwYXJ0cztcbiAgdmFyIG91dHB1dCA9IHt9O1xuXG4gIC8vIGlmIHdlIGRvbid0IGhhdmUgYSBzdHJpbmcgdXJsLCB0aGVuIGFsbG93IHRoZSBpbnB1dCB0byBwYXNzdGhyb3VnaFxuICBpZiAodHlwZW9mIHVybCAhPSAnc3RyaW5nJyAmJiAoISAodXJsIGluc3RhbmNlb2YgU3RyaW5nKSkpIHtcbiAgICByZXR1cm4gaW5wdXQ7XG4gIH1cblxuICAvLyB0cmltIHRoZSB1cmwgc3RyaW5nLCBhbmQgY29udmVydCB0byBhbiBhcnJheVxuICB1cmwgPSB1cmwudHJpbSgpO1xuXG4gIC8vIGlmIHRoZSBwcm90b2NvbCBpcyBub3Qga25vd24sIHRoZW4gcGFzc3Rocm91Z2hcbiAgcHJvdG9jb2wgPSBwcm90b2NvbHNbcHJvdG9jb2xzLmluZGV4T2YodXJsLnNsaWNlKDAsIDUpKV07XG4gIGlmICghIHByb3RvY29sKSB7XG4gICAgcmV0dXJuIGlucHV0O1xuICB9XG5cbiAgLy8gbm93IGxldCdzIGF0dGFjayB0aGUgcmVtYWluaW5nIHVybCBwYXJ0c1xuICB1cmwgPSB1cmwuc2xpY2UoNSk7XG4gIHBhcnRzID0gdXJsLnNwbGl0KCdAJyk7XG5cbiAgb3V0cHV0LnVzZXJuYW1lID0gaW5wdXQudXNlcm5hbWU7XG4gIG91dHB1dC5jcmVkZW50aWFsID0gaW5wdXQuY3JlZGVudGlhbDtcbiAgLy8gaWYgd2UgaGF2ZSBhbiBhdXRoZW50aWNhdGlvbiBwYXJ0LCB0aGVuIHNldCB0aGUgY3JlZGVudGlhbHNcbiAgaWYgKHBhcnRzLmxlbmd0aCA+IDEpIHtcbiAgICB1cmwgPSBwYXJ0c1sxXTtcbiAgICBwYXJ0cyA9IHBhcnRzWzBdLnNwbGl0KCc6Jyk7XG5cbiAgICAvLyBhZGQgdGhlIG91dHB1dCBjcmVkZW50aWFsIGFuZCB1c2VybmFtZVxuICAgIG91dHB1dC51c2VybmFtZSA9IHBhcnRzWzBdO1xuICAgIG91dHB1dC5jcmVkZW50aWFsID0gKGlucHV0IHx8IHt9KS5jcmVkZW50aWFsIHx8IHBhcnRzWzFdIHx8ICcnO1xuICB9XG5cbiAgb3V0cHV0LnVybCA9IHByb3RvY29sICsgdXJsO1xuICBvdXRwdXQudXJscyA9IFsgb3V0cHV0LnVybCBdO1xuXG4gIHJldHVybiBvdXRwdXQ7XG59O1xuIiwiLyohXG4gKiBQbGF0Zm9ybS5qcyA8aHR0cHM6Ly9tdGhzLmJlL3BsYXRmb3JtPlxuICogQ29weXJpZ2h0IDIwMTQtMjAxOCBCZW5qYW1pbiBUYW4gPGh0dHBzOi8vYm5qbW50NG4ubm93LnNoLz5cbiAqIENvcHlyaWdodCAyMDExLTIwMTMgSm9obi1EYXZpZCBEYWx0b24gPGh0dHA6Ly9hbGx5b3VjYW5sZWV0LmNvbS8+XG4gKiBBdmFpbGFibGUgdW5kZXIgTUlUIGxpY2Vuc2UgPGh0dHBzOi8vbXRocy5iZS9taXQ+XG4gKi9cbjsoZnVuY3Rpb24oKSB7XG4gICd1c2Ugc3RyaWN0JztcblxuICAvKiogVXNlZCB0byBkZXRlcm1pbmUgaWYgdmFsdWVzIGFyZSBvZiB0aGUgbGFuZ3VhZ2UgdHlwZSBgT2JqZWN0YC4gKi9cbiAgdmFyIG9iamVjdFR5cGVzID0ge1xuICAgICdmdW5jdGlvbic6IHRydWUsXG4gICAgJ29iamVjdCc6IHRydWVcbiAgfTtcblxuICAvKiogVXNlZCBhcyBhIHJlZmVyZW5jZSB0byB0aGUgZ2xvYmFsIG9iamVjdC4gKi9cbiAgdmFyIHJvb3QgPSAob2JqZWN0VHlwZXNbdHlwZW9mIHdpbmRvd10gJiYgd2luZG93KSB8fCB0aGlzO1xuXG4gIC8qKiBCYWNrdXAgcG9zc2libGUgZ2xvYmFsIG9iamVjdC4gKi9cbiAgdmFyIG9sZFJvb3QgPSByb290O1xuXG4gIC8qKiBEZXRlY3QgZnJlZSB2YXJpYWJsZSBgZXhwb3J0c2AuICovXG4gIHZhciBmcmVlRXhwb3J0cyA9IG9iamVjdFR5cGVzW3R5cGVvZiBleHBvcnRzXSAmJiBleHBvcnRzO1xuXG4gIC8qKiBEZXRlY3QgZnJlZSB2YXJpYWJsZSBgbW9kdWxlYC4gKi9cbiAgdmFyIGZyZWVNb2R1bGUgPSBvYmplY3RUeXBlc1t0eXBlb2YgbW9kdWxlXSAmJiBtb2R1bGUgJiYgIW1vZHVsZS5ub2RlVHlwZSAmJiBtb2R1bGU7XG5cbiAgLyoqIERldGVjdCBmcmVlIHZhcmlhYmxlIGBnbG9iYWxgIGZyb20gTm9kZS5qcyBvciBCcm93c2VyaWZpZWQgY29kZSBhbmQgdXNlIGl0IGFzIGByb290YC4gKi9cbiAgdmFyIGZyZWVHbG9iYWwgPSBmcmVlRXhwb3J0cyAmJiBmcmVlTW9kdWxlICYmIHR5cGVvZiBnbG9iYWwgPT0gJ29iamVjdCcgJiYgZ2xvYmFsO1xuICBpZiAoZnJlZUdsb2JhbCAmJiAoZnJlZUdsb2JhbC5nbG9iYWwgPT09IGZyZWVHbG9iYWwgfHwgZnJlZUdsb2JhbC53aW5kb3cgPT09IGZyZWVHbG9iYWwgfHwgZnJlZUdsb2JhbC5zZWxmID09PSBmcmVlR2xvYmFsKSkge1xuICAgIHJvb3QgPSBmcmVlR2xvYmFsO1xuICB9XG5cbiAgLyoqXG4gICAqIFVzZWQgYXMgdGhlIG1heGltdW0gbGVuZ3RoIG9mIGFuIGFycmF5LWxpa2Ugb2JqZWN0LlxuICAgKiBTZWUgdGhlIFtFUzYgc3BlY10oaHR0cDovL3Blb3BsZS5tb3ppbGxhLm9yZy9+am9yZW5kb3JmZi9lczYtZHJhZnQuaHRtbCNzZWMtdG9sZW5ndGgpXG4gICAqIGZvciBtb3JlIGRldGFpbHMuXG4gICAqL1xuICB2YXIgbWF4U2FmZUludGVnZXIgPSBNYXRoLnBvdygyLCA1MykgLSAxO1xuXG4gIC8qKiBSZWd1bGFyIGV4cHJlc3Npb24gdG8gZGV0ZWN0IE9wZXJhLiAqL1xuICB2YXIgcmVPcGVyYSA9IC9cXGJPcGVyYS87XG5cbiAgLyoqIFBvc3NpYmxlIGdsb2JhbCBvYmplY3QuICovXG4gIHZhciB0aGlzQmluZGluZyA9IHRoaXM7XG5cbiAgLyoqIFVzZWQgZm9yIG5hdGl2ZSBtZXRob2QgcmVmZXJlbmNlcy4gKi9cbiAgdmFyIG9iamVjdFByb3RvID0gT2JqZWN0LnByb3RvdHlwZTtcblxuICAvKiogVXNlZCB0byBjaGVjayBmb3Igb3duIHByb3BlcnRpZXMgb2YgYW4gb2JqZWN0LiAqL1xuICB2YXIgaGFzT3duUHJvcGVydHkgPSBvYmplY3RQcm90by5oYXNPd25Qcm9wZXJ0eTtcblxuICAvKiogVXNlZCB0byByZXNvbHZlIHRoZSBpbnRlcm5hbCBgW1tDbGFzc11dYCBvZiB2YWx1ZXMuICovXG4gIHZhciB0b1N0cmluZyA9IG9iamVjdFByb3RvLnRvU3RyaW5nO1xuXG4gIC8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuXG4gIC8qKlxuICAgKiBDYXBpdGFsaXplcyBhIHN0cmluZyB2YWx1ZS5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtzdHJpbmd9IHN0cmluZyBUaGUgc3RyaW5nIHRvIGNhcGl0YWxpemUuXG4gICAqIEByZXR1cm5zIHtzdHJpbmd9IFRoZSBjYXBpdGFsaXplZCBzdHJpbmcuXG4gICAqL1xuICBmdW5jdGlvbiBjYXBpdGFsaXplKHN0cmluZykge1xuICAgIHN0cmluZyA9IFN0cmluZyhzdHJpbmcpO1xuICAgIHJldHVybiBzdHJpbmcuY2hhckF0KDApLnRvVXBwZXJDYXNlKCkgKyBzdHJpbmcuc2xpY2UoMSk7XG4gIH1cblxuICAvKipcbiAgICogQSB1dGlsaXR5IGZ1bmN0aW9uIHRvIGNsZWFuIHVwIHRoZSBPUyBuYW1lLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gb3MgVGhlIE9TIG5hbWUgdG8gY2xlYW4gdXAuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbcGF0dGVybl0gQSBgUmVnRXhwYCBwYXR0ZXJuIG1hdGNoaW5nIHRoZSBPUyBuYW1lLlxuICAgKiBAcGFyYW0ge3N0cmluZ30gW2xhYmVsXSBBIGxhYmVsIGZvciB0aGUgT1MuXG4gICAqL1xuICBmdW5jdGlvbiBjbGVhbnVwT1Mob3MsIHBhdHRlcm4sIGxhYmVsKSB7XG4gICAgLy8gUGxhdGZvcm0gdG9rZW5zIGFyZSBkZWZpbmVkIGF0OlxuICAgIC8vIGh0dHA6Ly9tc2RuLm1pY3Jvc29mdC5jb20vZW4tdXMvbGlicmFyeS9tczUzNzUwMyhWUy44NSkuYXNweFxuICAgIC8vIGh0dHA6Ly93ZWIuYXJjaGl2ZS5vcmcvd2ViLzIwMDgxMTIyMDUzOTUwL2h0dHA6Ly9tc2RuLm1pY3Jvc29mdC5jb20vZW4tdXMvbGlicmFyeS9tczUzNzUwMyhWUy44NSkuYXNweFxuICAgIHZhciBkYXRhID0ge1xuICAgICAgJzEwLjAnOiAnMTAnLFxuICAgICAgJzYuNCc6ICAnMTAgVGVjaG5pY2FsIFByZXZpZXcnLFxuICAgICAgJzYuMyc6ICAnOC4xJyxcbiAgICAgICc2LjInOiAgJzgnLFxuICAgICAgJzYuMSc6ICAnU2VydmVyIDIwMDggUjIgLyA3JyxcbiAgICAgICc2LjAnOiAgJ1NlcnZlciAyMDA4IC8gVmlzdGEnLFxuICAgICAgJzUuMic6ICAnU2VydmVyIDIwMDMgLyBYUCA2NC1iaXQnLFxuICAgICAgJzUuMSc6ICAnWFAnLFxuICAgICAgJzUuMDEnOiAnMjAwMCBTUDEnLFxuICAgICAgJzUuMCc6ICAnMjAwMCcsXG4gICAgICAnNC4wJzogICdOVCcsXG4gICAgICAnNC45MCc6ICdNRSdcbiAgICB9O1xuICAgIC8vIERldGVjdCBXaW5kb3dzIHZlcnNpb24gZnJvbSBwbGF0Zm9ybSB0b2tlbnMuXG4gICAgaWYgKHBhdHRlcm4gJiYgbGFiZWwgJiYgL15XaW4vaS50ZXN0KG9zKSAmJiAhL15XaW5kb3dzIFBob25lIC9pLnRlc3Qob3MpICYmXG4gICAgICAgIChkYXRhID0gZGF0YVsvW1xcZC5dKyQvLmV4ZWMob3MpXSkpIHtcbiAgICAgIG9zID0gJ1dpbmRvd3MgJyArIGRhdGE7XG4gICAgfVxuICAgIC8vIENvcnJlY3QgY2hhcmFjdGVyIGNhc2UgYW5kIGNsZWFudXAgc3RyaW5nLlxuICAgIG9zID0gU3RyaW5nKG9zKTtcblxuICAgIGlmIChwYXR0ZXJuICYmIGxhYmVsKSB7XG4gICAgICBvcyA9IG9zLnJlcGxhY2UoUmVnRXhwKHBhdHRlcm4sICdpJyksIGxhYmVsKTtcbiAgICB9XG5cbiAgICBvcyA9IGZvcm1hdChcbiAgICAgIG9zLnJlcGxhY2UoLyBjZSQvaSwgJyBDRScpXG4gICAgICAgIC5yZXBsYWNlKC9cXGJocHcvaSwgJ3dlYicpXG4gICAgICAgIC5yZXBsYWNlKC9cXGJNYWNpbnRvc2hcXGIvLCAnTWFjIE9TJylcbiAgICAgICAgLnJlcGxhY2UoL19Qb3dlclBDXFxiL2ksICcgT1MnKVxuICAgICAgICAucmVwbGFjZSgvXFxiKE9TIFgpIFteIFxcZF0rL2ksICckMScpXG4gICAgICAgIC5yZXBsYWNlKC9cXGJNYWMgKE9TIFgpXFxiLywgJyQxJylcbiAgICAgICAgLnJlcGxhY2UoL1xcLyhcXGQpLywgJyAkMScpXG4gICAgICAgIC5yZXBsYWNlKC9fL2csICcuJylcbiAgICAgICAgLnJlcGxhY2UoLyg/OiBCZVBDfFsgLl0qZmNbIFxcZC5dKykkL2ksICcnKVxuICAgICAgICAucmVwbGFjZSgvXFxieDg2XFwuNjRcXGIvZ2ksICd4ODZfNjQnKVxuICAgICAgICAucmVwbGFjZSgvXFxiKFdpbmRvd3MgUGhvbmUpIE9TXFxiLywgJyQxJylcbiAgICAgICAgLnJlcGxhY2UoL1xcYihDaHJvbWUgT1MgXFx3KykgW1xcZC5dK1xcYi8sICckMScpXG4gICAgICAgIC5zcGxpdCgnIG9uICcpWzBdXG4gICAgKTtcblxuICAgIHJldHVybiBvcztcbiAgfVxuXG4gIC8qKlxuICAgKiBBbiBpdGVyYXRpb24gdXRpbGl0eSBmb3IgYXJyYXlzIGFuZCBvYmplY3RzLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge0FycmF5fE9iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gaXRlcmF0ZSBvdmVyLlxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBjYWxsYmFjayBUaGUgZnVuY3Rpb24gY2FsbGVkIHBlciBpdGVyYXRpb24uXG4gICAqL1xuICBmdW5jdGlvbiBlYWNoKG9iamVjdCwgY2FsbGJhY2spIHtcbiAgICB2YXIgaW5kZXggPSAtMSxcbiAgICAgICAgbGVuZ3RoID0gb2JqZWN0ID8gb2JqZWN0Lmxlbmd0aCA6IDA7XG5cbiAgICBpZiAodHlwZW9mIGxlbmd0aCA9PSAnbnVtYmVyJyAmJiBsZW5ndGggPiAtMSAmJiBsZW5ndGggPD0gbWF4U2FmZUludGVnZXIpIHtcbiAgICAgIHdoaWxlICgrK2luZGV4IDwgbGVuZ3RoKSB7XG4gICAgICAgIGNhbGxiYWNrKG9iamVjdFtpbmRleF0sIGluZGV4LCBvYmplY3QpO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBmb3JPd24ob2JqZWN0LCBjYWxsYmFjayk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFRyaW0gYW5kIGNvbmRpdGlvbmFsbHkgY2FwaXRhbGl6ZSBzdHJpbmcgdmFsdWVzLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gc3RyaW5nIFRoZSBzdHJpbmcgdG8gZm9ybWF0LlxuICAgKiBAcmV0dXJucyB7c3RyaW5nfSBUaGUgZm9ybWF0dGVkIHN0cmluZy5cbiAgICovXG4gIGZ1bmN0aW9uIGZvcm1hdChzdHJpbmcpIHtcbiAgICBzdHJpbmcgPSB0cmltKHN0cmluZyk7XG4gICAgcmV0dXJuIC9eKD86d2ViT1N8aSg/Ok9TfFApKS8udGVzdChzdHJpbmcpXG4gICAgICA/IHN0cmluZ1xuICAgICAgOiBjYXBpdGFsaXplKHN0cmluZyk7XG4gIH1cblxuICAvKipcbiAgICogSXRlcmF0ZXMgb3ZlciBhbiBvYmplY3QncyBvd24gcHJvcGVydGllcywgZXhlY3V0aW5nIHRoZSBgY2FsbGJhY2tgIGZvciBlYWNoLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gaXRlcmF0ZSBvdmVyLlxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBjYWxsYmFjayBUaGUgZnVuY3Rpb24gZXhlY3V0ZWQgcGVyIG93biBwcm9wZXJ0eS5cbiAgICovXG4gIGZ1bmN0aW9uIGZvck93bihvYmplY3QsIGNhbGxiYWNrKSB7XG4gICAgZm9yICh2YXIga2V5IGluIG9iamVjdCkge1xuICAgICAgaWYgKGhhc093blByb3BlcnR5LmNhbGwob2JqZWN0LCBrZXkpKSB7XG4gICAgICAgIGNhbGxiYWNrKG9iamVjdFtrZXldLCBrZXksIG9iamVjdCk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEdldHMgdGhlIGludGVybmFsIGBbW0NsYXNzXV1gIG9mIGEgdmFsdWUuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlLlxuICAgKiBAcmV0dXJucyB7c3RyaW5nfSBUaGUgYFtbQ2xhc3NdXWAuXG4gICAqL1xuICBmdW5jdGlvbiBnZXRDbGFzc09mKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlID09IG51bGxcbiAgICAgID8gY2FwaXRhbGl6ZSh2YWx1ZSlcbiAgICAgIDogdG9TdHJpbmcuY2FsbCh2YWx1ZSkuc2xpY2UoOCwgLTEpO1xuICB9XG5cbiAgLyoqXG4gICAqIEhvc3Qgb2JqZWN0cyBjYW4gcmV0dXJuIHR5cGUgdmFsdWVzIHRoYXQgYXJlIGRpZmZlcmVudCBmcm9tIHRoZWlyIGFjdHVhbFxuICAgKiBkYXRhIHR5cGUuIFRoZSBvYmplY3RzIHdlIGFyZSBjb25jZXJuZWQgd2l0aCB1c3VhbGx5IHJldHVybiBub24tcHJpbWl0aXZlXG4gICAqIHR5cGVzIG9mIFwib2JqZWN0XCIsIFwiZnVuY3Rpb25cIiwgb3IgXCJ1bmtub3duXCIuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7Kn0gb2JqZWN0IFRoZSBvd25lciBvZiB0aGUgcHJvcGVydHkuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBwcm9wZXJ0eSBUaGUgcHJvcGVydHkgdG8gY2hlY2suXG4gICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiB0aGUgcHJvcGVydHkgdmFsdWUgaXMgYSBub24tcHJpbWl0aXZlLCBlbHNlIGBmYWxzZWAuXG4gICAqL1xuICBmdW5jdGlvbiBpc0hvc3RUeXBlKG9iamVjdCwgcHJvcGVydHkpIHtcbiAgICB2YXIgdHlwZSA9IG9iamVjdCAhPSBudWxsID8gdHlwZW9mIG9iamVjdFtwcm9wZXJ0eV0gOiAnbnVtYmVyJztcbiAgICByZXR1cm4gIS9eKD86Ym9vbGVhbnxudW1iZXJ8c3RyaW5nfHVuZGVmaW5lZCkkLy50ZXN0KHR5cGUpICYmXG4gICAgICAodHlwZSA9PSAnb2JqZWN0JyA/ICEhb2JqZWN0W3Byb3BlcnR5XSA6IHRydWUpO1xuICB9XG5cbiAgLyoqXG4gICAqIFByZXBhcmVzIGEgc3RyaW5nIGZvciB1c2UgaW4gYSBgUmVnRXhwYCBieSBtYWtpbmcgaHlwaGVucyBhbmQgc3BhY2VzIG9wdGlvbmFsLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gc3RyaW5nIFRoZSBzdHJpbmcgdG8gcXVhbGlmeS5cbiAgICogQHJldHVybnMge3N0cmluZ30gVGhlIHF1YWxpZmllZCBzdHJpbmcuXG4gICAqL1xuICBmdW5jdGlvbiBxdWFsaWZ5KHN0cmluZykge1xuICAgIHJldHVybiBTdHJpbmcoc3RyaW5nKS5yZXBsYWNlKC8oWyAtXSkoPyEkKS9nLCAnJDE/Jyk7XG4gIH1cblxuICAvKipcbiAgICogQSBiYXJlLWJvbmVzIGBBcnJheSNyZWR1Y2VgIGxpa2UgdXRpbGl0eSBmdW5jdGlvbi5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIGl0ZXJhdGUgb3Zlci5cbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gY2FsbGJhY2sgVGhlIGZ1bmN0aW9uIGNhbGxlZCBwZXIgaXRlcmF0aW9uLlxuICAgKiBAcmV0dXJucyB7Kn0gVGhlIGFjY3VtdWxhdGVkIHJlc3VsdC5cbiAgICovXG4gIGZ1bmN0aW9uIHJlZHVjZShhcnJheSwgY2FsbGJhY2spIHtcbiAgICB2YXIgYWNjdW11bGF0b3IgPSBudWxsO1xuICAgIGVhY2goYXJyYXksIGZ1bmN0aW9uKHZhbHVlLCBpbmRleCkge1xuICAgICAgYWNjdW11bGF0b3IgPSBjYWxsYmFjayhhY2N1bXVsYXRvciwgdmFsdWUsIGluZGV4LCBhcnJheSk7XG4gICAgfSk7XG4gICAgcmV0dXJuIGFjY3VtdWxhdG9yO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlbW92ZXMgbGVhZGluZyBhbmQgdHJhaWxpbmcgd2hpdGVzcGFjZSBmcm9tIGEgc3RyaW5nLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gc3RyaW5nIFRoZSBzdHJpbmcgdG8gdHJpbS5cbiAgICogQHJldHVybnMge3N0cmluZ30gVGhlIHRyaW1tZWQgc3RyaW5nLlxuICAgKi9cbiAgZnVuY3Rpb24gdHJpbShzdHJpbmcpIHtcbiAgICByZXR1cm4gU3RyaW5nKHN0cmluZykucmVwbGFjZSgvXiArfCArJC9nLCAnJyk7XG4gIH1cblxuICAvKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cblxuICAvKipcbiAgICogQ3JlYXRlcyBhIG5ldyBwbGF0Zm9ybSBvYmplY3QuXG4gICAqXG4gICAqIEBtZW1iZXJPZiBwbGF0Zm9ybVxuICAgKiBAcGFyYW0ge09iamVjdHxzdHJpbmd9IFt1YT1uYXZpZ2F0b3IudXNlckFnZW50XSBUaGUgdXNlciBhZ2VudCBzdHJpbmcgb3JcbiAgICogIGNvbnRleHQgb2JqZWN0LlxuICAgKiBAcmV0dXJucyB7T2JqZWN0fSBBIHBsYXRmb3JtIG9iamVjdC5cbiAgICovXG4gIGZ1bmN0aW9uIHBhcnNlKHVhKSB7XG5cbiAgICAvKiogVGhlIGVudmlyb25tZW50IGNvbnRleHQgb2JqZWN0LiAqL1xuICAgIHZhciBjb250ZXh0ID0gcm9vdDtcblxuICAgIC8qKiBVc2VkIHRvIGZsYWcgd2hlbiBhIGN1c3RvbSBjb250ZXh0IGlzIHByb3ZpZGVkLiAqL1xuICAgIHZhciBpc0N1c3RvbUNvbnRleHQgPSB1YSAmJiB0eXBlb2YgdWEgPT0gJ29iamVjdCcgJiYgZ2V0Q2xhc3NPZih1YSkgIT0gJ1N0cmluZyc7XG5cbiAgICAvLyBKdWdnbGUgYXJndW1lbnRzLlxuICAgIGlmIChpc0N1c3RvbUNvbnRleHQpIHtcbiAgICAgIGNvbnRleHQgPSB1YTtcbiAgICAgIHVhID0gbnVsbDtcbiAgICB9XG5cbiAgICAvKiogQnJvd3NlciBuYXZpZ2F0b3Igb2JqZWN0LiAqL1xuICAgIHZhciBuYXYgPSBjb250ZXh0Lm5hdmlnYXRvciB8fCB7fTtcblxuICAgIC8qKiBCcm93c2VyIHVzZXIgYWdlbnQgc3RyaW5nLiAqL1xuICAgIHZhciB1c2VyQWdlbnQgPSBuYXYudXNlckFnZW50IHx8ICcnO1xuXG4gICAgdWEgfHwgKHVhID0gdXNlckFnZW50KTtcblxuICAgIC8qKiBVc2VkIHRvIGZsYWcgd2hlbiBgdGhpc0JpbmRpbmdgIGlzIHRoZSBbTW9kdWxlU2NvcGVdLiAqL1xuICAgIHZhciBpc01vZHVsZVNjb3BlID0gaXNDdXN0b21Db250ZXh0IHx8IHRoaXNCaW5kaW5nID09IG9sZFJvb3Q7XG5cbiAgICAvKiogVXNlZCB0byBkZXRlY3QgaWYgYnJvd3NlciBpcyBsaWtlIENocm9tZS4gKi9cbiAgICB2YXIgbGlrZUNocm9tZSA9IGlzQ3VzdG9tQ29udGV4dFxuICAgICAgPyAhIW5hdi5saWtlQ2hyb21lXG4gICAgICA6IC9cXGJDaHJvbWVcXGIvLnRlc3QodWEpICYmICEvaW50ZXJuYWx8XFxuL2kudGVzdCh0b1N0cmluZy50b1N0cmluZygpKTtcblxuICAgIC8qKiBJbnRlcm5hbCBgW1tDbGFzc11dYCB2YWx1ZSBzaG9ydGN1dHMuICovXG4gICAgdmFyIG9iamVjdENsYXNzID0gJ09iamVjdCcsXG4gICAgICAgIGFpclJ1bnRpbWVDbGFzcyA9IGlzQ3VzdG9tQ29udGV4dCA/IG9iamVjdENsYXNzIDogJ1NjcmlwdEJyaWRnaW5nUHJveHlPYmplY3QnLFxuICAgICAgICBlbnZpcm9DbGFzcyA9IGlzQ3VzdG9tQ29udGV4dCA/IG9iamVjdENsYXNzIDogJ0Vudmlyb25tZW50JyxcbiAgICAgICAgamF2YUNsYXNzID0gKGlzQ3VzdG9tQ29udGV4dCAmJiBjb250ZXh0LmphdmEpID8gJ0phdmFQYWNrYWdlJyA6IGdldENsYXNzT2YoY29udGV4dC5qYXZhKSxcbiAgICAgICAgcGhhbnRvbUNsYXNzID0gaXNDdXN0b21Db250ZXh0ID8gb2JqZWN0Q2xhc3MgOiAnUnVudGltZU9iamVjdCc7XG5cbiAgICAvKiogRGV0ZWN0IEphdmEgZW52aXJvbm1lbnRzLiAqL1xuICAgIHZhciBqYXZhID0gL1xcYkphdmEvLnRlc3QoamF2YUNsYXNzKSAmJiBjb250ZXh0LmphdmE7XG5cbiAgICAvKiogRGV0ZWN0IFJoaW5vLiAqL1xuICAgIHZhciByaGlubyA9IGphdmEgJiYgZ2V0Q2xhc3NPZihjb250ZXh0LmVudmlyb25tZW50KSA9PSBlbnZpcm9DbGFzcztcblxuICAgIC8qKiBBIGNoYXJhY3RlciB0byByZXByZXNlbnQgYWxwaGEuICovXG4gICAgdmFyIGFscGhhID0gamF2YSA/ICdhJyA6ICdcXHUwM2IxJztcblxuICAgIC8qKiBBIGNoYXJhY3RlciB0byByZXByZXNlbnQgYmV0YS4gKi9cbiAgICB2YXIgYmV0YSA9IGphdmEgPyAnYicgOiAnXFx1MDNiMic7XG5cbiAgICAvKiogQnJvd3NlciBkb2N1bWVudCBvYmplY3QuICovXG4gICAgdmFyIGRvYyA9IGNvbnRleHQuZG9jdW1lbnQgfHwge307XG5cbiAgICAvKipcbiAgICAgKiBEZXRlY3QgT3BlcmEgYnJvd3NlciAoUHJlc3RvLWJhc2VkKS5cbiAgICAgKiBodHRwOi8vd3d3Lmhvd3RvY3JlYXRlLmNvLnVrL29wZXJhU3R1ZmYvb3BlcmFPYmplY3QuaHRtbFxuICAgICAqIGh0dHA6Ly9kZXYub3BlcmEuY29tL2FydGljbGVzL3ZpZXcvb3BlcmEtbWluaS13ZWItY29udGVudC1hdXRob3JpbmctZ3VpZGVsaW5lcy8jb3BlcmFtaW5pXG4gICAgICovXG4gICAgdmFyIG9wZXJhID0gY29udGV4dC5vcGVyYW1pbmkgfHwgY29udGV4dC5vcGVyYTtcblxuICAgIC8qKiBPcGVyYSBgW1tDbGFzc11dYC4gKi9cbiAgICB2YXIgb3BlcmFDbGFzcyA9IHJlT3BlcmEudGVzdChvcGVyYUNsYXNzID0gKGlzQ3VzdG9tQ29udGV4dCAmJiBvcGVyYSkgPyBvcGVyYVsnW1tDbGFzc11dJ10gOiBnZXRDbGFzc09mKG9wZXJhKSlcbiAgICAgID8gb3BlcmFDbGFzc1xuICAgICAgOiAob3BlcmEgPSBudWxsKTtcblxuICAgIC8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cblxuICAgIC8qKiBUZW1wb3JhcnkgdmFyaWFibGUgdXNlZCBvdmVyIHRoZSBzY3JpcHQncyBsaWZldGltZS4gKi9cbiAgICB2YXIgZGF0YTtcblxuICAgIC8qKiBUaGUgQ1BVIGFyY2hpdGVjdHVyZS4gKi9cbiAgICB2YXIgYXJjaCA9IHVhO1xuXG4gICAgLyoqIFBsYXRmb3JtIGRlc2NyaXB0aW9uIGFycmF5LiAqL1xuICAgIHZhciBkZXNjcmlwdGlvbiA9IFtdO1xuXG4gICAgLyoqIFBsYXRmb3JtIGFscGhhL2JldGEgaW5kaWNhdG9yLiAqL1xuICAgIHZhciBwcmVyZWxlYXNlID0gbnVsbDtcblxuICAgIC8qKiBBIGZsYWcgdG8gaW5kaWNhdGUgdGhhdCBlbnZpcm9ubWVudCBmZWF0dXJlcyBzaG91bGQgYmUgdXNlZCB0byByZXNvbHZlIHRoZSBwbGF0Zm9ybS4gKi9cbiAgICB2YXIgdXNlRmVhdHVyZXMgPSB1YSA9PSB1c2VyQWdlbnQ7XG5cbiAgICAvKiogVGhlIGJyb3dzZXIvZW52aXJvbm1lbnQgdmVyc2lvbi4gKi9cbiAgICB2YXIgdmVyc2lvbiA9IHVzZUZlYXR1cmVzICYmIG9wZXJhICYmIHR5cGVvZiBvcGVyYS52ZXJzaW9uID09ICdmdW5jdGlvbicgJiYgb3BlcmEudmVyc2lvbigpO1xuXG4gICAgLyoqIEEgZmxhZyB0byBpbmRpY2F0ZSBpZiB0aGUgT1MgZW5kcyB3aXRoIFwiLyBWZXJzaW9uXCIgKi9cbiAgICB2YXIgaXNTcGVjaWFsQ2FzZWRPUztcblxuICAgIC8qIERldGVjdGFibGUgbGF5b3V0IGVuZ2luZXMgKG9yZGVyIGlzIGltcG9ydGFudCkuICovXG4gICAgdmFyIGxheW91dCA9IGdldExheW91dChbXG4gICAgICB7ICdsYWJlbCc6ICdFZGdlSFRNTCcsICdwYXR0ZXJuJzogJ0VkZ2UnIH0sXG4gICAgICAnVHJpZGVudCcsXG4gICAgICB7ICdsYWJlbCc6ICdXZWJLaXQnLCAncGF0dGVybic6ICdBcHBsZVdlYktpdCcgfSxcbiAgICAgICdpQ2FiJyxcbiAgICAgICdQcmVzdG8nLFxuICAgICAgJ05ldEZyb250JyxcbiAgICAgICdUYXNtYW4nLFxuICAgICAgJ0tIVE1MJyxcbiAgICAgICdHZWNrbydcbiAgICBdKTtcblxuICAgIC8qIERldGVjdGFibGUgYnJvd3NlciBuYW1lcyAob3JkZXIgaXMgaW1wb3J0YW50KS4gKi9cbiAgICB2YXIgbmFtZSA9IGdldE5hbWUoW1xuICAgICAgJ0Fkb2JlIEFJUicsXG4gICAgICAnQXJvcmEnLFxuICAgICAgJ0F2YW50IEJyb3dzZXInLFxuICAgICAgJ0JyZWFjaCcsXG4gICAgICAnQ2FtaW5vJyxcbiAgICAgICdFbGVjdHJvbicsXG4gICAgICAnRXBpcGhhbnknLFxuICAgICAgJ0Zlbm5lYycsXG4gICAgICAnRmxvY2snLFxuICAgICAgJ0dhbGVvbicsXG4gICAgICAnR3JlZW5Ccm93c2VyJyxcbiAgICAgICdpQ2FiJyxcbiAgICAgICdJY2V3ZWFzZWwnLFxuICAgICAgJ0stTWVsZW9uJyxcbiAgICAgICdLb25xdWVyb3InLFxuICAgICAgJ0x1bmFzY2FwZScsXG4gICAgICAnTWF4dGhvbicsXG4gICAgICB7ICdsYWJlbCc6ICdNaWNyb3NvZnQgRWRnZScsICdwYXR0ZXJuJzogJ0VkZ2UnIH0sXG4gICAgICAnTWlkb3JpJyxcbiAgICAgICdOb29rIEJyb3dzZXInLFxuICAgICAgJ1BhbGVNb29uJyxcbiAgICAgICdQaGFudG9tSlMnLFxuICAgICAgJ1JhdmVuJyxcbiAgICAgICdSZWtvbnEnLFxuICAgICAgJ1JvY2tNZWx0JyxcbiAgICAgIHsgJ2xhYmVsJzogJ1NhbXN1bmcgSW50ZXJuZXQnLCAncGF0dGVybic6ICdTYW1zdW5nQnJvd3NlcicgfSxcbiAgICAgICdTZWFNb25rZXknLFxuICAgICAgeyAnbGFiZWwnOiAnU2lsaycsICdwYXR0ZXJuJzogJyg/OkNsb3VkOXxTaWxrLUFjY2VsZXJhdGVkKScgfSxcbiAgICAgICdTbGVpcG5pcicsXG4gICAgICAnU2xpbUJyb3dzZXInLFxuICAgICAgeyAnbGFiZWwnOiAnU1JXYXJlIElyb24nLCAncGF0dGVybic6ICdJcm9uJyB9LFxuICAgICAgJ1N1bnJpc2UnLFxuICAgICAgJ1N3aWZ0Zm94JyxcbiAgICAgICdXYXRlcmZveCcsXG4gICAgICAnV2ViUG9zaXRpdmUnLFxuICAgICAgJ09wZXJhIE1pbmknLFxuICAgICAgeyAnbGFiZWwnOiAnT3BlcmEgTWluaScsICdwYXR0ZXJuJzogJ09QaU9TJyB9LFxuICAgICAgJ09wZXJhJyxcbiAgICAgIHsgJ2xhYmVsJzogJ09wZXJhJywgJ3BhdHRlcm4nOiAnT1BSJyB9LFxuICAgICAgJ0Nocm9tZScsXG4gICAgICB7ICdsYWJlbCc6ICdDaHJvbWUgTW9iaWxlJywgJ3BhdHRlcm4nOiAnKD86Q3JpT1N8Q3JNbyknIH0sXG4gICAgICB7ICdsYWJlbCc6ICdGaXJlZm94JywgJ3BhdHRlcm4nOiAnKD86RmlyZWZveHxNaW5lZmllbGQpJyB9LFxuICAgICAgeyAnbGFiZWwnOiAnRmlyZWZveCBmb3IgaU9TJywgJ3BhdHRlcm4nOiAnRnhpT1MnIH0sXG4gICAgICB7ICdsYWJlbCc6ICdJRScsICdwYXR0ZXJuJzogJ0lFTW9iaWxlJyB9LFxuICAgICAgeyAnbGFiZWwnOiAnSUUnLCAncGF0dGVybic6ICdNU0lFJyB9LFxuICAgICAgJ1NhZmFyaSdcbiAgICBdKTtcblxuICAgIC8qIERldGVjdGFibGUgcHJvZHVjdHMgKG9yZGVyIGlzIGltcG9ydGFudCkuICovXG4gICAgdmFyIHByb2R1Y3QgPSBnZXRQcm9kdWN0KFtcbiAgICAgIHsgJ2xhYmVsJzogJ0JsYWNrQmVycnknLCAncGF0dGVybic6ICdCQjEwJyB9LFxuICAgICAgJ0JsYWNrQmVycnknLFxuICAgICAgeyAnbGFiZWwnOiAnR2FsYXh5IFMnLCAncGF0dGVybic6ICdHVC1JOTAwMCcgfSxcbiAgICAgIHsgJ2xhYmVsJzogJ0dhbGF4eSBTMicsICdwYXR0ZXJuJzogJ0dULUk5MTAwJyB9LFxuICAgICAgeyAnbGFiZWwnOiAnR2FsYXh5IFMzJywgJ3BhdHRlcm4nOiAnR1QtSTkzMDAnIH0sXG4gICAgICB7ICdsYWJlbCc6ICdHYWxheHkgUzQnLCAncGF0dGVybic6ICdHVC1JOTUwMCcgfSxcbiAgICAgIHsgJ2xhYmVsJzogJ0dhbGF4eSBTNScsICdwYXR0ZXJuJzogJ1NNLUc5MDAnIH0sXG4gICAgICB7ICdsYWJlbCc6ICdHYWxheHkgUzYnLCAncGF0dGVybic6ICdTTS1HOTIwJyB9LFxuICAgICAgeyAnbGFiZWwnOiAnR2FsYXh5IFM2IEVkZ2UnLCAncGF0dGVybic6ICdTTS1HOTI1JyB9LFxuICAgICAgeyAnbGFiZWwnOiAnR2FsYXh5IFM3JywgJ3BhdHRlcm4nOiAnU00tRzkzMCcgfSxcbiAgICAgIHsgJ2xhYmVsJzogJ0dhbGF4eSBTNyBFZGdlJywgJ3BhdHRlcm4nOiAnU00tRzkzNScgfSxcbiAgICAgICdHb29nbGUgVFYnLFxuICAgICAgJ0x1bWlhJyxcbiAgICAgICdpUGFkJyxcbiAgICAgICdpUG9kJyxcbiAgICAgICdpUGhvbmUnLFxuICAgICAgJ0tpbmRsZScsXG4gICAgICB7ICdsYWJlbCc6ICdLaW5kbGUgRmlyZScsICdwYXR0ZXJuJzogJyg/OkNsb3VkOXxTaWxrLUFjY2VsZXJhdGVkKScgfSxcbiAgICAgICdOZXh1cycsXG4gICAgICAnTm9vaycsXG4gICAgICAnUGxheUJvb2snLFxuICAgICAgJ1BsYXlTdGF0aW9uIFZpdGEnLFxuICAgICAgJ1BsYXlTdGF0aW9uJyxcbiAgICAgICdUb3VjaFBhZCcsXG4gICAgICAnVHJhbnNmb3JtZXInLFxuICAgICAgeyAnbGFiZWwnOiAnV2lpIFUnLCAncGF0dGVybic6ICdXaWlVJyB9LFxuICAgICAgJ1dpaScsXG4gICAgICAnWGJveCBPbmUnLFxuICAgICAgeyAnbGFiZWwnOiAnWGJveCAzNjAnLCAncGF0dGVybic6ICdYYm94JyB9LFxuICAgICAgJ1hvb20nXG4gICAgXSk7XG5cbiAgICAvKiBEZXRlY3RhYmxlIG1hbnVmYWN0dXJlcnMuICovXG4gICAgdmFyIG1hbnVmYWN0dXJlciA9IGdldE1hbnVmYWN0dXJlcih7XG4gICAgICAnQXBwbGUnOiB7ICdpUGFkJzogMSwgJ2lQaG9uZSc6IDEsICdpUG9kJzogMSB9LFxuICAgICAgJ0FyY2hvcyc6IHt9LFxuICAgICAgJ0FtYXpvbic6IHsgJ0tpbmRsZSc6IDEsICdLaW5kbGUgRmlyZSc6IDEgfSxcbiAgICAgICdBc3VzJzogeyAnVHJhbnNmb3JtZXInOiAxIH0sXG4gICAgICAnQmFybmVzICYgTm9ibGUnOiB7ICdOb29rJzogMSB9LFxuICAgICAgJ0JsYWNrQmVycnknOiB7ICdQbGF5Qm9vayc6IDEgfSxcbiAgICAgICdHb29nbGUnOiB7ICdHb29nbGUgVFYnOiAxLCAnTmV4dXMnOiAxIH0sXG4gICAgICAnSFAnOiB7ICdUb3VjaFBhZCc6IDEgfSxcbiAgICAgICdIVEMnOiB7fSxcbiAgICAgICdMRyc6IHt9LFxuICAgICAgJ01pY3Jvc29mdCc6IHsgJ1hib3gnOiAxLCAnWGJveCBPbmUnOiAxIH0sXG4gICAgICAnTW90b3JvbGEnOiB7ICdYb29tJzogMSB9LFxuICAgICAgJ05pbnRlbmRvJzogeyAnV2lpIFUnOiAxLCAgJ1dpaSc6IDEgfSxcbiAgICAgICdOb2tpYSc6IHsgJ0x1bWlhJzogMSB9LFxuICAgICAgJ1NhbXN1bmcnOiB7ICdHYWxheHkgUyc6IDEsICdHYWxheHkgUzInOiAxLCAnR2FsYXh5IFMzJzogMSwgJ0dhbGF4eSBTNCc6IDEgfSxcbiAgICAgICdTb255JzogeyAnUGxheVN0YXRpb24nOiAxLCAnUGxheVN0YXRpb24gVml0YSc6IDEgfVxuICAgIH0pO1xuXG4gICAgLyogRGV0ZWN0YWJsZSBvcGVyYXRpbmcgc3lzdGVtcyAob3JkZXIgaXMgaW1wb3J0YW50KS4gKi9cbiAgICB2YXIgb3MgPSBnZXRPUyhbXG4gICAgICAnV2luZG93cyBQaG9uZScsXG4gICAgICAnQW5kcm9pZCcsXG4gICAgICAnQ2VudE9TJyxcbiAgICAgIHsgJ2xhYmVsJzogJ0Nocm9tZSBPUycsICdwYXR0ZXJuJzogJ0NyT1MnIH0sXG4gICAgICAnRGViaWFuJyxcbiAgICAgICdGZWRvcmEnLFxuICAgICAgJ0ZyZWVCU0QnLFxuICAgICAgJ0dlbnRvbycsXG4gICAgICAnSGFpa3UnLFxuICAgICAgJ0t1YnVudHUnLFxuICAgICAgJ0xpbnV4IE1pbnQnLFxuICAgICAgJ09wZW5CU0QnLFxuICAgICAgJ1JlZCBIYXQnLFxuICAgICAgJ1N1U0UnLFxuICAgICAgJ1VidW50dScsXG4gICAgICAnWHVidW50dScsXG4gICAgICAnQ3lnd2luJyxcbiAgICAgICdTeW1iaWFuIE9TJyxcbiAgICAgICdocHdPUycsXG4gICAgICAnd2ViT1MgJyxcbiAgICAgICd3ZWJPUycsXG4gICAgICAnVGFibGV0IE9TJyxcbiAgICAgICdUaXplbicsXG4gICAgICAnTGludXgnLFxuICAgICAgJ01hYyBPUyBYJyxcbiAgICAgICdNYWNpbnRvc2gnLFxuICAgICAgJ01hYycsXG4gICAgICAnV2luZG93cyA5ODsnLFxuICAgICAgJ1dpbmRvd3MgJ1xuICAgIF0pO1xuXG4gICAgLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuXG4gICAgLyoqXG4gICAgICogUGlja3MgdGhlIGxheW91dCBlbmdpbmUgZnJvbSBhbiBhcnJheSBvZiBndWVzc2VzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBndWVzc2VzIEFuIGFycmF5IG9mIGd1ZXNzZXMuXG4gICAgICogQHJldHVybnMge251bGx8c3RyaW5nfSBUaGUgZGV0ZWN0ZWQgbGF5b3V0IGVuZ2luZS5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBnZXRMYXlvdXQoZ3Vlc3Nlcykge1xuICAgICAgcmV0dXJuIHJlZHVjZShndWVzc2VzLCBmdW5jdGlvbihyZXN1bHQsIGd1ZXNzKSB7XG4gICAgICAgIHJldHVybiByZXN1bHQgfHwgUmVnRXhwKCdcXFxcYicgKyAoXG4gICAgICAgICAgZ3Vlc3MucGF0dGVybiB8fCBxdWFsaWZ5KGd1ZXNzKVxuICAgICAgICApICsgJ1xcXFxiJywgJ2knKS5leGVjKHVhKSAmJiAoZ3Vlc3MubGFiZWwgfHwgZ3Vlc3MpO1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUGlja3MgdGhlIG1hbnVmYWN0dXJlciBmcm9tIGFuIGFycmF5IG9mIGd1ZXNzZXMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGd1ZXNzZXMgQW4gb2JqZWN0IG9mIGd1ZXNzZXMuXG4gICAgICogQHJldHVybnMge251bGx8c3RyaW5nfSBUaGUgZGV0ZWN0ZWQgbWFudWZhY3R1cmVyLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGdldE1hbnVmYWN0dXJlcihndWVzc2VzKSB7XG4gICAgICByZXR1cm4gcmVkdWNlKGd1ZXNzZXMsIGZ1bmN0aW9uKHJlc3VsdCwgdmFsdWUsIGtleSkge1xuICAgICAgICAvLyBMb29rdXAgdGhlIG1hbnVmYWN0dXJlciBieSBwcm9kdWN0IG9yIHNjYW4gdGhlIFVBIGZvciB0aGUgbWFudWZhY3R1cmVyLlxuICAgICAgICByZXR1cm4gcmVzdWx0IHx8IChcbiAgICAgICAgICB2YWx1ZVtwcm9kdWN0XSB8fFxuICAgICAgICAgIHZhbHVlWy9eW2Etel0rKD86ICtbYS16XStcXGIpKi9pLmV4ZWMocHJvZHVjdCldIHx8XG4gICAgICAgICAgUmVnRXhwKCdcXFxcYicgKyBxdWFsaWZ5KGtleSkgKyAnKD86XFxcXGJ8XFxcXHcqXFxcXGQpJywgJ2knKS5leGVjKHVhKVxuICAgICAgICApICYmIGtleTtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFBpY2tzIHRoZSBicm93c2VyIG5hbWUgZnJvbSBhbiBhcnJheSBvZiBndWVzc2VzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBndWVzc2VzIEFuIGFycmF5IG9mIGd1ZXNzZXMuXG4gICAgICogQHJldHVybnMge251bGx8c3RyaW5nfSBUaGUgZGV0ZWN0ZWQgYnJvd3NlciBuYW1lLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGdldE5hbWUoZ3Vlc3Nlcykge1xuICAgICAgcmV0dXJuIHJlZHVjZShndWVzc2VzLCBmdW5jdGlvbihyZXN1bHQsIGd1ZXNzKSB7XG4gICAgICAgIHJldHVybiByZXN1bHQgfHwgUmVnRXhwKCdcXFxcYicgKyAoXG4gICAgICAgICAgZ3Vlc3MucGF0dGVybiB8fCBxdWFsaWZ5KGd1ZXNzKVxuICAgICAgICApICsgJ1xcXFxiJywgJ2knKS5leGVjKHVhKSAmJiAoZ3Vlc3MubGFiZWwgfHwgZ3Vlc3MpO1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUGlja3MgdGhlIE9TIG5hbWUgZnJvbSBhbiBhcnJheSBvZiBndWVzc2VzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBndWVzc2VzIEFuIGFycmF5IG9mIGd1ZXNzZXMuXG4gICAgICogQHJldHVybnMge251bGx8c3RyaW5nfSBUaGUgZGV0ZWN0ZWQgT1MgbmFtZS5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBnZXRPUyhndWVzc2VzKSB7XG4gICAgICByZXR1cm4gcmVkdWNlKGd1ZXNzZXMsIGZ1bmN0aW9uKHJlc3VsdCwgZ3Vlc3MpIHtcbiAgICAgICAgdmFyIHBhdHRlcm4gPSBndWVzcy5wYXR0ZXJuIHx8IHF1YWxpZnkoZ3Vlc3MpO1xuICAgICAgICBpZiAoIXJlc3VsdCAmJiAocmVzdWx0ID1cbiAgICAgICAgICAgICAgUmVnRXhwKCdcXFxcYicgKyBwYXR0ZXJuICsgJyg/Oi9bXFxcXGQuXSt8WyBcXFxcdy5dKiknLCAnaScpLmV4ZWModWEpXG4gICAgICAgICAgICApKSB7XG4gICAgICAgICAgcmVzdWx0ID0gY2xlYW51cE9TKHJlc3VsdCwgcGF0dGVybiwgZ3Vlc3MubGFiZWwgfHwgZ3Vlc3MpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBQaWNrcyB0aGUgcHJvZHVjdCBuYW1lIGZyb20gYW4gYXJyYXkgb2YgZ3Vlc3Nlcy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtBcnJheX0gZ3Vlc3NlcyBBbiBhcnJheSBvZiBndWVzc2VzLlxuICAgICAqIEByZXR1cm5zIHtudWxsfHN0cmluZ30gVGhlIGRldGVjdGVkIHByb2R1Y3QgbmFtZS5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBnZXRQcm9kdWN0KGd1ZXNzZXMpIHtcbiAgICAgIHJldHVybiByZWR1Y2UoZ3Vlc3NlcywgZnVuY3Rpb24ocmVzdWx0LCBndWVzcykge1xuICAgICAgICB2YXIgcGF0dGVybiA9IGd1ZXNzLnBhdHRlcm4gfHwgcXVhbGlmeShndWVzcyk7XG4gICAgICAgIGlmICghcmVzdWx0ICYmIChyZXN1bHQgPVxuICAgICAgICAgICAgICBSZWdFeHAoJ1xcXFxiJyArIHBhdHRlcm4gKyAnICpcXFxcZCtbLlxcXFx3X10qJywgJ2knKS5leGVjKHVhKSB8fFxuICAgICAgICAgICAgICBSZWdFeHAoJ1xcXFxiJyArIHBhdHRlcm4gKyAnICpcXFxcdystW1xcXFx3XSonLCAnaScpLmV4ZWModWEpIHx8XG4gICAgICAgICAgICAgIFJlZ0V4cCgnXFxcXGInICsgcGF0dGVybiArICcoPzo7ICooPzpbYS16XStbXy1dKT9bYS16XStcXFxcZCt8W14gKCk7LV0qKScsICdpJykuZXhlYyh1YSlcbiAgICAgICAgICAgICkpIHtcbiAgICAgICAgICAvLyBTcGxpdCBieSBmb3J3YXJkIHNsYXNoIGFuZCBhcHBlbmQgcHJvZHVjdCB2ZXJzaW9uIGlmIG5lZWRlZC5cbiAgICAgICAgICBpZiAoKHJlc3VsdCA9IFN0cmluZygoZ3Vlc3MubGFiZWwgJiYgIVJlZ0V4cChwYXR0ZXJuLCAnaScpLnRlc3QoZ3Vlc3MubGFiZWwpKSA/IGd1ZXNzLmxhYmVsIDogcmVzdWx0KS5zcGxpdCgnLycpKVsxXSAmJiAhL1tcXGQuXSsvLnRlc3QocmVzdWx0WzBdKSkge1xuICAgICAgICAgICAgcmVzdWx0WzBdICs9ICcgJyArIHJlc3VsdFsxXTtcbiAgICAgICAgICB9XG4gICAgICAgICAgLy8gQ29ycmVjdCBjaGFyYWN0ZXIgY2FzZSBhbmQgY2xlYW51cCBzdHJpbmcuXG4gICAgICAgICAgZ3Vlc3MgPSBndWVzcy5sYWJlbCB8fCBndWVzcztcbiAgICAgICAgICByZXN1bHQgPSBmb3JtYXQocmVzdWx0WzBdXG4gICAgICAgICAgICAucmVwbGFjZShSZWdFeHAocGF0dGVybiwgJ2knKSwgZ3Vlc3MpXG4gICAgICAgICAgICAucmVwbGFjZShSZWdFeHAoJzsgKig/OicgKyBndWVzcyArICdbXy1dKT8nLCAnaScpLCAnICcpXG4gICAgICAgICAgICAucmVwbGFjZShSZWdFeHAoJygnICsgZ3Vlc3MgKyAnKVstXy5dPyhcXFxcdyknLCAnaScpLCAnJDEgJDInKSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlc29sdmVzIHRoZSB2ZXJzaW9uIHVzaW5nIGFuIGFycmF5IG9mIFVBIHBhdHRlcm5zLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBwYXR0ZXJucyBBbiBhcnJheSBvZiBVQSBwYXR0ZXJucy5cbiAgICAgKiBAcmV0dXJucyB7bnVsbHxzdHJpbmd9IFRoZSBkZXRlY3RlZCB2ZXJzaW9uLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGdldFZlcnNpb24ocGF0dGVybnMpIHtcbiAgICAgIHJldHVybiByZWR1Y2UocGF0dGVybnMsIGZ1bmN0aW9uKHJlc3VsdCwgcGF0dGVybikge1xuICAgICAgICByZXR1cm4gcmVzdWx0IHx8IChSZWdFeHAocGF0dGVybiArXG4gICAgICAgICAgJyg/Oi1bXFxcXGQuXSsvfCg/OiBmb3IgW1xcXFx3LV0rKT9bIC8tXSkoW1xcXFxkLl0rW14gKCk7L18tXSopJywgJ2knKS5leGVjKHVhKSB8fCAwKVsxXSB8fCBudWxsO1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyBgcGxhdGZvcm0uZGVzY3JpcHRpb25gIHdoZW4gdGhlIHBsYXRmb3JtIG9iamVjdCBpcyBjb2VyY2VkIHRvIGEgc3RyaW5nLlxuICAgICAqXG4gICAgICogQG5hbWUgdG9TdHJpbmdcbiAgICAgKiBAbWVtYmVyT2YgcGxhdGZvcm1cbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfSBSZXR1cm5zIGBwbGF0Zm9ybS5kZXNjcmlwdGlvbmAgaWYgYXZhaWxhYmxlLCBlbHNlIGFuIGVtcHR5IHN0cmluZy5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiB0b1N0cmluZ1BsYXRmb3JtKCkge1xuICAgICAgcmV0dXJuIHRoaXMuZGVzY3JpcHRpb24gfHwgJyc7XG4gICAgfVxuXG4gICAgLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuXG4gICAgLy8gQ29udmVydCBsYXlvdXQgdG8gYW4gYXJyYXkgc28gd2UgY2FuIGFkZCBleHRyYSBkZXRhaWxzLlxuICAgIGxheW91dCAmJiAobGF5b3V0ID0gW2xheW91dF0pO1xuXG4gICAgLy8gRGV0ZWN0IHByb2R1Y3QgbmFtZXMgdGhhdCBjb250YWluIHRoZWlyIG1hbnVmYWN0dXJlcidzIG5hbWUuXG4gICAgaWYgKG1hbnVmYWN0dXJlciAmJiAhcHJvZHVjdCkge1xuICAgICAgcHJvZHVjdCA9IGdldFByb2R1Y3QoW21hbnVmYWN0dXJlcl0pO1xuICAgIH1cbiAgICAvLyBDbGVhbiB1cCBHb29nbGUgVFYuXG4gICAgaWYgKChkYXRhID0gL1xcYkdvb2dsZSBUVlxcYi8uZXhlYyhwcm9kdWN0KSkpIHtcbiAgICAgIHByb2R1Y3QgPSBkYXRhWzBdO1xuICAgIH1cbiAgICAvLyBEZXRlY3Qgc2ltdWxhdG9ycy5cbiAgICBpZiAoL1xcYlNpbXVsYXRvclxcYi9pLnRlc3QodWEpKSB7XG4gICAgICBwcm9kdWN0ID0gKHByb2R1Y3QgPyBwcm9kdWN0ICsgJyAnIDogJycpICsgJ1NpbXVsYXRvcic7XG4gICAgfVxuICAgIC8vIERldGVjdCBPcGVyYSBNaW5pIDgrIHJ1bm5pbmcgaW4gVHVyYm8vVW5jb21wcmVzc2VkIG1vZGUgb24gaU9TLlxuICAgIGlmIChuYW1lID09ICdPcGVyYSBNaW5pJyAmJiAvXFxiT1BpT1NcXGIvLnRlc3QodWEpKSB7XG4gICAgICBkZXNjcmlwdGlvbi5wdXNoKCdydW5uaW5nIGluIFR1cmJvL1VuY29tcHJlc3NlZCBtb2RlJyk7XG4gICAgfVxuICAgIC8vIERldGVjdCBJRSBNb2JpbGUgMTEuXG4gICAgaWYgKG5hbWUgPT0gJ0lFJyAmJiAvXFxibGlrZSBpUGhvbmUgT1NcXGIvLnRlc3QodWEpKSB7XG4gICAgICBkYXRhID0gcGFyc2UodWEucmVwbGFjZSgvbGlrZSBpUGhvbmUgT1MvLCAnJykpO1xuICAgICAgbWFudWZhY3R1cmVyID0gZGF0YS5tYW51ZmFjdHVyZXI7XG4gICAgICBwcm9kdWN0ID0gZGF0YS5wcm9kdWN0O1xuICAgIH1cbiAgICAvLyBEZXRlY3QgaU9TLlxuICAgIGVsc2UgaWYgKC9eaVAvLnRlc3QocHJvZHVjdCkpIHtcbiAgICAgIG5hbWUgfHwgKG5hbWUgPSAnU2FmYXJpJyk7XG4gICAgICBvcyA9ICdpT1MnICsgKChkYXRhID0gLyBPUyAoW1xcZF9dKykvaS5leGVjKHVhKSlcbiAgICAgICAgPyAnICcgKyBkYXRhWzFdLnJlcGxhY2UoL18vZywgJy4nKVxuICAgICAgICA6ICcnKTtcbiAgICB9XG4gICAgLy8gRGV0ZWN0IEt1YnVudHUuXG4gICAgZWxzZSBpZiAobmFtZSA9PSAnS29ucXVlcm9yJyAmJiAhL2J1bnR1L2kudGVzdChvcykpIHtcbiAgICAgIG9zID0gJ0t1YnVudHUnO1xuICAgIH1cbiAgICAvLyBEZXRlY3QgQW5kcm9pZCBicm93c2Vycy5cbiAgICBlbHNlIGlmICgobWFudWZhY3R1cmVyICYmIG1hbnVmYWN0dXJlciAhPSAnR29vZ2xlJyAmJlxuICAgICAgICAoKC9DaHJvbWUvLnRlc3QobmFtZSkgJiYgIS9cXGJNb2JpbGUgU2FmYXJpXFxiL2kudGVzdCh1YSkpIHx8IC9cXGJWaXRhXFxiLy50ZXN0KHByb2R1Y3QpKSkgfHxcbiAgICAgICAgKC9cXGJBbmRyb2lkXFxiLy50ZXN0KG9zKSAmJiAvXkNocm9tZS8udGVzdChuYW1lKSAmJiAvXFxiVmVyc2lvblxcLy9pLnRlc3QodWEpKSkge1xuICAgICAgbmFtZSA9ICdBbmRyb2lkIEJyb3dzZXInO1xuICAgICAgb3MgPSAvXFxiQW5kcm9pZFxcYi8udGVzdChvcykgPyBvcyA6ICdBbmRyb2lkJztcbiAgICB9XG4gICAgLy8gRGV0ZWN0IFNpbGsgZGVza3RvcC9hY2NlbGVyYXRlZCBtb2Rlcy5cbiAgICBlbHNlIGlmIChuYW1lID09ICdTaWxrJykge1xuICAgICAgaWYgKCEvXFxiTW9iaS9pLnRlc3QodWEpKSB7XG4gICAgICAgIG9zID0gJ0FuZHJvaWQnO1xuICAgICAgICBkZXNjcmlwdGlvbi51bnNoaWZ0KCdkZXNrdG9wIG1vZGUnKTtcbiAgICAgIH1cbiAgICAgIGlmICgvQWNjZWxlcmF0ZWQgKj0gKnRydWUvaS50ZXN0KHVhKSkge1xuICAgICAgICBkZXNjcmlwdGlvbi51bnNoaWZ0KCdhY2NlbGVyYXRlZCcpO1xuICAgICAgfVxuICAgIH1cbiAgICAvLyBEZXRlY3QgUGFsZU1vb24gaWRlbnRpZnlpbmcgYXMgRmlyZWZveC5cbiAgICBlbHNlIGlmIChuYW1lID09ICdQYWxlTW9vbicgJiYgKGRhdGEgPSAvXFxiRmlyZWZveFxcLyhbXFxkLl0rKVxcYi8uZXhlYyh1YSkpKSB7XG4gICAgICBkZXNjcmlwdGlvbi5wdXNoKCdpZGVudGlmeWluZyBhcyBGaXJlZm94ICcgKyBkYXRhWzFdKTtcbiAgICB9XG4gICAgLy8gRGV0ZWN0IEZpcmVmb3ggT1MgYW5kIHByb2R1Y3RzIHJ1bm5pbmcgRmlyZWZveC5cbiAgICBlbHNlIGlmIChuYW1lID09ICdGaXJlZm94JyAmJiAoZGF0YSA9IC9cXGIoTW9iaWxlfFRhYmxldHxUVilcXGIvaS5leGVjKHVhKSkpIHtcbiAgICAgIG9zIHx8IChvcyA9ICdGaXJlZm94IE9TJyk7XG4gICAgICBwcm9kdWN0IHx8IChwcm9kdWN0ID0gZGF0YVsxXSk7XG4gICAgfVxuICAgIC8vIERldGVjdCBmYWxzZSBwb3NpdGl2ZXMgZm9yIEZpcmVmb3gvU2FmYXJpLlxuICAgIGVsc2UgaWYgKCFuYW1lIHx8IChkYXRhID0gIS9cXGJNaW5lZmllbGRcXGIvaS50ZXN0KHVhKSAmJiAvXFxiKD86RmlyZWZveHxTYWZhcmkpXFxiLy5leGVjKG5hbWUpKSkge1xuICAgICAgLy8gRXNjYXBlIHRoZSBgL2AgZm9yIEZpcmVmb3ggMS5cbiAgICAgIGlmIChuYW1lICYmICFwcm9kdWN0ICYmIC9bXFwvLF18XlteKF0rP1xcKS8udGVzdCh1YS5zbGljZSh1YS5pbmRleE9mKGRhdGEgKyAnLycpICsgOCkpKSB7XG4gICAgICAgIC8vIENsZWFyIG5hbWUgb2YgZmFsc2UgcG9zaXRpdmVzLlxuICAgICAgICBuYW1lID0gbnVsbDtcbiAgICAgIH1cbiAgICAgIC8vIFJlYXNzaWduIGEgZ2VuZXJpYyBuYW1lLlxuICAgICAgaWYgKChkYXRhID0gcHJvZHVjdCB8fCBtYW51ZmFjdHVyZXIgfHwgb3MpICYmXG4gICAgICAgICAgKHByb2R1Y3QgfHwgbWFudWZhY3R1cmVyIHx8IC9cXGIoPzpBbmRyb2lkfFN5bWJpYW4gT1N8VGFibGV0IE9TfHdlYk9TKVxcYi8udGVzdChvcykpKSB7XG4gICAgICAgIG5hbWUgPSAvW2Etel0rKD86IEhhdCk/L2kuZXhlYygvXFxiQW5kcm9pZFxcYi8udGVzdChvcykgPyBvcyA6IGRhdGEpICsgJyBCcm93c2VyJztcbiAgICAgIH1cbiAgICB9XG4gICAgLy8gQWRkIENocm9tZSB2ZXJzaW9uIHRvIGRlc2NyaXB0aW9uIGZvciBFbGVjdHJvbi5cbiAgICBlbHNlIGlmIChuYW1lID09ICdFbGVjdHJvbicgJiYgKGRhdGEgPSAoL1xcYkNocm9tZVxcLyhbXFxkLl0rKVxcYi8uZXhlYyh1YSkgfHwgMClbMV0pKSB7XG4gICAgICBkZXNjcmlwdGlvbi5wdXNoKCdDaHJvbWl1bSAnICsgZGF0YSk7XG4gICAgfVxuICAgIC8vIERldGVjdCBub24tT3BlcmEgKFByZXN0by1iYXNlZCkgdmVyc2lvbnMgKG9yZGVyIGlzIGltcG9ydGFudCkuXG4gICAgaWYgKCF2ZXJzaW9uKSB7XG4gICAgICB2ZXJzaW9uID0gZ2V0VmVyc2lvbihbXG4gICAgICAgICcoPzpDbG91ZDl8Q3JpT1N8Q3JNb3xFZGdlfEZ4aU9TfElFTW9iaWxlfElyb258T3BlcmEgP01pbml8T1BpT1N8T1BSfFJhdmVufFNhbXN1bmdCcm93c2VyfFNpbGsoPyEvW1xcXFxkLl0rJCkpJyxcbiAgICAgICAgJ1ZlcnNpb24nLFxuICAgICAgICBxdWFsaWZ5KG5hbWUpLFxuICAgICAgICAnKD86RmlyZWZveHxNaW5lZmllbGR8TmV0RnJvbnQpJ1xuICAgICAgXSk7XG4gICAgfVxuICAgIC8vIERldGVjdCBzdHViYm9ybiBsYXlvdXQgZW5naW5lcy5cbiAgICBpZiAoKGRhdGEgPVxuICAgICAgICAgIGxheW91dCA9PSAnaUNhYicgJiYgcGFyc2VGbG9hdCh2ZXJzaW9uKSA+IDMgJiYgJ1dlYktpdCcgfHxcbiAgICAgICAgICAvXFxiT3BlcmFcXGIvLnRlc3QobmFtZSkgJiYgKC9cXGJPUFJcXGIvLnRlc3QodWEpID8gJ0JsaW5rJyA6ICdQcmVzdG8nKSB8fFxuICAgICAgICAgIC9cXGIoPzpNaWRvcml8Tm9va3xTYWZhcmkpXFxiL2kudGVzdCh1YSkgJiYgIS9eKD86VHJpZGVudHxFZGdlSFRNTCkkLy50ZXN0KGxheW91dCkgJiYgJ1dlYktpdCcgfHxcbiAgICAgICAgICAhbGF5b3V0ICYmIC9cXGJNU0lFXFxiL2kudGVzdCh1YSkgJiYgKG9zID09ICdNYWMgT1MnID8gJ1Rhc21hbicgOiAnVHJpZGVudCcpIHx8XG4gICAgICAgICAgbGF5b3V0ID09ICdXZWJLaXQnICYmIC9cXGJQbGF5U3RhdGlvblxcYig/ISBWaXRhXFxiKS9pLnRlc3QobmFtZSkgJiYgJ05ldEZyb250J1xuICAgICAgICApKSB7XG4gICAgICBsYXlvdXQgPSBbZGF0YV07XG4gICAgfVxuICAgIC8vIERldGVjdCBXaW5kb3dzIFBob25lIDcgZGVza3RvcCBtb2RlLlxuICAgIGlmIChuYW1lID09ICdJRScgJiYgKGRhdGEgPSAoLzsgKig/OlhCTFdQfFp1bmVXUCkoXFxkKykvaS5leGVjKHVhKSB8fCAwKVsxXSkpIHtcbiAgICAgIG5hbWUgKz0gJyBNb2JpbGUnO1xuICAgICAgb3MgPSAnV2luZG93cyBQaG9uZSAnICsgKC9cXCskLy50ZXN0KGRhdGEpID8gZGF0YSA6IGRhdGEgKyAnLngnKTtcbiAgICAgIGRlc2NyaXB0aW9uLnVuc2hpZnQoJ2Rlc2t0b3AgbW9kZScpO1xuICAgIH1cbiAgICAvLyBEZXRlY3QgV2luZG93cyBQaG9uZSA4LnggZGVza3RvcCBtb2RlLlxuICAgIGVsc2UgaWYgKC9cXGJXUERlc2t0b3BcXGIvaS50ZXN0KHVhKSkge1xuICAgICAgbmFtZSA9ICdJRSBNb2JpbGUnO1xuICAgICAgb3MgPSAnV2luZG93cyBQaG9uZSA4LngnO1xuICAgICAgZGVzY3JpcHRpb24udW5zaGlmdCgnZGVza3RvcCBtb2RlJyk7XG4gICAgICB2ZXJzaW9uIHx8ICh2ZXJzaW9uID0gKC9cXGJydjooW1xcZC5dKykvLmV4ZWModWEpIHx8IDApWzFdKTtcbiAgICB9XG4gICAgLy8gRGV0ZWN0IElFIDExIGlkZW50aWZ5aW5nIGFzIG90aGVyIGJyb3dzZXJzLlxuICAgIGVsc2UgaWYgKG5hbWUgIT0gJ0lFJyAmJiBsYXlvdXQgPT0gJ1RyaWRlbnQnICYmIChkYXRhID0gL1xcYnJ2OihbXFxkLl0rKS8uZXhlYyh1YSkpKSB7XG4gICAgICBpZiAobmFtZSkge1xuICAgICAgICBkZXNjcmlwdGlvbi5wdXNoKCdpZGVudGlmeWluZyBhcyAnICsgbmFtZSArICh2ZXJzaW9uID8gJyAnICsgdmVyc2lvbiA6ICcnKSk7XG4gICAgICB9XG4gICAgICBuYW1lID0gJ0lFJztcbiAgICAgIHZlcnNpb24gPSBkYXRhWzFdO1xuICAgIH1cbiAgICAvLyBMZXZlcmFnZSBlbnZpcm9ubWVudCBmZWF0dXJlcy5cbiAgICBpZiAodXNlRmVhdHVyZXMpIHtcbiAgICAgIC8vIERldGVjdCBzZXJ2ZXItc2lkZSBlbnZpcm9ubWVudHMuXG4gICAgICAvLyBSaGlubyBoYXMgYSBnbG9iYWwgZnVuY3Rpb24gd2hpbGUgb3RoZXJzIGhhdmUgYSBnbG9iYWwgb2JqZWN0LlxuICAgICAgaWYgKGlzSG9zdFR5cGUoY29udGV4dCwgJ2dsb2JhbCcpKSB7XG4gICAgICAgIGlmIChqYXZhKSB7XG4gICAgICAgICAgZGF0YSA9IGphdmEubGFuZy5TeXN0ZW07XG4gICAgICAgICAgYXJjaCA9IGRhdGEuZ2V0UHJvcGVydHkoJ29zLmFyY2gnKTtcbiAgICAgICAgICBvcyA9IG9zIHx8IGRhdGEuZ2V0UHJvcGVydHkoJ29zLm5hbWUnKSArICcgJyArIGRhdGEuZ2V0UHJvcGVydHkoJ29zLnZlcnNpb24nKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAocmhpbm8pIHtcbiAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgdmVyc2lvbiA9IGNvbnRleHQucmVxdWlyZSgncmluZ28vZW5naW5lJykudmVyc2lvbi5qb2luKCcuJyk7XG4gICAgICAgICAgICBuYW1lID0gJ1JpbmdvSlMnO1xuICAgICAgICAgIH0gY2F0Y2goZSkge1xuICAgICAgICAgICAgaWYgKChkYXRhID0gY29udGV4dC5zeXN0ZW0pICYmIGRhdGEuZ2xvYmFsLnN5c3RlbSA9PSBjb250ZXh0LnN5c3RlbSkge1xuICAgICAgICAgICAgICBuYW1lID0gJ05hcndoYWwnO1xuICAgICAgICAgICAgICBvcyB8fCAob3MgPSBkYXRhWzBdLm9zIHx8IG51bGwpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoIW5hbWUpIHtcbiAgICAgICAgICAgIG5hbWUgPSAnUmhpbm8nO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmIChcbiAgICAgICAgICB0eXBlb2YgY29udGV4dC5wcm9jZXNzID09ICdvYmplY3QnICYmICFjb250ZXh0LnByb2Nlc3MuYnJvd3NlciAmJlxuICAgICAgICAgIChkYXRhID0gY29udGV4dC5wcm9jZXNzKVxuICAgICAgICApIHtcbiAgICAgICAgICBpZiAodHlwZW9mIGRhdGEudmVyc2lvbnMgPT0gJ29iamVjdCcpIHtcbiAgICAgICAgICAgIGlmICh0eXBlb2YgZGF0YS52ZXJzaW9ucy5lbGVjdHJvbiA9PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgICBkZXNjcmlwdGlvbi5wdXNoKCdOb2RlICcgKyBkYXRhLnZlcnNpb25zLm5vZGUpO1xuICAgICAgICAgICAgICBuYW1lID0gJ0VsZWN0cm9uJztcbiAgICAgICAgICAgICAgdmVyc2lvbiA9IGRhdGEudmVyc2lvbnMuZWxlY3Ryb247XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHR5cGVvZiBkYXRhLnZlcnNpb25zLm53ID09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAgIGRlc2NyaXB0aW9uLnB1c2goJ0Nocm9taXVtICcgKyB2ZXJzaW9uLCAnTm9kZSAnICsgZGF0YS52ZXJzaW9ucy5ub2RlKTtcbiAgICAgICAgICAgICAgbmFtZSA9ICdOVy5qcyc7XG4gICAgICAgICAgICAgIHZlcnNpb24gPSBkYXRhLnZlcnNpb25zLm53O1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoIW5hbWUpIHtcbiAgICAgICAgICAgIG5hbWUgPSAnTm9kZS5qcyc7XG4gICAgICAgICAgICBhcmNoID0gZGF0YS5hcmNoO1xuICAgICAgICAgICAgb3MgPSBkYXRhLnBsYXRmb3JtO1xuICAgICAgICAgICAgdmVyc2lvbiA9IC9bXFxkLl0rLy5leGVjKGRhdGEudmVyc2lvbik7XG4gICAgICAgICAgICB2ZXJzaW9uID0gdmVyc2lvbiA/IHZlcnNpb25bMF0gOiBudWxsO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgLy8gRGV0ZWN0IEFkb2JlIEFJUi5cbiAgICAgIGVsc2UgaWYgKGdldENsYXNzT2YoKGRhdGEgPSBjb250ZXh0LnJ1bnRpbWUpKSA9PSBhaXJSdW50aW1lQ2xhc3MpIHtcbiAgICAgICAgbmFtZSA9ICdBZG9iZSBBSVInO1xuICAgICAgICBvcyA9IGRhdGEuZmxhc2guc3lzdGVtLkNhcGFiaWxpdGllcy5vcztcbiAgICAgIH1cbiAgICAgIC8vIERldGVjdCBQaGFudG9tSlMuXG4gICAgICBlbHNlIGlmIChnZXRDbGFzc09mKChkYXRhID0gY29udGV4dC5waGFudG9tKSkgPT0gcGhhbnRvbUNsYXNzKSB7XG4gICAgICAgIG5hbWUgPSAnUGhhbnRvbUpTJztcbiAgICAgICAgdmVyc2lvbiA9IChkYXRhID0gZGF0YS52ZXJzaW9uIHx8IG51bGwpICYmIChkYXRhLm1ham9yICsgJy4nICsgZGF0YS5taW5vciArICcuJyArIGRhdGEucGF0Y2gpO1xuICAgICAgfVxuICAgICAgLy8gRGV0ZWN0IElFIGNvbXBhdGliaWxpdHkgbW9kZXMuXG4gICAgICBlbHNlIGlmICh0eXBlb2YgZG9jLmRvY3VtZW50TW9kZSA9PSAnbnVtYmVyJyAmJiAoZGF0YSA9IC9cXGJUcmlkZW50XFwvKFxcZCspL2kuZXhlYyh1YSkpKSB7XG4gICAgICAgIC8vIFdlJ3JlIGluIGNvbXBhdGliaWxpdHkgbW9kZSB3aGVuIHRoZSBUcmlkZW50IHZlcnNpb24gKyA0IGRvZXNuJ3RcbiAgICAgICAgLy8gZXF1YWwgdGhlIGRvY3VtZW50IG1vZGUuXG4gICAgICAgIHZlcnNpb24gPSBbdmVyc2lvbiwgZG9jLmRvY3VtZW50TW9kZV07XG4gICAgICAgIGlmICgoZGF0YSA9ICtkYXRhWzFdICsgNCkgIT0gdmVyc2lvblsxXSkge1xuICAgICAgICAgIGRlc2NyaXB0aW9uLnB1c2goJ0lFICcgKyB2ZXJzaW9uWzFdICsgJyBtb2RlJyk7XG4gICAgICAgICAgbGF5b3V0ICYmIChsYXlvdXRbMV0gPSAnJyk7XG4gICAgICAgICAgdmVyc2lvblsxXSA9IGRhdGE7XG4gICAgICAgIH1cbiAgICAgICAgdmVyc2lvbiA9IG5hbWUgPT0gJ0lFJyA/IFN0cmluZyh2ZXJzaW9uWzFdLnRvRml4ZWQoMSkpIDogdmVyc2lvblswXTtcbiAgICAgIH1cbiAgICAgIC8vIERldGVjdCBJRSAxMSBtYXNraW5nIGFzIG90aGVyIGJyb3dzZXJzLlxuICAgICAgZWxzZSBpZiAodHlwZW9mIGRvYy5kb2N1bWVudE1vZGUgPT0gJ251bWJlcicgJiYgL14oPzpDaHJvbWV8RmlyZWZveClcXGIvLnRlc3QobmFtZSkpIHtcbiAgICAgICAgZGVzY3JpcHRpb24ucHVzaCgnbWFza2luZyBhcyAnICsgbmFtZSArICcgJyArIHZlcnNpb24pO1xuICAgICAgICBuYW1lID0gJ0lFJztcbiAgICAgICAgdmVyc2lvbiA9ICcxMS4wJztcbiAgICAgICAgbGF5b3V0ID0gWydUcmlkZW50J107XG4gICAgICAgIG9zID0gJ1dpbmRvd3MnO1xuICAgICAgfVxuICAgICAgb3MgPSBvcyAmJiBmb3JtYXQob3MpO1xuICAgIH1cbiAgICAvLyBEZXRlY3QgcHJlcmVsZWFzZSBwaGFzZXMuXG4gICAgaWYgKHZlcnNpb24gJiYgKGRhdGEgPVxuICAgICAgICAgIC8oPzpbYWJdfGRwfHByZXxbYWJdXFxkK3ByZSkoPzpcXGQrXFwrPyk/JC9pLmV4ZWModmVyc2lvbikgfHxcbiAgICAgICAgICAvKD86YWxwaGF8YmV0YSkoPzogP1xcZCk/L2kuZXhlYyh1YSArICc7JyArICh1c2VGZWF0dXJlcyAmJiBuYXYuYXBwTWlub3JWZXJzaW9uKSkgfHxcbiAgICAgICAgICAvXFxiTWluZWZpZWxkXFxiL2kudGVzdCh1YSkgJiYgJ2EnXG4gICAgICAgICkpIHtcbiAgICAgIHByZXJlbGVhc2UgPSAvYi9pLnRlc3QoZGF0YSkgPyAnYmV0YScgOiAnYWxwaGEnO1xuICAgICAgdmVyc2lvbiA9IHZlcnNpb24ucmVwbGFjZShSZWdFeHAoZGF0YSArICdcXFxcKz8kJyksICcnKSArXG4gICAgICAgIChwcmVyZWxlYXNlID09ICdiZXRhJyA/IGJldGEgOiBhbHBoYSkgKyAoL1xcZCtcXCs/Ly5leGVjKGRhdGEpIHx8ICcnKTtcbiAgICB9XG4gICAgLy8gRGV0ZWN0IEZpcmVmb3ggTW9iaWxlLlxuICAgIGlmIChuYW1lID09ICdGZW5uZWMnIHx8IG5hbWUgPT0gJ0ZpcmVmb3gnICYmIC9cXGIoPzpBbmRyb2lkfEZpcmVmb3ggT1MpXFxiLy50ZXN0KG9zKSkge1xuICAgICAgbmFtZSA9ICdGaXJlZm94IE1vYmlsZSc7XG4gICAgfVxuICAgIC8vIE9ic2N1cmUgTWF4dGhvbidzIHVucmVsaWFibGUgdmVyc2lvbi5cbiAgICBlbHNlIGlmIChuYW1lID09ICdNYXh0aG9uJyAmJiB2ZXJzaW9uKSB7XG4gICAgICB2ZXJzaW9uID0gdmVyc2lvbi5yZXBsYWNlKC9cXC5bXFxkLl0rLywgJy54Jyk7XG4gICAgfVxuICAgIC8vIERldGVjdCBYYm94IDM2MCBhbmQgWGJveCBPbmUuXG4gICAgZWxzZSBpZiAoL1xcYlhib3hcXGIvaS50ZXN0KHByb2R1Y3QpKSB7XG4gICAgICBpZiAocHJvZHVjdCA9PSAnWGJveCAzNjAnKSB7XG4gICAgICAgIG9zID0gbnVsbDtcbiAgICAgIH1cbiAgICAgIGlmIChwcm9kdWN0ID09ICdYYm94IDM2MCcgJiYgL1xcYklFTW9iaWxlXFxiLy50ZXN0KHVhKSkge1xuICAgICAgICBkZXNjcmlwdGlvbi51bnNoaWZ0KCdtb2JpbGUgbW9kZScpO1xuICAgICAgfVxuICAgIH1cbiAgICAvLyBBZGQgbW9iaWxlIHBvc3RmaXguXG4gICAgZWxzZSBpZiAoKC9eKD86Q2hyb21lfElFfE9wZXJhKSQvLnRlc3QobmFtZSkgfHwgbmFtZSAmJiAhcHJvZHVjdCAmJiAhL0Jyb3dzZXJ8TW9iaS8udGVzdChuYW1lKSkgJiZcbiAgICAgICAgKG9zID09ICdXaW5kb3dzIENFJyB8fCAvTW9iaS9pLnRlc3QodWEpKSkge1xuICAgICAgbmFtZSArPSAnIE1vYmlsZSc7XG4gICAgfVxuICAgIC8vIERldGVjdCBJRSBwbGF0Zm9ybSBwcmV2aWV3LlxuICAgIGVsc2UgaWYgKG5hbWUgPT0gJ0lFJyAmJiB1c2VGZWF0dXJlcykge1xuICAgICAgdHJ5IHtcbiAgICAgICAgaWYgKGNvbnRleHQuZXh0ZXJuYWwgPT09IG51bGwpIHtcbiAgICAgICAgICBkZXNjcmlwdGlvbi51bnNoaWZ0KCdwbGF0Zm9ybSBwcmV2aWV3Jyk7XG4gICAgICAgIH1cbiAgICAgIH0gY2F0Y2goZSkge1xuICAgICAgICBkZXNjcmlwdGlvbi51bnNoaWZ0KCdlbWJlZGRlZCcpO1xuICAgICAgfVxuICAgIH1cbiAgICAvLyBEZXRlY3QgQmxhY2tCZXJyeSBPUyB2ZXJzaW9uLlxuICAgIC8vIGh0dHA6Ly9kb2NzLmJsYWNrYmVycnkuY29tL2VuL2RldmVsb3BlcnMvZGVsaXZlcmFibGVzLzE4MTY5L0hUVFBfaGVhZGVyc19zZW50X2J5X0JCX0Jyb3dzZXJfMTIzNDkxMV8xMS5qc3BcbiAgICBlbHNlIGlmICgoL1xcYkJsYWNrQmVycnlcXGIvLnRlc3QocHJvZHVjdCkgfHwgL1xcYkJCMTBcXGIvLnRlc3QodWEpKSAmJiAoZGF0YSA9XG4gICAgICAgICAgKFJlZ0V4cChwcm9kdWN0LnJlcGxhY2UoLyArL2csICcgKicpICsgJy8oWy5cXFxcZF0rKScsICdpJykuZXhlYyh1YSkgfHwgMClbMV0gfHxcbiAgICAgICAgICB2ZXJzaW9uXG4gICAgICAgICkpIHtcbiAgICAgIGRhdGEgPSBbZGF0YSwgL0JCMTAvLnRlc3QodWEpXTtcbiAgICAgIG9zID0gKGRhdGFbMV0gPyAocHJvZHVjdCA9IG51bGwsIG1hbnVmYWN0dXJlciA9ICdCbGFja0JlcnJ5JykgOiAnRGV2aWNlIFNvZnR3YXJlJykgKyAnICcgKyBkYXRhWzBdO1xuICAgICAgdmVyc2lvbiA9IG51bGw7XG4gICAgfVxuICAgIC8vIERldGVjdCBPcGVyYSBpZGVudGlmeWluZy9tYXNraW5nIGl0c2VsZiBhcyBhbm90aGVyIGJyb3dzZXIuXG4gICAgLy8gaHR0cDovL3d3dy5vcGVyYS5jb20vc3VwcG9ydC9rYi92aWV3Lzg0My9cbiAgICBlbHNlIGlmICh0aGlzICE9IGZvck93biAmJiBwcm9kdWN0ICE9ICdXaWknICYmIChcbiAgICAgICAgICAodXNlRmVhdHVyZXMgJiYgb3BlcmEpIHx8XG4gICAgICAgICAgKC9PcGVyYS8udGVzdChuYW1lKSAmJiAvXFxiKD86TVNJRXxGaXJlZm94KVxcYi9pLnRlc3QodWEpKSB8fFxuICAgICAgICAgIChuYW1lID09ICdGaXJlZm94JyAmJiAvXFxiT1MgWCAoPzpcXGQrXFwuKXsyLH0vLnRlc3Qob3MpKSB8fFxuICAgICAgICAgIChuYW1lID09ICdJRScgJiYgKFxuICAgICAgICAgICAgKG9zICYmICEvXldpbi8udGVzdChvcykgJiYgdmVyc2lvbiA+IDUuNSkgfHxcbiAgICAgICAgICAgIC9cXGJXaW5kb3dzIFhQXFxiLy50ZXN0KG9zKSAmJiB2ZXJzaW9uID4gOCB8fFxuICAgICAgICAgICAgdmVyc2lvbiA9PSA4ICYmICEvXFxiVHJpZGVudFxcYi8udGVzdCh1YSlcbiAgICAgICAgICApKVxuICAgICAgICApICYmICFyZU9wZXJhLnRlc3QoKGRhdGEgPSBwYXJzZS5jYWxsKGZvck93biwgdWEucmVwbGFjZShyZU9wZXJhLCAnJykgKyAnOycpKSkgJiYgZGF0YS5uYW1lKSB7XG4gICAgICAvLyBXaGVuIFwiaWRlbnRpZnlpbmdcIiwgdGhlIFVBIGNvbnRhaW5zIGJvdGggT3BlcmEgYW5kIHRoZSBvdGhlciBicm93c2VyJ3MgbmFtZS5cbiAgICAgIGRhdGEgPSAnaW5nIGFzICcgKyBkYXRhLm5hbWUgKyAoKGRhdGEgPSBkYXRhLnZlcnNpb24pID8gJyAnICsgZGF0YSA6ICcnKTtcbiAgICAgIGlmIChyZU9wZXJhLnRlc3QobmFtZSkpIHtcbiAgICAgICAgaWYgKC9cXGJJRVxcYi8udGVzdChkYXRhKSAmJiBvcyA9PSAnTWFjIE9TJykge1xuICAgICAgICAgIG9zID0gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICBkYXRhID0gJ2lkZW50aWZ5JyArIGRhdGE7XG4gICAgICB9XG4gICAgICAvLyBXaGVuIFwibWFza2luZ1wiLCB0aGUgVUEgY29udGFpbnMgb25seSB0aGUgb3RoZXIgYnJvd3NlcidzIG5hbWUuXG4gICAgICBlbHNlIHtcbiAgICAgICAgZGF0YSA9ICdtYXNrJyArIGRhdGE7XG4gICAgICAgIGlmIChvcGVyYUNsYXNzKSB7XG4gICAgICAgICAgbmFtZSA9IGZvcm1hdChvcGVyYUNsYXNzLnJlcGxhY2UoLyhbYS16XSkoW0EtWl0pL2csICckMSAkMicpKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBuYW1lID0gJ09wZXJhJztcbiAgICAgICAgfVxuICAgICAgICBpZiAoL1xcYklFXFxiLy50ZXN0KGRhdGEpKSB7XG4gICAgICAgICAgb3MgPSBudWxsO1xuICAgICAgICB9XG4gICAgICAgIGlmICghdXNlRmVhdHVyZXMpIHtcbiAgICAgICAgICB2ZXJzaW9uID0gbnVsbDtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgbGF5b3V0ID0gWydQcmVzdG8nXTtcbiAgICAgIGRlc2NyaXB0aW9uLnB1c2goZGF0YSk7XG4gICAgfVxuICAgIC8vIERldGVjdCBXZWJLaXQgTmlnaHRseSBhbmQgYXBwcm94aW1hdGUgQ2hyb21lL1NhZmFyaSB2ZXJzaW9ucy5cbiAgICBpZiAoKGRhdGEgPSAoL1xcYkFwcGxlV2ViS2l0XFwvKFtcXGQuXStcXCs/KS9pLmV4ZWModWEpIHx8IDApWzFdKSkge1xuICAgICAgLy8gQ29ycmVjdCBidWlsZCBudW1iZXIgZm9yIG51bWVyaWMgY29tcGFyaXNvbi5cbiAgICAgIC8vIChlLmcuIFwiNTMyLjVcIiBiZWNvbWVzIFwiNTMyLjA1XCIpXG4gICAgICBkYXRhID0gW3BhcnNlRmxvYXQoZGF0YS5yZXBsYWNlKC9cXC4oXFxkKSQvLCAnLjAkMScpKSwgZGF0YV07XG4gICAgICAvLyBOaWdodGx5IGJ1aWxkcyBhcmUgcG9zdGZpeGVkIHdpdGggYSBcIitcIi5cbiAgICAgIGlmIChuYW1lID09ICdTYWZhcmknICYmIGRhdGFbMV0uc2xpY2UoLTEpID09ICcrJykge1xuICAgICAgICBuYW1lID0gJ1dlYktpdCBOaWdodGx5JztcbiAgICAgICAgcHJlcmVsZWFzZSA9ICdhbHBoYSc7XG4gICAgICAgIHZlcnNpb24gPSBkYXRhWzFdLnNsaWNlKDAsIC0xKTtcbiAgICAgIH1cbiAgICAgIC8vIENsZWFyIGluY29ycmVjdCBicm93c2VyIHZlcnNpb25zLlxuICAgICAgZWxzZSBpZiAodmVyc2lvbiA9PSBkYXRhWzFdIHx8XG4gICAgICAgICAgdmVyc2lvbiA9PSAoZGF0YVsyXSA9ICgvXFxiU2FmYXJpXFwvKFtcXGQuXStcXCs/KS9pLmV4ZWModWEpIHx8IDApWzFdKSkge1xuICAgICAgICB2ZXJzaW9uID0gbnVsbDtcbiAgICAgIH1cbiAgICAgIC8vIFVzZSB0aGUgZnVsbCBDaHJvbWUgdmVyc2lvbiB3aGVuIGF2YWlsYWJsZS5cbiAgICAgIGRhdGFbMV0gPSAoL1xcYkNocm9tZVxcLyhbXFxkLl0rKS9pLmV4ZWModWEpIHx8IDApWzFdO1xuICAgICAgLy8gRGV0ZWN0IEJsaW5rIGxheW91dCBlbmdpbmUuXG4gICAgICBpZiAoZGF0YVswXSA9PSA1MzcuMzYgJiYgZGF0YVsyXSA9PSA1MzcuMzYgJiYgcGFyc2VGbG9hdChkYXRhWzFdKSA+PSAyOCAmJiBsYXlvdXQgPT0gJ1dlYktpdCcpIHtcbiAgICAgICAgbGF5b3V0ID0gWydCbGluayddO1xuICAgICAgfVxuICAgICAgLy8gRGV0ZWN0IEphdmFTY3JpcHRDb3JlLlxuICAgICAgLy8gaHR0cDovL3N0YWNrb3ZlcmZsb3cuY29tL3F1ZXN0aW9ucy82NzY4NDc0L2hvdy1jYW4taS1kZXRlY3Qtd2hpY2gtamF2YXNjcmlwdC1lbmdpbmUtdjgtb3ItanNjLWlzLXVzZWQtYXQtcnVudGltZS1pbi1hbmRyb2lcbiAgICAgIGlmICghdXNlRmVhdHVyZXMgfHwgKCFsaWtlQ2hyb21lICYmICFkYXRhWzFdKSkge1xuICAgICAgICBsYXlvdXQgJiYgKGxheW91dFsxXSA9ICdsaWtlIFNhZmFyaScpO1xuICAgICAgICBkYXRhID0gKGRhdGEgPSBkYXRhWzBdLCBkYXRhIDwgNDAwID8gMSA6IGRhdGEgPCA1MDAgPyAyIDogZGF0YSA8IDUyNiA/IDMgOiBkYXRhIDwgNTMzID8gNCA6IGRhdGEgPCA1MzQgPyAnNCsnIDogZGF0YSA8IDUzNSA/IDUgOiBkYXRhIDwgNTM3ID8gNiA6IGRhdGEgPCA1MzggPyA3IDogZGF0YSA8IDYwMSA/IDggOiAnOCcpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbGF5b3V0ICYmIChsYXlvdXRbMV0gPSAnbGlrZSBDaHJvbWUnKTtcbiAgICAgICAgZGF0YSA9IGRhdGFbMV0gfHwgKGRhdGEgPSBkYXRhWzBdLCBkYXRhIDwgNTMwID8gMSA6IGRhdGEgPCA1MzIgPyAyIDogZGF0YSA8IDUzMi4wNSA/IDMgOiBkYXRhIDwgNTMzID8gNCA6IGRhdGEgPCA1MzQuMDMgPyA1IDogZGF0YSA8IDUzNC4wNyA/IDYgOiBkYXRhIDwgNTM0LjEwID8gNyA6IGRhdGEgPCA1MzQuMTMgPyA4IDogZGF0YSA8IDUzNC4xNiA/IDkgOiBkYXRhIDwgNTM0LjI0ID8gMTAgOiBkYXRhIDwgNTM0LjMwID8gMTEgOiBkYXRhIDwgNTM1LjAxID8gMTIgOiBkYXRhIDwgNTM1LjAyID8gJzEzKycgOiBkYXRhIDwgNTM1LjA3ID8gMTUgOiBkYXRhIDwgNTM1LjExID8gMTYgOiBkYXRhIDwgNTM1LjE5ID8gMTcgOiBkYXRhIDwgNTM2LjA1ID8gMTggOiBkYXRhIDwgNTM2LjEwID8gMTkgOiBkYXRhIDwgNTM3LjAxID8gMjAgOiBkYXRhIDwgNTM3LjExID8gJzIxKycgOiBkYXRhIDwgNTM3LjEzID8gMjMgOiBkYXRhIDwgNTM3LjE4ID8gMjQgOiBkYXRhIDwgNTM3LjI0ID8gMjUgOiBkYXRhIDwgNTM3LjM2ID8gMjYgOiBsYXlvdXQgIT0gJ0JsaW5rJyA/ICcyNycgOiAnMjgnKTtcbiAgICAgIH1cbiAgICAgIC8vIEFkZCB0aGUgcG9zdGZpeCBvZiBcIi54XCIgb3IgXCIrXCIgZm9yIGFwcHJveGltYXRlIHZlcnNpb25zLlxuICAgICAgbGF5b3V0ICYmIChsYXlvdXRbMV0gKz0gJyAnICsgKGRhdGEgKz0gdHlwZW9mIGRhdGEgPT0gJ251bWJlcicgPyAnLngnIDogL1suK10vLnRlc3QoZGF0YSkgPyAnJyA6ICcrJykpO1xuICAgICAgLy8gT2JzY3VyZSB2ZXJzaW9uIGZvciBzb21lIFNhZmFyaSAxLTIgcmVsZWFzZXMuXG4gICAgICBpZiAobmFtZSA9PSAnU2FmYXJpJyAmJiAoIXZlcnNpb24gfHwgcGFyc2VJbnQodmVyc2lvbikgPiA0NSkpIHtcbiAgICAgICAgdmVyc2lvbiA9IGRhdGE7XG4gICAgICB9XG4gICAgfVxuICAgIC8vIERldGVjdCBPcGVyYSBkZXNrdG9wIG1vZGVzLlxuICAgIGlmIChuYW1lID09ICdPcGVyYScgJiYgIChkYXRhID0gL1xcYnpib3Z8enZhdiQvLmV4ZWMob3MpKSkge1xuICAgICAgbmFtZSArPSAnICc7XG4gICAgICBkZXNjcmlwdGlvbi51bnNoaWZ0KCdkZXNrdG9wIG1vZGUnKTtcbiAgICAgIGlmIChkYXRhID09ICd6dmF2Jykge1xuICAgICAgICBuYW1lICs9ICdNaW5pJztcbiAgICAgICAgdmVyc2lvbiA9IG51bGw7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBuYW1lICs9ICdNb2JpbGUnO1xuICAgICAgfVxuICAgICAgb3MgPSBvcy5yZXBsYWNlKFJlZ0V4cCgnIConICsgZGF0YSArICckJyksICcnKTtcbiAgICB9XG4gICAgLy8gRGV0ZWN0IENocm9tZSBkZXNrdG9wIG1vZGUuXG4gICAgZWxzZSBpZiAobmFtZSA9PSAnU2FmYXJpJyAmJiAvXFxiQ2hyb21lXFxiLy5leGVjKGxheW91dCAmJiBsYXlvdXRbMV0pKSB7XG4gICAgICBkZXNjcmlwdGlvbi51bnNoaWZ0KCdkZXNrdG9wIG1vZGUnKTtcbiAgICAgIG5hbWUgPSAnQ2hyb21lIE1vYmlsZSc7XG4gICAgICB2ZXJzaW9uID0gbnVsbDtcblxuICAgICAgaWYgKC9cXGJPUyBYXFxiLy50ZXN0KG9zKSkge1xuICAgICAgICBtYW51ZmFjdHVyZXIgPSAnQXBwbGUnO1xuICAgICAgICBvcyA9ICdpT1MgNC4zKyc7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBvcyA9IG51bGw7XG4gICAgICB9XG4gICAgfVxuICAgIC8vIFN0cmlwIGluY29ycmVjdCBPUyB2ZXJzaW9ucy5cbiAgICBpZiAodmVyc2lvbiAmJiB2ZXJzaW9uLmluZGV4T2YoKGRhdGEgPSAvW1xcZC5dKyQvLmV4ZWMob3MpKSkgPT0gMCAmJlxuICAgICAgICB1YS5pbmRleE9mKCcvJyArIGRhdGEgKyAnLScpID4gLTEpIHtcbiAgICAgIG9zID0gdHJpbShvcy5yZXBsYWNlKGRhdGEsICcnKSk7XG4gICAgfVxuICAgIC8vIEFkZCBsYXlvdXQgZW5naW5lLlxuICAgIGlmIChsYXlvdXQgJiYgIS9cXGIoPzpBdmFudHxOb29rKVxcYi8udGVzdChuYW1lKSAmJiAoXG4gICAgICAgIC9Ccm93c2VyfEx1bmFzY2FwZXxNYXh0aG9uLy50ZXN0KG5hbWUpIHx8XG4gICAgICAgIG5hbWUgIT0gJ1NhZmFyaScgJiYgL15pT1MvLnRlc3Qob3MpICYmIC9cXGJTYWZhcmlcXGIvLnRlc3QobGF5b3V0WzFdKSB8fFxuICAgICAgICAvXig/OkFkb2JlfEFyb3JhfEJyZWFjaHxNaWRvcml8T3BlcmF8UGhhbnRvbXxSZWtvbnF8Um9ja3xTYW1zdW5nIEludGVybmV0fFNsZWlwbmlyfFdlYikvLnRlc3QobmFtZSkgJiYgbGF5b3V0WzFdKSkge1xuICAgICAgLy8gRG9uJ3QgYWRkIGxheW91dCBkZXRhaWxzIHRvIGRlc2NyaXB0aW9uIGlmIHRoZXkgYXJlIGZhbHNleS5cbiAgICAgIChkYXRhID0gbGF5b3V0W2xheW91dC5sZW5ndGggLSAxXSkgJiYgZGVzY3JpcHRpb24ucHVzaChkYXRhKTtcbiAgICB9XG4gICAgLy8gQ29tYmluZSBjb250ZXh0dWFsIGluZm9ybWF0aW9uLlxuICAgIGlmIChkZXNjcmlwdGlvbi5sZW5ndGgpIHtcbiAgICAgIGRlc2NyaXB0aW9uID0gWycoJyArIGRlc2NyaXB0aW9uLmpvaW4oJzsgJykgKyAnKSddO1xuICAgIH1cbiAgICAvLyBBcHBlbmQgbWFudWZhY3R1cmVyIHRvIGRlc2NyaXB0aW9uLlxuICAgIGlmIChtYW51ZmFjdHVyZXIgJiYgcHJvZHVjdCAmJiBwcm9kdWN0LmluZGV4T2YobWFudWZhY3R1cmVyKSA8IDApIHtcbiAgICAgIGRlc2NyaXB0aW9uLnB1c2goJ29uICcgKyBtYW51ZmFjdHVyZXIpO1xuICAgIH1cbiAgICAvLyBBcHBlbmQgcHJvZHVjdCB0byBkZXNjcmlwdGlvbi5cbiAgICBpZiAocHJvZHVjdCkge1xuICAgICAgZGVzY3JpcHRpb24ucHVzaCgoL15vbiAvLnRlc3QoZGVzY3JpcHRpb25bZGVzY3JpcHRpb24ubGVuZ3RoIC0gMV0pID8gJycgOiAnb24gJykgKyBwcm9kdWN0KTtcbiAgICB9XG4gICAgLy8gUGFyc2UgdGhlIE9TIGludG8gYW4gb2JqZWN0LlxuICAgIGlmIChvcykge1xuICAgICAgZGF0YSA9IC8gKFtcXGQuK10rKSQvLmV4ZWMob3MpO1xuICAgICAgaXNTcGVjaWFsQ2FzZWRPUyA9IGRhdGEgJiYgb3MuY2hhckF0KG9zLmxlbmd0aCAtIGRhdGFbMF0ubGVuZ3RoIC0gMSkgPT0gJy8nO1xuICAgICAgb3MgPSB7XG4gICAgICAgICdhcmNoaXRlY3R1cmUnOiAzMixcbiAgICAgICAgJ2ZhbWlseSc6IChkYXRhICYmICFpc1NwZWNpYWxDYXNlZE9TKSA/IG9zLnJlcGxhY2UoZGF0YVswXSwgJycpIDogb3MsXG4gICAgICAgICd2ZXJzaW9uJzogZGF0YSA/IGRhdGFbMV0gOiBudWxsLFxuICAgICAgICAndG9TdHJpbmcnOiBmdW5jdGlvbigpIHtcbiAgICAgICAgICB2YXIgdmVyc2lvbiA9IHRoaXMudmVyc2lvbjtcbiAgICAgICAgICByZXR1cm4gdGhpcy5mYW1pbHkgKyAoKHZlcnNpb24gJiYgIWlzU3BlY2lhbENhc2VkT1MpID8gJyAnICsgdmVyc2lvbiA6ICcnKSArICh0aGlzLmFyY2hpdGVjdHVyZSA9PSA2NCA/ICcgNjQtYml0JyA6ICcnKTtcbiAgICAgICAgfVxuICAgICAgfTtcbiAgICB9XG4gICAgLy8gQWRkIGJyb3dzZXIvT1MgYXJjaGl0ZWN0dXJlLlxuICAgIGlmICgoZGF0YSA9IC9cXGIoPzpBTUR8SUF8V2lufFdPV3x4ODZffHgpNjRcXGIvaS5leGVjKGFyY2gpKSAmJiAhL1xcYmk2ODZcXGIvaS50ZXN0KGFyY2gpKSB7XG4gICAgICBpZiAob3MpIHtcbiAgICAgICAgb3MuYXJjaGl0ZWN0dXJlID0gNjQ7XG4gICAgICAgIG9zLmZhbWlseSA9IG9zLmZhbWlseS5yZXBsYWNlKFJlZ0V4cCgnIConICsgZGF0YSksICcnKTtcbiAgICAgIH1cbiAgICAgIGlmIChcbiAgICAgICAgICBuYW1lICYmICgvXFxiV09XNjRcXGIvaS50ZXN0KHVhKSB8fFxuICAgICAgICAgICh1c2VGZWF0dXJlcyAmJiAvXFx3KD86ODZ8MzIpJC8udGVzdChuYXYuY3B1Q2xhc3MgfHwgbmF2LnBsYXRmb3JtKSAmJiAhL1xcYldpbjY0OyB4NjRcXGIvaS50ZXN0KHVhKSkpXG4gICAgICApIHtcbiAgICAgICAgZGVzY3JpcHRpb24udW5zaGlmdCgnMzItYml0Jyk7XG4gICAgICB9XG4gICAgfVxuICAgIC8vIENocm9tZSAzOSBhbmQgYWJvdmUgb24gT1MgWCBpcyBhbHdheXMgNjQtYml0LlxuICAgIGVsc2UgaWYgKFxuICAgICAgICBvcyAmJiAvXk9TIFgvLnRlc3Qob3MuZmFtaWx5KSAmJlxuICAgICAgICBuYW1lID09ICdDaHJvbWUnICYmIHBhcnNlRmxvYXQodmVyc2lvbikgPj0gMzlcbiAgICApIHtcbiAgICAgIG9zLmFyY2hpdGVjdHVyZSA9IDY0O1xuICAgIH1cblxuICAgIHVhIHx8ICh1YSA9IG51bGwpO1xuXG4gICAgLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuXG4gICAgLyoqXG4gICAgICogVGhlIHBsYXRmb3JtIG9iamVjdC5cbiAgICAgKlxuICAgICAqIEBuYW1lIHBsYXRmb3JtXG4gICAgICogQHR5cGUgT2JqZWN0XG4gICAgICovXG4gICAgdmFyIHBsYXRmb3JtID0ge307XG5cbiAgICAvKipcbiAgICAgKiBUaGUgcGxhdGZvcm0gZGVzY3JpcHRpb24uXG4gICAgICpcbiAgICAgKiBAbWVtYmVyT2YgcGxhdGZvcm1cbiAgICAgKiBAdHlwZSBzdHJpbmd8bnVsbFxuICAgICAqL1xuICAgIHBsYXRmb3JtLmRlc2NyaXB0aW9uID0gdWE7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgbmFtZSBvZiB0aGUgYnJvd3NlcidzIGxheW91dCBlbmdpbmUuXG4gICAgICpcbiAgICAgKiBUaGUgbGlzdCBvZiBjb21tb24gbGF5b3V0IGVuZ2luZXMgaW5jbHVkZTpcbiAgICAgKiBcIkJsaW5rXCIsIFwiRWRnZUhUTUxcIiwgXCJHZWNrb1wiLCBcIlRyaWRlbnRcIiBhbmQgXCJXZWJLaXRcIlxuICAgICAqXG4gICAgICogQG1lbWJlck9mIHBsYXRmb3JtXG4gICAgICogQHR5cGUgc3RyaW5nfG51bGxcbiAgICAgKi9cbiAgICBwbGF0Zm9ybS5sYXlvdXQgPSBsYXlvdXQgJiYgbGF5b3V0WzBdO1xuXG4gICAgLyoqXG4gICAgICogVGhlIG5hbWUgb2YgdGhlIHByb2R1Y3QncyBtYW51ZmFjdHVyZXIuXG4gICAgICpcbiAgICAgKiBUaGUgbGlzdCBvZiBtYW51ZmFjdHVyZXJzIGluY2x1ZGU6XG4gICAgICogXCJBcHBsZVwiLCBcIkFyY2hvc1wiLCBcIkFtYXpvblwiLCBcIkFzdXNcIiwgXCJCYXJuZXMgJiBOb2JsZVwiLCBcIkJsYWNrQmVycnlcIixcbiAgICAgKiBcIkdvb2dsZVwiLCBcIkhQXCIsIFwiSFRDXCIsIFwiTEdcIiwgXCJNaWNyb3NvZnRcIiwgXCJNb3Rvcm9sYVwiLCBcIk5pbnRlbmRvXCIsXG4gICAgICogXCJOb2tpYVwiLCBcIlNhbXN1bmdcIiBhbmQgXCJTb255XCJcbiAgICAgKlxuICAgICAqIEBtZW1iZXJPZiBwbGF0Zm9ybVxuICAgICAqIEB0eXBlIHN0cmluZ3xudWxsXG4gICAgICovXG4gICAgcGxhdGZvcm0ubWFudWZhY3R1cmVyID0gbWFudWZhY3R1cmVyO1xuXG4gICAgLyoqXG4gICAgICogVGhlIG5hbWUgb2YgdGhlIGJyb3dzZXIvZW52aXJvbm1lbnQuXG4gICAgICpcbiAgICAgKiBUaGUgbGlzdCBvZiBjb21tb24gYnJvd3NlciBuYW1lcyBpbmNsdWRlOlxuICAgICAqIFwiQ2hyb21lXCIsIFwiRWxlY3Ryb25cIiwgXCJGaXJlZm94XCIsIFwiRmlyZWZveCBmb3IgaU9TXCIsIFwiSUVcIixcbiAgICAgKiBcIk1pY3Jvc29mdCBFZGdlXCIsIFwiUGhhbnRvbUpTXCIsIFwiU2FmYXJpXCIsIFwiU2VhTW9ua2V5XCIsIFwiU2lsa1wiLFxuICAgICAqIFwiT3BlcmEgTWluaVwiIGFuZCBcIk9wZXJhXCJcbiAgICAgKlxuICAgICAqIE1vYmlsZSB2ZXJzaW9ucyBvZiBzb21lIGJyb3dzZXJzIGhhdmUgXCJNb2JpbGVcIiBhcHBlbmRlZCB0byB0aGVpciBuYW1lOlxuICAgICAqIGVnLiBcIkNocm9tZSBNb2JpbGVcIiwgXCJGaXJlZm94IE1vYmlsZVwiLCBcIklFIE1vYmlsZVwiIGFuZCBcIk9wZXJhIE1vYmlsZVwiXG4gICAgICpcbiAgICAgKiBAbWVtYmVyT2YgcGxhdGZvcm1cbiAgICAgKiBAdHlwZSBzdHJpbmd8bnVsbFxuICAgICAqL1xuICAgIHBsYXRmb3JtLm5hbWUgPSBuYW1lO1xuXG4gICAgLyoqXG4gICAgICogVGhlIGFscGhhL2JldGEgcmVsZWFzZSBpbmRpY2F0b3IuXG4gICAgICpcbiAgICAgKiBAbWVtYmVyT2YgcGxhdGZvcm1cbiAgICAgKiBAdHlwZSBzdHJpbmd8bnVsbFxuICAgICAqL1xuICAgIHBsYXRmb3JtLnByZXJlbGVhc2UgPSBwcmVyZWxlYXNlO1xuXG4gICAgLyoqXG4gICAgICogVGhlIG5hbWUgb2YgdGhlIHByb2R1Y3QgaG9zdGluZyB0aGUgYnJvd3Nlci5cbiAgICAgKlxuICAgICAqIFRoZSBsaXN0IG9mIGNvbW1vbiBwcm9kdWN0cyBpbmNsdWRlOlxuICAgICAqXG4gICAgICogXCJCbGFja0JlcnJ5XCIsIFwiR2FsYXh5IFM0XCIsIFwiTHVtaWFcIiwgXCJpUGFkXCIsIFwiaVBvZFwiLCBcImlQaG9uZVwiLCBcIktpbmRsZVwiLFxuICAgICAqIFwiS2luZGxlIEZpcmVcIiwgXCJOZXh1c1wiLCBcIk5vb2tcIiwgXCJQbGF5Qm9va1wiLCBcIlRvdWNoUGFkXCIgYW5kIFwiVHJhbnNmb3JtZXJcIlxuICAgICAqXG4gICAgICogQG1lbWJlck9mIHBsYXRmb3JtXG4gICAgICogQHR5cGUgc3RyaW5nfG51bGxcbiAgICAgKi9cbiAgICBwbGF0Zm9ybS5wcm9kdWN0ID0gcHJvZHVjdDtcblxuICAgIC8qKlxuICAgICAqIFRoZSBicm93c2VyJ3MgdXNlciBhZ2VudCBzdHJpbmcuXG4gICAgICpcbiAgICAgKiBAbWVtYmVyT2YgcGxhdGZvcm1cbiAgICAgKiBAdHlwZSBzdHJpbmd8bnVsbFxuICAgICAqL1xuICAgIHBsYXRmb3JtLnVhID0gdWE7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYnJvd3Nlci9lbnZpcm9ubWVudCB2ZXJzaW9uLlxuICAgICAqXG4gICAgICogQG1lbWJlck9mIHBsYXRmb3JtXG4gICAgICogQHR5cGUgc3RyaW5nfG51bGxcbiAgICAgKi9cbiAgICBwbGF0Zm9ybS52ZXJzaW9uID0gbmFtZSAmJiB2ZXJzaW9uO1xuXG4gICAgLyoqXG4gICAgICogVGhlIG5hbWUgb2YgdGhlIG9wZXJhdGluZyBzeXN0ZW0uXG4gICAgICpcbiAgICAgKiBAbWVtYmVyT2YgcGxhdGZvcm1cbiAgICAgKiBAdHlwZSBPYmplY3RcbiAgICAgKi9cbiAgICBwbGF0Zm9ybS5vcyA9IG9zIHx8IHtcblxuICAgICAgLyoqXG4gICAgICAgKiBUaGUgQ1BVIGFyY2hpdGVjdHVyZSB0aGUgT1MgaXMgYnVpbHQgZm9yLlxuICAgICAgICpcbiAgICAgICAqIEBtZW1iZXJPZiBwbGF0Zm9ybS5vc1xuICAgICAgICogQHR5cGUgbnVtYmVyfG51bGxcbiAgICAgICAqL1xuICAgICAgJ2FyY2hpdGVjdHVyZSc6IG51bGwsXG5cbiAgICAgIC8qKlxuICAgICAgICogVGhlIGZhbWlseSBvZiB0aGUgT1MuXG4gICAgICAgKlxuICAgICAgICogQ29tbW9uIHZhbHVlcyBpbmNsdWRlOlxuICAgICAgICogXCJXaW5kb3dzXCIsIFwiV2luZG93cyBTZXJ2ZXIgMjAwOCBSMiAvIDdcIiwgXCJXaW5kb3dzIFNlcnZlciAyMDA4IC8gVmlzdGFcIixcbiAgICAgICAqIFwiV2luZG93cyBYUFwiLCBcIk9TIFhcIiwgXCJVYnVudHVcIiwgXCJEZWJpYW5cIiwgXCJGZWRvcmFcIiwgXCJSZWQgSGF0XCIsIFwiU3VTRVwiLFxuICAgICAgICogXCJBbmRyb2lkXCIsIFwiaU9TXCIgYW5kIFwiV2luZG93cyBQaG9uZVwiXG4gICAgICAgKlxuICAgICAgICogQG1lbWJlck9mIHBsYXRmb3JtLm9zXG4gICAgICAgKiBAdHlwZSBzdHJpbmd8bnVsbFxuICAgICAgICovXG4gICAgICAnZmFtaWx5JzogbnVsbCxcblxuICAgICAgLyoqXG4gICAgICAgKiBUaGUgdmVyc2lvbiBvZiB0aGUgT1MuXG4gICAgICAgKlxuICAgICAgICogQG1lbWJlck9mIHBsYXRmb3JtLm9zXG4gICAgICAgKiBAdHlwZSBzdHJpbmd8bnVsbFxuICAgICAgICovXG4gICAgICAndmVyc2lvbic6IG51bGwsXG5cbiAgICAgIC8qKlxuICAgICAgICogUmV0dXJucyB0aGUgT1Mgc3RyaW5nLlxuICAgICAgICpcbiAgICAgICAqIEBtZW1iZXJPZiBwbGF0Zm9ybS5vc1xuICAgICAgICogQHJldHVybnMge3N0cmluZ30gVGhlIE9TIHN0cmluZy5cbiAgICAgICAqL1xuICAgICAgJ3RvU3RyaW5nJzogZnVuY3Rpb24oKSB7IHJldHVybiAnbnVsbCc7IH1cbiAgICB9O1xuXG4gICAgcGxhdGZvcm0ucGFyc2UgPSBwYXJzZTtcbiAgICBwbGF0Zm9ybS50b1N0cmluZyA9IHRvU3RyaW5nUGxhdGZvcm07XG5cbiAgICBpZiAocGxhdGZvcm0udmVyc2lvbikge1xuICAgICAgZGVzY3JpcHRpb24udW5zaGlmdCh2ZXJzaW9uKTtcbiAgICB9XG4gICAgaWYgKHBsYXRmb3JtLm5hbWUpIHtcbiAgICAgIGRlc2NyaXB0aW9uLnVuc2hpZnQobmFtZSk7XG4gICAgfVxuICAgIGlmIChvcyAmJiBuYW1lICYmICEob3MgPT0gU3RyaW5nKG9zKS5zcGxpdCgnICcpWzBdICYmIChvcyA9PSBuYW1lLnNwbGl0KCcgJylbMF0gfHwgcHJvZHVjdCkpKSB7XG4gICAgICBkZXNjcmlwdGlvbi5wdXNoKHByb2R1Y3QgPyAnKCcgKyBvcyArICcpJyA6ICdvbiAnICsgb3MpO1xuICAgIH1cbiAgICBpZiAoZGVzY3JpcHRpb24ubGVuZ3RoKSB7XG4gICAgICBwbGF0Zm9ybS5kZXNjcmlwdGlvbiA9IGRlc2NyaXB0aW9uLmpvaW4oJyAnKTtcbiAgICB9XG4gICAgcmV0dXJuIHBsYXRmb3JtO1xuICB9XG5cbiAgLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG5cbiAgLy8gRXhwb3J0IHBsYXRmb3JtLlxuICB2YXIgcGxhdGZvcm0gPSBwYXJzZSgpO1xuXG4gIC8vIFNvbWUgQU1EIGJ1aWxkIG9wdGltaXplcnMsIGxpa2Ugci5qcywgY2hlY2sgZm9yIGNvbmRpdGlvbiBwYXR0ZXJucyBsaWtlIHRoZSBmb2xsb3dpbmc6XG4gIGlmICh0eXBlb2YgZGVmaW5lID09ICdmdW5jdGlvbicgJiYgdHlwZW9mIGRlZmluZS5hbWQgPT0gJ29iamVjdCcgJiYgZGVmaW5lLmFtZCkge1xuICAgIC8vIEV4cG9zZSBwbGF0Zm9ybSBvbiB0aGUgZ2xvYmFsIG9iamVjdCB0byBwcmV2ZW50IGVycm9ycyB3aGVuIHBsYXRmb3JtIGlzXG4gICAgLy8gbG9hZGVkIGJ5IGEgc2NyaXB0IHRhZyBpbiB0aGUgcHJlc2VuY2Ugb2YgYW4gQU1EIGxvYWRlci5cbiAgICAvLyBTZWUgaHR0cDovL3JlcXVpcmVqcy5vcmcvZG9jcy9lcnJvcnMuaHRtbCNtaXNtYXRjaCBmb3IgbW9yZSBkZXRhaWxzLlxuICAgIHJvb3QucGxhdGZvcm0gPSBwbGF0Zm9ybTtcblxuICAgIC8vIERlZmluZSBhcyBhbiBhbm9ueW1vdXMgbW9kdWxlIHNvIHBsYXRmb3JtIGNhbiBiZSBhbGlhc2VkIHRocm91Z2ggcGF0aCBtYXBwaW5nLlxuICAgIGRlZmluZShmdW5jdGlvbigpIHtcbiAgICAgIHJldHVybiBwbGF0Zm9ybTtcbiAgICB9KTtcbiAgfVxuICAvLyBDaGVjayBmb3IgYGV4cG9ydHNgIGFmdGVyIGBkZWZpbmVgIGluIGNhc2UgYSBidWlsZCBvcHRpbWl6ZXIgYWRkcyBhbiBgZXhwb3J0c2Agb2JqZWN0LlxuICBlbHNlIGlmIChmcmVlRXhwb3J0cyAmJiBmcmVlTW9kdWxlKSB7XG4gICAgLy8gRXhwb3J0IGZvciBDb21tb25KUyBzdXBwb3J0LlxuICAgIGZvck93bihwbGF0Zm9ybSwgZnVuY3Rpb24odmFsdWUsIGtleSkge1xuICAgICAgZnJlZUV4cG9ydHNba2V5XSA9IHZhbHVlO1xuICAgIH0pO1xuICB9XG4gIGVsc2Uge1xuICAgIC8vIEV4cG9ydCB0byB0aGUgZ2xvYmFsIG9iamVjdC5cbiAgICByb290LnBsYXRmb3JtID0gcGxhdGZvcm07XG4gIH1cbn0uY2FsbCh0aGlzKSk7XG4iLCJ2YXIgdjEgPSByZXF1aXJlKCcuL3YxJyk7XG52YXIgdjQgPSByZXF1aXJlKCcuL3Y0Jyk7XG5cbnZhciB1dWlkID0gdjQ7XG51dWlkLnYxID0gdjE7XG51dWlkLnY0ID0gdjQ7XG5cbm1vZHVsZS5leHBvcnRzID0gdXVpZDtcbiIsIi8qKlxuICogQ29udmVydCBhcnJheSBvZiAxNiBieXRlIHZhbHVlcyB0byBVVUlEIHN0cmluZyBmb3JtYXQgb2YgdGhlIGZvcm06XG4gKiBYWFhYWFhYWC1YWFhYLVhYWFgtWFhYWC1YWFhYWFhYWFhYWFhcbiAqL1xudmFyIGJ5dGVUb0hleCA9IFtdO1xuZm9yICh2YXIgaSA9IDA7IGkgPCAyNTY7ICsraSkge1xuICBieXRlVG9IZXhbaV0gPSAoaSArIDB4MTAwKS50b1N0cmluZygxNikuc3Vic3RyKDEpO1xufVxuXG5mdW5jdGlvbiBieXRlc1RvVXVpZChidWYsIG9mZnNldCkge1xuICB2YXIgaSA9IG9mZnNldCB8fCAwO1xuICB2YXIgYnRoID0gYnl0ZVRvSGV4O1xuICAvLyBqb2luIHVzZWQgdG8gZml4IG1lbW9yeSBpc3N1ZSBjYXVzZWQgYnkgY29uY2F0ZW5hdGlvbjogaHR0cHM6Ly9idWdzLmNocm9taXVtLm9yZy9wL3Y4L2lzc3Vlcy9kZXRhaWw/aWQ9MzE3NSNjNFxuICByZXR1cm4gKFtidGhbYnVmW2krK11dLCBidGhbYnVmW2krK11dLCBcblx0YnRoW2J1ZltpKytdXSwgYnRoW2J1ZltpKytdXSwgJy0nLFxuXHRidGhbYnVmW2krK11dLCBidGhbYnVmW2krK11dLCAnLScsXG5cdGJ0aFtidWZbaSsrXV0sIGJ0aFtidWZbaSsrXV0sICctJyxcblx0YnRoW2J1ZltpKytdXSwgYnRoW2J1ZltpKytdXSwgJy0nLFxuXHRidGhbYnVmW2krK11dLCBidGhbYnVmW2krK11dLFxuXHRidGhbYnVmW2krK11dLCBidGhbYnVmW2krK11dLFxuXHRidGhbYnVmW2krK11dLCBidGhbYnVmW2krK11dXSkuam9pbignJyk7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gYnl0ZXNUb1V1aWQ7XG4iLCIvLyBVbmlxdWUgSUQgY3JlYXRpb24gcmVxdWlyZXMgYSBoaWdoIHF1YWxpdHkgcmFuZG9tICMgZ2VuZXJhdG9yLiAgSW4gdGhlXG4vLyBicm93c2VyIHRoaXMgaXMgYSBsaXR0bGUgY29tcGxpY2F0ZWQgZHVlIHRvIHVua25vd24gcXVhbGl0eSBvZiBNYXRoLnJhbmRvbSgpXG4vLyBhbmQgaW5jb25zaXN0ZW50IHN1cHBvcnQgZm9yIHRoZSBgY3J5cHRvYCBBUEkuICBXZSBkbyB0aGUgYmVzdCB3ZSBjYW4gdmlhXG4vLyBmZWF0dXJlLWRldGVjdGlvblxuXG4vLyBnZXRSYW5kb21WYWx1ZXMgbmVlZHMgdG8gYmUgaW52b2tlZCBpbiBhIGNvbnRleHQgd2hlcmUgXCJ0aGlzXCIgaXMgYSBDcnlwdG9cbi8vIGltcGxlbWVudGF0aW9uLiBBbHNvLCBmaW5kIHRoZSBjb21wbGV0ZSBpbXBsZW1lbnRhdGlvbiBvZiBjcnlwdG8gb24gSUUxMS5cbnZhciBnZXRSYW5kb21WYWx1ZXMgPSAodHlwZW9mKGNyeXB0bykgIT0gJ3VuZGVmaW5lZCcgJiYgY3J5cHRvLmdldFJhbmRvbVZhbHVlcyAmJiBjcnlwdG8uZ2V0UmFuZG9tVmFsdWVzLmJpbmQoY3J5cHRvKSkgfHxcbiAgICAgICAgICAgICAgICAgICAgICAodHlwZW9mKG1zQ3J5cHRvKSAhPSAndW5kZWZpbmVkJyAmJiB0eXBlb2Ygd2luZG93Lm1zQ3J5cHRvLmdldFJhbmRvbVZhbHVlcyA9PSAnZnVuY3Rpb24nICYmIG1zQ3J5cHRvLmdldFJhbmRvbVZhbHVlcy5iaW5kKG1zQ3J5cHRvKSk7XG5cbmlmIChnZXRSYW5kb21WYWx1ZXMpIHtcbiAgLy8gV0hBVFdHIGNyeXB0byBSTkcgLSBodHRwOi8vd2lraS53aGF0d2cub3JnL3dpa2kvQ3J5cHRvXG4gIHZhciBybmRzOCA9IG5ldyBVaW50OEFycmF5KDE2KTsgLy8gZXNsaW50LWRpc2FibGUtbGluZSBuby11bmRlZlxuXG4gIG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gd2hhdHdnUk5HKCkge1xuICAgIGdldFJhbmRvbVZhbHVlcyhybmRzOCk7XG4gICAgcmV0dXJuIHJuZHM4O1xuICB9O1xufSBlbHNlIHtcbiAgLy8gTWF0aC5yYW5kb20oKS1iYXNlZCAoUk5HKVxuICAvL1xuICAvLyBJZiBhbGwgZWxzZSBmYWlscywgdXNlIE1hdGgucmFuZG9tKCkuICBJdCdzIGZhc3QsIGJ1dCBpcyBvZiB1bnNwZWNpZmllZFxuICAvLyBxdWFsaXR5LlxuICB2YXIgcm5kcyA9IG5ldyBBcnJheSgxNik7XG5cbiAgbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBtYXRoUk5HKCkge1xuICAgIGZvciAodmFyIGkgPSAwLCByOyBpIDwgMTY7IGkrKykge1xuICAgICAgaWYgKChpICYgMHgwMykgPT09IDApIHIgPSBNYXRoLnJhbmRvbSgpICogMHgxMDAwMDAwMDA7XG4gICAgICBybmRzW2ldID0gciA+Pj4gKChpICYgMHgwMykgPDwgMykgJiAweGZmO1xuICAgIH1cblxuICAgIHJldHVybiBybmRzO1xuICB9O1xufVxuIiwidmFyIHJuZyA9IHJlcXVpcmUoJy4vbGliL3JuZycpO1xudmFyIGJ5dGVzVG9VdWlkID0gcmVxdWlyZSgnLi9saWIvYnl0ZXNUb1V1aWQnKTtcblxuLy8gKipgdjEoKWAgLSBHZW5lcmF0ZSB0aW1lLWJhc2VkIFVVSUQqKlxuLy9cbi8vIEluc3BpcmVkIGJ5IGh0dHBzOi8vZ2l0aHViLmNvbS9MaW9zSy9VVUlELmpzXG4vLyBhbmQgaHR0cDovL2RvY3MucHl0aG9uLm9yZy9saWJyYXJ5L3V1aWQuaHRtbFxuXG52YXIgX25vZGVJZDtcbnZhciBfY2xvY2tzZXE7XG5cbi8vIFByZXZpb3VzIHV1aWQgY3JlYXRpb24gdGltZVxudmFyIF9sYXN0TVNlY3MgPSAwO1xudmFyIF9sYXN0TlNlY3MgPSAwO1xuXG4vLyBTZWUgaHR0cHM6Ly9naXRodWIuY29tL2Jyb29mYS9ub2RlLXV1aWQgZm9yIEFQSSBkZXRhaWxzXG5mdW5jdGlvbiB2MShvcHRpb25zLCBidWYsIG9mZnNldCkge1xuICB2YXIgaSA9IGJ1ZiAmJiBvZmZzZXQgfHwgMDtcbiAgdmFyIGIgPSBidWYgfHwgW107XG5cbiAgb3B0aW9ucyA9IG9wdGlvbnMgfHwge307XG4gIHZhciBub2RlID0gb3B0aW9ucy5ub2RlIHx8IF9ub2RlSWQ7XG4gIHZhciBjbG9ja3NlcSA9IG9wdGlvbnMuY2xvY2tzZXEgIT09IHVuZGVmaW5lZCA/IG9wdGlvbnMuY2xvY2tzZXEgOiBfY2xvY2tzZXE7XG5cbiAgLy8gbm9kZSBhbmQgY2xvY2tzZXEgbmVlZCB0byBiZSBpbml0aWFsaXplZCB0byByYW5kb20gdmFsdWVzIGlmIHRoZXkncmUgbm90XG4gIC8vIHNwZWNpZmllZC4gIFdlIGRvIHRoaXMgbGF6aWx5IHRvIG1pbmltaXplIGlzc3VlcyByZWxhdGVkIHRvIGluc3VmZmljaWVudFxuICAvLyBzeXN0ZW0gZW50cm9weS4gIFNlZSAjMTg5XG4gIGlmIChub2RlID09IG51bGwgfHwgY2xvY2tzZXEgPT0gbnVsbCkge1xuICAgIHZhciBzZWVkQnl0ZXMgPSBybmcoKTtcbiAgICBpZiAobm9kZSA9PSBudWxsKSB7XG4gICAgICAvLyBQZXIgNC41LCBjcmVhdGUgYW5kIDQ4LWJpdCBub2RlIGlkLCAoNDcgcmFuZG9tIGJpdHMgKyBtdWx0aWNhc3QgYml0ID0gMSlcbiAgICAgIG5vZGUgPSBfbm9kZUlkID0gW1xuICAgICAgICBzZWVkQnl0ZXNbMF0gfCAweDAxLFxuICAgICAgICBzZWVkQnl0ZXNbMV0sIHNlZWRCeXRlc1syXSwgc2VlZEJ5dGVzWzNdLCBzZWVkQnl0ZXNbNF0sIHNlZWRCeXRlc1s1XVxuICAgICAgXTtcbiAgICB9XG4gICAgaWYgKGNsb2Nrc2VxID09IG51bGwpIHtcbiAgICAgIC8vIFBlciA0LjIuMiwgcmFuZG9taXplICgxNCBiaXQpIGNsb2Nrc2VxXG4gICAgICBjbG9ja3NlcSA9IF9jbG9ja3NlcSA9IChzZWVkQnl0ZXNbNl0gPDwgOCB8IHNlZWRCeXRlc1s3XSkgJiAweDNmZmY7XG4gICAgfVxuICB9XG5cbiAgLy8gVVVJRCB0aW1lc3RhbXBzIGFyZSAxMDAgbmFuby1zZWNvbmQgdW5pdHMgc2luY2UgdGhlIEdyZWdvcmlhbiBlcG9jaCxcbiAgLy8gKDE1ODItMTAtMTUgMDA6MDApLiAgSlNOdW1iZXJzIGFyZW4ndCBwcmVjaXNlIGVub3VnaCBmb3IgdGhpcywgc29cbiAgLy8gdGltZSBpcyBoYW5kbGVkIGludGVybmFsbHkgYXMgJ21zZWNzJyAoaW50ZWdlciBtaWxsaXNlY29uZHMpIGFuZCAnbnNlY3MnXG4gIC8vICgxMDAtbmFub3NlY29uZHMgb2Zmc2V0IGZyb20gbXNlY3MpIHNpbmNlIHVuaXggZXBvY2gsIDE5NzAtMDEtMDEgMDA6MDAuXG4gIHZhciBtc2VjcyA9IG9wdGlvbnMubXNlY3MgIT09IHVuZGVmaW5lZCA/IG9wdGlvbnMubXNlY3MgOiBuZXcgRGF0ZSgpLmdldFRpbWUoKTtcblxuICAvLyBQZXIgNC4yLjEuMiwgdXNlIGNvdW50IG9mIHV1aWQncyBnZW5lcmF0ZWQgZHVyaW5nIHRoZSBjdXJyZW50IGNsb2NrXG4gIC8vIGN5Y2xlIHRvIHNpbXVsYXRlIGhpZ2hlciByZXNvbHV0aW9uIGNsb2NrXG4gIHZhciBuc2VjcyA9IG9wdGlvbnMubnNlY3MgIT09IHVuZGVmaW5lZCA/IG9wdGlvbnMubnNlY3MgOiBfbGFzdE5TZWNzICsgMTtcblxuICAvLyBUaW1lIHNpbmNlIGxhc3QgdXVpZCBjcmVhdGlvbiAoaW4gbXNlY3MpXG4gIHZhciBkdCA9IChtc2VjcyAtIF9sYXN0TVNlY3MpICsgKG5zZWNzIC0gX2xhc3ROU2VjcykvMTAwMDA7XG5cbiAgLy8gUGVyIDQuMi4xLjIsIEJ1bXAgY2xvY2tzZXEgb24gY2xvY2sgcmVncmVzc2lvblxuICBpZiAoZHQgPCAwICYmIG9wdGlvbnMuY2xvY2tzZXEgPT09IHVuZGVmaW5lZCkge1xuICAgIGNsb2Nrc2VxID0gY2xvY2tzZXEgKyAxICYgMHgzZmZmO1xuICB9XG5cbiAgLy8gUmVzZXQgbnNlY3MgaWYgY2xvY2sgcmVncmVzc2VzIChuZXcgY2xvY2tzZXEpIG9yIHdlJ3ZlIG1vdmVkIG9udG8gYSBuZXdcbiAgLy8gdGltZSBpbnRlcnZhbFxuICBpZiAoKGR0IDwgMCB8fCBtc2VjcyA+IF9sYXN0TVNlY3MpICYmIG9wdGlvbnMubnNlY3MgPT09IHVuZGVmaW5lZCkge1xuICAgIG5zZWNzID0gMDtcbiAgfVxuXG4gIC8vIFBlciA0LjIuMS4yIFRocm93IGVycm9yIGlmIHRvbyBtYW55IHV1aWRzIGFyZSByZXF1ZXN0ZWRcbiAgaWYgKG5zZWNzID49IDEwMDAwKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCd1dWlkLnYxKCk6IENhblxcJ3QgY3JlYXRlIG1vcmUgdGhhbiAxME0gdXVpZHMvc2VjJyk7XG4gIH1cblxuICBfbGFzdE1TZWNzID0gbXNlY3M7XG4gIF9sYXN0TlNlY3MgPSBuc2VjcztcbiAgX2Nsb2Nrc2VxID0gY2xvY2tzZXE7XG5cbiAgLy8gUGVyIDQuMS40IC0gQ29udmVydCBmcm9tIHVuaXggZXBvY2ggdG8gR3JlZ29yaWFuIGVwb2NoXG4gIG1zZWNzICs9IDEyMjE5MjkyODAwMDAwO1xuXG4gIC8vIGB0aW1lX2xvd2BcbiAgdmFyIHRsID0gKChtc2VjcyAmIDB4ZmZmZmZmZikgKiAxMDAwMCArIG5zZWNzKSAlIDB4MTAwMDAwMDAwO1xuICBiW2krK10gPSB0bCA+Pj4gMjQgJiAweGZmO1xuICBiW2krK10gPSB0bCA+Pj4gMTYgJiAweGZmO1xuICBiW2krK10gPSB0bCA+Pj4gOCAmIDB4ZmY7XG4gIGJbaSsrXSA9IHRsICYgMHhmZjtcblxuICAvLyBgdGltZV9taWRgXG4gIHZhciB0bWggPSAobXNlY3MgLyAweDEwMDAwMDAwMCAqIDEwMDAwKSAmIDB4ZmZmZmZmZjtcbiAgYltpKytdID0gdG1oID4+PiA4ICYgMHhmZjtcbiAgYltpKytdID0gdG1oICYgMHhmZjtcblxuICAvLyBgdGltZV9oaWdoX2FuZF92ZXJzaW9uYFxuICBiW2krK10gPSB0bWggPj4+IDI0ICYgMHhmIHwgMHgxMDsgLy8gaW5jbHVkZSB2ZXJzaW9uXG4gIGJbaSsrXSA9IHRtaCA+Pj4gMTYgJiAweGZmO1xuXG4gIC8vIGBjbG9ja19zZXFfaGlfYW5kX3Jlc2VydmVkYCAoUGVyIDQuMi4yIC0gaW5jbHVkZSB2YXJpYW50KVxuICBiW2krK10gPSBjbG9ja3NlcSA+Pj4gOCB8IDB4ODA7XG5cbiAgLy8gYGNsb2NrX3NlcV9sb3dgXG4gIGJbaSsrXSA9IGNsb2Nrc2VxICYgMHhmZjtcblxuICAvLyBgbm9kZWBcbiAgZm9yICh2YXIgbiA9IDA7IG4gPCA2OyArK24pIHtcbiAgICBiW2kgKyBuXSA9IG5vZGVbbl07XG4gIH1cblxuICByZXR1cm4gYnVmID8gYnVmIDogYnl0ZXNUb1V1aWQoYik7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gdjE7XG4iLCJ2YXIgcm5nID0gcmVxdWlyZSgnLi9saWIvcm5nJyk7XG52YXIgYnl0ZXNUb1V1aWQgPSByZXF1aXJlKCcuL2xpYi9ieXRlc1RvVXVpZCcpO1xuXG5mdW5jdGlvbiB2NChvcHRpb25zLCBidWYsIG9mZnNldCkge1xuICB2YXIgaSA9IGJ1ZiAmJiBvZmZzZXQgfHwgMDtcblxuICBpZiAodHlwZW9mKG9wdGlvbnMpID09ICdzdHJpbmcnKSB7XG4gICAgYnVmID0gb3B0aW9ucyA9PT0gJ2JpbmFyeScgPyBuZXcgQXJyYXkoMTYpIDogbnVsbDtcbiAgICBvcHRpb25zID0gbnVsbDtcbiAgfVxuICBvcHRpb25zID0gb3B0aW9ucyB8fCB7fTtcblxuICB2YXIgcm5kcyA9IG9wdGlvbnMucmFuZG9tIHx8IChvcHRpb25zLnJuZyB8fCBybmcpKCk7XG5cbiAgLy8gUGVyIDQuNCwgc2V0IGJpdHMgZm9yIHZlcnNpb24gYW5kIGBjbG9ja19zZXFfaGlfYW5kX3Jlc2VydmVkYFxuICBybmRzWzZdID0gKHJuZHNbNl0gJiAweDBmKSB8IDB4NDA7XG4gIHJuZHNbOF0gPSAocm5kc1s4XSAmIDB4M2YpIHwgMHg4MDtcblxuICAvLyBDb3B5IGJ5dGVzIHRvIGJ1ZmZlciwgaWYgcHJvdmlkZWRcbiAgaWYgKGJ1Zikge1xuICAgIGZvciAodmFyIGlpID0gMDsgaWkgPCAxNjsgKytpaSkge1xuICAgICAgYnVmW2kgKyBpaV0gPSBybmRzW2lpXTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gYnVmIHx8IGJ5dGVzVG9VdWlkKHJuZHMpO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHY0O1xuIiwiLypcclxuV2lsZEVtaXR0ZXIuanMgaXMgYSBzbGltIGxpdHRsZSBldmVudCBlbWl0dGVyIGJ5IEBoZW5yaWtqb3JldGVnIGxhcmdlbHkgYmFzZWRcclxub24gQHZpc2lvbm1lZGlhJ3MgRW1pdHRlciBmcm9tIFVJIEtpdC5cclxuXHJcbldoeT8gSSB3YW50ZWQgaXQgc3RhbmRhbG9uZS5cclxuXHJcbkkgYWxzbyB3YW50ZWQgc3VwcG9ydCBmb3Igd2lsZGNhcmQgZW1pdHRlcnMgbGlrZSB0aGlzOlxyXG5cclxuZW1pdHRlci5vbignKicsIGZ1bmN0aW9uIChldmVudE5hbWUsIG90aGVyLCBldmVudCwgcGF5bG9hZHMpIHtcclxuXHJcbn0pO1xyXG5cclxuZW1pdHRlci5vbignc29tZW5hbWVzcGFjZSonLCBmdW5jdGlvbiAoZXZlbnROYW1lLCBwYXlsb2Fkcykge1xyXG5cclxufSk7XHJcblxyXG5QbGVhc2Ugbm90ZSB0aGF0IGNhbGxiYWNrcyB0cmlnZ2VyZWQgYnkgd2lsZGNhcmQgcmVnaXN0ZXJlZCBldmVudHMgYWxzbyBnZXRcclxudGhlIGV2ZW50IG5hbWUgYXMgdGhlIGZpcnN0IGFyZ3VtZW50LlxyXG4qL1xyXG5cclxubW9kdWxlLmV4cG9ydHMgPSBXaWxkRW1pdHRlcjtcclxuXHJcbmZ1bmN0aW9uIFdpbGRFbWl0dGVyKCkgeyB9XHJcblxyXG5XaWxkRW1pdHRlci5taXhpbiA9IGZ1bmN0aW9uIChjb25zdHJ1Y3Rvcikge1xyXG4gICAgdmFyIHByb3RvdHlwZSA9IGNvbnN0cnVjdG9yLnByb3RvdHlwZSB8fCBjb25zdHJ1Y3RvcjtcclxuXHJcbiAgICBwcm90b3R5cGUuaXNXaWxkRW1pdHRlcj0gdHJ1ZTtcclxuXHJcbiAgICAvLyBMaXN0ZW4gb24gdGhlIGdpdmVuIGBldmVudGAgd2l0aCBgZm5gLiBTdG9yZSBhIGdyb3VwIG5hbWUgaWYgcHJlc2VudC5cclxuICAgIHByb3RvdHlwZS5vbiA9IGZ1bmN0aW9uIChldmVudCwgZ3JvdXBOYW1lLCBmbikge1xyXG4gICAgICAgIHRoaXMuY2FsbGJhY2tzID0gdGhpcy5jYWxsYmFja3MgfHwge307XHJcbiAgICAgICAgdmFyIGhhc0dyb3VwID0gKGFyZ3VtZW50cy5sZW5ndGggPT09IDMpLFxyXG4gICAgICAgICAgICBncm91cCA9IGhhc0dyb3VwID8gYXJndW1lbnRzWzFdIDogdW5kZWZpbmVkLFxyXG4gICAgICAgICAgICBmdW5jID0gaGFzR3JvdXAgPyBhcmd1bWVudHNbMl0gOiBhcmd1bWVudHNbMV07XHJcbiAgICAgICAgZnVuYy5fZ3JvdXBOYW1lID0gZ3JvdXA7XHJcbiAgICAgICAgKHRoaXMuY2FsbGJhY2tzW2V2ZW50XSA9IHRoaXMuY2FsbGJhY2tzW2V2ZW50XSB8fCBbXSkucHVzaChmdW5jKTtcclxuICAgICAgICByZXR1cm4gdGhpcztcclxuICAgIH07XHJcblxyXG4gICAgLy8gQWRkcyBhbiBgZXZlbnRgIGxpc3RlbmVyIHRoYXQgd2lsbCBiZSBpbnZva2VkIGEgc2luZ2xlXHJcbiAgICAvLyB0aW1lIHRoZW4gYXV0b21hdGljYWxseSByZW1vdmVkLlxyXG4gICAgcHJvdG90eXBlLm9uY2UgPSBmdW5jdGlvbiAoZXZlbnQsIGdyb3VwTmFtZSwgZm4pIHtcclxuICAgICAgICB2YXIgc2VsZiA9IHRoaXMsXHJcbiAgICAgICAgICAgIGhhc0dyb3VwID0gKGFyZ3VtZW50cy5sZW5ndGggPT09IDMpLFxyXG4gICAgICAgICAgICBncm91cCA9IGhhc0dyb3VwID8gYXJndW1lbnRzWzFdIDogdW5kZWZpbmVkLFxyXG4gICAgICAgICAgICBmdW5jID0gaGFzR3JvdXAgPyBhcmd1bWVudHNbMl0gOiBhcmd1bWVudHNbMV07XHJcbiAgICAgICAgZnVuY3Rpb24gb24oKSB7XHJcbiAgICAgICAgICAgIHNlbGYub2ZmKGV2ZW50LCBvbik7XHJcbiAgICAgICAgICAgIGZ1bmMuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgdGhpcy5vbihldmVudCwgZ3JvdXAsIG9uKTtcclxuICAgICAgICByZXR1cm4gdGhpcztcclxuICAgIH07XHJcblxyXG4gICAgLy8gVW5iaW5kcyBhbiBlbnRpcmUgZ3JvdXBcclxuICAgIHByb3RvdHlwZS5yZWxlYXNlR3JvdXAgPSBmdW5jdGlvbiAoZ3JvdXBOYW1lKSB7XHJcbiAgICAgICAgdGhpcy5jYWxsYmFja3MgPSB0aGlzLmNhbGxiYWNrcyB8fCB7fTtcclxuICAgICAgICB2YXIgaXRlbSwgaSwgbGVuLCBoYW5kbGVycztcclxuICAgICAgICBmb3IgKGl0ZW0gaW4gdGhpcy5jYWxsYmFja3MpIHtcclxuICAgICAgICAgICAgaGFuZGxlcnMgPSB0aGlzLmNhbGxiYWNrc1tpdGVtXTtcclxuICAgICAgICAgICAgZm9yIChpID0gMCwgbGVuID0gaGFuZGxlcnMubGVuZ3RoOyBpIDwgbGVuOyBpKyspIHtcclxuICAgICAgICAgICAgICAgIGlmIChoYW5kbGVyc1tpXS5fZ3JvdXBOYW1lID09PSBncm91cE5hbWUpIHtcclxuICAgICAgICAgICAgICAgICAgICAvL2NvbnNvbGUubG9nKCdyZW1vdmluZycpO1xyXG4gICAgICAgICAgICAgICAgICAgIC8vIHJlbW92ZSBpdCBhbmQgc2hvcnRlbiB0aGUgYXJyYXkgd2UncmUgbG9vcGluZyB0aHJvdWdoXHJcbiAgICAgICAgICAgICAgICAgICAgaGFuZGxlcnMuc3BsaWNlKGksIDEpO1xyXG4gICAgICAgICAgICAgICAgICAgIGktLTtcclxuICAgICAgICAgICAgICAgICAgICBsZW4tLTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgICAgICByZXR1cm4gdGhpcztcclxuICAgIH07XHJcblxyXG4gICAgLy8gUmVtb3ZlIHRoZSBnaXZlbiBjYWxsYmFjayBmb3IgYGV2ZW50YCBvciBhbGxcclxuICAgIC8vIHJlZ2lzdGVyZWQgY2FsbGJhY2tzLlxyXG4gICAgcHJvdG90eXBlLm9mZiA9IGZ1bmN0aW9uIChldmVudCwgZm4pIHtcclxuICAgICAgICB0aGlzLmNhbGxiYWNrcyA9IHRoaXMuY2FsbGJhY2tzIHx8IHt9O1xyXG4gICAgICAgIHZhciBjYWxsYmFja3MgPSB0aGlzLmNhbGxiYWNrc1tldmVudF0sXHJcbiAgICAgICAgICAgIGk7XHJcblxyXG4gICAgICAgIGlmICghY2FsbGJhY2tzKSByZXR1cm4gdGhpcztcclxuXHJcbiAgICAgICAgLy8gcmVtb3ZlIGFsbCBoYW5kbGVyc1xyXG4gICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAxKSB7XHJcbiAgICAgICAgICAgIGRlbGV0ZSB0aGlzLmNhbGxiYWNrc1tldmVudF07XHJcbiAgICAgICAgICAgIHJldHVybiB0aGlzO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgLy8gcmVtb3ZlIHNwZWNpZmljIGhhbmRsZXJcclxuICAgICAgICBpID0gY2FsbGJhY2tzLmluZGV4T2YoZm4pO1xyXG4gICAgICAgIGNhbGxiYWNrcy5zcGxpY2UoaSwgMSk7XHJcbiAgICAgICAgaWYgKGNhbGxiYWNrcy5sZW5ndGggPT09IDApIHtcclxuICAgICAgICAgICAgZGVsZXRlIHRoaXMuY2FsbGJhY2tzW2V2ZW50XTtcclxuICAgICAgICB9XHJcbiAgICAgICAgcmV0dXJuIHRoaXM7XHJcbiAgICB9O1xyXG5cclxuICAgIC8vLyBFbWl0IGBldmVudGAgd2l0aCB0aGUgZ2l2ZW4gYXJncy5cclxuICAgIC8vIGFsc28gY2FsbHMgYW55IGAqYCBoYW5kbGVyc1xyXG4gICAgcHJvdG90eXBlLmVtaXQgPSBmdW5jdGlvbiAoZXZlbnQpIHtcclxuICAgICAgICB0aGlzLmNhbGxiYWNrcyA9IHRoaXMuY2FsbGJhY2tzIHx8IHt9O1xyXG4gICAgICAgIHZhciBhcmdzID0gW10uc2xpY2UuY2FsbChhcmd1bWVudHMsIDEpLFxyXG4gICAgICAgICAgICBjYWxsYmFja3MgPSB0aGlzLmNhbGxiYWNrc1tldmVudF0sXHJcbiAgICAgICAgICAgIHNwZWNpYWxDYWxsYmFja3MgPSB0aGlzLmdldFdpbGRjYXJkQ2FsbGJhY2tzKGV2ZW50KSxcclxuICAgICAgICAgICAgaSxcclxuICAgICAgICAgICAgbGVuLFxyXG4gICAgICAgICAgICBpdGVtLFxyXG4gICAgICAgICAgICBsaXN0ZW5lcnM7XHJcblxyXG4gICAgICAgIGlmIChjYWxsYmFja3MpIHtcclxuICAgICAgICAgICAgbGlzdGVuZXJzID0gY2FsbGJhY2tzLnNsaWNlKCk7XHJcbiAgICAgICAgICAgIGZvciAoaSA9IDAsIGxlbiA9IGxpc3RlbmVycy5sZW5ndGg7IGkgPCBsZW47ICsraSkge1xyXG4gICAgICAgICAgICAgICAgaWYgKCFsaXN0ZW5lcnNbaV0pIHtcclxuICAgICAgICAgICAgICAgICAgICBicmVhaztcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIGxpc3RlbmVyc1tpXS5hcHBseSh0aGlzLCBhcmdzKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgaWYgKHNwZWNpYWxDYWxsYmFja3MpIHtcclxuICAgICAgICAgICAgbGVuID0gc3BlY2lhbENhbGxiYWNrcy5sZW5ndGg7XHJcbiAgICAgICAgICAgIGxpc3RlbmVycyA9IHNwZWNpYWxDYWxsYmFja3Muc2xpY2UoKTtcclxuICAgICAgICAgICAgZm9yIChpID0gMCwgbGVuID0gbGlzdGVuZXJzLmxlbmd0aDsgaSA8IGxlbjsgKytpKSB7XHJcbiAgICAgICAgICAgICAgICBpZiAoIWxpc3RlbmVyc1tpXSkge1xyXG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgbGlzdGVuZXJzW2ldLmFwcGx5KHRoaXMsIFtldmVudF0uY29uY2F0KGFyZ3MpKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgcmV0dXJuIHRoaXM7XHJcbiAgICB9O1xyXG5cclxuICAgIC8vIEhlbHBlciBmb3IgZm9yIGZpbmRpbmcgc3BlY2lhbCB3aWxkY2FyZCBldmVudCBoYW5kbGVycyB0aGF0IG1hdGNoIHRoZSBldmVudFxyXG4gICAgcHJvdG90eXBlLmdldFdpbGRjYXJkQ2FsbGJhY2tzID0gZnVuY3Rpb24gKGV2ZW50TmFtZSkge1xyXG4gICAgICAgIHRoaXMuY2FsbGJhY2tzID0gdGhpcy5jYWxsYmFja3MgfHwge307XHJcbiAgICAgICAgdmFyIGl0ZW0sXHJcbiAgICAgICAgICAgIHNwbGl0LFxyXG4gICAgICAgICAgICByZXN1bHQgPSBbXTtcclxuXHJcbiAgICAgICAgZm9yIChpdGVtIGluIHRoaXMuY2FsbGJhY2tzKSB7XHJcbiAgICAgICAgICAgIHNwbGl0ID0gaXRlbS5zcGxpdCgnKicpO1xyXG4gICAgICAgICAgICBpZiAoaXRlbSA9PT0gJyonIHx8IChzcGxpdC5sZW5ndGggPT09IDIgJiYgZXZlbnROYW1lLnNsaWNlKDAsIHNwbGl0WzBdLmxlbmd0aCkgPT09IHNwbGl0WzBdKSkge1xyXG4gICAgICAgICAgICAgICAgcmVzdWx0ID0gcmVzdWx0LmNvbmNhdCh0aGlzLmNhbGxiYWNrc1tpdGVtXSk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcclxuICAgIH07XHJcblxyXG59O1xyXG5cclxuV2lsZEVtaXR0ZXIubWl4aW4oV2lsZEVtaXR0ZXIpO1xyXG4iLCIvKiFcbiAqIEV2ZW50RW1pdHRlciB2NS4yLjUgLSBnaXQuaW8vZWVcbiAqIFVubGljZW5zZSAtIGh0dHA6Ly91bmxpY2Vuc2Uub3JnL1xuICogT2xpdmVyIENhbGR3ZWxsIC0gaHR0cDovL29saS5tZS51ay9cbiAqIEBwcmVzZXJ2ZVxuICovXG5cbjsoZnVuY3Rpb24gKGV4cG9ydHMpIHtcbiAgICAndXNlIHN0cmljdCc7XG5cbiAgICAvKipcbiAgICAgKiBDbGFzcyBmb3IgbWFuYWdpbmcgZXZlbnRzLlxuICAgICAqIENhbiBiZSBleHRlbmRlZCB0byBwcm92aWRlIGV2ZW50IGZ1bmN0aW9uYWxpdHkgaW4gb3RoZXIgY2xhc3Nlcy5cbiAgICAgKlxuICAgICAqIEBjbGFzcyBFdmVudEVtaXR0ZXIgTWFuYWdlcyBldmVudCByZWdpc3RlcmluZyBhbmQgZW1pdHRpbmcuXG4gICAgICovXG4gICAgZnVuY3Rpb24gRXZlbnRFbWl0dGVyKCkge31cblxuICAgIC8vIFNob3J0Y3V0cyB0byBpbXByb3ZlIHNwZWVkIGFuZCBzaXplXG4gICAgdmFyIHByb3RvID0gRXZlbnRFbWl0dGVyLnByb3RvdHlwZTtcbiAgICB2YXIgb3JpZ2luYWxHbG9iYWxWYWx1ZSA9IGV4cG9ydHMuRXZlbnRFbWl0dGVyO1xuXG4gICAgLyoqXG4gICAgICogRmluZHMgdGhlIGluZGV4IG9mIHRoZSBsaXN0ZW5lciBmb3IgdGhlIGV2ZW50IGluIGl0cyBzdG9yYWdlIGFycmF5LlxuICAgICAqXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbltdfSBsaXN0ZW5lcnMgQXJyYXkgb2YgbGlzdGVuZXJzIHRvIHNlYXJjaCB0aHJvdWdoLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGxpc3RlbmVyIE1ldGhvZCB0byBsb29rIGZvci5cbiAgICAgKiBAcmV0dXJuIHtOdW1iZXJ9IEluZGV4IG9mIHRoZSBzcGVjaWZpZWQgbGlzdGVuZXIsIC0xIGlmIG5vdCBmb3VuZFxuICAgICAqIEBhcGkgcHJpdmF0ZVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGluZGV4T2ZMaXN0ZW5lcihsaXN0ZW5lcnMsIGxpc3RlbmVyKSB7XG4gICAgICAgIHZhciBpID0gbGlzdGVuZXJzLmxlbmd0aDtcbiAgICAgICAgd2hpbGUgKGktLSkge1xuICAgICAgICAgICAgaWYgKGxpc3RlbmVyc1tpXS5saXN0ZW5lciA9PT0gbGlzdGVuZXIpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiAtMTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBBbGlhcyBhIG1ldGhvZCB3aGlsZSBrZWVwaW5nIHRoZSBjb250ZXh0IGNvcnJlY3QsIHRvIGFsbG93IGZvciBvdmVyd3JpdGluZyBvZiB0YXJnZXQgbWV0aG9kLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtTdHJpbmd9IG5hbWUgVGhlIG5hbWUgb2YgdGhlIHRhcmdldCBtZXRob2QuXG4gICAgICogQHJldHVybiB7RnVuY3Rpb259IFRoZSBhbGlhc2VkIG1ldGhvZFxuICAgICAqIEBhcGkgcHJpdmF0ZVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGFsaWFzKG5hbWUpIHtcbiAgICAgICAgcmV0dXJuIGZ1bmN0aW9uIGFsaWFzQ2xvc3VyZSgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzW25hbWVdLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyB0aGUgbGlzdGVuZXIgYXJyYXkgZm9yIHRoZSBzcGVjaWZpZWQgZXZlbnQuXG4gICAgICogV2lsbCBpbml0aWFsaXNlIHRoZSBldmVudCBvYmplY3QgYW5kIGxpc3RlbmVyIGFycmF5cyBpZiByZXF1aXJlZC5cbiAgICAgKiBXaWxsIHJldHVybiBhbiBvYmplY3QgaWYgeW91IHVzZSBhIHJlZ2V4IHNlYXJjaC4gVGhlIG9iamVjdCBjb250YWlucyBrZXlzIGZvciBlYWNoIG1hdGNoZWQgZXZlbnQuIFNvIC9iYVtyel0vIG1pZ2h0IHJldHVybiBhbiBvYmplY3QgY29udGFpbmluZyBiYXIgYW5kIGJhei4gQnV0IG9ubHkgaWYgeW91IGhhdmUgZWl0aGVyIGRlZmluZWQgdGhlbSB3aXRoIGRlZmluZUV2ZW50IG9yIGFkZGVkIHNvbWUgbGlzdGVuZXJzIHRvIHRoZW0uXG4gICAgICogRWFjaCBwcm9wZXJ0eSBpbiB0aGUgb2JqZWN0IHJlc3BvbnNlIGlzIGFuIGFycmF5IG9mIGxpc3RlbmVyIGZ1bmN0aW9ucy5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfFJlZ0V4cH0gZXZ0IE5hbWUgb2YgdGhlIGV2ZW50IHRvIHJldHVybiB0aGUgbGlzdGVuZXJzIGZyb20uXG4gICAgICogQHJldHVybiB7RnVuY3Rpb25bXXxPYmplY3R9IEFsbCBsaXN0ZW5lciBmdW5jdGlvbnMgZm9yIHRoZSBldmVudC5cbiAgICAgKi9cbiAgICBwcm90by5nZXRMaXN0ZW5lcnMgPSBmdW5jdGlvbiBnZXRMaXN0ZW5lcnMoZXZ0KSB7XG4gICAgICAgIHZhciBldmVudHMgPSB0aGlzLl9nZXRFdmVudHMoKTtcbiAgICAgICAgdmFyIHJlc3BvbnNlO1xuICAgICAgICB2YXIga2V5O1xuXG4gICAgICAgIC8vIFJldHVybiBhIGNvbmNhdGVuYXRlZCBhcnJheSBvZiBhbGwgbWF0Y2hpbmcgZXZlbnRzIGlmXG4gICAgICAgIC8vIHRoZSBzZWxlY3RvciBpcyBhIHJlZ3VsYXIgZXhwcmVzc2lvbi5cbiAgICAgICAgaWYgKGV2dCBpbnN0YW5jZW9mIFJlZ0V4cCkge1xuICAgICAgICAgICAgcmVzcG9uc2UgPSB7fTtcbiAgICAgICAgICAgIGZvciAoa2V5IGluIGV2ZW50cykge1xuICAgICAgICAgICAgICAgIGlmIChldmVudHMuaGFzT3duUHJvcGVydHkoa2V5KSAmJiBldnQudGVzdChrZXkpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc3BvbnNlW2tleV0gPSBldmVudHNba2V5XTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICByZXNwb25zZSA9IGV2ZW50c1tldnRdIHx8IChldmVudHNbZXZ0XSA9IFtdKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiByZXNwb25zZTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogVGFrZXMgYSBsaXN0IG9mIGxpc3RlbmVyIG9iamVjdHMgYW5kIGZsYXR0ZW5zIGl0IGludG8gYSBsaXN0IG9mIGxpc3RlbmVyIGZ1bmN0aW9ucy5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7T2JqZWN0W119IGxpc3RlbmVycyBSYXcgbGlzdGVuZXIgb2JqZWN0cy5cbiAgICAgKiBAcmV0dXJuIHtGdW5jdGlvbltdfSBKdXN0IHRoZSBsaXN0ZW5lciBmdW5jdGlvbnMuXG4gICAgICovXG4gICAgcHJvdG8uZmxhdHRlbkxpc3RlbmVycyA9IGZ1bmN0aW9uIGZsYXR0ZW5MaXN0ZW5lcnMobGlzdGVuZXJzKSB7XG4gICAgICAgIHZhciBmbGF0TGlzdGVuZXJzID0gW107XG4gICAgICAgIHZhciBpO1xuXG4gICAgICAgIGZvciAoaSA9IDA7IGkgPCBsaXN0ZW5lcnMubGVuZ3RoOyBpICs9IDEpIHtcbiAgICAgICAgICAgIGZsYXRMaXN0ZW5lcnMucHVzaChsaXN0ZW5lcnNbaV0ubGlzdGVuZXIpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGZsYXRMaXN0ZW5lcnM7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEZldGNoZXMgdGhlIHJlcXVlc3RlZCBsaXN0ZW5lcnMgdmlhIGdldExpc3RlbmVycyBidXQgd2lsbCBhbHdheXMgcmV0dXJuIHRoZSByZXN1bHRzIGluc2lkZSBhbiBvYmplY3QuIFRoaXMgaXMgbWFpbmx5IGZvciBpbnRlcm5hbCB1c2UgYnV0IG90aGVycyBtYXkgZmluZCBpdCB1c2VmdWwuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1N0cmluZ3xSZWdFeHB9IGV2dCBOYW1lIG9mIHRoZSBldmVudCB0byByZXR1cm4gdGhlIGxpc3RlbmVycyBmcm9tLlxuICAgICAqIEByZXR1cm4ge09iamVjdH0gQWxsIGxpc3RlbmVyIGZ1bmN0aW9ucyBmb3IgYW4gZXZlbnQgaW4gYW4gb2JqZWN0LlxuICAgICAqL1xuICAgIHByb3RvLmdldExpc3RlbmVyc0FzT2JqZWN0ID0gZnVuY3Rpb24gZ2V0TGlzdGVuZXJzQXNPYmplY3QoZXZ0KSB7XG4gICAgICAgIHZhciBsaXN0ZW5lcnMgPSB0aGlzLmdldExpc3RlbmVycyhldnQpO1xuICAgICAgICB2YXIgcmVzcG9uc2U7XG5cbiAgICAgICAgaWYgKGxpc3RlbmVycyBpbnN0YW5jZW9mIEFycmF5KSB7XG4gICAgICAgICAgICByZXNwb25zZSA9IHt9O1xuICAgICAgICAgICAgcmVzcG9uc2VbZXZ0XSA9IGxpc3RlbmVycztcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiByZXNwb25zZSB8fCBsaXN0ZW5lcnM7XG4gICAgfTtcblxuICAgIGZ1bmN0aW9uIGlzVmFsaWRMaXN0ZW5lciAobGlzdGVuZXIpIHtcbiAgICAgICAgaWYgKHR5cGVvZiBsaXN0ZW5lciA9PT0gJ2Z1bmN0aW9uJyB8fCBsaXN0ZW5lciBpbnN0YW5jZW9mIFJlZ0V4cCkge1xuICAgICAgICAgICAgcmV0dXJuIHRydWVcbiAgICAgICAgfSBlbHNlIGlmIChsaXN0ZW5lciAmJiB0eXBlb2YgbGlzdGVuZXIgPT09ICdvYmplY3QnKSB7XG4gICAgICAgICAgICByZXR1cm4gaXNWYWxpZExpc3RlbmVyKGxpc3RlbmVyLmxpc3RlbmVyKVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlXG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBBZGRzIGEgbGlzdGVuZXIgZnVuY3Rpb24gdG8gdGhlIHNwZWNpZmllZCBldmVudC5cbiAgICAgKiBUaGUgbGlzdGVuZXIgd2lsbCBub3QgYmUgYWRkZWQgaWYgaXQgaXMgYSBkdXBsaWNhdGUuXG4gICAgICogSWYgdGhlIGxpc3RlbmVyIHJldHVybnMgdHJ1ZSB0aGVuIGl0IHdpbGwgYmUgcmVtb3ZlZCBhZnRlciBpdCBpcyBjYWxsZWQuXG4gICAgICogSWYgeW91IHBhc3MgYSByZWd1bGFyIGV4cHJlc3Npb24gYXMgdGhlIGV2ZW50IG5hbWUgdGhlbiB0aGUgbGlzdGVuZXIgd2lsbCBiZSBhZGRlZCB0byBhbGwgZXZlbnRzIHRoYXQgbWF0Y2ggaXQuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1N0cmluZ3xSZWdFeHB9IGV2dCBOYW1lIG9mIHRoZSBldmVudCB0byBhdHRhY2ggdGhlIGxpc3RlbmVyIHRvLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGxpc3RlbmVyIE1ldGhvZCB0byBiZSBjYWxsZWQgd2hlbiB0aGUgZXZlbnQgaXMgZW1pdHRlZC4gSWYgdGhlIGZ1bmN0aW9uIHJldHVybnMgdHJ1ZSB0aGVuIGl0IHdpbGwgYmUgcmVtb3ZlZCBhZnRlciBjYWxsaW5nLlxuICAgICAqIEByZXR1cm4ge09iamVjdH0gQ3VycmVudCBpbnN0YW5jZSBvZiBFdmVudEVtaXR0ZXIgZm9yIGNoYWluaW5nLlxuICAgICAqL1xuICAgIHByb3RvLmFkZExpc3RlbmVyID0gZnVuY3Rpb24gYWRkTGlzdGVuZXIoZXZ0LCBsaXN0ZW5lcikge1xuICAgICAgICBpZiAoIWlzVmFsaWRMaXN0ZW5lcihsaXN0ZW5lcikpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2xpc3RlbmVyIG11c3QgYmUgYSBmdW5jdGlvbicpO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIGxpc3RlbmVycyA9IHRoaXMuZ2V0TGlzdGVuZXJzQXNPYmplY3QoZXZ0KTtcbiAgICAgICAgdmFyIGxpc3RlbmVySXNXcmFwcGVkID0gdHlwZW9mIGxpc3RlbmVyID09PSAnb2JqZWN0JztcbiAgICAgICAgdmFyIGtleTtcblxuICAgICAgICBmb3IgKGtleSBpbiBsaXN0ZW5lcnMpIHtcbiAgICAgICAgICAgIGlmIChsaXN0ZW5lcnMuaGFzT3duUHJvcGVydHkoa2V5KSAmJiBpbmRleE9mTGlzdGVuZXIobGlzdGVuZXJzW2tleV0sIGxpc3RlbmVyKSA9PT0gLTEpIHtcbiAgICAgICAgICAgICAgICBsaXN0ZW5lcnNba2V5XS5wdXNoKGxpc3RlbmVySXNXcmFwcGVkID8gbGlzdGVuZXIgOiB7XG4gICAgICAgICAgICAgICAgICAgIGxpc3RlbmVyOiBsaXN0ZW5lcixcbiAgICAgICAgICAgICAgICAgICAgb25jZTogZmFsc2VcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBBbGlhcyBvZiBhZGRMaXN0ZW5lclxuICAgICAqL1xuICAgIHByb3RvLm9uID0gYWxpYXMoJ2FkZExpc3RlbmVyJyk7XG5cbiAgICAvKipcbiAgICAgKiBTZW1pLWFsaWFzIG9mIGFkZExpc3RlbmVyLiBJdCB3aWxsIGFkZCBhIGxpc3RlbmVyIHRoYXQgd2lsbCBiZVxuICAgICAqIGF1dG9tYXRpY2FsbHkgcmVtb3ZlZCBhZnRlciBpdHMgZmlyc3QgZXhlY3V0aW9uLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtTdHJpbmd8UmVnRXhwfSBldnQgTmFtZSBvZiB0aGUgZXZlbnQgdG8gYXR0YWNoIHRoZSBsaXN0ZW5lciB0by5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBsaXN0ZW5lciBNZXRob2QgdG8gYmUgY2FsbGVkIHdoZW4gdGhlIGV2ZW50IGlzIGVtaXR0ZWQuIElmIHRoZSBmdW5jdGlvbiByZXR1cm5zIHRydWUgdGhlbiBpdCB3aWxsIGJlIHJlbW92ZWQgYWZ0ZXIgY2FsbGluZy5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEN1cnJlbnQgaW5zdGFuY2Ugb2YgRXZlbnRFbWl0dGVyIGZvciBjaGFpbmluZy5cbiAgICAgKi9cbiAgICBwcm90by5hZGRPbmNlTGlzdGVuZXIgPSBmdW5jdGlvbiBhZGRPbmNlTGlzdGVuZXIoZXZ0LCBsaXN0ZW5lcikge1xuICAgICAgICByZXR1cm4gdGhpcy5hZGRMaXN0ZW5lcihldnQsIHtcbiAgICAgICAgICAgIGxpc3RlbmVyOiBsaXN0ZW5lcixcbiAgICAgICAgICAgIG9uY2U6IHRydWVcbiAgICAgICAgfSk7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEFsaWFzIG9mIGFkZE9uY2VMaXN0ZW5lci5cbiAgICAgKi9cbiAgICBwcm90by5vbmNlID0gYWxpYXMoJ2FkZE9uY2VMaXN0ZW5lcicpO1xuXG4gICAgLyoqXG4gICAgICogRGVmaW5lcyBhbiBldmVudCBuYW1lLiBUaGlzIGlzIHJlcXVpcmVkIGlmIHlvdSB3YW50IHRvIHVzZSBhIHJlZ2V4IHRvIGFkZCBhIGxpc3RlbmVyIHRvIG11bHRpcGxlIGV2ZW50cyBhdCBvbmNlLiBJZiB5b3UgZG9uJ3QgZG8gdGhpcyB0aGVuIGhvdyBkbyB5b3UgZXhwZWN0IGl0IHRvIGtub3cgd2hhdCBldmVudCB0byBhZGQgdG8/IFNob3VsZCBpdCBqdXN0IGFkZCB0byBldmVyeSBwb3NzaWJsZSBtYXRjaCBmb3IgYSByZWdleD8gTm8uIFRoYXQgaXMgc2NhcnkgYW5kIGJhZC5cbiAgICAgKiBZb3UgbmVlZCB0byB0ZWxsIGl0IHdoYXQgZXZlbnQgbmFtZXMgc2hvdWxkIGJlIG1hdGNoZWQgYnkgYSByZWdleC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfSBldnQgTmFtZSBvZiB0aGUgZXZlbnQgdG8gY3JlYXRlLlxuICAgICAqIEByZXR1cm4ge09iamVjdH0gQ3VycmVudCBpbnN0YW5jZSBvZiBFdmVudEVtaXR0ZXIgZm9yIGNoYWluaW5nLlxuICAgICAqL1xuICAgIHByb3RvLmRlZmluZUV2ZW50ID0gZnVuY3Rpb24gZGVmaW5lRXZlbnQoZXZ0KSB7XG4gICAgICAgIHRoaXMuZ2V0TGlzdGVuZXJzKGV2dCk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBVc2VzIGRlZmluZUV2ZW50IHRvIGRlZmluZSBtdWx0aXBsZSBldmVudHMuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1N0cmluZ1tdfSBldnRzIEFuIGFycmF5IG9mIGV2ZW50IG5hbWVzIHRvIGRlZmluZS5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEN1cnJlbnQgaW5zdGFuY2Ugb2YgRXZlbnRFbWl0dGVyIGZvciBjaGFpbmluZy5cbiAgICAgKi9cbiAgICBwcm90by5kZWZpbmVFdmVudHMgPSBmdW5jdGlvbiBkZWZpbmVFdmVudHMoZXZ0cykge1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGV2dHMubGVuZ3RoOyBpICs9IDEpIHtcbiAgICAgICAgICAgIHRoaXMuZGVmaW5lRXZlbnQoZXZ0c1tpXSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIFJlbW92ZXMgYSBsaXN0ZW5lciBmdW5jdGlvbiBmcm9tIHRoZSBzcGVjaWZpZWQgZXZlbnQuXG4gICAgICogV2hlbiBwYXNzZWQgYSByZWd1bGFyIGV4cHJlc3Npb24gYXMgdGhlIGV2ZW50IG5hbWUsIGl0IHdpbGwgcmVtb3ZlIHRoZSBsaXN0ZW5lciBmcm9tIGFsbCBldmVudHMgdGhhdCBtYXRjaCBpdC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfFJlZ0V4cH0gZXZ0IE5hbWUgb2YgdGhlIGV2ZW50IHRvIHJlbW92ZSB0aGUgbGlzdGVuZXIgZnJvbS5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBsaXN0ZW5lciBNZXRob2QgdG8gcmVtb3ZlIGZyb20gdGhlIGV2ZW50LlxuICAgICAqIEByZXR1cm4ge09iamVjdH0gQ3VycmVudCBpbnN0YW5jZSBvZiBFdmVudEVtaXR0ZXIgZm9yIGNoYWluaW5nLlxuICAgICAqL1xuICAgIHByb3RvLnJlbW92ZUxpc3RlbmVyID0gZnVuY3Rpb24gcmVtb3ZlTGlzdGVuZXIoZXZ0LCBsaXN0ZW5lcikge1xuICAgICAgICB2YXIgbGlzdGVuZXJzID0gdGhpcy5nZXRMaXN0ZW5lcnNBc09iamVjdChldnQpO1xuICAgICAgICB2YXIgaW5kZXg7XG4gICAgICAgIHZhciBrZXk7XG5cbiAgICAgICAgZm9yIChrZXkgaW4gbGlzdGVuZXJzKSB7XG4gICAgICAgICAgICBpZiAobGlzdGVuZXJzLmhhc093blByb3BlcnR5KGtleSkpIHtcbiAgICAgICAgICAgICAgICBpbmRleCA9IGluZGV4T2ZMaXN0ZW5lcihsaXN0ZW5lcnNba2V5XSwgbGlzdGVuZXIpO1xuXG4gICAgICAgICAgICAgICAgaWYgKGluZGV4ICE9PSAtMSkge1xuICAgICAgICAgICAgICAgICAgICBsaXN0ZW5lcnNba2V5XS5zcGxpY2UoaW5kZXgsIDEpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBBbGlhcyBvZiByZW1vdmVMaXN0ZW5lclxuICAgICAqL1xuICAgIHByb3RvLm9mZiA9IGFsaWFzKCdyZW1vdmVMaXN0ZW5lcicpO1xuXG4gICAgLyoqXG4gICAgICogQWRkcyBsaXN0ZW5lcnMgaW4gYnVsayB1c2luZyB0aGUgbWFuaXB1bGF0ZUxpc3RlbmVycyBtZXRob2QuXG4gICAgICogSWYgeW91IHBhc3MgYW4gb2JqZWN0IGFzIHRoZSBmaXJzdCBhcmd1bWVudCB5b3UgY2FuIGFkZCB0byBtdWx0aXBsZSBldmVudHMgYXQgb25jZS4gVGhlIG9iamVjdCBzaG91bGQgY29udGFpbiBrZXkgdmFsdWUgcGFpcnMgb2YgZXZlbnRzIGFuZCBsaXN0ZW5lcnMgb3IgbGlzdGVuZXIgYXJyYXlzLiBZb3UgY2FuIGFsc28gcGFzcyBpdCBhbiBldmVudCBuYW1lIGFuZCBhbiBhcnJheSBvZiBsaXN0ZW5lcnMgdG8gYmUgYWRkZWQuXG4gICAgICogWW91IGNhbiBhbHNvIHBhc3MgaXQgYSByZWd1bGFyIGV4cHJlc3Npb24gdG8gYWRkIHRoZSBhcnJheSBvZiBsaXN0ZW5lcnMgdG8gYWxsIGV2ZW50cyB0aGF0IG1hdGNoIGl0LlxuICAgICAqIFllYWgsIHRoaXMgZnVuY3Rpb24gZG9lcyBxdWl0ZSBhIGJpdC4gVGhhdCdzIHByb2JhYmx5IGEgYmFkIHRoaW5nLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtTdHJpbmd8T2JqZWN0fFJlZ0V4cH0gZXZ0IEFuIGV2ZW50IG5hbWUgaWYgeW91IHdpbGwgcGFzcyBhbiBhcnJheSBvZiBsaXN0ZW5lcnMgbmV4dC4gQW4gb2JqZWN0IGlmIHlvdSB3aXNoIHRvIGFkZCB0byBtdWx0aXBsZSBldmVudHMgYXQgb25jZS5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9uW119IFtsaXN0ZW5lcnNdIEFuIG9wdGlvbmFsIGFycmF5IG9mIGxpc3RlbmVyIGZ1bmN0aW9ucyB0byBhZGQuXG4gICAgICogQHJldHVybiB7T2JqZWN0fSBDdXJyZW50IGluc3RhbmNlIG9mIEV2ZW50RW1pdHRlciBmb3IgY2hhaW5pbmcuXG4gICAgICovXG4gICAgcHJvdG8uYWRkTGlzdGVuZXJzID0gZnVuY3Rpb24gYWRkTGlzdGVuZXJzKGV2dCwgbGlzdGVuZXJzKSB7XG4gICAgICAgIC8vIFBhc3MgdGhyb3VnaCB0byBtYW5pcHVsYXRlTGlzdGVuZXJzXG4gICAgICAgIHJldHVybiB0aGlzLm1hbmlwdWxhdGVMaXN0ZW5lcnMoZmFsc2UsIGV2dCwgbGlzdGVuZXJzKTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlcyBsaXN0ZW5lcnMgaW4gYnVsayB1c2luZyB0aGUgbWFuaXB1bGF0ZUxpc3RlbmVycyBtZXRob2QuXG4gICAgICogSWYgeW91IHBhc3MgYW4gb2JqZWN0IGFzIHRoZSBmaXJzdCBhcmd1bWVudCB5b3UgY2FuIHJlbW92ZSBmcm9tIG11bHRpcGxlIGV2ZW50cyBhdCBvbmNlLiBUaGUgb2JqZWN0IHNob3VsZCBjb250YWluIGtleSB2YWx1ZSBwYWlycyBvZiBldmVudHMgYW5kIGxpc3RlbmVycyBvciBsaXN0ZW5lciBhcnJheXMuXG4gICAgICogWW91IGNhbiBhbHNvIHBhc3MgaXQgYW4gZXZlbnQgbmFtZSBhbmQgYW4gYXJyYXkgb2YgbGlzdGVuZXJzIHRvIGJlIHJlbW92ZWQuXG4gICAgICogWW91IGNhbiBhbHNvIHBhc3MgaXQgYSByZWd1bGFyIGV4cHJlc3Npb24gdG8gcmVtb3ZlIHRoZSBsaXN0ZW5lcnMgZnJvbSBhbGwgZXZlbnRzIHRoYXQgbWF0Y2ggaXQuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1N0cmluZ3xPYmplY3R8UmVnRXhwfSBldnQgQW4gZXZlbnQgbmFtZSBpZiB5b3Ugd2lsbCBwYXNzIGFuIGFycmF5IG9mIGxpc3RlbmVycyBuZXh0LiBBbiBvYmplY3QgaWYgeW91IHdpc2ggdG8gcmVtb3ZlIGZyb20gbXVsdGlwbGUgZXZlbnRzIGF0IG9uY2UuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbltdfSBbbGlzdGVuZXJzXSBBbiBvcHRpb25hbCBhcnJheSBvZiBsaXN0ZW5lciBmdW5jdGlvbnMgdG8gcmVtb3ZlLlxuICAgICAqIEByZXR1cm4ge09iamVjdH0gQ3VycmVudCBpbnN0YW5jZSBvZiBFdmVudEVtaXR0ZXIgZm9yIGNoYWluaW5nLlxuICAgICAqL1xuICAgIHByb3RvLnJlbW92ZUxpc3RlbmVycyA9IGZ1bmN0aW9uIHJlbW92ZUxpc3RlbmVycyhldnQsIGxpc3RlbmVycykge1xuICAgICAgICAvLyBQYXNzIHRocm91Z2ggdG8gbWFuaXB1bGF0ZUxpc3RlbmVyc1xuICAgICAgICByZXR1cm4gdGhpcy5tYW5pcHVsYXRlTGlzdGVuZXJzKHRydWUsIGV2dCwgbGlzdGVuZXJzKTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogRWRpdHMgbGlzdGVuZXJzIGluIGJ1bGsuIFRoZSBhZGRMaXN0ZW5lcnMgYW5kIHJlbW92ZUxpc3RlbmVycyBtZXRob2RzIGJvdGggdXNlIHRoaXMgdG8gZG8gdGhlaXIgam9iLiBZb3Ugc2hvdWxkIHJlYWxseSB1c2UgdGhvc2UgaW5zdGVhZCwgdGhpcyBpcyBhIGxpdHRsZSBsb3dlciBsZXZlbC5cbiAgICAgKiBUaGUgZmlyc3QgYXJndW1lbnQgd2lsbCBkZXRlcm1pbmUgaWYgdGhlIGxpc3RlbmVycyBhcmUgcmVtb3ZlZCAodHJ1ZSkgb3IgYWRkZWQgKGZhbHNlKS5cbiAgICAgKiBJZiB5b3UgcGFzcyBhbiBvYmplY3QgYXMgdGhlIHNlY29uZCBhcmd1bWVudCB5b3UgY2FuIGFkZC9yZW1vdmUgZnJvbSBtdWx0aXBsZSBldmVudHMgYXQgb25jZS4gVGhlIG9iamVjdCBzaG91bGQgY29udGFpbiBrZXkgdmFsdWUgcGFpcnMgb2YgZXZlbnRzIGFuZCBsaXN0ZW5lcnMgb3IgbGlzdGVuZXIgYXJyYXlzLlxuICAgICAqIFlvdSBjYW4gYWxzbyBwYXNzIGl0IGFuIGV2ZW50IG5hbWUgYW5kIGFuIGFycmF5IG9mIGxpc3RlbmVycyB0byBiZSBhZGRlZC9yZW1vdmVkLlxuICAgICAqIFlvdSBjYW4gYWxzbyBwYXNzIGl0IGEgcmVndWxhciBleHByZXNzaW9uIHRvIG1hbmlwdWxhdGUgdGhlIGxpc3RlbmVycyBvZiBhbGwgZXZlbnRzIHRoYXQgbWF0Y2ggaXQuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0Jvb2xlYW59IHJlbW92ZSBUcnVlIGlmIHlvdSB3YW50IHRvIHJlbW92ZSBsaXN0ZW5lcnMsIGZhbHNlIGlmIHlvdSB3YW50IHRvIGFkZC5cbiAgICAgKiBAcGFyYW0ge1N0cmluZ3xPYmplY3R8UmVnRXhwfSBldnQgQW4gZXZlbnQgbmFtZSBpZiB5b3Ugd2lsbCBwYXNzIGFuIGFycmF5IG9mIGxpc3RlbmVycyBuZXh0LiBBbiBvYmplY3QgaWYgeW91IHdpc2ggdG8gYWRkL3JlbW92ZSBmcm9tIG11bHRpcGxlIGV2ZW50cyBhdCBvbmNlLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb25bXX0gW2xpc3RlbmVyc10gQW4gb3B0aW9uYWwgYXJyYXkgb2YgbGlzdGVuZXIgZnVuY3Rpb25zIHRvIGFkZC9yZW1vdmUuXG4gICAgICogQHJldHVybiB7T2JqZWN0fSBDdXJyZW50IGluc3RhbmNlIG9mIEV2ZW50RW1pdHRlciBmb3IgY2hhaW5pbmcuXG4gICAgICovXG4gICAgcHJvdG8ubWFuaXB1bGF0ZUxpc3RlbmVycyA9IGZ1bmN0aW9uIG1hbmlwdWxhdGVMaXN0ZW5lcnMocmVtb3ZlLCBldnQsIGxpc3RlbmVycykge1xuICAgICAgICB2YXIgaTtcbiAgICAgICAgdmFyIHZhbHVlO1xuICAgICAgICB2YXIgc2luZ2xlID0gcmVtb3ZlID8gdGhpcy5yZW1vdmVMaXN0ZW5lciA6IHRoaXMuYWRkTGlzdGVuZXI7XG4gICAgICAgIHZhciBtdWx0aXBsZSA9IHJlbW92ZSA/IHRoaXMucmVtb3ZlTGlzdGVuZXJzIDogdGhpcy5hZGRMaXN0ZW5lcnM7XG5cbiAgICAgICAgLy8gSWYgZXZ0IGlzIGFuIG9iamVjdCB0aGVuIHBhc3MgZWFjaCBvZiBpdHMgcHJvcGVydGllcyB0byB0aGlzIG1ldGhvZFxuICAgICAgICBpZiAodHlwZW9mIGV2dCA9PT0gJ29iamVjdCcgJiYgIShldnQgaW5zdGFuY2VvZiBSZWdFeHApKSB7XG4gICAgICAgICAgICBmb3IgKGkgaW4gZXZ0KSB7XG4gICAgICAgICAgICAgICAgaWYgKGV2dC5oYXNPd25Qcm9wZXJ0eShpKSAmJiAodmFsdWUgPSBldnRbaV0pKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIFBhc3MgdGhlIHNpbmdsZSBsaXN0ZW5lciBzdHJhaWdodCB0aHJvdWdoIHRvIHRoZSBzaW5ndWxhciBtZXRob2RcbiAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgc2luZ2xlLmNhbGwodGhpcywgaSwgdmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gT3RoZXJ3aXNlIHBhc3MgYmFjayB0byB0aGUgbXVsdGlwbGUgZnVuY3Rpb25cbiAgICAgICAgICAgICAgICAgICAgICAgIG11bHRpcGxlLmNhbGwodGhpcywgaSwgdmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgLy8gU28gZXZ0IG11c3QgYmUgYSBzdHJpbmdcbiAgICAgICAgICAgIC8vIEFuZCBsaXN0ZW5lcnMgbXVzdCBiZSBhbiBhcnJheSBvZiBsaXN0ZW5lcnNcbiAgICAgICAgICAgIC8vIExvb3Agb3ZlciBpdCBhbmQgcGFzcyBlYWNoIG9uZSB0byB0aGUgbXVsdGlwbGUgbWV0aG9kXG4gICAgICAgICAgICBpID0gbGlzdGVuZXJzLmxlbmd0aDtcbiAgICAgICAgICAgIHdoaWxlIChpLS0pIHtcbiAgICAgICAgICAgICAgICBzaW5nbGUuY2FsbCh0aGlzLCBldnQsIGxpc3RlbmVyc1tpXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlcyBhbGwgbGlzdGVuZXJzIGZyb20gYSBzcGVjaWZpZWQgZXZlbnQuXG4gICAgICogSWYgeW91IGRvIG5vdCBzcGVjaWZ5IGFuIGV2ZW50IHRoZW4gYWxsIGxpc3RlbmVycyB3aWxsIGJlIHJlbW92ZWQuXG4gICAgICogVGhhdCBtZWFucyBldmVyeSBldmVudCB3aWxsIGJlIGVtcHRpZWQuXG4gICAgICogWW91IGNhbiBhbHNvIHBhc3MgYSByZWdleCB0byByZW1vdmUgYWxsIGV2ZW50cyB0aGF0IG1hdGNoIGl0LlxuICAgICAqXG4gICAgICogQHBhcmFtIHtTdHJpbmd8UmVnRXhwfSBbZXZ0XSBPcHRpb25hbCBuYW1lIG9mIHRoZSBldmVudCB0byByZW1vdmUgYWxsIGxpc3RlbmVycyBmb3IuIFdpbGwgcmVtb3ZlIGZyb20gZXZlcnkgZXZlbnQgaWYgbm90IHBhc3NlZC5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEN1cnJlbnQgaW5zdGFuY2Ugb2YgRXZlbnRFbWl0dGVyIGZvciBjaGFpbmluZy5cbiAgICAgKi9cbiAgICBwcm90by5yZW1vdmVFdmVudCA9IGZ1bmN0aW9uIHJlbW92ZUV2ZW50KGV2dCkge1xuICAgICAgICB2YXIgdHlwZSA9IHR5cGVvZiBldnQ7XG4gICAgICAgIHZhciBldmVudHMgPSB0aGlzLl9nZXRFdmVudHMoKTtcbiAgICAgICAgdmFyIGtleTtcblxuICAgICAgICAvLyBSZW1vdmUgZGlmZmVyZW50IHRoaW5ncyBkZXBlbmRpbmcgb24gdGhlIHN0YXRlIG9mIGV2dFxuICAgICAgICBpZiAodHlwZSA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgIC8vIFJlbW92ZSBhbGwgbGlzdGVuZXJzIGZvciB0aGUgc3BlY2lmaWVkIGV2ZW50XG4gICAgICAgICAgICBkZWxldGUgZXZlbnRzW2V2dF07XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAoZXZ0IGluc3RhbmNlb2YgUmVnRXhwKSB7XG4gICAgICAgICAgICAvLyBSZW1vdmUgYWxsIGV2ZW50cyBtYXRjaGluZyB0aGUgcmVnZXguXG4gICAgICAgICAgICBmb3IgKGtleSBpbiBldmVudHMpIHtcbiAgICAgICAgICAgICAgICBpZiAoZXZlbnRzLmhhc093blByb3BlcnR5KGtleSkgJiYgZXZ0LnRlc3Qoa2V5KSkge1xuICAgICAgICAgICAgICAgICAgICBkZWxldGUgZXZlbnRzW2tleV07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgLy8gUmVtb3ZlIGFsbCBsaXN0ZW5lcnMgaW4gYWxsIGV2ZW50c1xuICAgICAgICAgICAgZGVsZXRlIHRoaXMuX2V2ZW50cztcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBBbGlhcyBvZiByZW1vdmVFdmVudC5cbiAgICAgKlxuICAgICAqIEFkZGVkIHRvIG1pcnJvciB0aGUgbm9kZSBBUEkuXG4gICAgICovXG4gICAgcHJvdG8ucmVtb3ZlQWxsTGlzdGVuZXJzID0gYWxpYXMoJ3JlbW92ZUV2ZW50Jyk7XG5cbiAgICAvKipcbiAgICAgKiBFbWl0cyBhbiBldmVudCBvZiB5b3VyIGNob2ljZS5cbiAgICAgKiBXaGVuIGVtaXR0ZWQsIGV2ZXJ5IGxpc3RlbmVyIGF0dGFjaGVkIHRvIHRoYXQgZXZlbnQgd2lsbCBiZSBleGVjdXRlZC5cbiAgICAgKiBJZiB5b3UgcGFzcyB0aGUgb3B0aW9uYWwgYXJndW1lbnQgYXJyYXkgdGhlbiB0aG9zZSBhcmd1bWVudHMgd2lsbCBiZSBwYXNzZWQgdG8gZXZlcnkgbGlzdGVuZXIgdXBvbiBleGVjdXRpb24uXG4gICAgICogQmVjYXVzZSBpdCB1c2VzIGBhcHBseWAsIHlvdXIgYXJyYXkgb2YgYXJndW1lbnRzIHdpbGwgYmUgcGFzc2VkIGFzIGlmIHlvdSB3cm90ZSB0aGVtIG91dCBzZXBhcmF0ZWx5LlxuICAgICAqIFNvIHRoZXkgd2lsbCBub3QgYXJyaXZlIHdpdGhpbiB0aGUgYXJyYXkgb24gdGhlIG90aGVyIHNpZGUsIHRoZXkgd2lsbCBiZSBzZXBhcmF0ZS5cbiAgICAgKiBZb3UgY2FuIGFsc28gcGFzcyBhIHJlZ3VsYXIgZXhwcmVzc2lvbiB0byBlbWl0IHRvIGFsbCBldmVudHMgdGhhdCBtYXRjaCBpdC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfFJlZ0V4cH0gZXZ0IE5hbWUgb2YgdGhlIGV2ZW50IHRvIGVtaXQgYW5kIGV4ZWN1dGUgbGlzdGVuZXJzIGZvci5cbiAgICAgKiBAcGFyYW0ge0FycmF5fSBbYXJnc10gT3B0aW9uYWwgYXJyYXkgb2YgYXJndW1lbnRzIHRvIGJlIHBhc3NlZCB0byBlYWNoIGxpc3RlbmVyLlxuICAgICAqIEByZXR1cm4ge09iamVjdH0gQ3VycmVudCBpbnN0YW5jZSBvZiBFdmVudEVtaXR0ZXIgZm9yIGNoYWluaW5nLlxuICAgICAqL1xuICAgIHByb3RvLmVtaXRFdmVudCA9IGZ1bmN0aW9uIGVtaXRFdmVudChldnQsIGFyZ3MpIHtcbiAgICAgICAgdmFyIGxpc3RlbmVyc01hcCA9IHRoaXMuZ2V0TGlzdGVuZXJzQXNPYmplY3QoZXZ0KTtcbiAgICAgICAgdmFyIGxpc3RlbmVycztcbiAgICAgICAgdmFyIGxpc3RlbmVyO1xuICAgICAgICB2YXIgaTtcbiAgICAgICAgdmFyIGtleTtcbiAgICAgICAgdmFyIHJlc3BvbnNlO1xuXG4gICAgICAgIGZvciAoa2V5IGluIGxpc3RlbmVyc01hcCkge1xuICAgICAgICAgICAgaWYgKGxpc3RlbmVyc01hcC5oYXNPd25Qcm9wZXJ0eShrZXkpKSB7XG4gICAgICAgICAgICAgICAgbGlzdGVuZXJzID0gbGlzdGVuZXJzTWFwW2tleV0uc2xpY2UoMCk7XG5cbiAgICAgICAgICAgICAgICBmb3IgKGkgPSAwOyBpIDwgbGlzdGVuZXJzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIElmIHRoZSBsaXN0ZW5lciByZXR1cm5zIHRydWUgdGhlbiBpdCBzaGFsbCBiZSByZW1vdmVkIGZyb20gdGhlIGV2ZW50XG4gICAgICAgICAgICAgICAgICAgIC8vIFRoZSBmdW5jdGlvbiBpcyBleGVjdXRlZCBlaXRoZXIgd2l0aCBhIGJhc2ljIGNhbGwgb3IgYW4gYXBwbHkgaWYgdGhlcmUgaXMgYW4gYXJncyBhcnJheVxuICAgICAgICAgICAgICAgICAgICBsaXN0ZW5lciA9IGxpc3RlbmVyc1tpXTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAobGlzdGVuZXIub25jZSA9PT0gdHJ1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5yZW1vdmVMaXN0ZW5lcihldnQsIGxpc3RlbmVyLmxpc3RlbmVyKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHJlc3BvbnNlID0gbGlzdGVuZXIubGlzdGVuZXIuYXBwbHkodGhpcywgYXJncyB8fCBbXSk7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKHJlc3BvbnNlID09PSB0aGlzLl9nZXRPbmNlUmV0dXJuVmFsdWUoKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5yZW1vdmVMaXN0ZW5lcihldnQsIGxpc3RlbmVyLmxpc3RlbmVyKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBBbGlhcyBvZiBlbWl0RXZlbnRcbiAgICAgKi9cbiAgICBwcm90by50cmlnZ2VyID0gYWxpYXMoJ2VtaXRFdmVudCcpO1xuXG4gICAgLyoqXG4gICAgICogU3VidGx5IGRpZmZlcmVudCBmcm9tIGVtaXRFdmVudCBpbiB0aGF0IGl0IHdpbGwgcGFzcyBpdHMgYXJndW1lbnRzIG9uIHRvIHRoZSBsaXN0ZW5lcnMsIGFzIG9wcG9zZWQgdG8gdGFraW5nIGEgc2luZ2xlIGFycmF5IG9mIGFyZ3VtZW50cyB0byBwYXNzIG9uLlxuICAgICAqIEFzIHdpdGggZW1pdEV2ZW50LCB5b3UgY2FuIHBhc3MgYSByZWdleCBpbiBwbGFjZSBvZiB0aGUgZXZlbnQgbmFtZSB0byBlbWl0IHRvIGFsbCBldmVudHMgdGhhdCBtYXRjaCBpdC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfFJlZ0V4cH0gZXZ0IE5hbWUgb2YgdGhlIGV2ZW50IHRvIGVtaXQgYW5kIGV4ZWN1dGUgbGlzdGVuZXJzIGZvci5cbiAgICAgKiBAcGFyYW0gey4uLip9IE9wdGlvbmFsIGFkZGl0aW9uYWwgYXJndW1lbnRzIHRvIGJlIHBhc3NlZCB0byBlYWNoIGxpc3RlbmVyLlxuICAgICAqIEByZXR1cm4ge09iamVjdH0gQ3VycmVudCBpbnN0YW5jZSBvZiBFdmVudEVtaXR0ZXIgZm9yIGNoYWluaW5nLlxuICAgICAqL1xuICAgIHByb3RvLmVtaXQgPSBmdW5jdGlvbiBlbWl0KGV2dCkge1xuICAgICAgICB2YXIgYXJncyA9IEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3VtZW50cywgMSk7XG4gICAgICAgIHJldHVybiB0aGlzLmVtaXRFdmVudChldnQsIGFyZ3MpO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBTZXRzIHRoZSBjdXJyZW50IHZhbHVlIHRvIGNoZWNrIGFnYWluc3Qgd2hlbiBleGVjdXRpbmcgbGlzdGVuZXJzLiBJZiBhXG4gICAgICogbGlzdGVuZXJzIHJldHVybiB2YWx1ZSBtYXRjaGVzIHRoZSBvbmUgc2V0IGhlcmUgdGhlbiBpdCB3aWxsIGJlIHJlbW92ZWRcbiAgICAgKiBhZnRlciBleGVjdXRpb24uIFRoaXMgdmFsdWUgZGVmYXVsdHMgdG8gdHJ1ZS5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIG5ldyB2YWx1ZSB0byBjaGVjayBmb3Igd2hlbiBleGVjdXRpbmcgbGlzdGVuZXJzLlxuICAgICAqIEByZXR1cm4ge09iamVjdH0gQ3VycmVudCBpbnN0YW5jZSBvZiBFdmVudEVtaXR0ZXIgZm9yIGNoYWluaW5nLlxuICAgICAqL1xuICAgIHByb3RvLnNldE9uY2VSZXR1cm5WYWx1ZSA9IGZ1bmN0aW9uIHNldE9uY2VSZXR1cm5WYWx1ZSh2YWx1ZSkge1xuICAgICAgICB0aGlzLl9vbmNlUmV0dXJuVmFsdWUgPSB2YWx1ZTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEZldGNoZXMgdGhlIGN1cnJlbnQgdmFsdWUgdG8gY2hlY2sgYWdhaW5zdCB3aGVuIGV4ZWN1dGluZyBsaXN0ZW5lcnMuIElmXG4gICAgICogdGhlIGxpc3RlbmVycyByZXR1cm4gdmFsdWUgbWF0Y2hlcyB0aGlzIG9uZSB0aGVuIGl0IHNob3VsZCBiZSByZW1vdmVkXG4gICAgICogYXV0b21hdGljYWxseS4gSXQgd2lsbCByZXR1cm4gdHJ1ZSBieSBkZWZhdWx0LlxuICAgICAqXG4gICAgICogQHJldHVybiB7KnxCb29sZWFufSBUaGUgY3VycmVudCB2YWx1ZSB0byBjaGVjayBmb3Igb3IgdGhlIGRlZmF1bHQsIHRydWUuXG4gICAgICogQGFwaSBwcml2YXRlXG4gICAgICovXG4gICAgcHJvdG8uX2dldE9uY2VSZXR1cm5WYWx1ZSA9IGZ1bmN0aW9uIF9nZXRPbmNlUmV0dXJuVmFsdWUoKSB7XG4gICAgICAgIGlmICh0aGlzLmhhc093blByb3BlcnR5KCdfb25jZVJldHVyblZhbHVlJykpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLl9vbmNlUmV0dXJuVmFsdWU7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBGZXRjaGVzIHRoZSBldmVudHMgb2JqZWN0IGFuZCBjcmVhdGVzIG9uZSBpZiByZXF1aXJlZC5cbiAgICAgKlxuICAgICAqIEByZXR1cm4ge09iamVjdH0gVGhlIGV2ZW50cyBzdG9yYWdlIG9iamVjdC5cbiAgICAgKiBAYXBpIHByaXZhdGVcbiAgICAgKi9cbiAgICBwcm90by5fZ2V0RXZlbnRzID0gZnVuY3Rpb24gX2dldEV2ZW50cygpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2V2ZW50cyB8fCAodGhpcy5fZXZlbnRzID0ge30pO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBSZXZlcnRzIHRoZSBnbG9iYWwge0BsaW5rIEV2ZW50RW1pdHRlcn0gdG8gaXRzIHByZXZpb3VzIHZhbHVlIGFuZCByZXR1cm5zIGEgcmVmZXJlbmNlIHRvIHRoaXMgdmVyc2lvbi5cbiAgICAgKlxuICAgICAqIEByZXR1cm4ge0Z1bmN0aW9ufSBOb24gY29uZmxpY3RpbmcgRXZlbnRFbWl0dGVyIGNsYXNzLlxuICAgICAqL1xuICAgIEV2ZW50RW1pdHRlci5ub0NvbmZsaWN0ID0gZnVuY3Rpb24gbm9Db25mbGljdCgpIHtcbiAgICAgICAgZXhwb3J0cy5FdmVudEVtaXR0ZXIgPSBvcmlnaW5hbEdsb2JhbFZhbHVlO1xuICAgICAgICByZXR1cm4gRXZlbnRFbWl0dGVyO1xuICAgIH07XG5cbiAgICAvLyBFeHBvc2UgdGhlIGNsYXNzIGVpdGhlciB2aWEgQU1ELCBDb21tb25KUyBvciB0aGUgZ2xvYmFsIG9iamVjdFxuICAgIGlmICh0eXBlb2YgZGVmaW5lID09PSAnZnVuY3Rpb24nICYmIGRlZmluZS5hbWQpIHtcbiAgICAgICAgZGVmaW5lKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiBFdmVudEVtaXR0ZXI7XG4gICAgICAgIH0pO1xuICAgIH1cbiAgICBlbHNlIGlmICh0eXBlb2YgbW9kdWxlID09PSAnb2JqZWN0JyAmJiBtb2R1bGUuZXhwb3J0cyl7XG4gICAgICAgIG1vZHVsZS5leHBvcnRzID0gRXZlbnRFbWl0dGVyO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgZXhwb3J0cy5FdmVudEVtaXR0ZXIgPSBFdmVudEVtaXR0ZXI7XG4gICAgfVxufSh0eXBlb2Ygd2luZG93ICE9PSAndW5kZWZpbmVkJyA/IHdpbmRvdyA6IHRoaXMgfHwge30pKTtcbiIsImltcG9ydCB7IE9wZW5WaWR1IH0gZnJvbSAnLi9PcGVuVmlkdS9PcGVuVmlkdSc7XG5cbmlmICh3aW5kb3cpIHtcbiAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6bm8tc3RyaW5nLWxpdGVyYWxcbiAgICB3aW5kb3dbJ09wZW5WaWR1J10gPSBPcGVuVmlkdTtcbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IFNlc3Npb24gfSBmcm9tICcuL1Nlc3Npb24nO1xuaW1wb3J0IHsgU3RyZWFtIH0gZnJvbSAnLi9TdHJlYW0nO1xuaW1wb3J0IHsgQ29ubmVjdGlvbk9wdGlvbnMgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHJpdmF0ZS9Db25uZWN0aW9uT3B0aW9ucyc7XG5pbXBvcnQgeyBJbmJvdW5kU3RyZWFtT3B0aW9ucyB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvSW50ZXJmYWNlcy9Qcml2YXRlL0luYm91bmRTdHJlYW1PcHRpb25zJztcbmltcG9ydCB7IFN0cmVhbU9wdGlvbnNTZXJ2ZXIgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHJpdmF0ZS9TdHJlYW1PcHRpb25zU2VydmVyJztcblxuXG4vKipcbiAqIFJlcHJlc2VudHMgZWFjaCBvbmUgb2YgdGhlIHVzZXIncyBjb25uZWN0aW9uIHRvIHRoZSBzZXNzaW9uICh0aGUgbG9jYWwgb25lIGFuZCBvdGhlciB1c2VyJ3MgY29ubmVjdGlvbnMpLlxuICogVGhlcmVmb3JlIGVhY2ggW1tTZXNzaW9uXV0gYW5kIFtbU3RyZWFtXV0gb2JqZWN0IGhhcyBhbiBhdHRyaWJ1dGUgb2YgdHlwZSBDb25uZWN0aW9uXG4gKi9cbmV4cG9ydCBjbGFzcyBDb25uZWN0aW9uIHtcblxuICAgIC8qKlxuICAgICAqIFVuaXF1ZSBpZGVudGlmaWVyIG9mIHRoZSBjb25uZWN0aW9uXG4gICAgICovXG4gICAgY29ubmVjdGlvbklkOiBzdHJpbmc7XG5cbiAgICAvKipcbiAgICAgKiBUaW1lIHdoZW4gdGhpcyBjb25uZWN0aW9uIHdhcyBjcmVhdGVkIChVVEMgbWlsbGlzZWNvbmRzKVxuICAgICAqL1xuICAgIGNyZWF0aW9uVGltZTogbnVtYmVyO1xuXG4gICAgLyoqXG4gICAgICogRGF0YSBhc3NvY2lhdGVkIHRvIHRoaXMgY29ubmVjdGlvbiAoYW5kIHRoZXJlZm9yZSB0byBjZXJ0YWluIHVzZXIpLiBUaGlzIGlzIGFuIGltcG9ydGFudCBmaWVsZDpcbiAgICAgKiBpdCBhbGxvd3MgeW91IHRvIGJyb2FkY2FzdCBhbGwgdGhlIGluZm9ybWF0aW9uIHlvdSB3YW50IGZvciBlYWNoIHVzZXIgKGEgdXNlcm5hbWUsIGZvciBleGFtcGxlKVxuICAgICAqL1xuICAgIGRhdGE6IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBzdHJlYW06IFN0cmVhbTtcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvcHRpb25zOiBDb25uZWN0aW9uT3B0aW9ucyB8IHVuZGVmaW5lZDtcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBkaXNwb3NlZCA9IGZhbHNlO1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHByaXZhdGUgc2Vzc2lvbjogU2Vzc2lvbiwgb3B0cz86IENvbm5lY3Rpb25PcHRpb25zKSB7XG5cbiAgICAgICAgbGV0IG1zZyA9IFwiJ0Nvbm5lY3Rpb24nIGNyZWF0ZWQgXCI7XG4gICAgICAgIGlmICghIW9wdHMpIHtcbiAgICAgICAgICAgIG1zZyArPSBcIihyZW1vdGUpIHdpdGggJ2Nvbm5lY3Rpb25JZCcgW1wiICsgb3B0cy5pZCArICddJztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIG1zZyArPSAnKGxvY2FsKSc7XG4gICAgICAgIH1cbiAgICAgICAgY29uc29sZS5pbmZvKG1zZyk7XG5cbiAgICAgICAgdGhpcy5vcHRpb25zID0gb3B0cztcblxuICAgICAgICBpZiAoISFvcHRzKSB7XG4gICAgICAgICAgICAvLyBDb25uZWN0aW9uIGlzIHJlbW90ZVxuICAgICAgICAgICAgdGhpcy5jb25uZWN0aW9uSWQgPSBvcHRzLmlkO1xuICAgICAgICAgICAgaWYgKG9wdHMubWV0YWRhdGEpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmRhdGEgPSBvcHRzLm1ldGFkYXRhO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG9wdHMuc3RyZWFtcykge1xuICAgICAgICAgICAgICAgIHRoaXMuaW5pdFJlbW90ZVN0cmVhbXMob3B0cy5zdHJlYW1zKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuY3JlYXRpb25UaW1lID0gbmV3IERhdGUoKS5nZXRUaW1lKCk7XG4gICAgfVxuXG5cbiAgICAvKiBIaWRkZW4gbWV0aG9kcyAqL1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHNlbmRJY2VDYW5kaWRhdGUoY2FuZGlkYXRlOiBSVENJY2VDYW5kaWRhdGUpOiB2b2lkIHtcblxuICAgICAgICBjb25zb2xlLmRlYnVnKCghIXRoaXMuc3RyZWFtLm91dGJvdW5kU3RyZWFtT3B0cyA/ICdMb2NhbCcgOiAnUmVtb3RlJyksICdjYW5kaWRhdGUgZm9yJyxcbiAgICAgICAgICAgIHRoaXMuY29ubmVjdGlvbklkLCBKU09OLnN0cmluZ2lmeShjYW5kaWRhdGUpKTtcblxuICAgICAgICB0aGlzLnNlc3Npb24ub3BlbnZpZHUuc2VuZFJlcXVlc3QoJ29uSWNlQ2FuZGlkYXRlJywge1xuICAgICAgICAgICAgZW5kcG9pbnROYW1lOiB0aGlzLmNvbm5lY3Rpb25JZCxcbiAgICAgICAgICAgIGNhbmRpZGF0ZTogY2FuZGlkYXRlLmNhbmRpZGF0ZSxcbiAgICAgICAgICAgIHNkcE1pZDogY2FuZGlkYXRlLnNkcE1pZCxcbiAgICAgICAgICAgIHNkcE1MaW5lSW5kZXg6IGNhbmRpZGF0ZS5zZHBNTGluZUluZGV4XG4gICAgICAgIH0sIChlcnJvciwgcmVzcG9uc2UpID0+IHtcbiAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ0Vycm9yIHNlbmRpbmcgSUNFIGNhbmRpZGF0ZTogJ1xuICAgICAgICAgICAgICAgICAgICArIEpTT04uc3RyaW5naWZ5KGVycm9yKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBpbml0UmVtb3RlU3RyZWFtcyhvcHRpb25zOiBTdHJlYW1PcHRpb25zU2VydmVyW10pOiB2b2lkIHtcblxuICAgICAgICAvLyBUaGlzIGlzIHJlYWR5IGZvciBzdXBwb3J0aW5nIG11bHRpcGxlIHN0cmVhbXMgcGVyIENvbm5lY3Rpb24gb2JqZWN0LiBSaWdodCBub3cgdGhlIGxvb3Agd2lsbCBhbHdheXMgcnVuIGp1c3Qgb25jZVxuICAgICAgICAvLyB0aGlzLnN0cmVhbSBzaG91bGQgYWxzbyBiZSByZXBsYWNlZCBieSBhIGNvbGxlY3Rpb24gb2Ygc3RyZWFtcyB0byBzdXBwb3J0IG11bHRpcGxlIHN0cmVhbXMgcGVyIENvbm5lY3Rpb25cbiAgICAgICAgb3B0aW9ucy5mb3JFYWNoKG9wdHMgPT4ge1xuICAgICAgICAgICAgY29uc3Qgc3RyZWFtT3B0aW9uczogSW5ib3VuZFN0cmVhbU9wdGlvbnMgPSB7XG4gICAgICAgICAgICAgICAgaWQ6IG9wdHMuaWQsXG4gICAgICAgICAgICAgICAgY29ubmVjdGlvbjogdGhpcyxcbiAgICAgICAgICAgICAgICBoYXNBdWRpbzogb3B0cy5oYXNBdWRpbyxcbiAgICAgICAgICAgICAgICBoYXNWaWRlbzogb3B0cy5oYXNWaWRlbyxcbiAgICAgICAgICAgICAgICBhdWRpb0FjdGl2ZTogb3B0cy5hdWRpb0FjdGl2ZSxcbiAgICAgICAgICAgICAgICB2aWRlb0FjdGl2ZTogb3B0cy52aWRlb0FjdGl2ZSxcbiAgICAgICAgICAgICAgICB0eXBlT2ZWaWRlbzogb3B0cy50eXBlT2ZWaWRlbyxcbiAgICAgICAgICAgICAgICBmcmFtZVJhdGU6IG9wdHMuZnJhbWVSYXRlLFxuICAgICAgICAgICAgICAgIHZpZGVvRGltZW5zaW9uczogISFvcHRzLnZpZGVvRGltZW5zaW9ucyA/IEpTT04ucGFyc2Uob3B0cy52aWRlb0RpbWVuc2lvbnMpIDogdW5kZWZpbmVkXG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgY29uc3Qgc3RyZWFtID0gbmV3IFN0cmVhbSh0aGlzLnNlc3Npb24sIHN0cmVhbU9wdGlvbnMpO1xuXG4gICAgICAgICAgICB0aGlzLmFkZFN0cmVhbShzdHJlYW0pO1xuICAgICAgICB9KTtcblxuICAgICAgICBjb25zb2xlLmluZm8oXCJSZW1vdGUgJ0Nvbm5lY3Rpb24nIHdpdGggJ2Nvbm5lY3Rpb25JZCcgW1wiICsgdGhpcy5jb25uZWN0aW9uSWQgKyAnXSBpcyBub3cgY29uZmlndXJlZCBmb3IgcmVjZWl2aW5nIFN0cmVhbXMgd2l0aCBvcHRpb25zOiAnLCB0aGlzLnN0cmVhbS5pbmJvdW5kU3RyZWFtT3B0cyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGFkZFN0cmVhbShzdHJlYW06IFN0cmVhbSk6IHZvaWQge1xuICAgICAgICBzdHJlYW0uY29ubmVjdGlvbiA9IHRoaXM7XG4gICAgICAgIHRoaXMuc3RyZWFtID0gc3RyZWFtO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICByZW1vdmVTdHJlYW0oc3RyZWFtSWQ6IHN0cmluZyk6IHZvaWQge1xuICAgICAgICBkZWxldGUgdGhpcy5zdHJlYW07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGRpc3Bvc2UoKTogdm9pZCB7XG4gICAgICAgIGlmICghIXRoaXMuc3RyZWFtKSB7XG4gICAgICAgICAgICBkZWxldGUgdGhpcy5zdHJlYW07XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5kaXNwb3NlZCA9IHRydWU7XG4gICAgfVxuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBTdHJlYW0gfSBmcm9tICcuL1N0cmVhbSc7XG5pbXBvcnQgeyBMb2NhbFJlY29yZGVyU3RhdGUgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0VudW1zL0xvY2FsUmVjb3JkZXJTdGF0ZSc7XG5cbi8qKlxuICogQGhpZGRlblxuICovXG5kZWNsYXJlIHZhciBNZWRpYVJlY29yZGVyOiBhbnk7XG5cblxuLyoqXG4gKiBFYXN5IHJlY29yZGluZyBvZiBbW1N0cmVhbV1dIG9iamVjdHMgc3RyYWlnaHRhd2F5IGZyb20gdGhlIGJyb3dzZXIuIEluaXRpYWxpemVkIHdpdGggW1tPcGVuVmlkdS5pbml0TG9jYWxSZWNvcmRlcl1dIG1ldGhvZFxuICpcbiAqID4gV0FSTklORzogUGVyZm9ybWluZyBicm93c2VyIGxvY2FsIHJlY29yZGluZyBvZiAqKnJlbW90ZSBzdHJlYW1zKiogbWF5IGNhdXNlIHNvbWUgdHJvdWJsZXMuIEEgbG9uZyB3YWl0aW5nIHRpbWUgbWF5IGJlIHJlcXVpcmVkIGFmdGVyIGNhbGxpbmcgX0xvY2FsUmVjb3JkZXIuc3RvcCgpXyBpbiB0aGlzIGNhc2VcbiAqL1xuZXhwb3J0IGNsYXNzIExvY2FsUmVjb3JkZXIge1xuXG4gICAgc3RhdGU6IExvY2FsUmVjb3JkZXJTdGF0ZTtcblxuICAgIHByaXZhdGUgY29ubmVjdGlvbklkOiBzdHJpbmc7XG4gICAgcHJpdmF0ZSBtZWRpYVJlY29yZGVyOiBhbnk7XG4gICAgcHJpdmF0ZSBjaHVua3M6IGFueVtdID0gW107XG4gICAgcHJpdmF0ZSBibG9iOiBCbG9iO1xuICAgIHByaXZhdGUgY291bnQgPSAwO1xuICAgIHByaXZhdGUgaWQ6IHN0cmluZztcbiAgICBwcml2YXRlIHZpZGVvUHJldmlld1NyYzogc3RyaW5nO1xuICAgIHByaXZhdGUgaHRtbFBhcmVudEVsZW1lbnRJZDogc3RyaW5nO1xuICAgIHByaXZhdGUgdmlkZW9QcmV2aWV3OiBIVE1MVmlkZW9FbGVtZW50O1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHByaXZhdGUgc3RyZWFtOiBTdHJlYW0pIHtcbiAgICAgICAgdGhpcy5jb25uZWN0aW9uSWQgPSAoISF0aGlzLnN0cmVhbS5jb25uZWN0aW9uKSA/IHRoaXMuc3RyZWFtLmNvbm5lY3Rpb24uY29ubmVjdGlvbklkIDogJ2RlZmF1bHQtY29ubmVjdGlvbic7XG4gICAgICAgIHRoaXMuaWQgPSB0aGlzLnN0cmVhbS5zdHJlYW1JZCArICdfJyArIHRoaXMuY29ubmVjdGlvbklkICsgJ19sb2NhbHJlY29yZCc7XG4gICAgICAgIHRoaXMuc3RhdGUgPSBMb2NhbFJlY29yZGVyU3RhdGUuUkVBRFk7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBTdGFydHMgdGhlIHJlY29yZGluZyBvZiB0aGUgU3RyZWFtLiBbW3N0YXRlXV0gcHJvcGVydHkgbXVzdCBiZSBgUkVBRFlgLiBBZnRlciBtZXRob2Qgc3VjY2VlZHMgaXMgc2V0IHRvIGBSRUNPUkRJTkdgXG4gICAgICogQHJldHVybnMgQSBQcm9taXNlICh0byB3aGljaCB5b3UgY2FuIG9wdGlvbmFsbHkgc3Vic2NyaWJlIHRvKSB0aGF0IGlzIHJlc29sdmVkIGlmIHRoZSByZWNvcmRpbmcgc3VjY2Vzc2Z1bGx5IHN0YXJ0ZWQgYW5kIHJlamVjdGVkIHdpdGggYW4gRXJyb3Igb2JqZWN0IGlmIG5vdFxuICAgICAqL1xuICAgIHJlY29yZCgpOiBQcm9taXNlPGFueT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuXG4gICAgICAgICAgICB0cnkge1xuXG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBNZWRpYVJlY29yZGVyID09PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKCdNZWRpYVJlY29yZGVyIG5vdCBzdXBwb3J0ZWQgb24geW91ciBicm93c2VyLiBTZWUgY29tcGF0aWJpbGl0eSBpbiBodHRwczovL2Nhbml1c2UuY29tLyNzZWFyY2g9TWVkaWFSZWNvcmRlcicpO1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyAoRXJyb3IoJ01lZGlhUmVjb3JkZXIgbm90IHN1cHBvcnRlZCBvbiB5b3VyIGJyb3dzZXIuIFNlZSBjb21wYXRpYmlsaXR5IGluIGh0dHBzOi8vY2FuaXVzZS5jb20vI3NlYXJjaD1NZWRpYVJlY29yZGVyJykpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAodGhpcy5zdGF0ZSAhPT0gTG9jYWxSZWNvcmRlclN0YXRlLlJFQURZKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IChFcnJvcignXFwnTG9jYWxSZWNvcmQucmVjb3JkKClcXCcgbmVlZHMgXFwnTG9jYWxSZWNvcmQuc3RhdGVcXCcgdG8gYmUgXFwnUkVBRFlcXCcgKGN1cnJlbnQgdmFsdWU6IFxcJycgKyB0aGlzLnN0YXRlICsgJ1xcJykuIENhbGwgXFwnTG9jYWxSZWNvcmRlci5jbGVhbigpXFwnIG9yIGluaXQgYSBuZXcgTG9jYWxSZWNvcmRlciBiZWZvcmUnKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKFwiU3RhcnRpbmcgbG9jYWwgcmVjb3JkaW5nIG9mIHN0cmVhbSAnXCIgKyB0aGlzLnN0cmVhbS5zdHJlYW1JZCArIFwiJyBvZiBjb25uZWN0aW9uICdcIiArIHRoaXMuY29ubmVjdGlvbklkICsgXCInXCIpO1xuXG5cbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIE1lZGlhUmVjb3JkZXIuaXNUeXBlU3VwcG9ydGVkID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICAgICAgICAgIGxldCBvcHRpb25zO1xuICAgICAgICAgICAgICAgICAgICBpZiAoTWVkaWFSZWNvcmRlci5pc1R5cGVTdXBwb3J0ZWQoJ3ZpZGVvL3dlYm07Y29kZWNzPXZwOScpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBvcHRpb25zID0geyBtaW1lVHlwZTogJ3ZpZGVvL3dlYm07Y29kZWNzPXZwOScgfTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChNZWRpYVJlY29yZGVyLmlzVHlwZVN1cHBvcnRlZCgndmlkZW8vd2VibTtjb2RlY3M9aDI2NCcpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBvcHRpb25zID0geyBtaW1lVHlwZTogJ3ZpZGVvL3dlYm07Y29kZWNzPWgyNjQnIH07XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoTWVkaWFSZWNvcmRlci5pc1R5cGVTdXBwb3J0ZWQoJ3ZpZGVvL3dlYm07Y29kZWNzPXZwOCcpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBvcHRpb25zID0geyBtaW1lVHlwZTogJ3ZpZGVvL3dlYm07Y29kZWNzPXZwOCcgfTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmxvZygnVXNpbmcgbWltZVR5cGUgJyArIG9wdGlvbnMubWltZVR5cGUpO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLm1lZGlhUmVjb3JkZXIgPSBuZXcgTWVkaWFSZWNvcmRlcih0aGlzLnN0cmVhbS5nZXRNZWRpYVN0cmVhbSgpLCBvcHRpb25zKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLndhcm4oJ2lzVHlwZVN1cHBvcnRlZCBpcyBub3Qgc3VwcG9ydGVkLCB1c2luZyBkZWZhdWx0IGNvZGVjcyBmb3IgYnJvd3NlcicpO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLm1lZGlhUmVjb3JkZXIgPSBuZXcgTWVkaWFSZWNvcmRlcih0aGlzLnN0cmVhbS5nZXRNZWRpYVN0cmVhbSgpKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB0aGlzLm1lZGlhUmVjb3JkZXIuc3RhcnQoMTApO1xuXG4gICAgICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAgICAgICByZWplY3QoZXJyKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5tZWRpYVJlY29yZGVyLm9uZGF0YWF2YWlsYWJsZSA9IChlKSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5jaHVua3MucHVzaChlLmRhdGEpO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgdGhpcy5tZWRpYVJlY29yZGVyLm9uZXJyb3IgPSAoZSkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ01lZGlhUmVjb3JkZXIgZXJyb3I6ICcsIGUpO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgdGhpcy5tZWRpYVJlY29yZGVyLm9uc3RhcnQgPSAoKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5sb2coJ01lZGlhUmVjb3JkZXIgc3RhcnRlZCAoc3RhdGU9JyArIHRoaXMubWVkaWFSZWNvcmRlci5zdGF0ZSArICcpJyk7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICB0aGlzLm1lZGlhUmVjb3JkZXIub25zdG9wID0gKCkgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMub25TdG9wRGVmYXVsdCgpO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgdGhpcy5tZWRpYVJlY29yZGVyLm9ucGF1c2UgPSAoKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5sb2coJ01lZGlhUmVjb3JkZXIgcGF1c2VkIChzdGF0ZT0nICsgdGhpcy5tZWRpYVJlY29yZGVyLnN0YXRlICsgJyknKTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIHRoaXMubWVkaWFSZWNvcmRlci5vbnJlc3VtZSA9ICgpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmxvZygnTWVkaWFSZWNvcmRlciByZXN1bWVkIChzdGF0ZT0nICsgdGhpcy5tZWRpYVJlY29yZGVyLnN0YXRlICsgJyknKTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIHRoaXMubWVkaWFSZWNvcmRlci5vbndhcm5pbmcgPSAoZSkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKCdNZWRpYVJlY29yZGVyIHdhcm5pbmc6ICcgKyBlKTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIHRoaXMuc3RhdGUgPSBMb2NhbFJlY29yZGVyU3RhdGUuUkVDT1JESU5HO1xuICAgICAgICAgICAgcmVzb2x2ZSgpO1xuXG4gICAgICAgIH0pO1xuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogRW5kcyB0aGUgcmVjb3JkaW5nIG9mIHRoZSBTdHJlYW0uIFtbc3RhdGVdXSBwcm9wZXJ0eSBtdXN0IGJlIGBSRUNPUkRJTkdgIG9yIGBQQVVTRURgLiBBZnRlciBtZXRob2Qgc3VjY2VlZHMgaXMgc2V0IHRvIGBGSU5JU0hFRGBcbiAgICAgKiBAcmV0dXJucyBBIFByb21pc2UgKHRvIHdoaWNoIHlvdSBjYW4gb3B0aW9uYWxseSBzdWJzY3JpYmUgdG8pIHRoYXQgaXMgcmVzb2x2ZWQgaWYgdGhlIHJlY29yZGluZyBzdWNjZXNzZnVsbHkgc3RvcHBlZCBhbmQgcmVqZWN0ZWQgd2l0aCBhbiBFcnJvciBvYmplY3QgaWYgbm90XG4gICAgICovXG4gICAgc3RvcCgpOiBQcm9taXNlPGFueT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5zdGF0ZSA9PT0gTG9jYWxSZWNvcmRlclN0YXRlLlJFQURZIHx8IHRoaXMuc3RhdGUgPT09IExvY2FsUmVjb3JkZXJTdGF0ZS5GSU5JU0hFRCkge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyAoRXJyb3IoJ1xcJ0xvY2FsUmVjb3JkLnN0b3AoKVxcJyBuZWVkcyBcXCdMb2NhbFJlY29yZC5zdGF0ZVxcJyB0byBiZSBcXCdSRUNPUkRJTkdcXCcgb3IgXFwnUEFVU0VEXFwnIChjdXJyZW50IHZhbHVlOiBcXCcnICsgdGhpcy5zdGF0ZSArICdcXCcpLiBDYWxsIFxcJ0xvY2FsUmVjb3JkZXIuc3RhcnQoKVxcJyBiZWZvcmUnKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRoaXMubWVkaWFSZWNvcmRlci5vbnN0b3AgPSAoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMub25TdG9wRGVmYXVsdCgpO1xuICAgICAgICAgICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB0aGlzLm1lZGlhUmVjb3JkZXIuc3RvcCgpO1xuICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICAgIHJlamVjdChlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBQYXVzZXMgdGhlIHJlY29yZGluZyBvZiB0aGUgU3RyZWFtLiBbW3N0YXRlXV0gcHJvcGVydHkgbXVzdCBiZSBgUkVDT1JESU5HYC4gQWZ0ZXIgbWV0aG9kIHN1Y2NlZWRzIGlzIHNldCB0byBgUEFVU0VEYFxuICAgICAqIEByZXR1cm5zIEEgUHJvbWlzZSAodG8gd2hpY2ggeW91IGNhbiBvcHRpb25hbGx5IHN1YnNjcmliZSB0bykgdGhhdCBpcyByZXNvbHZlZCBpZiB0aGUgcmVjb3JkaW5nIHdhcyBzdWNjZXNzZnVsbHkgcGF1c2VkIGFuZCByZWplY3RlZCB3aXRoIGFuIEVycm9yIG9iamVjdCBpZiBub3RcbiAgICAgKi9cbiAgICBwYXVzZSgpOiBQcm9taXNlPGFueT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5zdGF0ZSAhPT0gTG9jYWxSZWNvcmRlclN0YXRlLlJFQ09SRElORykge1xuICAgICAgICAgICAgICAgICAgICByZWplY3QoRXJyb3IoJ1xcJ0xvY2FsUmVjb3JkLnBhdXNlKClcXCcgbmVlZHMgXFwnTG9jYWxSZWNvcmQuc3RhdGVcXCcgdG8gYmUgXFwnUkVDT1JESU5HXFwnIChjdXJyZW50IHZhbHVlOiBcXCcnICsgdGhpcy5zdGF0ZSArICdcXCcpLiBDYWxsIFxcJ0xvY2FsUmVjb3JkZXIuc3RhcnQoKVxcJyBvciBcXCdMb2NhbFJlY29yZGVyLnJlc3VtZSgpXFwnIGJlZm9yZScpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhpcy5tZWRpYVJlY29yZGVyLnBhdXNlKCk7XG4gICAgICAgICAgICAgICAgdGhpcy5zdGF0ZSA9IExvY2FsUmVjb3JkZXJTdGF0ZS5QQVVTRUQ7XG4gICAgICAgICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlc3VtZXMgdGhlIHJlY29yZGluZyBvZiB0aGUgU3RyZWFtLiBbW3N0YXRlXV0gcHJvcGVydHkgbXVzdCBiZSBgUEFVU0VEYC4gQWZ0ZXIgbWV0aG9kIHN1Y2NlZWRzIGlzIHNldCB0byBgUkVDT1JESU5HYFxuICAgICAqIEByZXR1cm5zIEEgUHJvbWlzZSAodG8gd2hpY2ggeW91IGNhbiBvcHRpb25hbGx5IHN1YnNjcmliZSB0bykgdGhhdCBpcyByZXNvbHZlZCBpZiB0aGUgcmVjb3JkaW5nIHdhcyBzdWNjZXNzZnVsbHkgcmVzdW1lZCBhbmQgcmVqZWN0ZWQgd2l0aCBhbiBFcnJvciBvYmplY3QgaWYgbm90XG4gICAgICovXG4gICAgcmVzdW1lKCk6IFByb21pc2U8YW55PiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLnN0YXRlICE9PSBMb2NhbFJlY29yZGVyU3RhdGUuUEFVU0VEKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IChFcnJvcignXFwnTG9jYWxSZWNvcmQucmVzdW1lKClcXCcgbmVlZHMgXFwnTG9jYWxSZWNvcmQuc3RhdGVcXCcgdG8gYmUgXFwnUEFVU0VEXFwnIChjdXJyZW50IHZhbHVlOiBcXCcnICsgdGhpcy5zdGF0ZSArICdcXCcpLiBDYWxsIFxcJ0xvY2FsUmVjb3JkZXIucGF1c2UoKVxcJyBiZWZvcmUnKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRoaXMubWVkaWFSZWNvcmRlci5yZXN1bWUoKTtcbiAgICAgICAgICAgICAgICB0aGlzLnN0YXRlID0gTG9jYWxSZWNvcmRlclN0YXRlLlJFQ09SRElORztcbiAgICAgICAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBQcmV2aWV3cyB0aGUgcmVjb3JkaW5nLCBhcHBlbmRpbmcgYSBuZXcgSFRNTFZpZGVvRWxlbWVudCB0byBlbGVtZW50IHdpdGggaWQgYHBhcmVudElkYC4gW1tzdGF0ZV1dIHByb3BlcnR5IG11c3QgYmUgYEZJTklTSEVEYFxuICAgICAqL1xuICAgIHByZXZpZXcocGFyZW50RWxlbWVudCk6IEhUTUxWaWRlb0VsZW1lbnQge1xuXG4gICAgICAgIGlmICh0aGlzLnN0YXRlICE9PSBMb2NhbFJlY29yZGVyU3RhdGUuRklOSVNIRUQpIHtcbiAgICAgICAgICAgIHRocm93IChFcnJvcignXFwnTG9jYWxSZWNvcmQucHJldmlldygpXFwnIG5lZWRzIFxcJ0xvY2FsUmVjb3JkLnN0YXRlXFwnIHRvIGJlIFxcJ0ZJTklTSEVEXFwnIChjdXJyZW50IHZhbHVlOiBcXCcnICsgdGhpcy5zdGF0ZSArICdcXCcpLiBDYWxsIFxcJ0xvY2FsUmVjb3JkZXIuc3RvcCgpXFwnIGJlZm9yZScpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMudmlkZW9QcmV2aWV3ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgndmlkZW8nKTtcblxuICAgICAgICB0aGlzLnZpZGVvUHJldmlldy5pZCA9IHRoaXMuaWQ7XG4gICAgICAgIHRoaXMudmlkZW9QcmV2aWV3LmF1dG9wbGF5ID0gdHJ1ZTtcblxuICAgICAgICBpZiAodHlwZW9mIHBhcmVudEVsZW1lbnQgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICB0aGlzLmh0bWxQYXJlbnRFbGVtZW50SWQgPSBwYXJlbnRFbGVtZW50O1xuXG4gICAgICAgICAgICBjb25zdCBwYXJlbnRFbGVtZW50RG9tID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQocGFyZW50RWxlbWVudCk7XG4gICAgICAgICAgICBpZiAocGFyZW50RWxlbWVudERvbSkge1xuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9QcmV2aWV3ID0gcGFyZW50RWxlbWVudERvbS5hcHBlbmRDaGlsZCh0aGlzLnZpZGVvUHJldmlldyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLmh0bWxQYXJlbnRFbGVtZW50SWQgPSBwYXJlbnRFbGVtZW50LmlkO1xuICAgICAgICAgICAgdGhpcy52aWRlb1ByZXZpZXcgPSBwYXJlbnRFbGVtZW50LmFwcGVuZENoaWxkKHRoaXMudmlkZW9QcmV2aWV3KTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMudmlkZW9QcmV2aWV3LnNyYyA9IHRoaXMudmlkZW9QcmV2aWV3U3JjO1xuXG4gICAgICAgIHJldHVybiB0aGlzLnZpZGVvUHJldmlldztcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIEdyYWNlZnVsbHkgc3RvcHMgYW5kIGNsZWFucyB0aGUgY3VycmVudCByZWNvcmRpbmcgKFdBUk5JTkc6IGl0IGlzIGNvbXBsZXRlbHkgZGlzbWlzc2VkKS4gU2V0cyBbW3N0YXRlXV0gdG8gYFJFQURZYCBzbyB0aGUgcmVjb3JkaW5nIGNhbiBzdGFydCBhZ2FpblxuICAgICAqL1xuICAgIGNsZWFuKCk6IHZvaWQge1xuICAgICAgICBjb25zdCBmID0gKCkgPT4ge1xuICAgICAgICAgICAgZGVsZXRlIHRoaXMuYmxvYjtcbiAgICAgICAgICAgIHRoaXMuY2h1bmtzID0gW107XG4gICAgICAgICAgICB0aGlzLmNvdW50ID0gMDtcbiAgICAgICAgICAgIGRlbGV0ZSB0aGlzLm1lZGlhUmVjb3JkZXI7XG4gICAgICAgICAgICB0aGlzLnN0YXRlID0gTG9jYWxSZWNvcmRlclN0YXRlLlJFQURZO1xuICAgICAgICB9O1xuICAgICAgICBpZiAodGhpcy5zdGF0ZSA9PT0gTG9jYWxSZWNvcmRlclN0YXRlLlJFQ09SRElORyB8fCB0aGlzLnN0YXRlID09PSBMb2NhbFJlY29yZGVyU3RhdGUuUEFVU0VEKSB7XG4gICAgICAgICAgICB0aGlzLnN0b3AoKS50aGVuKCgpID0+IGYoKSkuY2F0Y2goKCkgPT4gZigpKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGYoKTtcbiAgICAgICAgfVxuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogRG93bmxvYWRzIHRoZSByZWNvcmRlZCB2aWRlbyB0aHJvdWdoIHRoZSBicm93c2VyLiBbW3N0YXRlXV0gcHJvcGVydHkgbXVzdCBiZSBgRklOSVNIRURgXG4gICAgICovXG4gICAgZG93bmxvYWQoKTogdm9pZCB7XG4gICAgICAgIGlmICh0aGlzLnN0YXRlICE9PSBMb2NhbFJlY29yZGVyU3RhdGUuRklOSVNIRUQpIHtcbiAgICAgICAgICAgIHRocm93IChFcnJvcignXFwnTG9jYWxSZWNvcmQuZG93bmxvYWQoKVxcJyBuZWVkcyBcXCdMb2NhbFJlY29yZC5zdGF0ZVxcJyB0byBiZSBcXCdGSU5JU0hFRFxcJyAoY3VycmVudCB2YWx1ZTogXFwnJyArIHRoaXMuc3RhdGUgKyAnXFwnKS4gQ2FsbCBcXCdMb2NhbFJlY29yZGVyLnN0b3AoKVxcJyBiZWZvcmUnKSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjb25zdCBhOiBIVE1MQW5jaG9yRWxlbWVudCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2EnKTtcbiAgICAgICAgICAgIGEuc3R5bGUuZGlzcGxheSA9ICdub25lJztcbiAgICAgICAgICAgIGRvY3VtZW50LmJvZHkuYXBwZW5kQ2hpbGQoYSk7XG5cbiAgICAgICAgICAgIGNvbnN0IHVybCA9IHdpbmRvdy5VUkwuY3JlYXRlT2JqZWN0VVJMKHRoaXMuYmxvYik7XG4gICAgICAgICAgICBhLmhyZWYgPSB1cmw7XG4gICAgICAgICAgICBhLmRvd25sb2FkID0gdGhpcy5pZCArICcud2VibSc7XG4gICAgICAgICAgICBhLmNsaWNrKCk7XG4gICAgICAgICAgICB3aW5kb3cuVVJMLnJldm9rZU9iamVjdFVSTCh1cmwpO1xuXG4gICAgICAgICAgICBkb2N1bWVudC5ib2R5LnJlbW92ZUNoaWxkKGEpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0cyB0aGUgcmF3IEJsb2IgZmlsZS4gTWV0aG9kcyBwcmV2aWV3LCBkb3dubG9hZCwgdXBsb2FkQXNCaW5hcnkgYW5kIHVwbG9hZEFzTXVsdGlwYXJ0ZmlsZSB1c2UgdGhpcyBzYW1lIGZpbGUgdG8gcGVyZm9ybSB0aGVpciBzcGVjaWZpYyBhY3Rpb25zLiBbW3N0YXRlXV0gcHJvcGVydHkgbXVzdCBiZSBgRklOSVNIRURgXG4gICAgICovXG4gICAgZ2V0QmxvYigpOiBCbG9iIHtcbiAgICAgICAgaWYgKHRoaXMuc3RhdGUgIT09IExvY2FsUmVjb3JkZXJTdGF0ZS5GSU5JU0hFRCkge1xuICAgICAgICAgICAgdGhyb3cgKEVycm9yKCdDYWxsIFxcJ0xvY2FsUmVjb3JkLnN0b3AoKVxcJyBiZWZvcmUgZ2V0dGluZyBCbG9iIGZpbGUnKSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5ibG9iO1xuICAgICAgICB9XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBVcGxvYWRzIHRoZSByZWNvcmRlZCB2aWRlbyBhcyBhIGJpbmFyeSBmaWxlIHBlcmZvcm1pbmcgYW4gSFRUUC9QT1NUIG9wZXJhdGlvbiB0byBVUkwgYGVuZHBvaW50YC4gW1tzdGF0ZV1dIHByb3BlcnR5IG11c3QgYmUgYEZJTklTSEVEYC4gT3B0aW9uYWwgSFRUUCBoZWFkZXJzIGNhbiBiZSBwYXNzZWQgYXMgc2Vjb25kIHBhcmFtZXRlci4gRm9yIGV4YW1wbGU6XG4gICAgICogYGBgXG4gICAgICogdmFyIGhlYWRlcnMgPSB7XG4gICAgICogIFwiQ29va2llXCI6IFwiJFZlcnNpb249MTsgU2tpbj1uZXc7XCIsXG4gICAgICogIFwiQXV0aG9yaXphdGlvblwiOlwiQmFzaWMgUVd4aFpHcGJqcHVJSE5sY3RaUT09XCJcbiAgICAgKiB9XG4gICAgICogYGBgXG4gICAgICogQHJldHVybnMgQSBQcm9taXNlICh0byB3aGljaCB5b3UgY2FuIG9wdGlvbmFsbHkgc3Vic2NyaWJlIHRvKSB0aGF0IGlzIHJlc29sdmVkIHdpdGggdGhlIGBodHRwLnJlc3BvbnNlVGV4dGAgZnJvbSBzZXJ2ZXIgaWYgdGhlIG9wZXJhdGlvbiB3YXMgc3VjY2Vzc2Z1bCBhbmQgcmVqZWN0ZWQgd2l0aCB0aGUgZmFpbGVkIGBodHRwLnN0YXR1c2AgaWYgbm90XG4gICAgICovXG4gICAgdXBsb2FkQXNCaW5hcnkoZW5kcG9pbnQ6IHN0cmluZywgaGVhZGVycz86IGFueSk6IFByb21pc2U8YW55PiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICBpZiAodGhpcy5zdGF0ZSAhPT0gTG9jYWxSZWNvcmRlclN0YXRlLkZJTklTSEVEKSB7XG4gICAgICAgICAgICAgICAgcmVqZWN0KEVycm9yKCdcXCdMb2NhbFJlY29yZC51cGxvYWRBc0JpbmFyeSgpXFwnIG5lZWRzIFxcJ0xvY2FsUmVjb3JkLnN0YXRlXFwnIHRvIGJlIFxcJ0ZJTklTSEVEXFwnIChjdXJyZW50IHZhbHVlOiBcXCcnICsgdGhpcy5zdGF0ZSArICdcXCcpLiBDYWxsIFxcJ0xvY2FsUmVjb3JkZXIuc3RvcCgpXFwnIGJlZm9yZScpKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY29uc3QgaHR0cCA9IG5ldyBYTUxIdHRwUmVxdWVzdCgpO1xuICAgICAgICAgICAgICAgIGh0dHAub3BlbignUE9TVCcsIGVuZHBvaW50LCB0cnVlKTtcblxuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgaGVhZGVycyA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgICAgICAgICAgICAgZm9yIChjb25zdCBrZXkgb2YgT2JqZWN0LmtleXMoaGVhZGVycykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGh0dHAuc2V0UmVxdWVzdEhlYWRlcihrZXksIGhlYWRlcnNba2V5XSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBodHRwLm9ucmVhZHlzdGF0ZWNoYW5nZSA9ICgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGh0dHAucmVhZHlTdGF0ZSA9PT0gNCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGh0dHAuc3RhdHVzLnRvU3RyaW5nKCkuY2hhckF0KDApID09PSAnMicpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBTdWNjZXNzIHJlc3BvbnNlIGZyb20gc2VydmVyIChIVFRQIHN0YXR1cyBzdGFuZGFyZDogMlhYIGlzIHN1Y2Nlc3MpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZShodHRwLnJlc3BvbnNlVGV4dCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChodHRwLnN0YXR1cyk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIGh0dHAuc2VuZCh0aGlzLmJsb2IpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFVwbG9hZHMgdGhlIHJlY29yZGVkIHZpZGVvIGFzIGEgbXVsdGlwYXJ0IGZpbGUgcGVyZm9ybWluZyBhbiBIVFRQL1BPU1Qgb3BlcmF0aW9uIHRvIFVSTCBgZW5kcG9pbnRgLiBbW3N0YXRlXV0gcHJvcGVydHkgbXVzdCBiZSBgRklOSVNIRURgLiBPcHRpb25hbCBIVFRQIGhlYWRlcnMgY2FuIGJlIHBhc3NlZCBhcyBzZWNvbmQgcGFyYW1ldGVyLiBGb3IgZXhhbXBsZTpcbiAgICAgKiBgYGBcbiAgICAgKiB2YXIgaGVhZGVycyA9IHtcbiAgICAgKiAgXCJDb29raWVcIjogXCIkVmVyc2lvbj0xOyBTa2luPW5ldztcIixcbiAgICAgKiAgXCJBdXRob3JpemF0aW9uXCI6XCJCYXNpYyBRV3hoWkdwYmpwdUlITmxjdFpRPT1cIlxuICAgICAqIH1cbiAgICAgKiBgYGBcbiAgICAgKiBAcmV0dXJucyBBIFByb21pc2UgKHRvIHdoaWNoIHlvdSBjYW4gb3B0aW9uYWxseSBzdWJzY3JpYmUgdG8pIHRoYXQgaXMgcmVzb2x2ZWQgd2l0aCB0aGUgYGh0dHAucmVzcG9uc2VUZXh0YCBmcm9tIHNlcnZlciBpZiB0aGUgb3BlcmF0aW9uIHdhcyBzdWNjZXNzZnVsIGFuZCByZWplY3RlZCB3aXRoIHRoZSBmYWlsZWQgYGh0dHAuc3RhdHVzYCBpZiBub3Q6XG4gICAgICovXG4gICAgdXBsb2FkQXNNdWx0aXBhcnRmaWxlKGVuZHBvaW50OiBzdHJpbmcsIGhlYWRlcnM/OiBhbnkpOiBQcm9taXNlPGFueT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgaWYgKHRoaXMuc3RhdGUgIT09IExvY2FsUmVjb3JkZXJTdGF0ZS5GSU5JU0hFRCkge1xuICAgICAgICAgICAgICAgIHJlamVjdChFcnJvcignXFwnTG9jYWxSZWNvcmQudXBsb2FkQXNNdWx0aXBhcnRmaWxlKClcXCcgbmVlZHMgXFwnTG9jYWxSZWNvcmQuc3RhdGVcXCcgdG8gYmUgXFwnRklOSVNIRURcXCcgKGN1cnJlbnQgdmFsdWU6IFxcJycgKyB0aGlzLnN0YXRlICsgJ1xcJykuIENhbGwgXFwnTG9jYWxSZWNvcmRlci5zdG9wKClcXCcgYmVmb3JlJykpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBjb25zdCBodHRwID0gbmV3IFhNTEh0dHBSZXF1ZXN0KCk7XG4gICAgICAgICAgICAgICAgaHR0cC5vcGVuKCdQT1NUJywgZW5kcG9pbnQsIHRydWUpO1xuXG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBoZWFkZXJzID09PSAnb2JqZWN0Jykge1xuICAgICAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IGtleSBvZiBPYmplY3Qua2V5cyhoZWFkZXJzKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaHR0cC5zZXRSZXF1ZXN0SGVhZGVyKGtleSwgaGVhZGVyc1trZXldKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGNvbnN0IHNlbmRhYmxlID0gbmV3IEZvcm1EYXRhKCk7XG4gICAgICAgICAgICAgICAgc2VuZGFibGUuYXBwZW5kKCdmaWxlJywgdGhpcy5ibG9iLCB0aGlzLmlkICsgJy53ZWJtJyk7XG5cbiAgICAgICAgICAgICAgICBodHRwLm9ucmVhZHlzdGF0ZWNoYW5nZSA9ICgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGh0dHAucmVhZHlTdGF0ZSA9PT0gNCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGh0dHAuc3RhdHVzLnRvU3RyaW5nKCkuY2hhckF0KDApID09PSAnMicpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBTdWNjZXNzIHJlc3BvbnNlIGZyb20gc2VydmVyIChIVFRQIHN0YXR1cyBzdGFuZGFyZDogMlhYIGlzIHN1Y2Nlc3MpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZShodHRwLnJlc3BvbnNlVGV4dCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChodHRwLnN0YXR1cyk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICAgICAgaHR0cC5zZW5kKHNlbmRhYmxlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG5cbiAgICAvKiBQcml2YXRlIG1ldGhvZHMgKi9cblxuICAgIHByaXZhdGUgb25TdG9wRGVmYXVsdCgpOiB2b2lkIHtcbiAgICAgICAgY29uc29sZS5sb2coJ01lZGlhUmVjb3JkZXIgc3RvcHBlZCAgKHN0YXRlPScgKyB0aGlzLm1lZGlhUmVjb3JkZXIuc3RhdGUgKyAnKScpO1xuXG4gICAgICAgIHRoaXMuYmxvYiA9IG5ldyBCbG9iKHRoaXMuY2h1bmtzLCB7IHR5cGU6ICd2aWRlby93ZWJtJyB9KTtcbiAgICAgICAgdGhpcy5jaHVua3MgPSBbXTtcblxuICAgICAgICB0aGlzLnZpZGVvUHJldmlld1NyYyA9IHdpbmRvdy5VUkwuY3JlYXRlT2JqZWN0VVJMKHRoaXMuYmxvYik7XG5cbiAgICAgICAgdGhpcy5zdGF0ZSA9IExvY2FsUmVjb3JkZXJTdGF0ZS5GSU5JU0hFRDtcbiAgICB9XG5cbn1cbiIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTctMjAxOCBPcGVuVmlkdSAoaHR0cHM6Ly9vcGVudmlkdS5pby8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuaW1wb3J0IHsgTG9jYWxSZWNvcmRlciB9IGZyb20gJy4vTG9jYWxSZWNvcmRlcic7XG5pbXBvcnQgeyBQdWJsaXNoZXIgfSBmcm9tICcuL1B1Ymxpc2hlcic7XG5pbXBvcnQgeyBTZXNzaW9uIH0gZnJvbSAnLi9TZXNzaW9uJztcbmltcG9ydCB7IFN0cmVhbSB9IGZyb20gJy4vU3RyZWFtJztcbmltcG9ydCB7IFN0cmVhbVByb3BlcnR5Q2hhbmdlZEV2ZW50IH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvU3RyZWFtUHJvcGVydHlDaGFuZ2VkRXZlbnQnO1xuaW1wb3J0IHsgRGV2aWNlIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9JbnRlcmZhY2VzL1B1YmxpYy9EZXZpY2UnO1xuaW1wb3J0IHsgT3BlblZpZHVBZHZhbmNlZENvbmZpZ3VyYXRpb24gfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHVibGljL09wZW5WaWR1QWR2YW5jZWRDb25maWd1cmF0aW9uJztcbmltcG9ydCB7IFB1Ymxpc2hlclByb3BlcnRpZXMgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHVibGljL1B1Ymxpc2hlclByb3BlcnRpZXMnO1xuaW1wb3J0IHsgT3BlblZpZHVFcnJvciwgT3BlblZpZHVFcnJvck5hbWUgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0VudW1zL09wZW5WaWR1RXJyb3InO1xuaW1wb3J0IHsgVmlkZW9JbnNlcnRNb2RlIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FbnVtcy9WaWRlb0luc2VydE1vZGUnO1xuXG5pbXBvcnQgKiBhcyBzY3JlZW5TaGFyaW5nQXV0byBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL1NjcmVlblNoYXJpbmcvU2NyZWVuLUNhcHR1cmluZy1BdXRvJztcbmltcG9ydCAqIGFzIHNjcmVlblNoYXJpbmcgZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9TY3JlZW5TaGFyaW5nL1NjcmVlbi1DYXB0dXJpbmcnO1xuXG5pbXBvcnQgUnBjQnVpbGRlciA9IHJlcXVpcmUoJy4uL09wZW5WaWR1SW50ZXJuYWwvS3VyZW50b1V0aWxzL2t1cmVudG8tanNvbnJwYycpO1xuaW1wb3J0IHBsYXRmb3JtID0gcmVxdWlyZSgncGxhdGZvcm0nKTtcblxuXG4vKipcbiAqIEVudHJ5cG9pbnQgb2YgT3BlblZpZHUgQnJvd3NlciBsaWJyYXJ5LlxuICogVXNlIGl0IHRvIGluaXRpYWxpemUgb2JqZWN0cyBvZiB0eXBlIFtbU2Vzc2lvbl1dLCBbW1B1Ymxpc2hlcl1dIGFuZCBbW0xvY2FsUmVjb3JkZXJdXVxuICovXG5leHBvcnQgY2xhc3MgT3BlblZpZHUge1xuXG4gIHByaXZhdGUganNvblJwY0NsaWVudDogYW55O1xuXG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICBzZXNzaW9uOiBTZXNzaW9uO1xuICAvKipcbiAgICogQGhpZGRlblxuICAgKi9cbiAgcHVibGlzaGVyczogUHVibGlzaGVyW10gPSBbXTtcbiAgLyoqXG4gICAqIEBoaWRkZW5cbiAgICovXG4gIHdzVXJpOiBzdHJpbmc7XG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICBzZWNyZXQgPSAnJztcbiAgLyoqXG4gICAqIEBoaWRkZW5cbiAgICovXG4gIHJlY29yZGVyID0gZmFsc2U7XG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICBpY2VTZXJ2ZXJzOiBSVENJY2VTZXJ2ZXJbXTtcbiAgLyoqXG4gICAqIEBoaWRkZW5cbiAgICovXG4gIHJvbGU6IHN0cmluZztcbiAgLyoqXG4gICAqIEBoaWRkZW5cbiAgICovXG4gIGFkdmFuY2VkQ29uZmlndXJhdGlvbjogT3BlblZpZHVBZHZhbmNlZENvbmZpZ3VyYXRpb24gPSB7fTtcblxuICBjb25zdHJ1Y3RvcigpIHtcbiAgICBjb25zb2xlLmluZm8oXCInT3BlblZpZHUnIGluaXRpYWxpemVkXCIpO1xuXG4gICAgaWYgKHBsYXRmb3JtLm5hbWUhIS50b0xvd2VyQ2FzZSgpLmluZGV4T2YoJ21vYmlsZScpICE9PSAtMSkge1xuICAgICAgLy8gTGlzdGVuIHRvIG9yaWVudGF0aW9uY2hhbmdlIG9ubHkgb24gbW9iaWxlIGJyb3dzZXJzXG4gICAgICAoPGFueT53aW5kb3cpLm9ub3JpZW50YXRpb25jaGFuZ2UgPSAoKSA9PiB7XG4gICAgICAgIHRoaXMucHVibGlzaGVycy5mb3JFYWNoKHB1Ymxpc2hlciA9PiB7XG4gICAgICAgICAgaWYgKCEhcHVibGlzaGVyLnN0cmVhbSAmJiAhIXB1Ymxpc2hlci5zdHJlYW0uaGFzVmlkZW8gJiYgISFwdWJsaXNoZXIuc3RyZWFtLnN0cmVhbU1hbmFnZXIudmlkZW9zWzBdKSB7XG5cbiAgICAgICAgICAgIGxldCBhdHRlbXB0cyA9IDA7XG5cbiAgICAgICAgICAgIGNvbnN0IG9sZFdpZHRoID0gcHVibGlzaGVyLnN0cmVhbS52aWRlb0RpbWVuc2lvbnMud2lkdGg7XG4gICAgICAgICAgICBjb25zdCBvbGRIZWlnaHQgPSBwdWJsaXNoZXIuc3RyZWFtLnZpZGVvRGltZW5zaW9ucy5oZWlnaHQ7XG4gICAgICAgICAgICAvLyBOZXcgcmVzb2x1dGlvbiBnb3QgZnJvbSBkaWZmZXJlbnQgcGxhY2VzIGZvciBDaHJvbWUgYW5kIEZpcmVmb3guIENocm9tZSBuZWVkcyBhIHZpZGVvV2lkdGggYW5kIHZpZGVvSGVpZ2h0IG9mIGEgdmlkZW9FbGVtZW50LlxuICAgICAgICAgICAgLy8gRmlyZWZveCBuZWVkcyBnZXRTZXR0aW5ncyBmcm9tIHRoZSB2aWRlb1RyYWNrXG4gICAgICAgICAgICBsZXQgZmlyZWZveFNldHRpbmdzID0gcHVibGlzaGVyLnN0cmVhbS5nZXRNZWRpYVN0cmVhbSgpLmdldFZpZGVvVHJhY2tzKClbMF0uZ2V0U2V0dGluZ3MoKTtcbiAgICAgICAgICAgIGxldCBuZXdXaWR0aCA9IChwbGF0Zm9ybS5uYW1lISEudG9Mb3dlckNhc2UoKS5pbmRleE9mKCdmaXJlZm94JykgIT09IC0xKSA/IGZpcmVmb3hTZXR0aW5ncy53aWR0aCA6IHB1Ymxpc2hlci52aWRlb1JlZmVyZW5jZS52aWRlb1dpZHRoO1xuICAgICAgICAgICAgbGV0IG5ld0hlaWdodCA9IChwbGF0Zm9ybS5uYW1lISEudG9Mb3dlckNhc2UoKS5pbmRleE9mKCdmaXJlZm94JykgIT09IC0xKSA/IGZpcmVmb3hTZXR0aW5ncy5oZWlnaHQgOiBwdWJsaXNoZXIudmlkZW9SZWZlcmVuY2UudmlkZW9IZWlnaHQ7XG5cbiAgICAgICAgICAgIGNvbnN0IHJlcGVhdFVudGlsQ2hhbmdlID0gc2V0SW50ZXJ2YWwoKCkgPT4ge1xuICAgICAgICAgICAgICBmaXJlZm94U2V0dGluZ3MgPSBwdWJsaXNoZXIuc3RyZWFtLmdldE1lZGlhU3RyZWFtKCkuZ2V0VmlkZW9UcmFja3MoKVswXS5nZXRTZXR0aW5ncygpO1xuICAgICAgICAgICAgICBuZXdXaWR0aCA9IChwbGF0Zm9ybS5uYW1lISEudG9Mb3dlckNhc2UoKS5pbmRleE9mKCdmaXJlZm94JykgIT09IC0xKSA/IGZpcmVmb3hTZXR0aW5ncy53aWR0aCA6IHB1Ymxpc2hlci52aWRlb1JlZmVyZW5jZS52aWRlb1dpZHRoO1xuICAgICAgICAgICAgICBuZXdIZWlnaHQgPSAocGxhdGZvcm0ubmFtZSEhLnRvTG93ZXJDYXNlKCkuaW5kZXhPZignZmlyZWZveCcpICE9PSAtMSkgPyBmaXJlZm94U2V0dGluZ3MuaGVpZ2h0IDogcHVibGlzaGVyLnZpZGVvUmVmZXJlbmNlLnZpZGVvSGVpZ2h0O1xuICAgICAgICAgICAgICBzZW5kU3RyZWFtUHJvcGVydHlDaGFuZ2VkRXZlbnQob2xkV2lkdGgsIG9sZEhlaWdodCwgbmV3V2lkdGgsIG5ld0hlaWdodCk7XG4gICAgICAgICAgICB9LCAxMDApO1xuXG4gICAgICAgICAgICBjb25zdCBzZW5kU3RyZWFtUHJvcGVydHlDaGFuZ2VkRXZlbnQgPSAob2xkV2lkdGgsIG9sZEhlaWdodCwgbmV3V2lkdGgsIG5ld0hlaWdodCkgPT4ge1xuICAgICAgICAgICAgICBhdHRlbXB0cysrO1xuICAgICAgICAgICAgICBpZiAoYXR0ZW1wdHMgPiA0KSB7XG4gICAgICAgICAgICAgICAgY2xlYXJUaW1lb3V0KHJlcGVhdFVudGlsQ2hhbmdlKTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICBpZiAobmV3V2lkdGggIT09IG9sZFdpZHRoIHx8IG5ld0hlaWdodCAhPT0gb2xkSGVpZ2h0KSB7XG4gICAgICAgICAgICAgICAgcHVibGlzaGVyLnN0cmVhbS52aWRlb0RpbWVuc2lvbnMgPSB7XG4gICAgICAgICAgICAgICAgICB3aWR0aDogbmV3V2lkdGggfHwgMCxcbiAgICAgICAgICAgICAgICAgIGhlaWdodDogbmV3SGVpZ2h0IHx8IDBcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIHRoaXMuc2VuZFJlcXVlc3QoXG4gICAgICAgICAgICAgICAgICAnc3RyZWFtUHJvcGVydHlDaGFuZ2VkJyxcbiAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgc3RyZWFtSWQ6IHB1Ymxpc2hlci5zdHJlYW0uc3RyZWFtSWQsXG4gICAgICAgICAgICAgICAgICAgIHByb3BlcnR5OiAndmlkZW9EaW1lbnNpb25zJyxcbiAgICAgICAgICAgICAgICAgICAgbmV3VmFsdWU6IEpTT04uc3RyaW5naWZ5KHB1Ymxpc2hlci5zdHJlYW0udmlkZW9EaW1lbnNpb25zKSxcbiAgICAgICAgICAgICAgICAgICAgcmVhc29uOiAnZGV2aWNlUm90YXRlZCdcbiAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAoZXJyb3IsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoXCJFcnJvciBzZW5kaW5nICdzdHJlYW1Qcm9wZXJ0eUNoYW5nZWQnIGV2ZW50XCIsIGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICB0aGlzLnNlc3Npb24uZW1pdEV2ZW50KCdzdHJlYW1Qcm9wZXJ0eUNoYW5nZWQnLCBbbmV3IFN0cmVhbVByb3BlcnR5Q2hhbmdlZEV2ZW50KHRoaXMuc2Vzc2lvbiwgcHVibGlzaGVyLnN0cmVhbSwgJ3ZpZGVvRGltZW5zaW9ucycsIHB1Ymxpc2hlci5zdHJlYW0udmlkZW9EaW1lbnNpb25zLCB7IHdpZHRoOiBvbGRXaWR0aCwgaGVpZ2h0OiBvbGRIZWlnaHQgfSwgJ2RldmljZVJvdGF0ZWQnKV0pO1xuICAgICAgICAgICAgICAgICAgICAgIHB1Ymxpc2hlci5lbWl0RXZlbnQoJ3N0cmVhbVByb3BlcnR5Q2hhbmdlZCcsIFtuZXcgU3RyZWFtUHJvcGVydHlDaGFuZ2VkRXZlbnQocHVibGlzaGVyLCBwdWJsaXNoZXIuc3RyZWFtLCAndmlkZW9EaW1lbnNpb25zJywgcHVibGlzaGVyLnN0cmVhbS52aWRlb0RpbWVuc2lvbnMsIHsgd2lkdGg6IG9sZFdpZHRoLCBoZWlnaHQ6IG9sZEhlaWdodCB9LCAnZGV2aWNlUm90YXRlZCcpXSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIGNsZWFyVGltZW91dChyZXBlYXRVbnRpbENoYW5nZSk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH07XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgIH07XG4gICAgfVxuICB9XG5cblxuICAvKipcbiAgICogUmV0dXJucyBuZXcgc2Vzc2lvblxuICAgKi9cbiAgaW5pdFNlc3Npb24oKTogU2Vzc2lvbiB7XG4gICAgdGhpcy5zZXNzaW9uID0gbmV3IFNlc3Npb24odGhpcyk7XG4gICAgcmV0dXJuIHRoaXMuc2Vzc2lvbjtcbiAgfVxuXG5cbiAgaW5pdFB1Ymxpc2hlcih0YXJnZXRFbGVtZW50OiBzdHJpbmcgfCBIVE1MRWxlbWVudCk6IFB1Ymxpc2hlcjtcbiAgaW5pdFB1Ymxpc2hlcih0YXJnZXRFbGVtZW50OiBzdHJpbmcgfCBIVE1MRWxlbWVudCwgcHJvcGVydGllczogUHVibGlzaGVyUHJvcGVydGllcyk6IFB1Ymxpc2hlcjtcbiAgaW5pdFB1Ymxpc2hlcih0YXJnZXRFbGVtZW50OiBzdHJpbmcgfCBIVE1MRWxlbWVudCwgY29tcGxldGlvbkhhbmRsZXI6IChlcnJvcjogRXJyb3IgfCB1bmRlZmluZWQpID0+IHZvaWQpOiBQdWJsaXNoZXI7XG4gIGluaXRQdWJsaXNoZXIodGFyZ2V0RWxlbWVudDogc3RyaW5nIHwgSFRNTEVsZW1lbnQsIHByb3BlcnRpZXM6IFB1Ymxpc2hlclByb3BlcnRpZXMsIGNvbXBsZXRpb25IYW5kbGVyOiAoZXJyb3I6IEVycm9yIHwgdW5kZWZpbmVkKSA9PiB2b2lkKTogUHVibGlzaGVyO1xuXG4gIC8qKlxuICAgKiBSZXR1cm5zIGEgbmV3IHB1Ymxpc2hlclxuICAgKlxuICAgKiAjIyMjIEV2ZW50cyBkaXNwYXRjaGVkXG4gICAqXG4gICAqIFRoZSBbW1B1Ymxpc2hlcl1dIG9iamVjdCB3aWxsIGRpc3BhdGNoIGFuIGBhY2Nlc3NEaWFsb2dPcGVuZWRgIGV2ZW50LCBvbmx5IGlmIHRoZSBwb3AtdXAgc2hvd24gYnkgdGhlIGJyb3dzZXIgdG8gcmVxdWVzdCBwZXJtaXNzaW9ucyBmb3IgdGhlIGNhbWVyYSBpcyBvcGVuZWQuIFlvdSBjYW4gdXNlIHRoaXMgZXZlbnQgdG8gYWxlcnQgdGhlIHVzZXIgYWJvdXQgZ3JhbnRpbmcgcGVybWlzc2lvbnNcbiAgICogZm9yIHlvdXIgd2Vic2l0ZS4gQW4gYGFjY2Vzc0RpYWxvZ0Nsb3NlZGAgZXZlbnQgd2lsbCBhbHNvIGJlIGRpc3BhdGNoZWQgYWZ0ZXIgdXNlciBjbGlja3Mgb24gXCJBbGxvd1wiIG9yIFwiQmxvY2tcIiBpbiB0aGUgcG9wLXVwLlxuICAgKlxuICAgKiBUaGUgW1tQdWJsaXNoZXJdXSBvYmplY3Qgd2lsbCBkaXNwYXRjaCBhbiBgYWNjZXNzQWxsb3dlZGAgb3IgYGFjY2Vzc0RlbmllZGAgZXZlbnQgb25jZSBpdCBoYXMgYmVlbiBncmFudGVkIGFjY2VzcyB0byB0aGUgcmVxdWVzdGVkIGlucHV0IGRldmljZXMgb3Igbm90LlxuICAgKlxuICAgKiBUaGUgW1tQdWJsaXNoZXJdXSBvYmplY3Qgd2lsbCBkaXNwYXRjaCBhIGB2aWRlb0VsZW1lbnRDcmVhdGVkYCBldmVudCBvbmNlIGEgSFRNTCB2aWRlbyBlbGVtZW50IGhhcyBiZWVuIGFkZGVkIHRvIERPTSAob25seSBpZiB5b3VcbiAgICogW2xldCBPcGVuVmlkdSB0YWtlIGNhcmUgb2YgdGhlIHZpZGVvIHBsYXllcnNdKC9kb2NzL2hvdy1kby1pL21hbmFnZS12aWRlb3MvI2xldC1vcGVudmlkdS10YWtlLWNhcmUtb2YtdGhlLXZpZGVvLXBsYXllcnMpKS4gU2VlIFtbVmlkZW9FbGVtZW50RXZlbnRdXSB0byBsZWFybiBtb3JlLlxuICAgKlxuICAgKiBUaGUgW1tQdWJsaXNoZXJdXSBvYmplY3Qgd2lsbCBkaXNwYXRjaCBhIGBzdHJlYW1QbGF5aW5nYCBldmVudCBvbmNlIHRoZSBsb2NhbCBzdHJlYW1zIHN0YXJ0cyBwbGF5aW5nLiBTZWUgW1tTdHJlYW1NYW5hZ2VyRXZlbnRdXSB0byBsZWFybiBtb3JlLlxuICAgKlxuICAgKiBAcGFyYW0gdGFyZ2V0RWxlbWVudCAgSFRNTCBET00gZWxlbWVudCAob3IgaXRzIGBpZGAgYXR0cmlidXRlKSBpbiB3aGljaCB0aGUgdmlkZW8gZWxlbWVudCBvZiB0aGUgUHVibGlzaGVyIHdpbGwgYmUgaW5zZXJ0ZWQgKHNlZSBbW1B1Ymxpc2hlclByb3BlcnRpZXMuaW5zZXJ0TW9kZV1dKS4gSWYgKm51bGwqIG9yICp1bmRlZmluZWQqIG5vIGRlZmF1bHQgdmlkZW8gd2lsbCBiZSBjcmVhdGVkIGZvciB0aGlzIFB1Ymxpc2hlci5cbiAgICogWW91IGNhbiBhbHdheXMgY2FsbCBtZXRob2QgW1tQdWJsaXNoZXIuYWRkVmlkZW9FbGVtZW50XV0gb3IgW1tQdWJsaXNoZXIuY3JlYXRlVmlkZW9FbGVtZW50XV0gdG8gbWFuYWdlIHRoZSB2aWRlbyBlbGVtZW50cyBvbiB5b3VyIG93biAoc2VlIFtNYW5hZ2UgdmlkZW8gcGxheWVyc10oL2RvY3MvaG93LWRvLWkvbWFuYWdlLXZpZGVvcykgc2VjdGlvbilcbiAgICogQHBhcmFtIGNvbXBsZXRpb25IYW5kbGVyIGBlcnJvcmAgcGFyYW1ldGVyIGlzIG51bGwgaWYgYGluaXRQdWJsaXNoZXJgIHN1Y2NlZWRzLCBhbmQgaXMgZGVmaW5lZCBpZiBpdCBmYWlscy5cbiAgICogICAgICAgICAgICAgICAgICAgICAgICAgIGBjb21wbGV0aW9uSGFuZGxlcmAgZnVuY3Rpb24gaXMgY2FsbGVkIGJlZm9yZSB0aGUgUHVibGlzaGVyIGRpc3BhdGNoZXMgYW4gYGFjY2Vzc0FsbG93ZWRgIG9yIGFuIGBhY2Nlc3NEZW5pZWRgIGV2ZW50XG4gICAqL1xuICBpbml0UHVibGlzaGVyKHRhcmdldEVsZW1lbnQ6IHN0cmluZyB8IEhUTUxFbGVtZW50LCBwYXJhbTI/LCBwYXJhbTM/KTogUHVibGlzaGVyIHtcblxuICAgIGxldCBwcm9wZXJ0aWVzOiBQdWJsaXNoZXJQcm9wZXJ0aWVzO1xuXG4gICAgaWYgKCEhcGFyYW0yICYmICh0eXBlb2YgcGFyYW0yICE9PSAnZnVuY3Rpb24nKSkge1xuXG4gICAgICAvLyBNYXRjaGVzICdpbml0UHVibGlzaGVyKHRhcmdldEVsZW1lbnQsIHByb3BlcnRpZXMpJyBvciAnaW5pdFB1Ymxpc2hlcih0YXJnZXRFbGVtZW50LCBwcm9wZXJ0aWVzLCBjb21wbGV0aW9uSGFuZGxlciknXG5cbiAgICAgIHByb3BlcnRpZXMgPSAoPFB1Ymxpc2hlclByb3BlcnRpZXM+cGFyYW0yKTtcblxuICAgICAgcHJvcGVydGllcyA9IHtcbiAgICAgICAgYXVkaW9Tb3VyY2U6ICh0eXBlb2YgcHJvcGVydGllcy5hdWRpb1NvdXJjZSAhPT0gJ3VuZGVmaW5lZCcpID8gcHJvcGVydGllcy5hdWRpb1NvdXJjZSA6IHVuZGVmaW5lZCxcbiAgICAgICAgZnJhbWVSYXRlOiB0aGlzLmlzTWVkaWFTdHJlYW1UcmFjayhwcm9wZXJ0aWVzLnZpZGVvU291cmNlKSA/IHVuZGVmaW5lZCA6ICgodHlwZW9mIHByb3BlcnRpZXMuZnJhbWVSYXRlICE9PSAndW5kZWZpbmVkJykgPyBwcm9wZXJ0aWVzLmZyYW1lUmF0ZSA6IHVuZGVmaW5lZCksXG4gICAgICAgIGluc2VydE1vZGU6ICh0eXBlb2YgcHJvcGVydGllcy5pbnNlcnRNb2RlICE9PSAndW5kZWZpbmVkJykgPyAoKHR5cGVvZiBwcm9wZXJ0aWVzLmluc2VydE1vZGUgPT09ICdzdHJpbmcnKSA/IFZpZGVvSW5zZXJ0TW9kZVtwcm9wZXJ0aWVzLmluc2VydE1vZGVdIDogcHJvcGVydGllcy5pbnNlcnRNb2RlKSA6IFZpZGVvSW5zZXJ0TW9kZS5BUFBFTkQsXG4gICAgICAgIG1pcnJvcjogKHR5cGVvZiBwcm9wZXJ0aWVzLm1pcnJvciAhPT0gJ3VuZGVmaW5lZCcpID8gcHJvcGVydGllcy5taXJyb3IgOiB0cnVlLFxuICAgICAgICBwdWJsaXNoQXVkaW86ICh0eXBlb2YgcHJvcGVydGllcy5wdWJsaXNoQXVkaW8gIT09ICd1bmRlZmluZWQnKSA/IHByb3BlcnRpZXMucHVibGlzaEF1ZGlvIDogdHJ1ZSxcbiAgICAgICAgcHVibGlzaFZpZGVvOiAodHlwZW9mIHByb3BlcnRpZXMucHVibGlzaFZpZGVvICE9PSAndW5kZWZpbmVkJykgPyBwcm9wZXJ0aWVzLnB1Ymxpc2hWaWRlbyA6IHRydWUsXG4gICAgICAgIHJlc29sdXRpb246IHRoaXMuaXNNZWRpYVN0cmVhbVRyYWNrKHByb3BlcnRpZXMudmlkZW9Tb3VyY2UpID8gdW5kZWZpbmVkIDogKCh0eXBlb2YgcHJvcGVydGllcy5yZXNvbHV0aW9uICE9PSAndW5kZWZpbmVkJykgPyBwcm9wZXJ0aWVzLnJlc29sdXRpb24gOiAnNjQweDQ4MCcpLFxuICAgICAgICB2aWRlb1NvdXJjZTogKHR5cGVvZiBwcm9wZXJ0aWVzLnZpZGVvU291cmNlICE9PSAndW5kZWZpbmVkJykgPyBwcm9wZXJ0aWVzLnZpZGVvU291cmNlIDogdW5kZWZpbmVkXG4gICAgICB9O1xuICAgIH0gZWxzZSB7XG5cbiAgICAgIC8vIE1hdGNoZXMgJ2luaXRQdWJsaXNoZXIodGFyZ2V0RWxlbWVudCknIG9yICdpbml0UHVibGlzaGVyKHRhcmdldEVsZW1lbnQsIGNvbXBsZXRpb25IYW5kbGVyKSdcblxuICAgICAgcHJvcGVydGllcyA9IHtcbiAgICAgICAgaW5zZXJ0TW9kZTogVmlkZW9JbnNlcnRNb2RlLkFQUEVORCxcbiAgICAgICAgbWlycm9yOiB0cnVlLFxuICAgICAgICBwdWJsaXNoQXVkaW86IHRydWUsXG4gICAgICAgIHB1Ymxpc2hWaWRlbzogdHJ1ZSxcbiAgICAgICAgcmVzb2x1dGlvbjogJzY0MHg0ODAnXG4gICAgICB9O1xuICAgIH1cblxuICAgIGNvbnN0IHB1Ymxpc2hlcjogUHVibGlzaGVyID0gbmV3IFB1Ymxpc2hlcih0YXJnZXRFbGVtZW50LCBwcm9wZXJ0aWVzLCB0aGlzKTtcblxuICAgIGxldCBjb21wbGV0aW9uSGFuZGxlcjogKGVycm9yOiBFcnJvciB8IHVuZGVmaW5lZCkgPT4gdm9pZDtcbiAgICBpZiAoISFwYXJhbTIgJiYgKHR5cGVvZiBwYXJhbTIgPT09ICdmdW5jdGlvbicpKSB7XG4gICAgICBjb21wbGV0aW9uSGFuZGxlciA9IHBhcmFtMjtcbiAgICB9IGVsc2UgaWYgKCEhcGFyYW0zKSB7XG4gICAgICBjb21wbGV0aW9uSGFuZGxlciA9IHBhcmFtMztcbiAgICB9XG5cbiAgICBwdWJsaXNoZXIuaW5pdGlhbGl6ZSgpXG4gICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgIGlmIChjb21wbGV0aW9uSGFuZGxlciAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgY29tcGxldGlvbkhhbmRsZXIodW5kZWZpbmVkKTtcbiAgICAgICAgfVxuICAgICAgICBwdWJsaXNoZXIuZW1pdEV2ZW50KCdhY2Nlc3NBbGxvd2VkJywgW10pO1xuICAgICAgfSkuY2F0Y2goKGVycm9yKSA9PiB7XG4gICAgICAgIGlmIChjb21wbGV0aW9uSGFuZGxlciAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgY29tcGxldGlvbkhhbmRsZXIoZXJyb3IpO1xuICAgICAgICB9XG4gICAgICAgIHB1Ymxpc2hlci5lbWl0RXZlbnQoJ2FjY2Vzc0RlbmllZCcsIFtdKTtcbiAgICAgIH0pO1xuXG4gICAgdGhpcy5wdWJsaXNoZXJzLnB1c2gocHVibGlzaGVyKTtcbiAgICByZXR1cm4gcHVibGlzaGVyO1xuICB9XG5cblxuICAvKipcbiAgICogUHJvbWlzaWZpZWQgdmVyc2lvbiBvZiBbW09wZW5WaWR1LmluaXRQdWJsaXNoZXJdXVxuICAgKlxuICAgKiA+IFdBUk5JTkc6IGV2ZW50cyBgYWNjZXNzRGlhbG9nT3BlbmVkYCBhbmQgYGFjY2Vzc0RpYWxvZ0Nsb3NlZGAgd2lsbCBub3QgYmUgZGlzcGF0Y2hlZCBpZiB1c2luZyB0aGlzIG1ldGhvZCBpbnN0ZWFkIG9mIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dXG4gICAqL1xuICBpbml0UHVibGlzaGVyQXN5bmModGFyZ2V0RWxlbWVudDogc3RyaW5nIHwgSFRNTEVsZW1lbnQpOiBQcm9taXNlPFB1Ymxpc2hlcj47XG4gIGluaXRQdWJsaXNoZXJBc3luYyh0YXJnZXRFbGVtZW50OiBzdHJpbmcgfCBIVE1MRWxlbWVudCwgcHJvcGVydGllczogUHVibGlzaGVyUHJvcGVydGllcyk6IFByb21pc2U8UHVibGlzaGVyPjtcblxuICBpbml0UHVibGlzaGVyQXN5bmModGFyZ2V0RWxlbWVudDogc3RyaW5nIHwgSFRNTEVsZW1lbnQsIHByb3BlcnRpZXM/OiBQdWJsaXNoZXJQcm9wZXJ0aWVzKTogUHJvbWlzZTxQdWJsaXNoZXI+IHtcbiAgICByZXR1cm4gbmV3IFByb21pc2U8UHVibGlzaGVyPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG5cbiAgICAgIGxldCBwdWJsaXNoZXI6IFB1Ymxpc2hlcjtcblxuICAgICAgY29uc3QgY2FsbGJhY2sgPSAoZXJyb3I6IEVycm9yKSA9PiB7XG4gICAgICAgIGlmICghIWVycm9yKSB7XG4gICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICByZXNvbHZlKHB1Ymxpc2hlcik7XG4gICAgICAgIH1cbiAgICAgIH07XG5cbiAgICAgIGlmICghIXByb3BlcnRpZXMpIHtcbiAgICAgICAgcHVibGlzaGVyID0gdGhpcy5pbml0UHVibGlzaGVyKHRhcmdldEVsZW1lbnQsIHByb3BlcnRpZXMsIGNhbGxiYWNrKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHB1Ymxpc2hlciA9IHRoaXMuaW5pdFB1Ymxpc2hlcih0YXJnZXRFbGVtZW50LCBjYWxsYmFjayk7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIGEgbmV3IGxvY2FsIHJlY29yZGVyIGZvciByZWNvcmRpbmcgc3RyZWFtcyBzdHJhaWdodCBhd2F5IGZyb20gdGhlIGJyb3dzZXJcbiAgICogQHBhcmFtIHN0cmVhbSAgU3RyZWFtIHRvIHJlY29yZFxuICAgKi9cbiAgaW5pdExvY2FsUmVjb3JkZXIoc3RyZWFtOiBTdHJlYW0pOiBMb2NhbFJlY29yZGVyIHtcbiAgICByZXR1cm4gbmV3IExvY2FsUmVjb3JkZXIoc3RyZWFtKTtcbiAgfVxuXG5cbiAgLyoqXG4gICAqIENoZWNrcyBpZiB0aGUgYnJvd3NlciBzdXBwb3J0cyBPcGVuVmlkdVxuICAgKiBAcmV0dXJucyAxIGlmIHRoZSBicm93c2VyIHN1cHBvcnRzIE9wZW5WaWR1LCAwIG90aGVyd2lzZVxuICAgKi9cbiAgY2hlY2tTeXN0ZW1SZXF1aXJlbWVudHMoKTogbnVtYmVyIHtcbiAgICBjb25zdCBicm93c2VyID0gcGxhdGZvcm0ubmFtZTtcbiAgICBjb25zdCB2ZXJzaW9uID0gcGxhdGZvcm0udmVyc2lvbjtcblxuICAgIGlmICgoYnJvd3NlciAhPT0gJ0Nocm9tZScpICYmIChicm93c2VyICE9PSAnQ2hyb21lIE1vYmlsZScpICYmXG4gICAgICAoYnJvd3NlciAhPT0gJ0ZpcmVmb3gnKSAmJiAoYnJvd3NlciAhPT0gJ0ZpcmVmb3ggTW9iaWxlJykgJiYgKGJyb3dzZXIgIT09ICdGaXJlZm94IGZvciBpT1MnKSAmJlxuICAgICAgKGJyb3dzZXIgIT09ICdPcGVyYScpICYmIChicm93c2VyICE9PSAnT3BlcmEgTW9iaWxlJykgJiZcbiAgICAgIChicm93c2VyICE9PSAnU2FmYXJpJykpIHtcbiAgICAgIHJldHVybiAwO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gMTtcbiAgICB9XG4gIH1cblxuXG4gIC8qKlxuICAgKiBDb2xsZWN0cyBpbmZvcm1hdGlvbiBhYm91dCB0aGUgbWVkaWEgaW5wdXQgZGV2aWNlcyBhdmFpbGFibGUgb24gdGhlIHN5c3RlbS4gWW91IGNhbiBwYXNzIHByb3BlcnR5IGBkZXZpY2VJZGAgb2YgYSBbW0RldmljZV1dIG9iamVjdCBhcyB2YWx1ZSBvZiBgYXVkaW9Tb3VyY2VgIG9yIGB2aWRlb1NvdXJjZWAgcHJvcGVydGllcyBpbiBbW2luaXRQdWJsaXNoZXJdXSBtZXRob2RcbiAgICovXG4gIGdldERldmljZXMoKTogUHJvbWlzZTxEZXZpY2VbXT4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZTxEZXZpY2VbXT4oKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgbmF2aWdhdG9yLm1lZGlhRGV2aWNlcy5lbnVtZXJhdGVEZXZpY2VzKCkudGhlbigoZGV2aWNlSW5mb3MpID0+IHtcbiAgICAgICAgY29uc3QgZGV2aWNlczogRGV2aWNlW10gPSBbXTtcbiAgICAgICAgZGV2aWNlSW5mb3MuZm9yRWFjaChkZXZpY2VJbmZvID0+IHtcbiAgICAgICAgICBpZiAoZGV2aWNlSW5mby5raW5kID09PSAnYXVkaW9pbnB1dCcgfHwgZGV2aWNlSW5mby5raW5kID09PSAndmlkZW9pbnB1dCcpIHtcbiAgICAgICAgICAgIGRldmljZXMucHVzaCh7XG4gICAgICAgICAgICAgIGtpbmQ6IGRldmljZUluZm8ua2luZCxcbiAgICAgICAgICAgICAgZGV2aWNlSWQ6IGRldmljZUluZm8uZGV2aWNlSWQsXG4gICAgICAgICAgICAgIGxhYmVsOiBkZXZpY2VJbmZvLmxhYmVsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICByZXNvbHZlKGRldmljZXMpO1xuICAgICAgfSkuY2F0Y2goKGVycm9yKSA9PiB7XG4gICAgICAgIGNvbnNvbGUuZXJyb3IoJ0Vycm9yIGdldHRpbmcgZGV2aWNlcycsIGVycm9yKTtcbiAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9XG5cblxuICAvKipcbiAgICogR2V0IGEgTWVkaWFTdHJlYW0gb2JqZWN0IHRoYXQgeW91IGNhbiBjdXN0b21pemUgYmVmb3JlIGNhbGxpbmcgW1tpbml0UHVibGlzaGVyXV0gKHBhc3MgX01lZGlhU3RyZWFtVHJhY2tfIHByb3BlcnR5IG9mIHRoZSBfTWVkaWFTdHJlYW1fIHZhbHVlIHJlc29sdmVkIGJ5IHRoZSBQcm9taXNlIGFzIGBhdWRpb1NvdXJjZWAgb3IgYHZpZGVvU291cmNlYCBwcm9wZXJ0aWVzIGluIFtbaW5pdFB1Ymxpc2hlcl1dKVxuICAgKlxuICAgKiBQYXJhbWV0ZXIgYG9wdGlvbnNgIGlzIHRoZSBzYW1lIGFzIGluIFtbaW5pdFB1Ymxpc2hlcl1dIHNlY29uZCBwYXJhbWV0ZXIgKG9mIHR5cGUgW1tQdWJsaXNoZXJQcm9wZXJ0aWVzXV0pLCBidXQgb25seSB0aGUgZm9sbG93aW5nIHByb3BlcnRpZXMgd2lsbCBiZSBhcHBsaWVkOiBgYXVkaW9Tb3VyY2VgLCBgdmlkZW9Tb3VyY2VgLCBgZnJhbWVSYXRlYCwgYHJlc29sdXRpb25gXG4gICAqXG4gICAqIFRvIGN1c3RvbWl6ZSB0aGUgUHVibGlzaGVyJ3MgdmlkZW8sIHRoZSBBUEkgZm9yIEhUTUxDYW52YXNFbGVtZW50IGlzIHZlcnkgdXNlZnVsLiBGb3IgZXhhbXBsZSwgdG8gZ2V0IGEgYmxhY2stYW5kLXdoaXRlIHZpZGVvIGF0IDEwIGZwcyBhbmQgSEQgcmVzb2x1dGlvbiB3aXRoIG5vIHNvdW5kOlxuICAgKiBgYGBcbiAgICogdmFyIE9WID0gbmV3IE9wZW5WaWR1KCk7XG4gICAqIHZhciBGUkFNRV9SQVRFID0gMTA7XG4gICAqXG4gICAqIE9WLmdldFVzZXJNZWRpYSh7XG4gICAqICAgIGF1ZGlvU291cmNlOiBmYWxzZTtcbiAgICogICAgdmlkZW9Tb3VyY2U6IHVuZGVmaW5lZCxcbiAgICogICAgcmVzb2x1dGlvbjogJzEyODB4NzIwJyxcbiAgICogICAgZnJhbWVSYXRlOiBGUkFNRV9SQVRFXG4gICAqIH0pXG4gICAqIC50aGVuKG1lZGlhU3RyZWFtID0+IHtcbiAgICpcbiAgICogICAgdmFyIHZpZGVvVHJhY2sgPSBtZWRpYVN0cmVhbS5nZXRWaWRlb1RyYWNrcygpWzBdO1xuICAgKiAgICB2YXIgdmlkZW8gPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCd2aWRlbycpO1xuICAgKiAgICB2aWRlby5zcmNPYmplY3QgPSBuZXcgTWVkaWFTdHJlYW0oW3ZpZGVvVHJhY2tdKTtcbiAgICpcbiAgICogICAgdmFyIGNhbnZhcyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2NhbnZhcycpO1xuICAgKiAgICB2YXIgY3R4ID0gY2FudmFzLmdldENvbnRleHQoJzJkJyk7XG4gICAqICAgIGN0eC5maWx0ZXIgPSAnZ3JheXNjYWxlKDEwMCUpJztcbiAgICpcbiAgICogICAgdmlkZW8uYWRkRXZlbnRMaXN0ZW5lcigncGxheScsICgpID0+IHtcbiAgICogICAgICB2YXIgbG9vcCA9ICgpID0+IHtcbiAgICogICAgICAgIGlmICghdmlkZW8ucGF1c2VkICYmICF2aWRlby5lbmRlZCkge1xuICAgKiAgICAgICAgICBjdHguZHJhd0ltYWdlKHZpZGVvLCAwLCAwLCAzMDAsIDE3MCk7XG4gICAqICAgICAgICAgIHNldFRpbWVvdXQobG9vcCwgMTAwMC8gRlJBTUVfUkFURSk7IC8vIERyYXdpbmcgYXQgMTAgZnBzXG4gICAqICAgICAgICB9XG4gICAqICAgICAgfTtcbiAgICogICAgICBsb29wKCk7XG4gICAqICAgIH0pO1xuICAgKiAgICB2aWRlby5wbGF5KCk7XG4gICAqXG4gICAqICAgIHZhciBncmF5VmlkZW9UcmFjayA9IGNhbnZhcy5jYXB0dXJlU3RyZWFtKEZSQU1FX1JBVEUpLmdldFZpZGVvVHJhY2tzKClbMF07XG4gICAqICAgIHZhciBwdWJsaXNoZXIgPSB0aGlzLk9WLmluaXRQdWJsaXNoZXIoXG4gICAqICAgICAgbXlIdG1sVGFyZ2V0LFxuICAgKiAgICAgIHtcbiAgICogICAgICAgIGF1ZGlvU291cmNlOiBmYWxzZSxcbiAgICogICAgICAgIHZpZGVvU291cmNlOiBncmF5VmlkZW9UcmFja1xuICAgKiAgICAgIH0pO1xuICAgKiB9KTtcbiAgICogYGBgXG4gICAqL1xuICBnZXRVc2VyTWVkaWEob3B0aW9uczogUHVibGlzaGVyUHJvcGVydGllcyk6IFByb21pc2U8TWVkaWFTdHJlYW0+IHtcbiAgICByZXR1cm4gbmV3IFByb21pc2U8TWVkaWFTdHJlYW0+KChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIHRoaXMuZ2VuZXJhdGVNZWRpYUNvbnN0cmFpbnRzKG9wdGlvbnMpXG4gICAgICAgIC50aGVuKGNvbnN0cmFpbnRzID0+IHtcbiAgICAgICAgICBuYXZpZ2F0b3IubWVkaWFEZXZpY2VzLmdldFVzZXJNZWRpYShjb25zdHJhaW50cylcbiAgICAgICAgICAgIC50aGVuKG1lZGlhU3RyZWFtID0+IHtcbiAgICAgICAgICAgICAgcmVzb2x2ZShtZWRpYVN0cmVhbSk7XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICAgICAgbGV0IGVycm9yTmFtZTogT3BlblZpZHVFcnJvck5hbWU7XG4gICAgICAgICAgICAgIGNvbnN0IGVycm9yTWVzc2FnZSA9IGVycm9yLnRvU3RyaW5nKCk7XG4gICAgICAgICAgICAgIGlmICghKG9wdGlvbnMudmlkZW9Tb3VyY2UgPT09ICdzY3JlZW4nKSkge1xuICAgICAgICAgICAgICAgIGVycm9yTmFtZSA9IE9wZW5WaWR1RXJyb3JOYW1lLkRFVklDRV9BQ0NFU1NfREVOSUVEO1xuICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGVycm9yTmFtZSA9IE9wZW5WaWR1RXJyb3JOYW1lLlNDUkVFTl9DQVBUVVJFX0RFTklFRDtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICByZWplY3QobmV3IE9wZW5WaWR1RXJyb3IoZXJyb3JOYW1lLCBlcnJvck1lc3NhZ2UpKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KVxuICAgICAgICAuY2F0Y2goKGVycm9yOiBPcGVuVmlkdUVycm9yKSA9PiB7XG4gICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgfSk7XG4gICAgfSk7XG4gIH1cblxuXG4gIC8qIHRzbGludDpkaXNhYmxlOm5vLWVtcHR5ICovXG4gIC8qKlxuICAgKiBEaXNhYmxlIGFsbCBsb2dnaW5nIGV4Y2VwdCBlcnJvciBsZXZlbFxuICAgKi9cbiAgZW5hYmxlUHJvZE1vZGUoKTogdm9pZCB7XG4gICAgY29uc29sZS5sb2cgPSAoKSA9PiB7IH07XG4gICAgY29uc29sZS5kZWJ1ZyA9ICgpID0+IHsgfTtcbiAgICBjb25zb2xlLmluZm8gPSAoKSA9PiB7IH07XG4gICAgY29uc29sZS53YXJuID0gKCkgPT4geyB9O1xuICB9XG4gIC8qIHRzbGludDplbmFibGU6bm8tZW1wdHkgKi9cblxuXG4gIC8qKlxuICAgKiBTZXQgT3BlblZpZHUgYWR2YW5jZWQgY29uZmlndXJhdGlvbiBvcHRpb25zLiBDdXJyZW50bHkgYGNvbmZpZ3VyYXRpb25gIGlzIGFuIG9iamVjdCB3aXRoIHRoZSBmb2xsb3dpbmcgb3B0aW9uYWwgcHJvcGVydGllcyAoc2VlIFtbT3BlblZpZHVBZHZhbmNlZENvbmZpZ3VyYXRpb25dXSBmb3IgbW9yZSBkZXRhaWxzKTpcbiAgICogLSBgaWNlU2VydmVyc2A6IHNldCBjdXN0b20gU1RVTi9UVVJOIHNlcnZlcnMgdG8gYmUgdXNlZCBieSBPcGVuVmlkdSBCcm93c2VyXG4gICAqIC0gYHNjcmVlblNoYXJlQ2hyb21lRXh0ZW5zaW9uYDogdXJsIHRvIGEgY3VzdG9tIHNjcmVlbiBzaGFyZSBleHRlbnNpb24gZm9yIENocm9tZSB0byBiZSB1c2VkIGluc3RlYWQgb2YgdGhlIGRlZmF1bHQgb25lLCBiYXNlZCBvbiBvdXJzIFtodHRwczovL2dpdGh1Yi5jb20vT3BlblZpZHUvb3BlbnZpZHUtc2NyZWVuLXNoYXJpbmctY2hyb21lLWV4dGVuc2lvbl0oaHR0cHM6Ly9naXRodWIuY29tL09wZW5WaWR1L29wZW52aWR1LXNjcmVlbi1zaGFyaW5nLWNocm9tZS1leHRlbnNpb24pXG4gICAqIC0gYHB1Ymxpc2hlclNwZWFraW5nRXZlbnRzT3B0aW9uc2A6IGN1c3RvbSBjb25maWd1cmF0aW9uIGZvciB0aGUgW1tQdWJsaXNoZXJTcGVha2luZ0V2ZW50XV0gZmVhdHVyZVxuICAgKi9cbiAgc2V0QWR2YW5jZWRDb25maWd1cmF0aW9uKGNvbmZpZ3VyYXRpb246IE9wZW5WaWR1QWR2YW5jZWRDb25maWd1cmF0aW9uKTogdm9pZCB7XG4gICAgdGhpcy5hZHZhbmNlZENvbmZpZ3VyYXRpb24gPSBjb25maWd1cmF0aW9uO1xuICB9XG5cblxuICAvKiBIaWRkZW4gbWV0aG9kcyAqL1xuXG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICBnZW5lcmF0ZU1lZGlhQ29uc3RyYWludHMocHVibGlzaGVyUHJvcGVydGllczogUHVibGlzaGVyUHJvcGVydGllcyk6IFByb21pc2U8TWVkaWFTdHJlYW1Db25zdHJhaW50cz4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZTxNZWRpYVN0cmVhbUNvbnN0cmFpbnRzPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICBsZXQgYXVkaW8sIHZpZGVvO1xuXG4gICAgICBpZiAocHVibGlzaGVyUHJvcGVydGllcy5hdWRpb1NvdXJjZSA9PT0gbnVsbCB8fCBwdWJsaXNoZXJQcm9wZXJ0aWVzLmF1ZGlvU291cmNlID09PSBmYWxzZSkge1xuICAgICAgICBhdWRpbyA9IGZhbHNlO1xuICAgICAgfSBlbHNlIGlmIChwdWJsaXNoZXJQcm9wZXJ0aWVzLmF1ZGlvU291cmNlID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgYXVkaW8gPSB0cnVlO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgYXVkaW8gPSBwdWJsaXNoZXJQcm9wZXJ0aWVzLmF1ZGlvU291cmNlO1xuICAgICAgfVxuXG4gICAgICBpZiAocHVibGlzaGVyUHJvcGVydGllcy52aWRlb1NvdXJjZSA9PT0gbnVsbCB8fCBwdWJsaXNoZXJQcm9wZXJ0aWVzLnZpZGVvU291cmNlID09PSBmYWxzZSkge1xuICAgICAgICB2aWRlbyA9IGZhbHNlO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdmlkZW8gPSB7XG4gICAgICAgICAgaGVpZ2h0OiB7XG4gICAgICAgICAgICBpZGVhbDogNDgwXG4gICAgICAgICAgfSxcbiAgICAgICAgICB3aWR0aDoge1xuICAgICAgICAgICAgaWRlYWw6IDY0MFxuICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgbWVkaWFDb25zdHJhaW50czogTWVkaWFTdHJlYW1Db25zdHJhaW50cyA9IHtcbiAgICAgICAgYXVkaW8sXG4gICAgICAgIHZpZGVvXG4gICAgICB9O1xuXG4gICAgICBpZiAodHlwZW9mIG1lZGlhQ29uc3RyYWludHMuYXVkaW8gPT09ICdzdHJpbmcnKSB7XG4gICAgICAgIG1lZGlhQ29uc3RyYWludHMuYXVkaW8gPSB7IGRldmljZUlkOiB7IGV4YWN0OiBtZWRpYUNvbnN0cmFpbnRzLmF1ZGlvIH0gfTtcbiAgICAgIH1cblxuICAgICAgaWYgKG1lZGlhQ29uc3RyYWludHMudmlkZW8pIHtcblxuICAgICAgICBpZiAoISFwdWJsaXNoZXJQcm9wZXJ0aWVzLnJlc29sdXRpb24pIHtcbiAgICAgICAgICBjb25zdCB3aWR0aEFuZEhlaWdodCA9IHB1Ymxpc2hlclByb3BlcnRpZXMucmVzb2x1dGlvbi50b0xvd2VyQ2FzZSgpLnNwbGl0KCd4Jyk7XG4gICAgICAgICAgY29uc3Qgd2lkdGggPSBOdW1iZXIod2lkdGhBbmRIZWlnaHRbMF0pO1xuICAgICAgICAgIGNvbnN0IGhlaWdodCA9IE51bWJlcih3aWR0aEFuZEhlaWdodFsxXSk7XG4gICAgICAgICAgKG1lZGlhQ29uc3RyYWludHMudmlkZW8gYXMgYW55KS53aWR0aC5pZGVhbCA9IHdpZHRoO1xuICAgICAgICAgIChtZWRpYUNvbnN0cmFpbnRzLnZpZGVvIGFzIGFueSkuaGVpZ2h0LmlkZWFsID0gaGVpZ2h0O1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCEhcHVibGlzaGVyUHJvcGVydGllcy5mcmFtZVJhdGUpIHtcbiAgICAgICAgICAobWVkaWFDb25zdHJhaW50cy52aWRlbyBhcyBhbnkpLmZyYW1lUmF0ZSA9IHsgaWRlYWw6IHB1Ymxpc2hlclByb3BlcnRpZXMuZnJhbWVSYXRlIH07XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoISFwdWJsaXNoZXJQcm9wZXJ0aWVzLnZpZGVvU291cmNlICYmIHR5cGVvZiBwdWJsaXNoZXJQcm9wZXJ0aWVzLnZpZGVvU291cmNlID09PSAnc3RyaW5nJykge1xuXG4gICAgICAgICAgaWYgKHB1Ymxpc2hlclByb3BlcnRpZXMudmlkZW9Tb3VyY2UgPT09ICdzY3JlZW4nKSB7XG5cbiAgICAgICAgICAgIGlmIChwbGF0Zm9ybS5uYW1lICE9PSAnQ2hyb21lJyAmJiBwbGF0Zm9ybS5uYW1lIS5pbmRleE9mKCdGaXJlZm94JykgPT09IC0xKSB7XG4gICAgICAgICAgICAgIGNvbnN0IGVycm9yID0gbmV3IE9wZW5WaWR1RXJyb3IoT3BlblZpZHVFcnJvck5hbWUuU0NSRUVOX1NIQVJJTkdfTk9UX1NVUFBPUlRFRCwgJ1lvdSBjYW4gb25seSBzY3JlZW4gc2hhcmUgaW4gZGVza3RvcCBDaHJvbWUgYW5kIEZpcmVmb3guIERldGVjdGVkIGJyb3dzZXI6ICcgKyBwbGF0Zm9ybS5uYW1lKTtcbiAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihlcnJvcik7XG4gICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICB9IGVsc2Uge1xuXG4gICAgICAgICAgICAgIGlmICghIXRoaXMuYWR2YW5jZWRDb25maWd1cmF0aW9uLnNjcmVlblNoYXJlQ2hyb21lRXh0ZW5zaW9uICYmICEocGxhdGZvcm0ubmFtZSEuaW5kZXhPZignRmlyZWZveCcpICE9PSAtMSkpIHtcblxuICAgICAgICAgICAgICAgIC8vIEN1c3RvbSBzY3JlZW4gc2hhcmluZyBleHRlbnNpb24gZm9yIENocm9tZVxuXG4gICAgICAgICAgICAgICAgc2NyZWVuU2hhcmluZy5nZXRTY3JlZW5Db25zdHJhaW50cygoZXJyb3IsIHNjcmVlbkNvbnN0cmFpbnRzKSA9PiB7XG4gICAgICAgICAgICAgICAgICBpZiAoISFlcnJvciB8fCAhIXNjcmVlbkNvbnN0cmFpbnRzLm1hbmRhdG9yeSAmJiBzY3JlZW5Db25zdHJhaW50cy5tYW5kYXRvcnkuY2hyb21lTWVkaWFTb3VyY2UgPT09ICdzY3JlZW4nKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnJvciA9PT0gJ3Blcm1pc3Npb24tZGVuaWVkJyB8fCBlcnJvciA9PT0gJ1Blcm1pc3Npb25EZW5pZWRFcnJvcicpIHtcbiAgICAgICAgICAgICAgICAgICAgICBjb25zdCBlcnJvciA9IG5ldyBPcGVuVmlkdUVycm9yKE9wZW5WaWR1RXJyb3JOYW1lLlNDUkVFTl9DQVBUVVJFX0RFTklFRCwgJ1lvdSBtdXN0IGFsbG93IGFjY2VzcyB0byBvbmUgd2luZG93IG9mIHlvdXIgZGVza3RvcCcpO1xuICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgY29uc3QgZXh0ZW5zaW9uSWQgPSB0aGlzLmFkdmFuY2VkQ29uZmlndXJhdGlvbi5zY3JlZW5TaGFyZUNocm9tZUV4dGVuc2lvbiEuc3BsaXQoJy8nKS5wb3AoKSEhLnRyaW0oKTtcbiAgICAgICAgICAgICAgICAgICAgICBzY3JlZW5TaGFyaW5nLmdldENocm9tZUV4dGVuc2lvblN0YXR1cyhleHRlbnNpb25JZCwgKHN0YXR1cykgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHN0YXR1cyA9PT0gJ2luc3RhbGxlZC1kaXNhYmxlZCcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZXJyb3IgPSBuZXcgT3BlblZpZHVFcnJvcihPcGVuVmlkdUVycm9yTmFtZS5TQ1JFRU5fRVhURU5TSU9OX0RJU0FCTEVELCAnWW91IG11c3QgZW5hYmxlIHRoZSBzY3JlZW4gZXh0ZW5zaW9uJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHN0YXR1cyA9PT0gJ25vdC1pbnN0YWxsZWQnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGVycm9yID0gbmV3IE9wZW5WaWR1RXJyb3IoT3BlblZpZHVFcnJvck5hbWUuU0NSRUVOX0VYVEVOU0lPTl9OT1RfSU5TVEFMTEVELCAoPHN0cmluZz50aGlzLmFkdmFuY2VkQ29uZmlndXJhdGlvbi5zY3JlZW5TaGFyZUNocm9tZUV4dGVuc2lvbikpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgbWVkaWFDb25zdHJhaW50cy52aWRlbyA9IHNjcmVlbkNvbnN0cmFpbnRzO1xuICAgICAgICAgICAgICAgICAgICByZXNvbHZlKG1lZGlhQ29uc3RyYWludHMpO1xuICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICB9IGVsc2Uge1xuXG4gICAgICAgICAgICAgICAgLy8gRGVmYXVsdCBzY3JlZW4gc2hhcmluZyBleHRlbnNpb24gZm9yIENocm9tZVxuXG4gICAgICAgICAgICAgICAgc2NyZWVuU2hhcmluZ0F1dG8uZ2V0U2NyZWVuSWQoKGVycm9yLCBzb3VyY2VJZCwgc2NyZWVuQ29uc3RyYWludHMpID0+IHtcbiAgICAgICAgICAgICAgICAgIGlmICghIWVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnJvciA9PT0gJ25vdC1pbnN0YWxsZWQnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgY29uc3QgZXh0ZW5zaW9uVXJsID0gISF0aGlzLmFkdmFuY2VkQ29uZmlndXJhdGlvbi5zY3JlZW5TaGFyZUNocm9tZUV4dGVuc2lvbiA/IHRoaXMuYWR2YW5jZWRDb25maWd1cmF0aW9uLnNjcmVlblNoYXJlQ2hyb21lRXh0ZW5zaW9uIDpcbiAgICAgICAgICAgICAgICAgICAgICAgICdodHRwczovL2Nocm9tZS5nb29nbGUuY29tL3dlYnN0b3JlL2RldGFpbC9vcGVudmlkdS1zY3JlZW5zaGFyaW5nL2xmY2dmZXBhZm5vYmRsb2VjY2huZmFjbGliZW5qb2xkJztcbiAgICAgICAgICAgICAgICAgICAgICBjb25zdCBlcnJvciA9IG5ldyBPcGVuVmlkdUVycm9yKE9wZW5WaWR1RXJyb3JOYW1lLlNDUkVFTl9FWFRFTlNJT05fTk9UX0lOU1RBTExFRCwgZXh0ZW5zaW9uVXJsKTtcbiAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGVycm9yID09PSAnaW5zdGFsbGVkLWRpc2FibGVkJykge1xuICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGVycm9yID0gbmV3IE9wZW5WaWR1RXJyb3IoT3BlblZpZHVFcnJvck5hbWUuU0NSRUVOX0VYVEVOU0lPTl9ESVNBQkxFRCwgJ1lvdSBtdXN0IGVuYWJsZSB0aGUgc2NyZWVuIGV4dGVuc2lvbicpO1xuICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoZXJyb3IgPT09ICdwZXJtaXNzaW9uLWRlbmllZCcpIHtcbiAgICAgICAgICAgICAgICAgICAgICBjb25zdCBlcnJvciA9IG5ldyBPcGVuVmlkdUVycm9yKE9wZW5WaWR1RXJyb3JOYW1lLlNDUkVFTl9DQVBUVVJFX0RFTklFRCwgJ1lvdSBtdXN0IGFsbG93IGFjY2VzcyB0byBvbmUgd2luZG93IG9mIHlvdXIgZGVza3RvcCcpO1xuICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIG1lZGlhQ29uc3RyYWludHMudmlkZW8gPSBzY3JlZW5Db25zdHJhaW50cy52aWRlbztcbiAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZShtZWRpYUNvbnN0cmFpbnRzKTtcbiAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgIHB1Ymxpc2hlclByb3BlcnRpZXMudmlkZW9Tb3VyY2UgPSAnc2NyZWVuJztcblxuICAgICAgICAgICAgfVxuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6bm8tc3RyaW5nLWxpdGVyYWxcbiAgICAgICAgICAgIG1lZGlhQ29uc3RyYWludHMudmlkZW9bJ2RldmljZUlkJ10gPSB7IGV4YWN0OiBwdWJsaXNoZXJQcm9wZXJ0aWVzLnZpZGVvU291cmNlIH07XG4gICAgICAgICAgICByZXNvbHZlKG1lZGlhQ29uc3RyYWludHMpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICByZXNvbHZlKG1lZGlhQ29uc3RyYWludHMpO1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXNvbHZlKG1lZGlhQ29uc3RyYWludHMpO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIEBoaWRkZW5cbiAgICovXG4gIHN0YXJ0V3Mob25Db25uZWN0U3VjY2VzOiAoZXJyb3I6IEVycm9yKSA9PiB2b2lkKTogdm9pZCB7XG4gICAgY29uc3QgY29uZmlnID0ge1xuICAgICAgaGVhcnRiZWF0OiA1MDAwLFxuICAgICAgc2VuZENsb3NlTWVzc2FnZTogZmFsc2UsXG4gICAgICB3czoge1xuICAgICAgICB1cmk6IHRoaXMud3NVcmksXG4gICAgICAgIHVzZVNvY2tKUzogZmFsc2UsXG4gICAgICAgIG9uY29ubmVjdGVkOiBvbkNvbm5lY3RTdWNjZXMsXG4gICAgICAgIG9uZGlzY29ubmVjdDogdGhpcy5kaXNjb25uZWN0Q2FsbGJhY2suYmluZCh0aGlzKSxcbiAgICAgICAgb25yZWNvbm5lY3Rpbmc6IHRoaXMucmVjb25uZWN0aW5nQ2FsbGJhY2suYmluZCh0aGlzKSxcbiAgICAgICAgb25yZWNvbm5lY3RlZDogdGhpcy5yZWNvbm5lY3RlZENhbGxiYWNrLmJpbmQodGhpcylcbiAgICAgIH0sXG4gICAgICBycGM6IHtcbiAgICAgICAgcmVxdWVzdFRpbWVvdXQ6IDEwMDAwLFxuICAgICAgICBwYXJ0aWNpcGFudEpvaW5lZDogdGhpcy5zZXNzaW9uLm9uUGFydGljaXBhbnRKb2luZWQuYmluZCh0aGlzLnNlc3Npb24pLFxuICAgICAgICBwYXJ0aWNpcGFudFB1Ymxpc2hlZDogdGhpcy5zZXNzaW9uLm9uUGFydGljaXBhbnRQdWJsaXNoZWQuYmluZCh0aGlzLnNlc3Npb24pLFxuICAgICAgICBwYXJ0aWNpcGFudFVucHVibGlzaGVkOiB0aGlzLnNlc3Npb24ub25QYXJ0aWNpcGFudFVucHVibGlzaGVkLmJpbmQodGhpcy5zZXNzaW9uKSxcbiAgICAgICAgcGFydGljaXBhbnRMZWZ0OiB0aGlzLnNlc3Npb24ub25QYXJ0aWNpcGFudExlZnQuYmluZCh0aGlzLnNlc3Npb24pLFxuICAgICAgICBwYXJ0aWNpcGFudEV2aWN0ZWQ6IHRoaXMuc2Vzc2lvbi5vblBhcnRpY2lwYW50RXZpY3RlZC5iaW5kKHRoaXMuc2Vzc2lvbiksXG4gICAgICAgIHJlY29yZGluZ1N0YXJ0ZWQ6IHRoaXMuc2Vzc2lvbi5vblJlY29yZGluZ1N0YXJ0ZWQuYmluZCh0aGlzLnNlc3Npb24pLFxuICAgICAgICByZWNvcmRpbmdTdG9wcGVkOiB0aGlzLnNlc3Npb24ub25SZWNvcmRpbmdTdG9wcGVkLmJpbmQodGhpcy5zZXNzaW9uKSxcbiAgICAgICAgc2VuZE1lc3NhZ2U6IHRoaXMuc2Vzc2lvbi5vbk5ld01lc3NhZ2UuYmluZCh0aGlzLnNlc3Npb24pLFxuICAgICAgICBzdHJlYW1Qcm9wZXJ0eUNoYW5nZWQ6IHRoaXMuc2Vzc2lvbi5vblN0cmVhbVByb3BlcnR5Q2hhbmdlZC5iaW5kKHRoaXMuc2Vzc2lvbiksXG4gICAgICAgIGljZUNhbmRpZGF0ZTogdGhpcy5zZXNzaW9uLnJlY3ZJY2VDYW5kaWRhdGUuYmluZCh0aGlzLnNlc3Npb24pLFxuICAgICAgICBtZWRpYUVycm9yOiB0aGlzLnNlc3Npb24ub25NZWRpYUVycm9yLmJpbmQodGhpcy5zZXNzaW9uKVxuICAgICAgfVxuICAgIH07XG4gICAgdGhpcy5qc29uUnBjQ2xpZW50ID0gbmV3IFJwY0J1aWxkZXIuY2xpZW50cy5Kc29uUnBjQ2xpZW50KGNvbmZpZyk7XG4gIH1cblxuICAvKipcbiAgICogQGhpZGRlblxuICAgKi9cbiAgY2xvc2VXcygpOiB2b2lkIHtcbiAgICB0aGlzLmpzb25ScGNDbGllbnQuY2xvc2UoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICBzZW5kUmVxdWVzdChtZXRob2Q6IHN0cmluZywgcGFyYW1zOiBhbnksIGNhbGxiYWNrPyk6IHZvaWQge1xuICAgIGlmIChwYXJhbXMgJiYgcGFyYW1zIGluc3RhbmNlb2YgRnVuY3Rpb24pIHtcbiAgICAgIGNhbGxiYWNrID0gcGFyYW1zO1xuICAgICAgcGFyYW1zID0ge307XG4gICAgfVxuICAgIGNvbnNvbGUuZGVidWcoJ1NlbmRpbmcgcmVxdWVzdDoge21ldGhvZDpcIicgKyBtZXRob2QgKyAnXCIsIHBhcmFtczogJyArIEpTT04uc3RyaW5naWZ5KHBhcmFtcykgKyAnfScpO1xuICAgIHRoaXMuanNvblJwY0NsaWVudC5zZW5kKG1ldGhvZCwgcGFyYW1zLCBjYWxsYmFjayk7XG4gIH1cblxuICAvKipcbiAgICogQGhpZGRlblxuICAgKi9cbiAgaXNNZWRpYVN0cmVhbVRyYWNrKG1lZGlhU291cmNlOiBhbnkpOiBib29sZWFuIHtcbiAgICBjb25zdCBpcyA9ICghIW1lZGlhU291cmNlICYmXG4gICAgICBtZWRpYVNvdXJjZS5lbmFibGVkICE9PSB1bmRlZmluZWQgJiYgdHlwZW9mIG1lZGlhU291cmNlLmVuYWJsZWQgPT09ICdib29sZWFuJyAmJlxuICAgICAgbWVkaWFTb3VyY2UuaWQgIT09IHVuZGVmaW5lZCAmJiB0eXBlb2YgbWVkaWFTb3VyY2UuaWQgPT09ICdzdHJpbmcnICYmXG4gICAgICBtZWRpYVNvdXJjZS5raW5kICE9PSB1bmRlZmluZWQgJiYgdHlwZW9mIG1lZGlhU291cmNlLmtpbmQgPT09ICdzdHJpbmcnICYmXG4gICAgICBtZWRpYVNvdXJjZS5sYWJlbCAhPT0gdW5kZWZpbmVkICYmIHR5cGVvZiBtZWRpYVNvdXJjZS5sYWJlbCA9PT0gJ3N0cmluZycgJiZcbiAgICAgIG1lZGlhU291cmNlLm11dGVkICE9PSB1bmRlZmluZWQgJiYgdHlwZW9mIG1lZGlhU291cmNlLm11dGVkID09PSAnYm9vbGVhbicgJiZcbiAgICAgIG1lZGlhU291cmNlLnJlYWR5U3RhdGUgIT09IHVuZGVmaW5lZCAmJiB0eXBlb2YgbWVkaWFTb3VyY2UucmVhZHlTdGF0ZSA9PT0gJ3N0cmluZycpO1xuICAgIHJldHVybiBpcztcbiAgfVxuXG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICBnZXRXc1VyaSgpOiBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLndzVXJpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBoaWRkZW5cbiAgICovXG4gIGdldFNlY3JldCgpOiBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLnNlY3JldDtcbiAgfVxuXG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICBnZXRSZWNvcmRlcigpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5yZWNvcmRlcjtcbiAgfVxuXG5cbiAgLyogUHJpdmF0ZSBtZXRob2RzICovXG5cbiAgcHJpdmF0ZSBkaXNjb25uZWN0Q2FsbGJhY2soKTogdm9pZCB7XG4gICAgY29uc29sZS53YXJuKCdXZWJzb2NrZXQgY29ubmVjdGlvbiBsb3N0Jyk7XG4gICAgaWYgKHRoaXMuaXNSb29tQXZhaWxhYmxlKCkpIHtcbiAgICAgIHRoaXMuc2Vzc2lvbi5vbkxvc3RDb25uZWN0aW9uKCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGFsZXJ0KCdDb25uZWN0aW9uIGVycm9yLiBQbGVhc2UgcmVsb2FkIHBhZ2UuJyk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSByZWNvbm5lY3RpbmdDYWxsYmFjaygpOiB2b2lkIHtcbiAgICBjb25zb2xlLndhcm4oJ1dlYnNvY2tldCBjb25uZWN0aW9uIGxvc3QgKHJlY29ubmVjdGluZyknKTtcbiAgICBpZiAodGhpcy5pc1Jvb21BdmFpbGFibGUoKSkge1xuICAgICAgdGhpcy5zZXNzaW9uLm9uTG9zdENvbm5lY3Rpb24oKTtcbiAgICB9IGVsc2Uge1xuICAgICAgYWxlcnQoJ0Nvbm5lY3Rpb24gZXJyb3IuIFBsZWFzZSByZWxvYWQgcGFnZS4nKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIHJlY29ubmVjdGVkQ2FsbGJhY2soKTogdm9pZCB7XG4gICAgY29uc29sZS53YXJuKCdXZWJzb2NrZXQgcmVjb25uZWN0ZWQnKTtcbiAgICBpZiAodGhpcy5pc1Jvb21BdmFpbGFibGUoKSkge1xuICAgICAgdGhpcy5zZXNzaW9uLm9uUmVjb3ZlcmVkQ29ubmVjdGlvbigpO1xuICAgIH0gZWxzZSB7XG4gICAgICBhbGVydCgnQ29ubmVjdGlvbiBlcnJvci4gUGxlYXNlIHJlbG9hZCBwYWdlLicpO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgaXNSb29tQXZhaWxhYmxlKCk6IGJvb2xlYW4ge1xuICAgIGlmICh0aGlzLnNlc3Npb24gIT09IHVuZGVmaW5lZCAmJiB0aGlzLnNlc3Npb24gaW5zdGFuY2VvZiBTZXNzaW9uKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9IGVsc2Uge1xuICAgICAgY29uc29sZS53YXJuKCdTZXNzaW9uIGluc3RhbmNlIG5vdCBmb3VuZCcpO1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfVxuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBPcGVuVmlkdSB9IGZyb20gJy4vT3BlblZpZHUnO1xuaW1wb3J0IHsgU2Vzc2lvbiB9IGZyb20gJy4vU2Vzc2lvbic7XG5pbXBvcnQgeyBTdHJlYW0gfSBmcm9tICcuL1N0cmVhbSc7XG5pbXBvcnQgeyBTdHJlYW1NYW5hZ2VyIH0gZnJvbSAnLi9TdHJlYW1NYW5hZ2VyJztcbmltcG9ydCB7IEV2ZW50RGlzcGF0Y2hlciB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvSW50ZXJmYWNlcy9QdWJsaWMvRXZlbnREaXNwYXRjaGVyJztcbmltcG9ydCB7IFB1Ymxpc2hlclByb3BlcnRpZXMgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHVibGljL1B1Ymxpc2hlclByb3BlcnRpZXMnO1xuaW1wb3J0IHsgRXZlbnQgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0V2ZW50cy9FdmVudCc7XG5pbXBvcnQgeyBTdHJlYW1FdmVudCB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1N0cmVhbUV2ZW50JztcbmltcG9ydCB7IFN0cmVhbVByb3BlcnR5Q2hhbmdlZEV2ZW50IH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvU3RyZWFtUHJvcGVydHlDaGFuZ2VkRXZlbnQnO1xuaW1wb3J0IHsgVmlkZW9FbGVtZW50RXZlbnQgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0V2ZW50cy9WaWRlb0VsZW1lbnRFdmVudCc7XG5pbXBvcnQgeyBPcGVuVmlkdUVycm9yLCBPcGVuVmlkdUVycm9yTmFtZSB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRW51bXMvT3BlblZpZHVFcnJvcic7XG5pbXBvcnQgeyBWaWRlb0luc2VydE1vZGUgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0VudW1zL1ZpZGVvSW5zZXJ0TW9kZSc7XG5cbmltcG9ydCBwbGF0Zm9ybSA9IHJlcXVpcmUoJ3BsYXRmb3JtJyk7XG5cblxuLyoqXG4gKiBQYWNrcyBsb2NhbCBtZWRpYSBzdHJlYW1zLiBQYXJ0aWNpcGFudHMgY2FuIHB1Ymxpc2ggaXQgdG8gYSBzZXNzaW9uLiBJbml0aWFsaXplZCB3aXRoIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dIG1ldGhvZFxuICovXG5leHBvcnQgY2xhc3MgUHVibGlzaGVyIGV4dGVuZHMgU3RyZWFtTWFuYWdlciB7XG5cbiAgICAvKipcbiAgICAgKiBXaGV0aGVyIHRoZSBQdWJsaXNoZXIgaGFzIGJlZW4gZ3JhbnRlZCBhY2Nlc3MgdG8gdGhlIHJlcXVlc3RlZCBpbnB1dCBkZXZpY2VzIG9yIG5vdFxuICAgICAqL1xuICAgIGFjY2Vzc0FsbG93ZWQgPSBmYWxzZTtcblxuICAgIC8qKlxuICAgICAqIFdoZXRoZXIgeW91IGhhdmUgY2FsbGVkIFtbUHVibGlzaGVyLnN1YnNjcmliZVRvUmVtb3RlXV0gd2l0aCB2YWx1ZSBgdHJ1ZWAgb3IgYGZhbHNlYCAoKmZhbHNlKiBieSBkZWZhdWx0KVxuICAgICAqL1xuICAgIGlzU3Vic2NyaWJlZFRvUmVtb3RlID0gZmFsc2U7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgW1tTZXNzaW9uXV0gdG8gd2hpY2ggdGhlIFB1Ymxpc2hlciBiZWxvbmdzXG4gICAgICovXG4gICAgc2Vzc2lvbjogU2Vzc2lvbjsgLy8gSW5pdGlhbGl6ZWQgYnkgU2Vzc2lvbi5wdWJsaXNoKFB1Ymxpc2hlcilcblxuICAgIHByaXZhdGUgYWNjZXNzRGVuaWVkID0gZmFsc2U7XG4gICAgcHJpdmF0ZSBwcm9wZXJ0aWVzOiBQdWJsaXNoZXJQcm9wZXJ0aWVzO1xuICAgIHByaXZhdGUgcGVybWlzc2lvbkRpYWxvZ1RpbWVvdXQ6IE5vZGVKUy5UaW1lcjtcblxuICAgIC8qKlxuICAgICAqIGhpZGRlblxuICAgICAqL1xuICAgIG9wZW52aWR1OiBPcGVuVmlkdTtcbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgdmlkZW9SZWZlcmVuY2U6IEhUTUxWaWRlb0VsZW1lbnQ7XG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHNjcmVlblNoYXJlUmVzaXplSW50ZXJ2YWw6IE5vZGVKUy5UaW1lcjtcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3Rvcih0YXJnRWw6IHN0cmluZyB8IEhUTUxFbGVtZW50LCBwcm9wZXJ0aWVzOiBQdWJsaXNoZXJQcm9wZXJ0aWVzLCBvcGVudmlkdTogT3BlblZpZHUpIHtcbiAgICAgICAgc3VwZXIobmV3IFN0cmVhbSgoISFvcGVudmlkdS5zZXNzaW9uKSA/IG9wZW52aWR1LnNlc3Npb24gOiBuZXcgU2Vzc2lvbihvcGVudmlkdSksIHsgcHVibGlzaGVyUHJvcGVydGllczogcHJvcGVydGllcywgbWVkaWFDb25zdHJhaW50czoge30gfSksIHRhcmdFbCk7XG4gICAgICAgIHRoaXMucHJvcGVydGllcyA9IHByb3BlcnRpZXM7XG4gICAgICAgIHRoaXMub3BlbnZpZHUgPSBvcGVudmlkdTtcblxuICAgICAgICB0aGlzLnN0cmVhbS5lZS5vbignbG9jYWwtc3RyZWFtLWRlc3Ryb3llZCcsIChyZWFzb246IHN0cmluZykgPT4ge1xuICAgICAgICAgICAgdGhpcy5zdHJlYW0uaXNMb2NhbFN0cmVhbVB1Ymxpc2hlZCA9IGZhbHNlO1xuICAgICAgICAgICAgY29uc3Qgc3RyZWFtRXZlbnQgPSBuZXcgU3RyZWFtRXZlbnQodHJ1ZSwgdGhpcywgJ3N0cmVhbURlc3Ryb3llZCcsIHRoaXMuc3RyZWFtLCByZWFzb24pO1xuICAgICAgICAgICAgdGhpcy5lbWl0RXZlbnQoJ3N0cmVhbURlc3Ryb3llZCcsIFtzdHJlYW1FdmVudF0pO1xuICAgICAgICAgICAgc3RyZWFtRXZlbnQuY2FsbERlZmF1bHRCZWhhdmlvcigpO1xuICAgICAgICB9KTtcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFB1Ymxpc2ggb3IgdW5wdWJsaXNoIHRoZSBhdWRpbyBzdHJlYW0gKGlmIGF2YWlsYWJsZSkuIENhbGxpbmcgdGhpcyBtZXRob2QgdHdpY2UgaW4gYSByb3cgcGFzc2luZyBzYW1lIHZhbHVlIHdpbGwgaGF2ZSBubyBlZmZlY3RcbiAgICAgKlxuICAgICAqICMjIyMgRXZlbnRzIGRpc3BhdGNoZWRcbiAgICAgKlxuICAgICAqIFRoZSBbW1Nlc3Npb25dXSBvYmplY3Qgb2YgdGhlIGxvY2FsIHBhcnRpY2lwYW50IHdpbGwgZGlzcGF0Y2ggYSBgc3RyZWFtUHJvcGVydHlDaGFuZ2VkYCBldmVudCB3aXRoIGBjaGFuZ2VkUHJvcGVydHlgIHNldCB0byBgXCJhdWRpb0FjdGl2ZVwiYCBhbmQgYHJlYXNvbmAgc2V0IHRvIGBcInB1Ymxpc2hBdWRpb1wiYFxuICAgICAqIFRoZSBbW1B1Ymxpc2hlcl1dIG9iamVjdCBvZiB0aGUgbG9jYWwgcGFydGljaXBhbnQgd2lsbCBhbHNvIGRpc3BhdGNoIHRoZSBleGFjdCBzYW1lIGV2ZW50XG4gICAgICpcbiAgICAgKiBUaGUgW1tTZXNzaW9uXV0gb2JqZWN0IG9mIGV2ZXJ5IG90aGVyIHBhcnRpY2lwYW50IGNvbm5lY3RlZCB0byB0aGUgc2Vzc2lvbiB3aWxsIGRpc3BhdGNoIGEgYHN0cmVhbVByb3BlcnR5Q2hhbmdlZGAgZXZlbnQgd2l0aCBgY2hhbmdlZFByb3BlcnR5YCBzZXQgdG8gYFwiYXVkaW9BY3RpdmVcImAgYW5kIGByZWFzb25gIHNldCB0byBgXCJwdWJsaXNoQXVkaW9cImBcbiAgICAgKiBUaGUgcmVzcGVjdGl2ZSBbW1N1YnNjcmliZXJdXSBvYmplY3Qgb2YgZXZlcnkgb3RoZXIgcGFydGljaXBhbnQgcmVjZWl2aW5nIHRoaXMgUHVibGlzaGVyJ3Mgc3RyZWFtIHdpbGwgYWxzbyBkaXNwYXRjaCB0aGUgZXhhY3Qgc2FtZSBldmVudFxuICAgICAqXG4gICAgICogU2VlIFtbU3RyZWFtUHJvcGVydHlDaGFuZ2VkRXZlbnRdXSB0byBsZWFybiBtb3JlLlxuICAgICAqXG4gICAgICogQHBhcmFtIHZhbHVlIGB0cnVlYCB0byBwdWJsaXNoIHRoZSBhdWRpbyBzdHJlYW0sIGBmYWxzZWAgdG8gdW5wdWJsaXNoIGl0XG4gICAgICovXG4gICAgcHVibGlzaEF1ZGlvKHZhbHVlOiBib29sZWFuKTogdm9pZCB7XG4gICAgICAgIGlmICh0aGlzLnN0cmVhbS5hdWRpb0FjdGl2ZSAhPT0gdmFsdWUpIHtcbiAgICAgICAgICAgIHRoaXMuc3RyZWFtLmdldE1lZGlhU3RyZWFtKCkuZ2V0QXVkaW9UcmFja3MoKS5mb3JFYWNoKCh0cmFjaykgPT4ge1xuICAgICAgICAgICAgICAgIHRyYWNrLmVuYWJsZWQgPSB2YWx1ZTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgdGhpcy5zZXNzaW9uLm9wZW52aWR1LnNlbmRSZXF1ZXN0KFxuICAgICAgICAgICAgICAgICdzdHJlYW1Qcm9wZXJ0eUNoYW5nZWQnLFxuICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgc3RyZWFtSWQ6IHRoaXMuc3RyZWFtLnN0cmVhbUlkLFxuICAgICAgICAgICAgICAgICAgICBwcm9wZXJ0eTogJ2F1ZGlvQWN0aXZlJyxcbiAgICAgICAgICAgICAgICAgICAgbmV3VmFsdWU6IHZhbHVlLFxuICAgICAgICAgICAgICAgICAgICByZWFzb246ICdwdWJsaXNoQXVkaW8nXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAoZXJyb3IsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihcIkVycm9yIHNlbmRpbmcgJ3N0cmVhbVByb3BlcnR5Q2hhbmdlZCcgZXZlbnRcIiwgZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXNzaW9uLmVtaXRFdmVudCgnc3RyZWFtUHJvcGVydHlDaGFuZ2VkJywgW25ldyBTdHJlYW1Qcm9wZXJ0eUNoYW5nZWRFdmVudCh0aGlzLnNlc3Npb24sIHRoaXMuc3RyZWFtLCAnYXVkaW9BY3RpdmUnLCB2YWx1ZSwgIXZhbHVlLCAncHVibGlzaEF1ZGlvJyldKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZW1pdEV2ZW50KCdzdHJlYW1Qcm9wZXJ0eUNoYW5nZWQnLCBbbmV3IFN0cmVhbVByb3BlcnR5Q2hhbmdlZEV2ZW50KHRoaXMsIHRoaXMuc3RyZWFtLCAnYXVkaW9BY3RpdmUnLCB2YWx1ZSwgIXZhbHVlLCAncHVibGlzaEF1ZGlvJyldKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgdGhpcy5zdHJlYW0uYXVkaW9BY3RpdmUgPSB2YWx1ZTtcbiAgICAgICAgICAgIGNvbnNvbGUuaW5mbyhcIidQdWJsaXNoZXInIGhhcyBcIiArICh2YWx1ZSA/ICdwdWJsaXNoZWQnIDogJ3VucHVibGlzaGVkJykgKyAnIGl0cyBhdWRpbyBzdHJlYW0nKTtcbiAgICAgICAgfVxuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogUHVibGlzaCBvciB1bnB1Ymxpc2ggdGhlIHZpZGVvIHN0cmVhbSAoaWYgYXZhaWxhYmxlKS4gQ2FsbGluZyB0aGlzIG1ldGhvZCB0d2ljZSBpbiBhIHJvdyBwYXNzaW5nIHNhbWUgdmFsdWUgd2lsbCBoYXZlIG5vIGVmZmVjdFxuICAgICAqXG4gICAgICogIyMjIyBFdmVudHMgZGlzcGF0Y2hlZFxuICAgICAqXG4gICAgICogVGhlIFtbU2Vzc2lvbl1dIG9iamVjdCBvZiB0aGUgbG9jYWwgcGFydGljaXBhbnQgd2lsbCBkaXNwYXRjaCBhIGBzdHJlYW1Qcm9wZXJ0eUNoYW5nZWRgIGV2ZW50IHdpdGggYGNoYW5nZWRQcm9wZXJ0eWAgc2V0IHRvIGBcInZpZGVvQWN0aXZlXCJgIGFuZCBgcmVhc29uYCBzZXQgdG8gYFwicHVibGlzaFZpZGVvXCJgXG4gICAgICogVGhlIFtbUHVibGlzaGVyXV0gb2JqZWN0IG9mIHRoZSBsb2NhbCBwYXJ0aWNpcGFudCB3aWxsIGFsc28gZGlzcGF0Y2ggdGhlIGV4YWN0IHNhbWUgZXZlbnRcbiAgICAgKlxuICAgICAqIFRoZSBbW1Nlc3Npb25dXSBvYmplY3Qgb2YgZXZlcnkgb3RoZXIgcGFydGljaXBhbnQgY29ubmVjdGVkIHRvIHRoZSBzZXNzaW9uIHdpbGwgZGlzcGF0Y2ggYSBgc3RyZWFtUHJvcGVydHlDaGFuZ2VkYCBldmVudCB3aXRoIGBjaGFuZ2VkUHJvcGVydHlgIHNldCB0byBgXCJ2aWRlb0FjdGl2ZVwiYCBhbmQgYHJlYXNvbmAgc2V0IHRvIGBcInB1Ymxpc2hWaWRlb1wiYFxuICAgICAqIFRoZSByZXNwZWN0aXZlIFtbU3Vic2NyaWJlcl1dIG9iamVjdCBvZiBldmVyeSBvdGhlciBwYXJ0aWNpcGFudCByZWNlaXZpbmcgdGhpcyBQdWJsaXNoZXIncyBzdHJlYW0gd2lsbCBhbHNvIGRpc3BhdGNoIHRoZSBleGFjdCBzYW1lIGV2ZW50XG4gICAgICpcbiAgICAgKiBTZWUgW1tTdHJlYW1Qcm9wZXJ0eUNoYW5nZWRFdmVudF1dIHRvIGxlYXJuIG1vcmUuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gdmFsdWUgYHRydWVgIHRvIHB1Ymxpc2ggdGhlIHZpZGVvIHN0cmVhbSwgYGZhbHNlYCB0byB1bnB1Ymxpc2ggaXRcbiAgICAgKi9cbiAgICBwdWJsaXNoVmlkZW8odmFsdWU6IGJvb2xlYW4pOiB2b2lkIHtcbiAgICAgICAgaWYgKHRoaXMuc3RyZWFtLnZpZGVvQWN0aXZlICE9PSB2YWx1ZSkge1xuICAgICAgICAgICAgdGhpcy5zdHJlYW0uZ2V0TWVkaWFTdHJlYW0oKS5nZXRWaWRlb1RyYWNrcygpLmZvckVhY2goKHRyYWNrKSA9PiB7XG4gICAgICAgICAgICAgICAgdHJhY2suZW5hYmxlZCA9IHZhbHVlO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB0aGlzLnNlc3Npb24ub3BlbnZpZHUuc2VuZFJlcXVlc3QoXG4gICAgICAgICAgICAgICAgJ3N0cmVhbVByb3BlcnR5Q2hhbmdlZCcsXG4gICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICBzdHJlYW1JZDogdGhpcy5zdHJlYW0uc3RyZWFtSWQsXG4gICAgICAgICAgICAgICAgICAgIHByb3BlcnR5OiAndmlkZW9BY3RpdmUnLFxuICAgICAgICAgICAgICAgICAgICBuZXdWYWx1ZTogdmFsdWUsXG4gICAgICAgICAgICAgICAgICAgIHJlYXNvbjogJ3B1Ymxpc2hWaWRlbydcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIChlcnJvciwgcmVzcG9uc2UpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKFwiRXJyb3Igc2VuZGluZyAnc3RyZWFtUHJvcGVydHlDaGFuZ2VkJyBldmVudFwiLCBlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnNlc3Npb24uZW1pdEV2ZW50KCdzdHJlYW1Qcm9wZXJ0eUNoYW5nZWQnLCBbbmV3IFN0cmVhbVByb3BlcnR5Q2hhbmdlZEV2ZW50KHRoaXMuc2Vzc2lvbiwgdGhpcy5zdHJlYW0sICd2aWRlb0FjdGl2ZScsIHZhbHVlLCAhdmFsdWUsICdwdWJsaXNoVmlkZW8nKV0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5lbWl0RXZlbnQoJ3N0cmVhbVByb3BlcnR5Q2hhbmdlZCcsIFtuZXcgU3RyZWFtUHJvcGVydHlDaGFuZ2VkRXZlbnQodGhpcywgdGhpcy5zdHJlYW0sICd2aWRlb0FjdGl2ZScsIHZhbHVlLCAhdmFsdWUsICdwdWJsaXNoVmlkZW8nKV0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB0aGlzLnN0cmVhbS52aWRlb0FjdGl2ZSA9IHZhbHVlO1xuICAgICAgICAgICAgY29uc29sZS5pbmZvKFwiJ1B1Ymxpc2hlcicgaGFzIFwiICsgKHZhbHVlID8gJ3B1Ymxpc2hlZCcgOiAndW5wdWJsaXNoZWQnKSArICcgaXRzIHZpZGVvIHN0cmVhbScpO1xuICAgICAgICB9XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBDYWxsIHRoaXMgbWV0aG9kIGJlZm9yZSBbW1Nlc3Npb24ucHVibGlzaF1dIGlmIHlvdSBwcmVmZXIgdG8gc3Vic2NyaWJlIHRvIHlvdXIgUHVibGlzaGVyJ3MgcmVtb3RlIHN0cmVhbSBpbnN0ZWFkIG9mIHVzaW5nIHRoZSBsb2NhbCBzdHJlYW0sIGFzIGFueSBvdGhlciB1c2VyIHdvdWxkIGRvLlxuICAgICAqL1xuICAgIHN1YnNjcmliZVRvUmVtb3RlKHZhbHVlPzogYm9vbGVhbik6IHZvaWQge1xuICAgICAgICB2YWx1ZSA9ICh2YWx1ZSAhPT0gdW5kZWZpbmVkKSA/IHZhbHVlIDogdHJ1ZTtcbiAgICAgICAgdGhpcy5pc1N1YnNjcmliZWRUb1JlbW90ZSA9IHZhbHVlO1xuICAgICAgICB0aGlzLnN0cmVhbS5zdWJzY3JpYmVUb015UmVtb3RlKHZhbHVlKTtcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFNlZSBbW0V2ZW50RGlzcGF0Y2hlci5vbl1dXG4gICAgICovXG4gICAgb24odHlwZTogc3RyaW5nLCBoYW5kbGVyOiAoZXZlbnQ6IEV2ZW50KSA9PiB2b2lkKTogRXZlbnREaXNwYXRjaGVyIHtcbiAgICAgICAgc3VwZXIub24odHlwZSwgaGFuZGxlcik7XG4gICAgICAgIGlmICh0eXBlID09PSAnc3RyZWFtQ3JlYXRlZCcpIHtcbiAgICAgICAgICAgIGlmICghIXRoaXMuc3RyZWFtICYmIHRoaXMuc3RyZWFtLmlzTG9jYWxTdHJlYW1QdWJsaXNoZWQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVtaXRFdmVudCgnc3RyZWFtQ3JlYXRlZCcsIFtuZXcgU3RyZWFtRXZlbnQoZmFsc2UsIHRoaXMsICdzdHJlYW1DcmVhdGVkJywgdGhpcy5zdHJlYW0sICcnKV0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbS5lZS5vbignc3RyZWFtLWNyZWF0ZWQtYnktcHVibGlzaGVyJywgKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmVtaXRFdmVudCgnc3RyZWFtQ3JlYXRlZCcsIFtuZXcgU3RyZWFtRXZlbnQoZmFsc2UsIHRoaXMsICdzdHJlYW1DcmVhdGVkJywgdGhpcy5zdHJlYW0sICcnKV0pO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmICh0eXBlID09PSAncmVtb3RlVmlkZW9QbGF5aW5nJykge1xuICAgICAgICAgICAgaWYgKHRoaXMuc3RyZWFtLmRpc3BsYXlNeVJlbW90ZSgpICYmIHRoaXMudmlkZW9zWzBdICYmIHRoaXMudmlkZW9zWzBdLnZpZGVvICYmXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8uY3VycmVudFRpbWUgPiAwICYmXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8ucGF1c2VkID09PSBmYWxzZSAmJlxuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9zWzBdLnZpZGVvLmVuZGVkID09PSBmYWxzZSAmJlxuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9zWzBdLnZpZGVvLnJlYWR5U3RhdGUgPT09IDQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVtaXRFdmVudCgncmVtb3RlVmlkZW9QbGF5aW5nJywgW25ldyBWaWRlb0VsZW1lbnRFdmVudCh0aGlzLnZpZGVvc1swXS52aWRlbywgdGhpcywgJ3JlbW90ZVZpZGVvUGxheWluZycpXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHR5cGUgPT09ICdhY2Nlc3NBbGxvd2VkJykge1xuICAgICAgICAgICAgaWYgKHRoaXMuYWNjZXNzQWxsb3dlZCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZW1pdEV2ZW50KCdhY2Nlc3NBbGxvd2VkJywgW10pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmICh0eXBlID09PSAnYWNjZXNzRGVuaWVkJykge1xuICAgICAgICAgICAgaWYgKHRoaXMuYWNjZXNzRGVuaWVkKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5lbWl0RXZlbnQoJ2FjY2Vzc0RlbmllZCcsIFtdKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFNlZSBbW0V2ZW50RGlzcGF0Y2hlci5vbmNlXV1cbiAgICAgKi9cbiAgICBvbmNlKHR5cGU6IHN0cmluZywgaGFuZGxlcjogKGV2ZW50OiBFdmVudCkgPT4gdm9pZCk6IFB1Ymxpc2hlciB7XG4gICAgICAgIHN1cGVyLm9uY2UodHlwZSwgaGFuZGxlcik7XG4gICAgICAgIGlmICh0eXBlID09PSAnc3RyZWFtQ3JlYXRlZCcpIHtcbiAgICAgICAgICAgIGlmICghIXRoaXMuc3RyZWFtICYmIHRoaXMuc3RyZWFtLmlzTG9jYWxTdHJlYW1QdWJsaXNoZWQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVtaXRFdmVudCgnc3RyZWFtQ3JlYXRlZCcsIFtuZXcgU3RyZWFtRXZlbnQoZmFsc2UsIHRoaXMsICdzdHJlYW1DcmVhdGVkJywgdGhpcy5zdHJlYW0sICcnKV0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbS5lZS5vbmNlKCdzdHJlYW0tY3JlYXRlZC1ieS1wdWJsaXNoZXInLCAoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZW1pdEV2ZW50KCdzdHJlYW1DcmVhdGVkJywgW25ldyBTdHJlYW1FdmVudChmYWxzZSwgdGhpcywgJ3N0cmVhbUNyZWF0ZWQnLCB0aGlzLnN0cmVhbSwgJycpXSk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHR5cGUgPT09ICdyZW1vdGVWaWRlb1BsYXlpbmcnKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5zdHJlYW0uZGlzcGxheU15UmVtb3RlKCkgJiYgdGhpcy52aWRlb3NbMF0gJiYgdGhpcy52aWRlb3NbMF0udmlkZW8gJiZcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvc1swXS52aWRlby5jdXJyZW50VGltZSA+IDAgJiZcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvc1swXS52aWRlby5wYXVzZWQgPT09IGZhbHNlICYmXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8uZW5kZWQgPT09IGZhbHNlICYmXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8ucmVhZHlTdGF0ZSA9PT0gNCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZW1pdEV2ZW50KCdyZW1vdGVWaWRlb1BsYXlpbmcnLCBbbmV3IFZpZGVvRWxlbWVudEV2ZW50KHRoaXMudmlkZW9zWzBdLnZpZGVvLCB0aGlzLCAncmVtb3RlVmlkZW9QbGF5aW5nJyldKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAodHlwZSA9PT0gJ2FjY2Vzc0FsbG93ZWQnKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5hY2Nlc3NBbGxvd2VkKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5lbWl0RXZlbnQoJ2FjY2Vzc0FsbG93ZWQnLCBbXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHR5cGUgPT09ICdhY2Nlc3NEZW5pZWQnKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5hY2Nlc3NEZW5pZWQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVtaXRFdmVudCgnYWNjZXNzRGVuaWVkJywgW10pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuXG4gICAgLyogSGlkZGVuIG1ldGhvZHMgKi9cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBpbml0aWFsaXplKCk6IFByb21pc2U8YW55PiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG5cbiAgICAgICAgICAgIGNvbnN0IGVycm9yQ2FsbGJhY2sgPSAob3BlblZpZHVFcnJvcjogT3BlblZpZHVFcnJvcikgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuYWNjZXNzRGVuaWVkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB0aGlzLmFjY2Vzc0FsbG93ZWQgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICByZWplY3Qob3BlblZpZHVFcnJvcik7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICBjb25zdCBzdWNjZXNzQ2FsbGJhY2sgPSAobWVkaWFTdHJlYW06IE1lZGlhU3RyZWFtKSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5hY2Nlc3NBbGxvd2VkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB0aGlzLmFjY2Vzc0RlbmllZCA9IGZhbHNlO1xuXG4gICAgICAgICAgICAgICAgaWYgKHRoaXMub3BlbnZpZHUuaXNNZWRpYVN0cmVhbVRyYWNrKHRoaXMucHJvcGVydGllcy5hdWRpb1NvdXJjZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgbWVkaWFTdHJlYW0ucmVtb3ZlVHJhY2sobWVkaWFTdHJlYW0uZ2V0QXVkaW9UcmFja3MoKVswXSk7XG4gICAgICAgICAgICAgICAgICAgIG1lZGlhU3RyZWFtLmFkZFRyYWNrKCg8TWVkaWFTdHJlYW1UcmFjaz50aGlzLnByb3BlcnRpZXMuYXVkaW9Tb3VyY2UpKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAodGhpcy5vcGVudmlkdS5pc01lZGlhU3RyZWFtVHJhY2sodGhpcy5wcm9wZXJ0aWVzLnZpZGVvU291cmNlKSkge1xuICAgICAgICAgICAgICAgICAgICBtZWRpYVN0cmVhbS5yZW1vdmVUcmFjayhtZWRpYVN0cmVhbS5nZXRWaWRlb1RyYWNrcygpWzBdKTtcbiAgICAgICAgICAgICAgICAgICAgbWVkaWFTdHJlYW0uYWRkVHJhY2soKDxNZWRpYVN0cmVhbVRyYWNrPnRoaXMucHJvcGVydGllcy52aWRlb1NvdXJjZSkpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIEFwcGx5IFB1Ymxpc2hlclByb3BlcnRpZXMucHVibGlzaEF1ZGlvIGFuZCBQdWJsaXNoZXJQcm9wZXJ0aWVzLnB1Ymxpc2hWaWRlb1xuICAgICAgICAgICAgICAgIGlmICghIW1lZGlhU3RyZWFtLmdldEF1ZGlvVHJhY2tzKClbMF0pIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgZW5hYmxlZCA9ICh0aGlzLnN0cmVhbS5hdWRpb0FjdGl2ZSAhPT0gdW5kZWZpbmVkICYmIHRoaXMuc3RyZWFtLmF1ZGlvQWN0aXZlICE9PSBudWxsKSA/IHRoaXMuc3RyZWFtLmF1ZGlvQWN0aXZlIDogISF0aGlzLnN0cmVhbS5vdXRib3VuZFN0cmVhbU9wdHMucHVibGlzaGVyUHJvcGVydGllcy5wdWJsaXNoQXVkaW87XG4gICAgICAgICAgICAgICAgICAgIG1lZGlhU3RyZWFtLmdldEF1ZGlvVHJhY2tzKClbMF0uZW5hYmxlZCA9IGVuYWJsZWQ7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmICghIW1lZGlhU3RyZWFtLmdldFZpZGVvVHJhY2tzKClbMF0pIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgZW5hYmxlZCA9ICh0aGlzLnN0cmVhbS52aWRlb0FjdGl2ZSAhPT0gdW5kZWZpbmVkICYmIHRoaXMuc3RyZWFtLnZpZGVvQWN0aXZlICE9PSBudWxsKSA/IHRoaXMuc3RyZWFtLnZpZGVvQWN0aXZlIDogISF0aGlzLnN0cmVhbS5vdXRib3VuZFN0cmVhbU9wdHMucHVibGlzaGVyUHJvcGVydGllcy5wdWJsaXNoVmlkZW87XG4gICAgICAgICAgICAgICAgICAgIG1lZGlhU3RyZWFtLmdldFZpZGVvVHJhY2tzKClbMF0uZW5hYmxlZCA9IGVuYWJsZWQ7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb1JlZmVyZW5jZSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3ZpZGVvJyk7XG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb1JlZmVyZW5jZS5zcmNPYmplY3QgPSBtZWRpYVN0cmVhbTtcblxuICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtLnNldE1lZGlhU3RyZWFtKG1lZGlhU3RyZWFtKTtcbiAgICAgICAgICAgICAgICBpZiAoIXRoaXMuc3RyZWFtLmRpc3BsYXlNeVJlbW90ZSgpKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIFdoZW4gd2UgYXJlIHN1YnNjcmliZWQgdG8gb3VyIHJlbW90ZSB3ZSBkb24ndCBzdGlsbCBzZXQgdGhlIE1lZGlhU3RyZWFtIG9iamVjdCBpbiB0aGUgdmlkZW8gZWxlbWVudHMgdG9cbiAgICAgICAgICAgICAgICAgICAgLy8gYXZvaWQgZWFybHkgJ3N0cmVhbVBsYXlpbmcnIGV2ZW50XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtLnVwZGF0ZU1lZGlhU3RyZWFtSW5WaWRlb3MoKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoISF0aGlzLmZpcnN0VmlkZW9FbGVtZW50KSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuY3JlYXRlVmlkZW9FbGVtZW50KHRoaXMuZmlyc3RWaWRlb0VsZW1lbnQudGFyZ2V0RWxlbWVudCwgPFZpZGVvSW5zZXJ0TW9kZT50aGlzLnByb3BlcnRpZXMuaW5zZXJ0TW9kZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGRlbGV0ZSB0aGlzLmZpcnN0VmlkZW9FbGVtZW50O1xuXG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuc3RyZWFtLmlzU2VuZFZpZGVvKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCF0aGlzLnN0cmVhbS5pc1NlbmRTY3JlZW4oKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gV2l0aCBubyBzY3JlZW4gc2hhcmUsIHZpZGVvIGRpbWVuc2lvbiBjYW4gYmUgc2V0IGRpcmVjdGx5IGZyb20gTWVkaWFTdHJlYW0gKGdldFNldHRpbmdzKVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gT3JpZW50YXRpb24gbXVzdCBiZSBjaGVja2VkIGZvciBtb2JpbGUgZGV2aWNlcyAod2lkdGggYW5kIGhlaWdodCBhcmUgcmV2ZXJzZWQpXG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB7IHdpZHRoLCBoZWlnaHQgfSA9IG1lZGlhU3RyZWFtLmdldFZpZGVvVHJhY2tzKClbMF0uZ2V0U2V0dGluZ3MoKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHBsYXRmb3JtLm5hbWUhIS50b0xvd2VyQ2FzZSgpLmluZGV4T2YoJ21vYmlsZScpICE9PSAtMSAmJiAod2luZG93LmlubmVySGVpZ2h0ID4gd2luZG93LmlubmVyV2lkdGgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gTW9iaWxlIHBvcnRyYWl0IG1vZGVcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbS52aWRlb0RpbWVuc2lvbnMgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdpZHRoOiBoZWlnaHQgfHwgMCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaGVpZ2h0OiB3aWR0aCB8fCAwXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdHJlYW0udmlkZW9EaW1lbnNpb25zID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3aWR0aDogd2lkdGggfHwgMCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaGVpZ2h0OiBoZWlnaHQgfHwgMFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbS5pc0xvY2FsU3RyZWFtUmVhZHlUb1B1Ymxpc2ggPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdHJlYW0uZWUuZW1pdEV2ZW50KCdzdHJlYW0tcmVhZHktdG8tcHVibGlzaCcsIFtdKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIFdpdGggc2NyZWVuIHNoYXJlLCB2aWRlbyBkaW1lbnNpb24gbXVzdCBiZSBnb3QgZnJvbSBhIHZpZGVvIGVsZW1lbnQgKG9ubG9hZGVkbWV0YWRhdGEgZXZlbnQpXG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnZpZGVvUmVmZXJlbmNlLm9ubG9hZGVkbWV0YWRhdGEgPSAoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdHJlYW0udmlkZW9EaW1lbnNpb25zID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3aWR0aDogdGhpcy52aWRlb1JlZmVyZW5jZS52aWRlb1dpZHRoLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBoZWlnaHQ6IHRoaXMudmlkZW9SZWZlcmVuY2UudmlkZW9IZWlnaHRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc2NyZWVuU2hhcmVSZXNpemVJbnRlcnZhbCA9IHNldEludGVydmFsKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZmlyZWZveFNldHRpbmdzID0gbWVkaWFTdHJlYW0uZ2V0VmlkZW9UcmFja3MoKVswXS5nZXRTZXR0aW5ncygpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBuZXdXaWR0aCA9IChwbGF0Zm9ybS5uYW1lID09PSAnQ2hyb21lJykgPyB0aGlzLnZpZGVvUmVmZXJlbmNlLnZpZGVvV2lkdGggOiBmaXJlZm94U2V0dGluZ3Mud2lkdGg7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG5ld0hlaWdodCA9IChwbGF0Zm9ybS5uYW1lID09PSAnQ2hyb21lJykgPyB0aGlzLnZpZGVvUmVmZXJlbmNlLnZpZGVvSGVpZ2h0IDogZmlyZWZveFNldHRpbmdzLmhlaWdodDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuc3RyZWFtLmlzTG9jYWxTdHJlYW1QdWJsaXNoZWQgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChuZXdXaWR0aCAhPT0gdGhpcy5zdHJlYW0udmlkZW9EaW1lbnNpb25zLndpZHRoIHx8XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3SGVpZ2h0ICE9PSB0aGlzLnN0cmVhbS52aWRlb0RpbWVuc2lvbnMuaGVpZ2h0KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3Qgb2xkVmFsdWUgPSB7IHdpZHRoOiB0aGlzLnN0cmVhbS52aWRlb0RpbWVuc2lvbnMud2lkdGgsIGhlaWdodDogdGhpcy5zdHJlYW0udmlkZW9EaW1lbnNpb25zLmhlaWdodCB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdHJlYW0udmlkZW9EaW1lbnNpb25zID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdpZHRoOiBuZXdXaWR0aCB8fCAwLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhlaWdodDogbmV3SGVpZ2h0IHx8IDBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnNlc3Npb24ub3BlbnZpZHUuc2VuZFJlcXVlc3QoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ3N0cmVhbVByb3BlcnR5Q2hhbmdlZCcsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJlYW1JZDogdGhpcy5zdHJlYW0uc3RyZWFtSWQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByb3BlcnR5OiAndmlkZW9EaW1lbnNpb25zJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3VmFsdWU6IEpTT04uc3RyaW5naWZ5KHRoaXMuc3RyZWFtLnZpZGVvRGltZW5zaW9ucyksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlYXNvbjogJ3NjcmVlblJlc2l6ZWQnXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoZXJyb3IsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihcIkVycm9yIHNlbmRpbmcgJ3N0cmVhbVByb3BlcnR5Q2hhbmdlZCcgZXZlbnRcIiwgZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXNzaW9uLmVtaXRFdmVudCgnc3RyZWFtUHJvcGVydHlDaGFuZ2VkJywgW25ldyBTdHJlYW1Qcm9wZXJ0eUNoYW5nZWRFdmVudCh0aGlzLnNlc3Npb24sIHRoaXMuc3RyZWFtLCAndmlkZW9EaW1lbnNpb25zJywgdGhpcy5zdHJlYW0udmlkZW9EaW1lbnNpb25zLCBvbGRWYWx1ZSwgJ3NjcmVlblJlc2l6ZWQnKV0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5lbWl0RXZlbnQoJ3N0cmVhbVByb3BlcnR5Q2hhbmdlZCcsIFtuZXcgU3RyZWFtUHJvcGVydHlDaGFuZ2VkRXZlbnQodGhpcywgdGhpcy5zdHJlYW0sICd2aWRlb0RpbWVuc2lvbnMnLCB0aGlzLnN0cmVhbS52aWRlb0RpbWVuc2lvbnMsIG9sZFZhbHVlLCAnc2NyZWVuUmVzaXplZCcpXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0sIDUwMCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdHJlYW0uaXNMb2NhbFN0cmVhbVJlYWR5VG9QdWJsaXNoID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbS5lZS5lbWl0RXZlbnQoJ3N0cmVhbS1yZWFkeS10by1wdWJsaXNoJywgW10pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtLmlzTG9jYWxTdHJlYW1SZWFkeVRvUHVibGlzaCA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtLmVlLmVtaXRFdmVudCgnc3RyZWFtLXJlYWR5LXRvLXB1Ymxpc2gnLCBbXSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIHRoaXMub3BlbnZpZHUuZ2VuZXJhdGVNZWRpYUNvbnN0cmFpbnRzKHRoaXMucHJvcGVydGllcylcbiAgICAgICAgICAgICAgICAudGhlbihjb25zdHJhaW50cyA9PiB7XG5cbiAgICAgICAgICAgICAgICAgICAgY29uc3Qgb3V0Ym91bmRTdHJlYW1PcHRpb25zID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgbWVkaWFDb25zdHJhaW50czogY29uc3RyYWludHMsXG4gICAgICAgICAgICAgICAgICAgICAgICBwdWJsaXNoZXJQcm9wZXJ0aWVzOiB0aGlzLnByb3BlcnRpZXNcbiAgICAgICAgICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbS5zZXRPdXRib3VuZFN0cmVhbU9wdGlvbnMob3V0Ym91bmRTdHJlYW1PcHRpb25zKTtcblxuICAgICAgICAgICAgICAgICAgICBjb25zdCBjb25zdHJhaW50c0F1eDogTWVkaWFTdHJlYW1Db25zdHJhaW50cyA9IHt9O1xuICAgICAgICAgICAgICAgICAgICBjb25zdCB0aW1lRm9yRGlhbG9nRXZlbnQgPSAxMjUwO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLnN0cmVhbS5pc1NlbmRWaWRlbygpIHx8IHRoaXMuc3RyZWFtLmlzU2VuZEF1ZGlvKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGRlZmluZWRBdWRpb0NvbnN0cmFpbnQgPSAoKGNvbnN0cmFpbnRzLmF1ZGlvID09PSB1bmRlZmluZWQpID8gdHJ1ZSA6IGNvbnN0cmFpbnRzLmF1ZGlvKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0cmFpbnRzQXV4LmF1ZGlvID0gdGhpcy5zdHJlYW0uaXNTZW5kU2NyZWVuKCkgPyBmYWxzZSA6IGRlZmluZWRBdWRpb0NvbnN0cmFpbnQ7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdHJhaW50c0F1eC52aWRlbyA9IGNvbnN0cmFpbnRzLnZpZGVvO1xuICAgICAgICAgICAgICAgICAgICAgICAgbGV0IHN0YXJ0VGltZSA9IERhdGUubm93KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnNldFBlcm1pc3Npb25EaWFsb2dUaW1lcih0aW1lRm9yRGlhbG9nRXZlbnQpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBuYXZpZ2F0b3IubWVkaWFEZXZpY2VzLmdldFVzZXJNZWRpYShjb25zdHJhaW50c0F1eClcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAudGhlbihtZWRpYVN0cmVhbSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY2xlYXJQZXJtaXNzaW9uRGlhbG9nVGltZXIoc3RhcnRUaW1lLCB0aW1lRm9yRGlhbG9nRXZlbnQpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLnN0cmVhbS5pc1NlbmRTY3JlZW4oKSAmJiB0aGlzLnN0cmVhbS5pc1NlbmRBdWRpbygpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBXaGVuIGdldHRpbmcgZGVza3RvcCBhcyB1c2VyIG1lZGlhIGF1ZGlvIGNvbnN0cmFpbnQgbXVzdCBiZSBmYWxzZS4gTm93IHdlIGNhbiBhc2sgZm9yIGl0IGlmIHJlcXVpcmVkXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdHJhaW50c0F1eC5hdWRpbyA9IGRlZmluZWRBdWRpb0NvbnN0cmFpbnQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdHJhaW50c0F1eC52aWRlbyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhcnRUaW1lID0gRGF0ZS5ub3coKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc2V0UGVybWlzc2lvbkRpYWxvZ1RpbWVyKHRpbWVGb3JEaWFsb2dFdmVudCk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hdmlnYXRvci5tZWRpYURldmljZXMuZ2V0VXNlck1lZGlhKGNvbnN0cmFpbnRzQXV4KVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC50aGVuKGF1ZGlvT25seVN0cmVhbSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY2xlYXJQZXJtaXNzaW9uRGlhbG9nVGltZXIoc3RhcnRUaW1lLCB0aW1lRm9yRGlhbG9nRXZlbnQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZWRpYVN0cmVhbS5hZGRUcmFjayhhdWRpb09ubHlTdHJlYW0uZ2V0QXVkaW9UcmFja3MoKVswXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN1Y2Nlc3NDYWxsYmFjayhtZWRpYVN0cmVhbSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNsZWFyUGVybWlzc2lvbkRpYWxvZ1RpbWVyKHN0YXJ0VGltZSwgdGltZUZvckRpYWxvZ0V2ZW50KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGVycm9yTmFtZSwgZXJyb3JNZXNzYWdlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzd2l0Y2ggKGVycm9yLm5hbWUudG9Mb3dlckNhc2UoKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAnbm90Zm91bmRlcnJvcic6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JOYW1lID0gT3BlblZpZHVFcnJvck5hbWUuSU5QVVRfQVVESU9fREVWSUNFX05PVF9GT1VORDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck1lc3NhZ2UgPSBlcnJvci50b1N0cmluZygpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yQ2FsbGJhY2sobmV3IE9wZW5WaWR1RXJyb3IoZXJyb3JOYW1lLCBlcnJvck1lc3NhZ2UpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJ25vdGFsbG93ZWRlcnJvcic6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JOYW1lID0gT3BlblZpZHVFcnJvck5hbWUuREVWSUNFX0FDQ0VTU19ERU5JRUQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JNZXNzYWdlID0gZXJyb3IudG9TdHJpbmcoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvckNhbGxiYWNrKG5ldyBPcGVuVmlkdUVycm9yKGVycm9yTmFtZSwgZXJyb3JNZXNzYWdlKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlICdvdmVyY29uc3RyYWluZWRlcnJvcic6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yLmNvbnN0cmFpbnQudG9Mb3dlckNhc2UoKSA9PT0gJ2RldmljZWlkJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck5hbWUgPSBPcGVuVmlkdUVycm9yTmFtZS5JTlBVVF9BVURJT19ERVZJQ0VfTk9UX0ZPVU5EO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck1lc3NhZ2UgPSBcIkF1ZGlvIGlucHV0IGRldmljZSB3aXRoIGRldmljZUlkICdcIiArICg8Q29uc3RyYWluRE9NU3RyaW5nUGFyYW1ldGVycz4oPE1lZGlhVHJhY2tDb25zdHJhaW50cz5jb25zdHJhaW50cy52aWRlbykuZGV2aWNlSWQhISkuZXhhY3QgKyBcIicgbm90IGZvdW5kXCI7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JOYW1lID0gT3BlblZpZHVFcnJvck5hbWUuUFVCTElTSEVSX1BST1BFUlRJRVNfRVJST1I7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yTWVzc2FnZSA9IFwiQXVkaW8gaW5wdXQgZGV2aWNlIGRvZXNuJ3Qgc3VwcG9ydCB0aGUgdmFsdWUgcGFzc2VkIGZvciBjb25zdHJhaW50ICdcIiArIGVycm9yLmNvbnN0cmFpbnQgKyBcIidcIjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JDYWxsYmFjayhuZXcgT3BlblZpZHVFcnJvcihlcnJvck5hbWUsIGVycm9yTWVzc2FnZSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdWNjZXNzQ2FsbGJhY2sobWVkaWFTdHJlYW0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNsZWFyUGVybWlzc2lvbkRpYWxvZ1RpbWVyKHN0YXJ0VGltZSwgdGltZUZvckRpYWxvZ0V2ZW50KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGVycm9yTmFtZSwgZXJyb3JNZXNzYWdlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzd2l0Y2ggKGVycm9yLm5hbWUudG9Mb3dlckNhc2UoKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAnbm90Zm91bmRlcnJvcic6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmF2aWdhdG9yLm1lZGlhRGV2aWNlcy5nZXRVc2VyTWVkaWEoe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhdWRpbzogZmFsc2UsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZpZGVvOiBjb25zdHJhaW50cy52aWRlb1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC50aGVuKG1lZGlhU3RyZWFtID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1lZGlhU3RyZWFtLmdldFZpZGVvVHJhY2tzKCkuZm9yRWFjaCgodHJhY2spID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cmFjay5zdG9wKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yTmFtZSA9IE9wZW5WaWR1RXJyb3JOYW1lLklOUFVUX0FVRElPX0RFVklDRV9OT1RfRk9VTkQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck1lc3NhZ2UgPSBlcnJvci50b1N0cmluZygpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JDYWxsYmFjayhuZXcgT3BlblZpZHVFcnJvcihlcnJvck5hbWUsIGVycm9yTWVzc2FnZSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KS5jYXRjaChlID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yTmFtZSA9IE9wZW5WaWR1RXJyb3JOYW1lLklOUFVUX1ZJREVPX0RFVklDRV9OT1RfRk9VTkQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck1lc3NhZ2UgPSBlcnJvci50b1N0cmluZygpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JDYWxsYmFjayhuZXcgT3BlblZpZHVFcnJvcihlcnJvck5hbWUsIGVycm9yTWVzc2FnZSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJ25vdGFsbG93ZWRlcnJvcic6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JOYW1lID0gdGhpcy5zdHJlYW0uaXNTZW5kU2NyZWVuKCkgPyBPcGVuVmlkdUVycm9yTmFtZS5TQ1JFRU5fQ0FQVFVSRV9ERU5JRUQgOiBPcGVuVmlkdUVycm9yTmFtZS5ERVZJQ0VfQUNDRVNTX0RFTklFRDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck1lc3NhZ2UgPSBlcnJvci50b1N0cmluZygpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yQ2FsbGJhY2sobmV3IE9wZW5WaWR1RXJyb3IoZXJyb3JOYW1lLCBlcnJvck1lc3NhZ2UpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJ292ZXJjb25zdHJhaW5lZGVycm9yJzpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYXZpZ2F0b3IubWVkaWFEZXZpY2VzLmdldFVzZXJNZWRpYSh7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGF1ZGlvOiBmYWxzZSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmlkZW86IGNvbnN0cmFpbnRzLnZpZGVvXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLnRoZW4obWVkaWFTdHJlYW0gPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWVkaWFTdHJlYW0uZ2V0VmlkZW9UcmFja3MoKS5mb3JFYWNoKCh0cmFjaykgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRyYWNrLnN0b3AoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yLmNvbnN0cmFpbnQudG9Mb3dlckNhc2UoKSA9PT0gJ2RldmljZWlkJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yTmFtZSA9IE9wZW5WaWR1RXJyb3JOYW1lLklOUFVUX0FVRElPX0RFVklDRV9OT1RfRk9VTkQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JNZXNzYWdlID0gXCJBdWRpbyBpbnB1dCBkZXZpY2Ugd2l0aCBkZXZpY2VJZCAnXCIgKyAoPENvbnN0cmFpbkRPTVN0cmluZ1BhcmFtZXRlcnM+KDxNZWRpYVRyYWNrQ29uc3RyYWludHM+Y29uc3RyYWludHMuYXVkaW8pLmRldmljZUlkISEpLmV4YWN0ICsgXCInIG5vdCBmb3VuZFwiO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck5hbWUgPSBPcGVuVmlkdUVycm9yTmFtZS5QVUJMSVNIRVJfUFJPUEVSVElFU19FUlJPUjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck1lc3NhZ2UgPSBcIkF1ZGlvIGlucHV0IGRldmljZSBkb2Vzbid0IHN1cHBvcnQgdGhlIHZhbHVlIHBhc3NlZCBmb3IgY29uc3RyYWludCAnXCIgKyBlcnJvci5jb25zdHJhaW50ICsgXCInXCI7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvckNhbGxiYWNrKG5ldyBPcGVuVmlkdUVycm9yKGVycm9yTmFtZSwgZXJyb3JNZXNzYWdlKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pLmNhdGNoKGUgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yLmNvbnN0cmFpbnQudG9Mb3dlckNhc2UoKSA9PT0gJ2RldmljZWlkJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yTmFtZSA9IE9wZW5WaWR1RXJyb3JOYW1lLklOUFVUX1ZJREVPX0RFVklDRV9OT1RfRk9VTkQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JNZXNzYWdlID0gXCJWaWRlbyBpbnB1dCBkZXZpY2Ugd2l0aCBkZXZpY2VJZCAnXCIgKyAoPENvbnN0cmFpbkRPTVN0cmluZ1BhcmFtZXRlcnM+KDxNZWRpYVRyYWNrQ29uc3RyYWludHM+Y29uc3RyYWludHMudmlkZW8pLmRldmljZUlkISEpLmV4YWN0ICsgXCInIG5vdCBmb3VuZFwiO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck5hbWUgPSBPcGVuVmlkdUVycm9yTmFtZS5QVUJMSVNIRVJfUFJPUEVSVElFU19FUlJPUjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck1lc3NhZ2UgPSBcIlZpZGVvIGlucHV0IGRldmljZSBkb2Vzbid0IHN1cHBvcnQgdGhlIHZhbHVlIHBhc3NlZCBmb3IgY29uc3RyYWludCAnXCIgKyBlcnJvci5jb25zdHJhaW50ICsgXCInXCI7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvckNhbGxiYWNrKG5ldyBPcGVuVmlkdUVycm9yKGVycm9yTmFtZSwgZXJyb3JNZXNzYWdlKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZWplY3QobmV3IE9wZW5WaWR1RXJyb3IoT3BlblZpZHVFcnJvck5hbWUuTk9fSU5QVVRfU09VUkNFX1NFVCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBcIlByb3BlcnRpZXMgJ2F1ZGlvU291cmNlJyBhbmQgJ3ZpZGVvU291cmNlJyBjYW5ub3QgYmUgc2V0IHRvIGZhbHNlIG9yIG51bGwgYXQgdGhlIHNhbWUgdGltZSB3aGVuIGNhbGxpbmcgJ09wZW5WaWR1LmluaXRQdWJsaXNoZXInXCIpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgLmNhdGNoKChlcnJvcjogT3BlblZpZHVFcnJvcikgPT4ge1xuICAgICAgICAgICAgICAgICAgICBlcnJvckNhbGxiYWNrKGVycm9yKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHJlZXN0YWJsaXNoU3RyZWFtUGxheWluZ0V2ZW50KCkge1xuICAgICAgICBpZiAodGhpcy5lZS5nZXRMaXN0ZW5lcnMoJ3N0cmVhbVBsYXlpbmcnKS5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICB0aGlzLmFkZFBsYXlFdmVudFRvRmlyc3RWaWRlbygpO1xuICAgICAgICB9XG4gICAgfVxuXG5cbiAgICAvKiBQcml2YXRlIG1ldGhvZHMgKi9cblxuICAgIHByaXZhdGUgc2V0UGVybWlzc2lvbkRpYWxvZ1RpbWVyKHdhaXRUaW1lOiBudW1iZXIpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5wZXJtaXNzaW9uRGlhbG9nVGltZW91dCA9IHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5lbWl0RXZlbnQoJ2FjY2Vzc0RpYWxvZ09wZW5lZCcsIFtdKTtcbiAgICAgICAgfSwgd2FpdFRpbWUpO1xuICAgIH1cblxuICAgIHByaXZhdGUgY2xlYXJQZXJtaXNzaW9uRGlhbG9nVGltZXIoc3RhcnRUaW1lOiBudW1iZXIsIHdhaXRUaW1lOiBudW1iZXIpOiB2b2lkIHtcbiAgICAgICAgY2xlYXJUaW1lb3V0KHRoaXMucGVybWlzc2lvbkRpYWxvZ1RpbWVvdXQpO1xuICAgICAgICBpZiAoKERhdGUubm93KCkgLSBzdGFydFRpbWUpID4gd2FpdFRpbWUpIHtcbiAgICAgICAgICAgIC8vIFBlcm1pc3Npb24gZGlhbG9nIHdhcyBzaG93biBhbmQgbm93IGlzIGNsb3NlZFxuICAgICAgICAgICAgdGhpcy5lbWl0RXZlbnQoJ2FjY2Vzc0RpYWxvZ0Nsb3NlZCcsIFtdKTtcbiAgICAgICAgfVxuICAgIH1cblxufSIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTctMjAxOCBPcGVuVmlkdSAoaHR0cHM6Ly9vcGVudmlkdS5pby8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuaW1wb3J0IHsgQ29ubmVjdGlvbiB9IGZyb20gJy4vQ29ubmVjdGlvbic7XG5pbXBvcnQgeyBPcGVuVmlkdSB9IGZyb20gJy4vT3BlblZpZHUnO1xuaW1wb3J0IHsgUHVibGlzaGVyIH0gZnJvbSAnLi9QdWJsaXNoZXInO1xuaW1wb3J0IHsgU3RyZWFtIH0gZnJvbSAnLi9TdHJlYW0nO1xuaW1wb3J0IHsgU3RyZWFtTWFuYWdlciB9IGZyb20gJy4vU3RyZWFtTWFuYWdlcic7XG5pbXBvcnQgeyBTdWJzY3JpYmVyIH0gZnJvbSAnLi9TdWJzY3JpYmVyJztcbmltcG9ydCB7IENhcGFiaWxpdGllcyB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvSW50ZXJmYWNlcy9QdWJsaWMvQ2FwYWJpbGl0aWVzJztcbmltcG9ydCB7IEV2ZW50RGlzcGF0Y2hlciB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvSW50ZXJmYWNlcy9QdWJsaWMvRXZlbnREaXNwYXRjaGVyJztcbmltcG9ydCB7IFNpZ25hbE9wdGlvbnMgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHVibGljL1NpZ25hbE9wdGlvbnMnO1xuaW1wb3J0IHsgU3Vic2NyaWJlclByb3BlcnRpZXMgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHVibGljL1N1YnNjcmliZXJQcm9wZXJ0aWVzJztcbmltcG9ydCB7IENvbm5lY3Rpb25PcHRpb25zIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9JbnRlcmZhY2VzL1ByaXZhdGUvQ29ubmVjdGlvbk9wdGlvbnMnO1xuaW1wb3J0IHsgT2JqTWFwIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9JbnRlcmZhY2VzL1ByaXZhdGUvT2JqTWFwJztcbmltcG9ydCB7IFNlc3Npb25PcHRpb25zIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9JbnRlcmZhY2VzL1ByaXZhdGUvU2Vzc2lvbk9wdGlvbnMnO1xuaW1wb3J0IHsgQ29ubmVjdGlvbkV2ZW50IH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvQ29ubmVjdGlvbkV2ZW50JztcbmltcG9ydCB7IFB1Ymxpc2hlclNwZWFraW5nRXZlbnQgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0V2ZW50cy9QdWJsaXNoZXJTcGVha2luZ0V2ZW50JztcbmltcG9ydCB7IFJlY29yZGluZ0V2ZW50IH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvUmVjb3JkaW5nRXZlbnQnO1xuaW1wb3J0IHsgU2Vzc2lvbkRpc2Nvbm5lY3RlZEV2ZW50IH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvU2Vzc2lvbkRpc2Nvbm5lY3RlZEV2ZW50JztcbmltcG9ydCB7IFNpZ25hbEV2ZW50IH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvU2lnbmFsRXZlbnQnO1xuaW1wb3J0IHsgU3RyZWFtRXZlbnQgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0V2ZW50cy9TdHJlYW1FdmVudCc7XG5pbXBvcnQgeyBTdHJlYW1Qcm9wZXJ0eUNoYW5nZWRFdmVudCB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1N0cmVhbVByb3BlcnR5Q2hhbmdlZEV2ZW50JztcbmltcG9ydCB7IE9wZW5WaWR1RXJyb3IsIE9wZW5WaWR1RXJyb3JOYW1lIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FbnVtcy9PcGVuVmlkdUVycm9yJztcbmltcG9ydCB7IFZpZGVvSW5zZXJ0TW9kZSB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRW51bXMvVmlkZW9JbnNlcnRNb2RlJztcblxuaW1wb3J0IHBsYXRmb3JtID0gcmVxdWlyZSgncGxhdGZvcm0nKTtcbmltcG9ydCBFdmVudEVtaXR0ZXIgPSByZXF1aXJlKCd3b2xmeTg3LWV2ZW50ZW1pdHRlcicpO1xuXG5cbi8qKlxuICogUmVwcmVzZW50cyBhIHZpZGVvIGNhbGwuIEl0IGNhbiBhbHNvIGJlIHNlZW4gYXMgYSB2aWRlb2NvbmZlcmVuY2Ugcm9vbSB3aGVyZSBtdWx0aXBsZSB1c2VycyBjYW4gY29ubmVjdC5cbiAqIFBhcnRpY2lwYW50cyB3aG8gcHVibGlzaCB0aGVpciB2aWRlb3MgdG8gYSBzZXNzaW9uIGNhbiBiZSBzZWVuIGJ5IHRoZSByZXN0IG9mIHVzZXJzIGNvbm5lY3RlZCB0byB0aGF0IHNwZWNpZmljIHNlc3Npb24uXG4gKiBJbml0aWFsaXplZCB3aXRoIFtbT3BlblZpZHUuaW5pdFNlc3Npb25dXSBtZXRob2RcbiAqL1xuZXhwb3J0IGNsYXNzIFNlc3Npb24gaW1wbGVtZW50cyBFdmVudERpc3BhdGNoZXIge1xuXG4gICAgLyoqXG4gICAgICogTG9jYWwgY29ubmVjdGlvbiB0byB0aGUgU2Vzc2lvbi4gVGhpcyBvYmplY3QgaXMgZGVmaW5lZCBvbmx5IGFmdGVyIFtbU2Vzc2lvbi5jb25uZWN0XV0gaGFzIGJlZW4gc3VjY2Vzc2Z1bGx5IGV4ZWN1dGVkLCBhbmQgY2FuIGJlIHJldHJpZXZlZCBzdWJzY3JpYmluZyB0byBgY29ubmVjdGlvbkNyZWF0ZWRgIGV2ZW50XG4gICAgICovXG4gICAgY29ubmVjdGlvbjogQ29ubmVjdGlvbjtcblxuICAgIC8qKlxuICAgICAqIFVuaXF1ZSBpZGVudGlmaWVyIG9mIHRoZSBTZXNzaW9uXG4gICAgICovXG4gICAgc2Vzc2lvbklkOiBzdHJpbmc7XG5cbiAgICAvKipcbiAgICAgKiBDb2xsZWN0aW9uIG9mIGFsbCBTdHJlYW1NYW5hZ2VycyBvZiB0aGlzIFNlc3Npb24gKFtbUHVibGlzaGVyXV0gYW5kIFtbU3Vic2NyaWJlcl1dKVxuICAgICAqL1xuICAgIHN0cmVhbU1hbmFnZXJzOiBTdHJlYW1NYW5hZ2VyW10gPSBbXTtcblxuICAgIC8qKlxuICAgICAqIE9iamVjdCBkZWZpbmluZyB0aGUgbWV0aG9kcyB0aGF0IHRoZSBjbGllbnQgaXMgYWJsZSB0byBjYWxsLiBUaGVzZSBhcmUgZGVmaW5lZCBieSB0aGUgcm9sZSBvZiB0aGUgdG9rZW4gdXNlZCB0byBjb25uZWN0IHRvIHRoZSBTZXNzaW9uLlxuICAgICAqIFRoaXMgb2JqZWN0IGlzIG9ubHkgZGVmaW5lZCBhZnRlciBbW1Nlc3Npb24uY29ubmVjdF1dIGhhcyBiZWVuIHN1Y2Nlc3NmdWxseSByZXNvbHZlZFxuICAgICAqL1xuICAgIGNhcGFiaWxpdGllczogQ2FwYWJpbGl0aWVzO1xuXG4gICAgLy8gVGhpcyBtYXAgaXMgb25seSB1c2VkIHRvIGF2b2lkIHJhY2UgY29uZGl0aW9uIGJldHdlZW4gJ2pvaW5Sb29tJyByZXNwb25zZSBhbmQgJ29uUGFydGljaXBhbnRQdWJsaXNoZWQnIG5vdGlmaWNhdGlvblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICByZW1vdGVTdHJlYW1zQ3JlYXRlZDogT2JqTWFwPGJvb2xlYW4+ID0ge307XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgcmVtb3RlQ29ubmVjdGlvbnM6IE9iak1hcDxDb25uZWN0aW9uPiA9IHt9O1xuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvcGVudmlkdTogT3BlblZpZHU7XG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIG9wdGlvbnM6IFNlc3Npb25PcHRpb25zO1xuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBzcGVha2luZ0V2ZW50c0VuYWJsZWQgPSBmYWxzZTtcblxuICAgIHByaXZhdGUgZWUgPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgY29uc3RydWN0b3Iob3BlbnZpZHU6IE9wZW5WaWR1KSB7XG4gICAgICAgIHRoaXMub3BlbnZpZHUgPSBvcGVudmlkdTtcbiAgICB9XG5cbiAgICBjb25uZWN0KHRva2VuOiBzdHJpbmcpOiBQcm9taXNlPGFueT47XG4gICAgY29ubmVjdCh0b2tlbjogc3RyaW5nLCBtZXRhZGF0YTogYW55KTogUHJvbWlzZTxhbnk+O1xuXG4gICAgLyoqXG4gICAgICogQ29ubmVjdHMgdG8gdGhlIHNlc3Npb24gdXNpbmcgYHRva2VuYC4gUGFyYW1ldGVyIGBtZXRhZGF0YWAgYWxsb3dzIHlvdSB0byBwYXNzIGV4dHJhIGRhdGEgdG8gc2hhcmUgd2l0aCBvdGhlciB1c2VycyB3aGVuXG4gICAgICogdGhleSByZWNlaXZlIGBzdHJlYW1DcmVhdGVkYCBldmVudC4gVGhlIHN0cnVjdHVyZSBvZiBgbWV0YWRhdGFgIHN0cmluZyBpcyB1cCB0byB5b3UgKG1heWJlIHNvbWUgc3RhbmRhcml6ZWQgZm9ybWF0XG4gICAgICogYXMgSlNPTiBvciBYTUwgaXMgYSBnb29kIGlkZWEpLCB0aGUgb25seSByZXN0cmljdGlvbiBpcyBhIG1heGltdW0gbGVuZ3RoIG9mIDEwMDAwIGNoYXJzLlxuICAgICAqXG4gICAgICogVGhpcyBtZXRhZGF0YSBpcyBub3QgY29uc2lkZXJlZCBzZWN1cmUsIGFzIGl0IGlzIGdlbmVyYXRlZCBpbiB0aGUgY2xpZW50IHNpZGUuIFRvIHBhc3Mgc2VjdXJpemVkIGRhdGEsIGFkZCBpdCBhcyBhIHBhcmFtZXRlciBpbiB0aGVcbiAgICAgKiB0b2tlbiBnZW5lcmF0aW9uIG9wZXJhdGlvbiAodGhyb3VnaCB0aGUgQVBJIFJFU1QsIG9wZW52aWR1LWphdmEtY2xpZW50IG9yIG9wZW52aWR1LW5vZGUtY2xpZW50KS5cbiAgICAgKlxuICAgICAqIE9ubHkgYWZ0ZXIgdGhlIHJldHVybmVkIFByb21pc2UgaXMgc3VjY2Vzc2Z1bGx5IHJlc29sdmVkIFtbU2Vzc2lvbi5jb25uZWN0aW9uXV0gb2JqZWN0IHdpbGwgYmUgYXZhaWxhYmxlIGFuZCBwcm9wZXJseSBkZWZpbmVkLlxuICAgICAqXG4gICAgICogIyMjIyBFdmVudHMgZGlzcGF0Y2hlZFxuICAgICAqXG4gICAgICogVGhlIFtbU2Vzc2lvbl1dIG9iamVjdCBvZiB0aGUgbG9jYWwgcGFydGljaXBhbnQgd2lsbCBmaXJzdCBkaXNwYXRjaCBvbmUgb3IgbW9yZSBgY29ubmVjdGlvbkNyZWF0ZWRgIGV2ZW50cyB1cG9uIHN1Y2Nlc3NmdWwgdGVybWluYXRpb24gb2YgdGhpcyBtZXRob2Q6XG4gICAgICogLSBGaXJzdCBvbmUgZm9yIHlvdXIgb3duIGxvY2FsIENvbm5lY3Rpb24gb2JqZWN0LCBzbyB5b3UgY2FuIHJldHJpZXZlIFtbU2Vzc2lvbi5jb25uZWN0aW9uXV0gcHJvcGVydHkuXG4gICAgICogLSBUaGVuIG9uZSBmb3IgZWFjaCByZW1vdGUgQ29ubmVjdGlvbiBwcmV2aW91c2x5IGNvbm5lY3RlZCB0byB0aGUgU2Vzc2lvbiwgaWYgYW55LiBBbnkgb3RoZXIgcmVtb3RlIHVzZXIgY29ubmVjdGluZyB0byB0aGUgU2Vzc2lvbiBhZnRlciB5b3UgaGF2ZVxuICAgICAqIHN1Y2Nlc3NmdWxseSBjb25uZWN0ZWQgd2lsbCBhbHNvIGRpc3BhdGNoIGEgYGNvbm5lY3Rpb25DcmVhdGVkYCBldmVudCB3aGVuIHRoZXkgZG8gc28uXG4gICAgICpcbiAgICAgKiBUaGUgW1tTZXNzaW9uXV0gb2JqZWN0IG9mIHRoZSBsb2NhbCBwYXJ0aWNpcGFudCB3aWxsIGFsc28gZGlzcGF0Y2ggYSBgc3RyZWFtQ3JlYXRlZGAgZXZlbnQgZm9yIGVhY2ggcmVtb3RlIGFjdGl2ZSBbW1B1Ymxpc2hlcl1dIHRoYXQgd2FzIGFscmVhZHkgc3RyZWFtaW5nXG4gICAgICogd2hlbiBjb25uZWN0aW5nLCBqdXN0IGFmdGVyIGRpc3BhdGNoaW5nIGFsbCByZW1vdGUgYGNvbm5lY3Rpb25DcmVhdGVkYCBldmVudHMuXG4gICAgICpcbiAgICAgKiBUaGUgW1tTZXNzaW9uXV0gb2JqZWN0IG9mIGV2ZXJ5IG90aGVyIHBhcnRpY2lwYW50IGNvbm5lY3RlZCB0byB0aGUgc2Vzc2lvbiB3aWxsIGRpc3BhdGNoIGEgYGNvbm5lY3Rpb25DcmVhdGVkYCBldmVudC5cbiAgICAgKlxuICAgICAqIFNlZSBbW0Nvbm5lY3Rpb25FdmVudF1dIGFuZCBbW1N0cmVhbUV2ZW50XV0gdG8gbGVhcm4gbW9yZS5cbiAgICAgKlxuICAgICAqIEByZXR1cm5zIEEgUHJvbWlzZSB0byB3aGljaCB5b3UgbXVzdCBzdWJzY3JpYmUgdGhhdCBpcyByZXNvbHZlZCBpZiB0aGUgdGhlIGNvbm5lY3Rpb24gdG8gdGhlIFNlc3Npb24gd2FzIHN1Y2Nlc3NmdWwgYW5kIHJlamVjdGVkIHdpdGggYW4gRXJyb3Igb2JqZWN0IGlmIG5vdFxuICAgICAqXG4gICAgICovXG4gICAgY29ubmVjdCh0b2tlbjogc3RyaW5nLCBtZXRhZGF0YT86IGFueSk6IFByb21pc2U8YW55PiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG5cbiAgICAgICAgICAgIHRoaXMucHJvY2Vzc1Rva2VuKHRva2VuKTtcblxuICAgICAgICAgICAgaWYgKHRoaXMub3BlbnZpZHUuY2hlY2tTeXN0ZW1SZXF1aXJlbWVudHMoKSkge1xuICAgICAgICAgICAgICAgIC8vIEVhcmx5IGNvbmZpZ3VyYXRpb24gdG8gZGVhY3RpdmF0ZSBhdXRvbWF0aWMgc3Vic2NyaXB0aW9uIHRvIHN0cmVhbXNcbiAgICAgICAgICAgICAgICB0aGlzLm9wdGlvbnMgPSB7XG4gICAgICAgICAgICAgICAgICAgIHNlc3Npb25JZDogdGhpcy5zZXNzaW9uSWQsXG4gICAgICAgICAgICAgICAgICAgIHBhcnRpY2lwYW50SWQ6IHRva2VuLFxuICAgICAgICAgICAgICAgICAgICBtZXRhZGF0YTogISFtZXRhZGF0YSA/IHRoaXMuc3RyaW5nQ2xpZW50TWV0YWRhdGEobWV0YWRhdGEpIDogJydcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIHRoaXMuY29ubmVjdEF1eCh0b2tlbikudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICB9KS5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJlamVjdChuZXcgT3BlblZpZHVFcnJvcihPcGVuVmlkdUVycm9yTmFtZS5CUk9XU0VSX05PVF9TVVBQT1JURUQsICdCcm93c2VyICcgKyBwbGF0Zm9ybS5uYW1lICsgJyAnICsgcGxhdGZvcm0udmVyc2lvbiArICcgaXMgbm90IHN1cHBvcnRlZCBpbiBPcGVuVmlkdScpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogTGVhdmVzIHRoZSBzZXNzaW9uLCBkZXN0cm95aW5nIGFsbCBzdHJlYW1zIGFuZCBkZWxldGluZyB0aGUgdXNlciBhcyBhIHBhcnRpY2lwYW50LlxuICAgICAqXG4gICAgICogIyMjIyBFdmVudHMgZGlzcGF0Y2hlZFxuICAgICAqXG4gICAgICogVGhlIFtbU2Vzc2lvbl1dIG9iamVjdCBvZiB0aGUgbG9jYWwgcGFydGljaXBhbnQgd2lsbCBkaXNwYXRjaCBhIGBzZXNzaW9uRGlzY29ubmVjdGVkYCBldmVudC5cbiAgICAgKiBUaGlzIGV2ZW50IHdpbGwgYXV0b21hdGljYWxseSB1bnN1YnNjcmliZSB0aGUgbGVhdmluZyBwYXJ0aWNpcGFudCBmcm9tIGV2ZXJ5IFN1YnNjcmliZXIgb2JqZWN0IG9mIHRoZSBzZXNzaW9uICh0aGlzIGluY2x1ZGVzIGNsb3NpbmcgdGhlIFdlYlJUQ1BlZXIgY29ubmVjdGlvbiBhbmQgZGlzcG9zaW5nIGFsbCBNZWRpYVN0cmVhbVRyYWNrcylcbiAgICAgKiBhbmQgYWxzbyBkZWxldGVzIGFueSBIVE1MIHZpZGVvIGVsZW1lbnQgYXNzb2NpYXRlZCB0byBlYWNoIFN1YnNjcmliZXIgKG9ubHkgdGhvc2UgW2NyZWF0ZWQgYnkgT3BlblZpZHUgQnJvd3Nlcl0oL2RvY3MvaG93LWRvLWkvbWFuYWdlLXZpZGVvcy8jbGV0LW9wZW52aWR1LXRha2UtY2FyZS1vZi10aGUtdmlkZW8tcGxheWVycykpLlxuICAgICAqIEZvciBldmVyeSB2aWRlbyByZW1vdmVkLCBlYWNoIFN1YnNjcmliZXIgb2JqZWN0IHdpbGwgZGlzcGF0Y2ggYSBgdmlkZW9FbGVtZW50RGVzdHJveWVkYCBldmVudC5cbiAgICAgKiBDYWxsIGBldmVudC5wcmV2ZW50RGVmYXVsdCgpYCB1cG9uIGV2ZW50IGBzZXNzaW9uRGlzY29ubmVjdGVkYCB0byBhdm9pZCB0aGlzIGJlaGF2aW9yIGFuZCB0YWtlIGNhcmUgb2YgZGlzcG9zaW5nIGFuZCBjbGVhbmluZyBhbGwgdGhlIFN1YnNjcmliZXIgb2JqZWN0cyB5b3Vyc2VsZi5cbiAgICAgKiBTZWUgW1tTZXNzaW9uRGlzY29ubmVjdGVkRXZlbnRdXSBhbmQgW1tWaWRlb0VsZW1lbnRFdmVudF1dIHRvIGxlYXJuIG1vcmUgdG8gbGVhcm4gbW9yZS5cbiAgICAgKlxuICAgICAqIFRoZSBbW1B1Ymxpc2hlcl1dIG9iamVjdCBvZiB0aGUgbG9jYWwgcGFydGljaXBhbnQgd2lsbCBkaXNwYXRjaCBhIGBzdHJlYW1EZXN0cm95ZWRgIGV2ZW50IGlmIHRoZXJlIGlzIGEgW1tQdWJsaXNoZXJdXSBvYmplY3QgcHVibGlzaGluZyB0byB0aGUgc2Vzc2lvbi5cbiAgICAgKiBUaGlzIGV2ZW50IHdpbGwgYXV0b21hdGljYWxseSBzdG9wIGFsbCBtZWRpYSB0cmFja3MgYW5kIGRlbGV0ZSBhbnkgSFRNTCB2aWRlbyBlbGVtZW50IGFzc29jaWF0ZWQgdG8gaXQgKG9ubHkgdGhvc2UgW2NyZWF0ZWQgYnkgT3BlblZpZHUgQnJvd3Nlcl0oL2RvY3MvaG93LWRvLWkvbWFuYWdlLXZpZGVvcy8jbGV0LW9wZW52aWR1LXRha2UtY2FyZS1vZi10aGUtdmlkZW8tcGxheWVycykpLlxuICAgICAqIEZvciBldmVyeSB2aWRlbyByZW1vdmVkLCB0aGUgUHVibGlzaGVyIG9iamVjdCB3aWxsIGRpc3BhdGNoIGEgYHZpZGVvRWxlbWVudERlc3Ryb3llZGAgZXZlbnQuXG4gICAgICogQ2FsbCBgZXZlbnQucHJldmVudERlZmF1bHQoKWAgdXBvbiBldmVudCBgc3RyZWFtRGVzdHJveWVkYCBpZiB5b3Ugd2FudCB0byBjbGVhbiB0aGUgUHVibGlzaGVyIG9iamVjdCBvbiB5b3VyIG93biBvciByZS1wdWJsaXNoIGl0IGluIGEgZGlmZmVyZW50IFNlc3Npb24gKHRvIGRvIHNvIGl0IGlzIGEgbWFuZGF0b3J5IHJlcXVpcmVtZW50IHRvIGNhbGwgYFNlc3Npb24udW5wdWJsaXNoKClgXG4gICAgICogb3IvYW5kIGBTZXNzaW9uLmRpc2Nvbm5lY3QoKWAgaW4gdGhlIHByZXZpb3VzIHNlc3Npb24pLiBTZWUgW1tTdHJlYW1FdmVudF1dIGFuZCBbW1ZpZGVvRWxlbWVudEV2ZW50XV0gdG8gbGVhcm4gbW9yZS5cbiAgICAgKlxuICAgICAqIFRoZSBbW1Nlc3Npb25dXSBvYmplY3Qgb2YgZXZlcnkgb3RoZXIgcGFydGljaXBhbnQgY29ubmVjdGVkIHRvIHRoZSBzZXNzaW9uIHdpbGwgZGlzcGF0Y2ggYSBgc3RyZWFtRGVzdHJveWVkYCBldmVudCBpZiB0aGUgZGlzY29ubmVjdGVkIHBhcnRpY2lwYW50IHdhcyBwdWJsaXNoaW5nLlxuICAgICAqIFRoaXMgZXZlbnQgd2lsbCBhdXRvbWF0aWNhbGx5IHVuc3Vic2NyaWJlIHRoZSBTdWJzY3JpYmVyIG9iamVjdCBmcm9tIHRoZSBzZXNzaW9uICh0aGlzIGluY2x1ZGVzIGNsb3NpbmcgdGhlIFdlYlJUQ1BlZXIgY29ubmVjdGlvbiBhbmQgZGlzcG9zaW5nIGFsbCBNZWRpYVN0cmVhbVRyYWNrcylcbiAgICAgKiBhbmQgYWxzbyBkZWxldGVzIGFueSBIVE1MIHZpZGVvIGVsZW1lbnQgYXNzb2NpYXRlZCB0byB0aGF0IFN1YnNjcmliZXIgKG9ubHkgdGhvc2UgW2NyZWF0ZWQgYnkgT3BlblZpZHUgQnJvd3Nlcl0oL2RvY3MvaG93LWRvLWkvbWFuYWdlLXZpZGVvcy8jbGV0LW9wZW52aWR1LXRha2UtY2FyZS1vZi10aGUtdmlkZW8tcGxheWVycykpLlxuICAgICAqIEZvciBldmVyeSB2aWRlbyByZW1vdmVkLCB0aGUgU3Vic2NyaWJlciBvYmplY3Qgd2lsbCBkaXNwYXRjaCBhIGB2aWRlb0VsZW1lbnREZXN0cm95ZWRgIGV2ZW50LlxuICAgICAqIENhbGwgYGV2ZW50LnByZXZlbnREZWZhdWx0KClgIHVwb24gZXZlbnQgYHN0cmVhbURlc3Ryb3llZGAgdG8gYXZvaWQgdGhpcyBkZWZhdWx0IGJlaGF2aW9yIGFuZCB0YWtlIGNhcmUgb2YgZGlzcG9zaW5nIGFuZCBjbGVhbmluZyB0aGUgU3Vic2NyaWJlciBvYmplY3QgeW91cnNlbGYuXG4gICAgICogU2VlIFtbU3RyZWFtRXZlbnRdXSBhbmQgW1tWaWRlb0VsZW1lbnRFdmVudF1dIHRvIGxlYXJuIG1vcmUuXG4gICAgICpcbiAgICAgKiBUaGUgW1tTZXNzaW9uXV0gb2JqZWN0IG9mIGV2ZXJ5IG90aGVyIHBhcnRpY2lwYW50IGNvbm5lY3RlZCB0byB0aGUgc2Vzc2lvbiB3aWxsIGRpc3BhdGNoIGEgYGNvbm5lY3Rpb25EZXN0cm95ZWRgIGV2ZW50IGluIGFueSBjYXNlLiBTZWUgW1tDb25uZWN0aW9uRXZlbnRdXSB0byBsZWFybiBtb3JlLlxuICAgICAqL1xuICAgIGRpc2Nvbm5lY3QoKTogdm9pZCB7XG4gICAgICAgIHRoaXMubGVhdmUoZmFsc2UsICdkaXNjb25uZWN0Jyk7XG4gICAgfVxuXG4gICAgc3Vic2NyaWJlKHN0cmVhbTogU3RyZWFtLCB0YXJnZXRFbGVtZW50OiBzdHJpbmcgfCBIVE1MRWxlbWVudCk6IFN1YnNjcmliZXI7XG4gICAgc3Vic2NyaWJlKHN0cmVhbTogU3RyZWFtLCB0YXJnZXRFbGVtZW50OiBzdHJpbmcgfCBIVE1MRWxlbWVudCwgcHJvcGVydGllczogU3Vic2NyaWJlclByb3BlcnRpZXMpOiBTdWJzY3JpYmVyO1xuICAgIHN1YnNjcmliZShzdHJlYW06IFN0cmVhbSwgdGFyZ2V0RWxlbWVudDogc3RyaW5nIHwgSFRNTEVsZW1lbnQsIGNvbXBsZXRpb25IYW5kbGVyOiAoZXJyb3I6IEVycm9yIHwgdW5kZWZpbmVkKSA9PiB2b2lkKTogU3Vic2NyaWJlcjtcbiAgICBzdWJzY3JpYmUoc3RyZWFtOiBTdHJlYW0sIHRhcmdldEVsZW1lbnQ6IHN0cmluZyB8IEhUTUxFbGVtZW50LCBwcm9wZXJ0aWVzOiBTdWJzY3JpYmVyUHJvcGVydGllcywgY29tcGxldGlvbkhhbmRsZXI6IChlcnJvcjogRXJyb3IgfCB1bmRlZmluZWQpID0+IHZvaWQpOiBTdWJzY3JpYmVyO1xuXG4gICAgLyoqXG4gICAgICogU3Vic2NyaWJlcyB0byBhIGBzdHJlYW1gLCBhZGRpbmcgYSBuZXcgSFRNTCB2aWRlbyBlbGVtZW50IHRvIERPTSB3aXRoIGBzdWJzY3JpYmVyUHJvcGVydGllc2Agc2V0dGluZ3MuIFRoaXMgbWV0aG9kIGlzIHVzdWFsbHkgY2FsbGVkIGluIHRoZSBjYWxsYmFjayBvZiBgc3RyZWFtQ3JlYXRlZGAgZXZlbnQuXG4gICAgICpcbiAgICAgKiAjIyMjIEV2ZW50cyBkaXNwYXRjaGVkXG4gICAgICpcbiAgICAgKiBUaGUgW1tTdWJzY3JpYmVyXV0gb2JqZWN0IHdpbGwgZGlzcGF0Y2ggYSBgdmlkZW9FbGVtZW50Q3JlYXRlZGAgZXZlbnQgb25jZSB0aGUgSFRNTCB2aWRlbyBlbGVtZW50IGhhcyBiZWVuIGFkZGVkIHRvIERPTSAob25seSBpZiB5b3VcbiAgICAgKiBbbGV0IE9wZW5WaWR1IHRha2UgY2FyZSBvZiB0aGUgdmlkZW8gcGxheWVyc10oL2RvY3MvaG93LWRvLWkvbWFuYWdlLXZpZGVvcy8jbGV0LW9wZW52aWR1LXRha2UtY2FyZS1vZi10aGUtdmlkZW8tcGxheWVycykpLiBTZWUgW1tWaWRlb0VsZW1lbnRFdmVudF1dIHRvIGxlYXJuIG1vcmUuXG4gICAgICpcbiAgICAgKiBUaGUgW1tTdWJzY3JpYmVyXV0gb2JqZWN0IHdpbGwgZGlzcGF0Y2ggYSBgc3RyZWFtUGxheWluZ2AgZXZlbnQgb25jZSB0aGUgcmVtb3RlIHN0cmVhbSBzdGFydHMgcGxheWluZy4gU2VlIFtbU3RyZWFtTWFuYWdlckV2ZW50XV0gdG8gbGVhcm4gbW9yZS5cbiAgICAgKlxuICAgICAqIEBwYXJhbSBzdHJlYW0gU3RyZWFtIG9iamVjdCB0byBzdWJzY3JpYmUgdG9cbiAgICAgKiBAcGFyYW0gdGFyZ2V0RWxlbWVudCBIVE1MIERPTSBlbGVtZW50IChvciBpdHMgYGlkYCBhdHRyaWJ1dGUpIGluIHdoaWNoIHRoZSB2aWRlbyBlbGVtZW50IG9mIHRoZSBTdWJzY3JpYmVyIHdpbGwgYmUgaW5zZXJ0ZWQgKHNlZSBbW1N1YnNjcmliZXJQcm9wZXJ0aWVzLmluc2VydE1vZGVdXSkuIElmICpudWxsKiBvciAqdW5kZWZpbmVkKiBubyBkZWZhdWx0IHZpZGVvIHdpbGwgYmUgY3JlYXRlZCBmb3IgdGhpcyBTdWJzY3JpYmVyLlxuICAgICAqIFlvdSBjYW4gYWx3YXlzIGNhbGwgbWV0aG9kIFtbU3Vic2NyaWJlci5hZGRWaWRlb0VsZW1lbnRdXSBvciBbW1N1YnNjcmliZXIuY3JlYXRlVmlkZW9FbGVtZW50XV0gdG8gbWFuYWdlIHRoZSB2aWRlbyBlbGVtZW50cyBvbiB5b3VyIG93biAoc2VlIFtNYW5hZ2UgdmlkZW8gcGxheWVyc10oL2RvY3MvaG93LWRvLWkvbWFuYWdlLXZpZGVvcykgc2VjdGlvbilcbiAgICAgKiBAcGFyYW0gY29tcGxldGlvbkhhbmRsZXIgYGVycm9yYCBwYXJhbWV0ZXIgaXMgbnVsbCBpZiBgc3Vic2NyaWJlYCBzdWNjZWVkcywgYW5kIGlzIGRlZmluZWQgaWYgaXQgZmFpbHMuXG4gICAgICovXG4gICAgc3Vic2NyaWJlKHN0cmVhbTogU3RyZWFtLCB0YXJnZXRFbGVtZW50OiBzdHJpbmcgfCBIVE1MRWxlbWVudCwgcGFyYW0zPzogKChlcnJvcjogRXJyb3IgfCB1bmRlZmluZWQpID0+IHZvaWQpIHwgU3Vic2NyaWJlclByb3BlcnRpZXMsIHBhcmFtND86ICgoZXJyb3I6IEVycm9yIHwgdW5kZWZpbmVkKSA9PiB2b2lkKSk6IFN1YnNjcmliZXIge1xuICAgICAgICBsZXQgcHJvcGVydGllczogU3Vic2NyaWJlclByb3BlcnRpZXMgPSB7fTtcbiAgICAgICAgaWYgKCEhcGFyYW0zICYmIHR5cGVvZiBwYXJhbTMgIT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgIHByb3BlcnRpZXMgPSB7XG4gICAgICAgICAgICAgICAgaW5zZXJ0TW9kZTogKHR5cGVvZiBwYXJhbTMuaW5zZXJ0TW9kZSAhPT0gJ3VuZGVmaW5lZCcpID8gKCh0eXBlb2YgcGFyYW0zLmluc2VydE1vZGUgPT09ICdzdHJpbmcnKSA/IFZpZGVvSW5zZXJ0TW9kZVtwYXJhbTMuaW5zZXJ0TW9kZV0gOiBwcm9wZXJ0aWVzLmluc2VydE1vZGUpIDogVmlkZW9JbnNlcnRNb2RlLkFQUEVORCxcbiAgICAgICAgICAgICAgICBzdWJzY3JpYmVUb0F1ZGlvOiAodHlwZW9mIHBhcmFtMy5zdWJzY3JpYmVUb0F1ZGlvICE9PSAndW5kZWZpbmVkJykgPyBwYXJhbTMuc3Vic2NyaWJlVG9BdWRpbyA6IHRydWUsXG4gICAgICAgICAgICAgICAgc3Vic2NyaWJlVG9WaWRlbzogKHR5cGVvZiBwYXJhbTMuc3Vic2NyaWJlVG9WaWRlbyAhPT0gJ3VuZGVmaW5lZCcpID8gcGFyYW0zLnN1YnNjcmliZVRvVmlkZW8gOiB0cnVlXG4gICAgICAgICAgICB9O1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcHJvcGVydGllcyA9IHtcbiAgICAgICAgICAgICAgICBpbnNlcnRNb2RlOiBWaWRlb0luc2VydE1vZGUuQVBQRU5ELFxuICAgICAgICAgICAgICAgIHN1YnNjcmliZVRvQXVkaW86IHRydWUsXG4gICAgICAgICAgICAgICAgc3Vic2NyaWJlVG9WaWRlbzogdHJ1ZVxuICAgICAgICAgICAgfTtcbiAgICAgICAgfVxuXG4gICAgICAgIGxldCBjb21wbGV0aW9uSGFuZGxlcjogKGVycm9yOiBFcnJvciB8IHVuZGVmaW5lZCkgPT4gdm9pZDtcbiAgICAgICAgaWYgKCEhcGFyYW0zICYmICh0eXBlb2YgcGFyYW0zID09PSAnZnVuY3Rpb24nKSkge1xuICAgICAgICAgICAgY29tcGxldGlvbkhhbmRsZXIgPSBwYXJhbTM7XG4gICAgICAgIH0gZWxzZSBpZiAoISFwYXJhbTQpIHtcbiAgICAgICAgICAgIGNvbXBsZXRpb25IYW5kbGVyID0gcGFyYW00O1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc29sZS5pbmZvKCdTdWJzY3JpYmluZyB0byAnICsgc3RyZWFtLmNvbm5lY3Rpb24uY29ubmVjdGlvbklkKTtcblxuICAgICAgICBzdHJlYW0uc3Vic2NyaWJlKClcbiAgICAgICAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oJ1N1YnNjcmliZWQgY29ycmVjdGx5IHRvICcgKyBzdHJlYW0uY29ubmVjdGlvbi5jb25uZWN0aW9uSWQpO1xuICAgICAgICAgICAgICAgIGlmIChjb21wbGV0aW9uSGFuZGxlciAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbXBsZXRpb25IYW5kbGVyKHVuZGVmaW5lZCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKGNvbXBsZXRpb25IYW5kbGVyICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgY29tcGxldGlvbkhhbmRsZXIoZXJyb3IpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICBjb25zdCBzdWJzY3JpYmVyID0gbmV3IFN1YnNjcmliZXIoc3RyZWFtLCB0YXJnZXRFbGVtZW50LCBwcm9wZXJ0aWVzKTtcbiAgICAgICAgaWYgKCEhc3Vic2NyaWJlci50YXJnZXRFbGVtZW50KSB7XG4gICAgICAgICAgICBzdHJlYW0uc3RyZWFtTWFuYWdlci5jcmVhdGVWaWRlb0VsZW1lbnQoc3Vic2NyaWJlci50YXJnZXRFbGVtZW50LCA8VmlkZW9JbnNlcnRNb2RlPnByb3BlcnRpZXMuaW5zZXJ0TW9kZSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHN1YnNjcmliZXI7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBQcm9taXNpZmllZCB2ZXJzaW9uIG9mIFtbU2Vzc2lvbi5zdWJzY3JpYmVdXVxuICAgICAqL1xuICAgIHN1YnNjcmliZUFzeW5jKHN0cmVhbTogU3RyZWFtLCB0YXJnZXRFbGVtZW50OiBzdHJpbmcgfCBIVE1MRWxlbWVudCk6IFByb21pc2U8U3Vic2NyaWJlcj47XG4gICAgc3Vic2NyaWJlQXN5bmMoc3RyZWFtOiBTdHJlYW0sIHRhcmdldEVsZW1lbnQ6IHN0cmluZyB8IEhUTUxFbGVtZW50LCBwcm9wZXJ0aWVzOiBTdWJzY3JpYmVyUHJvcGVydGllcyk6IFByb21pc2U8U3Vic2NyaWJlcj47XG5cbiAgICBzdWJzY3JpYmVBc3luYyhzdHJlYW06IFN0cmVhbSwgdGFyZ2V0RWxlbWVudDogc3RyaW5nIHwgSFRNTEVsZW1lbnQsIHByb3BlcnRpZXM/OiBTdWJzY3JpYmVyUHJvcGVydGllcyk6IFByb21pc2U8U3Vic2NyaWJlcj4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2U8U3Vic2NyaWJlcj4oKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuXG4gICAgICAgICAgICBsZXQgc3Vic2NyaWJlcjogU3Vic2NyaWJlcjtcblxuICAgICAgICAgICAgY29uc3QgY2FsbGJhY2sgPSAoZXJyb3I6IEVycm9yKSA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKCEhZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICByZXNvbHZlKHN1YnNjcmliZXIpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIGlmICghIXByb3BlcnRpZXMpIHtcbiAgICAgICAgICAgICAgICBzdWJzY3JpYmVyID0gdGhpcy5zdWJzY3JpYmUoc3RyZWFtLCB0YXJnZXRFbGVtZW50LCBwcm9wZXJ0aWVzLCBjYWxsYmFjayk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHN1YnNjcmliZXIgPSB0aGlzLnN1YnNjcmliZShzdHJlYW0sIHRhcmdldEVsZW1lbnQsIGNhbGxiYWNrKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICB9KTtcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFVuc3Vic2NyaWJlcyBmcm9tIGBzdWJzY3JpYmVyYCwgYXV0b21hdGljYWxseSByZW1vdmluZyBpdHMgYXNzb2NpYXRlZCBIVE1MIHZpZGVvIGVsZW1lbnRzLlxuICAgICAqXG4gICAgICogIyMjIyBFdmVudHMgZGlzcGF0Y2hlZFxuICAgICAqXG4gICAgICogVGhlIFtbU3Vic2NyaWJlcl1dIG9iamVjdCB3aWxsIGRpc3BhdGNoIGEgYHZpZGVvRWxlbWVudERlc3Ryb3llZGAgZXZlbnQgZm9yIGVhY2ggdmlkZW8gYXNzb2NpYXRlZCB0byBpdCB0aGF0IHdhcyByZW1vdmVkIGZyb20gRE9NLlxuICAgICAqIE9ubHkgdmlkZW9zIFtjcmVhdGVkIGJ5IE9wZW5WaWR1IEJyb3dzZXJdKC9kb2NzL2hvdy1kby1pL21hbmFnZS12aWRlb3MvI2xldC1vcGVudmlkdS10YWtlLWNhcmUtb2YtdGhlLXZpZGVvLXBsYXllcnMpKSB3aWxsIGJlIGF1dG9tYXRpY2FsbHkgcmVtb3ZlZFxuICAgICAqXG4gICAgICogU2VlIFtbVmlkZW9FbGVtZW50RXZlbnRdXSB0byBsZWFybiBtb3JlXG4gICAgICovXG4gICAgdW5zdWJzY3JpYmUoc3Vic2NyaWJlcjogU3Vic2NyaWJlcik6IHZvaWQge1xuICAgICAgICBjb25zdCBjb25uZWN0aW9uSWQgPSBzdWJzY3JpYmVyLnN0cmVhbS5jb25uZWN0aW9uLmNvbm5lY3Rpb25JZDtcblxuICAgICAgICBjb25zb2xlLmluZm8oJ1Vuc3Vic2NyaWJpbmcgZnJvbSAnICsgY29ubmVjdGlvbklkKTtcblxuICAgICAgICB0aGlzLm9wZW52aWR1LnNlbmRSZXF1ZXN0KFxuICAgICAgICAgICAgJ3Vuc3Vic2NyaWJlRnJvbVZpZGVvJyxcbiAgICAgICAgICAgIHsgc2VuZGVyOiBzdWJzY3JpYmVyLnN0cmVhbS5jb25uZWN0aW9uLmNvbm5lY3Rpb25JZCB9LFxuICAgICAgICAgICAgKGVycm9yLCByZXNwb25zZSkgPT4ge1xuICAgICAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKCdFcnJvciB1bnN1YnNjcmliaW5nIGZyb20gJyArIGNvbm5lY3Rpb25JZCwgZXJyb3IpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbygnVW5zdWJzY3JpYmVkIGNvcnJlY3RseSBmcm9tICcgKyBjb25uZWN0aW9uSWQpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBzdWJzY3JpYmVyLnN0cmVhbS5kaXNwb3NlV2ViUnRjUGVlcigpO1xuICAgICAgICAgICAgICAgIHN1YnNjcmliZXIuc3RyZWFtLmRpc3Bvc2VNZWRpYVN0cmVhbSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICApO1xuICAgICAgICBzdWJzY3JpYmVyLnN0cmVhbS5zdHJlYW1NYW5hZ2VyLnJlbW92ZUFsbFZpZGVvcygpO1xuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogUHVibGlzaGVzIHRvIHRoZSBTZXNzaW9uIHRoZSBQdWJsaXNoZXIgb2JqZWN0XG4gICAgICpcbiAgICAgKiAjIyMjIEV2ZW50cyBkaXNwYXRjaGVkXG4gICAgICpcbiAgICAgKiBUaGUgbG9jYWwgW1tQdWJsaXNoZXJdXSBvYmplY3Qgd2lsbCBkaXNwYXRjaCBhIGBzdHJlYW1DcmVhdGVkYCBldmVudCB1cG9uIHN1Y2Nlc3NmdWwgdGVybWluYXRpb24gb2YgdGhpcyBtZXRob2QuIFNlZSBbW1N0cmVhbUV2ZW50XV0gdG8gbGVhcm4gbW9yZS5cbiAgICAgKlxuICAgICAqIFRoZSBsb2NhbCBbW1B1Ymxpc2hlcl1dIG9iamVjdCB3aWxsIGRpc3BhdGNoIGEgYHN0cmVhbVBsYXlpbmdgIG9uY2UgdGhlIG1lZGlhIHN0cmVhbSBzdGFydHMgcGxheWluZy4gU2VlIFtbU3RyZWFtTWFuYWdlckV2ZW50XV0gdG8gbGVhcm4gbW9yZS5cbiAgICAgKlxuICAgICAqIFRoZSBbW1Nlc3Npb25dXSBvYmplY3Qgb2YgZXZlcnkgb3RoZXIgcGFydGljaXBhbnQgY29ubmVjdGVkIHRvIHRoZSBzZXNzaW9uIHdpbGwgZGlzcGF0Y2ggYSBgc3RyZWFtQ3JlYXRlZGAgZXZlbnQgc28gdGhleSBjYW4gc3Vic2NyaWJlIHRvIGl0LiBTZWUgW1tTdHJlYW1FdmVudF1dIHRvIGxlYXJuIG1vcmUuXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyBBIFByb21pc2UgKHRvIHdoaWNoIHlvdSBjYW4gb3B0aW9uYWxseSBzdWJzY3JpYmUgdG8pIHRoYXQgaXMgcmVzb2x2ZWQgb25seSBhZnRlciB0aGUgcHVibGlzaGVyIHdhcyBzdWNjZXNzZnVsbHkgcHVibGlzaGVkIGFuZCByZWplY3RlZCB3aXRoIGFuIEVycm9yIG9iamVjdCBpZiBub3RcbiAgICAgKi9cbiAgICBwdWJsaXNoKHB1Ymxpc2hlcjogUHVibGlzaGVyKTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIHB1Ymxpc2hlci5zZXNzaW9uID0gdGhpcztcbiAgICAgICAgICAgIHB1Ymxpc2hlci5zdHJlYW0uc2Vzc2lvbiA9IHRoaXM7XG5cbiAgICAgICAgICAgIGlmICghcHVibGlzaGVyLnN0cmVhbS5wdWJsaXNoZWRPbmNlKSB7XG4gICAgICAgICAgICAgICAgLy8gJ1Nlc3Npb24udW5wdWJsaXNoKFB1Ymxpc2hlciknIGhhcyBOT1QgYmVlbiBjYWxsZWRcbiAgICAgICAgICAgICAgICB0aGlzLmNvbm5lY3Rpb24uYWRkU3RyZWFtKHB1Ymxpc2hlci5zdHJlYW0pO1xuICAgICAgICAgICAgICAgIHB1Ymxpc2hlci5zdHJlYW0ucHVibGlzaCgpXG4gICAgICAgICAgICAgICAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAvLyAnU2Vzc2lvbi51bnB1Ymxpc2goUHVibGlzaGVyKScgaGFzIGJlZW4gY2FsbGVkLiBNdXN0IGluaXRpYWxpemUgYWdhaW4gUHVibGlzaGVyXG4gICAgICAgICAgICAgICAgcHVibGlzaGVyLmluaXRpYWxpemUoKVxuICAgICAgICAgICAgICAgICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbm5lY3Rpb24uYWRkU3RyZWFtKHB1Ymxpc2hlci5zdHJlYW0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgcHVibGlzaGVyLnJlZXN0YWJsaXNoU3RyZWFtUGxheWluZ0V2ZW50KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBwdWJsaXNoZXIuc3RyZWFtLnB1Ymxpc2goKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgfSkuY2F0Y2goKGVycm9yKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBVbnB1Ymxpc2hlcyBmcm9tIHRoZSBTZXNzaW9uIHRoZSBQdWJsaXNoZXIgb2JqZWN0LlxuICAgICAqXG4gICAgICogIyMjIyBFdmVudHMgZGlzcGF0Y2hlZFxuICAgICAqXG4gICAgICogVGhlIFtbUHVibGlzaGVyXV0gb2JqZWN0IG9mIHRoZSBsb2NhbCBwYXJ0aWNpcGFudCB3aWxsIGRpc3BhdGNoIGEgYHN0cmVhbURlc3Ryb3llZGAgZXZlbnQuXG4gICAgICogVGhpcyBldmVudCB3aWxsIGF1dG9tYXRpY2FsbHkgc3RvcCBhbGwgbWVkaWEgdHJhY2tzIGFuZCBkZWxldGUgYW55IEhUTUwgdmlkZW8gZWxlbWVudCBhc3NvY2lhdGVkIHRvIHRoaXMgUHVibGlzaGVyXG4gICAgICogKG9ubHkgdGhvc2UgdmlkZW9zIFtjcmVhdGVkIGJ5IE9wZW5WaWR1IEJyb3dzZXJdKC9kb2NzL2hvdy1kby1pL21hbmFnZS12aWRlb3MvI2xldC1vcGVudmlkdS10YWtlLWNhcmUtb2YtdGhlLXZpZGVvLXBsYXllcnMpKS5cbiAgICAgKiBGb3IgZXZlcnkgdmlkZW8gcmVtb3ZlZCwgdGhlIFB1Ymxpc2hlciBvYmplY3Qgd2lsbCBkaXNwYXRjaCBhIGB2aWRlb0VsZW1lbnREZXN0cm95ZWRgIGV2ZW50LlxuICAgICAqIENhbGwgYGV2ZW50LnByZXZlbnREZWZhdWx0KClgIHVwb24gZXZlbnQgYHN0cmVhbURlc3Ryb3llZGAgaWYgeW91IHdhbnQgdG8gY2xlYW4gdGhlIFB1Ymxpc2hlciBvYmplY3Qgb24geW91ciBvd24gb3IgcmUtcHVibGlzaCBpdCBpbiBhIGRpZmZlcmVudCBTZXNzaW9uLlxuICAgICAqXG4gICAgICogVGhlIFtbU2Vzc2lvbl1dIG9iamVjdCBvZiBldmVyeSBvdGhlciBwYXJ0aWNpcGFudCBjb25uZWN0ZWQgdG8gdGhlIHNlc3Npb24gd2lsbCBkaXNwYXRjaCBhIGBzdHJlYW1EZXN0cm95ZWRgIGV2ZW50LlxuICAgICAqIFRoaXMgZXZlbnQgd2lsbCBhdXRvbWF0aWNhbGx5IHVuc3Vic2NyaWJlIHRoZSBTdWJzY3JpYmVyIG9iamVjdCBmcm9tIHRoZSBzZXNzaW9uICh0aGlzIGluY2x1ZGVzIGNsb3NpbmcgdGhlIFdlYlJUQ1BlZXIgY29ubmVjdGlvbiBhbmQgZGlzcG9zaW5nIGFsbCBNZWRpYVN0cmVhbVRyYWNrcykgYW5kXG4gICAgICogZGVsZXRlIGFueSBIVE1MIHZpZGVvIGVsZW1lbnQgYXNzb2NpYXRlZCB0byBpdCAob25seSB0aG9zZSBbY3JlYXRlZCBieSBPcGVuVmlkdSBCcm93c2VyXSgvZG9jcy9ob3ctZG8taS9tYW5hZ2UtdmlkZW9zLyNsZXQtb3BlbnZpZHUtdGFrZS1jYXJlLW9mLXRoZS12aWRlby1wbGF5ZXJzKSkuXG4gICAgICogRm9yIGV2ZXJ5IHZpZGVvIHJlbW92ZWQsIHRoZSBTdWJzY3JpYmVyIG9iamVjdCB3aWxsIGRpc3BhdGNoIGEgYHZpZGVvRWxlbWVudERlc3Ryb3llZGAgZXZlbnQuXG4gICAgICogQ2FsbCBgZXZlbnQucHJldmVudERlZmF1bHQoKWAgdXBvbiBldmVudCBgc3RyZWFtRGVzdHJveWVkYCB0byBhdm9pZCB0aGlzIGRlZmF1bHQgYmVoYXZpb3IgYW5kIHRha2UgY2FyZSBvZiBkaXNwb3NpbmcgYW5kIGNsZWFuaW5nIHRoZSBTdWJzY3JpYmVyIG9iamVjdCBvbiB5b3VyIG93bi5cbiAgICAgKlxuICAgICAqIFNlZSBbW1N0cmVhbUV2ZW50XV0gYW5kIFtbVmlkZW9FbGVtZW50RXZlbnRdXSB0byBsZWFybiBtb3JlLlxuICAgICAqL1xuICAgIHVucHVibGlzaChwdWJsaXNoZXI6IFB1Ymxpc2hlcik6IHZvaWQge1xuXG4gICAgICAgIGNvbnN0IHN0cmVhbSA9IHB1Ymxpc2hlci5zdHJlYW07XG5cbiAgICAgICAgaWYgKCFzdHJlYW0uY29ubmVjdGlvbikge1xuICAgICAgICAgICAgY29uc29sZS5lcnJvcignVGhlIGFzc29jaWF0ZWQgQ29ubmVjdGlvbiBvYmplY3Qgb2YgdGhpcyBQdWJsaXNoZXIgaXMgbnVsbCcsIHN0cmVhbSk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH0gZWxzZSBpZiAoc3RyZWFtLmNvbm5lY3Rpb24gIT09IHRoaXMuY29ubmVjdGlvbikge1xuICAgICAgICAgICAgY29uc29sZS5lcnJvcignVGhlIGFzc29jaWF0ZWQgQ29ubmVjdGlvbiBvYmplY3Qgb2YgdGhpcyBQdWJsaXNoZXIgaXMgbm90IHlvdXIgbG9jYWwgQ29ubmVjdGlvbi4nICtcbiAgICAgICAgICAgICAgICBcIk9ubHkgbW9kZXJhdG9ycyBjYW4gZm9yY2UgdW5wdWJsaXNoIG9uIHJlbW90ZSBTdHJlYW1zIHZpYSAnZm9yY2VVbnB1Ymxpc2gnIG1ldGhvZFwiLCBzdHJlYW0pO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9IGVsc2Uge1xuXG4gICAgICAgICAgICBjb25zb2xlLmluZm8oJ1VucHVibGlzaGluZyBsb2NhbCBtZWRpYSAoJyArIHN0cmVhbS5jb25uZWN0aW9uLmNvbm5lY3Rpb25JZCArICcpJyk7XG5cbiAgICAgICAgICAgIHRoaXMub3BlbnZpZHUuc2VuZFJlcXVlc3QoJ3VucHVibGlzaFZpZGVvJywgKGVycm9yLCByZXNwb25zZSkgPT4ge1xuICAgICAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKGVycm9yKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oJ01lZGlhIHVucHVibGlzaGVkIGNvcnJlY3RseScpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICBzdHJlYW0uZGlzcG9zZVdlYlJ0Y1BlZXIoKTtcbiAgICAgICAgICAgIGRlbGV0ZSBzdHJlYW0uY29ubmVjdGlvbi5zdHJlYW07XG5cbiAgICAgICAgICAgIGNvbnN0IHN0cmVhbUV2ZW50ID0gbmV3IFN0cmVhbUV2ZW50KHRydWUsIHB1Ymxpc2hlciwgJ3N0cmVhbURlc3Ryb3llZCcsIHB1Ymxpc2hlci5zdHJlYW0sICd1bnB1Ymxpc2gnKTtcbiAgICAgICAgICAgIHB1Ymxpc2hlci5lbWl0RXZlbnQoJ3N0cmVhbURlc3Ryb3llZCcsIFtzdHJlYW1FdmVudF0pO1xuICAgICAgICAgICAgc3RyZWFtRXZlbnQuY2FsbERlZmF1bHRCZWhhdmlvcigpO1xuICAgICAgICB9XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBGb3JjZXMgc29tZSB1c2VyIHRvIGxlYXZlIHRoZSBzZXNzaW9uXG4gICAgICpcbiAgICAgKiAjIyMjIEV2ZW50cyBkaXNwYXRjaGVkXG4gICAgICpcbiAgICAgKiBUaGUgYmVoYXZpb3IgaXMgdGhlIHNhbWUgYXMgd2hlbiBzb21lIHVzZXIgY2FsbHMgW1tTZXNzaW9uLmRpc2Nvbm5lY3RdXSwgYnV0IGByZWFzb25gIHByb3BlcnR5IGluIGFsbCBldmVudHMgd2lsbCBiZSBgXCJmb3JjZURpc2Nvbm5lY3RCeVVzZXJcImAuXG4gICAgICpcbiAgICAgKiBUaGUgW1tTZXNzaW9uXV0gb2JqZWN0IG9mIGV2ZXJ5IHBhcnRpY2lwYW50IHdpbGwgZGlzcGF0Y2ggYSBgc3RyZWFtRGVzdHJveWVkYCBldmVudCBpZiB0aGUgZXZpY3RlZCB1c2VyIHdhcyBwdWJsaXNoaW5nIGEgc3RyZWFtLCB3aXRoIHByb3BlcnR5IGByZWFzb25gIHNldCB0byBgXCJmb3JjZURpc2Nvbm5lY3RCeVVzZXJcImAuXG4gICAgICogVGhlIFtbU2Vzc2lvbl1dIG9iamVjdCBvZiBldmVyeSBwYXJ0aWNpcGFudCBleGNlcHQgdGhlIGV2aWN0ZWQgb25lIHdpbGwgZGlzcGF0Y2ggYSBgY29ubmVjdGlvbkRlc3Ryb3llZGAgZXZlbnQgZm9yIHRoZSBldmljdGVkIHVzZXIsIHdpdGggcHJvcGVydHkgYHJlYXNvbmAgc2V0IHRvIGBcImZvcmNlRGlzY29ubmVjdEJ5VXNlclwiYC5cbiAgICAgKlxuICAgICAqIElmIGFueSwgdGhlIFtbUHVibGlzaGVyXV0gb2JqZWN0IG9mIHRoZSBldmljdGVkIHBhcnRpY2lwYW50IHdpbGwgYWxzbyBkaXNwYXRjaCBhIGBzdHJlYW1EZXN0cm95ZWRgIGV2ZW50IHdpdGggcHJvcGVydHkgYHJlYXNvbmAgc2V0IHRvIGBcImZvcmNlRGlzY29ubmVjdEJ5VXNlclwiYC5cbiAgICAgKiBUaGUgW1tTZXNzaW9uXV0gb2JqZWN0IG9mIHRoZSBldmljdGVkIHBhcnRpY2lwYW50IHdpbGwgZGlzcGF0Y2ggYSBgc2Vzc2lvbkRpc2Nvbm5lY3RlZGAgZXZlbnQgd2l0aCBwcm9wZXJ0eSBgcmVhc29uYCBzZXQgdG8gYFwiZm9yY2VEaXNjb25uZWN0QnlVc2VyXCJgLlxuICAgICAqXG4gICAgICogU2VlIFtbU3RyZWFtRXZlbnRdXSwgW1tDb25uZWN0aW9uRXZlbnRdXSBhbmQgW1tTZXNzaW9uRGlzY29ubmVjdGVkRXZlbnRdXSB0byBsZWFybiBtb3JlLlxuICAgICAqXG4gICAgICogQHJldHVybnMgQSBQcm9taXNlICh0byB3aGljaCB5b3UgY2FuIG9wdGlvbmFsbHkgc3Vic2NyaWJlIHRvKSB0aGF0IGlzIHJlc29sdmVkIG9ubHkgYWZ0ZXIgdGhlIHBhcnRpY2lwYW50IGhhcyBiZWVuIHN1Y2Nlc3NmdWxseSBldmljdGVkIGZyb20gdGhlIHNlc3Npb24gYW5kIHJlamVjdGVkIHdpdGggYW4gRXJyb3Igb2JqZWN0IGlmIG5vdFxuICAgICAqL1xuICAgIGZvcmNlRGlzY29ubmVjdChjb25uZWN0aW9uOiBDb25uZWN0aW9uKTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIGNvbnNvbGUuaW5mbygnRm9yY2luZyBkaXNjb25uZWN0IGZvciBjb25uZWN0aW9uICcgKyBjb25uZWN0aW9uLmNvbm5lY3Rpb25JZCk7XG4gICAgICAgICAgICB0aGlzLm9wZW52aWR1LnNlbmRSZXF1ZXN0KFxuICAgICAgICAgICAgICAgICdmb3JjZURpc2Nvbm5lY3QnLFxuICAgICAgICAgICAgICAgIHsgY29ubmVjdGlvbklkOiBjb25uZWN0aW9uLmNvbm5lY3Rpb25JZCB9LFxuICAgICAgICAgICAgICAgIChlcnJvciwgcmVzcG9uc2UpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKCdFcnJvciBmb3JjaW5nIGRpc2Nvbm5lY3QgZm9yIENvbm5lY3Rpb24gJyArIGNvbm5lY3Rpb24uY29ubmVjdGlvbklkLCBlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZXJyb3IuY29kZSA9PT0gNDAxKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KG5ldyBPcGVuVmlkdUVycm9yKE9wZW5WaWR1RXJyb3JOYW1lLk9QRU5WSURVX1BFUk1JU1NJT05fREVOSUVELCBcIllvdSBkb24ndCBoYXZlIHBlcm1pc3Npb25zIHRvIGZvcmNlIGEgZGlzY29ubmVjdGlvblwiKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oJ0ZvcmNpbmcgZGlzY29ubmVjdCBjb3JyZWN0bHkgZm9yIENvbm5lY3Rpb24gJyArIGNvbm5lY3Rpb24uY29ubmVjdGlvbklkKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogRm9yY2VzIHNvbWUgdXNlciB0byB1bnB1Ymxpc2ggYSBTdHJlYW1cbiAgICAgKlxuICAgICAqICMjIyMgRXZlbnRzIGRpc3BhdGNoZWRcbiAgICAgKlxuICAgICAqIFRoZSBiZWhhdmlvciBpcyB0aGUgc2FtZSBhcyB3aGVuIHNvbWUgdXNlciBjYWxscyBbW1Nlc3Npb24udW5wdWJsaXNoXV0sIGJ1dCBgcmVhc29uYCBwcm9wZXJ0eSBpbiBhbGwgZXZlbnRzIHdpbGwgYmUgYFwiZm9yY2VVbnB1Ymxpc2hCeVVzZXJcImBcbiAgICAgKlxuICAgICAqIFRoZSBbW1Nlc3Npb25dXSBvYmplY3Qgb2YgZXZlcnkgcGFydGljaXBhbnQgd2lsbCBkaXNwYXRjaCBhIGBzdHJlYW1EZXN0cm95ZWRgIGV2ZW50IHdpdGggcHJvcGVydHkgYHJlYXNvbmAgc2V0IHRvIGBcImZvcmNlRGlzY29ubmVjdEJ5VXNlclwiYFxuICAgICAqXG4gICAgICogVGhlIFtbUHVibGlzaGVyXV0gb2JqZWN0IG9mIHRoZSBhZmZlY3RlZCBwYXJ0aWNpcGFudCB3aWxsIGFsc28gZGlzcGF0Y2ggYSBgc3RyZWFtRGVzdHJveWVkYCBldmVudCB3aXRoIHByb3BlcnR5IGByZWFzb25gIHNldCB0byBgXCJmb3JjZURpc2Nvbm5lY3RCeVVzZXJcImBcbiAgICAgKlxuICAgICAqIFNlZSBbW1N0cmVhbUV2ZW50XV0gdG8gbGVhcm4gbW9yZS5cbiAgICAgKlxuICAgICAqIEByZXR1cm5zIEEgUHJvbWlzZSAodG8gd2hpY2ggeW91IGNhbiBvcHRpb25hbGx5IHN1YnNjcmliZSB0bykgdGhhdCBpcyByZXNvbHZlZCBvbmx5IGFmdGVyIHRoZSByZW1vdGUgU3RyZWFtIGhhcyBiZWVuIHN1Y2Nlc3NmdWxseSB1bnB1Ymxpc2hlZCBmcm9tIHRoZSBzZXNzaW9uIGFuZCByZWplY3RlZCB3aXRoIGFuIEVycm9yIG9iamVjdCBpZiBub3RcbiAgICAgKi9cbiAgICBmb3JjZVVucHVibGlzaChzdHJlYW06IFN0cmVhbSk6IFByb21pc2U8YW55PiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICBjb25zb2xlLmluZm8oJ0ZvcmNpbmcgdW5wdWJsaXNoIGZvciBzdHJlYW0gJyArIHN0cmVhbS5zdHJlYW1JZCk7XG4gICAgICAgICAgICB0aGlzLm9wZW52aWR1LnNlbmRSZXF1ZXN0KFxuICAgICAgICAgICAgICAgICdmb3JjZVVucHVibGlzaCcsXG4gICAgICAgICAgICAgICAgeyBzdHJlYW1JZDogc3RyZWFtLnN0cmVhbUlkIH0sXG4gICAgICAgICAgICAgICAgKGVycm9yLCByZXNwb25zZSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBpZiAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ0Vycm9yIGZvcmNpbmcgdW5wdWJsaXNoIGZvciBTdHJlYW0gJyArIHN0cmVhbS5zdHJlYW1JZCwgZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yLmNvZGUgPT09IDQwMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChuZXcgT3BlblZpZHVFcnJvcihPcGVuVmlkdUVycm9yTmFtZS5PUEVOVklEVV9QRVJNSVNTSU9OX0RFTklFRCwgXCJZb3UgZG9uJ3QgaGF2ZSBwZXJtaXNzaW9ucyB0byBmb3JjZSBhbiB1bnB1Ymxpc2hpbmdcIikpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5pbmZvKCdGb3JjaW5nIHVucHVibGlzaCBjb3JyZWN0bHkgZm9yIFN0cmVhbSAnICsgc3RyZWFtLnN0cmVhbUlkKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogU2VuZHMgb25lIHNpZ25hbC4gYHNpZ25hbGAgb2JqZWN0IGhhcyB0aGUgZm9sbG93aW5nIG9wdGlvbmFsIHByb3BlcnRpZXM6XG4gICAgICogYGBganNvblxuICAgICAqIHtkYXRhOnN0cmluZywgdG86Q29ubmVjdGlvbltdLCB0eXBlOnN0cmluZ31cbiAgICAgKiBgYGBcbiAgICAgKiBBbGwgdXNlcnMgc3Vic2NyaWJlZCB0byB0aGF0IHNpZ25hbCAoYHNlc3Npb24ub24oJ3NpZ25hbDp0eXBlJywgLi4uKWAgb3IgYHNlc3Npb24ub24oJ3NpZ25hbCcsIC4uLilgIGZvciBhbGwgc2lnbmFscykgYW5kIHdob3NlIENvbm5lY3Rpb24gb2JqZWN0cyBhcmUgaW4gYHRvYCBhcnJheSB3aWxsIHJlY2VpdmUgaXQuIFRoZWlyIGxvY2FsXG4gICAgICogU2Vzc2lvbiBvYmplY3RzIHdpbGwgZGlzcGF0Y2ggYSBgc2lnbmFsYCBvciBgc2lnbmFsOnR5cGVgIGV2ZW50LiBTZWUgW1tTaWduYWxFdmVudF1dIHRvIGxlYXJuIG1vcmUuXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyBBIFByb21pc2UgKHRvIHdoaWNoIHlvdSBjYW4gb3B0aW9uYWxseSBzdWJzY3JpYmUgdG8pIHRoYXQgaXMgcmVzb2x2ZWQgaWYgdGhlIG1lc3NhZ2Ugc3VjY2Vzc2Z1bGx5IHJlYWNoZWQgb3BlbnZpZHUtc2VydmVyIGFuZCByZWplY3RlZCB3aXRoIGFuIEVycm9yIG9iamVjdCBpZiBub3QuIF9UaGlzIGRvZXNuJ3RcbiAgICAgKiBtZWFuIHRoYXQgb3BlbnZpZHUtc2VydmVyIGNvdWxkIHJlc2VuZCB0aGUgbWVzc2FnZSB0byBhbGwgdGhlIGxpc3RlZCByZWNlaXZlcnMuX1xuICAgICAqL1xuICAgIC8qIHRzbGludDpkaXNhYmxlOm5vLXN0cmluZy1saXRlcmFsICovXG4gICAgc2lnbmFsKHNpZ25hbDogU2lnbmFsT3B0aW9ucyk6IFByb21pc2U8YW55PiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG5cbiAgICAgICAgICAgIGNvbnN0IHNpZ25hbE1lc3NhZ2UgPSB7fTtcblxuICAgICAgICAgICAgaWYgKHNpZ25hbC50byAmJiBzaWduYWwudG8ubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgICAgIGNvbnN0IGNvbm5lY3Rpb25JZHM6IHN0cmluZ1tdID0gW107XG5cbiAgICAgICAgICAgICAgICBzaWduYWwudG8uZm9yRWFjaChjb25uZWN0aW9uID0+IHtcbiAgICAgICAgICAgICAgICAgICAgY29ubmVjdGlvbklkcy5wdXNoKGNvbm5lY3Rpb24uY29ubmVjdGlvbklkKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICBzaWduYWxNZXNzYWdlWyd0byddID0gY29ubmVjdGlvbklkcztcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgc2lnbmFsTWVzc2FnZVsndG8nXSA9IFtdO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBzaWduYWxNZXNzYWdlWydkYXRhJ10gPSBzaWduYWwuZGF0YSA/IHNpZ25hbC5kYXRhIDogJyc7XG4gICAgICAgICAgICBzaWduYWxNZXNzYWdlWyd0eXBlJ10gPSBzaWduYWwudHlwZSA/IHNpZ25hbC50eXBlIDogJyc7XG5cbiAgICAgICAgICAgIHRoaXMub3BlbnZpZHUuc2VuZFJlcXVlc3QoJ3NlbmRNZXNzYWdlJywge1xuICAgICAgICAgICAgICAgIG1lc3NhZ2U6IEpTT04uc3RyaW5naWZ5KHNpZ25hbE1lc3NhZ2UpXG4gICAgICAgICAgICB9LCAoZXJyb3IsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKCEhZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgIH1cbiAgICAvKiB0c2xpbnQ6ZW5hYmxlOm5vLXN0cmluZy1saXRlcmFsICovXG5cblxuICAgIC8qKlxuICAgICAqIFNlZSBbW0V2ZW50RGlzcGF0Y2hlci5vbl1dXG4gICAgICovXG4gICAgb24odHlwZTogc3RyaW5nLCBoYW5kbGVyOiAoZXZlbnQ6IFNlc3Npb25EaXNjb25uZWN0ZWRFdmVudCB8IFNpZ25hbEV2ZW50IHwgU3RyZWFtRXZlbnQgfCBDb25uZWN0aW9uRXZlbnQgfCBQdWJsaXNoZXJTcGVha2luZ0V2ZW50IHwgUmVjb3JkaW5nRXZlbnQpID0+IHZvaWQpOiBFdmVudERpc3BhdGNoZXIge1xuXG4gICAgICAgIHRoaXMuZWUub24odHlwZSwgZXZlbnQgPT4ge1xuICAgICAgICAgICAgaWYgKGV2ZW50KSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5pbmZvKFwiRXZlbnQgJ1wiICsgdHlwZSArIFwiJyB0cmlnZ2VyZWQgYnkgJ1Nlc3Npb24nXCIsIGV2ZW50KTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5pbmZvKFwiRXZlbnQgJ1wiICsgdHlwZSArIFwiJyB0cmlnZ2VyZWQgYnkgJ1Nlc3Npb24nXCIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaGFuZGxlcihldmVudCk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGlmICh0eXBlID09PSAncHVibGlzaGVyU3RhcnRTcGVha2luZycgfHwgdHlwZSA9PT0gJ3B1Ymxpc2hlclN0b3BTcGVha2luZycpIHtcbiAgICAgICAgICAgIHRoaXMuc3BlYWtpbmdFdmVudHNFbmFibGVkID0gdHJ1ZTtcbiAgICAgICAgICAgIC8vIElmIHRoZXJlIGFyZSBhbHJlYWR5IGF2YWlsYWJsZSByZW1vdGUgc3RyZWFtcywgZW5hYmxlIGhhcmsgJ3NwZWFraW5nJyBldmVudCBpbiBhbGwgb2YgdGhlbVxuICAgICAgICAgICAgZm9yIChjb25zdCBjb25uZWN0aW9uSWQgaW4gdGhpcy5yZW1vdGVDb25uZWN0aW9ucykge1xuICAgICAgICAgICAgICAgIGNvbnN0IHN0ciA9IHRoaXMucmVtb3RlQ29ubmVjdGlvbnNbY29ubmVjdGlvbklkXS5zdHJlYW07XG4gICAgICAgICAgICAgICAgaWYgKCEhc3RyICYmICFzdHIuc3BlZWNoRXZlbnQgJiYgc3RyLmhhc0F1ZGlvKSB7XG4gICAgICAgICAgICAgICAgICAgIHN0ci5lbmFibGVTcGVha2luZ0V2ZW50cygpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogU2VlIFtbRXZlbnREaXNwYXRjaGVyLm9uY2VdXVxuICAgICAqL1xuICAgIG9uY2UodHlwZTogc3RyaW5nLCBoYW5kbGVyOiAoZXZlbnQ6IFNlc3Npb25EaXNjb25uZWN0ZWRFdmVudCB8IFNpZ25hbEV2ZW50IHwgU3RyZWFtRXZlbnQgfCBDb25uZWN0aW9uRXZlbnQgfCBQdWJsaXNoZXJTcGVha2luZ0V2ZW50IHwgUmVjb3JkaW5nRXZlbnQpID0+IHZvaWQpOiBTZXNzaW9uIHtcblxuICAgICAgICB0aGlzLmVlLm9uY2UodHlwZSwgZXZlbnQgPT4ge1xuICAgICAgICAgICAgaWYgKGV2ZW50KSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5pbmZvKFwiRXZlbnQgJ1wiICsgdHlwZSArIFwiJyB0cmlnZ2VyZWQgYnkgJ1Nlc3Npb24nXCIsIGV2ZW50KTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5pbmZvKFwiRXZlbnQgJ1wiICsgdHlwZSArIFwiJyB0cmlnZ2VyZWQgYnkgJ1Nlc3Npb24nXCIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaGFuZGxlcihldmVudCk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGlmICh0eXBlID09PSAncHVibGlzaGVyU3RhcnRTcGVha2luZycgfHwgdHlwZSA9PT0gJ3B1Ymxpc2hlclN0b3BTcGVha2luZycpIHtcbiAgICAgICAgICAgIHRoaXMuc3BlYWtpbmdFdmVudHNFbmFibGVkID0gdHJ1ZTtcbiAgICAgICAgICAgIC8vIElmIHRoZXJlIGFyZSBhbHJlYWR5IGF2YWlsYWJsZSByZW1vdGUgc3RyZWFtcywgZW5hYmxlIGhhcmsgaW4gYWxsIG9mIHRoZW1cbiAgICAgICAgICAgIGZvciAoY29uc3QgY29ubmVjdGlvbklkIGluIHRoaXMucmVtb3RlQ29ubmVjdGlvbnMpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBzdHIgPSB0aGlzLnJlbW90ZUNvbm5lY3Rpb25zW2Nvbm5lY3Rpb25JZF0uc3RyZWFtO1xuICAgICAgICAgICAgICAgIGlmICghIXN0ciAmJiAhc3RyLnNwZWVjaEV2ZW50ICYmIHN0ci5oYXNBdWRpbykge1xuICAgICAgICAgICAgICAgICAgICBzdHIuZW5hYmxlT25jZVNwZWFraW5nRXZlbnRzKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBTZWUgW1tFdmVudERpc3BhdGNoZXIub2ZmXV1cbiAgICAgKi9cbiAgICBvZmYodHlwZTogc3RyaW5nLCBoYW5kbGVyPzogKGV2ZW50OiBTZXNzaW9uRGlzY29ubmVjdGVkRXZlbnQgfCBTaWduYWxFdmVudCB8IFN0cmVhbUV2ZW50IHwgQ29ubmVjdGlvbkV2ZW50IHwgUHVibGlzaGVyU3BlYWtpbmdFdmVudCB8IFJlY29yZGluZ0V2ZW50KSA9PiB2b2lkKTogU2Vzc2lvbiB7XG5cbiAgICAgICAgaWYgKCFoYW5kbGVyKSB7XG4gICAgICAgICAgICB0aGlzLmVlLnJlbW92ZUFsbExpc3RlbmVycyh0eXBlKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuZWUub2ZmKHR5cGUsIGhhbmRsZXIpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHR5cGUgPT09ICdwdWJsaXNoZXJTdGFydFNwZWFraW5nJyB8fCB0eXBlID09PSAncHVibGlzaGVyU3RvcFNwZWFraW5nJykge1xuICAgICAgICAgICAgdGhpcy5zcGVha2luZ0V2ZW50c0VuYWJsZWQgPSBmYWxzZTtcblxuICAgICAgICAgICAgLy8gSWYgdGhlcmUgYXJlIGFscmVhZHkgYXZhaWxhYmxlIHJlbW90ZSBzdHJlYW1zLCBkaXNhYmxhZSBoYXJrIGluIGFsbCBvZiB0aGVtXG4gICAgICAgICAgICBmb3IgKGNvbnN0IGNvbm5lY3Rpb25JZCBpbiB0aGlzLnJlbW90ZUNvbm5lY3Rpb25zKSB7XG4gICAgICAgICAgICAgICAgY29uc3Qgc3RyID0gdGhpcy5yZW1vdGVDb25uZWN0aW9uc1tjb25uZWN0aW9uSWRdLnN0cmVhbTtcbiAgICAgICAgICAgICAgICBpZiAoISFzdHIgJiYgISFzdHIuc3BlZWNoRXZlbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgc3RyLmRpc2FibGVTcGVha2luZ0V2ZW50cygpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cblxuICAgIC8qIEhpZGRlbiBtZXRob2RzICovXG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgb25QYXJ0aWNpcGFudEpvaW5lZChyZXNwb25zZTogQ29ubmVjdGlvbk9wdGlvbnMpOiB2b2lkIHtcbiAgICAgICAgLy8gQ29ubmVjdGlvbiBzaG91bGRuJ3QgZXhpc3RcbiAgICAgICAgdGhpcy5nZXRDb25uZWN0aW9uKHJlc3BvbnNlLmlkLCAnJylcblxuICAgICAgICAgICAgLnRoZW4oY29ubmVjdGlvbiA9PiB7XG4gICAgICAgICAgICAgICAgY29uc29sZS53YXJuKCdDb25uZWN0aW9uICcgKyByZXNwb25zZS5pZCArICcgYWxyZWFkeSBleGlzdHMgaW4gY29ubmVjdGlvbnMgbGlzdCcpO1xuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIC5jYXRjaChvcGVuVmlkdUVycm9yID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCBjb25uZWN0aW9uID0gbmV3IENvbm5lY3Rpb24odGhpcywgcmVzcG9uc2UpO1xuICAgICAgICAgICAgICAgIHRoaXMucmVtb3RlQ29ubmVjdGlvbnNbcmVzcG9uc2UuaWRdID0gY29ubmVjdGlvbjtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnY29ubmVjdGlvbkNyZWF0ZWQnLCBbbmV3IENvbm5lY3Rpb25FdmVudChmYWxzZSwgdGhpcywgJ2Nvbm5lY3Rpb25DcmVhdGVkJywgY29ubmVjdGlvbiwgJycpXSk7XG4gICAgICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgb25QYXJ0aWNpcGFudExlZnQobXNnKTogdm9pZCB7XG4gICAgICAgIHRoaXMuZ2V0UmVtb3RlQ29ubmVjdGlvbihtc2cuY29ubmVjdGlvbklkLCAnUmVtb3RlIGNvbm5lY3Rpb24gJyArIG1zZy5jb25uZWN0aW9uSWQgKyBcIiB1bmtub3duIHdoZW4gJ29uUGFydGljaXBhbnRMZWZ0Jy4gXCIgK1xuICAgICAgICAgICAgJ0V4aXN0aW5nIHJlbW90ZSBjb25uZWN0aW9uczogJyArIEpTT04uc3RyaW5naWZ5KE9iamVjdC5rZXlzKHRoaXMucmVtb3RlQ29ubmVjdGlvbnMpKSlcblxuICAgICAgICAgICAgLnRoZW4oY29ubmVjdGlvbiA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKCEhY29ubmVjdGlvbi5zdHJlYW0pIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3Qgc3RyZWFtID0gY29ubmVjdGlvbi5zdHJlYW07XG5cbiAgICAgICAgICAgICAgICAgICAgY29uc3Qgc3RyZWFtRXZlbnQgPSBuZXcgU3RyZWFtRXZlbnQodHJ1ZSwgdGhpcywgJ3N0cmVhbURlc3Ryb3llZCcsIHN0cmVhbSwgbXNnLnJlYXNvbik7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdzdHJlYW1EZXN0cm95ZWQnLCBbc3RyZWFtRXZlbnRdKTtcbiAgICAgICAgICAgICAgICAgICAgc3RyZWFtRXZlbnQuY2FsbERlZmF1bHRCZWhhdmlvcigpO1xuXG4gICAgICAgICAgICAgICAgICAgIGRlbGV0ZSB0aGlzLnJlbW90ZVN0cmVhbXNDcmVhdGVkW3N0cmVhbS5zdHJlYW1JZF07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGRlbGV0ZSB0aGlzLnJlbW90ZUNvbm5lY3Rpb25zW2Nvbm5lY3Rpb24uY29ubmVjdGlvbklkXTtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnY29ubmVjdGlvbkRlc3Ryb3llZCcsIFtuZXcgQ29ubmVjdGlvbkV2ZW50KGZhbHNlLCB0aGlzLCAnY29ubmVjdGlvbkRlc3Ryb3llZCcsIGNvbm5lY3Rpb24sIG1zZy5yZWFzb24pXSk7XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLmNhdGNoKG9wZW5WaWR1RXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3Iob3BlblZpZHVFcnJvcik7XG4gICAgICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgb25QYXJ0aWNpcGFudFB1Ymxpc2hlZChyZXNwb25zZTogQ29ubmVjdGlvbk9wdGlvbnMpOiB2b2lkIHtcblxuICAgICAgICBjb25zdCBhZnRlckNvbm5lY3Rpb25Gb3VuZCA9IChjb25uZWN0aW9uKSA9PiB7XG4gICAgICAgICAgICB0aGlzLnJlbW90ZUNvbm5lY3Rpb25zW2Nvbm5lY3Rpb24uY29ubmVjdGlvbklkXSA9IGNvbm5lY3Rpb247XG5cbiAgICAgICAgICAgIGlmICghdGhpcy5yZW1vdGVTdHJlYW1zQ3JlYXRlZFtjb25uZWN0aW9uLnN0cmVhbS5zdHJlYW1JZF0pIHtcbiAgICAgICAgICAgICAgICAvLyBBdm9pZCByYWNlIGNvbmRpdGlvbiBiZXR3ZWVuIHN0cmVhbS5zdWJzY3JpYmUoKSBpbiBcIm9uUGFydGljaXBhbnRQdWJsaXNoZWRcIiBhbmQgaW4gXCJqb2luUm9vbVwiIHJwYyBjYWxsYmFja1xuICAgICAgICAgICAgICAgIC8vIFRoaXMgY29uZGl0aW9uIGlzIGZhbHNlIGlmIG9wZW52aWR1LXNlcnZlciBzZW5kcyBcInBhcnRpY2lwYW50UHVibGlzaGVkXCIgZXZlbnQgdG8gYSBzdWJzY3JpYmVyIHBhcnRpY2lwYW50IHRoYXQgaGFzXG4gICAgICAgICAgICAgICAgLy8gYWxyZWFkeSBzdWJzY3JpYmVkIHRvIGNlcnRhaW4gc3RyZWFtIGluIHRoZSBjYWxsYmFjayBvZiBcImpvaW5Sb29tXCIgbWV0aG9kXG5cbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnc3RyZWFtQ3JlYXRlZCcsIFtuZXcgU3RyZWFtRXZlbnQoZmFsc2UsIHRoaXMsICdzdHJlYW1DcmVhdGVkJywgY29ubmVjdGlvbi5zdHJlYW0sICcnKV0pO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLnJlbW90ZVN0cmVhbXNDcmVhdGVkW2Nvbm5lY3Rpb24uc3RyZWFtLnN0cmVhbUlkXSA9IHRydWU7XG4gICAgICAgIH07XG5cbiAgICAgICAgLy8gR2V0IHRoZSBleGlzdGluZyBDb25uZWN0aW9uIGNyZWF0ZWQgb24gJ29uUGFydGljaXBhbnRKb2luZWQnIGZvclxuICAgICAgICAvLyBleGlzdGluZyBwYXJ0aWNpcGFudHMgb3IgY3JlYXRlIGEgbmV3IG9uZSBmb3IgbmV3IHBhcnRpY2lwYW50c1xuICAgICAgICBsZXQgY29ubmVjdGlvbjogQ29ubmVjdGlvbjtcbiAgICAgICAgdGhpcy5nZXRSZW1vdGVDb25uZWN0aW9uKHJlc3BvbnNlLmlkLCBcIlJlbW90ZSBjb25uZWN0aW9uICdcIiArIHJlc3BvbnNlLmlkICsgXCInIHVua25vd24gd2hlbiAnb25QYXJ0aWNpcGFudFB1Ymxpc2hlZCcuIFwiICtcbiAgICAgICAgICAgICdFeGlzdGluZyByZW1vdGUgY29ubmVjdGlvbnM6ICcgKyBKU09OLnN0cmluZ2lmeShPYmplY3Qua2V5cyh0aGlzLnJlbW90ZUNvbm5lY3Rpb25zKSkpXG5cbiAgICAgICAgICAgIC50aGVuKGNvbiA9PiB7XG4gICAgICAgICAgICAgICAgLy8gVXBkYXRlIGV4aXN0aW5nIENvbm5lY3Rpb25cbiAgICAgICAgICAgICAgICBjb25uZWN0aW9uID0gY29uO1xuICAgICAgICAgICAgICAgIHJlc3BvbnNlLm1ldGFkYXRhID0gY29uLmRhdGE7XG4gICAgICAgICAgICAgICAgY29ubmVjdGlvbi5vcHRpb25zID0gcmVzcG9uc2U7XG4gICAgICAgICAgICAgICAgY29ubmVjdGlvbi5pbml0UmVtb3RlU3RyZWFtcyhyZXNwb25zZS5zdHJlYW1zKTtcbiAgICAgICAgICAgICAgICBhZnRlckNvbm5lY3Rpb25Gb3VuZChjb25uZWN0aW9uKTtcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAuY2F0Y2gob3BlblZpZHVFcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgLy8gQ3JlYXRlIG5ldyBDb25uZWN0aW9uXG4gICAgICAgICAgICAgICAgY29ubmVjdGlvbiA9IG5ldyBDb25uZWN0aW9uKHRoaXMsIHJlc3BvbnNlKTtcbiAgICAgICAgICAgICAgICBhZnRlckNvbm5lY3Rpb25Gb3VuZChjb25uZWN0aW9uKTtcbiAgICAgICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvblBhcnRpY2lwYW50VW5wdWJsaXNoZWQobXNnKTogdm9pZCB7XG4gICAgICAgIGlmIChtc2cuY29ubmVjdGlvbklkID09PSB0aGlzLmNvbm5lY3Rpb24uY29ubmVjdGlvbklkKSB7XG4gICAgICAgICAgICAvLyBZb3VyIHN0cmVhbSBoYXMgYmVlbiBmb3JjZWRseSB1bnB1Ymxpc2hlZCBmcm9tIHRoZSBzZXNzaW9uXG4gICAgICAgICAgICB0aGlzLnN0b3BQdWJsaXNoZXJTdHJlYW0obXNnLnJlYXNvbik7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLmdldFJlbW90ZUNvbm5lY3Rpb24obXNnLmNvbm5lY3Rpb25JZCwgXCJSZW1vdGUgY29ubmVjdGlvbiAnXCIgKyBtc2cuY29ubmVjdGlvbklkICsgXCInIHVua25vd24gd2hlbiAnb25QYXJ0aWNpcGFudFVucHVibGlzaGVkJy4gXCIgK1xuICAgICAgICAgICAgICAgICdFeGlzdGluZyByZW1vdGUgY29ubmVjdGlvbnM6ICcgKyBKU09OLnN0cmluZ2lmeShPYmplY3Qua2V5cyh0aGlzLnJlbW90ZUNvbm5lY3Rpb25zKSkpXG5cbiAgICAgICAgICAgICAgICAudGhlbihjb25uZWN0aW9uID0+IHtcblxuICAgICAgICAgICAgICAgICAgICBjb25zdCBzdHJlYW1FdmVudCA9IG5ldyBTdHJlYW1FdmVudCh0cnVlLCB0aGlzLCAnc3RyZWFtRGVzdHJveWVkJywgY29ubmVjdGlvbi5zdHJlYW0sIG1zZy5yZWFzb24pO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnc3RyZWFtRGVzdHJveWVkJywgW3N0cmVhbUV2ZW50XSk7XG4gICAgICAgICAgICAgICAgICAgIHN0cmVhbUV2ZW50LmNhbGxEZWZhdWx0QmVoYXZpb3IoKTtcblxuICAgICAgICAgICAgICAgICAgICAvLyBEZWxldGluZyB0aGUgcmVtb3RlIHN0cmVhbVxuICAgICAgICAgICAgICAgICAgICBjb25zdCBzdHJlYW1JZDogc3RyaW5nID0gY29ubmVjdGlvbi5zdHJlYW0uc3RyZWFtSWQ7XG4gICAgICAgICAgICAgICAgICAgIGRlbGV0ZSB0aGlzLnJlbW90ZVN0cmVhbXNDcmVhdGVkW3N0cmVhbUlkXTtcbiAgICAgICAgICAgICAgICAgICAgY29ubmVjdGlvbi5yZW1vdmVTdHJlYW0oc3RyZWFtSWQpO1xuICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgLmNhdGNoKG9wZW5WaWR1RXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKG9wZW5WaWR1RXJyb3IpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIG9uUGFydGljaXBhbnRFdmljdGVkKG1zZyk6IHZvaWQge1xuICAgICAgICBpZiAobXNnLmNvbm5lY3Rpb25JZCA9PT0gdGhpcy5jb25uZWN0aW9uLmNvbm5lY3Rpb25JZCkge1xuICAgICAgICAgICAgLy8gWW91IGhhdmUgYmVlbiBldmljdGVkIGZyb20gdGhlIHNlc3Npb25cbiAgICAgICAgICAgIGlmICghIXRoaXMuc2Vzc2lvbklkICYmICF0aGlzLmNvbm5lY3Rpb24uZGlzcG9zZWQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmxlYXZlKHRydWUsIG1zZy5yZWFzb24pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIG9uTmV3TWVzc2FnZShtc2cpOiB2b2lkIHtcblxuICAgICAgICBjb25zb2xlLmluZm8oJ05ldyBzaWduYWw6ICcgKyBKU09OLnN0cmluZ2lmeShtc2cpKTtcblxuICAgICAgICB0aGlzLmdldENvbm5lY3Rpb24obXNnLmZyb20sIFwiQ29ubmVjdGlvbiAnXCIgKyBtc2cuZnJvbSArIFwiJyB1bmtub3cgd2hlbiAnb25OZXdNZXNzYWdlJy4gRXhpc3RpbmcgcmVtb3RlIGNvbm5lY3Rpb25zOiBcIlxuICAgICAgICAgICAgKyBKU09OLnN0cmluZ2lmeShPYmplY3Qua2V5cyh0aGlzLnJlbW90ZUNvbm5lY3Rpb25zKSkgKyAnLiBFeGlzdGluZyBsb2NhbCBjb25uZWN0aW9uOiAnICsgdGhpcy5jb25uZWN0aW9uLmNvbm5lY3Rpb25JZClcblxuICAgICAgICAgICAgLnRoZW4oY29ubmVjdGlvbiA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3NpZ25hbCcsIFtuZXcgU2lnbmFsRXZlbnQodGhpcywgbXNnLnR5cGUsIG1zZy5kYXRhLCBjb25uZWN0aW9uKV0pO1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdzaWduYWw6JyArIG1zZy50eXBlLCBbbmV3IFNpZ25hbEV2ZW50KHRoaXMsIG1zZy50eXBlLCBtc2cuZGF0YSwgY29ubmVjdGlvbildKTtcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAuY2F0Y2gob3BlblZpZHVFcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihvcGVuVmlkdUVycm9yKTtcbiAgICAgICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvblN0cmVhbVByb3BlcnR5Q2hhbmdlZChtc2cpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5nZXRSZW1vdGVDb25uZWN0aW9uKG1zZy5jb25uZWN0aW9uSWQsICdSZW1vdGUgY29ubmVjdGlvbiAnICsgbXNnLmNvbm5lY3Rpb25JZCArIFwiIHVua25vd24gd2hlbiAnb25TdHJlYW1Qcm9wZXJ0eUNoYW5nZWQnLiBcIiArXG4gICAgICAgICAgICAnRXhpc3RpbmcgcmVtb3RlIGNvbm5lY3Rpb25zOiAnICsgSlNPTi5zdHJpbmdpZnkoT2JqZWN0LmtleXModGhpcy5yZW1vdGVDb25uZWN0aW9ucykpKVxuXG4gICAgICAgICAgICAudGhlbihjb25uZWN0aW9uID0+IHtcbiAgICAgICAgICAgICAgICBpZiAoISFjb25uZWN0aW9uLnN0cmVhbSAmJiBjb25uZWN0aW9uLnN0cmVhbS5zdHJlYW1JZCA9PT0gbXNnLnN0cmVhbUlkKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHN0cmVhbSA9IGNvbm5lY3Rpb24uc3RyZWFtO1xuICAgICAgICAgICAgICAgICAgICBsZXQgb2xkVmFsdWU7XG4gICAgICAgICAgICAgICAgICAgIHN3aXRjaCAobXNnLnByb3BlcnR5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlICdhdWRpb0FjdGl2ZSc6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgb2xkVmFsdWUgPSBzdHJlYW0uYXVkaW9BY3RpdmU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbXNnLm5ld1ZhbHVlID0gbXNnLm5ld1ZhbHVlID09PSAndHJ1ZSc7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyZWFtLmF1ZGlvQWN0aXZlID0gbXNnLm5ld1ZhbHVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAndmlkZW9BY3RpdmUnOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9sZFZhbHVlID0gc3RyZWFtLnZpZGVvQWN0aXZlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1zZy5uZXdWYWx1ZSA9IG1zZy5uZXdWYWx1ZSA9PT0gJ3RydWUnO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cmVhbS52aWRlb0FjdGl2ZSA9IG1zZy5uZXdWYWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJ3ZpZGVvRGltZW5zaW9ucyc6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgb2xkVmFsdWUgPSBzdHJlYW0udmlkZW9EaW1lbnNpb25zO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1zZy5uZXdWYWx1ZSA9IEpTT04ucGFyc2UoSlNPTi5wYXJzZShtc2cubmV3VmFsdWUpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJlYW0udmlkZW9EaW1lbnNpb25zID0gbXNnLm5ld1ZhbHVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3N0cmVhbVByb3BlcnR5Q2hhbmdlZCcsIFtuZXcgU3RyZWFtUHJvcGVydHlDaGFuZ2VkRXZlbnQodGhpcywgc3RyZWFtLCBtc2cucHJvcGVydHksIG1zZy5uZXdWYWx1ZSwgb2xkVmFsdWUsIG1zZy5yZWFzb24pXSk7XG4gICAgICAgICAgICAgICAgICAgIHN0cmVhbS5zdHJlYW1NYW5hZ2VyLmVtaXRFdmVudCgnc3RyZWFtUHJvcGVydHlDaGFuZ2VkJywgW25ldyBTdHJlYW1Qcm9wZXJ0eUNoYW5nZWRFdmVudChzdHJlYW0uc3RyZWFtTWFuYWdlciwgc3RyZWFtLCBtc2cucHJvcGVydHksIG1zZy5uZXdWYWx1ZSwgb2xkVmFsdWUsIG1zZy5yZWFzb24pXSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihcIk5vIHN0cmVhbSB3aXRoIHN0cmVhbUlkICdcIiArIG1zZy5zdHJlYW1JZCArIFwiJyBmb3VuZCBmb3IgY29ubmVjdGlvbiAnXCIgKyBtc2cuY29ubmVjdGlvbklkICsgXCInIG9uICdzdHJlYW1Qcm9wZXJ0eUNoYW5nZWQnIGV2ZW50XCIpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAuY2F0Y2gob3BlblZpZHVFcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihvcGVuVmlkdUVycm9yKTtcbiAgICAgICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICByZWN2SWNlQ2FuZGlkYXRlKG1zZyk6IHZvaWQge1xuICAgICAgICBjb25zdCBjYW5kaWRhdGUgPSB7XG4gICAgICAgICAgICBjYW5kaWRhdGU6IG1zZy5jYW5kaWRhdGUsXG4gICAgICAgICAgICBzZHBNaWQ6IG1zZy5zZHBNaWQsXG4gICAgICAgICAgICBzZHBNTGluZUluZGV4OiBtc2cuc2RwTUxpbmVJbmRleCxcbiAgICAgICAgICAgIHRvSlNPTjogKCkgPT4ge1xuICAgICAgICAgICAgICAgIHJldHVybiB7IGNhbmRpZGF0ZTogbXNnLmNhbmRpZGF0ZSB9O1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICB0aGlzLmdldENvbm5lY3Rpb24obXNnLmVuZHBvaW50TmFtZSwgJ0Nvbm5lY3Rpb24gbm90IGZvdW5kIGZvciBlbmRwb2ludCAnICsgbXNnLmVuZHBvaW50TmFtZSArICcuIEljZSBjYW5kaWRhdGUgd2lsbCBiZSBpZ25vcmVkOiAnICsgY2FuZGlkYXRlKVxuICAgICAgICAgICAgLnRoZW4oY29ubmVjdGlvbiA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3Qgc3RyZWFtID0gY29ubmVjdGlvbi5zdHJlYW07XG4gICAgICAgICAgICAgICAgc3RyZWFtLmdldFdlYlJ0Y1BlZXIoKS5hZGRJY2VDYW5kaWRhdGUoY2FuZGlkYXRlKS5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ0Vycm9yIGFkZGluZyBjYW5kaWRhdGUgZm9yICcgKyBzdHJlYW0uc3RyZWFtSWRcbiAgICAgICAgICAgICAgICAgICAgICAgICsgJyBzdHJlYW0gb2YgZW5kcG9pbnQgJyArIG1zZy5lbmRwb2ludE5hbWUgKyAnOiAnICsgZXJyb3IpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIC5jYXRjaChvcGVuVmlkdUVycm9yID0+IHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKG9wZW5WaWR1RXJyb3IpO1xuICAgICAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIG9uU2Vzc2lvbkNsb3NlZChtc2cpOiB2b2lkIHtcbiAgICAgICAgY29uc29sZS5pbmZvKCdTZXNzaW9uIGNsb3NlZDogJyArIEpTT04uc3RyaW5naWZ5KG1zZykpO1xuICAgICAgICBjb25zdCBzID0gbXNnLnNlc3Npb25JZDtcbiAgICAgICAgaWYgKHMgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3Nlc3Npb24tY2xvc2VkJywgW3tcbiAgICAgICAgICAgICAgICBzZXNzaW9uOiBzXG4gICAgICAgICAgICB9XSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjb25zb2xlLndhcm4oJ1Nlc3Npb24gdW5kZWZpbmVkIG9uIHNlc3Npb24gY2xvc2VkJywgbXNnKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvbkxvc3RDb25uZWN0aW9uKCk6IHZvaWQge1xuXG4gICAgICAgIC8qaWYgKCF0aGlzLmNvbm5lY3Rpb24pIHtcblxuICAgICAgICAgICAgY29uc29sZS53YXJuKCdOb3QgY29ubmVjdGVkIHRvIHNlc3Npb246IGlmIHlvdSBhcmUgbm90IGRlYnVnZ2luZywgdGhpcyBpcyBwcm9iYWJseSBhIGNlcnRpZmljYXRlIGVycm9yJyk7XG5cbiAgICAgICAgICAgIGNvbnN0IHVybCA9ICdodHRwczovLycgKyB0aGlzLm9wZW52aWR1LmdldFdzVXJpKCkuc3BsaXQoJ3dzczovLycpWzFdLnNwbGl0KCcvb3BlbnZpZHUnKVswXTtcbiAgICAgICAgICAgIGlmICh3aW5kb3cuY29uZmlybSgnSWYgeW91IGFyZSBub3QgZGVidWdnaW5nLCB0aGlzIGlzIHByb2JhYmx5IGEgY2VydGlmaWNhdGUgZXJyb3IgYXQgXFxcIicgKyB1cmwgKyAnXFxcIlxcblxcbkNsaWNrIE9LIHRvIG5hdmlnYXRlIGFuZCBhY2NlcHQgaXQnKSkge1xuICAgICAgICAgICAgICAgIGxvY2F0aW9uLmFzc2lnbih1cmwgKyAnL2FjY2VwdC1jZXJ0aWZpY2F0ZScpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9Ki9cblxuICAgICAgICBjb25zb2xlLndhcm4oJ0xvc3QgY29ubmVjdGlvbiBpbiBTZXNzaW9uICcgKyB0aGlzLnNlc3Npb25JZCk7XG4gICAgICAgIGlmICghIXRoaXMuc2Vzc2lvbklkICYmICF0aGlzLmNvbm5lY3Rpb24uZGlzcG9zZWQpIHtcbiAgICAgICAgICAgIHRoaXMubGVhdmUodHJ1ZSwgJ25ldHdvcmtEaXNjb25uZWN0Jyk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgb25SZWNvdmVyZWRDb25uZWN0aW9uKCk6IHZvaWQge1xuICAgICAgICBjb25zb2xlLndhcm4oJ1JlY292ZXJlZCBjb25uZWN0aW9uIGluIFNlc3Npb24gJyArIHRoaXMuc2Vzc2lvbklkKTtcbiAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ2Nvbm5lY3Rpb25SZWNvdmVyZWQnLCBbXSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIG9uTWVkaWFFcnJvcihwYXJhbXMpOiB2b2lkIHtcblxuICAgICAgICBjb25zb2xlLmVycm9yKCdNZWRpYSBlcnJvcjogJyArIEpTT04uc3RyaW5naWZ5KHBhcmFtcykpO1xuICAgICAgICBjb25zdCBlcnIgPSBwYXJhbXMuZXJyb3I7XG4gICAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdlcnJvci1tZWRpYScsIFt7XG4gICAgICAgICAgICAgICAgZXJyb3I6IGVyclxuICAgICAgICAgICAgfV0pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY29uc29sZS53YXJuKCdSZWNlaXZlZCB1bmRlZmluZWQgbWVkaWEgZXJyb3IuIFBhcmFtczonLCBwYXJhbXMpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIG9uUmVjb3JkaW5nU3RhcnRlZChyZXNwb25zZSk6IHZvaWQge1xuICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgncmVjb3JkaW5nU3RhcnRlZCcsIFtuZXcgUmVjb3JkaW5nRXZlbnQodGhpcywgJ3JlY29yZGluZ1N0YXJ0ZWQnLCByZXNwb25zZS5pZCwgcmVzcG9uc2UubmFtZSldKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgb25SZWNvcmRpbmdTdG9wcGVkKHJlc3BvbnNlKTogdm9pZCB7XG4gICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdyZWNvcmRpbmdTdG9wcGVkJywgW25ldyBSZWNvcmRpbmdFdmVudCh0aGlzLCAncmVjb3JkaW5nU3RvcHBlZCcsIHJlc3BvbnNlLmlkLCByZXNwb25zZS5uYW1lKV0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBlbWl0RXZlbnQodHlwZTogc3RyaW5nLCBldmVudEFycmF5OiBhbnlbXSk6IHZvaWQge1xuICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCh0eXBlLCBldmVudEFycmF5KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgbGVhdmUoZm9yY2VkOiBib29sZWFuLCByZWFzb246IHN0cmluZyk6IHZvaWQge1xuXG4gICAgICAgIGZvcmNlZCA9ICEhZm9yY2VkO1xuICAgICAgICBjb25zb2xlLmluZm8oJ0xlYXZpbmcgU2Vzc2lvbiAoZm9yY2VkPScgKyBmb3JjZWQgKyAnKScpO1xuXG4gICAgICAgIGlmICghIXRoaXMuY29ubmVjdGlvbikge1xuICAgICAgICAgICAgaWYgKCF0aGlzLmNvbm5lY3Rpb24uZGlzcG9zZWQgJiYgIWZvcmNlZCkge1xuICAgICAgICAgICAgICAgIHRoaXMub3BlbnZpZHUuc2VuZFJlcXVlc3QoJ2xlYXZlUm9vbScsIChlcnJvciwgcmVzcG9uc2UpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB0aGlzLm9wZW52aWR1LmNsb3NlV3MoKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy5vcGVudmlkdS5jbG9zZVdzKCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMuc3RvcFB1Ymxpc2hlclN0cmVhbShyZWFzb24pO1xuXG4gICAgICAgICAgICBpZiAoIXRoaXMuY29ubmVjdGlvbi5kaXNwb3NlZCkge1xuICAgICAgICAgICAgICAgIC8vIE1ha2UgU2Vzc2lvbiBvYmplY3QgZGlzcGF0Y2ggJ3Nlc3Npb25EaXNjb25uZWN0ZWQnIGV2ZW50IChpZiBpdCBpcyBub3QgYWxyZWFkeSBkaXNwb3NlZClcbiAgICAgICAgICAgICAgICBjb25zdCBzZXNzaW9uRGlzY29ubmVjdEV2ZW50ID0gbmV3IFNlc3Npb25EaXNjb25uZWN0ZWRFdmVudCh0aGlzLCByZWFzb24pO1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdzZXNzaW9uRGlzY29ubmVjdGVkJywgW3Nlc3Npb25EaXNjb25uZWN0RXZlbnRdKTtcbiAgICAgICAgICAgICAgICBzZXNzaW9uRGlzY29ubmVjdEV2ZW50LmNhbGxEZWZhdWx0QmVoYXZpb3IoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvbnNvbGUud2FybignWW91IHdlcmUgbm90IGNvbm5lY3RlZCB0byB0aGUgc2Vzc2lvbiAnICsgdGhpcy5zZXNzaW9uSWQpO1xuICAgICAgICB9XG4gICAgfVxuXG5cbiAgICAvKiBQcml2YXRlIG1ldGhvZHMgKi9cblxuICAgIHByaXZhdGUgY29ubmVjdEF1eCh0b2tlbjogc3RyaW5nKTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIHRoaXMub3BlbnZpZHUuc3RhcnRXcygoZXJyb3IpID0+IHtcbiAgICAgICAgICAgICAgICBpZiAoISFlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG5cbiAgICAgICAgICAgICAgICAgICAgY29uc3Qgam9pblBhcmFtcyA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRva2VuOiAoISF0b2tlbikgPyB0b2tlbiA6ICcnLFxuICAgICAgICAgICAgICAgICAgICAgICAgc2Vzc2lvbjogdGhpcy5zZXNzaW9uSWQsXG4gICAgICAgICAgICAgICAgICAgICAgICBtZXRhZGF0YTogISF0aGlzLm9wdGlvbnMubWV0YWRhdGEgPyB0aGlzLm9wdGlvbnMubWV0YWRhdGEgOiAnJyxcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlY3JldDogdGhpcy5vcGVudmlkdS5nZXRTZWNyZXQoKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlY29yZGVyOiB0aGlzLm9wZW52aWR1LmdldFJlY29yZGVyKCksXG4gICAgICAgICAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgICAgICAgICAgdGhpcy5vcGVudmlkdS5zZW5kUmVxdWVzdCgnam9pblJvb20nLCBqb2luUGFyYW1zLCAoZXJyb3IsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoISFlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gSW5pdGlhbGl6ZSBjYXBhYmlsaXRpZXMgb2JqZWN0IHdpdGggdGhlIHJvbGVcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNhcGFiaWxpdGllcyA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3Vic2NyaWJlOiB0cnVlLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwdWJsaXNoOiB0aGlzLm9wZW52aWR1LnJvbGUgIT09ICdTVUJTQ1JJQkVSJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yY2VVbnB1Ymxpc2g6IHRoaXMub3BlbnZpZHUucm9sZSA9PT0gJ01PREVSQVRPUicsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvcmNlRGlzY29ubmVjdDogdGhpcy5vcGVudmlkdS5yb2xlID09PSAnTU9ERVJBVE9SJ1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBJbml0aWFsaXplIGxvY2FsIENvbm5lY3Rpb24gb2JqZWN0IHdpdGggdmFsdWVzIHJldHVybmVkIGJ5IG9wZW52aWR1LXNlcnZlclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY29ubmVjdGlvbiA9IG5ldyBDb25uZWN0aW9uKHRoaXMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY29ubmVjdGlvbi5jb25uZWN0aW9uSWQgPSByZXNwb25zZS5pZDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbm5lY3Rpb24uZGF0YSA9IHJlc3BvbnNlLm1ldGFkYXRhO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gSW5pdGlhbGl6ZSByZW1vdGUgQ29ubmVjdGlvbnMgd2l0aCB2YWx1ZSByZXR1cm5lZCBieSBvcGVudmlkdS1zZXJ2ZXJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBldmVudHMgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbm5lY3Rpb25zOiBuZXcgQXJyYXk8Q29ubmVjdGlvbj4oKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyZWFtczogbmV3IEFycmF5PFN0cmVhbT4oKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZXhpc3RpbmdQYXJ0aWNpcGFudHM6IENvbm5lY3Rpb25PcHRpb25zW10gPSByZXNwb25zZS52YWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBleGlzdGluZ1BhcnRpY2lwYW50cy5mb3JFYWNoKHBhcnRpY2lwYW50ID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgY29ubmVjdGlvbiA9IG5ldyBDb25uZWN0aW9uKHRoaXMsIHBhcnRpY2lwYW50KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5yZW1vdGVDb25uZWN0aW9uc1tjb25uZWN0aW9uLmNvbm5lY3Rpb25JZF0gPSBjb25uZWN0aW9uO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBldmVudHMuY29ubmVjdGlvbnMucHVzaChjb25uZWN0aW9uKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCEhY29ubmVjdGlvbi5zdHJlYW0pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucmVtb3RlU3RyZWFtc0NyZWF0ZWRbY29ubmVjdGlvbi5zdHJlYW0uc3RyZWFtSWRdID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV2ZW50cy5zdHJlYW1zLnB1c2goY29ubmVjdGlvbi5zdHJlYW0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBPd24gJ2Nvbm5lY3Rpb25DcmVhdGVkJyBldmVudFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdjb25uZWN0aW9uQ3JlYXRlZCcsIFtuZXcgQ29ubmVjdGlvbkV2ZW50KGZhbHNlLCB0aGlzLCAnY29ubmVjdGlvbkNyZWF0ZWQnLCB0aGlzLmNvbm5lY3Rpb24sICcnKV0pO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gT25lICdjb25uZWN0aW9uQ3JlYXRlZCcgZXZlbnQgZm9yIGVhY2ggZXhpc3RpbmcgY29ubmVjdGlvbiBpbiB0aGUgc2Vzc2lvblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV2ZW50cy5jb25uZWN0aW9ucy5mb3JFYWNoKGNvbm5lY3Rpb24gPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnY29ubmVjdGlvbkNyZWF0ZWQnLCBbbmV3IENvbm5lY3Rpb25FdmVudChmYWxzZSwgdGhpcywgJ2Nvbm5lY3Rpb25DcmVhdGVkJywgY29ubmVjdGlvbiwgJycpXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBPbmUgJ3N0cmVhbUNyZWF0ZWQnIGV2ZW50IGZvciBlYWNoIGFjdGl2ZSBzdHJlYW0gaW4gdGhlIHNlc3Npb25cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBldmVudHMuc3RyZWFtcy5mb3JFYWNoKHN0cmVhbSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdzdHJlYW1DcmVhdGVkJywgW25ldyBTdHJlYW1FdmVudChmYWxzZSwgdGhpcywgJ3N0cmVhbUNyZWF0ZWQnLCBzdHJlYW0sICcnKV0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBzdG9wUHVibGlzaGVyU3RyZWFtKHJlYXNvbjogc3RyaW5nKSB7XG4gICAgICAgIGlmICghIXRoaXMuY29ubmVjdGlvbi5zdHJlYW0pIHtcbiAgICAgICAgICAgIC8vIERpc3Bvc2UgUHVibGlzaGVyJ3MgIGxvY2FsIHN0cmVhbVxuICAgICAgICAgICAgdGhpcy5jb25uZWN0aW9uLnN0cmVhbS5kaXNwb3NlV2ViUnRjUGVlcigpO1xuICAgICAgICAgICAgaWYgKHRoaXMuY29ubmVjdGlvbi5zdHJlYW0uaXNMb2NhbFN0cmVhbVB1Ymxpc2hlZCkge1xuICAgICAgICAgICAgICAgIC8vIE1ha2UgUHVibGlzaGVyIG9iamVjdCBkaXNwYXRjaCAnc3RyZWFtRGVzdHJveWVkJyBldmVudCBpZiB0aGUgU3RyZWFtIHdhcyBwdWJsaXNoZWRcbiAgICAgICAgICAgICAgICB0aGlzLmNvbm5lY3Rpb24uc3RyZWFtLmVlLmVtaXRFdmVudCgnbG9jYWwtc3RyZWFtLWRlc3Ryb3llZCcsIFtyZWFzb25dKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgc3RyaW5nQ2xpZW50TWV0YWRhdGEobWV0YWRhdGE6IGFueSk6IHN0cmluZyB7XG4gICAgICAgIGlmICh0eXBlb2YgbWV0YWRhdGEgIT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkobWV0YWRhdGEpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIG1ldGFkYXRhO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBnZXRDb25uZWN0aW9uKGNvbm5lY3Rpb25JZDogc3RyaW5nLCBlcnJvck1lc3NhZ2U6IHN0cmluZyk6IFByb21pc2U8Q29ubmVjdGlvbj4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2U8Q29ubmVjdGlvbj4oKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgY29uc3QgY29ubmVjdGlvbiA9IHRoaXMucmVtb3RlQ29ubmVjdGlvbnNbY29ubmVjdGlvbklkXTtcbiAgICAgICAgICAgIGlmICghIWNvbm5lY3Rpb24pIHtcbiAgICAgICAgICAgICAgICAvLyBSZXNvbHZlIHJlbW90ZSBjb25uZWN0aW9uXG4gICAgICAgICAgICAgICAgcmVzb2x2ZShjb25uZWN0aW9uKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuY29ubmVjdGlvbi5jb25uZWN0aW9uSWQgPT09IGNvbm5lY3Rpb25JZCkge1xuICAgICAgICAgICAgICAgICAgICAvLyBSZXNvbHZlIGxvY2FsIGNvbm5lY3Rpb25cbiAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSh0aGlzLmNvbm5lY3Rpb24pO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIENvbm5lY3Rpb24gbm90IGZvdW5kLiBSZWplY3Qgd2l0aCBPcGVuVmlkdUVycm9yXG4gICAgICAgICAgICAgICAgICAgIHJlamVjdChuZXcgT3BlblZpZHVFcnJvcihPcGVuVmlkdUVycm9yTmFtZS5HRU5FUklDX0VSUk9SLCBlcnJvck1lc3NhZ2UpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIHByaXZhdGUgZ2V0UmVtb3RlQ29ubmVjdGlvbihjb25uZWN0aW9uSWQ6IHN0cmluZywgZXJyb3JNZXNzYWdlOiBzdHJpbmcpOiBQcm9taXNlPENvbm5lY3Rpb24+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlPENvbm5lY3Rpb24+KChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGNvbm5lY3Rpb24gPSB0aGlzLnJlbW90ZUNvbm5lY3Rpb25zW2Nvbm5lY3Rpb25JZF07XG4gICAgICAgICAgICBpZiAoISFjb25uZWN0aW9uKSB7XG4gICAgICAgICAgICAgICAgLy8gUmVzb2x2ZSByZW1vdGUgY29ubmVjdGlvblxuICAgICAgICAgICAgICAgIHJlc29sdmUoY29ubmVjdGlvbik7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIC8vIFJlbW90ZSBjb25uZWN0aW9uIG5vdCBmb3VuZC4gUmVqZWN0IHdpdGggT3BlblZpZHVFcnJvclxuICAgICAgICAgICAgICAgIHJlamVjdChuZXcgT3BlblZpZHVFcnJvcihPcGVuVmlkdUVycm9yTmFtZS5HRU5FUklDX0VSUk9SLCBlcnJvck1lc3NhZ2UpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBwcm9jZXNzVG9rZW4odG9rZW46IHN0cmluZyk6IHZvaWQge1xuICAgICAgICBjb25zdCB1cmwgPSBuZXcgVVJMKHRva2VuKTtcbiAgICAgICAgdGhpcy5zZXNzaW9uSWQgPSA8c3RyaW5nPnVybC5zZWFyY2hQYXJhbXMuZ2V0KCdzZXNzaW9uSWQnKTtcbiAgICAgICAgY29uc3Qgc2VjcmV0ID0gdXJsLnNlYXJjaFBhcmFtcy5nZXQoJ3NlY3JldCcpO1xuICAgICAgICBjb25zdCByZWNvcmRlciA9IHVybC5zZWFyY2hQYXJhbXMuZ2V0KCdyZWNvcmRlcicpO1xuICAgICAgICBjb25zdCB0dXJuVXNlcm5hbWUgPSB1cmwuc2VhcmNoUGFyYW1zLmdldCgndHVyblVzZXJuYW1lJyk7XG4gICAgICAgIGNvbnN0IHR1cm5DcmVkZW50aWFsID0gdXJsLnNlYXJjaFBhcmFtcy5nZXQoJ3R1cm5DcmVkZW50aWFsJyk7XG4gICAgICAgIGNvbnN0IHJvbGUgPSB1cmwuc2VhcmNoUGFyYW1zLmdldCgncm9sZScpO1xuXG4gICAgICAgIGlmICghIXNlY3JldCkge1xuICAgICAgICAgICAgdGhpcy5vcGVudmlkdS5zZWNyZXQgPSBzZWNyZXQ7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCEhcmVjb3JkZXIpIHtcbiAgICAgICAgICAgIHRoaXMub3BlbnZpZHUucmVjb3JkZXIgPSB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIGlmICghIXR1cm5Vc2VybmFtZSAmJiAhIXR1cm5DcmVkZW50aWFsKSB7XG4gICAgICAgICAgICBjb25zdCBzdHVuVXJsID0gJ3N0dW46JyArIHVybC5ob3N0bmFtZSArICc6MzQ3OCc7XG4gICAgICAgICAgICBjb25zdCB0dXJuVXJsMSA9ICd0dXJuOicgKyB1cmwuaG9zdG5hbWUgKyAnOjM0NzgnO1xuICAgICAgICAgICAgY29uc3QgdHVyblVybDIgPSB0dXJuVXJsMSArICc/dHJhbnNwb3J0PXRjcCc7XG4gICAgICAgICAgICB0aGlzLm9wZW52aWR1LmljZVNlcnZlcnMgPSBbXG4gICAgICAgICAgICAgICAgeyB1cmxzOiBbc3R1blVybF0gfSxcbiAgICAgICAgICAgICAgICB7IHVybHM6IFt0dXJuVXJsMSwgdHVyblVybDJdLCB1c2VybmFtZTogdHVyblVzZXJuYW1lLCBjcmVkZW50aWFsOiB0dXJuQ3JlZGVudGlhbCB9XG4gICAgICAgICAgICBdO1xuICAgICAgICAgICAgY29uc29sZS5sb2coJ1RVUk4gdGVtcCBjcmVkZW50aWFscyBbJyArIHR1cm5Vc2VybmFtZSArICc6JyArIHR1cm5DcmVkZW50aWFsICsgJ10nKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoISFyb2xlKSB7XG4gICAgICAgICAgICB0aGlzLm9wZW52aWR1LnJvbGUgPSByb2xlO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5vcGVudmlkdS53c1VyaSA9ICd3c3M6Ly8nICsgdXJsLmhvc3QgKyAnL29wZW52aWR1JztcbiAgICB9XG5cbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IENvbm5lY3Rpb24gfSBmcm9tICcuL0Nvbm5lY3Rpb24nO1xuaW1wb3J0IHsgU2Vzc2lvbiB9IGZyb20gJy4vU2Vzc2lvbic7XG5pbXBvcnQgeyBTdHJlYW1NYW5hZ2VyIH0gZnJvbSAnLi9TdHJlYW1NYW5hZ2VyJztcbmltcG9ydCB7IEluYm91bmRTdHJlYW1PcHRpb25zIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9JbnRlcmZhY2VzL1ByaXZhdGUvSW5ib3VuZFN0cmVhbU9wdGlvbnMnO1xuaW1wb3J0IHsgT3V0Ym91bmRTdHJlYW1PcHRpb25zIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9JbnRlcmZhY2VzL1ByaXZhdGUvT3V0Ym91bmRTdHJlYW1PcHRpb25zJztcbmltcG9ydCB7IFdlYlJ0Y1BlZXIsIFdlYlJ0Y1BlZXJTZW5kb25seSwgV2ViUnRjUGVlclJlY3Zvbmx5LCBXZWJSdGNQZWVyU2VuZHJlY3YgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL1dlYlJ0Y1BlZXIvV2ViUnRjUGVlcic7XG5pbXBvcnQgeyBXZWJSdGNTdGF0cyB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvV2ViUnRjU3RhdHMvV2ViUnRjU3RhdHMnO1xuaW1wb3J0IHsgUHVibGlzaGVyU3BlYWtpbmdFdmVudCB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1B1Ymxpc2hlclNwZWFraW5nRXZlbnQnO1xuXG5pbXBvcnQgRXZlbnRFbWl0dGVyID0gcmVxdWlyZSgnd29sZnk4Ny1ldmVudGVtaXR0ZXInKTtcbmltcG9ydCBoYXJrID0gcmVxdWlyZSgnaGFyaycpO1xuaW1wb3J0IHsgT3BlblZpZHVFcnJvciwgT3BlblZpZHVFcnJvck5hbWUgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0VudW1zL09wZW5WaWR1RXJyb3InO1xuXG5cbi8qKlxuICogUmVwcmVzZW50cyBlYWNoIG9uZSBvZiB0aGUgbWVkaWEgc3RyZWFtcyBhdmFpbGFibGUgaW4gT3BlblZpZHUgU2VydmVyIGZvciBjZXJ0YWluIHNlc3Npb24uXG4gKiBFYWNoIFtbUHVibGlzaGVyXV0gYW5kIFtbU3Vic2NyaWJlcl1dIGhhcyBhbiBhdHRyaWJ1dGUgb2YgdHlwZSBTdHJlYW0sIGFzIHRoZXkgZ2l2ZSBhY2Nlc3NcbiAqIHRvIG9uZSBvZiB0aGVtIChzZW5kaW5nIGFuZCByZWNlaXZpbmcgaXQsIHJlc3BlY3RpdmVseSlcbiAqL1xuZXhwb3J0IGNsYXNzIFN0cmVhbSB7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgQ29ubmVjdGlvbiBvYmplY3QgdGhhdCBpcyBwdWJsaXNoaW5nIHRoZSBzdHJlYW1cbiAgICAgKi9cbiAgICBjb25uZWN0aW9uOiBDb25uZWN0aW9uO1xuXG4gICAgLyoqXG4gICAgICogRnJhbWUgcmF0ZSBvZiB0aGUgdmlkZW8gaW4gZnJhbWVzIHBlciBzZWNvbmQuIFRoaXMgcHJvcGVydHkgaXMgb25seSBkZWZpbmVkIGlmIHRoZSBbW1B1Ymxpc2hlcl1dIG9mXG4gICAgICogdGhlIHN0cmVhbSB3YXMgaW5pdGlhbGl6ZWQgcGFzc2luZyBhIF9mcmFtZVJhdGVfIHByb3BlcnR5IG9uIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dIG1ldGhvZFxuICAgICAqL1xuICAgIGZyYW1lUmF0ZT86IG51bWJlcjtcblxuICAgIC8qKlxuICAgICAqIFdoZXRoZXIgdGhlIHN0cmVhbSBoYXMgYSB2aWRlbyB0cmFjayBvciBub3RcbiAgICAgKi9cbiAgICBoYXNWaWRlbzogYm9vbGVhbjtcblxuICAgIC8qKlxuICAgICAqIFdoZXRoZXIgdGhlIHN0cmVhbSBoYXMgYW4gYXVkaW8gdHJhY2sgb3Igbm90XG4gICAgICovXG4gICAgaGFzQXVkaW86IGJvb2xlYW47XG5cbiAgICAvKipcbiAgICAgKiBXaGV0aGVyIHRoZSBzdHJlYW0gaGFzIHRoZSB2aWRlbyB0cmFjayBtdXRlZCBvciB1bm11dGVkLiBJZiBbW2hhc1ZpZGVvXV0gaXMgZmFsc2UsIHRoaXMgcHJvcGVydHkgaXMgdW5kZWZpbmVkLlxuICAgICAqXG4gICAgICogVGhpcyBwcm9wZXJ0eSBtYXkgY2hhbmdlIGlmIHRoZSBQdWJsaXNoZXIgcHVibGlzaGluZyB0aGUgc3RyZWFtIGNhbGxzIFtbUHVibGlzaGVyLnB1Ymxpc2hWaWRlb11dLiBXaGVuZXZlciB0aGlzIGhhcHBlbnMgYSBbW1N0cmVhbVByb3BlcnR5Q2hhbmdlZEV2ZW50XV0gd2lsbCBiZSBkaXNwYXRjaGVkXG4gICAgICogYnkgdGhlIFNlc3Npb24gb2JqZWN0IGFzIHdlbGwgYXMgYnkgdGhlIGFmZmVjdGVkIFN1YnNjcmliZXIvUHVibGlzaGVyIG9iamVjdFxuICAgICAqL1xuICAgIHZpZGVvQWN0aXZlOiBib29sZWFuO1xuXG4gICAgLyoqXG4gICAgICogV2hldGhlciB0aGUgc3RyZWFtIGhhcyB0aGUgYXVkaW8gdHJhY2sgbXV0ZWQgb3IgdW5tdXRlZC4gSWYgW1toYXNBdWRpb11dIGlzIGZhbHNlLCB0aGlzIHByb3BlcnR5IGlzIHVuZGVmaW5lZFxuICAgICAqXG4gICAgICogVGhpcyBwcm9wZXJ0eSBtYXkgY2hhbmdlIGlmIHRoZSBQdWJsaXNoZXIgcHVibGlzaGluZyB0aGUgc3RyZWFtIGNhbGxzIFtbUHVibGlzaGVyLnB1Ymxpc2hBdWRpb11dLiBXaGVuZXZlciB0aGlzIGhhcHBlbnMgYSBbW1N0cmVhbVByb3BlcnR5Q2hhbmdlZEV2ZW50XV0gd2lsbCBiZSBkaXNwYXRjaGVkXG4gICAgICogYnkgdGhlIFNlc3Npb24gb2JqZWN0IGFzIHdlbGwgYXMgYnkgdGhlIGFmZmVjdGVkIFN1YnNjcmliZXIvUHVibGlzaGVyIG9iamVjdFxuICAgICAqL1xuICAgIGF1ZGlvQWN0aXZlOiBib29sZWFuO1xuXG4gICAgLyoqXG4gICAgICogVW5pcXVlIGlkZW50aWZpZXIgb2YgdGhlIHN0cmVhbVxuICAgICAqL1xuICAgIHN0cmVhbUlkOiBzdHJpbmc7XG5cbiAgICAvKipcbiAgICAgKiBgXCJDQU1FUkFcImAsIGBcIlNDUkVFTlwiYCBvciBgXCJDVVNUT01cImAgKHRoZSBsYXR0ZXIgd2hlbiBbW1B1Ymxpc2hlclByb3BlcnRpZXMudmlkZW9Tb3VyY2VdXSBpcyBhIE1lZGlhU3RyZWFtVHJhY2sgd2hlbiBjYWxsaW5nIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dKS5cbiAgICAgKiBJZiBbW2hhc1ZpZGVvXV0gaXMgZmFsc2UsIHRoaXMgcHJvcGVydHkgaXMgdW5kZWZpbmVkXG4gICAgICovXG4gICAgdHlwZU9mVmlkZW8/OiBzdHJpbmc7XG5cbiAgICAvKipcbiAgICAgKiBTdHJlYW1NYW5hZ2VyIG9iamVjdCAoW1tQdWJsaXNoZXJdXSBvciBbW1N1YnNjcmliZXJdXSkgaW4gY2hhcmdlIG9mIGRpc3BsYXlpbmcgdGhpcyBzdHJlYW0gaW4gdGhlIERPTVxuICAgICAqL1xuICAgIHN0cmVhbU1hbmFnZXI6IFN0cmVhbU1hbmFnZXI7XG5cbiAgICAvKipcbiAgICAgKiBXaWR0aCBhbmQgaGVpZ2h0IGluIHBpeGVscyBvZiB0aGUgZW5jb2RlZCB2aWRlbyBzdHJlYW0uIElmIFtbaGFzVmlkZW9dXSBpcyBmYWxzZSwgdGhpcyBwcm9wZXJ0eSBpcyB1bmRlZmluZWRcbiAgICAgKlxuICAgICAqIFRoaXMgcHJvcGVydHkgbWF5IGNoYW5nZSBpZiB0aGUgUHVibGlzaGVyIHRoYXQgaXMgcHVibGlzaGluZzpcbiAgICAgKiAtIElmIGl0IGlzIGEgbW9iaWxlIGRldmljZSwgd2hlbmV2ZXIgdGhlIHVzZXIgcm90YXRlcyB0aGUgZGV2aWNlLlxuICAgICAqIC0gSWYgaXQgaXMgc2NyZWVuLXNoYXJpbmcsIHdoZW5ldmVyIHRoZSB1c2VyIGNoYW5nZXMgdGhlIHNpemUgb2YgdGhlIGNhcHR1cmVkIHdpbmRvdy5cbiAgICAgKlxuICAgICAqIFdoZW5ldmVyIHRoaXMgaGFwcGVucyBhIFtbU3RyZWFtUHJvcGVydHlDaGFuZ2VkRXZlbnRdXSB3aWxsIGJlIGRpc3BhdGNoZWQgYnkgdGhlIFNlc3Npb24gb2JqZWN0IGFzIHdlbGwgYXMgYnkgdGhlIGFmZmVjdGVkIFN1YnNjcmliZXIvUHVibGlzaGVyIG9iamVjdFxuICAgICAqL1xuICAgIHZpZGVvRGltZW5zaW9uczogeyB3aWR0aDogbnVtYmVyLCBoZWlnaHQ6IG51bWJlciB9O1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGVlID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuXG4gICAgcHJpdmF0ZSB3ZWJSdGNQZWVyOiBXZWJSdGNQZWVyO1xuICAgIHByaXZhdGUgbWVkaWFTdHJlYW06IE1lZGlhU3RyZWFtO1xuICAgIHByaXZhdGUgd2ViUnRjU3RhdHM6IFdlYlJ0Y1N0YXRzO1xuXG4gICAgcHJpdmF0ZSBpc1N1YnNjcmliZVRvUmVtb3RlID0gZmFsc2U7XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgaXNMb2NhbFN0cmVhbVJlYWR5VG9QdWJsaXNoID0gZmFsc2U7XG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGlzTG9jYWxTdHJlYW1QdWJsaXNoZWQgPSBmYWxzZTtcbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgcHVibGlzaGVkT25jZSA9IGZhbHNlO1xuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBzZXNzaW9uOiBTZXNzaW9uO1xuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBpbmJvdW5kU3RyZWFtT3B0czogSW5ib3VuZFN0cmVhbU9wdGlvbnM7XG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIG91dGJvdW5kU3RyZWFtT3B0czogT3V0Ym91bmRTdHJlYW1PcHRpb25zO1xuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBzcGVlY2hFdmVudDogYW55O1xuXG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgY29uc3RydWN0b3Ioc2Vzc2lvbjogU2Vzc2lvbiwgb3B0aW9uczogSW5ib3VuZFN0cmVhbU9wdGlvbnMgfCBPdXRib3VuZFN0cmVhbU9wdGlvbnMgfCB7fSkge1xuXG4gICAgICAgIHRoaXMuc2Vzc2lvbiA9IHNlc3Npb247XG5cbiAgICAgICAgaWYgKG9wdGlvbnMuaGFzT3duUHJvcGVydHkoJ2lkJykpIHtcbiAgICAgICAgICAgIC8vIEluYm91bmRTdHJlYW1PcHRpb25zOiBzdHJlYW0gYmVsb25ncyB0byBhIFN1YnNjcmliZXJcbiAgICAgICAgICAgIHRoaXMuaW5ib3VuZFN0cmVhbU9wdHMgPSA8SW5ib3VuZFN0cmVhbU9wdGlvbnM+b3B0aW9ucztcbiAgICAgICAgICAgIHRoaXMuc3RyZWFtSWQgPSB0aGlzLmluYm91bmRTdHJlYW1PcHRzLmlkO1xuICAgICAgICAgICAgdGhpcy5oYXNBdWRpbyA9IHRoaXMuaW5ib3VuZFN0cmVhbU9wdHMuaGFzQXVkaW87XG4gICAgICAgICAgICB0aGlzLmhhc1ZpZGVvID0gdGhpcy5pbmJvdW5kU3RyZWFtT3B0cy5oYXNWaWRlbztcbiAgICAgICAgICAgIGlmICh0aGlzLmhhc0F1ZGlvKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5hdWRpb0FjdGl2ZSA9IHRoaXMuaW5ib3VuZFN0cmVhbU9wdHMuYXVkaW9BY3RpdmU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodGhpcy5oYXNWaWRlbykge1xuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9BY3RpdmUgPSB0aGlzLmluYm91bmRTdHJlYW1PcHRzLnZpZGVvQWN0aXZlO1xuICAgICAgICAgICAgICAgIHRoaXMudHlwZU9mVmlkZW8gPSAoIXRoaXMuaW5ib3VuZFN0cmVhbU9wdHMudHlwZU9mVmlkZW8pID8gdW5kZWZpbmVkIDogdGhpcy5pbmJvdW5kU3RyZWFtT3B0cy50eXBlT2ZWaWRlbztcbiAgICAgICAgICAgICAgICB0aGlzLmZyYW1lUmF0ZSA9ICh0aGlzLmluYm91bmRTdHJlYW1PcHRzLmZyYW1lUmF0ZSA9PT0gLTEpID8gdW5kZWZpbmVkIDogdGhpcy5pbmJvdW5kU3RyZWFtT3B0cy5mcmFtZVJhdGU7XG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb0RpbWVuc2lvbnMgPSB0aGlzLmluYm91bmRTdHJlYW1PcHRzLnZpZGVvRGltZW5zaW9ucztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIE91dGJvdW5kU3RyZWFtT3B0aW9uczogc3RyZWFtIGJlbG9uZ3MgdG8gYSBQdWJsaXNoZXJcbiAgICAgICAgICAgIHRoaXMub3V0Ym91bmRTdHJlYW1PcHRzID0gPE91dGJvdW5kU3RyZWFtT3B0aW9ucz5vcHRpb25zO1xuXG4gICAgICAgICAgICB0aGlzLmhhc0F1ZGlvID0gdGhpcy5pc1NlbmRBdWRpbygpO1xuICAgICAgICAgICAgdGhpcy5oYXNWaWRlbyA9IHRoaXMuaXNTZW5kVmlkZW8oKTtcblxuICAgICAgICAgICAgaWYgKHRoaXMuaGFzQXVkaW8pIHtcbiAgICAgICAgICAgICAgICB0aGlzLmF1ZGlvQWN0aXZlID0gISF0aGlzLm91dGJvdW5kU3RyZWFtT3B0cy5wdWJsaXNoZXJQcm9wZXJ0aWVzLnB1Ymxpc2hBdWRpbztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0aGlzLmhhc1ZpZGVvKSB7XG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb0FjdGl2ZSA9ICEhdGhpcy5vdXRib3VuZFN0cmVhbU9wdHMucHVibGlzaGVyUHJvcGVydGllcy5wdWJsaXNoVmlkZW87XG4gICAgICAgICAgICAgICAgdGhpcy5mcmFtZVJhdGUgPSB0aGlzLm91dGJvdW5kU3RyZWFtT3B0cy5wdWJsaXNoZXJQcm9wZXJ0aWVzLmZyYW1lUmF0ZTtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5vdXRib3VuZFN0cmVhbU9wdHMucHVibGlzaGVyUHJvcGVydGllcy52aWRlb1NvdXJjZSBpbnN0YW5jZW9mIE1lZGlhU3RyZWFtVHJhY2spIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy50eXBlT2ZWaWRlbyA9ICdDVVNUT00nO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMudHlwZU9mVmlkZW8gPSB0aGlzLmlzU2VuZFNjcmVlbigpID8gJ1NDUkVFTicgOiAnQ0FNRVJBJztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLmVlLm9uKCdtZWRpYXN0cmVhbS11cGRhdGVkJywgKCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5zdHJlYW1NYW5hZ2VyLnVwZGF0ZU1lZGlhU3RyZWFtKHRoaXMubWVkaWFTdHJlYW0pO1xuICAgICAgICAgICAgY29uc29sZS5kZWJ1ZygnVmlkZW8gc3JjT2JqZWN0IFsnICsgdGhpcy5tZWRpYVN0cmVhbSArICddIHVwZGF0ZWQgaW4gc3RyZWFtIFsnICsgdGhpcy5zdHJlYW1JZCArICddJyk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuXG4gICAgLyogSGlkZGVuIG1ldGhvZHMgKi9cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBnZXRNZWRpYVN0cmVhbSgpOiBNZWRpYVN0cmVhbSB7XG4gICAgICAgIHJldHVybiB0aGlzLm1lZGlhU3RyZWFtO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBzZXRNZWRpYVN0cmVhbShtZWRpYVN0cmVhbTogTWVkaWFTdHJlYW0pOiB2b2lkIHtcbiAgICAgICAgdGhpcy5tZWRpYVN0cmVhbSA9IG1lZGlhU3RyZWFtO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICB1cGRhdGVNZWRpYVN0cmVhbUluVmlkZW9zKCkge1xuICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnbWVkaWFzdHJlYW0tdXBkYXRlZCcpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBnZXRXZWJSdGNQZWVyKCk6IFdlYlJ0Y1BlZXIge1xuICAgICAgICByZXR1cm4gdGhpcy53ZWJSdGNQZWVyO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBnZXRSVENQZWVyQ29ubmVjdGlvbigpOiBSVENQZWVyQ29ubmVjdGlvbiB7XG4gICAgICAgIHJldHVybiB0aGlzLndlYlJ0Y1BlZXIucGM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHN1YnNjcmliZVRvTXlSZW1vdGUodmFsdWU6IGJvb2xlYW4pOiB2b2lkIHtcbiAgICAgICAgdGhpcy5pc1N1YnNjcmliZVRvUmVtb3RlID0gdmFsdWU7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHNldE91dGJvdW5kU3RyZWFtT3B0aW9ucyhvdXRib3VuZFN0cmVhbU9wdHM6IE91dGJvdW5kU3RyZWFtT3B0aW9ucyk6IHZvaWQge1xuICAgICAgICB0aGlzLm91dGJvdW5kU3RyZWFtT3B0cyA9IG91dGJvdW5kU3RyZWFtT3B0cztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgc3Vic2NyaWJlKCk6IFByb21pc2U8YW55PiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICB0aGlzLmluaXRXZWJSdGNQZWVyUmVjZWl2ZSgpXG4gICAgICAgICAgICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgcHVibGlzaCgpOiBQcm9taXNlPGFueT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgaWYgKHRoaXMuaXNMb2NhbFN0cmVhbVJlYWR5VG9QdWJsaXNoKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5pbml0V2ViUnRjUGVlclNlbmQoKVxuICAgICAgICAgICAgICAgICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy5lZS5vbmNlKCdzdHJlYW0tcmVhZHktdG8tcHVibGlzaCcsICgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5wdWJsaXNoKClcbiAgICAgICAgICAgICAgICAgICAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgICAgICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBkaXNwb3NlV2ViUnRjUGVlcigpOiB2b2lkIHtcbiAgICAgICAgaWYgKHRoaXMud2ViUnRjUGVlcikge1xuICAgICAgICAgICAgdGhpcy53ZWJSdGNQZWVyLmRpc3Bvc2UoKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5zcGVlY2hFdmVudCkge1xuICAgICAgICAgICAgdGhpcy5zcGVlY2hFdmVudC5zdG9wKCk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLnN0b3BXZWJSdGNTdGF0cygpO1xuXG4gICAgICAgIGNvbnNvbGUuaW5mbygoISF0aGlzLm91dGJvdW5kU3RyZWFtT3B0cyA/ICdPdXRib3VuZCAnIDogJ0luYm91bmQgJykgKyBcIldlYlJUQ1BlZXIgZnJvbSAnU3RyZWFtJyB3aXRoIGlkIFtcIiArIHRoaXMuc3RyZWFtSWQgKyAnXSBpcyBub3cgY2xvc2VkJyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGRpc3Bvc2VNZWRpYVN0cmVhbSgpOiB2b2lkIHtcbiAgICAgICAgaWYgKHRoaXMubWVkaWFTdHJlYW0pIHtcbiAgICAgICAgICAgIHRoaXMubWVkaWFTdHJlYW0uZ2V0QXVkaW9UcmFja3MoKS5mb3JFYWNoKCh0cmFjaykgPT4ge1xuICAgICAgICAgICAgICAgIHRyYWNrLnN0b3AoKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgdGhpcy5tZWRpYVN0cmVhbS5nZXRWaWRlb1RyYWNrcygpLmZvckVhY2goKHRyYWNrKSA9PiB7XG4gICAgICAgICAgICAgICAgdHJhY2suc3RvcCgpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBkZWxldGUgdGhpcy5tZWRpYVN0cmVhbTtcbiAgICAgICAgfVxuICAgICAgICBjb25zb2xlLmluZm8oKCEhdGhpcy5vdXRib3VuZFN0cmVhbU9wdHMgPyAnTG9jYWwgJyA6ICdSZW1vdGUgJykgKyBcIk1lZGlhU3RyZWFtIGZyb20gJ1N0cmVhbScgd2l0aCBpZCBbXCIgKyB0aGlzLnN0cmVhbUlkICsgJ10gaXMgbm93IGRpc3Bvc2VkJyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGRpc3BsYXlNeVJlbW90ZSgpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuaXNTdWJzY3JpYmVUb1JlbW90ZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgaXNTZW5kQXVkaW8oKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiAoISF0aGlzLm91dGJvdW5kU3RyZWFtT3B0cyAmJlxuICAgICAgICAgICAgdGhpcy5vdXRib3VuZFN0cmVhbU9wdHMucHVibGlzaGVyUHJvcGVydGllcy5hdWRpb1NvdXJjZSAhPT0gbnVsbCAmJlxuICAgICAgICAgICAgdGhpcy5vdXRib3VuZFN0cmVhbU9wdHMucHVibGlzaGVyUHJvcGVydGllcy5hdWRpb1NvdXJjZSAhPT0gZmFsc2UpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBpc1NlbmRWaWRlbygpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuICghIXRoaXMub3V0Ym91bmRTdHJlYW1PcHRzICYmXG4gICAgICAgICAgICB0aGlzLm91dGJvdW5kU3RyZWFtT3B0cy5wdWJsaXNoZXJQcm9wZXJ0aWVzLnZpZGVvU291cmNlICE9PSBudWxsICYmXG4gICAgICAgICAgICB0aGlzLm91dGJvdW5kU3RyZWFtT3B0cy5wdWJsaXNoZXJQcm9wZXJ0aWVzLnZpZGVvU291cmNlICE9PSBmYWxzZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGlzU2VuZFNjcmVlbigpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuICghIXRoaXMub3V0Ym91bmRTdHJlYW1PcHRzICYmXG4gICAgICAgICAgICB0aGlzLm91dGJvdW5kU3RyZWFtT3B0cy5wdWJsaXNoZXJQcm9wZXJ0aWVzLnZpZGVvU291cmNlID09PSAnc2NyZWVuJyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHNldFNwZWVjaEV2ZW50SWZOb3RFeGlzdHMoKTogdm9pZCB7XG4gICAgICAgIGlmICghdGhpcy5zcGVlY2hFdmVudCkge1xuICAgICAgICAgICAgY29uc3QgaGFya09wdGlvbnMgPSB0aGlzLnNlc3Npb24ub3BlbnZpZHUuYWR2YW5jZWRDb25maWd1cmF0aW9uLnB1Ymxpc2hlclNwZWFraW5nRXZlbnRzT3B0aW9ucyB8fCB7fTtcbiAgICAgICAgICAgIGhhcmtPcHRpb25zLmludGVydmFsID0gKHR5cGVvZiBoYXJrT3B0aW9ucy5pbnRlcnZhbCA9PT0gJ251bWJlcicpID8gaGFya09wdGlvbnMuaW50ZXJ2YWwgOiA1MDtcbiAgICAgICAgICAgIGhhcmtPcHRpb25zLnRocmVzaG9sZCA9ICh0eXBlb2YgaGFya09wdGlvbnMudGhyZXNob2xkID09PSAnbnVtYmVyJykgPyBoYXJrT3B0aW9ucy50aHJlc2hvbGQgOiAtNTA7XG5cbiAgICAgICAgICAgIHRoaXMuc3BlZWNoRXZlbnQgPSBoYXJrKHRoaXMubWVkaWFTdHJlYW0sIGhhcmtPcHRpb25zKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBlbmFibGVTcGVha2luZ0V2ZW50cygpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5zZXRTcGVlY2hFdmVudElmTm90RXhpc3RzKCk7XG4gICAgICAgIHRoaXMuc3BlZWNoRXZlbnQub24oJ3NwZWFraW5nJywgKCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5zZXNzaW9uLmVtaXRFdmVudCgncHVibGlzaGVyU3RhcnRTcGVha2luZycsIFtuZXcgUHVibGlzaGVyU3BlYWtpbmdFdmVudCh0aGlzLnNlc3Npb24sICdwdWJsaXNoZXJTdGFydFNwZWFraW5nJywgdGhpcy5jb25uZWN0aW9uLCB0aGlzLnN0cmVhbUlkKV0pO1xuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy5zcGVlY2hFdmVudC5vbignc3RvcHBlZF9zcGVha2luZycsICgpID0+IHtcbiAgICAgICAgICAgIHRoaXMuc2Vzc2lvbi5lbWl0RXZlbnQoJ3B1Ymxpc2hlclN0b3BTcGVha2luZycsIFtuZXcgUHVibGlzaGVyU3BlYWtpbmdFdmVudCh0aGlzLnNlc3Npb24sICdwdWJsaXNoZXJTdG9wU3BlYWtpbmcnLCB0aGlzLmNvbm5lY3Rpb24sIHRoaXMuc3RyZWFtSWQpXSk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBlbmFibGVPbmNlU3BlYWtpbmdFdmVudHMoKTogdm9pZCB7XG4gICAgICAgIHRoaXMuc2V0U3BlZWNoRXZlbnRJZk5vdEV4aXN0cygpO1xuICAgICAgICB0aGlzLnNwZWVjaEV2ZW50Lm9uKCdzcGVha2luZycsICgpID0+IHtcbiAgICAgICAgICAgIHRoaXMuc2Vzc2lvbi5lbWl0RXZlbnQoJ3B1Ymxpc2hlclN0YXJ0U3BlYWtpbmcnLCBbbmV3IFB1Ymxpc2hlclNwZWFraW5nRXZlbnQodGhpcy5zZXNzaW9uLCAncHVibGlzaGVyU3RhcnRTcGVha2luZycsIHRoaXMuY29ubmVjdGlvbiwgdGhpcy5zdHJlYW1JZCldKTtcbiAgICAgICAgICAgIHRoaXMuZGlzYWJsZVNwZWFraW5nRXZlbnRzKCk7XG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLnNwZWVjaEV2ZW50Lm9uKCdzdG9wcGVkX3NwZWFraW5nJywgKCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5zZXNzaW9uLmVtaXRFdmVudCgncHVibGlzaGVyU3RvcFNwZWFraW5nJywgW25ldyBQdWJsaXNoZXJTcGVha2luZ0V2ZW50KHRoaXMuc2Vzc2lvbiwgJ3B1Ymxpc2hlclN0b3BTcGVha2luZycsIHRoaXMuY29ubmVjdGlvbiwgdGhpcy5zdHJlYW1JZCldKTtcbiAgICAgICAgICAgIHRoaXMuZGlzYWJsZVNwZWFraW5nRXZlbnRzKCk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBkaXNhYmxlU3BlYWtpbmdFdmVudHMoKTogdm9pZCB7XG4gICAgICAgIHRoaXMuc3BlZWNoRXZlbnQuc3RvcCgpO1xuICAgICAgICB0aGlzLnNwZWVjaEV2ZW50ID0gdW5kZWZpbmVkO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBpc0xvY2FsKCk6IGJvb2xlYW4ge1xuICAgICAgICAvLyBpbmJvdW5kIG9wdGlvbnMgdW5kZWZpbmVkIGFuZCBvdXRib3VuZCBvcHRpb25zIGRlZmluZWRcbiAgICAgICAgcmV0dXJuICghdGhpcy5pbmJvdW5kU3RyZWFtT3B0cyAmJiAhIXRoaXMub3V0Ym91bmRTdHJlYW1PcHRzKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgZ2V0U2VsZWN0ZWRJY2VDYW5kaWRhdGUoKTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIHRoaXMud2ViUnRjU3RhdHMuZ2V0U2VsZWN0ZWRJY2VDYW5kaWRhdGVJbmZvKClcbiAgICAgICAgICAgICAgICAudGhlbihyZXBvcnQgPT4gcmVzb2x2ZShyZXBvcnQpKVxuICAgICAgICAgICAgICAgIC5jYXRjaChlcnJvciA9PiByZWplY3QoZXJyb3IpKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGdldFJlbW90ZUljZUNhbmRpZGF0ZUxpc3QoKTogUlRDSWNlQ2FuZGlkYXRlW10ge1xuICAgICAgICByZXR1cm4gdGhpcy53ZWJSdGNQZWVyLnJlbW90ZUNhbmRpZGF0ZXNRdWV1ZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgZ2V0TG9jYWxJY2VDYW5kaWRhdGVMaXN0KCk6IFJUQ0ljZUNhbmRpZGF0ZVtdIHtcbiAgICAgICAgcmV0dXJuIHRoaXMud2ViUnRjUGVlci5sb2NhbENhbmRpZGF0ZXNRdWV1ZTtcbiAgICB9XG5cbiAgICAvKiBQcml2YXRlIG1ldGhvZHMgKi9cblxuICAgIHByaXZhdGUgaW5pdFdlYlJ0Y1BlZXJTZW5kKCk6IFByb21pc2U8YW55PiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG5cbiAgICAgICAgICAgIGNvbnN0IHVzZXJNZWRpYUNvbnN0cmFpbnRzID0ge1xuICAgICAgICAgICAgICAgIGF1ZGlvOiB0aGlzLmlzU2VuZEF1ZGlvKCksXG4gICAgICAgICAgICAgICAgdmlkZW86IHRoaXMuaXNTZW5kVmlkZW8oKVxuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgY29uc3Qgb3B0aW9ucyA9IHtcbiAgICAgICAgICAgICAgICBtZWRpYVN0cmVhbTogdGhpcy5tZWRpYVN0cmVhbSxcbiAgICAgICAgICAgICAgICBtZWRpYUNvbnN0cmFpbnRzOiB1c2VyTWVkaWFDb25zdHJhaW50cyxcbiAgICAgICAgICAgICAgICBvbmljZWNhbmRpZGF0ZTogdGhpcy5jb25uZWN0aW9uLnNlbmRJY2VDYW5kaWRhdGUuYmluZCh0aGlzLmNvbm5lY3Rpb24pLFxuICAgICAgICAgICAgICAgIGljZVNlcnZlcnM6IHRoaXMuZ2V0SWNlU2VydmVyc0NvbmYoKSxcbiAgICAgICAgICAgICAgICBzaW11bGNhc3Q6IGZhbHNlXG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICBjb25zdCBzdWNjZXNzQ2FsbGJhY2sgPSAoc2RwT2ZmZXJQYXJhbSkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuZGVidWcoJ1NlbmRpbmcgU0RQIG9mZmVyIHRvIHB1Ymxpc2ggYXMgJ1xuICAgICAgICAgICAgICAgICAgICArIHRoaXMuc3RyZWFtSWQsIHNkcE9mZmVyUGFyYW0pO1xuXG4gICAgICAgICAgICAgICAgbGV0IHR5cGVPZlZpZGVvID0gJyc7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuaXNTZW5kVmlkZW8oKSkge1xuICAgICAgICAgICAgICAgICAgICB0eXBlT2ZWaWRlbyA9IHRoaXMub3V0Ym91bmRTdHJlYW1PcHRzLnB1Ymxpc2hlclByb3BlcnRpZXMudmlkZW9Tb3VyY2UgaW5zdGFuY2VvZiBNZWRpYVN0cmVhbVRyYWNrID8gJ0NVU1RPTScgOiAodGhpcy5pc1NlbmRTY3JlZW4oKSA/ICdTQ1JFRU4nIDogJ0NBTUVSQScpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMuc2Vzc2lvbi5vcGVudmlkdS5zZW5kUmVxdWVzdCgncHVibGlzaFZpZGVvJywge1xuICAgICAgICAgICAgICAgICAgICBzZHBPZmZlcjogc2RwT2ZmZXJQYXJhbSxcbiAgICAgICAgICAgICAgICAgICAgZG9Mb29wYmFjazogdGhpcy5kaXNwbGF5TXlSZW1vdGUoKSB8fCBmYWxzZSxcbiAgICAgICAgICAgICAgICAgICAgaGFzQXVkaW86IHRoaXMuaXNTZW5kQXVkaW8oKSxcbiAgICAgICAgICAgICAgICAgICAgaGFzVmlkZW86IHRoaXMuaXNTZW5kVmlkZW8oKSxcbiAgICAgICAgICAgICAgICAgICAgYXVkaW9BY3RpdmU6IHRoaXMuYXVkaW9BY3RpdmUsXG4gICAgICAgICAgICAgICAgICAgIHZpZGVvQWN0aXZlOiB0aGlzLnZpZGVvQWN0aXZlLFxuICAgICAgICAgICAgICAgICAgICB0eXBlT2ZWaWRlbyxcbiAgICAgICAgICAgICAgICAgICAgZnJhbWVSYXRlOiAhIXRoaXMuZnJhbWVSYXRlID8gdGhpcy5mcmFtZVJhdGUgOiAtMSxcbiAgICAgICAgICAgICAgICAgICAgdmlkZW9EaW1lbnNpb25zOiBKU09OLnN0cmluZ2lmeSh0aGlzLnZpZGVvRGltZW5zaW9ucylcbiAgICAgICAgICAgICAgICB9LCAoZXJyb3IsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yLmNvZGUgPT09IDQwMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChuZXcgT3BlblZpZHVFcnJvcihPcGVuVmlkdUVycm9yTmFtZS5PUEVOVklEVV9QRVJNSVNTSU9OX0RFTklFRCwgXCJZb3UgZG9uJ3QgaGF2ZSBwZXJtaXNzaW9ucyB0byBwdWJsaXNoXCIpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KCdFcnJvciBvbiBwdWJsaXNoVmlkZW86ICcgKyBKU09OLnN0cmluZ2lmeShlcnJvcikpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy53ZWJSdGNQZWVyLnByb2Nlc3NBbnN3ZXIocmVzcG9uc2Uuc2RwQW5zd2VyKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdHJlYW1JZCA9IHJlc3BvbnNlLmlkO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmlzTG9jYWxTdHJlYW1QdWJsaXNoZWQgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnB1Ymxpc2hlZE9uY2UgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5kaXNwbGF5TXlSZW1vdGUoKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5yZW1vdGVQZWVyU3VjY2Vzc2Z1bGx5RXN0YWJsaXNoZWQoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnc3RyZWFtLWNyZWF0ZWQtYnktcHVibGlzaGVyJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuaW5pdFdlYlJ0Y1N0YXRzKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oXCInUHVibGlzaGVyJyBzdWNjZXNzZnVsbHkgcHVibGlzaGVkIHRvIHNlc3Npb25cIik7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIGlmICh0aGlzLmRpc3BsYXlNeVJlbW90ZSgpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy53ZWJSdGNQZWVyID0gbmV3IFdlYlJ0Y1BlZXJTZW5kcmVjdihvcHRpb25zKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy53ZWJSdGNQZWVyID0gbmV3IFdlYlJ0Y1BlZXJTZW5kb25seShvcHRpb25zKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMud2ViUnRjUGVlci5nZW5lcmF0ZU9mZmVyKCkudGhlbihvZmZlciA9PiB7XG4gICAgICAgICAgICAgICAgc3VjY2Vzc0NhbGxiYWNrKG9mZmVyKTtcbiAgICAgICAgICAgIH0pLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICAgICAgICByZWplY3QobmV3IEVycm9yKCcocHVibGlzaCkgU0RQIG9mZmVyIGVycm9yOiAnICsgSlNPTi5zdHJpbmdpZnkoZXJyb3IpKSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBpbml0V2ViUnRjUGVlclJlY2VpdmUoKTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcblxuICAgICAgICAgICAgY29uc3Qgb2ZmZXJDb25zdHJhaW50cyA9IHtcbiAgICAgICAgICAgICAgICBhdWRpbzogdGhpcy5pbmJvdW5kU3RyZWFtT3B0cy5oYXNBdWRpbyxcbiAgICAgICAgICAgICAgICB2aWRlbzogdGhpcy5pbmJvdW5kU3RyZWFtT3B0cy5oYXNWaWRlb1xuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGNvbnNvbGUuZGVidWcoXCInU2Vzc2lvbi5zdWJzY3JpYmUoU3RyZWFtKScgY2FsbGVkLiBDb25zdHJhaW50cyBvZiBnZW5lcmF0ZSBTRFAgb2ZmZXJcIixcbiAgICAgICAgICAgICAgICBvZmZlckNvbnN0cmFpbnRzKTtcbiAgICAgICAgICAgIGNvbnN0IG9wdGlvbnMgPSB7XG4gICAgICAgICAgICAgICAgb25pY2VjYW5kaWRhdGU6IHRoaXMuY29ubmVjdGlvbi5zZW5kSWNlQ2FuZGlkYXRlLmJpbmQodGhpcy5jb25uZWN0aW9uKSxcbiAgICAgICAgICAgICAgICBtZWRpYUNvbnN0cmFpbnRzOiBvZmZlckNvbnN0cmFpbnRzLFxuICAgICAgICAgICAgICAgIGljZVNlcnZlcnM6IHRoaXMuZ2V0SWNlU2VydmVyc0NvbmYoKSxcbiAgICAgICAgICAgICAgICBzaW11bGNhc3Q6IGZhbHNlXG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICBjb25zdCBzdWNjZXNzQ2FsbGJhY2sgPSAoc2RwT2ZmZXJQYXJhbSkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuZGVidWcoJ1NlbmRpbmcgU0RQIG9mZmVyIHRvIHN1YnNjcmliZSB0byAnXG4gICAgICAgICAgICAgICAgICAgICsgdGhpcy5zdHJlYW1JZCwgc2RwT2ZmZXJQYXJhbSk7XG4gICAgICAgICAgICAgICAgdGhpcy5zZXNzaW9uLm9wZW52aWR1LnNlbmRSZXF1ZXN0KCdyZWNlaXZlVmlkZW9Gcm9tJywge1xuICAgICAgICAgICAgICAgICAgICBzZW5kZXI6IHRoaXMuc3RyZWFtSWQsXG4gICAgICAgICAgICAgICAgICAgIHNkcE9mZmVyOiBzZHBPZmZlclBhcmFtXG4gICAgICAgICAgICAgICAgfSwgKGVycm9yLCByZXNwb25zZSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBpZiAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChuZXcgRXJyb3IoJ0Vycm9yIG9uIHJlY3ZWaWRlb0Zyb206ICcgKyBKU09OLnN0cmluZ2lmeShlcnJvcikpKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMud2ViUnRjUGVlci5wcm9jZXNzQW5zd2VyKHJlc3BvbnNlLnNkcEFuc3dlcikudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5yZW1vdGVQZWVyU3VjY2Vzc2Z1bGx5RXN0YWJsaXNoZWQoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmluaXRXZWJSdGNTdGF0cygpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIHRoaXMud2ViUnRjUGVlciA9IG5ldyBXZWJSdGNQZWVyUmVjdm9ubHkob3B0aW9ucyk7XG4gICAgICAgICAgICB0aGlzLndlYlJ0Y1BlZXIuZ2VuZXJhdGVPZmZlcigpXG4gICAgICAgICAgICAgICAgLnRoZW4ob2ZmZXIgPT4ge1xuICAgICAgICAgICAgICAgICAgICBzdWNjZXNzQ2FsbGJhY2sob2ZmZXIpO1xuICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICAgICAgICAgICAgcmVqZWN0KG5ldyBFcnJvcignKHN1YnNjcmliZSkgU0RQIG9mZmVyIGVycm9yOiAnICsgSlNPTi5zdHJpbmdpZnkoZXJyb3IpKSk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIHByaXZhdGUgcmVtb3RlUGVlclN1Y2Nlc3NmdWxseUVzdGFibGlzaGVkKCk6IHZvaWQge1xuICAgICAgICB0aGlzLm1lZGlhU3RyZWFtID0gdGhpcy53ZWJSdGNQZWVyLnBjLmdldFJlbW90ZVN0cmVhbXMoKVswXTtcbiAgICAgICAgY29uc29sZS5kZWJ1ZygnUGVlciByZW1vdGUgc3RyZWFtJywgdGhpcy5tZWRpYVN0cmVhbSk7XG5cbiAgICAgICAgaWYgKCEhdGhpcy5tZWRpYVN0cmVhbSkge1xuICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ21lZGlhc3RyZWFtLXVwZGF0ZWQnKTtcbiAgICAgICAgICAgIGlmICghdGhpcy5kaXNwbGF5TXlSZW1vdGUoKSAmJiAhIXRoaXMubWVkaWFTdHJlYW0uZ2V0QXVkaW9UcmFja3MoKVswXSAmJiB0aGlzLnNlc3Npb24uc3BlYWtpbmdFdmVudHNFbmFibGVkKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5lbmFibGVTcGVha2luZ0V2ZW50cygpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBpbml0V2ViUnRjU3RhdHMoKTogdm9pZCB7XG4gICAgICAgIHRoaXMud2ViUnRjU3RhdHMgPSBuZXcgV2ViUnRjU3RhdHModGhpcyk7XG4gICAgICAgIHRoaXMud2ViUnRjU3RhdHMuaW5pdFdlYlJ0Y1N0YXRzKCk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBzdG9wV2ViUnRjU3RhdHMoKTogdm9pZCB7XG4gICAgICAgIGlmICghIXRoaXMud2ViUnRjU3RhdHMgJiYgdGhpcy53ZWJSdGNTdGF0cy5pc0VuYWJsZWQoKSkge1xuICAgICAgICAgICAgdGhpcy53ZWJSdGNTdGF0cy5zdG9wV2ViUnRjU3RhdHMoKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgZ2V0SWNlU2VydmVyc0NvbmYoKTogUlRDSWNlU2VydmVyW10gfCB1bmRlZmluZWQge1xuICAgICAgICBsZXQgcmV0dXJuVmFsdWU7XG4gICAgICAgIGlmICghIXRoaXMuc2Vzc2lvbi5vcGVudmlkdS5hZHZhbmNlZENvbmZpZ3VyYXRpb24uaWNlU2VydmVycykge1xuICAgICAgICAgICAgcmV0dXJuVmFsdWUgPSB0aGlzLnNlc3Npb24ub3BlbnZpZHUuYWR2YW5jZWRDb25maWd1cmF0aW9uLmljZVNlcnZlcnMgPT09ICdmcmVlaWNlJyA/XG4gICAgICAgICAgICAgICAgdW5kZWZpbmVkIDpcbiAgICAgICAgICAgICAgICB0aGlzLnNlc3Npb24ub3BlbnZpZHUuYWR2YW5jZWRDb25maWd1cmF0aW9uLmljZVNlcnZlcnM7XG4gICAgICAgIH0gZWxzZSBpZiAodGhpcy5zZXNzaW9uLm9wZW52aWR1LmljZVNlcnZlcnMpIHtcbiAgICAgICAgICAgIHJldHVyblZhbHVlID0gdGhpcy5zZXNzaW9uLm9wZW52aWR1LmljZVNlcnZlcnM7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm5WYWx1ZSA9IHVuZGVmaW5lZDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcmV0dXJuVmFsdWU7XG4gICAgfVxuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBTdHJlYW0gfSBmcm9tICcuL1N0cmVhbSc7XG5pbXBvcnQgeyBFdmVudERpc3BhdGNoZXIgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHVibGljL0V2ZW50RGlzcGF0Y2hlcic7XG5pbXBvcnQgeyBTdHJlYW1NYW5hZ2VyVmlkZW8gfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHVibGljL1N0cmVhbU1hbmFnZXJWaWRlbyc7XG5pbXBvcnQgeyBFdmVudCB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL0V2ZW50JztcbmltcG9ydCB7IFN0cmVhbU1hbmFnZXJFdmVudCB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1N0cmVhbU1hbmFnZXJFdmVudCc7XG5pbXBvcnQgeyBWaWRlb0VsZW1lbnRFdmVudCB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1ZpZGVvRWxlbWVudEV2ZW50JztcbmltcG9ydCB7IFZpZGVvSW5zZXJ0TW9kZSB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRW51bXMvVmlkZW9JbnNlcnRNb2RlJztcblxuaW1wb3J0IEV2ZW50RW1pdHRlciA9IHJlcXVpcmUoJ3dvbGZ5ODctZXZlbnRlbWl0dGVyJyk7XG5cblxuLyoqXG4gKiBJbnRlcmZhY2UgaW4gY2hhcmdlIG9mIGRpc3BsYXlpbmcgdGhlIG1lZGlhIHN0cmVhbXMgaW4gdGhlIEhUTUwgRE9NLiBUaGlzIHdyYXBzIGFueSBbW1B1Ymxpc2hlcl1dIGFuZCBbW1N1YnNjcmliZXJdXSBvYmplY3QuXG4gKiBZb3UgY2FuIGluc2VydCBhcyBtYW55IHZpZGVvIHBsYXllcnMgZm8gdGhlIHNhbWUgU3RyZWFtIGFzIHlvdSB3YW50IGJ5IGNhbGxpbmcgW1tTdHJlYW1NYW5hZ2VyLmFkZFZpZGVvRWxlbWVudF1dIG9yXG4gKiBbW1N0cmVhbU1hbmFnZXIuY3JlYXRlVmlkZW9FbGVtZW50XV0uXG4gKlxuICogVGhlIHVzZSBvZiBTdHJlYW1NYW5hZ2VyIHdyYXBwZXIgaXMgcGFydGljdWxhcmx5IHVzZWZ1bCB3aGVuIHlvdSBkb24ndCBuZWVkIHRvIGRpZmZlcmVudGlhdGUgYmV0d2VlbiBQdWJsaXNoZXIgb3IgU3Vic2NyaWJlciBzdHJlYW1zIG9yIGp1c3RcbiAqIHdhbnQgdG8gZGlyZWN0bHkgbWFuYWdlIHlvdXIgb3duIHZpZGVvIGVsZW1lbnRzIChldmVuIG1vcmUgdGhhbiBvbmUgdmlkZW8gZWxlbWVudCBwZXIgU3RyZWFtKS4gVGhpcyBzY2VuYXJpbyBpcyBwcmV0dHkgY29tbW9uIGluXG4gKiBkZWNsYXJhdGl2ZSwgTVZDIGZyb250ZW5kIGZyYW1ld29ya3Mgc3VjaCBhcyBBbmd1bGFyLCBSZWFjdCBvciBWdWUuanNcbiAqL1xuZXhwb3J0IGNsYXNzIFN0cmVhbU1hbmFnZXIgaW1wbGVtZW50cyBFdmVudERpc3BhdGNoZXIge1xuXG4gICAgLyoqXG4gICAgICogVGhlIFN0cmVhbSByZXByZXNlbnRlZCBpbiB0aGUgRE9NIGJ5IHRoZSBQdWJsaXNoZXIvU3Vic2NyaWJlclxuICAgICAqL1xuICAgIHN0cmVhbTogU3RyZWFtO1xuXG4gICAgLyoqXG4gICAgICogQWxsIHRoZSB2aWRlb3MgZGlzcGxheWluZyB0aGUgU3RyZWFtIG9mIHRoaXMgUHVibGlzaGVyL1N1YnNjcmliZXJcbiAgICAgKi9cbiAgICB2aWRlb3M6IFN0cmVhbU1hbmFnZXJWaWRlb1tdID0gW107XG5cbiAgICAvKipcbiAgICAgKiBXaGV0aGVyIHRoZSBTdHJlYW0gcmVwcmVzZW50ZWQgaW4gdGhlIERPTSBpcyBsb2NhbCBvciByZW1vdGVcbiAgICAgKiAtIGBmYWxzZWAgZm9yIFtbUHVibGlzaGVyXV1cbiAgICAgKiAtIGB0cnVlYCBmb3IgW1tTdWJzY3JpYmVyXV1cbiAgICAgKi9cbiAgICByZW1vdGU6IGJvb2xlYW47XG5cbiAgICAvKipcbiAgICAgKiBUaGUgRE9NIEhUTUxFbGVtZW50IGFzc2lnbmVkIGFzIHRhcmdldCBlbGVtZW50IHdoZW4gY3JlYXRpbmcgdGhlIHZpZGVvIGZvciB0aGUgUHVibGlzaGVyL1N1YnNjcmliZXIuIFRoaXMgcHJvcGVydHkgaXMgb25seSBkZWZpbmVkIGlmOlxuICAgICAqIC0gW1tQdWJsaXNoZXJdXSBoYXMgYmVlbiBpbml0aWFsaXplZCBieSBjYWxsaW5nIG1ldGhvZCBbW09wZW5WaWR1LmluaXRQdWJsaXNoZXJdXSB3aXRoIGEgdmFsaWQgYHRhcmdldEVsZW1lbnRgIHBhcmFtZXRlclxuICAgICAqIC0gW1tTdWJzY3JpYmVyXV0gaGFzIGJlZW4gaW5pdGlhbGl6ZWQgYnkgY2FsbGluZyBtZXRob2QgW1tTZXNzaW9uLnN1YnNjcmliZV1dIHdpdGggYSB2YWxpZCBgdGFyZ2V0RWxlbWVudGAgcGFyYW1ldGVyXG4gICAgICovXG4gICAgdGFyZ2V0RWxlbWVudDogSFRNTEVsZW1lbnQ7XG5cbiAgICAvKipcbiAgICAgKiBgaWRgIGF0dHJpYnV0ZSBvZiB0aGUgRE9NIHZpZGVvIGVsZW1lbnQgZGlzcGxheWluZyB0aGUgUHVibGlzaGVyL1N1YnNjcmliZXIncyBzdHJlYW0uIFRoaXMgcHJvcGVydHkgaXMgb25seSBkZWZpbmVkIGlmOlxuICAgICAqIC0gW1tQdWJsaXNoZXJdXSBoYXMgYmVlbiBpbml0aWFsaXplZCBieSBjYWxsaW5nIG1ldGhvZCBbW09wZW5WaWR1LmluaXRQdWJsaXNoZXJdXSB3aXRoIGEgdmFsaWQgYHRhcmdldEVsZW1lbnRgIHBhcmFtZXRlclxuICAgICAqIC0gW1tTdWJzY3JpYmVyXV0gaGFzIGJlZW4gaW5pdGlhbGl6ZWQgYnkgY2FsbGluZyBtZXRob2QgW1tTZXNzaW9uLnN1YnNjcmliZV1dIHdpdGggYSB2YWxpZCBgdGFyZ2V0RWxlbWVudGAgcGFyYW1ldGVyXG4gICAgICovXG4gICAgaWQ6IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBmaXJzdFZpZGVvRWxlbWVudDogU3RyZWFtTWFuYWdlclZpZGVvO1xuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBsYXp5TGF1bmNoVmlkZW9FbGVtZW50Q3JlYXRlZEV2ZW50ID0gZmFsc2U7XG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGVsZW1lbnQ6IEhUTUxFbGVtZW50O1xuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgZWUgPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHByb3RlY3RlZCBjYW5QbGF5TGlzdGVuZXI6IEV2ZW50TGlzdGVuZXJPckV2ZW50TGlzdGVuZXJPYmplY3Q7XG5cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3RvcihzdHJlYW06IFN0cmVhbSwgdGFyZ2V0RWxlbWVudD86IEhUTUxFbGVtZW50IHwgc3RyaW5nKSB7XG4gICAgICAgIHRoaXMuc3RyZWFtID0gc3RyZWFtO1xuICAgICAgICB0aGlzLnN0cmVhbS5zdHJlYW1NYW5hZ2VyID0gdGhpcztcbiAgICAgICAgdGhpcy5yZW1vdGUgPSAhdGhpcy5zdHJlYW0uaXNMb2NhbCgpO1xuXG4gICAgICAgIGlmICghIXRhcmdldEVsZW1lbnQpIHtcbiAgICAgICAgICAgIGxldCB0YXJnRWw7XG4gICAgICAgICAgICBpZiAodHlwZW9mIHRhcmdldEVsZW1lbnQgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAgICAgdGFyZ0VsID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQodGFyZ2V0RWxlbWVudCk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHRhcmdldEVsZW1lbnQgaW5zdGFuY2VvZiBIVE1MRWxlbWVudCkge1xuICAgICAgICAgICAgICAgIHRhcmdFbCA9IHRhcmdldEVsZW1lbnQ7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICghIXRhcmdFbCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZmlyc3RWaWRlb0VsZW1lbnQgPSB7XG4gICAgICAgICAgICAgICAgICAgIHRhcmdldEVsZW1lbnQ6IHRhcmdFbCxcbiAgICAgICAgICAgICAgICAgICAgdmlkZW86IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3ZpZGVvJyksXG4gICAgICAgICAgICAgICAgICAgIGlkOiAnJ1xuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgdGhpcy50YXJnZXRFbGVtZW50ID0gdGFyZ0VsO1xuICAgICAgICAgICAgICAgIHRoaXMuZWxlbWVudCA9IHRhcmdFbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICB0aGlzLmNhblBsYXlMaXN0ZW5lciA9ICgpID0+IHtcbiAgICAgICAgICAgIGlmICh0aGlzLnN0cmVhbS5pc0xvY2FsKCkpIHtcbiAgICAgICAgICAgICAgICBpZiAoIXRoaXMuc3RyZWFtLmRpc3BsYXlNeVJlbW90ZSgpKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbyhcIllvdXIgbG9jYWwgJ1N0cmVhbScgd2l0aCBpZCBbXCIgKyB0aGlzLnN0cmVhbS5zdHJlYW1JZCArICddIHZpZGVvIGlzIG5vdyBwbGF5aW5nJyk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCd2aWRlb1BsYXlpbmcnLCBbbmV3IFZpZGVvRWxlbWVudEV2ZW50KHRoaXMudmlkZW9zWzBdLnZpZGVvLCB0aGlzLCAndmlkZW9QbGF5aW5nJyldKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oXCJZb3VyIG93biByZW1vdGUgJ1N0cmVhbScgd2l0aCBpZCBbXCIgKyB0aGlzLnN0cmVhbS5zdHJlYW1JZCArICddIHZpZGVvIGlzIG5vdyBwbGF5aW5nJyk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdyZW1vdGVWaWRlb1BsYXlpbmcnLCBbbmV3IFZpZGVvRWxlbWVudEV2ZW50KHRoaXMudmlkZW9zWzBdLnZpZGVvLCB0aGlzLCAncmVtb3RlVmlkZW9QbGF5aW5nJyldKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbyhcIlJlbW90ZSAnU3RyZWFtJyB3aXRoIGlkIFtcIiArIHRoaXMuc3RyZWFtLnN0cmVhbUlkICsgJ10gdmlkZW8gaXMgbm93IHBsYXlpbmcnKTtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgndmlkZW9QbGF5aW5nJywgW25ldyBWaWRlb0VsZW1lbnRFdmVudCh0aGlzLnZpZGVvc1swXS52aWRlbywgdGhpcywgJ3ZpZGVvUGxheWluZycpXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnc3RyZWFtUGxheWluZycsIFtuZXcgU3RyZWFtTWFuYWdlckV2ZW50KHRoaXMpXSk7XG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2VlIFtbRXZlbnREaXNwYXRjaGVyLm9uXV1cbiAgICAgKi9cbiAgICBvbih0eXBlOiBzdHJpbmcsIGhhbmRsZXI6IChldmVudDogRXZlbnQpID0+IHZvaWQpOiBFdmVudERpc3BhdGNoZXIge1xuICAgICAgICB0aGlzLmVlLm9uKHR5cGUsIGV2ZW50ID0+IHtcbiAgICAgICAgICAgIGlmIChldmVudCkge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbyhcIkV2ZW50ICdcIiArIHR5cGUgKyBcIicgdHJpZ2dlcmVkIGJ5ICdcIiArICh0aGlzLnJlbW90ZSA/ICdTdWJzY3JpYmVyJyA6ICdQdWJsaXNoZXInKSArIFwiJ1wiLCBldmVudCk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbyhcIkV2ZW50ICdcIiArIHR5cGUgKyBcIicgdHJpZ2dlcmVkIGJ5ICdcIiArICh0aGlzLnJlbW90ZSA/ICdTdWJzY3JpYmVyJyA6ICdQdWJsaXNoZXInKSArIFwiJ1wiKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGhhbmRsZXIoZXZlbnQpO1xuICAgICAgICB9KTtcbiAgICAgICAgaWYgKHR5cGUgPT09ICd2aWRlb0VsZW1lbnRDcmVhdGVkJykge1xuICAgICAgICAgICAgaWYgKCEhdGhpcy5zdHJlYW0gJiYgdGhpcy5sYXp5TGF1bmNoVmlkZW9FbGVtZW50Q3JlYXRlZEV2ZW50KSB7XG4gICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3ZpZGVvRWxlbWVudENyZWF0ZWQnLCBbbmV3IFZpZGVvRWxlbWVudEV2ZW50KHRoaXMudmlkZW9zWzBdLnZpZGVvLCB0aGlzLCAndmlkZW9FbGVtZW50Q3JlYXRlZCcpXSk7XG4gICAgICAgICAgICAgICAgdGhpcy5sYXp5TGF1bmNoVmlkZW9FbGVtZW50Q3JlYXRlZEV2ZW50ID0gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHR5cGUgPT09ICdzdHJlYW1QbGF5aW5nJyB8fCB0eXBlID09PSAndmlkZW9QbGF5aW5nJykge1xuICAgICAgICAgICAgaWYgKHRoaXMudmlkZW9zWzBdICYmIHRoaXMudmlkZW9zWzBdLnZpZGVvICYmXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8uY3VycmVudFRpbWUgPiAwICYmXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8ucGF1c2VkID09PSBmYWxzZSAmJlxuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9zWzBdLnZpZGVvLmVuZGVkID09PSBmYWxzZSAmJlxuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9zWzBdLnZpZGVvLnJlYWR5U3RhdGUgPT09IDQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnc3RyZWFtUGxheWluZycsIFtuZXcgU3RyZWFtTWFuYWdlckV2ZW50KHRoaXMpXSk7XG4gICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3ZpZGVvUGxheWluZycsIFtuZXcgVmlkZW9FbGVtZW50RXZlbnQodGhpcy52aWRlb3NbMF0udmlkZW8sIHRoaXMsICd2aWRlb1BsYXlpbmcnKV0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNlZSBbW0V2ZW50RGlzcGF0Y2hlci5vbmNlXV1cbiAgICAgKi9cbiAgICBvbmNlKHR5cGU6IHN0cmluZywgaGFuZGxlcjogKGV2ZW50OiBFdmVudCkgPT4gdm9pZCk6IFN0cmVhbU1hbmFnZXIge1xuICAgICAgICB0aGlzLmVlLm9uY2UodHlwZSwgZXZlbnQgPT4ge1xuICAgICAgICAgICAgaWYgKGV2ZW50KSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5pbmZvKFwiRXZlbnQgJ1wiICsgdHlwZSArIFwiJyB0cmlnZ2VyZWQgb25jZVwiLCBldmVudCk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbyhcIkV2ZW50ICdcIiArIHR5cGUgKyBcIicgdHJpZ2dlcmVkIG9uY2VcIik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBoYW5kbGVyKGV2ZW50KTtcbiAgICAgICAgfSk7XG4gICAgICAgIGlmICh0eXBlID09PSAndmlkZW9FbGVtZW50Q3JlYXRlZCcpIHtcbiAgICAgICAgICAgIGlmICghIXRoaXMuc3RyZWFtICYmIHRoaXMubGF6eUxhdW5jaFZpZGVvRWxlbWVudENyZWF0ZWRFdmVudCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCd2aWRlb0VsZW1lbnRDcmVhdGVkJywgW25ldyBWaWRlb0VsZW1lbnRFdmVudCh0aGlzLnZpZGVvc1swXS52aWRlbywgdGhpcywgJ3ZpZGVvRWxlbWVudENyZWF0ZWQnKV0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmICh0eXBlID09PSAnc3RyZWFtUGxheWluZycgfHwgdHlwZSA9PT0gJ3ZpZGVvUGxheWluZycpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLnZpZGVvc1swXSAmJiB0aGlzLnZpZGVvc1swXS52aWRlbyAmJlxuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9zWzBdLnZpZGVvLmN1cnJlbnRUaW1lID4gMCAmJlxuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9zWzBdLnZpZGVvLnBhdXNlZCA9PT0gZmFsc2UgJiZcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvc1swXS52aWRlby5lbmRlZCA9PT0gZmFsc2UgJiZcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvc1swXS52aWRlby5yZWFkeVN0YXRlID09PSA0KSB7XG4gICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3N0cmVhbVBsYXlpbmcnLCBbbmV3IFN0cmVhbU1hbmFnZXJFdmVudCh0aGlzKV0pO1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCd2aWRlb1BsYXlpbmcnLCBbbmV3IFZpZGVvRWxlbWVudEV2ZW50KHRoaXMudmlkZW9zWzBdLnZpZGVvLCB0aGlzLCAndmlkZW9QbGF5aW5nJyldKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZWUgW1tFdmVudERpc3BhdGNoZXIub2ZmXV1cbiAgICAgKi9cbiAgICBvZmYodHlwZTogc3RyaW5nLCBoYW5kbGVyPzogKGV2ZW50OiBFdmVudCkgPT4gdm9pZCk6IFN0cmVhbU1hbmFnZXIge1xuICAgICAgICBpZiAoIWhhbmRsZXIpIHtcbiAgICAgICAgICAgIHRoaXMuZWUucmVtb3ZlQWxsTGlzdGVuZXJzKHR5cGUpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5lZS5vZmYodHlwZSwgaGFuZGxlcik7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogTWFrZXMgYHZpZGVvYCBlbGVtZW50IHBhcmFtZXRlciBkaXNwbGF5IHRoaXMgW1tzdHJlYW1dXS4gVGhpcyBpcyB1c2VmdWwgd2hlbiB5b3UgYXJlXG4gICAgICogW21hbmFnaW5nIHRoZSB2aWRlbyBlbGVtZW50cyBvbiB5b3VyIG93bl0oL2RvY3MvaG93LWRvLWkvbWFuYWdlLXZpZGVvcy8jeW91LXRha2UtY2FyZS1vZi10aGUtdmlkZW8tcGxheWVycylcbiAgICAgKlxuICAgICAqIENhbGxpbmcgdGhpcyBtZXRob2Qgd2l0aCBhIHZpZGVvIGFscmVhZHkgYWRkZWQgdG8gb3RoZXIgUHVibGlzaGVyL1N1YnNjcmliZXIgd2lsbCBjYXVzZSB0aGUgdmlkZW8gZWxlbWVudCB0byBiZVxuICAgICAqIGRpc2Fzc29jaWF0ZWQgZnJvbSB0aGF0IHByZXZpb3VzIFB1Ymxpc2hlci9TdWJzY3JpYmVyIGFuZCB0byBiZSBhc3NvY2lhdGVkIHRvIHRoaXMgb25lLlxuICAgICAqXG4gICAgICogQHJldHVybnMgMSBpZiB0aGUgdmlkZW8gd2Fzbid0IGFzc29jaWF0ZWQgdG8gYW55IG90aGVyIFB1Ymxpc2hlci9TdWJzY3JpYmVyIGFuZCBoYXMgYmVlbiBzdWNjZXNzZnVsbHkgYWRkZWQgdG8gdGhpcyBvbmUuXG4gICAgICogMCBpZiB0aGUgdmlkZW8gd2FzIGFscmVhZHkgYWRkZWQgdG8gdGhpcyBQdWJsaXNoZXIvU3Vic2NyaWJlci4gLTEgaWYgdGhlIHZpZGVvIHdhcyBwcmV2aW91c2x5IGFzc29jaWF0ZWQgdG8gYW55IG90aGVyXG4gICAgICogUHVibGlzaGVyL1N1YnNjcmliZXIgYW5kIGhhcyBiZWVuIHN1Y2Nlc3NmdWxseSBkaXNhc3NvY2lhdGVkIGZyb20gdGhhdCBvbmUgYW5kIHByb3Blcmx5IGFkZGVkIHRvIHRoaXMgb25lLlxuICAgICAqL1xuICAgIGFkZFZpZGVvRWxlbWVudCh2aWRlbzogSFRNTFZpZGVvRWxlbWVudCk6IG51bWJlciB7XG5cbiAgICAgICAgdGhpcy5pbml0aWFsaXplVmlkZW9Qcm9wZXJ0aWVzKHZpZGVvKTtcblxuICAgICAgICAvLyBJZiB0aGUgdmlkZW8gZWxlbWVudCBpcyBhbHJlYWR5IHBhcnQgb2YgdGhpcyBTdHJlYW1NYW5hZ2VyIGRvIG5vdGhpbmdcbiAgICAgICAgZm9yIChjb25zdCB2IG9mIHRoaXMudmlkZW9zKSB7XG4gICAgICAgICAgICBpZiAodi52aWRlbyA9PT0gdmlkZW8pIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gMDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGxldCByZXR1cm5OdW1iZXIgPSAxO1xuXG4gICAgICAgIGZvciAoY29uc3Qgc3RyZWFtTWFuYWdlciBvZiB0aGlzLnN0cmVhbS5zZXNzaW9uLnN0cmVhbU1hbmFnZXJzKSB7XG4gICAgICAgICAgICBpZiAoc3RyZWFtTWFuYWdlci5kaXNhc3NvY2lhdGVWaWRlbyh2aWRlbykpIHtcbiAgICAgICAgICAgICAgICByZXR1cm5OdW1iZXIgPSAtMTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuc3RyZWFtLnNlc3Npb24uc3RyZWFtTWFuYWdlcnMuZm9yRWFjaChzdHJlYW1NYW5hZ2VyID0+IHtcbiAgICAgICAgICAgIHN0cmVhbU1hbmFnZXIuZGlzYXNzb2NpYXRlVmlkZW8odmlkZW8pO1xuICAgICAgICB9KTtcblxuICAgICAgICB0aGlzLnB1c2hOZXdTdHJlYW1NYW5hZ2VyVmlkZW8oe1xuICAgICAgICAgICAgdmlkZW8sXG4gICAgICAgICAgICBpZDogdmlkZW8uaWRcbiAgICAgICAgfSk7XG5cbiAgICAgICAgY29uc29sZS5pbmZvKCdOZXcgdmlkZW8gZWxlbWVudCBhc3NvY2lhdGVkIHRvICcsIHRoaXMpO1xuXG4gICAgICAgIHJldHVybiByZXR1cm5OdW1iZXI7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIG5ldyB2aWRlbyBlbGVtZW50IGRpc3BsYXlpbmcgdGhpcyBbW3N0cmVhbV1dLiBUaGlzIGFsbG93cyB5b3UgdG8gaGF2ZSBtdWx0aXBsZSB2aWRlbyBlbGVtZW50cyBkaXNwbGF5aW5nIHRoZSBzYW1lIG1lZGlhIHN0cmVhbS5cbiAgICAgKlxuICAgICAqICMjIyMgRXZlbnRzIGRpc3BhdGNoZWRcbiAgICAgKlxuICAgICAqIFRoZSBQdWJsaXNoZXIvU3Vic2NyaWJlciBvYmplY3Qgd2lsbCBkaXNwYXRjaCBhIGB2aWRlb0VsZW1lbnRDcmVhdGVkYCBldmVudCBvbmNlIHRoZSBIVE1MIHZpZGVvIGVsZW1lbnQgaGFzIGJlZW4gYWRkZWQgdG8gRE9NLiBTZWUgW1tWaWRlb0VsZW1lbnRFdmVudF1dXG4gICAgICpcbiAgICAgKiBAcGFyYW0gdGFyZ2V0RWxlbWVudCBIVE1MIERPTSBlbGVtZW50IChvciBpdHMgYGlkYCBhdHRyaWJ1dGUpIGluIHdoaWNoIHRoZSB2aWRlbyBlbGVtZW50IG9mIHRoZSBQdWJsaXNoZXIvU3Vic2NyaWJlciB3aWxsIGJlIGluc2VydGVkXG4gICAgICogQHBhcmFtIGluc2VydE1vZGUgSG93IHRoZSB2aWRlbyBlbGVtZW50IHdpbGwgYmUgaW5zZXJ0ZWQgYWNjb3JkaW5nbHkgdG8gYHRhcmdldEVsZW1ldGBcbiAgICAgKi9cbiAgICBjcmVhdGVWaWRlb0VsZW1lbnQodGFyZ2V0RWxlbWVudD86IHN0cmluZyB8IEhUTUxFbGVtZW50LCBpbnNlcnRNb2RlPzogVmlkZW9JbnNlcnRNb2RlKTogSFRNTFZpZGVvRWxlbWVudCB7XG4gICAgICAgIGxldCB0YXJnRWw7XG4gICAgICAgIGlmICh0eXBlb2YgdGFyZ2V0RWxlbWVudCA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgIHRhcmdFbCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKHRhcmdFbCk7XG4gICAgICAgICAgICBpZiAoIXRhcmdFbCkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIlRoZSBwcm92aWRlZCAndGFyZ2V0RWxlbWVudCcgY291bGRuJ3QgYmUgcmVzb2x2ZWQgdG8gYW55IEhUTUwgZWxlbWVudDogXCIgKyB0YXJnZXRFbGVtZW50KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIGlmICh0YXJnZXRFbGVtZW50IGluc3RhbmNlb2YgSFRNTEVsZW1lbnQpIHtcbiAgICAgICAgICAgIHRhcmdFbCA9IHRhcmdldEVsZW1lbnQ7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJUaGUgcHJvdmlkZWQgJ3RhcmdldEVsZW1lbnQnIGNvdWxkbid0IGJlIHJlc29sdmVkIHRvIGFueSBIVE1MIGVsZW1lbnQ6IFwiICsgdGFyZ2V0RWxlbWVudCk7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCB2aWRlbyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3ZpZGVvJyk7XG4gICAgICAgIHRoaXMuaW5pdGlhbGl6ZVZpZGVvUHJvcGVydGllcyh2aWRlbyk7XG5cbiAgICAgICAgbGV0IGluc01vZGUgPSAhIWluc2VydE1vZGUgPyBpbnNlcnRNb2RlIDogVmlkZW9JbnNlcnRNb2RlLkFQUEVORDtcbiAgICAgICAgc3dpdGNoIChpbnNNb2RlKSB7XG4gICAgICAgICAgICBjYXNlIFZpZGVvSW5zZXJ0TW9kZS5BRlRFUjpcbiAgICAgICAgICAgICAgICB0YXJnRWwucGFyZW50Tm9kZSEhLmluc2VydEJlZm9yZSh2aWRlbywgdGFyZ0VsLm5leHRTaWJsaW5nKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgVmlkZW9JbnNlcnRNb2RlLkFQUEVORDpcbiAgICAgICAgICAgICAgICB0YXJnRWwuYXBwZW5kQ2hpbGQodmlkZW8pO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBWaWRlb0luc2VydE1vZGUuQkVGT1JFOlxuICAgICAgICAgICAgICAgIHRhcmdFbC5wYXJlbnROb2RlISEuaW5zZXJ0QmVmb3JlKHZpZGVvLCB0YXJnRWwpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBWaWRlb0luc2VydE1vZGUuUFJFUEVORDpcbiAgICAgICAgICAgICAgICB0YXJnRWwuaW5zZXJ0QmVmb3JlKHZpZGVvLCB0YXJnRWwuY2hpbGROb2Rlc1swXSk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIFZpZGVvSW5zZXJ0TW9kZS5SRVBMQUNFOlxuICAgICAgICAgICAgICAgIHRhcmdFbC5wYXJlbnROb2RlISEucmVwbGFjZUNoaWxkKHZpZGVvLCB0YXJnRWwpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICBpbnNNb2RlID0gVmlkZW9JbnNlcnRNb2RlLkFQUEVORDtcbiAgICAgICAgICAgICAgICB0YXJnRWwuYXBwZW5kQ2hpbGQodmlkZW8pO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgdjogU3RyZWFtTWFuYWdlclZpZGVvID0ge1xuICAgICAgICAgICAgdGFyZ2V0RWxlbWVudDogdGFyZ0VsLFxuICAgICAgICAgICAgdmlkZW8sXG4gICAgICAgICAgICBpbnNlcnRNb2RlOiBpbnNNb2RlLFxuICAgICAgICAgICAgaWQ6IHZpZGVvLmlkXG4gICAgICAgIH07XG4gICAgICAgIHRoaXMucHVzaE5ld1N0cmVhbU1hbmFnZXJWaWRlbyh2KTtcblxuICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgndmlkZW9FbGVtZW50Q3JlYXRlZCcsIFtuZXcgVmlkZW9FbGVtZW50RXZlbnQodi52aWRlbywgdGhpcywgJ3ZpZGVvRWxlbWVudENyZWF0ZWQnKV0pO1xuXG4gICAgICAgIHRoaXMubGF6eUxhdW5jaFZpZGVvRWxlbWVudENyZWF0ZWRFdmVudCA9ICEhdGhpcy5maXJzdFZpZGVvRWxlbWVudDtcblxuICAgICAgICByZXR1cm4gdmlkZW87XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGluaXRpYWxpemVWaWRlb1Byb3BlcnRpZXModmlkZW86IEhUTUxWaWRlb0VsZW1lbnQpOiB2b2lkIHtcbiAgICAgICAgaWYgKCEodGhpcy5zdHJlYW0uaXNMb2NhbCgpICYmIHRoaXMuc3RyZWFtLmRpc3BsYXlNeVJlbW90ZSgpKSkge1xuICAgICAgICAgICAgLy8gQXZvaWQgc2V0dGluZyB0aGUgTWVkaWFTdHJlYW0gaW50byB0aGUgc3JjT2JqZWN0IGlmIHJlbW90ZSBzdWJzY3JpcHRpb24gYmVmb3JlIHB1Ymxpc2hpbmdcbiAgICAgICAgICAgIHZpZGVvLnNyY09iamVjdCA9IHRoaXMuc3RyZWFtLmdldE1lZGlhU3RyZWFtKCk7XG4gICAgICAgIH1cbiAgICAgICAgdmlkZW8uYXV0b3BsYXkgPSB0cnVlO1xuICAgICAgICB2aWRlby5jb250cm9scyA9IGZhbHNlO1xuICAgICAgICBpZiAoIXZpZGVvLmlkKSB7XG4gICAgICAgICAgICB2aWRlby5pZCA9ICh0aGlzLnJlbW90ZSA/ICdyZW1vdGUtJyA6ICdsb2NhbC0nKSArICd2aWRlby0nICsgdGhpcy5zdHJlYW0uc3RyZWFtSWQ7XG4gICAgICAgICAgICAvLyBERVBSRUNBVEVEIHByb3BlcnR5OiBhc3NpZ24gb25jZSB0aGUgcHJvcGVydHkgaWQgaWYgdGhlIHVzZXIgcHJvdmlkZWQgYSB2YWxpZCB0YXJnZXRFbGVtZW50XG4gICAgICAgICAgICBpZiAoIXRoaXMuaWQgJiYgISF0aGlzLnRhcmdldEVsZW1lbnQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmlkID0gdmlkZW8uaWQ7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCF0aGlzLnJlbW90ZSAmJiAhdGhpcy5zdHJlYW0uZGlzcGxheU15UmVtb3RlKCkpIHtcbiAgICAgICAgICAgIHZpZGVvLm11dGVkID0gdHJ1ZTtcbiAgICAgICAgICAgIGlmICh0aGlzLnN0cmVhbS5vdXRib3VuZFN0cmVhbU9wdHMucHVibGlzaGVyUHJvcGVydGllcy5taXJyb3IpIHtcbiAgICAgICAgICAgICAgICB0aGlzLm1pcnJvclZpZGVvKHZpZGVvKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICByZW1vdmVBbGxWaWRlb3MoKTogdm9pZCB7XG4gICAgICAgIGZvciAobGV0IGkgPSB0aGlzLnN0cmVhbS5zZXNzaW9uLnN0cmVhbU1hbmFnZXJzLmxlbmd0aCAtIDE7IGkgPj0gMDsgLS1pKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5zdHJlYW0uc2Vzc2lvbi5zdHJlYW1NYW5hZ2Vyc1tpXSA9PT0gdGhpcykge1xuICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtLnNlc3Npb24uc3RyZWFtTWFuYWdlcnMuc3BsaWNlKGksIDEpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy52aWRlb3MuZm9yRWFjaChzdHJlYW1NYW5hZ2VyVmlkZW8gPT4ge1xuICAgICAgICAgICAgLy8gUmVtb3ZlIG9uY2FucGxheSBldmVudCBsaXN0ZW5lciAob25seSBPcGVuVmlkdSBicm93c2VyIG9uZSwgbm90IHRoZSB1c2VyIG9uZXMpXG4gICAgICAgICAgICBzdHJlYW1NYW5hZ2VyVmlkZW8udmlkZW8ucmVtb3ZlRXZlbnRMaXN0ZW5lcignY2FucGxheScsIHRoaXMuY2FuUGxheUxpc3RlbmVyKTtcbiAgICAgICAgICAgIGlmICghIXN0cmVhbU1hbmFnZXJWaWRlby50YXJnZXRFbGVtZW50KSB7XG4gICAgICAgICAgICAgICAgLy8gT25seSByZW1vdmUgZnJvbSBET00gdmlkZW9zIGNyZWF0ZWQgYnkgT3BlblZpZHUgQnJvd3NlciAodGhvc2UgZ2VuZXJhdGVkIGJ5IHBhc3NpbmcgYSB2YWxpZCB0YXJnZXRFbGVtZW50IGluIE9wZW5WaWR1LmluaXRQdWJsaXNoZXJcbiAgICAgICAgICAgICAgICAvLyBhbmQgU2Vzc2lvbi5zdWJzY3JpYmUgb3IgdGhvc2UgY3JlYXRlZCBieSBTdHJlYW1NYW5hZ2VyLmNyZWF0ZVZpZGVvRWxlbWVudCkuIEFsbCB0aGlzIHZpZGVvcyB0cmlnZ2VyZWQgYSB2aWRlb0VsZW1lbnRDcmVhdGVkIGV2ZW50XG4gICAgICAgICAgICAgICAgc3RyZWFtTWFuYWdlclZpZGVvLnZpZGVvLnBhcmVudE5vZGUhLnJlbW92ZUNoaWxkKHN0cmVhbU1hbmFnZXJWaWRlby52aWRlbyk7XG4gICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3ZpZGVvRWxlbWVudERlc3Ryb3llZCcsIFtuZXcgVmlkZW9FbGVtZW50RXZlbnQoc3RyZWFtTWFuYWdlclZpZGVvLnZpZGVvLCB0aGlzLCAndmlkZW9FbGVtZW50RGVzdHJveWVkJyldKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIFJlbW92ZSBzcmNPYmplY3QgZnJvbSB0aGUgdmlkZW9cbiAgICAgICAgICAgIHN0cmVhbU1hbmFnZXJWaWRlby52aWRlby5zcmNPYmplY3QgPSBudWxsO1xuICAgICAgICAgICAgLy8gUmVtb3ZlIGZyb20gY29sbGVjdGlvbiBvZiB2aWRlb3MgZXZlcnkgdmlkZW8gbWFuYWdlZCBieSBPcGVuVmlkdSBCcm93c2VyXG4gICAgICAgICAgICB0aGlzLnZpZGVvcy5maWx0ZXIodiA9PiAhdi50YXJnZXRFbGVtZW50KTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGRpc2Fzc29jaWF0ZVZpZGVvKHZpZGVvOiBIVE1MVmlkZW9FbGVtZW50KTogYm9vbGVhbiB7XG4gICAgICAgIGxldCBkaXNhc3NvY2lhdGVkID0gZmFsc2U7XG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy52aWRlb3MubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGlmICh0aGlzLnZpZGVvc1tpXS52aWRlbyA9PT0gdmlkZW8pIHtcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvcy5zcGxpY2UoaSwgMSk7XG4gICAgICAgICAgICAgICAgZGlzYXNzb2NpYXRlZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgY29uc29sZS5pbmZvKCdWaWRlbyBlbGVtZW50IGRpc2Fzc29jaWF0ZWQgZnJvbSAnLCB0aGlzKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZGlzYXNzb2NpYXRlZDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgYWRkUGxheUV2ZW50VG9GaXJzdFZpZGVvKCkge1xuICAgICAgICBpZiAoKCEhdGhpcy52aWRlb3NbMF0pICYmICghIXRoaXMudmlkZW9zWzBdLnZpZGVvKSAmJiAodGhpcy52aWRlb3NbMF0udmlkZW8ub25jYW5wbGF5ID09PSBudWxsKSkge1xuICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8uYWRkRXZlbnRMaXN0ZW5lcignY2FucGxheScsIHRoaXMuY2FuUGxheUxpc3RlbmVyKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICB1cGRhdGVNZWRpYVN0cmVhbShtZWRpYVN0cmVhbTogTWVkaWFTdHJlYW0pIHtcbiAgICAgICAgdGhpcy52aWRlb3MuZm9yRWFjaChzdHJlYW1NYW5hZ2VyVmlkZW8gPT4ge1xuICAgICAgICAgICAgc3RyZWFtTWFuYWdlclZpZGVvLnZpZGVvLnNyY09iamVjdCA9IG1lZGlhU3RyZWFtO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgZW1pdEV2ZW50KHR5cGU6IHN0cmluZywgZXZlbnRBcnJheTogYW55W10pOiB2b2lkIHtcbiAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQodHlwZSwgZXZlbnRBcnJheSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBwdXNoTmV3U3RyZWFtTWFuYWdlclZpZGVvKHN0cmVhbU1hbmFnZXJWaWRlbzogU3RyZWFtTWFuYWdlclZpZGVvKSB7XG4gICAgICAgIHRoaXMudmlkZW9zLnB1c2goc3RyZWFtTWFuYWdlclZpZGVvKTtcbiAgICAgICAgdGhpcy5hZGRQbGF5RXZlbnRUb0ZpcnN0VmlkZW8oKTtcbiAgICAgICAgaWYgKHRoaXMuc3RyZWFtLnNlc3Npb24uc3RyZWFtTWFuYWdlcnMuaW5kZXhPZih0aGlzKSA9PT0gLTEpIHtcbiAgICAgICAgICAgIHRoaXMuc3RyZWFtLnNlc3Npb24uc3RyZWFtTWFuYWdlcnMucHVzaCh0aGlzKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgbWlycm9yVmlkZW8odmlkZW8pOiB2b2lkIHtcbiAgICAgICAgdmlkZW8uc3R5bGUudHJhbnNmb3JtID0gJ3JvdGF0ZVkoMTgwZGVnKSc7XG4gICAgICAgIHZpZGVvLnN0eWxlLndlYmtpdFRyYW5zZm9ybSA9ICdyb3RhdGVZKDE4MGRlZyknO1xuICAgIH1cblxufSIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTctMjAxOCBPcGVuVmlkdSAoaHR0cHM6Ly9vcGVudmlkdS5pby8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuaW1wb3J0IHsgU3RyZWFtIH0gZnJvbSAnLi9TdHJlYW0nO1xuaW1wb3J0IHsgU3RyZWFtTWFuYWdlciB9IGZyb20gJy4vU3RyZWFtTWFuYWdlcic7XG5pbXBvcnQgeyBTdWJzY3JpYmVyUHJvcGVydGllcyB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvSW50ZXJmYWNlcy9QdWJsaWMvU3Vic2NyaWJlclByb3BlcnRpZXMnO1xuXG5cbi8qKlxuICogUGFja3MgcmVtb3RlIG1lZGlhIHN0cmVhbXMuIFBhcnRpY2lwYW50cyBhdXRvbWF0aWNhbGx5IHJlY2VpdmUgdGhlbSB3aGVuIG90aGVycyBwdWJsaXNoIHRoZWlyIHN0cmVhbXMuIEluaXRpYWxpemVkIHdpdGggW1tTZXNzaW9uLnN1YnNjcmliZV1dIG1ldGhvZFxuICovXG5leHBvcnQgY2xhc3MgU3Vic2NyaWJlciBleHRlbmRzIFN0cmVhbU1hbmFnZXIge1xuXG4gICAgcHJpdmF0ZSBwcm9wZXJ0aWVzOiBTdWJzY3JpYmVyUHJvcGVydGllcztcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3RvcihzdHJlYW06IFN0cmVhbSwgdGFyZ0VsOiBzdHJpbmcgfCBIVE1MRWxlbWVudCwgcHJvcGVydGllczogU3Vic2NyaWJlclByb3BlcnRpZXMpIHtcbiAgICAgICAgc3VwZXIoc3RyZWFtLCB0YXJnRWwpO1xuICAgICAgICB0aGlzLmVsZW1lbnQgPSB0aGlzLnRhcmdldEVsZW1lbnQ7XG4gICAgICAgIHRoaXMuc3RyZWFtID0gc3RyZWFtO1xuICAgICAgICB0aGlzLnByb3BlcnRpZXMgPSBwcm9wZXJ0aWVzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFN1YnNjcmliZSBvciB1bnN1YnNjcmliZSBmcm9tIHRoZSBhdWRpbyBzdHJlYW0gKGlmIGF2YWlsYWJsZSkuIENhbGxpbmcgdGhpcyBtZXRob2QgdHdpY2UgaW4gYSByb3cgcGFzc2luZyBzYW1lIHZhbHVlIHdpbGwgaGF2ZSBubyBlZmZlY3RcbiAgICAgKiBAcGFyYW0gdmFsdWUgYHRydWVgIHRvIHN1YnNjcmliZSB0byB0aGUgYXVkaW8gc3RyZWFtLCBgZmFsc2VgIHRvIHVuc3Vic2NyaWJlIGZyb20gaXRcbiAgICAgKi9cbiAgICBzdWJzY3JpYmVUb0F1ZGlvKHZhbHVlOiBib29sZWFuKTogU3Vic2NyaWJlciB7XG4gICAgICAgIHRoaXMuc3RyZWFtLmdldE1lZGlhU3RyZWFtKCkuZ2V0QXVkaW9UcmFja3MoKS5mb3JFYWNoKCh0cmFjaykgPT4ge1xuICAgICAgICAgICAgdHJhY2suZW5hYmxlZCA9IHZhbHVlO1xuICAgICAgICB9KTtcbiAgICAgICAgY29uc29sZS5pbmZvKFwiJ1N1YnNjcmliZXInIGhhcyBcIiArICh2YWx1ZSA/ICdzdWJzY3JpYmVkIHRvJyA6ICd1bnN1YnNjcmliZWQgZnJvbScpICsgJyBpdHMgYXVkaW8gc3RyZWFtJyk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFN1YnNjcmliZSBvciB1bnN1YnNjcmliZSBmcm9tIHRoZSB2aWRlbyBzdHJlYW0gKGlmIGF2YWlsYWJsZSkuIENhbGxpbmcgdGhpcyBtZXRob2QgdHdpY2UgaW4gYSByb3cgcGFzc2luZyBzYW1lIHZhbHVlIHdpbGwgaGF2ZSBubyBlZmZlY3RcbiAgICAgKiBAcGFyYW0gdmFsdWUgYHRydWVgIHRvIHN1YnNjcmliZSB0byB0aGUgdmlkZW8gc3RyZWFtLCBgZmFsc2VgIHRvIHVuc3Vic2NyaWJlIGZyb20gaXRcbiAgICAgKi9cbiAgICBzdWJzY3JpYmVUb1ZpZGVvKHZhbHVlOiBib29sZWFuKTogU3Vic2NyaWJlciB7XG4gICAgICAgIHRoaXMuc3RyZWFtLmdldE1lZGlhU3RyZWFtKCkuZ2V0VmlkZW9UcmFja3MoKS5mb3JFYWNoKCh0cmFjaykgPT4ge1xuICAgICAgICAgICAgdHJhY2suZW5hYmxlZCA9IHZhbHVlO1xuICAgICAgICB9KTtcbiAgICAgICAgY29uc29sZS5pbmZvKFwiJ1N1YnNjcmliZXInIGhhcyBcIiArICh2YWx1ZSA/ICdzdWJzY3JpYmVkIHRvJyA6ICd1bnN1YnNjcmliZWQgZnJvbScpICsgJyBpdHMgdmlkZW8gc3RyZWFtJyk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxufSIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTctMjAxOCBPcGVuVmlkdSAoaHR0cHM6Ly9vcGVudmlkdS5pby8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuZXhwb3J0IGVudW0gTG9jYWxSZWNvcmRlclN0YXRlIHtcbiAgICBSRUFEWSA9ICdSRUFEWScsXG4gICAgUkVDT1JESU5HID0gJ1JFQ09SRElORycsXG4gICAgUEFVU0VEID0gJ1BBVVNFRCcsXG4gICAgRklOSVNIRUQgPSAnRklOSVNIRUQnXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG4vKipcbiAqIERlZmluZXMgcHJvcGVydHkgW1tPcGVuVmlkdUVycm9yLm5hbWVdXVxuICovXG5leHBvcnQgZW51bSBPcGVuVmlkdUVycm9yTmFtZSB7XG5cbiAgICAvKipcbiAgICAgKiBCcm93c2VyIGlzIG5vdCBzdXBwb3J0ZWQgYnkgT3BlblZpZHUuXG4gICAgICogUmV0dXJuZWQgdXBvbiB1bnN1Y2Nlc3NmdWwgW1tTZXNzaW9uLmNvbm5lY3RdXVxuICAgICAqL1xuICAgIEJST1dTRVJfTk9UX1NVUFBPUlRFRCA9ICdCUk9XU0VSX05PVF9TVVBQT1JURUQnLFxuXG4gICAgLyoqXG4gICAgICogVGhlIHVzZXIgaGFzbid0IGdyYW50ZWQgcGVybWlzc2lvbnMgdG8gdGhlIHJlcXVpcmVkIGlucHV0IGRldmljZSB3aGVuIHRoZSBicm93c2VyIGFza2VkIGZvciB0aGVtLlxuICAgICAqIFJldHVybmVkIHVwb24gdW5zdWNjZXNzZnVsIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dIG9yIFtbT3BlblZpZHUuZ2V0VXNlck1lZGlhXV1cbiAgICAgKi9cbiAgICBERVZJQ0VfQUNDRVNTX0RFTklFRCA9ICdERVZJQ0VfQUNDRVNTX0RFTklFRCcsXG5cbiAgICAvKipcbiAgICAgKiBUaGUgdXNlciBoYXNuJ3QgZ3JhbnRlZCBwZXJtaXNzaW9ucyB0byBjYXB0dXJlIHNvbWUgZGVza3RvcCBzY3JlZW4gd2hlbiB0aGUgYnJvd3NlciBhc2tlZCBmb3IgdGhlbS5cbiAgICAgKiBSZXR1cm5lZCB1cG9uIHVuc3VjY2Vzc2Z1bCBbW09wZW5WaWR1LmluaXRQdWJsaXNoZXJdXSBvciBbW09wZW5WaWR1LmdldFVzZXJNZWRpYV1dXG4gICAgICovXG4gICAgU0NSRUVOX0NBUFRVUkVfREVOSUVEID0gJ1NDUkVFTl9DQVBUVVJFX0RFTklFRCcsXG5cbiAgICAvKipcbiAgICAgKiBCcm93c2VyIGRvZXMgbm90IHN1cHBvcnQgc2NyZWVuIHNoYXJpbmcuXG4gICAgICogUmV0dXJuZWQgdXBvbiB1bnN1Y2Nlc3NmdWwgW1tPcGVuVmlkdS5pbml0UHVibGlzaGVyXV1cbiAgICAgKi9cbiAgICBTQ1JFRU5fU0hBUklOR19OT1RfU1VQUE9SVEVEID0gJ1NDUkVFTl9TSEFSSU5HX05PVF9TVVBQT1JURUQnLFxuXG4gICAgLyoqXG4gICAgICogT25seSBmb3IgQ2hyb21lLCB0aGVyZSdzIG5vIHNjcmVlbiBzaGFyaW5nIGV4dGVuc2lvbiBpbnN0YWxsZWRcbiAgICAgKiBSZXR1cm5lZCB1cG9uIHVuc3VjY2Vzc2Z1bCBbW09wZW5WaWR1LmluaXRQdWJsaXNoZXJdXVxuICAgICAqL1xuICAgIFNDUkVFTl9FWFRFTlNJT05fTk9UX0lOU1RBTExFRCA9ICdTQ1JFRU5fRVhURU5TSU9OX05PVF9JTlNUQUxMRUQnLFxuXG4gICAgLyoqXG4gICAgICogT25seSBmb3IgQ2hyb21lLCB0aGUgc2NyZWVuIHNoYXJpbmcgZXh0ZW5zaW9uIGlzIGluc3RhbGxlZCBidXQgaXMgZGlzYWJsZWRcbiAgICAgKiBSZXR1cm5lZCB1cG9uIHVuc3VjY2Vzc2Z1bCBbW09wZW5WaWR1LmluaXRQdWJsaXNoZXJdXVxuICAgICAqL1xuICAgIFNDUkVFTl9FWFRFTlNJT05fRElTQUJMRUQgPSAnU0NSRUVOX0VYVEVOU0lPTl9ESVNBQkxFRCcsXG5cbiAgICAvKipcbiAgICAgKiBObyB2aWRlbyBpbnB1dCBkZXZpY2UgZm91bmQgd2l0aCB0aGUgcHJvdmlkZWQgZGV2aWNlSWQgKHByb3BlcnR5IFtbUHVibGlzaGVyUHJvcGVydGllcy52aWRlb1NvdXJjZV1dKVxuICAgICAqIFJldHVybmVkIHVwb24gdW5zdWNjZXNzZnVsIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dXG4gICAgICovXG4gICAgSU5QVVRfVklERU9fREVWSUNFX05PVF9GT1VORCA9ICdJTlBVVF9WSURFT19ERVZJQ0VfTk9UX0ZPVU5EJyxcblxuICAgIC8qKlxuICAgICAqIE5vIGF1ZGlvIGlucHV0IGRldmljZSBmb3VuZCB3aXRoIHRoZSBwcm92aWRlZCBkZXZpY2VJZCAocHJvcGVydHkgW1tQdWJsaXNoZXJQcm9wZXJ0aWVzLmF1ZGlvU291cmNlXV0pXG4gICAgICogUmV0dXJuZWQgdXBvbiB1bnN1Y2Nlc3NmdWwgW1tPcGVuVmlkdS5pbml0UHVibGlzaGVyXV1cbiAgICAgKi9cbiAgICBJTlBVVF9BVURJT19ERVZJQ0VfTk9UX0ZPVU5EID0gJ0lOUFVUX0FVRElPX0RFVklDRV9OT1RfRk9VTkQnLFxuXG4gICAgLyoqXG4gICAgICogTWV0aG9kIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dIGhhcyBiZWVuIGNhbGxlZCB3aXRoIHByb3BlcnRpZXMgYHZpZGVvU291cmNlYCBhbmQgYGF1ZGlvU291cmNlYCBvZlxuICAgICAqIFtbUHVibGlzaGVyUHJvcGVydGllc11dIHBhcmFtZXRlciBib3RoIHNldCB0byAqZmFsc2UqIG9yICpudWxsKlxuICAgICAqL1xuICAgIE5PX0lOUFVUX1NPVVJDRV9TRVQgPSAnTk9fSU5QVVRfU09VUkNFX1NFVCcsXG5cbiAgICAvKipcbiAgICAgKiBTb21lIG1lZGlhIHByb3BlcnR5IG9mIFtbUHVibGlzaGVyUHJvcGVydGllc11dIHN1Y2ggYXMgYGZyYW1lUmF0ZWAgb3IgYHJlc29sdXRpb25gIGlzIG5vdCBzdXBwb3J0ZWRcbiAgICAgKiBieSB0aGUgaW5wdXQgZGV2aWNlcyAod2hlbmV2ZXIgaXQgaXMgcG9zc2libGUgdGhleSBhcmUgYXV0b21hdGljYWxseSBhZGp1c3RlZCB0byB0aGUgbW9zdCBzaW1pbGFyIHZhbHVlKS5cbiAgICAgKiBSZXR1cm5lZCB1cG9uIHVuc3VjY2Vzc2Z1bCBbW09wZW5WaWR1LmluaXRQdWJsaXNoZXJdXVxuICAgICAqL1xuICAgIFBVQkxJU0hFUl9QUk9QRVJUSUVTX0VSUk9SID0gJ1BVQkxJU0hFUl9QUk9QRVJUSUVTX0VSUk9SJyxcblxuICAgIC8qKlxuICAgICAqIFRoZSBjbGllbnQgdHJpZWQgdG8gY2FsbCBhIG1ldGhvZCB3aXRob3V0IHRoZSByZXF1aXJlZCBwZXJtaXNzaW9ucy4gVGhpcyBjYW4gb2NjdXIgZm9yIG1ldGhvZHMgW1tTZXNzaW9uLnB1Ymxpc2hdXSxcbiAgICAgKiBbW1Nlc3Npb24uZm9yY2VVbnB1Ymxpc2hdXSBhbmQgW1tTZXNzaW9uLmZvcmNlRGlzY29ubmVjdF1dXG4gICAgICovXG4gICAgT1BFTlZJRFVfUEVSTUlTU0lPTl9ERU5JRUQgPSAnT1BFTlZJRFVfUEVSTUlTU0lPTl9ERU5JRUQnLFxuXG4gICAgLyoqXG4gICAgICogX05vdCBpbiB1c2UgeWV0X1xuICAgICAqL1xuICAgIE9QRU5WSURVX05PVF9DT05ORUNURUQgPSAnT1BFTlZJRFVfTk9UX0NPTk5FQ1RFRCcsXG5cbiAgICAvKipcbiAgICAgKiBfTm90IGluIHVzZSB5ZXRfXG4gICAgICovXG4gICAgR0VORVJJQ19FUlJPUiA9ICdHRU5FUklDX0VSUk9SJ1xufVxuXG4vKipcbiAqIFNpbXBsZSBvYmplY3QgdG8gaWRlbnRpZnkgcnVudGltZSBlcnJvcnMgb24gdGhlIGNsaWVudCBzaWRlXG4gKi9cbmV4cG9ydCBjbGFzcyBPcGVuVmlkdUVycm9yIHtcblxuICAgIG5hbWU6IE9wZW5WaWR1RXJyb3JOYW1lO1xuICAgIG1lc3NhZ2U6IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3RvcihuYW1lOiBPcGVuVmlkdUVycm9yTmFtZSwgbWVzc2FnZTogc3RyaW5nKSB7XG4gICAgICAgIHRoaXMubmFtZSA9IG5hbWU7XG4gICAgICAgIHRoaXMubWVzc2FnZSA9IG1lc3NhZ2U7XG4gICAgfVxuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG4vKipcbiAqIEhvdyB0aGUgdmlkZW8gd2lsbCBiZSBpbnNlcnRlZCBpbiB0aGUgRE9NIGZvciBQdWJsaXNoZXJzIGFuZCBTdWJzY3JpYmVycy4gU2VlIFtbUHVibGlzaGVyUHJvcGVydGllcy5pbnNlcnRNb2RlXV0gYW5kIFtbU3Vic2NyaWJlclByb3BlcnRpZXMuaW5zZXJ0TW9kZV1dXG4gKi9cbmV4cG9ydCBlbnVtIFZpZGVvSW5zZXJ0TW9kZSB7XG5cbiAgICAvKipcbiAgICAgKiBWaWRlbyBpbnNlcnRlZCBhZnRlciB0aGUgdGFyZ2V0IGVsZW1lbnQgKGFzIG5leHQgc2libGluZylcbiAgICAgKi9cbiAgICBBRlRFUiA9ICdBRlRFUicsXG4gICAgLyoqXG4gICAgICogVmlkZW8gaW5zZXJ0ZWQgYXMgbGFzdCBjaGlsZCBvZiB0aGUgdGFyZ2V0IGVsZW1lbnRcbiAgICAgKi9cbiAgICBBUFBFTkQgPSAnQVBQRU5EJyxcbiAgICAvKipcbiAgICAgKiBWaWRlbyBpbnNlcnRlZCBiZWZvcmUgdGhlIHRhcmdldCBlbGVtZW50IChhcyBwcmV2aW91cyBzaWJsaW5nKVxuICAgICAqL1xuICAgIEJFRk9SRSA9ICdCRUZPUkUnLFxuICAgIC8qKlxuICAgICAqIFZpZGVvIGluc2VydGVkIGFzIGZpcnN0IGNoaWxkIG9mIHRoZSB0YXJnZXQgZWxlbWVudFxuICAgICAqL1xuICAgIFBSRVBFTkQgPSAnUFJFUEVORCcsXG4gICAgLyoqXG4gICAgICogVmlkZW8gcmVwbGFjZXMgdGFyZ2V0IGVsZW1lbnRcbiAgICAgKi9cbiAgICBSRVBMQUNFID0gJ1JFUExBQ0UnXG5cbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IEV2ZW50IH0gZnJvbSAnLi9FdmVudCc7XG5pbXBvcnQgeyBDb25uZWN0aW9uIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvQ29ubmVjdGlvbic7XG5pbXBvcnQgeyBTZXNzaW9uIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvU2Vzc2lvbic7XG5cblxuLyoqXG4gKiBEZWZpbmVzIHRoZSBmb2xsb3dpbmcgZXZlbnRzOlxuICogLSBgY29ubmVjdGlvbkNyZWF0ZWRgOiBkaXNwYXRjaGVkIGJ5IFtbU2Vzc2lvbl1dXG4gKiAtIGBjb25uZWN0aW9uRGVzdHJveWVkYDogZGlzcGF0Y2hlZCBieSBbW1Nlc3Npb25dXVxuICovXG5leHBvcnQgY2xhc3MgQ29ubmVjdGlvbkV2ZW50IGV4dGVuZHMgRXZlbnQge1xuXG4gICAgLyoqXG4gICAgICogQ29ubmVjdGlvbiBvYmplY3QgdGhhdCB3YXMgY3JlYXRlZCBvciBkZXN0cm95ZWRcbiAgICAgKi9cbiAgICBjb25uZWN0aW9uOiBDb25uZWN0aW9uO1xuXG4gICAgLyoqXG4gICAgICogRm9yICdjb25uZWN0aW9uRGVzdHJveWVkJyBldmVudDpcbiAgICAgKiAtIFwiZGlzY29ubmVjdFwiOiB0aGUgcmVtb3RlIHVzZXIgaGFzIGNhbGxlZCBgU2Vzc2lvbi5kaXNjb25uZWN0KClgXG4gICAgICogLSBcImZvcmNlRGlzY29ubmVjdEJ5VXNlclwiOiB0aGUgcmVtb3RlIHVzZXIgaGFzIGJlZW4gZXZpY3RlZCBmcm9tIHRoZSBTZXNzaW9uIGJ5IG90aGVyIHVzZXIgY2FsbGluZyBgU2Vzc2lvbi5mb3JjZURpc2Nvbm5lY3QoKWBcbiAgICAgKiAtIFwiZm9yY2VEaXNjb25uZWN0QnlTZXJ2ZXJcIjogdGhlIHJlbW90ZSB1c2VyIGhhcyBiZWVuIGV2aWN0ZWQgZnJvbSB0aGUgU2Vzc2lvbiBieSB0aGUgYXBwbGljYXRpb25cbiAgICAgKiAtIFwic2Vzc2lvbkNsb3NlZEJ5U2VydmVyXCI6IHRoZSBTZXNzaW9uIGhhcyBiZWVuIGNsb3NlZCBieSB0aGUgYXBwbGljYXRpb25cbiAgICAgKiAtIFwibmV0d29ya0Rpc2Nvbm5lY3RcIjogdGhlIHJlbW90ZSB1c2VyIG5ldHdvcmsgY29ubmVjdGlvbiBoYXMgZHJvcHBlZFxuICAgICAqXG4gICAgICogRm9yICdjb25uZWN0aW9uQ3JlYXRlZCcgZW1wdHkgc3RyaW5nXG4gICAgICovXG4gICAgcmVhc29uOiBzdHJpbmc7XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgY29uc3RydWN0b3IoY2FuY2VsYWJsZTogYm9vbGVhbiwgdGFyZ2V0OiBTZXNzaW9uLCB0eXBlOiBzdHJpbmcsIGNvbm5lY3Rpb246IENvbm5lY3Rpb24sIHJlYXNvbjogc3RyaW5nKSB7XG4gICAgICAgIHN1cGVyKGNhbmNlbGFibGUsIHRhcmdldCwgdHlwZSk7XG4gICAgICAgIHRoaXMuY29ubmVjdGlvbiA9IGNvbm5lY3Rpb247XG4gICAgICAgIHRoaXMucmVhc29uID0gcmVhc29uO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6bm8tZW1wdHlcbiAgICBjYWxsRGVmYXVsdEJlaGF2aW9yKCkgeyB9XG5cbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IFN0cmVhbU1hbmFnZXIgfSBmcm9tICcuLi8uLi9PcGVuVmlkdS9TdHJlYW1NYW5hZ2VyJztcbmltcG9ydCB7IFNlc3Npb24gfSBmcm9tICcuLi8uLi9PcGVuVmlkdS9TZXNzaW9uJztcblxuZXhwb3J0IGFic3RyYWN0IGNsYXNzIEV2ZW50IHtcblxuICAgIC8qKlxuICAgICAqIFdoZXRoZXIgdGhlIGV2ZW50IGhhcyBhIGRlZmF1bHQgYmVoYXZpb3IgdGhhdCBtYXkgYmUgcHJldmVudGVkIGJ5IGNhbGxpbmcgW1tFdmVudC5wcmV2ZW50RGVmYXVsdF1dXG4gICAgICovXG4gICAgY2FuY2VsYWJsZTogYm9vbGVhbjtcblxuICAgIC8qKlxuICAgICAqIFRoZSBvYmplY3QgdGhhdCBkaXNwYXRjaGVkIHRoZSBldmVudFxuICAgICAqL1xuICAgIHRhcmdldDogU2Vzc2lvbiB8IFN0cmVhbU1hbmFnZXI7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgdHlwZSBvZiBldmVudC4gVGhpcyBpcyB0aGUgc2FtZSBzdHJpbmcgeW91IHBhc3MgYXMgZmlyc3QgcGFyYW1ldGVyIHdoZW4gY2FsbGluZyBtZXRob2QgYG9uKClgIG9mIGFueSBvYmplY3QgaW1wbGVtZW50aW5nIFtbRXZlbnREaXNwYXRjaGVyXV0gaW50ZXJmYWNlXG4gICAgICovXG4gICAgdHlwZTogc3RyaW5nO1xuXG4gICAgcHJpdmF0ZSBoYXNCZWVuUHJldmVudGVkID0gZmFsc2U7XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgY29uc3RydWN0b3IoY2FuY2VsYWJsZTogYm9vbGVhbiwgdGFyZ2V0OiBTZXNzaW9uIHwgU3RyZWFtTWFuYWdlciwgdHlwZTogc3RyaW5nKSB7XG4gICAgICAgIHRoaXMuY2FuY2VsYWJsZSA9IGNhbmNlbGFibGU7XG4gICAgICAgIHRoaXMudGFyZ2V0ID0gdGFyZ2V0O1xuICAgICAgICB0aGlzLnR5cGUgPSB0eXBlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFdoZXRoZXIgdGhlIGRlZmF1bHQgYmVhaGl2b3VyIG9mIHRoZSBldmVudCBoYXMgYmVlbiBwcmV2ZW50ZWQgb3Igbm90LiBDYWxsIFtbRXZlbnQucHJldmVudERlZmF1bHRdXSB0byBwcmV2ZW50IGl0XG4gICAgICovXG4gICAgaXNEZWZhdWx0UHJldmVudGVkKCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gdGhpcy5oYXNCZWVuUHJldmVudGVkO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFByZXZlbnRzIHRoZSBkZWZhdWx0IGJlaGF2aW9yIG9mIHRoZSBldmVudC4gVGhlIGZvbGxvd2luZyBldmVudHMgaGF2ZSBhIGRlZmF1bHQgYmVoYXZpb3I6XG4gICAgICpcbiAgICAgKiAtIGBzZXNzaW9uRGlzY29ubmVjdGVkYDogZGlzcGF0Y2hlZCBieSBbW1Nlc3Npb25dXSBvYmplY3QsIGF1dG9tYXRpY2FsbHkgdW5zdWJzY3JpYmVzIHRoZSBsZWF2aW5nIHBhcnRpY2lwYW50IGZyb20gZXZlcnkgU3Vic2NyaWJlciBvYmplY3Qgb2YgdGhlIHNlc3Npb24gKHRoaXMgaW5jbHVkZXMgY2xvc2luZyB0aGUgV2ViUlRDUGVlciBjb25uZWN0aW9uIGFuZCBkaXNwb3NpbmcgYWxsIE1lZGlhU3RyZWFtVHJhY2tzKVxuICAgICAqIGFuZCBhbHNvIGRlbGV0ZXMgYW55IEhUTUwgdmlkZW8gZWxlbWVudCBhc3NvY2lhdGVkIHRvIGVhY2ggU3Vic2NyaWJlciAob25seSB0aG9zZSBjcmVhdGVkIGJ5IE9wZW5WaWR1IEJyb3dzZXIsIGVpdGhlciBieSBwYXNzaW5nIGEgdmFsaWQgcGFyYW1ldGVyIGFzIGB0YXJnZXRFbGVtZW50YCBpbiBtZXRob2QgW1tTZXNzaW9uLnN1YnNjcmliZV1dIG9yXG4gICAgICogYnkgY2FsbGluZyBbW1N1YnNjcmliZXIuY3JlYXRlVmlkZW9FbGVtZW50XV0pLiBGb3IgZXZlcnkgdmlkZW8gcmVtb3ZlZCwgZWFjaCBTdWJzY3JpYmVyIG9iamVjdCB3aWxsIGFsc28gZGlzcGF0Y2ggYSBgdmlkZW9FbGVtZW50RGVzdHJveWVkYCBldmVudC5cbiAgICAgKlxuICAgICAqIC0gYHN0cmVhbURlc3Ryb3llZGA6XG4gICAgICogICAtIElmIGRpc3BhdGNoZWQgYnkgYSBbW1B1Ymxpc2hlcl1dICgqeW91KiBoYXZlIHVucHVibGlzaGVkKTogYXV0b21hdGljYWxseSBzdG9wcyBhbGwgbWVkaWEgdHJhY2tzIGFuZCBkZWxldGVzIGFueSBIVE1MIHZpZGVvIGVsZW1lbnQgYXNzb2NpYXRlZCB0byBpdCAob25seSB0aG9zZSBjcmVhdGVkIGJ5IE9wZW5WaWR1IEJyb3dzZXIsIGVpdGhlciBieSBwYXNzaW5nIGEgdmFsaWQgcGFyYW1ldGVyIGFzIGB0YXJnZXRFbGVtZW50YFxuICAgICAqIGluIG1ldGhvZCBbW09wZW5WaWR1LmluaXRQdWJsaXNoZXJdXSBvciBieSBjYWxsaW5nIFtbUHVibGlzaGVyLmNyZWF0ZVZpZGVvRWxlbWVudF1dKS4gRm9yIGV2ZXJ5IHZpZGVvIHJlbW92ZWQsIHRoZSBQdWJsaXNoZXIgb2JqZWN0IHdpbGwgYWxzbyBkaXNwYXRjaCBhIGB2aWRlb0VsZW1lbnREZXN0cm95ZWRgIGV2ZW50LlxuICAgICAqICAgLSBJZiBkaXNwYXRjaGVkIGJ5IFtbU2Vzc2lvbl1dICgqb3RoZXIgdXNlciogaGFzIHVucHVibGlzaGVkKTogYXV0b21hdGljYWxseSB1bnN1YnNjcmliZXMgdGhlIHByb3BlciBTdWJzY3JpYmVyIG9iamVjdCBmcm9tIHRoZSBzZXNzaW9uICh0aGlzIGluY2x1ZGVzIGNsb3NpbmcgdGhlIFdlYlJUQ1BlZXIgY29ubmVjdGlvbiBhbmQgZGlzcG9zaW5nIGFsbCBNZWRpYVN0cmVhbVRyYWNrcylcbiAgICAgKiBhbmQgYWxzbyBkZWxldGVzIGFueSBIVE1MIHZpZGVvIGVsZW1lbnQgYXNzb2NpYXRlZCB0byB0aGF0IFN1YnNjcmliZXIgKG9ubHkgdGhvc2UgY3JlYXRlZCBieSBPcGVuVmlkdSBCcm93c2VyLCBlaXRoZXIgYnkgcGFzc2luZyBhIHZhbGlkIHBhcmFtZXRlciBhcyBgdGFyZ2V0RWxlbWVudGAgaW4gbWV0aG9kIFtbU2Vzc2lvbi5zdWJzY3JpYmVdXSBvclxuICAgICAqIGJ5IGNhbGxpbmcgW1tTdWJzY3JpYmVyLmNyZWF0ZVZpZGVvRWxlbWVudF1dKS4gRm9yIGV2ZXJ5IHZpZGVvIHJlbW92ZWQsIHRoZSBTdWJzY3JpYmVyIG9iamVjdCB3aWxsIGFsc28gZGlzcGF0Y2ggYSBgdmlkZW9FbGVtZW50RGVzdHJveWVkYCBldmVudC5cbiAgICAgKi9cbiAgICBwcmV2ZW50RGVmYXVsdCgpIHtcbiAgICAgICAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lOm5vLWVtcHR5XG4gICAgICAgIHRoaXMuY2FsbERlZmF1bHRCZWhhdmlvciA9ICgpID0+IHsgfTtcbiAgICAgICAgdGhpcy5oYXNCZWVuUHJldmVudGVkID0gdHJ1ZTtcbiAgICB9XG5cbiAgICBwcm90ZWN0ZWQgYWJzdHJhY3QgY2FsbERlZmF1bHRCZWhhdmlvcigpO1xuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBFdmVudCB9IGZyb20gJy4vRXZlbnQnO1xuaW1wb3J0IHsgQ29ubmVjdGlvbiB9IGZyb20gJy4uLy4uL09wZW5WaWR1L0Nvbm5lY3Rpb24nO1xuaW1wb3J0IHsgU2Vzc2lvbiB9IGZyb20gJy4uLy4uJztcblxuXG4vKipcbiAqIERlZmluZXMgdGhlIGZvbGxvd2luZyBldmVudHM6XG4gKiAtIGBwdWJsaXNoZXJTdGFydFNwZWFraW5nYDogZGlzcGF0Y2hlZCBieSBbW1Nlc3Npb25dXVxuICogLSBgcHVibGlzaGVyU3RvcFNwZWFraW5nYDogZGlzcGF0Y2hlZCBieSBbW1Nlc3Npb25dXVxuICpcbiAqIE1vcmUgaW5mb3JtYXRpb246XG4gKiAtIFRoaXMgZXZlbnRzIHdpbGwgb25seSBiZSB0cmlnZ2VyZWQgZm9yICoqcmVtb3RlIHN0cmVhbXMgdGhhdCBoYXZlIGF1ZGlvIHRyYWNrcyoqIChbW1N0cmVhbS5oYXNBdWRpb11dIG11c3QgYmUgdHJ1ZSlcbiAqIC0gQm90aCBldmVudHMgc2hhcmUgdGhlIHNhbWUgbGlmZWN5Y2xlLiBUaGF0IG1lYW5zIHRoYXQgeW91IGNhbiBzdWJzY3JpYmUgdG8gb25seSBvbmUgb2YgdGhlbSBpZiB5b3Ugd2FudCwgYnV0IGlmIHlvdSBjYWxsIGBTZXNzaW9uLm9mZigncHVibGlzaGVyU3RvcFNwZWFraW5nJylgLFxuICoga2VlcCBpbiBtaW5kIHRoYXQgdGhpcyB3aWxsIGFsc28gaW50ZXJuYWxseSByZW1vdmUgYW55ICdwdWJsaXNoZXJTdGFydFNwZWFraW5nJyBldmVudFxuICogLSBZb3UgY2FuIGZ1cnRoZXIgY29uZmlndXJlIGhvdyB0aGUgZXZlbnRzIGFyZSBkaXNwYXRjaGVkIGJ5IHNldHRpbmcgcHJvcGVydHkgYHB1Ymxpc2hlclNwZWFraW5nRXZlbnRzT3B0aW9uc2AgaW4gdGhlIGNhbGwgb2YgW1tPcGVuVmlkdS5zZXRBZHZhbmNlZENvbmZpZ3VyYXRpb25dXVxuICovXG5leHBvcnQgY2xhc3MgUHVibGlzaGVyU3BlYWtpbmdFdmVudCBleHRlbmRzIEV2ZW50IHtcblxuICAgIC8qKlxuICAgICAqIFRoZSBjbGllbnQgdGhhdCBzdGFydGVkIG9yIHN0b3BwZWQgc3BlYWtpbmdcbiAgICAgKi9cbiAgICBjb25uZWN0aW9uOiBDb25uZWN0aW9uO1xuXG4gICAgLyoqXG4gICAgICogVGhlIHN0cmVhbUlkIG9mIHRoZSBTdHJlYW0gYWZmZWN0ZWQgYnkgdGhlIHNwZWFraW5nIGV2ZW50XG4gICAgICovXG4gICAgc3RyZWFtSWQ6IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3Rvcih0YXJnZXQ6IFNlc3Npb24sIHR5cGU6IHN0cmluZywgY29ubmVjdGlvbjogQ29ubmVjdGlvbiwgc3RyZWFtSWQ6IHN0cmluZykge1xuICAgICAgICBzdXBlcihmYWxzZSwgdGFyZ2V0LCB0eXBlKTtcbiAgICAgICAgdGhpcy50eXBlID0gdHlwZTtcbiAgICAgICAgdGhpcy5jb25uZWN0aW9uID0gY29ubmVjdGlvbjtcbiAgICAgICAgdGhpcy5zdHJlYW1JZCA9IHN0cmVhbUlkO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6bm8tZW1wdHlcbiAgICBjYWxsRGVmYXVsdEJlaGF2aW9yKCkgeyB9XG5cbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IEV2ZW50IH0gZnJvbSAnLi9FdmVudCc7XG5pbXBvcnQgeyBTZXNzaW9uIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvU2Vzc2lvbic7XG5cblxuLyoqXG4gKiBEZWZpbmVzIHRoZSBmb2xsb3dpbmcgZXZlbnRzOlxuICogLSBgcmVjb3JkaW5nU3RhcnRlZGA6IGRpc3BhdGNoZWQgYnkgW1tTZXNzaW9uXV1cbiAqIC0gYHJlY29yZGluZ1N0b3BwZWRgOiBkaXNwYXRjaGVkIGJ5IFtbU2Vzc2lvbl1dXG4gKi9cbmV4cG9ydCBjbGFzcyBSZWNvcmRpbmdFdmVudCBleHRlbmRzIEV2ZW50IHtcblxuICAgIC8qKlxuICAgICAqIFRoZSByZWNvcmRpbmcgSUQgZ2VuZXJhdGVkIGluIG9wZW52aWR1LXNlcnZlclxuICAgICAqL1xuICAgIGlkOiBzdHJpbmc7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgcmVjb3JkaW5nIG5hbWUgeW91IHN1cHBsaWVkIHRvIG9wZW52aWR1LXNlcnZlci4gRm9yIGV4YW1wbGUsIHRvIG5hbWUgeW91ciByZWNvcmRpbmcgZmlsZSBNWV9SRUNPUkRJTkc6XG4gICAgICogLSBXaXRoICoqQVBJIFJFU1QqKjogUE9TVCB0byBgL2FwaS9yZWNvcmRpbmdzL3N0YXJ0YCBwYXNzaW5nIEpTT04gYm9keSBge1wic2Vzc2lvblwiOlwic2Vzc2lvbklkXCIsXCJuYW1lXCI6XCJNWV9SRUNPUkRJTkdcIn1gXG4gICAgICogLSBXaXRoICoqb3BlbnZpZHUtamF2YS1jbGllbnQqKjogYE9wZW5WaWR1LnN0YXJ0UmVjb3JkaW5nKHNlc3Npb25JZCwgXCJNWV9SRUNPUkRJTkdcIilgIG9yIGBPcGVuVmlkdS5zdGFydFJlY29yZGluZyhzZXNzaW9uSWQsIG5ldyBSZWNvcmRpbmdQcm9wZXJ0aWVzLkJ1aWxkZXIoKS5uYW1lKFwiTVlfUkVDT1JESU5HXCIpLmJ1aWxkKCkpYFxuICAgICAqIC0gV2l0aCAqKm9wZW52aWR1LW5vZGUtY2xpZW50Kio6IGBPcGVuVmlkdS5zdGFydFJlY29yZGluZyhzZXNzaW9uSWQsIFwiTVlfUkVDT1JESU5HXCIpYCBvciBgT3BlblZpZHUuc3RhcnRSZWNvcmRpbmcoc2Vzc2lvbklkLCB7bmFtZTogXCJNWV9SRUNPUkRJTkdcIn0pYFxuICAgICAqXG4gICAgICogSWYgbm8gbmFtZSBpcyBzdXBwbGllZCwgdGhpcyBwcm9wZXJ0eSB3aWxsIGJlIHVuZGVmaW5lZCBhbmQgdGhlIHJlY29yZGVkIGZpbGUgd2lsbCBiZSBuYW1lZCBhZnRlciBwcm9wZXJ0eSBbW2lkXV1cbiAgICAgKi9cbiAgICBuYW1lPzogc3RyaW5nO1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHRhcmdldDogU2Vzc2lvbiwgdHlwZTogc3RyaW5nLCBpZDogc3RyaW5nLCBuYW1lOiBzdHJpbmcpIHtcbiAgICAgICAgc3VwZXIoZmFsc2UsIHRhcmdldCwgdHlwZSk7XG4gICAgICAgIHRoaXMuaWQgPSBpZDtcbiAgICAgICAgaWYgKG5hbWUgIT09IGlkKSB7XG4gICAgICAgICAgICB0aGlzLm5hbWUgPSBuYW1lO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZTpuby1lbXB0eVxuICAgIGNhbGxEZWZhdWx0QmVoYXZpb3IoKSB7IH1cblxufSIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTctMjAxOCBPcGVuVmlkdSAoaHR0cHM6Ly9vcGVudmlkdS5pby8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuaW1wb3J0IHsgRXZlbnQgfSBmcm9tICcuL0V2ZW50JztcbmltcG9ydCB7IFNlc3Npb24gfSBmcm9tICcuLi8uLi9PcGVuVmlkdS9TZXNzaW9uJztcblxuXG4vKipcbiAqIERlZmluZXMgZXZlbnQgYHNlc3Npb25EaXNjb25uZWN0ZWRgIGRpc3BhdGNoZWQgYnkgW1tTZXNzaW9uXV1cbiAqL1xuZXhwb3J0IGNsYXNzIFNlc3Npb25EaXNjb25uZWN0ZWRFdmVudCBleHRlbmRzIEV2ZW50IHtcblxuICAgIC8qKlxuICAgICAqIC0gXCJkaXNjb25uZWN0XCI6IHlvdSBoYXZlIGNhbGxlZCBgU2Vzc2lvbi5kaXNjb25uZWN0KClgXG4gICAgICogLSBcImZvcmNlRGlzY29ubmVjdEJ5VXNlclwiOiB5b3UgaGF2ZSBiZWVuIGV2aWN0ZWQgZnJvbSB0aGUgU2Vzc2lvbiBieSBvdGhlciB1c2VyIGNhbGxpbmcgYFNlc3Npb24uZm9yY2VEaXNjb25uZWN0KClgXG4gICAgICogLSBcImZvcmNlRGlzY29ubmVjdEJ5U2VydmVyXCI6IHlvdSBoYXZlIGJlZW4gZXZpY3RlZCBmcm9tIHRoZSBTZXNzaW9uIGJ5IHRoZSBhcHBsaWNhdGlvblxuICAgICAqIC0gXCJzZXNzaW9uQ2xvc2VkQnlTZXJ2ZXJcIjogdGhlIFNlc3Npb24gaGFzIGJlZW4gY2xvc2VkIGJ5IHRoZSBhcHBsaWNhdGlvblxuICAgICAqIC0gXCJuZXR3b3JrRGlzY29ubmVjdFwiOiB5b3VyIG5ldHdvcmsgY29ubmVjdGlvbiBoYXMgZHJvcHBlZFxuICAgICAqL1xuICAgIHJlYXNvbjogc3RyaW5nO1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHRhcmdldDogU2Vzc2lvbiwgcmVhc29uOiBzdHJpbmcpIHtcbiAgICAgICAgc3VwZXIodHJ1ZSwgdGFyZ2V0LCAnc2Vzc2lvbkRpc2Nvbm5lY3RlZCcpO1xuICAgICAgICB0aGlzLnJlYXNvbiA9IHJlYXNvbjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgY2FsbERlZmF1bHRCZWhhdmlvcigpIHtcblxuICAgICAgICBjb25zb2xlLmluZm8oXCJDYWxsaW5nIGRlZmF1bHQgYmVoYXZpb3IgdXBvbiAnXCIgKyB0aGlzLnR5cGUgKyBcIicgZXZlbnQgZGlzcGF0Y2hlZCBieSAnU2Vzc2lvbidcIik7XG5cbiAgICAgICAgY29uc3Qgc2Vzc2lvbiA9IDxTZXNzaW9uPnRoaXMudGFyZ2V0O1xuXG4gICAgICAgIC8vIERpc3Bvc2UgYW5kIGRlbGV0ZSBhbGwgcmVtb3RlIENvbm5lY3Rpb25zXG4gICAgICAgIGZvciAoY29uc3QgY29ubmVjdGlvbklkIGluIHNlc3Npb24ucmVtb3RlQ29ubmVjdGlvbnMpIHtcbiAgICAgICAgICAgIGlmICghIXNlc3Npb24ucmVtb3RlQ29ubmVjdGlvbnNbY29ubmVjdGlvbklkXS5zdHJlYW0pIHtcbiAgICAgICAgICAgICAgICBzZXNzaW9uLnJlbW90ZUNvbm5lY3Rpb25zW2Nvbm5lY3Rpb25JZF0uc3RyZWFtLmRpc3Bvc2VXZWJSdGNQZWVyKCk7XG4gICAgICAgICAgICAgICAgc2Vzc2lvbi5yZW1vdGVDb25uZWN0aW9uc1tjb25uZWN0aW9uSWRdLnN0cmVhbS5kaXNwb3NlTWVkaWFTdHJlYW0oKTtcbiAgICAgICAgICAgICAgICBpZiAoc2Vzc2lvbi5yZW1vdGVDb25uZWN0aW9uc1tjb25uZWN0aW9uSWRdLnN0cmVhbS5zdHJlYW1NYW5hZ2VyKSB7XG4gICAgICAgICAgICAgICAgICAgIHNlc3Npb24ucmVtb3RlQ29ubmVjdGlvbnNbY29ubmVjdGlvbklkXS5zdHJlYW0uc3RyZWFtTWFuYWdlci5yZW1vdmVBbGxWaWRlb3MoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZGVsZXRlIHNlc3Npb24ucmVtb3RlU3RyZWFtc0NyZWF0ZWRbc2Vzc2lvbi5yZW1vdGVDb25uZWN0aW9uc1tjb25uZWN0aW9uSWRdLnN0cmVhbS5zdHJlYW1JZF07XG4gICAgICAgICAgICAgICAgc2Vzc2lvbi5yZW1vdGVDb25uZWN0aW9uc1tjb25uZWN0aW9uSWRdLmRpc3Bvc2UoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGRlbGV0ZSBzZXNzaW9uLnJlbW90ZUNvbm5lY3Rpb25zW2Nvbm5lY3Rpb25JZF07XG4gICAgICAgIH1cbiAgICB9XG5cbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IEV2ZW50IH0gZnJvbSAnLi9FdmVudCc7XG5pbXBvcnQgeyBDb25uZWN0aW9uIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvQ29ubmVjdGlvbic7XG5pbXBvcnQgeyBTZXNzaW9uIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvU2Vzc2lvbic7XG5cblxuLyoqXG4gKiBEZWZpbmVzIHRoZSBmb2xsb3dpbmcgZXZlbnRzOlxuICogLSBgc2lnbmFsYDogZGlzcGF0Y2hlZCBieSBbW1Nlc3Npb25dXVxuICogLSBgc2lnbmFsOlRZUEVgOiBkaXNwYXRjaGVkIGJ5IFtbU2Vzc2lvbl1dXG4gKi9cbmV4cG9ydCBjbGFzcyBTaWduYWxFdmVudCBleHRlbmRzIEV2ZW50IHtcblxuICAgIC8qKlxuICAgICAqIFRoZSB0eXBlIG9mIHNpZ25hbCAoY2FuIGJlIGVtcHR5KS5cbiAgICAgKlxuICAgICAqIFRoZSBjbGllbnQgbXVzdCBiZSBzdWJzY3JpYmVkIHRvIGBTZXNzaW9uLm9uKCdzaWduYWw6dHlwZScsIGZ1bmN0aW9uKHNpZ25hbEV2ZW50KSB7Li4ufSlgIHRvIHJlY2VpdmUgdGhpcyBvYmplY3QgaW4gdGhlIGNhbGxiYWNrLlxuICAgICAqXG4gICAgICogU3Vic2NyaWJpbmcgdG8gYFNlc3Npb24ub24oJ3NpZ25hbCcsIGZ1bmN0aW9uKHNpZ25hbEV2ZW50KSB7Li4ufSlgIHdpbGwgdHJpZ2dlciBhbGwgdHlwZXMgb2Ygc2lnbmFscy5cbiAgICAgKi9cbiAgICB0eXBlOiBzdHJpbmc7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgbWVzc2FnZSBvZiB0aGUgc2lnbmFsIChjYW4gYmUgZW10cHkpXG4gICAgICovXG4gICAgZGF0YTogc3RyaW5nO1xuXG4gICAgLyoqXG4gICAgICogVGhlIGNsaWVudCB0aGF0IHNlbnQgdGhlIHNpZ25hbFxuICAgICAqL1xuICAgIGZyb206IENvbm5lY3Rpb247XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgY29uc3RydWN0b3IodGFyZ2V0OiBTZXNzaW9uLCB0eXBlOiBzdHJpbmcsIGRhdGE6IHN0cmluZywgZnJvbTogQ29ubmVjdGlvbikge1xuICAgICAgICBzdXBlcihmYWxzZSwgdGFyZ2V0LCB0eXBlKTtcbiAgICAgICAgdGhpcy50eXBlID0gdHlwZTtcbiAgICAgICAgdGhpcy5kYXRhID0gZGF0YTtcbiAgICAgICAgdGhpcy5mcm9tID0gZnJvbTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lOm5vLWVtcHR5XG4gICAgY2FsbERlZmF1bHRCZWhhdmlvcigpIHsgfVxuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBFdmVudCB9IGZyb20gJy4vRXZlbnQnO1xuaW1wb3J0IHsgUHVibGlzaGVyIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvUHVibGlzaGVyJztcbmltcG9ydCB7IFNlc3Npb24gfSBmcm9tICcuLi8uLi9PcGVuVmlkdS9TZXNzaW9uJztcbmltcG9ydCB7IFN0cmVhbSB9IGZyb20gJy4uLy4uL09wZW5WaWR1L1N0cmVhbSc7XG5cblxuLyoqXG4gKiBEZWZpbmVzIHRoZSBmb2xsb3dpbmcgZXZlbnRzOlxuICogLSBgc3RyZWFtQ3JlYXRlZGA6IGRpc3BhdGNoZWQgYnkgW1tTZXNzaW9uXV0gYW5kIFtbUHVibGlzaGVyXV1cbiAqIC0gYHN0cmVhbURlc3Ryb3llZGA6IGRpc3BhdGNoZWQgYnkgW1tTZXNzaW9uXV0gYW5kIFtbUHVibGlzaGVyXV1cbiAqL1xuZXhwb3J0IGNsYXNzIFN0cmVhbUV2ZW50IGV4dGVuZHMgRXZlbnQge1xuXG4gICAgLyoqXG4gICAgICogU3RyZWFtIG9iamVjdCB0aGF0IHdhcyBjcmVhdGVkIG9yIGRlc3Ryb3llZFxuICAgICAqL1xuICAgIHN0cmVhbTogU3RyZWFtO1xuXG4gICAgLyoqXG4gICAgICogRm9yICdzdHJlYW1EZXN0cm95ZWQnIGV2ZW50OlxuICAgICAqIC0gXCJ1bnB1Ymxpc2hcIjogbWV0aG9kIGBTZXNzaW9uLnVucHVibGlzaCgpYCBoYXMgYmVlbiBjYWxsZWRcbiAgICAgKiAtIFwiZGlzY29ubmVjdFwiOiBtZXRob2QgYFNlc3Npb24uZGlzY29ubmVjdCgpYCBoYXMgYmVlbiBjYWxsZWRcbiAgICAgKiAtIFwiZm9yY2VVbnB1Ymxpc2hCeVVzZXJcIjogc29tZSB1c2VyIGhhcyBjYWxsZWQgYFNlc3Npb24uZm9yY2VVbnB1Ymxpc2goKWAgb3ZlciB0aGUgU3RyZWFtXG4gICAgICogLSBcImZvcmNlRGlzY29ubmVjdEJ5VXNlclwiOiBzb21lIHVzZXIgaGFzIGNhbGxlZCBgU2Vzc2lvbi5mb3JjZURpc2Nvbm5lY3QoKWAgb3ZlciB0aGUgU3RyZWFtXG4gICAgICogLSBcImZvcmNlVW5wdWJsaXNoQnlTZXJ2ZXJcIjogdGhlIHVzZXIncyBzdHJlYW0gaGFzIGJlZW4gdW5wdWJsaXNoZWQgZnJvbSB0aGUgU2Vzc2lvbiBieSB0aGUgYXBwbGljYXRpb25cbiAgICAgKiAtIFwiZm9yY2VEaXNjb25uZWN0QnlTZXJ2ZXJcIjogdGhlIHVzZXIgaGFzIGJlZW4gZXZpY3RlZCBmcm9tIHRoZSBTZXNzaW9uIGJ5IHRoZSBhcHBsaWNhdGlvblxuICAgICAqIC0gXCJzZXNzaW9uQ2xvc2VkQnlTZXJ2ZXJcIjogdGhlIFNlc3Npb24gaGFzIGJlZW4gY2xvc2VkIGJ5IHRoZSBhcHBsaWNhdGlvblxuICAgICAqIC0gXCJuZXR3b3JrRGlzY29ubmVjdFwiOiB0aGUgdXNlcidzIG5ldHdvcmsgY29ubmVjdGlvbiBoYXMgZHJvcHBlZFxuICAgICAqXG4gICAgICogRm9yICdzdHJlYW1DcmVhdGVkJyBlbXB0eSBzdHJpbmdcbiAgICAgKi9cbiAgICByZWFzb246IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3RvcihjYW5jZWxhYmxlOiBib29sZWFuLCB0YXJnZXQ6IFNlc3Npb24gfCBQdWJsaXNoZXIsIHR5cGU6IHN0cmluZywgc3RyZWFtOiBTdHJlYW0sIHJlYXNvbjogc3RyaW5nKSB7XG4gICAgICAgIHN1cGVyKGNhbmNlbGFibGUsIHRhcmdldCwgdHlwZSk7XG4gICAgICAgIHRoaXMuc3RyZWFtID0gc3RyZWFtO1xuICAgICAgICB0aGlzLnJlYXNvbiA9IHJlYXNvbjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgY2FsbERlZmF1bHRCZWhhdmlvcigpIHtcbiAgICAgICAgaWYgKHRoaXMudHlwZSA9PT0gJ3N0cmVhbURlc3Ryb3llZCcpIHtcblxuICAgICAgICAgICAgaWYgKHRoaXMudGFyZ2V0IGluc3RhbmNlb2YgU2Vzc2lvbikge1xuICAgICAgICAgICAgICAgIC8vIFJlbW90ZSBTdHJlYW1cbiAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oXCJDYWxsaW5nIGRlZmF1bHQgYmVoYXZpb3IgdXBvbiAnXCIgKyB0aGlzLnR5cGUgKyBcIicgZXZlbnQgZGlzcGF0Y2hlZCBieSAnU2Vzc2lvbidcIik7XG4gICAgICAgICAgICAgICAgdGhpcy5zdHJlYW0uZGlzcG9zZVdlYlJ0Y1BlZXIoKTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAodGhpcy50YXJnZXQgaW5zdGFuY2VvZiBQdWJsaXNoZXIpIHtcbiAgICAgICAgICAgICAgICAvLyBMb2NhbCBTdHJlYW1cbiAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oXCJDYWxsaW5nIGRlZmF1bHQgYmVoYXZpb3IgdXBvbiAnXCIgKyB0aGlzLnR5cGUgKyBcIicgZXZlbnQgZGlzcGF0Y2hlZCBieSAnUHVibGlzaGVyJ1wiKTtcbiAgICAgICAgICAgICAgICBjbGVhckludGVydmFsKCg8UHVibGlzaGVyPnRoaXMudGFyZ2V0KS5zY3JlZW5TaGFyZVJlc2l6ZUludGVydmFsKTtcbiAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbS5pc0xvY2FsU3RyZWFtUmVhZHlUb1B1Ymxpc2ggPSBmYWxzZTtcblxuICAgICAgICAgICAgICAgIC8vIERlbGV0ZSBQdWJsaXNoZXIgb2JqZWN0IGZyb20gT3BlblZpZHUgcHVibGlzaGVycyBhcnJheVxuICAgICAgICAgICAgICAgIGNvbnN0IG9wZW52aWR1UHVibGlzaGVycyA9ICg8UHVibGlzaGVyPnRoaXMudGFyZ2V0KS5vcGVudmlkdS5wdWJsaXNoZXJzO1xuICAgICAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgb3BlbnZpZHVQdWJsaXNoZXJzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChvcGVudmlkdVB1Ymxpc2hlcnNbaV0gPT09ICg8UHVibGlzaGVyPnRoaXMudGFyZ2V0KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgb3BlbnZpZHVQdWJsaXNoZXJzLnNwbGljZShpLCAxKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBEaXNwb3NlIHRoZSBNZWRpYVN0cmVhbSBsb2NhbCBvYmplY3RcbiAgICAgICAgICAgIHRoaXMuc3RyZWFtLmRpc3Bvc2VNZWRpYVN0cmVhbSgpO1xuXG4gICAgICAgICAgICAvLyBSZW1vdmUgZnJvbSBET00gYWxsIHZpZGVvIGVsZW1lbnRzIGFzc29jaWF0ZWQgdG8gdGhpcyBTdHJlYW0sIGlmIHRoZXJlJ3MgYSBTdHJlYW1NYW5hZ2VyIGRlZmluZWRcbiAgICAgICAgICAgIC8vIChtZXRob2QgU2Vzc2lvbi5zdWJzY3JpYmUgbXVzdCBoYXZlIGJlZW4gY2FsbGVkKVxuICAgICAgICAgICAgaWYgKHRoaXMuc3RyZWFtLnN0cmVhbU1hbmFnZXIpIHRoaXMuc3RyZWFtLnN0cmVhbU1hbmFnZXIucmVtb3ZlQWxsVmlkZW9zKCk7XG5cbiAgICAgICAgICAgIC8vIERlbGV0ZSBzdHJlYW0gZnJvbSBTZXNzaW9uLnJlbW90ZVN0cmVhbXNDcmVhdGVkIG1hcFxuICAgICAgICAgICAgZGVsZXRlIHRoaXMuc3RyZWFtLnNlc3Npb24ucmVtb3RlU3RyZWFtc0NyZWF0ZWRbdGhpcy5zdHJlYW0uc3RyZWFtSWRdO1xuXG4gICAgICAgICAgICAvLyBEZWxldGUgU3RyZWFtT3B0aW9uc1NlcnZlciBmcm9tIHJlbW90ZSBDb25uZWN0aW9uXG4gICAgICAgICAgICBjb25zdCByZW1vdGVDb25uZWN0aW9uID0gdGhpcy5zdHJlYW0uc2Vzc2lvbi5yZW1vdGVDb25uZWN0aW9uc1t0aGlzLnN0cmVhbS5jb25uZWN0aW9uLmNvbm5lY3Rpb25JZF07XG4gICAgICAgICAgICBpZiAoISFyZW1vdGVDb25uZWN0aW9uICYmICEhcmVtb3RlQ29ubmVjdGlvbi5vcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgY29uc3Qgc3RyZWFtT3B0aW9uc1NlcnZlciA9IHJlbW90ZUNvbm5lY3Rpb24ub3B0aW9ucy5zdHJlYW1zO1xuICAgICAgICAgICAgICAgIGZvciAobGV0IGkgPSBzdHJlYW1PcHRpb25zU2VydmVyLmxlbmd0aCAtIDE7IGkgPj0gMDsgLS1pKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChzdHJlYW1PcHRpb25zU2VydmVyW2ldLmlkID09PSB0aGlzLnN0cmVhbS5zdHJlYW1JZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgc3RyZWFtT3B0aW9uc1NlcnZlci5zcGxpY2UoaSwgMSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgfVxuICAgIH1cblxufSIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTctMjAxOCBPcGVuVmlkdSAoaHR0cHM6Ly9vcGVudmlkdS5pby8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuaW1wb3J0IHsgRXZlbnQgfSBmcm9tICcuL0V2ZW50JztcbmltcG9ydCB7IFN0cmVhbU1hbmFnZXIgfSBmcm9tICcuLi8uLi9PcGVuVmlkdS9TdHJlYW1NYW5hZ2VyJztcblxuLyoqXG4gKiBEZWZpbmVzIHRoZSBmb2xsb3dpbmcgZXZlbnRzOlxuICogLSBgc3RyZWFtUGxheWluZ2A6IGRpc3BhdGNoZWQgYnkgW1tTdHJlYW1NYW5hZ2VyXV0gKFtbUHVibGlzaGVyXV0gYW5kIFtbU3Vic2NyaWJlcl1dKVxuICovXG5leHBvcnQgY2xhc3MgU3RyZWFtTWFuYWdlckV2ZW50IGV4dGVuZHMgRXZlbnQge1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHRhcmdldDogU3RyZWFtTWFuYWdlcikge1xuICAgICAgICBzdXBlcihmYWxzZSwgdGFyZ2V0LCAnc3RyZWFtUGxheWluZycpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6bm8tZW1wdHlcbiAgICBjYWxsRGVmYXVsdEJlaGF2aW9yKCkgeyB9XG5cbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IEV2ZW50IH0gZnJvbSAnLi9FdmVudCc7XG5pbXBvcnQgeyBTZXNzaW9uIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvU2Vzc2lvbic7XG5pbXBvcnQgeyBTdHJlYW0gfSBmcm9tICcuLi8uLi9PcGVuVmlkdS9TdHJlYW0nO1xuaW1wb3J0IHsgU3RyZWFtTWFuYWdlciB9IGZyb20gJy4uLy4uL09wZW5WaWR1L1N0cmVhbU1hbmFnZXInO1xuXG4vKipcbiAqIERlZmluZXMgZXZlbnQgYHN0cmVhbVByb3BlcnR5Q2hhbmdlZGAgZGlzcGF0Y2hlZCBieSBbW1Nlc3Npb25dXSBhcyB3ZWxsIGFzIGJ5IFtbU3RyZWFtTWFuYWdlcl1dIChbW1B1Ymxpc2hlcl1dIGFuZCBbW1N1YnNjcmliZXJdXSkuXG4gKiBUaGlzIGV2ZW50IGlzIGZpcmVkIHdoZW4gYW55IHJlbW90ZSBzdHJlYW0gKG93bmVkIGJ5IGEgU3Vic2NyaWJlcikgb3IgbG9jYWwgc3RyZWFtIChvd25lZCBieSBhIFB1Ymxpc2hlcikgdW5kZXJnb2VzXG4gKiBhbnkgY2hhbmdlIGluIGFueSBvZiBpdHMgbXV0YWJsZSBwcm9wZXJ0aWVzIChzZWUgW1tjaGFuZ2VkUHJvcGVydHldXSkuXG4gKi9cbmV4cG9ydCBjbGFzcyBTdHJlYW1Qcm9wZXJ0eUNoYW5nZWRFdmVudCBleHRlbmRzIEV2ZW50IHtcblxuICAgIC8qKlxuICAgICAqIFRoZSBTdHJlYW0gd2hvc2UgcHJvcGVydHkgaGFzIGNoYW5nZWQuIFlvdSBjYW4gYWx3YXlzIGlkZW50aWZ5IHRoZSB1c2VyIHB1Ymxpc2hpbmcgdGhlIGNoYW5nZWQgc3RyZWFtIGJ5IGNvbnN1bHRpbmcgcHJvcGVydHkgW1tTdHJlYW0uY29ubmVjdGlvbl1dXG4gICAgICovXG4gICAgc3RyZWFtOiBTdHJlYW07XG5cbiAgICAvKipcbiAgICAgKiBUaGUgcHJvcGVydHkgb2YgdGhlIHN0cmVhbSB0aGF0IGNoYW5nZWQuIFRoaXMgdmFsdWUgaXMgZWl0aGVyIGBcInZpZGVvQWN0aXZlXCJgLCBgXCJhdWRpb0FjdGl2ZVwiYCBvciBgXCJ2aWRlb0RpbWVuc2lvbnNcImBcbiAgICAgKi9cbiAgICBjaGFuZ2VkUHJvcGVydHk6IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIENhdXNlIG9mIHRoZSBjaGFuZ2Ugb24gdGhlIHN0cmVhbSdzIHByb3BlcnR5OlxuICAgICAqIC0gRm9yIGB2aWRlb0FjdGl2ZWA6IGBcInB1Ymxpc2hWaWRlb1wiYFxuICAgICAqIC0gRm9yIGBhdWRpb0FjdGl2ZWA6IGBcInB1Ymxpc2hBdWRpb1wiYFxuICAgICAqIC0gRm9yIGB2aWRlb0RpbWVuc2lvbnNgOiBgXCJkZXZpY2VSb3RhdGVkXCJgIG9yIGBcInNjcmVlblJlc2l6ZWRcImBcbiAgICAgKi9cbiAgICByZWFzb246IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIE5ldyB2YWx1ZSBvZiB0aGUgcHJvcGVydHkgKGFmdGVyIGNoYW5nZSwgY3VycmVudCB2YWx1ZSlcbiAgICAgKi9cbiAgICBuZXdWYWx1ZTogT2JqZWN0O1xuXG4gICAgLyoqXG4gICAgICogUHJldmlvdXMgdmFsdWUgb2YgdGhlIHByb3BlcnR5IChiZWZvcmUgY2hhbmdlKVxuICAgICAqL1xuICAgIG9sZFZhbHVlOiBPYmplY3Q7XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgY29uc3RydWN0b3IodGFyZ2V0OiBTZXNzaW9uIHwgU3RyZWFtTWFuYWdlciwgc3RyZWFtOiBTdHJlYW0sIGNoYW5nZWRQcm9wZXJ0eTogc3RyaW5nLCBuZXdWYWx1ZTogT2JqZWN0LCBvbGRWYWx1ZTogT2JqZWN0LCByZWFzb246IHN0cmluZykge1xuICAgICAgICBzdXBlcihmYWxzZSwgdGFyZ2V0LCAnc3RyZWFtUHJvcGVydHlDaGFuZ2VkJyk7XG4gICAgICAgIHRoaXMuc3RyZWFtID0gc3RyZWFtO1xuICAgICAgICB0aGlzLmNoYW5nZWRQcm9wZXJ0eSA9IGNoYW5nZWRQcm9wZXJ0eTtcbiAgICAgICAgdGhpcy5uZXdWYWx1ZSA9IG5ld1ZhbHVlO1xuICAgICAgICB0aGlzLm9sZFZhbHVlID0gb2xkVmFsdWU7XG4gICAgICAgIHRoaXMucmVhc29uID0gcmVhc29uO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6bm8tZW1wdHlcbiAgICBjYWxsRGVmYXVsdEJlaGF2aW9yKCkgeyB9XG5cbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IEV2ZW50IH0gZnJvbSAnLi9FdmVudCc7XG5pbXBvcnQgeyBTdHJlYW1NYW5hZ2VyIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvU3RyZWFtTWFuYWdlcic7XG5cblxuLyoqXG4gKiBEZWZpbmVzIHRoZSBmb2xsb3dpbmcgZXZlbnRzOlxuICogLSBgdmlkZW9FbGVtZW50Q3JlYXRlZGA6IGRpc3BhdGNoZWQgYnkgW1tQdWJsaXNoZXJdXSBhbmQgW1tTdWJzY3JpYmVyXV0gd2hlbmV2ZXIgYSBuZXcgSFRNTCB2aWRlbyBlbGVtZW50IGhhcyBiZWVuIGluc2VydGVkIGludG8gRE9NIGJ5IE9wZW5WaWR1IEJyb3dzZXIgbGlicmFyeS4gU2VlXG4gKiBbTWFuYWdlIHZpZGVvIHBsYXllcnNdKC9kb2NzL2hvdy1kby1pL21hbmFnZS12aWRlb3MpIHNlY3Rpb24uXG4gKiAtIGB2aWRlb0VsZW1lbnREZXN0cm95ZWRgOiBkaXNwYXRjaGVkIGJ5IFtbUHVibGlzaGVyXV0gYW5kIFtbU3Vic2NyaWJlcl1dIHdoZW5ldmVyIGFuIEhUTUwgdmlkZW8gZWxlbWVudCBoYXMgYmVlbiByZW1vdmVkIGZyb20gRE9NIGJ5IE9wZW5WaWR1IEJyb3dzZXIgbGlicmFyeS5cbiAqL1xuZXhwb3J0IGNsYXNzIFZpZGVvRWxlbWVudEV2ZW50IGV4dGVuZHMgRXZlbnQge1xuXG4gICAgLyoqXG4gICAgICogVmlkZW8gZWxlbWVudCB0aGF0IHdhcyBjcmVhdGVkIG9yIGRlc3Ryb3llZFxuICAgICAqL1xuICAgIGVsZW1lbnQ6IEhUTUxWaWRlb0VsZW1lbnQ7XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgY29uc3RydWN0b3IoZWxlbWVudDogSFRNTFZpZGVvRWxlbWVudCwgdGFyZ2V0OiBTdHJlYW1NYW5hZ2VyLCB0eXBlOiBzdHJpbmcpIHtcbiAgICAgICAgc3VwZXIoZmFsc2UsIHRhcmdldCwgdHlwZSk7XG4gICAgICAgIHRoaXMuZWxlbWVudCA9IGVsZW1lbnQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZTpuby1lbXB0eVxuICAgIGNhbGxEZWZhdWx0QmVoYXZpb3IoKSB7IH1cblxufSIsImZ1bmN0aW9uIE1hcHBlcigpXG57XG4gIHZhciBzb3VyY2VzID0ge307XG5cblxuICB0aGlzLmZvckVhY2ggPSBmdW5jdGlvbihjYWxsYmFjaylcbiAge1xuICAgIGZvcih2YXIga2V5IGluIHNvdXJjZXMpXG4gICAge1xuICAgICAgdmFyIHNvdXJjZSA9IHNvdXJjZXNba2V5XTtcblxuICAgICAgZm9yKHZhciBrZXkyIGluIHNvdXJjZSlcbiAgICAgICAgY2FsbGJhY2soc291cmNlW2tleTJdKTtcbiAgICB9O1xuICB9O1xuXG4gIHRoaXMuZ2V0ID0gZnVuY3Rpb24oaWQsIHNvdXJjZSlcbiAge1xuICAgIHZhciBpZHMgPSBzb3VyY2VzW3NvdXJjZV07XG4gICAgaWYoaWRzID09IHVuZGVmaW5lZClcbiAgICAgIHJldHVybiB1bmRlZmluZWQ7XG5cbiAgICByZXR1cm4gaWRzW2lkXTtcbiAgfTtcblxuICB0aGlzLnJlbW92ZSA9IGZ1bmN0aW9uKGlkLCBzb3VyY2UpXG4gIHtcbiAgICB2YXIgaWRzID0gc291cmNlc1tzb3VyY2VdO1xuICAgIGlmKGlkcyA9PSB1bmRlZmluZWQpXG4gICAgICByZXR1cm47XG5cbiAgICBkZWxldGUgaWRzW2lkXTtcblxuICAgIC8vIENoZWNrIGl0J3MgZW1wdHlcbiAgICBmb3IodmFyIGkgaW4gaWRzKXtyZXR1cm4gZmFsc2V9XG5cbiAgICBkZWxldGUgc291cmNlc1tzb3VyY2VdO1xuICB9O1xuXG4gIHRoaXMuc2V0ID0gZnVuY3Rpb24odmFsdWUsIGlkLCBzb3VyY2UpXG4gIHtcbiAgICBpZih2YWx1ZSA9PSB1bmRlZmluZWQpXG4gICAgICByZXR1cm4gdGhpcy5yZW1vdmUoaWQsIHNvdXJjZSk7XG5cbiAgICB2YXIgaWRzID0gc291cmNlc1tzb3VyY2VdO1xuICAgIGlmKGlkcyA9PSB1bmRlZmluZWQpXG4gICAgICBzb3VyY2VzW3NvdXJjZV0gPSBpZHMgPSB7fTtcblxuICAgIGlkc1tpZF0gPSB2YWx1ZTtcbiAgfTtcbn07XG5cblxuTWFwcGVyLnByb3RvdHlwZS5wb3AgPSBmdW5jdGlvbihpZCwgc291cmNlKVxue1xuICB2YXIgdmFsdWUgPSB0aGlzLmdldChpZCwgc291cmNlKTtcbiAgaWYodmFsdWUgPT0gdW5kZWZpbmVkKVxuICAgIHJldHVybiB1bmRlZmluZWQ7XG5cbiAgdGhpcy5yZW1vdmUoaWQsIHNvdXJjZSk7XG5cbiAgcmV0dXJuIHZhbHVlO1xufTtcblxuXG5tb2R1bGUuZXhwb3J0cyA9IE1hcHBlcjtcbiIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTQgS3VyZW50byAoaHR0cDovL2t1cmVudG8ub3JnLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG52YXIgSnNvblJwY0NsaWVudCAgPSByZXF1aXJlKCcuL2pzb25ycGNjbGllbnQnKTtcblxuXG5leHBvcnRzLkpzb25ScGNDbGllbnQgID0gSnNvblJwY0NsaWVudDsiLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE0IEt1cmVudG8gKGh0dHA6Ly9rdXJlbnRvLm9yZy8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxudmFyIFJwY0J1aWxkZXIgPSByZXF1aXJlKCcuLi8nKTtcbnZhciBXZWJTb2NrZXRXaXRoUmVjb25uZWN0aW9uID0gcmVxdWlyZSgnLi90cmFuc3BvcnRzL3dlYlNvY2tldFdpdGhSZWNvbm5lY3Rpb24nKTtcblxuRGF0ZS5ub3cgPSBEYXRlLm5vdyB8fCBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gK25ldyBEYXRlO1xufTtcblxudmFyIFBJTkdfSU5URVJWQUwgPSA1MDAwO1xuXG52YXIgUkVDT05ORUNUSU5HID0gJ1JFQ09OTkVDVElORyc7XG52YXIgQ09OTkVDVEVEID0gJ0NPTk5FQ1RFRCc7XG52YXIgRElTQ09OTkVDVEVEID0gJ0RJU0NPTk5FQ1RFRCc7XG5cbnZhciBMb2dnZXIgPSBjb25zb2xlO1xuXG4vKipcbiAqXG4gKiBoZWFydGJlYXQ6IGludGVydmFsIGluIG1zIGZvciBlYWNoIGhlYXJ0YmVhdCBtZXNzYWdlLFxuICogc2VuZENsb3NlTWVzc2FnZSA6IHRydWUgLyBmYWxzZSwgYmVmb3JlIGNsb3NpbmcgdGhlIGNvbm5lY3Rpb24sIGl0IHNlbmRzIGEgY2xvc2VTZXNzaW9uIG1lc3NhZ2VcbiAqIDxwcmU+XG4gKiB3cyA6IHtcbiAqIFx0dXJpIDogVVJJIHRvIGNvbm50ZWN0IHRvLFxuICogIHVzZVNvY2tKUyA6IHRydWUgKHVzZSBTb2NrSlMpIC8gZmFsc2UgKHVzZSBXZWJTb2NrZXQpIGJ5IGRlZmF1bHQsXG4gKiBcdG9uY29ubmVjdGVkIDogY2FsbGJhY2sgbWV0aG9kIHRvIGludm9rZSB3aGVuIGNvbm5lY3Rpb24gaXMgc3VjY2Vzc2Z1bCxcbiAqIFx0b25kaXNjb25uZWN0IDogY2FsbGJhY2sgbWV0aG9kIHRvIGludm9rZSB3aGVuIHRoZSBjb25uZWN0aW9uIGlzIGxvc3QsXG4gKiBcdG9ucmVjb25uZWN0aW5nIDogY2FsbGJhY2sgbWV0aG9kIHRvIGludm9rZSB3aGVuIHRoZSBjbGllbnQgaXMgcmVjb25uZWN0aW5nLFxuICogXHRvbnJlY29ubmVjdGVkIDogY2FsbGJhY2sgbWV0aG9kIHRvIGludm9rZSB3aGVuIHRoZSBjbGllbnQgc3VjY2Vzc2Z1bGx5IHJlY29ubmVjdHMsXG4gKiBcdG9uZXJyb3IgOiBjYWxsYmFjayBtZXRob2QgdG8gaW52b2tlIHdoZW4gdGhlcmUgaXMgYW4gZXJyb3JcbiAqIH0sXG4gKiBycGMgOiB7XG4gKiBcdHJlcXVlc3RUaW1lb3V0IDogdGltZW91dCBmb3IgYSByZXF1ZXN0LFxuICogXHRzZXNzaW9uU3RhdHVzQ2hhbmdlZDogY2FsbGJhY2sgbWV0aG9kIGZvciBjaGFuZ2VzIGluIHNlc3Npb24gc3RhdHVzLFxuICogXHRtZWRpYVJlbmVnb3RpYXRpb246IG1lZGlhUmVuZWdvdGlhdGlvblxuICogfVxuICogPC9wcmU+XG4gKi9cbmZ1bmN0aW9uIEpzb25ScGNDbGllbnQoY29uZmlndXJhdGlvbikge1xuXG4gICAgdmFyIHNlbGYgPSB0aGlzO1xuXG4gICAgdmFyIHdzQ29uZmlnID0gY29uZmlndXJhdGlvbi53cztcblxuICAgIHZhciBub3RSZWNvbm5lY3RJZk51bUxlc3NUaGFuID0gLTE7XG5cbiAgICB2YXIgcGluZ05leHROdW0gPSAwO1xuICAgIHZhciBlbmFibGVkUGluZ3MgPSB0cnVlO1xuICAgIHZhciBwaW5nUG9uZ1N0YXJ0ZWQgPSBmYWxzZTtcbiAgICB2YXIgcGluZ0ludGVydmFsO1xuXG4gICAgdmFyIHN0YXR1cyA9IERJU0NPTk5FQ1RFRDtcblxuICAgIHZhciBvbnJlY29ubmVjdGluZyA9IHdzQ29uZmlnLm9ucmVjb25uZWN0aW5nO1xuICAgIHZhciBvbnJlY29ubmVjdGVkID0gd3NDb25maWcub25yZWNvbm5lY3RlZDtcbiAgICB2YXIgb25jb25uZWN0ZWQgPSB3c0NvbmZpZy5vbmNvbm5lY3RlZDtcbiAgICB2YXIgb25lcnJvciA9IHdzQ29uZmlnLm9uZXJyb3I7XG5cbiAgICBjb25maWd1cmF0aW9uLnJwYy5wdWxsID0gZnVuY3Rpb24ocGFyYW1zLCByZXF1ZXN0KSB7XG4gICAgICAgIHJlcXVlc3QucmVwbHkobnVsbCwgXCJwdXNoXCIpO1xuICAgIH1cblxuICAgIHdzQ29uZmlnLm9ucmVjb25uZWN0aW5nID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIExvZ2dlci5kZWJ1ZyhcIi0tLS0tLS0tLSBPTlJFQ09OTkVDVElORyAtLS0tLS0tLS0tLVwiKTtcbiAgICAgICAgaWYgKHN0YXR1cyA9PT0gUkVDT05ORUNUSU5HKSB7XG4gICAgICAgICAgICBMb2dnZXIuZXJyb3IoXCJXZWJzb2NrZXQgYWxyZWFkeSBpbiBSRUNPTk5FQ1RJTkcgc3RhdGUgd2hlbiByZWNlaXZpbmcgYSBuZXcgT05SRUNPTk5FQ1RJTkcgbWVzc2FnZS4gSWdub3JpbmcgaXRcIik7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBzdGF0dXMgPSBSRUNPTk5FQ1RJTkc7XG4gICAgICAgIGlmIChvbnJlY29ubmVjdGluZykge1xuICAgICAgICAgICAgb25yZWNvbm5lY3RpbmcoKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHdzQ29uZmlnLm9ucmVjb25uZWN0ZWQgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgTG9nZ2VyLmRlYnVnKFwiLS0tLS0tLS0tIE9OUkVDT05ORUNURUQgLS0tLS0tLS0tLS1cIik7XG4gICAgICAgIGlmIChzdGF0dXMgPT09IENPTk5FQ1RFRCkge1xuICAgICAgICAgICAgTG9nZ2VyLmVycm9yKFwiV2Vic29ja2V0IGFscmVhZHkgaW4gQ09OTkVDVEVEIHN0YXRlIHdoZW4gcmVjZWl2aW5nIGEgbmV3IE9OUkVDT05ORUNURUQgbWVzc2FnZS4gSWdub3JpbmcgaXRcIik7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgc3RhdHVzID0gQ09OTkVDVEVEO1xuXG4gICAgICAgIGVuYWJsZWRQaW5ncyA9IHRydWU7XG4gICAgICAgIHVwZGF0ZU5vdFJlY29ubmVjdElmTGVzc1RoYW4oKTtcbiAgICAgICAgdXNlUGluZygpO1xuXG4gICAgICAgIGlmIChvbnJlY29ubmVjdGVkKSB7XG4gICAgICAgICAgICBvbnJlY29ubmVjdGVkKCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB3c0NvbmZpZy5vbmNvbm5lY3RlZCA9IGZ1bmN0aW9uKCkge1xuICAgICAgICBMb2dnZXIuZGVidWcoXCItLS0tLS0tLS0gT05DT05ORUNURUQgLS0tLS0tLS0tLS1cIik7XG4gICAgICAgIGlmIChzdGF0dXMgPT09IENPTk5FQ1RFRCkge1xuICAgICAgICAgICAgTG9nZ2VyLmVycm9yKFwiV2Vic29ja2V0IGFscmVhZHkgaW4gQ09OTkVDVEVEIHN0YXRlIHdoZW4gcmVjZWl2aW5nIGEgbmV3IE9OQ09OTkVDVEVEIG1lc3NhZ2UuIElnbm9yaW5nIGl0XCIpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHN0YXR1cyA9IENPTk5FQ1RFRDtcblxuICAgICAgICBlbmFibGVkUGluZ3MgPSB0cnVlO1xuICAgICAgICB1c2VQaW5nKCk7XG5cbiAgICAgICAgaWYgKG9uY29ubmVjdGVkKSB7XG4gICAgICAgICAgICBvbmNvbm5lY3RlZCgpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgd3NDb25maWcub25lcnJvciA9IGZ1bmN0aW9uKGVycm9yKSB7XG4gICAgICAgIExvZ2dlci5kZWJ1ZyhcIi0tLS0tLS0tLSBPTkVSUk9SIC0tLS0tLS0tLS0tXCIpO1xuXG4gICAgICAgIHN0YXR1cyA9IERJU0NPTk5FQ1RFRDtcblxuICAgICAgICBpZiAob25lcnJvcikge1xuICAgICAgICAgICAgb25lcnJvcihlcnJvcik7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB2YXIgd3MgPSBuZXcgV2ViU29ja2V0V2l0aFJlY29ubmVjdGlvbih3c0NvbmZpZyk7XG5cbiAgICBMb2dnZXIuZGVidWcoJ0Nvbm5lY3Rpbmcgd2Vic29ja2V0IHRvIFVSSTogJyArIHdzQ29uZmlnLnVyaSk7XG5cbiAgICB2YXIgcnBjQnVpbGRlck9wdGlvbnMgPSB7XG4gICAgICAgIHJlcXVlc3RfdGltZW91dDogY29uZmlndXJhdGlvbi5ycGMucmVxdWVzdFRpbWVvdXQsXG4gICAgICAgIHBpbmdfcmVxdWVzdF90aW1lb3V0OiBjb25maWd1cmF0aW9uLnJwYy5oZWFydGJlYXRSZXF1ZXN0VGltZW91dFxuICAgIH07XG5cbiAgICB2YXIgcnBjID0gbmV3IFJwY0J1aWxkZXIoUnBjQnVpbGRlci5wYWNrZXJzLkpzb25SUEMsIHJwY0J1aWxkZXJPcHRpb25zLCB3cyxcbiAgICAgICAgZnVuY3Rpb24ocmVxdWVzdCkge1xuXG4gICAgICAgICAgICBMb2dnZXIuZGVidWcoJ1JlY2VpdmVkIHJlcXVlc3Q6ICcgKyBKU09OLnN0cmluZ2lmeShyZXF1ZXN0KSk7XG5cbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgdmFyIGZ1bmMgPSBjb25maWd1cmF0aW9uLnJwY1tyZXF1ZXN0Lm1ldGhvZF07XG5cbiAgICAgICAgICAgICAgICBpZiAoZnVuYyA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgIExvZ2dlci5lcnJvcihcIk1ldGhvZCBcIiArIHJlcXVlc3QubWV0aG9kICsgXCIgbm90IHJlZ2lzdGVyZWQgaW4gY2xpZW50XCIpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGZ1bmMocmVxdWVzdC5wYXJhbXMsIHJlcXVlc3QpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgICAgIExvZ2dlci5lcnJvcignRXhjZXB0aW9uIHByb2Nlc3NpbmcgcmVxdWVzdDogJyArIEpTT04uc3RyaW5naWZ5KHJlcXVlc3QpKTtcbiAgICAgICAgICAgICAgICBMb2dnZXIuZXJyb3IoZXJyKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG5cbiAgICB0aGlzLnNlbmQgPSBmdW5jdGlvbihtZXRob2QsIHBhcmFtcywgY2FsbGJhY2spIHtcbiAgICAgICAgaWYgKG1ldGhvZCAhPT0gJ3BpbmcnKSB7XG4gICAgICAgICAgICBMb2dnZXIuZGVidWcoJ1JlcXVlc3Q6IG1ldGhvZDonICsgbWV0aG9kICsgXCIgcGFyYW1zOlwiICsgSlNPTi5zdHJpbmdpZnkocGFyYW1zKSk7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgcmVxdWVzdFRpbWUgPSBEYXRlLm5vdygpO1xuXG4gICAgICAgIHJwYy5lbmNvZGUobWV0aG9kLCBwYXJhbXMsIGZ1bmN0aW9uKGVycm9yLCByZXN1bHQpIHtcbiAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgIExvZ2dlci5lcnJvcihcIkVSUk9SOlwiICsgZXJyb3IubWVzc2FnZSArIFwiIGluIFJlcXVlc3Q6IG1ldGhvZDpcIiArXG4gICAgICAgICAgICAgICAgICAgICAgICBtZXRob2QgKyBcIiBwYXJhbXM6XCIgKyBKU09OLnN0cmluZ2lmeShwYXJhbXMpICsgXCIgcmVxdWVzdDpcIiArXG4gICAgICAgICAgICAgICAgICAgICAgICBlcnJvci5yZXF1ZXN0KTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yLmRhdGEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIExvZ2dlci5lcnJvcihcIkVSUk9SIERBVEE6XCIgKyBKU09OLnN0cmluZ2lmeShlcnJvci5kYXRhKSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGNhdGNoIChlKSB7fVxuICAgICAgICAgICAgICAgIGVycm9yLnJlcXVlc3RUaW1lID0gcmVxdWVzdFRpbWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoY2FsbGJhY2spIHtcbiAgICAgICAgICAgICAgICBpZiAocmVzdWx0ICE9IHVuZGVmaW5lZCAmJiByZXN1bHQudmFsdWUgIT09ICdwb25nJykge1xuICAgICAgICAgICAgICAgICAgICBMb2dnZXIuZGVidWcoJ1Jlc3BvbnNlOiAnICsgSlNPTi5zdHJpbmdpZnkocmVzdWx0KSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNhbGxiYWNrKGVycm9yLCByZXN1bHQpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiB1cGRhdGVOb3RSZWNvbm5lY3RJZkxlc3NUaGFuKCkge1xuICAgICAgICBMb2dnZXIuZGVidWcoXCJub3RSZWNvbm5lY3RJZk51bUxlc3NUaGFuID0gXCIgKyBwaW5nTmV4dE51bSArICcgKG9sZD0nICtcbiAgICAgICAgICAgIG5vdFJlY29ubmVjdElmTnVtTGVzc1RoYW4gKyAnKScpO1xuICAgICAgICBub3RSZWNvbm5lY3RJZk51bUxlc3NUaGFuID0gcGluZ05leHROdW07XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gc2VuZFBpbmcoKSB7XG4gICAgICAgIGlmIChlbmFibGVkUGluZ3MpIHtcbiAgICAgICAgICAgIHZhciBwYXJhbXMgPSBudWxsO1xuICAgICAgICAgICAgaWYgKHBpbmdOZXh0TnVtID09IDAgfHwgcGluZ05leHROdW0gPT0gbm90UmVjb25uZWN0SWZOdW1MZXNzVGhhbikge1xuICAgICAgICAgICAgICAgIHBhcmFtcyA9IHtcbiAgICAgICAgICAgICAgICAgICAgaW50ZXJ2YWw6IGNvbmZpZ3VyYXRpb24uaGVhcnRiZWF0IHx8IFBJTkdfSU5URVJWQUxcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcGluZ05leHROdW0rKztcblxuICAgICAgICAgICAgc2VsZi5zZW5kKCdwaW5nJywgcGFyYW1zLCAoZnVuY3Rpb24ocGluZ051bSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmdW5jdGlvbihlcnJvciwgcmVzdWx0KSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFwiRXJyb3IgaW4gcGluZyByZXF1ZXN0ICNcIiArIHBpbmdOdW0gKyBcIiAoXCIgK1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yLm1lc3NhZ2UgKyBcIilcIik7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocGluZ051bSA+IG5vdFJlY29ubmVjdElmTnVtTGVzc1RoYW4pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbmFibGVkUGluZ3MgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB1cGRhdGVOb3RSZWNvbm5lY3RJZkxlc3NUaGFuKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFwiU2VydmVyIGRpZCBub3QgcmVzcG9uZCB0byBwaW5nIG1lc3NhZ2UgI1wiICtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGluZ051bSArIFwiLiBSZWNvbm5lY3RpbmcuLi4gXCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdzLnJlY29ubmVjdFdzKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KShwaW5nTmV4dE51bSkpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFwiVHJ5aW5nIHRvIHNlbmQgcGluZywgYnV0IHBpbmcgaXMgbm90IGVuYWJsZWRcIik7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKlxuICAgICogSWYgY29uZmlndXJhdGlvbi5oZWFyYmVhdCBoYXMgYW55IHZhbHVlLCB0aGUgcGluZy1wb25nIHdpbGwgd29yayB3aXRoIHRoZSBpbnRlcnZhbFxuICAgICogb2YgY29uZmlndXJhdGlvbi5oZWFyYmVhdFxuICAgICovXG4gICAgZnVuY3Rpb24gdXNlUGluZygpIHtcbiAgICAgICAgaWYgKCFwaW5nUG9uZ1N0YXJ0ZWQpIHtcbiAgICAgICAgICAgIExvZ2dlci5kZWJ1ZyhcIlN0YXJ0aW5nIHBpbmcgKGlmIGNvbmZpZ3VyZWQpXCIpXG4gICAgICAgICAgICBwaW5nUG9uZ1N0YXJ0ZWQgPSB0cnVlO1xuXG4gICAgICAgICAgICBpZiAoY29uZmlndXJhdGlvbi5oZWFydGJlYXQgIT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgcGluZ0ludGVydmFsID0gc2V0SW50ZXJ2YWwoc2VuZFBpbmcsIGNvbmZpZ3VyYXRpb24uaGVhcnRiZWF0KTtcbiAgICAgICAgICAgICAgICBzZW5kUGluZygpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgdGhpcy5jbG9zZSA9IGZ1bmN0aW9uKCkge1xuICAgICAgICBMb2dnZXIuZGVidWcoXCJDbG9zaW5nIGpzb25ScGNDbGllbnQgZXhwbGljaXRseSBieSBjbGllbnRcIik7XG5cbiAgICAgICAgaWYgKHBpbmdJbnRlcnZhbCAhPSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIExvZ2dlci5kZWJ1ZyhcIkNsZWFyaW5nIHBpbmcgaW50ZXJ2YWxcIik7XG4gICAgICAgICAgICBjbGVhckludGVydmFsKHBpbmdJbnRlcnZhbCk7XG4gICAgICAgIH1cbiAgICAgICAgcGluZ1BvbmdTdGFydGVkID0gZmFsc2U7XG4gICAgICAgIGVuYWJsZWRQaW5ncyA9IGZhbHNlO1xuXG4gICAgICAgIGlmIChjb25maWd1cmF0aW9uLnNlbmRDbG9zZU1lc3NhZ2UpIHtcbiAgICAgICAgICAgIExvZ2dlci5kZWJ1ZyhcIlNlbmRpbmcgY2xvc2UgbWVzc2FnZVwiKVxuICAgICAgICAgICAgdGhpcy5zZW5kKCdjbG9zZVNlc3Npb24nLCBudWxsLCBmdW5jdGlvbihlcnJvciwgcmVzdWx0KSB7XG4gICAgICAgICAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgIExvZ2dlci5lcnJvcihcIkVycm9yIHNlbmRpbmcgY2xvc2UgbWVzc2FnZTogXCIgKyBKU09OLnN0cmluZ2lmeShlcnJvcikpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB3cy5jbG9zZSgpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0gZWxzZSB7XG5cdFx0XHR3cy5jbG9zZSgpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gVGhpcyBtZXRob2QgaXMgb25seSBmb3IgdGVzdGluZ1xuICAgIHRoaXMuZm9yY2VDbG9zZSA9IGZ1bmN0aW9uKG1pbGxpcykge1xuICAgICAgICB3cy5mb3JjZUNsb3NlKG1pbGxpcyk7XG4gICAgfVxuXG4gICAgdGhpcy5yZWNvbm5lY3QgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgd3MucmVjb25uZWN0V3MoKTtcbiAgICB9XG59XG5cblxubW9kdWxlLmV4cG9ydHMgPSBKc29uUnBjQ2xpZW50O1xuIiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNCBLdXJlbnRvIChodHRwOi8va3VyZW50by5vcmcvKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbnZhciBXZWJTb2NrZXRXaXRoUmVjb25uZWN0aW9uICA9IHJlcXVpcmUoJy4vd2ViU29ja2V0V2l0aFJlY29ubmVjdGlvbicpO1xuXG5cbmV4cG9ydHMuV2ViU29ja2V0V2l0aFJlY29ubmVjdGlvbiAgPSBXZWJTb2NrZXRXaXRoUmVjb25uZWN0aW9uOyIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTMtMjAxNSBLdXJlbnRvIChodHRwOi8va3VyZW50by5vcmcvKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuXCJ1c2Ugc3RyaWN0XCI7XG5cbnZhciBCcm93c2VyV2ViU29ja2V0ID0gZ2xvYmFsLldlYlNvY2tldCB8fCBnbG9iYWwuTW96V2ViU29ja2V0O1xuXG52YXIgTG9nZ2VyID0gY29uc29sZTtcblxuLyoqXG4gKiBHZXQgZWl0aGVyIHRoZSBgV2ViU29ja2V0YCBvciBgTW96V2ViU29ja2V0YCBnbG9iYWxzXG4gKiBpbiB0aGUgYnJvd3NlciBvciB0cnkgdG8gcmVzb2x2ZSBXZWJTb2NrZXQtY29tcGF0aWJsZVxuICogaW50ZXJmYWNlIGV4cG9zZWQgYnkgYHdzYCBmb3IgTm9kZS1saWtlIGVudmlyb25tZW50LlxuICovXG5cbi8qdmFyIFdlYlNvY2tldCA9IEJyb3dzZXJXZWJTb2NrZXQ7XG5pZiAoIVdlYlNvY2tldCAmJiB0eXBlb2Ygd2luZG93ID09PSAndW5kZWZpbmVkJykge1xuICAgIHRyeSB7XG4gICAgICAgIFdlYlNvY2tldCA9IHJlcXVpcmUoJ3dzJyk7XG4gICAgfSBjYXRjaCAoZSkgeyB9XG59Ki9cblxuLy92YXIgU29ja0pTID0gcmVxdWlyZSgnc29ja2pzLWNsaWVudCcpO1xuXG52YXIgTUFYX1JFVFJJRVMgPSAyMDAwOyAvLyBGb3JldmVyLi4uXG52YXIgUkVUUllfVElNRV9NUyA9IDMwMDA7IC8vIEZJWE1FOiBJbXBsZW1lbnQgZXhwb25lbnRpYWwgd2FpdCB0aW1lcy4uLlxuXG52YXIgQ09OTkVDVElORyA9IDA7XG52YXIgT1BFTiA9IDE7XG52YXIgQ0xPU0lORyA9IDI7XG52YXIgQ0xPU0VEID0gMztcblxuLypcbmNvbmZpZyA9IHtcblx0XHR1cmkgOiB3c1VyaSxcblx0XHR1c2VTb2NrSlMgOiB0cnVlICh1c2UgU29ja0pTKSAvIGZhbHNlICh1c2UgV2ViU29ja2V0KSBieSBkZWZhdWx0LFxuXHRcdG9uY29ubmVjdGVkIDogY2FsbGJhY2sgbWV0aG9kIHRvIGludm9rZSB3aGVuIGNvbm5lY3Rpb24gaXMgc3VjY2Vzc2Z1bCxcblx0XHRvbmRpc2Nvbm5lY3QgOiBjYWxsYmFjayBtZXRob2QgdG8gaW52b2tlIHdoZW4gdGhlIGNvbm5lY3Rpb24gaXMgbG9zdCxcblx0XHRvbnJlY29ubmVjdGluZyA6IGNhbGxiYWNrIG1ldGhvZCB0byBpbnZva2Ugd2hlbiB0aGUgY2xpZW50IGlzIHJlY29ubmVjdGluZyxcblx0XHRvbnJlY29ubmVjdGVkIDogY2FsbGJhY2sgbWV0aG9kIHRvIGludm9rZSB3aGVuIHRoZSBjbGllbnQgc3VjY2Vzc2Z1bGx5IHJlY29ubmVjdHMsXG5cdH07XG4qL1xuZnVuY3Rpb24gV2ViU29ja2V0V2l0aFJlY29ubmVjdGlvbihjb25maWcpIHtcblxuICAgIHZhciBjbG9zaW5nID0gZmFsc2U7XG4gICAgdmFyIHJlZ2lzdGVyTWVzc2FnZUhhbmRsZXI7XG4gICAgdmFyIHdzVXJpID0gY29uZmlnLnVyaTtcbiAgICB2YXIgdXNlU29ja0pTID0gY29uZmlnLnVzZVNvY2tKUztcbiAgICB2YXIgcmVjb25uZWN0aW5nID0gZmFsc2U7XG5cbiAgICB2YXIgZm9yY2luZ0Rpc2Nvbm5lY3Rpb24gPSBmYWxzZTtcblxuICAgIHZhciB3cztcblxuICAgIGlmICh1c2VTb2NrSlMpIHtcbiAgICAgICAgd3MgPSBuZXcgU29ja0pTKHdzVXJpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICB3cyA9IG5ldyBXZWJTb2NrZXQod3NVcmkpO1xuICAgIH1cblxuICAgIHdzLm9ub3BlbiA9IGZ1bmN0aW9uKCkge1xuICAgICAgICBsb2dDb25uZWN0ZWQod3MsIHdzVXJpKTtcbiAgICAgICAgaWYgKGNvbmZpZy5vbmNvbm5lY3RlZCkge1xuICAgICAgICAgICAgY29uZmlnLm9uY29ubmVjdGVkKCk7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgd3Mub25lcnJvciA9IGZ1bmN0aW9uKGVycm9yKSB7XG4gICAgICAgIExvZ2dlci5lcnJvcihcIkNvdWxkIG5vdCBjb25uZWN0IHRvIFwiICsgd3NVcmkgKyBcIiAoaW52b2tpbmcgb25lcnJvciBpZiBkZWZpbmVkKVwiLCBlcnJvcik7XG4gICAgICAgIGlmIChjb25maWcub25lcnJvcikge1xuICAgICAgICAgICAgY29uZmlnLm9uZXJyb3IoZXJyb3IpO1xuICAgICAgICB9XG4gICAgfTtcblxuICAgIGZ1bmN0aW9uIGxvZ0Nvbm5lY3RlZCh3cywgd3NVcmkpIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIExvZ2dlci5kZWJ1ZyhcIldlYlNvY2tldCBjb25uZWN0ZWQgdG8gXCIgKyB3c1VyaSk7XG4gICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgIExvZ2dlci5lcnJvcihlKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHZhciByZWNvbm5lY3Rpb25PbkNsb3NlID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIGlmICh3cy5yZWFkeVN0YXRlID09PSBDTE9TRUQpIHtcbiAgICAgICAgICAgIGlmIChjbG9zaW5nKSB7XG4gICAgICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFwiQ29ubmVjdGlvbiBjbG9zZWQgYnkgdXNlclwiKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFwiQ29ubmVjdGlvbiBjbG9zZWQgdW5leHBlY3RlY2x5LiBSZWNvbm5lY3RpbmcuLi5cIik7XG4gICAgICAgICAgICAgICAgcmVjb25uZWN0VG9TYW1lVXJpKE1BWF9SRVRSSUVTLCAxKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIExvZ2dlci5kZWJ1ZyhcIkNsb3NlIGNhbGxiYWNrIGZyb20gcHJldmlvdXMgd2Vic29ja2V0LiBJZ25vcmluZyBpdFwiKTtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICB3cy5vbmNsb3NlID0gcmVjb25uZWN0aW9uT25DbG9zZTtcblxuICAgIGZ1bmN0aW9uIHJlY29ubmVjdFRvU2FtZVVyaShtYXhSZXRyaWVzLCBudW1SZXRyaWVzKSB7XG4gICAgICAgIExvZ2dlci5kZWJ1ZyhcInJlY29ubmVjdFRvU2FtZVVyaSAoYXR0ZW1wdCAjXCIgKyBudW1SZXRyaWVzICsgXCIsIG1heD1cIiArIG1heFJldHJpZXMgKyBcIilcIik7XG5cbiAgICAgICAgaWYgKG51bVJldHJpZXMgPT09IDEpIHtcbiAgICAgICAgICAgIGlmIChyZWNvbm5lY3RpbmcpIHtcbiAgICAgICAgICAgICAgICBMb2dnZXIud2FybihcIlRyeWluZyB0byByZWNvbm5lY3RUb05ld1VyaSB3aGVuIHJlY29ubmVjdGluZy4uLiBJZ25vcmluZyB0aGlzIHJlY29ubmVjdGlvbi5cIilcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJlY29ubmVjdGluZyA9IHRydWU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChjb25maWcub25yZWNvbm5lY3RpbmcpIHtcbiAgICAgICAgICAgICAgICBjb25maWcub25yZWNvbm5lY3RpbmcoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChmb3JjaW5nRGlzY29ubmVjdGlvbikge1xuICAgICAgICAgICAgcmVjb25uZWN0VG9OZXdVcmkobWF4UmV0cmllcywgbnVtUmV0cmllcywgd3NVcmkpO1xuXG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBpZiAoY29uZmlnLm5ld1dzVXJpT25SZWNvbm5lY3Rpb24pIHtcbiAgICAgICAgICAgICAgICBjb25maWcubmV3V3NVcmlPblJlY29ubmVjdGlvbihmdW5jdGlvbihlcnJvciwgbmV3V3NVcmkpIHtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIExvZ2dlci5kZWJ1ZyhlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlY29ubmVjdFRvU2FtZVVyaShtYXhSZXRyaWVzLCBudW1SZXRyaWVzICsgMSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9LCBSRVRSWV9USU1FX01TKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlY29ubmVjdFRvTmV3VXJpKG1heFJldHJpZXMsIG51bVJldHJpZXMsIG5ld1dzVXJpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJlY29ubmVjdFRvTmV3VXJpKG1heFJldHJpZXMsIG51bVJldHJpZXMsIHdzVXJpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIFRPRE8gVGVzdCByZXRyaWVzLiBIb3cgdG8gZm9yY2Ugbm90IGNvbm5lY3Rpb24/XG4gICAgZnVuY3Rpb24gcmVjb25uZWN0VG9OZXdVcmkobWF4UmV0cmllcywgbnVtUmV0cmllcywgcmVjb25uZWN0V3NVcmkpIHtcbiAgICAgICAgTG9nZ2VyLmRlYnVnKFwiUmVjb25uZWN0aW9uIGF0dGVtcHQgI1wiICsgbnVtUmV0cmllcyk7XG5cbiAgICAgICAgd3MuY2xvc2UoKTtcblxuICAgICAgICB3c1VyaSA9IHJlY29ubmVjdFdzVXJpIHx8IHdzVXJpO1xuXG4gICAgICAgIHZhciBuZXdXcztcbiAgICAgICAgaWYgKHVzZVNvY2tKUykge1xuICAgICAgICAgICAgbmV3V3MgPSBuZXcgU29ja0pTKHdzVXJpKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIG5ld1dzID0gbmV3IFdlYlNvY2tldCh3c1VyaSk7XG4gICAgICAgIH1cblxuICAgICAgICBuZXdXcy5vbm9wZW4gPSBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIExvZ2dlci5kZWJ1ZyhcIlJlY29ubmVjdGVkIGFmdGVyIFwiICsgbnVtUmV0cmllcyArIFwiIGF0dGVtcHRzLi4uXCIpO1xuICAgICAgICAgICAgbG9nQ29ubmVjdGVkKG5ld1dzLCB3c1VyaSk7XG4gICAgICAgICAgICByZWNvbm5lY3RpbmcgPSBmYWxzZTtcbiAgICAgICAgICAgIHJlZ2lzdGVyTWVzc2FnZUhhbmRsZXIoKTtcbiAgICAgICAgICAgIGlmIChjb25maWcub25yZWNvbm5lY3RlZCgpKSB7XG4gICAgICAgICAgICAgICAgY29uZmlnLm9ucmVjb25uZWN0ZWQoKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgbmV3V3Mub25jbG9zZSA9IHJlY29ubmVjdGlvbk9uQ2xvc2U7XG4gICAgICAgIH07XG5cbiAgICAgICAgdmFyIG9uRXJyb3JPckNsb3NlID0gZnVuY3Rpb24oZXJyb3IpIHtcbiAgICAgICAgICAgIExvZ2dlci53YXJuKFwiUmVjb25uZWN0aW9uIGVycm9yOiBcIiwgZXJyb3IpO1xuXG4gICAgICAgICAgICBpZiAobnVtUmV0cmllcyA9PT0gbWF4UmV0cmllcykge1xuICAgICAgICAgICAgICAgIGlmIChjb25maWcub25kaXNjb25uZWN0KSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbmZpZy5vbmRpc2Nvbm5lY3QoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlY29ubmVjdFRvU2FtZVVyaShtYXhSZXRyaWVzLCBudW1SZXRyaWVzICsgMSk7XG4gICAgICAgICAgICAgICAgfSwgUkVUUllfVElNRV9NUyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG5cbiAgICAgICAgbmV3V3Mub25lcnJvciA9IG9uRXJyb3JPckNsb3NlO1xuXG4gICAgICAgIHdzID0gbmV3V3M7XG4gICAgfVxuXG4gICAgdGhpcy5jbG9zZSA9IGZ1bmN0aW9uKCkge1xuICAgICAgICBjbG9zaW5nID0gdHJ1ZTtcbiAgICAgICAgd3MuY2xvc2UoKTtcbiAgICB9O1xuXG5cbiAgICAvLyBUaGlzIG1ldGhvZCBpcyBvbmx5IGZvciB0ZXN0aW5nXG4gICAgdGhpcy5mb3JjZUNsb3NlID0gZnVuY3Rpb24obWlsbGlzKSB7XG4gICAgICAgIExvZ2dlci5kZWJ1ZyhcIlRlc3Rpbmc6IEZvcmNlIFdlYlNvY2tldCBjbG9zZVwiKTtcblxuICAgICAgICBpZiAobWlsbGlzKSB7XG4gICAgICAgICAgICBMb2dnZXIuZGVidWcoXCJUZXN0aW5nOiBDaGFuZ2Ugd3NVcmkgZm9yIFwiICsgbWlsbGlzICsgXCIgbWlsbGlzIHRvIHNpbXVsYXRlIG5ldCBmYWlsdXJlXCIpO1xuICAgICAgICAgICAgdmFyIGdvb2RXc1VyaSA9IHdzVXJpO1xuICAgICAgICAgICAgd3NVcmkgPSBcIndzczovLzIxLjIzNC4xMi4zNC40OjQ0My9cIjtcblxuICAgICAgICAgICAgZm9yY2luZ0Rpc2Nvbm5lY3Rpb24gPSB0cnVlO1xuXG4gICAgICAgICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgIExvZ2dlci5kZWJ1ZyhcIlRlc3Rpbmc6IFJlY292ZXIgZ29vZCB3c1VyaSBcIiArIGdvb2RXc1VyaSk7XG4gICAgICAgICAgICAgICAgd3NVcmkgPSBnb29kV3NVcmk7XG5cbiAgICAgICAgICAgICAgICBmb3JjaW5nRGlzY29ubmVjdGlvbiA9IGZhbHNlO1xuXG4gICAgICAgICAgICB9LCBtaWxsaXMpO1xuICAgICAgICB9XG5cbiAgICAgICAgd3MuY2xvc2UoKTtcbiAgICB9O1xuXG4gICAgdGhpcy5yZWNvbm5lY3RXcyA9IGZ1bmN0aW9uKCkge1xuICAgICAgICBMb2dnZXIuZGVidWcoXCJyZWNvbm5lY3RXc1wiKTtcbiAgICAgICAgcmVjb25uZWN0VG9TYW1lVXJpKE1BWF9SRVRSSUVTLCAxKTtcbiAgICB9O1xuXG4gICAgdGhpcy5zZW5kID0gZnVuY3Rpb24obWVzc2FnZSkge1xuICAgICAgICB3cy5zZW5kKG1lc3NhZ2UpO1xuICAgIH07XG5cbiAgICB0aGlzLmFkZEV2ZW50TGlzdGVuZXIgPSBmdW5jdGlvbih0eXBlLCBjYWxsYmFjaykge1xuICAgICAgICByZWdpc3Rlck1lc3NhZ2VIYW5kbGVyID0gZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICB3cy5hZGRFdmVudExpc3RlbmVyKHR5cGUsIGNhbGxiYWNrKTtcbiAgICAgICAgfTtcblxuICAgICAgICByZWdpc3Rlck1lc3NhZ2VIYW5kbGVyKCk7XG4gICAgfTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBXZWJTb2NrZXRXaXRoUmVjb25uZWN0aW9uO1xuIiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNCBLdXJlbnRvIChodHRwOi8va3VyZW50by5vcmcvKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cblxudmFyIGRlZmluZVByb3BlcnR5X0lFOCA9IGZhbHNlXG5pZihPYmplY3QuZGVmaW5lUHJvcGVydHkpXG57XG4gIHRyeVxuICB7XG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHt9LCBcInhcIiwge30pO1xuICB9XG4gIGNhdGNoKGUpXG4gIHtcbiAgICBkZWZpbmVQcm9wZXJ0eV9JRTggPSB0cnVlXG4gIH1cbn1cblxuLy8gaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvSmF2YVNjcmlwdC9SZWZlcmVuY2UvR2xvYmFsX09iamVjdHMvRnVuY3Rpb24vYmluZFxuaWYgKCFGdW5jdGlvbi5wcm90b3R5cGUuYmluZCkge1xuICBGdW5jdGlvbi5wcm90b3R5cGUuYmluZCA9IGZ1bmN0aW9uKG9UaGlzKSB7XG4gICAgaWYgKHR5cGVvZiB0aGlzICE9PSAnZnVuY3Rpb24nKSB7XG4gICAgICAvLyBjbG9zZXN0IHRoaW5nIHBvc3NpYmxlIHRvIHRoZSBFQ01BU2NyaXB0IDVcbiAgICAgIC8vIGludGVybmFsIElzQ2FsbGFibGUgZnVuY3Rpb25cbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ0Z1bmN0aW9uLnByb3RvdHlwZS5iaW5kIC0gd2hhdCBpcyB0cnlpbmcgdG8gYmUgYm91bmQgaXMgbm90IGNhbGxhYmxlJyk7XG4gICAgfVxuXG4gICAgdmFyIGFBcmdzICAgPSBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMsIDEpLFxuICAgICAgICBmVG9CaW5kID0gdGhpcyxcbiAgICAgICAgZk5PUCAgICA9IGZ1bmN0aW9uKCkge30sXG4gICAgICAgIGZCb3VuZCAgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgICByZXR1cm4gZlRvQmluZC5hcHBseSh0aGlzIGluc3RhbmNlb2YgZk5PUCAmJiBvVGhpc1xuICAgICAgICAgICAgICAgICA/IHRoaXNcbiAgICAgICAgICAgICAgICAgOiBvVGhpcyxcbiAgICAgICAgICAgICAgICAgYUFyZ3MuY29uY2F0KEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3VtZW50cykpKTtcbiAgICAgICAgfTtcblxuICAgIGZOT1AucHJvdG90eXBlID0gdGhpcy5wcm90b3R5cGU7XG4gICAgZkJvdW5kLnByb3RvdHlwZSA9IG5ldyBmTk9QKCk7XG5cbiAgICByZXR1cm4gZkJvdW5kO1xuICB9O1xufVxuXG5cbnZhciBFdmVudEVtaXR0ZXIgPSByZXF1aXJlKCdldmVudHMnKS5FdmVudEVtaXR0ZXI7XG5cbnZhciBpbmhlcml0cyA9IHJlcXVpcmUoJ2luaGVyaXRzJyk7XG5cbnZhciBwYWNrZXJzID0gcmVxdWlyZSgnLi9wYWNrZXJzJyk7XG52YXIgTWFwcGVyID0gcmVxdWlyZSgnLi9NYXBwZXInKTtcblxuXG52YXIgQkFTRV9USU1FT1VUID0gNTAwMDtcblxuXG5mdW5jdGlvbiB1bmlmeVJlc3BvbnNlTWV0aG9kcyhyZXNwb25zZU1ldGhvZHMpXG57XG4gIGlmKCFyZXNwb25zZU1ldGhvZHMpIHJldHVybiB7fTtcblxuICBmb3IodmFyIGtleSBpbiByZXNwb25zZU1ldGhvZHMpXG4gIHtcbiAgICB2YXIgdmFsdWUgPSByZXNwb25zZU1ldGhvZHNba2V5XTtcblxuICAgIGlmKHR5cGVvZiB2YWx1ZSA9PSAnc3RyaW5nJylcbiAgICAgIHJlc3BvbnNlTWV0aG9kc1trZXldID1cbiAgICAgIHtcbiAgICAgICAgcmVzcG9uc2U6IHZhbHVlXG4gICAgICB9XG4gIH07XG5cbiAgcmV0dXJuIHJlc3BvbnNlTWV0aG9kcztcbn07XG5cbmZ1bmN0aW9uIHVuaWZ5VHJhbnNwb3J0KHRyYW5zcG9ydClcbntcbiAgaWYoIXRyYW5zcG9ydCkgcmV0dXJuO1xuXG4gIC8vIFRyYW5zcG9ydCBhcyBhIGZ1bmN0aW9uXG4gIGlmKHRyYW5zcG9ydCBpbnN0YW5jZW9mIEZ1bmN0aW9uKVxuICAgIHJldHVybiB7c2VuZDogdHJhbnNwb3J0fTtcblxuICAvLyBXZWJTb2NrZXQgJiBEYXRhQ2hhbm5lbFxuICBpZih0cmFuc3BvcnQuc2VuZCBpbnN0YW5jZW9mIEZ1bmN0aW9uKVxuICAgIHJldHVybiB0cmFuc3BvcnQ7XG5cbiAgLy8gTWVzc2FnZSBBUEkgKEludGVyLXdpbmRvdyAmIFdlYldvcmtlcilcbiAgaWYodHJhbnNwb3J0LnBvc3RNZXNzYWdlIGluc3RhbmNlb2YgRnVuY3Rpb24pXG4gIHtcbiAgICB0cmFuc3BvcnQuc2VuZCA9IHRyYW5zcG9ydC5wb3N0TWVzc2FnZTtcbiAgICByZXR1cm4gdHJhbnNwb3J0O1xuICB9XG5cbiAgLy8gU3RyZWFtIEFQSVxuICBpZih0cmFuc3BvcnQud3JpdGUgaW5zdGFuY2VvZiBGdW5jdGlvbilcbiAge1xuICAgIHRyYW5zcG9ydC5zZW5kID0gdHJhbnNwb3J0LndyaXRlO1xuICAgIHJldHVybiB0cmFuc3BvcnQ7XG4gIH1cblxuICAvLyBUcmFuc3BvcnRzIHRoYXQgb25seSBjYW4gcmVjZWl2ZSBtZXNzYWdlcywgYnV0IG5vdCBzZW5kXG4gIGlmKHRyYW5zcG9ydC5vbm1lc3NhZ2UgIT09IHVuZGVmaW5lZCkgcmV0dXJuO1xuICBpZih0cmFuc3BvcnQucGF1c2UgaW5zdGFuY2VvZiBGdW5jdGlvbikgcmV0dXJuO1xuXG4gIHRocm93IG5ldyBTeW50YXhFcnJvcihcIlRyYW5zcG9ydCBpcyBub3QgYSBmdW5jdGlvbiBub3IgYSB2YWxpZCBvYmplY3RcIik7XG59O1xuXG5cbi8qKlxuICogUmVwcmVzZW50YXRpb24gb2YgYSBSUEMgbm90aWZpY2F0aW9uXG4gKlxuICogQGNsYXNzXG4gKlxuICogQGNvbnN0cnVjdG9yXG4gKlxuICogQHBhcmFtIHtTdHJpbmd9IG1ldGhvZCAtbWV0aG9kIG9mIHRoZSBub3RpZmljYXRpb25cbiAqIEBwYXJhbSBwYXJhbXMgLSBwYXJhbWV0ZXJzIG9mIHRoZSBub3RpZmljYXRpb25cbiAqL1xuZnVuY3Rpb24gUnBjTm90aWZpY2F0aW9uKG1ldGhvZCwgcGFyYW1zKVxue1xuICBpZihkZWZpbmVQcm9wZXJ0eV9JRTgpXG4gIHtcbiAgICB0aGlzLm1ldGhvZCA9IG1ldGhvZFxuICAgIHRoaXMucGFyYW1zID0gcGFyYW1zXG4gIH1cbiAgZWxzZVxuICB7XG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRoaXMsICdtZXRob2QnLCB7dmFsdWU6IG1ldGhvZCwgZW51bWVyYWJsZTogdHJ1ZX0pO1xuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0aGlzLCAncGFyYW1zJywge3ZhbHVlOiBwYXJhbXMsIGVudW1lcmFibGU6IHRydWV9KTtcbiAgfVxufTtcblxuXG4vKipcbiAqIEBjbGFzc1xuICpcbiAqIEBjb25zdHJ1Y3RvclxuICpcbiAqIEBwYXJhbSB7b2JqZWN0fSBwYWNrZXJcbiAqXG4gKiBAcGFyYW0ge29iamVjdH0gW29wdGlvbnNdXG4gKlxuICogQHBhcmFtIHtvYmplY3R9IFt0cmFuc3BvcnRdXG4gKlxuICogQHBhcmFtIHtGdW5jdGlvbn0gW29uUmVxdWVzdF1cbiAqL1xuZnVuY3Rpb24gUnBjQnVpbGRlcihwYWNrZXIsIG9wdGlvbnMsIHRyYW5zcG9ydCwgb25SZXF1ZXN0KVxue1xuICB2YXIgc2VsZiA9IHRoaXM7XG5cbiAgaWYoIXBhY2tlcilcbiAgICB0aHJvdyBuZXcgU3ludGF4RXJyb3IoJ1BhY2tlciBpcyBub3QgZGVmaW5lZCcpO1xuXG4gIGlmKCFwYWNrZXIucGFjayB8fCAhcGFja2VyLnVucGFjaylcbiAgICB0aHJvdyBuZXcgU3ludGF4RXJyb3IoJ1BhY2tlciBpcyBpbnZhbGlkJyk7XG5cbiAgdmFyIHJlc3BvbnNlTWV0aG9kcyA9IHVuaWZ5UmVzcG9uc2VNZXRob2RzKHBhY2tlci5yZXNwb25zZU1ldGhvZHMpO1xuXG5cbiAgaWYob3B0aW9ucyBpbnN0YW5jZW9mIEZ1bmN0aW9uKVxuICB7XG4gICAgaWYodHJhbnNwb3J0ICE9IHVuZGVmaW5lZClcbiAgICAgIHRocm93IG5ldyBTeW50YXhFcnJvcihcIlRoZXJlIGNhbid0IGJlIHBhcmFtZXRlcnMgYWZ0ZXIgb25SZXF1ZXN0XCIpO1xuXG4gICAgb25SZXF1ZXN0ID0gb3B0aW9ucztcbiAgICB0cmFuc3BvcnQgPSB1bmRlZmluZWQ7XG4gICAgb3B0aW9ucyAgID0gdW5kZWZpbmVkO1xuICB9O1xuXG4gIGlmKG9wdGlvbnMgJiYgb3B0aW9ucy5zZW5kIGluc3RhbmNlb2YgRnVuY3Rpb24pXG4gIHtcbiAgICBpZih0cmFuc3BvcnQgJiYgISh0cmFuc3BvcnQgaW5zdGFuY2VvZiBGdW5jdGlvbikpXG4gICAgICB0aHJvdyBuZXcgU3ludGF4RXJyb3IoXCJPbmx5IGEgZnVuY3Rpb24gY2FuIGJlIGFmdGVyIHRyYW5zcG9ydFwiKTtcblxuICAgIG9uUmVxdWVzdCA9IHRyYW5zcG9ydDtcbiAgICB0cmFuc3BvcnQgPSBvcHRpb25zO1xuICAgIG9wdGlvbnMgICA9IHVuZGVmaW5lZDtcbiAgfTtcblxuICBpZih0cmFuc3BvcnQgaW5zdGFuY2VvZiBGdW5jdGlvbilcbiAge1xuICAgIGlmKG9uUmVxdWVzdCAhPSB1bmRlZmluZWQpXG4gICAgICB0aHJvdyBuZXcgU3ludGF4RXJyb3IoXCJUaGVyZSBjYW4ndCBiZSBwYXJhbWV0ZXJzIGFmdGVyIG9uUmVxdWVzdFwiKTtcblxuICAgIG9uUmVxdWVzdCA9IHRyYW5zcG9ydDtcbiAgICB0cmFuc3BvcnQgPSB1bmRlZmluZWQ7XG4gIH07XG5cbiAgaWYodHJhbnNwb3J0ICYmIHRyYW5zcG9ydC5zZW5kIGluc3RhbmNlb2YgRnVuY3Rpb24pXG4gICAgaWYob25SZXF1ZXN0ICYmICEob25SZXF1ZXN0IGluc3RhbmNlb2YgRnVuY3Rpb24pKVxuICAgICAgdGhyb3cgbmV3IFN5bnRheEVycm9yKFwiT25seSBhIGZ1bmN0aW9uIGNhbiBiZSBhZnRlciB0cmFuc3BvcnRcIik7XG5cbiAgb3B0aW9ucyA9IG9wdGlvbnMgfHwge307XG5cblxuICBFdmVudEVtaXR0ZXIuY2FsbCh0aGlzKTtcblxuICBpZihvblJlcXVlc3QpXG4gICAgdGhpcy5vbigncmVxdWVzdCcsIG9uUmVxdWVzdCk7XG5cblxuICBpZihkZWZpbmVQcm9wZXJ0eV9JRTgpXG4gICAgdGhpcy5wZWVySUQgPSBvcHRpb25zLnBlZXJJRFxuICBlbHNlXG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRoaXMsICdwZWVySUQnLCB7dmFsdWU6IG9wdGlvbnMucGVlcklEfSk7XG5cbiAgdmFyIG1heF9yZXRyaWVzID0gb3B0aW9ucy5tYXhfcmV0cmllcyB8fCAwO1xuXG5cbiAgZnVuY3Rpb24gdHJhbnNwb3J0TWVzc2FnZShldmVudClcbiAge1xuICAgIHNlbGYuZGVjb2RlKGV2ZW50LmRhdGEgfHwgZXZlbnQpO1xuICB9O1xuXG4gIHRoaXMuZ2V0VHJhbnNwb3J0ID0gZnVuY3Rpb24oKVxuICB7XG4gICAgcmV0dXJuIHRyYW5zcG9ydDtcbiAgfVxuICB0aGlzLnNldFRyYW5zcG9ydCA9IGZ1bmN0aW9uKHZhbHVlKVxuICB7XG4gICAgLy8gUmVtb3ZlIGxpc3RlbmVyIGZyb20gb2xkIHRyYW5zcG9ydFxuICAgIGlmKHRyYW5zcG9ydClcbiAgICB7XG4gICAgICAvLyBXM0MgdHJhbnNwb3J0c1xuICAgICAgaWYodHJhbnNwb3J0LnJlbW92ZUV2ZW50TGlzdGVuZXIpXG4gICAgICAgIHRyYW5zcG9ydC5yZW1vdmVFdmVudExpc3RlbmVyKCdtZXNzYWdlJywgdHJhbnNwb3J0TWVzc2FnZSk7XG5cbiAgICAgIC8vIE5vZGUuanMgU3RyZWFtcyBBUElcbiAgICAgIGVsc2UgaWYodHJhbnNwb3J0LnJlbW92ZUxpc3RlbmVyKVxuICAgICAgICB0cmFuc3BvcnQucmVtb3ZlTGlzdGVuZXIoJ2RhdGEnLCB0cmFuc3BvcnRNZXNzYWdlKTtcbiAgICB9O1xuXG4gICAgLy8gU2V0IGxpc3RlbmVyIG9uIG5ldyB0cmFuc3BvcnRcbiAgICBpZih2YWx1ZSlcbiAgICB7XG4gICAgICAvLyBXM0MgdHJhbnNwb3J0c1xuICAgICAgaWYodmFsdWUuYWRkRXZlbnRMaXN0ZW5lcilcbiAgICAgICAgdmFsdWUuYWRkRXZlbnRMaXN0ZW5lcignbWVzc2FnZScsIHRyYW5zcG9ydE1lc3NhZ2UpO1xuXG4gICAgICAvLyBOb2RlLmpzIFN0cmVhbXMgQVBJXG4gICAgICBlbHNlIGlmKHZhbHVlLmFkZExpc3RlbmVyKVxuICAgICAgICB2YWx1ZS5hZGRMaXN0ZW5lcignZGF0YScsIHRyYW5zcG9ydE1lc3NhZ2UpO1xuICAgIH07XG5cbiAgICB0cmFuc3BvcnQgPSB1bmlmeVRyYW5zcG9ydCh2YWx1ZSk7XG4gIH1cblxuICBpZighZGVmaW5lUHJvcGVydHlfSUU4KVxuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0aGlzLCAndHJhbnNwb3J0JyxcbiAgICB7XG4gICAgICBnZXQ6IHRoaXMuZ2V0VHJhbnNwb3J0LmJpbmQodGhpcyksXG4gICAgICBzZXQ6IHRoaXMuc2V0VHJhbnNwb3J0LmJpbmQodGhpcylcbiAgICB9KVxuXG4gIHRoaXMuc2V0VHJhbnNwb3J0KHRyYW5zcG9ydCk7XG5cblxuICB2YXIgcmVxdWVzdF90aW1lb3V0ICAgICAgPSBvcHRpb25zLnJlcXVlc3RfdGltZW91dCAgICAgIHx8IEJBU0VfVElNRU9VVDtcbiAgdmFyIHBpbmdfcmVxdWVzdF90aW1lb3V0ID0gb3B0aW9ucy5waW5nX3JlcXVlc3RfdGltZW91dCB8fCByZXF1ZXN0X3RpbWVvdXQ7XG4gIHZhciByZXNwb25zZV90aW1lb3V0ICAgICA9IG9wdGlvbnMucmVzcG9uc2VfdGltZW91dCAgICAgfHwgQkFTRV9USU1FT1VUO1xuICB2YXIgZHVwbGljYXRlc190aW1lb3V0ICAgPSBvcHRpb25zLmR1cGxpY2F0ZXNfdGltZW91dCAgIHx8IEJBU0VfVElNRU9VVDtcblxuXG4gIHZhciByZXF1ZXN0SUQgPSAwO1xuXG4gIHZhciByZXF1ZXN0cyAgPSBuZXcgTWFwcGVyKCk7XG4gIHZhciByZXNwb25zZXMgPSBuZXcgTWFwcGVyKCk7XG4gIHZhciBwcm9jZXNzZWRSZXNwb25zZXMgPSBuZXcgTWFwcGVyKCk7XG5cbiAgdmFyIG1lc3NhZ2UyS2V5ID0ge307XG5cblxuICAvKipcbiAgICogU3RvcmUgdGhlIHJlc3BvbnNlIHRvIHByZXZlbnQgdG8gcHJvY2VzcyBkdXBsaWNhdGUgcmVxdWVzdCBsYXRlclxuICAgKi9cbiAgZnVuY3Rpb24gc3RvcmVSZXNwb25zZShtZXNzYWdlLCBpZCwgZGVzdClcbiAge1xuICAgIHZhciByZXNwb25zZSA9XG4gICAge1xuICAgICAgbWVzc2FnZTogbWVzc2FnZSxcbiAgICAgIC8qKiBUaW1lb3V0IHRvIGF1dG8tY2xlYW4gb2xkIHJlc3BvbnNlcyAqL1xuICAgICAgdGltZW91dDogc2V0VGltZW91dChmdW5jdGlvbigpXG4gICAgICB7XG4gICAgICAgIHJlc3BvbnNlcy5yZW1vdmUoaWQsIGRlc3QpO1xuICAgICAgfSxcbiAgICAgIHJlc3BvbnNlX3RpbWVvdXQpXG4gICAgfTtcblxuICAgIHJlc3BvbnNlcy5zZXQocmVzcG9uc2UsIGlkLCBkZXN0KTtcbiAgfTtcblxuICAvKipcbiAgICogU3RvcmUgdGhlIHJlc3BvbnNlIHRvIGlnbm9yZSBkdXBsaWNhdGVkIG1lc3NhZ2VzIGxhdGVyXG4gICAqL1xuICBmdW5jdGlvbiBzdG9yZVByb2Nlc3NlZFJlc3BvbnNlKGFjaywgZnJvbSlcbiAge1xuICAgIHZhciB0aW1lb3V0ID0gc2V0VGltZW91dChmdW5jdGlvbigpXG4gICAge1xuICAgICAgcHJvY2Vzc2VkUmVzcG9uc2VzLnJlbW92ZShhY2ssIGZyb20pO1xuICAgIH0sXG4gICAgZHVwbGljYXRlc190aW1lb3V0KTtcblxuICAgIHByb2Nlc3NlZFJlc3BvbnNlcy5zZXQodGltZW91dCwgYWNrLCBmcm9tKTtcbiAgfTtcblxuXG4gIC8qKlxuICAgKiBSZXByZXNlbnRhdGlvbiBvZiBhIFJQQyByZXF1ZXN0XG4gICAqXG4gICAqIEBjbGFzc1xuICAgKiBAZXh0ZW5kcyBScGNOb3RpZmljYXRpb25cbiAgICpcbiAgICogQGNvbnN0cnVjdG9yXG4gICAqXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBtZXRob2QgLW1ldGhvZCBvZiB0aGUgbm90aWZpY2F0aW9uXG4gICAqIEBwYXJhbSBwYXJhbXMgLSBwYXJhbWV0ZXJzIG9mIHRoZSBub3RpZmljYXRpb25cbiAgICogQHBhcmFtIHtJbnRlZ2VyfSBpZCAtIGlkZW50aWZpZXIgb2YgdGhlIHJlcXVlc3RcbiAgICogQHBhcmFtIFtmcm9tXSAtIHNvdXJjZSBvZiB0aGUgbm90aWZpY2F0aW9uXG4gICAqL1xuICBmdW5jdGlvbiBScGNSZXF1ZXN0KG1ldGhvZCwgcGFyYW1zLCBpZCwgZnJvbSwgdHJhbnNwb3J0KVxuICB7XG4gICAgUnBjTm90aWZpY2F0aW9uLmNhbGwodGhpcywgbWV0aG9kLCBwYXJhbXMpO1xuXG4gICAgdGhpcy5nZXRUcmFuc3BvcnQgPSBmdW5jdGlvbigpXG4gICAge1xuICAgICAgcmV0dXJuIHRyYW5zcG9ydDtcbiAgICB9XG4gICAgdGhpcy5zZXRUcmFuc3BvcnQgPSBmdW5jdGlvbih2YWx1ZSlcbiAgICB7XG4gICAgICB0cmFuc3BvcnQgPSB1bmlmeVRyYW5zcG9ydCh2YWx1ZSk7XG4gICAgfVxuXG4gICAgaWYoIWRlZmluZVByb3BlcnR5X0lFOClcbiAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0aGlzLCAndHJhbnNwb3J0JyxcbiAgICAgIHtcbiAgICAgICAgZ2V0OiB0aGlzLmdldFRyYW5zcG9ydC5iaW5kKHRoaXMpLFxuICAgICAgICBzZXQ6IHRoaXMuc2V0VHJhbnNwb3J0LmJpbmQodGhpcylcbiAgICAgIH0pXG5cbiAgICB2YXIgcmVzcG9uc2UgPSByZXNwb25zZXMuZ2V0KGlkLCBmcm9tKTtcblxuICAgIC8qKlxuICAgICAqIEBjb25zdGFudCB7Qm9vbGVhbn0gZHVwbGljYXRlZFxuICAgICAqL1xuICAgIGlmKCEodHJhbnNwb3J0IHx8IHNlbGYuZ2V0VHJhbnNwb3J0KCkpKVxuICAgIHtcbiAgICAgIGlmKGRlZmluZVByb3BlcnR5X0lFOClcbiAgICAgICAgdGhpcy5kdXBsaWNhdGVkID0gQm9vbGVhbihyZXNwb25zZSlcbiAgICAgIGVsc2VcbiAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRoaXMsICdkdXBsaWNhdGVkJyxcbiAgICAgICAge1xuICAgICAgICAgIHZhbHVlOiBCb29sZWFuKHJlc3BvbnNlKVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICB2YXIgcmVzcG9uc2VNZXRob2QgPSByZXNwb25zZU1ldGhvZHNbbWV0aG9kXTtcblxuICAgIHRoaXMucGFjayA9IHBhY2tlci5wYWNrLmJpbmQocGFja2VyLCB0aGlzLCBpZClcblxuICAgIC8qKlxuICAgICAqIEdlbmVyYXRlIGEgcmVzcG9uc2UgdG8gdGhpcyByZXF1ZXN0XG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0Vycm9yfSBbZXJyb3JdXG4gICAgICogQHBhcmFtIHsqfSBbcmVzdWx0XVxuICAgICAqXG4gICAgICogQHJldHVybnMge3N0cmluZ31cbiAgICAgKi9cbiAgICB0aGlzLnJlcGx5ID0gZnVuY3Rpb24oZXJyb3IsIHJlc3VsdCwgdHJhbnNwb3J0KVxuICAgIHtcbiAgICAgIC8vIEZpeCBvcHRpb25hbCBwYXJhbWV0ZXJzXG4gICAgICBpZihlcnJvciBpbnN0YW5jZW9mIEZ1bmN0aW9uIHx8IGVycm9yICYmIGVycm9yLnNlbmQgaW5zdGFuY2VvZiBGdW5jdGlvbilcbiAgICAgIHtcbiAgICAgICAgaWYocmVzdWx0ICE9IHVuZGVmaW5lZClcbiAgICAgICAgICB0aHJvdyBuZXcgU3ludGF4RXJyb3IoXCJUaGVyZSBjYW4ndCBiZSBwYXJhbWV0ZXJzIGFmdGVyIGNhbGxiYWNrXCIpO1xuXG4gICAgICAgIHRyYW5zcG9ydCA9IGVycm9yO1xuICAgICAgICByZXN1bHQgPSBudWxsO1xuICAgICAgICBlcnJvciA9IHVuZGVmaW5lZDtcbiAgICAgIH1cblxuICAgICAgZWxzZSBpZihyZXN1bHQgaW5zdGFuY2VvZiBGdW5jdGlvblxuICAgICAgfHwgcmVzdWx0ICYmIHJlc3VsdC5zZW5kIGluc3RhbmNlb2YgRnVuY3Rpb24pXG4gICAgICB7XG4gICAgICAgIGlmKHRyYW5zcG9ydCAhPSB1bmRlZmluZWQpXG4gICAgICAgICAgdGhyb3cgbmV3IFN5bnRheEVycm9yKFwiVGhlcmUgY2FuJ3QgYmUgcGFyYW1ldGVycyBhZnRlciBjYWxsYmFja1wiKTtcblxuICAgICAgICB0cmFuc3BvcnQgPSByZXN1bHQ7XG4gICAgICAgIHJlc3VsdCA9IG51bGw7XG4gICAgICB9O1xuXG4gICAgICB0cmFuc3BvcnQgPSB1bmlmeVRyYW5zcG9ydCh0cmFuc3BvcnQpO1xuXG4gICAgICAvLyBEdXBsaWNhdGVkIHJlcXVlc3QsIHJlbW92ZSBvbGQgcmVzcG9uc2UgdGltZW91dFxuICAgICAgaWYocmVzcG9uc2UpXG4gICAgICAgIGNsZWFyVGltZW91dChyZXNwb25zZS50aW1lb3V0KTtcblxuICAgICAgaWYoZnJvbSAhPSB1bmRlZmluZWQpXG4gICAgICB7XG4gICAgICAgIGlmKGVycm9yKVxuICAgICAgICAgIGVycm9yLmRlc3QgPSBmcm9tO1xuXG4gICAgICAgIGlmKHJlc3VsdClcbiAgICAgICAgICByZXN1bHQuZGVzdCA9IGZyb207XG4gICAgICB9O1xuXG4gICAgICB2YXIgbWVzc2FnZTtcblxuICAgICAgLy8gTmV3IHJlcXVlc3Qgb3Igb3ZlcnJpZGVuIG9uZSwgY3JlYXRlIG5ldyByZXNwb25zZSB3aXRoIHByb3ZpZGVkIGRhdGFcbiAgICAgIGlmKGVycm9yIHx8IHJlc3VsdCAhPSB1bmRlZmluZWQpXG4gICAgICB7XG4gICAgICAgIGlmKHNlbGYucGVlcklEICE9IHVuZGVmaW5lZClcbiAgICAgICAge1xuICAgICAgICAgIGlmKGVycm9yKVxuICAgICAgICAgICAgZXJyb3IuZnJvbSA9IHNlbGYucGVlcklEO1xuICAgICAgICAgIGVsc2VcbiAgICAgICAgICAgIHJlc3VsdC5mcm9tID0gc2VsZi5wZWVySUQ7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBQcm90b2NvbCBpbmRpY2F0ZXMgdGhhdCByZXNwb25zZXMgaGFzIG93biByZXF1ZXN0IG1ldGhvZHNcbiAgICAgICAgaWYocmVzcG9uc2VNZXRob2QpXG4gICAgICAgIHtcbiAgICAgICAgICBpZihyZXNwb25zZU1ldGhvZC5lcnJvciA9PSB1bmRlZmluZWQgJiYgZXJyb3IpXG4gICAgICAgICAgICBtZXNzYWdlID1cbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgZXJyb3I6IGVycm9yXG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgZWxzZVxuICAgICAgICAgIHtcbiAgICAgICAgICAgIHZhciBtZXRob2QgPSBlcnJvclxuICAgICAgICAgICAgICAgICAgICAgICA/IHJlc3BvbnNlTWV0aG9kLmVycm9yXG4gICAgICAgICAgICAgICAgICAgICAgIDogcmVzcG9uc2VNZXRob2QucmVzcG9uc2U7XG5cbiAgICAgICAgICAgIG1lc3NhZ2UgPVxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICBtZXRob2Q6IG1ldGhvZCxcbiAgICAgICAgICAgICAgcGFyYW1zOiBlcnJvciB8fCByZXN1bHRcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGVsc2VcbiAgICAgICAgICBtZXNzYWdlID1cbiAgICAgICAgICB7XG4gICAgICAgICAgICBlcnJvcjogIGVycm9yLFxuICAgICAgICAgICAgcmVzdWx0OiByZXN1bHRcbiAgICAgICAgICB9O1xuXG4gICAgICAgIG1lc3NhZ2UgPSBwYWNrZXIucGFjayhtZXNzYWdlLCBpZCk7XG4gICAgICB9XG5cbiAgICAgIC8vIER1cGxpY2F0ZSAmIG5vdC1vdmVycmlkZW4gcmVxdWVzdCwgcmUtc2VuZCBvbGQgcmVzcG9uc2VcbiAgICAgIGVsc2UgaWYocmVzcG9uc2UpXG4gICAgICAgIG1lc3NhZ2UgPSByZXNwb25zZS5tZXNzYWdlO1xuXG4gICAgICAvLyBOZXcgZW1wdHkgcmVwbHksIHJlc3BvbnNlIG51bGwgdmFsdWVcbiAgICAgIGVsc2VcbiAgICAgICAgbWVzc2FnZSA9IHBhY2tlci5wYWNrKHtyZXN1bHQ6IG51bGx9LCBpZCk7XG5cbiAgICAgIC8vIFN0b3JlIHRoZSByZXNwb25zZSB0byBwcmV2ZW50IHRvIHByb2Nlc3MgYSBkdXBsaWNhdGVkIHJlcXVlc3QgbGF0ZXJcbiAgICAgIHN0b3JlUmVzcG9uc2UobWVzc2FnZSwgaWQsIGZyb20pO1xuXG4gICAgICAvLyBSZXR1cm4gdGhlIHN0b3JlZCByZXNwb25zZSBzbyBpdCBjYW4gYmUgZGlyZWN0bHkgc2VuZCBiYWNrXG4gICAgICB0cmFuc3BvcnQgPSB0cmFuc3BvcnQgfHwgdGhpcy5nZXRUcmFuc3BvcnQoKSB8fCBzZWxmLmdldFRyYW5zcG9ydCgpO1xuXG4gICAgICBpZih0cmFuc3BvcnQpXG4gICAgICAgIHJldHVybiB0cmFuc3BvcnQuc2VuZChtZXNzYWdlKTtcblxuICAgICAgcmV0dXJuIG1lc3NhZ2U7XG4gICAgfVxuICB9O1xuICBpbmhlcml0cyhScGNSZXF1ZXN0LCBScGNOb3RpZmljYXRpb24pO1xuXG5cbiAgZnVuY3Rpb24gY2FuY2VsKG1lc3NhZ2UpXG4gIHtcbiAgICB2YXIga2V5ID0gbWVzc2FnZTJLZXlbbWVzc2FnZV07XG4gICAgaWYoIWtleSkgcmV0dXJuO1xuXG4gICAgZGVsZXRlIG1lc3NhZ2UyS2V5W21lc3NhZ2VdO1xuXG4gICAgdmFyIHJlcXVlc3QgPSByZXF1ZXN0cy5wb3Aoa2V5LmlkLCBrZXkuZGVzdCk7XG4gICAgaWYoIXJlcXVlc3QpIHJldHVybjtcblxuICAgIGNsZWFyVGltZW91dChyZXF1ZXN0LnRpbWVvdXQpO1xuXG4gICAgLy8gU3RhcnQgZHVwbGljYXRlZCByZXNwb25zZXMgdGltZW91dFxuICAgIHN0b3JlUHJvY2Vzc2VkUmVzcG9uc2Uoa2V5LmlkLCBrZXkuZGVzdCk7XG4gIH07XG5cbiAgLyoqXG4gICAqIEFsbG93IHRvIGNhbmNlbCBhIHJlcXVlc3QgYW5kIGRvbid0IHdhaXQgZm9yIGEgcmVzcG9uc2VcbiAgICpcbiAgICogSWYgYG1lc3NhZ2VgIGlzIG5vdCBnaXZlbiwgY2FuY2VsIGFsbCB0aGUgcmVxdWVzdFxuICAgKi9cbiAgdGhpcy5jYW5jZWwgPSBmdW5jdGlvbihtZXNzYWdlKVxuICB7XG4gICAgaWYobWVzc2FnZSkgcmV0dXJuIGNhbmNlbChtZXNzYWdlKTtcblxuICAgIGZvcih2YXIgbWVzc2FnZSBpbiBtZXNzYWdlMktleSlcbiAgICAgIGNhbmNlbChtZXNzYWdlKTtcbiAgfTtcblxuXG4gIHRoaXMuY2xvc2UgPSBmdW5jdGlvbigpXG4gIHtcbiAgICAvLyBQcmV2ZW50IHRvIHJlY2VpdmUgbmV3IG1lc3NhZ2VzXG4gICAgdmFyIHRyYW5zcG9ydCA9IHRoaXMuZ2V0VHJhbnNwb3J0KCk7XG4gICAgaWYodHJhbnNwb3J0ICYmIHRyYW5zcG9ydC5jbG9zZSlcbiAgICAgICB0cmFuc3BvcnQuY2xvc2UoKTtcblxuICAgIC8vIFJlcXVlc3QgJiBwcm9jZXNzZWQgcmVzcG9uc2VzXG4gICAgdGhpcy5jYW5jZWwoKTtcblxuICAgIHByb2Nlc3NlZFJlc3BvbnNlcy5mb3JFYWNoKGNsZWFyVGltZW91dCk7XG5cbiAgICAvLyBSZXNwb25zZXNcbiAgICByZXNwb25zZXMuZm9yRWFjaChmdW5jdGlvbihyZXNwb25zZSlcbiAgICB7XG4gICAgICBjbGVhclRpbWVvdXQocmVzcG9uc2UudGltZW91dCk7XG4gICAgfSk7XG4gIH07XG5cblxuICAvKipcbiAgICogR2VuZXJhdGVzIGFuZCBlbmNvZGUgYSBKc29uUlBDIDIuMCBtZXNzYWdlXG4gICAqXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBtZXRob2QgLW1ldGhvZCBvZiB0aGUgbm90aWZpY2F0aW9uXG4gICAqIEBwYXJhbSBwYXJhbXMgLSBwYXJhbWV0ZXJzIG9mIHRoZSBub3RpZmljYXRpb25cbiAgICogQHBhcmFtIFtkZXN0XSAtIGRlc3RpbmF0aW9uIG9mIHRoZSBub3RpZmljYXRpb25cbiAgICogQHBhcmFtIHtvYmplY3R9IFt0cmFuc3BvcnRdIC0gdHJhbnNwb3J0IHdoZXJlIHRvIHNlbmQgdGhlIG1lc3NhZ2VcbiAgICogQHBhcmFtIFtjYWxsYmFja10gLSBmdW5jdGlvbiBjYWxsZWQgd2hlbiBhIHJlc3BvbnNlIHRvIHRoaXMgcmVxdWVzdCBpc1xuICAgKiAgIHJlY2VpdmVkLiBJZiBub3QgZGVmaW5lZCwgYSBub3RpZmljYXRpb24gd2lsbCBiZSBzZW5kIGluc3RlYWRcbiAgICpcbiAgICogQHJldHVybnMge3N0cmluZ30gQSByYXcgSnNvblJQQyAyLjAgcmVxdWVzdCBvciBub3RpZmljYXRpb24gc3RyaW5nXG4gICAqL1xuICB0aGlzLmVuY29kZSA9IGZ1bmN0aW9uKG1ldGhvZCwgcGFyYW1zLCBkZXN0LCB0cmFuc3BvcnQsIGNhbGxiYWNrKVxuICB7XG4gICAgLy8gRml4IG9wdGlvbmFsIHBhcmFtZXRlcnNcbiAgICBpZihwYXJhbXMgaW5zdGFuY2VvZiBGdW5jdGlvbilcbiAgICB7XG4gICAgICBpZihkZXN0ICE9IHVuZGVmaW5lZClcbiAgICAgICAgdGhyb3cgbmV3IFN5bnRheEVycm9yKFwiVGhlcmUgY2FuJ3QgYmUgcGFyYW1ldGVycyBhZnRlciBjYWxsYmFja1wiKTtcblxuICAgICAgY2FsbGJhY2sgID0gcGFyYW1zO1xuICAgICAgdHJhbnNwb3J0ID0gdW5kZWZpbmVkO1xuICAgICAgZGVzdCAgICAgID0gdW5kZWZpbmVkO1xuICAgICAgcGFyYW1zICAgID0gdW5kZWZpbmVkO1xuICAgIH1cblxuICAgIGVsc2UgaWYoZGVzdCBpbnN0YW5jZW9mIEZ1bmN0aW9uKVxuICAgIHtcbiAgICAgIGlmKHRyYW5zcG9ydCAhPSB1bmRlZmluZWQpXG4gICAgICAgIHRocm93IG5ldyBTeW50YXhFcnJvcihcIlRoZXJlIGNhbid0IGJlIHBhcmFtZXRlcnMgYWZ0ZXIgY2FsbGJhY2tcIik7XG5cbiAgICAgIGNhbGxiYWNrICA9IGRlc3Q7XG4gICAgICB0cmFuc3BvcnQgPSB1bmRlZmluZWQ7XG4gICAgICBkZXN0ICAgICAgPSB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgZWxzZSBpZih0cmFuc3BvcnQgaW5zdGFuY2VvZiBGdW5jdGlvbilcbiAgICB7XG4gICAgICBpZihjYWxsYmFjayAhPSB1bmRlZmluZWQpXG4gICAgICAgIHRocm93IG5ldyBTeW50YXhFcnJvcihcIlRoZXJlIGNhbid0IGJlIHBhcmFtZXRlcnMgYWZ0ZXIgY2FsbGJhY2tcIik7XG5cbiAgICAgIGNhbGxiYWNrICA9IHRyYW5zcG9ydDtcbiAgICAgIHRyYW5zcG9ydCA9IHVuZGVmaW5lZDtcbiAgICB9O1xuXG4gICAgaWYoc2VsZi5wZWVySUQgIT0gdW5kZWZpbmVkKVxuICAgIHtcbiAgICAgIHBhcmFtcyA9IHBhcmFtcyB8fCB7fTtcblxuICAgICAgcGFyYW1zLmZyb20gPSBzZWxmLnBlZXJJRDtcbiAgICB9O1xuXG4gICAgaWYoZGVzdCAhPSB1bmRlZmluZWQpXG4gICAge1xuICAgICAgcGFyYW1zID0gcGFyYW1zIHx8IHt9O1xuXG4gICAgICBwYXJhbXMuZGVzdCA9IGRlc3Q7XG4gICAgfTtcblxuICAgIC8vIEVuY29kZSBtZXNzYWdlXG4gICAgdmFyIG1lc3NhZ2UgPVxuICAgIHtcbiAgICAgIG1ldGhvZDogbWV0aG9kLFxuICAgICAgcGFyYW1zOiBwYXJhbXNcbiAgICB9O1xuXG4gICAgaWYoY2FsbGJhY2spXG4gICAge1xuICAgICAgdmFyIGlkID0gcmVxdWVzdElEKys7XG4gICAgICB2YXIgcmV0cmllZCA9IDA7XG5cbiAgICAgIG1lc3NhZ2UgPSBwYWNrZXIucGFjayhtZXNzYWdlLCBpZCk7XG5cbiAgICAgIGZ1bmN0aW9uIGRpc3BhdGNoQ2FsbGJhY2soZXJyb3IsIHJlc3VsdClcbiAgICAgIHtcbiAgICAgICAgc2VsZi5jYW5jZWwobWVzc2FnZSk7XG5cbiAgICAgICAgY2FsbGJhY2soZXJyb3IsIHJlc3VsdCk7XG4gICAgICB9O1xuXG4gICAgICB2YXIgcmVxdWVzdCA9XG4gICAgICB7XG4gICAgICAgIG1lc3NhZ2U6ICAgICAgICAgbWVzc2FnZSxcbiAgICAgICAgY2FsbGJhY2s6ICAgICAgICBkaXNwYXRjaENhbGxiYWNrLFxuICAgICAgICByZXNwb25zZU1ldGhvZHM6IHJlc3BvbnNlTWV0aG9kc1ttZXRob2RdIHx8IHt9XG4gICAgICB9O1xuXG4gICAgICB2YXIgZW5jb2RlX3RyYW5zcG9ydCA9IHVuaWZ5VHJhbnNwb3J0KHRyYW5zcG9ydCk7XG5cbiAgICAgIGZ1bmN0aW9uIHNlbmRSZXF1ZXN0KHRyYW5zcG9ydClcbiAgICAgIHtcbiAgICAgICAgdmFyIHJ0ID0gKG1ldGhvZCA9PT0gJ3BpbmcnID8gcGluZ19yZXF1ZXN0X3RpbWVvdXQgOiByZXF1ZXN0X3RpbWVvdXQpO1xuICAgICAgICByZXF1ZXN0LnRpbWVvdXQgPSBzZXRUaW1lb3V0KHRpbWVvdXQsIHJ0Kk1hdGgucG93KDIsIHJldHJpZWQrKykpO1xuICAgICAgICBtZXNzYWdlMktleVttZXNzYWdlXSA9IHtpZDogaWQsIGRlc3Q6IGRlc3R9O1xuICAgICAgICByZXF1ZXN0cy5zZXQocmVxdWVzdCwgaWQsIGRlc3QpO1xuXG4gICAgICAgIHRyYW5zcG9ydCA9IHRyYW5zcG9ydCB8fCBlbmNvZGVfdHJhbnNwb3J0IHx8IHNlbGYuZ2V0VHJhbnNwb3J0KCk7XG4gICAgICAgIGlmKHRyYW5zcG9ydClcbiAgICAgICAgICByZXR1cm4gdHJhbnNwb3J0LnNlbmQobWVzc2FnZSk7XG5cbiAgICAgICAgcmV0dXJuIG1lc3NhZ2U7XG4gICAgICB9O1xuXG4gICAgICBmdW5jdGlvbiByZXRyeSh0cmFuc3BvcnQpXG4gICAgICB7XG4gICAgICAgIHRyYW5zcG9ydCA9IHVuaWZ5VHJhbnNwb3J0KHRyYW5zcG9ydCk7XG5cbiAgICAgICAgY29uc29sZS53YXJuKHJldHJpZWQrJyByZXRyeSBmb3IgcmVxdWVzdCBtZXNzYWdlOicsbWVzc2FnZSk7XG5cbiAgICAgICAgdmFyIHRpbWVvdXQgPSBwcm9jZXNzZWRSZXNwb25zZXMucG9wKGlkLCBkZXN0KTtcbiAgICAgICAgY2xlYXJUaW1lb3V0KHRpbWVvdXQpO1xuXG4gICAgICAgIHJldHVybiBzZW5kUmVxdWVzdCh0cmFuc3BvcnQpO1xuICAgICAgfTtcblxuICAgICAgZnVuY3Rpb24gdGltZW91dCgpXG4gICAgICB7XG4gICAgICAgIGlmKHJldHJpZWQgPCBtYXhfcmV0cmllcylcbiAgICAgICAgICByZXR1cm4gcmV0cnkodHJhbnNwb3J0KTtcblxuICAgICAgICB2YXIgZXJyb3IgPSBuZXcgRXJyb3IoJ1JlcXVlc3QgaGFzIHRpbWVkIG91dCcpO1xuICAgICAgICAgICAgZXJyb3IucmVxdWVzdCA9IG1lc3NhZ2U7XG5cbiAgICAgICAgZXJyb3IucmV0cnkgPSByZXRyeTtcblxuICAgICAgICBkaXNwYXRjaENhbGxiYWNrKGVycm9yKVxuICAgICAgfTtcblxuICAgICAgcmV0dXJuIHNlbmRSZXF1ZXN0KHRyYW5zcG9ydCk7XG4gICAgfTtcblxuICAgIC8vIFJldHVybiB0aGUgcGFja2VkIG1lc3NhZ2VcbiAgICBtZXNzYWdlID0gcGFja2VyLnBhY2sobWVzc2FnZSk7XG5cbiAgICB0cmFuc3BvcnQgPSB0cmFuc3BvcnQgfHwgdGhpcy5nZXRUcmFuc3BvcnQoKTtcbiAgICBpZih0cmFuc3BvcnQpXG4gICAgICByZXR1cm4gdHJhbnNwb3J0LnNlbmQobWVzc2FnZSk7XG5cbiAgICByZXR1cm4gbWVzc2FnZTtcbiAgfTtcblxuICAvKipcbiAgICogRGVjb2RlIGFuZCBwcm9jZXNzIGEgSnNvblJQQyAyLjAgbWVzc2FnZVxuICAgKlxuICAgKiBAcGFyYW0ge3N0cmluZ30gbWVzc2FnZSAtIHN0cmluZyB3aXRoIHRoZSBjb250ZW50IG9mIHRoZSBtZXNzYWdlXG4gICAqXG4gICAqIEByZXR1cm5zIHtScGNOb3RpZmljYXRpb258UnBjUmVxdWVzdHx1bmRlZmluZWR9IC0gdGhlIHJlcHJlc2VudGF0aW9uIG9mIHRoZVxuICAgKiAgIG5vdGlmaWNhdGlvbiBvciB0aGUgcmVxdWVzdC4gSWYgYSByZXNwb25zZSB3YXMgcHJvY2Vzc2VkLCBpdCB3aWxsIHJldHVyblxuICAgKiAgIGB1bmRlZmluZWRgIHRvIG5vdGlmeSB0aGF0IGl0IHdhcyBwcm9jZXNzZWRcbiAgICpcbiAgICogQHRocm93cyB7VHlwZUVycm9yfSAtIE1lc3NhZ2UgaXMgbm90IGRlZmluZWRcbiAgICovXG4gIHRoaXMuZGVjb2RlID0gZnVuY3Rpb24obWVzc2FnZSwgdHJhbnNwb3J0KVxuICB7XG4gICAgaWYoIW1lc3NhZ2UpXG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiTWVzc2FnZSBpcyBub3QgZGVmaW5lZFwiKTtcblxuICAgIHRyeVxuICAgIHtcbiAgICAgIG1lc3NhZ2UgPSBwYWNrZXIudW5wYWNrKG1lc3NhZ2UpO1xuICAgIH1cbiAgICBjYXRjaChlKVxuICAgIHtcbiAgICAgIC8vIElnbm9yZSBpbnZhbGlkIG1lc3NhZ2VzXG4gICAgICByZXR1cm4gY29uc29sZS5kZWJ1ZyhlLCBtZXNzYWdlKTtcbiAgICB9O1xuXG4gICAgdmFyIGlkICAgICA9IG1lc3NhZ2UuaWQ7XG4gICAgdmFyIGFjayAgICA9IG1lc3NhZ2UuYWNrO1xuICAgIHZhciBtZXRob2QgPSBtZXNzYWdlLm1ldGhvZDtcbiAgICB2YXIgcGFyYW1zID0gbWVzc2FnZS5wYXJhbXMgfHwge307XG5cbiAgICB2YXIgZnJvbSA9IHBhcmFtcy5mcm9tO1xuICAgIHZhciBkZXN0ID0gcGFyYW1zLmRlc3Q7XG5cbiAgICAvLyBJZ25vcmUgbWVzc2FnZXMgc2VuZCBieSB1c1xuICAgIGlmKHNlbGYucGVlcklEICE9IHVuZGVmaW5lZCAmJiBmcm9tID09IHNlbGYucGVlcklEKSByZXR1cm47XG5cbiAgICAvLyBOb3RpZmljYXRpb25cbiAgICBpZihpZCA9PSB1bmRlZmluZWQgJiYgYWNrID09IHVuZGVmaW5lZClcbiAgICB7XG4gICAgICB2YXIgbm90aWZpY2F0aW9uID0gbmV3IFJwY05vdGlmaWNhdGlvbihtZXRob2QsIHBhcmFtcyk7XG5cbiAgICAgIGlmKHNlbGYuZW1pdCgncmVxdWVzdCcsIG5vdGlmaWNhdGlvbikpIHJldHVybjtcbiAgICAgIHJldHVybiBub3RpZmljYXRpb247XG4gICAgfTtcblxuXG4gICAgZnVuY3Rpb24gcHJvY2Vzc1JlcXVlc3QoKVxuICAgIHtcbiAgICAgIC8vIElmIHdlIGhhdmUgYSB0cmFuc3BvcnQgYW5kIGl0J3MgYSBkdXBsaWNhdGVkIHJlcXVlc3QsIHJlcGx5IGlubWVkaWF0bHlcbiAgICAgIHRyYW5zcG9ydCA9IHVuaWZ5VHJhbnNwb3J0KHRyYW5zcG9ydCkgfHwgc2VsZi5nZXRUcmFuc3BvcnQoKTtcbiAgICAgIGlmKHRyYW5zcG9ydClcbiAgICAgIHtcbiAgICAgICAgdmFyIHJlc3BvbnNlID0gcmVzcG9uc2VzLmdldChpZCwgZnJvbSk7XG4gICAgICAgIGlmKHJlc3BvbnNlKVxuICAgICAgICAgIHJldHVybiB0cmFuc3BvcnQuc2VuZChyZXNwb25zZS5tZXNzYWdlKTtcbiAgICAgIH07XG5cbiAgICAgIHZhciBpZEFjayA9IChpZCAhPSB1bmRlZmluZWQpID8gaWQgOiBhY2s7XG4gICAgICB2YXIgcmVxdWVzdCA9IG5ldyBScGNSZXF1ZXN0KG1ldGhvZCwgcGFyYW1zLCBpZEFjaywgZnJvbSwgdHJhbnNwb3J0KTtcblxuICAgICAgaWYoc2VsZi5lbWl0KCdyZXF1ZXN0JywgcmVxdWVzdCkpIHJldHVybjtcbiAgICAgIHJldHVybiByZXF1ZXN0O1xuICAgIH07XG5cbiAgICBmdW5jdGlvbiBwcm9jZXNzUmVzcG9uc2UocmVxdWVzdCwgZXJyb3IsIHJlc3VsdClcbiAgICB7XG4gICAgICByZXF1ZXN0LmNhbGxiYWNrKGVycm9yLCByZXN1bHQpO1xuICAgIH07XG5cbiAgICBmdW5jdGlvbiBkdXBsaWNhdGVkUmVzcG9uc2UodGltZW91dClcbiAgICB7XG4gICAgICBjb25zb2xlLndhcm4oXCJSZXNwb25zZSBhbHJlYWR5IHByb2Nlc3NlZFwiLCBtZXNzYWdlKTtcblxuICAgICAgLy8gVXBkYXRlIGR1cGxpY2F0ZWQgcmVzcG9uc2VzIHRpbWVvdXRcbiAgICAgIGNsZWFyVGltZW91dCh0aW1lb3V0KTtcbiAgICAgIHN0b3JlUHJvY2Vzc2VkUmVzcG9uc2UoYWNrLCBmcm9tKTtcbiAgICB9O1xuXG5cbiAgICAvLyBSZXF1ZXN0LCBvciByZXNwb25zZSB3aXRoIG93biBtZXRob2RcbiAgICBpZihtZXRob2QpXG4gICAge1xuICAgICAgLy8gQ2hlY2sgaWYgaXQncyBhIHJlc3BvbnNlIHdpdGggb3duIG1ldGhvZFxuICAgICAgaWYoZGVzdCA9PSB1bmRlZmluZWQgfHwgZGVzdCA9PSBzZWxmLnBlZXJJRClcbiAgICAgIHtcbiAgICAgICAgdmFyIHJlcXVlc3QgPSByZXF1ZXN0cy5nZXQoYWNrLCBmcm9tKTtcbiAgICAgICAgaWYocmVxdWVzdClcbiAgICAgICAge1xuICAgICAgICAgIHZhciByZXNwb25zZU1ldGhvZHMgPSByZXF1ZXN0LnJlc3BvbnNlTWV0aG9kcztcblxuICAgICAgICAgIGlmKG1ldGhvZCA9PSByZXNwb25zZU1ldGhvZHMuZXJyb3IpXG4gICAgICAgICAgICByZXR1cm4gcHJvY2Vzc1Jlc3BvbnNlKHJlcXVlc3QsIHBhcmFtcyk7XG5cbiAgICAgICAgICBpZihtZXRob2QgPT0gcmVzcG9uc2VNZXRob2RzLnJlc3BvbnNlKVxuICAgICAgICAgICAgcmV0dXJuIHByb2Nlc3NSZXNwb25zZShyZXF1ZXN0LCBudWxsLCBwYXJhbXMpO1xuXG4gICAgICAgICAgcmV0dXJuIHByb2Nlc3NSZXF1ZXN0KCk7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgcHJvY2Vzc2VkID0gcHJvY2Vzc2VkUmVzcG9uc2VzLmdldChhY2ssIGZyb20pO1xuICAgICAgICBpZihwcm9jZXNzZWQpXG4gICAgICAgICAgcmV0dXJuIGR1cGxpY2F0ZWRSZXNwb25zZShwcm9jZXNzZWQpO1xuICAgICAgfVxuXG4gICAgICAvLyBSZXF1ZXN0XG4gICAgICByZXR1cm4gcHJvY2Vzc1JlcXVlc3QoKTtcbiAgICB9O1xuXG4gICAgdmFyIGVycm9yICA9IG1lc3NhZ2UuZXJyb3I7XG4gICAgdmFyIHJlc3VsdCA9IG1lc3NhZ2UucmVzdWx0O1xuXG4gICAgLy8gSWdub3JlIHJlc3BvbnNlcyBub3Qgc2VuZCB0byB1c1xuICAgIGlmKGVycm9yICAmJiBlcnJvci5kZXN0ICAmJiBlcnJvci5kZXN0ICAhPSBzZWxmLnBlZXJJRCkgcmV0dXJuO1xuICAgIGlmKHJlc3VsdCAmJiByZXN1bHQuZGVzdCAmJiByZXN1bHQuZGVzdCAhPSBzZWxmLnBlZXJJRCkgcmV0dXJuO1xuXG4gICAgLy8gUmVzcG9uc2VcbiAgICB2YXIgcmVxdWVzdCA9IHJlcXVlc3RzLmdldChhY2ssIGZyb20pO1xuICAgIGlmKCFyZXF1ZXN0KVxuICAgIHtcbiAgICAgIHZhciBwcm9jZXNzZWQgPSBwcm9jZXNzZWRSZXNwb25zZXMuZ2V0KGFjaywgZnJvbSk7XG4gICAgICBpZihwcm9jZXNzZWQpXG4gICAgICAgIHJldHVybiBkdXBsaWNhdGVkUmVzcG9uc2UocHJvY2Vzc2VkKTtcblxuICAgICAgcmV0dXJuIGNvbnNvbGUud2FybihcIk5vIGNhbGxiYWNrIHdhcyBkZWZpbmVkIGZvciB0aGlzIG1lc3NhZ2VcIiwgbWVzc2FnZSk7XG4gICAgfTtcblxuICAgIC8vIFByb2Nlc3MgcmVzcG9uc2VcbiAgICBwcm9jZXNzUmVzcG9uc2UocmVxdWVzdCwgZXJyb3IsIHJlc3VsdCk7XG4gIH07XG59O1xuaW5oZXJpdHMoUnBjQnVpbGRlciwgRXZlbnRFbWl0dGVyKTtcblxuXG5ScGNCdWlsZGVyLlJwY05vdGlmaWNhdGlvbiA9IFJwY05vdGlmaWNhdGlvbjtcblxuXG5tb2R1bGUuZXhwb3J0cyA9IFJwY0J1aWxkZXI7XG5cbnZhciBjbGllbnRzID0gcmVxdWlyZSgnLi9jbGllbnRzJyk7XG52YXIgdHJhbnNwb3J0cyA9IHJlcXVpcmUoJy4vY2xpZW50cy90cmFuc3BvcnRzJyk7XG5cblJwY0J1aWxkZXIuY2xpZW50cyA9IGNsaWVudHM7XG5ScGNCdWlsZGVyLmNsaWVudHMudHJhbnNwb3J0cyA9IHRyYW5zcG9ydHM7XG5ScGNCdWlsZGVyLnBhY2tlcnMgPSBwYWNrZXJzO1xuIiwiLyoqXG4gKiBKc29uUlBDIDIuMCBwYWNrZXJcbiAqL1xuXG4vKipcbiAqIFBhY2sgYSBKc29uUlBDIDIuMCBtZXNzYWdlXG4gKlxuICogQHBhcmFtIHtPYmplY3R9IG1lc3NhZ2UgLSBvYmplY3QgdG8gYmUgcGFja2FnZWQuIEl0IHJlcXVpcmVzIHRvIGhhdmUgYWxsIHRoZVxuICogICBmaWVsZHMgbmVlZGVkIGJ5IHRoZSBKc29uUlBDIDIuMCBtZXNzYWdlIHRoYXQgaXQncyBnb2luZyB0byBiZSBnZW5lcmF0ZWRcbiAqXG4gKiBAcmV0dXJuIHtTdHJpbmd9IC0gdGhlIHN0cmluZ2lmaWVkIEpzb25SUEMgMi4wIG1lc3NhZ2VcbiAqL1xuZnVuY3Rpb24gcGFjayhtZXNzYWdlLCBpZClcbntcbiAgdmFyIHJlc3VsdCA9XG4gIHtcbiAgICBqc29ucnBjOiBcIjIuMFwiXG4gIH07XG5cbiAgLy8gUmVxdWVzdFxuICBpZihtZXNzYWdlLm1ldGhvZClcbiAge1xuICAgIHJlc3VsdC5tZXRob2QgPSBtZXNzYWdlLm1ldGhvZDtcblxuICAgIGlmKG1lc3NhZ2UucGFyYW1zKVxuICAgICAgcmVzdWx0LnBhcmFtcyA9IG1lc3NhZ2UucGFyYW1zO1xuXG4gICAgLy8gUmVxdWVzdCBpcyBhIG5vdGlmaWNhdGlvblxuICAgIGlmKGlkICE9IHVuZGVmaW5lZClcbiAgICAgIHJlc3VsdC5pZCA9IGlkO1xuICB9XG5cbiAgLy8gUmVzcG9uc2VcbiAgZWxzZSBpZihpZCAhPSB1bmRlZmluZWQpXG4gIHtcbiAgICBpZihtZXNzYWdlLmVycm9yKVxuICAgIHtcbiAgICAgIGlmKG1lc3NhZ2UucmVzdWx0ICE9PSB1bmRlZmluZWQpXG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJCb3RoIHJlc3VsdCBhbmQgZXJyb3IgYXJlIGRlZmluZWRcIik7XG5cbiAgICAgIHJlc3VsdC5lcnJvciA9IG1lc3NhZ2UuZXJyb3I7XG4gICAgfVxuICAgIGVsc2UgaWYobWVzc2FnZS5yZXN1bHQgIT09IHVuZGVmaW5lZClcbiAgICAgIHJlc3VsdC5yZXN1bHQgPSBtZXNzYWdlLnJlc3VsdDtcbiAgICBlbHNlXG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiTm8gcmVzdWx0IG9yIGVycm9yIGlzIGRlZmluZWRcIik7XG5cbiAgICByZXN1bHQuaWQgPSBpZDtcbiAgfTtcblxuICByZXR1cm4gSlNPTi5zdHJpbmdpZnkocmVzdWx0KTtcbn07XG5cbi8qKlxuICogVW5wYWNrIGEgSnNvblJQQyAyLjAgbWVzc2FnZVxuICpcbiAqIEBwYXJhbSB7U3RyaW5nfSBtZXNzYWdlIC0gc3RyaW5nIHdpdGggdGhlIGNvbnRlbnQgb2YgdGhlIEpzb25SUEMgMi4wIG1lc3NhZ2VcbiAqXG4gKiBAdGhyb3dzIHtUeXBlRXJyb3J9IC0gSW52YWxpZCBKc29uUlBDIHZlcnNpb25cbiAqXG4gKiBAcmV0dXJuIHtPYmplY3R9IC0gb2JqZWN0IGZpbGxlZCB3aXRoIHRoZSBKc29uUlBDIDIuMCBtZXNzYWdlIGNvbnRlbnRcbiAqL1xuZnVuY3Rpb24gdW5wYWNrKG1lc3NhZ2UpXG57XG4gIHZhciByZXN1bHQgPSBtZXNzYWdlO1xuXG4gIGlmKHR5cGVvZiBtZXNzYWdlID09PSAnc3RyaW5nJyB8fCBtZXNzYWdlIGluc3RhbmNlb2YgU3RyaW5nKSB7XG4gICAgcmVzdWx0ID0gSlNPTi5wYXJzZShtZXNzYWdlKTtcbiAgfVxuXG4gIC8vIENoZWNrIGlmIGl0J3MgYSB2YWxpZCBtZXNzYWdlXG5cbiAgdmFyIHZlcnNpb24gPSByZXN1bHQuanNvbnJwYztcbiAgaWYodmVyc2lvbiAhPT0gJzIuMCcpXG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkludmFsaWQgSnNvblJQQyB2ZXJzaW9uICdcIiArIHZlcnNpb24gKyBcIic6IFwiICsgbWVzc2FnZSk7XG5cbiAgLy8gUmVzcG9uc2VcbiAgaWYocmVzdWx0Lm1ldGhvZCA9PSB1bmRlZmluZWQpXG4gIHtcbiAgICBpZihyZXN1bHQuaWQgPT0gdW5kZWZpbmVkKVxuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkludmFsaWQgbWVzc2FnZTogXCIrbWVzc2FnZSk7XG5cbiAgICB2YXIgcmVzdWx0X2RlZmluZWQgPSByZXN1bHQucmVzdWx0ICE9PSB1bmRlZmluZWQ7XG4gICAgdmFyIGVycm9yX2RlZmluZWQgID0gcmVzdWx0LmVycm9yICAhPT0gdW5kZWZpbmVkO1xuXG4gICAgLy8gQ2hlY2sgb25seSByZXN1bHQgb3IgZXJyb3IgaXMgZGVmaW5lZCwgbm90IGJvdGggb3Igbm9uZVxuICAgIGlmKHJlc3VsdF9kZWZpbmVkICYmIGVycm9yX2RlZmluZWQpXG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQm90aCByZXN1bHQgYW5kIGVycm9yIGFyZSBkZWZpbmVkOiBcIittZXNzYWdlKTtcblxuICAgIGlmKCFyZXN1bHRfZGVmaW5lZCAmJiAhZXJyb3JfZGVmaW5lZClcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJObyByZXN1bHQgb3IgZXJyb3IgaXMgZGVmaW5lZDogXCIrbWVzc2FnZSk7XG5cbiAgICByZXN1bHQuYWNrID0gcmVzdWx0LmlkO1xuICAgIGRlbGV0ZSByZXN1bHQuaWQ7XG4gIH1cblxuICAvLyBSZXR1cm4gdW5wYWNrZWQgbWVzc2FnZVxuICByZXR1cm4gcmVzdWx0O1xufTtcblxuXG5leHBvcnRzLnBhY2sgICA9IHBhY2s7XG5leHBvcnRzLnVucGFjayA9IHVucGFjaztcbiIsImZ1bmN0aW9uIHBhY2sobWVzc2FnZSlcbntcbiAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIk5vdCB5ZXQgaW1wbGVtZW50ZWRcIik7XG59O1xuXG5mdW5jdGlvbiB1bnBhY2sobWVzc2FnZSlcbntcbiAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIk5vdCB5ZXQgaW1wbGVtZW50ZWRcIik7XG59O1xuXG5cbmV4cG9ydHMucGFjayAgID0gcGFjaztcbmV4cG9ydHMudW5wYWNrID0gdW5wYWNrO1xuIiwidmFyIEpzb25SUEMgPSByZXF1aXJlKCcuL0pzb25SUEMnKTtcbnZhciBYbWxSUEMgID0gcmVxdWlyZSgnLi9YbWxSUEMnKTtcblxuXG5leHBvcnRzLkpzb25SUEMgPSBKc29uUlBDO1xuZXhwb3J0cy5YbWxSUEMgID0gWG1sUlBDO1xuIiwiLy8gTGFzdCB0aW1lIHVwZGF0ZWQgb24gSnVuZSAwOCwgMjAxOFxuXG4vLyBMYXRlc3QgZmlsZSBjYW4gYmUgZm91bmQgaGVyZTogaHR0cHM6Ly9jZG4ud2VicnRjLWV4cGVyaW1lbnQuY29tL2dldFNjcmVlbklkLmpzXG5cbi8vIE11YXogS2hhbiAgICAgICAgIC0gd3d3Lk11YXpLaGFuLmNvbVxuLy8gTUlUIExpY2Vuc2UgICAgICAgLSB3d3cuV2ViUlRDLUV4cGVyaW1lbnQuY29tL2xpY2VuY2Vcbi8vIERvY3VtZW50YXRpb24gICAgIC0gaHR0cHM6Ly9naXRodWIuY29tL211YXota2hhbi9nZXRTY3JlZW5JZC5cblxuLy8gX19fX19fX19fX19fX19cbi8vIGdldFNjcmVlbklkLmpzXG5cbi8qXG5nZXRTY3JlZW5JZChmdW5jdGlvbiAoZXJyb3IsIHNvdXJjZUlkLCBzY3JlZW5fY29uc3RyYWludHMpIHtcbiAgICAvLyBlcnJvciAgICA9PSBudWxsIHx8ICdwZXJtaXNzaW9uLWRlbmllZCcgfHwgJ25vdC1pbnN0YWxsZWQnIHx8ICdpbnN0YWxsZWQtZGlzYWJsZWQnIHx8ICdub3QtY2hyb21lJ1xuICAgIC8vIHNvdXJjZUlkID09IG51bGwgfHwgJ3N0cmluZycgfHwgJ2ZpcmVmb3gnXG4gICAgXG4gICAgaWYobWljcm9zb2Z0RWRnZSkge1xuICAgICAgICBuYXZpZ2F0b3IuZ2V0RGlzcGxheU1lZGlhKHNjcmVlbl9jb25zdHJhaW50cykudGhlbihvblN1Y2Nlc3MsIG9uRmFpbHVyZSk7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICBuYXZpZ2F0b3IubWVkaWFEZXZpY2VzLmdldFVzZXJNZWRpYShzY3JlZW5fY29uc3RyYWludHMpLnRoZW4ob25TdWNjZXNzKWNhdGNoKG9uRmFpbHVyZSk7XG4gICAgfVxufSwgJ3Bhc3Mgc2Vjb25kIHBhcmFtZXRlciBvbmx5IGlmIHlvdSB3YW50IHN5c3RlbSBhdWRpbycpO1xuKi9cblxud2luZG93LmdldFNjcmVlbklkID0gZnVuY3Rpb24gKGNhbGxiYWNrLCBjdXN0b21fcGFyYW1ldGVyKSB7XG4gICAgaWYgKG5hdmlnYXRvci51c2VyQWdlbnQuaW5kZXhPZignRWRnZScpICE9PSAtMSAmJiAoISFuYXZpZ2F0b3IubXNTYXZlT3JPcGVuQmxvYiB8fCAhIW5hdmlnYXRvci5tc1NhdmVCbG9iKSkge1xuICAgICAgICAvLyBtaWNyb3NvZnQgZWRnZSA9PiBuYXZpZ2F0b3IuZ2V0RGlzcGxheU1lZGlhKHNjcmVlbl9jb25zdHJhaW50cykudGhlbihvblN1Y2Nlc3MsIG9uRmFpbHVyZSk7XG4gICAgICAgIGNhbGxiYWNrKHtcbiAgICAgICAgICAgIHZpZGVvOiB0cnVlXG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gZm9yIEZpcmVmb3g6XG4gICAgLy8gc291cmNlSWQgPT0gJ2ZpcmVmb3gnXG4gICAgLy8gc2NyZWVuX2NvbnN0cmFpbnRzID0gey4uLn1cbiAgICBpZiAoISFuYXZpZ2F0b3IubW96R2V0VXNlck1lZGlhKSB7XG4gICAgICAgIGNhbGxiYWNrKG51bGwsICdmaXJlZm94Jywge1xuICAgICAgICAgICAgdmlkZW86IHtcbiAgICAgICAgICAgICAgICBtb3pNZWRpYVNvdXJjZTogJ3dpbmRvdycsXG4gICAgICAgICAgICAgICAgbWVkaWFTb3VyY2U6ICd3aW5kb3cnXG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ21lc3NhZ2UnLCBvbklGcmFtZUNhbGxiYWNrKTtcblxuICAgIGZ1bmN0aW9uIG9uSUZyYW1lQ2FsbGJhY2soZXZlbnQpIHtcbiAgICAgICAgaWYgKCFldmVudC5kYXRhKSByZXR1cm47XG5cbiAgICAgICAgaWYgKGV2ZW50LmRhdGEuY2hyb21lTWVkaWFTb3VyY2VJZCkge1xuICAgICAgICAgICAgaWYgKGV2ZW50LmRhdGEuY2hyb21lTWVkaWFTb3VyY2VJZCA9PT0gJ1Blcm1pc3Npb25EZW5pZWRFcnJvcicpIHtcbiAgICAgICAgICAgICAgICBjYWxsYmFjaygncGVybWlzc2lvbi1kZW5pZWQnKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY2FsbGJhY2sobnVsbCwgZXZlbnQuZGF0YS5jaHJvbWVNZWRpYVNvdXJjZUlkLCBnZXRTY3JlZW5Db25zdHJhaW50cyhudWxsLCBldmVudC5kYXRhLmNocm9tZU1lZGlhU291cmNlSWQsIGV2ZW50LmRhdGEuY2FuUmVxdWVzdEF1ZGlvVHJhY2spKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gdGhpcyBldmVudCBsaXN0ZW5lciBpcyBubyBtb3JlIG5lZWRlZFxuICAgICAgICAgICAgd2luZG93LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ21lc3NhZ2UnLCBvbklGcmFtZUNhbGxiYWNrKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChldmVudC5kYXRhLmNocm9tZUV4dGVuc2lvblN0YXR1cykge1xuICAgICAgICAgICAgY2FsbGJhY2soZXZlbnQuZGF0YS5jaHJvbWVFeHRlbnNpb25TdGF0dXMsIG51bGwsIGdldFNjcmVlbkNvbnN0cmFpbnRzKGV2ZW50LmRhdGEuY2hyb21lRXh0ZW5zaW9uU3RhdHVzKSk7XG5cbiAgICAgICAgICAgIC8vIHRoaXMgZXZlbnQgbGlzdGVuZXIgaXMgbm8gbW9yZSBuZWVkZWRcbiAgICAgICAgICAgIHdpbmRvdy5yZW1vdmVFdmVudExpc3RlbmVyKCdtZXNzYWdlJywgb25JRnJhbWVDYWxsYmFjayk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoIWN1c3RvbV9wYXJhbWV0ZXIpIHtcbiAgICAgICAgc2V0VGltZW91dChwb3N0R2V0U291cmNlSWRNZXNzYWdlLCAxMDApO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBwb3N0R2V0U291cmNlSWRNZXNzYWdlKGN1c3RvbV9wYXJhbWV0ZXIpO1xuICAgICAgICB9LCAxMDApO1xuICAgIH1cbn07XG5cbmZ1bmN0aW9uIGdldFNjcmVlbkNvbnN0cmFpbnRzKGVycm9yLCBzb3VyY2VJZCwgY2FuUmVxdWVzdEF1ZGlvVHJhY2spIHtcbiAgICB2YXIgc2NyZWVuX2NvbnN0cmFpbnRzID0ge1xuICAgICAgICBhdWRpbzogZmFsc2UsXG4gICAgICAgIHZpZGVvOiB7XG4gICAgICAgICAgICBtYW5kYXRvcnk6IHtcbiAgICAgICAgICAgICAgICBjaHJvbWVNZWRpYVNvdXJjZTogZXJyb3IgPyAnc2NyZWVuJyA6ICdkZXNrdG9wJyxcbiAgICAgICAgICAgICAgICBtYXhXaWR0aDogd2luZG93LnNjcmVlbi53aWR0aCA+IDE5MjAgPyB3aW5kb3cuc2NyZWVuLndpZHRoIDogMTkyMCxcbiAgICAgICAgICAgICAgICBtYXhIZWlnaHQ6IHdpbmRvdy5zY3JlZW4uaGVpZ2h0ID4gMTA4MCA/IHdpbmRvdy5zY3JlZW4uaGVpZ2h0IDogMTA4MFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIG9wdGlvbmFsOiBbXVxuICAgICAgICB9XG4gICAgfTtcblxuICAgIGlmICghIWNhblJlcXVlc3RBdWRpb1RyYWNrKSB7XG4gICAgICAgIHNjcmVlbl9jb25zdHJhaW50cy5hdWRpbyA9IHtcbiAgICAgICAgICAgIG1hbmRhdG9yeToge1xuICAgICAgICAgICAgICAgIGNocm9tZU1lZGlhU291cmNlOiBlcnJvciA/ICdzY3JlZW4nIDogJ2Rlc2t0b3AnLFxuICAgICAgICAgICAgICAgIC8vIGVjaG9DYW5jZWxsYXRpb246IHRydWVcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBvcHRpb25hbDogW11cbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICBpZiAoc291cmNlSWQpIHtcbiAgICAgICAgc2NyZWVuX2NvbnN0cmFpbnRzLnZpZGVvLm1hbmRhdG9yeS5jaHJvbWVNZWRpYVNvdXJjZUlkID0gc291cmNlSWQ7XG5cbiAgICAgICAgaWYgKHNjcmVlbl9jb25zdHJhaW50cy5hdWRpbyAmJiBzY3JlZW5fY29uc3RyYWludHMuYXVkaW8ubWFuZGF0b3J5KSB7XG4gICAgICAgICAgICBzY3JlZW5fY29uc3RyYWludHMuYXVkaW8ubWFuZGF0b3J5LmNocm9tZU1lZGlhU291cmNlSWQgPSBzb3VyY2VJZDtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBzY3JlZW5fY29uc3RyYWludHM7XG59XG5cbmZ1bmN0aW9uIHBvc3RHZXRTb3VyY2VJZE1lc3NhZ2UoY3VzdG9tX3BhcmFtZXRlcikge1xuICAgIGlmICghaWZyYW1lKSB7XG4gICAgICAgIGxvYWRJRnJhbWUoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcG9zdEdldFNvdXJjZUlkTWVzc2FnZShjdXN0b21fcGFyYW1ldGVyKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAoIWlmcmFtZS5pc0xvYWRlZCkge1xuICAgICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHBvc3RHZXRTb3VyY2VJZE1lc3NhZ2UoY3VzdG9tX3BhcmFtZXRlcik7XG4gICAgICAgIH0sIDEwMCk7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAoIWN1c3RvbV9wYXJhbWV0ZXIpIHtcbiAgICAgICAgaWZyYW1lLmNvbnRlbnRXaW5kb3cucG9zdE1lc3NhZ2Uoe1xuICAgICAgICAgICAgY2FwdHVyZVNvdXJjZUlkOiB0cnVlXG4gICAgICAgIH0sICcqJyk7XG4gICAgfVxuICAgIGVsc2UgaWYgKCEhY3VzdG9tX3BhcmFtZXRlci5mb3JFYWNoKSB7XG4gICAgICAgIGlmcmFtZS5jb250ZW50V2luZG93LnBvc3RNZXNzYWdlKHtcbiAgICAgICAgICAgIGNhcHR1cmVDdXN0b21Tb3VyY2VJZDogY3VzdG9tX3BhcmFtZXRlclxuICAgICAgICB9LCAnKicpO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgaWZyYW1lLmNvbnRlbnRXaW5kb3cucG9zdE1lc3NhZ2Uoe1xuICAgICAgICAgICAgY2FwdHVyZVNvdXJjZUlkV2l0aEF1ZGlvOiB0cnVlXG4gICAgICAgIH0sICcqJyk7XG4gICAgfVxufVxuXG52YXIgaWZyYW1lO1xuXG4vLyB0aGlzIGZ1bmN0aW9uIGlzIHVzZWQgaW4gUlRDTXVsdGlDb25uZWN0aW9uIHYzXG53aW5kb3cuZ2V0U2NyZWVuQ29uc3RyYWludHMgPSBmdW5jdGlvbiAoY2FsbGJhY2spIHtcbiAgICBsb2FkSUZyYW1lKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgZ2V0U2NyZWVuSWQoZnVuY3Rpb24gKGVycm9yLCBzb3VyY2VJZCwgc2NyZWVuX2NvbnN0cmFpbnRzKSB7XG4gICAgICAgICAgICBpZiAoIXNjcmVlbl9jb25zdHJhaW50cykge1xuICAgICAgICAgICAgICAgIHNjcmVlbl9jb25zdHJhaW50cyA9IHtcbiAgICAgICAgICAgICAgICAgICAgdmlkZW86IHRydWVcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBjYWxsYmFjayhlcnJvciwgc2NyZWVuX2NvbnN0cmFpbnRzLnZpZGVvKTtcbiAgICAgICAgfSk7XG4gICAgfSk7XG59O1xuXG5mdW5jdGlvbiBsb2FkSUZyYW1lKGxvYWRDYWxsYmFjaykge1xuICAgIGlmIChpZnJhbWUpIHtcbiAgICAgICAgbG9hZENhbGxiYWNrKCk7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZnJhbWUgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdpZnJhbWUnKTtcbiAgICBpZnJhbWUub25sb2FkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZnJhbWUuaXNMb2FkZWQgPSB0cnVlO1xuICAgICAgICBsb2FkQ2FsbGJhY2soKTtcbiAgICB9O1xuICAgIGlmcmFtZS5zcmMgPSAnaHR0cHM6Ly9vcGVudmlkdS5naXRodWIuaW8vb3BlbnZpZHUtc2NyZWVuLXNoYXJpbmctY2hyb21lLWV4dGVuc2lvbi8nO1xuICAgIGlmcmFtZS5zdHlsZS5kaXNwbGF5ID0gJ25vbmUnO1xuICAgIChkb2N1bWVudC5ib2R5IHx8IGRvY3VtZW50LmRvY3VtZW50RWxlbWVudCkuYXBwZW5kQ2hpbGQoaWZyYW1lKTtcbn1cblxud2luZG93LmdldENocm9tZUV4dGVuc2lvblN0YXR1cyA9IGZ1bmN0aW9uIChjYWxsYmFjaykge1xuICAgIC8vIGZvciBGaXJlZm94OlxuICAgIGlmICghIW5hdmlnYXRvci5tb3pHZXRVc2VyTWVkaWEpIHtcbiAgICAgICAgY2FsbGJhY2soJ2luc3RhbGxlZC1lbmFibGVkJyk7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcignbWVzc2FnZScsIG9uSUZyYW1lQ2FsbGJhY2spO1xuXG4gICAgZnVuY3Rpb24gb25JRnJhbWVDYWxsYmFjayhldmVudCkge1xuICAgICAgICBpZiAoIWV2ZW50LmRhdGEpIHJldHVybjtcblxuICAgICAgICBpZiAoZXZlbnQuZGF0YS5jaHJvbWVFeHRlbnNpb25TdGF0dXMpIHtcbiAgICAgICAgICAgIGNhbGxiYWNrKGV2ZW50LmRhdGEuY2hyb21lRXh0ZW5zaW9uU3RhdHVzKTtcblxuICAgICAgICAgICAgLy8gdGhpcyBldmVudCBsaXN0ZW5lciBpcyBubyBtb3JlIG5lZWRlZFxuICAgICAgICAgICAgd2luZG93LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ21lc3NhZ2UnLCBvbklGcmFtZUNhbGxiYWNrKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHNldFRpbWVvdXQocG9zdEdldENocm9tZUV4dGVuc2lvblN0YXR1c01lc3NhZ2UsIDEwMCk7XG59O1xuXG5mdW5jdGlvbiBwb3N0R2V0Q2hyb21lRXh0ZW5zaW9uU3RhdHVzTWVzc2FnZSgpIHtcbiAgICBpZiAoIWlmcmFtZSkge1xuICAgICAgICBsb2FkSUZyYW1lKHBvc3RHZXRDaHJvbWVFeHRlbnNpb25TdGF0dXNNZXNzYWdlKTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmICghaWZyYW1lLmlzTG9hZGVkKSB7XG4gICAgICAgIHNldFRpbWVvdXQocG9zdEdldENocm9tZUV4dGVuc2lvblN0YXR1c01lc3NhZ2UsIDEwMCk7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZnJhbWUuY29udGVudFdpbmRvdy5wb3N0TWVzc2FnZSh7XG4gICAgICAgIGdldENocm9tZUV4dGVuc2lvblN0YXR1czogdHJ1ZVxuICAgIH0sICcqJyk7XG59XG5cbmV4cG9ydHMuZ2V0U2NyZWVuSWQgPSBnZXRTY3JlZW5JZDsiLCIvLyBnbG9iYWwgdmFyaWFibGVzXG52YXIgY2hyb21lTWVkaWFTb3VyY2UgPSAnc2NyZWVuJztcbnZhciBzb3VyY2VJZDtcbnZhciBzY3JlZW5DYWxsYmFjaztcbnZhciBpc0ZpcmVmb3ggPSB0eXBlb2Ygd2luZG93Lkluc3RhbGxUcmlnZ2VyICE9PSAndW5kZWZpbmVkJztcbnZhciBpc09wZXJhID0gISF3aW5kb3cub3BlcmEgfHwgbmF2aWdhdG9yLnVzZXJBZ2VudC5pbmRleE9mKCcgT1BSLycpID49IDA7XG52YXIgaXNDaHJvbWUgPSAhIXdpbmRvdy5jaHJvbWUgJiYgIWlzT3BlcmE7XG5cbndpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdtZXNzYWdlJywgZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgaWYgKGV2ZW50Lm9yaWdpbiAhPSB3aW5kb3cubG9jYXRpb24ub3JpZ2luKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgb25NZXNzYWdlQ2FsbGJhY2soZXZlbnQuZGF0YSk7XG59KTtcblxuLy8gYW5kIHRoZSBmdW5jdGlvbiB0aGF0IGhhbmRsZXMgcmVjZWl2ZWQgbWVzc2FnZXNcbmZ1bmN0aW9uIG9uTWVzc2FnZUNhbGxiYWNrKGRhdGEpIHtcbiAgICAvLyBcImNhbmNlbFwiIGJ1dHRvbiBpcyBjbGlja2VkXG4gICAgaWYgKGRhdGEgPT0gJ1Blcm1pc3Npb25EZW5pZWRFcnJvcicpIHtcbiAgICAgICAgaWYgKHNjcmVlbkNhbGxiYWNrKVxuICAgICAgICAgICAgcmV0dXJuIHNjcmVlbkNhbGxiYWNrKCdQZXJtaXNzaW9uRGVuaWVkRXJyb3InKTtcbiAgICAgICAgZWxzZVxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdQZXJtaXNzaW9uRGVuaWVkRXJyb3InKTtcbiAgICB9XG4gICAgLy8gZXh0ZW5zaW9uIG5vdGlmaWVkIGhpcyBwcmVzZW5jZVxuICAgIGlmIChkYXRhID09ICdydGNtdWx0aWNvbm5lY3Rpb24tZXh0ZW5zaW9uLWxvYWRlZCcpIHtcbiAgICAgICAgY2hyb21lTWVkaWFTb3VyY2UgPSAnZGVza3RvcCc7XG4gICAgfVxuICAgIC8vIGV4dGVuc2lvbiBzaGFyZWQgdGVtcCBzb3VyY2VJZFxuICAgIGlmIChkYXRhLnNvdXJjZUlkICYmIHNjcmVlbkNhbGxiYWNrKSB7XG4gICAgICAgIHNjcmVlbkNhbGxiYWNrKHNvdXJjZUlkID0gZGF0YS5zb3VyY2VJZCwgZGF0YS5jYW5SZXF1ZXN0QXVkaW9UcmFjayA9PT0gdHJ1ZSk7XG4gICAgfVxufVxuXG4vLyB0aGlzIG1ldGhvZCBjYW4gYmUgdXNlZCB0byBjaGVjayBpZiBjaHJvbWUgZXh0ZW5zaW9uIGlzIGluc3RhbGxlZCAmIGVuYWJsZWQuXG5mdW5jdGlvbiBpc0Nocm9tZUV4dGVuc2lvbkF2YWlsYWJsZShjYWxsYmFjaykge1xuICAgIGlmICghY2FsbGJhY2spIHJldHVybjtcbiAgICBpZiAoY2hyb21lTWVkaWFTb3VyY2UgPT0gJ2Rlc2t0b3AnKSByZXR1cm4gY2FsbGJhY2sodHJ1ZSk7XG5cbiAgICAvLyBhc2sgZXh0ZW5zaW9uIGlmIGl0IGlzIGF2YWlsYWJsZVxuICAgIHdpbmRvdy5wb3N0TWVzc2FnZSgnYXJlLXlvdS10aGVyZScsICcqJyk7XG4gICAgc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmIChjaHJvbWVNZWRpYVNvdXJjZSA9PSAnc2NyZWVuJykge1xuICAgICAgICAgICAgY2FsbGJhY2soZmFsc2UpO1xuICAgICAgICB9IGVsc2UgY2FsbGJhY2sodHJ1ZSk7XG4gICAgfSwgMjAwMCk7XG59XG5cbi8vIHRoaXMgZnVuY3Rpb24gY2FuIGJlIHVzZWQgdG8gZ2V0IFwic291cmNlLWlkXCIgZnJvbSB0aGUgZXh0ZW5zaW9uXG5mdW5jdGlvbiBnZXRTb3VyY2VJZChjYWxsYmFjaykge1xuICAgIGlmICghY2FsbGJhY2spXG4gICAgICAgIHRocm93ICdcImNhbGxiYWNrXCIgcGFyYW1ldGVyIGlzIG1hbmRhdG9yeS4nO1xuICAgIGlmIChzb3VyY2VJZClcbiAgICAgICAgcmV0dXJuIGNhbGxiYWNrKHNvdXJjZUlkKTtcbiAgICBzY3JlZW5DYWxsYmFjayA9IGNhbGxiYWNrO1xuICAgIHdpbmRvdy5wb3N0TWVzc2FnZSgnZ2V0LXNvdXJjZUlkJywgJyonKTtcbn1cblxuLy8gdGhpcyBmdW5jdGlvbiBjYW4gYmUgdXNlZCB0byBnZXQgXCJzb3VyY2UtaWRcIiBmcm9tIHRoZSBleHRlbnNpb25cbmZ1bmN0aW9uIGdldEN1c3RvbVNvdXJjZUlkKGFyciwgY2FsbGJhY2spIHtcbiAgICBpZiAoIWFyciB8fCAhYXJyLmZvckVhY2gpIHRocm93ICdcImFyclwiIHBhcmFtZXRlciBpcyBtYW5kYXRvcnkgYW5kIGl0IG11c3QgYmUgYW4gYXJyYXkuJztcbiAgICBpZiAoIWNhbGxiYWNrKSB0aHJvdyAnXCJjYWxsYmFja1wiIHBhcmFtZXRlciBpcyBtYW5kYXRvcnkuJztcblxuICAgIGlmIChzb3VyY2VJZCkgcmV0dXJuIGNhbGxiYWNrKHNvdXJjZUlkKTtcblxuICAgIHNjcmVlbkNhbGxiYWNrID0gY2FsbGJhY2s7XG4gICAgd2luZG93LnBvc3RNZXNzYWdlKHtcbiAgICAgICAgJ2dldC1jdXN0b20tc291cmNlSWQnOiBhcnJcbiAgICB9LCAnKicpO1xufVxuXG4vLyB0aGlzIGZ1bmN0aW9uIGNhbiBiZSB1c2VkIHRvIGdldCBcInNvdXJjZS1pZFwiIGZyb20gdGhlIGV4dGVuc2lvblxuZnVuY3Rpb24gZ2V0U291cmNlSWRXaXRoQXVkaW8oY2FsbGJhY2spIHtcbiAgICBpZiAoIWNhbGxiYWNrKSB0aHJvdyAnXCJjYWxsYmFja1wiIHBhcmFtZXRlciBpcyBtYW5kYXRvcnkuJztcbiAgICBpZiAoc291cmNlSWQpIHJldHVybiBjYWxsYmFjayhzb3VyY2VJZCk7XG5cbiAgICBzY3JlZW5DYWxsYmFjayA9IGNhbGxiYWNrO1xuICAgIHdpbmRvdy5wb3N0TWVzc2FnZSgnYXVkaW8tcGx1cy10YWInLCAnKicpO1xufVxuXG5mdW5jdGlvbiBnZXRDaHJvbWVFeHRlbnNpb25TdGF0dXMoZXh0ZW5zaW9uaWQsIGNhbGxiYWNrKSB7XG4gICAgaWYgKGlzRmlyZWZveClcbiAgICAgICAgcmV0dXJuIGNhbGxiYWNrKCdub3QtY2hyb21lJyk7XG4gICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggIT0gMikge1xuICAgICAgICBjYWxsYmFjayA9IGV4dGVuc2lvbmlkO1xuICAgICAgICBleHRlbnNpb25pZCA9ICdsZmNnZmVwYWZub2JkbG9lY2NobmZhY2xpYmVuam9sZCc7IC8vIGRlZmF1bHQgZXh0ZW5zaW9uLWlkXG4gICAgfVxuICAgIHZhciBpbWFnZSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2ltZycpO1xuICAgIGltYWdlLnNyYyA9ICdjaHJvbWUtZXh0ZW5zaW9uOi8vJyArIGV4dGVuc2lvbmlkICsgJy9pY29uLnBuZyc7XG4gICAgaW1hZ2Uub25sb2FkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBjaHJvbWVNZWRpYVNvdXJjZSA9ICdzY3JlZW4nO1xuICAgICAgICB3aW5kb3cucG9zdE1lc3NhZ2UoJ2FyZS15b3UtdGhlcmUnLCAnKicpO1xuICAgICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIGlmIChjaHJvbWVNZWRpYVNvdXJjZSA9PSAnc2NyZWVuJykge1xuICAgICAgICAgICAgICAgIGNhbGxiYWNrKCdpbnN0YWxsZWQtZGlzYWJsZWQnKTtcbiAgICAgICAgICAgIH0gZWxzZVxuICAgICAgICAgICAgICAgIGNhbGxiYWNrKCdpbnN0YWxsZWQtZW5hYmxlZCcpO1xuICAgICAgICB9LCAyMDAwKTtcbiAgICB9O1xuICAgIGltYWdlLm9uZXJyb3IgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGNhbGxiYWNrKCdub3QtaW5zdGFsbGVkJyk7XG4gICAgfTtcbn1cblxuZnVuY3Rpb24gZ2V0U2NyZWVuQ29uc3RyYWludHNXaXRoQXVkaW8oY2FsbGJhY2spIHtcbiAgICBnZXRTY3JlZW5Db25zdHJhaW50cyhjYWxsYmFjaywgdHJ1ZSk7XG59XG5cbi8vIHRoaXMgZnVuY3Rpb24gZXhwbGFpbnMgaG93IHRvIHVzZSBhYm92ZSBtZXRob2RzL29iamVjdHNcbmZ1bmN0aW9uIGdldFNjcmVlbkNvbnN0cmFpbnRzKGNhbGxiYWNrLCBjYXB0dXJlU291cmNlSWRXaXRoQXVkaW8pIHtcbiAgICBzb3VyY2VJZCA9ICcnO1xuICAgIHZhciBmaXJlZm94U2NyZWVuQ29uc3RyYWludHMgPSB7XG4gICAgICAgIG1vek1lZGlhU291cmNlOiAnd2luZG93JyxcbiAgICAgICAgbWVkaWFTb3VyY2U6ICd3aW5kb3cnXG4gICAgfTtcbiAgICBpZiAoaXNGaXJlZm94KVxuICAgICAgICByZXR1cm4gY2FsbGJhY2sobnVsbCwgZmlyZWZveFNjcmVlbkNvbnN0cmFpbnRzKTtcbiAgICAvLyB0aGlzIHN0YXRlbWVudCBkZWZpbmVzIGdldFVzZXJNZWRpYSBjb25zdHJhaW50c1xuICAgIC8vIHRoYXQgd2lsbCBiZSB1c2VkIHRvIGNhcHR1cmUgY29udGVudCBvZiBzY3JlZW5cbiAgICB2YXIgc2NyZWVuX2NvbnN0cmFpbnRzID0ge1xuICAgICAgICBtYW5kYXRvcnk6IHtcbiAgICAgICAgICAgIGNocm9tZU1lZGlhU291cmNlOiBjaHJvbWVNZWRpYVNvdXJjZSxcbiAgICAgICAgICAgIG1heFdpZHRoOiBzY3JlZW4ud2lkdGggPiAxOTIwID8gc2NyZWVuLndpZHRoIDogMTkyMCxcbiAgICAgICAgICAgIG1heEhlaWdodDogc2NyZWVuLmhlaWdodCA+IDEwODAgPyBzY3JlZW4uaGVpZ2h0IDogMTA4MFxuICAgICAgICB9LFxuICAgICAgICBvcHRpb25hbDogW11cbiAgICB9O1xuICAgIC8vIHRoaXMgc3RhdGVtZW50IHZlcmlmaWVzIGNocm9tZSBleHRlbnNpb24gYXZhaWxhYmlsaXR5XG4gICAgLy8gaWYgaW5zdGFsbGVkIGFuZCBhdmFpbGFibGUgdGhlbiBpdCB3aWxsIGludm9rZSBleHRlbnNpb24gQVBJXG4gICAgLy8gb3RoZXJ3aXNlIGl0IHdpbGwgZmFsbGJhY2sgdG8gY29tbWFuZC1saW5lIGJhc2VkIHNjcmVlbiBjYXB0dXJpbmcgQVBJXG4gICAgaWYgKGNocm9tZU1lZGlhU291cmNlID09ICdkZXNrdG9wJyAmJiAhc291cmNlSWQpIHtcbiAgICAgICAgaWYgKGNhcHR1cmVTb3VyY2VJZFdpdGhBdWRpbykge1xuICAgICAgICAgICAgZ2V0U291cmNlSWRXaXRoQXVkaW8oZnVuY3Rpb24gKHNvdXJjZUlkLCBjYW5SZXF1ZXN0QXVkaW9UcmFjaykge1xuICAgICAgICAgICAgICAgIHNjcmVlbl9jb25zdHJhaW50cy5tYW5kYXRvcnkuY2hyb21lTWVkaWFTb3VyY2VJZCA9IHNvdXJjZUlkO1xuXG4gICAgICAgICAgICAgICAgaWYgKGNhblJlcXVlc3RBdWRpb1RyYWNrKSB7XG4gICAgICAgICAgICAgICAgICAgIHNjcmVlbl9jb25zdHJhaW50cy5jYW5SZXF1ZXN0QXVkaW9UcmFjayA9IHRydWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNhbGxiYWNrKHNvdXJjZUlkID09ICdQZXJtaXNzaW9uRGVuaWVkRXJyb3InID8gc291cmNlSWQgOiBudWxsLCBzY3JlZW5fY29uc3RyYWludHMpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBnZXRTb3VyY2VJZChmdW5jdGlvbiAoc291cmNlSWQpIHtcbiAgICAgICAgICAgICAgICBzY3JlZW5fY29uc3RyYWludHMubWFuZGF0b3J5LmNocm9tZU1lZGlhU291cmNlSWQgPSBzb3VyY2VJZDtcbiAgICAgICAgICAgICAgICBjYWxsYmFjayhzb3VyY2VJZCA9PSAnUGVybWlzc2lvbkRlbmllZEVycm9yJyA/IHNvdXJjZUlkIDogbnVsbCwgc2NyZWVuX2NvbnN0cmFpbnRzKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyB0aGlzIHN0YXRlbWVudCBzZXRzIGdldHMgJ3NvdXJjZUlkXCIgYW5kIHNldHMgXCJjaHJvbWVNZWRpYVNvdXJjZUlkXCIgXG4gICAgaWYgKGNocm9tZU1lZGlhU291cmNlID09ICdkZXNrdG9wJykge1xuICAgICAgICBzY3JlZW5fY29uc3RyYWludHMubWFuZGF0b3J5LmNocm9tZU1lZGlhU291cmNlSWQgPSBzb3VyY2VJZDtcbiAgICB9XG5cbiAgICAvLyBub3cgaW52b2tpbmcgbmF0aXZlIGdldFVzZXJNZWRpYSBBUElcbiAgICBjYWxsYmFjayhudWxsLCBzY3JlZW5fY29uc3RyYWludHMpO1xufVxuXG5leHBvcnRzLmdldFNjcmVlbkNvbnN0cmFpbnRzID0gZ2V0U2NyZWVuQ29uc3RyYWludHM7XG5leHBvcnRzLmdldFNjcmVlbkNvbnN0cmFpbnRzV2l0aEF1ZGlvID0gZ2V0U2NyZWVuQ29uc3RyYWludHNXaXRoQXVkaW87XG5leHBvcnRzLmlzQ2hyb21lRXh0ZW5zaW9uQXZhaWxhYmxlID0gaXNDaHJvbWVFeHRlbnNpb25BdmFpbGFibGU7XG5leHBvcnRzLmdldENocm9tZUV4dGVuc2lvblN0YXR1cyA9IGdldENocm9tZUV4dGVuc2lvblN0YXR1cztcbmV4cG9ydHMuZ2V0U291cmNlSWQgPSBnZXRTb3VyY2VJZDsiLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCBmcmVlaWNlID0gcmVxdWlyZSgnZnJlZWljZScpO1xuaW1wb3J0IHV1aWQgPSByZXF1aXJlKCd1dWlkJyk7XG5pbXBvcnQgcGxhdGZvcm0gPSByZXF1aXJlKCdwbGF0Zm9ybScpO1xuXG5cbmV4cG9ydCBpbnRlcmZhY2UgV2ViUnRjUGVlckNvbmZpZ3VyYXRpb24ge1xuICAgIG1lZGlhQ29uc3RyYWludHM6IHtcbiAgICAgICAgYXVkaW86IGJvb2xlYW4sXG4gICAgICAgIHZpZGVvOiBib29sZWFuXG4gICAgfTtcbiAgICBzaW11bGNhc3Q6IGJvb2xlYW47XG4gICAgb25pY2VjYW5kaWRhdGU6IChldmVudCkgPT4gdm9pZDtcbiAgICBpY2VTZXJ2ZXJzOiBSVENJY2VTZXJ2ZXJbXSB8IHVuZGVmaW5lZDtcbiAgICBtZWRpYVN0cmVhbT86IE1lZGlhU3RyZWFtO1xuICAgIG1vZGU/OiBzdHJpbmc7IC8vIHNlbmRvbmx5LCByZWNvbmx5LCBzZW5kcmVjdlxuICAgIGlkPzogc3RyaW5nO1xufVxuXG5leHBvcnQgY2xhc3MgV2ViUnRjUGVlciB7XG5cbiAgICBwYzogUlRDUGVlckNvbm5lY3Rpb247XG4gICAgaWQ6IHN0cmluZztcbiAgICByZW1vdGVDYW5kaWRhdGVzUXVldWU6IFJUQ0ljZUNhbmRpZGF0ZVtdID0gW107XG4gICAgbG9jYWxDYW5kaWRhdGVzUXVldWU6IFJUQ0ljZUNhbmRpZGF0ZVtdID0gW107XG5cbiAgICBpY2VDYW5kaWRhdGVMaXN0OiBSVENJY2VDYW5kaWRhdGVbXSA9IFtdO1xuXG4gICAgcHJpdmF0ZSBjYW5kaWRhdGVnYXRoZXJpbmdkb25lID0gZmFsc2U7XG5cbiAgICBjb25zdHJ1Y3Rvcihwcml2YXRlIGNvbmZpZ3VyYXRpb246IFdlYlJ0Y1BlZXJDb25maWd1cmF0aW9uKSB7XG4gICAgICAgIHRoaXMuY29uZmlndXJhdGlvbi5pY2VTZXJ2ZXJzID0gKCEhdGhpcy5jb25maWd1cmF0aW9uLmljZVNlcnZlcnMgJiYgdGhpcy5jb25maWd1cmF0aW9uLmljZVNlcnZlcnMubGVuZ3RoID4gMCkgPyB0aGlzLmNvbmZpZ3VyYXRpb24uaWNlU2VydmVycyA6IGZyZWVpY2UoKTtcblxuICAgICAgICB0aGlzLnBjID0gbmV3IFJUQ1BlZXJDb25uZWN0aW9uKHsgaWNlU2VydmVyczogdGhpcy5jb25maWd1cmF0aW9uLmljZVNlcnZlcnMgfSk7XG4gICAgICAgIHRoaXMuaWQgPSAhIWNvbmZpZ3VyYXRpb24uaWQgPyBjb25maWd1cmF0aW9uLmlkIDogdXVpZC52NCgpO1xuXG4gICAgICAgIHRoaXMucGMub25pY2VjYW5kaWRhdGUgPSBldmVudCA9PiB7XG4gICAgICAgICAgICBjb25zdCBjYW5kaWRhdGU6IFJUQ0ljZUNhbmRpZGF0ZSA9IGV2ZW50LmNhbmRpZGF0ZTtcbiAgICAgICAgICAgIGlmIChjYW5kaWRhdGUpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmxvY2FsQ2FuZGlkYXRlc1F1ZXVlLnB1c2goPFJUQ0ljZUNhbmRpZGF0ZT57IGNhbmRpZGF0ZTogY2FuZGlkYXRlLmNhbmRpZGF0ZSB9KTtcbiAgICAgICAgICAgICAgICB0aGlzLmNhbmRpZGF0ZWdhdGhlcmluZ2RvbmUgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB0aGlzLmNvbmZpZ3VyYXRpb24ub25pY2VjYW5kaWRhdGUoZXZlbnQuY2FuZGlkYXRlKTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoIXRoaXMuY2FuZGlkYXRlZ2F0aGVyaW5nZG9uZSkge1xuICAgICAgICAgICAgICAgIHRoaXMuY2FuZGlkYXRlZ2F0aGVyaW5nZG9uZSA9IHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG5cbiAgICAgICAgdGhpcy5wYy5vbnNpZ25hbGluZ3N0YXRlY2hhbmdlID0gKCkgPT4ge1xuICAgICAgICAgICAgaWYgKHRoaXMucGMuc2lnbmFsaW5nU3RhdGUgPT09ICdzdGFibGUnKSB7XG4gICAgICAgICAgICAgICAgd2hpbGUgKHRoaXMuaWNlQ2FuZGlkYXRlTGlzdC5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMucGMuYWRkSWNlQ2FuZGlkYXRlKDxSVENJY2VDYW5kaWRhdGU+dGhpcy5pY2VDYW5kaWRhdGVMaXN0LnNoaWZ0KCkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcblxuICAgICAgICB0aGlzLnN0YXJ0KCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhpcyBmdW5jdGlvbiBjcmVhdGVzIHRoZSBSVENQZWVyQ29ubmVjdGlvbiBvYmplY3QgdGFraW5nIGludG8gYWNjb3VudCB0aGVcbiAgICAgKiBwcm9wZXJ0aWVzIHJlY2VpdmVkIGluIHRoZSBjb25zdHJ1Y3Rvci4gSXQgc3RhcnRzIHRoZSBTRFAgbmVnb3RpYXRpb25cbiAgICAgKiBwcm9jZXNzOiBnZW5lcmF0ZXMgdGhlIFNEUCBvZmZlciBhbmQgaW52b2tlcyB0aGUgb25zZHBvZmZlciBjYWxsYmFjay4gVGhpc1xuICAgICAqIGNhbGxiYWNrIGlzIGV4cGVjdGVkIHRvIHNlbmQgdGhlIFNEUCBvZmZlciwgaW4gb3JkZXIgdG8gb2J0YWluIGFuIFNEUFxuICAgICAqIGFuc3dlciBmcm9tIGFub3RoZXIgcGVlci5cbiAgICAgKi9cbiAgICBzdGFydCgpOiBQcm9taXNlPGFueT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgaWYgKHRoaXMucGMuc2lnbmFsaW5nU3RhdGUgPT09ICdjbG9zZWQnKSB7XG4gICAgICAgICAgICAgICAgcmVqZWN0KCdUaGUgcGVlciBjb25uZWN0aW9uIG9iamVjdCBpcyBpbiBcImNsb3NlZFwiIHN0YXRlLiBUaGlzIGlzIG1vc3QgbGlrZWx5IGR1ZSB0byBhbiBpbnZvY2F0aW9uIG9mIHRoZSBkaXNwb3NlIG1ldGhvZCBiZWZvcmUgYWNjZXB0aW5nIGluIHRoZSBkaWFsb2d1ZScpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCEhdGhpcy5jb25maWd1cmF0aW9uLm1lZGlhU3RyZWFtKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5wYy5hZGRTdHJlYW0odGhpcy5jb25maWd1cmF0aW9uLm1lZGlhU3RyZWFtKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gW0hhY2tdIGh0dHBzOi8vY29kZS5nb29nbGUuY29tL3AvY2hyb21pdW0vaXNzdWVzL2RldGFpbD9pZD00NDM1NThcbiAgICAgICAgICAgIGlmICh0aGlzLmNvbmZpZ3VyYXRpb24ubW9kZSA9PT0gJ3NlbmRvbmx5JyAmJlxuICAgICAgICAgICAgICAgIChwbGF0Zm9ybS5uYW1lID09PSAnQ2hyb21lJyAmJiBwbGF0Zm9ybS52ZXJzaW9uIS50b1N0cmluZygpLnN1YnN0cmluZygwLCAyKSA9PT0gJzM5JykpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmNvbmZpZ3VyYXRpb24ubW9kZSA9ICdzZW5kcmVjdic7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhpcyBtZXRob2QgZnJlZXMgdGhlIHJlc291cmNlcyB1c2VkIGJ5IFdlYlJ0Y1BlZXJcbiAgICAgKi9cbiAgICBkaXNwb3NlKCkge1xuICAgICAgICBjb25zb2xlLmRlYnVnKCdEaXNwb3NpbmcgV2ViUnRjUGVlcicpO1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgaWYgKHRoaXMucGMpIHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5wYy5zaWduYWxpbmdTdGF0ZSA9PT0gJ2Nsb3NlZCcpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLnJlbW90ZUNhbmRpZGF0ZXNRdWV1ZSA9IFtdO1xuICAgICAgICAgICAgICAgIHRoaXMubG9jYWxDYW5kaWRhdGVzUXVldWUgPSBbXTtcblxuICAgICAgICAgICAgICAgIHRoaXMucGMuZ2V0TG9jYWxTdHJlYW1zKCkuZm9yRWFjaChzdHIgPT4ge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbVN0b3Aoc3RyKTtcbiAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAgIC8vIEZJWE1FIFRoaXMgaXMgbm90IHlldCBpbXBsZW1lbnRlZCBpbiBmaXJlZm94XG4gICAgICAgICAgICAgICAgLy8gaWYodmlkZW9TdHJlYW0pIHBjLnJlbW92ZVN0cmVhbSh2aWRlb1N0cmVhbSk7XG4gICAgICAgICAgICAgICAgLy8gaWYoYXVkaW9TdHJlYW0pIHBjLnJlbW92ZVN0cmVhbShhdWRpb1N0cmVhbSk7XG5cbiAgICAgICAgICAgICAgICB0aGlzLnBjLmNsb3NlKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgY29uc29sZS53YXJuKCdFeGNlcHRpb24gZGlzcG9zaW5nIHdlYnJ0YyBwZWVyICcgKyBlcnIpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogMSkgRnVuY3Rpb24gdGhhdCBjcmVhdGVzIGFuIG9mZmVyLCBzZXRzIGl0IGFzIGxvY2FsIGRlc2NyaXB0aW9uIGFuZCByZXR1cm5zIHRoZSBvZmZlciBwYXJhbVxuICAgICAqIHRvIHNlbmQgdG8gT3BlblZpZHUgU2VydmVyICh3aWxsIGJlIHRoZSByZW1vdGUgZGVzY3JpcHRpb24gb2Ygb3RoZXIgcGVlcilcbiAgICAgKi9cbiAgICBnZW5lcmF0ZU9mZmVyKCk6IFByb21pc2U8c3RyaW5nPiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICBsZXQgb2ZmZXJBdWRpbywgb2ZmZXJWaWRlbyA9IHRydWU7XG5cbiAgICAgICAgICAgIC8vIENvbnN0cmFpbnRzIG11c3QgaGF2ZSBib3RoIGJsb2Nrc1xuICAgICAgICAgICAgaWYgKCEhdGhpcy5jb25maWd1cmF0aW9uLm1lZGlhQ29uc3RyYWludHMpIHtcbiAgICAgICAgICAgICAgICBvZmZlckF1ZGlvID0gKHR5cGVvZiB0aGlzLmNvbmZpZ3VyYXRpb24ubWVkaWFDb25zdHJhaW50cy5hdWRpbyA9PT0gJ2Jvb2xlYW4nKSA/XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuY29uZmlndXJhdGlvbi5tZWRpYUNvbnN0cmFpbnRzLmF1ZGlvIDogdHJ1ZTtcbiAgICAgICAgICAgICAgICBvZmZlclZpZGVvID0gKHR5cGVvZiB0aGlzLmNvbmZpZ3VyYXRpb24ubWVkaWFDb25zdHJhaW50cy52aWRlbyA9PT0gJ2Jvb2xlYW4nKSA/XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuY29uZmlndXJhdGlvbi5tZWRpYUNvbnN0cmFpbnRzLnZpZGVvIDogdHJ1ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgY29uc3QgY29uc3RyYWludHM6IFJUQ09mZmVyT3B0aW9ucyA9IHtcbiAgICAgICAgICAgICAgICBvZmZlclRvUmVjZWl2ZUF1ZGlvOiArICh0aGlzLmNvbmZpZ3VyYXRpb24ubW9kZSAhPT0gJ3NlbmRvbmx5JyAmJiBvZmZlckF1ZGlvKSxcbiAgICAgICAgICAgICAgICBvZmZlclRvUmVjZWl2ZVZpZGVvOiArICh0aGlzLmNvbmZpZ3VyYXRpb24ubW9kZSAhPT0gJ3NlbmRvbmx5JyAmJiBvZmZlclZpZGVvKVxuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgY29uc29sZS5kZWJ1ZygnUlRDUGVlckNvbm5lY3Rpb24gY29uc3RyYWludHM6ICcgKyBKU09OLnN0cmluZ2lmeShjb25zdHJhaW50cykpO1xuXG4gICAgICAgICAgICB0aGlzLnBjLmNyZWF0ZU9mZmVyKGNvbnN0cmFpbnRzKS50aGVuKG9mZmVyID0+IHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmRlYnVnKCdDcmVhdGVkIFNEUCBvZmZlcicpO1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLnBjLnNldExvY2FsRGVzY3JpcHRpb24ob2ZmZXIpO1xuICAgICAgICAgICAgfSkudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3QgbG9jYWxEZXNjcmlwdGlvbiA9IHRoaXMucGMubG9jYWxEZXNjcmlwdGlvbjtcbiAgICAgICAgICAgICAgICBpZiAoISFsb2NhbERlc2NyaXB0aW9uKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZGVidWcoJ0xvY2FsIGRlc2NyaXB0aW9uIHNldCcsIGxvY2FsRGVzY3JpcHRpb24uc2RwKTtcbiAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSg8c3RyaW5nPmxvY2FsRGVzY3JpcHRpb24uc2RwKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICByZWplY3QoJ0xvY2FsIGRlc2NyaXB0aW9uIGlzIG5vdCBkZWZpbmVkJyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSkuY2F0Y2goZXJyb3IgPT4gcmVqZWN0KGVycm9yKSk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIDIpIEZ1bmN0aW9uIHRvIGludm9rZSB3aGVuIGEgU0RQIG9mZmVyIGlzIHJlY2VpdmVkLiBTZXRzIGl0IGFzIHJlbW90ZSBkZXNjcmlwdGlvbixcbiAgICAgKiBnZW5lcmF0ZXMgYW5kIGFuc3dlciBhbmQgcmV0dXJucyBpdCB0byBzZW5kIGl0IHRvIE9wZW5WaWR1IFNlcnZlclxuICAgICAqL1xuICAgIHByb2Nlc3NPZmZlcihzZHBPZmZlcjogc3RyaW5nKTogUHJvbWlzZTxDb25zdHJhaW5ET01TdHJpbmc+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IG9mZmVyOiBSVENTZXNzaW9uRGVzY3JpcHRpb25Jbml0ID0ge1xuICAgICAgICAgICAgICAgIHR5cGU6ICdvZmZlcicsXG4gICAgICAgICAgICAgICAgc2RwOiBzZHBPZmZlclxuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgY29uc29sZS5kZWJ1ZygnU0RQIG9mZmVyIHJlY2VpdmVkLCBzZXR0aW5nIHJlbW90ZSBkZXNjcmlwdGlvbicpO1xuXG4gICAgICAgICAgICBpZiAodGhpcy5wYy5zaWduYWxpbmdTdGF0ZSA9PT0gJ2Nsb3NlZCcpIHtcbiAgICAgICAgICAgICAgICByZWplY3QoJ1BlZXJDb25uZWN0aW9uIGlzIGNsb3NlZCcpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLnBjLnNldFJlbW90ZURlc2NyaXB0aW9uKG9mZmVyKVxuICAgICAgICAgICAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMucGMuY3JlYXRlQW5zd2VyKCk7XG4gICAgICAgICAgICAgICAgfSkudGhlbihhbnN3ZXIgPT4ge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmRlYnVnKCdDcmVhdGVkIFNEUCBhbnN3ZXInKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMucGMuc2V0TG9jYWxEZXNjcmlwdGlvbihhbnN3ZXIpO1xuICAgICAgICAgICAgICAgIH0pLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBsb2NhbERlc2NyaXB0aW9uID0gdGhpcy5wYy5sb2NhbERlc2NyaXB0aW9uO1xuICAgICAgICAgICAgICAgICAgICBpZiAoISFsb2NhbERlc2NyaXB0aW9uKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmRlYnVnKCdMb2NhbCBkZXNjcmlwdGlvbiBzZXQnLCBsb2NhbERlc2NyaXB0aW9uLnNkcCk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXNvbHZlKDxzdHJpbmc+bG9jYWxEZXNjcmlwdGlvbi5zZHApO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KCdMb2NhbCBkZXNjcmlwdGlvbiBpcyBub3QgZGVmaW5lZCcpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSkuY2F0Y2goZXJyb3IgPT4gcmVqZWN0KGVycm9yKSk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIDMpIEZ1bmN0aW9uIGludm9rZWQgd2hlbiBhIFNEUCBhbnN3ZXIgaXMgcmVjZWl2ZWQuIEZpbmFsIHN0ZXAgaW4gU0RQIG5lZ290aWF0aW9uLCB0aGUgcGVlclxuICAgICAqIGp1c3QgbmVlZHMgdG8gc2V0IHRoZSBhbnN3ZXIgYXMgaXRzIHJlbW90ZSBkZXNjcmlwdGlvblxuICAgICAqL1xuICAgIHByb2Nlc3NBbnN3ZXIoc2RwQW5zd2VyOiBzdHJpbmcpOiBQcm9taXNlPHN0cmluZz4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuXG4gICAgICAgICAgICBjb25zdCBhbnN3ZXI6IFJUQ1Nlc3Npb25EZXNjcmlwdGlvbkluaXQgPSB7XG4gICAgICAgICAgICAgICAgdHlwZTogJ2Fuc3dlcicsXG4gICAgICAgICAgICAgICAgc2RwOiBzZHBBbnN3ZXJcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIGNvbnNvbGUuZGVidWcoJ1NEUCBhbnN3ZXIgcmVjZWl2ZWQsIHNldHRpbmcgcmVtb3RlIGRlc2NyaXB0aW9uJyk7XG5cbiAgICAgICAgICAgIGlmICh0aGlzLnBjLnNpZ25hbGluZ1N0YXRlID09PSAnY2xvc2VkJykge1xuICAgICAgICAgICAgICAgIHJlamVjdCgnUlRDUGVlckNvbm5lY3Rpb24gaXMgY2xvc2VkJyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMucGMuc2V0UmVtb3RlRGVzY3JpcHRpb24oYW5zd2VyKS50aGVuKCgpID0+IHJlc29sdmUoKSkuY2F0Y2goZXJyb3IgPT4gcmVqZWN0KGVycm9yKSk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENhbGxiYWNrIGZ1bmN0aW9uIGludm9rZWQgd2hlbiBhbiBJQ0UgY2FuZGlkYXRlIGlzIHJlY2VpdmVkXG4gICAgICovXG4gICAgYWRkSWNlQ2FuZGlkYXRlKGljZUNhbmRpZGF0ZTogUlRDSWNlQ2FuZGlkYXRlKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICBjb25zb2xlLmRlYnVnKCdSZW1vdGUgSUNFIGNhbmRpZGF0ZSByZWNlaXZlZCcsIGljZUNhbmRpZGF0ZSk7XG4gICAgICAgICAgICB0aGlzLnJlbW90ZUNhbmRpZGF0ZXNRdWV1ZS5wdXNoKGljZUNhbmRpZGF0ZSk7XG4gICAgICAgICAgICBzd2l0Y2ggKHRoaXMucGMuc2lnbmFsaW5nU3RhdGUpIHtcbiAgICAgICAgICAgICAgICBjYXNlICdjbG9zZWQnOlxuICAgICAgICAgICAgICAgICAgICByZWplY3QobmV3IEVycm9yKCdQZWVyQ29ubmVjdGlvbiBvYmplY3QgaXMgY2xvc2VkJykpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlICdzdGFibGUnOlxuICAgICAgICAgICAgICAgICAgICBpZiAoISF0aGlzLnBjLnJlbW90ZURlc2NyaXB0aW9uKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnBjLmFkZEljZUNhbmRpZGF0ZShpY2VDYW5kaWRhdGUpLnRoZW4oKCkgPT4gcmVzb2x2ZSgpKS5jYXRjaChlcnJvciA9PiByZWplY3QoZXJyb3IpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICB0aGlzLmljZUNhbmRpZGF0ZUxpc3QucHVzaChpY2VDYW5kaWRhdGUpO1xuICAgICAgICAgICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIHByaXZhdGUgc3RyZWFtU3RvcChzdHJlYW06IE1lZGlhU3RyZWFtKTogdm9pZCB7XG4gICAgICAgIHN0cmVhbS5nZXRUcmFja3MoKS5mb3JFYWNoKHRyYWNrID0+IHtcbiAgICAgICAgICAgIHRyYWNrLnN0b3AoKTtcbiAgICAgICAgICAgIHN0cmVhbS5yZW1vdmVUcmFjayh0cmFjayk7XG4gICAgICAgIH0pO1xuICAgIH1cbn1cblxuXG5leHBvcnQgY2xhc3MgV2ViUnRjUGVlclJlY3Zvbmx5IGV4dGVuZHMgV2ViUnRjUGVlciB7XG4gICAgY29uc3RydWN0b3IoY29uZmlndXJhdGlvbjogV2ViUnRjUGVlckNvbmZpZ3VyYXRpb24pIHtcbiAgICAgICAgY29uZmlndXJhdGlvbi5tb2RlID0gJ3JlY3Zvbmx5JztcbiAgICAgICAgc3VwZXIoY29uZmlndXJhdGlvbik7XG4gICAgfVxufVxuXG5leHBvcnQgY2xhc3MgV2ViUnRjUGVlclNlbmRvbmx5IGV4dGVuZHMgV2ViUnRjUGVlciB7XG4gICAgY29uc3RydWN0b3IoY29uZmlndXJhdGlvbjogV2ViUnRjUGVlckNvbmZpZ3VyYXRpb24pIHtcbiAgICAgICAgY29uZmlndXJhdGlvbi5tb2RlID0gJ3NlbmRvbmx5JztcbiAgICAgICAgc3VwZXIoY29uZmlndXJhdGlvbik7XG4gICAgfVxufVxuXG5leHBvcnQgY2xhc3MgV2ViUnRjUGVlclNlbmRyZWN2IGV4dGVuZHMgV2ViUnRjUGVlciB7XG4gICAgY29uc3RydWN0b3IoY29uZmlndXJhdGlvbjogV2ViUnRjUGVlckNvbmZpZ3VyYXRpb24pIHtcbiAgICAgICAgY29uZmlndXJhdGlvbi5tb2RlID0gJ3NlbmRyZWN2JztcbiAgICAgICAgc3VwZXIoY29uZmlndXJhdGlvbik7XG4gICAgfVxufSIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTctMjAxOCBPcGVuVmlkdSAoaHR0cHM6Ly9vcGVudmlkdS5pby8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuLy8gdHNsaW50OmRpc2FibGU6bm8tc3RyaW5nLWxpdGVyYWxcblxuaW1wb3J0IHsgU3RyZWFtIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvU3RyZWFtJztcbmltcG9ydCBwbGF0Zm9ybSA9IHJlcXVpcmUoJ3BsYXRmb3JtJyk7XG5cbmV4cG9ydCBjbGFzcyBXZWJSdGNTdGF0cyB7XG5cbiAgICBwcml2YXRlIHdlYlJ0Y1N0YXRzRW5hYmxlZCA9IGZhbHNlO1xuICAgIHByaXZhdGUgd2ViUnRjU3RhdHNJbnRlcnZhbElkOiBOb2RlSlMuVGltZXI7XG4gICAgcHJpdmF0ZSBzdGF0c0ludGVydmFsID0gMTtcbiAgICBwcml2YXRlIHN0YXRzOiBhbnkgPSB7XG4gICAgICAgIGluYm91bmQ6IHtcbiAgICAgICAgICAgIGF1ZGlvOiB7XG4gICAgICAgICAgICAgICAgYnl0ZXNSZWNlaXZlZDogMCxcbiAgICAgICAgICAgICAgICBwYWNrZXRzUmVjZWl2ZWQ6IDAsXG4gICAgICAgICAgICAgICAgcGFja2V0c0xvc3Q6IDBcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB2aWRlbzoge1xuICAgICAgICAgICAgICAgIGJ5dGVzUmVjZWl2ZWQ6IDAsXG4gICAgICAgICAgICAgICAgcGFja2V0c1JlY2VpdmVkOiAwLFxuICAgICAgICAgICAgICAgIHBhY2tldHNMb3N0OiAwLFxuICAgICAgICAgICAgICAgIGZyYW1lc0RlY29kZWQ6IDAsXG4gICAgICAgICAgICAgICAgbmFja0NvdW50OiAwXG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIG91dGJvdW5kOiB7XG4gICAgICAgICAgICBhdWRpbzoge1xuICAgICAgICAgICAgICAgIGJ5dGVzU2VudDogMCxcbiAgICAgICAgICAgICAgICBwYWNrZXRzU2VudDogMCxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB2aWRlbzoge1xuICAgICAgICAgICAgICAgIGJ5dGVzU2VudDogMCxcbiAgICAgICAgICAgICAgICBwYWNrZXRzU2VudDogMCxcbiAgICAgICAgICAgICAgICBmcmFtZXNFbmNvZGVkOiAwLFxuICAgICAgICAgICAgICAgIG5hY2tDb3VudDogMFxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfTtcblxuICAgIGNvbnN0cnVjdG9yKHByaXZhdGUgc3RyZWFtOiBTdHJlYW0pIHsgfVxuXG4gICAgcHVibGljIGlzRW5hYmxlZCgpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuIHRoaXMud2ViUnRjU3RhdHNFbmFibGVkO1xuICAgIH1cblxuICAgIHB1YmxpYyBpbml0V2ViUnRjU3RhdHMoKTogdm9pZCB7XG5cbiAgICAgICAgY29uc3QgZWxhc3Rlc3RJbnN0cnVtZW50YXRpb24gPSBsb2NhbFN0b3JhZ2UuZ2V0SXRlbSgnZWxhc3Rlc3QtaW5zdHJ1bWVudGF0aW9uJyk7XG5cbiAgICAgICAgaWYgKGVsYXN0ZXN0SW5zdHJ1bWVudGF0aW9uKSB7XG4gICAgICAgICAgICAvLyBFbGFzVGVzdCBpbnN0cnVtZW50YXRpb24gb2JqZWN0IGZvdW5kIGluIGxvY2FsIHN0b3JhZ2VcblxuICAgICAgICAgICAgY29uc29sZS53YXJuKCdXZWJSdGMgc3RhdHMgZW5hYmxlZCBmb3Igc3RyZWFtICcgKyB0aGlzLnN0cmVhbS5zdHJlYW1JZCArICcgb2YgY29ubmVjdGlvbiAnICsgdGhpcy5zdHJlYW0uY29ubmVjdGlvbi5jb25uZWN0aW9uSWQpO1xuXG4gICAgICAgICAgICB0aGlzLndlYlJ0Y1N0YXRzRW5hYmxlZCA9IHRydWU7XG5cbiAgICAgICAgICAgIGNvbnN0IGluc3RydW1lbnRhdGlvbiA9IEpTT04ucGFyc2UoZWxhc3Rlc3RJbnN0cnVtZW50YXRpb24pO1xuICAgICAgICAgICAgdGhpcy5zdGF0c0ludGVydmFsID0gaW5zdHJ1bWVudGF0aW9uLndlYnJ0Yy5pbnRlcnZhbDsgIC8vIEludGVydmFsIGluIHNlY29uZHNcblxuICAgICAgICAgICAgY29uc29sZS53YXJuKCdsb2NhbFN0b3JhZ2UgaXRlbTogJyArIEpTT04uc3RyaW5naWZ5KGluc3RydW1lbnRhdGlvbikpO1xuXG4gICAgICAgICAgICB0aGlzLndlYlJ0Y1N0YXRzSW50ZXJ2YWxJZCA9IHNldEludGVydmFsKCgpID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLnNlbmRTdGF0c1RvSHR0cEVuZHBvaW50KGluc3RydW1lbnRhdGlvbik7XG4gICAgICAgICAgICB9LCB0aGlzLnN0YXRzSW50ZXJ2YWwgKiAxMDAwKTtcblxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc29sZS5kZWJ1ZygnV2ViUnRjIHN0YXRzIG5vdCBlbmFibGVkJyk7XG4gICAgfVxuXG4gICAgcHVibGljIHN0b3BXZWJSdGNTdGF0cygpIHtcbiAgICAgICAgaWYgKHRoaXMud2ViUnRjU3RhdHNFbmFibGVkKSB7XG4gICAgICAgICAgICBjbGVhckludGVydmFsKHRoaXMud2ViUnRjU3RhdHNJbnRlcnZhbElkKTtcbiAgICAgICAgICAgIGNvbnNvbGUud2FybignV2ViUnRjIHN0YXRzIHN0b3BwZWQgZm9yIGRpc3Bvc2VkIHN0cmVhbSAnICsgdGhpcy5zdHJlYW0uc3RyZWFtSWQgKyAnIG9mIGNvbm5lY3Rpb24gJyArIHRoaXMuc3RyZWFtLmNvbm5lY3Rpb24uY29ubmVjdGlvbklkKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHB1YmxpYyBnZXRTZWxlY3RlZEljZUNhbmRpZGF0ZUluZm8oKTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIHRoaXMuZ2V0U3RhdHNBZ25vc3RpYyh0aGlzLnN0cmVhbS5nZXRSVENQZWVyQ29ubmVjdGlvbigpLFxuICAgICAgICAgICAgICAgIChzdGF0cykgPT4ge1xuICAgICAgICAgICAgICAgICAgICBpZiAoKHBsYXRmb3JtLm5hbWUhLmluZGV4T2YoJ0Nocm9tZScpICE9PSAtMSkgfHwgKHBsYXRmb3JtLm5hbWUhLmluZGV4T2YoJ09wZXJhJykgIT09IC0xKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGxvY2FsQ2FuZGlkYXRlSWQsIHJlbW90ZUNhbmRpZGF0ZUlkLCBnb29nQ2FuZGlkYXRlUGFpcjtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGxvY2FsQ2FuZGlkYXRlcyA9IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgcmVtb3RlQ2FuZGlkYXRlcyA9IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChjb25zdCBrZXkgaW4gc3RhdHMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBzdGF0ID0gc3RhdHNba2V5XTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoc3RhdC50eXBlID09PSAnbG9jYWxjYW5kaWRhdGUnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxvY2FsQ2FuZGlkYXRlc1tzdGF0LmlkXSA9IHN0YXQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChzdGF0LnR5cGUgPT09ICdyZW1vdGVjYW5kaWRhdGUnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlbW90ZUNhbmRpZGF0ZXNbc3RhdC5pZF0gPSBzdGF0O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoc3RhdC50eXBlID09PSAnZ29vZ0NhbmRpZGF0ZVBhaXInICYmIChzdGF0Lmdvb2dBY3RpdmVDb25uZWN0aW9uID09PSAndHJ1ZScpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdvb2dDYW5kaWRhdGVQYWlyID0gc3RhdDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbG9jYWxDYW5kaWRhdGVJZCA9IHN0YXQubG9jYWxDYW5kaWRhdGVJZDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3RlQ2FuZGlkYXRlSWQgPSBzdGF0LnJlbW90ZUNhbmRpZGF0ZUlkO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBmaW5hbExvY2FsQ2FuZGlkYXRlID0gbG9jYWxDYW5kaWRhdGVzW2xvY2FsQ2FuZGlkYXRlSWRdO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCEhZmluYWxMb2NhbENhbmRpZGF0ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGNhbmRMaXN0ID0gdGhpcy5zdHJlYW0uZ2V0TG9jYWxJY2VDYW5kaWRhdGVMaXN0KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgY2FuZCA9IGNhbmRMaXN0LmZpbHRlcigoYzogUlRDSWNlQ2FuZGlkYXRlKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAoISFjLmNhbmRpZGF0ZSAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5jYW5kaWRhdGUuaW5kZXhPZihmaW5hbExvY2FsQ2FuZGlkYXRlLmlwQWRkcmVzcykgPj0gMCAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5jYW5kaWRhdGUuaW5kZXhPZihmaW5hbExvY2FsQ2FuZGlkYXRlLnBvcnROdW1iZXIpID49IDAgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuY2FuZGlkYXRlLmluZGV4T2YoZmluYWxMb2NhbENhbmRpZGF0ZS5wcmlvcml0eSkgPj0gMCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZmluYWxMb2NhbENhbmRpZGF0ZS5yYXcgPSAhIWNhbmRbMF0gPyBjYW5kWzBdLmNhbmRpZGF0ZSA6ICdFUlJPUjogQ2Fubm90IGZpbmQgbG9jYWwgY2FuZGlkYXRlIGluIGxpc3Qgb2Ygc2VudCBJQ0UgY2FuZGlkYXRlcyc7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbmFsTG9jYWxDYW5kaWRhdGUgPSAnRVJST1I6IE5vIGFjdGl2ZSBsb2NhbCBJQ0UgY2FuZGlkYXRlLiBQcm9iYWJseSBJQ0UtVENQIGlzIGJlaW5nIHVzZWQnO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICBsZXQgZmluYWxSZW1vdGVDYW5kaWRhdGUgPSByZW1vdGVDYW5kaWRhdGVzW3JlbW90ZUNhbmRpZGF0ZUlkXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghIWZpbmFsUmVtb3RlQ2FuZGlkYXRlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgY2FuZExpc3QgPSB0aGlzLnN0cmVhbS5nZXRSZW1vdGVJY2VDYW5kaWRhdGVMaXN0KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgY2FuZCA9IGNhbmRMaXN0LmZpbHRlcigoYzogUlRDSWNlQ2FuZGlkYXRlKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAoISFjLmNhbmRpZGF0ZSAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5jYW5kaWRhdGUuaW5kZXhPZihmaW5hbFJlbW90ZUNhbmRpZGF0ZS5pcEFkZHJlc3MpID49IDAgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuY2FuZGlkYXRlLmluZGV4T2YoZmluYWxSZW1vdGVDYW5kaWRhdGUucG9ydE51bWJlcikgPj0gMCAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5jYW5kaWRhdGUuaW5kZXhPZihmaW5hbFJlbW90ZUNhbmRpZGF0ZS5wcmlvcml0eSkgPj0gMCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZmluYWxSZW1vdGVDYW5kaWRhdGUucmF3ID0gISFjYW5kWzBdID8gY2FuZFswXS5jYW5kaWRhdGUgOiAnRVJST1I6IENhbm5vdCBmaW5kIHJlbW90ZSBjYW5kaWRhdGUgaW4gbGlzdCBvZiByZWNlaXZlZCBJQ0UgY2FuZGlkYXRlcyc7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbmFsUmVtb3RlQ2FuZGlkYXRlID0gJ0VSUk9SOiBObyBhY3RpdmUgcmVtb3RlIElDRSBjYW5kaWRhdGUuIFByb2JhYmx5IElDRS1UQ1AgaXMgYmVpbmcgdXNlZCc7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdvb2dDYW5kaWRhdGVQYWlyLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxvY2FsQ2FuZGlkYXRlOiBmaW5hbExvY2FsQ2FuZGlkYXRlLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlbW90ZUNhbmRpZGF0ZTogZmluYWxSZW1vdGVDYW5kaWRhdGVcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KCdTZWxlY3RlZCBJQ0UgY2FuZGlkYXRlIGluZm8gb25seSBhdmFpbGFibGUgZm9yIENocm9tZScpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAoZXJyb3IpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBzZW5kU3RhdHNUb0h0dHBFbmRwb2ludChpbnN0cnVtZW50YXRpb24pOiB2b2lkIHtcblxuICAgICAgICBjb25zdCBzZW5kUG9zdCA9IChqc29uKSA9PiB7XG4gICAgICAgICAgICBjb25zdCBodHRwOiBYTUxIdHRwUmVxdWVzdCA9IG5ldyBYTUxIdHRwUmVxdWVzdCgpO1xuICAgICAgICAgICAgY29uc3QgdXJsOiBzdHJpbmcgPSBpbnN0cnVtZW50YXRpb24ud2VicnRjLmh0dHBFbmRwb2ludDtcbiAgICAgICAgICAgIGh0dHAub3BlbignUE9TVCcsIHVybCwgdHJ1ZSk7XG5cbiAgICAgICAgICAgIGh0dHAuc2V0UmVxdWVzdEhlYWRlcignQ29udGVudC10eXBlJywgJ2FwcGxpY2F0aW9uL2pzb24nKTtcblxuICAgICAgICAgICAgaHR0cC5vbnJlYWR5c3RhdGVjaGFuZ2UgPSAoKSA9PiB7IC8vIENhbGwgYSBmdW5jdGlvbiB3aGVuIHRoZSBzdGF0ZSBjaGFuZ2VzLlxuICAgICAgICAgICAgICAgIGlmIChodHRwLnJlYWR5U3RhdGUgPT09IDQgJiYgaHR0cC5zdGF0dXMgPT09IDIwMCkge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmxvZygnV2ViUnRjIHN0YXRzIHN1Y2Nlc3NmdWxseSBzZW50IHRvICcgKyB1cmwgKyAnIGZvciBzdHJlYW0gJyArIHRoaXMuc3RyZWFtLnN0cmVhbUlkICsgJyBvZiBjb25uZWN0aW9uICcgKyB0aGlzLnN0cmVhbS5jb25uZWN0aW9uLmNvbm5lY3Rpb25JZCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGh0dHAuc2VuZChqc29uKTtcbiAgICAgICAgfTtcblxuICAgICAgICBjb25zdCBmID0gKHN0YXRzKSA9PiB7XG5cbiAgICAgICAgICAgIGlmIChwbGF0Zm9ybS5uYW1lIS5pbmRleE9mKCdGaXJlZm94JykgIT09IC0xKSB7XG4gICAgICAgICAgICAgICAgc3RhdHMuZm9yRWFjaCgoc3RhdCkgPT4ge1xuXG4gICAgICAgICAgICAgICAgICAgIGxldCBqc29uID0ge307XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKChzdGF0LnR5cGUgPT09ICdpbmJvdW5kLXJ0cCcpICYmXG4gICAgICAgICAgICAgICAgICAgICAgICAoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gQXZvaWQgZmlyZWZveCBlbXB0eSBvdXRib3VuZC1ydHAgc3RhdGlzdGljc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0YXQubmFja0NvdW50ICE9PSBudWxsICYmXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhdC5pc1JlbW90ZSA9PT0gZmFsc2UgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGF0LmlkLnN0YXJ0c1dpdGgoJ2luYm91bmQnKSAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0YXQucmVtb3RlSWQuc3RhcnRzV2l0aCgnaW5ib3VuZCcpXG4gICAgICAgICAgICAgICAgICAgICAgICApKSB7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG1ldHJpY0lkID0gJ3dlYnJ0Y19pbmJvdW5kXycgKyBzdGF0Lm1lZGlhVHlwZSArICdfJyArIHN0YXQuc3NyYztcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGppdCA9IHN0YXQuaml0dGVyICogMTAwMDtcblxuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgbWV0cmljcyA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBieXRlc1JlY2VpdmVkOiAoc3RhdC5ieXRlc1JlY2VpdmVkIC0gdGhpcy5zdGF0cy5pbmJvdW5kW3N0YXQubWVkaWFUeXBlXS5ieXRlc1JlY2VpdmVkKSAvIHRoaXMuc3RhdHNJbnRlcnZhbCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBqaXR0ZXI6IGppdCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYWNrZXRzUmVjZWl2ZWQ6IChzdGF0LnBhY2tldHNSZWNlaXZlZCAtIHRoaXMuc3RhdHMuaW5ib3VuZFtzdGF0Lm1lZGlhVHlwZV0ucGFja2V0c1JlY2VpdmVkKSAvIHRoaXMuc3RhdHNJbnRlcnZhbCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYWNrZXRzTG9zdDogKHN0YXQucGFja2V0c0xvc3QgLSB0aGlzLnN0YXRzLmluYm91bmRbc3RhdC5tZWRpYVR5cGVdLnBhY2tldHNMb3N0KSAvIHRoaXMuc3RhdHNJbnRlcnZhbFxuICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHVuaXRzID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ5dGVzUmVjZWl2ZWQ6ICdieXRlcycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaml0dGVyOiAnbXMnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhY2tldHNSZWNlaXZlZDogJ3BhY2tldHMnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhY2tldHNMb3N0OiAncGFja2V0cydcbiAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoc3RhdC5tZWRpYVR5cGUgPT09ICd2aWRlbycpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXRyaWNzWydmcmFtZXNEZWNvZGVkJ10gPSAoc3RhdC5mcmFtZXNEZWNvZGVkIC0gdGhpcy5zdGF0cy5pbmJvdW5kLnZpZGVvLmZyYW1lc0RlY29kZWQpIC8gdGhpcy5zdGF0c0ludGVydmFsO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1ldHJpY3NbJ25hY2tDb3VudCddID0gKHN0YXQubmFja0NvdW50IC0gdGhpcy5zdGF0cy5pbmJvdW5kLnZpZGVvLm5hY2tDb3VudCkgLyB0aGlzLnN0YXRzSW50ZXJ2YWw7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdW5pdHNbJ2ZyYW1lc0RlY29kZWQnXSA9ICdmcmFtZXMnO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVuaXRzWyduYWNrQ291bnQnXSA9ICdwYWNrZXRzJztcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdHMuaW5ib3VuZC52aWRlby5mcmFtZXNEZWNvZGVkID0gc3RhdC5mcmFtZXNEZWNvZGVkO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdHMuaW5ib3VuZC52aWRlby5uYWNrQ291bnQgPSBzdGF0Lm5hY2tDb3VudDtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0cy5pbmJvdW5kW3N0YXQubWVkaWFUeXBlXS5ieXRlc1JlY2VpdmVkID0gc3RhdC5ieXRlc1JlY2VpdmVkO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0cy5pbmJvdW5kW3N0YXQubWVkaWFUeXBlXS5wYWNrZXRzUmVjZWl2ZWQgPSBzdGF0LnBhY2tldHNSZWNlaXZlZDtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdHMuaW5ib3VuZFtzdGF0Lm1lZGlhVHlwZV0ucGFja2V0c0xvc3QgPSBzdGF0LnBhY2tldHNMb3N0O1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBqc29uID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICdAdGltZXN0YW1wJzogbmV3IERhdGUoc3RhdC50aW1lc3RhbXApLnRvSVNPU3RyaW5nKCksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJ2V4ZWMnOiBpbnN0cnVtZW50YXRpb24uZXhlYyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAnY29tcG9uZW50JzogaW5zdHJ1bWVudGF0aW9uLmNvbXBvbmVudCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAnc3RyZWFtJzogJ3dlYlJ0YycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJ3R5cGUnOiBtZXRyaWNJZCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAnc3RyZWFtX3R5cGUnOiAnY29tcG9zZWRfbWV0cmljcycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJ3VuaXRzJzogdW5pdHNcbiAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICBqc29uW21ldHJpY0lkXSA9IG1ldHJpY3M7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIHNlbmRQb3N0KEpTT04uc3RyaW5naWZ5KGpzb24pKTtcblxuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKChzdGF0LnR5cGUgPT09ICdvdXRib3VuZC1ydHAnKSAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEF2b2lkIGZpcmVmb3ggZW1wdHkgaW5ib3VuZC1ydHAgc3RhdGlzdGljc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0YXQuaXNSZW1vdGUgPT09IGZhbHNlICYmXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhdC5pZC50b0xvd2VyQ2FzZSgpLmluY2x1ZGVzKCdvdXRib3VuZCcpXG4gICAgICAgICAgICAgICAgICAgICAgICApKSB7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG1ldHJpY0lkID0gJ3dlYnJ0Y19vdXRib3VuZF8nICsgc3RhdC5tZWRpYVR5cGUgKyAnXycgKyBzdGF0LnNzcmM7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG1ldHJpY3MgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnl0ZXNTZW50OiAoc3RhdC5ieXRlc1NlbnQgLSB0aGlzLnN0YXRzLm91dGJvdW5kW3N0YXQubWVkaWFUeXBlXS5ieXRlc1NlbnQpIC8gdGhpcy5zdGF0c0ludGVydmFsLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhY2tldHNTZW50OiAoc3RhdC5wYWNrZXRzU2VudCAtIHRoaXMuc3RhdHMub3V0Ym91bmRbc3RhdC5tZWRpYVR5cGVdLnBhY2tldHNTZW50KSAvIHRoaXMuc3RhdHNJbnRlcnZhbFxuICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHVuaXRzID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ5dGVzU2VudDogJ2J5dGVzJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYWNrZXRzU2VudDogJ3BhY2tldHMnXG4gICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHN0YXQubWVkaWFUeXBlID09PSAndmlkZW8nKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbWV0cmljc1snZnJhbWVzRW5jb2RlZCddID0gKHN0YXQuZnJhbWVzRW5jb2RlZCAtIHRoaXMuc3RhdHMub3V0Ym91bmQudmlkZW8uZnJhbWVzRW5jb2RlZCkgLyB0aGlzLnN0YXRzSW50ZXJ2YWw7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdW5pdHNbJ2ZyYW1lc0VuY29kZWQnXSA9ICdmcmFtZXMnO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0cy5vdXRib3VuZC52aWRlby5mcmFtZXNFbmNvZGVkID0gc3RhdC5mcmFtZXNFbmNvZGVkO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXRzLm91dGJvdW5kW3N0YXQubWVkaWFUeXBlXS5ieXRlc1NlbnQgPSBzdGF0LmJ5dGVzU2VudDtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdHMub3V0Ym91bmRbc3RhdC5tZWRpYVR5cGVdLnBhY2tldHNTZW50ID0gc3RhdC5wYWNrZXRzU2VudDtcblxuICAgICAgICAgICAgICAgICAgICAgICAganNvbiA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAnQHRpbWVzdGFtcCc6IG5ldyBEYXRlKHN0YXQudGltZXN0YW1wKS50b0lTT1N0cmluZygpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICdleGVjJzogaW5zdHJ1bWVudGF0aW9uLmV4ZWMsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJ2NvbXBvbmVudCc6IGluc3RydW1lbnRhdGlvbi5jb21wb25lbnQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJ3N0cmVhbSc6ICd3ZWJSdGMnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICd0eXBlJzogbWV0cmljSWQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJ3N0cmVhbV90eXBlJzogJ2NvbXBvc2VkX21ldHJpY3MnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICd1bml0cyc6IHVuaXRzXG4gICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAganNvblttZXRyaWNJZF0gPSBtZXRyaWNzO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBzZW5kUG9zdChKU09OLnN0cmluZ2lmeShqc29uKSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoKHBsYXRmb3JtLm5hbWUhLmluZGV4T2YoJ0Nocm9tZScpICE9PSAtMSkgfHwgKHBsYXRmb3JtLm5hbWUhLmluZGV4T2YoJ09wZXJhJykgIT09IC0xKSkge1xuICAgICAgICAgICAgICAgIGZvciAoY29uc3Qga2V5IG9mIE9iamVjdC5rZXlzKHN0YXRzKSkge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBzdGF0ID0gc3RhdHNba2V5XTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHN0YXQudHlwZSA9PT0gJ3NzcmMnKSB7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBqc29uID0ge307XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICgnYnl0ZXNSZWNlaXZlZCcgaW4gc3RhdCAmJiAoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKHN0YXQubWVkaWFUeXBlID09PSAnYXVkaW8nICYmICdhdWRpb091dHB1dExldmVsJyBpbiBzdGF0KSB8fFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIChzdGF0Lm1lZGlhVHlwZSA9PT0gJ3ZpZGVvJyAmJiAncXBTdW0nIGluIHN0YXQpXG4gICAgICAgICAgICAgICAgICAgICAgICApKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaW5ib3VuZC1ydHBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBtZXRyaWNJZCA9ICd3ZWJydGNfaW5ib3VuZF8nICsgc3RhdC5tZWRpYVR5cGUgKyAnXycgKyBzdGF0LnNzcmM7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBtZXRyaWNzID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBieXRlc1JlY2VpdmVkOiAoc3RhdC5ieXRlc1JlY2VpdmVkIC0gdGhpcy5zdGF0cy5pbmJvdW5kW3N0YXQubWVkaWFUeXBlXS5ieXRlc1JlY2VpdmVkKSAvIHRoaXMuc3RhdHNJbnRlcnZhbCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaml0dGVyOiBzdGF0Lmdvb2dKaXR0ZXJCdWZmZXJNcyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFja2V0c1JlY2VpdmVkOiAoc3RhdC5wYWNrZXRzUmVjZWl2ZWQgLSB0aGlzLnN0YXRzLmluYm91bmRbc3RhdC5tZWRpYVR5cGVdLnBhY2tldHNSZWNlaXZlZCkgLyB0aGlzLnN0YXRzSW50ZXJ2YWwsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhY2tldHNMb3N0OiAoc3RhdC5wYWNrZXRzTG9zdCAtIHRoaXMuc3RhdHMuaW5ib3VuZFtzdGF0Lm1lZGlhVHlwZV0ucGFja2V0c0xvc3QpIC8gdGhpcy5zdGF0c0ludGVydmFsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB1bml0cyA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnl0ZXNSZWNlaXZlZDogJ2J5dGVzJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaml0dGVyOiAnbXMnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYWNrZXRzUmVjZWl2ZWQ6ICdwYWNrZXRzJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFja2V0c0xvc3Q6ICdwYWNrZXRzJ1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHN0YXQubWVkaWFUeXBlID09PSAndmlkZW8nKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1ldHJpY3NbJ2ZyYW1lc0RlY29kZWQnXSA9IChzdGF0LmZyYW1lc0RlY29kZWQgLSB0aGlzLnN0YXRzLmluYm91bmQudmlkZW8uZnJhbWVzRGVjb2RlZCkgLyB0aGlzLnN0YXRzSW50ZXJ2YWw7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1ldHJpY3NbJ25hY2tDb3VudCddID0gKHN0YXQuZ29vZ05hY2tzU2VudCAtIHRoaXMuc3RhdHMuaW5ib3VuZC52aWRlby5uYWNrQ291bnQpIC8gdGhpcy5zdGF0c0ludGVydmFsO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1bml0c1snZnJhbWVzRGVjb2RlZCddID0gJ2ZyYW1lcyc7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVuaXRzWyduYWNrQ291bnQnXSA9ICdwYWNrZXRzJztcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXRzLmluYm91bmQudmlkZW8uZnJhbWVzRGVjb2RlZCA9IHN0YXQuZnJhbWVzRGVjb2RlZDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0cy5pbmJvdW5kLnZpZGVvLm5hY2tDb3VudCA9IHN0YXQuZ29vZ05hY2tzU2VudDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXRzLmluYm91bmRbc3RhdC5tZWRpYVR5cGVdLmJ5dGVzUmVjZWl2ZWQgPSBzdGF0LmJ5dGVzUmVjZWl2ZWQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0cy5pbmJvdW5kW3N0YXQubWVkaWFUeXBlXS5wYWNrZXRzUmVjZWl2ZWQgPSBzdGF0LnBhY2tldHNSZWNlaXZlZDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXRzLmluYm91bmRbc3RhdC5tZWRpYVR5cGVdLnBhY2tldHNMb3N0ID0gc3RhdC5wYWNrZXRzTG9zdDtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGpzb24gPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdAdGltZXN0YW1wJzogbmV3IERhdGUoc3RhdC50aW1lc3RhbXApLnRvSVNPU3RyaW5nKCksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdleGVjJzogaW5zdHJ1bWVudGF0aW9uLmV4ZWMsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdjb21wb25lbnQnOiBpbnN0cnVtZW50YXRpb24uY29tcG9uZW50LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnc3RyZWFtJzogJ3dlYlJ0YycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICd0eXBlJzogbWV0cmljSWQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdzdHJlYW1fdHlwZSc6ICdjb21wb3NlZF9tZXRyaWNzJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ3VuaXRzJzogdW5pdHNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGpzb25bbWV0cmljSWRdID0gbWV0cmljcztcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbmRQb3N0KEpTT04uc3RyaW5naWZ5KGpzb24pKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoJ2J5dGVzU2VudCcgaW4gc3RhdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIG91dGJvdW5kLXJ0cFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG1ldHJpY0lkID0gJ3dlYnJ0Y19vdXRib3VuZF8nICsgc3RhdC5tZWRpYVR5cGUgKyAnXycgKyBzdGF0LnNzcmM7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBtZXRyaWNzID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBieXRlc1NlbnQ6IChzdGF0LmJ5dGVzU2VudCAtIHRoaXMuc3RhdHMub3V0Ym91bmRbc3RhdC5tZWRpYVR5cGVdLmJ5dGVzU2VudCkgLyB0aGlzLnN0YXRzSW50ZXJ2YWwsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhY2tldHNTZW50OiAoc3RhdC5wYWNrZXRzU2VudCAtIHRoaXMuc3RhdHMub3V0Ym91bmRbc3RhdC5tZWRpYVR5cGVdLnBhY2tldHNTZW50KSAvIHRoaXMuc3RhdHNJbnRlcnZhbFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgdW5pdHMgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ5dGVzU2VudDogJ2J5dGVzJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFja2V0c1NlbnQ6ICdwYWNrZXRzJ1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHN0YXQubWVkaWFUeXBlID09PSAndmlkZW8nKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1ldHJpY3NbJ2ZyYW1lc0VuY29kZWQnXSA9IChzdGF0LmZyYW1lc0VuY29kZWQgLSB0aGlzLnN0YXRzLm91dGJvdW5kLnZpZGVvLmZyYW1lc0VuY29kZWQpIC8gdGhpcy5zdGF0c0ludGVydmFsO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1bml0c1snZnJhbWVzRW5jb2RlZCddID0gJ2ZyYW1lcyc7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0cy5vdXRib3VuZC52aWRlby5mcmFtZXNFbmNvZGVkID0gc3RhdC5mcmFtZXNFbmNvZGVkO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdHMub3V0Ym91bmRbc3RhdC5tZWRpYVR5cGVdLmJ5dGVzU2VudCA9IHN0YXQuYnl0ZXNTZW50O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdHMub3V0Ym91bmRbc3RhdC5tZWRpYVR5cGVdLnBhY2tldHNTZW50ID0gc3RhdC5wYWNrZXRzU2VudDtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGpzb24gPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdAdGltZXN0YW1wJzogbmV3IERhdGUoc3RhdC50aW1lc3RhbXApLnRvSVNPU3RyaW5nKCksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdleGVjJzogaW5zdHJ1bWVudGF0aW9uLmV4ZWMsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdjb21wb25lbnQnOiBpbnN0cnVtZW50YXRpb24uY29tcG9uZW50LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnc3RyZWFtJzogJ3dlYlJ0YycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICd0eXBlJzogbWV0cmljSWQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdzdHJlYW1fdHlwZSc6ICdjb21wb3NlZF9tZXRyaWNzJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ3VuaXRzJzogdW5pdHNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGpzb25bbWV0cmljSWRdID0gbWV0cmljcztcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbmRQb3N0KEpTT04uc3RyaW5naWZ5KGpzb24pKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcblxuICAgICAgICB0aGlzLmdldFN0YXRzQWdub3N0aWModGhpcy5zdHJlYW0uZ2V0UlRDUGVlckNvbm5lY3Rpb24oKSwgZiwgKGVycm9yKSA9PiB7IGNvbnNvbGUubG9nKGVycm9yKTsgfSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBzdGFuZGFyZGl6ZVJlcG9ydChyZXNwb25zZSkge1xuICAgICAgICBjb25zb2xlLmxvZyhyZXNwb25zZSk7XG4gICAgICAgIGNvbnN0IHN0YW5kYXJkUmVwb3J0ID0ge307XG5cbiAgICAgICAgaWYgKHBsYXRmb3JtLm5hbWUhLmluZGV4T2YoJ0ZpcmVmb3gnKSAhPT0gLTEpIHtcbiAgICAgICAgICAgIE9iamVjdC5rZXlzKHJlc3BvbnNlKS5mb3JFYWNoKGtleSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5sb2cocmVzcG9uc2Vba2V5XSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHJldHVybiByZXNwb25zZTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJlc3BvbnNlLnJlc3VsdCgpLmZvckVhY2gocmVwb3J0ID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHN0YW5kYXJkU3RhdHMgPSB7XG4gICAgICAgICAgICAgICAgaWQ6IHJlcG9ydC5pZCxcbiAgICAgICAgICAgICAgICB0aW1lc3RhbXA6IHJlcG9ydC50aW1lc3RhbXAsXG4gICAgICAgICAgICAgICAgdHlwZTogcmVwb3J0LnR5cGVcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICByZXBvcnQubmFtZXMoKS5mb3JFYWNoKChuYW1lKSA9PiB7XG4gICAgICAgICAgICAgICAgc3RhbmRhcmRTdGF0c1tuYW1lXSA9IHJlcG9ydC5zdGF0KG5hbWUpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBzdGFuZGFyZFJlcG9ydFtzdGFuZGFyZFN0YXRzLmlkXSA9IHN0YW5kYXJkU3RhdHM7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHJldHVybiBzdGFuZGFyZFJlcG9ydDtcbiAgICB9XG5cbiAgICBwcml2YXRlIGdldFN0YXRzQWdub3N0aWMocGMsIHN1Y2Nlc3NDYiwgZmFpbHVyZUNiKSB7XG4gICAgICAgIGlmIChwbGF0Zm9ybS5uYW1lIS5pbmRleE9mKCdGaXJlZm94JykgIT09IC0xKSB7XG4gICAgICAgICAgICAvLyBnZXRTdGF0cyB0YWtlcyBhcmdzIGluIGRpZmZlcmVudCBvcmRlciBpbiBDaHJvbWUgYW5kIEZpcmVmb3hcbiAgICAgICAgICAgIHJldHVybiBwYy5nZXRTdGF0cyhudWxsKS50aGVuKHJlc3BvbnNlID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCByZXBvcnQgPSB0aGlzLnN0YW5kYXJkaXplUmVwb3J0KHJlc3BvbnNlKTtcbiAgICAgICAgICAgICAgICBzdWNjZXNzQ2IocmVwb3J0KTtcbiAgICAgICAgICAgIH0pLmNhdGNoKGZhaWx1cmVDYik7XG4gICAgICAgIH0gZWxzZSBpZiAoKHBsYXRmb3JtLm5hbWUhLmluZGV4T2YoJ0Nocm9tZScpICE9PSAtMSkgfHwgKHBsYXRmb3JtLm5hbWUhLmluZGV4T2YoJ09wZXJhJykgIT09IC0xKSkge1xuICAgICAgICAgICAgLy8gSW4gQ2hyb21lLCB0aGUgZmlyc3QgdHdvIGFyZ3VtZW50cyBhcmUgcmV2ZXJzZWRcbiAgICAgICAgICAgIHJldHVybiBwYy5nZXRTdGF0cygocmVzcG9uc2UpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCByZXBvcnQgPSB0aGlzLnN0YW5kYXJkaXplUmVwb3J0KHJlc3BvbnNlKTtcbiAgICAgICAgICAgICAgICBzdWNjZXNzQ2IocmVwb3J0KTtcbiAgICAgICAgICAgIH0sIG51bGwsIGZhaWx1cmVDYik7XG4gICAgICAgIH1cbiAgICB9XG5cbn0iXX0=
diff --git a/openvidu-hello-world/web/index.html b/openvidu-hello-world/web/index.html
index 126303aeb..cfe854d66 100644
--- a/openvidu-hello-world/web/index.html
+++ b/openvidu-hello-world/web/index.html
@@ -5,7 +5,7 @@
-
+
diff --git a/openvidu-hello-world/web/openvidu-browser-2.3.0.js b/openvidu-hello-world/web/openvidu-browser-2.3.0.js
deleted file mode 100644
index 83a78adcf..000000000
--- a/openvidu-hello-world/web/openvidu-browser-2.3.0.js
+++ /dev/null
@@ -1,7700 +0,0 @@
-(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 1)
- er = arguments[1];
- if (er instanceof Error) {
- throw er; // Unhandled 'error' event
- } else {
- // At least give some kind of context to the user
- var err = new Error('Unhandled "error" event. (' + er + ')');
- err.context = er;
- throw err;
- }
- return false;
- }
-
- handler = events[type];
-
- if (!handler)
- return false;
-
- var isFn = typeof handler === 'function';
- len = arguments.length;
- switch (len) {
- // fast cases
- case 1:
- emitNone(handler, isFn, this);
- break;
- case 2:
- emitOne(handler, isFn, this, arguments[1]);
- break;
- case 3:
- emitTwo(handler, isFn, this, arguments[1], arguments[2]);
- break;
- case 4:
- emitThree(handler, isFn, this, arguments[1], arguments[2], arguments[3]);
- break;
- // slower
- default:
- args = new Array(len - 1);
- for (i = 1; i < len; i++)
- args[i - 1] = arguments[i];
- emitMany(handler, isFn, this, args);
- }
-
- return true;
-};
-
-function _addListener(target, type, listener, prepend) {
- var m;
- var events;
- var existing;
-
- if (typeof listener !== 'function')
- throw new TypeError('"listener" argument must be a function');
-
- events = target._events;
- if (!events) {
- events = target._events = objectCreate(null);
- target._eventsCount = 0;
- } else {
- // To avoid recursion in the case that type === "newListener"! Before
- // adding it to the listeners, first emit "newListener".
- if (events.newListener) {
- target.emit('newListener', type,
- listener.listener ? listener.listener : listener);
-
- // Re-assign `events` because a newListener handler could have caused the
- // this._events to be assigned to a new object
- events = target._events;
- }
- existing = events[type];
- }
-
- if (!existing) {
- // Optimize the case of one listener. Don't need the extra array object.
- existing = events[type] = listener;
- ++target._eventsCount;
- } else {
- if (typeof existing === 'function') {
- // Adding the second element, need to change to array.
- existing = events[type] =
- prepend ? [listener, existing] : [existing, listener];
- } else {
- // If we've already got an array, just append.
- if (prepend) {
- existing.unshift(listener);
- } else {
- existing.push(listener);
- }
- }
-
- // Check for listener leak
- if (!existing.warned) {
- m = $getMaxListeners(target);
- if (m && m > 0 && existing.length > m) {
- existing.warned = true;
- var w = new Error('Possible EventEmitter memory leak detected. ' +
- existing.length + ' "' + String(type) + '" listeners ' +
- 'added. Use emitter.setMaxListeners() to ' +
- 'increase limit.');
- w.name = 'MaxListenersExceededWarning';
- w.emitter = target;
- w.type = type;
- w.count = existing.length;
- if (typeof console === 'object' && console.warn) {
- console.warn('%s: %s', w.name, w.message);
- }
- }
- }
- }
-
- return target;
-}
-
-EventEmitter.prototype.addListener = function addListener(type, listener) {
- return _addListener(this, type, listener, false);
-};
-
-EventEmitter.prototype.on = EventEmitter.prototype.addListener;
-
-EventEmitter.prototype.prependListener =
- function prependListener(type, listener) {
- return _addListener(this, type, listener, true);
- };
-
-function onceWrapper() {
- if (!this.fired) {
- this.target.removeListener(this.type, this.wrapFn);
- this.fired = true;
- switch (arguments.length) {
- case 0:
- return this.listener.call(this.target);
- case 1:
- return this.listener.call(this.target, arguments[0]);
- case 2:
- return this.listener.call(this.target, arguments[0], arguments[1]);
- case 3:
- return this.listener.call(this.target, arguments[0], arguments[1],
- arguments[2]);
- default:
- var args = new Array(arguments.length);
- for (var i = 0; i < args.length; ++i)
- args[i] = arguments[i];
- this.listener.apply(this.target, args);
- }
- }
-}
-
-function _onceWrap(target, type, listener) {
- var state = { fired: false, wrapFn: undefined, target: target, type: type, listener: listener };
- var wrapped = bind.call(onceWrapper, state);
- wrapped.listener = listener;
- state.wrapFn = wrapped;
- return wrapped;
-}
-
-EventEmitter.prototype.once = function once(type, listener) {
- if (typeof listener !== 'function')
- throw new TypeError('"listener" argument must be a function');
- this.on(type, _onceWrap(this, type, listener));
- return this;
-};
-
-EventEmitter.prototype.prependOnceListener =
- function prependOnceListener(type, listener) {
- if (typeof listener !== 'function')
- throw new TypeError('"listener" argument must be a function');
- this.prependListener(type, _onceWrap(this, type, listener));
- return this;
- };
-
-// Emits a 'removeListener' event if and only if the listener was removed.
-EventEmitter.prototype.removeListener =
- function removeListener(type, listener) {
- var list, events, position, i, originalListener;
-
- if (typeof listener !== 'function')
- throw new TypeError('"listener" argument must be a function');
-
- events = this._events;
- if (!events)
- return this;
-
- list = events[type];
- if (!list)
- return this;
-
- if (list === listener || list.listener === listener) {
- if (--this._eventsCount === 0)
- this._events = objectCreate(null);
- else {
- delete events[type];
- if (events.removeListener)
- this.emit('removeListener', type, list.listener || listener);
- }
- } else if (typeof list !== 'function') {
- position = -1;
-
- for (i = list.length - 1; i >= 0; i--) {
- if (list[i] === listener || list[i].listener === listener) {
- originalListener = list[i].listener;
- position = i;
- break;
- }
- }
-
- if (position < 0)
- return this;
-
- if (position === 0)
- list.shift();
- else
- spliceOne(list, position);
-
- if (list.length === 1)
- events[type] = list[0];
-
- if (events.removeListener)
- this.emit('removeListener', type, originalListener || listener);
- }
-
- return this;
- };
-
-EventEmitter.prototype.removeAllListeners =
- function removeAllListeners(type) {
- var listeners, events, i;
-
- events = this._events;
- if (!events)
- return this;
-
- // not listening for removeListener, no need to emit
- if (!events.removeListener) {
- if (arguments.length === 0) {
- this._events = objectCreate(null);
- this._eventsCount = 0;
- } else if (events[type]) {
- if (--this._eventsCount === 0)
- this._events = objectCreate(null);
- else
- delete events[type];
- }
- return this;
- }
-
- // emit removeListener for all listeners on all events
- if (arguments.length === 0) {
- var keys = objectKeys(events);
- var key;
- for (i = 0; i < keys.length; ++i) {
- key = keys[i];
- if (key === 'removeListener') continue;
- this.removeAllListeners(key);
- }
- this.removeAllListeners('removeListener');
- this._events = objectCreate(null);
- this._eventsCount = 0;
- return this;
- }
-
- listeners = events[type];
-
- if (typeof listeners === 'function') {
- this.removeListener(type, listeners);
- } else if (listeners) {
- // LIFO order
- for (i = listeners.length - 1; i >= 0; i--) {
- this.removeListener(type, listeners[i]);
- }
- }
-
- return this;
- };
-
-function _listeners(target, type, unwrap) {
- var events = target._events;
-
- if (!events)
- return [];
-
- var evlistener = events[type];
- if (!evlistener)
- return [];
-
- if (typeof evlistener === 'function')
- return unwrap ? [evlistener.listener || evlistener] : [evlistener];
-
- return unwrap ? unwrapListeners(evlistener) : arrayClone(evlistener, evlistener.length);
-}
-
-EventEmitter.prototype.listeners = function listeners(type) {
- return _listeners(this, type, true);
-};
-
-EventEmitter.prototype.rawListeners = function rawListeners(type) {
- return _listeners(this, type, false);
-};
-
-EventEmitter.listenerCount = function(emitter, type) {
- if (typeof emitter.listenerCount === 'function') {
- return emitter.listenerCount(type);
- } else {
- return listenerCount.call(emitter, type);
- }
-};
-
-EventEmitter.prototype.listenerCount = listenerCount;
-function listenerCount(type) {
- var events = this._events;
-
- if (events) {
- var evlistener = events[type];
-
- if (typeof evlistener === 'function') {
- return 1;
- } else if (evlistener) {
- return evlistener.length;
- }
- }
-
- return 0;
-}
-
-EventEmitter.prototype.eventNames = function eventNames() {
- return this._eventsCount > 0 ? Reflect.ownKeys(this._events) : [];
-};
-
-// About 1.5x faster than the two-arg version of Array#splice().
-function spliceOne(list, index) {
- for (var i = index, k = i + 1, n = list.length; k < n; i += 1, k += 1)
- list[i] = list[k];
- list.pop();
-}
-
-function arrayClone(arr, n) {
- var copy = new Array(n);
- for (var i = 0; i < n; ++i)
- copy[i] = arr[i];
- return copy;
-}
-
-function unwrapListeners(arr) {
- var ret = new Array(arr.length);
- for (var i = 0; i < ret.length; ++i) {
- ret[i] = arr[i].listener || arr[i];
- }
- return ret;
-}
-
-function objectCreatePolyfill(proto) {
- var F = function() {};
- F.prototype = proto;
- return new F;
-}
-function objectKeysPolyfill(obj) {
- var keys = [];
- for (var k in obj) if (Object.prototype.hasOwnProperty.call(obj, k)) {
- keys.push(k);
- }
- return k;
-}
-function functionBindPolyfill(context) {
- var fn = this;
- return function () {
- return fn.apply(context, arguments);
- };
-}
-
-},{}],2:[function(require,module,exports){
-/* jshint node: true */
-'use strict';
-
-var normalice = require('normalice');
-
-/**
- # freeice
-
- The `freeice` module is a simple way of getting random STUN or TURN server
- for your WebRTC application. The list of servers (just STUN at this stage)
- were sourced from this [gist](https://gist.github.com/zziuni/3741933).
-
- ## Example Use
-
- The following demonstrates how you can use `freeice` with
- [rtc-quickconnect](https://github.com/rtc-io/rtc-quickconnect):
-
- <<< examples/quickconnect.js
-
- As the `freeice` module generates ice servers in a list compliant with the
- WebRTC spec you will be able to use it with raw `RTCPeerConnection`
- constructors and other WebRTC libraries.
-
- ## Hey, don't use my STUN/TURN server!
-
- If for some reason your free STUN or TURN server ends up in the
- list of servers ([stun](https://github.com/DamonOehlman/freeice/blob/master/stun.json) or
- [turn](https://github.com/DamonOehlman/freeice/blob/master/turn.json))
- that is used in this module, you can feel
- free to open an issue on this repository and those servers will be removed
- within 24 hours (or sooner). This is the quickest and probably the most
- polite way to have something removed (and provides us some visibility
- if someone opens a pull request requesting that a server is added).
-
- ## Please add my server!
-
- If you have a server that you wish to add to the list, that's awesome! I'm
- sure I speak on behalf of a whole pile of WebRTC developers who say thanks.
- To get it into the list, feel free to either open a pull request or if you
- find that process a bit daunting then just create an issue requesting
- the addition of the server (make sure you provide all the details, and if
- you have a Terms of Service then including that in the PR/issue would be
- awesome).
-
- ## I know of a free server, can I add it?
-
- Sure, if you do your homework and make sure it is ok to use (I'm currently
- in the process of reviewing the terms of those STUN servers included from
- the original list). If it's ok to go, then please see the previous entry
- for how to add it.
-
- ## Current List of Servers
-
- * current as at the time of last `README.md` file generation
-
- ### STUN
-
- <<< stun.json
-
- ### TURN
-
- <<< turn.json
-
-**/
-
-var freeice = module.exports = function(opts) {
- // if a list of servers has been provided, then use it instead of defaults
- var servers = {
- stun: (opts || {}).stun || require('./stun.json'),
- turn: (opts || {}).turn || require('./turn.json')
- };
-
- var stunCount = (opts || {}).stunCount || 2;
- var turnCount = (opts || {}).turnCount || 0;
- var selected;
-
- function getServers(type, count) {
- var out = [];
- var input = [].concat(servers[type]);
- var idx;
-
- while (input.length && out.length < count) {
- idx = (Math.random() * input.length) | 0;
- out = out.concat(input.splice(idx, 1));
- }
-
- return out.map(function(url) {
- //If it's a not a string, don't try to "normalice" it otherwise using type:url will screw it up
- if ((typeof url !== 'string') && (! (url instanceof String))) {
- return url;
- } else {
- return normalice(type + ':' + url);
- }
- });
- }
-
- // add stun servers
- selected = [].concat(getServers('stun', stunCount));
-
- if (turnCount) {
- selected = selected.concat(getServers('turn', turnCount));
- }
-
- return selected;
-};
-
-},{"./stun.json":3,"./turn.json":4,"normalice":7}],3:[function(require,module,exports){
-module.exports=[
- "stun.l.google.com:19302",
- "stun1.l.google.com:19302",
- "stun2.l.google.com:19302",
- "stun3.l.google.com:19302",
- "stun4.l.google.com:19302",
- "stun.ekiga.net",
- "stun.ideasip.com",
- "stun.schlund.de",
- "stun.stunprotocol.org:3478",
- "stun.voiparound.com",
- "stun.voipbuster.com",
- "stun.voipstunt.com",
- "stun.voxgratia.org",
- "stun.services.mozilla.com"
-]
-
-},{}],4:[function(require,module,exports){
-module.exports=[]
-
-},{}],5:[function(require,module,exports){
-var WildEmitter = require('wildemitter');
-
-function getMaxVolume (analyser, fftBins) {
- var maxVolume = -Infinity;
- analyser.getFloatFrequencyData(fftBins);
-
- for(var i=4, ii=fftBins.length; i < ii; i++) {
- if (fftBins[i] > maxVolume && fftBins[i] < 0) {
- maxVolume = fftBins[i];
- }
- };
-
- return maxVolume;
-}
-
-
-var audioContextType;
-if (typeof window !== 'undefined') {
- audioContextType = window.AudioContext || window.webkitAudioContext;
-}
-// use a single audio context due to hardware limits
-var audioContext = null;
-module.exports = function(stream, options) {
- var harker = new WildEmitter();
-
-
- // make it not break in non-supported browsers
- if (!audioContextType) return harker;
-
- //Config
- var options = options || {},
- smoothing = (options.smoothing || 0.1),
- interval = (options.interval || 50),
- threshold = options.threshold,
- play = options.play,
- history = options.history || 10,
- running = true;
-
- //Setup Audio Context
- if (!audioContext) {
- audioContext = new audioContextType();
- }
- var sourceNode, fftBins, analyser;
-
- analyser = audioContext.createAnalyser();
- analyser.fftSize = 512;
- analyser.smoothingTimeConstant = smoothing;
- fftBins = new Float32Array(analyser.frequencyBinCount);
-
- if (stream.jquery) stream = stream[0];
- if (stream instanceof HTMLAudioElement || stream instanceof HTMLVideoElement) {
- //Audio Tag
- sourceNode = audioContext.createMediaElementSource(stream);
- if (typeof play === 'undefined') play = true;
- threshold = threshold || -50;
- } else {
- //WebRTC Stream
- sourceNode = audioContext.createMediaStreamSource(stream);
- threshold = threshold || -50;
- }
-
- sourceNode.connect(analyser);
- if (play) analyser.connect(audioContext.destination);
-
- harker.speaking = false;
-
- harker.suspend = function() {
- audioContext.suspend();
- }
- harker.resume = function() {
- audioContext.resume();
- }
- Object.defineProperty(harker, 'state', { get: function() {
- return audioContext.state;
- }});
- audioContext.onstatechange = function() {
- harker.emit('state_change', audioContext.state);
- }
-
- harker.setThreshold = function(t) {
- threshold = t;
- };
-
- harker.setInterval = function(i) {
- interval = i;
- };
-
- harker.stop = function() {
- running = false;
- harker.emit('volume_change', -100, threshold);
- if (harker.speaking) {
- harker.speaking = false;
- harker.emit('stopped_speaking');
- }
- analyser.disconnect();
- sourceNode.disconnect();
- };
- harker.speakingHistory = [];
- for (var i = 0; i < history; i++) {
- harker.speakingHistory.push(0);
- }
-
- // Poll the analyser node to determine if speaking
- // and emit events if changed
- var looper = function() {
- setTimeout(function() {
-
- //check if stop has been called
- if(!running) {
- return;
- }
-
- var currentVolume = getMaxVolume(analyser, fftBins);
-
- harker.emit('volume_change', currentVolume, threshold);
-
- var history = 0;
- if (currentVolume > threshold && !harker.speaking) {
- // trigger quickly, short history
- for (var i = harker.speakingHistory.length - 3; i < harker.speakingHistory.length; i++) {
- history += harker.speakingHistory[i];
- }
- if (history >= 2) {
- harker.speaking = true;
- harker.emit('speaking');
- }
- } else if (currentVolume < threshold && harker.speaking) {
- for (var i = 0; i < harker.speakingHistory.length; i++) {
- history += harker.speakingHistory[i];
- }
- if (history == 0) {
- harker.speaking = false;
- harker.emit('stopped_speaking');
- }
- }
- harker.speakingHistory.shift();
- harker.speakingHistory.push(0 + (currentVolume > threshold));
-
- looper();
- }, interval);
- };
- looper();
-
-
- return harker;
-}
-
-},{"wildemitter":14}],6:[function(require,module,exports){
-if (typeof Object.create === 'function') {
- // implementation from standard node.js 'util' module
- module.exports = function inherits(ctor, superCtor) {
- ctor.super_ = superCtor
- ctor.prototype = Object.create(superCtor.prototype, {
- constructor: {
- value: ctor,
- enumerable: false,
- writable: true,
- configurable: true
- }
- });
- };
-} else {
- // old school shim for old browsers
- module.exports = function inherits(ctor, superCtor) {
- ctor.super_ = superCtor
- var TempCtor = function () {}
- TempCtor.prototype = superCtor.prototype
- ctor.prototype = new TempCtor()
- ctor.prototype.constructor = ctor
- }
-}
-
-},{}],7:[function(require,module,exports){
-/**
- # normalice
-
- Normalize an ice server configuration object (or plain old string) into a format
- that is usable in all browsers supporting WebRTC. Primarily this module is designed
- to help with the transition of the `url` attribute of the configuration object to
- the `urls` attribute.
-
- ## Example Usage
-
- <<< examples/simple.js
-
-**/
-
-var protocols = [
- 'stun:',
- 'turn:'
-];
-
-module.exports = function(input) {
- var url = (input || {}).url || input;
- var protocol;
- var parts;
- var output = {};
-
- // if we don't have a string url, then allow the input to passthrough
- if (typeof url != 'string' && (! (url instanceof String))) {
- return input;
- }
-
- // trim the url string, and convert to an array
- url = url.trim();
-
- // if the protocol is not known, then passthrough
- protocol = protocols[protocols.indexOf(url.slice(0, 5))];
- if (! protocol) {
- return input;
- }
-
- // now let's attack the remaining url parts
- url = url.slice(5);
- parts = url.split('@');
-
- output.username = input.username;
- output.credential = input.credential;
- // if we have an authentication part, then set the credentials
- if (parts.length > 1) {
- url = parts[1];
- parts = parts[0].split(':');
-
- // add the output credential and username
- output.username = parts[0];
- output.credential = (input || {}).credential || parts[1] || '';
- }
-
- output.url = protocol + url;
- output.urls = [ output.url ];
-
- return output;
-};
-
-},{}],8:[function(require,module,exports){
-(function (global){
-/*!
- * Platform.js
- * Copyright 2014-2018 Benjamin Tan
- * Copyright 2011-2013 John-David Dalton
- * Available under MIT license
- */
-;(function() {
- 'use strict';
-
- /** Used to determine if values are of the language type `Object`. */
- var objectTypes = {
- 'function': true,
- 'object': true
- };
-
- /** Used as a reference to the global object. */
- var root = (objectTypes[typeof window] && window) || this;
-
- /** Backup possible global object. */
- var oldRoot = root;
-
- /** Detect free variable `exports`. */
- var freeExports = objectTypes[typeof exports] && exports;
-
- /** Detect free variable `module`. */
- var freeModule = objectTypes[typeof module] && module && !module.nodeType && module;
-
- /** Detect free variable `global` from Node.js or Browserified code and use it as `root`. */
- var freeGlobal = freeExports && freeModule && typeof global == 'object' && global;
- if (freeGlobal && (freeGlobal.global === freeGlobal || freeGlobal.window === freeGlobal || freeGlobal.self === freeGlobal)) {
- root = freeGlobal;
- }
-
- /**
- * Used as the maximum length of an array-like object.
- * See the [ES6 spec](http://people.mozilla.org/~jorendorff/es6-draft.html#sec-tolength)
- * for more details.
- */
- var maxSafeInteger = Math.pow(2, 53) - 1;
-
- /** Regular expression to detect Opera. */
- var reOpera = /\bOpera/;
-
- /** Possible global object. */
- var thisBinding = this;
-
- /** Used for native method references. */
- var objectProto = Object.prototype;
-
- /** Used to check for own properties of an object. */
- var hasOwnProperty = objectProto.hasOwnProperty;
-
- /** Used to resolve the internal `[[Class]]` of values. */
- var toString = objectProto.toString;
-
- /*--------------------------------------------------------------------------*/
-
- /**
- * Capitalizes a string value.
- *
- * @private
- * @param {string} string The string to capitalize.
- * @returns {string} The capitalized string.
- */
- function capitalize(string) {
- string = String(string);
- return string.charAt(0).toUpperCase() + string.slice(1);
- }
-
- /**
- * A utility function to clean up the OS name.
- *
- * @private
- * @param {string} os The OS name to clean up.
- * @param {string} [pattern] A `RegExp` pattern matching the OS name.
- * @param {string} [label] A label for the OS.
- */
- function cleanupOS(os, pattern, label) {
- // Platform tokens are defined at:
- // http://msdn.microsoft.com/en-us/library/ms537503(VS.85).aspx
- // http://web.archive.org/web/20081122053950/http://msdn.microsoft.com/en-us/library/ms537503(VS.85).aspx
- var data = {
- '10.0': '10',
- '6.4': '10 Technical Preview',
- '6.3': '8.1',
- '6.2': '8',
- '6.1': 'Server 2008 R2 / 7',
- '6.0': 'Server 2008 / Vista',
- '5.2': 'Server 2003 / XP 64-bit',
- '5.1': 'XP',
- '5.01': '2000 SP1',
- '5.0': '2000',
- '4.0': 'NT',
- '4.90': 'ME'
- };
- // Detect Windows version from platform tokens.
- if (pattern && label && /^Win/i.test(os) && !/^Windows Phone /i.test(os) &&
- (data = data[/[\d.]+$/.exec(os)])) {
- os = 'Windows ' + data;
- }
- // Correct character case and cleanup string.
- os = String(os);
-
- if (pattern && label) {
- os = os.replace(RegExp(pattern, 'i'), label);
- }
-
- os = format(
- os.replace(/ ce$/i, ' CE')
- .replace(/\bhpw/i, 'web')
- .replace(/\bMacintosh\b/, 'Mac OS')
- .replace(/_PowerPC\b/i, ' OS')
- .replace(/\b(OS X) [^ \d]+/i, '$1')
- .replace(/\bMac (OS X)\b/, '$1')
- .replace(/\/(\d)/, ' $1')
- .replace(/_/g, '.')
- .replace(/(?: BePC|[ .]*fc[ \d.]+)$/i, '')
- .replace(/\bx86\.64\b/gi, 'x86_64')
- .replace(/\b(Windows Phone) OS\b/, '$1')
- .replace(/\b(Chrome OS \w+) [\d.]+\b/, '$1')
- .split(' on ')[0]
- );
-
- return os;
- }
-
- /**
- * An iteration utility for arrays and objects.
- *
- * @private
- * @param {Array|Object} object The object to iterate over.
- * @param {Function} callback The function called per iteration.
- */
- function each(object, callback) {
- var index = -1,
- length = object ? object.length : 0;
-
- if (typeof length == 'number' && length > -1 && length <= maxSafeInteger) {
- while (++index < length) {
- callback(object[index], index, object);
- }
- } else {
- forOwn(object, callback);
- }
- }
-
- /**
- * Trim and conditionally capitalize string values.
- *
- * @private
- * @param {string} string The string to format.
- * @returns {string} The formatted string.
- */
- function format(string) {
- string = trim(string);
- return /^(?:webOS|i(?:OS|P))/.test(string)
- ? string
- : capitalize(string);
- }
-
- /**
- * Iterates over an object's own properties, executing the `callback` for each.
- *
- * @private
- * @param {Object} object The object to iterate over.
- * @param {Function} callback The function executed per own property.
- */
- function forOwn(object, callback) {
- for (var key in object) {
- if (hasOwnProperty.call(object, key)) {
- callback(object[key], key, object);
- }
- }
- }
-
- /**
- * Gets the internal `[[Class]]` of a value.
- *
- * @private
- * @param {*} value The value.
- * @returns {string} The `[[Class]]`.
- */
- function getClassOf(value) {
- return value == null
- ? capitalize(value)
- : toString.call(value).slice(8, -1);
- }
-
- /**
- * Host objects can return type values that are different from their actual
- * data type. The objects we are concerned with usually return non-primitive
- * types of "object", "function", or "unknown".
- *
- * @private
- * @param {*} object The owner of the property.
- * @param {string} property The property to check.
- * @returns {boolean} Returns `true` if the property value is a non-primitive, else `false`.
- */
- function isHostType(object, property) {
- var type = object != null ? typeof object[property] : 'number';
- return !/^(?:boolean|number|string|undefined)$/.test(type) &&
- (type == 'object' ? !!object[property] : true);
- }
-
- /**
- * Prepares a string for use in a `RegExp` by making hyphens and spaces optional.
- *
- * @private
- * @param {string} string The string to qualify.
- * @returns {string} The qualified string.
- */
- function qualify(string) {
- return String(string).replace(/([ -])(?!$)/g, '$1?');
- }
-
- /**
- * A bare-bones `Array#reduce` like utility function.
- *
- * @private
- * @param {Array} array The array to iterate over.
- * @param {Function} callback The function called per iteration.
- * @returns {*} The accumulated result.
- */
- function reduce(array, callback) {
- var accumulator = null;
- each(array, function(value, index) {
- accumulator = callback(accumulator, value, index, array);
- });
- return accumulator;
- }
-
- /**
- * Removes leading and trailing whitespace from a string.
- *
- * @private
- * @param {string} string The string to trim.
- * @returns {string} The trimmed string.
- */
- function trim(string) {
- return String(string).replace(/^ +| +$/g, '');
- }
-
- /*--------------------------------------------------------------------------*/
-
- /**
- * Creates a new platform object.
- *
- * @memberOf platform
- * @param {Object|string} [ua=navigator.userAgent] The user agent string or
- * context object.
- * @returns {Object} A platform object.
- */
- function parse(ua) {
-
- /** The environment context object. */
- var context = root;
-
- /** Used to flag when a custom context is provided. */
- var isCustomContext = ua && typeof ua == 'object' && getClassOf(ua) != 'String';
-
- // Juggle arguments.
- if (isCustomContext) {
- context = ua;
- ua = null;
- }
-
- /** Browser navigator object. */
- var nav = context.navigator || {};
-
- /** Browser user agent string. */
- var userAgent = nav.userAgent || '';
-
- ua || (ua = userAgent);
-
- /** Used to flag when `thisBinding` is the [ModuleScope]. */
- var isModuleScope = isCustomContext || thisBinding == oldRoot;
-
- /** Used to detect if browser is like Chrome. */
- var likeChrome = isCustomContext
- ? !!nav.likeChrome
- : /\bChrome\b/.test(ua) && !/internal|\n/i.test(toString.toString());
-
- /** Internal `[[Class]]` value shortcuts. */
- var objectClass = 'Object',
- airRuntimeClass = isCustomContext ? objectClass : 'ScriptBridgingProxyObject',
- enviroClass = isCustomContext ? objectClass : 'Environment',
- javaClass = (isCustomContext && context.java) ? 'JavaPackage' : getClassOf(context.java),
- phantomClass = isCustomContext ? objectClass : 'RuntimeObject';
-
- /** Detect Java environments. */
- var java = /\bJava/.test(javaClass) && context.java;
-
- /** Detect Rhino. */
- var rhino = java && getClassOf(context.environment) == enviroClass;
-
- /** A character to represent alpha. */
- var alpha = java ? 'a' : '\u03b1';
-
- /** A character to represent beta. */
- var beta = java ? 'b' : '\u03b2';
-
- /** Browser document object. */
- var doc = context.document || {};
-
- /**
- * Detect Opera browser (Presto-based).
- * http://www.howtocreate.co.uk/operaStuff/operaObject.html
- * http://dev.opera.com/articles/view/opera-mini-web-content-authoring-guidelines/#operamini
- */
- var opera = context.operamini || context.opera;
-
- /** Opera `[[Class]]`. */
- var operaClass = reOpera.test(operaClass = (isCustomContext && opera) ? opera['[[Class]]'] : getClassOf(opera))
- ? operaClass
- : (opera = null);
-
- /*------------------------------------------------------------------------*/
-
- /** Temporary variable used over the script's lifetime. */
- var data;
-
- /** The CPU architecture. */
- var arch = ua;
-
- /** Platform description array. */
- var description = [];
-
- /** Platform alpha/beta indicator. */
- var prerelease = null;
-
- /** A flag to indicate that environment features should be used to resolve the platform. */
- var useFeatures = ua == userAgent;
-
- /** The browser/environment version. */
- var version = useFeatures && opera && typeof opera.version == 'function' && opera.version();
-
- /** A flag to indicate if the OS ends with "/ Version" */
- var isSpecialCasedOS;
-
- /* Detectable layout engines (order is important). */
- var layout = getLayout([
- { 'label': 'EdgeHTML', 'pattern': 'Edge' },
- 'Trident',
- { 'label': 'WebKit', 'pattern': 'AppleWebKit' },
- 'iCab',
- 'Presto',
- 'NetFront',
- 'Tasman',
- 'KHTML',
- 'Gecko'
- ]);
-
- /* Detectable browser names (order is important). */
- var name = getName([
- 'Adobe AIR',
- 'Arora',
- 'Avant Browser',
- 'Breach',
- 'Camino',
- 'Electron',
- 'Epiphany',
- 'Fennec',
- 'Flock',
- 'Galeon',
- 'GreenBrowser',
- 'iCab',
- 'Iceweasel',
- 'K-Meleon',
- 'Konqueror',
- 'Lunascape',
- 'Maxthon',
- { 'label': 'Microsoft Edge', 'pattern': 'Edge' },
- 'Midori',
- 'Nook Browser',
- 'PaleMoon',
- 'PhantomJS',
- 'Raven',
- 'Rekonq',
- 'RockMelt',
- { 'label': 'Samsung Internet', 'pattern': 'SamsungBrowser' },
- 'SeaMonkey',
- { 'label': 'Silk', 'pattern': '(?:Cloud9|Silk-Accelerated)' },
- 'Sleipnir',
- 'SlimBrowser',
- { 'label': 'SRWare Iron', 'pattern': 'Iron' },
- 'Sunrise',
- 'Swiftfox',
- 'Waterfox',
- 'WebPositive',
- 'Opera Mini',
- { 'label': 'Opera Mini', 'pattern': 'OPiOS' },
- 'Opera',
- { 'label': 'Opera', 'pattern': 'OPR' },
- 'Chrome',
- { 'label': 'Chrome Mobile', 'pattern': '(?:CriOS|CrMo)' },
- { 'label': 'Firefox', 'pattern': '(?:Firefox|Minefield)' },
- { 'label': 'Firefox for iOS', 'pattern': 'FxiOS' },
- { 'label': 'IE', 'pattern': 'IEMobile' },
- { 'label': 'IE', 'pattern': 'MSIE' },
- 'Safari'
- ]);
-
- /* Detectable products (order is important). */
- var product = getProduct([
- { 'label': 'BlackBerry', 'pattern': 'BB10' },
- 'BlackBerry',
- { 'label': 'Galaxy S', 'pattern': 'GT-I9000' },
- { 'label': 'Galaxy S2', 'pattern': 'GT-I9100' },
- { 'label': 'Galaxy S3', 'pattern': 'GT-I9300' },
- { 'label': 'Galaxy S4', 'pattern': 'GT-I9500' },
- { 'label': 'Galaxy S5', 'pattern': 'SM-G900' },
- { 'label': 'Galaxy S6', 'pattern': 'SM-G920' },
- { 'label': 'Galaxy S6 Edge', 'pattern': 'SM-G925' },
- { 'label': 'Galaxy S7', 'pattern': 'SM-G930' },
- { 'label': 'Galaxy S7 Edge', 'pattern': 'SM-G935' },
- 'Google TV',
- 'Lumia',
- 'iPad',
- 'iPod',
- 'iPhone',
- 'Kindle',
- { 'label': 'Kindle Fire', 'pattern': '(?:Cloud9|Silk-Accelerated)' },
- 'Nexus',
- 'Nook',
- 'PlayBook',
- 'PlayStation Vita',
- 'PlayStation',
- 'TouchPad',
- 'Transformer',
- { 'label': 'Wii U', 'pattern': 'WiiU' },
- 'Wii',
- 'Xbox One',
- { 'label': 'Xbox 360', 'pattern': 'Xbox' },
- 'Xoom'
- ]);
-
- /* Detectable manufacturers. */
- var manufacturer = getManufacturer({
- 'Apple': { 'iPad': 1, 'iPhone': 1, 'iPod': 1 },
- 'Archos': {},
- 'Amazon': { 'Kindle': 1, 'Kindle Fire': 1 },
- 'Asus': { 'Transformer': 1 },
- 'Barnes & Noble': { 'Nook': 1 },
- 'BlackBerry': { 'PlayBook': 1 },
- 'Google': { 'Google TV': 1, 'Nexus': 1 },
- 'HP': { 'TouchPad': 1 },
- 'HTC': {},
- 'LG': {},
- 'Microsoft': { 'Xbox': 1, 'Xbox One': 1 },
- 'Motorola': { 'Xoom': 1 },
- 'Nintendo': { 'Wii U': 1, 'Wii': 1 },
- 'Nokia': { 'Lumia': 1 },
- 'Samsung': { 'Galaxy S': 1, 'Galaxy S2': 1, 'Galaxy S3': 1, 'Galaxy S4': 1 },
- 'Sony': { 'PlayStation': 1, 'PlayStation Vita': 1 }
- });
-
- /* Detectable operating systems (order is important). */
- var os = getOS([
- 'Windows Phone',
- 'Android',
- 'CentOS',
- { 'label': 'Chrome OS', 'pattern': 'CrOS' },
- 'Debian',
- 'Fedora',
- 'FreeBSD',
- 'Gentoo',
- 'Haiku',
- 'Kubuntu',
- 'Linux Mint',
- 'OpenBSD',
- 'Red Hat',
- 'SuSE',
- 'Ubuntu',
- 'Xubuntu',
- 'Cygwin',
- 'Symbian OS',
- 'hpwOS',
- 'webOS ',
- 'webOS',
- 'Tablet OS',
- 'Tizen',
- 'Linux',
- 'Mac OS X',
- 'Macintosh',
- 'Mac',
- 'Windows 98;',
- 'Windows '
- ]);
-
- /*------------------------------------------------------------------------*/
-
- /**
- * Picks the layout engine from an array of guesses.
- *
- * @private
- * @param {Array} guesses An array of guesses.
- * @returns {null|string} The detected layout engine.
- */
- function getLayout(guesses) {
- return reduce(guesses, function(result, guess) {
- return result || RegExp('\\b' + (
- guess.pattern || qualify(guess)
- ) + '\\b', 'i').exec(ua) && (guess.label || guess);
- });
- }
-
- /**
- * Picks the manufacturer from an array of guesses.
- *
- * @private
- * @param {Array} guesses An object of guesses.
- * @returns {null|string} The detected manufacturer.
- */
- function getManufacturer(guesses) {
- return reduce(guesses, function(result, value, key) {
- // Lookup the manufacturer by product or scan the UA for the manufacturer.
- return result || (
- value[product] ||
- value[/^[a-z]+(?: +[a-z]+\b)*/i.exec(product)] ||
- RegExp('\\b' + qualify(key) + '(?:\\b|\\w*\\d)', 'i').exec(ua)
- ) && key;
- });
- }
-
- /**
- * Picks the browser name from an array of guesses.
- *
- * @private
- * @param {Array} guesses An array of guesses.
- * @returns {null|string} The detected browser name.
- */
- function getName(guesses) {
- return reduce(guesses, function(result, guess) {
- return result || RegExp('\\b' + (
- guess.pattern || qualify(guess)
- ) + '\\b', 'i').exec(ua) && (guess.label || guess);
- });
- }
-
- /**
- * Picks the OS name from an array of guesses.
- *
- * @private
- * @param {Array} guesses An array of guesses.
- * @returns {null|string} The detected OS name.
- */
- function getOS(guesses) {
- return reduce(guesses, function(result, guess) {
- var pattern = guess.pattern || qualify(guess);
- if (!result && (result =
- RegExp('\\b' + pattern + '(?:/[\\d.]+|[ \\w.]*)', 'i').exec(ua)
- )) {
- result = cleanupOS(result, pattern, guess.label || guess);
- }
- return result;
- });
- }
-
- /**
- * Picks the product name from an array of guesses.
- *
- * @private
- * @param {Array} guesses An array of guesses.
- * @returns {null|string} The detected product name.
- */
- function getProduct(guesses) {
- return reduce(guesses, function(result, guess) {
- var pattern = guess.pattern || qualify(guess);
- if (!result && (result =
- RegExp('\\b' + pattern + ' *\\d+[.\\w_]*', 'i').exec(ua) ||
- RegExp('\\b' + pattern + ' *\\w+-[\\w]*', 'i').exec(ua) ||
- RegExp('\\b' + pattern + '(?:; *(?:[a-z]+[_-])?[a-z]+\\d+|[^ ();-]*)', 'i').exec(ua)
- )) {
- // Split by forward slash and append product version if needed.
- if ((result = String((guess.label && !RegExp(pattern, 'i').test(guess.label)) ? guess.label : result).split('/'))[1] && !/[\d.]+/.test(result[0])) {
- result[0] += ' ' + result[1];
- }
- // Correct character case and cleanup string.
- guess = guess.label || guess;
- result = format(result[0]
- .replace(RegExp(pattern, 'i'), guess)
- .replace(RegExp('; *(?:' + guess + '[_-])?', 'i'), ' ')
- .replace(RegExp('(' + guess + ')[-_.]?(\\w)', 'i'), '$1 $2'));
- }
- return result;
- });
- }
-
- /**
- * Resolves the version using an array of UA patterns.
- *
- * @private
- * @param {Array} patterns An array of UA patterns.
- * @returns {null|string} The detected version.
- */
- function getVersion(patterns) {
- return reduce(patterns, function(result, pattern) {
- return result || (RegExp(pattern +
- '(?:-[\\d.]+/|(?: for [\\w-]+)?[ /-])([\\d.]+[^ ();/_-]*)', 'i').exec(ua) || 0)[1] || null;
- });
- }
-
- /**
- * Returns `platform.description` when the platform object is coerced to a string.
- *
- * @name toString
- * @memberOf platform
- * @returns {string} Returns `platform.description` if available, else an empty string.
- */
- function toStringPlatform() {
- return this.description || '';
- }
-
- /*------------------------------------------------------------------------*/
-
- // Convert layout to an array so we can add extra details.
- layout && (layout = [layout]);
-
- // Detect product names that contain their manufacturer's name.
- if (manufacturer && !product) {
- product = getProduct([manufacturer]);
- }
- // Clean up Google TV.
- if ((data = /\bGoogle TV\b/.exec(product))) {
- product = data[0];
- }
- // Detect simulators.
- if (/\bSimulator\b/i.test(ua)) {
- product = (product ? product + ' ' : '') + 'Simulator';
- }
- // Detect Opera Mini 8+ running in Turbo/Uncompressed mode on iOS.
- if (name == 'Opera Mini' && /\bOPiOS\b/.test(ua)) {
- description.push('running in Turbo/Uncompressed mode');
- }
- // Detect IE Mobile 11.
- if (name == 'IE' && /\blike iPhone OS\b/.test(ua)) {
- data = parse(ua.replace(/like iPhone OS/, ''));
- manufacturer = data.manufacturer;
- product = data.product;
- }
- // Detect iOS.
- else if (/^iP/.test(product)) {
- name || (name = 'Safari');
- os = 'iOS' + ((data = / OS ([\d_]+)/i.exec(ua))
- ? ' ' + data[1].replace(/_/g, '.')
- : '');
- }
- // Detect Kubuntu.
- else if (name == 'Konqueror' && !/buntu/i.test(os)) {
- os = 'Kubuntu';
- }
- // Detect Android browsers.
- else if ((manufacturer && manufacturer != 'Google' &&
- ((/Chrome/.test(name) && !/\bMobile Safari\b/i.test(ua)) || /\bVita\b/.test(product))) ||
- (/\bAndroid\b/.test(os) && /^Chrome/.test(name) && /\bVersion\//i.test(ua))) {
- name = 'Android Browser';
- os = /\bAndroid\b/.test(os) ? os : 'Android';
- }
- // Detect Silk desktop/accelerated modes.
- else if (name == 'Silk') {
- if (!/\bMobi/i.test(ua)) {
- os = 'Android';
- description.unshift('desktop mode');
- }
- if (/Accelerated *= *true/i.test(ua)) {
- description.unshift('accelerated');
- }
- }
- // Detect PaleMoon identifying as Firefox.
- else if (name == 'PaleMoon' && (data = /\bFirefox\/([\d.]+)\b/.exec(ua))) {
- description.push('identifying as Firefox ' + data[1]);
- }
- // Detect Firefox OS and products running Firefox.
- else if (name == 'Firefox' && (data = /\b(Mobile|Tablet|TV)\b/i.exec(ua))) {
- os || (os = 'Firefox OS');
- product || (product = data[1]);
- }
- // Detect false positives for Firefox/Safari.
- else if (!name || (data = !/\bMinefield\b/i.test(ua) && /\b(?:Firefox|Safari)\b/.exec(name))) {
- // Escape the `/` for Firefox 1.
- if (name && !product && /[\/,]|^[^(]+?\)/.test(ua.slice(ua.indexOf(data + '/') + 8))) {
- // Clear name of false positives.
- name = null;
- }
- // Reassign a generic name.
- if ((data = product || manufacturer || os) &&
- (product || manufacturer || /\b(?:Android|Symbian OS|Tablet OS|webOS)\b/.test(os))) {
- name = /[a-z]+(?: Hat)?/i.exec(/\bAndroid\b/.test(os) ? os : data) + ' Browser';
- }
- }
- // Add Chrome version to description for Electron.
- else if (name == 'Electron' && (data = (/\bChrome\/([\d.]+)\b/.exec(ua) || 0)[1])) {
- description.push('Chromium ' + data);
- }
- // Detect non-Opera (Presto-based) versions (order is important).
- if (!version) {
- version = getVersion([
- '(?:Cloud9|CriOS|CrMo|Edge|FxiOS|IEMobile|Iron|Opera ?Mini|OPiOS|OPR|Raven|SamsungBrowser|Silk(?!/[\\d.]+$))',
- 'Version',
- qualify(name),
- '(?:Firefox|Minefield|NetFront)'
- ]);
- }
- // Detect stubborn layout engines.
- if ((data =
- layout == 'iCab' && parseFloat(version) > 3 && 'WebKit' ||
- /\bOpera\b/.test(name) && (/\bOPR\b/.test(ua) ? 'Blink' : 'Presto') ||
- /\b(?:Midori|Nook|Safari)\b/i.test(ua) && !/^(?:Trident|EdgeHTML)$/.test(layout) && 'WebKit' ||
- !layout && /\bMSIE\b/i.test(ua) && (os == 'Mac OS' ? 'Tasman' : 'Trident') ||
- layout == 'WebKit' && /\bPlayStation\b(?! Vita\b)/i.test(name) && 'NetFront'
- )) {
- layout = [data];
- }
- // Detect Windows Phone 7 desktop mode.
- if (name == 'IE' && (data = (/; *(?:XBLWP|ZuneWP)(\d+)/i.exec(ua) || 0)[1])) {
- name += ' Mobile';
- os = 'Windows Phone ' + (/\+$/.test(data) ? data : data + '.x');
- description.unshift('desktop mode');
- }
- // Detect Windows Phone 8.x desktop mode.
- else if (/\bWPDesktop\b/i.test(ua)) {
- name = 'IE Mobile';
- os = 'Windows Phone 8.x';
- description.unshift('desktop mode');
- version || (version = (/\brv:([\d.]+)/.exec(ua) || 0)[1]);
- }
- // Detect IE 11 identifying as other browsers.
- else if (name != 'IE' && layout == 'Trident' && (data = /\brv:([\d.]+)/.exec(ua))) {
- if (name) {
- description.push('identifying as ' + name + (version ? ' ' + version : ''));
- }
- name = 'IE';
- version = data[1];
- }
- // Leverage environment features.
- if (useFeatures) {
- // Detect server-side environments.
- // Rhino has a global function while others have a global object.
- if (isHostType(context, 'global')) {
- if (java) {
- data = java.lang.System;
- arch = data.getProperty('os.arch');
- os = os || data.getProperty('os.name') + ' ' + data.getProperty('os.version');
- }
- if (rhino) {
- try {
- version = context.require('ringo/engine').version.join('.');
- name = 'RingoJS';
- } catch(e) {
- if ((data = context.system) && data.global.system == context.system) {
- name = 'Narwhal';
- os || (os = data[0].os || null);
- }
- }
- if (!name) {
- name = 'Rhino';
- }
- }
- else if (
- typeof context.process == 'object' && !context.process.browser &&
- (data = context.process)
- ) {
- if (typeof data.versions == 'object') {
- if (typeof data.versions.electron == 'string') {
- description.push('Node ' + data.versions.node);
- name = 'Electron';
- version = data.versions.electron;
- } else if (typeof data.versions.nw == 'string') {
- description.push('Chromium ' + version, 'Node ' + data.versions.node);
- name = 'NW.js';
- version = data.versions.nw;
- }
- }
- if (!name) {
- name = 'Node.js';
- arch = data.arch;
- os = data.platform;
- version = /[\d.]+/.exec(data.version);
- version = version ? version[0] : null;
- }
- }
- }
- // Detect Adobe AIR.
- else if (getClassOf((data = context.runtime)) == airRuntimeClass) {
- name = 'Adobe AIR';
- os = data.flash.system.Capabilities.os;
- }
- // Detect PhantomJS.
- else if (getClassOf((data = context.phantom)) == phantomClass) {
- name = 'PhantomJS';
- version = (data = data.version || null) && (data.major + '.' + data.minor + '.' + data.patch);
- }
- // Detect IE compatibility modes.
- else if (typeof doc.documentMode == 'number' && (data = /\bTrident\/(\d+)/i.exec(ua))) {
- // We're in compatibility mode when the Trident version + 4 doesn't
- // equal the document mode.
- version = [version, doc.documentMode];
- if ((data = +data[1] + 4) != version[1]) {
- description.push('IE ' + version[1] + ' mode');
- layout && (layout[1] = '');
- version[1] = data;
- }
- version = name == 'IE' ? String(version[1].toFixed(1)) : version[0];
- }
- // Detect IE 11 masking as other browsers.
- else if (typeof doc.documentMode == 'number' && /^(?:Chrome|Firefox)\b/.test(name)) {
- description.push('masking as ' + name + ' ' + version);
- name = 'IE';
- version = '11.0';
- layout = ['Trident'];
- os = 'Windows';
- }
- os = os && format(os);
- }
- // Detect prerelease phases.
- if (version && (data =
- /(?:[ab]|dp|pre|[ab]\d+pre)(?:\d+\+?)?$/i.exec(version) ||
- /(?:alpha|beta)(?: ?\d)?/i.exec(ua + ';' + (useFeatures && nav.appMinorVersion)) ||
- /\bMinefield\b/i.test(ua) && 'a'
- )) {
- prerelease = /b/i.test(data) ? 'beta' : 'alpha';
- version = version.replace(RegExp(data + '\\+?$'), '') +
- (prerelease == 'beta' ? beta : alpha) + (/\d+\+?/.exec(data) || '');
- }
- // Detect Firefox Mobile.
- if (name == 'Fennec' || name == 'Firefox' && /\b(?:Android|Firefox OS)\b/.test(os)) {
- name = 'Firefox Mobile';
- }
- // Obscure Maxthon's unreliable version.
- else if (name == 'Maxthon' && version) {
- version = version.replace(/\.[\d.]+/, '.x');
- }
- // Detect Xbox 360 and Xbox One.
- else if (/\bXbox\b/i.test(product)) {
- if (product == 'Xbox 360') {
- os = null;
- }
- if (product == 'Xbox 360' && /\bIEMobile\b/.test(ua)) {
- description.unshift('mobile mode');
- }
- }
- // Add mobile postfix.
- else if ((/^(?:Chrome|IE|Opera)$/.test(name) || name && !product && !/Browser|Mobi/.test(name)) &&
- (os == 'Windows CE' || /Mobi/i.test(ua))) {
- name += ' Mobile';
- }
- // Detect IE platform preview.
- else if (name == 'IE' && useFeatures) {
- try {
- if (context.external === null) {
- description.unshift('platform preview');
- }
- } catch(e) {
- description.unshift('embedded');
- }
- }
- // Detect BlackBerry OS version.
- // http://docs.blackberry.com/en/developers/deliverables/18169/HTTP_headers_sent_by_BB_Browser_1234911_11.jsp
- else if ((/\bBlackBerry\b/.test(product) || /\bBB10\b/.test(ua)) && (data =
- (RegExp(product.replace(/ +/g, ' *') + '/([.\\d]+)', 'i').exec(ua) || 0)[1] ||
- version
- )) {
- data = [data, /BB10/.test(ua)];
- os = (data[1] ? (product = null, manufacturer = 'BlackBerry') : 'Device Software') + ' ' + data[0];
- version = null;
- }
- // Detect Opera identifying/masking itself as another browser.
- // http://www.opera.com/support/kb/view/843/
- else if (this != forOwn && product != 'Wii' && (
- (useFeatures && opera) ||
- (/Opera/.test(name) && /\b(?:MSIE|Firefox)\b/i.test(ua)) ||
- (name == 'Firefox' && /\bOS X (?:\d+\.){2,}/.test(os)) ||
- (name == 'IE' && (
- (os && !/^Win/.test(os) && version > 5.5) ||
- /\bWindows XP\b/.test(os) && version > 8 ||
- version == 8 && !/\bTrident\b/.test(ua)
- ))
- ) && !reOpera.test((data = parse.call(forOwn, ua.replace(reOpera, '') + ';'))) && data.name) {
- // When "identifying", the UA contains both Opera and the other browser's name.
- data = 'ing as ' + data.name + ((data = data.version) ? ' ' + data : '');
- if (reOpera.test(name)) {
- if (/\bIE\b/.test(data) && os == 'Mac OS') {
- os = null;
- }
- data = 'identify' + data;
- }
- // When "masking", the UA contains only the other browser's name.
- else {
- data = 'mask' + data;
- if (operaClass) {
- name = format(operaClass.replace(/([a-z])([A-Z])/g, '$1 $2'));
- } else {
- name = 'Opera';
- }
- if (/\bIE\b/.test(data)) {
- os = null;
- }
- if (!useFeatures) {
- version = null;
- }
- }
- layout = ['Presto'];
- description.push(data);
- }
- // Detect WebKit Nightly and approximate Chrome/Safari versions.
- if ((data = (/\bAppleWebKit\/([\d.]+\+?)/i.exec(ua) || 0)[1])) {
- // Correct build number for numeric comparison.
- // (e.g. "532.5" becomes "532.05")
- data = [parseFloat(data.replace(/\.(\d)$/, '.0$1')), data];
- // Nightly builds are postfixed with a "+".
- if (name == 'Safari' && data[1].slice(-1) == '+') {
- name = 'WebKit Nightly';
- prerelease = 'alpha';
- version = data[1].slice(0, -1);
- }
- // Clear incorrect browser versions.
- else if (version == data[1] ||
- version == (data[2] = (/\bSafari\/([\d.]+\+?)/i.exec(ua) || 0)[1])) {
- version = null;
- }
- // Use the full Chrome version when available.
- data[1] = (/\bChrome\/([\d.]+)/i.exec(ua) || 0)[1];
- // Detect Blink layout engine.
- if (data[0] == 537.36 && data[2] == 537.36 && parseFloat(data[1]) >= 28 && layout == 'WebKit') {
- layout = ['Blink'];
- }
- // Detect JavaScriptCore.
- // http://stackoverflow.com/questions/6768474/how-can-i-detect-which-javascript-engine-v8-or-jsc-is-used-at-runtime-in-androi
- if (!useFeatures || (!likeChrome && !data[1])) {
- layout && (layout[1] = 'like Safari');
- data = (data = data[0], data < 400 ? 1 : data < 500 ? 2 : data < 526 ? 3 : data < 533 ? 4 : data < 534 ? '4+' : data < 535 ? 5 : data < 537 ? 6 : data < 538 ? 7 : data < 601 ? 8 : '8');
- } else {
- layout && (layout[1] = 'like Chrome');
- data = data[1] || (data = data[0], data < 530 ? 1 : data < 532 ? 2 : data < 532.05 ? 3 : data < 533 ? 4 : data < 534.03 ? 5 : data < 534.07 ? 6 : data < 534.10 ? 7 : data < 534.13 ? 8 : data < 534.16 ? 9 : data < 534.24 ? 10 : data < 534.30 ? 11 : data < 535.01 ? 12 : data < 535.02 ? '13+' : data < 535.07 ? 15 : data < 535.11 ? 16 : data < 535.19 ? 17 : data < 536.05 ? 18 : data < 536.10 ? 19 : data < 537.01 ? 20 : data < 537.11 ? '21+' : data < 537.13 ? 23 : data < 537.18 ? 24 : data < 537.24 ? 25 : data < 537.36 ? 26 : layout != 'Blink' ? '27' : '28');
- }
- // Add the postfix of ".x" or "+" for approximate versions.
- layout && (layout[1] += ' ' + (data += typeof data == 'number' ? '.x' : /[.+]/.test(data) ? '' : '+'));
- // Obscure version for some Safari 1-2 releases.
- if (name == 'Safari' && (!version || parseInt(version) > 45)) {
- version = data;
- }
- }
- // Detect Opera desktop modes.
- if (name == 'Opera' && (data = /\bzbov|zvav$/.exec(os))) {
- name += ' ';
- description.unshift('desktop mode');
- if (data == 'zvav') {
- name += 'Mini';
- version = null;
- } else {
- name += 'Mobile';
- }
- os = os.replace(RegExp(' *' + data + '$'), '');
- }
- // Detect Chrome desktop mode.
- else if (name == 'Safari' && /\bChrome\b/.exec(layout && layout[1])) {
- description.unshift('desktop mode');
- name = 'Chrome Mobile';
- version = null;
-
- if (/\bOS X\b/.test(os)) {
- manufacturer = 'Apple';
- os = 'iOS 4.3+';
- } else {
- os = null;
- }
- }
- // Strip incorrect OS versions.
- if (version && version.indexOf((data = /[\d.]+$/.exec(os))) == 0 &&
- ua.indexOf('/' + data + '-') > -1) {
- os = trim(os.replace(data, ''));
- }
- // Add layout engine.
- if (layout && !/\b(?:Avant|Nook)\b/.test(name) && (
- /Browser|Lunascape|Maxthon/.test(name) ||
- name != 'Safari' && /^iOS/.test(os) && /\bSafari\b/.test(layout[1]) ||
- /^(?:Adobe|Arora|Breach|Midori|Opera|Phantom|Rekonq|Rock|Samsung Internet|Sleipnir|Web)/.test(name) && layout[1])) {
- // Don't add layout details to description if they are falsey.
- (data = layout[layout.length - 1]) && description.push(data);
- }
- // Combine contextual information.
- if (description.length) {
- description = ['(' + description.join('; ') + ')'];
- }
- // Append manufacturer to description.
- if (manufacturer && product && product.indexOf(manufacturer) < 0) {
- description.push('on ' + manufacturer);
- }
- // Append product to description.
- if (product) {
- description.push((/^on /.test(description[description.length - 1]) ? '' : 'on ') + product);
- }
- // Parse the OS into an object.
- if (os) {
- data = / ([\d.+]+)$/.exec(os);
- isSpecialCasedOS = data && os.charAt(os.length - data[0].length - 1) == '/';
- os = {
- 'architecture': 32,
- 'family': (data && !isSpecialCasedOS) ? os.replace(data[0], '') : os,
- 'version': data ? data[1] : null,
- 'toString': function() {
- var version = this.version;
- return this.family + ((version && !isSpecialCasedOS) ? ' ' + version : '') + (this.architecture == 64 ? ' 64-bit' : '');
- }
- };
- }
- // Add browser/OS architecture.
- if ((data = /\b(?:AMD|IA|Win|WOW|x86_|x)64\b/i.exec(arch)) && !/\bi686\b/i.test(arch)) {
- if (os) {
- os.architecture = 64;
- os.family = os.family.replace(RegExp(' *' + data), '');
- }
- if (
- name && (/\bWOW64\b/i.test(ua) ||
- (useFeatures && /\w(?:86|32)$/.test(nav.cpuClass || nav.platform) && !/\bWin64; x64\b/i.test(ua)))
- ) {
- description.unshift('32-bit');
- }
- }
- // Chrome 39 and above on OS X is always 64-bit.
- else if (
- os && /^OS X/.test(os.family) &&
- name == 'Chrome' && parseFloat(version) >= 39
- ) {
- os.architecture = 64;
- }
-
- ua || (ua = null);
-
- /*------------------------------------------------------------------------*/
-
- /**
- * The platform object.
- *
- * @name platform
- * @type Object
- */
- var platform = {};
-
- /**
- * The platform description.
- *
- * @memberOf platform
- * @type string|null
- */
- platform.description = ua;
-
- /**
- * The name of the browser's layout engine.
- *
- * The list of common layout engines include:
- * "Blink", "EdgeHTML", "Gecko", "Trident" and "WebKit"
- *
- * @memberOf platform
- * @type string|null
- */
- platform.layout = layout && layout[0];
-
- /**
- * The name of the product's manufacturer.
- *
- * The list of manufacturers include:
- * "Apple", "Archos", "Amazon", "Asus", "Barnes & Noble", "BlackBerry",
- * "Google", "HP", "HTC", "LG", "Microsoft", "Motorola", "Nintendo",
- * "Nokia", "Samsung" and "Sony"
- *
- * @memberOf platform
- * @type string|null
- */
- platform.manufacturer = manufacturer;
-
- /**
- * The name of the browser/environment.
- *
- * The list of common browser names include:
- * "Chrome", "Electron", "Firefox", "Firefox for iOS", "IE",
- * "Microsoft Edge", "PhantomJS", "Safari", "SeaMonkey", "Silk",
- * "Opera Mini" and "Opera"
- *
- * Mobile versions of some browsers have "Mobile" appended to their name:
- * eg. "Chrome Mobile", "Firefox Mobile", "IE Mobile" and "Opera Mobile"
- *
- * @memberOf platform
- * @type string|null
- */
- platform.name = name;
-
- /**
- * The alpha/beta release indicator.
- *
- * @memberOf platform
- * @type string|null
- */
- platform.prerelease = prerelease;
-
- /**
- * The name of the product hosting the browser.
- *
- * The list of common products include:
- *
- * "BlackBerry", "Galaxy S4", "Lumia", "iPad", "iPod", "iPhone", "Kindle",
- * "Kindle Fire", "Nexus", "Nook", "PlayBook", "TouchPad" and "Transformer"
- *
- * @memberOf platform
- * @type string|null
- */
- platform.product = product;
-
- /**
- * The browser's user agent string.
- *
- * @memberOf platform
- * @type string|null
- */
- platform.ua = ua;
-
- /**
- * The browser/environment version.
- *
- * @memberOf platform
- * @type string|null
- */
- platform.version = name && version;
-
- /**
- * The name of the operating system.
- *
- * @memberOf platform
- * @type Object
- */
- platform.os = os || {
-
- /**
- * The CPU architecture the OS is built for.
- *
- * @memberOf platform.os
- * @type number|null
- */
- 'architecture': null,
-
- /**
- * The family of the OS.
- *
- * Common values include:
- * "Windows", "Windows Server 2008 R2 / 7", "Windows Server 2008 / Vista",
- * "Windows XP", "OS X", "Ubuntu", "Debian", "Fedora", "Red Hat", "SuSE",
- * "Android", "iOS" and "Windows Phone"
- *
- * @memberOf platform.os
- * @type string|null
- */
- 'family': null,
-
- /**
- * The version of the OS.
- *
- * @memberOf platform.os
- * @type string|null
- */
- 'version': null,
-
- /**
- * Returns the OS string.
- *
- * @memberOf platform.os
- * @returns {string} The OS string.
- */
- 'toString': function() { return 'null'; }
- };
-
- platform.parse = parse;
- platform.toString = toStringPlatform;
-
- if (platform.version) {
- description.unshift(version);
- }
- if (platform.name) {
- description.unshift(name);
- }
- if (os && name && !(os == String(os).split(' ')[0] && (os == name.split(' ')[0] || product))) {
- description.push(product ? '(' + os + ')' : 'on ' + os);
- }
- if (description.length) {
- platform.description = description.join(' ');
- }
- return platform;
- }
-
- /*--------------------------------------------------------------------------*/
-
- // Export platform.
- var platform = parse();
-
- // Some AMD build optimizers, like r.js, check for condition patterns like the following:
- if (typeof define == 'function' && typeof define.amd == 'object' && define.amd) {
- // Expose platform on the global object to prevent errors when platform is
- // loaded by a script tag in the presence of an AMD loader.
- // See http://requirejs.org/docs/errors.html#mismatch for more details.
- root.platform = platform;
-
- // Define as an anonymous module so platform can be aliased through path mapping.
- define(function() {
- return platform;
- });
- }
- // Check for `exports` after `define` in case a build optimizer adds an `exports` object.
- else if (freeExports && freeModule) {
- // Export for CommonJS support.
- forOwn(platform, function(value, key) {
- freeExports[key] = value;
- });
- }
- else {
- // Export to the global object.
- root.platform = platform;
- }
-}.call(this));
-
-}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
-
-},{}],9:[function(require,module,exports){
-var v1 = require('./v1');
-var v4 = require('./v4');
-
-var uuid = v4;
-uuid.v1 = v1;
-uuid.v4 = v4;
-
-module.exports = uuid;
-
-},{"./v1":12,"./v4":13}],10:[function(require,module,exports){
-/**
- * Convert array of 16 byte values to UUID string format of the form:
- * XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
- */
-var byteToHex = [];
-for (var i = 0; i < 256; ++i) {
- byteToHex[i] = (i + 0x100).toString(16).substr(1);
-}
-
-function bytesToUuid(buf, offset) {
- var i = offset || 0;
- var bth = byteToHex;
- // join used to fix memory issue caused by concatenation: https://bugs.chromium.org/p/v8/issues/detail?id=3175#c4
- return ([bth[buf[i++]], bth[buf[i++]],
- bth[buf[i++]], bth[buf[i++]], '-',
- bth[buf[i++]], bth[buf[i++]], '-',
- bth[buf[i++]], bth[buf[i++]], '-',
- bth[buf[i++]], bth[buf[i++]], '-',
- bth[buf[i++]], bth[buf[i++]],
- bth[buf[i++]], bth[buf[i++]],
- bth[buf[i++]], bth[buf[i++]]]).join('');
-}
-
-module.exports = bytesToUuid;
-
-},{}],11:[function(require,module,exports){
-// Unique ID creation requires a high quality random # generator. In the
-// browser this is a little complicated due to unknown quality of Math.random()
-// and inconsistent support for the `crypto` API. We do the best we can via
-// feature-detection
-
-// getRandomValues needs to be invoked in a context where "this" is a Crypto
-// implementation. Also, find the complete implementation of crypto on IE11.
-var getRandomValues = (typeof(crypto) != 'undefined' && crypto.getRandomValues && crypto.getRandomValues.bind(crypto)) ||
- (typeof(msCrypto) != 'undefined' && typeof window.msCrypto.getRandomValues == 'function' && msCrypto.getRandomValues.bind(msCrypto));
-
-if (getRandomValues) {
- // WHATWG crypto RNG - http://wiki.whatwg.org/wiki/Crypto
- var rnds8 = new Uint8Array(16); // eslint-disable-line no-undef
-
- module.exports = function whatwgRNG() {
- getRandomValues(rnds8);
- return rnds8;
- };
-} else {
- // Math.random()-based (RNG)
- //
- // If all else fails, use Math.random(). It's fast, but is of unspecified
- // quality.
- var rnds = new Array(16);
-
- module.exports = function mathRNG() {
- for (var i = 0, r; i < 16; i++) {
- if ((i & 0x03) === 0) r = Math.random() * 0x100000000;
- rnds[i] = r >>> ((i & 0x03) << 3) & 0xff;
- }
-
- return rnds;
- };
-}
-
-},{}],12:[function(require,module,exports){
-var rng = require('./lib/rng');
-var bytesToUuid = require('./lib/bytesToUuid');
-
-// **`v1()` - Generate time-based UUID**
-//
-// Inspired by https://github.com/LiosK/UUID.js
-// and http://docs.python.org/library/uuid.html
-
-var _nodeId;
-var _clockseq;
-
-// Previous uuid creation time
-var _lastMSecs = 0;
-var _lastNSecs = 0;
-
-// See https://github.com/broofa/node-uuid for API details
-function v1(options, buf, offset) {
- var i = buf && offset || 0;
- var b = buf || [];
-
- options = options || {};
- var node = options.node || _nodeId;
- var clockseq = options.clockseq !== undefined ? options.clockseq : _clockseq;
-
- // node and clockseq need to be initialized to random values if they're not
- // specified. We do this lazily to minimize issues related to insufficient
- // system entropy. See #189
- if (node == null || clockseq == null) {
- var seedBytes = rng();
- if (node == null) {
- // Per 4.5, create and 48-bit node id, (47 random bits + multicast bit = 1)
- node = _nodeId = [
- seedBytes[0] | 0x01,
- seedBytes[1], seedBytes[2], seedBytes[3], seedBytes[4], seedBytes[5]
- ];
- }
- if (clockseq == null) {
- // Per 4.2.2, randomize (14 bit) clockseq
- clockseq = _clockseq = (seedBytes[6] << 8 | seedBytes[7]) & 0x3fff;
- }
- }
-
- // UUID timestamps are 100 nano-second units since the Gregorian epoch,
- // (1582-10-15 00:00). JSNumbers aren't precise enough for this, so
- // time is handled internally as 'msecs' (integer milliseconds) and 'nsecs'
- // (100-nanoseconds offset from msecs) since unix epoch, 1970-01-01 00:00.
- var msecs = options.msecs !== undefined ? options.msecs : new Date().getTime();
-
- // Per 4.2.1.2, use count of uuid's generated during the current clock
- // cycle to simulate higher resolution clock
- var nsecs = options.nsecs !== undefined ? options.nsecs : _lastNSecs + 1;
-
- // Time since last uuid creation (in msecs)
- var dt = (msecs - _lastMSecs) + (nsecs - _lastNSecs)/10000;
-
- // Per 4.2.1.2, Bump clockseq on clock regression
- if (dt < 0 && options.clockseq === undefined) {
- clockseq = clockseq + 1 & 0x3fff;
- }
-
- // Reset nsecs if clock regresses (new clockseq) or we've moved onto a new
- // time interval
- if ((dt < 0 || msecs > _lastMSecs) && options.nsecs === undefined) {
- nsecs = 0;
- }
-
- // Per 4.2.1.2 Throw error if too many uuids are requested
- if (nsecs >= 10000) {
- throw new Error('uuid.v1(): Can\'t create more than 10M uuids/sec');
- }
-
- _lastMSecs = msecs;
- _lastNSecs = nsecs;
- _clockseq = clockseq;
-
- // Per 4.1.4 - Convert from unix epoch to Gregorian epoch
- msecs += 12219292800000;
-
- // `time_low`
- var tl = ((msecs & 0xfffffff) * 10000 + nsecs) % 0x100000000;
- b[i++] = tl >>> 24 & 0xff;
- b[i++] = tl >>> 16 & 0xff;
- b[i++] = tl >>> 8 & 0xff;
- b[i++] = tl & 0xff;
-
- // `time_mid`
- var tmh = (msecs / 0x100000000 * 10000) & 0xfffffff;
- b[i++] = tmh >>> 8 & 0xff;
- b[i++] = tmh & 0xff;
-
- // `time_high_and_version`
- b[i++] = tmh >>> 24 & 0xf | 0x10; // include version
- b[i++] = tmh >>> 16 & 0xff;
-
- // `clock_seq_hi_and_reserved` (Per 4.2.2 - include variant)
- b[i++] = clockseq >>> 8 | 0x80;
-
- // `clock_seq_low`
- b[i++] = clockseq & 0xff;
-
- // `node`
- for (var n = 0; n < 6; ++n) {
- b[i + n] = node[n];
- }
-
- return buf ? buf : bytesToUuid(b);
-}
-
-module.exports = v1;
-
-},{"./lib/bytesToUuid":10,"./lib/rng":11}],13:[function(require,module,exports){
-var rng = require('./lib/rng');
-var bytesToUuid = require('./lib/bytesToUuid');
-
-function v4(options, buf, offset) {
- var i = buf && offset || 0;
-
- if (typeof(options) == 'string') {
- buf = options === 'binary' ? new Array(16) : null;
- options = null;
- }
- options = options || {};
-
- var rnds = options.random || (options.rng || rng)();
-
- // Per 4.4, set bits for version and `clock_seq_hi_and_reserved`
- rnds[6] = (rnds[6] & 0x0f) | 0x40;
- rnds[8] = (rnds[8] & 0x3f) | 0x80;
-
- // Copy bytes to buffer, if provided
- if (buf) {
- for (var ii = 0; ii < 16; ++ii) {
- buf[i + ii] = rnds[ii];
- }
- }
-
- return buf || bytesToUuid(rnds);
-}
-
-module.exports = v4;
-
-},{"./lib/bytesToUuid":10,"./lib/rng":11}],14:[function(require,module,exports){
-/*
-WildEmitter.js is a slim little event emitter by @henrikjoreteg largely based
-on @visionmedia's Emitter from UI Kit.
-
-Why? I wanted it standalone.
-
-I also wanted support for wildcard emitters like this:
-
-emitter.on('*', function (eventName, other, event, payloads) {
-
-});
-
-emitter.on('somenamespace*', function (eventName, payloads) {
-
-});
-
-Please note that callbacks triggered by wildcard registered events also get
-the event name as the first argument.
-*/
-
-module.exports = WildEmitter;
-
-function WildEmitter() { }
-
-WildEmitter.mixin = function (constructor) {
- var prototype = constructor.prototype || constructor;
-
- prototype.isWildEmitter= true;
-
- // Listen on the given `event` with `fn`. Store a group name if present.
- prototype.on = function (event, groupName, fn) {
- this.callbacks = this.callbacks || {};
- var hasGroup = (arguments.length === 3),
- group = hasGroup ? arguments[1] : undefined,
- func = hasGroup ? arguments[2] : arguments[1];
- func._groupName = group;
- (this.callbacks[event] = this.callbacks[event] || []).push(func);
- return this;
- };
-
- // Adds an `event` listener that will be invoked a single
- // time then automatically removed.
- prototype.once = function (event, groupName, fn) {
- var self = this,
- hasGroup = (arguments.length === 3),
- group = hasGroup ? arguments[1] : undefined,
- func = hasGroup ? arguments[2] : arguments[1];
- function on() {
- self.off(event, on);
- func.apply(this, arguments);
- }
- this.on(event, group, on);
- return this;
- };
-
- // Unbinds an entire group
- prototype.releaseGroup = function (groupName) {
- this.callbacks = this.callbacks || {};
- var item, i, len, handlers;
- for (item in this.callbacks) {
- handlers = this.callbacks[item];
- for (i = 0, len = handlers.length; i < len; i++) {
- if (handlers[i]._groupName === groupName) {
- //console.log('removing');
- // remove it and shorten the array we're looping through
- handlers.splice(i, 1);
- i--;
- len--;
- }
- }
- }
- return this;
- };
-
- // Remove the given callback for `event` or all
- // registered callbacks.
- prototype.off = function (event, fn) {
- this.callbacks = this.callbacks || {};
- var callbacks = this.callbacks[event],
- i;
-
- if (!callbacks) return this;
-
- // remove all handlers
- if (arguments.length === 1) {
- delete this.callbacks[event];
- return this;
- }
-
- // remove specific handler
- i = callbacks.indexOf(fn);
- callbacks.splice(i, 1);
- if (callbacks.length === 0) {
- delete this.callbacks[event];
- }
- return this;
- };
-
- /// Emit `event` with the given args.
- // also calls any `*` handlers
- prototype.emit = function (event) {
- this.callbacks = this.callbacks || {};
- var args = [].slice.call(arguments, 1),
- callbacks = this.callbacks[event],
- specialCallbacks = this.getWildcardCallbacks(event),
- i,
- len,
- item,
- listeners;
-
- if (callbacks) {
- listeners = callbacks.slice();
- for (i = 0, len = listeners.length; i < len; ++i) {
- if (!listeners[i]) {
- break;
- }
- listeners[i].apply(this, args);
- }
- }
-
- if (specialCallbacks) {
- len = specialCallbacks.length;
- listeners = specialCallbacks.slice();
- for (i = 0, len = listeners.length; i < len; ++i) {
- if (!listeners[i]) {
- break;
- }
- listeners[i].apply(this, [event].concat(args));
- }
- }
-
- return this;
- };
-
- // Helper for for finding special wildcard event handlers that match the event
- prototype.getWildcardCallbacks = function (eventName) {
- this.callbacks = this.callbacks || {};
- var item,
- split,
- result = [];
-
- for (item in this.callbacks) {
- split = item.split('*');
- if (item === '*' || (split.length === 2 && eventName.slice(0, split[0].length) === split[0])) {
- result = result.concat(this.callbacks[item]);
- }
- }
- return result;
- };
-
-};
-
-WildEmitter.mixin(WildEmitter);
-
-},{}],15:[function(require,module,exports){
-/*!
- * EventEmitter v5.2.5 - git.io/ee
- * Unlicense - http://unlicense.org/
- * Oliver Caldwell - http://oli.me.uk/
- * @preserve
- */
-
-;(function (exports) {
- 'use strict';
-
- /**
- * Class for managing events.
- * Can be extended to provide event functionality in other classes.
- *
- * @class EventEmitter Manages event registering and emitting.
- */
- function EventEmitter() {}
-
- // Shortcuts to improve speed and size
- var proto = EventEmitter.prototype;
- var originalGlobalValue = exports.EventEmitter;
-
- /**
- * Finds the index of the listener for the event in its storage array.
- *
- * @param {Function[]} listeners Array of listeners to search through.
- * @param {Function} listener Method to look for.
- * @return {Number} Index of the specified listener, -1 if not found
- * @api private
- */
- function indexOfListener(listeners, listener) {
- var i = listeners.length;
- while (i--) {
- if (listeners[i].listener === listener) {
- return i;
- }
- }
-
- return -1;
- }
-
- /**
- * Alias a method while keeping the context correct, to allow for overwriting of target method.
- *
- * @param {String} name The name of the target method.
- * @return {Function} The aliased method
- * @api private
- */
- function alias(name) {
- return function aliasClosure() {
- return this[name].apply(this, arguments);
- };
- }
-
- /**
- * Returns the listener array for the specified event.
- * Will initialise the event object and listener arrays if required.
- * Will return an object if you use a regex search. The object contains keys for each matched event. So /ba[rz]/ might return an object containing bar and baz. But only if you have either defined them with defineEvent or added some listeners to them.
- * Each property in the object response is an array of listener functions.
- *
- * @param {String|RegExp} evt Name of the event to return the listeners from.
- * @return {Function[]|Object} All listener functions for the event.
- */
- proto.getListeners = function getListeners(evt) {
- var events = this._getEvents();
- var response;
- var key;
-
- // Return a concatenated array of all matching events if
- // the selector is a regular expression.
- if (evt instanceof RegExp) {
- response = {};
- for (key in events) {
- if (events.hasOwnProperty(key) && evt.test(key)) {
- response[key] = events[key];
- }
- }
- }
- else {
- response = events[evt] || (events[evt] = []);
- }
-
- return response;
- };
-
- /**
- * Takes a list of listener objects and flattens it into a list of listener functions.
- *
- * @param {Object[]} listeners Raw listener objects.
- * @return {Function[]} Just the listener functions.
- */
- proto.flattenListeners = function flattenListeners(listeners) {
- var flatListeners = [];
- var i;
-
- for (i = 0; i < listeners.length; i += 1) {
- flatListeners.push(listeners[i].listener);
- }
-
- return flatListeners;
- };
-
- /**
- * Fetches the requested listeners via getListeners but will always return the results inside an object. This is mainly for internal use but others may find it useful.
- *
- * @param {String|RegExp} evt Name of the event to return the listeners from.
- * @return {Object} All listener functions for an event in an object.
- */
- proto.getListenersAsObject = function getListenersAsObject(evt) {
- var listeners = this.getListeners(evt);
- var response;
-
- if (listeners instanceof Array) {
- response = {};
- response[evt] = listeners;
- }
-
- return response || listeners;
- };
-
- function isValidListener (listener) {
- if (typeof listener === 'function' || listener instanceof RegExp) {
- return true
- } else if (listener && typeof listener === 'object') {
- return isValidListener(listener.listener)
- } else {
- return false
- }
- }
-
- /**
- * Adds a listener function to the specified event.
- * The listener will not be added if it is a duplicate.
- * If the listener returns true then it will be removed after it is called.
- * If you pass a regular expression as the event name then the listener will be added to all events that match it.
- *
- * @param {String|RegExp} evt Name of the event to attach the listener to.
- * @param {Function} listener Method to be called when the event is emitted. If the function returns true then it will be removed after calling.
- * @return {Object} Current instance of EventEmitter for chaining.
- */
- proto.addListener = function addListener(evt, listener) {
- if (!isValidListener(listener)) {
- throw new TypeError('listener must be a function');
- }
-
- var listeners = this.getListenersAsObject(evt);
- var listenerIsWrapped = typeof listener === 'object';
- var key;
-
- for (key in listeners) {
- if (listeners.hasOwnProperty(key) && indexOfListener(listeners[key], listener) === -1) {
- listeners[key].push(listenerIsWrapped ? listener : {
- listener: listener,
- once: false
- });
- }
- }
-
- return this;
- };
-
- /**
- * Alias of addListener
- */
- proto.on = alias('addListener');
-
- /**
- * Semi-alias of addListener. It will add a listener that will be
- * automatically removed after its first execution.
- *
- * @param {String|RegExp} evt Name of the event to attach the listener to.
- * @param {Function} listener Method to be called when the event is emitted. If the function returns true then it will be removed after calling.
- * @return {Object} Current instance of EventEmitter for chaining.
- */
- proto.addOnceListener = function addOnceListener(evt, listener) {
- return this.addListener(evt, {
- listener: listener,
- once: true
- });
- };
-
- /**
- * Alias of addOnceListener.
- */
- proto.once = alias('addOnceListener');
-
- /**
- * Defines an event name. This is required if you want to use a regex to add a listener to multiple events at once. If you don't do this then how do you expect it to know what event to add to? Should it just add to every possible match for a regex? No. That is scary and bad.
- * You need to tell it what event names should be matched by a regex.
- *
- * @param {String} evt Name of the event to create.
- * @return {Object} Current instance of EventEmitter for chaining.
- */
- proto.defineEvent = function defineEvent(evt) {
- this.getListeners(evt);
- return this;
- };
-
- /**
- * Uses defineEvent to define multiple events.
- *
- * @param {String[]} evts An array of event names to define.
- * @return {Object} Current instance of EventEmitter for chaining.
- */
- proto.defineEvents = function defineEvents(evts) {
- for (var i = 0; i < evts.length; i += 1) {
- this.defineEvent(evts[i]);
- }
- return this;
- };
-
- /**
- * Removes a listener function from the specified event.
- * When passed a regular expression as the event name, it will remove the listener from all events that match it.
- *
- * @param {String|RegExp} evt Name of the event to remove the listener from.
- * @param {Function} listener Method to remove from the event.
- * @return {Object} Current instance of EventEmitter for chaining.
- */
- proto.removeListener = function removeListener(evt, listener) {
- var listeners = this.getListenersAsObject(evt);
- var index;
- var key;
-
- for (key in listeners) {
- if (listeners.hasOwnProperty(key)) {
- index = indexOfListener(listeners[key], listener);
-
- if (index !== -1) {
- listeners[key].splice(index, 1);
- }
- }
- }
-
- return this;
- };
-
- /**
- * Alias of removeListener
- */
- proto.off = alias('removeListener');
-
- /**
- * Adds listeners in bulk using the manipulateListeners method.
- * If you pass an object as the first argument you can add to multiple events at once. The object should contain key value pairs of events and listeners or listener arrays. You can also pass it an event name and an array of listeners to be added.
- * You can also pass it a regular expression to add the array of listeners to all events that match it.
- * Yeah, this function does quite a bit. That's probably a bad thing.
- *
- * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to add to multiple events at once.
- * @param {Function[]} [listeners] An optional array of listener functions to add.
- * @return {Object} Current instance of EventEmitter for chaining.
- */
- proto.addListeners = function addListeners(evt, listeners) {
- // Pass through to manipulateListeners
- return this.manipulateListeners(false, evt, listeners);
- };
-
- /**
- * Removes listeners in bulk using the manipulateListeners method.
- * If you pass an object as the first argument you can remove from multiple events at once. The object should contain key value pairs of events and listeners or listener arrays.
- * You can also pass it an event name and an array of listeners to be removed.
- * You can also pass it a regular expression to remove the listeners from all events that match it.
- *
- * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to remove from multiple events at once.
- * @param {Function[]} [listeners] An optional array of listener functions to remove.
- * @return {Object} Current instance of EventEmitter for chaining.
- */
- proto.removeListeners = function removeListeners(evt, listeners) {
- // Pass through to manipulateListeners
- return this.manipulateListeners(true, evt, listeners);
- };
-
- /**
- * Edits listeners in bulk. The addListeners and removeListeners methods both use this to do their job. You should really use those instead, this is a little lower level.
- * The first argument will determine if the listeners are removed (true) or added (false).
- * If you pass an object as the second argument you can add/remove from multiple events at once. The object should contain key value pairs of events and listeners or listener arrays.
- * You can also pass it an event name and an array of listeners to be added/removed.
- * You can also pass it a regular expression to manipulate the listeners of all events that match it.
- *
- * @param {Boolean} remove True if you want to remove listeners, false if you want to add.
- * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to add/remove from multiple events at once.
- * @param {Function[]} [listeners] An optional array of listener functions to add/remove.
- * @return {Object} Current instance of EventEmitter for chaining.
- */
- proto.manipulateListeners = function manipulateListeners(remove, evt, listeners) {
- var i;
- var value;
- var single = remove ? this.removeListener : this.addListener;
- var multiple = remove ? this.removeListeners : this.addListeners;
-
- // If evt is an object then pass each of its properties to this method
- if (typeof evt === 'object' && !(evt instanceof RegExp)) {
- for (i in evt) {
- if (evt.hasOwnProperty(i) && (value = evt[i])) {
- // Pass the single listener straight through to the singular method
- if (typeof value === 'function') {
- single.call(this, i, value);
- }
- else {
- // Otherwise pass back to the multiple function
- multiple.call(this, i, value);
- }
- }
- }
- }
- else {
- // So evt must be a string
- // And listeners must be an array of listeners
- // Loop over it and pass each one to the multiple method
- i = listeners.length;
- while (i--) {
- single.call(this, evt, listeners[i]);
- }
- }
-
- return this;
- };
-
- /**
- * Removes all listeners from a specified event.
- * If you do not specify an event then all listeners will be removed.
- * That means every event will be emptied.
- * You can also pass a regex to remove all events that match it.
- *
- * @param {String|RegExp} [evt] Optional name of the event to remove all listeners for. Will remove from every event if not passed.
- * @return {Object} Current instance of EventEmitter for chaining.
- */
- proto.removeEvent = function removeEvent(evt) {
- var type = typeof evt;
- var events = this._getEvents();
- var key;
-
- // Remove different things depending on the state of evt
- if (type === 'string') {
- // Remove all listeners for the specified event
- delete events[evt];
- }
- else if (evt instanceof RegExp) {
- // Remove all events matching the regex.
- for (key in events) {
- if (events.hasOwnProperty(key) && evt.test(key)) {
- delete events[key];
- }
- }
- }
- else {
- // Remove all listeners in all events
- delete this._events;
- }
-
- return this;
- };
-
- /**
- * Alias of removeEvent.
- *
- * Added to mirror the node API.
- */
- proto.removeAllListeners = alias('removeEvent');
-
- /**
- * Emits an event of your choice.
- * When emitted, every listener attached to that event will be executed.
- * If you pass the optional argument array then those arguments will be passed to every listener upon execution.
- * Because it uses `apply`, your array of arguments will be passed as if you wrote them out separately.
- * So they will not arrive within the array on the other side, they will be separate.
- * You can also pass a regular expression to emit to all events that match it.
- *
- * @param {String|RegExp} evt Name of the event to emit and execute listeners for.
- * @param {Array} [args] Optional array of arguments to be passed to each listener.
- * @return {Object} Current instance of EventEmitter for chaining.
- */
- proto.emitEvent = function emitEvent(evt, args) {
- var listenersMap = this.getListenersAsObject(evt);
- var listeners;
- var listener;
- var i;
- var key;
- var response;
-
- for (key in listenersMap) {
- if (listenersMap.hasOwnProperty(key)) {
- listeners = listenersMap[key].slice(0);
-
- for (i = 0; i < listeners.length; i++) {
- // If the listener returns true then it shall be removed from the event
- // The function is executed either with a basic call or an apply if there is an args array
- listener = listeners[i];
-
- if (listener.once === true) {
- this.removeListener(evt, listener.listener);
- }
-
- response = listener.listener.apply(this, args || []);
-
- if (response === this._getOnceReturnValue()) {
- this.removeListener(evt, listener.listener);
- }
- }
- }
- }
-
- return this;
- };
-
- /**
- * Alias of emitEvent
- */
- proto.trigger = alias('emitEvent');
-
- /**
- * Subtly different from emitEvent in that it will pass its arguments on to the listeners, as opposed to taking a single array of arguments to pass on.
- * As with emitEvent, you can pass a regex in place of the event name to emit to all events that match it.
- *
- * @param {String|RegExp} evt Name of the event to emit and execute listeners for.
- * @param {...*} Optional additional arguments to be passed to each listener.
- * @return {Object} Current instance of EventEmitter for chaining.
- */
- proto.emit = function emit(evt) {
- var args = Array.prototype.slice.call(arguments, 1);
- return this.emitEvent(evt, args);
- };
-
- /**
- * Sets the current value to check against when executing listeners. If a
- * listeners return value matches the one set here then it will be removed
- * after execution. This value defaults to true.
- *
- * @param {*} value The new value to check for when executing listeners.
- * @return {Object} Current instance of EventEmitter for chaining.
- */
- proto.setOnceReturnValue = function setOnceReturnValue(value) {
- this._onceReturnValue = value;
- return this;
- };
-
- /**
- * Fetches the current value to check against when executing listeners. If
- * the listeners return value matches this one then it should be removed
- * automatically. It will return true by default.
- *
- * @return {*|Boolean} The current value to check for or the default, true.
- * @api private
- */
- proto._getOnceReturnValue = function _getOnceReturnValue() {
- if (this.hasOwnProperty('_onceReturnValue')) {
- return this._onceReturnValue;
- }
- else {
- return true;
- }
- };
-
- /**
- * Fetches the events object and creates one if required.
- *
- * @return {Object} The events storage object.
- * @api private
- */
- proto._getEvents = function _getEvents() {
- return this._events || (this._events = {});
- };
-
- /**
- * Reverts the global {@link EventEmitter} to its previous value and returns a reference to this version.
- *
- * @return {Function} Non conflicting EventEmitter class.
- */
- EventEmitter.noConflict = function noConflict() {
- exports.EventEmitter = originalGlobalValue;
- return EventEmitter;
- };
-
- // Expose the class either via AMD, CommonJS or the global object
- if (typeof define === 'function' && define.amd) {
- define(function () {
- return EventEmitter;
- });
- }
- else if (typeof module === 'object' && module.exports){
- module.exports = EventEmitter;
- }
- else {
- exports.EventEmitter = EventEmitter;
- }
-}(typeof window !== 'undefined' ? window : this || {}));
-
-},{}],16:[function(require,module,exports){
-"use strict";
-Object.defineProperty(exports, "__esModule", { value: true });
-var OpenVidu_1 = require("./OpenVidu/OpenVidu");
-if (window) {
- window['OpenVidu'] = OpenVidu_1.OpenVidu;
-}
-
-},{"./OpenVidu/OpenVidu":19}],17:[function(require,module,exports){
-"use strict";
-Object.defineProperty(exports, "__esModule", { value: true });
-var Stream_1 = require("./Stream");
-var Connection = (function () {
- function Connection(session, opts) {
- this.session = session;
- this.disposed = false;
- var msg = "'Connection' created ";
- if (!!opts) {
- msg += "(remote) with 'connectionId' [" + opts.id + ']';
- }
- else {
- msg += '(local)';
- }
- console.info(msg);
- this.options = opts;
- if (!!opts) {
- this.connectionId = opts.id;
- if (opts.metadata) {
- this.data = opts.metadata;
- }
- if (opts.streams) {
- this.initRemoteStreams(opts.streams);
- }
- }
- this.creationTime = new Date().getTime();
- }
- Connection.prototype.sendIceCandidate = function (candidate) {
- console.debug((!!this.stream.outboundStreamOpts ? 'Local' : 'Remote'), 'candidate for', this.connectionId, JSON.stringify(candidate));
- this.session.openvidu.sendRequest('onIceCandidate', {
- endpointName: this.connectionId,
- candidate: candidate.candidate,
- sdpMid: candidate.sdpMid,
- sdpMLineIndex: candidate.sdpMLineIndex
- }, function (error, response) {
- if (error) {
- console.error('Error sending ICE candidate: '
- + JSON.stringify(error));
- }
- });
- };
- Connection.prototype.initRemoteStreams = function (options) {
- var _this = this;
- options.forEach(function (opts) {
- var streamOptions = {
- id: opts.id,
- connection: _this,
- hasAudio: opts.hasAudio,
- hasVideo: opts.hasVideo,
- audioActive: opts.audioActive,
- videoActive: opts.videoActive,
- typeOfVideo: opts.typeOfVideo,
- frameRate: opts.frameRate,
- videoDimensions: !!opts.videoDimensions ? JSON.parse(opts.videoDimensions) : undefined
- };
- var stream = new Stream_1.Stream(_this.session, streamOptions);
- _this.addStream(stream);
- });
- console.info("Remote 'Connection' with 'connectionId' [" + this.connectionId + '] is now configured for receiving Streams with options: ', this.stream.inboundStreamOpts);
- };
- Connection.prototype.addStream = function (stream) {
- stream.connection = this;
- this.stream = stream;
- };
- Connection.prototype.removeStream = function (streamId) {
- delete this.stream;
- };
- Connection.prototype.dispose = function () {
- if (!!this.stream) {
- delete this.stream;
- }
- this.disposed = true;
- };
- return Connection;
-}());
-exports.Connection = Connection;
-
-},{"./Stream":22}],18:[function(require,module,exports){
-"use strict";
-Object.defineProperty(exports, "__esModule", { value: true });
-var LocalRecorderState_1 = require("../OpenViduInternal/Enums/LocalRecorderState");
-var LocalRecorder = (function () {
- function LocalRecorder(stream) {
- this.stream = stream;
- this.chunks = [];
- this.count = 0;
- this.connectionId = (!!this.stream.connection) ? this.stream.connection.connectionId : 'default-connection';
- this.id = this.stream.streamId + '_' + this.connectionId + '_localrecord';
- this.state = LocalRecorderState_1.LocalRecorderState.READY;
- }
- LocalRecorder.prototype.record = function () {
- var _this = this;
- return new Promise(function (resolve, reject) {
- try {
- if (typeof MediaRecorder === 'undefined') {
- console.error('MediaRecorder not supported on your browser. See compatibility in https://caniuse.com/#search=MediaRecorder');
- throw (Error('MediaRecorder not supported on your browser. See compatibility in https://caniuse.com/#search=MediaRecorder'));
- }
- if (_this.state !== LocalRecorderState_1.LocalRecorderState.READY) {
- throw (Error('\'LocalRecord.record()\' needs \'LocalRecord.state\' to be \'READY\' (current value: \'' + _this.state + '\'). Call \'LocalRecorder.clean()\' or init a new LocalRecorder before'));
- }
- console.log("Starting local recording of stream '" + _this.stream.streamId + "' of connection '" + _this.connectionId + "'");
- if (typeof MediaRecorder.isTypeSupported === 'function') {
- var options = void 0;
- if (MediaRecorder.isTypeSupported('video/webm;codecs=vp9')) {
- options = { mimeType: 'video/webm;codecs=vp9' };
- }
- else if (MediaRecorder.isTypeSupported('video/webm;codecs=h264')) {
- options = { mimeType: 'video/webm;codecs=h264' };
- }
- else if (MediaRecorder.isTypeSupported('video/webm;codecs=vp8')) {
- options = { mimeType: 'video/webm;codecs=vp8' };
- }
- console.log('Using mimeType ' + options.mimeType);
- _this.mediaRecorder = new MediaRecorder(_this.stream.getMediaStream(), options);
- }
- else {
- console.warn('isTypeSupported is not supported, using default codecs for browser');
- _this.mediaRecorder = new MediaRecorder(_this.stream.getMediaStream());
- }
- _this.mediaRecorder.start(10);
- }
- catch (err) {
- reject(err);
- }
- _this.mediaRecorder.ondataavailable = function (e) {
- _this.chunks.push(e.data);
- };
- _this.mediaRecorder.onerror = function (e) {
- console.error('MediaRecorder error: ', e);
- };
- _this.mediaRecorder.onstart = function () {
- console.log('MediaRecorder started (state=' + _this.mediaRecorder.state + ')');
- };
- _this.mediaRecorder.onstop = function () {
- _this.onStopDefault();
- };
- _this.mediaRecorder.onpause = function () {
- console.log('MediaRecorder paused (state=' + _this.mediaRecorder.state + ')');
- };
- _this.mediaRecorder.onresume = function () {
- console.log('MediaRecorder resumed (state=' + _this.mediaRecorder.state + ')');
- };
- _this.mediaRecorder.onwarning = function (e) {
- console.log('MediaRecorder warning: ' + e);
- };
- _this.state = LocalRecorderState_1.LocalRecorderState.RECORDING;
- resolve();
- });
- };
- LocalRecorder.prototype.stop = function () {
- var _this = this;
- return new Promise(function (resolve, reject) {
- try {
- if (_this.state === LocalRecorderState_1.LocalRecorderState.READY || _this.state === LocalRecorderState_1.LocalRecorderState.FINISHED) {
- throw (Error('\'LocalRecord.stop()\' needs \'LocalRecord.state\' to be \'RECORDING\' or \'PAUSED\' (current value: \'' + _this.state + '\'). Call \'LocalRecorder.start()\' before'));
- }
- _this.mediaRecorder.onstop = function () {
- _this.onStopDefault();
- resolve();
- };
- _this.mediaRecorder.stop();
- }
- catch (e) {
- reject(e);
- }
- });
- };
- LocalRecorder.prototype.pause = function () {
- var _this = this;
- return new Promise(function (resolve, reject) {
- try {
- if (_this.state !== LocalRecorderState_1.LocalRecorderState.RECORDING) {
- reject(Error('\'LocalRecord.pause()\' needs \'LocalRecord.state\' to be \'RECORDING\' (current value: \'' + _this.state + '\'). Call \'LocalRecorder.start()\' or \'LocalRecorder.resume()\' before'));
- }
- _this.mediaRecorder.pause();
- _this.state = LocalRecorderState_1.LocalRecorderState.PAUSED;
- }
- catch (error) {
- reject(error);
- }
- });
- };
- LocalRecorder.prototype.resume = function () {
- var _this = this;
- return new Promise(function (resolve, reject) {
- try {
- if (_this.state !== LocalRecorderState_1.LocalRecorderState.PAUSED) {
- throw (Error('\'LocalRecord.resume()\' needs \'LocalRecord.state\' to be \'PAUSED\' (current value: \'' + _this.state + '\'). Call \'LocalRecorder.pause()\' before'));
- }
- _this.mediaRecorder.resume();
- _this.state = LocalRecorderState_1.LocalRecorderState.RECORDING;
- }
- catch (error) {
- reject(error);
- }
- });
- };
- LocalRecorder.prototype.preview = function (parentElement) {
- if (this.state !== LocalRecorderState_1.LocalRecorderState.FINISHED) {
- throw (Error('\'LocalRecord.preview()\' needs \'LocalRecord.state\' to be \'FINISHED\' (current value: \'' + this.state + '\'). Call \'LocalRecorder.stop()\' before'));
- }
- this.videoPreview = document.createElement('video');
- this.videoPreview.id = this.id;
- this.videoPreview.autoplay = true;
- if (typeof parentElement === 'string') {
- this.htmlParentElementId = parentElement;
- var parentElementDom = document.getElementById(parentElement);
- if (parentElementDom) {
- this.videoPreview = parentElementDom.appendChild(this.videoPreview);
- }
- }
- else {
- this.htmlParentElementId = parentElement.id;
- this.videoPreview = parentElement.appendChild(this.videoPreview);
- }
- this.videoPreview.src = this.videoPreviewSrc;
- return this.videoPreview;
- };
- LocalRecorder.prototype.clean = function () {
- var _this = this;
- var f = function () {
- delete _this.blob;
- _this.chunks = [];
- _this.count = 0;
- delete _this.mediaRecorder;
- _this.state = LocalRecorderState_1.LocalRecorderState.READY;
- };
- if (this.state === LocalRecorderState_1.LocalRecorderState.RECORDING || this.state === LocalRecorderState_1.LocalRecorderState.PAUSED) {
- this.stop().then(function () { return f(); }).catch(function () { return f(); });
- }
- else {
- f();
- }
- };
- LocalRecorder.prototype.download = function () {
- if (this.state !== LocalRecorderState_1.LocalRecorderState.FINISHED) {
- throw (Error('\'LocalRecord.download()\' needs \'LocalRecord.state\' to be \'FINISHED\' (current value: \'' + this.state + '\'). Call \'LocalRecorder.stop()\' before'));
- }
- else {
- var a = document.createElement('a');
- a.style.display = 'none';
- document.body.appendChild(a);
- var url = window.URL.createObjectURL(this.blob);
- a.href = url;
- a.download = this.id + '.webm';
- a.click();
- window.URL.revokeObjectURL(url);
- document.body.removeChild(a);
- }
- };
- LocalRecorder.prototype.getBlob = function () {
- if (this.state !== LocalRecorderState_1.LocalRecorderState.FINISHED) {
- throw (Error('Call \'LocalRecord.stop()\' before getting Blob file'));
- }
- else {
- return this.blob;
- }
- };
- LocalRecorder.prototype.uploadAsBinary = function (endpoint, headers) {
- var _this = this;
- return new Promise(function (resolve, reject) {
- if (_this.state !== LocalRecorderState_1.LocalRecorderState.FINISHED) {
- reject(Error('\'LocalRecord.uploadAsBinary()\' needs \'LocalRecord.state\' to be \'FINISHED\' (current value: \'' + _this.state + '\'). Call \'LocalRecorder.stop()\' before'));
- }
- else {
- var http_1 = new XMLHttpRequest();
- http_1.open('POST', endpoint, true);
- if (typeof headers === 'object') {
- for (var _i = 0, _a = Object.keys(headers); _i < _a.length; _i++) {
- var key = _a[_i];
- http_1.setRequestHeader(key, headers[key]);
- }
- }
- http_1.onreadystatechange = function () {
- if (http_1.readyState === 4) {
- if (http_1.status.toString().charAt(0) === '2') {
- resolve(http_1.responseText);
- }
- else {
- reject(http_1.status);
- }
- }
- };
- http_1.send(_this.blob);
- }
- });
- };
- LocalRecorder.prototype.uploadAsMultipartfile = function (endpoint, headers) {
- var _this = this;
- return new Promise(function (resolve, reject) {
- if (_this.state !== LocalRecorderState_1.LocalRecorderState.FINISHED) {
- reject(Error('\'LocalRecord.uploadAsMultipartfile()\' needs \'LocalRecord.state\' to be \'FINISHED\' (current value: \'' + _this.state + '\'). Call \'LocalRecorder.stop()\' before'));
- }
- else {
- var http_2 = new XMLHttpRequest();
- http_2.open('POST', endpoint, true);
- if (typeof headers === 'object') {
- for (var _i = 0, _a = Object.keys(headers); _i < _a.length; _i++) {
- var key = _a[_i];
- http_2.setRequestHeader(key, headers[key]);
- }
- }
- var sendable = new FormData();
- sendable.append('file', _this.blob, _this.id + '.webm');
- http_2.onreadystatechange = function () {
- if (http_2.readyState === 4) {
- if (http_2.status.toString().charAt(0) === '2') {
- resolve(http_2.responseText);
- }
- else {
- reject(http_2.status);
- }
- }
- };
- http_2.send(sendable);
- }
- });
- };
- LocalRecorder.prototype.onStopDefault = function () {
- console.log('MediaRecorder stopped (state=' + this.mediaRecorder.state + ')');
- this.blob = new Blob(this.chunks, { type: 'video/webm' });
- this.chunks = [];
- this.videoPreviewSrc = window.URL.createObjectURL(this.blob);
- this.state = LocalRecorderState_1.LocalRecorderState.FINISHED;
- };
- return LocalRecorder;
-}());
-exports.LocalRecorder = LocalRecorder;
-
-},{"../OpenViduInternal/Enums/LocalRecorderState":25}],19:[function(require,module,exports){
-"use strict";
-Object.defineProperty(exports, "__esModule", { value: true });
-var LocalRecorder_1 = require("./LocalRecorder");
-var Publisher_1 = require("./Publisher");
-var Session_1 = require("./Session");
-var StreamPropertyChangedEvent_1 = require("../OpenViduInternal/Events/StreamPropertyChangedEvent");
-var OpenViduError_1 = require("../OpenViduInternal/Enums/OpenViduError");
-var VideoInsertMode_1 = require("../OpenViduInternal/Enums/VideoInsertMode");
-var screenSharingAuto = require("../OpenViduInternal/ScreenSharing/Screen-Capturing-Auto");
-var screenSharing = require("../OpenViduInternal/ScreenSharing/Screen-Capturing");
-var RpcBuilder = require("../OpenViduInternal/KurentoUtils/kurento-jsonrpc");
-var platform = require("platform");
-var OpenVidu = (function () {
- function OpenVidu() {
- var _this = this;
- this.publishers = [];
- this.secret = '';
- this.recorder = false;
- this.advancedConfiguration = {};
- console.info("'OpenVidu' initialized");
- if (platform.name.toLowerCase().indexOf('mobile') !== -1) {
- window.onorientationchange = function () {
- _this.publishers.forEach(function (publisher) {
- if (!!publisher.stream && !!publisher.stream.hasVideo && !!publisher.stream.streamManager.videos[0]) {
- var attempts_1 = 0;
- var oldWidth_1 = publisher.stream.videoDimensions.width;
- var oldHeight_1 = publisher.stream.videoDimensions.height;
- var firefoxSettings_1 = publisher.stream.getMediaStream().getVideoTracks()[0].getSettings();
- var newWidth_1 = (platform.name.toLowerCase().indexOf('firefox') !== -1) ? firefoxSettings_1.width : publisher.videoReference.videoWidth;
- var newHeight_1 = (platform.name.toLowerCase().indexOf('firefox') !== -1) ? firefoxSettings_1.height : publisher.videoReference.videoHeight;
- var repeatUntilChange_1 = setInterval(function () {
- firefoxSettings_1 = publisher.stream.getMediaStream().getVideoTracks()[0].getSettings();
- newWidth_1 = (platform.name.toLowerCase().indexOf('firefox') !== -1) ? firefoxSettings_1.width : publisher.videoReference.videoWidth;
- newHeight_1 = (platform.name.toLowerCase().indexOf('firefox') !== -1) ? firefoxSettings_1.height : publisher.videoReference.videoHeight;
- sendStreamPropertyChangedEvent_1(oldWidth_1, oldHeight_1, newWidth_1, newHeight_1);
- }, 100);
- var sendStreamPropertyChangedEvent_1 = function (oldWidth, oldHeight, newWidth, newHeight) {
- attempts_1++;
- if (attempts_1 > 4) {
- clearTimeout(repeatUntilChange_1);
- }
- if (newWidth !== oldWidth || newHeight !== oldHeight) {
- publisher.stream.videoDimensions = {
- width: newWidth || 0,
- height: newHeight || 0
- };
- _this.sendRequest('streamPropertyChanged', {
- streamId: publisher.stream.streamId,
- property: 'videoDimensions',
- newValue: JSON.stringify(publisher.stream.videoDimensions),
- reason: 'deviceRotated'
- }, function (error, response) {
- if (error) {
- console.error("Error sending 'streamPropertyChanged' event", error);
- }
- else {
- _this.session.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent_1.StreamPropertyChangedEvent(_this.session, publisher.stream, 'videoDimensions', publisher.stream.videoDimensions, { width: oldWidth, height: oldHeight }, 'deviceRotated')]);
- publisher.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent_1.StreamPropertyChangedEvent(publisher, publisher.stream, 'videoDimensions', publisher.stream.videoDimensions, { width: oldWidth, height: oldHeight }, 'deviceRotated')]);
- }
- });
- clearTimeout(repeatUntilChange_1);
- }
- };
- }
- });
- };
- }
- }
- OpenVidu.prototype.initSession = function () {
- this.session = new Session_1.Session(this);
- return this.session;
- };
- OpenVidu.prototype.initPublisher = function (targetElement, param2, param3) {
- var properties;
- if (!!param2 && (typeof param2 !== 'function')) {
- properties = param2;
- properties = {
- audioSource: (typeof properties.audioSource !== 'undefined') ? properties.audioSource : undefined,
- frameRate: this.isMediaStreamTrack(properties.videoSource) ? undefined : ((typeof properties.frameRate !== 'undefined') ? properties.frameRate : undefined),
- insertMode: (typeof properties.insertMode !== 'undefined') ? ((typeof properties.insertMode === 'string') ? VideoInsertMode_1.VideoInsertMode[properties.insertMode] : properties.insertMode) : VideoInsertMode_1.VideoInsertMode.APPEND,
- mirror: (typeof properties.mirror !== 'undefined') ? properties.mirror : true,
- publishAudio: (typeof properties.publishAudio !== 'undefined') ? properties.publishAudio : true,
- publishVideo: (typeof properties.publishVideo !== 'undefined') ? properties.publishVideo : true,
- resolution: this.isMediaStreamTrack(properties.videoSource) ? undefined : ((typeof properties.resolution !== 'undefined') ? properties.resolution : '640x480'),
- videoSource: (typeof properties.videoSource !== 'undefined') ? properties.videoSource : undefined
- };
- }
- else {
- properties = {
- insertMode: VideoInsertMode_1.VideoInsertMode.APPEND,
- mirror: true,
- publishAudio: true,
- publishVideo: true,
- resolution: '640x480'
- };
- }
- var publisher = new Publisher_1.Publisher(targetElement, properties, this);
- var completionHandler;
- if (!!param2 && (typeof param2 === 'function')) {
- completionHandler = param2;
- }
- else if (!!param3) {
- completionHandler = param3;
- }
- publisher.initialize()
- .then(function () {
- if (completionHandler !== undefined) {
- completionHandler(undefined);
- }
- publisher.emitEvent('accessAllowed', []);
- }).catch(function (error) {
- if (completionHandler !== undefined) {
- completionHandler(error);
- }
- publisher.emitEvent('accessDenied', []);
- });
- this.publishers.push(publisher);
- return publisher;
- };
- OpenVidu.prototype.initPublisherAsync = function (targetElement, properties) {
- var _this = this;
- return new Promise(function (resolve, reject) {
- var publisher;
- var callback = function (error) {
- if (!!error) {
- reject(error);
- }
- else {
- resolve(publisher);
- }
- };
- if (!!properties) {
- publisher = _this.initPublisher(targetElement, properties, callback);
- }
- else {
- publisher = _this.initPublisher(targetElement, callback);
- }
- });
- };
- OpenVidu.prototype.initLocalRecorder = function (stream) {
- return new LocalRecorder_1.LocalRecorder(stream);
- };
- OpenVidu.prototype.checkSystemRequirements = function () {
- var browser = platform.name;
- var version = platform.version;
- if ((browser !== 'Chrome') && (browser !== 'Chrome Mobile') &&
- (browser !== 'Firefox') && (browser !== 'Firefox Mobile') && (browser !== 'Firefox for iOS') &&
- (browser !== 'Opera') && (browser !== 'Opera Mobile') &&
- (browser !== 'Safari')) {
- return 0;
- }
- else {
- return 1;
- }
- };
- OpenVidu.prototype.getDevices = function () {
- return new Promise(function (resolve, reject) {
- navigator.mediaDevices.enumerateDevices().then(function (deviceInfos) {
- var devices = [];
- deviceInfos.forEach(function (deviceInfo) {
- if (deviceInfo.kind === 'audioinput' || deviceInfo.kind === 'videoinput') {
- devices.push({
- kind: deviceInfo.kind,
- deviceId: deviceInfo.deviceId,
- label: deviceInfo.label
- });
- }
- });
- resolve(devices);
- }).catch(function (error) {
- console.error('Error getting devices', error);
- reject(error);
- });
- });
- };
- OpenVidu.prototype.getUserMedia = function (options) {
- var _this = this;
- return new Promise(function (resolve, reject) {
- _this.generateMediaConstraints(options)
- .then(function (constraints) {
- navigator.mediaDevices.getUserMedia(constraints)
- .then(function (mediaStream) {
- resolve(mediaStream);
- })
- .catch(function (error) {
- var errorName;
- var errorMessage = error.toString();
- if (!(options.videoSource === 'screen')) {
- errorName = OpenViduError_1.OpenViduErrorName.DEVICE_ACCESS_DENIED;
- }
- else {
- errorName = OpenViduError_1.OpenViduErrorName.SCREEN_CAPTURE_DENIED;
- }
- reject(new OpenViduError_1.OpenViduError(errorName, errorMessage));
- });
- })
- .catch(function (error) {
- reject(error);
- });
- });
- };
- OpenVidu.prototype.enableProdMode = function () {
- console.log = function () { };
- console.debug = function () { };
- console.info = function () { };
- console.warn = function () { };
- };
- OpenVidu.prototype.setAdvancedConfiguration = function (configuration) {
- this.advancedConfiguration = configuration;
- };
- OpenVidu.prototype.generateMediaConstraints = function (publisherProperties) {
- var _this = this;
- return new Promise(function (resolve, reject) {
- var audio, video;
- if (publisherProperties.audioSource === null || publisherProperties.audioSource === false) {
- audio = false;
- }
- else if (publisherProperties.audioSource === undefined) {
- audio = true;
- }
- else {
- audio = publisherProperties.audioSource;
- }
- if (publisherProperties.videoSource === null || publisherProperties.videoSource === false) {
- video = false;
- }
- else {
- video = {
- height: {
- ideal: 480
- },
- width: {
- ideal: 640
- }
- };
- }
- var mediaConstraints = {
- audio: audio,
- video: video
- };
- if (typeof mediaConstraints.audio === 'string') {
- mediaConstraints.audio = { deviceId: { exact: mediaConstraints.audio } };
- }
- if (mediaConstraints.video) {
- if (!!publisherProperties.resolution) {
- var widthAndHeight = publisherProperties.resolution.toLowerCase().split('x');
- var width = Number(widthAndHeight[0]);
- var height = Number(widthAndHeight[1]);
- mediaConstraints.video.width.ideal = width;
- mediaConstraints.video.height.ideal = height;
- }
- if (!!publisherProperties.frameRate) {
- mediaConstraints.video.frameRate = { ideal: publisherProperties.frameRate };
- }
- if (!!publisherProperties.videoSource && typeof publisherProperties.videoSource === 'string') {
- if (publisherProperties.videoSource === 'screen') {
- if (platform.name !== 'Chrome' && platform.name.indexOf('Firefox') === -1) {
- var error = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_SHARING_NOT_SUPPORTED, 'You can only screen share in desktop Chrome and Firefox. Detected browser: ' + platform.name);
- console.error(error);
- reject(error);
- }
- else {
- if (!!_this.advancedConfiguration.screenShareChromeExtension && !(platform.name.indexOf('Firefox') !== -1)) {
- screenSharing.getScreenConstraints(function (error, screenConstraints) {
- if (!!error || !!screenConstraints.mandatory && screenConstraints.mandatory.chromeMediaSource === 'screen') {
- if (error === 'permission-denied' || error === 'PermissionDeniedError') {
- var error_1 = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_CAPTURE_DENIED, 'You must allow access to one window of your desktop');
- console.error(error_1);
- reject(error_1);
- }
- else {
- var extensionId = _this.advancedConfiguration.screenShareChromeExtension.split('/').pop().trim();
- screenSharing.getChromeExtensionStatus(extensionId, function (status) {
- if (status === 'installed-disabled') {
- var error_2 = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_EXTENSION_DISABLED, 'You must enable the screen extension');
- console.error(error_2);
- reject(error_2);
- }
- if (status === 'not-installed') {
- var error_3 = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_EXTENSION_NOT_INSTALLED, _this.advancedConfiguration.screenShareChromeExtension);
- console.error(error_3);
- reject(error_3);
- }
- });
- }
- }
- else {
- mediaConstraints.video = screenConstraints;
- resolve(mediaConstraints);
- }
- });
- }
- else {
- screenSharingAuto.getScreenId(function (error, sourceId, screenConstraints) {
- if (!!error) {
- if (error === 'not-installed') {
- var extensionUrl = !!_this.advancedConfiguration.screenShareChromeExtension ? _this.advancedConfiguration.screenShareChromeExtension :
- 'https://chrome.google.com/webstore/detail/openvidu-screensharing/lfcgfepafnobdloecchnfaclibenjold';
- var error_4 = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_EXTENSION_NOT_INSTALLED, extensionUrl);
- console.error(error_4);
- reject(error_4);
- }
- else if (error === 'installed-disabled') {
- var error_5 = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_EXTENSION_DISABLED, 'You must enable the screen extension');
- console.error(error_5);
- reject(error_5);
- }
- else if (error === 'permission-denied') {
- var error_6 = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_CAPTURE_DENIED, 'You must allow access to one window of your desktop');
- console.error(error_6);
- reject(error_6);
- }
- }
- else {
- mediaConstraints.video = screenConstraints.video;
- resolve(mediaConstraints);
- }
- });
- }
- publisherProperties.videoSource = 'screen';
- }
- }
- else {
- mediaConstraints.video['deviceId'] = { exact: publisherProperties.videoSource };
- resolve(mediaConstraints);
- }
- }
- else {
- resolve(mediaConstraints);
- }
- }
- else {
- resolve(mediaConstraints);
- }
- });
- };
- OpenVidu.prototype.startWs = function (onConnectSucces) {
- var config = {
- heartbeat: 5000,
- sendCloseMessage: false,
- ws: {
- uri: this.wsUri,
- useSockJS: false,
- onconnected: onConnectSucces,
- ondisconnect: this.disconnectCallback.bind(this),
- onreconnecting: this.reconnectingCallback.bind(this),
- onreconnected: this.reconnectedCallback.bind(this)
- },
- rpc: {
- requestTimeout: 10000,
- participantJoined: this.session.onParticipantJoined.bind(this.session),
- participantPublished: this.session.onParticipantPublished.bind(this.session),
- participantUnpublished: this.session.onParticipantUnpublished.bind(this.session),
- participantLeft: this.session.onParticipantLeft.bind(this.session),
- participantEvicted: this.session.onParticipantEvicted.bind(this.session),
- recordingStarted: this.session.onRecordingStarted.bind(this.session),
- recordingStopped: this.session.onRecordingStopped.bind(this.session),
- sendMessage: this.session.onNewMessage.bind(this.session),
- streamPropertyChanged: this.session.onStreamPropertyChanged.bind(this.session),
- iceCandidate: this.session.recvIceCandidate.bind(this.session),
- mediaError: this.session.onMediaError.bind(this.session)
- }
- };
- this.jsonRpcClient = new RpcBuilder.clients.JsonRpcClient(config);
- };
- OpenVidu.prototype.closeWs = function () {
- this.jsonRpcClient.close();
- };
- OpenVidu.prototype.sendRequest = function (method, params, callback) {
- if (params && params instanceof Function) {
- callback = params;
- params = {};
- }
- console.debug('Sending request: {method:"' + method + '", params: ' + JSON.stringify(params) + '}');
- this.jsonRpcClient.send(method, params, callback);
- };
- OpenVidu.prototype.isMediaStreamTrack = function (mediaSource) {
- var is = (!!mediaSource &&
- mediaSource.enabled !== undefined && typeof mediaSource.enabled === 'boolean' &&
- mediaSource.id !== undefined && typeof mediaSource.id === 'string' &&
- mediaSource.kind !== undefined && typeof mediaSource.kind === 'string' &&
- mediaSource.label !== undefined && typeof mediaSource.label === 'string' &&
- mediaSource.muted !== undefined && typeof mediaSource.muted === 'boolean' &&
- mediaSource.readyState !== undefined && typeof mediaSource.readyState === 'string');
- return is;
- };
- OpenVidu.prototype.getWsUri = function () {
- return this.wsUri;
- };
- OpenVidu.prototype.getSecret = function () {
- return this.secret;
- };
- OpenVidu.prototype.getRecorder = function () {
- return this.recorder;
- };
- OpenVidu.prototype.disconnectCallback = function () {
- console.warn('Websocket connection lost');
- if (this.isRoomAvailable()) {
- this.session.onLostConnection();
- }
- else {
- alert('Connection error. Please reload page.');
- }
- };
- OpenVidu.prototype.reconnectingCallback = function () {
- console.warn('Websocket connection lost (reconnecting)');
- if (this.isRoomAvailable()) {
- this.session.onLostConnection();
- }
- else {
- alert('Connection error. Please reload page.');
- }
- };
- OpenVidu.prototype.reconnectedCallback = function () {
- console.warn('Websocket reconnected');
- if (this.isRoomAvailable()) {
- this.session.onRecoveredConnection();
- }
- else {
- alert('Connection error. Please reload page.');
- }
- };
- OpenVidu.prototype.isRoomAvailable = function () {
- if (this.session !== undefined && this.session instanceof Session_1.Session) {
- return true;
- }
- else {
- console.warn('Session instance not found');
- return false;
- }
- };
- return OpenVidu;
-}());
-exports.OpenVidu = OpenVidu;
-
-},{"../OpenViduInternal/Enums/OpenViduError":26,"../OpenViduInternal/Enums/VideoInsertMode":27,"../OpenViduInternal/Events/StreamPropertyChangedEvent":36,"../OpenViduInternal/KurentoUtils/kurento-jsonrpc":43,"../OpenViduInternal/ScreenSharing/Screen-Capturing":48,"../OpenViduInternal/ScreenSharing/Screen-Capturing-Auto":47,"./LocalRecorder":18,"./Publisher":20,"./Session":21,"platform":8}],20:[function(require,module,exports){
-"use strict";
-var __extends = (this && this.__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 __());
- };
-})();
-Object.defineProperty(exports, "__esModule", { value: true });
-var Session_1 = require("./Session");
-var Stream_1 = require("./Stream");
-var StreamManager_1 = require("./StreamManager");
-var StreamEvent_1 = require("../OpenViduInternal/Events/StreamEvent");
-var StreamPropertyChangedEvent_1 = require("../OpenViduInternal/Events/StreamPropertyChangedEvent");
-var VideoElementEvent_1 = require("../OpenViduInternal/Events/VideoElementEvent");
-var OpenViduError_1 = require("../OpenViduInternal/Enums/OpenViduError");
-var platform = require("platform");
-var Publisher = (function (_super) {
- __extends(Publisher, _super);
- function Publisher(targEl, properties, openvidu) {
- var _this = _super.call(this, new Stream_1.Stream((!!openvidu.session) ? openvidu.session : new Session_1.Session(openvidu), { publisherProperties: properties, mediaConstraints: {} }), targEl) || this;
- _this.accessAllowed = false;
- _this.isSubscribedToRemote = false;
- _this.accessDenied = false;
- _this.properties = properties;
- _this.openvidu = openvidu;
- _this.stream.ee.on('local-stream-destroyed', function (reason) {
- _this.stream.isLocalStreamPublished = false;
- var streamEvent = new StreamEvent_1.StreamEvent(true, _this, 'streamDestroyed', _this.stream, reason);
- _this.emitEvent('streamDestroyed', [streamEvent]);
- streamEvent.callDefaultBehavior();
- });
- return _this;
- }
- Publisher.prototype.publishAudio = function (value) {
- var _this = this;
- if (this.stream.audioActive !== value) {
- this.stream.getMediaStream().getAudioTracks().forEach(function (track) {
- track.enabled = value;
- });
- this.session.openvidu.sendRequest('streamPropertyChanged', {
- streamId: this.stream.streamId,
- property: 'audioActive',
- newValue: value,
- reason: 'publishAudio'
- }, function (error, response) {
- if (error) {
- console.error("Error sending 'streamPropertyChanged' event", error);
- }
- else {
- _this.session.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent_1.StreamPropertyChangedEvent(_this.session, _this.stream, 'audioActive', value, !value, 'publishAudio')]);
- _this.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent_1.StreamPropertyChangedEvent(_this, _this.stream, 'audioActive', value, !value, 'publishAudio')]);
- }
- });
- this.stream.audioActive = value;
- console.info("'Publisher' has " + (value ? 'published' : 'unpublished') + ' its audio stream');
- }
- };
- Publisher.prototype.publishVideo = function (value) {
- var _this = this;
- if (this.stream.videoActive !== value) {
- this.stream.getMediaStream().getVideoTracks().forEach(function (track) {
- track.enabled = value;
- });
- this.session.openvidu.sendRequest('streamPropertyChanged', {
- streamId: this.stream.streamId,
- property: 'videoActive',
- newValue: value,
- reason: 'publishVideo'
- }, function (error, response) {
- if (error) {
- console.error("Error sending 'streamPropertyChanged' event", error);
- }
- else {
- _this.session.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent_1.StreamPropertyChangedEvent(_this.session, _this.stream, 'videoActive', value, !value, 'publishVideo')]);
- _this.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent_1.StreamPropertyChangedEvent(_this, _this.stream, 'videoActive', value, !value, 'publishVideo')]);
- }
- });
- this.stream.videoActive = value;
- console.info("'Publisher' has " + (value ? 'published' : 'unpublished') + ' its video stream');
- }
- };
- Publisher.prototype.subscribeToRemote = function (value) {
- value = (value !== undefined) ? value : true;
- this.isSubscribedToRemote = value;
- this.stream.subscribeToMyRemote(value);
- };
- Publisher.prototype.on = function (type, handler) {
- var _this = this;
- _super.prototype.on.call(this, type, handler);
- if (type === 'streamCreated') {
- if (!!this.stream && this.stream.isLocalStreamPublished) {
- this.emitEvent('streamCreated', [new StreamEvent_1.StreamEvent(false, this, 'streamCreated', this.stream, '')]);
- }
- else {
- this.stream.ee.on('stream-created-by-publisher', function () {
- _this.emitEvent('streamCreated', [new StreamEvent_1.StreamEvent(false, _this, 'streamCreated', _this.stream, '')]);
- });
- }
- }
- if (type === 'remoteVideoPlaying') {
- if (this.stream.displayMyRemote() && this.videos[0] && this.videos[0].video &&
- this.videos[0].video.currentTime > 0 &&
- this.videos[0].video.paused === false &&
- this.videos[0].video.ended === false &&
- this.videos[0].video.readyState === 4) {
- this.emitEvent('remoteVideoPlaying', [new VideoElementEvent_1.VideoElementEvent(this.videos[0].video, this, 'remoteVideoPlaying')]);
- }
- }
- if (type === 'accessAllowed') {
- if (this.accessAllowed) {
- this.emitEvent('accessAllowed', []);
- }
- }
- if (type === 'accessDenied') {
- if (this.accessDenied) {
- this.emitEvent('accessDenied', []);
- }
- }
- return this;
- };
- Publisher.prototype.once = function (type, handler) {
- var _this = this;
- _super.prototype.once.call(this, type, handler);
- if (type === 'streamCreated') {
- if (!!this.stream && this.stream.isLocalStreamPublished) {
- this.emitEvent('streamCreated', [new StreamEvent_1.StreamEvent(false, this, 'streamCreated', this.stream, '')]);
- }
- else {
- this.stream.ee.once('stream-created-by-publisher', function () {
- _this.emitEvent('streamCreated', [new StreamEvent_1.StreamEvent(false, _this, 'streamCreated', _this.stream, '')]);
- });
- }
- }
- if (type === 'remoteVideoPlaying') {
- if (this.stream.displayMyRemote() && this.videos[0] && this.videos[0].video &&
- this.videos[0].video.currentTime > 0 &&
- this.videos[0].video.paused === false &&
- this.videos[0].video.ended === false &&
- this.videos[0].video.readyState === 4) {
- this.emitEvent('remoteVideoPlaying', [new VideoElementEvent_1.VideoElementEvent(this.videos[0].video, this, 'remoteVideoPlaying')]);
- }
- }
- if (type === 'accessAllowed') {
- if (this.accessAllowed) {
- this.emitEvent('accessAllowed', []);
- }
- }
- if (type === 'accessDenied') {
- if (this.accessDenied) {
- this.emitEvent('accessDenied', []);
- }
- }
- return this;
- };
- Publisher.prototype.initialize = function () {
- var _this = this;
- return new Promise(function (resolve, reject) {
- var errorCallback = function (openViduError) {
- _this.accessDenied = true;
- _this.accessAllowed = false;
- reject(openViduError);
- };
- var successCallback = function (mediaStream) {
- _this.accessAllowed = true;
- _this.accessDenied = false;
- if (_this.openvidu.isMediaStreamTrack(_this.properties.audioSource)) {
- mediaStream.removeTrack(mediaStream.getAudioTracks()[0]);
- mediaStream.addTrack(_this.properties.audioSource);
- }
- if (_this.openvidu.isMediaStreamTrack(_this.properties.videoSource)) {
- mediaStream.removeTrack(mediaStream.getVideoTracks()[0]);
- mediaStream.addTrack(_this.properties.videoSource);
- }
- if (!!mediaStream.getAudioTracks()[0]) {
- mediaStream.getAudioTracks()[0].enabled = !!_this.stream.outboundStreamOpts.publisherProperties.publishAudio;
- }
- if (!!mediaStream.getVideoTracks()[0]) {
- mediaStream.getVideoTracks()[0].enabled = !!_this.stream.outboundStreamOpts.publisherProperties.publishVideo;
- }
- _this.videoReference = document.createElement('video');
- _this.videoReference.srcObject = mediaStream;
- _this.stream.setMediaStream(mediaStream);
- if (!_this.stream.displayMyRemote()) {
- _this.stream.updateMediaStreamInVideos();
- }
- if (!!_this.firstVideoElement) {
- _this.createVideoElement(_this.firstVideoElement.targetElement, _this.properties.insertMode);
- }
- delete _this.firstVideoElement;
- if (_this.stream.isSendVideo()) {
- if (!_this.stream.isSendScreen()) {
- var _a = mediaStream.getVideoTracks()[0].getSettings(), width = _a.width, height = _a.height;
- if (platform.name.toLowerCase().indexOf('mobile') !== -1 && (window.innerHeight > window.innerWidth)) {
- _this.stream.videoDimensions = {
- width: height || 0,
- height: width || 0
- };
- }
- else {
- _this.stream.videoDimensions = {
- width: width || 0,
- height: height || 0
- };
- }
- _this.stream.isLocalStreamReadyToPublish = true;
- _this.stream.ee.emitEvent('stream-ready-to-publish', []);
- }
- else {
- _this.videoReference.onloadedmetadata = function () {
- _this.stream.videoDimensions = {
- width: _this.videoReference.videoWidth,
- height: _this.videoReference.videoHeight
- };
- _this.screenShareResizeInterval = setInterval(function () {
- var firefoxSettings = mediaStream.getVideoTracks()[0].getSettings();
- var newWidth = (platform.name === 'Chrome') ? _this.videoReference.videoWidth : firefoxSettings.width;
- var newHeight = (platform.name === 'Chrome') ? _this.videoReference.videoHeight : firefoxSettings.height;
- if (_this.stream.isLocalStreamPublished &&
- (newWidth !== _this.stream.videoDimensions.width ||
- newHeight !== _this.stream.videoDimensions.height)) {
- var oldValue_1 = { width: _this.stream.videoDimensions.width, height: _this.stream.videoDimensions.height };
- _this.stream.videoDimensions = {
- width: newWidth || 0,
- height: newHeight || 0
- };
- _this.session.openvidu.sendRequest('streamPropertyChanged', {
- streamId: _this.stream.streamId,
- property: 'videoDimensions',
- newValue: JSON.stringify(_this.stream.videoDimensions),
- reason: 'screenResized'
- }, function (error, response) {
- if (error) {
- console.error("Error sending 'streamPropertyChanged' event", error);
- }
- else {
- _this.session.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent_1.StreamPropertyChangedEvent(_this.session, _this.stream, 'videoDimensions', _this.stream.videoDimensions, oldValue_1, 'screenResized')]);
- _this.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent_1.StreamPropertyChangedEvent(_this, _this.stream, 'videoDimensions', _this.stream.videoDimensions, oldValue_1, 'screenResized')]);
- }
- });
- }
- }, 500);
- _this.stream.isLocalStreamReadyToPublish = true;
- _this.stream.ee.emitEvent('stream-ready-to-publish', []);
- };
- }
- }
- else {
- _this.stream.isLocalStreamReadyToPublish = true;
- _this.stream.ee.emitEvent('stream-ready-to-publish', []);
- }
- resolve();
- };
- _this.openvidu.generateMediaConstraints(_this.properties)
- .then(function (constraints) {
- var outboundStreamOptions = {
- mediaConstraints: constraints,
- publisherProperties: _this.properties
- };
- _this.stream.setOutboundStreamOptions(outboundStreamOptions);
- var constraintsAux = {};
- var timeForDialogEvent = 1250;
- if (_this.stream.isSendVideo() || _this.stream.isSendAudio()) {
- var definedAudioConstraint_1 = ((constraints.audio === undefined) ? true : constraints.audio);
- constraintsAux.audio = _this.stream.isSendScreen() ? false : definedAudioConstraint_1;
- constraintsAux.video = constraints.video;
- var startTime_1 = Date.now();
- _this.setPermissionDialogTimer(timeForDialogEvent);
- navigator.mediaDevices.getUserMedia(constraintsAux)
- .then(function (mediaStream) {
- _this.clearPermissionDialogTimer(startTime_1, timeForDialogEvent);
- if (_this.stream.isSendScreen() && _this.stream.isSendAudio()) {
- constraintsAux.audio = definedAudioConstraint_1;
- constraintsAux.video = false;
- startTime_1 = Date.now();
- _this.setPermissionDialogTimer(timeForDialogEvent);
- navigator.mediaDevices.getUserMedia(constraintsAux)
- .then(function (audioOnlyStream) {
- _this.clearPermissionDialogTimer(startTime_1, timeForDialogEvent);
- mediaStream.addTrack(audioOnlyStream.getAudioTracks()[0]);
- successCallback(mediaStream);
- })
- .catch(function (error) {
- _this.clearPermissionDialogTimer(startTime_1, timeForDialogEvent);
- var errorName, errorMessage;
- switch (error.name.toLowerCase()) {
- case 'notfounderror':
- errorName = OpenViduError_1.OpenViduErrorName.INPUT_AUDIO_DEVICE_NOT_FOUND;
- errorMessage = error.toString();
- errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage));
- break;
- case 'notallowederror':
- errorName = OpenViduError_1.OpenViduErrorName.DEVICE_ACCESS_DENIED;
- errorMessage = error.toString();
- errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage));
- break;
- case 'overconstrainederror':
- if (error.constraint.toLowerCase() === 'deviceid') {
- errorName = OpenViduError_1.OpenViduErrorName.INPUT_AUDIO_DEVICE_NOT_FOUND;
- errorMessage = "Audio input device with deviceId '" + constraints.video.deviceId.exact + "' not found";
- }
- else {
- errorName = OpenViduError_1.OpenViduErrorName.PUBLISHER_PROPERTIES_ERROR;
- errorMessage = "Audio input device doesn't support the value passed for constraint '" + error.constraint + "'";
- }
- errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage));
- break;
- }
- });
- }
- else {
- successCallback(mediaStream);
- }
- })
- .catch(function (error) {
- _this.clearPermissionDialogTimer(startTime_1, timeForDialogEvent);
- var errorName, errorMessage;
- switch (error.name.toLowerCase()) {
- case 'notfounderror':
- navigator.mediaDevices.getUserMedia({
- audio: false,
- video: constraints.video
- })
- .then(function (mediaStream) {
- mediaStream.getVideoTracks().forEach(function (track) {
- track.stop();
- });
- errorName = OpenViduError_1.OpenViduErrorName.INPUT_AUDIO_DEVICE_NOT_FOUND;
- errorMessage = error.toString();
- errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage));
- }).catch(function (e) {
- errorName = OpenViduError_1.OpenViduErrorName.INPUT_VIDEO_DEVICE_NOT_FOUND;
- errorMessage = error.toString();
- errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage));
- });
- break;
- case 'notallowederror':
- errorName = _this.stream.isSendScreen() ? OpenViduError_1.OpenViduErrorName.SCREEN_CAPTURE_DENIED : OpenViduError_1.OpenViduErrorName.DEVICE_ACCESS_DENIED;
- errorMessage = error.toString();
- errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage));
- break;
- case 'overconstrainederror':
- navigator.mediaDevices.getUserMedia({
- audio: false,
- video: constraints.video
- })
- .then(function (mediaStream) {
- mediaStream.getVideoTracks().forEach(function (track) {
- track.stop();
- });
- if (error.constraint.toLowerCase() === 'deviceid') {
- errorName = OpenViduError_1.OpenViduErrorName.INPUT_AUDIO_DEVICE_NOT_FOUND;
- errorMessage = "Audio input device with deviceId '" + constraints.audio.deviceId.exact + "' not found";
- }
- else {
- errorName = OpenViduError_1.OpenViduErrorName.PUBLISHER_PROPERTIES_ERROR;
- errorMessage = "Audio input device doesn't support the value passed for constraint '" + error.constraint + "'";
- }
- errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage));
- }).catch(function (e) {
- if (error.constraint.toLowerCase() === 'deviceid') {
- errorName = OpenViduError_1.OpenViduErrorName.INPUT_VIDEO_DEVICE_NOT_FOUND;
- errorMessage = "Video input device with deviceId '" + constraints.video.deviceId.exact + "' not found";
- }
- else {
- errorName = OpenViduError_1.OpenViduErrorName.PUBLISHER_PROPERTIES_ERROR;
- errorMessage = "Video input device doesn't support the value passed for constraint '" + error.constraint + "'";
- }
- errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage));
- });
- break;
- }
- });
- }
- else {
- reject(new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.NO_INPUT_SOURCE_SET, "Properties 'audioSource' and 'videoSource' cannot be set to false or null at the same time when calling 'OpenVidu.initPublisher'"));
- }
- })
- .catch(function (error) {
- errorCallback(error);
- });
- });
- };
- Publisher.prototype.updateSession = function (session) {
- this.session = session;
- this.stream.session = session;
- };
- Publisher.prototype.reestablishStreamPlayingEvent = function () {
- if (this.ee.getListeners('streamPlaying').length > 0) {
- this.addPlayEventToFirstVideo();
- }
- };
- Publisher.prototype.setPermissionDialogTimer = function (waitTime) {
- var _this = this;
- this.permissionDialogTimeout = setTimeout(function () {
- _this.emitEvent('accessDialogOpened', []);
- }, waitTime);
- };
- Publisher.prototype.clearPermissionDialogTimer = function (startTime, waitTime) {
- clearTimeout(this.permissionDialogTimeout);
- if ((Date.now() - startTime) > waitTime) {
- this.emitEvent('accessDialogClosed', []);
- }
- };
- return Publisher;
-}(StreamManager_1.StreamManager));
-exports.Publisher = Publisher;
-
-},{"../OpenViduInternal/Enums/OpenViduError":26,"../OpenViduInternal/Events/StreamEvent":34,"../OpenViduInternal/Events/StreamPropertyChangedEvent":36,"../OpenViduInternal/Events/VideoElementEvent":37,"./Session":21,"./Stream":22,"./StreamManager":23,"platform":8}],21:[function(require,module,exports){
-"use strict";
-Object.defineProperty(exports, "__esModule", { value: true });
-var Connection_1 = require("./Connection");
-var Subscriber_1 = require("./Subscriber");
-var ConnectionEvent_1 = require("../OpenViduInternal/Events/ConnectionEvent");
-var RecordingEvent_1 = require("../OpenViduInternal/Events/RecordingEvent");
-var SessionDisconnectedEvent_1 = require("../OpenViduInternal/Events/SessionDisconnectedEvent");
-var SignalEvent_1 = require("../OpenViduInternal/Events/SignalEvent");
-var StreamEvent_1 = require("../OpenViduInternal/Events/StreamEvent");
-var StreamPropertyChangedEvent_1 = require("../OpenViduInternal/Events/StreamPropertyChangedEvent");
-var OpenViduError_1 = require("../OpenViduInternal/Enums/OpenViduError");
-var VideoInsertMode_1 = require("../OpenViduInternal/Enums/VideoInsertMode");
-var platform = require("platform");
-var EventEmitter = require("wolfy87-eventemitter");
-var Session = (function () {
- function Session(openvidu) {
- this.streamManagers = [];
- this.remoteStreamsCreated = {};
- this.remoteConnections = {};
- this.speakingEventsEnabled = false;
- this.ee = new EventEmitter();
- this.openvidu = openvidu;
- }
- Session.prototype.connect = function (token, metadata) {
- var _this = this;
- return new Promise(function (resolve, reject) {
- _this.processToken(token);
- if (_this.openvidu.checkSystemRequirements()) {
- _this.options = {
- sessionId: _this.sessionId,
- participantId: token,
- metadata: !!metadata ? _this.stringClientMetadata(metadata) : ''
- };
- _this.connectAux(token).then(function () {
- resolve();
- }).catch(function (error) {
- reject(error);
- });
- }
- else {
- reject(new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.BROWSER_NOT_SUPPORTED, 'Browser ' + platform.name + ' ' + platform.version + ' is not supported in OpenVidu'));
- }
- });
- };
- Session.prototype.disconnect = function () {
- this.leave(false, 'disconnect');
- };
- Session.prototype.subscribe = function (stream, targetElement, param3, param4) {
- var properties = {};
- if (!!param3 && typeof param3 !== 'function') {
- properties = {
- insertMode: (typeof param3.insertMode !== 'undefined') ? ((typeof param3.insertMode === 'string') ? VideoInsertMode_1.VideoInsertMode[param3.insertMode] : properties.insertMode) : VideoInsertMode_1.VideoInsertMode.APPEND,
- subscribeToAudio: (typeof param3.subscribeToAudio !== 'undefined') ? param3.subscribeToAudio : true,
- subscribeToVideo: (typeof param3.subscribeToVideo !== 'undefined') ? param3.subscribeToVideo : true
- };
- }
- else {
- properties = {
- insertMode: VideoInsertMode_1.VideoInsertMode.APPEND,
- subscribeToAudio: true,
- subscribeToVideo: true
- };
- }
- var completionHandler;
- if (!!param3 && (typeof param3 === 'function')) {
- completionHandler = param3;
- }
- else if (!!param4) {
- completionHandler = param4;
- }
- console.info('Subscribing to ' + stream.connection.connectionId);
- stream.subscribe()
- .then(function () {
- console.info('Subscribed correctly to ' + stream.connection.connectionId);
- if (completionHandler !== undefined) {
- completionHandler(undefined);
- }
- })
- .catch(function (error) {
- if (completionHandler !== undefined) {
- completionHandler(error);
- }
- });
- var subscriber = new Subscriber_1.Subscriber(stream, targetElement, properties);
- if (!!subscriber.targetElement) {
- stream.streamManager.createVideoElement(subscriber.targetElement, properties.insertMode);
- }
- return subscriber;
- };
- Session.prototype.subscribeAsync = function (stream, targetElement, properties) {
- var _this = this;
- return new Promise(function (resolve, reject) {
- var subscriber;
- var callback = function (error) {
- if (!!error) {
- reject(error);
- }
- else {
- resolve(subscriber);
- }
- };
- if (!!properties) {
- subscriber = _this.subscribe(stream, targetElement, properties, callback);
- }
- else {
- subscriber = _this.subscribe(stream, targetElement, callback);
- }
- });
- };
- Session.prototype.unsubscribe = function (subscriber) {
- var connectionId = subscriber.stream.connection.connectionId;
- console.info('Unsubscribing from ' + connectionId);
- this.openvidu.sendRequest('unsubscribeFromVideo', { sender: subscriber.stream.connection.connectionId }, function (error, response) {
- if (error) {
- console.error('Error unsubscribing from ' + connectionId, error);
- }
- else {
- console.info('Unsubscribed correctly from ' + connectionId);
- }
- subscriber.stream.disposeWebRtcPeer();
- subscriber.stream.disposeMediaStream();
- });
- subscriber.stream.streamManager.removeAllVideos();
- };
- Session.prototype.publish = function (publisher) {
- var _this = this;
- return new Promise(function (resolve, reject) {
- publisher.session = _this;
- publisher.stream.session = _this;
- if (!publisher.stream.publishedOnce) {
- _this.connection.addStream(publisher.stream);
- publisher.stream.publish()
- .then(function () {
- resolve();
- })
- .catch(function (error) {
- reject(error);
- });
- }
- else {
- publisher.initialize()
- .then(function () {
- _this.connection.addStream(publisher.stream);
- publisher.reestablishStreamPlayingEvent();
- publisher.stream.publish()
- .then(function () {
- resolve();
- })
- .catch(function (error) {
- reject(error);
- });
- }).catch(function (error) {
- reject(error);
- });
- }
- });
- };
- Session.prototype.unpublish = function (publisher) {
- var stream = publisher.stream;
- if (!stream.connection) {
- console.error('The associated Connection object of this Publisher is null', stream);
- return;
- }
- else if (stream.connection !== this.connection) {
- console.error('The associated Connection object of this Publisher is not your local Connection.' +
- "Only moderators can force unpublish on remote Streams via 'forceUnpublish' method", stream);
- return;
- }
- else {
- console.info('Unpublishing local media (' + stream.connection.connectionId + ')');
- this.openvidu.sendRequest('unpublishVideo', function (error, response) {
- if (error) {
- console.error(error);
- }
- else {
- console.info('Media unpublished correctly');
- }
- });
- stream.disposeWebRtcPeer();
- delete stream.connection.stream;
- var streamEvent = new StreamEvent_1.StreamEvent(true, publisher, 'streamDestroyed', publisher.stream, 'unpublish');
- publisher.emitEvent('streamDestroyed', [streamEvent]);
- streamEvent.callDefaultBehavior();
- }
- };
- Session.prototype.forceDisconnect = function (connection) {
- var _this = this;
- return new Promise(function (resolve, reject) {
- console.info('Forcing disconnect for connection ' + connection.connectionId);
- _this.openvidu.sendRequest('forceDisconnect', { connectionId: connection.connectionId }, function (error, response) {
- if (error) {
- console.error('Error forcing disconnect for Connection ' + connection.connectionId, error);
- if (error.code === 401) {
- reject(new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.OPENVIDU_PERMISSION_DENIED, "You don't have permissions to force a disconnection"));
- }
- else {
- reject(error);
- }
- }
- else {
- console.info('Forcing disconnect correctly for Connection ' + connection.connectionId);
- resolve();
- }
- });
- });
- };
- Session.prototype.forceUnpublish = function (stream) {
- var _this = this;
- return new Promise(function (resolve, reject) {
- console.info('Forcing unpublish for stream ' + stream.streamId);
- _this.openvidu.sendRequest('forceUnpublish', { streamId: stream.streamId }, function (error, response) {
- if (error) {
- console.error('Error forcing unpublish for Stream ' + stream.streamId, error);
- if (error.code === 401) {
- reject(new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.OPENVIDU_PERMISSION_DENIED, "You don't have permissions to force an unpublishing"));
- }
- else {
- reject(error);
- }
- }
- else {
- console.info('Forcing unpublish correctly for Stream ' + stream.streamId);
- resolve();
- }
- });
- });
- };
- Session.prototype.signal = function (signal) {
- var _this = this;
- return new Promise(function (resolve, reject) {
- var signalMessage = {};
- if (signal.to && signal.to.length > 0) {
- var connectionIds_1 = [];
- signal.to.forEach(function (connection) {
- connectionIds_1.push(connection.connectionId);
- });
- signalMessage['to'] = connectionIds_1;
- }
- else {
- signalMessage['to'] = [];
- }
- signalMessage['data'] = signal.data ? signal.data : '';
- signalMessage['type'] = signal.type ? signal.type : '';
- _this.openvidu.sendRequest('sendMessage', {
- message: JSON.stringify(signalMessage)
- }, function (error, response) {
- if (!!error) {
- reject(error);
- }
- else {
- resolve();
- }
- });
- });
- };
- Session.prototype.on = function (type, handler) {
- this.ee.on(type, function (event) {
- if (event) {
- console.info("Event '" + type + "' triggered by 'Session'", event);
- }
- else {
- console.info("Event '" + type + "' triggered by 'Session'");
- }
- handler(event);
- });
- if (type === 'publisherStartSpeaking' || type === 'publisherStopSpeaking') {
- this.speakingEventsEnabled = true;
- for (var connectionId in this.remoteConnections) {
- var str = this.remoteConnections[connectionId].stream;
- if (!!str && !str.speechEvent && str.hasAudio) {
- str.enableSpeakingEvents();
- }
- }
- }
- return this;
- };
- Session.prototype.once = function (type, handler) {
- this.ee.once(type, function (event) {
- if (event) {
- console.info("Event '" + type + "' triggered by 'Session'", event);
- }
- else {
- console.info("Event '" + type + "' triggered by 'Session'");
- }
- handler(event);
- });
- if (type === 'publisherStartSpeaking' || type === 'publisherStopSpeaking') {
- this.speakingEventsEnabled = true;
- for (var connectionId in this.remoteConnections) {
- var str = this.remoteConnections[connectionId].stream;
- if (!!str && !str.speechEvent && str.hasAudio) {
- str.enableOnceSpeakingEvents();
- }
- }
- }
- return this;
- };
- Session.prototype.off = function (type, handler) {
- if (!handler) {
- this.ee.removeAllListeners(type);
- }
- else {
- this.ee.off(type, handler);
- }
- if (type === 'publisherStartSpeaking' || type === 'publisherStopSpeaking') {
- this.speakingEventsEnabled = false;
- for (var connectionId in this.remoteConnections) {
- var str = this.remoteConnections[connectionId].stream;
- if (!!str && !!str.speechEvent) {
- str.disableSpeakingEvents();
- }
- }
- }
- return this;
- };
- Session.prototype.onParticipantJoined = function (response) {
- var _this = this;
- this.getConnection(response.id, '')
- .then(function (connection) {
- console.warn('Connection ' + response.id + ' already exists in connections list');
- })
- .catch(function (openViduError) {
- var connection = new Connection_1.Connection(_this, response);
- _this.remoteConnections[response.id] = connection;
- _this.ee.emitEvent('connectionCreated', [new ConnectionEvent_1.ConnectionEvent(false, _this, 'connectionCreated', connection, '')]);
- });
- };
- Session.prototype.onParticipantLeft = function (msg) {
- var _this = this;
- this.getRemoteConnection(msg.connectionId, 'Remote connection ' + msg.connectionId + " unknown when 'onParticipantLeft'. " +
- 'Existing remote connections: ' + JSON.stringify(Object.keys(this.remoteConnections)))
- .then(function (connection) {
- if (!!connection.stream) {
- var stream = connection.stream;
- var streamEvent = new StreamEvent_1.StreamEvent(true, _this, 'streamDestroyed', stream, msg.reason);
- _this.ee.emitEvent('streamDestroyed', [streamEvent]);
- streamEvent.callDefaultBehavior();
- delete _this.remoteStreamsCreated[stream.streamId];
- }
- delete _this.remoteConnections[connection.connectionId];
- _this.ee.emitEvent('connectionDestroyed', [new ConnectionEvent_1.ConnectionEvent(false, _this, 'connectionDestroyed', connection, msg.reason)]);
- })
- .catch(function (openViduError) {
- console.error(openViduError);
- });
- };
- Session.prototype.onParticipantPublished = function (response) {
- var _this = this;
- var afterConnectionFound = function (connection) {
- _this.remoteConnections[connection.connectionId] = connection;
- if (!_this.remoteStreamsCreated[connection.stream.streamId]) {
- _this.ee.emitEvent('streamCreated', [new StreamEvent_1.StreamEvent(false, _this, 'streamCreated', connection.stream, '')]);
- }
- _this.remoteStreamsCreated[connection.stream.streamId] = true;
- };
- var connection;
- this.getRemoteConnection(response.id, "Remote connection '" + response.id + "' unknown when 'onParticipantPublished'. " +
- 'Existing remote connections: ' + JSON.stringify(Object.keys(this.remoteConnections)))
- .then(function (con) {
- connection = con;
- response.metadata = con.data;
- connection.options = response;
- connection.initRemoteStreams(response.streams);
- afterConnectionFound(connection);
- })
- .catch(function (openViduError) {
- connection = new Connection_1.Connection(_this, response);
- afterConnectionFound(connection);
- });
- };
- Session.prototype.onParticipantUnpublished = function (msg) {
- var _this = this;
- if (msg.connectionId === this.connection.connectionId) {
- this.stopPublisherStream(msg.reason);
- }
- else {
- this.getRemoteConnection(msg.connectionId, "Remote connection '" + msg.connectionId + "' unknown when 'onParticipantUnpublished'. " +
- 'Existing remote connections: ' + JSON.stringify(Object.keys(this.remoteConnections)))
- .then(function (connection) {
- var streamEvent = new StreamEvent_1.StreamEvent(true, _this, 'streamDestroyed', connection.stream, msg.reason);
- _this.ee.emitEvent('streamDestroyed', [streamEvent]);
- streamEvent.callDefaultBehavior();
- var streamId = connection.stream.streamId;
- delete _this.remoteStreamsCreated[streamId];
- connection.removeStream(streamId);
- })
- .catch(function (openViduError) {
- console.error(openViduError);
- });
- }
- };
- Session.prototype.onParticipantEvicted = function (msg) {
- if (msg.connectionId === this.connection.connectionId) {
- if (!!this.sessionId && !this.connection.disposed) {
- this.leave(true, msg.reason);
- }
- }
- };
- Session.prototype.onNewMessage = function (msg) {
- var _this = this;
- console.info('New signal: ' + JSON.stringify(msg));
- this.getConnection(msg.from, "Connection '" + msg.from + "' unknow when 'onNewMessage'. Existing remote connections: "
- + JSON.stringify(Object.keys(this.remoteConnections)) + '. Existing local connection: ' + this.connection.connectionId)
- .then(function (connection) {
- _this.ee.emitEvent('signal', [new SignalEvent_1.SignalEvent(_this, msg.type, msg.data, connection)]);
- _this.ee.emitEvent('signal:' + msg.type, [new SignalEvent_1.SignalEvent(_this, msg.type, msg.data, connection)]);
- })
- .catch(function (openViduError) {
- console.error(openViduError);
- });
- };
- Session.prototype.onStreamPropertyChanged = function (msg) {
- var _this = this;
- this.getRemoteConnection(msg.connectionId, 'Remote connection ' + msg.connectionId + " unknown when 'onStreamPropertyChanged'. " +
- 'Existing remote connections: ' + JSON.stringify(Object.keys(this.remoteConnections)))
- .then(function (connection) {
- if (!!connection.stream && connection.stream.streamId === msg.streamId) {
- var stream = connection.stream;
- var oldValue = void 0;
- switch (msg.property) {
- case 'audioActive':
- oldValue = stream.audioActive;
- msg.newValue = msg.newValue === 'true';
- stream.audioActive = msg.newValue;
- break;
- case 'videoActive':
- oldValue = stream.videoActive;
- msg.newValue = msg.newValue === 'true';
- stream.videoActive = msg.newValue;
- break;
- case 'videoDimensions':
- oldValue = stream.videoDimensions;
- msg.newValue = JSON.parse(JSON.parse(msg.newValue));
- stream.videoDimensions = msg.newValue;
- break;
- }
- _this.ee.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent_1.StreamPropertyChangedEvent(_this, stream, msg.property, msg.newValue, oldValue, msg.reason)]);
- stream.streamManager.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent_1.StreamPropertyChangedEvent(stream.streamManager, stream, msg.property, msg.newValue, oldValue, msg.reason)]);
- }
- else {
- console.error("No stream with streamId '" + msg.streamId + "' found for connection '" + msg.connectionId + "' on 'streamPropertyChanged' event");
- }
- })
- .catch(function (openViduError) {
- console.error(openViduError);
- });
- };
- Session.prototype.recvIceCandidate = function (msg) {
- var candidate = {
- candidate: msg.candidate,
- sdpMid: msg.sdpMid,
- sdpMLineIndex: msg.sdpMLineIndex,
- toJSON: function () {
- return { candidate: msg.candidate };
- }
- };
- this.getConnection(msg.endpointName, 'Connection not found for endpoint ' + msg.endpointName + '. Ice candidate will be ignored: ' + candidate)
- .then(function (connection) {
- var stream = connection.stream;
- stream.getWebRtcPeer().addIceCandidate(candidate).catch(function (error) {
- console.error('Error adding candidate for ' + stream.streamId
- + ' stream of endpoint ' + msg.endpointName + ': ' + error);
- });
- })
- .catch(function (openViduError) {
- console.error(openViduError);
- });
- };
- Session.prototype.onSessionClosed = function (msg) {
- console.info('Session closed: ' + JSON.stringify(msg));
- var s = msg.sessionId;
- if (s !== undefined) {
- this.ee.emitEvent('session-closed', [{
- session: s
- }]);
- }
- else {
- console.warn('Session undefined on session closed', msg);
- }
- };
- Session.prototype.onLostConnection = function () {
- console.warn('Lost connection in Session ' + this.sessionId);
- if (!!this.sessionId && !this.connection.disposed) {
- this.leave(true, 'networkDisconnect');
- }
- };
- Session.prototype.onRecoveredConnection = function () {
- console.warn('Recovered connection in Session ' + this.sessionId);
- this.ee.emitEvent('connectionRecovered', []);
- };
- Session.prototype.onMediaError = function (params) {
- console.error('Media error: ' + JSON.stringify(params));
- var err = params.error;
- if (err) {
- this.ee.emitEvent('error-media', [{
- error: err
- }]);
- }
- else {
- console.warn('Received undefined media error. Params:', params);
- }
- };
- Session.prototype.onRecordingStarted = function (response) {
- this.ee.emitEvent('recordingStarted', [new RecordingEvent_1.RecordingEvent(this, 'recordingStarted', response.id, response.name)]);
- };
- Session.prototype.onRecordingStopped = function (response) {
- this.ee.emitEvent('recordingStopped', [new RecordingEvent_1.RecordingEvent(this, 'recordingStopped', response.id, response.name)]);
- };
- Session.prototype.emitEvent = function (type, eventArray) {
- this.ee.emitEvent(type, eventArray);
- };
- Session.prototype.leave = function (forced, reason) {
- var _this = this;
- forced = !!forced;
- console.info('Leaving Session (forced=' + forced + ')');
- if (!!this.connection) {
- if (!this.connection.disposed && !forced) {
- this.openvidu.sendRequest('leaveRoom', function (error, response) {
- if (error) {
- console.error(error);
- }
- _this.openvidu.closeWs();
- });
- }
- else {
- this.openvidu.closeWs();
- }
- this.stopPublisherStream(reason);
- if (!this.connection.disposed) {
- var sessionDisconnectEvent = new SessionDisconnectedEvent_1.SessionDisconnectedEvent(this, reason);
- this.ee.emitEvent('sessionDisconnected', [sessionDisconnectEvent]);
- sessionDisconnectEvent.callDefaultBehavior();
- }
- }
- else {
- console.warn('You were not connected to the session ' + this.sessionId);
- }
- };
- Session.prototype.connectAux = function (token) {
- var _this = this;
- return new Promise(function (resolve, reject) {
- _this.openvidu.startWs(function (error) {
- if (!!error) {
- reject(error);
- }
- else {
- var joinParams = {
- token: (!!token) ? token : '',
- session: _this.sessionId,
- metadata: !!_this.options.metadata ? _this.options.metadata : '',
- secret: _this.openvidu.getSecret(),
- recorder: _this.openvidu.getRecorder(),
- };
- _this.openvidu.sendRequest('joinRoom', joinParams, function (error, response) {
- if (!!error) {
- reject(error);
- }
- else {
- _this.capabilities = {
- subscribe: true,
- publish: _this.openvidu.role !== 'SUBSCRIBER',
- forceUnpublish: _this.openvidu.role === 'MODERATOR',
- forceDisconnect: _this.openvidu.role === 'MODERATOR'
- };
- _this.connection = new Connection_1.Connection(_this);
- _this.connection.connectionId = response.id;
- _this.connection.data = response.metadata;
- var events_1 = {
- connections: new Array(),
- streams: new Array()
- };
- var existingParticipants = response.value;
- existingParticipants.forEach(function (participant) {
- var connection = new Connection_1.Connection(_this, participant);
- _this.remoteConnections[connection.connectionId] = connection;
- events_1.connections.push(connection);
- if (!!connection.stream) {
- _this.remoteStreamsCreated[connection.stream.streamId] = true;
- events_1.streams.push(connection.stream);
- }
- });
- _this.ee.emitEvent('connectionCreated', [new ConnectionEvent_1.ConnectionEvent(false, _this, 'connectionCreated', _this.connection, '')]);
- events_1.connections.forEach(function (connection) {
- _this.ee.emitEvent('connectionCreated', [new ConnectionEvent_1.ConnectionEvent(false, _this, 'connectionCreated', connection, '')]);
- });
- events_1.streams.forEach(function (stream) {
- _this.ee.emitEvent('streamCreated', [new StreamEvent_1.StreamEvent(false, _this, 'streamCreated', stream, '')]);
- });
- resolve();
- }
- });
- }
- });
- });
- };
- Session.prototype.stopPublisherStream = function (reason) {
- if (!!this.connection.stream) {
- this.connection.stream.disposeWebRtcPeer();
- if (this.connection.stream.isLocalStreamPublished) {
- this.connection.stream.ee.emitEvent('local-stream-destroyed', [reason]);
- }
- }
- };
- Session.prototype.stringClientMetadata = function (metadata) {
- if (typeof metadata !== 'string') {
- return JSON.stringify(metadata);
- }
- else {
- return metadata;
- }
- };
- Session.prototype.getConnection = function (connectionId, errorMessage) {
- var _this = this;
- return new Promise(function (resolve, reject) {
- var connection = _this.remoteConnections[connectionId];
- if (!!connection) {
- resolve(connection);
- }
- else {
- if (_this.connection.connectionId === connectionId) {
- resolve(_this.connection);
- }
- else {
- reject(new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.GENERIC_ERROR, errorMessage));
- }
- }
- });
- };
- Session.prototype.getRemoteConnection = function (connectionId, errorMessage) {
- var _this = this;
- return new Promise(function (resolve, reject) {
- var connection = _this.remoteConnections[connectionId];
- if (!!connection) {
- resolve(connection);
- }
- else {
- reject(new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.GENERIC_ERROR, errorMessage));
- }
- });
- };
- Session.prototype.processToken = function (token) {
- var url = new URL(token);
- this.sessionId = url.searchParams.get('sessionId');
- var secret = url.searchParams.get('secret');
- var recorder = url.searchParams.get('recorder');
- var turnUsername = url.searchParams.get('turnUsername');
- var turnCredential = url.searchParams.get('turnCredential');
- var role = url.searchParams.get('role');
- if (!!secret) {
- this.openvidu.secret = secret;
- }
- if (!!recorder) {
- this.openvidu.recorder = true;
- }
- if (!!turnUsername && !!turnCredential) {
- var stunUrl = 'stun:' + url.hostname + ':3478';
- var turnUrl1 = 'turn:' + url.hostname + ':3478';
- var turnUrl2 = turnUrl1 + '?transport=tcp';
- this.openvidu.iceServers = [
- { urls: [stunUrl] },
- { urls: [turnUrl1, turnUrl2], username: turnUsername, credential: turnCredential }
- ];
- console.log('TURN temp credentials [' + turnUsername + ':' + turnCredential + ']');
- }
- if (!!role) {
- this.openvidu.role = role;
- }
- this.openvidu.wsUri = 'wss://' + url.host + '/openvidu';
- };
- return Session;
-}());
-exports.Session = Session;
-
-},{"../OpenViduInternal/Enums/OpenViduError":26,"../OpenViduInternal/Enums/VideoInsertMode":27,"../OpenViduInternal/Events/ConnectionEvent":28,"../OpenViduInternal/Events/RecordingEvent":31,"../OpenViduInternal/Events/SessionDisconnectedEvent":32,"../OpenViduInternal/Events/SignalEvent":33,"../OpenViduInternal/Events/StreamEvent":34,"../OpenViduInternal/Events/StreamPropertyChangedEvent":36,"./Connection":17,"./Subscriber":24,"platform":8,"wolfy87-eventemitter":15}],22:[function(require,module,exports){
-"use strict";
-Object.defineProperty(exports, "__esModule", { value: true });
-var WebRtcPeer_1 = require("../OpenViduInternal/WebRtcPeer/WebRtcPeer");
-var WebRtcStats_1 = require("../OpenViduInternal/WebRtcStats/WebRtcStats");
-var PublisherSpeakingEvent_1 = require("../OpenViduInternal/Events/PublisherSpeakingEvent");
-var EventEmitter = require("wolfy87-eventemitter");
-var hark = require("hark");
-var OpenViduError_1 = require("../OpenViduInternal/Enums/OpenViduError");
-var Stream = (function () {
- function Stream(session, options) {
- var _this = this;
- this.ee = new EventEmitter();
- this.isSubscribeToRemote = false;
- this.isLocalStreamReadyToPublish = false;
- this.isLocalStreamPublished = false;
- this.publishedOnce = false;
- this.session = session;
- if (options.hasOwnProperty('id')) {
- this.inboundStreamOpts = options;
- this.streamId = this.inboundStreamOpts.id;
- this.hasAudio = this.inboundStreamOpts.hasAudio;
- this.hasVideo = this.inboundStreamOpts.hasVideo;
- if (this.hasAudio) {
- this.audioActive = this.inboundStreamOpts.audioActive;
- }
- if (this.hasVideo) {
- this.videoActive = this.inboundStreamOpts.videoActive;
- this.typeOfVideo = (!this.inboundStreamOpts.typeOfVideo) ? undefined : this.inboundStreamOpts.typeOfVideo;
- this.frameRate = (this.inboundStreamOpts.frameRate === -1) ? undefined : this.inboundStreamOpts.frameRate;
- this.videoDimensions = this.inboundStreamOpts.videoDimensions;
- }
- }
- else {
- this.outboundStreamOpts = options;
- this.hasAudio = this.isSendAudio();
- this.hasVideo = this.isSendVideo();
- if (this.hasAudio) {
- this.audioActive = !!this.outboundStreamOpts.publisherProperties.publishAudio;
- }
- if (this.hasVideo) {
- this.videoActive = !!this.outboundStreamOpts.publisherProperties.publishVideo;
- this.frameRate = this.outboundStreamOpts.publisherProperties.frameRate;
- if (this.outboundStreamOpts.publisherProperties.videoSource instanceof MediaStreamTrack) {
- this.typeOfVideo = 'CUSTOM';
- }
- else {
- this.typeOfVideo = this.isSendScreen() ? 'SCREEN' : 'CAMERA';
- }
- }
- }
- this.ee.on('mediastream-updated', function () {
- _this.streamManager.updateMediaStream(_this.mediaStream);
- console.debug('Video srcObject [' + _this.mediaStream + '] updated in stream [' + _this.streamId + ']');
- });
- }
- Stream.prototype.getMediaStream = function () {
- return this.mediaStream;
- };
- Stream.prototype.setMediaStream = function (mediaStream) {
- this.mediaStream = mediaStream;
- };
- Stream.prototype.updateMediaStreamInVideos = function () {
- this.ee.emitEvent('mediastream-updated');
- };
- Stream.prototype.getWebRtcPeer = function () {
- return this.webRtcPeer;
- };
- Stream.prototype.getRTCPeerConnection = function () {
- return this.webRtcPeer.pc;
- };
- Stream.prototype.subscribeToMyRemote = function (value) {
- this.isSubscribeToRemote = value;
- };
- Stream.prototype.setOutboundStreamOptions = function (outboundStreamOpts) {
- this.outboundStreamOpts = outboundStreamOpts;
- };
- Stream.prototype.subscribe = function () {
- var _this = this;
- return new Promise(function (resolve, reject) {
- _this.initWebRtcPeerReceive()
- .then(function () {
- resolve();
- })
- .catch(function (error) {
- reject(error);
- });
- });
- };
- Stream.prototype.publish = function () {
- var _this = this;
- return new Promise(function (resolve, reject) {
- if (_this.isLocalStreamReadyToPublish) {
- _this.initWebRtcPeerSend()
- .then(function () {
- resolve();
- })
- .catch(function (error) {
- reject(error);
- });
- }
- else {
- _this.ee.once('stream-ready-to-publish', function () {
- _this.publish()
- .then(function () {
- resolve();
- })
- .catch(function (error) {
- reject(error);
- });
- });
- }
- });
- };
- Stream.prototype.disposeWebRtcPeer = function () {
- if (this.webRtcPeer) {
- this.webRtcPeer.dispose();
- }
- if (this.speechEvent) {
- this.speechEvent.stop();
- }
- this.stopWebRtcStats();
- console.info((!!this.outboundStreamOpts ? 'Outbound ' : 'Inbound ') + "WebRTCPeer from 'Stream' with id [" + this.streamId + '] is now closed');
- };
- Stream.prototype.disposeMediaStream = function () {
- if (this.mediaStream) {
- this.mediaStream.getAudioTracks().forEach(function (track) {
- track.stop();
- });
- this.mediaStream.getVideoTracks().forEach(function (track) {
- track.stop();
- });
- delete this.mediaStream;
- }
- console.info((!!this.outboundStreamOpts ? 'Local ' : 'Remote ') + "MediaStream from 'Stream' with id [" + this.streamId + '] is now disposed');
- };
- Stream.prototype.displayMyRemote = function () {
- return this.isSubscribeToRemote;
- };
- Stream.prototype.isSendAudio = function () {
- return (!!this.outboundStreamOpts &&
- this.outboundStreamOpts.publisherProperties.audioSource !== null &&
- this.outboundStreamOpts.publisherProperties.audioSource !== false);
- };
- Stream.prototype.isSendVideo = function () {
- return (!!this.outboundStreamOpts &&
- this.outboundStreamOpts.publisherProperties.videoSource !== null &&
- this.outboundStreamOpts.publisherProperties.videoSource !== false);
- };
- Stream.prototype.isSendScreen = function () {
- return (!!this.outboundStreamOpts &&
- this.outboundStreamOpts.publisherProperties.videoSource === 'screen');
- };
- Stream.prototype.setSpeechEventIfNotExists = function () {
- if (!this.speechEvent) {
- var harkOptions = this.session.openvidu.advancedConfiguration.publisherSpeakingEventsOptions || {};
- harkOptions.interval = (typeof harkOptions.interval === 'number') ? harkOptions.interval : 50;
- harkOptions.threshold = (typeof harkOptions.threshold === 'number') ? harkOptions.threshold : -50;
- this.speechEvent = hark(this.mediaStream, harkOptions);
- }
- };
- Stream.prototype.enableSpeakingEvents = function () {
- var _this = this;
- this.setSpeechEventIfNotExists();
- this.speechEvent.on('speaking', function () {
- _this.session.emitEvent('publisherStartSpeaking', [new PublisherSpeakingEvent_1.PublisherSpeakingEvent(_this.session, 'publisherStartSpeaking', _this.connection, _this.streamId)]);
- });
- this.speechEvent.on('stopped_speaking', function () {
- _this.session.emitEvent('publisherStopSpeaking', [new PublisherSpeakingEvent_1.PublisherSpeakingEvent(_this.session, 'publisherStopSpeaking', _this.connection, _this.streamId)]);
- });
- };
- Stream.prototype.enableOnceSpeakingEvents = function () {
- var _this = this;
- this.setSpeechEventIfNotExists();
- this.speechEvent.on('speaking', function () {
- _this.session.emitEvent('publisherStartSpeaking', [new PublisherSpeakingEvent_1.PublisherSpeakingEvent(_this.session, 'publisherStartSpeaking', _this.connection, _this.streamId)]);
- _this.disableSpeakingEvents();
- });
- this.speechEvent.on('stopped_speaking', function () {
- _this.session.emitEvent('publisherStopSpeaking', [new PublisherSpeakingEvent_1.PublisherSpeakingEvent(_this.session, 'publisherStopSpeaking', _this.connection, _this.streamId)]);
- _this.disableSpeakingEvents();
- });
- };
- Stream.prototype.disableSpeakingEvents = function () {
- this.speechEvent.stop();
- this.speechEvent = undefined;
- };
- Stream.prototype.isLocal = function () {
- return (!this.inboundStreamOpts && !!this.outboundStreamOpts);
- };
- Stream.prototype.getSelectedIceCandidate = function () {
- var _this = this;
- return new Promise(function (resolve, reject) {
- _this.webRtcStats.getSelectedIceCandidateInfo()
- .then(function (report) { return resolve(report); })
- .catch(function (error) { return reject(error); });
- });
- };
- Stream.prototype.getRemoteIceCandidateList = function () {
- return this.webRtcPeer.remoteCandidatesQueue;
- };
- Stream.prototype.getLocalIceCandidateList = function () {
- return this.webRtcPeer.localCandidatesQueue;
- };
- Stream.prototype.initWebRtcPeerSend = function () {
- var _this = this;
- return new Promise(function (resolve, reject) {
- var userMediaConstraints = {
- audio: _this.isSendAudio(),
- video: _this.isSendVideo()
- };
- var options = {
- mediaStream: _this.mediaStream,
- mediaConstraints: userMediaConstraints,
- onicecandidate: _this.connection.sendIceCandidate.bind(_this.connection),
- iceServers: _this.getIceServersConf(),
- simulcast: false
- };
- var successCallback = function (sdpOfferParam) {
- console.debug('Sending SDP offer to publish as '
- + _this.streamId, sdpOfferParam);
- var typeOfVideo = '';
- if (_this.isSendVideo()) {
- typeOfVideo = _this.outboundStreamOpts.publisherProperties.videoSource instanceof MediaStreamTrack ? 'CUSTOM' : (_this.isSendScreen() ? 'SCREEN' : 'CAMERA');
- }
- _this.session.openvidu.sendRequest('publishVideo', {
- sdpOffer: sdpOfferParam,
- doLoopback: _this.displayMyRemote() || false,
- hasAudio: _this.isSendAudio(),
- hasVideo: _this.isSendVideo(),
- audioActive: _this.audioActive,
- videoActive: _this.videoActive,
- typeOfVideo: typeOfVideo,
- frameRate: !!_this.frameRate ? _this.frameRate : -1,
- videoDimensions: JSON.stringify(_this.videoDimensions)
- }, function (error, response) {
- if (error) {
- if (error.code === 401) {
- reject(new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.OPENVIDU_PERMISSION_DENIED, "You don't have permissions to publish"));
- }
- else {
- reject('Error on publishVideo: ' + JSON.stringify(error));
- }
- }
- else {
- _this.webRtcPeer.processAnswer(response.sdpAnswer)
- .then(function () {
- _this.streamId = response.id;
- _this.isLocalStreamPublished = true;
- _this.publishedOnce = true;
- if (_this.displayMyRemote()) {
- _this.remotePeerSuccessfullyEstablished();
- }
- _this.ee.emitEvent('stream-created-by-publisher');
- _this.initWebRtcStats();
- resolve();
- })
- .catch(function (error) {
- reject(error);
- });
- console.info("'Publisher' successfully published to session");
- }
- });
- };
- if (_this.displayMyRemote()) {
- _this.webRtcPeer = new WebRtcPeer_1.WebRtcPeerSendrecv(options);
- }
- else {
- _this.webRtcPeer = new WebRtcPeer_1.WebRtcPeerSendonly(options);
- }
- _this.webRtcPeer.generateOffer().then(function (offer) {
- successCallback(offer);
- }).catch(function (error) {
- reject(new Error('(publish) SDP offer error: ' + JSON.stringify(error)));
- });
- });
- };
- Stream.prototype.initWebRtcPeerReceive = function () {
- var _this = this;
- return new Promise(function (resolve, reject) {
- var offerConstraints = {
- audio: _this.inboundStreamOpts.hasAudio,
- video: _this.inboundStreamOpts.hasVideo
- };
- console.debug("'Session.subscribe(Stream)' called. Constraints of generate SDP offer", offerConstraints);
- var options = {
- onicecandidate: _this.connection.sendIceCandidate.bind(_this.connection),
- mediaConstraints: offerConstraints,
- iceServers: _this.getIceServersConf(),
- simulcast: false
- };
- var successCallback = function (sdpOfferParam) {
- console.debug('Sending SDP offer to subscribe to '
- + _this.streamId, sdpOfferParam);
- _this.session.openvidu.sendRequest('receiveVideoFrom', {
- sender: _this.streamId,
- sdpOffer: sdpOfferParam
- }, function (error, response) {
- if (error) {
- reject(new Error('Error on recvVideoFrom: ' + JSON.stringify(error)));
- }
- else {
- _this.webRtcPeer.processAnswer(response.sdpAnswer).then(function () {
- _this.remotePeerSuccessfullyEstablished();
- _this.initWebRtcStats();
- resolve();
- }).catch(function (error) {
- reject(error);
- });
- }
- });
- };
- _this.webRtcPeer = new WebRtcPeer_1.WebRtcPeerRecvonly(options);
- _this.webRtcPeer.generateOffer()
- .then(function (offer) {
- successCallback(offer);
- })
- .catch(function (error) {
- reject(new Error('(subscribe) SDP offer error: ' + JSON.stringify(error)));
- });
- });
- };
- Stream.prototype.remotePeerSuccessfullyEstablished = function () {
- this.mediaStream = this.webRtcPeer.pc.getRemoteStreams()[0];
- console.debug('Peer remote stream', this.mediaStream);
- if (!!this.mediaStream) {
- this.ee.emitEvent('mediastream-updated');
- if (!this.displayMyRemote() && !!this.mediaStream.getAudioTracks()[0] && this.session.speakingEventsEnabled) {
- this.enableSpeakingEvents();
- }
- }
- };
- Stream.prototype.initWebRtcStats = function () {
- this.webRtcStats = new WebRtcStats_1.WebRtcStats(this);
- this.webRtcStats.initWebRtcStats();
- };
- Stream.prototype.stopWebRtcStats = function () {
- if (!!this.webRtcStats && this.webRtcStats.isEnabled()) {
- this.webRtcStats.stopWebRtcStats();
- }
- };
- Stream.prototype.getIceServersConf = function () {
- var returnValue;
- if (!!this.session.openvidu.advancedConfiguration.iceServers) {
- returnValue = this.session.openvidu.advancedConfiguration.iceServers === 'freeice' ?
- undefined :
- this.session.openvidu.advancedConfiguration.iceServers;
- }
- else if (this.session.openvidu.iceServers) {
- returnValue = this.session.openvidu.iceServers;
- }
- else {
- returnValue = undefined;
- }
- return returnValue;
- };
- return Stream;
-}());
-exports.Stream = Stream;
-
-},{"../OpenViduInternal/Enums/OpenViduError":26,"../OpenViduInternal/Events/PublisherSpeakingEvent":30,"../OpenViduInternal/WebRtcPeer/WebRtcPeer":49,"../OpenViduInternal/WebRtcStats/WebRtcStats":50,"hark":5,"wolfy87-eventemitter":15}],23:[function(require,module,exports){
-"use strict";
-Object.defineProperty(exports, "__esModule", { value: true });
-var StreamManagerEvent_1 = require("../OpenViduInternal/Events/StreamManagerEvent");
-var VideoElementEvent_1 = require("../OpenViduInternal/Events/VideoElementEvent");
-var VideoInsertMode_1 = require("../OpenViduInternal/Enums/VideoInsertMode");
-var EventEmitter = require("wolfy87-eventemitter");
-var StreamManager = (function () {
- function StreamManager(stream, targetElement) {
- var _this = this;
- this.videos = [];
- this.lazyLaunchVideoElementCreatedEvent = false;
- this.ee = new EventEmitter();
- this.stream = stream;
- this.stream.streamManager = this;
- this.remote = !this.stream.isLocal();
- if (!!targetElement) {
- var targEl = void 0;
- if (typeof targetElement === 'string') {
- targEl = document.getElementById(targetElement);
- }
- else if (targetElement instanceof HTMLElement) {
- targEl = targetElement;
- }
- if (!!targEl) {
- this.firstVideoElement = {
- targetElement: targEl,
- video: document.createElement('video'),
- id: ''
- };
- this.targetElement = targEl;
- this.element = targEl;
- }
- }
- this.canPlayListener = function () {
- if (_this.stream.isLocal()) {
- if (!_this.stream.displayMyRemote()) {
- console.info("Your local 'Stream' with id [" + _this.stream.streamId + '] video is now playing');
- _this.ee.emitEvent('videoPlaying', [new VideoElementEvent_1.VideoElementEvent(_this.videos[0].video, _this, 'videoPlaying')]);
- }
- else {
- console.info("Your own remote 'Stream' with id [" + _this.stream.streamId + '] video is now playing');
- _this.ee.emitEvent('remoteVideoPlaying', [new VideoElementEvent_1.VideoElementEvent(_this.videos[0].video, _this, 'remoteVideoPlaying')]);
- }
- }
- else {
- console.info("Remote 'Stream' with id [" + _this.stream.streamId + '] video is now playing');
- _this.ee.emitEvent('videoPlaying', [new VideoElementEvent_1.VideoElementEvent(_this.videos[0].video, _this, 'videoPlaying')]);
- }
- _this.ee.emitEvent('streamPlaying', [new StreamManagerEvent_1.StreamManagerEvent(_this)]);
- };
- }
- StreamManager.prototype.on = function (type, handler) {
- var _this = this;
- this.ee.on(type, function (event) {
- if (event) {
- console.info("Event '" + type + "' triggered by '" + (_this.remote ? 'Subscriber' : 'Publisher') + "'", event);
- }
- else {
- console.info("Event '" + type + "' triggered by '" + (_this.remote ? 'Subscriber' : 'Publisher') + "'");
- }
- handler(event);
- });
- if (type === 'videoElementCreated') {
- if (!!this.stream && this.lazyLaunchVideoElementCreatedEvent) {
- this.ee.emitEvent('videoElementCreated', [new VideoElementEvent_1.VideoElementEvent(this.videos[0].video, this, 'videoElementCreated')]);
- this.lazyLaunchVideoElementCreatedEvent = false;
- }
- }
- if (type === 'streamPlaying' || type === 'videoPlaying') {
- if (this.videos[0] && this.videos[0].video &&
- this.videos[0].video.currentTime > 0 &&
- this.videos[0].video.paused === false &&
- this.videos[0].video.ended === false &&
- this.videos[0].video.readyState === 4) {
- this.ee.emitEvent('streamPlaying', [new StreamManagerEvent_1.StreamManagerEvent(this)]);
- this.ee.emitEvent('videoPlaying', [new VideoElementEvent_1.VideoElementEvent(this.videos[0].video, this, 'videoPlaying')]);
- }
- }
- return this;
- };
- StreamManager.prototype.once = function (type, handler) {
- this.ee.once(type, function (event) {
- if (event) {
- console.info("Event '" + type + "' triggered once", event);
- }
- else {
- console.info("Event '" + type + "' triggered once");
- }
- handler(event);
- });
- if (type === 'videoElementCreated') {
- if (!!this.stream && this.lazyLaunchVideoElementCreatedEvent) {
- this.ee.emitEvent('videoElementCreated', [new VideoElementEvent_1.VideoElementEvent(this.videos[0].video, this, 'videoElementCreated')]);
- }
- }
- if (type === 'streamPlaying' || type === 'videoPlaying') {
- if (this.videos[0] && this.videos[0].video &&
- this.videos[0].video.currentTime > 0 &&
- this.videos[0].video.paused === false &&
- this.videos[0].video.ended === false &&
- this.videos[0].video.readyState === 4) {
- this.ee.emitEvent('streamPlaying', [new StreamManagerEvent_1.StreamManagerEvent(this)]);
- this.ee.emitEvent('videoPlaying', [new VideoElementEvent_1.VideoElementEvent(this.videos[0].video, this, 'videoPlaying')]);
- }
- }
- return this;
- };
- StreamManager.prototype.off = function (type, handler) {
- if (!handler) {
- this.ee.removeAllListeners(type);
- }
- else {
- this.ee.off(type, handler);
- }
- return this;
- };
- StreamManager.prototype.addVideoElement = function (video) {
- this.initializeVideoProperties(video);
- for (var _i = 0, _a = this.videos; _i < _a.length; _i++) {
- var v = _a[_i];
- if (v.video === video) {
- return 0;
- }
- }
- var returnNumber = 1;
- for (var _b = 0, _c = this.stream.session.streamManagers; _b < _c.length; _b++) {
- var streamManager = _c[_b];
- if (streamManager.disassociateVideo(video)) {
- returnNumber = -1;
- break;
- }
- }
- this.stream.session.streamManagers.forEach(function (streamManager) {
- streamManager.disassociateVideo(video);
- });
- this.pushNewStreamManagerVideo({
- video: video,
- id: video.id
- });
- console.info('New video element associated to ', this);
- return returnNumber;
- };
- StreamManager.prototype.createVideoElement = function (targetElement, insertMode) {
- var targEl;
- if (typeof targetElement === 'string') {
- targEl = document.getElementById(targEl);
- if (!targEl) {
- throw new Error("The provided 'targetElement' couldn't be resolved to any HTML element: " + targetElement);
- }
- }
- else if (targetElement instanceof HTMLElement) {
- targEl = targetElement;
- }
- else {
- throw new Error("The provided 'targetElement' couldn't be resolved to any HTML element: " + targetElement);
- }
- var video = document.createElement('video');
- this.initializeVideoProperties(video);
- var insMode = !!insertMode ? insertMode : VideoInsertMode_1.VideoInsertMode.APPEND;
- switch (insMode) {
- case VideoInsertMode_1.VideoInsertMode.AFTER:
- targEl.parentNode.insertBefore(video, targEl.nextSibling);
- break;
- case VideoInsertMode_1.VideoInsertMode.APPEND:
- targEl.appendChild(video);
- break;
- case VideoInsertMode_1.VideoInsertMode.BEFORE:
- targEl.parentNode.insertBefore(video, targEl);
- break;
- case VideoInsertMode_1.VideoInsertMode.PREPEND:
- targEl.insertBefore(video, targEl.childNodes[0]);
- break;
- case VideoInsertMode_1.VideoInsertMode.REPLACE:
- targEl.parentNode.replaceChild(video, targEl);
- break;
- default:
- insMode = VideoInsertMode_1.VideoInsertMode.APPEND;
- targEl.appendChild(video);
- break;
- }
- var v = {
- targetElement: targEl,
- video: video,
- insertMode: insMode,
- id: video.id
- };
- this.pushNewStreamManagerVideo(v);
- this.ee.emitEvent('videoElementCreated', [new VideoElementEvent_1.VideoElementEvent(v.video, this, 'videoElementCreated')]);
- this.lazyLaunchVideoElementCreatedEvent = !!this.firstVideoElement;
- return video;
- };
- StreamManager.prototype.initializeVideoProperties = function (video) {
- if (!(this.stream.isLocal() && this.stream.displayMyRemote())) {
- video.srcObject = this.stream.getMediaStream();
- }
- video.autoplay = true;
- video.controls = false;
- if (!video.id) {
- video.id = (this.remote ? 'remote-' : 'local-') + 'video-' + this.stream.streamId;
- if (!this.id && !!this.targetElement) {
- this.id = video.id;
- }
- }
- if (!this.remote && !this.stream.displayMyRemote()) {
- video.muted = true;
- if (this.stream.outboundStreamOpts.publisherProperties.mirror) {
- this.mirrorVideo(video);
- }
- }
- };
- StreamManager.prototype.removeAllVideos = function () {
- var _this = this;
- for (var i = this.stream.session.streamManagers.length - 1; i >= 0; --i) {
- if (this.stream.session.streamManagers[i] === this) {
- this.stream.session.streamManagers.splice(i, 1);
- }
- }
- this.videos.slice().reverse().forEach(function (streamManagerVideo, index, videos) {
- streamManagerVideo.video.removeEventListener('canplay', _this.canPlayListener);
- if (!!streamManagerVideo.targetElement) {
- streamManagerVideo.video.parentNode.removeChild(streamManagerVideo.video);
- _this.ee.emitEvent('videoElementDestroyed', [new VideoElementEvent_1.VideoElementEvent(streamManagerVideo.video, _this, 'videoElementDestroyed')]);
- _this.videos.splice(videos.length - 1 - index, 1);
- }
- else {
- streamManagerVideo.video.srcObject = null;
- }
- });
- };
- StreamManager.prototype.disassociateVideo = function (video) {
- var disassociated = false;
- for (var i = 0; i < this.videos.length; i++) {
- if (this.videos[i].video === video) {
- this.videos.splice(i, 1);
- disassociated = true;
- console.info('Video element disassociated from ', this);
- break;
- }
- }
- return disassociated;
- };
- StreamManager.prototype.addPlayEventToFirstVideo = function () {
- if ((!!this.videos[0]) && (!!this.videos[0].video) && (this.videos[0].video.oncanplay === null)) {
- this.videos[0].video.addEventListener('canplay', this.canPlayListener);
- }
- };
- StreamManager.prototype.updateMediaStream = function (mediaStream) {
- this.videos.forEach(function (streamManagerVideo) {
- streamManagerVideo.video.srcObject = mediaStream;
- });
- };
- StreamManager.prototype.emitEvent = function (type, eventArray) {
- this.ee.emitEvent(type, eventArray);
- };
- StreamManager.prototype.pushNewStreamManagerVideo = function (streamManagerVideo) {
- this.videos.push(streamManagerVideo);
- this.addPlayEventToFirstVideo();
- if (this.stream.session.streamManagers.indexOf(this) === -1) {
- this.stream.session.streamManagers.push(this);
- }
- };
- StreamManager.prototype.mirrorVideo = function (video) {
- video.style.transform = 'rotateY(180deg)';
- video.style.webkitTransform = 'rotateY(180deg)';
- };
- return StreamManager;
-}());
-exports.StreamManager = StreamManager;
-
-},{"../OpenViduInternal/Enums/VideoInsertMode":27,"../OpenViduInternal/Events/StreamManagerEvent":35,"../OpenViduInternal/Events/VideoElementEvent":37,"wolfy87-eventemitter":15}],24:[function(require,module,exports){
-"use strict";
-var __extends = (this && this.__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 __());
- };
-})();
-Object.defineProperty(exports, "__esModule", { value: true });
-var StreamManager_1 = require("./StreamManager");
-var Subscriber = (function (_super) {
- __extends(Subscriber, _super);
- function Subscriber(stream, targEl, properties) {
- var _this = _super.call(this, stream, targEl) || this;
- _this.element = _this.targetElement;
- _this.stream = stream;
- _this.properties = properties;
- return _this;
- }
- Subscriber.prototype.subscribeToAudio = function (value) {
- this.stream.getMediaStream().getAudioTracks().forEach(function (track) {
- track.enabled = value;
- });
- console.info("'Subscriber' has " + (value ? 'subscribed to' : 'unsubscribed from') + ' its audio stream');
- return this;
- };
- Subscriber.prototype.subscribeToVideo = function (value) {
- this.stream.getMediaStream().getVideoTracks().forEach(function (track) {
- track.enabled = value;
- });
- console.info("'Subscriber' has " + (value ? 'subscribed to' : 'unsubscribed from') + ' its video stream');
- return this;
- };
- return Subscriber;
-}(StreamManager_1.StreamManager));
-exports.Subscriber = Subscriber;
-
-},{"./StreamManager":23}],25:[function(require,module,exports){
-"use strict";
-Object.defineProperty(exports, "__esModule", { value: true });
-var LocalRecorderState;
-(function (LocalRecorderState) {
- LocalRecorderState["READY"] = "READY";
- LocalRecorderState["RECORDING"] = "RECORDING";
- LocalRecorderState["PAUSED"] = "PAUSED";
- LocalRecorderState["FINISHED"] = "FINISHED";
-})(LocalRecorderState = exports.LocalRecorderState || (exports.LocalRecorderState = {}));
-
-},{}],26:[function(require,module,exports){
-"use strict";
-Object.defineProperty(exports, "__esModule", { value: true });
-var OpenViduErrorName;
-(function (OpenViduErrorName) {
- OpenViduErrorName["BROWSER_NOT_SUPPORTED"] = "BROWSER_NOT_SUPPORTED";
- OpenViduErrorName["DEVICE_ACCESS_DENIED"] = "DEVICE_ACCESS_DENIED";
- OpenViduErrorName["SCREEN_CAPTURE_DENIED"] = "SCREEN_CAPTURE_DENIED";
- OpenViduErrorName["SCREEN_SHARING_NOT_SUPPORTED"] = "SCREEN_SHARING_NOT_SUPPORTED";
- OpenViduErrorName["SCREEN_EXTENSION_NOT_INSTALLED"] = "SCREEN_EXTENSION_NOT_INSTALLED";
- OpenViduErrorName["SCREEN_EXTENSION_DISABLED"] = "SCREEN_EXTENSION_DISABLED";
- OpenViduErrorName["INPUT_VIDEO_DEVICE_NOT_FOUND"] = "INPUT_VIDEO_DEVICE_NOT_FOUND";
- OpenViduErrorName["INPUT_AUDIO_DEVICE_NOT_FOUND"] = "INPUT_AUDIO_DEVICE_NOT_FOUND";
- OpenViduErrorName["NO_INPUT_SOURCE_SET"] = "NO_INPUT_SOURCE_SET";
- OpenViduErrorName["PUBLISHER_PROPERTIES_ERROR"] = "PUBLISHER_PROPERTIES_ERROR";
- OpenViduErrorName["OPENVIDU_PERMISSION_DENIED"] = "OPENVIDU_PERMISSION_DENIED";
- OpenViduErrorName["OPENVIDU_NOT_CONNECTED"] = "OPENVIDU_NOT_CONNECTED";
- OpenViduErrorName["GENERIC_ERROR"] = "GENERIC_ERROR";
-})(OpenViduErrorName = exports.OpenViduErrorName || (exports.OpenViduErrorName = {}));
-var OpenViduError = (function () {
- function OpenViduError(name, message) {
- this.name = name;
- this.message = message;
- }
- return OpenViduError;
-}());
-exports.OpenViduError = OpenViduError;
-
-},{}],27:[function(require,module,exports){
-"use strict";
-Object.defineProperty(exports, "__esModule", { value: true });
-var VideoInsertMode;
-(function (VideoInsertMode) {
- VideoInsertMode["AFTER"] = "AFTER";
- VideoInsertMode["APPEND"] = "APPEND";
- VideoInsertMode["BEFORE"] = "BEFORE";
- VideoInsertMode["PREPEND"] = "PREPEND";
- VideoInsertMode["REPLACE"] = "REPLACE";
-})(VideoInsertMode = exports.VideoInsertMode || (exports.VideoInsertMode = {}));
-
-},{}],28:[function(require,module,exports){
-"use strict";
-var __extends = (this && this.__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 __());
- };
-})();
-Object.defineProperty(exports, "__esModule", { value: true });
-var Event_1 = require("./Event");
-var ConnectionEvent = (function (_super) {
- __extends(ConnectionEvent, _super);
- function ConnectionEvent(cancelable, target, type, connection, reason) {
- var _this = _super.call(this, cancelable, target, type) || this;
- _this.connection = connection;
- _this.reason = reason;
- return _this;
- }
- ConnectionEvent.prototype.callDefaultBehavior = function () { };
- return ConnectionEvent;
-}(Event_1.Event));
-exports.ConnectionEvent = ConnectionEvent;
-
-},{"./Event":29}],29:[function(require,module,exports){
-"use strict";
-Object.defineProperty(exports, "__esModule", { value: true });
-var Event = (function () {
- function Event(cancelable, target, type) {
- this.hasBeenPrevented = false;
- this.cancelable = cancelable;
- this.target = target;
- this.type = type;
- }
- Event.prototype.isDefaultPrevented = function () {
- return this.hasBeenPrevented;
- };
- Event.prototype.preventDefault = function () {
- this.callDefaultBehavior = function () { };
- this.hasBeenPrevented = true;
- };
- return Event;
-}());
-exports.Event = Event;
-
-},{}],30:[function(require,module,exports){
-"use strict";
-var __extends = (this && this.__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 __());
- };
-})();
-Object.defineProperty(exports, "__esModule", { value: true });
-var Event_1 = require("./Event");
-var PublisherSpeakingEvent = (function (_super) {
- __extends(PublisherSpeakingEvent, _super);
- function PublisherSpeakingEvent(target, type, connection, streamId) {
- var _this = _super.call(this, false, target, type) || this;
- _this.type = type;
- _this.connection = connection;
- _this.streamId = streamId;
- return _this;
- }
- PublisherSpeakingEvent.prototype.callDefaultBehavior = function () { };
- return PublisherSpeakingEvent;
-}(Event_1.Event));
-exports.PublisherSpeakingEvent = PublisherSpeakingEvent;
-
-},{"./Event":29}],31:[function(require,module,exports){
-"use strict";
-var __extends = (this && this.__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 __());
- };
-})();
-Object.defineProperty(exports, "__esModule", { value: true });
-var Event_1 = require("./Event");
-var RecordingEvent = (function (_super) {
- __extends(RecordingEvent, _super);
- function RecordingEvent(target, type, id, name) {
- var _this = _super.call(this, false, target, type) || this;
- _this.id = id;
- if (name !== id) {
- _this.name = name;
- }
- return _this;
- }
- RecordingEvent.prototype.callDefaultBehavior = function () { };
- return RecordingEvent;
-}(Event_1.Event));
-exports.RecordingEvent = RecordingEvent;
-
-},{"./Event":29}],32:[function(require,module,exports){
-"use strict";
-var __extends = (this && this.__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 __());
- };
-})();
-Object.defineProperty(exports, "__esModule", { value: true });
-var Event_1 = require("./Event");
-var SessionDisconnectedEvent = (function (_super) {
- __extends(SessionDisconnectedEvent, _super);
- function SessionDisconnectedEvent(target, reason) {
- var _this = _super.call(this, true, target, 'sessionDisconnected') || this;
- _this.reason = reason;
- return _this;
- }
- SessionDisconnectedEvent.prototype.callDefaultBehavior = function () {
- console.info("Calling default behavior upon '" + this.type + "' event dispatched by 'Session'");
- var session = this.target;
- for (var connectionId in session.remoteConnections) {
- if (!!session.remoteConnections[connectionId].stream) {
- session.remoteConnections[connectionId].stream.disposeWebRtcPeer();
- session.remoteConnections[connectionId].stream.disposeMediaStream();
- if (session.remoteConnections[connectionId].stream.streamManager) {
- session.remoteConnections[connectionId].stream.streamManager.removeAllVideos();
- }
- delete session.remoteStreamsCreated[session.remoteConnections[connectionId].stream.streamId];
- session.remoteConnections[connectionId].dispose();
- }
- delete session.remoteConnections[connectionId];
- }
- };
- return SessionDisconnectedEvent;
-}(Event_1.Event));
-exports.SessionDisconnectedEvent = SessionDisconnectedEvent;
-
-},{"./Event":29}],33:[function(require,module,exports){
-"use strict";
-var __extends = (this && this.__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 __());
- };
-})();
-Object.defineProperty(exports, "__esModule", { value: true });
-var Event_1 = require("./Event");
-var SignalEvent = (function (_super) {
- __extends(SignalEvent, _super);
- function SignalEvent(target, type, data, from) {
- var _this = _super.call(this, false, target, type) || this;
- _this.type = type;
- _this.data = data;
- _this.from = from;
- return _this;
- }
- SignalEvent.prototype.callDefaultBehavior = function () { };
- return SignalEvent;
-}(Event_1.Event));
-exports.SignalEvent = SignalEvent;
-
-},{"./Event":29}],34:[function(require,module,exports){
-"use strict";
-var __extends = (this && this.__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 __());
- };
-})();
-Object.defineProperty(exports, "__esModule", { value: true });
-var Event_1 = require("./Event");
-var Publisher_1 = require("../../OpenVidu/Publisher");
-var Session_1 = require("../../OpenVidu/Session");
-var StreamEvent = (function (_super) {
- __extends(StreamEvent, _super);
- function StreamEvent(cancelable, target, type, stream, reason) {
- var _this = _super.call(this, cancelable, target, type) || this;
- _this.stream = stream;
- _this.reason = reason;
- return _this;
- }
- StreamEvent.prototype.callDefaultBehavior = function () {
- if (this.type === 'streamDestroyed') {
- if (this.target instanceof Session_1.Session) {
- console.info("Calling default behavior upon '" + this.type + "' event dispatched by 'Session'");
- this.stream.disposeWebRtcPeer();
- }
- else if (this.target instanceof Publisher_1.Publisher) {
- console.info("Calling default behavior upon '" + this.type + "' event dispatched by 'Publisher'");
- clearInterval(this.target.screenShareResizeInterval);
- this.stream.isLocalStreamReadyToPublish = false;
- var openviduPublishers = this.target.openvidu.publishers;
- for (var i = 0; i < openviduPublishers.length; i++) {
- if (openviduPublishers[i] === this.target) {
- openviduPublishers.splice(i, 1);
- break;
- }
- }
- }
- this.stream.disposeMediaStream();
- if (this.stream.streamManager)
- this.stream.streamManager.removeAllVideos();
- delete this.stream.session.remoteStreamsCreated[this.stream.streamId];
- var remoteConnection = this.stream.session.remoteConnections[this.stream.connection.connectionId];
- if (!!remoteConnection && !!remoteConnection.options) {
- var streamOptionsServer = remoteConnection.options.streams;
- for (var i = streamOptionsServer.length - 1; i >= 0; --i) {
- if (streamOptionsServer[i].id === this.stream.streamId) {
- streamOptionsServer.splice(i, 1);
- }
- }
- }
- }
- };
- return StreamEvent;
-}(Event_1.Event));
-exports.StreamEvent = StreamEvent;
-
-},{"../../OpenVidu/Publisher":20,"../../OpenVidu/Session":21,"./Event":29}],35:[function(require,module,exports){
-"use strict";
-var __extends = (this && this.__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 __());
- };
-})();
-Object.defineProperty(exports, "__esModule", { value: true });
-var Event_1 = require("./Event");
-var StreamManagerEvent = (function (_super) {
- __extends(StreamManagerEvent, _super);
- function StreamManagerEvent(target) {
- return _super.call(this, false, target, 'streamPlaying') || this;
- }
- StreamManagerEvent.prototype.callDefaultBehavior = function () { };
- return StreamManagerEvent;
-}(Event_1.Event));
-exports.StreamManagerEvent = StreamManagerEvent;
-
-},{"./Event":29}],36:[function(require,module,exports){
-"use strict";
-var __extends = (this && this.__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 __());
- };
-})();
-Object.defineProperty(exports, "__esModule", { value: true });
-var Event_1 = require("./Event");
-var StreamPropertyChangedEvent = (function (_super) {
- __extends(StreamPropertyChangedEvent, _super);
- function StreamPropertyChangedEvent(target, stream, changedProperty, newValue, oldValue, reason) {
- var _this = _super.call(this, false, target, 'streamPropertyChanged') || this;
- _this.stream = stream;
- _this.changedProperty = changedProperty;
- _this.newValue = newValue;
- _this.oldValue = oldValue;
- _this.reason = reason;
- return _this;
- }
- StreamPropertyChangedEvent.prototype.callDefaultBehavior = function () { };
- return StreamPropertyChangedEvent;
-}(Event_1.Event));
-exports.StreamPropertyChangedEvent = StreamPropertyChangedEvent;
-
-},{"./Event":29}],37:[function(require,module,exports){
-"use strict";
-var __extends = (this && this.__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 __());
- };
-})();
-Object.defineProperty(exports, "__esModule", { value: true });
-var Event_1 = require("./Event");
-var VideoElementEvent = (function (_super) {
- __extends(VideoElementEvent, _super);
- function VideoElementEvent(element, target, type) {
- var _this = _super.call(this, false, target, type) || this;
- _this.element = element;
- return _this;
- }
- VideoElementEvent.prototype.callDefaultBehavior = function () { };
- return VideoElementEvent;
-}(Event_1.Event));
-exports.VideoElementEvent = VideoElementEvent;
-
-},{"./Event":29}],38:[function(require,module,exports){
-function Mapper() {
- var sources = {};
- this.forEach = function (callback) {
- for (var key in sources) {
- var source = sources[key];
- for (var key2 in source)
- callback(source[key2]);
- }
- ;
- };
- this.get = function (id, source) {
- var ids = sources[source];
- if (ids == undefined)
- return undefined;
- return ids[id];
- };
- this.remove = function (id, source) {
- var ids = sources[source];
- if (ids == undefined)
- return;
- delete ids[id];
- for (var i in ids) {
- return false;
- }
- delete sources[source];
- };
- this.set = function (value, id, source) {
- if (value == undefined)
- return this.remove(id, source);
- var ids = sources[source];
- if (ids == undefined)
- sources[source] = ids = {};
- ids[id] = value;
- };
-}
-;
-Mapper.prototype.pop = function (id, source) {
- var value = this.get(id, source);
- if (value == undefined)
- return undefined;
- this.remove(id, source);
- return value;
-};
-module.exports = Mapper;
-
-},{}],39:[function(require,module,exports){
-var JsonRpcClient = require('./jsonrpcclient');
-exports.JsonRpcClient = JsonRpcClient;
-
-},{"./jsonrpcclient":40}],40:[function(require,module,exports){
-var RpcBuilder = require('../');
-var WebSocketWithReconnection = require('./transports/webSocketWithReconnection');
-Date.now = Date.now || function () {
- return +new Date;
-};
-var PING_INTERVAL = 5000;
-var RECONNECTING = 'RECONNECTING';
-var CONNECTED = 'CONNECTED';
-var DISCONNECTED = 'DISCONNECTED';
-var Logger = console;
-function JsonRpcClient(configuration) {
- var self = this;
- var wsConfig = configuration.ws;
- var notReconnectIfNumLessThan = -1;
- var pingNextNum = 0;
- var enabledPings = true;
- var pingPongStarted = false;
- var pingInterval;
- var status = DISCONNECTED;
- var onreconnecting = wsConfig.onreconnecting;
- var onreconnected = wsConfig.onreconnected;
- var onconnected = wsConfig.onconnected;
- var onerror = wsConfig.onerror;
- configuration.rpc.pull = function (params, request) {
- request.reply(null, "push");
- };
- wsConfig.onreconnecting = function () {
- Logger.debug("--------- ONRECONNECTING -----------");
- if (status === RECONNECTING) {
- Logger.error("Websocket already in RECONNECTING state when receiving a new ONRECONNECTING message. Ignoring it");
- return;
- }
- status = RECONNECTING;
- if (onreconnecting) {
- onreconnecting();
- }
- };
- wsConfig.onreconnected = function () {
- Logger.debug("--------- ONRECONNECTED -----------");
- if (status === CONNECTED) {
- Logger.error("Websocket already in CONNECTED state when receiving a new ONRECONNECTED message. Ignoring it");
- return;
- }
- status = CONNECTED;
- enabledPings = true;
- updateNotReconnectIfLessThan();
- usePing();
- if (onreconnected) {
- onreconnected();
- }
- };
- wsConfig.onconnected = function () {
- Logger.debug("--------- ONCONNECTED -----------");
- if (status === CONNECTED) {
- Logger.error("Websocket already in CONNECTED state when receiving a new ONCONNECTED message. Ignoring it");
- return;
- }
- status = CONNECTED;
- enabledPings = true;
- usePing();
- if (onconnected) {
- onconnected();
- }
- };
- wsConfig.onerror = function (error) {
- Logger.debug("--------- ONERROR -----------");
- status = DISCONNECTED;
- if (onerror) {
- onerror(error);
- }
- };
- var ws = new WebSocketWithReconnection(wsConfig);
- Logger.debug('Connecting websocket to URI: ' + wsConfig.uri);
- var rpcBuilderOptions = {
- request_timeout: configuration.rpc.requestTimeout,
- ping_request_timeout: configuration.rpc.heartbeatRequestTimeout
- };
- var rpc = new RpcBuilder(RpcBuilder.packers.JsonRPC, rpcBuilderOptions, ws, function (request) {
- Logger.debug('Received request: ' + JSON.stringify(request));
- try {
- var func = configuration.rpc[request.method];
- if (func === undefined) {
- Logger.error("Method " + request.method + " not registered in client");
- }
- else {
- func(request.params, request);
- }
- }
- catch (err) {
- Logger.error('Exception processing request: ' + JSON.stringify(request));
- Logger.error(err);
- }
- });
- this.send = function (method, params, callback) {
- if (method !== 'ping') {
- Logger.debug('Request: method:' + method + " params:" + JSON.stringify(params));
- }
- var requestTime = Date.now();
- rpc.encode(method, params, function (error, result) {
- if (error) {
- try {
- Logger.error("ERROR:" + error.message + " in Request: method:" +
- method + " params:" + JSON.stringify(params) + " request:" +
- error.request);
- if (error.data) {
- Logger.error("ERROR DATA:" + JSON.stringify(error.data));
- }
- }
- catch (e) { }
- error.requestTime = requestTime;
- }
- if (callback) {
- if (result != undefined && result.value !== 'pong') {
- Logger.debug('Response: ' + JSON.stringify(result));
- }
- callback(error, result);
- }
- });
- };
- function updateNotReconnectIfLessThan() {
- Logger.debug("notReconnectIfNumLessThan = " + pingNextNum + ' (old=' +
- notReconnectIfNumLessThan + ')');
- notReconnectIfNumLessThan = pingNextNum;
- }
- function sendPing() {
- if (enabledPings) {
- var params = null;
- if (pingNextNum == 0 || pingNextNum == notReconnectIfNumLessThan) {
- params = {
- interval: configuration.heartbeat || PING_INTERVAL
- };
- }
- pingNextNum++;
- self.send('ping', params, (function (pingNum) {
- return function (error, result) {
- if (error) {
- Logger.debug("Error in ping request #" + pingNum + " (" +
- error.message + ")");
- if (pingNum > notReconnectIfNumLessThan) {
- enabledPings = false;
- updateNotReconnectIfLessThan();
- Logger.debug("Server did not respond to ping message #" +
- pingNum + ". Reconnecting... ");
- ws.reconnectWs();
- }
- }
- };
- })(pingNextNum));
- }
- else {
- Logger.debug("Trying to send ping, but ping is not enabled");
- }
- }
- function usePing() {
- if (!pingPongStarted) {
- Logger.debug("Starting ping (if configured)");
- pingPongStarted = true;
- if (configuration.heartbeat != undefined) {
- pingInterval = setInterval(sendPing, configuration.heartbeat);
- sendPing();
- }
- }
- }
- this.close = function () {
- Logger.debug("Closing jsonRpcClient explicitly by client");
- if (pingInterval != undefined) {
- Logger.debug("Clearing ping interval");
- clearInterval(pingInterval);
- }
- pingPongStarted = false;
- enabledPings = false;
- if (configuration.sendCloseMessage) {
- Logger.debug("Sending close message");
- this.send('closeSession', null, function (error, result) {
- if (error) {
- Logger.error("Error sending close message: " + JSON.stringify(error));
- }
- ws.close();
- });
- }
- else {
- ws.close();
- }
- };
- this.forceClose = function (millis) {
- ws.forceClose(millis);
- };
- this.reconnect = function () {
- ws.reconnectWs();
- };
-}
-module.exports = JsonRpcClient;
-
-},{"../":43,"./transports/webSocketWithReconnection":42}],41:[function(require,module,exports){
-var WebSocketWithReconnection = require('./webSocketWithReconnection');
-exports.WebSocketWithReconnection = WebSocketWithReconnection;
-
-},{"./webSocketWithReconnection":42}],42:[function(require,module,exports){
-(function (global){
-"use strict";
-var BrowserWebSocket = global.WebSocket || global.MozWebSocket;
-var Logger = console;
-var MAX_RETRIES = 2000;
-var RETRY_TIME_MS = 3000;
-var CONNECTING = 0;
-var OPEN = 1;
-var CLOSING = 2;
-var CLOSED = 3;
-function WebSocketWithReconnection(config) {
- var closing = false;
- var registerMessageHandler;
- var wsUri = config.uri;
- var useSockJS = config.useSockJS;
- var reconnecting = false;
- var forcingDisconnection = false;
- var ws;
- if (useSockJS) {
- ws = new SockJS(wsUri);
- }
- else {
- ws = new WebSocket(wsUri);
- }
- ws.onopen = function () {
- logConnected(ws, wsUri);
- if (config.onconnected) {
- config.onconnected();
- }
- };
- ws.onerror = function (error) {
- Logger.error("Could not connect to " + wsUri + " (invoking onerror if defined)", error);
- if (config.onerror) {
- config.onerror(error);
- }
- };
- function logConnected(ws, wsUri) {
- try {
- Logger.debug("WebSocket connected to " + wsUri);
- }
- catch (e) {
- Logger.error(e);
- }
- }
- var reconnectionOnClose = function () {
- if (ws.readyState === CLOSED) {
- if (closing) {
- Logger.debug("Connection closed by user");
- }
- else {
- Logger.debug("Connection closed unexpectecly. Reconnecting...");
- reconnectToSameUri(MAX_RETRIES, 1);
- }
- }
- else {
- Logger.debug("Close callback from previous websocket. Ignoring it");
- }
- };
- ws.onclose = reconnectionOnClose;
- function reconnectToSameUri(maxRetries, numRetries) {
- Logger.debug("reconnectToSameUri (attempt #" + numRetries + ", max=" + maxRetries + ")");
- if (numRetries === 1) {
- if (reconnecting) {
- Logger.warn("Trying to reconnectToNewUri when reconnecting... Ignoring this reconnection.");
- return;
- }
- else {
- reconnecting = true;
- }
- if (config.onreconnecting) {
- config.onreconnecting();
- }
- }
- if (forcingDisconnection) {
- reconnectToNewUri(maxRetries, numRetries, wsUri);
- }
- else {
- if (config.newWsUriOnReconnection) {
- config.newWsUriOnReconnection(function (error, newWsUri) {
- if (error) {
- Logger.debug(error);
- setTimeout(function () {
- reconnectToSameUri(maxRetries, numRetries + 1);
- }, RETRY_TIME_MS);
- }
- else {
- reconnectToNewUri(maxRetries, numRetries, newWsUri);
- }
- });
- }
- else {
- reconnectToNewUri(maxRetries, numRetries, wsUri);
- }
- }
- }
- function reconnectToNewUri(maxRetries, numRetries, reconnectWsUri) {
- Logger.debug("Reconnection attempt #" + numRetries);
- ws.close();
- wsUri = reconnectWsUri || wsUri;
- var newWs;
- if (useSockJS) {
- newWs = new SockJS(wsUri);
- }
- else {
- newWs = new WebSocket(wsUri);
- }
- newWs.onopen = function () {
- Logger.debug("Reconnected after " + numRetries + " attempts...");
- logConnected(newWs, wsUri);
- reconnecting = false;
- registerMessageHandler();
- if (config.onreconnected()) {
- config.onreconnected();
- }
- newWs.onclose = reconnectionOnClose;
- };
- var onErrorOrClose = function (error) {
- Logger.warn("Reconnection error: ", error);
- if (numRetries === maxRetries) {
- if (config.ondisconnect) {
- config.ondisconnect();
- }
- }
- else {
- setTimeout(function () {
- reconnectToSameUri(maxRetries, numRetries + 1);
- }, RETRY_TIME_MS);
- }
- };
- newWs.onerror = onErrorOrClose;
- ws = newWs;
- }
- this.close = function () {
- closing = true;
- ws.close();
- };
- this.forceClose = function (millis) {
- Logger.debug("Testing: Force WebSocket close");
- if (millis) {
- Logger.debug("Testing: Change wsUri for " + millis + " millis to simulate net failure");
- var goodWsUri = wsUri;
- wsUri = "wss://21.234.12.34.4:443/";
- forcingDisconnection = true;
- setTimeout(function () {
- Logger.debug("Testing: Recover good wsUri " + goodWsUri);
- wsUri = goodWsUri;
- forcingDisconnection = false;
- }, millis);
- }
- ws.close();
- };
- this.reconnectWs = function () {
- Logger.debug("reconnectWs");
- reconnectToSameUri(MAX_RETRIES, 1, wsUri);
- };
- this.send = function (message) {
- ws.send(message);
- };
- this.addEventListener = function (type, callback) {
- registerMessageHandler = function () {
- ws.addEventListener(type, callback);
- };
- registerMessageHandler();
- };
-}
-module.exports = WebSocketWithReconnection;
-
-}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
-
-},{}],43:[function(require,module,exports){
-var defineProperty_IE8 = false;
-if (Object.defineProperty) {
- try {
- Object.defineProperty({}, "x", {});
- }
- catch (e) {
- defineProperty_IE8 = true;
- }
-}
-if (!Function.prototype.bind) {
- Function.prototype.bind = function (oThis) {
- if (typeof this !== 'function') {
- throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable');
- }
- var aArgs = Array.prototype.slice.call(arguments, 1), fToBind = this, fNOP = function () { }, fBound = function () {
- return fToBind.apply(this instanceof fNOP && oThis
- ? this
- : oThis, aArgs.concat(Array.prototype.slice.call(arguments)));
- };
- fNOP.prototype = this.prototype;
- fBound.prototype = new fNOP();
- return fBound;
- };
-}
-var EventEmitter = require('events').EventEmitter;
-var inherits = require('inherits');
-var packers = require('./packers');
-var Mapper = require('./Mapper');
-var BASE_TIMEOUT = 5000;
-function unifyResponseMethods(responseMethods) {
- if (!responseMethods)
- return {};
- for (var key in responseMethods) {
- var value = responseMethods[key];
- if (typeof value == 'string')
- responseMethods[key] =
- {
- response: value
- };
- }
- ;
- return responseMethods;
-}
-;
-function unifyTransport(transport) {
- if (!transport)
- return;
- if (transport instanceof Function)
- return { send: transport };
- if (transport.send instanceof Function)
- return transport;
- if (transport.postMessage instanceof Function) {
- transport.send = transport.postMessage;
- return transport;
- }
- if (transport.write instanceof Function) {
- transport.send = transport.write;
- return transport;
- }
- if (transport.onmessage !== undefined)
- return;
- if (transport.pause instanceof Function)
- return;
- throw new SyntaxError("Transport is not a function nor a valid object");
-}
-;
-function RpcNotification(method, params) {
- if (defineProperty_IE8) {
- this.method = method;
- this.params = params;
- }
- else {
- Object.defineProperty(this, 'method', { value: method, enumerable: true });
- Object.defineProperty(this, 'params', { value: params, enumerable: true });
- }
-}
-;
-function RpcBuilder(packer, options, transport, onRequest) {
- var self = this;
- if (!packer)
- throw new SyntaxError('Packer is not defined');
- if (!packer.pack || !packer.unpack)
- throw new SyntaxError('Packer is invalid');
- var responseMethods = unifyResponseMethods(packer.responseMethods);
- if (options instanceof Function) {
- if (transport != undefined)
- throw new SyntaxError("There can't be parameters after onRequest");
- onRequest = options;
- transport = undefined;
- options = undefined;
- }
- ;
- if (options && options.send instanceof Function) {
- if (transport && !(transport instanceof Function))
- throw new SyntaxError("Only a function can be after transport");
- onRequest = transport;
- transport = options;
- options = undefined;
- }
- ;
- if (transport instanceof Function) {
- if (onRequest != undefined)
- throw new SyntaxError("There can't be parameters after onRequest");
- onRequest = transport;
- transport = undefined;
- }
- ;
- if (transport && transport.send instanceof Function)
- if (onRequest && !(onRequest instanceof Function))
- throw new SyntaxError("Only a function can be after transport");
- options = options || {};
- EventEmitter.call(this);
- if (onRequest)
- this.on('request', onRequest);
- if (defineProperty_IE8)
- this.peerID = options.peerID;
- else
- Object.defineProperty(this, 'peerID', { value: options.peerID });
- var max_retries = options.max_retries || 0;
- function transportMessage(event) {
- self.decode(event.data || event);
- }
- ;
- this.getTransport = function () {
- return transport;
- };
- this.setTransport = function (value) {
- if (transport) {
- if (transport.removeEventListener)
- transport.removeEventListener('message', transportMessage);
- else if (transport.removeListener)
- transport.removeListener('data', transportMessage);
- }
- ;
- if (value) {
- if (value.addEventListener)
- value.addEventListener('message', transportMessage);
- else if (value.addListener)
- value.addListener('data', transportMessage);
- }
- ;
- transport = unifyTransport(value);
- };
- if (!defineProperty_IE8)
- Object.defineProperty(this, 'transport', {
- get: this.getTransport.bind(this),
- set: this.setTransport.bind(this)
- });
- this.setTransport(transport);
- var request_timeout = options.request_timeout || BASE_TIMEOUT;
- var ping_request_timeout = options.ping_request_timeout || request_timeout;
- var response_timeout = options.response_timeout || BASE_TIMEOUT;
- var duplicates_timeout = options.duplicates_timeout || BASE_TIMEOUT;
- var requestID = 0;
- var requests = new Mapper();
- var responses = new Mapper();
- var processedResponses = new Mapper();
- var message2Key = {};
- function storeResponse(message, id, dest) {
- var response = {
- message: message,
- timeout: setTimeout(function () {
- responses.remove(id, dest);
- }, response_timeout)
- };
- responses.set(response, id, dest);
- }
- ;
- function storeProcessedResponse(ack, from) {
- var timeout = setTimeout(function () {
- processedResponses.remove(ack, from);
- }, duplicates_timeout);
- processedResponses.set(timeout, ack, from);
- }
- ;
- function RpcRequest(method, params, id, from, transport) {
- RpcNotification.call(this, method, params);
- this.getTransport = function () {
- return transport;
- };
- this.setTransport = function (value) {
- transport = unifyTransport(value);
- };
- if (!defineProperty_IE8)
- Object.defineProperty(this, 'transport', {
- get: this.getTransport.bind(this),
- set: this.setTransport.bind(this)
- });
- var response = responses.get(id, from);
- if (!(transport || self.getTransport())) {
- if (defineProperty_IE8)
- this.duplicated = Boolean(response);
- else
- Object.defineProperty(this, 'duplicated', {
- value: Boolean(response)
- });
- }
- var responseMethod = responseMethods[method];
- this.pack = packer.pack.bind(packer, this, id);
- this.reply = function (error, result, transport) {
- if (error instanceof Function || error && error.send instanceof Function) {
- if (result != undefined)
- throw new SyntaxError("There can't be parameters after callback");
- transport = error;
- result = null;
- error = undefined;
- }
- else if (result instanceof Function
- || result && result.send instanceof Function) {
- if (transport != undefined)
- throw new SyntaxError("There can't be parameters after callback");
- transport = result;
- result = null;
- }
- ;
- transport = unifyTransport(transport);
- if (response)
- clearTimeout(response.timeout);
- if (from != undefined) {
- if (error)
- error.dest = from;
- if (result)
- result.dest = from;
- }
- ;
- var message;
- if (error || result != undefined) {
- if (self.peerID != undefined) {
- if (error)
- error.from = self.peerID;
- else
- result.from = self.peerID;
- }
- if (responseMethod) {
- if (responseMethod.error == undefined && error)
- message =
- {
- error: error
- };
- else {
- var method = error
- ? responseMethod.error
- : responseMethod.response;
- message =
- {
- method: method,
- params: error || result
- };
- }
- }
- else
- message =
- {
- error: error,
- result: result
- };
- message = packer.pack(message, id);
- }
- else if (response)
- message = response.message;
- else
- message = packer.pack({ result: null }, id);
- storeResponse(message, id, from);
- transport = transport || this.getTransport() || self.getTransport();
- if (transport)
- return transport.send(message);
- return message;
- };
- }
- ;
- inherits(RpcRequest, RpcNotification);
- function cancel(message) {
- var key = message2Key[message];
- if (!key)
- return;
- delete message2Key[message];
- var request = requests.pop(key.id, key.dest);
- if (!request)
- return;
- clearTimeout(request.timeout);
- storeProcessedResponse(key.id, key.dest);
- }
- ;
- this.cancel = function (message) {
- if (message)
- return cancel(message);
- for (var message in message2Key)
- cancel(message);
- };
- this.close = function () {
- var transport = this.getTransport();
- if (transport && transport.close)
- transport.close();
- this.cancel();
- processedResponses.forEach(clearTimeout);
- responses.forEach(function (response) {
- clearTimeout(response.timeout);
- });
- };
- this.encode = function (method, params, dest, transport, callback) {
- if (params instanceof Function) {
- if (dest != undefined)
- throw new SyntaxError("There can't be parameters after callback");
- callback = params;
- transport = undefined;
- dest = undefined;
- params = undefined;
- }
- else if (dest instanceof Function) {
- if (transport != undefined)
- throw new SyntaxError("There can't be parameters after callback");
- callback = dest;
- transport = undefined;
- dest = undefined;
- }
- else if (transport instanceof Function) {
- if (callback != undefined)
- throw new SyntaxError("There can't be parameters after callback");
- callback = transport;
- transport = undefined;
- }
- ;
- if (self.peerID != undefined) {
- params = params || {};
- params.from = self.peerID;
- }
- ;
- if (dest != undefined) {
- params = params || {};
- params.dest = dest;
- }
- ;
- var message = {
- method: method,
- params: params
- };
- if (callback) {
- var id = requestID++;
- var retried = 0;
- message = packer.pack(message, id);
- function dispatchCallback(error, result) {
- self.cancel(message);
- callback(error, result);
- }
- ;
- var request = {
- message: message,
- callback: dispatchCallback,
- responseMethods: responseMethods[method] || {}
- };
- var encode_transport = unifyTransport(transport);
- function sendRequest(transport) {
- var rt = (method === 'ping' ? ping_request_timeout : request_timeout);
- request.timeout = setTimeout(timeout, rt * Math.pow(2, retried++));
- message2Key[message] = { id: id, dest: dest };
- requests.set(request, id, dest);
- transport = transport || encode_transport || self.getTransport();
- if (transport)
- return transport.send(message);
- return message;
- }
- ;
- function retry(transport) {
- transport = unifyTransport(transport);
- console.warn(retried + ' retry for request message:', message);
- var timeout = processedResponses.pop(id, dest);
- clearTimeout(timeout);
- return sendRequest(transport);
- }
- ;
- function timeout() {
- if (retried < max_retries)
- return retry(transport);
- var error = new Error('Request has timed out');
- error.request = message;
- error.retry = retry;
- dispatchCallback(error);
- }
- ;
- return sendRequest(transport);
- }
- ;
- message = packer.pack(message);
- transport = transport || this.getTransport();
- if (transport)
- return transport.send(message);
- return message;
- };
- this.decode = function (message, transport) {
- if (!message)
- throw new TypeError("Message is not defined");
- try {
- message = packer.unpack(message);
- }
- catch (e) {
- return console.debug(e, message);
- }
- ;
- var id = message.id;
- var ack = message.ack;
- var method = message.method;
- var params = message.params || {};
- var from = params.from;
- var dest = params.dest;
- if (self.peerID != undefined && from == self.peerID)
- return;
- if (id == undefined && ack == undefined) {
- var notification = new RpcNotification(method, params);
- if (self.emit('request', notification))
- return;
- return notification;
- }
- ;
- function processRequest() {
- transport = unifyTransport(transport) || self.getTransport();
- if (transport) {
- var response = responses.get(id, from);
- if (response)
- return transport.send(response.message);
- }
- ;
- var idAck = (id != undefined) ? id : ack;
- var request = new RpcRequest(method, params, idAck, from, transport);
- if (self.emit('request', request))
- return;
- return request;
- }
- ;
- function processResponse(request, error, result) {
- request.callback(error, result);
- }
- ;
- function duplicatedResponse(timeout) {
- console.warn("Response already processed", message);
- clearTimeout(timeout);
- storeProcessedResponse(ack, from);
- }
- ;
- if (method) {
- if (dest == undefined || dest == self.peerID) {
- var request = requests.get(ack, from);
- if (request) {
- var responseMethods = request.responseMethods;
- if (method == responseMethods.error)
- return processResponse(request, params);
- if (method == responseMethods.response)
- return processResponse(request, null, params);
- return processRequest();
- }
- var processed = processedResponses.get(ack, from);
- if (processed)
- return duplicatedResponse(processed);
- }
- return processRequest();
- }
- ;
- var error = message.error;
- var result = message.result;
- if (error && error.dest && error.dest != self.peerID)
- return;
- if (result && result.dest && result.dest != self.peerID)
- return;
- var request = requests.get(ack, from);
- if (!request) {
- var processed = processedResponses.get(ack, from);
- if (processed)
- return duplicatedResponse(processed);
- return console.warn("No callback was defined for this message", message);
- }
- ;
- processResponse(request, error, result);
- };
-}
-;
-inherits(RpcBuilder, EventEmitter);
-RpcBuilder.RpcNotification = RpcNotification;
-module.exports = RpcBuilder;
-var clients = require('./clients');
-var transports = require('./clients/transports');
-RpcBuilder.clients = clients;
-RpcBuilder.clients.transports = transports;
-RpcBuilder.packers = packers;
-
-},{"./Mapper":38,"./clients":39,"./clients/transports":41,"./packers":46,"events":1,"inherits":6}],44:[function(require,module,exports){
-function pack(message, id) {
- var result = {
- jsonrpc: "2.0"
- };
- if (message.method) {
- result.method = message.method;
- if (message.params)
- result.params = message.params;
- if (id != undefined)
- result.id = id;
- }
- else if (id != undefined) {
- if (message.error) {
- if (message.result !== undefined)
- throw new TypeError("Both result and error are defined");
- result.error = message.error;
- }
- else if (message.result !== undefined)
- result.result = message.result;
- else
- throw new TypeError("No result or error is defined");
- result.id = id;
- }
- ;
- return JSON.stringify(result);
-}
-;
-function unpack(message) {
- var result = message;
- if (typeof message === 'string' || message instanceof String) {
- result = JSON.parse(message);
- }
- var version = result.jsonrpc;
- if (version !== '2.0')
- throw new TypeError("Invalid JsonRPC version '" + version + "': " + message);
- if (result.method == undefined) {
- if (result.id == undefined)
- throw new TypeError("Invalid message: " + message);
- var result_defined = result.result !== undefined;
- var error_defined = result.error !== undefined;
- if (result_defined && error_defined)
- throw new TypeError("Both result and error are defined: " + message);
- if (!result_defined && !error_defined)
- throw new TypeError("No result or error is defined: " + message);
- result.ack = result.id;
- delete result.id;
- }
- return result;
-}
-;
-exports.pack = pack;
-exports.unpack = unpack;
-
-},{}],45:[function(require,module,exports){
-function pack(message) {
- throw new TypeError("Not yet implemented");
-}
-;
-function unpack(message) {
- throw new TypeError("Not yet implemented");
-}
-;
-exports.pack = pack;
-exports.unpack = unpack;
-
-},{}],46:[function(require,module,exports){
-var JsonRPC = require('./JsonRPC');
-var XmlRPC = require('./XmlRPC');
-exports.JsonRPC = JsonRPC;
-exports.XmlRPC = XmlRPC;
-
-},{"./JsonRPC":44,"./XmlRPC":45}],47:[function(require,module,exports){
-window.getScreenId = function (callback, custom_parameter) {
- if (navigator.userAgent.indexOf('Edge') !== -1 && (!!navigator.msSaveOrOpenBlob || !!navigator.msSaveBlob)) {
- callback({
- video: true
- });
- return;
- }
- if (!!navigator.mozGetUserMedia) {
- callback(null, 'firefox', {
- video: {
- mozMediaSource: 'window',
- mediaSource: 'window'
- }
- });
- return;
- }
- window.addEventListener('message', onIFrameCallback);
- function onIFrameCallback(event) {
- if (!event.data)
- return;
- if (event.data.chromeMediaSourceId) {
- if (event.data.chromeMediaSourceId === 'PermissionDeniedError') {
- callback('permission-denied');
- }
- else {
- callback(null, event.data.chromeMediaSourceId, getScreenConstraints(null, event.data.chromeMediaSourceId, event.data.canRequestAudioTrack));
- }
- window.removeEventListener('message', onIFrameCallback);
- }
- if (event.data.chromeExtensionStatus) {
- callback(event.data.chromeExtensionStatus, null, getScreenConstraints(event.data.chromeExtensionStatus));
- window.removeEventListener('message', onIFrameCallback);
- }
- }
- if (!custom_parameter) {
- setTimeout(postGetSourceIdMessage, 100);
- }
- else {
- setTimeout(function () {
- postGetSourceIdMessage(custom_parameter);
- }, 100);
- }
-};
-function getScreenConstraints(error, sourceId, canRequestAudioTrack) {
- var screen_constraints = {
- audio: false,
- video: {
- mandatory: {
- chromeMediaSource: error ? 'screen' : 'desktop',
- maxWidth: window.screen.width > 1920 ? window.screen.width : 1920,
- maxHeight: window.screen.height > 1080 ? window.screen.height : 1080
- },
- optional: []
- }
- };
- if (!!canRequestAudioTrack) {
- screen_constraints.audio = {
- mandatory: {
- chromeMediaSource: error ? 'screen' : 'desktop',
- },
- optional: []
- };
- }
- if (sourceId) {
- screen_constraints.video.mandatory.chromeMediaSourceId = sourceId;
- if (screen_constraints.audio && screen_constraints.audio.mandatory) {
- screen_constraints.audio.mandatory.chromeMediaSourceId = sourceId;
- }
- }
- return screen_constraints;
-}
-function postGetSourceIdMessage(custom_parameter) {
- if (!iframe) {
- loadIFrame(function () {
- postGetSourceIdMessage(custom_parameter);
- });
- return;
- }
- if (!iframe.isLoaded) {
- setTimeout(function () {
- postGetSourceIdMessage(custom_parameter);
- }, 100);
- return;
- }
- if (!custom_parameter) {
- iframe.contentWindow.postMessage({
- captureSourceId: true
- }, '*');
- }
- else if (!!custom_parameter.forEach) {
- iframe.contentWindow.postMessage({
- captureCustomSourceId: custom_parameter
- }, '*');
- }
- else {
- iframe.contentWindow.postMessage({
- captureSourceIdWithAudio: true
- }, '*');
- }
-}
-var iframe;
-window.getScreenConstraints = function (callback) {
- loadIFrame(function () {
- getScreenId(function (error, sourceId, screen_constraints) {
- if (!screen_constraints) {
- screen_constraints = {
- video: true
- };
- }
- callback(error, screen_constraints.video);
- });
- });
-};
-function loadIFrame(loadCallback) {
- if (iframe) {
- loadCallback();
- return;
- }
- iframe = document.createElement('iframe');
- iframe.onload = function () {
- iframe.isLoaded = true;
- loadCallback();
- };
- iframe.src = 'https://openvidu.github.io/openvidu-screen-sharing-chrome-extension/';
- iframe.style.display = 'none';
- (document.body || document.documentElement).appendChild(iframe);
-}
-window.getChromeExtensionStatus = function (callback) {
- if (!!navigator.mozGetUserMedia) {
- callback('installed-enabled');
- return;
- }
- window.addEventListener('message', onIFrameCallback);
- function onIFrameCallback(event) {
- if (!event.data)
- return;
- if (event.data.chromeExtensionStatus) {
- callback(event.data.chromeExtensionStatus);
- window.removeEventListener('message', onIFrameCallback);
- }
- }
- setTimeout(postGetChromeExtensionStatusMessage, 100);
-};
-function postGetChromeExtensionStatusMessage() {
- if (!iframe) {
- loadIFrame(postGetChromeExtensionStatusMessage);
- return;
- }
- if (!iframe.isLoaded) {
- setTimeout(postGetChromeExtensionStatusMessage, 100);
- return;
- }
- iframe.contentWindow.postMessage({
- getChromeExtensionStatus: true
- }, '*');
-}
-exports.getScreenId = getScreenId;
-
-},{}],48:[function(require,module,exports){
-var chromeMediaSource = 'screen';
-var sourceId;
-var screenCallback;
-var isFirefox = typeof window.InstallTrigger !== 'undefined';
-var isOpera = !!window.opera || navigator.userAgent.indexOf(' OPR/') >= 0;
-var isChrome = !!window.chrome && !isOpera;
-window.addEventListener('message', function (event) {
- if (event.origin != window.location.origin) {
- return;
- }
- onMessageCallback(event.data);
-});
-function onMessageCallback(data) {
- if (data == 'PermissionDeniedError') {
- if (screenCallback)
- return screenCallback('PermissionDeniedError');
- else
- throw new Error('PermissionDeniedError');
- }
- if (data == 'rtcmulticonnection-extension-loaded') {
- chromeMediaSource = 'desktop';
- }
- if (data.sourceId && screenCallback) {
- screenCallback(sourceId = data.sourceId, data.canRequestAudioTrack === true);
- }
-}
-function isChromeExtensionAvailable(callback) {
- if (!callback)
- return;
- if (chromeMediaSource == 'desktop')
- return callback(true);
- window.postMessage('are-you-there', '*');
- setTimeout(function () {
- if (chromeMediaSource == 'screen') {
- callback(false);
- }
- else
- callback(true);
- }, 2000);
-}
-function getSourceId(callback) {
- if (!callback)
- throw '"callback" parameter is mandatory.';
- if (sourceId)
- return callback(sourceId);
- screenCallback = callback;
- window.postMessage('get-sourceId', '*');
-}
-function getCustomSourceId(arr, callback) {
- if (!arr || !arr.forEach)
- throw '"arr" parameter is mandatory and it must be an array.';
- if (!callback)
- throw '"callback" parameter is mandatory.';
- if (sourceId)
- return callback(sourceId);
- screenCallback = callback;
- window.postMessage({
- 'get-custom-sourceId': arr
- }, '*');
-}
-function getSourceIdWithAudio(callback) {
- if (!callback)
- throw '"callback" parameter is mandatory.';
- if (sourceId)
- return callback(sourceId);
- screenCallback = callback;
- window.postMessage('audio-plus-tab', '*');
-}
-function getChromeExtensionStatus(extensionid, callback) {
- if (isFirefox)
- return callback('not-chrome');
- if (arguments.length != 2) {
- callback = extensionid;
- extensionid = 'lfcgfepafnobdloecchnfaclibenjold';
- }
- var image = document.createElement('img');
- image.src = 'chrome-extension://' + extensionid + '/icon.png';
- image.onload = function () {
- chromeMediaSource = 'screen';
- window.postMessage('are-you-there', '*');
- setTimeout(function () {
- if (chromeMediaSource == 'screen') {
- callback('installed-disabled');
- }
- else
- callback('installed-enabled');
- }, 2000);
- };
- image.onerror = function () {
- callback('not-installed');
- };
-}
-function getScreenConstraintsWithAudio(callback) {
- getScreenConstraints(callback, true);
-}
-function getScreenConstraints(callback, captureSourceIdWithAudio) {
- sourceId = '';
- var firefoxScreenConstraints = {
- mozMediaSource: 'window',
- mediaSource: 'window'
- };
- if (isFirefox)
- return callback(null, firefoxScreenConstraints);
- var screen_constraints = {
- mandatory: {
- chromeMediaSource: chromeMediaSource,
- maxWidth: screen.width > 1920 ? screen.width : 1920,
- maxHeight: screen.height > 1080 ? screen.height : 1080
- },
- optional: []
- };
- if (chromeMediaSource == 'desktop' && !sourceId) {
- if (captureSourceIdWithAudio) {
- getSourceIdWithAudio(function (sourceId, canRequestAudioTrack) {
- screen_constraints.mandatory.chromeMediaSourceId = sourceId;
- if (canRequestAudioTrack) {
- screen_constraints.canRequestAudioTrack = true;
- }
- callback(sourceId == 'PermissionDeniedError' ? sourceId : null, screen_constraints);
- });
- }
- else {
- getSourceId(function (sourceId) {
- screen_constraints.mandatory.chromeMediaSourceId = sourceId;
- callback(sourceId == 'PermissionDeniedError' ? sourceId : null, screen_constraints);
- });
- }
- return;
- }
- if (chromeMediaSource == 'desktop') {
- screen_constraints.mandatory.chromeMediaSourceId = sourceId;
- }
- callback(null, screen_constraints);
-}
-exports.getScreenConstraints = getScreenConstraints;
-exports.getScreenConstraintsWithAudio = getScreenConstraintsWithAudio;
-exports.isChromeExtensionAvailable = isChromeExtensionAvailable;
-exports.getChromeExtensionStatus = getChromeExtensionStatus;
-exports.getSourceId = getSourceId;
-
-},{}],49:[function(require,module,exports){
-"use strict";
-var __extends = (this && this.__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 __());
- };
-})();
-Object.defineProperty(exports, "__esModule", { value: true });
-var freeice = require("freeice");
-var uuid = require("uuid");
-var platform = require("platform");
-var WebRtcPeer = (function () {
- function WebRtcPeer(configuration) {
- var _this = this;
- this.configuration = configuration;
- this.remoteCandidatesQueue = [];
- this.localCandidatesQueue = [];
- this.iceCandidateList = [];
- this.candidategatheringdone = false;
- this.configuration.iceServers = (!!this.configuration.iceServers && this.configuration.iceServers.length > 0) ? this.configuration.iceServers : freeice();
- this.pc = new RTCPeerConnection({ iceServers: this.configuration.iceServers });
- this.id = !!configuration.id ? configuration.id : uuid.v4();
- this.pc.onicecandidate = function (event) {
- var candidate = event.candidate;
- if (candidate) {
- _this.localCandidatesQueue.push({ candidate: candidate.candidate });
- _this.candidategatheringdone = false;
- _this.configuration.onicecandidate(event.candidate);
- }
- else if (!_this.candidategatheringdone) {
- _this.candidategatheringdone = true;
- }
- };
- this.pc.onsignalingstatechange = function () {
- if (_this.pc.signalingState === 'stable') {
- while (_this.iceCandidateList.length > 0) {
- _this.pc.addIceCandidate(_this.iceCandidateList.shift());
- }
- }
- };
- this.start();
- }
- WebRtcPeer.prototype.start = function () {
- var _this = this;
- return new Promise(function (resolve, reject) {
- if (_this.pc.signalingState === 'closed') {
- reject('The peer connection object is in "closed" state. This is most likely due to an invocation of the dispose method before accepting in the dialogue');
- }
- if (!!_this.configuration.mediaStream) {
- _this.pc.addStream(_this.configuration.mediaStream);
- }
- if (_this.configuration.mode === 'sendonly' &&
- (platform.name === 'Chrome' && platform.version.toString().substring(0, 2) === '39')) {
- _this.configuration.mode = 'sendrecv';
- }
- resolve();
- });
- };
- WebRtcPeer.prototype.dispose = function () {
- var _this = this;
- console.debug('Disposing WebRtcPeer');
- try {
- if (this.pc) {
- if (this.pc.signalingState === 'closed') {
- return;
- }
- this.remoteCandidatesQueue = [];
- this.localCandidatesQueue = [];
- this.pc.getLocalStreams().forEach(function (str) {
- _this.streamStop(str);
- });
- this.pc.close();
- }
- }
- catch (err) {
- console.warn('Exception disposing webrtc peer ' + err);
- }
- };
- WebRtcPeer.prototype.generateOffer = function () {
- var _this = this;
- return new Promise(function (resolve, reject) {
- var offerAudio, offerVideo = true;
- if (!!_this.configuration.mediaConstraints) {
- offerAudio = (typeof _this.configuration.mediaConstraints.audio === 'boolean') ?
- _this.configuration.mediaConstraints.audio : true;
- offerVideo = (typeof _this.configuration.mediaConstraints.video === 'boolean') ?
- _this.configuration.mediaConstraints.video : true;
- }
- var constraints = {
- offerToReceiveAudio: +(_this.configuration.mode !== 'sendonly' && offerAudio),
- offerToReceiveVideo: +(_this.configuration.mode !== 'sendonly' && offerVideo)
- };
- console.debug('RTCPeerConnection constraints: ' + JSON.stringify(constraints));
- _this.pc.createOffer(constraints).then(function (offer) {
- console.debug('Created SDP offer');
- return _this.pc.setLocalDescription(offer);
- }).then(function () {
- var localDescription = _this.pc.localDescription;
- if (!!localDescription) {
- console.debug('Local description set', localDescription.sdp);
- resolve(localDescription.sdp);
- }
- else {
- reject('Local description is not defined');
- }
- }).catch(function (error) { return reject(error); });
- });
- };
- WebRtcPeer.prototype.processOffer = function (sdpOffer) {
- var _this = this;
- return new Promise(function (resolve, reject) {
- var offer = {
- type: 'offer',
- sdp: sdpOffer
- };
- console.debug('SDP offer received, setting remote description');
- if (_this.pc.signalingState === 'closed') {
- reject('PeerConnection is closed');
- }
- _this.pc.setRemoteDescription(offer)
- .then(function () {
- return _this.pc.createAnswer();
- }).then(function (answer) {
- console.debug('Created SDP answer');
- return _this.pc.setLocalDescription(answer);
- }).then(function () {
- var localDescription = _this.pc.localDescription;
- if (!!localDescription) {
- console.debug('Local description set', localDescription.sdp);
- resolve(localDescription.sdp);
- }
- else {
- reject('Local description is not defined');
- }
- }).catch(function (error) { return reject(error); });
- });
- };
- WebRtcPeer.prototype.processAnswer = function (sdpAnswer) {
- var _this = this;
- return new Promise(function (resolve, reject) {
- var answer = {
- type: 'answer',
- sdp: sdpAnswer
- };
- console.debug('SDP answer received, setting remote description');
- if (_this.pc.signalingState === 'closed') {
- reject('RTCPeerConnection is closed');
- }
- _this.pc.setRemoteDescription(answer).then(function () { return resolve(); }).catch(function (error) { return reject(error); });
- });
- };
- WebRtcPeer.prototype.addIceCandidate = function (iceCandidate) {
- var _this = this;
- return new Promise(function (resolve, reject) {
- console.debug('Remote ICE candidate received', iceCandidate);
- _this.remoteCandidatesQueue.push(iceCandidate);
- switch (_this.pc.signalingState) {
- case 'closed':
- reject(new Error('PeerConnection object is closed'));
- break;
- case 'stable':
- if (!!_this.pc.remoteDescription) {
- _this.pc.addIceCandidate(iceCandidate).then(function () { return resolve(); }).catch(function (error) { return reject(error); });
- }
- break;
- default:
- _this.iceCandidateList.push(iceCandidate);
- resolve();
- }
- });
- };
- WebRtcPeer.prototype.streamStop = function (stream) {
- stream.getTracks().forEach(function (track) {
- track.stop();
- stream.removeTrack(track);
- });
- };
- return WebRtcPeer;
-}());
-exports.WebRtcPeer = WebRtcPeer;
-var WebRtcPeerRecvonly = (function (_super) {
- __extends(WebRtcPeerRecvonly, _super);
- function WebRtcPeerRecvonly(configuration) {
- var _this = this;
- configuration.mode = 'recvonly';
- _this = _super.call(this, configuration) || this;
- return _this;
- }
- return WebRtcPeerRecvonly;
-}(WebRtcPeer));
-exports.WebRtcPeerRecvonly = WebRtcPeerRecvonly;
-var WebRtcPeerSendonly = (function (_super) {
- __extends(WebRtcPeerSendonly, _super);
- function WebRtcPeerSendonly(configuration) {
- var _this = this;
- configuration.mode = 'sendonly';
- _this = _super.call(this, configuration) || this;
- return _this;
- }
- return WebRtcPeerSendonly;
-}(WebRtcPeer));
-exports.WebRtcPeerSendonly = WebRtcPeerSendonly;
-var WebRtcPeerSendrecv = (function (_super) {
- __extends(WebRtcPeerSendrecv, _super);
- function WebRtcPeerSendrecv(configuration) {
- var _this = this;
- configuration.mode = 'sendrecv';
- _this = _super.call(this, configuration) || this;
- return _this;
- }
- return WebRtcPeerSendrecv;
-}(WebRtcPeer));
-exports.WebRtcPeerSendrecv = WebRtcPeerSendrecv;
-
-},{"freeice":2,"platform":8,"uuid":9}],50:[function(require,module,exports){
-"use strict";
-Object.defineProperty(exports, "__esModule", { value: true });
-var platform = require("platform");
-var WebRtcStats = (function () {
- function WebRtcStats(stream) {
- this.stream = stream;
- this.webRtcStatsEnabled = false;
- this.statsInterval = 1;
- this.stats = {
- inbound: {
- audio: {
- bytesReceived: 0,
- packetsReceived: 0,
- packetsLost: 0
- },
- video: {
- bytesReceived: 0,
- packetsReceived: 0,
- packetsLost: 0,
- framesDecoded: 0,
- nackCount: 0
- }
- },
- outbound: {
- audio: {
- bytesSent: 0,
- packetsSent: 0,
- },
- video: {
- bytesSent: 0,
- packetsSent: 0,
- framesEncoded: 0,
- nackCount: 0
- }
- }
- };
- }
- WebRtcStats.prototype.isEnabled = function () {
- return this.webRtcStatsEnabled;
- };
- WebRtcStats.prototype.initWebRtcStats = function () {
- var _this = this;
- var elastestInstrumentation = localStorage.getItem('elastest-instrumentation');
- if (elastestInstrumentation) {
- console.warn('WebRtc stats enabled for stream ' + this.stream.streamId + ' of connection ' + this.stream.connection.connectionId);
- this.webRtcStatsEnabled = true;
- var instrumentation_1 = JSON.parse(elastestInstrumentation);
- this.statsInterval = instrumentation_1.webrtc.interval;
- console.warn('localStorage item: ' + JSON.stringify(instrumentation_1));
- this.webRtcStatsIntervalId = setInterval(function () {
- _this.sendStatsToHttpEndpoint(instrumentation_1);
- }, this.statsInterval * 1000);
- return;
- }
- console.debug('WebRtc stats not enabled');
- };
- WebRtcStats.prototype.stopWebRtcStats = function () {
- if (this.webRtcStatsEnabled) {
- clearInterval(this.webRtcStatsIntervalId);
- console.warn('WebRtc stats stopped for disposed stream ' + this.stream.streamId + ' of connection ' + this.stream.connection.connectionId);
- }
- };
- WebRtcStats.prototype.getSelectedIceCandidateInfo = function () {
- var _this = this;
- return new Promise(function (resolve, reject) {
- _this.getStatsAgnostic(_this.stream.getRTCPeerConnection(), function (stats) {
- if ((platform.name.indexOf('Chrome') !== -1) || (platform.name.indexOf('Opera') !== -1)) {
- var localCandidateId = void 0, remoteCandidateId = void 0, googCandidatePair = void 0;
- var localCandidates = {};
- var remoteCandidates = {};
- for (var key in stats) {
- var stat = stats[key];
- if (stat.type === 'localcandidate') {
- localCandidates[stat.id] = stat;
- }
- else if (stat.type === 'remotecandidate') {
- remoteCandidates[stat.id] = stat;
- }
- else if (stat.type === 'googCandidatePair' && (stat.googActiveConnection === 'true')) {
- googCandidatePair = stat;
- localCandidateId = stat.localCandidateId;
- remoteCandidateId = stat.remoteCandidateId;
- }
- }
- var finalLocalCandidate_1 = localCandidates[localCandidateId];
- if (!!finalLocalCandidate_1) {
- var candList = _this.stream.getLocalIceCandidateList();
- var cand = candList.filter(function (c) {
- return (!!c.candidate &&
- c.candidate.indexOf(finalLocalCandidate_1.ipAddress) >= 0 &&
- c.candidate.indexOf(finalLocalCandidate_1.portNumber) >= 0 &&
- c.candidate.indexOf(finalLocalCandidate_1.priority) >= 0);
- });
- finalLocalCandidate_1.raw = !!cand[0] ? cand[0].candidate : 'ERROR: Cannot find local candidate in list of sent ICE candidates';
- }
- else {
- finalLocalCandidate_1 = 'ERROR: No active local ICE candidate. Probably ICE-TCP is being used';
- }
- var finalRemoteCandidate_1 = remoteCandidates[remoteCandidateId];
- if (!!finalRemoteCandidate_1) {
- var candList = _this.stream.getRemoteIceCandidateList();
- var cand = candList.filter(function (c) {
- return (!!c.candidate &&
- c.candidate.indexOf(finalRemoteCandidate_1.ipAddress) >= 0 &&
- c.candidate.indexOf(finalRemoteCandidate_1.portNumber) >= 0 &&
- c.candidate.indexOf(finalRemoteCandidate_1.priority) >= 0);
- });
- finalRemoteCandidate_1.raw = !!cand[0] ? cand[0].candidate : 'ERROR: Cannot find remote candidate in list of received ICE candidates';
- }
- else {
- finalRemoteCandidate_1 = 'ERROR: No active remote ICE candidate. Probably ICE-TCP is being used';
- }
- resolve({
- googCandidatePair: googCandidatePair,
- localCandidate: finalLocalCandidate_1,
- remoteCandidate: finalRemoteCandidate_1
- });
- }
- else {
- reject('Selected ICE candidate info only available for Chrome');
- }
- }, function (error) {
- reject(error);
- });
- });
- };
- WebRtcStats.prototype.sendStatsToHttpEndpoint = function (instrumentation) {
- var _this = this;
- var sendPost = function (json) {
- var http = new XMLHttpRequest();
- var url = instrumentation.webrtc.httpEndpoint;
- http.open('POST', url, true);
- http.setRequestHeader('Content-type', 'application/json');
- http.onreadystatechange = function () {
- if (http.readyState === 4 && http.status === 200) {
- console.log('WebRtc stats successfully sent to ' + url + ' for stream ' + _this.stream.streamId + ' of connection ' + _this.stream.connection.connectionId);
- }
- };
- http.send(json);
- };
- var f = function (stats) {
- if (platform.name.indexOf('Firefox') !== -1) {
- stats.forEach(function (stat) {
- var json = {};
- if ((stat.type === 'inbound-rtp') &&
- (stat.nackCount !== null &&
- stat.isRemote === false &&
- stat.id.startsWith('inbound') &&
- stat.remoteId.startsWith('inbound'))) {
- var metricId = 'webrtc_inbound_' + stat.mediaType + '_' + stat.ssrc;
- var jit = stat.jitter * 1000;
- var metrics = {
- bytesReceived: (stat.bytesReceived - _this.stats.inbound[stat.mediaType].bytesReceived) / _this.statsInterval,
- jitter: jit,
- packetsReceived: (stat.packetsReceived - _this.stats.inbound[stat.mediaType].packetsReceived) / _this.statsInterval,
- packetsLost: (stat.packetsLost - _this.stats.inbound[stat.mediaType].packetsLost) / _this.statsInterval
- };
- var units = {
- bytesReceived: 'bytes',
- jitter: 'ms',
- packetsReceived: 'packets',
- packetsLost: 'packets'
- };
- if (stat.mediaType === 'video') {
- metrics['framesDecoded'] = (stat.framesDecoded - _this.stats.inbound.video.framesDecoded) / _this.statsInterval;
- metrics['nackCount'] = (stat.nackCount - _this.stats.inbound.video.nackCount) / _this.statsInterval;
- units['framesDecoded'] = 'frames';
- units['nackCount'] = 'packets';
- _this.stats.inbound.video.framesDecoded = stat.framesDecoded;
- _this.stats.inbound.video.nackCount = stat.nackCount;
- }
- _this.stats.inbound[stat.mediaType].bytesReceived = stat.bytesReceived;
- _this.stats.inbound[stat.mediaType].packetsReceived = stat.packetsReceived;
- _this.stats.inbound[stat.mediaType].packetsLost = stat.packetsLost;
- json = {
- '@timestamp': new Date(stat.timestamp).toISOString(),
- 'exec': instrumentation.exec,
- 'component': instrumentation.component,
- 'stream': 'webRtc',
- 'type': metricId,
- 'stream_type': 'composed_metrics',
- 'units': units
- };
- json[metricId] = metrics;
- sendPost(JSON.stringify(json));
- }
- else if ((stat.type === 'outbound-rtp') &&
- (stat.isRemote === false &&
- stat.id.toLowerCase().includes('outbound'))) {
- var metricId = 'webrtc_outbound_' + stat.mediaType + '_' + stat.ssrc;
- var metrics = {
- bytesSent: (stat.bytesSent - _this.stats.outbound[stat.mediaType].bytesSent) / _this.statsInterval,
- packetsSent: (stat.packetsSent - _this.stats.outbound[stat.mediaType].packetsSent) / _this.statsInterval
- };
- var units = {
- bytesSent: 'bytes',
- packetsSent: 'packets'
- };
- if (stat.mediaType === 'video') {
- metrics['framesEncoded'] = (stat.framesEncoded - _this.stats.outbound.video.framesEncoded) / _this.statsInterval;
- units['framesEncoded'] = 'frames';
- _this.stats.outbound.video.framesEncoded = stat.framesEncoded;
- }
- _this.stats.outbound[stat.mediaType].bytesSent = stat.bytesSent;
- _this.stats.outbound[stat.mediaType].packetsSent = stat.packetsSent;
- json = {
- '@timestamp': new Date(stat.timestamp).toISOString(),
- 'exec': instrumentation.exec,
- 'component': instrumentation.component,
- 'stream': 'webRtc',
- 'type': metricId,
- 'stream_type': 'composed_metrics',
- 'units': units
- };
- json[metricId] = metrics;
- sendPost(JSON.stringify(json));
- }
- });
- }
- else if ((platform.name.indexOf('Chrome') !== -1) || (platform.name.indexOf('Opera') !== -1)) {
- for (var _i = 0, _a = Object.keys(stats); _i < _a.length; _i++) {
- var key = _a[_i];
- var stat = stats[key];
- if (stat.type === 'ssrc') {
- var json = {};
- if ('bytesReceived' in stat && ((stat.mediaType === 'audio' && 'audioOutputLevel' in stat) ||
- (stat.mediaType === 'video' && 'qpSum' in stat))) {
- var metricId = 'webrtc_inbound_' + stat.mediaType + '_' + stat.ssrc;
- var metrics = {
- bytesReceived: (stat.bytesReceived - _this.stats.inbound[stat.mediaType].bytesReceived) / _this.statsInterval,
- jitter: stat.googJitterBufferMs,
- packetsReceived: (stat.packetsReceived - _this.stats.inbound[stat.mediaType].packetsReceived) / _this.statsInterval,
- packetsLost: (stat.packetsLost - _this.stats.inbound[stat.mediaType].packetsLost) / _this.statsInterval
- };
- var units = {
- bytesReceived: 'bytes',
- jitter: 'ms',
- packetsReceived: 'packets',
- packetsLost: 'packets'
- };
- if (stat.mediaType === 'video') {
- metrics['framesDecoded'] = (stat.framesDecoded - _this.stats.inbound.video.framesDecoded) / _this.statsInterval;
- metrics['nackCount'] = (stat.googNacksSent - _this.stats.inbound.video.nackCount) / _this.statsInterval;
- units['framesDecoded'] = 'frames';
- units['nackCount'] = 'packets';
- _this.stats.inbound.video.framesDecoded = stat.framesDecoded;
- _this.stats.inbound.video.nackCount = stat.googNacksSent;
- }
- _this.stats.inbound[stat.mediaType].bytesReceived = stat.bytesReceived;
- _this.stats.inbound[stat.mediaType].packetsReceived = stat.packetsReceived;
- _this.stats.inbound[stat.mediaType].packetsLost = stat.packetsLost;
- json = {
- '@timestamp': new Date(stat.timestamp).toISOString(),
- 'exec': instrumentation.exec,
- 'component': instrumentation.component,
- 'stream': 'webRtc',
- 'type': metricId,
- 'stream_type': 'composed_metrics',
- 'units': units
- };
- json[metricId] = metrics;
- sendPost(JSON.stringify(json));
- }
- else if ('bytesSent' in stat) {
- var metricId = 'webrtc_outbound_' + stat.mediaType + '_' + stat.ssrc;
- var metrics = {
- bytesSent: (stat.bytesSent - _this.stats.outbound[stat.mediaType].bytesSent) / _this.statsInterval,
- packetsSent: (stat.packetsSent - _this.stats.outbound[stat.mediaType].packetsSent) / _this.statsInterval
- };
- var units = {
- bytesSent: 'bytes',
- packetsSent: 'packets'
- };
- if (stat.mediaType === 'video') {
- metrics['framesEncoded'] = (stat.framesEncoded - _this.stats.outbound.video.framesEncoded) / _this.statsInterval;
- units['framesEncoded'] = 'frames';
- _this.stats.outbound.video.framesEncoded = stat.framesEncoded;
- }
- _this.stats.outbound[stat.mediaType].bytesSent = stat.bytesSent;
- _this.stats.outbound[stat.mediaType].packetsSent = stat.packetsSent;
- json = {
- '@timestamp': new Date(stat.timestamp).toISOString(),
- 'exec': instrumentation.exec,
- 'component': instrumentation.component,
- 'stream': 'webRtc',
- 'type': metricId,
- 'stream_type': 'composed_metrics',
- 'units': units
- };
- json[metricId] = metrics;
- sendPost(JSON.stringify(json));
- }
- }
- }
- }
- };
- this.getStatsAgnostic(this.stream.getRTCPeerConnection(), f, function (error) { console.log(error); });
- };
- WebRtcStats.prototype.standardizeReport = function (response) {
- console.log(response);
- var standardReport = {};
- if (platform.name.indexOf('Firefox') !== -1) {
- Object.keys(response).forEach(function (key) {
- console.log(response[key]);
- });
- return response;
- }
- response.result().forEach(function (report) {
- var standardStats = {
- id: report.id,
- timestamp: report.timestamp,
- type: report.type
- };
- report.names().forEach(function (name) {
- standardStats[name] = report.stat(name);
- });
- standardReport[standardStats.id] = standardStats;
- });
- return standardReport;
- };
- WebRtcStats.prototype.getStatsAgnostic = function (pc, successCb, failureCb) {
- var _this = this;
- if (platform.name.indexOf('Firefox') !== -1) {
- return pc.getStats(null).then(function (response) {
- var report = _this.standardizeReport(response);
- successCb(report);
- }).catch(failureCb);
- }
- else if ((platform.name.indexOf('Chrome') !== -1) || (platform.name.indexOf('Opera') !== -1)) {
- return pc.getStats(function (response) {
- var report = _this.standardizeReport(response);
- successCb(report);
- }, null, failureCb);
- }
- };
- return WebRtcStats;
-}());
-exports.WebRtcStats = WebRtcStats;
-
-},{"platform":8}]},{},[16])
-//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL25vZGVfbW9kdWxlcy9icm93c2VyLXBhY2svX3ByZWx1ZGUuanMiLCIuLi9ub2RlX21vZHVsZXMvZXZlbnRzL2V2ZW50cy5qcyIsIi4uL25vZGVfbW9kdWxlcy9mcmVlaWNlL2luZGV4LmpzIiwiLi4vbm9kZV9tb2R1bGVzL2ZyZWVpY2Uvc3R1bi5qc29uIiwiLi4vbm9kZV9tb2R1bGVzL2ZyZWVpY2UvdHVybi5qc29uIiwiLi4vbm9kZV9tb2R1bGVzL2hhcmsvaGFyay5qcyIsIi4uL25vZGVfbW9kdWxlcy9pbmhlcml0cy9pbmhlcml0c19icm93c2VyLmpzIiwiLi4vbm9kZV9tb2R1bGVzL25vcm1hbGljZS9pbmRleC5qcyIsIi4uL25vZGVfbW9kdWxlcy9wbGF0Zm9ybS9wbGF0Zm9ybS5qcyIsIi4uL25vZGVfbW9kdWxlcy91dWlkL2luZGV4LmpzIiwiLi4vbm9kZV9tb2R1bGVzL3V1aWQvbGliL2J5dGVzVG9VdWlkLmpzIiwiLi4vbm9kZV9tb2R1bGVzL3V1aWQvbGliL3JuZy1icm93c2VyLmpzIiwiLi4vbm9kZV9tb2R1bGVzL3V1aWQvdjEuanMiLCIuLi9ub2RlX21vZHVsZXMvdXVpZC92NC5qcyIsIi4uL25vZGVfbW9kdWxlcy93aWxkZW1pdHRlci93aWxkZW1pdHRlci5qcyIsIi4uL25vZGVfbW9kdWxlcy93b2xmeTg3LWV2ZW50ZW1pdHRlci9FdmVudEVtaXR0ZXIuanMiLCJNYWluLnRzIiwiT3BlblZpZHUvQ29ubmVjdGlvbi50cyIsIk9wZW5WaWR1L0xvY2FsUmVjb3JkZXIudHMiLCJPcGVuVmlkdS9PcGVuVmlkdS50cyIsIk9wZW5WaWR1L1B1Ymxpc2hlci50cyIsIk9wZW5WaWR1L1Nlc3Npb24udHMiLCJPcGVuVmlkdS9TdHJlYW0udHMiLCJPcGVuVmlkdS9TdHJlYW1NYW5hZ2VyLnRzIiwiT3BlblZpZHUvU3Vic2NyaWJlci50cyIsIk9wZW5WaWR1SW50ZXJuYWwvRW51bXMvTG9jYWxSZWNvcmRlclN0YXRlLnRzIiwiT3BlblZpZHVJbnRlcm5hbC9FbnVtcy9PcGVuVmlkdUVycm9yLnRzIiwiT3BlblZpZHVJbnRlcm5hbC9FbnVtcy9WaWRlb0luc2VydE1vZGUudHMiLCJPcGVuVmlkdUludGVybmFsL0V2ZW50cy9Db25uZWN0aW9uRXZlbnQudHMiLCJPcGVuVmlkdUludGVybmFsL0V2ZW50cy9FdmVudC50cyIsIk9wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1B1Ymxpc2hlclNwZWFraW5nRXZlbnQudHMiLCJPcGVuVmlkdUludGVybmFsL0V2ZW50cy9SZWNvcmRpbmdFdmVudC50cyIsIk9wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1Nlc3Npb25EaXNjb25uZWN0ZWRFdmVudC50cyIsIk9wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1NpZ25hbEV2ZW50LnRzIiwiT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvU3RyZWFtRXZlbnQudHMiLCJPcGVuVmlkdUludGVybmFsL0V2ZW50cy9TdHJlYW1NYW5hZ2VyRXZlbnQudHMiLCJPcGVuVmlkdUludGVybmFsL0V2ZW50cy9TdHJlYW1Qcm9wZXJ0eUNoYW5nZWRFdmVudC50cyIsIk9wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1ZpZGVvRWxlbWVudEV2ZW50LnRzIiwiT3BlblZpZHVJbnRlcm5hbC9LdXJlbnRvVXRpbHMva3VyZW50by1qc29ucnBjL01hcHBlci5qcyIsIk9wZW5WaWR1SW50ZXJuYWwvS3VyZW50b1V0aWxzL2t1cmVudG8tanNvbnJwYy9jbGllbnRzL2luZGV4LmpzIiwiT3BlblZpZHVJbnRlcm5hbC9LdXJlbnRvVXRpbHMva3VyZW50by1qc29ucnBjL2NsaWVudHMvanNvbnJwY2NsaWVudC5qcyIsIk9wZW5WaWR1SW50ZXJuYWwvS3VyZW50b1V0aWxzL2t1cmVudG8tanNvbnJwYy9jbGllbnRzL3RyYW5zcG9ydHMvaW5kZXguanMiLCJPcGVuVmlkdUludGVybmFsL0t1cmVudG9VdGlscy9rdXJlbnRvLWpzb25ycGMvY2xpZW50cy90cmFuc3BvcnRzL3dlYlNvY2tldFdpdGhSZWNvbm5lY3Rpb24uanMiLCJPcGVuVmlkdUludGVybmFsL0t1cmVudG9VdGlscy9rdXJlbnRvLWpzb25ycGMvaW5kZXguanMiLCJPcGVuVmlkdUludGVybmFsL0t1cmVudG9VdGlscy9rdXJlbnRvLWpzb25ycGMvcGFja2Vycy9Kc29uUlBDLmpzIiwiT3BlblZpZHVJbnRlcm5hbC9LdXJlbnRvVXRpbHMva3VyZW50by1qc29ucnBjL3BhY2tlcnMvWG1sUlBDLmpzIiwiT3BlblZpZHVJbnRlcm5hbC9LdXJlbnRvVXRpbHMva3VyZW50by1qc29ucnBjL3BhY2tlcnMvaW5kZXguanMiLCJPcGVuVmlkdUludGVybmFsL1NjcmVlblNoYXJpbmcvU2NyZWVuLUNhcHR1cmluZy1BdXRvLmpzIiwiT3BlblZpZHVJbnRlcm5hbC9TY3JlZW5TaGFyaW5nL1NjcmVlbi1DYXB0dXJpbmcuanMiLCJPcGVuVmlkdUludGVybmFsL1dlYlJ0Y1BlZXIvV2ViUnRjUGVlci50cyIsIk9wZW5WaWR1SW50ZXJuYWwvV2ViUnRjU3RhdHMvV2ViUnRjU3RhdHMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7QUNBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzNnQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDekdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDaEJBO0FBQ0E7O0FDREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2xKQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdkJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUM1REE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7O0FDanNDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDUkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDeEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbENBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDN0dBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM3QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDekpBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7O0FDdGVBLGdEQUErQztBQUUvQyxJQUFJLE1BQU0s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O1FBQWpELGlCQWNDO1FBYkcsSUFBSSxRQUFRLENBQUMsSUFBSyxDQUFDLE9BQU8sQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLENBQUMsRUFBRTtZQUUxQyxPQUFPLEVBQUUsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLENBQUMsSUFBSSxDQUFDLFVBQUEsUUFBUTtnQkFDbEMsSUFBTSxNQUFNLEdBQUcsS0FBSSxDQUFDLGlCQUFpQixDQUFDLFFBQVEsQ0FBQyxDQUFDO2dCQUNoRCxTQUFTLENBQUMsTUFBTSxDQUFDLENBQUM7WUFDdEIsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLFNBQVMsQ0FBQyxDQUFDO1NBQ3ZCO2FBQU0sSUFBSSxDQUFDLFFBQVEsQ0FBQyxJQUFLLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSyxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxFQUFFO1lBRTlGLE9BQU8sRUFBRSxDQUFDLFFBQVEsQ0FBQyxVQUFDLFFBQVE7Z0JBQ3hCLElBQU0sTUFBTSxHQUFHLEtBQUksQ0FBQyxpQkFBaUIsQ0FBQyxRQUFRLENBQUMsQ0FBQztnQkFDaEQsU0FBUyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1lBQ3RCLENBQUMsRUFBRSxJQUFJLEVBQUUsU0FBUyxDQUFDLENBQUM7U0FDdkI7SUFDTCxDQUFDO0lBRUwsa0JBQUM7QUFBRCxDQXJZQSxBQXFZQyxJQUFBO0FBcllZLGtDQUFXIiwiZmlsZSI6ImdlbmVyYXRlZC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzQ29udGVudCI6WyIoZnVuY3Rpb24oKXtmdW5jdGlvbiByKGUsbix0KXtmdW5jdGlvbiBvKGksZil7aWYoIW5baV0pe2lmKCFlW2ldKXt2YXIgYz1cImZ1bmN0aW9uXCI9PXR5cGVvZiByZXF1aXJlJiZyZXF1aXJlO2lmKCFmJiZjKXJldHVybiBjKGksITApO2lmKHUpcmV0dXJuIHUoaSwhMCk7dmFyIGE9bmV3IEVycm9yKFwiQ2Fubm90IGZpbmQgbW9kdWxlICdcIitpK1wiJ1wiKTt0aHJvdyBhLmNvZGU9XCJNT0RVTEVfTk9UX0ZPVU5EXCIsYX12YXIgcD1uW2ldPXtleHBvcnRzOnt9fTtlW2ldWzBdLmNhbGwocC5leHBvcnRzLGZ1bmN0aW9uKHIpe3ZhciBuPWVbaV1bMV1bcl07cmV0dXJuIG8obnx8cil9LHAscC5leHBvcnRzLHIsZSxuLHQpfXJldHVybiBuW2ldLmV4cG9ydHN9Zm9yKHZhciB1PVwiZnVuY3Rpb25cIj09dHlwZW9mIHJlcXVpcmUmJnJlcXVpcmUsaT0wO2k8dC5sZW5ndGg7aSsrKW8odFtpXSk7cmV0dXJuIG99cmV0dXJuIHJ9KSgpIiwiLy8gQ29weXJpZ2h0IEpveWVudCwgSW5jLiBhbmQgb3RoZXIgTm9kZSBjb250cmlidXRvcnMuXG4vL1xuLy8gUGVybWlzc2lvbiBpcyBoZXJlYnkgZ3JhbnRlZCwgZnJlZSBvZiBjaGFyZ2UsIHRvIGFueSBwZXJzb24gb2J0YWluaW5nIGFcbi8vIGNvcHkgb2YgdGhpcyBzb2Z0d2FyZSBhbmQgYXNzb2NpYXRlZCBkb2N1bWVudGF0aW9uIGZpbGVzICh0aGVcbi8vIFwiU29mdHdhcmVcIiksIHRvIGRlYWwgaW4gdGhlIFNvZnR3YXJlIHdpdGhvdXQgcmVzdHJpY3Rpb24sIGluY2x1ZGluZ1xuLy8gd2l0aG91dCBsaW1pdGF0aW9uIHRoZSByaWdodHMgdG8gdXNlLCBjb3B5LCBtb2RpZnksIG1lcmdlLCBwdWJsaXNoLFxuLy8gZGlzdHJpYnV0ZSwgc3VibGljZW5zZSwgYW5kL29yIHNlbGwgY29waWVzIG9mIHRoZSBTb2Z0d2FyZSwgYW5kIHRvIHBlcm1pdFxuLy8gcGVyc29ucyB0byB3aG9tIHRoZSBTb2Z0d2FyZSBpcyBmdXJuaXNoZWQgdG8gZG8gc28sIHN1YmplY3QgdG8gdGhlXG4vLyBmb2xsb3dpbmcgY29uZGl0aW9uczpcbi8vXG4vLyBUaGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSBhbmQgdGhpcyBwZXJtaXNzaW9uIG5vdGljZSBzaGFsbCBiZSBpbmNsdWRlZFxuLy8gaW4gYWxsIGNvcGllcyBvciBzdWJzdGFudGlhbCBwb3J0aW9ucyBvZiB0aGUgU29mdHdhcmUuXG4vL1xuLy8gVEhFIFNPRlRXQVJFIElTIFBST1ZJREVEIFwiQVMgSVNcIiwgV0lUSE9VVCBXQVJSQU5UWSBPRiBBTlkgS0lORCwgRVhQUkVTU1xuLy8gT1IgSU1QTElFRCwgSU5DTFVESU5HIEJVVCBOT1QgTElNSVRFRCBUTyBUSEUgV0FSUkFOVElFUyBPRlxuLy8gTUVSQ0hBTlRBQklMSVRZLCBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBTkQgTk9OSU5GUklOR0VNRU5ULiBJTlxuLy8gTk8gRVZFTlQgU0hBTEwgVEhFIEFVVEhPUlMgT1IgQ09QWVJJR0hUIEhPTERFUlMgQkUgTElBQkxFIEZPUiBBTlkgQ0xBSU0sXG4vLyBEQU1BR0VTIE9SIE9USEVSIExJQUJJTElUWSwgV0hFVEhFUiBJTiBBTiBBQ1RJT04gT0YgQ09OVFJBQ1QsIFRPUlQgT1Jcbi8vIE9USEVSV0lTRSwgQVJJU0lORyBGUk9NLCBPVVQgT0YgT1IgSU4gQ09OTkVDVElPTiBXSVRIIFRIRSBTT0ZUV0FSRSBPUiBUSEVcbi8vIFVTRSBPUiBPVEhFUiBERUFMSU5HUyBJTiBUSEUgU09GVFdBUkUuXG5cbnZhciBvYmplY3RDcmVhdGUgPSBPYmplY3QuY3JlYXRlIHx8IG9iamVjdENyZWF0ZVBvbHlmaWxsXG52YXIgb2JqZWN0S2V5cyA9IE9iamVjdC5rZXlzIHx8IG9iamVjdEtleXNQb2x5ZmlsbFxudmFyIGJpbmQgPSBGdW5jdGlvbi5wcm90b3R5cGUuYmluZCB8fCBmdW5jdGlvbkJpbmRQb2x5ZmlsbFxuXG5mdW5jdGlvbiBFdmVudEVtaXR0ZXIoKSB7XG4gIGlmICghdGhpcy5fZXZlbnRzIHx8ICFPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwodGhpcywgJ19ldmVudHMnKSkge1xuICAgIHRoaXMuX2V2ZW50cyA9IG9iamVjdENyZWF0ZShudWxsKTtcbiAgICB0aGlzLl9ldmVudHNDb3VudCA9IDA7XG4gIH1cblxuICB0aGlzLl9tYXhMaXN0ZW5lcnMgPSB0aGlzLl9tYXhMaXN0ZW5lcnMgfHwgdW5kZWZpbmVkO1xufVxubW9kdWxlLmV4cG9ydHMgPSBFdmVudEVtaXR0ZXI7XG5cbi8vIEJhY2t3YXJkcy1jb21wYXQgd2l0aCBub2RlIDAuMTAueFxuRXZlbnRFbWl0dGVyLkV2ZW50RW1pdHRlciA9IEV2ZW50RW1pdHRlcjtcblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5fZXZlbnRzID0gdW5kZWZpbmVkO1xuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5fbWF4TGlzdGVuZXJzID0gdW5kZWZpbmVkO1xuXG4vLyBCeSBkZWZhdWx0IEV2ZW50RW1pdHRlcnMgd2lsbCBwcmludCBhIHdhcm5pbmcgaWYgbW9yZSB0aGFuIDEwIGxpc3RlbmVycyBhcmVcbi8vIGFkZGVkIHRvIGl0LiBUaGlzIGlzIGEgdXNlZnVsIGRlZmF1bHQgd2hpY2ggaGVscHMgZmluZGluZyBtZW1vcnkgbGVha3MuXG52YXIgZGVmYXVsdE1heExpc3RlbmVycyA9IDEwO1xuXG52YXIgaGFzRGVmaW5lUHJvcGVydHk7XG50cnkge1xuICB2YXIgbyA9IHt9O1xuICBpZiAoT2JqZWN0LmRlZmluZVByb3BlcnR5KSBPYmplY3QuZGVmaW5lUHJvcGVydHkobywgJ3gnLCB7IHZhbHVlOiAwIH0pO1xuICBoYXNEZWZpbmVQcm9wZXJ0eSA9IG8ueCA9PT0gMDtcbn0gY2F0Y2ggKGVycikgeyBoYXNEZWZpbmVQcm9wZXJ0eSA9IGZhbHNlIH1cbmlmIChoYXNEZWZpbmVQcm9wZXJ0eSkge1xuICBPYmplY3QuZGVmaW5lUHJvcGVydHkoRXZlbnRFbWl0dGVyLCAnZGVmYXVsdE1heExpc3RlbmVycycsIHtcbiAgICBlbnVtZXJhYmxlOiB0cnVlLFxuICAgIGdldDogZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4gZGVmYXVsdE1heExpc3RlbmVycztcbiAgICB9LFxuICAgIHNldDogZnVuY3Rpb24oYXJnKSB7XG4gICAgICAvLyBjaGVjayB3aGV0aGVyIHRoZSBpbnB1dCBpcyBhIHBvc2l0aXZlIG51bWJlciAod2hvc2UgdmFsdWUgaXMgemVybyBvclxuICAgICAgLy8gZ3JlYXRlciBhbmQgbm90IGEgTmFOKS5cbiAgICAgIGlmICh0eXBlb2YgYXJnICE9PSAnbnVtYmVyJyB8fCBhcmcgPCAwIHx8IGFyZyAhPT0gYXJnKVxuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdcImRlZmF1bHRNYXhMaXN0ZW5lcnNcIiBtdXN0IGJlIGEgcG9zaXRpdmUgbnVtYmVyJyk7XG4gICAgICBkZWZhdWx0TWF4TGlzdGVuZXJzID0gYXJnO1xuICAgIH1cbiAgfSk7XG59IGVsc2Uge1xuICBFdmVudEVtaXR0ZXIuZGVmYXVsdE1heExpc3RlbmVycyA9IGRlZmF1bHRNYXhMaXN0ZW5lcnM7XG59XG5cbi8vIE9idmlvdXNseSBub3QgYWxsIEVtaXR0ZXJzIHNob3VsZCBiZSBsaW1pdGVkIHRvIDEwLiBUaGlzIGZ1bmN0aW9uIGFsbG93c1xuLy8gdGhhdCB0byBiZSBpbmNyZWFzZWQuIFNldCB0byB6ZXJvIGZvciB1bmxpbWl0ZWQuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLnNldE1heExpc3RlbmVycyA9IGZ1bmN0aW9uIHNldE1heExpc3RlbmVycyhuKSB7XG4gIGlmICh0eXBlb2YgbiAhPT0gJ251bWJlcicgfHwgbiA8IDAgfHwgaXNOYU4obikpXG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcignXCJuXCIgYXJndW1lbnQgbXVzdCBiZSBhIHBvc2l0aXZlIG51bWJlcicpO1xuICB0aGlzLl9tYXhMaXN0ZW5lcnMgPSBuO1xuICByZXR1cm4gdGhpcztcbn07XG5cbmZ1bmN0aW9uICRnZXRNYXhMaXN0ZW5lcnModGhhdCkge1xuICBpZiAodGhhdC5fbWF4TGlzdGVuZXJzID09PSB1bmRlZmluZWQpXG4gICAgcmV0dXJuIEV2ZW50RW1pdHRlci5kZWZhdWx0TWF4TGlzdGVuZXJzO1xuICByZXR1cm4gdGhhdC5fbWF4TGlzdGVuZXJzO1xufVxuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLmdldE1heExpc3RlbmVycyA9IGZ1bmN0aW9uIGdldE1heExpc3RlbmVycygpIHtcbiAgcmV0dXJuICRnZXRNYXhMaXN0ZW5lcnModGhpcyk7XG59O1xuXG4vLyBUaGVzZSBzdGFuZGFsb25lIGVtaXQqIGZ1bmN0aW9ucyBhcmUgdXNlZCB0byBvcHRpbWl6ZSBjYWxsaW5nIG9mIGV2ZW50XG4vLyBoYW5kbGVycyBmb3IgZmFzdCBjYXNlcyBiZWNhdXNlIGVtaXQoKSBpdHNlbGYgb2Z0ZW4gaGFzIGEgdmFyaWFibGUgbnVtYmVyIG9mXG4vLyBhcmd1bWVudHMgYW5kIGNhbiBiZSBkZW9wdGltaXplZCBiZWNhdXNlIG9mIHRoYXQuIFRoZXNlIGZ1bmN0aW9ucyBhbHdheXMgaGF2ZVxuLy8gdGhlIHNhbWUgbnVtYmVyIG9mIGFyZ3VtZW50cyBhbmQgdGh1cyBkbyBub3QgZ2V0IGRlb3B0aW1pemVkLCBzbyB0aGUgY29kZVxuLy8gaW5zaWRlIHRoZW0gY2FuIGV4ZWN1dGUgZmFzdGVyLlxuZnVuY3Rpb24gZW1pdE5vbmUoaGFuZGxlciwgaXNGbiwgc2VsZikge1xuICBpZiAoaXNGbilcbiAgICBoYW5kbGVyLmNhbGwoc2VsZik7XG4gIGVsc2Uge1xuICAgIHZhciBsZW4gPSBoYW5kbGVyLmxlbmd0aDtcbiAgICB2YXIgbGlzdGVuZXJzID0gYXJyYXlDbG9uZShoYW5kbGVyLCBsZW4pO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuOyArK2kpXG4gICAgICBsaXN0ZW5lcnNbaV0uY2FsbChzZWxmKTtcbiAgfVxufVxuZnVuY3Rpb24gZW1pdE9uZShoYW5kbGVyLCBpc0ZuLCBzZWxmLCBhcmcxKSB7XG4gIGlmIChpc0ZuKVxuICAgIGhhbmRsZXIuY2FsbChzZWxmLCBhcmcxKTtcbiAgZWxzZSB7XG4gICAgdmFyIGxlbiA9IGhhbmRsZXIubGVuZ3RoO1xuICAgIHZhciBsaXN0ZW5lcnMgPSBhcnJheUNsb25lKGhhbmRsZXIsIGxlbik7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW47ICsraSlcbiAgICAgIGxpc3RlbmVyc1tpXS5jYWxsKHNlbGYsIGFyZzEpO1xuICB9XG59XG5mdW5jdGlvbiBlbWl0VHdvKGhhbmRsZXIsIGlzRm4sIHNlbGYsIGFyZzEsIGFyZzIpIHtcbiAgaWYgKGlzRm4pXG4gICAgaGFuZGxlci5jYWxsKHNlbGYsIGFyZzEsIGFyZzIpO1xuICBlbHNlIHtcbiAgICB2YXIgbGVuID0gaGFuZGxlci5sZW5ndGg7XG4gICAgdmFyIGxpc3RlbmVycyA9IGFycmF5Q2xvbmUoaGFuZGxlciwgbGVuKTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgKytpKVxuICAgICAgbGlzdGVuZXJzW2ldLmNhbGwoc2VsZiwgYXJnMSwgYXJnMik7XG4gIH1cbn1cbmZ1bmN0aW9uIGVtaXRUaHJlZShoYW5kbGVyLCBpc0ZuLCBzZWxmLCBhcmcxLCBhcmcyLCBhcmczKSB7XG4gIGlmIChpc0ZuKVxuICAgIGhhbmRsZXIuY2FsbChzZWxmLCBhcmcxLCBhcmcyLCBhcmczKTtcbiAgZWxzZSB7XG4gICAgdmFyIGxlbiA9IGhhbmRsZXIubGVuZ3RoO1xuICAgIHZhciBsaXN0ZW5lcnMgPSBhcnJheUNsb25lKGhhbmRsZXIsIGxlbik7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW47ICsraSlcbiAgICAgIGxpc3RlbmVyc1tpXS5jYWxsKHNlbGYsIGFyZzEsIGFyZzIsIGFyZzMpO1xuICB9XG59XG5cbmZ1bmN0aW9uIGVtaXRNYW55KGhhbmRsZXIsIGlzRm4sIHNlbGYsIGFyZ3MpIHtcbiAgaWYgKGlzRm4pXG4gICAgaGFuZGxlci5hcHBseShzZWxmLCBhcmdzKTtcbiAgZWxzZSB7XG4gICAgdmFyIGxlbiA9IGhhbmRsZXIubGVuZ3RoO1xuICAgIHZhciBsaXN0ZW5lcnMgPSBhcnJheUNsb25lKGhhbmRsZXIsIGxlbik7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW47ICsraSlcbiAgICAgIGxpc3RlbmVyc1tpXS5hcHBseShzZWxmLCBhcmdzKTtcbiAgfVxufVxuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLmVtaXQgPSBmdW5jdGlvbiBlbWl0KHR5cGUpIHtcbiAgdmFyIGVyLCBoYW5kbGVyLCBsZW4sIGFyZ3MsIGksIGV2ZW50cztcbiAgdmFyIGRvRXJyb3IgPSAodHlwZSA9PT0gJ2Vycm9yJyk7XG5cbiAgZXZlbnRzID0gdGhpcy5fZXZlbnRzO1xuICBpZiAoZXZlbnRzKVxuICAgIGRvRXJyb3IgPSAoZG9FcnJvciAmJiBldmVudHMuZXJyb3IgPT0gbnVsbCk7XG4gIGVsc2UgaWYgKCFkb0Vycm9yKVxuICAgIHJldHVybiBmYWxzZTtcblxuICAvLyBJZiB0aGVyZSBpcyBubyAnZXJyb3InIGV2ZW50IGxpc3RlbmVyIHRoZW4gdGhyb3cuXG4gIGlmIChkb0Vycm9yKSB7XG4gICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPiAxKVxuICAgICAgZXIgPSBhcmd1bWVudHNbMV07XG4gICAgaWYgKGVyIGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICAgIHRocm93IGVyOyAvLyBVbmhhbmRsZWQgJ2Vycm9yJyBldmVudFxuICAgIH0gZWxzZSB7XG4gICAgICAvLyBBdCBsZWFzdCBnaXZlIHNvbWUga2luZCBvZiBjb250ZXh0IHRvIHRoZSB1c2VyXG4gICAgICB2YXIgZXJyID0gbmV3IEVycm9yKCdVbmhhbmRsZWQgXCJlcnJvclwiIGV2ZW50LiAoJyArIGVyICsgJyknKTtcbiAgICAgIGVyci5jb250ZXh0ID0gZXI7XG4gICAgICB0aHJvdyBlcnI7XG4gICAgfVxuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIGhhbmRsZXIgPSBldmVudHNbdHlwZV07XG5cbiAgaWYgKCFoYW5kbGVyKVxuICAgIHJldHVybiBmYWxzZTtcblxuICB2YXIgaXNGbiA9IHR5cGVvZiBoYW5kbGVyID09PSAnZnVuY3Rpb24nO1xuICBsZW4gPSBhcmd1bWVudHMubGVuZ3RoO1xuICBzd2l0Y2ggKGxlbikge1xuICAgICAgLy8gZmFzdCBjYXNlc1xuICAgIGNhc2UgMTpcbiAgICAgIGVtaXROb25lKGhhbmRsZXIsIGlzRm4sIHRoaXMpO1xuICAgICAgYnJlYWs7XG4gICAgY2FzZSAyOlxuICAgICAgZW1pdE9uZShoYW5kbGVyLCBpc0ZuLCB0aGlzLCBhcmd1bWVudHNbMV0pO1xuICAgICAgYnJlYWs7XG4gICAgY2FzZSAzOlxuICAgICAgZW1pdFR3byhoYW5kbGVyLCBpc0ZuLCB0aGlzLCBhcmd1bWVudHNbMV0sIGFyZ3VtZW50c1syXSk7XG4gICAgICBicmVhaztcbiAgICBjYXNlIDQ6XG4gICAgICBlbWl0VGhyZWUoaGFuZGxlciwgaXNGbiwgdGhpcywgYXJndW1lbnRzWzFdLCBhcmd1bWVudHNbMl0sIGFyZ3VtZW50c1szXSk7XG4gICAgICBicmVhaztcbiAgICAgIC8vIHNsb3dlclxuICAgIGRlZmF1bHQ6XG4gICAgICBhcmdzID0gbmV3IEFycmF5KGxlbiAtIDEpO1xuICAgICAgZm9yIChpID0gMTsgaSA8IGxlbjsgaSsrKVxuICAgICAgICBhcmdzW2kgLSAxXSA9IGFyZ3VtZW50c1tpXTtcbiAgICAgIGVtaXRNYW55KGhhbmRsZXIsIGlzRm4sIHRoaXMsIGFyZ3MpO1xuICB9XG5cbiAgcmV0dXJuIHRydWU7XG59O1xuXG5mdW5jdGlvbiBfYWRkTGlzdGVuZXIodGFyZ2V0LCB0eXBlLCBsaXN0ZW5lciwgcHJlcGVuZCkge1xuICB2YXIgbTtcbiAgdmFyIGV2ZW50cztcbiAgdmFyIGV4aXN0aW5nO1xuXG4gIGlmICh0eXBlb2YgbGlzdGVuZXIgIT09ICdmdW5jdGlvbicpXG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcignXCJsaXN0ZW5lclwiIGFyZ3VtZW50IG11c3QgYmUgYSBmdW5jdGlvbicpO1xuXG4gIGV2ZW50cyA9IHRhcmdldC5fZXZlbnRzO1xuICBpZiAoIWV2ZW50cykge1xuICAgIGV2ZW50cyA9IHRhcmdldC5fZXZlbnRzID0gb2JqZWN0Q3JlYXRlKG51bGwpO1xuICAgIHRhcmdldC5fZXZlbnRzQ291bnQgPSAwO1xuICB9IGVsc2Uge1xuICAgIC8vIFRvIGF2b2lkIHJlY3Vyc2lvbiBpbiB0aGUgY2FzZSB0aGF0IHR5cGUgPT09IFwibmV3TGlzdGVuZXJcIiEgQmVmb3JlXG4gICAgLy8gYWRkaW5nIGl0IHRvIHRoZSBsaXN0ZW5lcnMsIGZpcnN0IGVtaXQgXCJuZXdMaXN0ZW5lclwiLlxuICAgIGlmIChldmVudHMubmV3TGlzdGVuZXIpIHtcbiAgICAgIHRhcmdldC5lbWl0KCduZXdMaXN0ZW5lcicsIHR5cGUsXG4gICAgICAgICAgbGlzdGVuZXIubGlzdGVuZXIgPyBsaXN0ZW5lci5saXN0ZW5lciA6IGxpc3RlbmVyKTtcblxuICAgICAgLy8gUmUtYXNzaWduIGBldmVudHNgIGJlY2F1c2UgYSBuZXdMaXN0ZW5lciBoYW5kbGVyIGNvdWxkIGhhdmUgY2F1c2VkIHRoZVxuICAgICAgLy8gdGhpcy5fZXZlbnRzIHRvIGJlIGFzc2lnbmVkIHRvIGEgbmV3IG9iamVjdFxuICAgICAgZXZlbnRzID0gdGFyZ2V0Ll9ldmVudHM7XG4gICAgfVxuICAgIGV4aXN0aW5nID0gZXZlbnRzW3R5cGVdO1xuICB9XG5cbiAgaWYgKCFleGlzdGluZykge1xuICAgIC8vIE9wdGltaXplIHRoZSBjYXNlIG9mIG9uZSBsaXN0ZW5lci4gRG9uJ3QgbmVlZCB0aGUgZXh0cmEgYXJyYXkgb2JqZWN0LlxuICAgIGV4aXN0aW5nID0gZXZlbnRzW3R5cGVdID0gbGlzdGVuZXI7XG4gICAgKyt0YXJnZXQuX2V2ZW50c0NvdW50O1xuICB9IGVsc2Uge1xuICAgIGlmICh0eXBlb2YgZXhpc3RpbmcgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgIC8vIEFkZGluZyB0aGUgc2Vjb25kIGVsZW1lbnQsIG5lZWQgdG8gY2hhbmdlIHRvIGFycmF5LlxuICAgICAgZXhpc3RpbmcgPSBldmVudHNbdHlwZV0gPVxuICAgICAgICAgIHByZXBlbmQgPyBbbGlzdGVuZXIsIGV4aXN0aW5nXSA6IFtleGlzdGluZywgbGlzdGVuZXJdO1xuICAgIH0gZWxzZSB7XG4gICAgICAvLyBJZiB3ZSd2ZSBhbHJlYWR5IGdvdCBhbiBhcnJheSwganVzdCBhcHBlbmQuXG4gICAgICBpZiAocHJlcGVuZCkge1xuICAgICAgICBleGlzdGluZy51bnNoaWZ0KGxpc3RlbmVyKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGV4aXN0aW5nLnB1c2gobGlzdGVuZXIpO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIENoZWNrIGZvciBsaXN0ZW5lciBsZWFrXG4gICAgaWYgKCFleGlzdGluZy53YXJuZWQpIHtcbiAgICAgIG0gPSAkZ2V0TWF4TGlzdGVuZXJzKHRhcmdldCk7XG4gICAgICBpZiAobSAmJiBtID4gMCAmJiBleGlzdGluZy5sZW5ndGggPiBtKSB7XG4gICAgICAgIGV4aXN0aW5nLndhcm5lZCA9IHRydWU7XG4gICAgICAgIHZhciB3ID0gbmV3IEVycm9yKCdQb3NzaWJsZSBFdmVudEVtaXR0ZXIgbWVtb3J5IGxlYWsgZGV0ZWN0ZWQuICcgK1xuICAgICAgICAgICAgZXhpc3RpbmcubGVuZ3RoICsgJyBcIicgKyBTdHJpbmcodHlwZSkgKyAnXCIgbGlzdGVuZXJzICcgK1xuICAgICAgICAgICAgJ2FkZGVkLiBVc2UgZW1pdHRlci5zZXRNYXhMaXN0ZW5lcnMoKSB0byAnICtcbiAgICAgICAgICAgICdpbmNyZWFzZSBsaW1pdC4nKTtcbiAgICAgICAgdy5uYW1lID0gJ01heExpc3RlbmVyc0V4Y2VlZGVkV2FybmluZyc7XG4gICAgICAgIHcuZW1pdHRlciA9IHRhcmdldDtcbiAgICAgICAgdy50eXBlID0gdHlwZTtcbiAgICAgICAgdy5jb3VudCA9IGV4aXN0aW5nLmxlbmd0aDtcbiAgICAgICAgaWYgKHR5cGVvZiBjb25zb2xlID09PSAnb2JqZWN0JyAmJiBjb25zb2xlLndhcm4pIHtcbiAgICAgICAgICBjb25zb2xlLndhcm4oJyVzOiAlcycsIHcubmFtZSwgdy5tZXNzYWdlKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHJldHVybiB0YXJnZXQ7XG59XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUuYWRkTGlzdGVuZXIgPSBmdW5jdGlvbiBhZGRMaXN0ZW5lcih0eXBlLCBsaXN0ZW5lcikge1xuICByZXR1cm4gX2FkZExpc3RlbmVyKHRoaXMsIHR5cGUsIGxpc3RlbmVyLCBmYWxzZSk7XG59O1xuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLm9uID0gRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5hZGRMaXN0ZW5lcjtcblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5wcmVwZW5kTGlzdGVuZXIgPVxuICAgIGZ1bmN0aW9uIHByZXBlbmRMaXN0ZW5lcih0eXBlLCBsaXN0ZW5lcikge1xuICAgICAgcmV0dXJuIF9hZGRMaXN0ZW5lcih0aGlzLCB0eXBlLCBsaXN0ZW5lciwgdHJ1ZSk7XG4gICAgfTtcblxuZnVuY3Rpb24gb25jZVdyYXBwZXIoKSB7XG4gIGlmICghdGhpcy5maXJlZCkge1xuICAgIHRoaXMudGFyZ2V0LnJlbW92ZUxpc3RlbmVyKHRoaXMudHlwZSwgdGhpcy53cmFwRm4pO1xuICAgIHRoaXMuZmlyZWQgPSB0cnVlO1xuICAgIHN3aXRjaCAoYXJndW1lbnRzLmxlbmd0aCkge1xuICAgICAgY2FzZSAwOlxuICAgICAgICByZXR1cm4gdGhpcy5saXN0ZW5lci5jYWxsKHRoaXMudGFyZ2V0KTtcbiAgICAgIGNhc2UgMTpcbiAgICAgICAgcmV0dXJuIHRoaXMubGlzdGVuZXIuY2FsbCh0aGlzLnRhcmdldCwgYXJndW1lbnRzWzBdKTtcbiAgICAgIGNhc2UgMjpcbiAgICAgICAgcmV0dXJuIHRoaXMubGlzdGVuZXIuY2FsbCh0aGlzLnRhcmdldCwgYXJndW1lbnRzWzBdLCBhcmd1bWVudHNbMV0pO1xuICAgICAgY2FzZSAzOlxuICAgICAgICByZXR1cm4gdGhpcy5saXN0ZW5lci5jYWxsKHRoaXMudGFyZ2V0LCBhcmd1bWVudHNbMF0sIGFyZ3VtZW50c1sxXSxcbiAgICAgICAgICAgIGFyZ3VtZW50c1syXSk7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB2YXIgYXJncyA9IG5ldyBBcnJheShhcmd1bWVudHMubGVuZ3RoKTtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBhcmdzLmxlbmd0aDsgKytpKVxuICAgICAgICAgIGFyZ3NbaV0gPSBhcmd1bWVudHNbaV07XG4gICAgICAgIHRoaXMubGlzdGVuZXIuYXBwbHkodGhpcy50YXJnZXQsIGFyZ3MpO1xuICAgIH1cbiAgfVxufVxuXG5mdW5jdGlvbiBfb25jZVdyYXAodGFyZ2V0LCB0eXBlLCBsaXN0ZW5lcikge1xuICB2YXIgc3RhdGUgPSB7IGZpcmVkOiBmYWxzZSwgd3JhcEZuOiB1bmRlZmluZWQsIHRhcmdldDogdGFyZ2V0LCB0eXBlOiB0eXBlLCBsaXN0ZW5lcjogbGlzdGVuZXIgfTtcbiAgdmFyIHdyYXBwZWQgPSBiaW5kLmNhbGwob25jZVdyYXBwZXIsIHN0YXRlKTtcbiAgd3JhcHBlZC5saXN0ZW5lciA9IGxpc3RlbmVyO1xuICBzdGF0ZS53cmFwRm4gPSB3cmFwcGVkO1xuICByZXR1cm4gd3JhcHBlZDtcbn1cblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5vbmNlID0gZnVuY3Rpb24gb25jZSh0eXBlLCBsaXN0ZW5lcikge1xuICBpZiAodHlwZW9mIGxpc3RlbmVyICE9PSAnZnVuY3Rpb24nKVxuICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ1wibGlzdGVuZXJcIiBhcmd1bWVudCBtdXN0IGJlIGEgZnVuY3Rpb24nKTtcbiAgdGhpcy5vbih0eXBlLCBfb25jZVdyYXAodGhpcywgdHlwZSwgbGlzdGVuZXIpKTtcbiAgcmV0dXJuIHRoaXM7XG59O1xuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLnByZXBlbmRPbmNlTGlzdGVuZXIgPVxuICAgIGZ1bmN0aW9uIHByZXBlbmRPbmNlTGlzdGVuZXIodHlwZSwgbGlzdGVuZXIpIHtcbiAgICAgIGlmICh0eXBlb2YgbGlzdGVuZXIgIT09ICdmdW5jdGlvbicpXG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ1wibGlzdGVuZXJcIiBhcmd1bWVudCBtdXN0IGJlIGEgZnVuY3Rpb24nKTtcbiAgICAgIHRoaXMucHJlcGVuZExpc3RlbmVyKHR5cGUsIF9vbmNlV3JhcCh0aGlzLCB0eXBlLCBsaXN0ZW5lcikpO1xuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcblxuLy8gRW1pdHMgYSAncmVtb3ZlTGlzdGVuZXInIGV2ZW50IGlmIGFuZCBvbmx5IGlmIHRoZSBsaXN0ZW5lciB3YXMgcmVtb3ZlZC5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUucmVtb3ZlTGlzdGVuZXIgPVxuICAgIGZ1bmN0aW9uIHJlbW92ZUxpc3RlbmVyKHR5cGUsIGxpc3RlbmVyKSB7XG4gICAgICB2YXIgbGlzdCwgZXZlbnRzLCBwb3NpdGlvbiwgaSwgb3JpZ2luYWxMaXN0ZW5lcjtcblxuICAgICAgaWYgKHR5cGVvZiBsaXN0ZW5lciAhPT0gJ2Z1bmN0aW9uJylcbiAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignXCJsaXN0ZW5lclwiIGFyZ3VtZW50IG11c3QgYmUgYSBmdW5jdGlvbicpO1xuXG4gICAgICBldmVudHMgPSB0aGlzLl9ldmVudHM7XG4gICAgICBpZiAoIWV2ZW50cylcbiAgICAgICAgcmV0dXJuIHRoaXM7XG5cbiAgICAgIGxpc3QgPSBldmVudHNbdHlwZV07XG4gICAgICBpZiAoIWxpc3QpXG4gICAgICAgIHJldHVybiB0aGlzO1xuXG4gICAgICBpZiAobGlzdCA9PT0gbGlzdGVuZXIgfHwgbGlzdC5saXN0ZW5lciA9PT0gbGlzdGVuZXIpIHtcbiAgICAgICAgaWYgKC0tdGhpcy5fZXZlbnRzQ291bnQgPT09IDApXG4gICAgICAgICAgdGhpcy5fZXZlbnRzID0gb2JqZWN0Q3JlYXRlKG51bGwpO1xuICAgICAgICBlbHNlIHtcbiAgICAgICAgICBkZWxldGUgZXZlbnRzW3R5cGVdO1xuICAgICAgICAgIGlmIChldmVudHMucmVtb3ZlTGlzdGVuZXIpXG4gICAgICAgICAgICB0aGlzLmVtaXQoJ3JlbW92ZUxpc3RlbmVyJywgdHlwZSwgbGlzdC5saXN0ZW5lciB8fCBsaXN0ZW5lcik7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSBpZiAodHlwZW9mIGxpc3QgIT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgcG9zaXRpb24gPSAtMTtcblxuICAgICAgICBmb3IgKGkgPSBsaXN0Lmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgICAgICAgaWYgKGxpc3RbaV0gPT09IGxpc3RlbmVyIHx8IGxpc3RbaV0ubGlzdGVuZXIgPT09IGxpc3RlbmVyKSB7XG4gICAgICAgICAgICBvcmlnaW5hbExpc3RlbmVyID0gbGlzdFtpXS5saXN0ZW5lcjtcbiAgICAgICAgICAgIHBvc2l0aW9uID0gaTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChwb3NpdGlvbiA8IDApXG4gICAgICAgICAgcmV0dXJuIHRoaXM7XG5cbiAgICAgICAgaWYgKHBvc2l0aW9uID09PSAwKVxuICAgICAgICAgIGxpc3Quc2hpZnQoKTtcbiAgICAgICAgZWxzZVxuICAgICAgICAgIHNwbGljZU9uZShsaXN0LCBwb3NpdGlvbik7XG5cbiAgICAgICAgaWYgKGxpc3QubGVuZ3RoID09PSAxKVxuICAgICAgICAgIGV2ZW50c1t0eXBlXSA9IGxpc3RbMF07XG5cbiAgICAgICAgaWYgKGV2ZW50cy5yZW1vdmVMaXN0ZW5lcilcbiAgICAgICAgICB0aGlzLmVtaXQoJ3JlbW92ZUxpc3RlbmVyJywgdHlwZSwgb3JpZ2luYWxMaXN0ZW5lciB8fCBsaXN0ZW5lcik7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUucmVtb3ZlQWxsTGlzdGVuZXJzID1cbiAgICBmdW5jdGlvbiByZW1vdmVBbGxMaXN0ZW5lcnModHlwZSkge1xuICAgICAgdmFyIGxpc3RlbmVycywgZXZlbnRzLCBpO1xuXG4gICAgICBldmVudHMgPSB0aGlzLl9ldmVudHM7XG4gICAgICBpZiAoIWV2ZW50cylcbiAgICAgICAgcmV0dXJuIHRoaXM7XG5cbiAgICAgIC8vIG5vdCBsaXN0ZW5pbmcgZm9yIHJlbW92ZUxpc3RlbmVyLCBubyBuZWVkIHRvIGVtaXRcbiAgICAgIGlmICghZXZlbnRzLnJlbW92ZUxpc3RlbmVyKSB7XG4gICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgdGhpcy5fZXZlbnRzID0gb2JqZWN0Q3JlYXRlKG51bGwpO1xuICAgICAgICAgIHRoaXMuX2V2ZW50c0NvdW50ID0gMDtcbiAgICAgICAgfSBlbHNlIGlmIChldmVudHNbdHlwZV0pIHtcbiAgICAgICAgICBpZiAoLS10aGlzLl9ldmVudHNDb3VudCA9PT0gMClcbiAgICAgICAgICAgIHRoaXMuX2V2ZW50cyA9IG9iamVjdENyZWF0ZShudWxsKTtcbiAgICAgICAgICBlbHNlXG4gICAgICAgICAgICBkZWxldGUgZXZlbnRzW3R5cGVdO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgfVxuXG4gICAgICAvLyBlbWl0IHJlbW92ZUxpc3RlbmVyIGZvciBhbGwgbGlzdGVuZXJzIG9uIGFsbCBldmVudHNcbiAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgIHZhciBrZXlzID0gb2JqZWN0S2V5cyhldmVudHMpO1xuICAgICAgICB2YXIga2V5O1xuICAgICAgICBmb3IgKGkgPSAwOyBpIDwga2V5cy5sZW5ndGg7ICsraSkge1xuICAgICAgICAgIGtleSA9IGtleXNbaV07XG4gICAgICAgICAgaWYgKGtleSA9PT0gJ3JlbW92ZUxpc3RlbmVyJykgY29udGludWU7XG4gICAgICAgICAgdGhpcy5yZW1vdmVBbGxMaXN0ZW5lcnMoa2V5KTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnJlbW92ZUFsbExpc3RlbmVycygncmVtb3ZlTGlzdGVuZXInKTtcbiAgICAgICAgdGhpcy5fZXZlbnRzID0gb2JqZWN0Q3JlYXRlKG51bGwpO1xuICAgICAgICB0aGlzLl9ldmVudHNDb3VudCA9IDA7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgfVxuXG4gICAgICBsaXN0ZW5lcnMgPSBldmVudHNbdHlwZV07XG5cbiAgICAgIGlmICh0eXBlb2YgbGlzdGVuZXJzID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgIHRoaXMucmVtb3ZlTGlzdGVuZXIodHlwZSwgbGlzdGVuZXJzKTtcbiAgICAgIH0gZWxzZSBpZiAobGlzdGVuZXJzKSB7XG4gICAgICAgIC8vIExJRk8gb3JkZXJcbiAgICAgICAgZm9yIChpID0gbGlzdGVuZXJzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgICAgICAgdGhpcy5yZW1vdmVMaXN0ZW5lcih0eXBlLCBsaXN0ZW5lcnNbaV0pO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG5cbmZ1bmN0aW9uIF9saXN0ZW5lcnModGFyZ2V0LCB0eXBlLCB1bndyYXApIHtcbiAgdmFyIGV2ZW50cyA9IHRhcmdldC5fZXZlbnRzO1xuXG4gIGlmICghZXZlbnRzKVxuICAgIHJldHVybiBbXTtcblxuICB2YXIgZXZsaXN0ZW5lciA9IGV2ZW50c1t0eXBlXTtcbiAgaWYgKCFldmxpc3RlbmVyKVxuICAgIHJldHVybiBbXTtcblxuICBpZiAodHlwZW9mIGV2bGlzdGVuZXIgPT09ICdmdW5jdGlvbicpXG4gICAgcmV0dXJuIHVud3JhcCA/IFtldmxpc3RlbmVyLmxpc3RlbmVyIHx8IGV2bGlzdGVuZXJdIDogW2V2bGlzdGVuZXJdO1xuXG4gIHJldHVybiB1bndyYXAgPyB1bndyYXBMaXN0ZW5lcnMoZXZsaXN0ZW5lcikgOiBhcnJheUNsb25lKGV2bGlzdGVuZXIsIGV2bGlzdGVuZXIubGVuZ3RoKTtcbn1cblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5saXN0ZW5lcnMgPSBmdW5jdGlvbiBsaXN0ZW5lcnModHlwZSkge1xuICByZXR1cm4gX2xpc3RlbmVycyh0aGlzLCB0eXBlLCB0cnVlKTtcbn07XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUucmF3TGlzdGVuZXJzID0gZnVuY3Rpb24gcmF3TGlzdGVuZXJzKHR5cGUpIHtcbiAgcmV0dXJuIF9saXN0ZW5lcnModGhpcywgdHlwZSwgZmFsc2UpO1xufTtcblxuRXZlbnRFbWl0dGVyLmxpc3RlbmVyQ291bnQgPSBmdW5jdGlvbihlbWl0dGVyLCB0eXBlKSB7XG4gIGlmICh0eXBlb2YgZW1pdHRlci5saXN0ZW5lckNvdW50ID09PSAnZnVuY3Rpb24nKSB7XG4gICAgcmV0dXJuIGVtaXR0ZXIubGlzdGVuZXJDb3VudCh0eXBlKTtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gbGlzdGVuZXJDb3VudC5jYWxsKGVtaXR0ZXIsIHR5cGUpO1xuICB9XG59O1xuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLmxpc3RlbmVyQ291bnQgPSBsaXN0ZW5lckNvdW50O1xuZnVuY3Rpb24gbGlzdGVuZXJDb3VudCh0eXBlKSB7XG4gIHZhciBldmVudHMgPSB0aGlzLl9ldmVudHM7XG5cbiAgaWYgKGV2ZW50cykge1xuICAgIHZhciBldmxpc3RlbmVyID0gZXZlbnRzW3R5cGVdO1xuXG4gICAgaWYgKHR5cGVvZiBldmxpc3RlbmVyID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICByZXR1cm4gMTtcbiAgICB9IGVsc2UgaWYgKGV2bGlzdGVuZXIpIHtcbiAgICAgIHJldHVybiBldmxpc3RlbmVyLmxlbmd0aDtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gMDtcbn1cblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5ldmVudE5hbWVzID0gZnVuY3Rpb24gZXZlbnROYW1lcygpIHtcbiAgcmV0dXJuIHRoaXMuX2V2ZW50c0NvdW50ID4gMCA/IFJlZmxlY3Qub3duS2V5cyh0aGlzLl9ldmVudHMpIDogW107XG59O1xuXG4vLyBBYm91dCAxLjV4IGZhc3RlciB0aGFuIHRoZSB0d28tYXJnIHZlcnNpb24gb2YgQXJyYXkjc3BsaWNlKCkuXG5mdW5jdGlvbiBzcGxpY2VPbmUobGlzdCwgaW5kZXgpIHtcbiAgZm9yICh2YXIgaSA9IGluZGV4LCBrID0gaSArIDEsIG4gPSBsaXN0Lmxlbmd0aDsgayA8IG47IGkgKz0gMSwgayArPSAxKVxuICAgIGxpc3RbaV0gPSBsaXN0W2tdO1xuICBsaXN0LnBvcCgpO1xufVxuXG5mdW5jdGlvbiBhcnJheUNsb25lKGFyciwgbikge1xuICB2YXIgY29weSA9IG5ldyBBcnJheShuKTtcbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBuOyArK2kpXG4gICAgY29weVtpXSA9IGFycltpXTtcbiAgcmV0dXJuIGNvcHk7XG59XG5cbmZ1bmN0aW9uIHVud3JhcExpc3RlbmVycyhhcnIpIHtcbiAgdmFyIHJldCA9IG5ldyBBcnJheShhcnIubGVuZ3RoKTtcbiAgZm9yICh2YXIgaSA9IDA7IGkgPCByZXQubGVuZ3RoOyArK2kpIHtcbiAgICByZXRbaV0gPSBhcnJbaV0ubGlzdGVuZXIgfHwgYXJyW2ldO1xuICB9XG4gIHJldHVybiByZXQ7XG59XG5cbmZ1bmN0aW9uIG9iamVjdENyZWF0ZVBvbHlmaWxsKHByb3RvKSB7XG4gIHZhciBGID0gZnVuY3Rpb24oKSB7fTtcbiAgRi5wcm90b3R5cGUgPSBwcm90bztcbiAgcmV0dXJuIG5ldyBGO1xufVxuZnVuY3Rpb24gb2JqZWN0S2V5c1BvbHlmaWxsKG9iaikge1xuICB2YXIga2V5cyA9IFtdO1xuICBmb3IgKHZhciBrIGluIG9iaikgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChvYmosIGspKSB7XG4gICAga2V5cy5wdXNoKGspO1xuICB9XG4gIHJldHVybiBrO1xufVxuZnVuY3Rpb24gZnVuY3Rpb25CaW5kUG9seWZpbGwoY29udGV4dCkge1xuICB2YXIgZm4gPSB0aGlzO1xuICByZXR1cm4gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiBmbi5hcHBseShjb250ZXh0LCBhcmd1bWVudHMpO1xuICB9O1xufVxuIiwiLyoganNoaW50IG5vZGU6IHRydWUgKi9cbid1c2Ugc3RyaWN0JztcblxudmFyIG5vcm1hbGljZSA9IHJlcXVpcmUoJ25vcm1hbGljZScpO1xuXG4vKipcbiAgIyBmcmVlaWNlXG5cbiAgVGhlIGBmcmVlaWNlYCBtb2R1bGUgaXMgYSBzaW1wbGUgd2F5IG9mIGdldHRpbmcgcmFuZG9tIFNUVU4gb3IgVFVSTiBzZXJ2ZXJcbiAgZm9yIHlvdXIgV2ViUlRDIGFwcGxpY2F0aW9uLiAgVGhlIGxpc3Qgb2Ygc2VydmVycyAoanVzdCBTVFVOIGF0IHRoaXMgc3RhZ2UpXG4gIHdlcmUgc291cmNlZCBmcm9tIHRoaXMgW2dpc3RdKGh0dHBzOi8vZ2lzdC5naXRodWIuY29tL3p6aXVuaS8zNzQxOTMzKS5cblxuICAjIyBFeGFtcGxlIFVzZVxuXG4gIFRoZSBmb2xsb3dpbmcgZGVtb25zdHJhdGVzIGhvdyB5b3UgY2FuIHVzZSBgZnJlZWljZWAgd2l0aFxuICBbcnRjLXF1aWNrY29ubmVjdF0oaHR0cHM6Ly9naXRodWIuY29tL3J0Yy1pby9ydGMtcXVpY2tjb25uZWN0KTpcblxuICA8PDwgZXhhbXBsZXMvcXVpY2tjb25uZWN0LmpzXG5cbiAgQXMgdGhlIGBmcmVlaWNlYCBtb2R1bGUgZ2VuZXJhdGVzIGljZSBzZXJ2ZXJzIGluIGEgbGlzdCBjb21wbGlhbnQgd2l0aCB0aGVcbiAgV2ViUlRDIHNwZWMgeW91IHdpbGwgYmUgYWJsZSB0byB1c2UgaXQgd2l0aCByYXcgYFJUQ1BlZXJDb25uZWN0aW9uYFxuICBjb25zdHJ1Y3RvcnMgYW5kIG90aGVyIFdlYlJUQyBsaWJyYXJpZXMuXG5cbiAgIyMgSGV5LCBkb24ndCB1c2UgbXkgU1RVTi9UVVJOIHNlcnZlciFcblxuICBJZiBmb3Igc29tZSByZWFzb24geW91ciBmcmVlIFNUVU4gb3IgVFVSTiBzZXJ2ZXIgZW5kcyB1cCBpbiB0aGVcbiAgbGlzdCBvZiBzZXJ2ZXJzIChbc3R1bl0oaHR0cHM6Ly9naXRodWIuY29tL0RhbW9uT2VobG1hbi9mcmVlaWNlL2Jsb2IvbWFzdGVyL3N0dW4uanNvbikgb3JcbiAgW3R1cm5dKGh0dHBzOi8vZ2l0aHViLmNvbS9EYW1vbk9laGxtYW4vZnJlZWljZS9ibG9iL21hc3Rlci90dXJuLmpzb24pKVxuICB0aGF0IGlzIHVzZWQgaW4gdGhpcyBtb2R1bGUsIHlvdSBjYW4gZmVlbFxuICBmcmVlIHRvIG9wZW4gYW4gaXNzdWUgb24gdGhpcyByZXBvc2l0b3J5IGFuZCB0aG9zZSBzZXJ2ZXJzIHdpbGwgYmUgcmVtb3ZlZFxuICB3aXRoaW4gMjQgaG91cnMgKG9yIHNvb25lcikuICBUaGlzIGlzIHRoZSBxdWlja2VzdCBhbmQgcHJvYmFibHkgdGhlIG1vc3RcbiAgcG9saXRlIHdheSB0byBoYXZlIHNvbWV0aGluZyByZW1vdmVkIChhbmQgcHJvdmlkZXMgdXMgc29tZSB2aXNpYmlsaXR5XG4gIGlmIHNvbWVvbmUgb3BlbnMgYSBwdWxsIHJlcXVlc3QgcmVxdWVzdGluZyB0aGF0IGEgc2VydmVyIGlzIGFkZGVkKS5cblxuICAjIyBQbGVhc2UgYWRkIG15IHNlcnZlciFcblxuICBJZiB5b3UgaGF2ZSBhIHNlcnZlciB0aGF0IHlvdSB3aXNoIHRvIGFkZCB0byB0aGUgbGlzdCwgdGhhdCdzIGF3ZXNvbWUhIEknbVxuICBzdXJlIEkgc3BlYWsgb24gYmVoYWxmIG9mIGEgd2hvbGUgcGlsZSBvZiBXZWJSVEMgZGV2ZWxvcGVycyB3aG8gc2F5IHRoYW5rcy5cbiAgVG8gZ2V0IGl0IGludG8gdGhlIGxpc3QsIGZlZWwgZnJlZSB0byBlaXRoZXIgb3BlbiBhIHB1bGwgcmVxdWVzdCBvciBpZiB5b3VcbiAgZmluZCB0aGF0IHByb2Nlc3MgYSBiaXQgZGF1bnRpbmcgdGhlbiBqdXN0IGNyZWF0ZSBhbiBpc3N1ZSByZXF1ZXN0aW5nXG4gIHRoZSBhZGRpdGlvbiBvZiB0aGUgc2VydmVyIChtYWtlIHN1cmUgeW91IHByb3ZpZGUgYWxsIHRoZSBkZXRhaWxzLCBhbmQgaWZcbiAgeW91IGhhdmUgYSBUZXJtcyBvZiBTZXJ2aWNlIHRoZW4gaW5jbHVkaW5nIHRoYXQgaW4gdGhlIFBSL2lzc3VlIHdvdWxkIGJlXG4gIGF3ZXNvbWUpLlxuXG4gICMjIEkga25vdyBvZiBhIGZyZWUgc2VydmVyLCBjYW4gSSBhZGQgaXQ/XG5cbiAgU3VyZSwgaWYgeW91IGRvIHlvdXIgaG9tZXdvcmsgYW5kIG1ha2Ugc3VyZSBpdCBpcyBvayB0byB1c2UgKEknbSBjdXJyZW50bHlcbiAgaW4gdGhlIHByb2Nlc3Mgb2YgcmV2aWV3aW5nIHRoZSB0ZXJtcyBvZiB0aG9zZSBTVFVOIHNlcnZlcnMgaW5jbHVkZWQgZnJvbVxuICB0aGUgb3JpZ2luYWwgbGlzdCkuICBJZiBpdCdzIG9rIHRvIGdvLCB0aGVuIHBsZWFzZSBzZWUgdGhlIHByZXZpb3VzIGVudHJ5XG4gIGZvciBob3cgdG8gYWRkIGl0LlxuXG4gICMjIEN1cnJlbnQgTGlzdCBvZiBTZXJ2ZXJzXG5cbiAgKiBjdXJyZW50IGFzIGF0IHRoZSB0aW1lIG9mIGxhc3QgYFJFQURNRS5tZGAgZmlsZSBnZW5lcmF0aW9uXG5cbiAgIyMjIFNUVU5cblxuICA8PDwgc3R1bi5qc29uXG5cbiAgIyMjIFRVUk5cblxuICA8PDwgdHVybi5qc29uXG5cbioqL1xuXG52YXIgZnJlZWljZSA9IG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24ob3B0cykge1xuICAvLyBpZiBhIGxpc3Qgb2Ygc2VydmVycyBoYXMgYmVlbiBwcm92aWRlZCwgdGhlbiB1c2UgaXQgaW5zdGVhZCBvZiBkZWZhdWx0c1xuICB2YXIgc2VydmVycyA9IHtcbiAgICBzdHVuOiAob3B0cyB8fCB7fSkuc3R1biB8fCByZXF1aXJlKCcuL3N0dW4uanNvbicpLFxuICAgIHR1cm46IChvcHRzIHx8IHt9KS50dXJuIHx8IHJlcXVpcmUoJy4vdHVybi5qc29uJylcbiAgfTtcblxuICB2YXIgc3R1bkNvdW50ID0gKG9wdHMgfHwge30pLnN0dW5Db3VudCB8fCAyO1xuICB2YXIgdHVybkNvdW50ID0gKG9wdHMgfHwge30pLnR1cm5Db3VudCB8fCAwO1xuICB2YXIgc2VsZWN0ZWQ7XG5cbiAgZnVuY3Rpb24gZ2V0U2VydmVycyh0eXBlLCBjb3VudCkge1xuICAgIHZhciBvdXQgPSBbXTtcbiAgICB2YXIgaW5wdXQgPSBbXS5jb25jYXQoc2VydmVyc1t0eXBlXSk7XG4gICAgdmFyIGlkeDtcblxuICAgIHdoaWxlIChpbnB1dC5sZW5ndGggJiYgb3V0Lmxlbmd0aCA8IGNvdW50KSB7XG4gICAgICBpZHggPSAoTWF0aC5yYW5kb20oKSAqIGlucHV0Lmxlbmd0aCkgfCAwO1xuICAgICAgb3V0ID0gb3V0LmNvbmNhdChpbnB1dC5zcGxpY2UoaWR4LCAxKSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIG91dC5tYXAoZnVuY3Rpb24odXJsKSB7XG4gICAgICAgIC8vSWYgaXQncyBhIG5vdCBhIHN0cmluZywgZG9uJ3QgdHJ5IHRvIFwibm9ybWFsaWNlXCIgaXQgb3RoZXJ3aXNlIHVzaW5nIHR5cGU6dXJsIHdpbGwgc2NyZXcgaXQgdXBcbiAgICAgICAgaWYgKCh0eXBlb2YgdXJsICE9PSAnc3RyaW5nJykgJiYgKCEgKHVybCBpbnN0YW5jZW9mIFN0cmluZykpKSB7XG4gICAgICAgICAgICByZXR1cm4gdXJsO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIG5vcm1hbGljZSh0eXBlICsgJzonICsgdXJsKTtcbiAgICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgLy8gYWRkIHN0dW4gc2VydmVyc1xuICBzZWxlY3RlZCA9IFtdLmNvbmNhdChnZXRTZXJ2ZXJzKCdzdHVuJywgc3R1bkNvdW50KSk7XG5cbiAgaWYgKHR1cm5Db3VudCkge1xuICAgIHNlbGVjdGVkID0gc2VsZWN0ZWQuY29uY2F0KGdldFNlcnZlcnMoJ3R1cm4nLCB0dXJuQ291bnQpKTtcbiAgfVxuXG4gIHJldHVybiBzZWxlY3RlZDtcbn07XG4iLCJtb2R1bGUuZXhwb3J0cz1bXG4gIFwic3R1bi5sLmdvb2dsZS5jb206MTkzMDJcIixcbiAgXCJzdHVuMS5sLmdvb2dsZS5jb206MTkzMDJcIixcbiAgXCJzdHVuMi5sLmdvb2dsZS5jb206MTkzMDJcIixcbiAgXCJzdHVuMy5sLmdvb2dsZS5jb206MTkzMDJcIixcbiAgXCJzdHVuNC5sLmdvb2dsZS5jb206MTkzMDJcIixcbiAgXCJzdHVuLmVraWdhLm5ldFwiLFxuICBcInN0dW4uaWRlYXNpcC5jb21cIixcbiAgXCJzdHVuLnNjaGx1bmQuZGVcIixcbiAgXCJzdHVuLnN0dW5wcm90b2NvbC5vcmc6MzQ3OFwiLFxuICBcInN0dW4udm9pcGFyb3VuZC5jb21cIixcbiAgXCJzdHVuLnZvaXBidXN0ZXIuY29tXCIsXG4gIFwic3R1bi52b2lwc3R1bnQuY29tXCIsXG4gIFwic3R1bi52b3hncmF0aWEub3JnXCIsXG4gIFwic3R1bi5zZXJ2aWNlcy5tb3ppbGxhLmNvbVwiXG5dXG4iLCJtb2R1bGUuZXhwb3J0cz1bXVxuIiwidmFyIFdpbGRFbWl0dGVyID0gcmVxdWlyZSgnd2lsZGVtaXR0ZXInKTtcblxuZnVuY3Rpb24gZ2V0TWF4Vm9sdW1lIChhbmFseXNlciwgZmZ0Qmlucykge1xuICB2YXIgbWF4Vm9sdW1lID0gLUluZmluaXR5O1xuICBhbmFseXNlci5nZXRGbG9hdEZyZXF1ZW5jeURhdGEoZmZ0Qmlucyk7XG5cbiAgZm9yKHZhciBpPTQsIGlpPWZmdEJpbnMubGVuZ3RoOyBpIDwgaWk7IGkrKykge1xuICAgIGlmIChmZnRCaW5zW2ldID4gbWF4Vm9sdW1lICYmIGZmdEJpbnNbaV0gPCAwKSB7XG4gICAgICBtYXhWb2x1bWUgPSBmZnRCaW5zW2ldO1xuICAgIH1cbiAgfTtcblxuICByZXR1cm4gbWF4Vm9sdW1lO1xufVxuXG5cbnZhciBhdWRpb0NvbnRleHRUeXBlO1xuaWYgKHR5cGVvZiB3aW5kb3cgIT09ICd1bmRlZmluZWQnKSB7XG4gIGF1ZGlvQ29udGV4dFR5cGUgPSB3aW5kb3cuQXVkaW9Db250ZXh0IHx8IHdpbmRvdy53ZWJraXRBdWRpb0NvbnRleHQ7XG59XG4vLyB1c2UgYSBzaW5nbGUgYXVkaW8gY29udGV4dCBkdWUgdG8gaGFyZHdhcmUgbGltaXRzXG52YXIgYXVkaW9Db250ZXh0ID0gbnVsbDtcbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24oc3RyZWFtLCBvcHRpb25zKSB7XG4gIHZhciBoYXJrZXIgPSBuZXcgV2lsZEVtaXR0ZXIoKTtcblxuXG4gIC8vIG1ha2UgaXQgbm90IGJyZWFrIGluIG5vbi1zdXBwb3J0ZWQgYnJvd3NlcnNcbiAgaWYgKCFhdWRpb0NvbnRleHRUeXBlKSByZXR1cm4gaGFya2VyO1xuXG4gIC8vQ29uZmlnXG4gIHZhciBvcHRpb25zID0gb3B0aW9ucyB8fCB7fSxcbiAgICAgIHNtb290aGluZyA9IChvcHRpb25zLnNtb290aGluZyB8fCAwLjEpLFxuICAgICAgaW50ZXJ2YWwgPSAob3B0aW9ucy5pbnRlcnZhbCB8fCA1MCksXG4gICAgICB0aHJlc2hvbGQgPSBvcHRpb25zLnRocmVzaG9sZCxcbiAgICAgIHBsYXkgPSBvcHRpb25zLnBsYXksXG4gICAgICBoaXN0b3J5ID0gb3B0aW9ucy5oaXN0b3J5IHx8IDEwLFxuICAgICAgcnVubmluZyA9IHRydWU7XG5cbiAgLy9TZXR1cCBBdWRpbyBDb250ZXh0XG4gIGlmICghYXVkaW9Db250ZXh0KSB7XG4gICAgYXVkaW9Db250ZXh0ID0gbmV3IGF1ZGlvQ29udGV4dFR5cGUoKTtcbiAgfVxuICB2YXIgc291cmNlTm9kZSwgZmZ0QmlucywgYW5hbHlzZXI7XG5cbiAgYW5hbHlzZXIgPSBhdWRpb0NvbnRleHQuY3JlYXRlQW5hbHlzZXIoKTtcbiAgYW5hbHlzZXIuZmZ0U2l6ZSA9IDUxMjtcbiAgYW5hbHlzZXIuc21vb3RoaW5nVGltZUNvbnN0YW50ID0gc21vb3RoaW5nO1xuICBmZnRCaW5zID0gbmV3IEZsb2F0MzJBcnJheShhbmFseXNlci5mcmVxdWVuY3lCaW5Db3VudCk7XG5cbiAgaWYgKHN0cmVhbS5qcXVlcnkpIHN0cmVhbSA9IHN0cmVhbVswXTtcbiAgaWYgKHN0cmVhbSBpbnN0YW5jZW9mIEhUTUxBdWRpb0VsZW1lbnQgfHwgc3RyZWFtIGluc3RhbmNlb2YgSFRNTFZpZGVvRWxlbWVudCkge1xuICAgIC8vQXVkaW8gVGFnXG4gICAgc291cmNlTm9kZSA9IGF1ZGlvQ29udGV4dC5jcmVhdGVNZWRpYUVsZW1lbnRTb3VyY2Uoc3RyZWFtKTtcbiAgICBpZiAodHlwZW9mIHBsYXkgPT09ICd1bmRlZmluZWQnKSBwbGF5ID0gdHJ1ZTtcbiAgICB0aHJlc2hvbGQgPSB0aHJlc2hvbGQgfHwgLTUwO1xuICB9IGVsc2Uge1xuICAgIC8vV2ViUlRDIFN0cmVhbVxuICAgIHNvdXJjZU5vZGUgPSBhdWRpb0NvbnRleHQuY3JlYXRlTWVkaWFTdHJlYW1Tb3VyY2Uoc3RyZWFtKTtcbiAgICB0aHJlc2hvbGQgPSB0aHJlc2hvbGQgfHwgLTUwO1xuICB9XG5cbiAgc291cmNlTm9kZS5jb25uZWN0KGFuYWx5c2VyKTtcbiAgaWYgKHBsYXkpIGFuYWx5c2VyLmNvbm5lY3QoYXVkaW9Db250ZXh0LmRlc3RpbmF0aW9uKTtcblxuICBoYXJrZXIuc3BlYWtpbmcgPSBmYWxzZTtcblxuICBoYXJrZXIuc3VzcGVuZCA9IGZ1bmN0aW9uKCkge1xuICAgIGF1ZGlvQ29udGV4dC5zdXNwZW5kKCk7XG4gIH1cbiAgaGFya2VyLnJlc3VtZSA9IGZ1bmN0aW9uKCkge1xuICAgIGF1ZGlvQ29udGV4dC5yZXN1bWUoKTtcbiAgfVxuICBPYmplY3QuZGVmaW5lUHJvcGVydHkoaGFya2VyLCAnc3RhdGUnLCB7IGdldDogZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIGF1ZGlvQ29udGV4dC5zdGF0ZTtcbiAgfX0pO1xuICBhdWRpb0NvbnRleHQub25zdGF0ZWNoYW5nZSA9IGZ1bmN0aW9uKCkge1xuICAgIGhhcmtlci5lbWl0KCdzdGF0ZV9jaGFuZ2UnLCBhdWRpb0NvbnRleHQuc3RhdGUpO1xuICB9XG5cbiAgaGFya2VyLnNldFRocmVzaG9sZCA9IGZ1bmN0aW9uKHQpIHtcbiAgICB0aHJlc2hvbGQgPSB0O1xuICB9O1xuXG4gIGhhcmtlci5zZXRJbnRlcnZhbCA9IGZ1bmN0aW9uKGkpIHtcbiAgICBpbnRlcnZhbCA9IGk7XG4gIH07XG5cbiAgaGFya2VyLnN0b3AgPSBmdW5jdGlvbigpIHtcbiAgICBydW5uaW5nID0gZmFsc2U7XG4gICAgaGFya2VyLmVtaXQoJ3ZvbHVtZV9jaGFuZ2UnLCAtMTAwLCB0aHJlc2hvbGQpO1xuICAgIGlmIChoYXJrZXIuc3BlYWtpbmcpIHtcbiAgICAgIGhhcmtlci5zcGVha2luZyA9IGZhbHNlO1xuICAgICAgaGFya2VyLmVtaXQoJ3N0b3BwZWRfc3BlYWtpbmcnKTtcbiAgICB9XG4gICAgYW5hbHlzZXIuZGlzY29ubmVjdCgpO1xuICAgIHNvdXJjZU5vZGUuZGlzY29ubmVjdCgpO1xuICB9O1xuICBoYXJrZXIuc3BlYWtpbmdIaXN0b3J5ID0gW107XG4gIGZvciAodmFyIGkgPSAwOyBpIDwgaGlzdG9yeTsgaSsrKSB7XG4gICAgICBoYXJrZXIuc3BlYWtpbmdIaXN0b3J5LnB1c2goMCk7XG4gIH1cblxuICAvLyBQb2xsIHRoZSBhbmFseXNlciBub2RlIHRvIGRldGVybWluZSBpZiBzcGVha2luZ1xuICAvLyBhbmQgZW1pdCBldmVudHMgaWYgY2hhbmdlZFxuICB2YXIgbG9vcGVyID0gZnVuY3Rpb24oKSB7XG4gICAgc2V0VGltZW91dChmdW5jdGlvbigpIHtcblxuICAgICAgLy9jaGVjayBpZiBzdG9wIGhhcyBiZWVuIGNhbGxlZFxuICAgICAgaWYoIXJ1bm5pbmcpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICB2YXIgY3VycmVudFZvbHVtZSA9IGdldE1heFZvbHVtZShhbmFseXNlciwgZmZ0Qmlucyk7XG5cbiAgICAgIGhhcmtlci5lbWl0KCd2b2x1bWVfY2hhbmdlJywgY3VycmVudFZvbHVtZSwgdGhyZXNob2xkKTtcblxuICAgICAgdmFyIGhpc3RvcnkgPSAwO1xuICAgICAgaWYgKGN1cnJlbnRWb2x1bWUgPiB0aHJlc2hvbGQgJiYgIWhhcmtlci5zcGVha2luZykge1xuICAgICAgICAvLyB0cmlnZ2VyIHF1aWNrbHksIHNob3J0IGhpc3RvcnlcbiAgICAgICAgZm9yICh2YXIgaSA9IGhhcmtlci5zcGVha2luZ0hpc3RvcnkubGVuZ3RoIC0gMzsgaSA8IGhhcmtlci5zcGVha2luZ0hpc3RvcnkubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICBoaXN0b3J5ICs9IGhhcmtlci5zcGVha2luZ0hpc3RvcnlbaV07XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGhpc3RvcnkgPj0gMikge1xuICAgICAgICAgIGhhcmtlci5zcGVha2luZyA9IHRydWU7XG4gICAgICAgICAgaGFya2VyLmVtaXQoJ3NwZWFraW5nJyk7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSBpZiAoY3VycmVudFZvbHVtZSA8IHRocmVzaG9sZCAmJiBoYXJrZXIuc3BlYWtpbmcpIHtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBoYXJrZXIuc3BlYWtpbmdIaXN0b3J5Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgaGlzdG9yeSArPSBoYXJrZXIuc3BlYWtpbmdIaXN0b3J5W2ldO1xuICAgICAgICB9XG4gICAgICAgIGlmIChoaXN0b3J5ID09IDApIHtcbiAgICAgICAgICBoYXJrZXIuc3BlYWtpbmcgPSBmYWxzZTtcbiAgICAgICAgICBoYXJrZXIuZW1pdCgnc3RvcHBlZF9zcGVha2luZycpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBoYXJrZXIuc3BlYWtpbmdIaXN0b3J5LnNoaWZ0KCk7XG4gICAgICBoYXJrZXIuc3BlYWtpbmdIaXN0b3J5LnB1c2goMCArIChjdXJyZW50Vm9sdW1lID4gdGhyZXNob2xkKSk7XG5cbiAgICAgIGxvb3BlcigpO1xuICAgIH0sIGludGVydmFsKTtcbiAgfTtcbiAgbG9vcGVyKCk7XG5cblxuICByZXR1cm4gaGFya2VyO1xufVxuIiwiaWYgKHR5cGVvZiBPYmplY3QuY3JlYXRlID09PSAnZnVuY3Rpb24nKSB7XG4gIC8vIGltcGxlbWVudGF0aW9uIGZyb20gc3RhbmRhcmQgbm9kZS5qcyAndXRpbCcgbW9kdWxlXG4gIG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gaW5oZXJpdHMoY3Rvciwgc3VwZXJDdG9yKSB7XG4gICAgY3Rvci5zdXBlcl8gPSBzdXBlckN0b3JcbiAgICBjdG9yLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoc3VwZXJDdG9yLnByb3RvdHlwZSwge1xuICAgICAgY29uc3RydWN0b3I6IHtcbiAgICAgICAgdmFsdWU6IGN0b3IsXG4gICAgICAgIGVudW1lcmFibGU6IGZhbHNlLFxuICAgICAgICB3cml0YWJsZTogdHJ1ZSxcbiAgICAgICAgY29uZmlndXJhYmxlOiB0cnVlXG4gICAgICB9XG4gICAgfSk7XG4gIH07XG59IGVsc2Uge1xuICAvLyBvbGQgc2Nob29sIHNoaW0gZm9yIG9sZCBicm93c2Vyc1xuICBtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGluaGVyaXRzKGN0b3IsIHN1cGVyQ3Rvcikge1xuICAgIGN0b3Iuc3VwZXJfID0gc3VwZXJDdG9yXG4gICAgdmFyIFRlbXBDdG9yID0gZnVuY3Rpb24gKCkge31cbiAgICBUZW1wQ3Rvci5wcm90b3R5cGUgPSBzdXBlckN0b3IucHJvdG90eXBlXG4gICAgY3Rvci5wcm90b3R5cGUgPSBuZXcgVGVtcEN0b3IoKVxuICAgIGN0b3IucHJvdG90eXBlLmNvbnN0cnVjdG9yID0gY3RvclxuICB9XG59XG4iLCIvKipcbiAgIyBub3JtYWxpY2VcblxuICBOb3JtYWxpemUgYW4gaWNlIHNlcnZlciBjb25maWd1cmF0aW9uIG9iamVjdCAob3IgcGxhaW4gb2xkIHN0cmluZykgaW50byBhIGZvcm1hdFxuICB0aGF0IGlzIHVzYWJsZSBpbiBhbGwgYnJvd3NlcnMgc3VwcG9ydGluZyBXZWJSVEMuICBQcmltYXJpbHkgdGhpcyBtb2R1bGUgaXMgZGVzaWduZWRcbiAgdG8gaGVscCB3aXRoIHRoZSB0cmFuc2l0aW9uIG9mIHRoZSBgdXJsYCBhdHRyaWJ1dGUgb2YgdGhlIGNvbmZpZ3VyYXRpb24gb2JqZWN0IHRvXG4gIHRoZSBgdXJsc2AgYXR0cmlidXRlLlxuXG4gICMjIEV4YW1wbGUgVXNhZ2VcblxuICA8PDwgZXhhbXBsZXMvc2ltcGxlLmpzXG5cbioqL1xuXG52YXIgcHJvdG9jb2xzID0gW1xuICAnc3R1bjonLFxuICAndHVybjonXG5dO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKGlucHV0KSB7XG4gIHZhciB1cmwgPSAoaW5wdXQgfHwge30pLnVybCB8fCBpbnB1dDtcbiAgdmFyIHByb3RvY29sO1xuICB2YXIgcGFydHM7XG4gIHZhciBvdXRwdXQgPSB7fTtcblxuICAvLyBpZiB3ZSBkb24ndCBoYXZlIGEgc3RyaW5nIHVybCwgdGhlbiBhbGxvdyB0aGUgaW5wdXQgdG8gcGFzc3Rocm91Z2hcbiAgaWYgKHR5cGVvZiB1cmwgIT0gJ3N0cmluZycgJiYgKCEgKHVybCBpbnN0YW5jZW9mIFN0cmluZykpKSB7XG4gICAgcmV0dXJuIGlucHV0O1xuICB9XG5cbiAgLy8gdHJpbSB0aGUgdXJsIHN0cmluZywgYW5kIGNvbnZlcnQgdG8gYW4gYXJyYXlcbiAgdXJsID0gdXJsLnRyaW0oKTtcblxuICAvLyBpZiB0aGUgcHJvdG9jb2wgaXMgbm90IGtub3duLCB0aGVuIHBhc3N0aHJvdWdoXG4gIHByb3RvY29sID0gcHJvdG9jb2xzW3Byb3RvY29scy5pbmRleE9mKHVybC5zbGljZSgwLCA1KSldO1xuICBpZiAoISBwcm90b2NvbCkge1xuICAgIHJldHVybiBpbnB1dDtcbiAgfVxuXG4gIC8vIG5vdyBsZXQncyBhdHRhY2sgdGhlIHJlbWFpbmluZyB1cmwgcGFydHNcbiAgdXJsID0gdXJsLnNsaWNlKDUpO1xuICBwYXJ0cyA9IHVybC5zcGxpdCgnQCcpO1xuXG4gIG91dHB1dC51c2VybmFtZSA9IGlucHV0LnVzZXJuYW1lO1xuICBvdXRwdXQuY3JlZGVudGlhbCA9IGlucHV0LmNyZWRlbnRpYWw7XG4gIC8vIGlmIHdlIGhhdmUgYW4gYXV0aGVudGljYXRpb24gcGFydCwgdGhlbiBzZXQgdGhlIGNyZWRlbnRpYWxzXG4gIGlmIChwYXJ0cy5sZW5ndGggPiAxKSB7XG4gICAgdXJsID0gcGFydHNbMV07XG4gICAgcGFydHMgPSBwYXJ0c1swXS5zcGxpdCgnOicpO1xuXG4gICAgLy8gYWRkIHRoZSBvdXRwdXQgY3JlZGVudGlhbCBhbmQgdXNlcm5hbWVcbiAgICBvdXRwdXQudXNlcm5hbWUgPSBwYXJ0c1swXTtcbiAgICBvdXRwdXQuY3JlZGVudGlhbCA9IChpbnB1dCB8fCB7fSkuY3JlZGVudGlhbCB8fCBwYXJ0c1sxXSB8fCAnJztcbiAgfVxuXG4gIG91dHB1dC51cmwgPSBwcm90b2NvbCArIHVybDtcbiAgb3V0cHV0LnVybHMgPSBbIG91dHB1dC51cmwgXTtcblxuICByZXR1cm4gb3V0cHV0O1xufTtcbiIsIi8qIVxuICogUGxhdGZvcm0uanMgPGh0dHBzOi8vbXRocy5iZS9wbGF0Zm9ybT5cbiAqIENvcHlyaWdodCAyMDE0LTIwMTggQmVuamFtaW4gVGFuIDxodHRwczovL2Juam1udDRuLm5vdy5zaC8+XG4gKiBDb3B5cmlnaHQgMjAxMS0yMDEzIEpvaG4tRGF2aWQgRGFsdG9uIDxodHRwOi8vYWxseW91Y2FubGVldC5jb20vPlxuICogQXZhaWxhYmxlIHVuZGVyIE1JVCBsaWNlbnNlIDxodHRwczovL210aHMuYmUvbWl0PlxuICovXG47KGZ1bmN0aW9uKCkge1xuICAndXNlIHN0cmljdCc7XG5cbiAgLyoqIFVzZWQgdG8gZGV0ZXJtaW5lIGlmIHZhbHVlcyBhcmUgb2YgdGhlIGxhbmd1YWdlIHR5cGUgYE9iamVjdGAuICovXG4gIHZhciBvYmplY3RUeXBlcyA9IHtcbiAgICAnZnVuY3Rpb24nOiB0cnVlLFxuICAgICdvYmplY3QnOiB0cnVlXG4gIH07XG5cbiAgLyoqIFVzZWQgYXMgYSByZWZlcmVuY2UgdG8gdGhlIGdsb2JhbCBvYmplY3QuICovXG4gIHZhciByb290ID0gKG9iamVjdFR5cGVzW3R5cGVvZiB3aW5kb3ddICYmIHdpbmRvdykgfHwgdGhpcztcblxuICAvKiogQmFja3VwIHBvc3NpYmxlIGdsb2JhbCBvYmplY3QuICovXG4gIHZhciBvbGRSb290ID0gcm9vdDtcblxuICAvKiogRGV0ZWN0IGZyZWUgdmFyaWFibGUgYGV4cG9ydHNgLiAqL1xuICB2YXIgZnJlZUV4cG9ydHMgPSBvYmplY3RUeXBlc1t0eXBlb2YgZXhwb3J0c10gJiYgZXhwb3J0cztcblxuICAvKiogRGV0ZWN0IGZyZWUgdmFyaWFibGUgYG1vZHVsZWAuICovXG4gIHZhciBmcmVlTW9kdWxlID0gb2JqZWN0VHlwZXNbdHlwZW9mIG1vZHVsZV0gJiYgbW9kdWxlICYmICFtb2R1bGUubm9kZVR5cGUgJiYgbW9kdWxlO1xuXG4gIC8qKiBEZXRlY3QgZnJlZSB2YXJpYWJsZSBgZ2xvYmFsYCBmcm9tIE5vZGUuanMgb3IgQnJvd3NlcmlmaWVkIGNvZGUgYW5kIHVzZSBpdCBhcyBgcm9vdGAuICovXG4gIHZhciBmcmVlR2xvYmFsID0gZnJlZUV4cG9ydHMgJiYgZnJlZU1vZHVsZSAmJiB0eXBlb2YgZ2xvYmFsID09ICdvYmplY3QnICYmIGdsb2JhbDtcbiAgaWYgKGZyZWVHbG9iYWwgJiYgKGZyZWVHbG9iYWwuZ2xvYmFsID09PSBmcmVlR2xvYmFsIHx8IGZyZWVHbG9iYWwud2luZG93ID09PSBmcmVlR2xvYmFsIHx8IGZyZWVHbG9iYWwuc2VsZiA9PT0gZnJlZUdsb2JhbCkpIHtcbiAgICByb290ID0gZnJlZUdsb2JhbDtcbiAgfVxuXG4gIC8qKlxuICAgKiBVc2VkIGFzIHRoZSBtYXhpbXVtIGxlbmd0aCBvZiBhbiBhcnJheS1saWtlIG9iamVjdC5cbiAgICogU2VlIHRoZSBbRVM2IHNwZWNdKGh0dHA6Ly9wZW9wbGUubW96aWxsYS5vcmcvfmpvcmVuZG9yZmYvZXM2LWRyYWZ0Lmh0bWwjc2VjLXRvbGVuZ3RoKVxuICAgKiBmb3IgbW9yZSBkZXRhaWxzLlxuICAgKi9cbiAgdmFyIG1heFNhZmVJbnRlZ2VyID0gTWF0aC5wb3coMiwgNTMpIC0gMTtcblxuICAvKiogUmVndWxhciBleHByZXNzaW9uIHRvIGRldGVjdCBPcGVyYS4gKi9cbiAgdmFyIHJlT3BlcmEgPSAvXFxiT3BlcmEvO1xuXG4gIC8qKiBQb3NzaWJsZSBnbG9iYWwgb2JqZWN0LiAqL1xuICB2YXIgdGhpc0JpbmRpbmcgPSB0aGlzO1xuXG4gIC8qKiBVc2VkIGZvciBuYXRpdmUgbWV0aG9kIHJlZmVyZW5jZXMuICovXG4gIHZhciBvYmplY3RQcm90byA9IE9iamVjdC5wcm90b3R5cGU7XG5cbiAgLyoqIFVzZWQgdG8gY2hlY2sgZm9yIG93biBwcm9wZXJ0aWVzIG9mIGFuIG9iamVjdC4gKi9cbiAgdmFyIGhhc093blByb3BlcnR5ID0gb2JqZWN0UHJvdG8uaGFzT3duUHJvcGVydHk7XG5cbiAgLyoqIFVzZWQgdG8gcmVzb2x2ZSB0aGUgaW50ZXJuYWwgYFtbQ2xhc3NdXWAgb2YgdmFsdWVzLiAqL1xuICB2YXIgdG9TdHJpbmcgPSBvYmplY3RQcm90by50b1N0cmluZztcblxuICAvKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cblxuICAvKipcbiAgICogQ2FwaXRhbGl6ZXMgYSBzdHJpbmcgdmFsdWUuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBzdHJpbmcgVGhlIHN0cmluZyB0byBjYXBpdGFsaXplLlxuICAgKiBAcmV0dXJucyB7c3RyaW5nfSBUaGUgY2FwaXRhbGl6ZWQgc3RyaW5nLlxuICAgKi9cbiAgZnVuY3Rpb24gY2FwaXRhbGl6ZShzdHJpbmcpIHtcbiAgICBzdHJpbmcgPSBTdHJpbmcoc3RyaW5nKTtcbiAgICByZXR1cm4gc3RyaW5nLmNoYXJBdCgwKS50b1VwcGVyQ2FzZSgpICsgc3RyaW5nLnNsaWNlKDEpO1xuICB9XG5cbiAgLyoqXG4gICAqIEEgdXRpbGl0eSBmdW5jdGlvbiB0byBjbGVhbiB1cCB0aGUgT1MgbmFtZS5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtzdHJpbmd9IG9zIFRoZSBPUyBuYW1lIHRvIGNsZWFuIHVwLlxuICAgKiBAcGFyYW0ge3N0cmluZ30gW3BhdHRlcm5dIEEgYFJlZ0V4cGAgcGF0dGVybiBtYXRjaGluZyB0aGUgT1MgbmFtZS5cbiAgICogQHBhcmFtIHtzdHJpbmd9IFtsYWJlbF0gQSBsYWJlbCBmb3IgdGhlIE9TLlxuICAgKi9cbiAgZnVuY3Rpb24gY2xlYW51cE9TKG9zLCBwYXR0ZXJuLCBsYWJlbCkge1xuICAgIC8vIFBsYXRmb3JtIHRva2VucyBhcmUgZGVmaW5lZCBhdDpcbiAgICAvLyBodHRwOi8vbXNkbi5taWNyb3NvZnQuY29tL2VuLXVzL2xpYnJhcnkvbXM1Mzc1MDMoVlMuODUpLmFzcHhcbiAgICAvLyBodHRwOi8vd2ViLmFyY2hpdmUub3JnL3dlYi8yMDA4MTEyMjA1Mzk1MC9odHRwOi8vbXNkbi5taWNyb3NvZnQuY29tL2VuLXVzL2xpYnJhcnkvbXM1Mzc1MDMoVlMuODUpLmFzcHhcbiAgICB2YXIgZGF0YSA9IHtcbiAgICAgICcxMC4wJzogJzEwJyxcbiAgICAgICc2LjQnOiAgJzEwIFRlY2huaWNhbCBQcmV2aWV3JyxcbiAgICAgICc2LjMnOiAgJzguMScsXG4gICAgICAnNi4yJzogICc4JyxcbiAgICAgICc2LjEnOiAgJ1NlcnZlciAyMDA4IFIyIC8gNycsXG4gICAgICAnNi4wJzogICdTZXJ2ZXIgMjAwOCAvIFZpc3RhJyxcbiAgICAgICc1LjInOiAgJ1NlcnZlciAyMDAzIC8gWFAgNjQtYml0JyxcbiAgICAgICc1LjEnOiAgJ1hQJyxcbiAgICAgICc1LjAxJzogJzIwMDAgU1AxJyxcbiAgICAgICc1LjAnOiAgJzIwMDAnLFxuICAgICAgJzQuMCc6ICAnTlQnLFxuICAgICAgJzQuOTAnOiAnTUUnXG4gICAgfTtcbiAgICAvLyBEZXRlY3QgV2luZG93cyB2ZXJzaW9uIGZyb20gcGxhdGZvcm0gdG9rZW5zLlxuICAgIGlmIChwYXR0ZXJuICYmIGxhYmVsICYmIC9eV2luL2kudGVzdChvcykgJiYgIS9eV2luZG93cyBQaG9uZSAvaS50ZXN0KG9zKSAmJlxuICAgICAgICAoZGF0YSA9IGRhdGFbL1tcXGQuXSskLy5leGVjKG9zKV0pKSB7XG4gICAgICBvcyA9ICdXaW5kb3dzICcgKyBkYXRhO1xuICAgIH1cbiAgICAvLyBDb3JyZWN0IGNoYXJhY3RlciBjYXNlIGFuZCBjbGVhbnVwIHN0cmluZy5cbiAgICBvcyA9IFN0cmluZyhvcyk7XG5cbiAgICBpZiAocGF0dGVybiAmJiBsYWJlbCkge1xuICAgICAgb3MgPSBvcy5yZXBsYWNlKFJlZ0V4cChwYXR0ZXJuLCAnaScpLCBsYWJlbCk7XG4gICAgfVxuXG4gICAgb3MgPSBmb3JtYXQoXG4gICAgICBvcy5yZXBsYWNlKC8gY2UkL2ksICcgQ0UnKVxuICAgICAgICAucmVwbGFjZSgvXFxiaHB3L2ksICd3ZWInKVxuICAgICAgICAucmVwbGFjZSgvXFxiTWFjaW50b3NoXFxiLywgJ01hYyBPUycpXG4gICAgICAgIC5yZXBsYWNlKC9fUG93ZXJQQ1xcYi9pLCAnIE9TJylcbiAgICAgICAgLnJlcGxhY2UoL1xcYihPUyBYKSBbXiBcXGRdKy9pLCAnJDEnKVxuICAgICAgICAucmVwbGFjZSgvXFxiTWFjIChPUyBYKVxcYi8sICckMScpXG4gICAgICAgIC5yZXBsYWNlKC9cXC8oXFxkKS8sICcgJDEnKVxuICAgICAgICAucmVwbGFjZSgvXy9nLCAnLicpXG4gICAgICAgIC5yZXBsYWNlKC8oPzogQmVQQ3xbIC5dKmZjWyBcXGQuXSspJC9pLCAnJylcbiAgICAgICAgLnJlcGxhY2UoL1xcYng4NlxcLjY0XFxiL2dpLCAneDg2XzY0JylcbiAgICAgICAgLnJlcGxhY2UoL1xcYihXaW5kb3dzIFBob25lKSBPU1xcYi8sICckMScpXG4gICAgICAgIC5yZXBsYWNlKC9cXGIoQ2hyb21lIE9TIFxcdyspIFtcXGQuXStcXGIvLCAnJDEnKVxuICAgICAgICAuc3BsaXQoJyBvbiAnKVswXVxuICAgICk7XG5cbiAgICByZXR1cm4gb3M7XG4gIH1cblxuICAvKipcbiAgICogQW4gaXRlcmF0aW9uIHV0aWxpdHkgZm9yIGFycmF5cyBhbmQgb2JqZWN0cy5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtBcnJheXxPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIGl0ZXJhdGUgb3Zlci5cbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gY2FsbGJhY2sgVGhlIGZ1bmN0aW9uIGNhbGxlZCBwZXIgaXRlcmF0aW9uLlxuICAgKi9cbiAgZnVuY3Rpb24gZWFjaChvYmplY3QsIGNhbGxiYWNrKSB7XG4gICAgdmFyIGluZGV4ID0gLTEsXG4gICAgICAgIGxlbmd0aCA9IG9iamVjdCA/IG9iamVjdC5sZW5ndGggOiAwO1xuXG4gICAgaWYgKHR5cGVvZiBsZW5ndGggPT0gJ251bWJlcicgJiYgbGVuZ3RoID4gLTEgJiYgbGVuZ3RoIDw9IG1heFNhZmVJbnRlZ2VyKSB7XG4gICAgICB3aGlsZSAoKytpbmRleCA8IGxlbmd0aCkge1xuICAgICAgICBjYWxsYmFjayhvYmplY3RbaW5kZXhdLCBpbmRleCwgb2JqZWN0KTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgZm9yT3duKG9iamVjdCwgY2FsbGJhY2spO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBUcmltIGFuZCBjb25kaXRpb25hbGx5IGNhcGl0YWxpemUgc3RyaW5nIHZhbHVlcy5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtzdHJpbmd9IHN0cmluZyBUaGUgc3RyaW5nIHRvIGZvcm1hdC5cbiAgICogQHJldHVybnMge3N0cmluZ30gVGhlIGZvcm1hdHRlZCBzdHJpbmcuXG4gICAqL1xuICBmdW5jdGlvbiBmb3JtYXQoc3RyaW5nKSB7XG4gICAgc3RyaW5nID0gdHJpbShzdHJpbmcpO1xuICAgIHJldHVybiAvXig/OndlYk9TfGkoPzpPU3xQKSkvLnRlc3Qoc3RyaW5nKVxuICAgICAgPyBzdHJpbmdcbiAgICAgIDogY2FwaXRhbGl6ZShzdHJpbmcpO1xuICB9XG5cbiAgLyoqXG4gICAqIEl0ZXJhdGVzIG92ZXIgYW4gb2JqZWN0J3Mgb3duIHByb3BlcnRpZXMsIGV4ZWN1dGluZyB0aGUgYGNhbGxiYWNrYCBmb3IgZWFjaC5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIGl0ZXJhdGUgb3Zlci5cbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gY2FsbGJhY2sgVGhlIGZ1bmN0aW9uIGV4ZWN1dGVkIHBlciBvd24gcHJvcGVydHkuXG4gICAqL1xuICBmdW5jdGlvbiBmb3JPd24ob2JqZWN0LCBjYWxsYmFjaykge1xuICAgIGZvciAodmFyIGtleSBpbiBvYmplY3QpIHtcbiAgICAgIGlmIChoYXNPd25Qcm9wZXJ0eS5jYWxsKG9iamVjdCwga2V5KSkge1xuICAgICAgICBjYWxsYmFjayhvYmplY3Rba2V5XSwga2V5LCBvYmplY3QpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBHZXRzIHRoZSBpbnRlcm5hbCBgW1tDbGFzc11dYCBvZiBhIHZhbHVlLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZS5cbiAgICogQHJldHVybnMge3N0cmluZ30gVGhlIGBbW0NsYXNzXV1gLlxuICAgKi9cbiAgZnVuY3Rpb24gZ2V0Q2xhc3NPZih2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZSA9PSBudWxsXG4gICAgICA/IGNhcGl0YWxpemUodmFsdWUpXG4gICAgICA6IHRvU3RyaW5nLmNhbGwodmFsdWUpLnNsaWNlKDgsIC0xKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBIb3N0IG9iamVjdHMgY2FuIHJldHVybiB0eXBlIHZhbHVlcyB0aGF0IGFyZSBkaWZmZXJlbnQgZnJvbSB0aGVpciBhY3R1YWxcbiAgICogZGF0YSB0eXBlLiBUaGUgb2JqZWN0cyB3ZSBhcmUgY29uY2VybmVkIHdpdGggdXN1YWxseSByZXR1cm4gbm9uLXByaW1pdGl2ZVxuICAgKiB0eXBlcyBvZiBcIm9iamVjdFwiLCBcImZ1bmN0aW9uXCIsIG9yIFwidW5rbm93blwiLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0geyp9IG9iamVjdCBUaGUgb3duZXIgb2YgdGhlIHByb3BlcnR5LlxuICAgKiBAcGFyYW0ge3N0cmluZ30gcHJvcGVydHkgVGhlIHByb3BlcnR5IHRvIGNoZWNrLlxuICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgdGhlIHByb3BlcnR5IHZhbHVlIGlzIGEgbm9uLXByaW1pdGl2ZSwgZWxzZSBgZmFsc2VgLlxuICAgKi9cbiAgZnVuY3Rpb24gaXNIb3N0VHlwZShvYmplY3QsIHByb3BlcnR5KSB7XG4gICAgdmFyIHR5cGUgPSBvYmplY3QgIT0gbnVsbCA/IHR5cGVvZiBvYmplY3RbcHJvcGVydHldIDogJ251bWJlcic7XG4gICAgcmV0dXJuICEvXig/OmJvb2xlYW58bnVtYmVyfHN0cmluZ3x1bmRlZmluZWQpJC8udGVzdCh0eXBlKSAmJlxuICAgICAgKHR5cGUgPT0gJ29iamVjdCcgPyAhIW9iamVjdFtwcm9wZXJ0eV0gOiB0cnVlKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBQcmVwYXJlcyBhIHN0cmluZyBmb3IgdXNlIGluIGEgYFJlZ0V4cGAgYnkgbWFraW5nIGh5cGhlbnMgYW5kIHNwYWNlcyBvcHRpb25hbC5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtzdHJpbmd9IHN0cmluZyBUaGUgc3RyaW5nIHRvIHF1YWxpZnkuXG4gICAqIEByZXR1cm5zIHtzdHJpbmd9IFRoZSBxdWFsaWZpZWQgc3RyaW5nLlxuICAgKi9cbiAgZnVuY3Rpb24gcXVhbGlmeShzdHJpbmcpIHtcbiAgICByZXR1cm4gU3RyaW5nKHN0cmluZykucmVwbGFjZSgvKFsgLV0pKD8hJCkvZywgJyQxPycpO1xuICB9XG5cbiAgLyoqXG4gICAqIEEgYmFyZS1ib25lcyBgQXJyYXkjcmVkdWNlYCBsaWtlIHV0aWxpdHkgZnVuY3Rpb24uXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBpdGVyYXRlIG92ZXIuXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IGNhbGxiYWNrIFRoZSBmdW5jdGlvbiBjYWxsZWQgcGVyIGl0ZXJhdGlvbi5cbiAgICogQHJldHVybnMgeyp9IFRoZSBhY2N1bXVsYXRlZCByZXN1bHQuXG4gICAqL1xuICBmdW5jdGlvbiByZWR1Y2UoYXJyYXksIGNhbGxiYWNrKSB7XG4gICAgdmFyIGFjY3VtdWxhdG9yID0gbnVsbDtcbiAgICBlYWNoKGFycmF5LCBmdW5jdGlvbih2YWx1ZSwgaW5kZXgpIHtcbiAgICAgIGFjY3VtdWxhdG9yID0gY2FsbGJhY2soYWNjdW11bGF0b3IsIHZhbHVlLCBpbmRleCwgYXJyYXkpO1xuICAgIH0pO1xuICAgIHJldHVybiBhY2N1bXVsYXRvcjtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZW1vdmVzIGxlYWRpbmcgYW5kIHRyYWlsaW5nIHdoaXRlc3BhY2UgZnJvbSBhIHN0cmluZy5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtzdHJpbmd9IHN0cmluZyBUaGUgc3RyaW5nIHRvIHRyaW0uXG4gICAqIEByZXR1cm5zIHtzdHJpbmd9IFRoZSB0cmltbWVkIHN0cmluZy5cbiAgICovXG4gIGZ1bmN0aW9uIHRyaW0oc3RyaW5nKSB7XG4gICAgcmV0dXJuIFN0cmluZyhzdHJpbmcpLnJlcGxhY2UoL14gK3wgKyQvZywgJycpO1xuICB9XG5cbiAgLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG5cbiAgLyoqXG4gICAqIENyZWF0ZXMgYSBuZXcgcGxhdGZvcm0gb2JqZWN0LlxuICAgKlxuICAgKiBAbWVtYmVyT2YgcGxhdGZvcm1cbiAgICogQHBhcmFtIHtPYmplY3R8c3RyaW5nfSBbdWE9bmF2aWdhdG9yLnVzZXJBZ2VudF0gVGhlIHVzZXIgYWdlbnQgc3RyaW5nIG9yXG4gICAqICBjb250ZXh0IG9iamVjdC5cbiAgICogQHJldHVybnMge09iamVjdH0gQSBwbGF0Zm9ybSBvYmplY3QuXG4gICAqL1xuICBmdW5jdGlvbiBwYXJzZSh1YSkge1xuXG4gICAgLyoqIFRoZSBlbnZpcm9ubWVudCBjb250ZXh0IG9iamVjdC4gKi9cbiAgICB2YXIgY29udGV4dCA9IHJvb3Q7XG5cbiAgICAvKiogVXNlZCB0byBmbGFnIHdoZW4gYSBjdXN0b20gY29udGV4dCBpcyBwcm92aWRlZC4gKi9cbiAgICB2YXIgaXNDdXN0b21Db250ZXh0ID0gdWEgJiYgdHlwZW9mIHVhID09ICdvYmplY3QnICYmIGdldENsYXNzT2YodWEpICE9ICdTdHJpbmcnO1xuXG4gICAgLy8gSnVnZ2xlIGFyZ3VtZW50cy5cbiAgICBpZiAoaXNDdXN0b21Db250ZXh0KSB7XG4gICAgICBjb250ZXh0ID0gdWE7XG4gICAgICB1YSA9IG51bGw7XG4gICAgfVxuXG4gICAgLyoqIEJyb3dzZXIgbmF2aWdhdG9yIG9iamVjdC4gKi9cbiAgICB2YXIgbmF2ID0gY29udGV4dC5uYXZpZ2F0b3IgfHwge307XG5cbiAgICAvKiogQnJvd3NlciB1c2VyIGFnZW50IHN0cmluZy4gKi9cbiAgICB2YXIgdXNlckFnZW50ID0gbmF2LnVzZXJBZ2VudCB8fCAnJztcblxuICAgIHVhIHx8ICh1YSA9IHVzZXJBZ2VudCk7XG5cbiAgICAvKiogVXNlZCB0byBmbGFnIHdoZW4gYHRoaXNCaW5kaW5nYCBpcyB0aGUgW01vZHVsZVNjb3BlXS4gKi9cbiAgICB2YXIgaXNNb2R1bGVTY29wZSA9IGlzQ3VzdG9tQ29udGV4dCB8fCB0aGlzQmluZGluZyA9PSBvbGRSb290O1xuXG4gICAgLyoqIFVzZWQgdG8gZGV0ZWN0IGlmIGJyb3dzZXIgaXMgbGlrZSBDaHJvbWUuICovXG4gICAgdmFyIGxpa2VDaHJvbWUgPSBpc0N1c3RvbUNvbnRleHRcbiAgICAgID8gISFuYXYubGlrZUNocm9tZVxuICAgICAgOiAvXFxiQ2hyb21lXFxiLy50ZXN0KHVhKSAmJiAhL2ludGVybmFsfFxcbi9pLnRlc3QodG9TdHJpbmcudG9TdHJpbmcoKSk7XG5cbiAgICAvKiogSW50ZXJuYWwgYFtbQ2xhc3NdXWAgdmFsdWUgc2hvcnRjdXRzLiAqL1xuICAgIHZhciBvYmplY3RDbGFzcyA9ICdPYmplY3QnLFxuICAgICAgICBhaXJSdW50aW1lQ2xhc3MgPSBpc0N1c3RvbUNvbnRleHQgPyBvYmplY3RDbGFzcyA6ICdTY3JpcHRCcmlkZ2luZ1Byb3h5T2JqZWN0JyxcbiAgICAgICAgZW52aXJvQ2xhc3MgPSBpc0N1c3RvbUNvbnRleHQgPyBvYmplY3RDbGFzcyA6ICdFbnZpcm9ubWVudCcsXG4gICAgICAgIGphdmFDbGFzcyA9IChpc0N1c3RvbUNvbnRleHQgJiYgY29udGV4dC5qYXZhKSA/ICdKYXZhUGFja2FnZScgOiBnZXRDbGFzc09mKGNvbnRleHQuamF2YSksXG4gICAgICAgIHBoYW50b21DbGFzcyA9IGlzQ3VzdG9tQ29udGV4dCA/IG9iamVjdENsYXNzIDogJ1J1bnRpbWVPYmplY3QnO1xuXG4gICAgLyoqIERldGVjdCBKYXZhIGVudmlyb25tZW50cy4gKi9cbiAgICB2YXIgamF2YSA9IC9cXGJKYXZhLy50ZXN0KGphdmFDbGFzcykgJiYgY29udGV4dC5qYXZhO1xuXG4gICAgLyoqIERldGVjdCBSaGluby4gKi9cbiAgICB2YXIgcmhpbm8gPSBqYXZhICYmIGdldENsYXNzT2YoY29udGV4dC5lbnZpcm9ubWVudCkgPT0gZW52aXJvQ2xhc3M7XG5cbiAgICAvKiogQSBjaGFyYWN0ZXIgdG8gcmVwcmVzZW50IGFscGhhLiAqL1xuICAgIHZhciBhbHBoYSA9IGphdmEgPyAnYScgOiAnXFx1MDNiMSc7XG5cbiAgICAvKiogQSBjaGFyYWN0ZXIgdG8gcmVwcmVzZW50IGJldGEuICovXG4gICAgdmFyIGJldGEgPSBqYXZhID8gJ2InIDogJ1xcdTAzYjInO1xuXG4gICAgLyoqIEJyb3dzZXIgZG9jdW1lbnQgb2JqZWN0LiAqL1xuICAgIHZhciBkb2MgPSBjb250ZXh0LmRvY3VtZW50IHx8IHt9O1xuXG4gICAgLyoqXG4gICAgICogRGV0ZWN0IE9wZXJhIGJyb3dzZXIgKFByZXN0by1iYXNlZCkuXG4gICAgICogaHR0cDovL3d3dy5ob3d0b2NyZWF0ZS5jby51ay9vcGVyYVN0dWZmL29wZXJhT2JqZWN0Lmh0bWxcbiAgICAgKiBodHRwOi8vZGV2Lm9wZXJhLmNvbS9hcnRpY2xlcy92aWV3L29wZXJhLW1pbmktd2ViLWNvbnRlbnQtYXV0aG9yaW5nLWd1aWRlbGluZXMvI29wZXJhbWluaVxuICAgICAqL1xuICAgIHZhciBvcGVyYSA9IGNvbnRleHQub3BlcmFtaW5pIHx8IGNvbnRleHQub3BlcmE7XG5cbiAgICAvKiogT3BlcmEgYFtbQ2xhc3NdXWAuICovXG4gICAgdmFyIG9wZXJhQ2xhc3MgPSByZU9wZXJhLnRlc3Qob3BlcmFDbGFzcyA9IChpc0N1c3RvbUNvbnRleHQgJiYgb3BlcmEpID8gb3BlcmFbJ1tbQ2xhc3NdXSddIDogZ2V0Q2xhc3NPZihvcGVyYSkpXG4gICAgICA/IG9wZXJhQ2xhc3NcbiAgICAgIDogKG9wZXJhID0gbnVsbCk7XG5cbiAgICAvKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG5cbiAgICAvKiogVGVtcG9yYXJ5IHZhcmlhYmxlIHVzZWQgb3ZlciB0aGUgc2NyaXB0J3MgbGlmZXRpbWUuICovXG4gICAgdmFyIGRhdGE7XG5cbiAgICAvKiogVGhlIENQVSBhcmNoaXRlY3R1cmUuICovXG4gICAgdmFyIGFyY2ggPSB1YTtcblxuICAgIC8qKiBQbGF0Zm9ybSBkZXNjcmlwdGlvbiBhcnJheS4gKi9cbiAgICB2YXIgZGVzY3JpcHRpb24gPSBbXTtcblxuICAgIC8qKiBQbGF0Zm9ybSBhbHBoYS9iZXRhIGluZGljYXRvci4gKi9cbiAgICB2YXIgcHJlcmVsZWFzZSA9IG51bGw7XG5cbiAgICAvKiogQSBmbGFnIHRvIGluZGljYXRlIHRoYXQgZW52aXJvbm1lbnQgZmVhdHVyZXMgc2hvdWxkIGJlIHVzZWQgdG8gcmVzb2x2ZSB0aGUgcGxhdGZvcm0uICovXG4gICAgdmFyIHVzZUZlYXR1cmVzID0gdWEgPT0gdXNlckFnZW50O1xuXG4gICAgLyoqIFRoZSBicm93c2VyL2Vudmlyb25tZW50IHZlcnNpb24uICovXG4gICAgdmFyIHZlcnNpb24gPSB1c2VGZWF0dXJlcyAmJiBvcGVyYSAmJiB0eXBlb2Ygb3BlcmEudmVyc2lvbiA9PSAnZnVuY3Rpb24nICYmIG9wZXJhLnZlcnNpb24oKTtcblxuICAgIC8qKiBBIGZsYWcgdG8gaW5kaWNhdGUgaWYgdGhlIE9TIGVuZHMgd2l0aCBcIi8gVmVyc2lvblwiICovXG4gICAgdmFyIGlzU3BlY2lhbENhc2VkT1M7XG5cbiAgICAvKiBEZXRlY3RhYmxlIGxheW91dCBlbmdpbmVzIChvcmRlciBpcyBpbXBvcnRhbnQpLiAqL1xuICAgIHZhciBsYXlvdXQgPSBnZXRMYXlvdXQoW1xuICAgICAgeyAnbGFiZWwnOiAnRWRnZUhUTUwnLCAncGF0dGVybic6ICdFZGdlJyB9LFxuICAgICAgJ1RyaWRlbnQnLFxuICAgICAgeyAnbGFiZWwnOiAnV2ViS2l0JywgJ3BhdHRlcm4nOiAnQXBwbGVXZWJLaXQnIH0sXG4gICAgICAnaUNhYicsXG4gICAgICAnUHJlc3RvJyxcbiAgICAgICdOZXRGcm9udCcsXG4gICAgICAnVGFzbWFuJyxcbiAgICAgICdLSFRNTCcsXG4gICAgICAnR2Vja28nXG4gICAgXSk7XG5cbiAgICAvKiBEZXRlY3RhYmxlIGJyb3dzZXIgbmFtZXMgKG9yZGVyIGlzIGltcG9ydGFudCkuICovXG4gICAgdmFyIG5hbWUgPSBnZXROYW1lKFtcbiAgICAgICdBZG9iZSBBSVInLFxuICAgICAgJ0Fyb3JhJyxcbiAgICAgICdBdmFudCBCcm93c2VyJyxcbiAgICAgICdCcmVhY2gnLFxuICAgICAgJ0NhbWlubycsXG4gICAgICAnRWxlY3Ryb24nLFxuICAgICAgJ0VwaXBoYW55JyxcbiAgICAgICdGZW5uZWMnLFxuICAgICAgJ0Zsb2NrJyxcbiAgICAgICdHYWxlb24nLFxuICAgICAgJ0dyZWVuQnJvd3NlcicsXG4gICAgICAnaUNhYicsXG4gICAgICAnSWNld2Vhc2VsJyxcbiAgICAgICdLLU1lbGVvbicsXG4gICAgICAnS29ucXVlcm9yJyxcbiAgICAgICdMdW5hc2NhcGUnLFxuICAgICAgJ01heHRob24nLFxuICAgICAgeyAnbGFiZWwnOiAnTWljcm9zb2Z0IEVkZ2UnLCAncGF0dGVybic6ICdFZGdlJyB9LFxuICAgICAgJ01pZG9yaScsXG4gICAgICAnTm9vayBCcm93c2VyJyxcbiAgICAgICdQYWxlTW9vbicsXG4gICAgICAnUGhhbnRvbUpTJyxcbiAgICAgICdSYXZlbicsXG4gICAgICAnUmVrb25xJyxcbiAgICAgICdSb2NrTWVsdCcsXG4gICAgICB7ICdsYWJlbCc6ICdTYW1zdW5nIEludGVybmV0JywgJ3BhdHRlcm4nOiAnU2Ftc3VuZ0Jyb3dzZXInIH0sXG4gICAgICAnU2VhTW9ua2V5JyxcbiAgICAgIHsgJ2xhYmVsJzogJ1NpbGsnLCAncGF0dGVybic6ICcoPzpDbG91ZDl8U2lsay1BY2NlbGVyYXRlZCknIH0sXG4gICAgICAnU2xlaXBuaXInLFxuICAgICAgJ1NsaW1Ccm93c2VyJyxcbiAgICAgIHsgJ2xhYmVsJzogJ1NSV2FyZSBJcm9uJywgJ3BhdHRlcm4nOiAnSXJvbicgfSxcbiAgICAgICdTdW5yaXNlJyxcbiAgICAgICdTd2lmdGZveCcsXG4gICAgICAnV2F0ZXJmb3gnLFxuICAgICAgJ1dlYlBvc2l0aXZlJyxcbiAgICAgICdPcGVyYSBNaW5pJyxcbiAgICAgIHsgJ2xhYmVsJzogJ09wZXJhIE1pbmknLCAncGF0dGVybic6ICdPUGlPUycgfSxcbiAgICAgICdPcGVyYScsXG4gICAgICB7ICdsYWJlbCc6ICdPcGVyYScsICdwYXR0ZXJuJzogJ09QUicgfSxcbiAgICAgICdDaHJvbWUnLFxuICAgICAgeyAnbGFiZWwnOiAnQ2hyb21lIE1vYmlsZScsICdwYXR0ZXJuJzogJyg/OkNyaU9TfENyTW8pJyB9LFxuICAgICAgeyAnbGFiZWwnOiAnRmlyZWZveCcsICdwYXR0ZXJuJzogJyg/OkZpcmVmb3h8TWluZWZpZWxkKScgfSxcbiAgICAgIHsgJ2xhYmVsJzogJ0ZpcmVmb3ggZm9yIGlPUycsICdwYXR0ZXJuJzogJ0Z4aU9TJyB9LFxuICAgICAgeyAnbGFiZWwnOiAnSUUnLCAncGF0dGVybic6ICdJRU1vYmlsZScgfSxcbiAgICAgIHsgJ2xhYmVsJzogJ0lFJywgJ3BhdHRlcm4nOiAnTVNJRScgfSxcbiAgICAgICdTYWZhcmknXG4gICAgXSk7XG5cbiAgICAvKiBEZXRlY3RhYmxlIHByb2R1Y3RzIChvcmRlciBpcyBpbXBvcnRhbnQpLiAqL1xuICAgIHZhciBwcm9kdWN0ID0gZ2V0UHJvZHVjdChbXG4gICAgICB7ICdsYWJlbCc6ICdCbGFja0JlcnJ5JywgJ3BhdHRlcm4nOiAnQkIxMCcgfSxcbiAgICAgICdCbGFja0JlcnJ5JyxcbiAgICAgIHsgJ2xhYmVsJzogJ0dhbGF4eSBTJywgJ3BhdHRlcm4nOiAnR1QtSTkwMDAnIH0sXG4gICAgICB7ICdsYWJlbCc6ICdHYWxheHkgUzInLCAncGF0dGVybic6ICdHVC1JOTEwMCcgfSxcbiAgICAgIHsgJ2xhYmVsJzogJ0dhbGF4eSBTMycsICdwYXR0ZXJuJzogJ0dULUk5MzAwJyB9LFxuICAgICAgeyAnbGFiZWwnOiAnR2FsYXh5IFM0JywgJ3BhdHRlcm4nOiAnR1QtSTk1MDAnIH0sXG4gICAgICB7ICdsYWJlbCc6ICdHYWxheHkgUzUnLCAncGF0dGVybic6ICdTTS1HOTAwJyB9LFxuICAgICAgeyAnbGFiZWwnOiAnR2FsYXh5IFM2JywgJ3BhdHRlcm4nOiAnU00tRzkyMCcgfSxcbiAgICAgIHsgJ2xhYmVsJzogJ0dhbGF4eSBTNiBFZGdlJywgJ3BhdHRlcm4nOiAnU00tRzkyNScgfSxcbiAgICAgIHsgJ2xhYmVsJzogJ0dhbGF4eSBTNycsICdwYXR0ZXJuJzogJ1NNLUc5MzAnIH0sXG4gICAgICB7ICdsYWJlbCc6ICdHYWxheHkgUzcgRWRnZScsICdwYXR0ZXJuJzogJ1NNLUc5MzUnIH0sXG4gICAgICAnR29vZ2xlIFRWJyxcbiAgICAgICdMdW1pYScsXG4gICAgICAnaVBhZCcsXG4gICAgICAnaVBvZCcsXG4gICAgICAnaVBob25lJyxcbiAgICAgICdLaW5kbGUnLFxuICAgICAgeyAnbGFiZWwnOiAnS2luZGxlIEZpcmUnLCAncGF0dGVybic6ICcoPzpDbG91ZDl8U2lsay1BY2NlbGVyYXRlZCknIH0sXG4gICAgICAnTmV4dXMnLFxuICAgICAgJ05vb2snLFxuICAgICAgJ1BsYXlCb29rJyxcbiAgICAgICdQbGF5U3RhdGlvbiBWaXRhJyxcbiAgICAgICdQbGF5U3RhdGlvbicsXG4gICAgICAnVG91Y2hQYWQnLFxuICAgICAgJ1RyYW5zZm9ybWVyJyxcbiAgICAgIHsgJ2xhYmVsJzogJ1dpaSBVJywgJ3BhdHRlcm4nOiAnV2lpVScgfSxcbiAgICAgICdXaWknLFxuICAgICAgJ1hib3ggT25lJyxcbiAgICAgIHsgJ2xhYmVsJzogJ1hib3ggMzYwJywgJ3BhdHRlcm4nOiAnWGJveCcgfSxcbiAgICAgICdYb29tJ1xuICAgIF0pO1xuXG4gICAgLyogRGV0ZWN0YWJsZSBtYW51ZmFjdHVyZXJzLiAqL1xuICAgIHZhciBtYW51ZmFjdHVyZXIgPSBnZXRNYW51ZmFjdHVyZXIoe1xuICAgICAgJ0FwcGxlJzogeyAnaVBhZCc6IDEsICdpUGhvbmUnOiAxLCAnaVBvZCc6IDEgfSxcbiAgICAgICdBcmNob3MnOiB7fSxcbiAgICAgICdBbWF6b24nOiB7ICdLaW5kbGUnOiAxLCAnS2luZGxlIEZpcmUnOiAxIH0sXG4gICAgICAnQXN1cyc6IHsgJ1RyYW5zZm9ybWVyJzogMSB9LFxuICAgICAgJ0Jhcm5lcyAmIE5vYmxlJzogeyAnTm9vayc6IDEgfSxcbiAgICAgICdCbGFja0JlcnJ5JzogeyAnUGxheUJvb2snOiAxIH0sXG4gICAgICAnR29vZ2xlJzogeyAnR29vZ2xlIFRWJzogMSwgJ05leHVzJzogMSB9LFxuICAgICAgJ0hQJzogeyAnVG91Y2hQYWQnOiAxIH0sXG4gICAgICAnSFRDJzoge30sXG4gICAgICAnTEcnOiB7fSxcbiAgICAgICdNaWNyb3NvZnQnOiB7ICdYYm94JzogMSwgJ1hib3ggT25lJzogMSB9LFxuICAgICAgJ01vdG9yb2xhJzogeyAnWG9vbSc6IDEgfSxcbiAgICAgICdOaW50ZW5kbyc6IHsgJ1dpaSBVJzogMSwgICdXaWknOiAxIH0sXG4gICAgICAnTm9raWEnOiB7ICdMdW1pYSc6IDEgfSxcbiAgICAgICdTYW1zdW5nJzogeyAnR2FsYXh5IFMnOiAxLCAnR2FsYXh5IFMyJzogMSwgJ0dhbGF4eSBTMyc6IDEsICdHYWxheHkgUzQnOiAxIH0sXG4gICAgICAnU29ueSc6IHsgJ1BsYXlTdGF0aW9uJzogMSwgJ1BsYXlTdGF0aW9uIFZpdGEnOiAxIH1cbiAgICB9KTtcblxuICAgIC8qIERldGVjdGFibGUgb3BlcmF0aW5nIHN5c3RlbXMgKG9yZGVyIGlzIGltcG9ydGFudCkuICovXG4gICAgdmFyIG9zID0gZ2V0T1MoW1xuICAgICAgJ1dpbmRvd3MgUGhvbmUnLFxuICAgICAgJ0FuZHJvaWQnLFxuICAgICAgJ0NlbnRPUycsXG4gICAgICB7ICdsYWJlbCc6ICdDaHJvbWUgT1MnLCAncGF0dGVybic6ICdDck9TJyB9LFxuICAgICAgJ0RlYmlhbicsXG4gICAgICAnRmVkb3JhJyxcbiAgICAgICdGcmVlQlNEJyxcbiAgICAgICdHZW50b28nLFxuICAgICAgJ0hhaWt1JyxcbiAgICAgICdLdWJ1bnR1JyxcbiAgICAgICdMaW51eCBNaW50JyxcbiAgICAgICdPcGVuQlNEJyxcbiAgICAgICdSZWQgSGF0JyxcbiAgICAgICdTdVNFJyxcbiAgICAgICdVYnVudHUnLFxuICAgICAgJ1h1YnVudHUnLFxuICAgICAgJ0N5Z3dpbicsXG4gICAgICAnU3ltYmlhbiBPUycsXG4gICAgICAnaHB3T1MnLFxuICAgICAgJ3dlYk9TICcsXG4gICAgICAnd2ViT1MnLFxuICAgICAgJ1RhYmxldCBPUycsXG4gICAgICAnVGl6ZW4nLFxuICAgICAgJ0xpbnV4JyxcbiAgICAgICdNYWMgT1MgWCcsXG4gICAgICAnTWFjaW50b3NoJyxcbiAgICAgICdNYWMnLFxuICAgICAgJ1dpbmRvd3MgOTg7JyxcbiAgICAgICdXaW5kb3dzICdcbiAgICBdKTtcblxuICAgIC8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cblxuICAgIC8qKlxuICAgICAqIFBpY2tzIHRoZSBsYXlvdXQgZW5naW5lIGZyb20gYW4gYXJyYXkgb2YgZ3Vlc3Nlcy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtBcnJheX0gZ3Vlc3NlcyBBbiBhcnJheSBvZiBndWVzc2VzLlxuICAgICAqIEByZXR1cm5zIHtudWxsfHN0cmluZ30gVGhlIGRldGVjdGVkIGxheW91dCBlbmdpbmUuXG4gICAgICovXG4gICAgZnVuY3Rpb24gZ2V0TGF5b3V0KGd1ZXNzZXMpIHtcbiAgICAgIHJldHVybiByZWR1Y2UoZ3Vlc3NlcywgZnVuY3Rpb24ocmVzdWx0LCBndWVzcykge1xuICAgICAgICByZXR1cm4gcmVzdWx0IHx8IFJlZ0V4cCgnXFxcXGInICsgKFxuICAgICAgICAgIGd1ZXNzLnBhdHRlcm4gfHwgcXVhbGlmeShndWVzcylcbiAgICAgICAgKSArICdcXFxcYicsICdpJykuZXhlYyh1YSkgJiYgKGd1ZXNzLmxhYmVsIHx8IGd1ZXNzKTtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFBpY2tzIHRoZSBtYW51ZmFjdHVyZXIgZnJvbSBhbiBhcnJheSBvZiBndWVzc2VzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBndWVzc2VzIEFuIG9iamVjdCBvZiBndWVzc2VzLlxuICAgICAqIEByZXR1cm5zIHtudWxsfHN0cmluZ30gVGhlIGRldGVjdGVkIG1hbnVmYWN0dXJlci5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBnZXRNYW51ZmFjdHVyZXIoZ3Vlc3Nlcykge1xuICAgICAgcmV0dXJuIHJlZHVjZShndWVzc2VzLCBmdW5jdGlvbihyZXN1bHQsIHZhbHVlLCBrZXkpIHtcbiAgICAgICAgLy8gTG9va3VwIHRoZSBtYW51ZmFjdHVyZXIgYnkgcHJvZHVjdCBvciBzY2FuIHRoZSBVQSBmb3IgdGhlIG1hbnVmYWN0dXJlci5cbiAgICAgICAgcmV0dXJuIHJlc3VsdCB8fCAoXG4gICAgICAgICAgdmFsdWVbcHJvZHVjdF0gfHxcbiAgICAgICAgICB2YWx1ZVsvXlthLXpdKyg/OiArW2Etel0rXFxiKSovaS5leGVjKHByb2R1Y3QpXSB8fFxuICAgICAgICAgIFJlZ0V4cCgnXFxcXGInICsgcXVhbGlmeShrZXkpICsgJyg/OlxcXFxifFxcXFx3KlxcXFxkKScsICdpJykuZXhlYyh1YSlcbiAgICAgICAgKSAmJiBrZXk7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBQaWNrcyB0aGUgYnJvd3NlciBuYW1lIGZyb20gYW4gYXJyYXkgb2YgZ3Vlc3Nlcy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtBcnJheX0gZ3Vlc3NlcyBBbiBhcnJheSBvZiBndWVzc2VzLlxuICAgICAqIEByZXR1cm5zIHtudWxsfHN0cmluZ30gVGhlIGRldGVjdGVkIGJyb3dzZXIgbmFtZS5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBnZXROYW1lKGd1ZXNzZXMpIHtcbiAgICAgIHJldHVybiByZWR1Y2UoZ3Vlc3NlcywgZnVuY3Rpb24ocmVzdWx0LCBndWVzcykge1xuICAgICAgICByZXR1cm4gcmVzdWx0IHx8IFJlZ0V4cCgnXFxcXGInICsgKFxuICAgICAgICAgIGd1ZXNzLnBhdHRlcm4gfHwgcXVhbGlmeShndWVzcylcbiAgICAgICAgKSArICdcXFxcYicsICdpJykuZXhlYyh1YSkgJiYgKGd1ZXNzLmxhYmVsIHx8IGd1ZXNzKTtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFBpY2tzIHRoZSBPUyBuYW1lIGZyb20gYW4gYXJyYXkgb2YgZ3Vlc3Nlcy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtBcnJheX0gZ3Vlc3NlcyBBbiBhcnJheSBvZiBndWVzc2VzLlxuICAgICAqIEByZXR1cm5zIHtudWxsfHN0cmluZ30gVGhlIGRldGVjdGVkIE9TIG5hbWUuXG4gICAgICovXG4gICAgZnVuY3Rpb24gZ2V0T1MoZ3Vlc3Nlcykge1xuICAgICAgcmV0dXJuIHJlZHVjZShndWVzc2VzLCBmdW5jdGlvbihyZXN1bHQsIGd1ZXNzKSB7XG4gICAgICAgIHZhciBwYXR0ZXJuID0gZ3Vlc3MucGF0dGVybiB8fCBxdWFsaWZ5KGd1ZXNzKTtcbiAgICAgICAgaWYgKCFyZXN1bHQgJiYgKHJlc3VsdCA9XG4gICAgICAgICAgICAgIFJlZ0V4cCgnXFxcXGInICsgcGF0dGVybiArICcoPzovW1xcXFxkLl0rfFsgXFxcXHcuXSopJywgJ2knKS5leGVjKHVhKVxuICAgICAgICAgICAgKSkge1xuICAgICAgICAgIHJlc3VsdCA9IGNsZWFudXBPUyhyZXN1bHQsIHBhdHRlcm4sIGd1ZXNzLmxhYmVsIHx8IGd1ZXNzKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUGlja3MgdGhlIHByb2R1Y3QgbmFtZSBmcm9tIGFuIGFycmF5IG9mIGd1ZXNzZXMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGd1ZXNzZXMgQW4gYXJyYXkgb2YgZ3Vlc3Nlcy5cbiAgICAgKiBAcmV0dXJucyB7bnVsbHxzdHJpbmd9IFRoZSBkZXRlY3RlZCBwcm9kdWN0IG5hbWUuXG4gICAgICovXG4gICAgZnVuY3Rpb24gZ2V0UHJvZHVjdChndWVzc2VzKSB7XG4gICAgICByZXR1cm4gcmVkdWNlKGd1ZXNzZXMsIGZ1bmN0aW9uKHJlc3VsdCwgZ3Vlc3MpIHtcbiAgICAgICAgdmFyIHBhdHRlcm4gPSBndWVzcy5wYXR0ZXJuIHx8IHF1YWxpZnkoZ3Vlc3MpO1xuICAgICAgICBpZiAoIXJlc3VsdCAmJiAocmVzdWx0ID1cbiAgICAgICAgICAgICAgUmVnRXhwKCdcXFxcYicgKyBwYXR0ZXJuICsgJyAqXFxcXGQrWy5cXFxcd19dKicsICdpJykuZXhlYyh1YSkgfHxcbiAgICAgICAgICAgICAgUmVnRXhwKCdcXFxcYicgKyBwYXR0ZXJuICsgJyAqXFxcXHcrLVtcXFxcd10qJywgJ2knKS5leGVjKHVhKSB8fFxuICAgICAgICAgICAgICBSZWdFeHAoJ1xcXFxiJyArIHBhdHRlcm4gKyAnKD86OyAqKD86W2Etel0rW18tXSk/W2Etel0rXFxcXGQrfFteICgpOy1dKiknLCAnaScpLmV4ZWModWEpXG4gICAgICAgICAgICApKSB7XG4gICAgICAgICAgLy8gU3BsaXQgYnkgZm9yd2FyZCBzbGFzaCBhbmQgYXBwZW5kIHByb2R1Y3QgdmVyc2lvbiBpZiBuZWVkZWQuXG4gICAgICAgICAgaWYgKChyZXN1bHQgPSBTdHJpbmcoKGd1ZXNzLmxhYmVsICYmICFSZWdFeHAocGF0dGVybiwgJ2knKS50ZXN0KGd1ZXNzLmxhYmVsKSkgPyBndWVzcy5sYWJlbCA6IHJlc3VsdCkuc3BsaXQoJy8nKSlbMV0gJiYgIS9bXFxkLl0rLy50ZXN0KHJlc3VsdFswXSkpIHtcbiAgICAgICAgICAgIHJlc3VsdFswXSArPSAnICcgKyByZXN1bHRbMV07XG4gICAgICAgICAgfVxuICAgICAgICAgIC8vIENvcnJlY3QgY2hhcmFjdGVyIGNhc2UgYW5kIGNsZWFudXAgc3RyaW5nLlxuICAgICAgICAgIGd1ZXNzID0gZ3Vlc3MubGFiZWwgfHwgZ3Vlc3M7XG4gICAgICAgICAgcmVzdWx0ID0gZm9ybWF0KHJlc3VsdFswXVxuICAgICAgICAgICAgLnJlcGxhY2UoUmVnRXhwKHBhdHRlcm4sICdpJyksIGd1ZXNzKVxuICAgICAgICAgICAgLnJlcGxhY2UoUmVnRXhwKCc7ICooPzonICsgZ3Vlc3MgKyAnW18tXSk/JywgJ2knKSwgJyAnKVxuICAgICAgICAgICAgLnJlcGxhY2UoUmVnRXhwKCcoJyArIGd1ZXNzICsgJylbLV8uXT8oXFxcXHcpJywgJ2knKSwgJyQxICQyJykpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXNvbHZlcyB0aGUgdmVyc2lvbiB1c2luZyBhbiBhcnJheSBvZiBVQSBwYXR0ZXJucy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtBcnJheX0gcGF0dGVybnMgQW4gYXJyYXkgb2YgVUEgcGF0dGVybnMuXG4gICAgICogQHJldHVybnMge251bGx8c3RyaW5nfSBUaGUgZGV0ZWN0ZWQgdmVyc2lvbi5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBnZXRWZXJzaW9uKHBhdHRlcm5zKSB7XG4gICAgICByZXR1cm4gcmVkdWNlKHBhdHRlcm5zLCBmdW5jdGlvbihyZXN1bHQsIHBhdHRlcm4pIHtcbiAgICAgICAgcmV0dXJuIHJlc3VsdCB8fCAoUmVnRXhwKHBhdHRlcm4gK1xuICAgICAgICAgICcoPzotW1xcXFxkLl0rL3woPzogZm9yIFtcXFxcdy1dKyk/WyAvLV0pKFtcXFxcZC5dK1teICgpOy9fLV0qKScsICdpJykuZXhlYyh1YSkgfHwgMClbMV0gfHwgbnVsbDtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgYHBsYXRmb3JtLmRlc2NyaXB0aW9uYCB3aGVuIHRoZSBwbGF0Zm9ybSBvYmplY3QgaXMgY29lcmNlZCB0byBhIHN0cmluZy5cbiAgICAgKlxuICAgICAqIEBuYW1lIHRvU3RyaW5nXG4gICAgICogQG1lbWJlck9mIHBsYXRmb3JtXG4gICAgICogQHJldHVybnMge3N0cmluZ30gUmV0dXJucyBgcGxhdGZvcm0uZGVzY3JpcHRpb25gIGlmIGF2YWlsYWJsZSwgZWxzZSBhbiBlbXB0eSBzdHJpbmcuXG4gICAgICovXG4gICAgZnVuY3Rpb24gdG9TdHJpbmdQbGF0Zm9ybSgpIHtcbiAgICAgIHJldHVybiB0aGlzLmRlc2NyaXB0aW9uIHx8ICcnO1xuICAgIH1cblxuICAgIC8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cblxuICAgIC8vIENvbnZlcnQgbGF5b3V0IHRvIGFuIGFycmF5IHNvIHdlIGNhbiBhZGQgZXh0cmEgZGV0YWlscy5cbiAgICBsYXlvdXQgJiYgKGxheW91dCA9IFtsYXlvdXRdKTtcblxuICAgIC8vIERldGVjdCBwcm9kdWN0IG5hbWVzIHRoYXQgY29udGFpbiB0aGVpciBtYW51ZmFjdHVyZXIncyBuYW1lLlxuICAgIGlmIChtYW51ZmFjdHVyZXIgJiYgIXByb2R1Y3QpIHtcbiAgICAgIHByb2R1Y3QgPSBnZXRQcm9kdWN0KFttYW51ZmFjdHVyZXJdKTtcbiAgICB9XG4gICAgLy8gQ2xlYW4gdXAgR29vZ2xlIFRWLlxuICAgIGlmICgoZGF0YSA9IC9cXGJHb29nbGUgVFZcXGIvLmV4ZWMocHJvZHVjdCkpKSB7XG4gICAgICBwcm9kdWN0ID0gZGF0YVswXTtcbiAgICB9XG4gICAgLy8gRGV0ZWN0IHNpbXVsYXRvcnMuXG4gICAgaWYgKC9cXGJTaW11bGF0b3JcXGIvaS50ZXN0KHVhKSkge1xuICAgICAgcHJvZHVjdCA9IChwcm9kdWN0ID8gcHJvZHVjdCArICcgJyA6ICcnKSArICdTaW11bGF0b3InO1xuICAgIH1cbiAgICAvLyBEZXRlY3QgT3BlcmEgTWluaSA4KyBydW5uaW5nIGluIFR1cmJvL1VuY29tcHJlc3NlZCBtb2RlIG9uIGlPUy5cbiAgICBpZiAobmFtZSA9PSAnT3BlcmEgTWluaScgJiYgL1xcYk9QaU9TXFxiLy50ZXN0KHVhKSkge1xuICAgICAgZGVzY3JpcHRpb24ucHVzaCgncnVubmluZyBpbiBUdXJiby9VbmNvbXByZXNzZWQgbW9kZScpO1xuICAgIH1cbiAgICAvLyBEZXRlY3QgSUUgTW9iaWxlIDExLlxuICAgIGlmIChuYW1lID09ICdJRScgJiYgL1xcYmxpa2UgaVBob25lIE9TXFxiLy50ZXN0KHVhKSkge1xuICAgICAgZGF0YSA9IHBhcnNlKHVhLnJlcGxhY2UoL2xpa2UgaVBob25lIE9TLywgJycpKTtcbiAgICAgIG1hbnVmYWN0dXJlciA9IGRhdGEubWFudWZhY3R1cmVyO1xuICAgICAgcHJvZHVjdCA9IGRhdGEucHJvZHVjdDtcbiAgICB9XG4gICAgLy8gRGV0ZWN0IGlPUy5cbiAgICBlbHNlIGlmICgvXmlQLy50ZXN0KHByb2R1Y3QpKSB7XG4gICAgICBuYW1lIHx8IChuYW1lID0gJ1NhZmFyaScpO1xuICAgICAgb3MgPSAnaU9TJyArICgoZGF0YSA9IC8gT1MgKFtcXGRfXSspL2kuZXhlYyh1YSkpXG4gICAgICAgID8gJyAnICsgZGF0YVsxXS5yZXBsYWNlKC9fL2csICcuJylcbiAgICAgICAgOiAnJyk7XG4gICAgfVxuICAgIC8vIERldGVjdCBLdWJ1bnR1LlxuICAgIGVsc2UgaWYgKG5hbWUgPT0gJ0tvbnF1ZXJvcicgJiYgIS9idW50dS9pLnRlc3Qob3MpKSB7XG4gICAgICBvcyA9ICdLdWJ1bnR1JztcbiAgICB9XG4gICAgLy8gRGV0ZWN0IEFuZHJvaWQgYnJvd3NlcnMuXG4gICAgZWxzZSBpZiAoKG1hbnVmYWN0dXJlciAmJiBtYW51ZmFjdHVyZXIgIT0gJ0dvb2dsZScgJiZcbiAgICAgICAgKCgvQ2hyb21lLy50ZXN0KG5hbWUpICYmICEvXFxiTW9iaWxlIFNhZmFyaVxcYi9pLnRlc3QodWEpKSB8fCAvXFxiVml0YVxcYi8udGVzdChwcm9kdWN0KSkpIHx8XG4gICAgICAgICgvXFxiQW5kcm9pZFxcYi8udGVzdChvcykgJiYgL15DaHJvbWUvLnRlc3QobmFtZSkgJiYgL1xcYlZlcnNpb25cXC8vaS50ZXN0KHVhKSkpIHtcbiAgICAgIG5hbWUgPSAnQW5kcm9pZCBCcm93c2VyJztcbiAgICAgIG9zID0gL1xcYkFuZHJvaWRcXGIvLnRlc3Qob3MpID8gb3MgOiAnQW5kcm9pZCc7XG4gICAgfVxuICAgIC8vIERldGVjdCBTaWxrIGRlc2t0b3AvYWNjZWxlcmF0ZWQgbW9kZXMuXG4gICAgZWxzZSBpZiAobmFtZSA9PSAnU2lsaycpIHtcbiAgICAgIGlmICghL1xcYk1vYmkvaS50ZXN0KHVhKSkge1xuICAgICAgICBvcyA9ICdBbmRyb2lkJztcbiAgICAgICAgZGVzY3JpcHRpb24udW5zaGlmdCgnZGVza3RvcCBtb2RlJyk7XG4gICAgICB9XG4gICAgICBpZiAoL0FjY2VsZXJhdGVkICo9ICp0cnVlL2kudGVzdCh1YSkpIHtcbiAgICAgICAgZGVzY3JpcHRpb24udW5zaGlmdCgnYWNjZWxlcmF0ZWQnKTtcbiAgICAgIH1cbiAgICB9XG4gICAgLy8gRGV0ZWN0IFBhbGVNb29uIGlkZW50aWZ5aW5nIGFzIEZpcmVmb3guXG4gICAgZWxzZSBpZiAobmFtZSA9PSAnUGFsZU1vb24nICYmIChkYXRhID0gL1xcYkZpcmVmb3hcXC8oW1xcZC5dKylcXGIvLmV4ZWModWEpKSkge1xuICAgICAgZGVzY3JpcHRpb24ucHVzaCgnaWRlbnRpZnlpbmcgYXMgRmlyZWZveCAnICsgZGF0YVsxXSk7XG4gICAgfVxuICAgIC8vIERldGVjdCBGaXJlZm94IE9TIGFuZCBwcm9kdWN0cyBydW5uaW5nIEZpcmVmb3guXG4gICAgZWxzZSBpZiAobmFtZSA9PSAnRmlyZWZveCcgJiYgKGRhdGEgPSAvXFxiKE1vYmlsZXxUYWJsZXR8VFYpXFxiL2kuZXhlYyh1YSkpKSB7XG4gICAgICBvcyB8fCAob3MgPSAnRmlyZWZveCBPUycpO1xuICAgICAgcHJvZHVjdCB8fCAocHJvZHVjdCA9IGRhdGFbMV0pO1xuICAgIH1cbiAgICAvLyBEZXRlY3QgZmFsc2UgcG9zaXRpdmVzIGZvciBGaXJlZm94L1NhZmFyaS5cbiAgICBlbHNlIGlmICghbmFtZSB8fCAoZGF0YSA9ICEvXFxiTWluZWZpZWxkXFxiL2kudGVzdCh1YSkgJiYgL1xcYig/OkZpcmVmb3h8U2FmYXJpKVxcYi8uZXhlYyhuYW1lKSkpIHtcbiAgICAgIC8vIEVzY2FwZSB0aGUgYC9gIGZvciBGaXJlZm94IDEuXG4gICAgICBpZiAobmFtZSAmJiAhcHJvZHVjdCAmJiAvW1xcLyxdfF5bXihdKz9cXCkvLnRlc3QodWEuc2xpY2UodWEuaW5kZXhPZihkYXRhICsgJy8nKSArIDgpKSkge1xuICAgICAgICAvLyBDbGVhciBuYW1lIG9mIGZhbHNlIHBvc2l0aXZlcy5cbiAgICAgICAgbmFtZSA9IG51bGw7XG4gICAgICB9XG4gICAgICAvLyBSZWFzc2lnbiBhIGdlbmVyaWMgbmFtZS5cbiAgICAgIGlmICgoZGF0YSA9IHByb2R1Y3QgfHwgbWFudWZhY3R1cmVyIHx8IG9zKSAmJlxuICAgICAgICAgIChwcm9kdWN0IHx8IG1hbnVmYWN0dXJlciB8fCAvXFxiKD86QW5kcm9pZHxTeW1iaWFuIE9TfFRhYmxldCBPU3x3ZWJPUylcXGIvLnRlc3Qob3MpKSkge1xuICAgICAgICBuYW1lID0gL1thLXpdKyg/OiBIYXQpPy9pLmV4ZWMoL1xcYkFuZHJvaWRcXGIvLnRlc3Qob3MpID8gb3MgOiBkYXRhKSArICcgQnJvd3Nlcic7XG4gICAgICB9XG4gICAgfVxuICAgIC8vIEFkZCBDaHJvbWUgdmVyc2lvbiB0byBkZXNjcmlwdGlvbiBmb3IgRWxlY3Ryb24uXG4gICAgZWxzZSBpZiAobmFtZSA9PSAnRWxlY3Ryb24nICYmIChkYXRhID0gKC9cXGJDaHJvbWVcXC8oW1xcZC5dKylcXGIvLmV4ZWModWEpIHx8IDApWzFdKSkge1xuICAgICAgZGVzY3JpcHRpb24ucHVzaCgnQ2hyb21pdW0gJyArIGRhdGEpO1xuICAgIH1cbiAgICAvLyBEZXRlY3Qgbm9uLU9wZXJhIChQcmVzdG8tYmFzZWQpIHZlcnNpb25zIChvcmRlciBpcyBpbXBvcnRhbnQpLlxuICAgIGlmICghdmVyc2lvbikge1xuICAgICAgdmVyc2lvbiA9IGdldFZlcnNpb24oW1xuICAgICAgICAnKD86Q2xvdWQ5fENyaU9TfENyTW98RWRnZXxGeGlPU3xJRU1vYmlsZXxJcm9ufE9wZXJhID9NaW5pfE9QaU9TfE9QUnxSYXZlbnxTYW1zdW5nQnJvd3NlcnxTaWxrKD8hL1tcXFxcZC5dKyQpKScsXG4gICAgICAgICdWZXJzaW9uJyxcbiAgICAgICAgcXVhbGlmeShuYW1lKSxcbiAgICAgICAgJyg/OkZpcmVmb3h8TWluZWZpZWxkfE5ldEZyb250KSdcbiAgICAgIF0pO1xuICAgIH1cbiAgICAvLyBEZXRlY3Qgc3R1YmJvcm4gbGF5b3V0IGVuZ2luZXMuXG4gICAgaWYgKChkYXRhID1cbiAgICAgICAgICBsYXlvdXQgPT0gJ2lDYWInICYmIHBhcnNlRmxvYXQodmVyc2lvbikgPiAzICYmICdXZWJLaXQnIHx8XG4gICAgICAgICAgL1xcYk9wZXJhXFxiLy50ZXN0KG5hbWUpICYmICgvXFxiT1BSXFxiLy50ZXN0KHVhKSA/ICdCbGluaycgOiAnUHJlc3RvJykgfHxcbiAgICAgICAgICAvXFxiKD86TWlkb3JpfE5vb2t8U2FmYXJpKVxcYi9pLnRlc3QodWEpICYmICEvXig/OlRyaWRlbnR8RWRnZUhUTUwpJC8udGVzdChsYXlvdXQpICYmICdXZWJLaXQnIHx8XG4gICAgICAgICAgIWxheW91dCAmJiAvXFxiTVNJRVxcYi9pLnRlc3QodWEpICYmIChvcyA9PSAnTWFjIE9TJyA/ICdUYXNtYW4nIDogJ1RyaWRlbnQnKSB8fFxuICAgICAgICAgIGxheW91dCA9PSAnV2ViS2l0JyAmJiAvXFxiUGxheVN0YXRpb25cXGIoPyEgVml0YVxcYikvaS50ZXN0KG5hbWUpICYmICdOZXRGcm9udCdcbiAgICAgICAgKSkge1xuICAgICAgbGF5b3V0ID0gW2RhdGFdO1xuICAgIH1cbiAgICAvLyBEZXRlY3QgV2luZG93cyBQaG9uZSA3IGRlc2t0b3AgbW9kZS5cbiAgICBpZiAobmFtZSA9PSAnSUUnICYmIChkYXRhID0gKC87ICooPzpYQkxXUHxadW5lV1ApKFxcZCspL2kuZXhlYyh1YSkgfHwgMClbMV0pKSB7XG4gICAgICBuYW1lICs9ICcgTW9iaWxlJztcbiAgICAgIG9zID0gJ1dpbmRvd3MgUGhvbmUgJyArICgvXFwrJC8udGVzdChkYXRhKSA/IGRhdGEgOiBkYXRhICsgJy54Jyk7XG4gICAgICBkZXNjcmlwdGlvbi51bnNoaWZ0KCdkZXNrdG9wIG1vZGUnKTtcbiAgICB9XG4gICAgLy8gRGV0ZWN0IFdpbmRvd3MgUGhvbmUgOC54IGRlc2t0b3AgbW9kZS5cbiAgICBlbHNlIGlmICgvXFxiV1BEZXNrdG9wXFxiL2kudGVzdCh1YSkpIHtcbiAgICAgIG5hbWUgPSAnSUUgTW9iaWxlJztcbiAgICAgIG9zID0gJ1dpbmRvd3MgUGhvbmUgOC54JztcbiAgICAgIGRlc2NyaXB0aW9uLnVuc2hpZnQoJ2Rlc2t0b3AgbW9kZScpO1xuICAgICAgdmVyc2lvbiB8fCAodmVyc2lvbiA9ICgvXFxicnY6KFtcXGQuXSspLy5leGVjKHVhKSB8fCAwKVsxXSk7XG4gICAgfVxuICAgIC8vIERldGVjdCBJRSAxMSBpZGVudGlmeWluZyBhcyBvdGhlciBicm93c2Vycy5cbiAgICBlbHNlIGlmIChuYW1lICE9ICdJRScgJiYgbGF5b3V0ID09ICdUcmlkZW50JyAmJiAoZGF0YSA9IC9cXGJydjooW1xcZC5dKykvLmV4ZWModWEpKSkge1xuICAgICAgaWYgKG5hbWUpIHtcbiAgICAgICAgZGVzY3JpcHRpb24ucHVzaCgnaWRlbnRpZnlpbmcgYXMgJyArIG5hbWUgKyAodmVyc2lvbiA/ICcgJyArIHZlcnNpb24gOiAnJykpO1xuICAgICAgfVxuICAgICAgbmFtZSA9ICdJRSc7XG4gICAgICB2ZXJzaW9uID0gZGF0YVsxXTtcbiAgICB9XG4gICAgLy8gTGV2ZXJhZ2UgZW52aXJvbm1lbnQgZmVhdHVyZXMuXG4gICAgaWYgKHVzZUZlYXR1cmVzKSB7XG4gICAgICAvLyBEZXRlY3Qgc2VydmVyLXNpZGUgZW52aXJvbm1lbnRzLlxuICAgICAgLy8gUmhpbm8gaGFzIGEgZ2xvYmFsIGZ1bmN0aW9uIHdoaWxlIG90aGVycyBoYXZlIGEgZ2xvYmFsIG9iamVjdC5cbiAgICAgIGlmIChpc0hvc3RUeXBlKGNvbnRleHQsICdnbG9iYWwnKSkge1xuICAgICAgICBpZiAoamF2YSkge1xuICAgICAgICAgIGRhdGEgPSBqYXZhLmxhbmcuU3lzdGVtO1xuICAgICAgICAgIGFyY2ggPSBkYXRhLmdldFByb3BlcnR5KCdvcy5hcmNoJyk7XG4gICAgICAgICAgb3MgPSBvcyB8fCBkYXRhLmdldFByb3BlcnR5KCdvcy5uYW1lJykgKyAnICcgKyBkYXRhLmdldFByb3BlcnR5KCdvcy52ZXJzaW9uJyk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHJoaW5vKSB7XG4gICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIHZlcnNpb24gPSBjb250ZXh0LnJlcXVpcmUoJ3JpbmdvL2VuZ2luZScpLnZlcnNpb24uam9pbignLicpO1xuICAgICAgICAgICAgbmFtZSA9ICdSaW5nb0pTJztcbiAgICAgICAgICB9IGNhdGNoKGUpIHtcbiAgICAgICAgICAgIGlmICgoZGF0YSA9IGNvbnRleHQuc3lzdGVtKSAmJiBkYXRhLmdsb2JhbC5zeXN0ZW0gPT0gY29udGV4dC5zeXN0ZW0pIHtcbiAgICAgICAgICAgICAgbmFtZSA9ICdOYXJ3aGFsJztcbiAgICAgICAgICAgICAgb3MgfHwgKG9zID0gZGF0YVswXS5vcyB8fCBudWxsKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKCFuYW1lKSB7XG4gICAgICAgICAgICBuYW1lID0gJ1JoaW5vJztcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAoXG4gICAgICAgICAgdHlwZW9mIGNvbnRleHQucHJvY2VzcyA9PSAnb2JqZWN0JyAmJiAhY29udGV4dC5wcm9jZXNzLmJyb3dzZXIgJiZcbiAgICAgICAgICAoZGF0YSA9IGNvbnRleHQucHJvY2VzcylcbiAgICAgICAgKSB7XG4gICAgICAgICAgaWYgKHR5cGVvZiBkYXRhLnZlcnNpb25zID09ICdvYmplY3QnKSB7XG4gICAgICAgICAgICBpZiAodHlwZW9mIGRhdGEudmVyc2lvbnMuZWxlY3Ryb24gPT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgICAgZGVzY3JpcHRpb24ucHVzaCgnTm9kZSAnICsgZGF0YS52ZXJzaW9ucy5ub2RlKTtcbiAgICAgICAgICAgICAgbmFtZSA9ICdFbGVjdHJvbic7XG4gICAgICAgICAgICAgIHZlcnNpb24gPSBkYXRhLnZlcnNpb25zLmVsZWN0cm9uO1xuICAgICAgICAgICAgfSBlbHNlIGlmICh0eXBlb2YgZGF0YS52ZXJzaW9ucy5udyA9PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgICBkZXNjcmlwdGlvbi5wdXNoKCdDaHJvbWl1bSAnICsgdmVyc2lvbiwgJ05vZGUgJyArIGRhdGEudmVyc2lvbnMubm9kZSk7XG4gICAgICAgICAgICAgIG5hbWUgPSAnTlcuanMnO1xuICAgICAgICAgICAgICB2ZXJzaW9uID0gZGF0YS52ZXJzaW9ucy5udztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKCFuYW1lKSB7XG4gICAgICAgICAgICBuYW1lID0gJ05vZGUuanMnO1xuICAgICAgICAgICAgYXJjaCA9IGRhdGEuYXJjaDtcbiAgICAgICAgICAgIG9zID0gZGF0YS5wbGF0Zm9ybTtcbiAgICAgICAgICAgIHZlcnNpb24gPSAvW1xcZC5dKy8uZXhlYyhkYXRhLnZlcnNpb24pO1xuICAgICAgICAgICAgdmVyc2lvbiA9IHZlcnNpb24gPyB2ZXJzaW9uWzBdIDogbnVsbDtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIC8vIERldGVjdCBBZG9iZSBBSVIuXG4gICAgICBlbHNlIGlmIChnZXRDbGFzc09mKChkYXRhID0gY29udGV4dC5ydW50aW1lKSkgPT0gYWlyUnVudGltZUNsYXNzKSB7XG4gICAgICAgIG5hbWUgPSAnQWRvYmUgQUlSJztcbiAgICAgICAgb3MgPSBkYXRhLmZsYXNoLnN5c3RlbS5DYXBhYmlsaXRpZXMub3M7XG4gICAgICB9XG4gICAgICAvLyBEZXRlY3QgUGhhbnRvbUpTLlxuICAgICAgZWxzZSBpZiAoZ2V0Q2xhc3NPZigoZGF0YSA9IGNvbnRleHQucGhhbnRvbSkpID09IHBoYW50b21DbGFzcykge1xuICAgICAgICBuYW1lID0gJ1BoYW50b21KUyc7XG4gICAgICAgIHZlcnNpb24gPSAoZGF0YSA9IGRhdGEudmVyc2lvbiB8fCBudWxsKSAmJiAoZGF0YS5tYWpvciArICcuJyArIGRhdGEubWlub3IgKyAnLicgKyBkYXRhLnBhdGNoKTtcbiAgICAgIH1cbiAgICAgIC8vIERldGVjdCBJRSBjb21wYXRpYmlsaXR5IG1vZGVzLlxuICAgICAgZWxzZSBpZiAodHlwZW9mIGRvYy5kb2N1bWVudE1vZGUgPT0gJ251bWJlcicgJiYgKGRhdGEgPSAvXFxiVHJpZGVudFxcLyhcXGQrKS9pLmV4ZWModWEpKSkge1xuICAgICAgICAvLyBXZSdyZSBpbiBjb21wYXRpYmlsaXR5IG1vZGUgd2hlbiB0aGUgVHJpZGVudCB2ZXJzaW9uICsgNCBkb2Vzbid0XG4gICAgICAgIC8vIGVxdWFsIHRoZSBkb2N1bWVudCBtb2RlLlxuICAgICAgICB2ZXJzaW9uID0gW3ZlcnNpb24sIGRvYy5kb2N1bWVudE1vZGVdO1xuICAgICAgICBpZiAoKGRhdGEgPSArZGF0YVsxXSArIDQpICE9IHZlcnNpb25bMV0pIHtcbiAgICAgICAgICBkZXNjcmlwdGlvbi5wdXNoKCdJRSAnICsgdmVyc2lvblsxXSArICcgbW9kZScpO1xuICAgICAgICAgIGxheW91dCAmJiAobGF5b3V0WzFdID0gJycpO1xuICAgICAgICAgIHZlcnNpb25bMV0gPSBkYXRhO1xuICAgICAgICB9XG4gICAgICAgIHZlcnNpb24gPSBuYW1lID09ICdJRScgPyBTdHJpbmcodmVyc2lvblsxXS50b0ZpeGVkKDEpKSA6IHZlcnNpb25bMF07XG4gICAgICB9XG4gICAgICAvLyBEZXRlY3QgSUUgMTEgbWFza2luZyBhcyBvdGhlciBicm93c2Vycy5cbiAgICAgIGVsc2UgaWYgKHR5cGVvZiBkb2MuZG9jdW1lbnRNb2RlID09ICdudW1iZXInICYmIC9eKD86Q2hyb21lfEZpcmVmb3gpXFxiLy50ZXN0KG5hbWUpKSB7XG4gICAgICAgIGRlc2NyaXB0aW9uLnB1c2goJ21hc2tpbmcgYXMgJyArIG5hbWUgKyAnICcgKyB2ZXJzaW9uKTtcbiAgICAgICAgbmFtZSA9ICdJRSc7XG4gICAgICAgIHZlcnNpb24gPSAnMTEuMCc7XG4gICAgICAgIGxheW91dCA9IFsnVHJpZGVudCddO1xuICAgICAgICBvcyA9ICdXaW5kb3dzJztcbiAgICAgIH1cbiAgICAgIG9zID0gb3MgJiYgZm9ybWF0KG9zKTtcbiAgICB9XG4gICAgLy8gRGV0ZWN0IHByZXJlbGVhc2UgcGhhc2VzLlxuICAgIGlmICh2ZXJzaW9uICYmIChkYXRhID1cbiAgICAgICAgICAvKD86W2FiXXxkcHxwcmV8W2FiXVxcZCtwcmUpKD86XFxkK1xcKz8pPyQvaS5leGVjKHZlcnNpb24pIHx8XG4gICAgICAgICAgLyg/OmFscGhhfGJldGEpKD86ID9cXGQpPy9pLmV4ZWModWEgKyAnOycgKyAodXNlRmVhdHVyZXMgJiYgbmF2LmFwcE1pbm9yVmVyc2lvbikpIHx8XG4gICAgICAgICAgL1xcYk1pbmVmaWVsZFxcYi9pLnRlc3QodWEpICYmICdhJ1xuICAgICAgICApKSB7XG4gICAgICBwcmVyZWxlYXNlID0gL2IvaS50ZXN0KGRhdGEpID8gJ2JldGEnIDogJ2FscGhhJztcbiAgICAgIHZlcnNpb24gPSB2ZXJzaW9uLnJlcGxhY2UoUmVnRXhwKGRhdGEgKyAnXFxcXCs/JCcpLCAnJykgK1xuICAgICAgICAocHJlcmVsZWFzZSA9PSAnYmV0YScgPyBiZXRhIDogYWxwaGEpICsgKC9cXGQrXFwrPy8uZXhlYyhkYXRhKSB8fCAnJyk7XG4gICAgfVxuICAgIC8vIERldGVjdCBGaXJlZm94IE1vYmlsZS5cbiAgICBpZiAobmFtZSA9PSAnRmVubmVjJyB8fCBuYW1lID09ICdGaXJlZm94JyAmJiAvXFxiKD86QW5kcm9pZHxGaXJlZm94IE9TKVxcYi8udGVzdChvcykpIHtcbiAgICAgIG5hbWUgPSAnRmlyZWZveCBNb2JpbGUnO1xuICAgIH1cbiAgICAvLyBPYnNjdXJlIE1heHRob24ncyB1bnJlbGlhYmxlIHZlcnNpb24uXG4gICAgZWxzZSBpZiAobmFtZSA9PSAnTWF4dGhvbicgJiYgdmVyc2lvbikge1xuICAgICAgdmVyc2lvbiA9IHZlcnNpb24ucmVwbGFjZSgvXFwuW1xcZC5dKy8sICcueCcpO1xuICAgIH1cbiAgICAvLyBEZXRlY3QgWGJveCAzNjAgYW5kIFhib3ggT25lLlxuICAgIGVsc2UgaWYgKC9cXGJYYm94XFxiL2kudGVzdChwcm9kdWN0KSkge1xuICAgICAgaWYgKHByb2R1Y3QgPT0gJ1hib3ggMzYwJykge1xuICAgICAgICBvcyA9IG51bGw7XG4gICAgICB9XG4gICAgICBpZiAocHJvZHVjdCA9PSAnWGJveCAzNjAnICYmIC9cXGJJRU1vYmlsZVxcYi8udGVzdCh1YSkpIHtcbiAgICAgICAgZGVzY3JpcHRpb24udW5zaGlmdCgnbW9iaWxlIG1vZGUnKTtcbiAgICAgIH1cbiAgICB9XG4gICAgLy8gQWRkIG1vYmlsZSBwb3N0Zml4LlxuICAgIGVsc2UgaWYgKCgvXig/OkNocm9tZXxJRXxPcGVyYSkkLy50ZXN0KG5hbWUpIHx8IG5hbWUgJiYgIXByb2R1Y3QgJiYgIS9Ccm93c2VyfE1vYmkvLnRlc3QobmFtZSkpICYmXG4gICAgICAgIChvcyA9PSAnV2luZG93cyBDRScgfHwgL01vYmkvaS50ZXN0KHVhKSkpIHtcbiAgICAgIG5hbWUgKz0gJyBNb2JpbGUnO1xuICAgIH1cbiAgICAvLyBEZXRlY3QgSUUgcGxhdGZvcm0gcHJldmlldy5cbiAgICBlbHNlIGlmIChuYW1lID09ICdJRScgJiYgdXNlRmVhdHVyZXMpIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIGlmIChjb250ZXh0LmV4dGVybmFsID09PSBudWxsKSB7XG4gICAgICAgICAgZGVzY3JpcHRpb24udW5zaGlmdCgncGxhdGZvcm0gcHJldmlldycpO1xuICAgICAgICB9XG4gICAgICB9IGNhdGNoKGUpIHtcbiAgICAgICAgZGVzY3JpcHRpb24udW5zaGlmdCgnZW1iZWRkZWQnKTtcbiAgICAgIH1cbiAgICB9XG4gICAgLy8gRGV0ZWN0IEJsYWNrQmVycnkgT1MgdmVyc2lvbi5cbiAgICAvLyBodHRwOi8vZG9jcy5ibGFja2JlcnJ5LmNvbS9lbi9kZXZlbG9wZXJzL2RlbGl2ZXJhYmxlcy8xODE2OS9IVFRQX2hlYWRlcnNfc2VudF9ieV9CQl9Ccm93c2VyXzEyMzQ5MTFfMTEuanNwXG4gICAgZWxzZSBpZiAoKC9cXGJCbGFja0JlcnJ5XFxiLy50ZXN0KHByb2R1Y3QpIHx8IC9cXGJCQjEwXFxiLy50ZXN0KHVhKSkgJiYgKGRhdGEgPVxuICAgICAgICAgIChSZWdFeHAocHJvZHVjdC5yZXBsYWNlKC8gKy9nLCAnIConKSArICcvKFsuXFxcXGRdKyknLCAnaScpLmV4ZWModWEpIHx8IDApWzFdIHx8XG4gICAgICAgICAgdmVyc2lvblxuICAgICAgICApKSB7XG4gICAgICBkYXRhID0gW2RhdGEsIC9CQjEwLy50ZXN0KHVhKV07XG4gICAgICBvcyA9IChkYXRhWzFdID8gKHByb2R1Y3QgPSBudWxsLCBtYW51ZmFjdHVyZXIgPSAnQmxhY2tCZXJyeScpIDogJ0RldmljZSBTb2Z0d2FyZScpICsgJyAnICsgZGF0YVswXTtcbiAgICAgIHZlcnNpb24gPSBudWxsO1xuICAgIH1cbiAgICAvLyBEZXRlY3QgT3BlcmEgaWRlbnRpZnlpbmcvbWFza2luZyBpdHNlbGYgYXMgYW5vdGhlciBicm93c2VyLlxuICAgIC8vIGh0dHA6Ly93d3cub3BlcmEuY29tL3N1cHBvcnQva2Ivdmlldy84NDMvXG4gICAgZWxzZSBpZiAodGhpcyAhPSBmb3JPd24gJiYgcHJvZHVjdCAhPSAnV2lpJyAmJiAoXG4gICAgICAgICAgKHVzZUZlYXR1cmVzICYmIG9wZXJhKSB8fFxuICAgICAgICAgICgvT3BlcmEvLnRlc3QobmFtZSkgJiYgL1xcYig/Ok1TSUV8RmlyZWZveClcXGIvaS50ZXN0KHVhKSkgfHxcbiAgICAgICAgICAobmFtZSA9PSAnRmlyZWZveCcgJiYgL1xcYk9TIFggKD86XFxkK1xcLil7Mix9Ly50ZXN0KG9zKSkgfHxcbiAgICAgICAgICAobmFtZSA9PSAnSUUnICYmIChcbiAgICAgICAgICAgIChvcyAmJiAhL15XaW4vLnRlc3Qob3MpICYmIHZlcnNpb24gPiA1LjUpIHx8XG4gICAgICAgICAgICAvXFxiV2luZG93cyBYUFxcYi8udGVzdChvcykgJiYgdmVyc2lvbiA+IDggfHxcbiAgICAgICAgICAgIHZlcnNpb24gPT0gOCAmJiAhL1xcYlRyaWRlbnRcXGIvLnRlc3QodWEpXG4gICAgICAgICAgKSlcbiAgICAgICAgKSAmJiAhcmVPcGVyYS50ZXN0KChkYXRhID0gcGFyc2UuY2FsbChmb3JPd24sIHVhLnJlcGxhY2UocmVPcGVyYSwgJycpICsgJzsnKSkpICYmIGRhdGEubmFtZSkge1xuICAgICAgLy8gV2hlbiBcImlkZW50aWZ5aW5nXCIsIHRoZSBVQSBjb250YWlucyBib3RoIE9wZXJhIGFuZCB0aGUgb3RoZXIgYnJvd3NlcidzIG5hbWUuXG4gICAgICBkYXRhID0gJ2luZyBhcyAnICsgZGF0YS5uYW1lICsgKChkYXRhID0gZGF0YS52ZXJzaW9uKSA/ICcgJyArIGRhdGEgOiAnJyk7XG4gICAgICBpZiAocmVPcGVyYS50ZXN0KG5hbWUpKSB7XG4gICAgICAgIGlmICgvXFxiSUVcXGIvLnRlc3QoZGF0YSkgJiYgb3MgPT0gJ01hYyBPUycpIHtcbiAgICAgICAgICBvcyA9IG51bGw7XG4gICAgICAgIH1cbiAgICAgICAgZGF0YSA9ICdpZGVudGlmeScgKyBkYXRhO1xuICAgICAgfVxuICAgICAgLy8gV2hlbiBcIm1hc2tpbmdcIiwgdGhlIFVBIGNvbnRhaW5zIG9ubHkgdGhlIG90aGVyIGJyb3dzZXIncyBuYW1lLlxuICAgICAgZWxzZSB7XG4gICAgICAgIGRhdGEgPSAnbWFzaycgKyBkYXRhO1xuICAgICAgICBpZiAob3BlcmFDbGFzcykge1xuICAgICAgICAgIG5hbWUgPSBmb3JtYXQob3BlcmFDbGFzcy5yZXBsYWNlKC8oW2Etel0pKFtBLVpdKS9nLCAnJDEgJDInKSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgbmFtZSA9ICdPcGVyYSc7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKC9cXGJJRVxcYi8udGVzdChkYXRhKSkge1xuICAgICAgICAgIG9zID0gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIXVzZUZlYXR1cmVzKSB7XG4gICAgICAgICAgdmVyc2lvbiA9IG51bGw7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGxheW91dCA9IFsnUHJlc3RvJ107XG4gICAgICBkZXNjcmlwdGlvbi5wdXNoKGRhdGEpO1xuICAgIH1cbiAgICAvLyBEZXRlY3QgV2ViS2l0IE5pZ2h0bHkgYW5kIGFwcHJveGltYXRlIENocm9tZS9TYWZhcmkgdmVyc2lvbnMuXG4gICAgaWYgKChkYXRhID0gKC9cXGJBcHBsZVdlYktpdFxcLyhbXFxkLl0rXFwrPykvaS5leGVjKHVhKSB8fCAwKVsxXSkpIHtcbiAgICAgIC8vIENvcnJlY3QgYnVpbGQgbnVtYmVyIGZvciBudW1lcmljIGNvbXBhcmlzb24uXG4gICAgICAvLyAoZS5nLiBcIjUzMi41XCIgYmVjb21lcyBcIjUzMi4wNVwiKVxuICAgICAgZGF0YSA9IFtwYXJzZUZsb2F0KGRhdGEucmVwbGFjZSgvXFwuKFxcZCkkLywgJy4wJDEnKSksIGRhdGFdO1xuICAgICAgLy8gTmlnaHRseSBidWlsZHMgYXJlIHBvc3RmaXhlZCB3aXRoIGEgXCIrXCIuXG4gICAgICBpZiAobmFtZSA9PSAnU2FmYXJpJyAmJiBkYXRhWzFdLnNsaWNlKC0xKSA9PSAnKycpIHtcbiAgICAgICAgbmFtZSA9ICdXZWJLaXQgTmlnaHRseSc7XG4gICAgICAgIHByZXJlbGVhc2UgPSAnYWxwaGEnO1xuICAgICAgICB2ZXJzaW9uID0gZGF0YVsxXS5zbGljZSgwLCAtMSk7XG4gICAgICB9XG4gICAgICAvLyBDbGVhciBpbmNvcnJlY3QgYnJvd3NlciB2ZXJzaW9ucy5cbiAgICAgIGVsc2UgaWYgKHZlcnNpb24gPT0gZGF0YVsxXSB8fFxuICAgICAgICAgIHZlcnNpb24gPT0gKGRhdGFbMl0gPSAoL1xcYlNhZmFyaVxcLyhbXFxkLl0rXFwrPykvaS5leGVjKHVhKSB8fCAwKVsxXSkpIHtcbiAgICAgICAgdmVyc2lvbiA9IG51bGw7XG4gICAgICB9XG4gICAgICAvLyBVc2UgdGhlIGZ1bGwgQ2hyb21lIHZlcnNpb24gd2hlbiBhdmFpbGFibGUuXG4gICAgICBkYXRhWzFdID0gKC9cXGJDaHJvbWVcXC8oW1xcZC5dKykvaS5leGVjKHVhKSB8fCAwKVsxXTtcbiAgICAgIC8vIERldGVjdCBCbGluayBsYXlvdXQgZW5naW5lLlxuICAgICAgaWYgKGRhdGFbMF0gPT0gNTM3LjM2ICYmIGRhdGFbMl0gPT0gNTM3LjM2ICYmIHBhcnNlRmxvYXQoZGF0YVsxXSkgPj0gMjggJiYgbGF5b3V0ID09ICdXZWJLaXQnKSB7XG4gICAgICAgIGxheW91dCA9IFsnQmxpbmsnXTtcbiAgICAgIH1cbiAgICAgIC8vIERldGVjdCBKYXZhU2NyaXB0Q29yZS5cbiAgICAgIC8vIGh0dHA6Ly9zdGFja292ZXJmbG93LmNvbS9xdWVzdGlvbnMvNjc2ODQ3NC9ob3ctY2FuLWktZGV0ZWN0LXdoaWNoLWphdmFzY3JpcHQtZW5naW5lLXY4LW9yLWpzYy1pcy11c2VkLWF0LXJ1bnRpbWUtaW4tYW5kcm9pXG4gICAgICBpZiAoIXVzZUZlYXR1cmVzIHx8ICghbGlrZUNocm9tZSAmJiAhZGF0YVsxXSkpIHtcbiAgICAgICAgbGF5b3V0ICYmIChsYXlvdXRbMV0gPSAnbGlrZSBTYWZhcmknKTtcbiAgICAgICAgZGF0YSA9IChkYXRhID0gZGF0YVswXSwgZGF0YSA8IDQwMCA/IDEgOiBkYXRhIDwgNTAwID8gMiA6IGRhdGEgPCA1MjYgPyAzIDogZGF0YSA8IDUzMyA/IDQgOiBkYXRhIDwgNTM0ID8gJzQrJyA6IGRhdGEgPCA1MzUgPyA1IDogZGF0YSA8IDUzNyA/IDYgOiBkYXRhIDwgNTM4ID8gNyA6IGRhdGEgPCA2MDEgPyA4IDogJzgnKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGxheW91dCAmJiAobGF5b3V0WzFdID0gJ2xpa2UgQ2hyb21lJyk7XG4gICAgICAgIGRhdGEgPSBkYXRhWzFdIHx8IChkYXRhID0gZGF0YVswXSwgZGF0YSA8IDUzMCA/IDEgOiBkYXRhIDwgNTMyID8gMiA6IGRhdGEgPCA1MzIuMDUgPyAzIDogZGF0YSA8IDUzMyA/IDQgOiBkYXRhIDwgNTM0LjAzID8gNSA6IGRhdGEgPCA1MzQuMDcgPyA2IDogZGF0YSA8IDUzNC4xMCA/IDcgOiBkYXRhIDwgNTM0LjEzID8gOCA6IGRhdGEgPCA1MzQuMTYgPyA5IDogZGF0YSA8IDUzNC4yNCA/IDEwIDogZGF0YSA8IDUzNC4zMCA/IDExIDogZGF0YSA8IDUzNS4wMSA/IDEyIDogZGF0YSA8IDUzNS4wMiA/ICcxMysnIDogZGF0YSA8IDUzNS4wNyA/IDE1IDogZGF0YSA8IDUzNS4xMSA/IDE2IDogZGF0YSA8IDUzNS4xOSA/IDE3IDogZGF0YSA8IDUzNi4wNSA/IDE4IDogZGF0YSA8IDUzNi4xMCA/IDE5IDogZGF0YSA8IDUzNy4wMSA/IDIwIDogZGF0YSA8IDUzNy4xMSA/ICcyMSsnIDogZGF0YSA8IDUzNy4xMyA/IDIzIDogZGF0YSA8IDUzNy4xOCA/IDI0IDogZGF0YSA8IDUzNy4yNCA/IDI1IDogZGF0YSA8IDUzNy4zNiA/IDI2IDogbGF5b3V0ICE9ICdCbGluaycgPyAnMjcnIDogJzI4Jyk7XG4gICAgICB9XG4gICAgICAvLyBBZGQgdGhlIHBvc3RmaXggb2YgXCIueFwiIG9yIFwiK1wiIGZvciBhcHByb3hpbWF0ZSB2ZXJzaW9ucy5cbiAgICAgIGxheW91dCAmJiAobGF5b3V0WzFdICs9ICcgJyArIChkYXRhICs9IHR5cGVvZiBkYXRhID09ICdudW1iZXInID8gJy54JyA6IC9bLitdLy50ZXN0KGRhdGEpID8gJycgOiAnKycpKTtcbiAgICAgIC8vIE9ic2N1cmUgdmVyc2lvbiBmb3Igc29tZSBTYWZhcmkgMS0yIHJlbGVhc2VzLlxuICAgICAgaWYgKG5hbWUgPT0gJ1NhZmFyaScgJiYgKCF2ZXJzaW9uIHx8IHBhcnNlSW50KHZlcnNpb24pID4gNDUpKSB7XG4gICAgICAgIHZlcnNpb24gPSBkYXRhO1xuICAgICAgfVxuICAgIH1cbiAgICAvLyBEZXRlY3QgT3BlcmEgZGVza3RvcCBtb2Rlcy5cbiAgICBpZiAobmFtZSA9PSAnT3BlcmEnICYmICAoZGF0YSA9IC9cXGJ6Ym92fHp2YXYkLy5leGVjKG9zKSkpIHtcbiAgICAgIG5hbWUgKz0gJyAnO1xuICAgICAgZGVzY3JpcHRpb24udW5zaGlmdCgnZGVza3RvcCBtb2RlJyk7XG4gICAgICBpZiAoZGF0YSA9PSAnenZhdicpIHtcbiAgICAgICAgbmFtZSArPSAnTWluaSc7XG4gICAgICAgIHZlcnNpb24gPSBudWxsO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbmFtZSArPSAnTW9iaWxlJztcbiAgICAgIH1cbiAgICAgIG9zID0gb3MucmVwbGFjZShSZWdFeHAoJyAqJyArIGRhdGEgKyAnJCcpLCAnJyk7XG4gICAgfVxuICAgIC8vIERldGVjdCBDaHJvbWUgZGVza3RvcCBtb2RlLlxuICAgIGVsc2UgaWYgKG5hbWUgPT0gJ1NhZmFyaScgJiYgL1xcYkNocm9tZVxcYi8uZXhlYyhsYXlvdXQgJiYgbGF5b3V0WzFdKSkge1xuICAgICAgZGVzY3JpcHRpb24udW5zaGlmdCgnZGVza3RvcCBtb2RlJyk7XG4gICAgICBuYW1lID0gJ0Nocm9tZSBNb2JpbGUnO1xuICAgICAgdmVyc2lvbiA9IG51bGw7XG5cbiAgICAgIGlmICgvXFxiT1MgWFxcYi8udGVzdChvcykpIHtcbiAgICAgICAgbWFudWZhY3R1cmVyID0gJ0FwcGxlJztcbiAgICAgICAgb3MgPSAnaU9TIDQuMysnO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgb3MgPSBudWxsO1xuICAgICAgfVxuICAgIH1cbiAgICAvLyBTdHJpcCBpbmNvcnJlY3QgT1MgdmVyc2lvbnMuXG4gICAgaWYgKHZlcnNpb24gJiYgdmVyc2lvbi5pbmRleE9mKChkYXRhID0gL1tcXGQuXSskLy5leGVjKG9zKSkpID09IDAgJiZcbiAgICAgICAgdWEuaW5kZXhPZignLycgKyBkYXRhICsgJy0nKSA+IC0xKSB7XG4gICAgICBvcyA9IHRyaW0ob3MucmVwbGFjZShkYXRhLCAnJykpO1xuICAgIH1cbiAgICAvLyBBZGQgbGF5b3V0IGVuZ2luZS5cbiAgICBpZiAobGF5b3V0ICYmICEvXFxiKD86QXZhbnR8Tm9vaylcXGIvLnRlc3QobmFtZSkgJiYgKFxuICAgICAgICAvQnJvd3NlcnxMdW5hc2NhcGV8TWF4dGhvbi8udGVzdChuYW1lKSB8fFxuICAgICAgICBuYW1lICE9ICdTYWZhcmknICYmIC9eaU9TLy50ZXN0KG9zKSAmJiAvXFxiU2FmYXJpXFxiLy50ZXN0KGxheW91dFsxXSkgfHxcbiAgICAgICAgL14oPzpBZG9iZXxBcm9yYXxCcmVhY2h8TWlkb3JpfE9wZXJhfFBoYW50b218UmVrb25xfFJvY2t8U2Ftc3VuZyBJbnRlcm5ldHxTbGVpcG5pcnxXZWIpLy50ZXN0KG5hbWUpICYmIGxheW91dFsxXSkpIHtcbiAgICAgIC8vIERvbid0IGFkZCBsYXlvdXQgZGV0YWlscyB0byBkZXNjcmlwdGlvbiBpZiB0aGV5IGFyZSBmYWxzZXkuXG4gICAgICAoZGF0YSA9IGxheW91dFtsYXlvdXQubGVuZ3RoIC0gMV0pICYmIGRlc2NyaXB0aW9uLnB1c2goZGF0YSk7XG4gICAgfVxuICAgIC8vIENvbWJpbmUgY29udGV4dHVhbCBpbmZvcm1hdGlvbi5cbiAgICBpZiAoZGVzY3JpcHRpb24ubGVuZ3RoKSB7XG4gICAgICBkZXNjcmlwdGlvbiA9IFsnKCcgKyBkZXNjcmlwdGlvbi5qb2luKCc7ICcpICsgJyknXTtcbiAgICB9XG4gICAgLy8gQXBwZW5kIG1hbnVmYWN0dXJlciB0byBkZXNjcmlwdGlvbi5cbiAgICBpZiAobWFudWZhY3R1cmVyICYmIHByb2R1Y3QgJiYgcHJvZHVjdC5pbmRleE9mKG1hbnVmYWN0dXJlcikgPCAwKSB7XG4gICAgICBkZXNjcmlwdGlvbi5wdXNoKCdvbiAnICsgbWFudWZhY3R1cmVyKTtcbiAgICB9XG4gICAgLy8gQXBwZW5kIHByb2R1Y3QgdG8gZGVzY3JpcHRpb24uXG4gICAgaWYgKHByb2R1Y3QpIHtcbiAgICAgIGRlc2NyaXB0aW9uLnB1c2goKC9eb24gLy50ZXN0KGRlc2NyaXB0aW9uW2Rlc2NyaXB0aW9uLmxlbmd0aCAtIDFdKSA/ICcnIDogJ29uICcpICsgcHJvZHVjdCk7XG4gICAgfVxuICAgIC8vIFBhcnNlIHRoZSBPUyBpbnRvIGFuIG9iamVjdC5cbiAgICBpZiAob3MpIHtcbiAgICAgIGRhdGEgPSAvIChbXFxkLitdKykkLy5leGVjKG9zKTtcbiAgICAgIGlzU3BlY2lhbENhc2VkT1MgPSBkYXRhICYmIG9zLmNoYXJBdChvcy5sZW5ndGggLSBkYXRhWzBdLmxlbmd0aCAtIDEpID09ICcvJztcbiAgICAgIG9zID0ge1xuICAgICAgICAnYXJjaGl0ZWN0dXJlJzogMzIsXG4gICAgICAgICdmYW1pbHknOiAoZGF0YSAmJiAhaXNTcGVjaWFsQ2FzZWRPUykgPyBvcy5yZXBsYWNlKGRhdGFbMF0sICcnKSA6IG9zLFxuICAgICAgICAndmVyc2lvbic6IGRhdGEgPyBkYXRhWzFdIDogbnVsbCxcbiAgICAgICAgJ3RvU3RyaW5nJzogZnVuY3Rpb24oKSB7XG4gICAgICAgICAgdmFyIHZlcnNpb24gPSB0aGlzLnZlcnNpb247XG4gICAgICAgICAgcmV0dXJuIHRoaXMuZmFtaWx5ICsgKCh2ZXJzaW9uICYmICFpc1NwZWNpYWxDYXNlZE9TKSA/ICcgJyArIHZlcnNpb24gOiAnJykgKyAodGhpcy5hcmNoaXRlY3R1cmUgPT0gNjQgPyAnIDY0LWJpdCcgOiAnJyk7XG4gICAgICAgIH1cbiAgICAgIH07XG4gICAgfVxuICAgIC8vIEFkZCBicm93c2VyL09TIGFyY2hpdGVjdHVyZS5cbiAgICBpZiAoKGRhdGEgPSAvXFxiKD86QU1EfElBfFdpbnxXT1d8eDg2X3x4KTY0XFxiL2kuZXhlYyhhcmNoKSkgJiYgIS9cXGJpNjg2XFxiL2kudGVzdChhcmNoKSkge1xuICAgICAgaWYgKG9zKSB7XG4gICAgICAgIG9zLmFyY2hpdGVjdHVyZSA9IDY0O1xuICAgICAgICBvcy5mYW1pbHkgPSBvcy5mYW1pbHkucmVwbGFjZShSZWdFeHAoJyAqJyArIGRhdGEpLCAnJyk7XG4gICAgICB9XG4gICAgICBpZiAoXG4gICAgICAgICAgbmFtZSAmJiAoL1xcYldPVzY0XFxiL2kudGVzdCh1YSkgfHxcbiAgICAgICAgICAodXNlRmVhdHVyZXMgJiYgL1xcdyg/Ojg2fDMyKSQvLnRlc3QobmF2LmNwdUNsYXNzIHx8IG5hdi5wbGF0Zm9ybSkgJiYgIS9cXGJXaW42NDsgeDY0XFxiL2kudGVzdCh1YSkpKVxuICAgICAgKSB7XG4gICAgICAgIGRlc2NyaXB0aW9uLnVuc2hpZnQoJzMyLWJpdCcpO1xuICAgICAgfVxuICAgIH1cbiAgICAvLyBDaHJvbWUgMzkgYW5kIGFib3ZlIG9uIE9TIFggaXMgYWx3YXlzIDY0LWJpdC5cbiAgICBlbHNlIGlmIChcbiAgICAgICAgb3MgJiYgL15PUyBYLy50ZXN0KG9zLmZhbWlseSkgJiZcbiAgICAgICAgbmFtZSA9PSAnQ2hyb21lJyAmJiBwYXJzZUZsb2F0KHZlcnNpb24pID49IDM5XG4gICAgKSB7XG4gICAgICBvcy5hcmNoaXRlY3R1cmUgPSA2NDtcbiAgICB9XG5cbiAgICB1YSB8fCAodWEgPSBudWxsKTtcblxuICAgIC8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cblxuICAgIC8qKlxuICAgICAqIFRoZSBwbGF0Zm9ybSBvYmplY3QuXG4gICAgICpcbiAgICAgKiBAbmFtZSBwbGF0Zm9ybVxuICAgICAqIEB0eXBlIE9iamVjdFxuICAgICAqL1xuICAgIHZhciBwbGF0Zm9ybSA9IHt9O1xuXG4gICAgLyoqXG4gICAgICogVGhlIHBsYXRmb3JtIGRlc2NyaXB0aW9uLlxuICAgICAqXG4gICAgICogQG1lbWJlck9mIHBsYXRmb3JtXG4gICAgICogQHR5cGUgc3RyaW5nfG51bGxcbiAgICAgKi9cbiAgICBwbGF0Zm9ybS5kZXNjcmlwdGlvbiA9IHVhO1xuXG4gICAgLyoqXG4gICAgICogVGhlIG5hbWUgb2YgdGhlIGJyb3dzZXIncyBsYXlvdXQgZW5naW5lLlxuICAgICAqXG4gICAgICogVGhlIGxpc3Qgb2YgY29tbW9uIGxheW91dCBlbmdpbmVzIGluY2x1ZGU6XG4gICAgICogXCJCbGlua1wiLCBcIkVkZ2VIVE1MXCIsIFwiR2Vja29cIiwgXCJUcmlkZW50XCIgYW5kIFwiV2ViS2l0XCJcbiAgICAgKlxuICAgICAqIEBtZW1iZXJPZiBwbGF0Zm9ybVxuICAgICAqIEB0eXBlIHN0cmluZ3xudWxsXG4gICAgICovXG4gICAgcGxhdGZvcm0ubGF5b3V0ID0gbGF5b3V0ICYmIGxheW91dFswXTtcblxuICAgIC8qKlxuICAgICAqIFRoZSBuYW1lIG9mIHRoZSBwcm9kdWN0J3MgbWFudWZhY3R1cmVyLlxuICAgICAqXG4gICAgICogVGhlIGxpc3Qgb2YgbWFudWZhY3R1cmVycyBpbmNsdWRlOlxuICAgICAqIFwiQXBwbGVcIiwgXCJBcmNob3NcIiwgXCJBbWF6b25cIiwgXCJBc3VzXCIsIFwiQmFybmVzICYgTm9ibGVcIiwgXCJCbGFja0JlcnJ5XCIsXG4gICAgICogXCJHb29nbGVcIiwgXCJIUFwiLCBcIkhUQ1wiLCBcIkxHXCIsIFwiTWljcm9zb2Z0XCIsIFwiTW90b3JvbGFcIiwgXCJOaW50ZW5kb1wiLFxuICAgICAqIFwiTm9raWFcIiwgXCJTYW1zdW5nXCIgYW5kIFwiU29ueVwiXG4gICAgICpcbiAgICAgKiBAbWVtYmVyT2YgcGxhdGZvcm1cbiAgICAgKiBAdHlwZSBzdHJpbmd8bnVsbFxuICAgICAqL1xuICAgIHBsYXRmb3JtLm1hbnVmYWN0dXJlciA9IG1hbnVmYWN0dXJlcjtcblxuICAgIC8qKlxuICAgICAqIFRoZSBuYW1lIG9mIHRoZSBicm93c2VyL2Vudmlyb25tZW50LlxuICAgICAqXG4gICAgICogVGhlIGxpc3Qgb2YgY29tbW9uIGJyb3dzZXIgbmFtZXMgaW5jbHVkZTpcbiAgICAgKiBcIkNocm9tZVwiLCBcIkVsZWN0cm9uXCIsIFwiRmlyZWZveFwiLCBcIkZpcmVmb3ggZm9yIGlPU1wiLCBcIklFXCIsXG4gICAgICogXCJNaWNyb3NvZnQgRWRnZVwiLCBcIlBoYW50b21KU1wiLCBcIlNhZmFyaVwiLCBcIlNlYU1vbmtleVwiLCBcIlNpbGtcIixcbiAgICAgKiBcIk9wZXJhIE1pbmlcIiBhbmQgXCJPcGVyYVwiXG4gICAgICpcbiAgICAgKiBNb2JpbGUgdmVyc2lvbnMgb2Ygc29tZSBicm93c2VycyBoYXZlIFwiTW9iaWxlXCIgYXBwZW5kZWQgdG8gdGhlaXIgbmFtZTpcbiAgICAgKiBlZy4gXCJDaHJvbWUgTW9iaWxlXCIsIFwiRmlyZWZveCBNb2JpbGVcIiwgXCJJRSBNb2JpbGVcIiBhbmQgXCJPcGVyYSBNb2JpbGVcIlxuICAgICAqXG4gICAgICogQG1lbWJlck9mIHBsYXRmb3JtXG4gICAgICogQHR5cGUgc3RyaW5nfG51bGxcbiAgICAgKi9cbiAgICBwbGF0Zm9ybS5uYW1lID0gbmFtZTtcblxuICAgIC8qKlxuICAgICAqIFRoZSBhbHBoYS9iZXRhIHJlbGVhc2UgaW5kaWNhdG9yLlxuICAgICAqXG4gICAgICogQG1lbWJlck9mIHBsYXRmb3JtXG4gICAgICogQHR5cGUgc3RyaW5nfG51bGxcbiAgICAgKi9cbiAgICBwbGF0Zm9ybS5wcmVyZWxlYXNlID0gcHJlcmVsZWFzZTtcblxuICAgIC8qKlxuICAgICAqIFRoZSBuYW1lIG9mIHRoZSBwcm9kdWN0IGhvc3RpbmcgdGhlIGJyb3dzZXIuXG4gICAgICpcbiAgICAgKiBUaGUgbGlzdCBvZiBjb21tb24gcHJvZHVjdHMgaW5jbHVkZTpcbiAgICAgKlxuICAgICAqIFwiQmxhY2tCZXJyeVwiLCBcIkdhbGF4eSBTNFwiLCBcIkx1bWlhXCIsIFwiaVBhZFwiLCBcImlQb2RcIiwgXCJpUGhvbmVcIiwgXCJLaW5kbGVcIixcbiAgICAgKiBcIktpbmRsZSBGaXJlXCIsIFwiTmV4dXNcIiwgXCJOb29rXCIsIFwiUGxheUJvb2tcIiwgXCJUb3VjaFBhZFwiIGFuZCBcIlRyYW5zZm9ybWVyXCJcbiAgICAgKlxuICAgICAqIEBtZW1iZXJPZiBwbGF0Zm9ybVxuICAgICAqIEB0eXBlIHN0cmluZ3xudWxsXG4gICAgICovXG4gICAgcGxhdGZvcm0ucHJvZHVjdCA9IHByb2R1Y3Q7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYnJvd3NlcidzIHVzZXIgYWdlbnQgc3RyaW5nLlxuICAgICAqXG4gICAgICogQG1lbWJlck9mIHBsYXRmb3JtXG4gICAgICogQHR5cGUgc3RyaW5nfG51bGxcbiAgICAgKi9cbiAgICBwbGF0Zm9ybS51YSA9IHVhO1xuXG4gICAgLyoqXG4gICAgICogVGhlIGJyb3dzZXIvZW52aXJvbm1lbnQgdmVyc2lvbi5cbiAgICAgKlxuICAgICAqIEBtZW1iZXJPZiBwbGF0Zm9ybVxuICAgICAqIEB0eXBlIHN0cmluZ3xudWxsXG4gICAgICovXG4gICAgcGxhdGZvcm0udmVyc2lvbiA9IG5hbWUgJiYgdmVyc2lvbjtcblxuICAgIC8qKlxuICAgICAqIFRoZSBuYW1lIG9mIHRoZSBvcGVyYXRpbmcgc3lzdGVtLlxuICAgICAqXG4gICAgICogQG1lbWJlck9mIHBsYXRmb3JtXG4gICAgICogQHR5cGUgT2JqZWN0XG4gICAgICovXG4gICAgcGxhdGZvcm0ub3MgPSBvcyB8fCB7XG5cbiAgICAgIC8qKlxuICAgICAgICogVGhlIENQVSBhcmNoaXRlY3R1cmUgdGhlIE9TIGlzIGJ1aWx0IGZvci5cbiAgICAgICAqXG4gICAgICAgKiBAbWVtYmVyT2YgcGxhdGZvcm0ub3NcbiAgICAgICAqIEB0eXBlIG51bWJlcnxudWxsXG4gICAgICAgKi9cbiAgICAgICdhcmNoaXRlY3R1cmUnOiBudWxsLFxuXG4gICAgICAvKipcbiAgICAgICAqIFRoZSBmYW1pbHkgb2YgdGhlIE9TLlxuICAgICAgICpcbiAgICAgICAqIENvbW1vbiB2YWx1ZXMgaW5jbHVkZTpcbiAgICAgICAqIFwiV2luZG93c1wiLCBcIldpbmRvd3MgU2VydmVyIDIwMDggUjIgLyA3XCIsIFwiV2luZG93cyBTZXJ2ZXIgMjAwOCAvIFZpc3RhXCIsXG4gICAgICAgKiBcIldpbmRvd3MgWFBcIiwgXCJPUyBYXCIsIFwiVWJ1bnR1XCIsIFwiRGViaWFuXCIsIFwiRmVkb3JhXCIsIFwiUmVkIEhhdFwiLCBcIlN1U0VcIixcbiAgICAgICAqIFwiQW5kcm9pZFwiLCBcImlPU1wiIGFuZCBcIldpbmRvd3MgUGhvbmVcIlxuICAgICAgICpcbiAgICAgICAqIEBtZW1iZXJPZiBwbGF0Zm9ybS5vc1xuICAgICAgICogQHR5cGUgc3RyaW5nfG51bGxcbiAgICAgICAqL1xuICAgICAgJ2ZhbWlseSc6IG51bGwsXG5cbiAgICAgIC8qKlxuICAgICAgICogVGhlIHZlcnNpb24gb2YgdGhlIE9TLlxuICAgICAgICpcbiAgICAgICAqIEBtZW1iZXJPZiBwbGF0Zm9ybS5vc1xuICAgICAgICogQHR5cGUgc3RyaW5nfG51bGxcbiAgICAgICAqL1xuICAgICAgJ3ZlcnNpb24nOiBudWxsLFxuXG4gICAgICAvKipcbiAgICAgICAqIFJldHVybnMgdGhlIE9TIHN0cmluZy5cbiAgICAgICAqXG4gICAgICAgKiBAbWVtYmVyT2YgcGxhdGZvcm0ub3NcbiAgICAgICAqIEByZXR1cm5zIHtzdHJpbmd9IFRoZSBPUyBzdHJpbmcuXG4gICAgICAgKi9cbiAgICAgICd0b1N0cmluZyc6IGZ1bmN0aW9uKCkgeyByZXR1cm4gJ251bGwnOyB9XG4gICAgfTtcblxuICAgIHBsYXRmb3JtLnBhcnNlID0gcGFyc2U7XG4gICAgcGxhdGZvcm0udG9TdHJpbmcgPSB0b1N0cmluZ1BsYXRmb3JtO1xuXG4gICAgaWYgKHBsYXRmb3JtLnZlcnNpb24pIHtcbiAgICAgIGRlc2NyaXB0aW9uLnVuc2hpZnQodmVyc2lvbik7XG4gICAgfVxuICAgIGlmIChwbGF0Zm9ybS5uYW1lKSB7XG4gICAgICBkZXNjcmlwdGlvbi51bnNoaWZ0KG5hbWUpO1xuICAgIH1cbiAgICBpZiAob3MgJiYgbmFtZSAmJiAhKG9zID09IFN0cmluZyhvcykuc3BsaXQoJyAnKVswXSAmJiAob3MgPT0gbmFtZS5zcGxpdCgnICcpWzBdIHx8IHByb2R1Y3QpKSkge1xuICAgICAgZGVzY3JpcHRpb24ucHVzaChwcm9kdWN0ID8gJygnICsgb3MgKyAnKScgOiAnb24gJyArIG9zKTtcbiAgICB9XG4gICAgaWYgKGRlc2NyaXB0aW9uLmxlbmd0aCkge1xuICAgICAgcGxhdGZvcm0uZGVzY3JpcHRpb24gPSBkZXNjcmlwdGlvbi5qb2luKCcgJyk7XG4gICAgfVxuICAgIHJldHVybiBwbGF0Zm9ybTtcbiAgfVxuXG4gIC8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuXG4gIC8vIEV4cG9ydCBwbGF0Zm9ybS5cbiAgdmFyIHBsYXRmb3JtID0gcGFyc2UoKTtcblxuICAvLyBTb21lIEFNRCBidWlsZCBvcHRpbWl6ZXJzLCBsaWtlIHIuanMsIGNoZWNrIGZvciBjb25kaXRpb24gcGF0dGVybnMgbGlrZSB0aGUgZm9sbG93aW5nOlxuICBpZiAodHlwZW9mIGRlZmluZSA9PSAnZnVuY3Rpb24nICYmIHR5cGVvZiBkZWZpbmUuYW1kID09ICdvYmplY3QnICYmIGRlZmluZS5hbWQpIHtcbiAgICAvLyBFeHBvc2UgcGxhdGZvcm0gb24gdGhlIGdsb2JhbCBvYmplY3QgdG8gcHJldmVudCBlcnJvcnMgd2hlbiBwbGF0Zm9ybSBpc1xuICAgIC8vIGxvYWRlZCBieSBhIHNjcmlwdCB0YWcgaW4gdGhlIHByZXNlbmNlIG9mIGFuIEFNRCBsb2FkZXIuXG4gICAgLy8gU2VlIGh0dHA6Ly9yZXF1aXJlanMub3JnL2RvY3MvZXJyb3JzLmh0bWwjbWlzbWF0Y2ggZm9yIG1vcmUgZGV0YWlscy5cbiAgICByb290LnBsYXRmb3JtID0gcGxhdGZvcm07XG5cbiAgICAvLyBEZWZpbmUgYXMgYW4gYW5vbnltb3VzIG1vZHVsZSBzbyBwbGF0Zm9ybSBjYW4gYmUgYWxpYXNlZCB0aHJvdWdoIHBhdGggbWFwcGluZy5cbiAgICBkZWZpbmUoZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4gcGxhdGZvcm07XG4gICAgfSk7XG4gIH1cbiAgLy8gQ2hlY2sgZm9yIGBleHBvcnRzYCBhZnRlciBgZGVmaW5lYCBpbiBjYXNlIGEgYnVpbGQgb3B0aW1pemVyIGFkZHMgYW4gYGV4cG9ydHNgIG9iamVjdC5cbiAgZWxzZSBpZiAoZnJlZUV4cG9ydHMgJiYgZnJlZU1vZHVsZSkge1xuICAgIC8vIEV4cG9ydCBmb3IgQ29tbW9uSlMgc3VwcG9ydC5cbiAgICBmb3JPd24ocGxhdGZvcm0sIGZ1bmN0aW9uKHZhbHVlLCBrZXkpIHtcbiAgICAgIGZyZWVFeHBvcnRzW2tleV0gPSB2YWx1ZTtcbiAgICB9KTtcbiAgfVxuICBlbHNlIHtcbiAgICAvLyBFeHBvcnQgdG8gdGhlIGdsb2JhbCBvYmplY3QuXG4gICAgcm9vdC5wbGF0Zm9ybSA9IHBsYXRmb3JtO1xuICB9XG59LmNhbGwodGhpcykpO1xuIiwidmFyIHYxID0gcmVxdWlyZSgnLi92MScpO1xudmFyIHY0ID0gcmVxdWlyZSgnLi92NCcpO1xuXG52YXIgdXVpZCA9IHY0O1xudXVpZC52MSA9IHYxO1xudXVpZC52NCA9IHY0O1xuXG5tb2R1bGUuZXhwb3J0cyA9IHV1aWQ7XG4iLCIvKipcbiAqIENvbnZlcnQgYXJyYXkgb2YgMTYgYnl0ZSB2YWx1ZXMgdG8gVVVJRCBzdHJpbmcgZm9ybWF0IG9mIHRoZSBmb3JtOlxuICogWFhYWFhYWFgtWFhYWC1YWFhYLVhYWFgtWFhYWFhYWFhYWFhYXG4gKi9cbnZhciBieXRlVG9IZXggPSBbXTtcbmZvciAodmFyIGkgPSAwOyBpIDwgMjU2OyArK2kpIHtcbiAgYnl0ZVRvSGV4W2ldID0gKGkgKyAweDEwMCkudG9TdHJpbmcoMTYpLnN1YnN0cigxKTtcbn1cblxuZnVuY3Rpb24gYnl0ZXNUb1V1aWQoYnVmLCBvZmZzZXQpIHtcbiAgdmFyIGkgPSBvZmZzZXQgfHwgMDtcbiAgdmFyIGJ0aCA9IGJ5dGVUb0hleDtcbiAgLy8gam9pbiB1c2VkIHRvIGZpeCBtZW1vcnkgaXNzdWUgY2F1c2VkIGJ5IGNvbmNhdGVuYXRpb246IGh0dHBzOi8vYnVncy5jaHJvbWl1bS5vcmcvcC92OC9pc3N1ZXMvZGV0YWlsP2lkPTMxNzUjYzRcbiAgcmV0dXJuIChbYnRoW2J1ZltpKytdXSwgYnRoW2J1ZltpKytdXSwgXG5cdGJ0aFtidWZbaSsrXV0sIGJ0aFtidWZbaSsrXV0sICctJyxcblx0YnRoW2J1ZltpKytdXSwgYnRoW2J1ZltpKytdXSwgJy0nLFxuXHRidGhbYnVmW2krK11dLCBidGhbYnVmW2krK11dLCAnLScsXG5cdGJ0aFtidWZbaSsrXV0sIGJ0aFtidWZbaSsrXV0sICctJyxcblx0YnRoW2J1ZltpKytdXSwgYnRoW2J1ZltpKytdXSxcblx0YnRoW2J1ZltpKytdXSwgYnRoW2J1ZltpKytdXSxcblx0YnRoW2J1ZltpKytdXSwgYnRoW2J1ZltpKytdXV0pLmpvaW4oJycpO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGJ5dGVzVG9VdWlkO1xuIiwiLy8gVW5pcXVlIElEIGNyZWF0aW9uIHJlcXVpcmVzIGEgaGlnaCBxdWFsaXR5IHJhbmRvbSAjIGdlbmVyYXRvci4gIEluIHRoZVxuLy8gYnJvd3NlciB0aGlzIGlzIGEgbGl0dGxlIGNvbXBsaWNhdGVkIGR1ZSB0byB1bmtub3duIHF1YWxpdHkgb2YgTWF0aC5yYW5kb20oKVxuLy8gYW5kIGluY29uc2lzdGVudCBzdXBwb3J0IGZvciB0aGUgYGNyeXB0b2AgQVBJLiAgV2UgZG8gdGhlIGJlc3Qgd2UgY2FuIHZpYVxuLy8gZmVhdHVyZS1kZXRlY3Rpb25cblxuLy8gZ2V0UmFuZG9tVmFsdWVzIG5lZWRzIHRvIGJlIGludm9rZWQgaW4gYSBjb250ZXh0IHdoZXJlIFwidGhpc1wiIGlzIGEgQ3J5cHRvXG4vLyBpbXBsZW1lbnRhdGlvbi4gQWxzbywgZmluZCB0aGUgY29tcGxldGUgaW1wbGVtZW50YXRpb24gb2YgY3J5cHRvIG9uIElFMTEuXG52YXIgZ2V0UmFuZG9tVmFsdWVzID0gKHR5cGVvZihjcnlwdG8pICE9ICd1bmRlZmluZWQnICYmIGNyeXB0by5nZXRSYW5kb21WYWx1ZXMgJiYgY3J5cHRvLmdldFJhbmRvbVZhbHVlcy5iaW5kKGNyeXB0bykpIHx8XG4gICAgICAgICAgICAgICAgICAgICAgKHR5cGVvZihtc0NyeXB0bykgIT0gJ3VuZGVmaW5lZCcgJiYgdHlwZW9mIHdpbmRvdy5tc0NyeXB0by5nZXRSYW5kb21WYWx1ZXMgPT0gJ2Z1bmN0aW9uJyAmJiBtc0NyeXB0by5nZXRSYW5kb21WYWx1ZXMuYmluZChtc0NyeXB0bykpO1xuXG5pZiAoZ2V0UmFuZG9tVmFsdWVzKSB7XG4gIC8vIFdIQVRXRyBjcnlwdG8gUk5HIC0gaHR0cDovL3dpa2kud2hhdHdnLm9yZy93aWtpL0NyeXB0b1xuICB2YXIgcm5kczggPSBuZXcgVWludDhBcnJheSgxNik7IC8vIGVzbGludC1kaXNhYmxlLWxpbmUgbm8tdW5kZWZcblxuICBtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHdoYXR3Z1JORygpIHtcbiAgICBnZXRSYW5kb21WYWx1ZXMocm5kczgpO1xuICAgIHJldHVybiBybmRzODtcbiAgfTtcbn0gZWxzZSB7XG4gIC8vIE1hdGgucmFuZG9tKCktYmFzZWQgKFJORylcbiAgLy9cbiAgLy8gSWYgYWxsIGVsc2UgZmFpbHMsIHVzZSBNYXRoLnJhbmRvbSgpLiAgSXQncyBmYXN0LCBidXQgaXMgb2YgdW5zcGVjaWZpZWRcbiAgLy8gcXVhbGl0eS5cbiAgdmFyIHJuZHMgPSBuZXcgQXJyYXkoMTYpO1xuXG4gIG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gbWF0aFJORygpIHtcbiAgICBmb3IgKHZhciBpID0gMCwgcjsgaSA8IDE2OyBpKyspIHtcbiAgICAgIGlmICgoaSAmIDB4MDMpID09PSAwKSByID0gTWF0aC5yYW5kb20oKSAqIDB4MTAwMDAwMDAwO1xuICAgICAgcm5kc1tpXSA9IHIgPj4+ICgoaSAmIDB4MDMpIDw8IDMpICYgMHhmZjtcbiAgICB9XG5cbiAgICByZXR1cm4gcm5kcztcbiAgfTtcbn1cbiIsInZhciBybmcgPSByZXF1aXJlKCcuL2xpYi9ybmcnKTtcbnZhciBieXRlc1RvVXVpZCA9IHJlcXVpcmUoJy4vbGliL2J5dGVzVG9VdWlkJyk7XG5cbi8vICoqYHYxKClgIC0gR2VuZXJhdGUgdGltZS1iYXNlZCBVVUlEKipcbi8vXG4vLyBJbnNwaXJlZCBieSBodHRwczovL2dpdGh1Yi5jb20vTGlvc0svVVVJRC5qc1xuLy8gYW5kIGh0dHA6Ly9kb2NzLnB5dGhvbi5vcmcvbGlicmFyeS91dWlkLmh0bWxcblxudmFyIF9ub2RlSWQ7XG52YXIgX2Nsb2Nrc2VxO1xuXG4vLyBQcmV2aW91cyB1dWlkIGNyZWF0aW9uIHRpbWVcbnZhciBfbGFzdE1TZWNzID0gMDtcbnZhciBfbGFzdE5TZWNzID0gMDtcblxuLy8gU2VlIGh0dHBzOi8vZ2l0aHViLmNvbS9icm9vZmEvbm9kZS11dWlkIGZvciBBUEkgZGV0YWlsc1xuZnVuY3Rpb24gdjEob3B0aW9ucywgYnVmLCBvZmZzZXQpIHtcbiAgdmFyIGkgPSBidWYgJiYgb2Zmc2V0IHx8IDA7XG4gIHZhciBiID0gYnVmIHx8IFtdO1xuXG4gIG9wdGlvbnMgPSBvcHRpb25zIHx8IHt9O1xuICB2YXIgbm9kZSA9IG9wdGlvbnMubm9kZSB8fCBfbm9kZUlkO1xuICB2YXIgY2xvY2tzZXEgPSBvcHRpb25zLmNsb2Nrc2VxICE9PSB1bmRlZmluZWQgPyBvcHRpb25zLmNsb2Nrc2VxIDogX2Nsb2Nrc2VxO1xuXG4gIC8vIG5vZGUgYW5kIGNsb2Nrc2VxIG5lZWQgdG8gYmUgaW5pdGlhbGl6ZWQgdG8gcmFuZG9tIHZhbHVlcyBpZiB0aGV5J3JlIG5vdFxuICAvLyBzcGVjaWZpZWQuICBXZSBkbyB0aGlzIGxhemlseSB0byBtaW5pbWl6ZSBpc3N1ZXMgcmVsYXRlZCB0byBpbnN1ZmZpY2llbnRcbiAgLy8gc3lzdGVtIGVudHJvcHkuICBTZWUgIzE4OVxuICBpZiAobm9kZSA9PSBudWxsIHx8IGNsb2Nrc2VxID09IG51bGwpIHtcbiAgICB2YXIgc2VlZEJ5dGVzID0gcm5nKCk7XG4gICAgaWYgKG5vZGUgPT0gbnVsbCkge1xuICAgICAgLy8gUGVyIDQuNSwgY3JlYXRlIGFuZCA0OC1iaXQgbm9kZSBpZCwgKDQ3IHJhbmRvbSBiaXRzICsgbXVsdGljYXN0IGJpdCA9IDEpXG4gICAgICBub2RlID0gX25vZGVJZCA9IFtcbiAgICAgICAgc2VlZEJ5dGVzWzBdIHwgMHgwMSxcbiAgICAgICAgc2VlZEJ5dGVzWzFdLCBzZWVkQnl0ZXNbMl0sIHNlZWRCeXRlc1szXSwgc2VlZEJ5dGVzWzRdLCBzZWVkQnl0ZXNbNV1cbiAgICAgIF07XG4gICAgfVxuICAgIGlmIChjbG9ja3NlcSA9PSBudWxsKSB7XG4gICAgICAvLyBQZXIgNC4yLjIsIHJhbmRvbWl6ZSAoMTQgYml0KSBjbG9ja3NlcVxuICAgICAgY2xvY2tzZXEgPSBfY2xvY2tzZXEgPSAoc2VlZEJ5dGVzWzZdIDw8IDggfCBzZWVkQnl0ZXNbN10pICYgMHgzZmZmO1xuICAgIH1cbiAgfVxuXG4gIC8vIFVVSUQgdGltZXN0YW1wcyBhcmUgMTAwIG5hbm8tc2Vjb25kIHVuaXRzIHNpbmNlIHRoZSBHcmVnb3JpYW4gZXBvY2gsXG4gIC8vICgxNTgyLTEwLTE1IDAwOjAwKS4gIEpTTnVtYmVycyBhcmVuJ3QgcHJlY2lzZSBlbm91Z2ggZm9yIHRoaXMsIHNvXG4gIC8vIHRpbWUgaXMgaGFuZGxlZCBpbnRlcm5hbGx5IGFzICdtc2VjcycgKGludGVnZXIgbWlsbGlzZWNvbmRzKSBhbmQgJ25zZWNzJ1xuICAvLyAoMTAwLW5hbm9zZWNvbmRzIG9mZnNldCBmcm9tIG1zZWNzKSBzaW5jZSB1bml4IGVwb2NoLCAxOTcwLTAxLTAxIDAwOjAwLlxuICB2YXIgbXNlY3MgPSBvcHRpb25zLm1zZWNzICE9PSB1bmRlZmluZWQgPyBvcHRpb25zLm1zZWNzIDogbmV3IERhdGUoKS5nZXRUaW1lKCk7XG5cbiAgLy8gUGVyIDQuMi4xLjIsIHVzZSBjb3VudCBvZiB1dWlkJ3MgZ2VuZXJhdGVkIGR1cmluZyB0aGUgY3VycmVudCBjbG9ja1xuICAvLyBjeWNsZSB0byBzaW11bGF0ZSBoaWdoZXIgcmVzb2x1dGlvbiBjbG9ja1xuICB2YXIgbnNlY3MgPSBvcHRpb25zLm5zZWNzICE9PSB1bmRlZmluZWQgPyBvcHRpb25zLm5zZWNzIDogX2xhc3ROU2VjcyArIDE7XG5cbiAgLy8gVGltZSBzaW5jZSBsYXN0IHV1aWQgY3JlYXRpb24gKGluIG1zZWNzKVxuICB2YXIgZHQgPSAobXNlY3MgLSBfbGFzdE1TZWNzKSArIChuc2VjcyAtIF9sYXN0TlNlY3MpLzEwMDAwO1xuXG4gIC8vIFBlciA0LjIuMS4yLCBCdW1wIGNsb2Nrc2VxIG9uIGNsb2NrIHJlZ3Jlc3Npb25cbiAgaWYgKGR0IDwgMCAmJiBvcHRpb25zLmNsb2Nrc2VxID09PSB1bmRlZmluZWQpIHtcbiAgICBjbG9ja3NlcSA9IGNsb2Nrc2VxICsgMSAmIDB4M2ZmZjtcbiAgfVxuXG4gIC8vIFJlc2V0IG5zZWNzIGlmIGNsb2NrIHJlZ3Jlc3NlcyAobmV3IGNsb2Nrc2VxKSBvciB3ZSd2ZSBtb3ZlZCBvbnRvIGEgbmV3XG4gIC8vIHRpbWUgaW50ZXJ2YWxcbiAgaWYgKChkdCA8IDAgfHwgbXNlY3MgPiBfbGFzdE1TZWNzKSAmJiBvcHRpb25zLm5zZWNzID09PSB1bmRlZmluZWQpIHtcbiAgICBuc2VjcyA9IDA7XG4gIH1cblxuICAvLyBQZXIgNC4yLjEuMiBUaHJvdyBlcnJvciBpZiB0b28gbWFueSB1dWlkcyBhcmUgcmVxdWVzdGVkXG4gIGlmIChuc2VjcyA+PSAxMDAwMCkge1xuICAgIHRocm93IG5ldyBFcnJvcigndXVpZC52MSgpOiBDYW5cXCd0IGNyZWF0ZSBtb3JlIHRoYW4gMTBNIHV1aWRzL3NlYycpO1xuICB9XG5cbiAgX2xhc3RNU2VjcyA9IG1zZWNzO1xuICBfbGFzdE5TZWNzID0gbnNlY3M7XG4gIF9jbG9ja3NlcSA9IGNsb2Nrc2VxO1xuXG4gIC8vIFBlciA0LjEuNCAtIENvbnZlcnQgZnJvbSB1bml4IGVwb2NoIHRvIEdyZWdvcmlhbiBlcG9jaFxuICBtc2VjcyArPSAxMjIxOTI5MjgwMDAwMDtcblxuICAvLyBgdGltZV9sb3dgXG4gIHZhciB0bCA9ICgobXNlY3MgJiAweGZmZmZmZmYpICogMTAwMDAgKyBuc2VjcykgJSAweDEwMDAwMDAwMDtcbiAgYltpKytdID0gdGwgPj4+IDI0ICYgMHhmZjtcbiAgYltpKytdID0gdGwgPj4+IDE2ICYgMHhmZjtcbiAgYltpKytdID0gdGwgPj4+IDggJiAweGZmO1xuICBiW2krK10gPSB0bCAmIDB4ZmY7XG5cbiAgLy8gYHRpbWVfbWlkYFxuICB2YXIgdG1oID0gKG1zZWNzIC8gMHgxMDAwMDAwMDAgKiAxMDAwMCkgJiAweGZmZmZmZmY7XG4gIGJbaSsrXSA9IHRtaCA+Pj4gOCAmIDB4ZmY7XG4gIGJbaSsrXSA9IHRtaCAmIDB4ZmY7XG5cbiAgLy8gYHRpbWVfaGlnaF9hbmRfdmVyc2lvbmBcbiAgYltpKytdID0gdG1oID4+PiAyNCAmIDB4ZiB8IDB4MTA7IC8vIGluY2x1ZGUgdmVyc2lvblxuICBiW2krK10gPSB0bWggPj4+IDE2ICYgMHhmZjtcblxuICAvLyBgY2xvY2tfc2VxX2hpX2FuZF9yZXNlcnZlZGAgKFBlciA0LjIuMiAtIGluY2x1ZGUgdmFyaWFudClcbiAgYltpKytdID0gY2xvY2tzZXEgPj4+IDggfCAweDgwO1xuXG4gIC8vIGBjbG9ja19zZXFfbG93YFxuICBiW2krK10gPSBjbG9ja3NlcSAmIDB4ZmY7XG5cbiAgLy8gYG5vZGVgXG4gIGZvciAodmFyIG4gPSAwOyBuIDwgNjsgKytuKSB7XG4gICAgYltpICsgbl0gPSBub2RlW25dO1xuICB9XG5cbiAgcmV0dXJuIGJ1ZiA/IGJ1ZiA6IGJ5dGVzVG9VdWlkKGIpO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHYxO1xuIiwidmFyIHJuZyA9IHJlcXVpcmUoJy4vbGliL3JuZycpO1xudmFyIGJ5dGVzVG9VdWlkID0gcmVxdWlyZSgnLi9saWIvYnl0ZXNUb1V1aWQnKTtcblxuZnVuY3Rpb24gdjQob3B0aW9ucywgYnVmLCBvZmZzZXQpIHtcbiAgdmFyIGkgPSBidWYgJiYgb2Zmc2V0IHx8IDA7XG5cbiAgaWYgKHR5cGVvZihvcHRpb25zKSA9PSAnc3RyaW5nJykge1xuICAgIGJ1ZiA9IG9wdGlvbnMgPT09ICdiaW5hcnknID8gbmV3IEFycmF5KDE2KSA6IG51bGw7XG4gICAgb3B0aW9ucyA9IG51bGw7XG4gIH1cbiAgb3B0aW9ucyA9IG9wdGlvbnMgfHwge307XG5cbiAgdmFyIHJuZHMgPSBvcHRpb25zLnJhbmRvbSB8fCAob3B0aW9ucy5ybmcgfHwgcm5nKSgpO1xuXG4gIC8vIFBlciA0LjQsIHNldCBiaXRzIGZvciB2ZXJzaW9uIGFuZCBgY2xvY2tfc2VxX2hpX2FuZF9yZXNlcnZlZGBcbiAgcm5kc1s2XSA9IChybmRzWzZdICYgMHgwZikgfCAweDQwO1xuICBybmRzWzhdID0gKHJuZHNbOF0gJiAweDNmKSB8IDB4ODA7XG5cbiAgLy8gQ29weSBieXRlcyB0byBidWZmZXIsIGlmIHByb3ZpZGVkXG4gIGlmIChidWYpIHtcbiAgICBmb3IgKHZhciBpaSA9IDA7IGlpIDwgMTY7ICsraWkpIHtcbiAgICAgIGJ1ZltpICsgaWldID0gcm5kc1tpaV07XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGJ1ZiB8fCBieXRlc1RvVXVpZChybmRzKTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSB2NDtcbiIsIi8qXHJcbldpbGRFbWl0dGVyLmpzIGlzIGEgc2xpbSBsaXR0bGUgZXZlbnQgZW1pdHRlciBieSBAaGVucmlram9yZXRlZyBsYXJnZWx5IGJhc2VkXHJcbm9uIEB2aXNpb25tZWRpYSdzIEVtaXR0ZXIgZnJvbSBVSSBLaXQuXHJcblxyXG5XaHk/IEkgd2FudGVkIGl0IHN0YW5kYWxvbmUuXHJcblxyXG5JIGFsc28gd2FudGVkIHN1cHBvcnQgZm9yIHdpbGRjYXJkIGVtaXR0ZXJzIGxpa2UgdGhpczpcclxuXHJcbmVtaXR0ZXIub24oJyonLCBmdW5jdGlvbiAoZXZlbnROYW1lLCBvdGhlciwgZXZlbnQsIHBheWxvYWRzKSB7XHJcblxyXG59KTtcclxuXHJcbmVtaXR0ZXIub24oJ3NvbWVuYW1lc3BhY2UqJywgZnVuY3Rpb24gKGV2ZW50TmFtZSwgcGF5bG9hZHMpIHtcclxuXHJcbn0pO1xyXG5cclxuUGxlYXNlIG5vdGUgdGhhdCBjYWxsYmFja3MgdHJpZ2dlcmVkIGJ5IHdpbGRjYXJkIHJlZ2lzdGVyZWQgZXZlbnRzIGFsc28gZ2V0XHJcbnRoZSBldmVudCBuYW1lIGFzIHRoZSBmaXJzdCBhcmd1bWVudC5cclxuKi9cclxuXHJcbm1vZHVsZS5leHBvcnRzID0gV2lsZEVtaXR0ZXI7XHJcblxyXG5mdW5jdGlvbiBXaWxkRW1pdHRlcigpIHsgfVxyXG5cclxuV2lsZEVtaXR0ZXIubWl4aW4gPSBmdW5jdGlvbiAoY29uc3RydWN0b3IpIHtcclxuICAgIHZhciBwcm90b3R5cGUgPSBjb25zdHJ1Y3Rvci5wcm90b3R5cGUgfHwgY29uc3RydWN0b3I7XHJcblxyXG4gICAgcHJvdG90eXBlLmlzV2lsZEVtaXR0ZXI9IHRydWU7XHJcblxyXG4gICAgLy8gTGlzdGVuIG9uIHRoZSBnaXZlbiBgZXZlbnRgIHdpdGggYGZuYC4gU3RvcmUgYSBncm91cCBuYW1lIGlmIHByZXNlbnQuXHJcbiAgICBwcm90b3R5cGUub24gPSBmdW5jdGlvbiAoZXZlbnQsIGdyb3VwTmFtZSwgZm4pIHtcclxuICAgICAgICB0aGlzLmNhbGxiYWNrcyA9IHRoaXMuY2FsbGJhY2tzIHx8IHt9O1xyXG4gICAgICAgIHZhciBoYXNHcm91cCA9IChhcmd1bWVudHMubGVuZ3RoID09PSAzKSxcclxuICAgICAgICAgICAgZ3JvdXAgPSBoYXNHcm91cCA/IGFyZ3VtZW50c1sxXSA6IHVuZGVmaW5lZCxcclxuICAgICAgICAgICAgZnVuYyA9IGhhc0dyb3VwID8gYXJndW1lbnRzWzJdIDogYXJndW1lbnRzWzFdO1xyXG4gICAgICAgIGZ1bmMuX2dyb3VwTmFtZSA9IGdyb3VwO1xyXG4gICAgICAgICh0aGlzLmNhbGxiYWNrc1tldmVudF0gPSB0aGlzLmNhbGxiYWNrc1tldmVudF0gfHwgW10pLnB1c2goZnVuYyk7XHJcbiAgICAgICAgcmV0dXJuIHRoaXM7XHJcbiAgICB9O1xyXG5cclxuICAgIC8vIEFkZHMgYW4gYGV2ZW50YCBsaXN0ZW5lciB0aGF0IHdpbGwgYmUgaW52b2tlZCBhIHNpbmdsZVxyXG4gICAgLy8gdGltZSB0aGVuIGF1dG9tYXRpY2FsbHkgcmVtb3ZlZC5cclxuICAgIHByb3RvdHlwZS5vbmNlID0gZnVuY3Rpb24gKGV2ZW50LCBncm91cE5hbWUsIGZuKSB7XHJcbiAgICAgICAgdmFyIHNlbGYgPSB0aGlzLFxyXG4gICAgICAgICAgICBoYXNHcm91cCA9IChhcmd1bWVudHMubGVuZ3RoID09PSAzKSxcclxuICAgICAgICAgICAgZ3JvdXAgPSBoYXNHcm91cCA/IGFyZ3VtZW50c1sxXSA6IHVuZGVmaW5lZCxcclxuICAgICAgICAgICAgZnVuYyA9IGhhc0dyb3VwID8gYXJndW1lbnRzWzJdIDogYXJndW1lbnRzWzFdO1xyXG4gICAgICAgIGZ1bmN0aW9uIG9uKCkge1xyXG4gICAgICAgICAgICBzZWxmLm9mZihldmVudCwgb24pO1xyXG4gICAgICAgICAgICBmdW5jLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHRoaXMub24oZXZlbnQsIGdyb3VwLCBvbik7XHJcbiAgICAgICAgcmV0dXJuIHRoaXM7XHJcbiAgICB9O1xyXG5cclxuICAgIC8vIFVuYmluZHMgYW4gZW50aXJlIGdyb3VwXHJcbiAgICBwcm90b3R5cGUucmVsZWFzZUdyb3VwID0gZnVuY3Rpb24gKGdyb3VwTmFtZSkge1xyXG4gICAgICAgIHRoaXMuY2FsbGJhY2tzID0gdGhpcy5jYWxsYmFja3MgfHwge307XHJcbiAgICAgICAgdmFyIGl0ZW0sIGksIGxlbiwgaGFuZGxlcnM7XHJcbiAgICAgICAgZm9yIChpdGVtIGluIHRoaXMuY2FsbGJhY2tzKSB7XHJcbiAgICAgICAgICAgIGhhbmRsZXJzID0gdGhpcy5jYWxsYmFja3NbaXRlbV07XHJcbiAgICAgICAgICAgIGZvciAoaSA9IDAsIGxlbiA9IGhhbmRsZXJzLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XHJcbiAgICAgICAgICAgICAgICBpZiAoaGFuZGxlcnNbaV0uX2dyb3VwTmFtZSA9PT0gZ3JvdXBOYW1lKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgLy9jb25zb2xlLmxvZygncmVtb3ZpbmcnKTtcclxuICAgICAgICAgICAgICAgICAgICAvLyByZW1vdmUgaXQgYW5kIHNob3J0ZW4gdGhlIGFycmF5IHdlJ3JlIGxvb3BpbmcgdGhyb3VnaFxyXG4gICAgICAgICAgICAgICAgICAgIGhhbmRsZXJzLnNwbGljZShpLCAxKTtcclxuICAgICAgICAgICAgICAgICAgICBpLS07XHJcbiAgICAgICAgICAgICAgICAgICAgbGVuLS07XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgICAgcmV0dXJuIHRoaXM7XHJcbiAgICB9O1xyXG5cclxuICAgIC8vIFJlbW92ZSB0aGUgZ2l2ZW4gY2FsbGJhY2sgZm9yIGBldmVudGAgb3IgYWxsXHJcbiAgICAvLyByZWdpc3RlcmVkIGNhbGxiYWNrcy5cclxuICAgIHByb3RvdHlwZS5vZmYgPSBmdW5jdGlvbiAoZXZlbnQsIGZuKSB7XHJcbiAgICAgICAgdGhpcy5jYWxsYmFja3MgPSB0aGlzLmNhbGxiYWNrcyB8fCB7fTtcclxuICAgICAgICB2YXIgY2FsbGJhY2tzID0gdGhpcy5jYWxsYmFja3NbZXZlbnRdLFxyXG4gICAgICAgICAgICBpO1xyXG5cclxuICAgICAgICBpZiAoIWNhbGxiYWNrcykgcmV0dXJuIHRoaXM7XHJcblxyXG4gICAgICAgIC8vIHJlbW92ZSBhbGwgaGFuZGxlcnNcclxuICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMSkge1xyXG4gICAgICAgICAgICBkZWxldGUgdGhpcy5jYWxsYmFja3NbZXZlbnRdO1xyXG4gICAgICAgICAgICByZXR1cm4gdGhpcztcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC8vIHJlbW92ZSBzcGVjaWZpYyBoYW5kbGVyXHJcbiAgICAgICAgaSA9IGNhbGxiYWNrcy5pbmRleE9mKGZuKTtcclxuICAgICAgICBjYWxsYmFja3Muc3BsaWNlKGksIDEpO1xyXG4gICAgICAgIGlmIChjYWxsYmFja3MubGVuZ3RoID09PSAwKSB7XHJcbiAgICAgICAgICAgIGRlbGV0ZSB0aGlzLmNhbGxiYWNrc1tldmVudF07XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJldHVybiB0aGlzO1xyXG4gICAgfTtcclxuXHJcbiAgICAvLy8gRW1pdCBgZXZlbnRgIHdpdGggdGhlIGdpdmVuIGFyZ3MuXHJcbiAgICAvLyBhbHNvIGNhbGxzIGFueSBgKmAgaGFuZGxlcnNcclxuICAgIHByb3RvdHlwZS5lbWl0ID0gZnVuY3Rpb24gKGV2ZW50KSB7XHJcbiAgICAgICAgdGhpcy5jYWxsYmFja3MgPSB0aGlzLmNhbGxiYWNrcyB8fCB7fTtcclxuICAgICAgICB2YXIgYXJncyA9IFtdLnNsaWNlLmNhbGwoYXJndW1lbnRzLCAxKSxcclxuICAgICAgICAgICAgY2FsbGJhY2tzID0gdGhpcy5jYWxsYmFja3NbZXZlbnRdLFxyXG4gICAgICAgICAgICBzcGVjaWFsQ2FsbGJhY2tzID0gdGhpcy5nZXRXaWxkY2FyZENhbGxiYWNrcyhldmVudCksXHJcbiAgICAgICAgICAgIGksXHJcbiAgICAgICAgICAgIGxlbixcclxuICAgICAgICAgICAgaXRlbSxcclxuICAgICAgICAgICAgbGlzdGVuZXJzO1xyXG5cclxuICAgICAgICBpZiAoY2FsbGJhY2tzKSB7XHJcbiAgICAgICAgICAgIGxpc3RlbmVycyA9IGNhbGxiYWNrcy5zbGljZSgpO1xyXG4gICAgICAgICAgICBmb3IgKGkgPSAwLCBsZW4gPSBsaXN0ZW5lcnMubGVuZ3RoOyBpIDwgbGVuOyArK2kpIHtcclxuICAgICAgICAgICAgICAgIGlmICghbGlzdGVuZXJzW2ldKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICBsaXN0ZW5lcnNbaV0uYXBwbHkodGhpcywgYXJncyk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGlmIChzcGVjaWFsQ2FsbGJhY2tzKSB7XHJcbiAgICAgICAgICAgIGxlbiA9IHNwZWNpYWxDYWxsYmFja3MubGVuZ3RoO1xyXG4gICAgICAgICAgICBsaXN0ZW5lcnMgPSBzcGVjaWFsQ2FsbGJhY2tzLnNsaWNlKCk7XHJcbiAgICAgICAgICAgIGZvciAoaSA9IDAsIGxlbiA9IGxpc3RlbmVycy5sZW5ndGg7IGkgPCBsZW47ICsraSkge1xyXG4gICAgICAgICAgICAgICAgaWYgKCFsaXN0ZW5lcnNbaV0pIHtcclxuICAgICAgICAgICAgICAgICAgICBicmVhaztcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIGxpc3RlbmVyc1tpXS5hcHBseSh0aGlzLCBbZXZlbnRdLmNvbmNhdChhcmdzKSk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHJldHVybiB0aGlzO1xyXG4gICAgfTtcclxuXHJcbiAgICAvLyBIZWxwZXIgZm9yIGZvciBmaW5kaW5nIHNwZWNpYWwgd2lsZGNhcmQgZXZlbnQgaGFuZGxlcnMgdGhhdCBtYXRjaCB0aGUgZXZlbnRcclxuICAgIHByb3RvdHlwZS5nZXRXaWxkY2FyZENhbGxiYWNrcyA9IGZ1bmN0aW9uIChldmVudE5hbWUpIHtcclxuICAgICAgICB0aGlzLmNhbGxiYWNrcyA9IHRoaXMuY2FsbGJhY2tzIHx8IHt9O1xyXG4gICAgICAgIHZhciBpdGVtLFxyXG4gICAgICAgICAgICBzcGxpdCxcclxuICAgICAgICAgICAgcmVzdWx0ID0gW107XHJcblxyXG4gICAgICAgIGZvciAoaXRlbSBpbiB0aGlzLmNhbGxiYWNrcykge1xyXG4gICAgICAgICAgICBzcGxpdCA9IGl0ZW0uc3BsaXQoJyonKTtcclxuICAgICAgICAgICAgaWYgKGl0ZW0gPT09ICcqJyB8fCAoc3BsaXQubGVuZ3RoID09PSAyICYmIGV2ZW50TmFtZS5zbGljZSgwLCBzcGxpdFswXS5sZW5ndGgpID09PSBzcGxpdFswXSkpIHtcclxuICAgICAgICAgICAgICAgIHJlc3VsdCA9IHJlc3VsdC5jb25jYXQodGhpcy5jYWxsYmFja3NbaXRlbV0pO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJldHVybiByZXN1bHQ7XHJcbiAgICB9O1xyXG5cclxufTtcclxuXHJcbldpbGRFbWl0dGVyLm1peGluKFdpbGRFbWl0dGVyKTtcclxuIiwiLyohXG4gKiBFdmVudEVtaXR0ZXIgdjUuMi41IC0gZ2l0LmlvL2VlXG4gKiBVbmxpY2Vuc2UgLSBodHRwOi8vdW5saWNlbnNlLm9yZy9cbiAqIE9saXZlciBDYWxkd2VsbCAtIGh0dHA6Ly9vbGkubWUudWsvXG4gKiBAcHJlc2VydmVcbiAqL1xuXG47KGZ1bmN0aW9uIChleHBvcnRzKSB7XG4gICAgJ3VzZSBzdHJpY3QnO1xuXG4gICAgLyoqXG4gICAgICogQ2xhc3MgZm9yIG1hbmFnaW5nIGV2ZW50cy5cbiAgICAgKiBDYW4gYmUgZXh0ZW5kZWQgdG8gcHJvdmlkZSBldmVudCBmdW5jdGlvbmFsaXR5IGluIG90aGVyIGNsYXNzZXMuXG4gICAgICpcbiAgICAgKiBAY2xhc3MgRXZlbnRFbWl0dGVyIE1hbmFnZXMgZXZlbnQgcmVnaXN0ZXJpbmcgYW5kIGVtaXR0aW5nLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIEV2ZW50RW1pdHRlcigpIHt9XG5cbiAgICAvLyBTaG9ydGN1dHMgdG8gaW1wcm92ZSBzcGVlZCBhbmQgc2l6ZVxuICAgIHZhciBwcm90byA9IEV2ZW50RW1pdHRlci5wcm90b3R5cGU7XG4gICAgdmFyIG9yaWdpbmFsR2xvYmFsVmFsdWUgPSBleHBvcnRzLkV2ZW50RW1pdHRlcjtcblxuICAgIC8qKlxuICAgICAqIEZpbmRzIHRoZSBpbmRleCBvZiB0aGUgbGlzdGVuZXIgZm9yIHRoZSBldmVudCBpbiBpdHMgc3RvcmFnZSBhcnJheS5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb25bXX0gbGlzdGVuZXJzIEFycmF5IG9mIGxpc3RlbmVycyB0byBzZWFyY2ggdGhyb3VnaC5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBsaXN0ZW5lciBNZXRob2QgdG8gbG9vayBmb3IuXG4gICAgICogQHJldHVybiB7TnVtYmVyfSBJbmRleCBvZiB0aGUgc3BlY2lmaWVkIGxpc3RlbmVyLCAtMSBpZiBub3QgZm91bmRcbiAgICAgKiBAYXBpIHByaXZhdGVcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBpbmRleE9mTGlzdGVuZXIobGlzdGVuZXJzLCBsaXN0ZW5lcikge1xuICAgICAgICB2YXIgaSA9IGxpc3RlbmVycy5sZW5ndGg7XG4gICAgICAgIHdoaWxlIChpLS0pIHtcbiAgICAgICAgICAgIGlmIChsaXN0ZW5lcnNbaV0ubGlzdGVuZXIgPT09IGxpc3RlbmVyKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gLTE7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQWxpYXMgYSBtZXRob2Qgd2hpbGUga2VlcGluZyB0aGUgY29udGV4dCBjb3JyZWN0LCB0byBhbGxvdyBmb3Igb3ZlcndyaXRpbmcgb2YgdGFyZ2V0IG1ldGhvZC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfSBuYW1lIFRoZSBuYW1lIG9mIHRoZSB0YXJnZXQgbWV0aG9kLlxuICAgICAqIEByZXR1cm4ge0Z1bmN0aW9ufSBUaGUgYWxpYXNlZCBtZXRob2RcbiAgICAgKiBAYXBpIHByaXZhdGVcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBhbGlhcyhuYW1lKSB7XG4gICAgICAgIHJldHVybiBmdW5jdGlvbiBhbGlhc0Nsb3N1cmUoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpc1tuYW1lXS5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgICAgICB9O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgdGhlIGxpc3RlbmVyIGFycmF5IGZvciB0aGUgc3BlY2lmaWVkIGV2ZW50LlxuICAgICAqIFdpbGwgaW5pdGlhbGlzZSB0aGUgZXZlbnQgb2JqZWN0IGFuZCBsaXN0ZW5lciBhcnJheXMgaWYgcmVxdWlyZWQuXG4gICAgICogV2lsbCByZXR1cm4gYW4gb2JqZWN0IGlmIHlvdSB1c2UgYSByZWdleCBzZWFyY2guIFRoZSBvYmplY3QgY29udGFpbnMga2V5cyBmb3IgZWFjaCBtYXRjaGVkIGV2ZW50LiBTbyAvYmFbcnpdLyBtaWdodCByZXR1cm4gYW4gb2JqZWN0IGNvbnRhaW5pbmcgYmFyIGFuZCBiYXouIEJ1dCBvbmx5IGlmIHlvdSBoYXZlIGVpdGhlciBkZWZpbmVkIHRoZW0gd2l0aCBkZWZpbmVFdmVudCBvciBhZGRlZCBzb21lIGxpc3RlbmVycyB0byB0aGVtLlxuICAgICAqIEVhY2ggcHJvcGVydHkgaW4gdGhlIG9iamVjdCByZXNwb25zZSBpcyBhbiBhcnJheSBvZiBsaXN0ZW5lciBmdW5jdGlvbnMuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1N0cmluZ3xSZWdFeHB9IGV2dCBOYW1lIG9mIHRoZSBldmVudCB0byByZXR1cm4gdGhlIGxpc3RlbmVycyBmcm9tLlxuICAgICAqIEByZXR1cm4ge0Z1bmN0aW9uW118T2JqZWN0fSBBbGwgbGlzdGVuZXIgZnVuY3Rpb25zIGZvciB0aGUgZXZlbnQuXG4gICAgICovXG4gICAgcHJvdG8uZ2V0TGlzdGVuZXJzID0gZnVuY3Rpb24gZ2V0TGlzdGVuZXJzKGV2dCkge1xuICAgICAgICB2YXIgZXZlbnRzID0gdGhpcy5fZ2V0RXZlbnRzKCk7XG4gICAgICAgIHZhciByZXNwb25zZTtcbiAgICAgICAgdmFyIGtleTtcblxuICAgICAgICAvLyBSZXR1cm4gYSBjb25jYXRlbmF0ZWQgYXJyYXkgb2YgYWxsIG1hdGNoaW5nIGV2ZW50cyBpZlxuICAgICAgICAvLyB0aGUgc2VsZWN0b3IgaXMgYSByZWd1bGFyIGV4cHJlc3Npb24uXG4gICAgICAgIGlmIChldnQgaW5zdGFuY2VvZiBSZWdFeHApIHtcbiAgICAgICAgICAgIHJlc3BvbnNlID0ge307XG4gICAgICAgICAgICBmb3IgKGtleSBpbiBldmVudHMpIHtcbiAgICAgICAgICAgICAgICBpZiAoZXZlbnRzLmhhc093blByb3BlcnR5KGtleSkgJiYgZXZ0LnRlc3Qoa2V5KSkge1xuICAgICAgICAgICAgICAgICAgICByZXNwb25zZVtrZXldID0gZXZlbnRzW2tleV07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgcmVzcG9uc2UgPSBldmVudHNbZXZ0XSB8fCAoZXZlbnRzW2V2dF0gPSBbXSk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gcmVzcG9uc2U7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIFRha2VzIGEgbGlzdCBvZiBsaXN0ZW5lciBvYmplY3RzIGFuZCBmbGF0dGVucyBpdCBpbnRvIGEgbGlzdCBvZiBsaXN0ZW5lciBmdW5jdGlvbnMuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge09iamVjdFtdfSBsaXN0ZW5lcnMgUmF3IGxpc3RlbmVyIG9iamVjdHMuXG4gICAgICogQHJldHVybiB7RnVuY3Rpb25bXX0gSnVzdCB0aGUgbGlzdGVuZXIgZnVuY3Rpb25zLlxuICAgICAqL1xuICAgIHByb3RvLmZsYXR0ZW5MaXN0ZW5lcnMgPSBmdW5jdGlvbiBmbGF0dGVuTGlzdGVuZXJzKGxpc3RlbmVycykge1xuICAgICAgICB2YXIgZmxhdExpc3RlbmVycyA9IFtdO1xuICAgICAgICB2YXIgaTtcblxuICAgICAgICBmb3IgKGkgPSAwOyBpIDwgbGlzdGVuZXJzLmxlbmd0aDsgaSArPSAxKSB7XG4gICAgICAgICAgICBmbGF0TGlzdGVuZXJzLnB1c2gobGlzdGVuZXJzW2ldLmxpc3RlbmVyKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBmbGF0TGlzdGVuZXJzO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBGZXRjaGVzIHRoZSByZXF1ZXN0ZWQgbGlzdGVuZXJzIHZpYSBnZXRMaXN0ZW5lcnMgYnV0IHdpbGwgYWx3YXlzIHJldHVybiB0aGUgcmVzdWx0cyBpbnNpZGUgYW4gb2JqZWN0LiBUaGlzIGlzIG1haW5seSBmb3IgaW50ZXJuYWwgdXNlIGJ1dCBvdGhlcnMgbWF5IGZpbmQgaXQgdXNlZnVsLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtTdHJpbmd8UmVnRXhwfSBldnQgTmFtZSBvZiB0aGUgZXZlbnQgdG8gcmV0dXJuIHRoZSBsaXN0ZW5lcnMgZnJvbS5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEFsbCBsaXN0ZW5lciBmdW5jdGlvbnMgZm9yIGFuIGV2ZW50IGluIGFuIG9iamVjdC5cbiAgICAgKi9cbiAgICBwcm90by5nZXRMaXN0ZW5lcnNBc09iamVjdCA9IGZ1bmN0aW9uIGdldExpc3RlbmVyc0FzT2JqZWN0KGV2dCkge1xuICAgICAgICB2YXIgbGlzdGVuZXJzID0gdGhpcy5nZXRMaXN0ZW5lcnMoZXZ0KTtcbiAgICAgICAgdmFyIHJlc3BvbnNlO1xuXG4gICAgICAgIGlmIChsaXN0ZW5lcnMgaW5zdGFuY2VvZiBBcnJheSkge1xuICAgICAgICAgICAgcmVzcG9uc2UgPSB7fTtcbiAgICAgICAgICAgIHJlc3BvbnNlW2V2dF0gPSBsaXN0ZW5lcnM7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gcmVzcG9uc2UgfHwgbGlzdGVuZXJzO1xuICAgIH07XG5cbiAgICBmdW5jdGlvbiBpc1ZhbGlkTGlzdGVuZXIgKGxpc3RlbmVyKSB7XG4gICAgICAgIGlmICh0eXBlb2YgbGlzdGVuZXIgPT09ICdmdW5jdGlvbicgfHwgbGlzdGVuZXIgaW5zdGFuY2VvZiBSZWdFeHApIHtcbiAgICAgICAgICAgIHJldHVybiB0cnVlXG4gICAgICAgIH0gZWxzZSBpZiAobGlzdGVuZXIgJiYgdHlwZW9mIGxpc3RlbmVyID09PSAnb2JqZWN0Jykge1xuICAgICAgICAgICAgcmV0dXJuIGlzVmFsaWRMaXN0ZW5lcihsaXN0ZW5lci5saXN0ZW5lcilcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQWRkcyBhIGxpc3RlbmVyIGZ1bmN0aW9uIHRvIHRoZSBzcGVjaWZpZWQgZXZlbnQuXG4gICAgICogVGhlIGxpc3RlbmVyIHdpbGwgbm90IGJlIGFkZGVkIGlmIGl0IGlzIGEgZHVwbGljYXRlLlxuICAgICAqIElmIHRoZSBsaXN0ZW5lciByZXR1cm5zIHRydWUgdGhlbiBpdCB3aWxsIGJlIHJlbW92ZWQgYWZ0ZXIgaXQgaXMgY2FsbGVkLlxuICAgICAqIElmIHlvdSBwYXNzIGEgcmVndWxhciBleHByZXNzaW9uIGFzIHRoZSBldmVudCBuYW1lIHRoZW4gdGhlIGxpc3RlbmVyIHdpbGwgYmUgYWRkZWQgdG8gYWxsIGV2ZW50cyB0aGF0IG1hdGNoIGl0LlxuICAgICAqXG4gICAgICogQHBhcmFtIHtTdHJpbmd8UmVnRXhwfSBldnQgTmFtZSBvZiB0aGUgZXZlbnQgdG8gYXR0YWNoIHRoZSBsaXN0ZW5lciB0by5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBsaXN0ZW5lciBNZXRob2QgdG8gYmUgY2FsbGVkIHdoZW4gdGhlIGV2ZW50IGlzIGVtaXR0ZWQuIElmIHRoZSBmdW5jdGlvbiByZXR1cm5zIHRydWUgdGhlbiBpdCB3aWxsIGJlIHJlbW92ZWQgYWZ0ZXIgY2FsbGluZy5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEN1cnJlbnQgaW5zdGFuY2Ugb2YgRXZlbnRFbWl0dGVyIGZvciBjaGFpbmluZy5cbiAgICAgKi9cbiAgICBwcm90by5hZGRMaXN0ZW5lciA9IGZ1bmN0aW9uIGFkZExpc3RlbmVyKGV2dCwgbGlzdGVuZXIpIHtcbiAgICAgICAgaWYgKCFpc1ZhbGlkTGlzdGVuZXIobGlzdGVuZXIpKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdsaXN0ZW5lciBtdXN0IGJlIGEgZnVuY3Rpb24nKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBsaXN0ZW5lcnMgPSB0aGlzLmdldExpc3RlbmVyc0FzT2JqZWN0KGV2dCk7XG4gICAgICAgIHZhciBsaXN0ZW5lcklzV3JhcHBlZCA9IHR5cGVvZiBsaXN0ZW5lciA9PT0gJ29iamVjdCc7XG4gICAgICAgIHZhciBrZXk7XG5cbiAgICAgICAgZm9yIChrZXkgaW4gbGlzdGVuZXJzKSB7XG4gICAgICAgICAgICBpZiAobGlzdGVuZXJzLmhhc093blByb3BlcnR5KGtleSkgJiYgaW5kZXhPZkxpc3RlbmVyKGxpc3RlbmVyc1trZXldLCBsaXN0ZW5lcikgPT09IC0xKSB7XG4gICAgICAgICAgICAgICAgbGlzdGVuZXJzW2tleV0ucHVzaChsaXN0ZW5lcklzV3JhcHBlZCA/IGxpc3RlbmVyIDoge1xuICAgICAgICAgICAgICAgICAgICBsaXN0ZW5lcjogbGlzdGVuZXIsXG4gICAgICAgICAgICAgICAgICAgIG9uY2U6IGZhbHNlXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogQWxpYXMgb2YgYWRkTGlzdGVuZXJcbiAgICAgKi9cbiAgICBwcm90by5vbiA9IGFsaWFzKCdhZGRMaXN0ZW5lcicpO1xuXG4gICAgLyoqXG4gICAgICogU2VtaS1hbGlhcyBvZiBhZGRMaXN0ZW5lci4gSXQgd2lsbCBhZGQgYSBsaXN0ZW5lciB0aGF0IHdpbGwgYmVcbiAgICAgKiBhdXRvbWF0aWNhbGx5IHJlbW92ZWQgYWZ0ZXIgaXRzIGZpcnN0IGV4ZWN1dGlvbi5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfFJlZ0V4cH0gZXZ0IE5hbWUgb2YgdGhlIGV2ZW50IHRvIGF0dGFjaCB0aGUgbGlzdGVuZXIgdG8uXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gbGlzdGVuZXIgTWV0aG9kIHRvIGJlIGNhbGxlZCB3aGVuIHRoZSBldmVudCBpcyBlbWl0dGVkLiBJZiB0aGUgZnVuY3Rpb24gcmV0dXJucyB0cnVlIHRoZW4gaXQgd2lsbCBiZSByZW1vdmVkIGFmdGVyIGNhbGxpbmcuXG4gICAgICogQHJldHVybiB7T2JqZWN0fSBDdXJyZW50IGluc3RhbmNlIG9mIEV2ZW50RW1pdHRlciBmb3IgY2hhaW5pbmcuXG4gICAgICovXG4gICAgcHJvdG8uYWRkT25jZUxpc3RlbmVyID0gZnVuY3Rpb24gYWRkT25jZUxpc3RlbmVyKGV2dCwgbGlzdGVuZXIpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuYWRkTGlzdGVuZXIoZXZ0LCB7XG4gICAgICAgICAgICBsaXN0ZW5lcjogbGlzdGVuZXIsXG4gICAgICAgICAgICBvbmNlOiB0cnVlXG4gICAgICAgIH0pO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBBbGlhcyBvZiBhZGRPbmNlTGlzdGVuZXIuXG4gICAgICovXG4gICAgcHJvdG8ub25jZSA9IGFsaWFzKCdhZGRPbmNlTGlzdGVuZXInKTtcblxuICAgIC8qKlxuICAgICAqIERlZmluZXMgYW4gZXZlbnQgbmFtZS4gVGhpcyBpcyByZXF1aXJlZCBpZiB5b3Ugd2FudCB0byB1c2UgYSByZWdleCB0byBhZGQgYSBsaXN0ZW5lciB0byBtdWx0aXBsZSBldmVudHMgYXQgb25jZS4gSWYgeW91IGRvbid0IGRvIHRoaXMgdGhlbiBob3cgZG8geW91IGV4cGVjdCBpdCB0byBrbm93IHdoYXQgZXZlbnQgdG8gYWRkIHRvPyBTaG91bGQgaXQganVzdCBhZGQgdG8gZXZlcnkgcG9zc2libGUgbWF0Y2ggZm9yIGEgcmVnZXg/IE5vLiBUaGF0IGlzIHNjYXJ5IGFuZCBiYWQuXG4gICAgICogWW91IG5lZWQgdG8gdGVsbCBpdCB3aGF0IGV2ZW50IG5hbWVzIHNob3VsZCBiZSBtYXRjaGVkIGJ5IGEgcmVnZXguXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1N0cmluZ30gZXZ0IE5hbWUgb2YgdGhlIGV2ZW50IHRvIGNyZWF0ZS5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEN1cnJlbnQgaW5zdGFuY2Ugb2YgRXZlbnRFbWl0dGVyIGZvciBjaGFpbmluZy5cbiAgICAgKi9cbiAgICBwcm90by5kZWZpbmVFdmVudCA9IGZ1bmN0aW9uIGRlZmluZUV2ZW50KGV2dCkge1xuICAgICAgICB0aGlzLmdldExpc3RlbmVycyhldnQpO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogVXNlcyBkZWZpbmVFdmVudCB0byBkZWZpbmUgbXVsdGlwbGUgZXZlbnRzLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtTdHJpbmdbXX0gZXZ0cyBBbiBhcnJheSBvZiBldmVudCBuYW1lcyB0byBkZWZpbmUuXG4gICAgICogQHJldHVybiB7T2JqZWN0fSBDdXJyZW50IGluc3RhbmNlIG9mIEV2ZW50RW1pdHRlciBmb3IgY2hhaW5pbmcuXG4gICAgICovXG4gICAgcHJvdG8uZGVmaW5lRXZlbnRzID0gZnVuY3Rpb24gZGVmaW5lRXZlbnRzKGV2dHMpIHtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBldnRzLmxlbmd0aDsgaSArPSAxKSB7XG4gICAgICAgICAgICB0aGlzLmRlZmluZUV2ZW50KGV2dHNbaV0pO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBSZW1vdmVzIGEgbGlzdGVuZXIgZnVuY3Rpb24gZnJvbSB0aGUgc3BlY2lmaWVkIGV2ZW50LlxuICAgICAqIFdoZW4gcGFzc2VkIGEgcmVndWxhciBleHByZXNzaW9uIGFzIHRoZSBldmVudCBuYW1lLCBpdCB3aWxsIHJlbW92ZSB0aGUgbGlzdGVuZXIgZnJvbSBhbGwgZXZlbnRzIHRoYXQgbWF0Y2ggaXQuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1N0cmluZ3xSZWdFeHB9IGV2dCBOYW1lIG9mIHRoZSBldmVudCB0byByZW1vdmUgdGhlIGxpc3RlbmVyIGZyb20uXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gbGlzdGVuZXIgTWV0aG9kIHRvIHJlbW92ZSBmcm9tIHRoZSBldmVudC5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEN1cnJlbnQgaW5zdGFuY2Ugb2YgRXZlbnRFbWl0dGVyIGZvciBjaGFpbmluZy5cbiAgICAgKi9cbiAgICBwcm90by5yZW1vdmVMaXN0ZW5lciA9IGZ1bmN0aW9uIHJlbW92ZUxpc3RlbmVyKGV2dCwgbGlzdGVuZXIpIHtcbiAgICAgICAgdmFyIGxpc3RlbmVycyA9IHRoaXMuZ2V0TGlzdGVuZXJzQXNPYmplY3QoZXZ0KTtcbiAgICAgICAgdmFyIGluZGV4O1xuICAgICAgICB2YXIga2V5O1xuXG4gICAgICAgIGZvciAoa2V5IGluIGxpc3RlbmVycykge1xuICAgICAgICAgICAgaWYgKGxpc3RlbmVycy5oYXNPd25Qcm9wZXJ0eShrZXkpKSB7XG4gICAgICAgICAgICAgICAgaW5kZXggPSBpbmRleE9mTGlzdGVuZXIobGlzdGVuZXJzW2tleV0sIGxpc3RlbmVyKTtcblxuICAgICAgICAgICAgICAgIGlmIChpbmRleCAhPT0gLTEpIHtcbiAgICAgICAgICAgICAgICAgICAgbGlzdGVuZXJzW2tleV0uc3BsaWNlKGluZGV4LCAxKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogQWxpYXMgb2YgcmVtb3ZlTGlzdGVuZXJcbiAgICAgKi9cbiAgICBwcm90by5vZmYgPSBhbGlhcygncmVtb3ZlTGlzdGVuZXInKTtcblxuICAgIC8qKlxuICAgICAqIEFkZHMgbGlzdGVuZXJzIGluIGJ1bGsgdXNpbmcgdGhlIG1hbmlwdWxhdGVMaXN0ZW5lcnMgbWV0aG9kLlxuICAgICAqIElmIHlvdSBwYXNzIGFuIG9iamVjdCBhcyB0aGUgZmlyc3QgYXJndW1lbnQgeW91IGNhbiBhZGQgdG8gbXVsdGlwbGUgZXZlbnRzIGF0IG9uY2UuIFRoZSBvYmplY3Qgc2hvdWxkIGNvbnRhaW4ga2V5IHZhbHVlIHBhaXJzIG9mIGV2ZW50cyBhbmQgbGlzdGVuZXJzIG9yIGxpc3RlbmVyIGFycmF5cy4gWW91IGNhbiBhbHNvIHBhc3MgaXQgYW4gZXZlbnQgbmFtZSBhbmQgYW4gYXJyYXkgb2YgbGlzdGVuZXJzIHRvIGJlIGFkZGVkLlxuICAgICAqIFlvdSBjYW4gYWxzbyBwYXNzIGl0IGEgcmVndWxhciBleHByZXNzaW9uIHRvIGFkZCB0aGUgYXJyYXkgb2YgbGlzdGVuZXJzIHRvIGFsbCBldmVudHMgdGhhdCBtYXRjaCBpdC5cbiAgICAgKiBZZWFoLCB0aGlzIGZ1bmN0aW9uIGRvZXMgcXVpdGUgYSBiaXQuIFRoYXQncyBwcm9iYWJseSBhIGJhZCB0aGluZy5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfE9iamVjdHxSZWdFeHB9IGV2dCBBbiBldmVudCBuYW1lIGlmIHlvdSB3aWxsIHBhc3MgYW4gYXJyYXkgb2YgbGlzdGVuZXJzIG5leHQuIEFuIG9iamVjdCBpZiB5b3Ugd2lzaCB0byBhZGQgdG8gbXVsdGlwbGUgZXZlbnRzIGF0IG9uY2UuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbltdfSBbbGlzdGVuZXJzXSBBbiBvcHRpb25hbCBhcnJheSBvZiBsaXN0ZW5lciBmdW5jdGlvbnMgdG8gYWRkLlxuICAgICAqIEByZXR1cm4ge09iamVjdH0gQ3VycmVudCBpbnN0YW5jZSBvZiBFdmVudEVtaXR0ZXIgZm9yIGNoYWluaW5nLlxuICAgICAqL1xuICAgIHByb3RvLmFkZExpc3RlbmVycyA9IGZ1bmN0aW9uIGFkZExpc3RlbmVycyhldnQsIGxpc3RlbmVycykge1xuICAgICAgICAvLyBQYXNzIHRocm91Z2ggdG8gbWFuaXB1bGF0ZUxpc3RlbmVyc1xuICAgICAgICByZXR1cm4gdGhpcy5tYW5pcHVsYXRlTGlzdGVuZXJzKGZhbHNlLCBldnQsIGxpc3RlbmVycyk7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIFJlbW92ZXMgbGlzdGVuZXJzIGluIGJ1bGsgdXNpbmcgdGhlIG1hbmlwdWxhdGVMaXN0ZW5lcnMgbWV0aG9kLlxuICAgICAqIElmIHlvdSBwYXNzIGFuIG9iamVjdCBhcyB0aGUgZmlyc3QgYXJndW1lbnQgeW91IGNhbiByZW1vdmUgZnJvbSBtdWx0aXBsZSBldmVudHMgYXQgb25jZS4gVGhlIG9iamVjdCBzaG91bGQgY29udGFpbiBrZXkgdmFsdWUgcGFpcnMgb2YgZXZlbnRzIGFuZCBsaXN0ZW5lcnMgb3IgbGlzdGVuZXIgYXJyYXlzLlxuICAgICAqIFlvdSBjYW4gYWxzbyBwYXNzIGl0IGFuIGV2ZW50IG5hbWUgYW5kIGFuIGFycmF5IG9mIGxpc3RlbmVycyB0byBiZSByZW1vdmVkLlxuICAgICAqIFlvdSBjYW4gYWxzbyBwYXNzIGl0IGEgcmVndWxhciBleHByZXNzaW9uIHRvIHJlbW92ZSB0aGUgbGlzdGVuZXJzIGZyb20gYWxsIGV2ZW50cyB0aGF0IG1hdGNoIGl0LlxuICAgICAqXG4gICAgICogQHBhcmFtIHtTdHJpbmd8T2JqZWN0fFJlZ0V4cH0gZXZ0IEFuIGV2ZW50IG5hbWUgaWYgeW91IHdpbGwgcGFzcyBhbiBhcnJheSBvZiBsaXN0ZW5lcnMgbmV4dC4gQW4gb2JqZWN0IGlmIHlvdSB3aXNoIHRvIHJlbW92ZSBmcm9tIG11bHRpcGxlIGV2ZW50cyBhdCBvbmNlLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb25bXX0gW2xpc3RlbmVyc10gQW4gb3B0aW9uYWwgYXJyYXkgb2YgbGlzdGVuZXIgZnVuY3Rpb25zIHRvIHJlbW92ZS5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEN1cnJlbnQgaW5zdGFuY2Ugb2YgRXZlbnRFbWl0dGVyIGZvciBjaGFpbmluZy5cbiAgICAgKi9cbiAgICBwcm90by5yZW1vdmVMaXN0ZW5lcnMgPSBmdW5jdGlvbiByZW1vdmVMaXN0ZW5lcnMoZXZ0LCBsaXN0ZW5lcnMpIHtcbiAgICAgICAgLy8gUGFzcyB0aHJvdWdoIHRvIG1hbmlwdWxhdGVMaXN0ZW5lcnNcbiAgICAgICAgcmV0dXJuIHRoaXMubWFuaXB1bGF0ZUxpc3RlbmVycyh0cnVlLCBldnQsIGxpc3RlbmVycyk7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEVkaXRzIGxpc3RlbmVycyBpbiBidWxrLiBUaGUgYWRkTGlzdGVuZXJzIGFuZCByZW1vdmVMaXN0ZW5lcnMgbWV0aG9kcyBib3RoIHVzZSB0aGlzIHRvIGRvIHRoZWlyIGpvYi4gWW91IHNob3VsZCByZWFsbHkgdXNlIHRob3NlIGluc3RlYWQsIHRoaXMgaXMgYSBsaXR0bGUgbG93ZXIgbGV2ZWwuXG4gICAgICogVGhlIGZpcnN0IGFyZ3VtZW50IHdpbGwgZGV0ZXJtaW5lIGlmIHRoZSBsaXN0ZW5lcnMgYXJlIHJlbW92ZWQgKHRydWUpIG9yIGFkZGVkIChmYWxzZSkuXG4gICAgICogSWYgeW91IHBhc3MgYW4gb2JqZWN0IGFzIHRoZSBzZWNvbmQgYXJndW1lbnQgeW91IGNhbiBhZGQvcmVtb3ZlIGZyb20gbXVsdGlwbGUgZXZlbnRzIGF0IG9uY2UuIFRoZSBvYmplY3Qgc2hvdWxkIGNvbnRhaW4ga2V5IHZhbHVlIHBhaXJzIG9mIGV2ZW50cyBhbmQgbGlzdGVuZXJzIG9yIGxpc3RlbmVyIGFycmF5cy5cbiAgICAgKiBZb3UgY2FuIGFsc28gcGFzcyBpdCBhbiBldmVudCBuYW1lIGFuZCBhbiBhcnJheSBvZiBsaXN0ZW5lcnMgdG8gYmUgYWRkZWQvcmVtb3ZlZC5cbiAgICAgKiBZb3UgY2FuIGFsc28gcGFzcyBpdCBhIHJlZ3VsYXIgZXhwcmVzc2lvbiB0byBtYW5pcHVsYXRlIHRoZSBsaXN0ZW5lcnMgb2YgYWxsIGV2ZW50cyB0aGF0IG1hdGNoIGl0LlxuICAgICAqXG4gICAgICogQHBhcmFtIHtCb29sZWFufSByZW1vdmUgVHJ1ZSBpZiB5b3Ugd2FudCB0byByZW1vdmUgbGlzdGVuZXJzLCBmYWxzZSBpZiB5b3Ugd2FudCB0byBhZGQuXG4gICAgICogQHBhcmFtIHtTdHJpbmd8T2JqZWN0fFJlZ0V4cH0gZXZ0IEFuIGV2ZW50IG5hbWUgaWYgeW91IHdpbGwgcGFzcyBhbiBhcnJheSBvZiBsaXN0ZW5lcnMgbmV4dC4gQW4gb2JqZWN0IGlmIHlvdSB3aXNoIHRvIGFkZC9yZW1vdmUgZnJvbSBtdWx0aXBsZSBldmVudHMgYXQgb25jZS5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9uW119IFtsaXN0ZW5lcnNdIEFuIG9wdGlvbmFsIGFycmF5IG9mIGxpc3RlbmVyIGZ1bmN0aW9ucyB0byBhZGQvcmVtb3ZlLlxuICAgICAqIEByZXR1cm4ge09iamVjdH0gQ3VycmVudCBpbnN0YW5jZSBvZiBFdmVudEVtaXR0ZXIgZm9yIGNoYWluaW5nLlxuICAgICAqL1xuICAgIHByb3RvLm1hbmlwdWxhdGVMaXN0ZW5lcnMgPSBmdW5jdGlvbiBtYW5pcHVsYXRlTGlzdGVuZXJzKHJlbW92ZSwgZXZ0LCBsaXN0ZW5lcnMpIHtcbiAgICAgICAgdmFyIGk7XG4gICAgICAgIHZhciB2YWx1ZTtcbiAgICAgICAgdmFyIHNpbmdsZSA9IHJlbW92ZSA/IHRoaXMucmVtb3ZlTGlzdGVuZXIgOiB0aGlzLmFkZExpc3RlbmVyO1xuICAgICAgICB2YXIgbXVsdGlwbGUgPSByZW1vdmUgPyB0aGlzLnJlbW92ZUxpc3RlbmVycyA6IHRoaXMuYWRkTGlzdGVuZXJzO1xuXG4gICAgICAgIC8vIElmIGV2dCBpcyBhbiBvYmplY3QgdGhlbiBwYXNzIGVhY2ggb2YgaXRzIHByb3BlcnRpZXMgdG8gdGhpcyBtZXRob2RcbiAgICAgICAgaWYgKHR5cGVvZiBldnQgPT09ICdvYmplY3QnICYmICEoZXZ0IGluc3RhbmNlb2YgUmVnRXhwKSkge1xuICAgICAgICAgICAgZm9yIChpIGluIGV2dCkge1xuICAgICAgICAgICAgICAgIGlmIChldnQuaGFzT3duUHJvcGVydHkoaSkgJiYgKHZhbHVlID0gZXZ0W2ldKSkge1xuICAgICAgICAgICAgICAgICAgICAvLyBQYXNzIHRoZSBzaW5nbGUgbGlzdGVuZXIgc3RyYWlnaHQgdGhyb3VnaCB0byB0aGUgc2luZ3VsYXIgbWV0aG9kXG4gICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgdmFsdWUgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNpbmdsZS5jYWxsKHRoaXMsIGksIHZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIE90aGVyd2lzZSBwYXNzIGJhY2sgdG8gdGhlIG11bHRpcGxlIGZ1bmN0aW9uXG4gICAgICAgICAgICAgICAgICAgICAgICBtdWx0aXBsZS5jYWxsKHRoaXMsIGksIHZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIC8vIFNvIGV2dCBtdXN0IGJlIGEgc3RyaW5nXG4gICAgICAgICAgICAvLyBBbmQgbGlzdGVuZXJzIG11c3QgYmUgYW4gYXJyYXkgb2YgbGlzdGVuZXJzXG4gICAgICAgICAgICAvLyBMb29wIG92ZXIgaXQgYW5kIHBhc3MgZWFjaCBvbmUgdG8gdGhlIG11bHRpcGxlIG1ldGhvZFxuICAgICAgICAgICAgaSA9IGxpc3RlbmVycy5sZW5ndGg7XG4gICAgICAgICAgICB3aGlsZSAoaS0tKSB7XG4gICAgICAgICAgICAgICAgc2luZ2xlLmNhbGwodGhpcywgZXZ0LCBsaXN0ZW5lcnNbaV0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIFJlbW92ZXMgYWxsIGxpc3RlbmVycyBmcm9tIGEgc3BlY2lmaWVkIGV2ZW50LlxuICAgICAqIElmIHlvdSBkbyBub3Qgc3BlY2lmeSBhbiBldmVudCB0aGVuIGFsbCBsaXN0ZW5lcnMgd2lsbCBiZSByZW1vdmVkLlxuICAgICAqIFRoYXQgbWVhbnMgZXZlcnkgZXZlbnQgd2lsbCBiZSBlbXB0aWVkLlxuICAgICAqIFlvdSBjYW4gYWxzbyBwYXNzIGEgcmVnZXggdG8gcmVtb3ZlIGFsbCBldmVudHMgdGhhdCBtYXRjaCBpdC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfFJlZ0V4cH0gW2V2dF0gT3B0aW9uYWwgbmFtZSBvZiB0aGUgZXZlbnQgdG8gcmVtb3ZlIGFsbCBsaXN0ZW5lcnMgZm9yLiBXaWxsIHJlbW92ZSBmcm9tIGV2ZXJ5IGV2ZW50IGlmIG5vdCBwYXNzZWQuXG4gICAgICogQHJldHVybiB7T2JqZWN0fSBDdXJyZW50IGluc3RhbmNlIG9mIEV2ZW50RW1pdHRlciBmb3IgY2hhaW5pbmcuXG4gICAgICovXG4gICAgcHJvdG8ucmVtb3ZlRXZlbnQgPSBmdW5jdGlvbiByZW1vdmVFdmVudChldnQpIHtcbiAgICAgICAgdmFyIHR5cGUgPSB0eXBlb2YgZXZ0O1xuICAgICAgICB2YXIgZXZlbnRzID0gdGhpcy5fZ2V0RXZlbnRzKCk7XG4gICAgICAgIHZhciBrZXk7XG5cbiAgICAgICAgLy8gUmVtb3ZlIGRpZmZlcmVudCB0aGluZ3MgZGVwZW5kaW5nIG9uIHRoZSBzdGF0ZSBvZiBldnRcbiAgICAgICAgaWYgKHR5cGUgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAvLyBSZW1vdmUgYWxsIGxpc3RlbmVycyBmb3IgdGhlIHNwZWNpZmllZCBldmVudFxuICAgICAgICAgICAgZGVsZXRlIGV2ZW50c1tldnRdO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKGV2dCBpbnN0YW5jZW9mIFJlZ0V4cCkge1xuICAgICAgICAgICAgLy8gUmVtb3ZlIGFsbCBldmVudHMgbWF0Y2hpbmcgdGhlIHJlZ2V4LlxuICAgICAgICAgICAgZm9yIChrZXkgaW4gZXZlbnRzKSB7XG4gICAgICAgICAgICAgICAgaWYgKGV2ZW50cy5oYXNPd25Qcm9wZXJ0eShrZXkpICYmIGV2dC50ZXN0KGtleSkpIHtcbiAgICAgICAgICAgICAgICAgICAgZGVsZXRlIGV2ZW50c1trZXldO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIC8vIFJlbW92ZSBhbGwgbGlzdGVuZXJzIGluIGFsbCBldmVudHNcbiAgICAgICAgICAgIGRlbGV0ZSB0aGlzLl9ldmVudHM7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogQWxpYXMgb2YgcmVtb3ZlRXZlbnQuXG4gICAgICpcbiAgICAgKiBBZGRlZCB0byBtaXJyb3IgdGhlIG5vZGUgQVBJLlxuICAgICAqL1xuICAgIHByb3RvLnJlbW92ZUFsbExpc3RlbmVycyA9IGFsaWFzKCdyZW1vdmVFdmVudCcpO1xuXG4gICAgLyoqXG4gICAgICogRW1pdHMgYW4gZXZlbnQgb2YgeW91ciBjaG9pY2UuXG4gICAgICogV2hlbiBlbWl0dGVkLCBldmVyeSBsaXN0ZW5lciBhdHRhY2hlZCB0byB0aGF0IGV2ZW50IHdpbGwgYmUgZXhlY3V0ZWQuXG4gICAgICogSWYgeW91IHBhc3MgdGhlIG9wdGlvbmFsIGFyZ3VtZW50IGFycmF5IHRoZW4gdGhvc2UgYXJndW1lbnRzIHdpbGwgYmUgcGFzc2VkIHRvIGV2ZXJ5IGxpc3RlbmVyIHVwb24gZXhlY3V0aW9uLlxuICAgICAqIEJlY2F1c2UgaXQgdXNlcyBgYXBwbHlgLCB5b3VyIGFycmF5IG9mIGFyZ3VtZW50cyB3aWxsIGJlIHBhc3NlZCBhcyBpZiB5b3Ugd3JvdGUgdGhlbSBvdXQgc2VwYXJhdGVseS5cbiAgICAgKiBTbyB0aGV5IHdpbGwgbm90IGFycml2ZSB3aXRoaW4gdGhlIGFycmF5IG9uIHRoZSBvdGhlciBzaWRlLCB0aGV5IHdpbGwgYmUgc2VwYXJhdGUuXG4gICAgICogWW91IGNhbiBhbHNvIHBhc3MgYSByZWd1bGFyIGV4cHJlc3Npb24gdG8gZW1pdCB0byBhbGwgZXZlbnRzIHRoYXQgbWF0Y2ggaXQuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1N0cmluZ3xSZWdFeHB9IGV2dCBOYW1lIG9mIHRoZSBldmVudCB0byBlbWl0IGFuZCBleGVjdXRlIGxpc3RlbmVycyBmb3IuXG4gICAgICogQHBhcmFtIHtBcnJheX0gW2FyZ3NdIE9wdGlvbmFsIGFycmF5IG9mIGFyZ3VtZW50cyB0byBiZSBwYXNzZWQgdG8gZWFjaCBsaXN0ZW5lci5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEN1cnJlbnQgaW5zdGFuY2Ugb2YgRXZlbnRFbWl0dGVyIGZvciBjaGFpbmluZy5cbiAgICAgKi9cbiAgICBwcm90by5lbWl0RXZlbnQgPSBmdW5jdGlvbiBlbWl0RXZlbnQoZXZ0LCBhcmdzKSB7XG4gICAgICAgIHZhciBsaXN0ZW5lcnNNYXAgPSB0aGlzLmdldExpc3RlbmVyc0FzT2JqZWN0KGV2dCk7XG4gICAgICAgIHZhciBsaXN0ZW5lcnM7XG4gICAgICAgIHZhciBsaXN0ZW5lcjtcbiAgICAgICAgdmFyIGk7XG4gICAgICAgIHZhciBrZXk7XG4gICAgICAgIHZhciByZXNwb25zZTtcblxuICAgICAgICBmb3IgKGtleSBpbiBsaXN0ZW5lcnNNYXApIHtcbiAgICAgICAgICAgIGlmIChsaXN0ZW5lcnNNYXAuaGFzT3duUHJvcGVydHkoa2V5KSkge1xuICAgICAgICAgICAgICAgIGxpc3RlbmVycyA9IGxpc3RlbmVyc01hcFtrZXldLnNsaWNlKDApO1xuXG4gICAgICAgICAgICAgICAgZm9yIChpID0gMDsgaSA8IGxpc3RlbmVycy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAvLyBJZiB0aGUgbGlzdGVuZXIgcmV0dXJucyB0cnVlIHRoZW4gaXQgc2hhbGwgYmUgcmVtb3ZlZCBmcm9tIHRoZSBldmVudFxuICAgICAgICAgICAgICAgICAgICAvLyBUaGUgZnVuY3Rpb24gaXMgZXhlY3V0ZWQgZWl0aGVyIHdpdGggYSBiYXNpYyBjYWxsIG9yIGFuIGFwcGx5IGlmIHRoZXJlIGlzIGFuIGFyZ3MgYXJyYXlcbiAgICAgICAgICAgICAgICAgICAgbGlzdGVuZXIgPSBsaXN0ZW5lcnNbaV07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGxpc3RlbmVyLm9uY2UgPT09IHRydWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucmVtb3ZlTGlzdGVuZXIoZXZ0LCBsaXN0ZW5lci5saXN0ZW5lcik7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICByZXNwb25zZSA9IGxpc3RlbmVyLmxpc3RlbmVyLmFwcGx5KHRoaXMsIGFyZ3MgfHwgW10pO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChyZXNwb25zZSA9PT0gdGhpcy5fZ2V0T25jZVJldHVyblZhbHVlKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucmVtb3ZlTGlzdGVuZXIoZXZ0LCBsaXN0ZW5lci5saXN0ZW5lcik7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogQWxpYXMgb2YgZW1pdEV2ZW50XG4gICAgICovXG4gICAgcHJvdG8udHJpZ2dlciA9IGFsaWFzKCdlbWl0RXZlbnQnKTtcblxuICAgIC8qKlxuICAgICAqIFN1YnRseSBkaWZmZXJlbnQgZnJvbSBlbWl0RXZlbnQgaW4gdGhhdCBpdCB3aWxsIHBhc3MgaXRzIGFyZ3VtZW50cyBvbiB0byB0aGUgbGlzdGVuZXJzLCBhcyBvcHBvc2VkIHRvIHRha2luZyBhIHNpbmdsZSBhcnJheSBvZiBhcmd1bWVudHMgdG8gcGFzcyBvbi5cbiAgICAgKiBBcyB3aXRoIGVtaXRFdmVudCwgeW91IGNhbiBwYXNzIGEgcmVnZXggaW4gcGxhY2Ugb2YgdGhlIGV2ZW50IG5hbWUgdG8gZW1pdCB0byBhbGwgZXZlbnRzIHRoYXQgbWF0Y2ggaXQuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1N0cmluZ3xSZWdFeHB9IGV2dCBOYW1lIG9mIHRoZSBldmVudCB0byBlbWl0IGFuZCBleGVjdXRlIGxpc3RlbmVycyBmb3IuXG4gICAgICogQHBhcmFtIHsuLi4qfSBPcHRpb25hbCBhZGRpdGlvbmFsIGFyZ3VtZW50cyB0byBiZSBwYXNzZWQgdG8gZWFjaCBsaXN0ZW5lci5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEN1cnJlbnQgaW5zdGFuY2Ugb2YgRXZlbnRFbWl0dGVyIGZvciBjaGFpbmluZy5cbiAgICAgKi9cbiAgICBwcm90by5lbWl0ID0gZnVuY3Rpb24gZW1pdChldnQpIHtcbiAgICAgICAgdmFyIGFyZ3MgPSBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMsIDEpO1xuICAgICAgICByZXR1cm4gdGhpcy5lbWl0RXZlbnQoZXZ0LCBhcmdzKTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogU2V0cyB0aGUgY3VycmVudCB2YWx1ZSB0byBjaGVjayBhZ2FpbnN0IHdoZW4gZXhlY3V0aW5nIGxpc3RlbmVycy4gSWYgYVxuICAgICAqIGxpc3RlbmVycyByZXR1cm4gdmFsdWUgbWF0Y2hlcyB0aGUgb25lIHNldCBoZXJlIHRoZW4gaXQgd2lsbCBiZSByZW1vdmVkXG4gICAgICogYWZ0ZXIgZXhlY3V0aW9uLiBUaGlzIHZhbHVlIGRlZmF1bHRzIHRvIHRydWUuXG4gICAgICpcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSBuZXcgdmFsdWUgdG8gY2hlY2sgZm9yIHdoZW4gZXhlY3V0aW5nIGxpc3RlbmVycy5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEN1cnJlbnQgaW5zdGFuY2Ugb2YgRXZlbnRFbWl0dGVyIGZvciBjaGFpbmluZy5cbiAgICAgKi9cbiAgICBwcm90by5zZXRPbmNlUmV0dXJuVmFsdWUgPSBmdW5jdGlvbiBzZXRPbmNlUmV0dXJuVmFsdWUodmFsdWUpIHtcbiAgICAgICAgdGhpcy5fb25jZVJldHVyblZhbHVlID0gdmFsdWU7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBGZXRjaGVzIHRoZSBjdXJyZW50IHZhbHVlIHRvIGNoZWNrIGFnYWluc3Qgd2hlbiBleGVjdXRpbmcgbGlzdGVuZXJzLiBJZlxuICAgICAqIHRoZSBsaXN0ZW5lcnMgcmV0dXJuIHZhbHVlIG1hdGNoZXMgdGhpcyBvbmUgdGhlbiBpdCBzaG91bGQgYmUgcmVtb3ZlZFxuICAgICAqIGF1dG9tYXRpY2FsbHkuIEl0IHdpbGwgcmV0dXJuIHRydWUgYnkgZGVmYXVsdC5cbiAgICAgKlxuICAgICAqIEByZXR1cm4geyp8Qm9vbGVhbn0gVGhlIGN1cnJlbnQgdmFsdWUgdG8gY2hlY2sgZm9yIG9yIHRoZSBkZWZhdWx0LCB0cnVlLlxuICAgICAqIEBhcGkgcHJpdmF0ZVxuICAgICAqL1xuICAgIHByb3RvLl9nZXRPbmNlUmV0dXJuVmFsdWUgPSBmdW5jdGlvbiBfZ2V0T25jZVJldHVyblZhbHVlKCkge1xuICAgICAgICBpZiAodGhpcy5oYXNPd25Qcm9wZXJ0eSgnX29uY2VSZXR1cm5WYWx1ZScpKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5fb25jZVJldHVyblZhbHVlO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogRmV0Y2hlcyB0aGUgZXZlbnRzIG9iamVjdCBhbmQgY3JlYXRlcyBvbmUgaWYgcmVxdWlyZWQuXG4gICAgICpcbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IFRoZSBldmVudHMgc3RvcmFnZSBvYmplY3QuXG4gICAgICogQGFwaSBwcml2YXRlXG4gICAgICovXG4gICAgcHJvdG8uX2dldEV2ZW50cyA9IGZ1bmN0aW9uIF9nZXRFdmVudHMoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9ldmVudHMgfHwgKHRoaXMuX2V2ZW50cyA9IHt9KTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogUmV2ZXJ0cyB0aGUgZ2xvYmFsIHtAbGluayBFdmVudEVtaXR0ZXJ9IHRvIGl0cyBwcmV2aW91cyB2YWx1ZSBhbmQgcmV0dXJucyBhIHJlZmVyZW5jZSB0byB0aGlzIHZlcnNpb24uXG4gICAgICpcbiAgICAgKiBAcmV0dXJuIHtGdW5jdGlvbn0gTm9uIGNvbmZsaWN0aW5nIEV2ZW50RW1pdHRlciBjbGFzcy5cbiAgICAgKi9cbiAgICBFdmVudEVtaXR0ZXIubm9Db25mbGljdCA9IGZ1bmN0aW9uIG5vQ29uZmxpY3QoKSB7XG4gICAgICAgIGV4cG9ydHMuRXZlbnRFbWl0dGVyID0gb3JpZ2luYWxHbG9iYWxWYWx1ZTtcbiAgICAgICAgcmV0dXJuIEV2ZW50RW1pdHRlcjtcbiAgICB9O1xuXG4gICAgLy8gRXhwb3NlIHRoZSBjbGFzcyBlaXRoZXIgdmlhIEFNRCwgQ29tbW9uSlMgb3IgdGhlIGdsb2JhbCBvYmplY3RcbiAgICBpZiAodHlwZW9mIGRlZmluZSA9PT0gJ2Z1bmN0aW9uJyAmJiBkZWZpbmUuYW1kKSB7XG4gICAgICAgIGRlZmluZShmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gRXZlbnRFbWl0dGVyO1xuICAgICAgICB9KTtcbiAgICB9XG4gICAgZWxzZSBpZiAodHlwZW9mIG1vZHVsZSA9PT0gJ29iamVjdCcgJiYgbW9kdWxlLmV4cG9ydHMpe1xuICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IEV2ZW50RW1pdHRlcjtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIGV4cG9ydHMuRXZlbnRFbWl0dGVyID0gRXZlbnRFbWl0dGVyO1xuICAgIH1cbn0odHlwZW9mIHdpbmRvdyAhPT0gJ3VuZGVmaW5lZCcgPyB3aW5kb3cgOiB0aGlzIHx8IHt9KSk7XG4iLCJpbXBvcnQgeyBPcGVuVmlkdSB9IGZyb20gJy4vT3BlblZpZHUvT3BlblZpZHUnO1xuXG5pZiAod2luZG93KSB7XG4gICAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lOm5vLXN0cmluZy1saXRlcmFsXG4gICAgd2luZG93WydPcGVuVmlkdSddID0gT3BlblZpZHU7XG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBTZXNzaW9uIH0gZnJvbSAnLi9TZXNzaW9uJztcbmltcG9ydCB7IFN0cmVhbSB9IGZyb20gJy4vU3RyZWFtJztcbmltcG9ydCB7IENvbm5lY3Rpb25PcHRpb25zIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9JbnRlcmZhY2VzL1ByaXZhdGUvQ29ubmVjdGlvbk9wdGlvbnMnO1xuaW1wb3J0IHsgSW5ib3VuZFN0cmVhbU9wdGlvbnMgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHJpdmF0ZS9JbmJvdW5kU3RyZWFtT3B0aW9ucyc7XG5pbXBvcnQgeyBTdHJlYW1PcHRpb25zU2VydmVyIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9JbnRlcmZhY2VzL1ByaXZhdGUvU3RyZWFtT3B0aW9uc1NlcnZlcic7XG5cblxuLyoqXG4gKiBSZXByZXNlbnRzIGVhY2ggb25lIG9mIHRoZSB1c2VyJ3MgY29ubmVjdGlvbiB0byB0aGUgc2Vzc2lvbiAodGhlIGxvY2FsIG9uZSBhbmQgb3RoZXIgdXNlcidzIGNvbm5lY3Rpb25zKS5cbiAqIFRoZXJlZm9yZSBlYWNoIFtbU2Vzc2lvbl1dIGFuZCBbW1N0cmVhbV1dIG9iamVjdCBoYXMgYW4gYXR0cmlidXRlIG9mIHR5cGUgQ29ubmVjdGlvblxuICovXG5leHBvcnQgY2xhc3MgQ29ubmVjdGlvbiB7XG5cbiAgICAvKipcbiAgICAgKiBVbmlxdWUgaWRlbnRpZmllciBvZiB0aGUgY29ubmVjdGlvblxuICAgICAqL1xuICAgIGNvbm5lY3Rpb25JZDogc3RyaW5nO1xuXG4gICAgLyoqXG4gICAgICogVGltZSB3aGVuIHRoaXMgY29ubmVjdGlvbiB3YXMgY3JlYXRlZCAoVVRDIG1pbGxpc2Vjb25kcylcbiAgICAgKi9cbiAgICBjcmVhdGlvblRpbWU6IG51bWJlcjtcblxuICAgIC8qKlxuICAgICAqIERhdGEgYXNzb2NpYXRlZCB0byB0aGlzIGNvbm5lY3Rpb24gKGFuZCB0aGVyZWZvcmUgdG8gY2VydGFpbiB1c2VyKS4gVGhpcyBpcyBhbiBpbXBvcnRhbnQgZmllbGQ6XG4gICAgICogaXQgYWxsb3dzIHlvdSB0byBicm9hZGNhc3QgYWxsIHRoZSBpbmZvcm1hdGlvbiB5b3Ugd2FudCBmb3IgZWFjaCB1c2VyIChhIHVzZXJuYW1lLCBmb3IgZXhhbXBsZSlcbiAgICAgKi9cbiAgICBkYXRhOiBzdHJpbmc7XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgc3RyZWFtOiBTdHJlYW07XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgb3B0aW9uczogQ29ubmVjdGlvbk9wdGlvbnMgfCB1bmRlZmluZWQ7XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgZGlzcG9zZWQgPSBmYWxzZTtcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3Rvcihwcml2YXRlIHNlc3Npb246IFNlc3Npb24sIG9wdHM/OiBDb25uZWN0aW9uT3B0aW9ucykge1xuXG4gICAgICAgIGxldCBtc2cgPSBcIidDb25uZWN0aW9uJyBjcmVhdGVkIFwiO1xuICAgICAgICBpZiAoISFvcHRzKSB7XG4gICAgICAgICAgICBtc2cgKz0gXCIocmVtb3RlKSB3aXRoICdjb25uZWN0aW9uSWQnIFtcIiArIG9wdHMuaWQgKyAnXSc7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBtc2cgKz0gJyhsb2NhbCknO1xuICAgICAgICB9XG4gICAgICAgIGNvbnNvbGUuaW5mbyhtc2cpO1xuXG4gICAgICAgIHRoaXMub3B0aW9ucyA9IG9wdHM7XG5cbiAgICAgICAgaWYgKCEhb3B0cykge1xuICAgICAgICAgICAgLy8gQ29ubmVjdGlvbiBpcyByZW1vdGVcbiAgICAgICAgICAgIHRoaXMuY29ubmVjdGlvbklkID0gb3B0cy5pZDtcbiAgICAgICAgICAgIGlmIChvcHRzLm1ldGFkYXRhKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5kYXRhID0gb3B0cy5tZXRhZGF0YTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChvcHRzLnN0cmVhbXMpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmluaXRSZW1vdGVTdHJlYW1zKG9wdHMuc3RyZWFtcyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLmNyZWF0aW9uVGltZSA9IG5ldyBEYXRlKCkuZ2V0VGltZSgpO1xuICAgIH1cblxuXG4gICAgLyogSGlkZGVuIG1ldGhvZHMgKi9cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBzZW5kSWNlQ2FuZGlkYXRlKGNhbmRpZGF0ZTogUlRDSWNlQ2FuZGlkYXRlKTogdm9pZCB7XG5cbiAgICAgICAgY29uc29sZS5kZWJ1ZygoISF0aGlzLnN0cmVhbS5vdXRib3VuZFN0cmVhbU9wdHMgPyAnTG9jYWwnIDogJ1JlbW90ZScpLCAnY2FuZGlkYXRlIGZvcicsXG4gICAgICAgICAgICB0aGlzLmNvbm5lY3Rpb25JZCwgSlNPTi5zdHJpbmdpZnkoY2FuZGlkYXRlKSk7XG5cbiAgICAgICAgdGhpcy5zZXNzaW9uLm9wZW52aWR1LnNlbmRSZXF1ZXN0KCdvbkljZUNhbmRpZGF0ZScsIHtcbiAgICAgICAgICAgIGVuZHBvaW50TmFtZTogdGhpcy5jb25uZWN0aW9uSWQsXG4gICAgICAgICAgICBjYW5kaWRhdGU6IGNhbmRpZGF0ZS5jYW5kaWRhdGUsXG4gICAgICAgICAgICBzZHBNaWQ6IGNhbmRpZGF0ZS5zZHBNaWQsXG4gICAgICAgICAgICBzZHBNTGluZUluZGV4OiBjYW5kaWRhdGUuc2RwTUxpbmVJbmRleFxuICAgICAgICB9LCAoZXJyb3IsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICBpZiAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKCdFcnJvciBzZW5kaW5nIElDRSBjYW5kaWRhdGU6ICdcbiAgICAgICAgICAgICAgICAgICAgKyBKU09OLnN0cmluZ2lmeShlcnJvcikpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgaW5pdFJlbW90ZVN0cmVhbXMob3B0aW9uczogU3RyZWFtT3B0aW9uc1NlcnZlcltdKTogdm9pZCB7XG5cbiAgICAgICAgLy8gVGhpcyBpcyByZWFkeSBmb3Igc3VwcG9ydGluZyBtdWx0aXBsZSBzdHJlYW1zIHBlciBDb25uZWN0aW9uIG9iamVjdC4gUmlnaHQgbm93IHRoZSBsb29wIHdpbGwgYWx3YXlzIHJ1biBqdXN0IG9uY2VcbiAgICAgICAgLy8gdGhpcy5zdHJlYW0gc2hvdWxkIGFsc28gYmUgcmVwbGFjZWQgYnkgYSBjb2xsZWN0aW9uIG9mIHN0cmVhbXMgdG8gc3VwcG9ydCBtdWx0aXBsZSBzdHJlYW1zIHBlciBDb25uZWN0aW9uXG4gICAgICAgIG9wdGlvbnMuZm9yRWFjaChvcHRzID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHN0cmVhbU9wdGlvbnM6IEluYm91bmRTdHJlYW1PcHRpb25zID0ge1xuICAgICAgICAgICAgICAgIGlkOiBvcHRzLmlkLFxuICAgICAgICAgICAgICAgIGNvbm5lY3Rpb246IHRoaXMsXG4gICAgICAgICAgICAgICAgaGFzQXVkaW86IG9wdHMuaGFzQXVkaW8sXG4gICAgICAgICAgICAgICAgaGFzVmlkZW86IG9wdHMuaGFzVmlkZW8sXG4gICAgICAgICAgICAgICAgYXVkaW9BY3RpdmU6IG9wdHMuYXVkaW9BY3RpdmUsXG4gICAgICAgICAgICAgICAgdmlkZW9BY3RpdmU6IG9wdHMudmlkZW9BY3RpdmUsXG4gICAgICAgICAgICAgICAgdHlwZU9mVmlkZW86IG9wdHMudHlwZU9mVmlkZW8sXG4gICAgICAgICAgICAgICAgZnJhbWVSYXRlOiBvcHRzLmZyYW1lUmF0ZSxcbiAgICAgICAgICAgICAgICB2aWRlb0RpbWVuc2lvbnM6ICEhb3B0cy52aWRlb0RpbWVuc2lvbnMgPyBKU09OLnBhcnNlKG9wdHMudmlkZW9EaW1lbnNpb25zKSA6IHVuZGVmaW5lZFxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGNvbnN0IHN0cmVhbSA9IG5ldyBTdHJlYW0odGhpcy5zZXNzaW9uLCBzdHJlYW1PcHRpb25zKTtcblxuICAgICAgICAgICAgdGhpcy5hZGRTdHJlYW0oc3RyZWFtKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgY29uc29sZS5pbmZvKFwiUmVtb3RlICdDb25uZWN0aW9uJyB3aXRoICdjb25uZWN0aW9uSWQnIFtcIiArIHRoaXMuY29ubmVjdGlvbklkICsgJ10gaXMgbm93IGNvbmZpZ3VyZWQgZm9yIHJlY2VpdmluZyBTdHJlYW1zIHdpdGggb3B0aW9uczogJywgdGhpcy5zdHJlYW0uaW5ib3VuZFN0cmVhbU9wdHMpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBhZGRTdHJlYW0oc3RyZWFtOiBTdHJlYW0pOiB2b2lkIHtcbiAgICAgICAgc3RyZWFtLmNvbm5lY3Rpb24gPSB0aGlzO1xuICAgICAgICB0aGlzLnN0cmVhbSA9IHN0cmVhbTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgcmVtb3ZlU3RyZWFtKHN0cmVhbUlkOiBzdHJpbmcpOiB2b2lkIHtcbiAgICAgICAgZGVsZXRlIHRoaXMuc3RyZWFtO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBkaXNwb3NlKCk6IHZvaWQge1xuICAgICAgICBpZiAoISF0aGlzLnN0cmVhbSkge1xuICAgICAgICAgICAgZGVsZXRlIHRoaXMuc3RyZWFtO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuZGlzcG9zZWQgPSB0cnVlO1xuICAgIH1cblxufSIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTctMjAxOCBPcGVuVmlkdSAoaHR0cHM6Ly9vcGVudmlkdS5pby8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuaW1wb3J0IHsgU3RyZWFtIH0gZnJvbSAnLi9TdHJlYW0nO1xuaW1wb3J0IHsgTG9jYWxSZWNvcmRlclN0YXRlIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FbnVtcy9Mb2NhbFJlY29yZGVyU3RhdGUnO1xuXG4vKipcbiAqIEBoaWRkZW5cbiAqL1xuZGVjbGFyZSB2YXIgTWVkaWFSZWNvcmRlcjogYW55O1xuXG5cbi8qKlxuICogRWFzeSByZWNvcmRpbmcgb2YgW1tTdHJlYW1dXSBvYmplY3RzIHN0cmFpZ2h0YXdheSBmcm9tIHRoZSBicm93c2VyLlxuICpcbiAqID4gV0FSTklORzogUGVyZm9ybWluZyBicm93c2VyIGxvY2FsIHJlY29yZGluZyBvZiAqKnJlbW90ZSBzdHJlYW1zKiogbWF5IGNhdXNlIHNvbWUgdHJvdWJsZXMuIEEgbG9uZyB3YWl0aW5nIHRpbWUgbWF5IGJlIHJlcXVpcmVkIGFmdGVyIGNhbGxpbmcgX0xvY2FsUmVjb3JkZXIuc3RvcCgpXyBpbiB0aGlzIGNhc2VcbiAqL1xuZXhwb3J0IGNsYXNzIExvY2FsUmVjb3JkZXIge1xuXG4gICAgc3RhdGU6IExvY2FsUmVjb3JkZXJTdGF0ZTtcblxuICAgIHByaXZhdGUgY29ubmVjdGlvbklkOiBzdHJpbmc7XG4gICAgcHJpdmF0ZSBtZWRpYVJlY29yZGVyOiBhbnk7XG4gICAgcHJpdmF0ZSBjaHVua3M6IGFueVtdID0gW107XG4gICAgcHJpdmF0ZSBibG9iOiBCbG9iO1xuICAgIHByaXZhdGUgY291bnQgPSAwO1xuICAgIHByaXZhdGUgaWQ6IHN0cmluZztcbiAgICBwcml2YXRlIHZpZGVvUHJldmlld1NyYzogc3RyaW5nO1xuICAgIHByaXZhdGUgaHRtbFBhcmVudEVsZW1lbnRJZDogc3RyaW5nO1xuICAgIHByaXZhdGUgdmlkZW9QcmV2aWV3OiBIVE1MVmlkZW9FbGVtZW50O1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHByaXZhdGUgc3RyZWFtOiBTdHJlYW0pIHtcbiAgICAgICAgdGhpcy5jb25uZWN0aW9uSWQgPSAoISF0aGlzLnN0cmVhbS5jb25uZWN0aW9uKSA/IHRoaXMuc3RyZWFtLmNvbm5lY3Rpb24uY29ubmVjdGlvbklkIDogJ2RlZmF1bHQtY29ubmVjdGlvbic7XG4gICAgICAgIHRoaXMuaWQgPSB0aGlzLnN0cmVhbS5zdHJlYW1JZCArICdfJyArIHRoaXMuY29ubmVjdGlvbklkICsgJ19sb2NhbHJlY29yZCc7XG4gICAgICAgIHRoaXMuc3RhdGUgPSBMb2NhbFJlY29yZGVyU3RhdGUuUkVBRFk7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBTdGFydHMgdGhlIHJlY29yZGluZyBvZiB0aGUgU3RyZWFtLiBbW3N0YXRlXV0gcHJvcGVydHkgbXVzdCBiZSBgUkVBRFlgLiBBZnRlciBtZXRob2Qgc3VjY2VlZHMgaXMgc2V0IHRvIGBSRUNPUkRJTkdgXG4gICAgICogQHJldHVybnMgQSBQcm9taXNlICh0byB3aGljaCB5b3UgY2FuIG9wdGlvbmFsbHkgc3Vic2NyaWJlIHRvKSB0aGF0IGlzIHJlc29sdmVkIGlmIHRoZSByZWNvcmRpbmcgc3VjY2Vzc2Z1bGx5IHN0YXJ0ZWQgYW5kIHJlamVjdGVkIHdpdGggYW4gRXJyb3Igb2JqZWN0IGlmIG5vdFxuICAgICAqL1xuICAgIHJlY29yZCgpOiBQcm9taXNlPGFueT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuXG4gICAgICAgICAgICB0cnkge1xuXG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBNZWRpYVJlY29yZGVyID09PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKCdNZWRpYVJlY29yZGVyIG5vdCBzdXBwb3J0ZWQgb24geW91ciBicm93c2VyLiBTZWUgY29tcGF0aWJpbGl0eSBpbiBodHRwczovL2Nhbml1c2UuY29tLyNzZWFyY2g9TWVkaWFSZWNvcmRlcicpO1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyAoRXJyb3IoJ01lZGlhUmVjb3JkZXIgbm90IHN1cHBvcnRlZCBvbiB5b3VyIGJyb3dzZXIuIFNlZSBjb21wYXRpYmlsaXR5IGluIGh0dHBzOi8vY2FuaXVzZS5jb20vI3NlYXJjaD1NZWRpYVJlY29yZGVyJykpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAodGhpcy5zdGF0ZSAhPT0gTG9jYWxSZWNvcmRlclN0YXRlLlJFQURZKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IChFcnJvcignXFwnTG9jYWxSZWNvcmQucmVjb3JkKClcXCcgbmVlZHMgXFwnTG9jYWxSZWNvcmQuc3RhdGVcXCcgdG8gYmUgXFwnUkVBRFlcXCcgKGN1cnJlbnQgdmFsdWU6IFxcJycgKyB0aGlzLnN0YXRlICsgJ1xcJykuIENhbGwgXFwnTG9jYWxSZWNvcmRlci5jbGVhbigpXFwnIG9yIGluaXQgYSBuZXcgTG9jYWxSZWNvcmRlciBiZWZvcmUnKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKFwiU3RhcnRpbmcgbG9jYWwgcmVjb3JkaW5nIG9mIHN0cmVhbSAnXCIgKyB0aGlzLnN0cmVhbS5zdHJlYW1JZCArIFwiJyBvZiBjb25uZWN0aW9uICdcIiArIHRoaXMuY29ubmVjdGlvbklkICsgXCInXCIpO1xuXG5cbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIE1lZGlhUmVjb3JkZXIuaXNUeXBlU3VwcG9ydGVkID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICAgICAgICAgIGxldCBvcHRpb25zO1xuICAgICAgICAgICAgICAgICAgICBpZiAoTWVkaWFSZWNvcmRlci5pc1R5cGVTdXBwb3J0ZWQoJ3ZpZGVvL3dlYm07Y29kZWNzPXZwOScpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBvcHRpb25zID0geyBtaW1lVHlwZTogJ3ZpZGVvL3dlYm07Y29kZWNzPXZwOScgfTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChNZWRpYVJlY29yZGVyLmlzVHlwZVN1cHBvcnRlZCgndmlkZW8vd2VibTtjb2RlY3M9aDI2NCcpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBvcHRpb25zID0geyBtaW1lVHlwZTogJ3ZpZGVvL3dlYm07Y29kZWNzPWgyNjQnIH07XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoTWVkaWFSZWNvcmRlci5pc1R5cGVTdXBwb3J0ZWQoJ3ZpZGVvL3dlYm07Y29kZWNzPXZwOCcpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBvcHRpb25zID0geyBtaW1lVHlwZTogJ3ZpZGVvL3dlYm07Y29kZWNzPXZwOCcgfTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmxvZygnVXNpbmcgbWltZVR5cGUgJyArIG9wdGlvbnMubWltZVR5cGUpO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLm1lZGlhUmVjb3JkZXIgPSBuZXcgTWVkaWFSZWNvcmRlcih0aGlzLnN0cmVhbS5nZXRNZWRpYVN0cmVhbSgpLCBvcHRpb25zKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLndhcm4oJ2lzVHlwZVN1cHBvcnRlZCBpcyBub3Qgc3VwcG9ydGVkLCB1c2luZyBkZWZhdWx0IGNvZGVjcyBmb3IgYnJvd3NlcicpO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLm1lZGlhUmVjb3JkZXIgPSBuZXcgTWVkaWFSZWNvcmRlcih0aGlzLnN0cmVhbS5nZXRNZWRpYVN0cmVhbSgpKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB0aGlzLm1lZGlhUmVjb3JkZXIuc3RhcnQoMTApO1xuXG4gICAgICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAgICAgICByZWplY3QoZXJyKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5tZWRpYVJlY29yZGVyLm9uZGF0YWF2YWlsYWJsZSA9IChlKSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5jaHVua3MucHVzaChlLmRhdGEpO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgdGhpcy5tZWRpYVJlY29yZGVyLm9uZXJyb3IgPSAoZSkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ01lZGlhUmVjb3JkZXIgZXJyb3I6ICcsIGUpO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgdGhpcy5tZWRpYVJlY29yZGVyLm9uc3RhcnQgPSAoKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5sb2coJ01lZGlhUmVjb3JkZXIgc3RhcnRlZCAoc3RhdGU9JyArIHRoaXMubWVkaWFSZWNvcmRlci5zdGF0ZSArICcpJyk7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICB0aGlzLm1lZGlhUmVjb3JkZXIub25zdG9wID0gKCkgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMub25TdG9wRGVmYXVsdCgpO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgdGhpcy5tZWRpYVJlY29yZGVyLm9ucGF1c2UgPSAoKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5sb2coJ01lZGlhUmVjb3JkZXIgcGF1c2VkIChzdGF0ZT0nICsgdGhpcy5tZWRpYVJlY29yZGVyLnN0YXRlICsgJyknKTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIHRoaXMubWVkaWFSZWNvcmRlci5vbnJlc3VtZSA9ICgpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmxvZygnTWVkaWFSZWNvcmRlciByZXN1bWVkIChzdGF0ZT0nICsgdGhpcy5tZWRpYVJlY29yZGVyLnN0YXRlICsgJyknKTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIHRoaXMubWVkaWFSZWNvcmRlci5vbndhcm5pbmcgPSAoZSkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKCdNZWRpYVJlY29yZGVyIHdhcm5pbmc6ICcgKyBlKTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIHRoaXMuc3RhdGUgPSBMb2NhbFJlY29yZGVyU3RhdGUuUkVDT1JESU5HO1xuICAgICAgICAgICAgcmVzb2x2ZSgpO1xuXG4gICAgICAgIH0pO1xuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogRW5kcyB0aGUgcmVjb3JkaW5nIG9mIHRoZSBTdHJlYW0uIFtbc3RhdGVdXSBwcm9wZXJ0eSBtdXN0IGJlIGBSRUNPUkRJTkdgIG9yIGBQQVVTRURgLiBBZnRlciBtZXRob2Qgc3VjY2VlZHMgaXMgc2V0IHRvIGBGSU5JU0hFRGBcbiAgICAgKiBAcmV0dXJucyBBIFByb21pc2UgKHRvIHdoaWNoIHlvdSBjYW4gb3B0aW9uYWxseSBzdWJzY3JpYmUgdG8pIHRoYXQgaXMgcmVzb2x2ZWQgaWYgdGhlIHJlY29yZGluZyBzdWNjZXNzZnVsbHkgc3RvcHBlZCBhbmQgcmVqZWN0ZWQgd2l0aCBhbiBFcnJvciBvYmplY3QgaWYgbm90XG4gICAgICovXG4gICAgc3RvcCgpOiBQcm9taXNlPGFueT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5zdGF0ZSA9PT0gTG9jYWxSZWNvcmRlclN0YXRlLlJFQURZIHx8IHRoaXMuc3RhdGUgPT09IExvY2FsUmVjb3JkZXJTdGF0ZS5GSU5JU0hFRCkge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyAoRXJyb3IoJ1xcJ0xvY2FsUmVjb3JkLnN0b3AoKVxcJyBuZWVkcyBcXCdMb2NhbFJlY29yZC5zdGF0ZVxcJyB0byBiZSBcXCdSRUNPUkRJTkdcXCcgb3IgXFwnUEFVU0VEXFwnIChjdXJyZW50IHZhbHVlOiBcXCcnICsgdGhpcy5zdGF0ZSArICdcXCcpLiBDYWxsIFxcJ0xvY2FsUmVjb3JkZXIuc3RhcnQoKVxcJyBiZWZvcmUnKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRoaXMubWVkaWFSZWNvcmRlci5vbnN0b3AgPSAoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMub25TdG9wRGVmYXVsdCgpO1xuICAgICAgICAgICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB0aGlzLm1lZGlhUmVjb3JkZXIuc3RvcCgpO1xuICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICAgIHJlamVjdChlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBQYXVzZXMgdGhlIHJlY29yZGluZyBvZiB0aGUgU3RyZWFtLiBbW3N0YXRlXV0gcHJvcGVydHkgbXVzdCBiZSBgUkVDT1JESU5HYC4gQWZ0ZXIgbWV0aG9kIHN1Y2NlZWRzIGlzIHNldCB0byBgUEFVU0VEYFxuICAgICAqIEByZXR1cm5zIEEgUHJvbWlzZSAodG8gd2hpY2ggeW91IGNhbiBvcHRpb25hbGx5IHN1YnNjcmliZSB0bykgdGhhdCBpcyByZXNvbHZlZCBpZiB0aGUgcmVjb3JkaW5nIHdhcyBzdWNjZXNzZnVsbHkgcGF1c2VkIGFuZCByZWplY3RlZCB3aXRoIGFuIEVycm9yIG9iamVjdCBpZiBub3RcbiAgICAgKi9cbiAgICBwYXVzZSgpOiBQcm9taXNlPGFueT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5zdGF0ZSAhPT0gTG9jYWxSZWNvcmRlclN0YXRlLlJFQ09SRElORykge1xuICAgICAgICAgICAgICAgICAgICByZWplY3QoRXJyb3IoJ1xcJ0xvY2FsUmVjb3JkLnBhdXNlKClcXCcgbmVlZHMgXFwnTG9jYWxSZWNvcmQuc3RhdGVcXCcgdG8gYmUgXFwnUkVDT1JESU5HXFwnIChjdXJyZW50IHZhbHVlOiBcXCcnICsgdGhpcy5zdGF0ZSArICdcXCcpLiBDYWxsIFxcJ0xvY2FsUmVjb3JkZXIuc3RhcnQoKVxcJyBvciBcXCdMb2NhbFJlY29yZGVyLnJlc3VtZSgpXFwnIGJlZm9yZScpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhpcy5tZWRpYVJlY29yZGVyLnBhdXNlKCk7XG4gICAgICAgICAgICAgICAgdGhpcy5zdGF0ZSA9IExvY2FsUmVjb3JkZXJTdGF0ZS5QQVVTRUQ7XG4gICAgICAgICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlc3VtZXMgdGhlIHJlY29yZGluZyBvZiB0aGUgU3RyZWFtLiBbW3N0YXRlXV0gcHJvcGVydHkgbXVzdCBiZSBgUEFVU0VEYC4gQWZ0ZXIgbWV0aG9kIHN1Y2NlZWRzIGlzIHNldCB0byBgUkVDT1JESU5HYFxuICAgICAqIEByZXR1cm5zIEEgUHJvbWlzZSAodG8gd2hpY2ggeW91IGNhbiBvcHRpb25hbGx5IHN1YnNjcmliZSB0bykgdGhhdCBpcyByZXNvbHZlZCBpZiB0aGUgcmVjb3JkaW5nIHdhcyBzdWNjZXNzZnVsbHkgcmVzdW1lZCBhbmQgcmVqZWN0ZWQgd2l0aCBhbiBFcnJvciBvYmplY3QgaWYgbm90XG4gICAgICovXG4gICAgcmVzdW1lKCk6IFByb21pc2U8YW55PiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLnN0YXRlICE9PSBMb2NhbFJlY29yZGVyU3RhdGUuUEFVU0VEKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IChFcnJvcignXFwnTG9jYWxSZWNvcmQucmVzdW1lKClcXCcgbmVlZHMgXFwnTG9jYWxSZWNvcmQuc3RhdGVcXCcgdG8gYmUgXFwnUEFVU0VEXFwnIChjdXJyZW50IHZhbHVlOiBcXCcnICsgdGhpcy5zdGF0ZSArICdcXCcpLiBDYWxsIFxcJ0xvY2FsUmVjb3JkZXIucGF1c2UoKVxcJyBiZWZvcmUnKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRoaXMubWVkaWFSZWNvcmRlci5yZXN1bWUoKTtcbiAgICAgICAgICAgICAgICB0aGlzLnN0YXRlID0gTG9jYWxSZWNvcmRlclN0YXRlLlJFQ09SRElORztcbiAgICAgICAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBQcmV2aWV3cyB0aGUgcmVjb3JkaW5nLCBhcHBlbmRpbmcgYSBuZXcgSFRNTFZpZGVvRWxlbWVudCB0byBlbGVtZW50IHdpdGggaWQgYHBhcmVudElkYC4gW1tzdGF0ZV1dIHByb3BlcnR5IG11c3QgYmUgYEZJTklTSEVEYFxuICAgICAqL1xuICAgIHByZXZpZXcocGFyZW50RWxlbWVudCk6IEhUTUxWaWRlb0VsZW1lbnQge1xuXG4gICAgICAgIGlmICh0aGlzLnN0YXRlICE9PSBMb2NhbFJlY29yZGVyU3RhdGUuRklOSVNIRUQpIHtcbiAgICAgICAgICAgIHRocm93IChFcnJvcignXFwnTG9jYWxSZWNvcmQucHJldmlldygpXFwnIG5lZWRzIFxcJ0xvY2FsUmVjb3JkLnN0YXRlXFwnIHRvIGJlIFxcJ0ZJTklTSEVEXFwnIChjdXJyZW50IHZhbHVlOiBcXCcnICsgdGhpcy5zdGF0ZSArICdcXCcpLiBDYWxsIFxcJ0xvY2FsUmVjb3JkZXIuc3RvcCgpXFwnIGJlZm9yZScpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMudmlkZW9QcmV2aWV3ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgndmlkZW8nKTtcblxuICAgICAgICB0aGlzLnZpZGVvUHJldmlldy5pZCA9IHRoaXMuaWQ7XG4gICAgICAgIHRoaXMudmlkZW9QcmV2aWV3LmF1dG9wbGF5ID0gdHJ1ZTtcblxuICAgICAgICBpZiAodHlwZW9mIHBhcmVudEVsZW1lbnQgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICB0aGlzLmh0bWxQYXJlbnRFbGVtZW50SWQgPSBwYXJlbnRFbGVtZW50O1xuXG4gICAgICAgICAgICBjb25zdCBwYXJlbnRFbGVtZW50RG9tID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQocGFyZW50RWxlbWVudCk7XG4gICAgICAgICAgICBpZiAocGFyZW50RWxlbWVudERvbSkge1xuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9QcmV2aWV3ID0gcGFyZW50RWxlbWVudERvbS5hcHBlbmRDaGlsZCh0aGlzLnZpZGVvUHJldmlldyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLmh0bWxQYXJlbnRFbGVtZW50SWQgPSBwYXJlbnRFbGVtZW50LmlkO1xuICAgICAgICAgICAgdGhpcy52aWRlb1ByZXZpZXcgPSBwYXJlbnRFbGVtZW50LmFwcGVuZENoaWxkKHRoaXMudmlkZW9QcmV2aWV3KTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMudmlkZW9QcmV2aWV3LnNyYyA9IHRoaXMudmlkZW9QcmV2aWV3U3JjO1xuXG4gICAgICAgIHJldHVybiB0aGlzLnZpZGVvUHJldmlldztcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIEdyYWNlZnVsbHkgc3RvcHMgYW5kIGNsZWFucyB0aGUgY3VycmVudCByZWNvcmRpbmcgKFdBUk5JTkc6IGl0IGlzIGNvbXBsZXRlbHkgZGlzbWlzc2VkKS4gU2V0cyBbW3N0YXRlXV0gdG8gYFJFQURZYCBzbyB0aGUgcmVjb3JkaW5nIGNhbiBzdGFydCBhZ2FpblxuICAgICAqL1xuICAgIGNsZWFuKCk6IHZvaWQge1xuICAgICAgICBjb25zdCBmID0gKCkgPT4ge1xuICAgICAgICAgICAgZGVsZXRlIHRoaXMuYmxvYjtcbiAgICAgICAgICAgIHRoaXMuY2h1bmtzID0gW107XG4gICAgICAgICAgICB0aGlzLmNvdW50ID0gMDtcbiAgICAgICAgICAgIGRlbGV0ZSB0aGlzLm1lZGlhUmVjb3JkZXI7XG4gICAgICAgICAgICB0aGlzLnN0YXRlID0gTG9jYWxSZWNvcmRlclN0YXRlLlJFQURZO1xuICAgICAgICB9O1xuICAgICAgICBpZiAodGhpcy5zdGF0ZSA9PT0gTG9jYWxSZWNvcmRlclN0YXRlLlJFQ09SRElORyB8fCB0aGlzLnN0YXRlID09PSBMb2NhbFJlY29yZGVyU3RhdGUuUEFVU0VEKSB7XG4gICAgICAgICAgICB0aGlzLnN0b3AoKS50aGVuKCgpID0+IGYoKSkuY2F0Y2goKCkgPT4gZigpKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGYoKTtcbiAgICAgICAgfVxuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogRG93bmxvYWRzIHRoZSByZWNvcmRlZCB2aWRlbyB0aHJvdWdoIHRoZSBicm93c2VyLiBbW3N0YXRlXV0gcHJvcGVydHkgbXVzdCBiZSBgRklOSVNIRURgXG4gICAgICovXG4gICAgZG93bmxvYWQoKTogdm9pZCB7XG4gICAgICAgIGlmICh0aGlzLnN0YXRlICE9PSBMb2NhbFJlY29yZGVyU3RhdGUuRklOSVNIRUQpIHtcbiAgICAgICAgICAgIHRocm93IChFcnJvcignXFwnTG9jYWxSZWNvcmQuZG93bmxvYWQoKVxcJyBuZWVkcyBcXCdMb2NhbFJlY29yZC5zdGF0ZVxcJyB0byBiZSBcXCdGSU5JU0hFRFxcJyAoY3VycmVudCB2YWx1ZTogXFwnJyArIHRoaXMuc3RhdGUgKyAnXFwnKS4gQ2FsbCBcXCdMb2NhbFJlY29yZGVyLnN0b3AoKVxcJyBiZWZvcmUnKSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjb25zdCBhOiBIVE1MQW5jaG9yRWxlbWVudCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2EnKTtcbiAgICAgICAgICAgIGEuc3R5bGUuZGlzcGxheSA9ICdub25lJztcbiAgICAgICAgICAgIGRvY3VtZW50LmJvZHkuYXBwZW5kQ2hpbGQoYSk7XG5cbiAgICAgICAgICAgIGNvbnN0IHVybCA9IHdpbmRvdy5VUkwuY3JlYXRlT2JqZWN0VVJMKHRoaXMuYmxvYik7XG4gICAgICAgICAgICBhLmhyZWYgPSB1cmw7XG4gICAgICAgICAgICBhLmRvd25sb2FkID0gdGhpcy5pZCArICcud2VibSc7XG4gICAgICAgICAgICBhLmNsaWNrKCk7XG4gICAgICAgICAgICB3aW5kb3cuVVJMLnJldm9rZU9iamVjdFVSTCh1cmwpO1xuXG4gICAgICAgICAgICBkb2N1bWVudC5ib2R5LnJlbW92ZUNoaWxkKGEpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0cyB0aGUgcmF3IEJsb2IgZmlsZS4gTWV0aG9kcyBwcmV2aWV3LCBkb3dubG9hZCwgdXBsb2FkQXNCaW5hcnkgYW5kIHVwbG9hZEFzTXVsdGlwYXJ0ZmlsZSB1c2UgdGhpcyBzYW1lIGZpbGUgdG8gcGVyZm9ybSB0aGVpciBzcGVjaWZpYyBhY3Rpb25zLiBbW3N0YXRlXV0gcHJvcGVydHkgbXVzdCBiZSBgRklOSVNIRURgXG4gICAgICovXG4gICAgZ2V0QmxvYigpOiBCbG9iIHtcbiAgICAgICAgaWYgKHRoaXMuc3RhdGUgIT09IExvY2FsUmVjb3JkZXJTdGF0ZS5GSU5JU0hFRCkge1xuICAgICAgICAgICAgdGhyb3cgKEVycm9yKCdDYWxsIFxcJ0xvY2FsUmVjb3JkLnN0b3AoKVxcJyBiZWZvcmUgZ2V0dGluZyBCbG9iIGZpbGUnKSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5ibG9iO1xuICAgICAgICB9XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBVcGxvYWRzIHRoZSByZWNvcmRlZCB2aWRlbyBhcyBhIGJpbmFyeSBmaWxlIHBlcmZvcm1pbmcgYW4gSFRUUC9QT1NUIG9wZXJhdGlvbiB0byBVUkwgYGVuZHBvaW50YC4gW1tzdGF0ZV1dIHByb3BlcnR5IG11c3QgYmUgYEZJTklTSEVEYC4gT3B0aW9uYWwgSFRUUCBoZWFkZXJzIGNhbiBiZSBwYXNzZWQgYXMgc2Vjb25kIHBhcmFtZXRlci4gRm9yIGV4YW1wbGU6XG4gICAgICogYGBgXG4gICAgICogdmFyIGhlYWRlcnMgPSB7XG4gICAgICogIFwiQ29va2llXCI6IFwiJFZlcnNpb249MTsgU2tpbj1uZXc7XCIsXG4gICAgICogIFwiQXV0aG9yaXphdGlvblwiOlwiQmFzaWMgUVd4aFpHcGJqcHVJSE5sY3RaUT09XCJcbiAgICAgKiB9XG4gICAgICogYGBgXG4gICAgICogQHJldHVybnMgQSBQcm9taXNlICh0byB3aGljaCB5b3UgY2FuIG9wdGlvbmFsbHkgc3Vic2NyaWJlIHRvKSB0aGF0IGlzIHJlc29sdmVkIHdpdGggdGhlIGBodHRwLnJlc3BvbnNlVGV4dGAgZnJvbSBzZXJ2ZXIgaWYgdGhlIG9wZXJhdGlvbiB3YXMgc3VjY2Vzc2Z1bCBhbmQgcmVqZWN0ZWQgd2l0aCB0aGUgZmFpbGVkIGBodHRwLnN0YXR1c2AgaWYgbm90XG4gICAgICovXG4gICAgdXBsb2FkQXNCaW5hcnkoZW5kcG9pbnQ6IHN0cmluZywgaGVhZGVycz86IGFueSk6IFByb21pc2U8YW55PiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICBpZiAodGhpcy5zdGF0ZSAhPT0gTG9jYWxSZWNvcmRlclN0YXRlLkZJTklTSEVEKSB7XG4gICAgICAgICAgICAgICAgcmVqZWN0KEVycm9yKCdcXCdMb2NhbFJlY29yZC51cGxvYWRBc0JpbmFyeSgpXFwnIG5lZWRzIFxcJ0xvY2FsUmVjb3JkLnN0YXRlXFwnIHRvIGJlIFxcJ0ZJTklTSEVEXFwnIChjdXJyZW50IHZhbHVlOiBcXCcnICsgdGhpcy5zdGF0ZSArICdcXCcpLiBDYWxsIFxcJ0xvY2FsUmVjb3JkZXIuc3RvcCgpXFwnIGJlZm9yZScpKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY29uc3QgaHR0cCA9IG5ldyBYTUxIdHRwUmVxdWVzdCgpO1xuICAgICAgICAgICAgICAgIGh0dHAub3BlbignUE9TVCcsIGVuZHBvaW50LCB0cnVlKTtcblxuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgaGVhZGVycyA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgICAgICAgICAgICAgZm9yIChjb25zdCBrZXkgb2YgT2JqZWN0LmtleXMoaGVhZGVycykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGh0dHAuc2V0UmVxdWVzdEhlYWRlcihrZXksIGhlYWRlcnNba2V5XSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBodHRwLm9ucmVhZHlzdGF0ZWNoYW5nZSA9ICgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGh0dHAucmVhZHlTdGF0ZSA9PT0gNCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGh0dHAuc3RhdHVzLnRvU3RyaW5nKCkuY2hhckF0KDApID09PSAnMicpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBTdWNjZXNzIHJlc3BvbnNlIGZyb20gc2VydmVyIChIVFRQIHN0YXR1cyBzdGFuZGFyZDogMlhYIGlzIHN1Y2Nlc3MpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZShodHRwLnJlc3BvbnNlVGV4dCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChodHRwLnN0YXR1cyk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIGh0dHAuc2VuZCh0aGlzLmJsb2IpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFVwbG9hZHMgdGhlIHJlY29yZGVkIHZpZGVvIGFzIGEgbXVsdGlwYXJ0IGZpbGUgcGVyZm9ybWluZyBhbiBIVFRQL1BPU1Qgb3BlcmF0aW9uIHRvIFVSTCBgZW5kcG9pbnRgLiBbW3N0YXRlXV0gcHJvcGVydHkgbXVzdCBiZSBgRklOSVNIRURgLiBPcHRpb25hbCBIVFRQIGhlYWRlcnMgY2FuIGJlIHBhc3NlZCBhcyBzZWNvbmQgcGFyYW1ldGVyLiBGb3IgZXhhbXBsZTpcbiAgICAgKiBgYGBcbiAgICAgKiB2YXIgaGVhZGVycyA9IHtcbiAgICAgKiAgXCJDb29raWVcIjogXCIkVmVyc2lvbj0xOyBTa2luPW5ldztcIixcbiAgICAgKiAgXCJBdXRob3JpemF0aW9uXCI6XCJCYXNpYyBRV3hoWkdwYmpwdUlITmxjdFpRPT1cIlxuICAgICAqIH1cbiAgICAgKiBgYGBcbiAgICAgKiBAcmV0dXJucyBBIFByb21pc2UgKHRvIHdoaWNoIHlvdSBjYW4gb3B0aW9uYWxseSBzdWJzY3JpYmUgdG8pIHRoYXQgaXMgcmVzb2x2ZWQgd2l0aCB0aGUgYGh0dHAucmVzcG9uc2VUZXh0YCBmcm9tIHNlcnZlciBpZiB0aGUgb3BlcmF0aW9uIHdhcyBzdWNjZXNzZnVsIGFuZCByZWplY3RlZCB3aXRoIHRoZSBmYWlsZWQgYGh0dHAuc3RhdHVzYCBpZiBub3Q6XG4gICAgICovXG4gICAgdXBsb2FkQXNNdWx0aXBhcnRmaWxlKGVuZHBvaW50OiBzdHJpbmcsIGhlYWRlcnM/OiBhbnkpOiBQcm9taXNlPGFueT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgaWYgKHRoaXMuc3RhdGUgIT09IExvY2FsUmVjb3JkZXJTdGF0ZS5GSU5JU0hFRCkge1xuICAgICAgICAgICAgICAgIHJlamVjdChFcnJvcignXFwnTG9jYWxSZWNvcmQudXBsb2FkQXNNdWx0aXBhcnRmaWxlKClcXCcgbmVlZHMgXFwnTG9jYWxSZWNvcmQuc3RhdGVcXCcgdG8gYmUgXFwnRklOSVNIRURcXCcgKGN1cnJlbnQgdmFsdWU6IFxcJycgKyB0aGlzLnN0YXRlICsgJ1xcJykuIENhbGwgXFwnTG9jYWxSZWNvcmRlci5zdG9wKClcXCcgYmVmb3JlJykpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBjb25zdCBodHRwID0gbmV3IFhNTEh0dHBSZXF1ZXN0KCk7XG4gICAgICAgICAgICAgICAgaHR0cC5vcGVuKCdQT1NUJywgZW5kcG9pbnQsIHRydWUpO1xuXG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBoZWFkZXJzID09PSAnb2JqZWN0Jykge1xuICAgICAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IGtleSBvZiBPYmplY3Qua2V5cyhoZWFkZXJzKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaHR0cC5zZXRSZXF1ZXN0SGVhZGVyKGtleSwgaGVhZGVyc1trZXldKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGNvbnN0IHNlbmRhYmxlID0gbmV3IEZvcm1EYXRhKCk7XG4gICAgICAgICAgICAgICAgc2VuZGFibGUuYXBwZW5kKCdmaWxlJywgdGhpcy5ibG9iLCB0aGlzLmlkICsgJy53ZWJtJyk7XG5cbiAgICAgICAgICAgICAgICBodHRwLm9ucmVhZHlzdGF0ZWNoYW5nZSA9ICgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGh0dHAucmVhZHlTdGF0ZSA9PT0gNCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGh0dHAuc3RhdHVzLnRvU3RyaW5nKCkuY2hhckF0KDApID09PSAnMicpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBTdWNjZXNzIHJlc3BvbnNlIGZyb20gc2VydmVyIChIVFRQIHN0YXR1cyBzdGFuZGFyZDogMlhYIGlzIHN1Y2Nlc3MpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZShodHRwLnJlc3BvbnNlVGV4dCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChodHRwLnN0YXR1cyk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICAgICAgaHR0cC5zZW5kKHNlbmRhYmxlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG5cbiAgICAvKiBQcml2YXRlIG1ldGhvZHMgKi9cblxuICAgIHByaXZhdGUgb25TdG9wRGVmYXVsdCgpOiB2b2lkIHtcbiAgICAgICAgY29uc29sZS5sb2coJ01lZGlhUmVjb3JkZXIgc3RvcHBlZCAgKHN0YXRlPScgKyB0aGlzLm1lZGlhUmVjb3JkZXIuc3RhdGUgKyAnKScpO1xuXG4gICAgICAgIHRoaXMuYmxvYiA9IG5ldyBCbG9iKHRoaXMuY2h1bmtzLCB7IHR5cGU6ICd2aWRlby93ZWJtJyB9KTtcbiAgICAgICAgdGhpcy5jaHVua3MgPSBbXTtcblxuICAgICAgICB0aGlzLnZpZGVvUHJldmlld1NyYyA9IHdpbmRvdy5VUkwuY3JlYXRlT2JqZWN0VVJMKHRoaXMuYmxvYik7XG5cbiAgICAgICAgdGhpcy5zdGF0ZSA9IExvY2FsUmVjb3JkZXJTdGF0ZS5GSU5JU0hFRDtcbiAgICB9XG5cbn1cbiIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTctMjAxOCBPcGVuVmlkdSAoaHR0cHM6Ly9vcGVudmlkdS5pby8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuaW1wb3J0IHsgTG9jYWxSZWNvcmRlciB9IGZyb20gJy4vTG9jYWxSZWNvcmRlcic7XG5pbXBvcnQgeyBQdWJsaXNoZXIgfSBmcm9tICcuL1B1Ymxpc2hlcic7XG5pbXBvcnQgeyBTZXNzaW9uIH0gZnJvbSAnLi9TZXNzaW9uJztcbmltcG9ydCB7IFN0cmVhbSB9IGZyb20gJy4vU3RyZWFtJztcbmltcG9ydCB7IFN0cmVhbVByb3BlcnR5Q2hhbmdlZEV2ZW50IH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvU3RyZWFtUHJvcGVydHlDaGFuZ2VkRXZlbnQnO1xuaW1wb3J0IHsgRGV2aWNlIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9JbnRlcmZhY2VzL1B1YmxpYy9EZXZpY2UnO1xuaW1wb3J0IHsgT3BlblZpZHVBZHZhbmNlZENvbmZpZ3VyYXRpb24gfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHVibGljL09wZW5WaWR1QWR2YW5jZWRDb25maWd1cmF0aW9uJztcbmltcG9ydCB7IFB1Ymxpc2hlclByb3BlcnRpZXMgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHVibGljL1B1Ymxpc2hlclByb3BlcnRpZXMnO1xuaW1wb3J0IHsgT3BlblZpZHVFcnJvciwgT3BlblZpZHVFcnJvck5hbWUgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0VudW1zL09wZW5WaWR1RXJyb3InO1xuaW1wb3J0IHsgVmlkZW9JbnNlcnRNb2RlIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FbnVtcy9WaWRlb0luc2VydE1vZGUnO1xuXG5pbXBvcnQgKiBhcyBzY3JlZW5TaGFyaW5nQXV0byBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL1NjcmVlblNoYXJpbmcvU2NyZWVuLUNhcHR1cmluZy1BdXRvJztcbmltcG9ydCAqIGFzIHNjcmVlblNoYXJpbmcgZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9TY3JlZW5TaGFyaW5nL1NjcmVlbi1DYXB0dXJpbmcnO1xuXG5pbXBvcnQgUnBjQnVpbGRlciA9IHJlcXVpcmUoJy4uL09wZW5WaWR1SW50ZXJuYWwvS3VyZW50b1V0aWxzL2t1cmVudG8tanNvbnJwYycpO1xuaW1wb3J0IHBsYXRmb3JtID0gcmVxdWlyZSgncGxhdGZvcm0nKTtcblxuXG4vKipcbiAqIEVudHJ5cG9pbnQgb2YgT3BlblZpZHUgQnJvd3NlciBsaWJyYXJ5LlxuICogVXNlIGl0IHRvIGluaXRpYWxpemUgb2JqZWN0cyBvZiB0eXBlIFtbU2Vzc2lvbl1dLCBbW1B1Ymxpc2hlcl1dIGFuZCBbW0xvY2FsUmVjb3JkZXJdXVxuICovXG5leHBvcnQgY2xhc3MgT3BlblZpZHUge1xuXG4gIHByaXZhdGUganNvblJwY0NsaWVudDogYW55O1xuXG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICBzZXNzaW9uOiBTZXNzaW9uO1xuICAvKipcbiAgICogQGhpZGRlblxuICAgKi9cbiAgcHVibGlzaGVyczogUHVibGlzaGVyW10gPSBbXTtcbiAgLyoqXG4gICAqIEBoaWRkZW5cbiAgICovXG4gIHdzVXJpOiBzdHJpbmc7XG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICBzZWNyZXQgPSAnJztcbiAgLyoqXG4gICAqIEBoaWRkZW5cbiAgICovXG4gIHJlY29yZGVyID0gZmFsc2U7XG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICBpY2VTZXJ2ZXJzOiBSVENJY2VTZXJ2ZXJbXTtcbiAgLyoqXG4gICAqIEBoaWRkZW5cbiAgICovXG4gIHJvbGU6IHN0cmluZztcbiAgLyoqXG4gICAqIEBoaWRkZW5cbiAgICovXG4gIGFkdmFuY2VkQ29uZmlndXJhdGlvbjogT3BlblZpZHVBZHZhbmNlZENvbmZpZ3VyYXRpb24gPSB7fTtcblxuICBjb25zdHJ1Y3RvcigpIHtcbiAgICBjb25zb2xlLmluZm8oXCInT3BlblZpZHUnIGluaXRpYWxpemVkXCIpO1xuXG4gICAgaWYgKHBsYXRmb3JtLm5hbWUhIS50b0xvd2VyQ2FzZSgpLmluZGV4T2YoJ21vYmlsZScpICE9PSAtMSkge1xuICAgICAgLy8gTGlzdGVuIHRvIG9yaWVudGF0aW9uY2hhbmdlIG9ubHkgb24gbW9iaWxlIGJyb3dzZXJzXG4gICAgICAoPGFueT53aW5kb3cpLm9ub3JpZW50YXRpb25jaGFuZ2UgPSAoKSA9PiB7XG4gICAgICAgIHRoaXMucHVibGlzaGVycy5mb3JFYWNoKHB1Ymxpc2hlciA9PiB7XG4gICAgICAgICAgaWYgKCEhcHVibGlzaGVyLnN0cmVhbSAmJiAhIXB1Ymxpc2hlci5zdHJlYW0uaGFzVmlkZW8gJiYgISFwdWJsaXNoZXIuc3RyZWFtLnN0cmVhbU1hbmFnZXIudmlkZW9zWzBdKSB7XG5cbiAgICAgICAgICAgIGxldCBhdHRlbXB0cyA9IDA7XG5cbiAgICAgICAgICAgIGNvbnN0IG9sZFdpZHRoID0gcHVibGlzaGVyLnN0cmVhbS52aWRlb0RpbWVuc2lvbnMud2lkdGg7XG4gICAgICAgICAgICBjb25zdCBvbGRIZWlnaHQgPSBwdWJsaXNoZXIuc3RyZWFtLnZpZGVvRGltZW5zaW9ucy5oZWlnaHQ7XG4gICAgICAgICAgICAvLyBOZXcgcmVzb2x1dGlvbiBnb3QgZnJvbSBkaWZmZXJlbnQgcGxhY2VzIGZvciBDaHJvbWUgYW5kIEZpcmVmb3guIENocm9tZSBuZWVkcyBhIHZpZGVvV2lkdGggYW5kIHZpZGVvSGVpZ2h0IG9mIGEgdmlkZW9FbGVtZW50LlxuICAgICAgICAgICAgLy8gRmlyZWZveCBuZWVkcyBnZXRTZXR0aW5ncyBmcm9tIHRoZSB2aWRlb1RyYWNrXG4gICAgICAgICAgICBsZXQgZmlyZWZveFNldHRpbmdzID0gcHVibGlzaGVyLnN0cmVhbS5nZXRNZWRpYVN0cmVhbSgpLmdldFZpZGVvVHJhY2tzKClbMF0uZ2V0U2V0dGluZ3MoKTtcbiAgICAgICAgICAgIGxldCBuZXdXaWR0aCA9IChwbGF0Zm9ybS5uYW1lISEudG9Mb3dlckNhc2UoKS5pbmRleE9mKCdmaXJlZm94JykgIT09IC0xKSA/IGZpcmVmb3hTZXR0aW5ncy53aWR0aCA6IHB1Ymxpc2hlci52aWRlb1JlZmVyZW5jZS52aWRlb1dpZHRoO1xuICAgICAgICAgICAgbGV0IG5ld0hlaWdodCA9IChwbGF0Zm9ybS5uYW1lISEudG9Mb3dlckNhc2UoKS5pbmRleE9mKCdmaXJlZm94JykgIT09IC0xKSA/IGZpcmVmb3hTZXR0aW5ncy5oZWlnaHQgOiBwdWJsaXNoZXIudmlkZW9SZWZlcmVuY2UudmlkZW9IZWlnaHQ7XG5cbiAgICAgICAgICAgIGNvbnN0IHJlcGVhdFVudGlsQ2hhbmdlID0gc2V0SW50ZXJ2YWwoKCkgPT4ge1xuICAgICAgICAgICAgICBmaXJlZm94U2V0dGluZ3MgPSBwdWJsaXNoZXIuc3RyZWFtLmdldE1lZGlhU3RyZWFtKCkuZ2V0VmlkZW9UcmFja3MoKVswXS5nZXRTZXR0aW5ncygpO1xuICAgICAgICAgICAgICBuZXdXaWR0aCA9IChwbGF0Zm9ybS5uYW1lISEudG9Mb3dlckNhc2UoKS5pbmRleE9mKCdmaXJlZm94JykgIT09IC0xKSA/IGZpcmVmb3hTZXR0aW5ncy53aWR0aCA6IHB1Ymxpc2hlci52aWRlb1JlZmVyZW5jZS52aWRlb1dpZHRoO1xuICAgICAgICAgICAgICBuZXdIZWlnaHQgPSAocGxhdGZvcm0ubmFtZSEhLnRvTG93ZXJDYXNlKCkuaW5kZXhPZignZmlyZWZveCcpICE9PSAtMSkgPyBmaXJlZm94U2V0dGluZ3MuaGVpZ2h0IDogcHVibGlzaGVyLnZpZGVvUmVmZXJlbmNlLnZpZGVvSGVpZ2h0O1xuICAgICAgICAgICAgICBzZW5kU3RyZWFtUHJvcGVydHlDaGFuZ2VkRXZlbnQob2xkV2lkdGgsIG9sZEhlaWdodCwgbmV3V2lkdGgsIG5ld0hlaWdodCk7XG4gICAgICAgICAgICB9LCAxMDApO1xuXG4gICAgICAgICAgICBjb25zdCBzZW5kU3RyZWFtUHJvcGVydHlDaGFuZ2VkRXZlbnQgPSAob2xkV2lkdGgsIG9sZEhlaWdodCwgbmV3V2lkdGgsIG5ld0hlaWdodCkgPT4ge1xuICAgICAgICAgICAgICBhdHRlbXB0cysrO1xuICAgICAgICAgICAgICBpZiAoYXR0ZW1wdHMgPiA0KSB7XG4gICAgICAgICAgICAgICAgY2xlYXJUaW1lb3V0KHJlcGVhdFVudGlsQ2hhbmdlKTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICBpZiAobmV3V2lkdGggIT09IG9sZFdpZHRoIHx8IG5ld0hlaWdodCAhPT0gb2xkSGVpZ2h0KSB7XG4gICAgICAgICAgICAgICAgcHVibGlzaGVyLnN0cmVhbS52aWRlb0RpbWVuc2lvbnMgPSB7XG4gICAgICAgICAgICAgICAgICB3aWR0aDogbmV3V2lkdGggfHwgMCxcbiAgICAgICAgICAgICAgICAgIGhlaWdodDogbmV3SGVpZ2h0IHx8IDBcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIHRoaXMuc2VuZFJlcXVlc3QoXG4gICAgICAgICAgICAgICAgICAnc3RyZWFtUHJvcGVydHlDaGFuZ2VkJyxcbiAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgc3RyZWFtSWQ6IHB1Ymxpc2hlci5zdHJlYW0uc3RyZWFtSWQsXG4gICAgICAgICAgICAgICAgICAgIHByb3BlcnR5OiAndmlkZW9EaW1lbnNpb25zJyxcbiAgICAgICAgICAgICAgICAgICAgbmV3VmFsdWU6IEpTT04uc3RyaW5naWZ5KHB1Ymxpc2hlci5zdHJlYW0udmlkZW9EaW1lbnNpb25zKSxcbiAgICAgICAgICAgICAgICAgICAgcmVhc29uOiAnZGV2aWNlUm90YXRlZCdcbiAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAoZXJyb3IsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoXCJFcnJvciBzZW5kaW5nICdzdHJlYW1Qcm9wZXJ0eUNoYW5nZWQnIGV2ZW50XCIsIGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICB0aGlzLnNlc3Npb24uZW1pdEV2ZW50KCdzdHJlYW1Qcm9wZXJ0eUNoYW5nZWQnLCBbbmV3IFN0cmVhbVByb3BlcnR5Q2hhbmdlZEV2ZW50KHRoaXMuc2Vzc2lvbiwgcHVibGlzaGVyLnN0cmVhbSwgJ3ZpZGVvRGltZW5zaW9ucycsIHB1Ymxpc2hlci5zdHJlYW0udmlkZW9EaW1lbnNpb25zLCB7IHdpZHRoOiBvbGRXaWR0aCwgaGVpZ2h0OiBvbGRIZWlnaHQgfSwgJ2RldmljZVJvdGF0ZWQnKV0pO1xuICAgICAgICAgICAgICAgICAgICAgIHB1Ymxpc2hlci5lbWl0RXZlbnQoJ3N0cmVhbVByb3BlcnR5Q2hhbmdlZCcsIFtuZXcgU3RyZWFtUHJvcGVydHlDaGFuZ2VkRXZlbnQocHVibGlzaGVyLCBwdWJsaXNoZXIuc3RyZWFtLCAndmlkZW9EaW1lbnNpb25zJywgcHVibGlzaGVyLnN0cmVhbS52aWRlb0RpbWVuc2lvbnMsIHsgd2lkdGg6IG9sZFdpZHRoLCBoZWlnaHQ6IG9sZEhlaWdodCB9LCAnZGV2aWNlUm90YXRlZCcpXSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIGNsZWFyVGltZW91dChyZXBlYXRVbnRpbENoYW5nZSk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH07XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgIH07XG4gICAgfVxuICB9XG5cblxuICAvKipcbiAgICogUmV0dXJucyBuZXcgc2Vzc2lvblxuICAgKi9cbiAgaW5pdFNlc3Npb24oKTogU2Vzc2lvbiB7XG4gICAgdGhpcy5zZXNzaW9uID0gbmV3IFNlc3Npb24odGhpcyk7XG4gICAgcmV0dXJuIHRoaXMuc2Vzc2lvbjtcbiAgfVxuXG5cbiAgaW5pdFB1Ymxpc2hlcih0YXJnZXRFbGVtZW50OiBzdHJpbmcgfCBIVE1MRWxlbWVudCk6IFB1Ymxpc2hlcjtcbiAgaW5pdFB1Ymxpc2hlcih0YXJnZXRFbGVtZW50OiBzdHJpbmcgfCBIVE1MRWxlbWVudCwgcHJvcGVydGllczogUHVibGlzaGVyUHJvcGVydGllcyk6IFB1Ymxpc2hlcjtcbiAgaW5pdFB1Ymxpc2hlcih0YXJnZXRFbGVtZW50OiBzdHJpbmcgfCBIVE1MRWxlbWVudCwgY29tcGxldGlvbkhhbmRsZXI6IChlcnJvcjogRXJyb3IgfCB1bmRlZmluZWQpID0+IHZvaWQpOiBQdWJsaXNoZXI7XG4gIGluaXRQdWJsaXNoZXIodGFyZ2V0RWxlbWVudDogc3RyaW5nIHwgSFRNTEVsZW1lbnQsIHByb3BlcnRpZXM6IFB1Ymxpc2hlclByb3BlcnRpZXMsIGNvbXBsZXRpb25IYW5kbGVyOiAoZXJyb3I6IEVycm9yIHwgdW5kZWZpbmVkKSA9PiB2b2lkKTogUHVibGlzaGVyO1xuXG4gIC8qKlxuICAgKiBSZXR1cm5zIGEgbmV3IHB1Ymxpc2hlclxuICAgKlxuICAgKiAjIyMjIEV2ZW50cyBkaXNwYXRjaGVkXG4gICAqXG4gICAqIFRoZSBbW1B1Ymxpc2hlcl1dIG9iamVjdCB3aWxsIGRpc3BhdGNoIGFuIGBhY2Nlc3NEaWFsb2dPcGVuZWRgIGV2ZW50LCBvbmx5IGlmIHRoZSBwb3AtdXAgc2hvd24gYnkgdGhlIGJyb3dzZXIgdG8gcmVxdWVzdCBwZXJtaXNzaW9ucyBmb3IgdGhlIGNhbWVyYSBpcyBvcGVuZWQuIFlvdSBjYW4gdXNlIHRoaXMgZXZlbnQgdG8gYWxlcnQgdGhlIHVzZXIgYWJvdXQgZ3JhbnRpbmcgcGVybWlzc2lvbnNcbiAgICogZm9yIHlvdXIgd2Vic2l0ZS4gQW4gYGFjY2Vzc0RpYWxvZ0Nsb3NlZGAgZXZlbnQgd2lsbCBhbHNvIGJlIGRpc3BhdGNoZWQgYWZ0ZXIgdXNlciBjbGlja3Mgb24gXCJBbGxvd1wiIG9yIFwiQmxvY2tcIiBpbiB0aGUgcG9wLXVwLlxuICAgKlxuICAgKiBUaGUgW1tQdWJsaXNoZXJdXSBvYmplY3Qgd2lsbCBkaXNwYXRjaCBhbiBgYWNjZXNzQWxsb3dlZGAgb3IgYGFjY2Vzc0RlbmllZGAgZXZlbnQgb25jZSBpdCBoYXMgYmVlbiBncmFudGVkIGFjY2VzcyB0byB0aGUgcmVxdWVzdGVkIGlucHV0IGRldmljZXMgb3Igbm90LlxuICAgKlxuICAgKiBUaGUgW1tQdWJsaXNoZXJdXSBvYmplY3Qgd2lsbCBkaXNwYXRjaCBhIGB2aWRlb0VsZW1lbnRDcmVhdGVkYCBldmVudCBvbmNlIGEgSFRNTCB2aWRlbyBlbGVtZW50IGhhcyBiZWVuIGFkZGVkIHRvIERPTSAob25seSBpZiB5b3VcbiAgICogW2xldCBPcGVuVmlkdSB0YWtlIGNhcmUgb2YgdGhlIHZpZGVvIHBsYXllcnNdKC9kb2NzL2hvdy1kby1pL21hbmFnZS12aWRlb3MvI2xldC1vcGVudmlkdS10YWtlLWNhcmUtb2YtdGhlLXZpZGVvLXBsYXllcnMpKS4gU2VlIFtbVmlkZW9FbGVtZW50RXZlbnRdXSB0byBsZWFybiBtb3JlLlxuICAgKlxuICAgKiBUaGUgW1tQdWJsaXNoZXJdXSBvYmplY3Qgd2lsbCBkaXNwYXRjaCBhIGBzdHJlYW1QbGF5aW5nYCBldmVudCBvbmNlIHRoZSBsb2NhbCBzdHJlYW1zIHN0YXJ0cyBwbGF5aW5nLiBTZWUgW1tTdHJlYW1NYW5hZ2VyRXZlbnRdXSB0byBsZWFybiBtb3JlLlxuICAgKlxuICAgKiBAcGFyYW0gdGFyZ2V0RWxlbWVudCAgSFRNTCBET00gZWxlbWVudCAob3IgaXRzIGBpZGAgYXR0cmlidXRlKSBpbiB3aGljaCB0aGUgdmlkZW8gZWxlbWVudCBvZiB0aGUgUHVibGlzaGVyIHdpbGwgYmUgaW5zZXJ0ZWQgKHNlZSBbW1B1Ymxpc2hlclByb3BlcnRpZXMuaW5zZXJ0TW9kZV1dKS4gSWYgKm51bGwqIG9yICp1bmRlZmluZWQqIG5vIGRlZmF1bHQgdmlkZW8gd2lsbCBiZSBjcmVhdGVkIGZvciB0aGlzIFB1Ymxpc2hlci5cbiAgICogWW91IGNhbiBhbHdheXMgY2FsbCBtZXRob2QgW1tQdWJsaXNoZXIuYWRkVmlkZW9FbGVtZW50XV0gb3IgW1tQdWJsaXNoZXIuY3JlYXRlVmlkZW9FbGVtZW50XV0gdG8gbWFuYWdlIHRoZSB2aWRlbyBlbGVtZW50cyBvbiB5b3VyIG93biAoc2VlIFtNYW5hZ2UgdmlkZW8gcGxheWVyc10oL2RvY3MvaG93LWRvLWkvbWFuYWdlLXZpZGVvcykgc2VjdGlvbilcbiAgICogQHBhcmFtIGNvbXBsZXRpb25IYW5kbGVyIGBlcnJvcmAgcGFyYW1ldGVyIGlzIG51bGwgaWYgYGluaXRQdWJsaXNoZXJgIHN1Y2NlZWRzLCBhbmQgaXMgZGVmaW5lZCBpZiBpdCBmYWlscy5cbiAgICogICAgICAgICAgICAgICAgICAgICAgICAgIGBjb21wbGV0aW9uSGFuZGxlcmAgZnVuY3Rpb24gaXMgY2FsbGVkIGJlZm9yZSB0aGUgUHVibGlzaGVyIGRpc3BhdGNoZXMgYW4gYGFjY2Vzc0FsbG93ZWRgIG9yIGFuIGBhY2Nlc3NEZW5pZWRgIGV2ZW50XG4gICAqL1xuICBpbml0UHVibGlzaGVyKHRhcmdldEVsZW1lbnQ6IHN0cmluZyB8IEhUTUxFbGVtZW50LCBwYXJhbTI/LCBwYXJhbTM/KTogUHVibGlzaGVyIHtcblxuICAgIGxldCBwcm9wZXJ0aWVzOiBQdWJsaXNoZXJQcm9wZXJ0aWVzO1xuXG4gICAgaWYgKCEhcGFyYW0yICYmICh0eXBlb2YgcGFyYW0yICE9PSAnZnVuY3Rpb24nKSkge1xuXG4gICAgICAvLyBNYXRjaGVzICdpbml0UHVibGlzaGVyKHRhcmdldEVsZW1lbnQsIHByb3BlcnRpZXMpJyBvciAnaW5pdFB1Ymxpc2hlcih0YXJnZXRFbGVtZW50LCBwcm9wZXJ0aWVzLCBjb21wbGV0aW9uSGFuZGxlciknXG5cbiAgICAgIHByb3BlcnRpZXMgPSAoPFB1Ymxpc2hlclByb3BlcnRpZXM+cGFyYW0yKTtcblxuICAgICAgcHJvcGVydGllcyA9IHtcbiAgICAgICAgYXVkaW9Tb3VyY2U6ICh0eXBlb2YgcHJvcGVydGllcy5hdWRpb1NvdXJjZSAhPT0gJ3VuZGVmaW5lZCcpID8gcHJvcGVydGllcy5hdWRpb1NvdXJjZSA6IHVuZGVmaW5lZCxcbiAgICAgICAgZnJhbWVSYXRlOiB0aGlzLmlzTWVkaWFTdHJlYW1UcmFjayhwcm9wZXJ0aWVzLnZpZGVvU291cmNlKSA/IHVuZGVmaW5lZCA6ICgodHlwZW9mIHByb3BlcnRpZXMuZnJhbWVSYXRlICE9PSAndW5kZWZpbmVkJykgPyBwcm9wZXJ0aWVzLmZyYW1lUmF0ZSA6IHVuZGVmaW5lZCksXG4gICAgICAgIGluc2VydE1vZGU6ICh0eXBlb2YgcHJvcGVydGllcy5pbnNlcnRNb2RlICE9PSAndW5kZWZpbmVkJykgPyAoKHR5cGVvZiBwcm9wZXJ0aWVzLmluc2VydE1vZGUgPT09ICdzdHJpbmcnKSA/IFZpZGVvSW5zZXJ0TW9kZVtwcm9wZXJ0aWVzLmluc2VydE1vZGVdIDogcHJvcGVydGllcy5pbnNlcnRNb2RlKSA6IFZpZGVvSW5zZXJ0TW9kZS5BUFBFTkQsXG4gICAgICAgIG1pcnJvcjogKHR5cGVvZiBwcm9wZXJ0aWVzLm1pcnJvciAhPT0gJ3VuZGVmaW5lZCcpID8gcHJvcGVydGllcy5taXJyb3IgOiB0cnVlLFxuICAgICAgICBwdWJsaXNoQXVkaW86ICh0eXBlb2YgcHJvcGVydGllcy5wdWJsaXNoQXVkaW8gIT09ICd1bmRlZmluZWQnKSA/IHByb3BlcnRpZXMucHVibGlzaEF1ZGlvIDogdHJ1ZSxcbiAgICAgICAgcHVibGlzaFZpZGVvOiAodHlwZW9mIHByb3BlcnRpZXMucHVibGlzaFZpZGVvICE9PSAndW5kZWZpbmVkJykgPyBwcm9wZXJ0aWVzLnB1Ymxpc2hWaWRlbyA6IHRydWUsXG4gICAgICAgIHJlc29sdXRpb246IHRoaXMuaXNNZWRpYVN0cmVhbVRyYWNrKHByb3BlcnRpZXMudmlkZW9Tb3VyY2UpID8gdW5kZWZpbmVkIDogKCh0eXBlb2YgcHJvcGVydGllcy5yZXNvbHV0aW9uICE9PSAndW5kZWZpbmVkJykgPyBwcm9wZXJ0aWVzLnJlc29sdXRpb24gOiAnNjQweDQ4MCcpLFxuICAgICAgICB2aWRlb1NvdXJjZTogKHR5cGVvZiBwcm9wZXJ0aWVzLnZpZGVvU291cmNlICE9PSAndW5kZWZpbmVkJykgPyBwcm9wZXJ0aWVzLnZpZGVvU291cmNlIDogdW5kZWZpbmVkXG4gICAgICB9O1xuICAgIH0gZWxzZSB7XG5cbiAgICAgIC8vIE1hdGNoZXMgJ2luaXRQdWJsaXNoZXIodGFyZ2V0RWxlbWVudCknIG9yICdpbml0UHVibGlzaGVyKHRhcmdldEVsZW1lbnQsIGNvbXBsZXRpb25IYW5kbGVyKSdcblxuICAgICAgcHJvcGVydGllcyA9IHtcbiAgICAgICAgaW5zZXJ0TW9kZTogVmlkZW9JbnNlcnRNb2RlLkFQUEVORCxcbiAgICAgICAgbWlycm9yOiB0cnVlLFxuICAgICAgICBwdWJsaXNoQXVkaW86IHRydWUsXG4gICAgICAgIHB1Ymxpc2hWaWRlbzogdHJ1ZSxcbiAgICAgICAgcmVzb2x1dGlvbjogJzY0MHg0ODAnXG4gICAgICB9O1xuICAgIH1cblxuICAgIGNvbnN0IHB1Ymxpc2hlcjogUHVibGlzaGVyID0gbmV3IFB1Ymxpc2hlcih0YXJnZXRFbGVtZW50LCBwcm9wZXJ0aWVzLCB0aGlzKTtcblxuICAgIGxldCBjb21wbGV0aW9uSGFuZGxlcjogKGVycm9yOiBFcnJvciB8IHVuZGVmaW5lZCkgPT4gdm9pZDtcbiAgICBpZiAoISFwYXJhbTIgJiYgKHR5cGVvZiBwYXJhbTIgPT09ICdmdW5jdGlvbicpKSB7XG4gICAgICBjb21wbGV0aW9uSGFuZGxlciA9IHBhcmFtMjtcbiAgICB9IGVsc2UgaWYgKCEhcGFyYW0zKSB7XG4gICAgICBjb21wbGV0aW9uSGFuZGxlciA9IHBhcmFtMztcbiAgICB9XG5cbiAgICBwdWJsaXNoZXIuaW5pdGlhbGl6ZSgpXG4gICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgIGlmIChjb21wbGV0aW9uSGFuZGxlciAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgY29tcGxldGlvbkhhbmRsZXIodW5kZWZpbmVkKTtcbiAgICAgICAgfVxuICAgICAgICBwdWJsaXNoZXIuZW1pdEV2ZW50KCdhY2Nlc3NBbGxvd2VkJywgW10pO1xuICAgICAgfSkuY2F0Y2goKGVycm9yKSA9PiB7XG4gICAgICAgIGlmIChjb21wbGV0aW9uSGFuZGxlciAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgY29tcGxldGlvbkhhbmRsZXIoZXJyb3IpO1xuICAgICAgICB9XG4gICAgICAgIHB1Ymxpc2hlci5lbWl0RXZlbnQoJ2FjY2Vzc0RlbmllZCcsIFtdKTtcbiAgICAgIH0pO1xuXG4gICAgdGhpcy5wdWJsaXNoZXJzLnB1c2gocHVibGlzaGVyKTtcbiAgICByZXR1cm4gcHVibGlzaGVyO1xuICB9XG5cblxuICAvKipcbiAgICogUHJvbWlzaWZpZWQgdmVyc2lvbiBvZiBbW09wZW5WaWR1LmluaXRQdWJsaXNoZXJdXVxuICAgKlxuICAgKiA+IFdBUk5JTkc6IGV2ZW50cyBgYWNjZXNzRGlhbG9nT3BlbmVkYCBhbmQgYGFjY2Vzc0RpYWxvZ0Nsb3NlZGAgd2lsbCBub3QgYmUgZGlzcGF0Y2hlZCBpZiB1c2luZyB0aGlzIG1ldGhvZCBpbnN0ZWFkIG9mIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dXG4gICAqL1xuICBpbml0UHVibGlzaGVyQXN5bmModGFyZ2V0RWxlbWVudDogc3RyaW5nIHwgSFRNTEVsZW1lbnQpOiBQcm9taXNlPFB1Ymxpc2hlcj47XG4gIGluaXRQdWJsaXNoZXJBc3luYyh0YXJnZXRFbGVtZW50OiBzdHJpbmcgfCBIVE1MRWxlbWVudCwgcHJvcGVydGllczogUHVibGlzaGVyUHJvcGVydGllcyk6IFByb21pc2U8UHVibGlzaGVyPjtcblxuICBpbml0UHVibGlzaGVyQXN5bmModGFyZ2V0RWxlbWVudDogc3RyaW5nIHwgSFRNTEVsZW1lbnQsIHByb3BlcnRpZXM/OiBQdWJsaXNoZXJQcm9wZXJ0aWVzKTogUHJvbWlzZTxQdWJsaXNoZXI+IHtcbiAgICByZXR1cm4gbmV3IFByb21pc2U8UHVibGlzaGVyPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG5cbiAgICAgIGxldCBwdWJsaXNoZXI6IFB1Ymxpc2hlcjtcblxuICAgICAgY29uc3QgY2FsbGJhY2sgPSAoZXJyb3I6IEVycm9yKSA9PiB7XG4gICAgICAgIGlmICghIWVycm9yKSB7XG4gICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICByZXNvbHZlKHB1Ymxpc2hlcik7XG4gICAgICAgIH1cbiAgICAgIH07XG5cbiAgICAgIGlmICghIXByb3BlcnRpZXMpIHtcbiAgICAgICAgcHVibGlzaGVyID0gdGhpcy5pbml0UHVibGlzaGVyKHRhcmdldEVsZW1lbnQsIHByb3BlcnRpZXMsIGNhbGxiYWNrKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHB1Ymxpc2hlciA9IHRoaXMuaW5pdFB1Ymxpc2hlcih0YXJnZXRFbGVtZW50LCBjYWxsYmFjayk7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIGEgbmV3IGxvY2FsIHJlY29yZGVyIGZvciByZWNvcmRpbmcgc3RyZWFtcyBzdHJhaWdodCBhd2F5IGZyb20gdGhlIGJyb3dzZXJcbiAgICogQHBhcmFtIHN0cmVhbSAgU3RyZWFtIHRvIHJlY29yZFxuICAgKi9cbiAgaW5pdExvY2FsUmVjb3JkZXIoc3RyZWFtOiBTdHJlYW0pOiBMb2NhbFJlY29yZGVyIHtcbiAgICByZXR1cm4gbmV3IExvY2FsUmVjb3JkZXIoc3RyZWFtKTtcbiAgfVxuXG5cbiAgLyoqXG4gICAqIENoZWNrcyBpZiB0aGUgYnJvd3NlciBzdXBwb3J0cyBPcGVuVmlkdVxuICAgKiBAcmV0dXJucyAxIGlmIHRoZSBicm93c2VyIHN1cHBvcnRzIE9wZW5WaWR1LCAwIG90aGVyd2lzZVxuICAgKi9cbiAgY2hlY2tTeXN0ZW1SZXF1aXJlbWVudHMoKTogbnVtYmVyIHtcbiAgICBjb25zdCBicm93c2VyID0gcGxhdGZvcm0ubmFtZTtcbiAgICBjb25zdCB2ZXJzaW9uID0gcGxhdGZvcm0udmVyc2lvbjtcblxuICAgIGlmICgoYnJvd3NlciAhPT0gJ0Nocm9tZScpICYmIChicm93c2VyICE9PSAnQ2hyb21lIE1vYmlsZScpICYmXG4gICAgICAoYnJvd3NlciAhPT0gJ0ZpcmVmb3gnKSAmJiAoYnJvd3NlciAhPT0gJ0ZpcmVmb3ggTW9iaWxlJykgJiYgKGJyb3dzZXIgIT09ICdGaXJlZm94IGZvciBpT1MnKSAmJlxuICAgICAgKGJyb3dzZXIgIT09ICdPcGVyYScpICYmIChicm93c2VyICE9PSAnT3BlcmEgTW9iaWxlJykgJiZcbiAgICAgIChicm93c2VyICE9PSAnU2FmYXJpJykpIHtcbiAgICAgIHJldHVybiAwO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gMTtcbiAgICB9XG4gIH1cblxuXG4gIC8qKlxuICAgKiBDb2xsZWN0cyBpbmZvcm1hdGlvbiBhYm91dCB0aGUgbWVkaWEgaW5wdXQgZGV2aWNlcyBhdmFpbGFibGUgb24gdGhlIHN5c3RlbS4gWW91IGNhbiBwYXNzIHByb3BlcnR5IGBkZXZpY2VJZGAgb2YgYSBbW0RldmljZV1dIG9iamVjdCBhcyB2YWx1ZSBvZiBgYXVkaW9Tb3VyY2VgIG9yIGB2aWRlb1NvdXJjZWAgcHJvcGVydGllcyBpbiBbW2luaXRQdWJsaXNoZXJdXSBtZXRob2RcbiAgICovXG4gIGdldERldmljZXMoKTogUHJvbWlzZTxEZXZpY2VbXT4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZTxEZXZpY2VbXT4oKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgbmF2aWdhdG9yLm1lZGlhRGV2aWNlcy5lbnVtZXJhdGVEZXZpY2VzKCkudGhlbigoZGV2aWNlSW5mb3MpID0+IHtcbiAgICAgICAgY29uc3QgZGV2aWNlczogRGV2aWNlW10gPSBbXTtcbiAgICAgICAgZGV2aWNlSW5mb3MuZm9yRWFjaChkZXZpY2VJbmZvID0+IHtcbiAgICAgICAgICBpZiAoZGV2aWNlSW5mby5raW5kID09PSAnYXVkaW9pbnB1dCcgfHwgZGV2aWNlSW5mby5raW5kID09PSAndmlkZW9pbnB1dCcpIHtcbiAgICAgICAgICAgIGRldmljZXMucHVzaCh7XG4gICAgICAgICAgICAgIGtpbmQ6IGRldmljZUluZm8ua2luZCxcbiAgICAgICAgICAgICAgZGV2aWNlSWQ6IGRldmljZUluZm8uZGV2aWNlSWQsXG4gICAgICAgICAgICAgIGxhYmVsOiBkZXZpY2VJbmZvLmxhYmVsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICByZXNvbHZlKGRldmljZXMpO1xuICAgICAgfSkuY2F0Y2goKGVycm9yKSA9PiB7XG4gICAgICAgIGNvbnNvbGUuZXJyb3IoJ0Vycm9yIGdldHRpbmcgZGV2aWNlcycsIGVycm9yKTtcbiAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9XG5cblxuICAvKipcbiAgICogR2V0IGEgTWVkaWFTdHJlYW0gb2JqZWN0IHRoYXQgeW91IGNhbiBjdXN0b21pemUgYmVmb3JlIGNhbGxpbmcgW1tpbml0UHVibGlzaGVyXV0gKHBhc3MgX01lZGlhU3RyZWFtVHJhY2tfIHByb3BlcnR5IG9mIHRoZSBfTWVkaWFTdHJlYW1fIHZhbHVlIHJlc29sdmVkIGJ5IHRoZSBQcm9taXNlIGFzIGBhdWRpb1NvdXJjZWAgb3IgYHZpZGVvU291cmNlYCBwcm9wZXJ0aWVzIGluIFtbaW5pdFB1Ymxpc2hlcl1dKVxuICAgKlxuICAgKiBQYXJhbWV0ZXIgYG9wdGlvbnNgIGlzIHRoZSBzYW1lIGFzIGluIFtbaW5pdFB1Ymxpc2hlcl1dIHNlY29uZCBwYXJhbWV0ZXIgKG9mIHR5cGUgW1tQdWJsaXNoZXJQcm9wZXJ0aWVzXV0pLCBidXQgb25seSB0aGUgZm9sbG93aW5nIHByb3BlcnRpZXMgd2lsbCBiZSBhcHBsaWVkOiBgYXVkaW9Tb3VyY2VgLCBgdmlkZW9Tb3VyY2VgLCBgZnJhbWVSYXRlYCwgYHJlc29sdXRpb25gXG4gICAqXG4gICAqIFRvIGN1c3RvbWl6ZSB0aGUgUHVibGlzaGVyJ3MgdmlkZW8sIHRoZSBBUEkgZm9yIEhUTUxDYW52YXNFbGVtZW50IGlzIHZlcnkgdXNlZnVsLiBGb3IgZXhhbXBsZSwgdG8gZ2V0IGEgYmxhY2stYW5kLXdoaXRlIHZpZGVvIGF0IDEwIGZwcyBhbmQgSEQgcmVzb2x1dGlvbiB3aXRoIG5vIHNvdW5kOlxuICAgKiBgYGBcbiAgICogdmFyIE9WID0gbmV3IE9wZW5WaWR1KCk7XG4gICAqIHZhciBGUkFNRV9SQVRFID0gMTA7XG4gICAqXG4gICAqIE9WLmdldFVzZXJNZWRpYSh7XG4gICAqICAgIGF1ZGlvU291cmNlOiBmYWxzZTtcbiAgICogICAgdmlkZW9Tb3VyY2U6IHVuZGVmaW5lZCxcbiAgICogICAgcmVzb2x1dGlvbjogJzEyODB4NzIwJyxcbiAgICogICAgZnJhbWVSYXRlOiBGUkFNRV9SQVRFXG4gICAqIH0pXG4gICAqIC50aGVuKG1lZGlhU3RyZWFtID0+IHtcbiAgICpcbiAgICogICAgdmFyIHZpZGVvVHJhY2sgPSBtZWRpYVN0cmVhbS5nZXRWaWRlb1RyYWNrcygpWzBdO1xuICAgKiAgICB2YXIgdmlkZW8gPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCd2aWRlbycpO1xuICAgKiAgICB2aWRlby5zcmNPYmplY3QgPSBuZXcgTWVkaWFTdHJlYW0oW3ZpZGVvVHJhY2tdKTtcbiAgICpcbiAgICogICAgdmFyIGNhbnZhcyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2NhbnZhcycpO1xuICAgKiAgICB2YXIgY3R4ID0gY2FudmFzLmdldENvbnRleHQoJzJkJyk7XG4gICAqICAgIGN0eC5maWx0ZXIgPSAnZ3JheXNjYWxlKDEwMCUpJztcbiAgICpcbiAgICogICAgdmlkZW8uYWRkRXZlbnRMaXN0ZW5lcigncGxheScsICgpID0+IHtcbiAgICogICAgICB2YXIgbG9vcCA9ICgpID0+IHtcbiAgICogICAgICAgIGlmICghdmlkZW8ucGF1c2VkICYmICF2aWRlby5lbmRlZCkge1xuICAgKiAgICAgICAgICBjdHguZHJhd0ltYWdlKHZpZGVvLCAwLCAwLCAzMDAsIDE3MCk7XG4gICAqICAgICAgICAgIHNldFRpbWVvdXQobG9vcCwgMTAwMC8gRlJBTUVfUkFURSk7IC8vIERyYXdpbmcgYXQgMTAgZnBzXG4gICAqICAgICAgICB9XG4gICAqICAgICAgfTtcbiAgICogICAgICBsb29wKCk7XG4gICAqICAgIH0pO1xuICAgKiAgICB2aWRlby5wbGF5KCk7XG4gICAqXG4gICAqICAgIHZhciBncmF5VmlkZW9UcmFjayA9IGNhbnZhcy5jYXB0dXJlU3RyZWFtKEZSQU1FX1JBVEUpLmdldFZpZGVvVHJhY2tzKClbMF07XG4gICAqICAgIHZhciBwdWJsaXNoZXIgPSB0aGlzLk9WLmluaXRQdWJsaXNoZXIoXG4gICAqICAgICAgbXlIdG1sVGFyZ2V0LFxuICAgKiAgICAgIHtcbiAgICogICAgICAgIGF1ZGlvU291cmNlOiBmYWxzZSxcbiAgICogICAgICAgIHZpZGVvU291cmNlOiBncmF5VmlkZW9UcmFja1xuICAgKiAgICAgIH0pO1xuICAgKiB9KTtcbiAgICogYGBgXG4gICAqL1xuICBnZXRVc2VyTWVkaWEob3B0aW9uczogUHVibGlzaGVyUHJvcGVydGllcyk6IFByb21pc2U8TWVkaWFTdHJlYW0+IHtcbiAgICByZXR1cm4gbmV3IFByb21pc2U8TWVkaWFTdHJlYW0+KChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIHRoaXMuZ2VuZXJhdGVNZWRpYUNvbnN0cmFpbnRzKG9wdGlvbnMpXG4gICAgICAgIC50aGVuKGNvbnN0cmFpbnRzID0+IHtcbiAgICAgICAgICBuYXZpZ2F0b3IubWVkaWFEZXZpY2VzLmdldFVzZXJNZWRpYShjb25zdHJhaW50cylcbiAgICAgICAgICAgIC50aGVuKG1lZGlhU3RyZWFtID0+IHtcbiAgICAgICAgICAgICAgcmVzb2x2ZShtZWRpYVN0cmVhbSk7XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICAgICAgbGV0IGVycm9yTmFtZTogT3BlblZpZHVFcnJvck5hbWU7XG4gICAgICAgICAgICAgIGNvbnN0IGVycm9yTWVzc2FnZSA9IGVycm9yLnRvU3RyaW5nKCk7XG4gICAgICAgICAgICAgIGlmICghKG9wdGlvbnMudmlkZW9Tb3VyY2UgPT09ICdzY3JlZW4nKSkge1xuICAgICAgICAgICAgICAgIGVycm9yTmFtZSA9IE9wZW5WaWR1RXJyb3JOYW1lLkRFVklDRV9BQ0NFU1NfREVOSUVEO1xuICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGVycm9yTmFtZSA9IE9wZW5WaWR1RXJyb3JOYW1lLlNDUkVFTl9DQVBUVVJFX0RFTklFRDtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICByZWplY3QobmV3IE9wZW5WaWR1RXJyb3IoZXJyb3JOYW1lLCBlcnJvck1lc3NhZ2UpKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KVxuICAgICAgICAuY2F0Y2goKGVycm9yOiBPcGVuVmlkdUVycm9yKSA9PiB7XG4gICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgfSk7XG4gICAgfSk7XG4gIH1cblxuXG4gIC8qIHRzbGludDpkaXNhYmxlOm5vLWVtcHR5ICovXG4gIC8qKlxuICAgKiBEaXNhYmxlIGFsbCBsb2dnaW5nIGV4Y2VwdCBlcnJvciBsZXZlbFxuICAgKi9cbiAgZW5hYmxlUHJvZE1vZGUoKTogdm9pZCB7XG4gICAgY29uc29sZS5sb2cgPSAoKSA9PiB7IH07XG4gICAgY29uc29sZS5kZWJ1ZyA9ICgpID0+IHsgfTtcbiAgICBjb25zb2xlLmluZm8gPSAoKSA9PiB7IH07XG4gICAgY29uc29sZS53YXJuID0gKCkgPT4geyB9O1xuICB9XG4gIC8qIHRzbGludDplbmFibGU6bm8tZW1wdHkgKi9cblxuXG4gIC8qKlxuICAgKiBTZXQgT3BlblZpZHUgYWR2YW5jZWQgY29uZmlndXJhdGlvbiBvcHRpb25zLiBDdXJyZW50bHkgYGNvbmZpZ3VyYXRpb25gIGlzIGFuIG9iamVjdCB3aXRoIHRoZSBmb2xsb3dpbmcgb3B0aW9uYWwgcHJvcGVydGllcyAoc2VlIFtbT3BlblZpZHVBZHZhbmNlZENvbmZpZ3VyYXRpb25dXSBmb3IgbW9yZSBkZXRhaWxzKTpcbiAgICogLSBgaWNlU2VydmVyc2A6IHNldCBjdXN0b20gU1RVTi9UVVJOIHNlcnZlcnMgdG8gYmUgdXNlZCBieSBPcGVuVmlkdSBCcm93c2VyXG4gICAqIC0gYHNjcmVlblNoYXJlQ2hyb21lRXh0ZW5zaW9uYDogdXJsIHRvIGEgY3VzdG9tIHNjcmVlbiBzaGFyZSBleHRlbnNpb24gZm9yIENocm9tZSB0byBiZSB1c2VkIGluc3RlYWQgb2YgdGhlIGRlZmF1bHQgb25lLCBiYXNlZCBvbiBvdXJzIFtodHRwczovL2dpdGh1Yi5jb20vT3BlblZpZHUvb3BlbnZpZHUtc2NyZWVuLXNoYXJpbmctY2hyb21lLWV4dGVuc2lvbl0oaHR0cHM6Ly9naXRodWIuY29tL09wZW5WaWR1L29wZW52aWR1LXNjcmVlbi1zaGFyaW5nLWNocm9tZS1leHRlbnNpb24pXG4gICAqIC0gYHB1Ymxpc2hlclNwZWFraW5nRXZlbnRzT3B0aW9uc2A6IGN1c3RvbSBjb25maWd1cmF0aW9uIGZvciB0aGUgW1tQdWJsaXNoZXJTcGVha2luZ0V2ZW50XV0gZmVhdHVyZVxuICAgKi9cbiAgc2V0QWR2YW5jZWRDb25maWd1cmF0aW9uKGNvbmZpZ3VyYXRpb246IE9wZW5WaWR1QWR2YW5jZWRDb25maWd1cmF0aW9uKTogdm9pZCB7XG4gICAgdGhpcy5hZHZhbmNlZENvbmZpZ3VyYXRpb24gPSBjb25maWd1cmF0aW9uO1xuICB9XG5cblxuICAvKiBIaWRkZW4gbWV0aG9kcyAqL1xuXG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICBnZW5lcmF0ZU1lZGlhQ29uc3RyYWludHMocHVibGlzaGVyUHJvcGVydGllczogUHVibGlzaGVyUHJvcGVydGllcyk6IFByb21pc2U8TWVkaWFTdHJlYW1Db25zdHJhaW50cz4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZTxNZWRpYVN0cmVhbUNvbnN0cmFpbnRzPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICBsZXQgYXVkaW8sIHZpZGVvO1xuXG4gICAgICBpZiAocHVibGlzaGVyUHJvcGVydGllcy5hdWRpb1NvdXJjZSA9PT0gbnVsbCB8fCBwdWJsaXNoZXJQcm9wZXJ0aWVzLmF1ZGlvU291cmNlID09PSBmYWxzZSkge1xuICAgICAgICBhdWRpbyA9IGZhbHNlO1xuICAgICAgfSBlbHNlIGlmIChwdWJsaXNoZXJQcm9wZXJ0aWVzLmF1ZGlvU291cmNlID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgYXVkaW8gPSB0cnVlO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgYXVkaW8gPSBwdWJsaXNoZXJQcm9wZXJ0aWVzLmF1ZGlvU291cmNlO1xuICAgICAgfVxuXG4gICAgICBpZiAocHVibGlzaGVyUHJvcGVydGllcy52aWRlb1NvdXJjZSA9PT0gbnVsbCB8fCBwdWJsaXNoZXJQcm9wZXJ0aWVzLnZpZGVvU291cmNlID09PSBmYWxzZSkge1xuICAgICAgICB2aWRlbyA9IGZhbHNlO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdmlkZW8gPSB7XG4gICAgICAgICAgaGVpZ2h0OiB7XG4gICAgICAgICAgICBpZGVhbDogNDgwXG4gICAgICAgICAgfSxcbiAgICAgICAgICB3aWR0aDoge1xuICAgICAgICAgICAgaWRlYWw6IDY0MFxuICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgbWVkaWFDb25zdHJhaW50czogTWVkaWFTdHJlYW1Db25zdHJhaW50cyA9IHtcbiAgICAgICAgYXVkaW8sXG4gICAgICAgIHZpZGVvXG4gICAgICB9O1xuXG4gICAgICBpZiAodHlwZW9mIG1lZGlhQ29uc3RyYWludHMuYXVkaW8gPT09ICdzdHJpbmcnKSB7XG4gICAgICAgIG1lZGlhQ29uc3RyYWludHMuYXVkaW8gPSB7IGRldmljZUlkOiB7IGV4YWN0OiBtZWRpYUNvbnN0cmFpbnRzLmF1ZGlvIH0gfTtcbiAgICAgIH1cblxuICAgICAgaWYgKG1lZGlhQ29uc3RyYWludHMudmlkZW8pIHtcblxuICAgICAgICBpZiAoISFwdWJsaXNoZXJQcm9wZXJ0aWVzLnJlc29sdXRpb24pIHtcbiAgICAgICAgICBjb25zdCB3aWR0aEFuZEhlaWdodCA9IHB1Ymxpc2hlclByb3BlcnRpZXMucmVzb2x1dGlvbi50b0xvd2VyQ2FzZSgpLnNwbGl0KCd4Jyk7XG4gICAgICAgICAgY29uc3Qgd2lkdGggPSBOdW1iZXIod2lkdGhBbmRIZWlnaHRbMF0pO1xuICAgICAgICAgIGNvbnN0IGhlaWdodCA9IE51bWJlcih3aWR0aEFuZEhlaWdodFsxXSk7XG4gICAgICAgICAgKG1lZGlhQ29uc3RyYWludHMudmlkZW8gYXMgYW55KS53aWR0aC5pZGVhbCA9IHdpZHRoO1xuICAgICAgICAgIChtZWRpYUNvbnN0cmFpbnRzLnZpZGVvIGFzIGFueSkuaGVpZ2h0LmlkZWFsID0gaGVpZ2h0O1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCEhcHVibGlzaGVyUHJvcGVydGllcy5mcmFtZVJhdGUpIHtcbiAgICAgICAgICAobWVkaWFDb25zdHJhaW50cy52aWRlbyBhcyBhbnkpLmZyYW1lUmF0ZSA9IHsgaWRlYWw6IHB1Ymxpc2hlclByb3BlcnRpZXMuZnJhbWVSYXRlIH07XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoISFwdWJsaXNoZXJQcm9wZXJ0aWVzLnZpZGVvU291cmNlICYmIHR5cGVvZiBwdWJsaXNoZXJQcm9wZXJ0aWVzLnZpZGVvU291cmNlID09PSAnc3RyaW5nJykge1xuXG4gICAgICAgICAgaWYgKHB1Ymxpc2hlclByb3BlcnRpZXMudmlkZW9Tb3VyY2UgPT09ICdzY3JlZW4nKSB7XG5cbiAgICAgICAgICAgIGlmIChwbGF0Zm9ybS5uYW1lICE9PSAnQ2hyb21lJyAmJiBwbGF0Zm9ybS5uYW1lIS5pbmRleE9mKCdGaXJlZm94JykgPT09IC0xKSB7XG4gICAgICAgICAgICAgIGNvbnN0IGVycm9yID0gbmV3IE9wZW5WaWR1RXJyb3IoT3BlblZpZHVFcnJvck5hbWUuU0NSRUVOX1NIQVJJTkdfTk9UX1NVUFBPUlRFRCwgJ1lvdSBjYW4gb25seSBzY3JlZW4gc2hhcmUgaW4gZGVza3RvcCBDaHJvbWUgYW5kIEZpcmVmb3guIERldGVjdGVkIGJyb3dzZXI6ICcgKyBwbGF0Zm9ybS5uYW1lKTtcbiAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihlcnJvcik7XG4gICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICB9IGVsc2Uge1xuXG4gICAgICAgICAgICAgIGlmICghIXRoaXMuYWR2YW5jZWRDb25maWd1cmF0aW9uLnNjcmVlblNoYXJlQ2hyb21lRXh0ZW5zaW9uICYmICEocGxhdGZvcm0ubmFtZSEuaW5kZXhPZignRmlyZWZveCcpICE9PSAtMSkpIHtcblxuICAgICAgICAgICAgICAgIC8vIEN1c3RvbSBzY3JlZW4gc2hhcmluZyBleHRlbnNpb24gZm9yIENocm9tZVxuXG4gICAgICAgICAgICAgICAgc2NyZWVuU2hhcmluZy5nZXRTY3JlZW5Db25zdHJhaW50cygoZXJyb3IsIHNjcmVlbkNvbnN0cmFpbnRzKSA9PiB7XG4gICAgICAgICAgICAgICAgICBpZiAoISFlcnJvciB8fCAhIXNjcmVlbkNvbnN0cmFpbnRzLm1hbmRhdG9yeSAmJiBzY3JlZW5Db25zdHJhaW50cy5tYW5kYXRvcnkuY2hyb21lTWVkaWFTb3VyY2UgPT09ICdzY3JlZW4nKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnJvciA9PT0gJ3Blcm1pc3Npb24tZGVuaWVkJyB8fCBlcnJvciA9PT0gJ1Blcm1pc3Npb25EZW5pZWRFcnJvcicpIHtcbiAgICAgICAgICAgICAgICAgICAgICBjb25zdCBlcnJvciA9IG5ldyBPcGVuVmlkdUVycm9yKE9wZW5WaWR1RXJyb3JOYW1lLlNDUkVFTl9DQVBUVVJFX0RFTklFRCwgJ1lvdSBtdXN0IGFsbG93IGFjY2VzcyB0byBvbmUgd2luZG93IG9mIHlvdXIgZGVza3RvcCcpO1xuICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgY29uc3QgZXh0ZW5zaW9uSWQgPSB0aGlzLmFkdmFuY2VkQ29uZmlndXJhdGlvbi5zY3JlZW5TaGFyZUNocm9tZUV4dGVuc2lvbiEuc3BsaXQoJy8nKS5wb3AoKSEhLnRyaW0oKTtcbiAgICAgICAgICAgICAgICAgICAgICBzY3JlZW5TaGFyaW5nLmdldENocm9tZUV4dGVuc2lvblN0YXR1cyhleHRlbnNpb25JZCwgKHN0YXR1cykgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHN0YXR1cyA9PT0gJ2luc3RhbGxlZC1kaXNhYmxlZCcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZXJyb3IgPSBuZXcgT3BlblZpZHVFcnJvcihPcGVuVmlkdUVycm9yTmFtZS5TQ1JFRU5fRVhURU5TSU9OX0RJU0FCTEVELCAnWW91IG11c3QgZW5hYmxlIHRoZSBzY3JlZW4gZXh0ZW5zaW9uJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHN0YXR1cyA9PT0gJ25vdC1pbnN0YWxsZWQnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGVycm9yID0gbmV3IE9wZW5WaWR1RXJyb3IoT3BlblZpZHVFcnJvck5hbWUuU0NSRUVOX0VYVEVOU0lPTl9OT1RfSU5TVEFMTEVELCAoPHN0cmluZz50aGlzLmFkdmFuY2VkQ29uZmlndXJhdGlvbi5zY3JlZW5TaGFyZUNocm9tZUV4dGVuc2lvbikpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgbWVkaWFDb25zdHJhaW50cy52aWRlbyA9IHNjcmVlbkNvbnN0cmFpbnRzO1xuICAgICAgICAgICAgICAgICAgICByZXNvbHZlKG1lZGlhQ29uc3RyYWludHMpO1xuICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICB9IGVsc2Uge1xuXG4gICAgICAgICAgICAgICAgLy8gRGVmYXVsdCBzY3JlZW4gc2hhcmluZyBleHRlbnNpb24gZm9yIENocm9tZVxuXG4gICAgICAgICAgICAgICAgc2NyZWVuU2hhcmluZ0F1dG8uZ2V0U2NyZWVuSWQoKGVycm9yLCBzb3VyY2VJZCwgc2NyZWVuQ29uc3RyYWludHMpID0+IHtcbiAgICAgICAgICAgICAgICAgIGlmICghIWVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnJvciA9PT0gJ25vdC1pbnN0YWxsZWQnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgY29uc3QgZXh0ZW5zaW9uVXJsID0gISF0aGlzLmFkdmFuY2VkQ29uZmlndXJhdGlvbi5zY3JlZW5TaGFyZUNocm9tZUV4dGVuc2lvbiA/IHRoaXMuYWR2YW5jZWRDb25maWd1cmF0aW9uLnNjcmVlblNoYXJlQ2hyb21lRXh0ZW5zaW9uIDpcbiAgICAgICAgICAgICAgICAgICAgICAgICdodHRwczovL2Nocm9tZS5nb29nbGUuY29tL3dlYnN0b3JlL2RldGFpbC9vcGVudmlkdS1zY3JlZW5zaGFyaW5nL2xmY2dmZXBhZm5vYmRsb2VjY2huZmFjbGliZW5qb2xkJztcbiAgICAgICAgICAgICAgICAgICAgICBjb25zdCBlcnJvciA9IG5ldyBPcGVuVmlkdUVycm9yKE9wZW5WaWR1RXJyb3JOYW1lLlNDUkVFTl9FWFRFTlNJT05fTk9UX0lOU1RBTExFRCwgZXh0ZW5zaW9uVXJsKTtcbiAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGVycm9yID09PSAnaW5zdGFsbGVkLWRpc2FibGVkJykge1xuICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGVycm9yID0gbmV3IE9wZW5WaWR1RXJyb3IoT3BlblZpZHVFcnJvck5hbWUuU0NSRUVOX0VYVEVOU0lPTl9ESVNBQkxFRCwgJ1lvdSBtdXN0IGVuYWJsZSB0aGUgc2NyZWVuIGV4dGVuc2lvbicpO1xuICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoZXJyb3IgPT09ICdwZXJtaXNzaW9uLWRlbmllZCcpIHtcbiAgICAgICAgICAgICAgICAgICAgICBjb25zdCBlcnJvciA9IG5ldyBPcGVuVmlkdUVycm9yKE9wZW5WaWR1RXJyb3JOYW1lLlNDUkVFTl9DQVBUVVJFX0RFTklFRCwgJ1lvdSBtdXN0IGFsbG93IGFjY2VzcyB0byBvbmUgd2luZG93IG9mIHlvdXIgZGVza3RvcCcpO1xuICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIG1lZGlhQ29uc3RyYWludHMudmlkZW8gPSBzY3JlZW5Db25zdHJhaW50cy52aWRlbztcbiAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZShtZWRpYUNvbnN0cmFpbnRzKTtcbiAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgIHB1Ymxpc2hlclByb3BlcnRpZXMudmlkZW9Tb3VyY2UgPSAnc2NyZWVuJztcblxuICAgICAgICAgICAgfVxuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6bm8tc3RyaW5nLWxpdGVyYWxcbiAgICAgICAgICAgIG1lZGlhQ29uc3RyYWludHMudmlkZW9bJ2RldmljZUlkJ10gPSB7IGV4YWN0OiBwdWJsaXNoZXJQcm9wZXJ0aWVzLnZpZGVvU291cmNlIH07XG4gICAgICAgICAgICByZXNvbHZlKG1lZGlhQ29uc3RyYWludHMpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICByZXNvbHZlKG1lZGlhQ29uc3RyYWludHMpO1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXNvbHZlKG1lZGlhQ29uc3RyYWludHMpO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIEBoaWRkZW5cbiAgICovXG4gIHN0YXJ0V3Mob25Db25uZWN0U3VjY2VzOiAoZXJyb3I6IEVycm9yKSA9PiB2b2lkKTogdm9pZCB7XG4gICAgY29uc3QgY29uZmlnID0ge1xuICAgICAgaGVhcnRiZWF0OiA1MDAwLFxuICAgICAgc2VuZENsb3NlTWVzc2FnZTogZmFsc2UsXG4gICAgICB3czoge1xuICAgICAgICB1cmk6IHRoaXMud3NVcmksXG4gICAgICAgIHVzZVNvY2tKUzogZmFsc2UsXG4gICAgICAgIG9uY29ubmVjdGVkOiBvbkNvbm5lY3RTdWNjZXMsXG4gICAgICAgIG9uZGlzY29ubmVjdDogdGhpcy5kaXNjb25uZWN0Q2FsbGJhY2suYmluZCh0aGlzKSxcbiAgICAgICAgb25yZWNvbm5lY3Rpbmc6IHRoaXMucmVjb25uZWN0aW5nQ2FsbGJhY2suYmluZCh0aGlzKSxcbiAgICAgICAgb25yZWNvbm5lY3RlZDogdGhpcy5yZWNvbm5lY3RlZENhbGxiYWNrLmJpbmQodGhpcylcbiAgICAgIH0sXG4gICAgICBycGM6IHtcbiAgICAgICAgcmVxdWVzdFRpbWVvdXQ6IDEwMDAwLFxuICAgICAgICBwYXJ0aWNpcGFudEpvaW5lZDogdGhpcy5zZXNzaW9uLm9uUGFydGljaXBhbnRKb2luZWQuYmluZCh0aGlzLnNlc3Npb24pLFxuICAgICAgICBwYXJ0aWNpcGFudFB1Ymxpc2hlZDogdGhpcy5zZXNzaW9uLm9uUGFydGljaXBhbnRQdWJsaXNoZWQuYmluZCh0aGlzLnNlc3Npb24pLFxuICAgICAgICBwYXJ0aWNpcGFudFVucHVibGlzaGVkOiB0aGlzLnNlc3Npb24ub25QYXJ0aWNpcGFudFVucHVibGlzaGVkLmJpbmQodGhpcy5zZXNzaW9uKSxcbiAgICAgICAgcGFydGljaXBhbnRMZWZ0OiB0aGlzLnNlc3Npb24ub25QYXJ0aWNpcGFudExlZnQuYmluZCh0aGlzLnNlc3Npb24pLFxuICAgICAgICBwYXJ0aWNpcGFudEV2aWN0ZWQ6IHRoaXMuc2Vzc2lvbi5vblBhcnRpY2lwYW50RXZpY3RlZC5iaW5kKHRoaXMuc2Vzc2lvbiksXG4gICAgICAgIHJlY29yZGluZ1N0YXJ0ZWQ6IHRoaXMuc2Vzc2lvbi5vblJlY29yZGluZ1N0YXJ0ZWQuYmluZCh0aGlzLnNlc3Npb24pLFxuICAgICAgICByZWNvcmRpbmdTdG9wcGVkOiB0aGlzLnNlc3Npb24ub25SZWNvcmRpbmdTdG9wcGVkLmJpbmQodGhpcy5zZXNzaW9uKSxcbiAgICAgICAgc2VuZE1lc3NhZ2U6IHRoaXMuc2Vzc2lvbi5vbk5ld01lc3NhZ2UuYmluZCh0aGlzLnNlc3Npb24pLFxuICAgICAgICBzdHJlYW1Qcm9wZXJ0eUNoYW5nZWQ6IHRoaXMuc2Vzc2lvbi5vblN0cmVhbVByb3BlcnR5Q2hhbmdlZC5iaW5kKHRoaXMuc2Vzc2lvbiksXG4gICAgICAgIGljZUNhbmRpZGF0ZTogdGhpcy5zZXNzaW9uLnJlY3ZJY2VDYW5kaWRhdGUuYmluZCh0aGlzLnNlc3Npb24pLFxuICAgICAgICBtZWRpYUVycm9yOiB0aGlzLnNlc3Npb24ub25NZWRpYUVycm9yLmJpbmQodGhpcy5zZXNzaW9uKVxuICAgICAgfVxuICAgIH07XG4gICAgdGhpcy5qc29uUnBjQ2xpZW50ID0gbmV3IFJwY0J1aWxkZXIuY2xpZW50cy5Kc29uUnBjQ2xpZW50KGNvbmZpZyk7XG4gIH1cblxuICAvKipcbiAgICogQGhpZGRlblxuICAgKi9cbiAgY2xvc2VXcygpOiB2b2lkIHtcbiAgICB0aGlzLmpzb25ScGNDbGllbnQuY2xvc2UoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICBzZW5kUmVxdWVzdChtZXRob2Q6IHN0cmluZywgcGFyYW1zOiBhbnksIGNhbGxiYWNrPyk6IHZvaWQge1xuICAgIGlmIChwYXJhbXMgJiYgcGFyYW1zIGluc3RhbmNlb2YgRnVuY3Rpb24pIHtcbiAgICAgIGNhbGxiYWNrID0gcGFyYW1zO1xuICAgICAgcGFyYW1zID0ge307XG4gICAgfVxuICAgIGNvbnNvbGUuZGVidWcoJ1NlbmRpbmcgcmVxdWVzdDoge21ldGhvZDpcIicgKyBtZXRob2QgKyAnXCIsIHBhcmFtczogJyArIEpTT04uc3RyaW5naWZ5KHBhcmFtcykgKyAnfScpO1xuICAgIHRoaXMuanNvblJwY0NsaWVudC5zZW5kKG1ldGhvZCwgcGFyYW1zLCBjYWxsYmFjayk7XG4gIH1cblxuICAvKipcbiAgICogQGhpZGRlblxuICAgKi9cbiAgaXNNZWRpYVN0cmVhbVRyYWNrKG1lZGlhU291cmNlOiBhbnkpOiBib29sZWFuIHtcbiAgICBjb25zdCBpcyA9ICghIW1lZGlhU291cmNlICYmXG4gICAgICBtZWRpYVNvdXJjZS5lbmFibGVkICE9PSB1bmRlZmluZWQgJiYgdHlwZW9mIG1lZGlhU291cmNlLmVuYWJsZWQgPT09ICdib29sZWFuJyAmJlxuICAgICAgbWVkaWFTb3VyY2UuaWQgIT09IHVuZGVmaW5lZCAmJiB0eXBlb2YgbWVkaWFTb3VyY2UuaWQgPT09ICdzdHJpbmcnICYmXG4gICAgICBtZWRpYVNvdXJjZS5raW5kICE9PSB1bmRlZmluZWQgJiYgdHlwZW9mIG1lZGlhU291cmNlLmtpbmQgPT09ICdzdHJpbmcnICYmXG4gICAgICBtZWRpYVNvdXJjZS5sYWJlbCAhPT0gdW5kZWZpbmVkICYmIHR5cGVvZiBtZWRpYVNvdXJjZS5sYWJlbCA9PT0gJ3N0cmluZycgJiZcbiAgICAgIG1lZGlhU291cmNlLm11dGVkICE9PSB1bmRlZmluZWQgJiYgdHlwZW9mIG1lZGlhU291cmNlLm11dGVkID09PSAnYm9vbGVhbicgJiZcbiAgICAgIG1lZGlhU291cmNlLnJlYWR5U3RhdGUgIT09IHVuZGVmaW5lZCAmJiB0eXBlb2YgbWVkaWFTb3VyY2UucmVhZHlTdGF0ZSA9PT0gJ3N0cmluZycpO1xuICAgIHJldHVybiBpcztcbiAgfVxuXG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICBnZXRXc1VyaSgpOiBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLndzVXJpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBoaWRkZW5cbiAgICovXG4gIGdldFNlY3JldCgpOiBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLnNlY3JldDtcbiAgfVxuXG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICBnZXRSZWNvcmRlcigpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5yZWNvcmRlcjtcbiAgfVxuXG5cbiAgLyogUHJpdmF0ZSBtZXRob2RzICovXG5cbiAgcHJpdmF0ZSBkaXNjb25uZWN0Q2FsbGJhY2soKTogdm9pZCB7XG4gICAgY29uc29sZS53YXJuKCdXZWJzb2NrZXQgY29ubmVjdGlvbiBsb3N0Jyk7XG4gICAgaWYgKHRoaXMuaXNSb29tQXZhaWxhYmxlKCkpIHtcbiAgICAgIHRoaXMuc2Vzc2lvbi5vbkxvc3RDb25uZWN0aW9uKCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGFsZXJ0KCdDb25uZWN0aW9uIGVycm9yLiBQbGVhc2UgcmVsb2FkIHBhZ2UuJyk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSByZWNvbm5lY3RpbmdDYWxsYmFjaygpOiB2b2lkIHtcbiAgICBjb25zb2xlLndhcm4oJ1dlYnNvY2tldCBjb25uZWN0aW9uIGxvc3QgKHJlY29ubmVjdGluZyknKTtcbiAgICBpZiAodGhpcy5pc1Jvb21BdmFpbGFibGUoKSkge1xuICAgICAgdGhpcy5zZXNzaW9uLm9uTG9zdENvbm5lY3Rpb24oKTtcbiAgICB9IGVsc2Uge1xuICAgICAgYWxlcnQoJ0Nvbm5lY3Rpb24gZXJyb3IuIFBsZWFzZSByZWxvYWQgcGFnZS4nKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIHJlY29ubmVjdGVkQ2FsbGJhY2soKTogdm9pZCB7XG4gICAgY29uc29sZS53YXJuKCdXZWJzb2NrZXQgcmVjb25uZWN0ZWQnKTtcbiAgICBpZiAodGhpcy5pc1Jvb21BdmFpbGFibGUoKSkge1xuICAgICAgdGhpcy5zZXNzaW9uLm9uUmVjb3ZlcmVkQ29ubmVjdGlvbigpO1xuICAgIH0gZWxzZSB7XG4gICAgICBhbGVydCgnQ29ubmVjdGlvbiBlcnJvci4gUGxlYXNlIHJlbG9hZCBwYWdlLicpO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgaXNSb29tQXZhaWxhYmxlKCk6IGJvb2xlYW4ge1xuICAgIGlmICh0aGlzLnNlc3Npb24gIT09IHVuZGVmaW5lZCAmJiB0aGlzLnNlc3Npb24gaW5zdGFuY2VvZiBTZXNzaW9uKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9IGVsc2Uge1xuICAgICAgY29uc29sZS53YXJuKCdTZXNzaW9uIGluc3RhbmNlIG5vdCBmb3VuZCcpO1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfVxuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBPcGVuVmlkdSB9IGZyb20gJy4vT3BlblZpZHUnO1xuaW1wb3J0IHsgU2Vzc2lvbiB9IGZyb20gJy4vU2Vzc2lvbic7XG5pbXBvcnQgeyBTdHJlYW0gfSBmcm9tICcuL1N0cmVhbSc7XG5pbXBvcnQgeyBTdHJlYW1NYW5hZ2VyIH0gZnJvbSAnLi9TdHJlYW1NYW5hZ2VyJztcbmltcG9ydCB7IEV2ZW50RGlzcGF0Y2hlciB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvSW50ZXJmYWNlcy9QdWJsaWMvRXZlbnREaXNwYXRjaGVyJztcbmltcG9ydCB7IFB1Ymxpc2hlclByb3BlcnRpZXMgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHVibGljL1B1Ymxpc2hlclByb3BlcnRpZXMnO1xuaW1wb3J0IHsgRXZlbnQgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0V2ZW50cy9FdmVudCc7XG5pbXBvcnQgeyBTdHJlYW1FdmVudCB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1N0cmVhbUV2ZW50JztcbmltcG9ydCB7IFN0cmVhbVByb3BlcnR5Q2hhbmdlZEV2ZW50IH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvU3RyZWFtUHJvcGVydHlDaGFuZ2VkRXZlbnQnO1xuaW1wb3J0IHsgVmlkZW9FbGVtZW50RXZlbnQgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0V2ZW50cy9WaWRlb0VsZW1lbnRFdmVudCc7XG5pbXBvcnQgeyBPcGVuVmlkdUVycm9yLCBPcGVuVmlkdUVycm9yTmFtZSB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRW51bXMvT3BlblZpZHVFcnJvcic7XG5pbXBvcnQgeyBWaWRlb0luc2VydE1vZGUgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0VudW1zL1ZpZGVvSW5zZXJ0TW9kZSc7XG5cbmltcG9ydCBwbGF0Zm9ybSA9IHJlcXVpcmUoJ3BsYXRmb3JtJyk7XG5cblxuLyoqXG4gKiBQYWNrcyBsb2NhbCBtZWRpYSBzdHJlYW1zLiBQYXJ0aWNpcGFudHMgY2FuIHB1Ymxpc2ggaXQgdG8gYSBzZXNzaW9uLiBJbml0aWFsaXplZCB3aXRoIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dIG1ldGhvZFxuICovXG5leHBvcnQgY2xhc3MgUHVibGlzaGVyIGV4dGVuZHMgU3RyZWFtTWFuYWdlciB7XG5cbiAgICAvKipcbiAgICAgKiBXaGV0aGVyIHRoZSBQdWJsaXNoZXIgaGFzIGJlZW4gZ3JhbnRlZCBhY2Nlc3MgdG8gdGhlIHJlcXVlc3RlZCBpbnB1dCBkZXZpY2VzIG9yIG5vdFxuICAgICAqL1xuICAgIGFjY2Vzc0FsbG93ZWQgPSBmYWxzZTtcblxuICAgIC8qKlxuICAgICAqIFdoZXRoZXIgeW91IGhhdmUgY2FsbGVkIFtbUHVibGlzaGVyLnN1YnNjcmliZVRvUmVtb3RlXV0gd2l0aCB2YWx1ZSBgdHJ1ZWAgb3IgYGZhbHNlYCAoKmZhbHNlKiBieSBkZWZhdWx0KVxuICAgICAqL1xuICAgIGlzU3Vic2NyaWJlZFRvUmVtb3RlID0gZmFsc2U7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgW1tTZXNzaW9uXV0gdG8gd2hpY2ggdGhlIFB1Ymxpc2hlciBiZWxvbmdzXG4gICAgICovXG4gICAgc2Vzc2lvbjogU2Vzc2lvbjsgLy8gSW5pdGlhbGl6ZWQgYnkgU2Vzc2lvbi5wdWJsaXNoKFB1Ymxpc2hlcilcblxuICAgIHByaXZhdGUgYWNjZXNzRGVuaWVkID0gZmFsc2U7XG4gICAgcHJpdmF0ZSBwcm9wZXJ0aWVzOiBQdWJsaXNoZXJQcm9wZXJ0aWVzO1xuICAgIHByaXZhdGUgcGVybWlzc2lvbkRpYWxvZ1RpbWVvdXQ6IE5vZGVKUy5UaW1lcjtcblxuICAgIC8qKlxuICAgICAqIGhpZGRlblxuICAgICAqL1xuICAgIG9wZW52aWR1OiBPcGVuVmlkdTtcbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgdmlkZW9SZWZlcmVuY2U6IEhUTUxWaWRlb0VsZW1lbnQ7XG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHNjcmVlblNoYXJlUmVzaXplSW50ZXJ2YWw6IE5vZGVKUy5UaW1lcjtcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3Rvcih0YXJnRWw6IHN0cmluZyB8IEhUTUxFbGVtZW50LCBwcm9wZXJ0aWVzOiBQdWJsaXNoZXJQcm9wZXJ0aWVzLCBvcGVudmlkdTogT3BlblZpZHUpIHtcbiAgICAgICAgc3VwZXIobmV3IFN0cmVhbSgoISFvcGVudmlkdS5zZXNzaW9uKSA/IG9wZW52aWR1LnNlc3Npb24gOiBuZXcgU2Vzc2lvbihvcGVudmlkdSksIHsgcHVibGlzaGVyUHJvcGVydGllczogcHJvcGVydGllcywgbWVkaWFDb25zdHJhaW50czoge30gfSksIHRhcmdFbCk7XG4gICAgICAgIHRoaXMucHJvcGVydGllcyA9IHByb3BlcnRpZXM7XG4gICAgICAgIHRoaXMub3BlbnZpZHUgPSBvcGVudmlkdTtcblxuICAgICAgICB0aGlzLnN0cmVhbS5lZS5vbignbG9jYWwtc3RyZWFtLWRlc3Ryb3llZCcsIChyZWFzb246IHN0cmluZykgPT4ge1xuICAgICAgICAgICAgdGhpcy5zdHJlYW0uaXNMb2NhbFN0cmVhbVB1Ymxpc2hlZCA9IGZhbHNlO1xuICAgICAgICAgICAgY29uc3Qgc3RyZWFtRXZlbnQgPSBuZXcgU3RyZWFtRXZlbnQodHJ1ZSwgdGhpcywgJ3N0cmVhbURlc3Ryb3llZCcsIHRoaXMuc3RyZWFtLCByZWFzb24pO1xuICAgICAgICAgICAgdGhpcy5lbWl0RXZlbnQoJ3N0cmVhbURlc3Ryb3llZCcsIFtzdHJlYW1FdmVudF0pO1xuICAgICAgICAgICAgc3RyZWFtRXZlbnQuY2FsbERlZmF1bHRCZWhhdmlvcigpO1xuICAgICAgICB9KTtcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFB1Ymxpc2ggb3IgdW5wdWJsaXNoIHRoZSBhdWRpbyBzdHJlYW0gKGlmIGF2YWlsYWJsZSkuIENhbGxpbmcgdGhpcyBtZXRob2QgdHdpY2UgaW4gYSByb3cgcGFzc2luZyBzYW1lIHZhbHVlIHdpbGwgaGF2ZSBubyBlZmZlY3RcbiAgICAgKlxuICAgICAqICMjIyMgRXZlbnRzIGRpc3BhdGNoZWRcbiAgICAgKlxuICAgICAqIFRoZSBbW1Nlc3Npb25dXSBvYmplY3Qgb2YgdGhlIGxvY2FsIHBhcnRpY2lwYW50IHdpbGwgZGlzcGF0Y2ggYSBgc3RyZWFtUHJvcGVydHlDaGFuZ2VkYCBldmVudCB3aXRoIGBjaGFuZ2VkUHJvcGVydHlgIHNldCB0byBgXCJhdWRpb0FjdGl2ZVwiYCBhbmQgYHJlYXNvbmAgc2V0IHRvIGBcInB1Ymxpc2hBdWRpb1wiYFxuICAgICAqIFRoZSBbW1B1Ymxpc2hlcl1dIG9iamVjdCBvZiB0aGUgbG9jYWwgcGFydGljaXBhbnQgd2lsbCBhbHNvIGRpc3BhdGNoIHRoZSBleGFjdCBzYW1lIGV2ZW50XG4gICAgICpcbiAgICAgKiBUaGUgW1tTZXNzaW9uXV0gb2JqZWN0IG9mIGV2ZXJ5IG90aGVyIHBhcnRpY2lwYW50IGNvbm5lY3RlZCB0byB0aGUgc2Vzc2lvbiB3aWxsIGRpc3BhdGNoIGEgYHN0cmVhbVByb3BlcnR5Q2hhbmdlZGAgZXZlbnQgd2l0aCBgY2hhbmdlZFByb3BlcnR5YCBzZXQgdG8gYFwiYXVkaW9BY3RpdmVcImAgYW5kIGByZWFzb25gIHNldCB0byBgXCJwdWJsaXNoQXVkaW9cImBcbiAgICAgKiBUaGUgcmVzcGVjdGl2ZSBbW1N1YnNjcmliZXJdXSBvYmplY3Qgb2YgZXZlcnkgb3RoZXIgcGFydGljaXBhbnQgcmVjZWl2aW5nIHRoaXMgUHVibGlzaGVyJ3Mgc3RyZWFtIHdpbGwgYWxzbyBkaXNwYXRjaCB0aGUgZXhhY3Qgc2FtZSBldmVudFxuICAgICAqXG4gICAgICogU2VlIFtbU3RyZWFtUHJvcGVydHlDaGFuZ2VkRXZlbnRdXSB0byBsZWFybiBtb3JlLlxuICAgICAqXG4gICAgICogQHBhcmFtIHZhbHVlIGB0cnVlYCB0byBwdWJsaXNoIHRoZSBhdWRpbyBzdHJlYW0sIGBmYWxzZWAgdG8gdW5wdWJsaXNoIGl0XG4gICAgICovXG4gICAgcHVibGlzaEF1ZGlvKHZhbHVlOiBib29sZWFuKTogdm9pZCB7XG4gICAgICAgIGlmICh0aGlzLnN0cmVhbS5hdWRpb0FjdGl2ZSAhPT0gdmFsdWUpIHtcbiAgICAgICAgICAgIHRoaXMuc3RyZWFtLmdldE1lZGlhU3RyZWFtKCkuZ2V0QXVkaW9UcmFja3MoKS5mb3JFYWNoKCh0cmFjaykgPT4ge1xuICAgICAgICAgICAgICAgIHRyYWNrLmVuYWJsZWQgPSB2YWx1ZTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgdGhpcy5zZXNzaW9uLm9wZW52aWR1LnNlbmRSZXF1ZXN0KFxuICAgICAgICAgICAgICAgICdzdHJlYW1Qcm9wZXJ0eUNoYW5nZWQnLFxuICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgc3RyZWFtSWQ6IHRoaXMuc3RyZWFtLnN0cmVhbUlkLFxuICAgICAgICAgICAgICAgICAgICBwcm9wZXJ0eTogJ2F1ZGlvQWN0aXZlJyxcbiAgICAgICAgICAgICAgICAgICAgbmV3VmFsdWU6IHZhbHVlLFxuICAgICAgICAgICAgICAgICAgICByZWFzb246ICdwdWJsaXNoQXVkaW8nXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAoZXJyb3IsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihcIkVycm9yIHNlbmRpbmcgJ3N0cmVhbVByb3BlcnR5Q2hhbmdlZCcgZXZlbnRcIiwgZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXNzaW9uLmVtaXRFdmVudCgnc3RyZWFtUHJvcGVydHlDaGFuZ2VkJywgW25ldyBTdHJlYW1Qcm9wZXJ0eUNoYW5nZWRFdmVudCh0aGlzLnNlc3Npb24sIHRoaXMuc3RyZWFtLCAnYXVkaW9BY3RpdmUnLCB2YWx1ZSwgIXZhbHVlLCAncHVibGlzaEF1ZGlvJyldKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZW1pdEV2ZW50KCdzdHJlYW1Qcm9wZXJ0eUNoYW5nZWQnLCBbbmV3IFN0cmVhbVByb3BlcnR5Q2hhbmdlZEV2ZW50KHRoaXMsIHRoaXMuc3RyZWFtLCAnYXVkaW9BY3RpdmUnLCB2YWx1ZSwgIXZhbHVlLCAncHVibGlzaEF1ZGlvJyldKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgdGhpcy5zdHJlYW0uYXVkaW9BY3RpdmUgPSB2YWx1ZTtcbiAgICAgICAgICAgIGNvbnNvbGUuaW5mbyhcIidQdWJsaXNoZXInIGhhcyBcIiArICh2YWx1ZSA/ICdwdWJsaXNoZWQnIDogJ3VucHVibGlzaGVkJykgKyAnIGl0cyBhdWRpbyBzdHJlYW0nKTtcbiAgICAgICAgfVxuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogUHVibGlzaCBvciB1bnB1Ymxpc2ggdGhlIHZpZGVvIHN0cmVhbSAoaWYgYXZhaWxhYmxlKS4gQ2FsbGluZyB0aGlzIG1ldGhvZCB0d2ljZSBpbiBhIHJvdyBwYXNzaW5nIHNhbWUgdmFsdWUgd2lsbCBoYXZlIG5vIGVmZmVjdFxuICAgICAqXG4gICAgICogIyMjIyBFdmVudHMgZGlzcGF0Y2hlZFxuICAgICAqXG4gICAgICogVGhlIFtbU2Vzc2lvbl1dIG9iamVjdCBvZiB0aGUgbG9jYWwgcGFydGljaXBhbnQgd2lsbCBkaXNwYXRjaCBhIGBzdHJlYW1Qcm9wZXJ0eUNoYW5nZWRgIGV2ZW50IHdpdGggYGNoYW5nZWRQcm9wZXJ0eWAgc2V0IHRvIGBcInZpZGVvQWN0aXZlXCJgIGFuZCBgcmVhc29uYCBzZXQgdG8gYFwicHVibGlzaFZpZGVvXCJgXG4gICAgICogVGhlIFtbUHVibGlzaGVyXV0gb2JqZWN0IG9mIHRoZSBsb2NhbCBwYXJ0aWNpcGFudCB3aWxsIGFsc28gZGlzcGF0Y2ggdGhlIGV4YWN0IHNhbWUgZXZlbnRcbiAgICAgKlxuICAgICAqIFRoZSBbW1Nlc3Npb25dXSBvYmplY3Qgb2YgZXZlcnkgb3RoZXIgcGFydGljaXBhbnQgY29ubmVjdGVkIHRvIHRoZSBzZXNzaW9uIHdpbGwgZGlzcGF0Y2ggYSBgc3RyZWFtUHJvcGVydHlDaGFuZ2VkYCBldmVudCB3aXRoIGBjaGFuZ2VkUHJvcGVydHlgIHNldCB0byBgXCJ2aWRlb0FjdGl2ZVwiYCBhbmQgYHJlYXNvbmAgc2V0IHRvIGBcInB1Ymxpc2hWaWRlb1wiYFxuICAgICAqIFRoZSByZXNwZWN0aXZlIFtbU3Vic2NyaWJlcl1dIG9iamVjdCBvZiBldmVyeSBvdGhlciBwYXJ0aWNpcGFudCByZWNlaXZpbmcgdGhpcyBQdWJsaXNoZXIncyBzdHJlYW0gd2lsbCBhbHNvIGRpc3BhdGNoIHRoZSBleGFjdCBzYW1lIGV2ZW50XG4gICAgICpcbiAgICAgKiBTZWUgW1tTdHJlYW1Qcm9wZXJ0eUNoYW5nZWRFdmVudF1dIHRvIGxlYXJuIG1vcmUuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gdmFsdWUgYHRydWVgIHRvIHB1Ymxpc2ggdGhlIHZpZGVvIHN0cmVhbSwgYGZhbHNlYCB0byB1bnB1Ymxpc2ggaXRcbiAgICAgKi9cbiAgICBwdWJsaXNoVmlkZW8odmFsdWU6IGJvb2xlYW4pOiB2b2lkIHtcbiAgICAgICAgaWYgKHRoaXMuc3RyZWFtLnZpZGVvQWN0aXZlICE9PSB2YWx1ZSkge1xuICAgICAgICAgICAgdGhpcy5zdHJlYW0uZ2V0TWVkaWFTdHJlYW0oKS5nZXRWaWRlb1RyYWNrcygpLmZvckVhY2goKHRyYWNrKSA9PiB7XG4gICAgICAgICAgICAgICAgdHJhY2suZW5hYmxlZCA9IHZhbHVlO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB0aGlzLnNlc3Npb24ub3BlbnZpZHUuc2VuZFJlcXVlc3QoXG4gICAgICAgICAgICAgICAgJ3N0cmVhbVByb3BlcnR5Q2hhbmdlZCcsXG4gICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICBzdHJlYW1JZDogdGhpcy5zdHJlYW0uc3RyZWFtSWQsXG4gICAgICAgICAgICAgICAgICAgIHByb3BlcnR5OiAndmlkZW9BY3RpdmUnLFxuICAgICAgICAgICAgICAgICAgICBuZXdWYWx1ZTogdmFsdWUsXG4gICAgICAgICAgICAgICAgICAgIHJlYXNvbjogJ3B1Ymxpc2hWaWRlbydcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIChlcnJvciwgcmVzcG9uc2UpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKFwiRXJyb3Igc2VuZGluZyAnc3RyZWFtUHJvcGVydHlDaGFuZ2VkJyBldmVudFwiLCBlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnNlc3Npb24uZW1pdEV2ZW50KCdzdHJlYW1Qcm9wZXJ0eUNoYW5nZWQnLCBbbmV3IFN0cmVhbVByb3BlcnR5Q2hhbmdlZEV2ZW50KHRoaXMuc2Vzc2lvbiwgdGhpcy5zdHJlYW0sICd2aWRlb0FjdGl2ZScsIHZhbHVlLCAhdmFsdWUsICdwdWJsaXNoVmlkZW8nKV0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5lbWl0RXZlbnQoJ3N0cmVhbVByb3BlcnR5Q2hhbmdlZCcsIFtuZXcgU3RyZWFtUHJvcGVydHlDaGFuZ2VkRXZlbnQodGhpcywgdGhpcy5zdHJlYW0sICd2aWRlb0FjdGl2ZScsIHZhbHVlLCAhdmFsdWUsICdwdWJsaXNoVmlkZW8nKV0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB0aGlzLnN0cmVhbS52aWRlb0FjdGl2ZSA9IHZhbHVlO1xuICAgICAgICAgICAgY29uc29sZS5pbmZvKFwiJ1B1Ymxpc2hlcicgaGFzIFwiICsgKHZhbHVlID8gJ3B1Ymxpc2hlZCcgOiAndW5wdWJsaXNoZWQnKSArICcgaXRzIHZpZGVvIHN0cmVhbScpO1xuICAgICAgICB9XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBDYWxsIHRoaXMgbWV0aG9kIGJlZm9yZSBbW1Nlc3Npb24ucHVibGlzaF1dIGlmIHlvdSBwcmVmZXIgdG8gc3Vic2NyaWJlIHRvIHlvdXIgUHVibGlzaGVyJ3MgcmVtb3RlIHN0cmVhbSBpbnN0ZWFkIG9mIHVzaW5nIHRoZSBsb2NhbCBzdHJlYW0sIGFzIGFueSBvdGhlciB1c2VyIHdvdWxkIGRvLlxuICAgICAqL1xuICAgIHN1YnNjcmliZVRvUmVtb3RlKHZhbHVlPzogYm9vbGVhbik6IHZvaWQge1xuICAgICAgICB2YWx1ZSA9ICh2YWx1ZSAhPT0gdW5kZWZpbmVkKSA/IHZhbHVlIDogdHJ1ZTtcbiAgICAgICAgdGhpcy5pc1N1YnNjcmliZWRUb1JlbW90ZSA9IHZhbHVlO1xuICAgICAgICB0aGlzLnN0cmVhbS5zdWJzY3JpYmVUb015UmVtb3RlKHZhbHVlKTtcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFNlZSBbW0V2ZW50RGlzcGF0Y2hlci5vbl1dXG4gICAgICovXG4gICAgb24odHlwZTogc3RyaW5nLCBoYW5kbGVyOiAoZXZlbnQ6IEV2ZW50KSA9PiB2b2lkKTogRXZlbnREaXNwYXRjaGVyIHtcbiAgICAgICAgc3VwZXIub24odHlwZSwgaGFuZGxlcik7XG4gICAgICAgIGlmICh0eXBlID09PSAnc3RyZWFtQ3JlYXRlZCcpIHtcbiAgICAgICAgICAgIGlmICghIXRoaXMuc3RyZWFtICYmIHRoaXMuc3RyZWFtLmlzTG9jYWxTdHJlYW1QdWJsaXNoZWQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVtaXRFdmVudCgnc3RyZWFtQ3JlYXRlZCcsIFtuZXcgU3RyZWFtRXZlbnQoZmFsc2UsIHRoaXMsICdzdHJlYW1DcmVhdGVkJywgdGhpcy5zdHJlYW0sICcnKV0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbS5lZS5vbignc3RyZWFtLWNyZWF0ZWQtYnktcHVibGlzaGVyJywgKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmVtaXRFdmVudCgnc3RyZWFtQ3JlYXRlZCcsIFtuZXcgU3RyZWFtRXZlbnQoZmFsc2UsIHRoaXMsICdzdHJlYW1DcmVhdGVkJywgdGhpcy5zdHJlYW0sICcnKV0pO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmICh0eXBlID09PSAncmVtb3RlVmlkZW9QbGF5aW5nJykge1xuICAgICAgICAgICAgaWYgKHRoaXMuc3RyZWFtLmRpc3BsYXlNeVJlbW90ZSgpICYmIHRoaXMudmlkZW9zWzBdICYmIHRoaXMudmlkZW9zWzBdLnZpZGVvICYmXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8uY3VycmVudFRpbWUgPiAwICYmXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8ucGF1c2VkID09PSBmYWxzZSAmJlxuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9zWzBdLnZpZGVvLmVuZGVkID09PSBmYWxzZSAmJlxuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9zWzBdLnZpZGVvLnJlYWR5U3RhdGUgPT09IDQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVtaXRFdmVudCgncmVtb3RlVmlkZW9QbGF5aW5nJywgW25ldyBWaWRlb0VsZW1lbnRFdmVudCh0aGlzLnZpZGVvc1swXS52aWRlbywgdGhpcywgJ3JlbW90ZVZpZGVvUGxheWluZycpXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHR5cGUgPT09ICdhY2Nlc3NBbGxvd2VkJykge1xuICAgICAgICAgICAgaWYgKHRoaXMuYWNjZXNzQWxsb3dlZCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZW1pdEV2ZW50KCdhY2Nlc3NBbGxvd2VkJywgW10pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmICh0eXBlID09PSAnYWNjZXNzRGVuaWVkJykge1xuICAgICAgICAgICAgaWYgKHRoaXMuYWNjZXNzRGVuaWVkKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5lbWl0RXZlbnQoJ2FjY2Vzc0RlbmllZCcsIFtdKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFNlZSBbW0V2ZW50RGlzcGF0Y2hlci5vbmNlXV1cbiAgICAgKi9cbiAgICBvbmNlKHR5cGU6IHN0cmluZywgaGFuZGxlcjogKGV2ZW50OiBFdmVudCkgPT4gdm9pZCk6IFB1Ymxpc2hlciB7XG4gICAgICAgIHN1cGVyLm9uY2UodHlwZSwgaGFuZGxlcik7XG4gICAgICAgIGlmICh0eXBlID09PSAnc3RyZWFtQ3JlYXRlZCcpIHtcbiAgICAgICAgICAgIGlmICghIXRoaXMuc3RyZWFtICYmIHRoaXMuc3RyZWFtLmlzTG9jYWxTdHJlYW1QdWJsaXNoZWQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVtaXRFdmVudCgnc3RyZWFtQ3JlYXRlZCcsIFtuZXcgU3RyZWFtRXZlbnQoZmFsc2UsIHRoaXMsICdzdHJlYW1DcmVhdGVkJywgdGhpcy5zdHJlYW0sICcnKV0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbS5lZS5vbmNlKCdzdHJlYW0tY3JlYXRlZC1ieS1wdWJsaXNoZXInLCAoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZW1pdEV2ZW50KCdzdHJlYW1DcmVhdGVkJywgW25ldyBTdHJlYW1FdmVudChmYWxzZSwgdGhpcywgJ3N0cmVhbUNyZWF0ZWQnLCB0aGlzLnN0cmVhbSwgJycpXSk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHR5cGUgPT09ICdyZW1vdGVWaWRlb1BsYXlpbmcnKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5zdHJlYW0uZGlzcGxheU15UmVtb3RlKCkgJiYgdGhpcy52aWRlb3NbMF0gJiYgdGhpcy52aWRlb3NbMF0udmlkZW8gJiZcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvc1swXS52aWRlby5jdXJyZW50VGltZSA+IDAgJiZcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvc1swXS52aWRlby5wYXVzZWQgPT09IGZhbHNlICYmXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8uZW5kZWQgPT09IGZhbHNlICYmXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8ucmVhZHlTdGF0ZSA9PT0gNCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZW1pdEV2ZW50KCdyZW1vdGVWaWRlb1BsYXlpbmcnLCBbbmV3IFZpZGVvRWxlbWVudEV2ZW50KHRoaXMudmlkZW9zWzBdLnZpZGVvLCB0aGlzLCAncmVtb3RlVmlkZW9QbGF5aW5nJyldKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAodHlwZSA9PT0gJ2FjY2Vzc0FsbG93ZWQnKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5hY2Nlc3NBbGxvd2VkKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5lbWl0RXZlbnQoJ2FjY2Vzc0FsbG93ZWQnLCBbXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHR5cGUgPT09ICdhY2Nlc3NEZW5pZWQnKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5hY2Nlc3NEZW5pZWQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVtaXRFdmVudCgnYWNjZXNzRGVuaWVkJywgW10pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuXG4gICAgLyogSGlkZGVuIG1ldGhvZHMgKi9cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBpbml0aWFsaXplKCk6IFByb21pc2U8YW55PiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG5cbiAgICAgICAgICAgIGNvbnN0IGVycm9yQ2FsbGJhY2sgPSAob3BlblZpZHVFcnJvcjogT3BlblZpZHVFcnJvcikgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuYWNjZXNzRGVuaWVkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB0aGlzLmFjY2Vzc0FsbG93ZWQgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICByZWplY3Qob3BlblZpZHVFcnJvcik7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICBjb25zdCBzdWNjZXNzQ2FsbGJhY2sgPSAobWVkaWFTdHJlYW06IE1lZGlhU3RyZWFtKSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5hY2Nlc3NBbGxvd2VkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB0aGlzLmFjY2Vzc0RlbmllZCA9IGZhbHNlO1xuXG4gICAgICAgICAgICAgICAgaWYgKHRoaXMub3BlbnZpZHUuaXNNZWRpYVN0cmVhbVRyYWNrKHRoaXMucHJvcGVydGllcy5hdWRpb1NvdXJjZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgbWVkaWFTdHJlYW0ucmVtb3ZlVHJhY2sobWVkaWFTdHJlYW0uZ2V0QXVkaW9UcmFja3MoKVswXSk7XG4gICAgICAgICAgICAgICAgICAgIG1lZGlhU3RyZWFtLmFkZFRyYWNrKCg8TWVkaWFTdHJlYW1UcmFjaz50aGlzLnByb3BlcnRpZXMuYXVkaW9Tb3VyY2UpKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAodGhpcy5vcGVudmlkdS5pc01lZGlhU3RyZWFtVHJhY2sodGhpcy5wcm9wZXJ0aWVzLnZpZGVvU291cmNlKSkge1xuICAgICAgICAgICAgICAgICAgICBtZWRpYVN0cmVhbS5yZW1vdmVUcmFjayhtZWRpYVN0cmVhbS5nZXRWaWRlb1RyYWNrcygpWzBdKTtcbiAgICAgICAgICAgICAgICAgICAgbWVkaWFTdHJlYW0uYWRkVHJhY2soKDxNZWRpYVN0cmVhbVRyYWNrPnRoaXMucHJvcGVydGllcy52aWRlb1NvdXJjZSkpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIEFwcGx5IFB1Ymxpc2hlclByb3BlcnRpZXMucHVibGlzaEF1ZGlvIGFuZCBQdWJsaXNoZXJQcm9wZXJ0aWVzLnB1Ymxpc2hWaWRlb1xuICAgICAgICAgICAgICAgIGlmICghIW1lZGlhU3RyZWFtLmdldEF1ZGlvVHJhY2tzKClbMF0pIHtcbiAgICAgICAgICAgICAgICAgICAgbWVkaWFTdHJlYW0uZ2V0QXVkaW9UcmFja3MoKVswXS5lbmFibGVkID0gISF0aGlzLnN0cmVhbS5vdXRib3VuZFN0cmVhbU9wdHMucHVibGlzaGVyUHJvcGVydGllcy5wdWJsaXNoQXVkaW87XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmICghIW1lZGlhU3RyZWFtLmdldFZpZGVvVHJhY2tzKClbMF0pIHtcbiAgICAgICAgICAgICAgICAgICAgbWVkaWFTdHJlYW0uZ2V0VmlkZW9UcmFja3MoKVswXS5lbmFibGVkID0gISF0aGlzLnN0cmVhbS5vdXRib3VuZFN0cmVhbU9wdHMucHVibGlzaGVyUHJvcGVydGllcy5wdWJsaXNoVmlkZW87XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb1JlZmVyZW5jZSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3ZpZGVvJyk7XG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb1JlZmVyZW5jZS5zcmNPYmplY3QgPSBtZWRpYVN0cmVhbTtcblxuICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtLnNldE1lZGlhU3RyZWFtKG1lZGlhU3RyZWFtKTtcbiAgICAgICAgICAgICAgICBpZiAoIXRoaXMuc3RyZWFtLmRpc3BsYXlNeVJlbW90ZSgpKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIFdoZW4gd2UgYXJlIHN1YnNjcmliZWQgdG8gb3VyIHJlbW90ZSB3ZSBkb24ndCBzdGlsbCBzZXQgdGhlIE1lZGlhU3RyZWFtIG9iamVjdCBpbiB0aGUgdmlkZW8gZWxlbWVudHMgdG9cbiAgICAgICAgICAgICAgICAgICAgLy8gYXZvaWQgZWFybHkgJ3N0cmVhbVBsYXlpbmcnIGV2ZW50XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtLnVwZGF0ZU1lZGlhU3RyZWFtSW5WaWRlb3MoKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoISF0aGlzLmZpcnN0VmlkZW9FbGVtZW50KSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuY3JlYXRlVmlkZW9FbGVtZW50KHRoaXMuZmlyc3RWaWRlb0VsZW1lbnQudGFyZ2V0RWxlbWVudCwgPFZpZGVvSW5zZXJ0TW9kZT50aGlzLnByb3BlcnRpZXMuaW5zZXJ0TW9kZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGRlbGV0ZSB0aGlzLmZpcnN0VmlkZW9FbGVtZW50O1xuXG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuc3RyZWFtLmlzU2VuZFZpZGVvKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCF0aGlzLnN0cmVhbS5pc1NlbmRTY3JlZW4oKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gV2l0aCBubyBzY3JlZW4gc2hhcmUsIHZpZGVvIGRpbWVuc2lvbiBjYW4gYmUgc2V0IGRpcmVjdGx5IGZyb20gTWVkaWFTdHJlYW0gKGdldFNldHRpbmdzKVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gT3JpZW50YXRpb24gbXVzdCBiZSBjaGVja2VkIGZvciBtb2JpbGUgZGV2aWNlcyAod2lkdGggYW5kIGhlaWdodCBhcmUgcmV2ZXJzZWQpXG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB7IHdpZHRoLCBoZWlnaHQgfSA9IG1lZGlhU3RyZWFtLmdldFZpZGVvVHJhY2tzKClbMF0uZ2V0U2V0dGluZ3MoKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHBsYXRmb3JtLm5hbWUhIS50b0xvd2VyQ2FzZSgpLmluZGV4T2YoJ21vYmlsZScpICE9PSAtMSAmJiAod2luZG93LmlubmVySGVpZ2h0ID4gd2luZG93LmlubmVyV2lkdGgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gTW9iaWxlIHBvcnRyYWl0IG1vZGVcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbS52aWRlb0RpbWVuc2lvbnMgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdpZHRoOiBoZWlnaHQgfHwgMCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaGVpZ2h0OiB3aWR0aCB8fCAwXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdHJlYW0udmlkZW9EaW1lbnNpb25zID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3aWR0aDogd2lkdGggfHwgMCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaGVpZ2h0OiBoZWlnaHQgfHwgMFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbS5pc0xvY2FsU3RyZWFtUmVhZHlUb1B1Ymxpc2ggPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdHJlYW0uZWUuZW1pdEV2ZW50KCdzdHJlYW0tcmVhZHktdG8tcHVibGlzaCcsIFtdKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIFdpdGggc2NyZWVuIHNoYXJlLCB2aWRlbyBkaW1lbnNpb24gbXVzdCBiZSBnb3QgZnJvbSBhIHZpZGVvIGVsZW1lbnQgKG9ubG9hZGVkbWV0YWRhdGEgZXZlbnQpXG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnZpZGVvUmVmZXJlbmNlLm9ubG9hZGVkbWV0YWRhdGEgPSAoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdHJlYW0udmlkZW9EaW1lbnNpb25zID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3aWR0aDogdGhpcy52aWRlb1JlZmVyZW5jZS52aWRlb1dpZHRoLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBoZWlnaHQ6IHRoaXMudmlkZW9SZWZlcmVuY2UudmlkZW9IZWlnaHRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc2NyZWVuU2hhcmVSZXNpemVJbnRlcnZhbCA9IHNldEludGVydmFsKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZmlyZWZveFNldHRpbmdzID0gbWVkaWFTdHJlYW0uZ2V0VmlkZW9UcmFja3MoKVswXS5nZXRTZXR0aW5ncygpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBuZXdXaWR0aCA9IChwbGF0Zm9ybS5uYW1lID09PSAnQ2hyb21lJykgPyB0aGlzLnZpZGVvUmVmZXJlbmNlLnZpZGVvV2lkdGggOiBmaXJlZm94U2V0dGluZ3Mud2lkdGg7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG5ld0hlaWdodCA9IChwbGF0Zm9ybS5uYW1lID09PSAnQ2hyb21lJykgPyB0aGlzLnZpZGVvUmVmZXJlbmNlLnZpZGVvSGVpZ2h0IDogZmlyZWZveFNldHRpbmdzLmhlaWdodDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuc3RyZWFtLmlzTG9jYWxTdHJlYW1QdWJsaXNoZWQgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChuZXdXaWR0aCAhPT0gdGhpcy5zdHJlYW0udmlkZW9EaW1lbnNpb25zLndpZHRoIHx8XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3SGVpZ2h0ICE9PSB0aGlzLnN0cmVhbS52aWRlb0RpbWVuc2lvbnMuaGVpZ2h0KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3Qgb2xkVmFsdWUgPSB7IHdpZHRoOiB0aGlzLnN0cmVhbS52aWRlb0RpbWVuc2lvbnMud2lkdGgsIGhlaWdodDogdGhpcy5zdHJlYW0udmlkZW9EaW1lbnNpb25zLmhlaWdodCB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdHJlYW0udmlkZW9EaW1lbnNpb25zID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdpZHRoOiBuZXdXaWR0aCB8fCAwLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhlaWdodDogbmV3SGVpZ2h0IHx8IDBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnNlc3Npb24ub3BlbnZpZHUuc2VuZFJlcXVlc3QoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ3N0cmVhbVByb3BlcnR5Q2hhbmdlZCcsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJlYW1JZDogdGhpcy5zdHJlYW0uc3RyZWFtSWQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByb3BlcnR5OiAndmlkZW9EaW1lbnNpb25zJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3VmFsdWU6IEpTT04uc3RyaW5naWZ5KHRoaXMuc3RyZWFtLnZpZGVvRGltZW5zaW9ucyksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlYXNvbjogJ3NjcmVlblJlc2l6ZWQnXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoZXJyb3IsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihcIkVycm9yIHNlbmRpbmcgJ3N0cmVhbVByb3BlcnR5Q2hhbmdlZCcgZXZlbnRcIiwgZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXNzaW9uLmVtaXRFdmVudCgnc3RyZWFtUHJvcGVydHlDaGFuZ2VkJywgW25ldyBTdHJlYW1Qcm9wZXJ0eUNoYW5nZWRFdmVudCh0aGlzLnNlc3Npb24sIHRoaXMuc3RyZWFtLCAndmlkZW9EaW1lbnNpb25zJywgdGhpcy5zdHJlYW0udmlkZW9EaW1lbnNpb25zLCBvbGRWYWx1ZSwgJ3NjcmVlblJlc2l6ZWQnKV0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5lbWl0RXZlbnQoJ3N0cmVhbVByb3BlcnR5Q2hhbmdlZCcsIFtuZXcgU3RyZWFtUHJvcGVydHlDaGFuZ2VkRXZlbnQodGhpcywgdGhpcy5zdHJlYW0sICd2aWRlb0RpbWVuc2lvbnMnLCB0aGlzLnN0cmVhbS52aWRlb0RpbWVuc2lvbnMsIG9sZFZhbHVlLCAnc2NyZWVuUmVzaXplZCcpXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0sIDUwMCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdHJlYW0uaXNMb2NhbFN0cmVhbVJlYWR5VG9QdWJsaXNoID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbS5lZS5lbWl0RXZlbnQoJ3N0cmVhbS1yZWFkeS10by1wdWJsaXNoJywgW10pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtLmlzTG9jYWxTdHJlYW1SZWFkeVRvUHVibGlzaCA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtLmVlLmVtaXRFdmVudCgnc3RyZWFtLXJlYWR5LXRvLXB1Ymxpc2gnLCBbXSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIHRoaXMub3BlbnZpZHUuZ2VuZXJhdGVNZWRpYUNvbnN0cmFpbnRzKHRoaXMucHJvcGVydGllcylcbiAgICAgICAgICAgICAgICAudGhlbihjb25zdHJhaW50cyA9PiB7XG5cbiAgICAgICAgICAgICAgICAgICAgY29uc3Qgb3V0Ym91bmRTdHJlYW1PcHRpb25zID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgbWVkaWFDb25zdHJhaW50czogY29uc3RyYWludHMsXG4gICAgICAgICAgICAgICAgICAgICAgICBwdWJsaXNoZXJQcm9wZXJ0aWVzOiB0aGlzLnByb3BlcnRpZXNcbiAgICAgICAgICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbS5zZXRPdXRib3VuZFN0cmVhbU9wdGlvbnMob3V0Ym91bmRTdHJlYW1PcHRpb25zKTtcblxuICAgICAgICAgICAgICAgICAgICBjb25zdCBjb25zdHJhaW50c0F1eDogTWVkaWFTdHJlYW1Db25zdHJhaW50cyA9IHt9O1xuICAgICAgICAgICAgICAgICAgICBjb25zdCB0aW1lRm9yRGlhbG9nRXZlbnQgPSAxMjUwO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLnN0cmVhbS5pc1NlbmRWaWRlbygpIHx8IHRoaXMuc3RyZWFtLmlzU2VuZEF1ZGlvKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGRlZmluZWRBdWRpb0NvbnN0cmFpbnQgPSAoKGNvbnN0cmFpbnRzLmF1ZGlvID09PSB1bmRlZmluZWQpID8gdHJ1ZSA6IGNvbnN0cmFpbnRzLmF1ZGlvKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0cmFpbnRzQXV4LmF1ZGlvID0gdGhpcy5zdHJlYW0uaXNTZW5kU2NyZWVuKCkgPyBmYWxzZSA6IGRlZmluZWRBdWRpb0NvbnN0cmFpbnQ7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdHJhaW50c0F1eC52aWRlbyA9IGNvbnN0cmFpbnRzLnZpZGVvO1xuICAgICAgICAgICAgICAgICAgICAgICAgbGV0IHN0YXJ0VGltZSA9IERhdGUubm93KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnNldFBlcm1pc3Npb25EaWFsb2dUaW1lcih0aW1lRm9yRGlhbG9nRXZlbnQpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBuYXZpZ2F0b3IubWVkaWFEZXZpY2VzLmdldFVzZXJNZWRpYShjb25zdHJhaW50c0F1eClcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAudGhlbihtZWRpYVN0cmVhbSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY2xlYXJQZXJtaXNzaW9uRGlhbG9nVGltZXIoc3RhcnRUaW1lLCB0aW1lRm9yRGlhbG9nRXZlbnQpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLnN0cmVhbS5pc1NlbmRTY3JlZW4oKSAmJiB0aGlzLnN0cmVhbS5pc1NlbmRBdWRpbygpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBXaGVuIGdldHRpbmcgZGVza3RvcCBhcyB1c2VyIG1lZGlhIGF1ZGlvIGNvbnN0cmFpbnQgbXVzdCBiZSBmYWxzZS4gTm93IHdlIGNhbiBhc2sgZm9yIGl0IGlmIHJlcXVpcmVkXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdHJhaW50c0F1eC5hdWRpbyA9IGRlZmluZWRBdWRpb0NvbnN0cmFpbnQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdHJhaW50c0F1eC52aWRlbyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhcnRUaW1lID0gRGF0ZS5ub3coKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc2V0UGVybWlzc2lvbkRpYWxvZ1RpbWVyKHRpbWVGb3JEaWFsb2dFdmVudCk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hdmlnYXRvci5tZWRpYURldmljZXMuZ2V0VXNlck1lZGlhKGNvbnN0cmFpbnRzQXV4KVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC50aGVuKGF1ZGlvT25seVN0cmVhbSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY2xlYXJQZXJtaXNzaW9uRGlhbG9nVGltZXIoc3RhcnRUaW1lLCB0aW1lRm9yRGlhbG9nRXZlbnQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZWRpYVN0cmVhbS5hZGRUcmFjayhhdWRpb09ubHlTdHJlYW0uZ2V0QXVkaW9UcmFja3MoKVswXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN1Y2Nlc3NDYWxsYmFjayhtZWRpYVN0cmVhbSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNsZWFyUGVybWlzc2lvbkRpYWxvZ1RpbWVyKHN0YXJ0VGltZSwgdGltZUZvckRpYWxvZ0V2ZW50KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGVycm9yTmFtZSwgZXJyb3JNZXNzYWdlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzd2l0Y2ggKGVycm9yLm5hbWUudG9Mb3dlckNhc2UoKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAnbm90Zm91bmRlcnJvcic6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JOYW1lID0gT3BlblZpZHVFcnJvck5hbWUuSU5QVVRfQVVESU9fREVWSUNFX05PVF9GT1VORDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck1lc3NhZ2UgPSBlcnJvci50b1N0cmluZygpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yQ2FsbGJhY2sobmV3IE9wZW5WaWR1RXJyb3IoZXJyb3JOYW1lLCBlcnJvck1lc3NhZ2UpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJ25vdGFsbG93ZWRlcnJvcic6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JOYW1lID0gT3BlblZpZHVFcnJvck5hbWUuREVWSUNFX0FDQ0VTU19ERU5JRUQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JNZXNzYWdlID0gZXJyb3IudG9TdHJpbmcoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvckNhbGxiYWNrKG5ldyBPcGVuVmlkdUVycm9yKGVycm9yTmFtZSwgZXJyb3JNZXNzYWdlKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlICdvdmVyY29uc3RyYWluZWRlcnJvcic6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yLmNvbnN0cmFpbnQudG9Mb3dlckNhc2UoKSA9PT0gJ2RldmljZWlkJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck5hbWUgPSBPcGVuVmlkdUVycm9yTmFtZS5JTlBVVF9BVURJT19ERVZJQ0VfTk9UX0ZPVU5EO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck1lc3NhZ2UgPSBcIkF1ZGlvIGlucHV0IGRldmljZSB3aXRoIGRldmljZUlkICdcIiArICg8Q29uc3RyYWluRE9NU3RyaW5nUGFyYW1ldGVycz4oPE1lZGlhVHJhY2tDb25zdHJhaW50cz5jb25zdHJhaW50cy52aWRlbykuZGV2aWNlSWQhISkuZXhhY3QgKyBcIicgbm90IGZvdW5kXCI7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JOYW1lID0gT3BlblZpZHVFcnJvck5hbWUuUFVCTElTSEVSX1BST1BFUlRJRVNfRVJST1I7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yTWVzc2FnZSA9IFwiQXVkaW8gaW5wdXQgZGV2aWNlIGRvZXNuJ3Qgc3VwcG9ydCB0aGUgdmFsdWUgcGFzc2VkIGZvciBjb25zdHJhaW50ICdcIiArIGVycm9yLmNvbnN0cmFpbnQgKyBcIidcIjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JDYWxsYmFjayhuZXcgT3BlblZpZHVFcnJvcihlcnJvck5hbWUsIGVycm9yTWVzc2FnZSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdWNjZXNzQ2FsbGJhY2sobWVkaWFTdHJlYW0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNsZWFyUGVybWlzc2lvbkRpYWxvZ1RpbWVyKHN0YXJ0VGltZSwgdGltZUZvckRpYWxvZ0V2ZW50KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGVycm9yTmFtZSwgZXJyb3JNZXNzYWdlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzd2l0Y2ggKGVycm9yLm5hbWUudG9Mb3dlckNhc2UoKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAnbm90Zm91bmRlcnJvcic6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmF2aWdhdG9yLm1lZGlhRGV2aWNlcy5nZXRVc2VyTWVkaWEoe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhdWRpbzogZmFsc2UsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZpZGVvOiBjb25zdHJhaW50cy52aWRlb1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC50aGVuKG1lZGlhU3RyZWFtID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1lZGlhU3RyZWFtLmdldFZpZGVvVHJhY2tzKCkuZm9yRWFjaCgodHJhY2spID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cmFjay5zdG9wKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yTmFtZSA9IE9wZW5WaWR1RXJyb3JOYW1lLklOUFVUX0FVRElPX0RFVklDRV9OT1RfRk9VTkQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck1lc3NhZ2UgPSBlcnJvci50b1N0cmluZygpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JDYWxsYmFjayhuZXcgT3BlblZpZHVFcnJvcihlcnJvck5hbWUsIGVycm9yTWVzc2FnZSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KS5jYXRjaChlID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yTmFtZSA9IE9wZW5WaWR1RXJyb3JOYW1lLklOUFVUX1ZJREVPX0RFVklDRV9OT1RfRk9VTkQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck1lc3NhZ2UgPSBlcnJvci50b1N0cmluZygpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JDYWxsYmFjayhuZXcgT3BlblZpZHVFcnJvcihlcnJvck5hbWUsIGVycm9yTWVzc2FnZSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJ25vdGFsbG93ZWRlcnJvcic6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JOYW1lID0gdGhpcy5zdHJlYW0uaXNTZW5kU2NyZWVuKCkgPyBPcGVuVmlkdUVycm9yTmFtZS5TQ1JFRU5fQ0FQVFVSRV9ERU5JRUQgOiBPcGVuVmlkdUVycm9yTmFtZS5ERVZJQ0VfQUNDRVNTX0RFTklFRDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck1lc3NhZ2UgPSBlcnJvci50b1N0cmluZygpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yQ2FsbGJhY2sobmV3IE9wZW5WaWR1RXJyb3IoZXJyb3JOYW1lLCBlcnJvck1lc3NhZ2UpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJ292ZXJjb25zdHJhaW5lZGVycm9yJzpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYXZpZ2F0b3IubWVkaWFEZXZpY2VzLmdldFVzZXJNZWRpYSh7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGF1ZGlvOiBmYWxzZSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmlkZW86IGNvbnN0cmFpbnRzLnZpZGVvXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLnRoZW4obWVkaWFTdHJlYW0gPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWVkaWFTdHJlYW0uZ2V0VmlkZW9UcmFja3MoKS5mb3JFYWNoKCh0cmFjaykgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRyYWNrLnN0b3AoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yLmNvbnN0cmFpbnQudG9Mb3dlckNhc2UoKSA9PT0gJ2RldmljZWlkJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yTmFtZSA9IE9wZW5WaWR1RXJyb3JOYW1lLklOUFVUX0FVRElPX0RFVklDRV9OT1RfRk9VTkQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JNZXNzYWdlID0gXCJBdWRpbyBpbnB1dCBkZXZpY2Ugd2l0aCBkZXZpY2VJZCAnXCIgKyAoPENvbnN0cmFpbkRPTVN0cmluZ1BhcmFtZXRlcnM+KDxNZWRpYVRyYWNrQ29uc3RyYWludHM+Y29uc3RyYWludHMuYXVkaW8pLmRldmljZUlkISEpLmV4YWN0ICsgXCInIG5vdCBmb3VuZFwiO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck5hbWUgPSBPcGVuVmlkdUVycm9yTmFtZS5QVUJMSVNIRVJfUFJPUEVSVElFU19FUlJPUjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck1lc3NhZ2UgPSBcIkF1ZGlvIGlucHV0IGRldmljZSBkb2Vzbid0IHN1cHBvcnQgdGhlIHZhbHVlIHBhc3NlZCBmb3IgY29uc3RyYWludCAnXCIgKyBlcnJvci5jb25zdHJhaW50ICsgXCInXCI7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvckNhbGxiYWNrKG5ldyBPcGVuVmlkdUVycm9yKGVycm9yTmFtZSwgZXJyb3JNZXNzYWdlKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pLmNhdGNoKGUgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yLmNvbnN0cmFpbnQudG9Mb3dlckNhc2UoKSA9PT0gJ2RldmljZWlkJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yTmFtZSA9IE9wZW5WaWR1RXJyb3JOYW1lLklOUFVUX1ZJREVPX0RFVklDRV9OT1RfRk9VTkQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JNZXNzYWdlID0gXCJWaWRlbyBpbnB1dCBkZXZpY2Ugd2l0aCBkZXZpY2VJZCAnXCIgKyAoPENvbnN0cmFpbkRPTVN0cmluZ1BhcmFtZXRlcnM+KDxNZWRpYVRyYWNrQ29uc3RyYWludHM+Y29uc3RyYWludHMudmlkZW8pLmRldmljZUlkISEpLmV4YWN0ICsgXCInIG5vdCBmb3VuZFwiO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck5hbWUgPSBPcGVuVmlkdUVycm9yTmFtZS5QVUJMSVNIRVJfUFJPUEVSVElFU19FUlJPUjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck1lc3NhZ2UgPSBcIlZpZGVvIGlucHV0IGRldmljZSBkb2Vzbid0IHN1cHBvcnQgdGhlIHZhbHVlIHBhc3NlZCBmb3IgY29uc3RyYWludCAnXCIgKyBlcnJvci5jb25zdHJhaW50ICsgXCInXCI7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvckNhbGxiYWNrKG5ldyBPcGVuVmlkdUVycm9yKGVycm9yTmFtZSwgZXJyb3JNZXNzYWdlKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZWplY3QobmV3IE9wZW5WaWR1RXJyb3IoT3BlblZpZHVFcnJvck5hbWUuTk9fSU5QVVRfU09VUkNFX1NFVCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBcIlByb3BlcnRpZXMgJ2F1ZGlvU291cmNlJyBhbmQgJ3ZpZGVvU291cmNlJyBjYW5ub3QgYmUgc2V0IHRvIGZhbHNlIG9yIG51bGwgYXQgdGhlIHNhbWUgdGltZSB3aGVuIGNhbGxpbmcgJ09wZW5WaWR1LmluaXRQdWJsaXNoZXInXCIpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgLmNhdGNoKChlcnJvcjogT3BlblZpZHVFcnJvcikgPT4ge1xuICAgICAgICAgICAgICAgICAgICBlcnJvckNhbGxiYWNrKGVycm9yKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHVwZGF0ZVNlc3Npb24oc2Vzc2lvbjogU2Vzc2lvbik6IHZvaWQge1xuICAgICAgICB0aGlzLnNlc3Npb24gPSBzZXNzaW9uO1xuICAgICAgICB0aGlzLnN0cmVhbS5zZXNzaW9uID0gc2Vzc2lvbjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgcmVlc3RhYmxpc2hTdHJlYW1QbGF5aW5nRXZlbnQoKSB7XG4gICAgICAgIGlmICh0aGlzLmVlLmdldExpc3RlbmVycygnc3RyZWFtUGxheWluZycpLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgIHRoaXMuYWRkUGxheUV2ZW50VG9GaXJzdFZpZGVvKCk7XG4gICAgICAgIH1cbiAgICB9XG5cblxuICAgIC8qIFByaXZhdGUgbWV0aG9kcyAqL1xuXG4gICAgcHJpdmF0ZSBzZXRQZXJtaXNzaW9uRGlhbG9nVGltZXIod2FpdFRpbWU6IG51bWJlcik6IHZvaWQge1xuICAgICAgICB0aGlzLnBlcm1pc3Npb25EaWFsb2dUaW1lb3V0ID0gc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgICAgICB0aGlzLmVtaXRFdmVudCgnYWNjZXNzRGlhbG9nT3BlbmVkJywgW10pO1xuICAgICAgICB9LCB3YWl0VGltZSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBjbGVhclBlcm1pc3Npb25EaWFsb2dUaW1lcihzdGFydFRpbWU6IG51bWJlciwgd2FpdFRpbWU6IG51bWJlcik6IHZvaWQge1xuICAgICAgICBjbGVhclRpbWVvdXQodGhpcy5wZXJtaXNzaW9uRGlhbG9nVGltZW91dCk7XG4gICAgICAgIGlmICgoRGF0ZS5ub3coKSAtIHN0YXJ0VGltZSkgPiB3YWl0VGltZSkge1xuICAgICAgICAgICAgLy8gUGVybWlzc2lvbiBkaWFsb2cgd2FzIHNob3duIGFuZCBub3cgaXMgY2xvc2VkXG4gICAgICAgICAgICB0aGlzLmVtaXRFdmVudCgnYWNjZXNzRGlhbG9nQ2xvc2VkJywgW10pO1xuICAgICAgICB9XG4gICAgfVxuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBDb25uZWN0aW9uIH0gZnJvbSAnLi9Db25uZWN0aW9uJztcbmltcG9ydCB7IE9wZW5WaWR1IH0gZnJvbSAnLi9PcGVuVmlkdSc7XG5pbXBvcnQgeyBQdWJsaXNoZXIgfSBmcm9tICcuL1B1Ymxpc2hlcic7XG5pbXBvcnQgeyBTdHJlYW0gfSBmcm9tICcuL1N0cmVhbSc7XG5pbXBvcnQgeyBTdHJlYW1NYW5hZ2VyIH0gZnJvbSAnLi9TdHJlYW1NYW5hZ2VyJztcbmltcG9ydCB7IFN1YnNjcmliZXIgfSBmcm9tICcuL1N1YnNjcmliZXInO1xuaW1wb3J0IHsgQ2FwYWJpbGl0aWVzIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9JbnRlcmZhY2VzL1B1YmxpYy9DYXBhYmlsaXRpZXMnO1xuaW1wb3J0IHsgRXZlbnREaXNwYXRjaGVyIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9JbnRlcmZhY2VzL1B1YmxpYy9FdmVudERpc3BhdGNoZXInO1xuaW1wb3J0IHsgU2lnbmFsT3B0aW9ucyB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvSW50ZXJmYWNlcy9QdWJsaWMvU2lnbmFsT3B0aW9ucyc7XG5pbXBvcnQgeyBTdWJzY3JpYmVyUHJvcGVydGllcyB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvSW50ZXJmYWNlcy9QdWJsaWMvU3Vic2NyaWJlclByb3BlcnRpZXMnO1xuaW1wb3J0IHsgQ29ubmVjdGlvbk9wdGlvbnMgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHJpdmF0ZS9Db25uZWN0aW9uT3B0aW9ucyc7XG5pbXBvcnQgeyBPYmpNYXAgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHJpdmF0ZS9PYmpNYXAnO1xuaW1wb3J0IHsgU2Vzc2lvbk9wdGlvbnMgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHJpdmF0ZS9TZXNzaW9uT3B0aW9ucyc7XG5pbXBvcnQgeyBDb25uZWN0aW9uRXZlbnQgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0V2ZW50cy9Db25uZWN0aW9uRXZlbnQnO1xuaW1wb3J0IHsgUHVibGlzaGVyU3BlYWtpbmdFdmVudCB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1B1Ymxpc2hlclNwZWFraW5nRXZlbnQnO1xuaW1wb3J0IHsgUmVjb3JkaW5nRXZlbnQgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0V2ZW50cy9SZWNvcmRpbmdFdmVudCc7XG5pbXBvcnQgeyBTZXNzaW9uRGlzY29ubmVjdGVkRXZlbnQgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0V2ZW50cy9TZXNzaW9uRGlzY29ubmVjdGVkRXZlbnQnO1xuaW1wb3J0IHsgU2lnbmFsRXZlbnQgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0V2ZW50cy9TaWduYWxFdmVudCc7XG5pbXBvcnQgeyBTdHJlYW1FdmVudCB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1N0cmVhbUV2ZW50JztcbmltcG9ydCB7IFN0cmVhbVByb3BlcnR5Q2hhbmdlZEV2ZW50IH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvU3RyZWFtUHJvcGVydHlDaGFuZ2VkRXZlbnQnO1xuaW1wb3J0IHsgT3BlblZpZHVFcnJvciwgT3BlblZpZHVFcnJvck5hbWUgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0VudW1zL09wZW5WaWR1RXJyb3InO1xuaW1wb3J0IHsgVmlkZW9JbnNlcnRNb2RlIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FbnVtcy9WaWRlb0luc2VydE1vZGUnO1xuXG5pbXBvcnQgcGxhdGZvcm0gPSByZXF1aXJlKCdwbGF0Zm9ybScpO1xuaW1wb3J0IEV2ZW50RW1pdHRlciA9IHJlcXVpcmUoJ3dvbGZ5ODctZXZlbnRlbWl0dGVyJyk7XG5cblxuLyoqXG4gKiBSZXByZXNlbnRzIGEgdmlkZW8gY2FsbC4gSXQgY2FuIGFsc28gYmUgc2VlbiBhcyBhIHZpZGVvY29uZmVyZW5jZSByb29tIHdoZXJlIG11bHRpcGxlIHVzZXJzIGNhbiBjb25uZWN0LlxuICogUGFydGljaXBhbnRzIHdobyBwdWJsaXNoIHRoZWlyIHZpZGVvcyB0byBhIHNlc3Npb24gY2FuIGJlIHNlZW4gYnkgdGhlIHJlc3Qgb2YgdXNlcnMgY29ubmVjdGVkIHRvIHRoYXQgc3BlY2lmaWMgc2Vzc2lvbi5cbiAqIEluaXRpYWxpemVkIHdpdGggW1tPcGVuVmlkdS5pbml0U2Vzc2lvbl1dIG1ldGhvZFxuICovXG5leHBvcnQgY2xhc3MgU2Vzc2lvbiBpbXBsZW1lbnRzIEV2ZW50RGlzcGF0Y2hlciB7XG5cbiAgICAvKipcbiAgICAgKiBMb2NhbCBjb25uZWN0aW9uIHRvIHRoZSBTZXNzaW9uLiBUaGlzIG9iamVjdCBpcyBkZWZpbmVkIG9ubHkgYWZ0ZXIgW1tTZXNzaW9uLmNvbm5lY3RdXSBoYXMgYmVlbiBzdWNjZXNzZnVsbHkgZXhlY3V0ZWQsIGFuZCBjYW4gYmUgcmV0cmlldmVkIHN1YnNjcmliaW5nIHRvIGBjb25uZWN0aW9uQ3JlYXRlZGAgZXZlbnRcbiAgICAgKi9cbiAgICBjb25uZWN0aW9uOiBDb25uZWN0aW9uO1xuXG4gICAgLyoqXG4gICAgICogVW5pcXVlIGlkZW50aWZpZXIgb2YgdGhlIFNlc3Npb25cbiAgICAgKi9cbiAgICBzZXNzaW9uSWQ6IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIENvbGxlY3Rpb24gb2YgYWxsIFN0cmVhbU1hbmFnZXJzIG9mIHRoaXMgU2Vzc2lvbiAoW1tQdWJsaXNoZXJdXSBhbmQgW1tTdWJzY3JpYmVyXV0pXG4gICAgICovXG4gICAgc3RyZWFtTWFuYWdlcnM6IFN0cmVhbU1hbmFnZXJbXSA9IFtdO1xuXG4gICAgLyoqXG4gICAgICogT2JqZWN0IGRlZmluaW5nIHRoZSBtZXRob2RzIHRoYXQgdGhlIGNsaWVudCBpcyBhYmxlIHRvIGNhbGwuIFRoZXNlIGFyZSBkZWZpbmVkIGJ5IHRoZSByb2xlIG9mIHRoZSB0b2tlbiB1c2VkIHRvIGNvbm5lY3QgdG8gdGhlIFNlc3Npb24uXG4gICAgICogVGhpcyBvYmplY3QgaXMgb25seSBkZWZpbmVkIGFmdGVyIFtbU2Vzc2lvbi5jb25uZWN0XV0gaGFzIGJlZW4gc3VjY2Vzc2Z1bGx5IHJlc29sdmVkXG4gICAgICovXG4gICAgY2FwYWJpbGl0aWVzOiBDYXBhYmlsaXRpZXM7XG5cbiAgICAvLyBUaGlzIG1hcCBpcyBvbmx5IHVzZWQgdG8gYXZvaWQgcmFjZSBjb25kaXRpb24gYmV0d2VlbiAnam9pblJvb20nIHJlc3BvbnNlIGFuZCAnb25QYXJ0aWNpcGFudFB1Ymxpc2hlZCcgbm90aWZpY2F0aW9uXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHJlbW90ZVN0cmVhbXNDcmVhdGVkOiBPYmpNYXA8Ym9vbGVhbj4gPSB7fTtcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICByZW1vdGVDb25uZWN0aW9uczogT2JqTWFwPENvbm5lY3Rpb24+ID0ge307XG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIG9wZW52aWR1OiBPcGVuVmlkdTtcbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgb3B0aW9uczogU2Vzc2lvbk9wdGlvbnM7XG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHNwZWFraW5nRXZlbnRzRW5hYmxlZCA9IGZhbHNlO1xuXG4gICAgcHJpdmF0ZSBlZSA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3RvcihvcGVudmlkdTogT3BlblZpZHUpIHtcbiAgICAgICAgdGhpcy5vcGVudmlkdSA9IG9wZW52aWR1O1xuICAgIH1cblxuICAgIGNvbm5lY3QodG9rZW46IHN0cmluZyk6IFByb21pc2U8YW55PjtcbiAgICBjb25uZWN0KHRva2VuOiBzdHJpbmcsIG1ldGFkYXRhOiBhbnkpOiBQcm9taXNlPGFueT47XG5cbiAgICAvKipcbiAgICAgKiBDb25uZWN0cyB0byB0aGUgc2Vzc2lvbiB1c2luZyBgdG9rZW5gLiBQYXJhbWV0ZXIgYG1ldGFkYXRhYCBhbGxvd3MgeW91IHRvIHBhc3MgZXh0cmEgZGF0YSB0byBzaGFyZSB3aXRoIG90aGVyIHVzZXJzIHdoZW5cbiAgICAgKiB0aGV5IHJlY2VpdmUgYHN0cmVhbUNyZWF0ZWRgIGV2ZW50LiBUaGUgc3RydWN0dXJlIG9mIGBtZXRhZGF0YWAgc3RyaW5nIGlzIHVwIHRvIHlvdSAobWF5YmUgc29tZSBzdGFuZGFyaXplZCBmb3JtYXRcbiAgICAgKiBhcyBKU09OIG9yIFhNTCBpcyBhIGdvb2QgaWRlYSksIHRoZSBvbmx5IHJlc3RyaWN0aW9uIGlzIGEgbWF4aW11bSBsZW5ndGggb2YgMTAwMDAgY2hhcnMuXG4gICAgICpcbiAgICAgKiBUaGlzIG1ldGFkYXRhIGlzIG5vdCBjb25zaWRlcmVkIHNlY3VyZSwgYXMgaXQgaXMgZ2VuZXJhdGVkIGluIHRoZSBjbGllbnQgc2lkZS4gVG8gcGFzcyBzZWN1cml6ZWQgZGF0YSwgYWRkIGl0IGFzIGEgcGFyYW1ldGVyIGluIHRoZVxuICAgICAqIHRva2VuIGdlbmVyYXRpb24gb3BlcmF0aW9uICh0aHJvdWdoIHRoZSBBUEkgUkVTVCwgb3BlbnZpZHUtamF2YS1jbGllbnQgb3Igb3BlbnZpZHUtbm9kZS1jbGllbnQpLlxuICAgICAqXG4gICAgICogT25seSBhZnRlciB0aGUgcmV0dXJuZWQgUHJvbWlzZSBpcyBzdWNjZXNzZnVsbHkgcmVzb2x2ZWQgW1tTZXNzaW9uLmNvbm5lY3Rpb25dXSBvYmplY3Qgd2lsbCBiZSBhdmFpbGFibGUgYW5kIHByb3Blcmx5IGRlZmluZWQuXG4gICAgICpcbiAgICAgKiAjIyMjIEV2ZW50cyBkaXNwYXRjaGVkXG4gICAgICpcbiAgICAgKiBUaGUgW1tTZXNzaW9uXV0gb2JqZWN0IG9mIHRoZSBsb2NhbCBwYXJ0aWNpcGFudCB3aWxsIGZpcnN0IGRpc3BhdGNoIG9uZSBvciBtb3JlIGBjb25uZWN0aW9uQ3JlYXRlZGAgZXZlbnRzIHVwb24gc3VjY2Vzc2Z1bCB0ZXJtaW5hdGlvbiBvZiB0aGlzIG1ldGhvZDpcbiAgICAgKiAtIEZpcnN0IG9uZSBmb3IgeW91ciBvd24gbG9jYWwgQ29ubmVjdGlvbiBvYmplY3QsIHNvIHlvdSBjYW4gcmV0cmlldmUgW1tTZXNzaW9uLmNvbm5lY3Rpb25dXSBwcm9wZXJ0eS5cbiAgICAgKiAtIFRoZW4gb25lIGZvciBlYWNoIHJlbW90ZSBDb25uZWN0aW9uIHByZXZpb3VzbHkgY29ubmVjdGVkIHRvIHRoZSBTZXNzaW9uLCBpZiBhbnkuIEFueSBvdGhlciByZW1vdGUgdXNlciBjb25uZWN0aW5nIHRvIHRoZSBTZXNzaW9uIGFmdGVyIHlvdSBoYXZlXG4gICAgICogc3VjY2Vzc2Z1bGx5IGNvbm5lY3RlZCB3aWxsIGFsc28gZGlzcGF0Y2ggYSBgY29ubmVjdGlvbkNyZWF0ZWRgIGV2ZW50IHdoZW4gdGhleSBkbyBzby5cbiAgICAgKlxuICAgICAqIFRoZSBbW1Nlc3Npb25dXSBvYmplY3Qgb2YgdGhlIGxvY2FsIHBhcnRpY2lwYW50IHdpbGwgYWxzbyBkaXNwYXRjaCBhIGBzdHJlYW1DcmVhdGVkYCBldmVudCBmb3IgZWFjaCByZW1vdGUgYWN0aXZlIFtbUHVibGlzaGVyXV0gdGhhdCB3YXMgYWxyZWFkeSBzdHJlYW1pbmdcbiAgICAgKiB3aGVuIGNvbm5lY3RpbmcsIGp1c3QgYWZ0ZXIgZGlzcGF0Y2hpbmcgYWxsIHJlbW90ZSBgY29ubmVjdGlvbkNyZWF0ZWRgIGV2ZW50cy5cbiAgICAgKlxuICAgICAqIFRoZSBbW1Nlc3Npb25dXSBvYmplY3Qgb2YgZXZlcnkgb3RoZXIgcGFydGljaXBhbnQgY29ubmVjdGVkIHRvIHRoZSBzZXNzaW9uIHdpbGwgZGlzcGF0Y2ggYSBgY29ubmVjdGlvbkNyZWF0ZWRgIGV2ZW50LlxuICAgICAqXG4gICAgICogU2VlIFtbQ29ubmVjdGlvbkV2ZW50XV0gYW5kIFtbU3RyZWFtRXZlbnRdXSB0byBsZWFybiBtb3JlLlxuICAgICAqXG4gICAgICogQHJldHVybnMgQSBQcm9taXNlIHRvIHdoaWNoIHlvdSBtdXN0IHN1YnNjcmliZSB0aGF0IGlzIHJlc29sdmVkIGlmIHRoZSB0aGUgY29ubmVjdGlvbiB0byB0aGUgU2Vzc2lvbiB3YXMgc3VjY2Vzc2Z1bCBhbmQgcmVqZWN0ZWQgd2l0aCBhbiBFcnJvciBvYmplY3QgaWYgbm90XG4gICAgICpcbiAgICAgKi9cbiAgICBjb25uZWN0KHRva2VuOiBzdHJpbmcsIG1ldGFkYXRhPzogYW55KTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcblxuICAgICAgICAgICAgdGhpcy5wcm9jZXNzVG9rZW4odG9rZW4pO1xuXG4gICAgICAgICAgICBpZiAodGhpcy5vcGVudmlkdS5jaGVja1N5c3RlbVJlcXVpcmVtZW50cygpKSB7XG4gICAgICAgICAgICAgICAgLy8gRWFybHkgY29uZmlndXJhdGlvbiB0byBkZWFjdGl2YXRlIGF1dG9tYXRpYyBzdWJzY3JpcHRpb24gdG8gc3RyZWFtc1xuICAgICAgICAgICAgICAgIHRoaXMub3B0aW9ucyA9IHtcbiAgICAgICAgICAgICAgICAgICAgc2Vzc2lvbklkOiB0aGlzLnNlc3Npb25JZCxcbiAgICAgICAgICAgICAgICAgICAgcGFydGljaXBhbnRJZDogdG9rZW4sXG4gICAgICAgICAgICAgICAgICAgIG1ldGFkYXRhOiAhIW1ldGFkYXRhID8gdGhpcy5zdHJpbmdDbGllbnRNZXRhZGF0YShtZXRhZGF0YSkgOiAnJ1xuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgdGhpcy5jb25uZWN0QXV4KHRva2VuKS50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgICAgICAgIH0pLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmVqZWN0KG5ldyBPcGVuVmlkdUVycm9yKE9wZW5WaWR1RXJyb3JOYW1lLkJST1dTRVJfTk9UX1NVUFBPUlRFRCwgJ0Jyb3dzZXIgJyArIHBsYXRmb3JtLm5hbWUgKyAnICcgKyBwbGF0Zm9ybS52ZXJzaW9uICsgJyBpcyBub3Qgc3VwcG9ydGVkIGluIE9wZW5WaWR1JykpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBMZWF2ZXMgdGhlIHNlc3Npb24sIGRlc3Ryb3lpbmcgYWxsIHN0cmVhbXMgYW5kIGRlbGV0aW5nIHRoZSB1c2VyIGFzIGEgcGFydGljaXBhbnQuXG4gICAgICpcbiAgICAgKiAjIyMjIEV2ZW50cyBkaXNwYXRjaGVkXG4gICAgICpcbiAgICAgKiBUaGUgW1tTZXNzaW9uXV0gb2JqZWN0IG9mIHRoZSBsb2NhbCBwYXJ0aWNpcGFudCB3aWxsIGRpc3BhdGNoIGEgYHNlc3Npb25EaXNjb25uZWN0ZWRgIGV2ZW50LlxuICAgICAqIFRoaXMgZXZlbnQgd2lsbCBhdXRvbWF0aWNhbGx5IHVuc3Vic2NyaWJlIHRoZSBsZWF2aW5nIHBhcnRpY2lwYW50IGZyb20gZXZlcnkgU3Vic2NyaWJlciBvYmplY3Qgb2YgdGhlIHNlc3Npb24gKHRoaXMgaW5jbHVkZXMgY2xvc2luZyB0aGUgV2ViUlRDUGVlciBjb25uZWN0aW9uIGFuZCBkaXNwb3NpbmcgYWxsIE1lZGlhU3RyZWFtVHJhY2tzKVxuICAgICAqIGFuZCBhbHNvIGRlbGV0ZXMgYW55IEhUTUwgdmlkZW8gZWxlbWVudCBhc3NvY2lhdGVkIHRvIGVhY2ggU3Vic2NyaWJlciAob25seSB0aG9zZSBbY3JlYXRlZCBieSBPcGVuVmlkdSBCcm93c2VyXSgvZG9jcy9ob3ctZG8taS9tYW5hZ2UtdmlkZW9zLyNsZXQtb3BlbnZpZHUtdGFrZS1jYXJlLW9mLXRoZS12aWRlby1wbGF5ZXJzKSkuXG4gICAgICogRm9yIGV2ZXJ5IHZpZGVvIHJlbW92ZWQsIGVhY2ggU3Vic2NyaWJlciBvYmplY3Qgd2lsbCBkaXNwYXRjaCBhIGB2aWRlb0VsZW1lbnREZXN0cm95ZWRgIGV2ZW50LlxuICAgICAqIENhbGwgYGV2ZW50LnByZXZlbnREZWZhdWx0KClgIHVwb24gZXZlbnQgYHNlc3Npb25EaXNjb25uZWN0ZWRgIHRvIGF2b2lkIHRoaXMgYmVoYXZpb3IgYW5kIHRha2UgY2FyZSBvZiBkaXNwb3NpbmcgYW5kIGNsZWFuaW5nIGFsbCB0aGUgU3Vic2NyaWJlciBvYmplY3RzIHlvdXJzZWxmLlxuICAgICAqIFNlZSBbW1Nlc3Npb25EaXNjb25uZWN0ZWRFdmVudF1dIGFuZCBbW1ZpZGVvRWxlbWVudEV2ZW50XV0gdG8gbGVhcm4gbW9yZSB0byBsZWFybiBtb3JlLlxuICAgICAqXG4gICAgICogVGhlIFtbUHVibGlzaGVyXV0gb2JqZWN0IG9mIHRoZSBsb2NhbCBwYXJ0aWNpcGFudCB3aWxsIGRpc3BhdGNoIGEgYHN0cmVhbURlc3Ryb3llZGAgZXZlbnQgaWYgdGhlcmUgaXMgYSBbW1B1Ymxpc2hlcl1dIG9iamVjdCBwdWJsaXNoaW5nIHRvIHRoZSBzZXNzaW9uLlxuICAgICAqIFRoaXMgZXZlbnQgd2lsbCBhdXRvbWF0aWNhbGx5IHN0b3AgYWxsIG1lZGlhIHRyYWNrcyBhbmQgZGVsZXRlIGFueSBIVE1MIHZpZGVvIGVsZW1lbnQgYXNzb2NpYXRlZCB0byBpdCAob25seSB0aG9zZSBbY3JlYXRlZCBieSBPcGVuVmlkdSBCcm93c2VyXSgvZG9jcy9ob3ctZG8taS9tYW5hZ2UtdmlkZW9zLyNsZXQtb3BlbnZpZHUtdGFrZS1jYXJlLW9mLXRoZS12aWRlby1wbGF5ZXJzKSkuXG4gICAgICogRm9yIGV2ZXJ5IHZpZGVvIHJlbW92ZWQsIHRoZSBQdWJsaXNoZXIgb2JqZWN0IHdpbGwgZGlzcGF0Y2ggYSBgdmlkZW9FbGVtZW50RGVzdHJveWVkYCBldmVudC5cbiAgICAgKiBDYWxsIGBldmVudC5wcmV2ZW50RGVmYXVsdCgpYCB1cG9uIGV2ZW50IGBzdHJlYW1EZXN0cm95ZWRgIGlmIHlvdSB3YW50IHRvIGNsZWFuIHRoZSBQdWJsaXNoZXIgb2JqZWN0IG9uIHlvdXIgb3duIG9yIHJlLXB1Ymxpc2ggaXQgaW4gYSBkaWZmZXJlbnQgU2Vzc2lvbiAodG8gZG8gc28gaXQgaXMgYSBtYW5kYXRvcnkgcmVxdWlyZW1lbnQgdG8gY2FsbCBgU2Vzc2lvbi51bnB1Ymxpc2goKWBcbiAgICAgKiBvci9hbmQgYFNlc3Npb24uZGlzY29ubmVjdCgpYCBpbiB0aGUgcHJldmlvdXMgc2Vzc2lvbikuIFNlZSBbW1N0cmVhbUV2ZW50XV0gYW5kIFtbVmlkZW9FbGVtZW50RXZlbnRdXSB0byBsZWFybiBtb3JlLlxuICAgICAqXG4gICAgICogVGhlIFtbU2Vzc2lvbl1dIG9iamVjdCBvZiBldmVyeSBvdGhlciBwYXJ0aWNpcGFudCBjb25uZWN0ZWQgdG8gdGhlIHNlc3Npb24gd2lsbCBkaXNwYXRjaCBhIGBzdHJlYW1EZXN0cm95ZWRgIGV2ZW50IGlmIHRoZSBkaXNjb25uZWN0ZWQgcGFydGljaXBhbnQgd2FzIHB1Ymxpc2hpbmcuXG4gICAgICogVGhpcyBldmVudCB3aWxsIGF1dG9tYXRpY2FsbHkgdW5zdWJzY3JpYmUgdGhlIFN1YnNjcmliZXIgb2JqZWN0IGZyb20gdGhlIHNlc3Npb24gKHRoaXMgaW5jbHVkZXMgY2xvc2luZyB0aGUgV2ViUlRDUGVlciBjb25uZWN0aW9uIGFuZCBkaXNwb3NpbmcgYWxsIE1lZGlhU3RyZWFtVHJhY2tzKVxuICAgICAqIGFuZCBhbHNvIGRlbGV0ZXMgYW55IEhUTUwgdmlkZW8gZWxlbWVudCBhc3NvY2lhdGVkIHRvIHRoYXQgU3Vic2NyaWJlciAob25seSB0aG9zZSBbY3JlYXRlZCBieSBPcGVuVmlkdSBCcm93c2VyXSgvZG9jcy9ob3ctZG8taS9tYW5hZ2UtdmlkZW9zLyNsZXQtb3BlbnZpZHUtdGFrZS1jYXJlLW9mLXRoZS12aWRlby1wbGF5ZXJzKSkuXG4gICAgICogRm9yIGV2ZXJ5IHZpZGVvIHJlbW92ZWQsIHRoZSBTdWJzY3JpYmVyIG9iamVjdCB3aWxsIGRpc3BhdGNoIGEgYHZpZGVvRWxlbWVudERlc3Ryb3llZGAgZXZlbnQuXG4gICAgICogQ2FsbCBgZXZlbnQucHJldmVudERlZmF1bHQoKWAgdXBvbiBldmVudCBgc3RyZWFtRGVzdHJveWVkYCB0byBhdm9pZCB0aGlzIGRlZmF1bHQgYmVoYXZpb3IgYW5kIHRha2UgY2FyZSBvZiBkaXNwb3NpbmcgYW5kIGNsZWFuaW5nIHRoZSBTdWJzY3JpYmVyIG9iamVjdCB5b3Vyc2VsZi5cbiAgICAgKiBTZWUgW1tTdHJlYW1FdmVudF1dIGFuZCBbW1ZpZGVvRWxlbWVudEV2ZW50XV0gdG8gbGVhcm4gbW9yZS5cbiAgICAgKlxuICAgICAqIFRoZSBbW1Nlc3Npb25dXSBvYmplY3Qgb2YgZXZlcnkgb3RoZXIgcGFydGljaXBhbnQgY29ubmVjdGVkIHRvIHRoZSBzZXNzaW9uIHdpbGwgZGlzcGF0Y2ggYSBgY29ubmVjdGlvbkRlc3Ryb3llZGAgZXZlbnQgaW4gYW55IGNhc2UuIFNlZSBbW0Nvbm5lY3Rpb25FdmVudF1dIHRvIGxlYXJuIG1vcmUuXG4gICAgICovXG4gICAgZGlzY29ubmVjdCgpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5sZWF2ZShmYWxzZSwgJ2Rpc2Nvbm5lY3QnKTtcbiAgICB9XG5cbiAgICBzdWJzY3JpYmUoc3RyZWFtOiBTdHJlYW0sIHRhcmdldEVsZW1lbnQ6IHN0cmluZyB8IEhUTUxFbGVtZW50KTogU3Vic2NyaWJlcjtcbiAgICBzdWJzY3JpYmUoc3RyZWFtOiBTdHJlYW0sIHRhcmdldEVsZW1lbnQ6IHN0cmluZyB8IEhUTUxFbGVtZW50LCBwcm9wZXJ0aWVzOiBTdWJzY3JpYmVyUHJvcGVydGllcyk6IFN1YnNjcmliZXI7XG4gICAgc3Vic2NyaWJlKHN0cmVhbTogU3RyZWFtLCB0YXJnZXRFbGVtZW50OiBzdHJpbmcgfCBIVE1MRWxlbWVudCwgY29tcGxldGlvbkhhbmRsZXI6IChlcnJvcjogRXJyb3IgfCB1bmRlZmluZWQpID0+IHZvaWQpOiBTdWJzY3JpYmVyO1xuICAgIHN1YnNjcmliZShzdHJlYW06IFN0cmVhbSwgdGFyZ2V0RWxlbWVudDogc3RyaW5nIHwgSFRNTEVsZW1lbnQsIHByb3BlcnRpZXM6IFN1YnNjcmliZXJQcm9wZXJ0aWVzLCBjb21wbGV0aW9uSGFuZGxlcjogKGVycm9yOiBFcnJvciB8IHVuZGVmaW5lZCkgPT4gdm9pZCk6IFN1YnNjcmliZXI7XG5cbiAgICAvKipcbiAgICAgKiBTdWJzY3JpYmVzIHRvIGEgYHN0cmVhbWAsIGFkZGluZyBhIG5ldyBIVE1MIHZpZGVvIGVsZW1lbnQgdG8gRE9NIHdpdGggYHN1YnNjcmliZXJQcm9wZXJ0aWVzYCBzZXR0aW5ncy4gVGhpcyBtZXRob2QgaXMgdXN1YWxseSBjYWxsZWQgaW4gdGhlIGNhbGxiYWNrIG9mIGBzdHJlYW1DcmVhdGVkYCBldmVudC5cbiAgICAgKlxuICAgICAqICMjIyMgRXZlbnRzIGRpc3BhdGNoZWRcbiAgICAgKlxuICAgICAqIFRoZSBbW1N1YnNjcmliZXJdXSBvYmplY3Qgd2lsbCBkaXNwYXRjaCBhIGB2aWRlb0VsZW1lbnRDcmVhdGVkYCBldmVudCBvbmNlIHRoZSBIVE1MIHZpZGVvIGVsZW1lbnQgaGFzIGJlZW4gYWRkZWQgdG8gRE9NIChvbmx5IGlmIHlvdVxuICAgICAqIFtsZXQgT3BlblZpZHUgdGFrZSBjYXJlIG9mIHRoZSB2aWRlbyBwbGF5ZXJzXSgvZG9jcy9ob3ctZG8taS9tYW5hZ2UtdmlkZW9zLyNsZXQtb3BlbnZpZHUtdGFrZS1jYXJlLW9mLXRoZS12aWRlby1wbGF5ZXJzKSkuIFNlZSBbW1ZpZGVvRWxlbWVudEV2ZW50XV0gdG8gbGVhcm4gbW9yZS5cbiAgICAgKlxuICAgICAqIFRoZSBbW1N1YnNjcmliZXJdXSBvYmplY3Qgd2lsbCBkaXNwYXRjaCBhIGBzdHJlYW1QbGF5aW5nYCBldmVudCBvbmNlIHRoZSByZW1vdGUgc3RyZWFtIHN0YXJ0cyBwbGF5aW5nLiBTZWUgW1tTdHJlYW1NYW5hZ2VyRXZlbnRdXSB0byBsZWFybiBtb3JlLlxuICAgICAqXG4gICAgICogQHBhcmFtIHN0cmVhbSBTdHJlYW0gb2JqZWN0IHRvIHN1YnNjcmliZSB0b1xuICAgICAqIEBwYXJhbSB0YXJnZXRFbGVtZW50IEhUTUwgRE9NIGVsZW1lbnQgKG9yIGl0cyBgaWRgIGF0dHJpYnV0ZSkgaW4gd2hpY2ggdGhlIHZpZGVvIGVsZW1lbnQgb2YgdGhlIFN1YnNjcmliZXIgd2lsbCBiZSBpbnNlcnRlZCAoc2VlIFtbU3Vic2NyaWJlclByb3BlcnRpZXMuaW5zZXJ0TW9kZV1dKS4gSWYgKm51bGwqIG9yICp1bmRlZmluZWQqIG5vIGRlZmF1bHQgdmlkZW8gd2lsbCBiZSBjcmVhdGVkIGZvciB0aGlzIFN1YnNjcmliZXIuXG4gICAgICogWW91IGNhbiBhbHdheXMgY2FsbCBtZXRob2QgW1tTdWJzY3JpYmVyLmFkZFZpZGVvRWxlbWVudF1dIG9yIFtbU3Vic2NyaWJlci5jcmVhdGVWaWRlb0VsZW1lbnRdXSB0byBtYW5hZ2UgdGhlIHZpZGVvIGVsZW1lbnRzIG9uIHlvdXIgb3duIChzZWUgW01hbmFnZSB2aWRlbyBwbGF5ZXJzXSgvZG9jcy9ob3ctZG8taS9tYW5hZ2UtdmlkZW9zKSBzZWN0aW9uKVxuICAgICAqIEBwYXJhbSBjb21wbGV0aW9uSGFuZGxlciBgZXJyb3JgIHBhcmFtZXRlciBpcyBudWxsIGlmIGBzdWJzY3JpYmVgIHN1Y2NlZWRzLCBhbmQgaXMgZGVmaW5lZCBpZiBpdCBmYWlscy5cbiAgICAgKi9cbiAgICBzdWJzY3JpYmUoc3RyZWFtOiBTdHJlYW0sIHRhcmdldEVsZW1lbnQ6IHN0cmluZyB8IEhUTUxFbGVtZW50LCBwYXJhbTM/OiAoKGVycm9yOiBFcnJvciB8IHVuZGVmaW5lZCkgPT4gdm9pZCkgfCBTdWJzY3JpYmVyUHJvcGVydGllcywgcGFyYW00PzogKChlcnJvcjogRXJyb3IgfCB1bmRlZmluZWQpID0+IHZvaWQpKTogU3Vic2NyaWJlciB7XG4gICAgICAgIGxldCBwcm9wZXJ0aWVzOiBTdWJzY3JpYmVyUHJvcGVydGllcyA9IHt9O1xuICAgICAgICBpZiAoISFwYXJhbTMgJiYgdHlwZW9mIHBhcmFtMyAhPT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgcHJvcGVydGllcyA9IHtcbiAgICAgICAgICAgICAgICBpbnNlcnRNb2RlOiAodHlwZW9mIHBhcmFtMy5pbnNlcnRNb2RlICE9PSAndW5kZWZpbmVkJykgPyAoKHR5cGVvZiBwYXJhbTMuaW5zZXJ0TW9kZSA9PT0gJ3N0cmluZycpID8gVmlkZW9JbnNlcnRNb2RlW3BhcmFtMy5pbnNlcnRNb2RlXSA6IHByb3BlcnRpZXMuaW5zZXJ0TW9kZSkgOiBWaWRlb0luc2VydE1vZGUuQVBQRU5ELFxuICAgICAgICAgICAgICAgIHN1YnNjcmliZVRvQXVkaW86ICh0eXBlb2YgcGFyYW0zLnN1YnNjcmliZVRvQXVkaW8gIT09ICd1bmRlZmluZWQnKSA/IHBhcmFtMy5zdWJzY3JpYmVUb0F1ZGlvIDogdHJ1ZSxcbiAgICAgICAgICAgICAgICBzdWJzY3JpYmVUb1ZpZGVvOiAodHlwZW9mIHBhcmFtMy5zdWJzY3JpYmVUb1ZpZGVvICE9PSAndW5kZWZpbmVkJykgPyBwYXJhbTMuc3Vic2NyaWJlVG9WaWRlbyA6IHRydWVcbiAgICAgICAgICAgIH07XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBwcm9wZXJ0aWVzID0ge1xuICAgICAgICAgICAgICAgIGluc2VydE1vZGU6IFZpZGVvSW5zZXJ0TW9kZS5BUFBFTkQsXG4gICAgICAgICAgICAgICAgc3Vic2NyaWJlVG9BdWRpbzogdHJ1ZSxcbiAgICAgICAgICAgICAgICBzdWJzY3JpYmVUb1ZpZGVvOiB0cnVlXG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG5cbiAgICAgICAgbGV0IGNvbXBsZXRpb25IYW5kbGVyOiAoZXJyb3I6IEVycm9yIHwgdW5kZWZpbmVkKSA9PiB2b2lkO1xuICAgICAgICBpZiAoISFwYXJhbTMgJiYgKHR5cGVvZiBwYXJhbTMgPT09ICdmdW5jdGlvbicpKSB7XG4gICAgICAgICAgICBjb21wbGV0aW9uSGFuZGxlciA9IHBhcmFtMztcbiAgICAgICAgfSBlbHNlIGlmICghIXBhcmFtNCkge1xuICAgICAgICAgICAgY29tcGxldGlvbkhhbmRsZXIgPSBwYXJhbTQ7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zb2xlLmluZm8oJ1N1YnNjcmliaW5nIHRvICcgKyBzdHJlYW0uY29ubmVjdGlvbi5jb25uZWN0aW9uSWQpO1xuXG4gICAgICAgIHN0cmVhbS5zdWJzY3JpYmUoKVxuICAgICAgICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbygnU3Vic2NyaWJlZCBjb3JyZWN0bHkgdG8gJyArIHN0cmVhbS5jb25uZWN0aW9uLmNvbm5lY3Rpb25JZCk7XG4gICAgICAgICAgICAgICAgaWYgKGNvbXBsZXRpb25IYW5kbGVyICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgY29tcGxldGlvbkhhbmRsZXIodW5kZWZpbmVkKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICAgICAgICBpZiAoY29tcGxldGlvbkhhbmRsZXIgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICBjb21wbGV0aW9uSGFuZGxlcihlcnJvcik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIGNvbnN0IHN1YnNjcmliZXIgPSBuZXcgU3Vic2NyaWJlcihzdHJlYW0sIHRhcmdldEVsZW1lbnQsIHByb3BlcnRpZXMpO1xuICAgICAgICBpZiAoISFzdWJzY3JpYmVyLnRhcmdldEVsZW1lbnQpIHtcbiAgICAgICAgICAgIHN0cmVhbS5zdHJlYW1NYW5hZ2VyLmNyZWF0ZVZpZGVvRWxlbWVudChzdWJzY3JpYmVyLnRhcmdldEVsZW1lbnQsIDxWaWRlb0luc2VydE1vZGU+cHJvcGVydGllcy5pbnNlcnRNb2RlKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gc3Vic2NyaWJlcjtcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFByb21pc2lmaWVkIHZlcnNpb24gb2YgW1tTZXNzaW9uLnN1YnNjcmliZV1dXG4gICAgICovXG4gICAgc3Vic2NyaWJlQXN5bmMoc3RyZWFtOiBTdHJlYW0sIHRhcmdldEVsZW1lbnQ6IHN0cmluZyB8IEhUTUxFbGVtZW50KTogUHJvbWlzZTxTdWJzY3JpYmVyPjtcbiAgICBzdWJzY3JpYmVBc3luYyhzdHJlYW06IFN0cmVhbSwgdGFyZ2V0RWxlbWVudDogc3RyaW5nIHwgSFRNTEVsZW1lbnQsIHByb3BlcnRpZXM6IFN1YnNjcmliZXJQcm9wZXJ0aWVzKTogUHJvbWlzZTxTdWJzY3JpYmVyPjtcblxuICAgIHN1YnNjcmliZUFzeW5jKHN0cmVhbTogU3RyZWFtLCB0YXJnZXRFbGVtZW50OiBzdHJpbmcgfCBIVE1MRWxlbWVudCwgcHJvcGVydGllcz86IFN1YnNjcmliZXJQcm9wZXJ0aWVzKTogUHJvbWlzZTxTdWJzY3JpYmVyPiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZTxTdWJzY3JpYmVyPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG5cbiAgICAgICAgICAgIGxldCBzdWJzY3JpYmVyOiBTdWJzY3JpYmVyO1xuXG4gICAgICAgICAgICBjb25zdCBjYWxsYmFjayA9IChlcnJvcjogRXJyb3IpID0+IHtcbiAgICAgICAgICAgICAgICBpZiAoISFlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc29sdmUoc3Vic2NyaWJlcik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgaWYgKCEhcHJvcGVydGllcykge1xuICAgICAgICAgICAgICAgIHN1YnNjcmliZXIgPSB0aGlzLnN1YnNjcmliZShzdHJlYW0sIHRhcmdldEVsZW1lbnQsIHByb3BlcnRpZXMsIGNhbGxiYWNrKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgc3Vic2NyaWJlciA9IHRoaXMuc3Vic2NyaWJlKHN0cmVhbSwgdGFyZ2V0RWxlbWVudCwgY2FsbGJhY2spO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgIH0pO1xuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogVW5zdWJzY3JpYmVzIGZyb20gYHN1YnNjcmliZXJgLCBhdXRvbWF0aWNhbGx5IHJlbW92aW5nIGl0cyBhc3NvY2lhdGVkIEhUTUwgdmlkZW8gZWxlbWVudHMuXG4gICAgICpcbiAgICAgKiAjIyMjIEV2ZW50cyBkaXNwYXRjaGVkXG4gICAgICpcbiAgICAgKiBUaGUgW1tTdWJzY3JpYmVyXV0gb2JqZWN0IHdpbGwgZGlzcGF0Y2ggYSBgdmlkZW9FbGVtZW50RGVzdHJveWVkYCBldmVudCBmb3IgZWFjaCB2aWRlbyBhc3NvY2lhdGVkIHRvIGl0IHRoYXQgd2FzIHJlbW92ZWQgZnJvbSBET00uXG4gICAgICogT25seSB2aWRlb3MgW2NyZWF0ZWQgYnkgT3BlblZpZHUgQnJvd3Nlcl0oL2RvY3MvaG93LWRvLWkvbWFuYWdlLXZpZGVvcy8jbGV0LW9wZW52aWR1LXRha2UtY2FyZS1vZi10aGUtdmlkZW8tcGxheWVycykpIHdpbGwgYmUgYXV0b21hdGljYWxseSByZW1vdmVkXG4gICAgICpcbiAgICAgKiBTZWUgW1tWaWRlb0VsZW1lbnRFdmVudF1dIHRvIGxlYXJuIG1vcmVcbiAgICAgKi9cbiAgICB1bnN1YnNjcmliZShzdWJzY3JpYmVyOiBTdWJzY3JpYmVyKTogdm9pZCB7XG4gICAgICAgIGNvbnN0IGNvbm5lY3Rpb25JZCA9IHN1YnNjcmliZXIuc3RyZWFtLmNvbm5lY3Rpb24uY29ubmVjdGlvbklkO1xuXG4gICAgICAgIGNvbnNvbGUuaW5mbygnVW5zdWJzY3JpYmluZyBmcm9tICcgKyBjb25uZWN0aW9uSWQpO1xuXG4gICAgICAgIHRoaXMub3BlbnZpZHUuc2VuZFJlcXVlc3QoXG4gICAgICAgICAgICAndW5zdWJzY3JpYmVGcm9tVmlkZW8nLFxuICAgICAgICAgICAgeyBzZW5kZXI6IHN1YnNjcmliZXIuc3RyZWFtLmNvbm5lY3Rpb24uY29ubmVjdGlvbklkIH0sXG4gICAgICAgICAgICAoZXJyb3IsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ0Vycm9yIHVuc3Vic2NyaWJpbmcgZnJvbSAnICsgY29ubmVjdGlvbklkLCBlcnJvcik7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS5pbmZvKCdVbnN1YnNjcmliZWQgY29ycmVjdGx5IGZyb20gJyArIGNvbm5lY3Rpb25JZCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHN1YnNjcmliZXIuc3RyZWFtLmRpc3Bvc2VXZWJSdGNQZWVyKCk7XG4gICAgICAgICAgICAgICAgc3Vic2NyaWJlci5zdHJlYW0uZGlzcG9zZU1lZGlhU3RyZWFtKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICk7XG4gICAgICAgIHN1YnNjcmliZXIuc3RyZWFtLnN0cmVhbU1hbmFnZXIucmVtb3ZlQWxsVmlkZW9zKCk7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBQdWJsaXNoZXMgdG8gdGhlIFNlc3Npb24gdGhlIFB1Ymxpc2hlciBvYmplY3RcbiAgICAgKlxuICAgICAqICMjIyMgRXZlbnRzIGRpc3BhdGNoZWRcbiAgICAgKlxuICAgICAqIFRoZSBsb2NhbCBbW1B1Ymxpc2hlcl1dIG9iamVjdCB3aWxsIGRpc3BhdGNoIGEgYHN0cmVhbUNyZWF0ZWRgIGV2ZW50IHVwb24gc3VjY2Vzc2Z1bCB0ZXJtaW5hdGlvbiBvZiB0aGlzIG1ldGhvZC4gU2VlIFtbU3RyZWFtRXZlbnRdXSB0byBsZWFybiBtb3JlLlxuICAgICAqXG4gICAgICogVGhlIGxvY2FsIFtbUHVibGlzaGVyXV0gb2JqZWN0IHdpbGwgZGlzcGF0Y2ggYSBgc3RyZWFtUGxheWluZ2Agb25jZSB0aGUgbWVkaWEgc3RyZWFtIHN0YXJ0cyBwbGF5aW5nLiBTZWUgW1tTdHJlYW1NYW5hZ2VyRXZlbnRdXSB0byBsZWFybiBtb3JlLlxuICAgICAqXG4gICAgICogVGhlIFtbU2Vzc2lvbl1dIG9iamVjdCBvZiBldmVyeSBvdGhlciBwYXJ0aWNpcGFudCBjb25uZWN0ZWQgdG8gdGhlIHNlc3Npb24gd2lsbCBkaXNwYXRjaCBhIGBzdHJlYW1DcmVhdGVkYCBldmVudCBzbyB0aGV5IGNhbiBzdWJzY3JpYmUgdG8gaXQuIFNlZSBbW1N0cmVhbUV2ZW50XV0gdG8gbGVhcm4gbW9yZS5cbiAgICAgKlxuICAgICAqIEByZXR1cm5zIEEgUHJvbWlzZSAodG8gd2hpY2ggeW91IGNhbiBvcHRpb25hbGx5IHN1YnNjcmliZSB0bykgdGhhdCBpcyByZXNvbHZlZCBvbmx5IGFmdGVyIHRoZSBwdWJsaXNoZXIgd2FzIHN1Y2Nlc3NmdWxseSBwdWJsaXNoZWQgYW5kIHJlamVjdGVkIHdpdGggYW4gRXJyb3Igb2JqZWN0IGlmIG5vdFxuICAgICAqL1xuICAgIHB1Ymxpc2gocHVibGlzaGVyOiBQdWJsaXNoZXIpOiBQcm9taXNlPGFueT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgcHVibGlzaGVyLnNlc3Npb24gPSB0aGlzO1xuICAgICAgICAgICAgcHVibGlzaGVyLnN0cmVhbS5zZXNzaW9uID0gdGhpcztcblxuICAgICAgICAgICAgaWYgKCFwdWJsaXNoZXIuc3RyZWFtLnB1Ymxpc2hlZE9uY2UpIHtcbiAgICAgICAgICAgICAgICAvLyAnU2Vzc2lvbi51bnB1Ymxpc2goUHVibGlzaGVyKScgaGFzIE5PVCBiZWVuIGNhbGxlZFxuICAgICAgICAgICAgICAgIHRoaXMuY29ubmVjdGlvbi5hZGRTdHJlYW0ocHVibGlzaGVyLnN0cmVhbSk7XG4gICAgICAgICAgICAgICAgcHVibGlzaGVyLnN0cmVhbS5wdWJsaXNoKClcbiAgICAgICAgICAgICAgICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIC8vICdTZXNzaW9uLnVucHVibGlzaChQdWJsaXNoZXIpJyBoYXMgYmVlbiBjYWxsZWQuIE11c3QgaW5pdGlhbGl6ZSBhZ2FpbiBQdWJsaXNoZXJcbiAgICAgICAgICAgICAgICBwdWJsaXNoZXIuaW5pdGlhbGl6ZSgpXG4gICAgICAgICAgICAgICAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY29ubmVjdGlvbi5hZGRTdHJlYW0ocHVibGlzaGVyLnN0cmVhbSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBwdWJsaXNoZXIucmVlc3RhYmxpc2hTdHJlYW1QbGF5aW5nRXZlbnQoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHB1Ymxpc2hlci5zdHJlYW0ucHVibGlzaCgpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICB9KS5jYXRjaCgoZXJyb3IpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFVucHVibGlzaGVzIGZyb20gdGhlIFNlc3Npb24gdGhlIFB1Ymxpc2hlciBvYmplY3QuXG4gICAgICpcbiAgICAgKiAjIyMjIEV2ZW50cyBkaXNwYXRjaGVkXG4gICAgICpcbiAgICAgKiBUaGUgW1tQdWJsaXNoZXJdXSBvYmplY3Qgb2YgdGhlIGxvY2FsIHBhcnRpY2lwYW50IHdpbGwgZGlzcGF0Y2ggYSBgc3RyZWFtRGVzdHJveWVkYCBldmVudC5cbiAgICAgKiBUaGlzIGV2ZW50IHdpbGwgYXV0b21hdGljYWxseSBzdG9wIGFsbCBtZWRpYSB0cmFja3MgYW5kIGRlbGV0ZSBhbnkgSFRNTCB2aWRlbyBlbGVtZW50IGFzc29jaWF0ZWQgdG8gdGhpcyBQdWJsaXNoZXJcbiAgICAgKiAob25seSB0aG9zZSB2aWRlb3MgW2NyZWF0ZWQgYnkgT3BlblZpZHUgQnJvd3Nlcl0oL2RvY3MvaG93LWRvLWkvbWFuYWdlLXZpZGVvcy8jbGV0LW9wZW52aWR1LXRha2UtY2FyZS1vZi10aGUtdmlkZW8tcGxheWVycykpLlxuICAgICAqIEZvciBldmVyeSB2aWRlbyByZW1vdmVkLCB0aGUgUHVibGlzaGVyIG9iamVjdCB3aWxsIGRpc3BhdGNoIGEgYHZpZGVvRWxlbWVudERlc3Ryb3llZGAgZXZlbnQuXG4gICAgICogQ2FsbCBgZXZlbnQucHJldmVudERlZmF1bHQoKWAgdXBvbiBldmVudCBgc3RyZWFtRGVzdHJveWVkYCBpZiB5b3Ugd2FudCB0byBjbGVhbiB0aGUgUHVibGlzaGVyIG9iamVjdCBvbiB5b3VyIG93biBvciByZS1wdWJsaXNoIGl0IGluIGEgZGlmZmVyZW50IFNlc3Npb24uXG4gICAgICpcbiAgICAgKiBUaGUgW1tTZXNzaW9uXV0gb2JqZWN0IG9mIGV2ZXJ5IG90aGVyIHBhcnRpY2lwYW50IGNvbm5lY3RlZCB0byB0aGUgc2Vzc2lvbiB3aWxsIGRpc3BhdGNoIGEgYHN0cmVhbURlc3Ryb3llZGAgZXZlbnQuXG4gICAgICogVGhpcyBldmVudCB3aWxsIGF1dG9tYXRpY2FsbHkgdW5zdWJzY3JpYmUgdGhlIFN1YnNjcmliZXIgb2JqZWN0IGZyb20gdGhlIHNlc3Npb24gKHRoaXMgaW5jbHVkZXMgY2xvc2luZyB0aGUgV2ViUlRDUGVlciBjb25uZWN0aW9uIGFuZCBkaXNwb3NpbmcgYWxsIE1lZGlhU3RyZWFtVHJhY2tzKSBhbmRcbiAgICAgKiBkZWxldGUgYW55IEhUTUwgdmlkZW8gZWxlbWVudCBhc3NvY2lhdGVkIHRvIGl0IChvbmx5IHRob3NlIFtjcmVhdGVkIGJ5IE9wZW5WaWR1IEJyb3dzZXJdKC9kb2NzL2hvdy1kby1pL21hbmFnZS12aWRlb3MvI2xldC1vcGVudmlkdS10YWtlLWNhcmUtb2YtdGhlLXZpZGVvLXBsYXllcnMpKS5cbiAgICAgKiBGb3IgZXZlcnkgdmlkZW8gcmVtb3ZlZCwgdGhlIFN1YnNjcmliZXIgb2JqZWN0IHdpbGwgZGlzcGF0Y2ggYSBgdmlkZW9FbGVtZW50RGVzdHJveWVkYCBldmVudC5cbiAgICAgKiBDYWxsIGBldmVudC5wcmV2ZW50RGVmYXVsdCgpYCB1cG9uIGV2ZW50IGBzdHJlYW1EZXN0cm95ZWRgIHRvIGF2b2lkIHRoaXMgZGVmYXVsdCBiZWhhdmlvciBhbmQgdGFrZSBjYXJlIG9mIGRpc3Bvc2luZyBhbmQgY2xlYW5pbmcgdGhlIFN1YnNjcmliZXIgb2JqZWN0IG9uIHlvdXIgb3duLlxuICAgICAqXG4gICAgICogU2VlIFtbU3RyZWFtRXZlbnRdXSBhbmQgW1tWaWRlb0VsZW1lbnRFdmVudF1dIHRvIGxlYXJuIG1vcmUuXG4gICAgICovXG4gICAgdW5wdWJsaXNoKHB1Ymxpc2hlcjogUHVibGlzaGVyKTogdm9pZCB7XG5cbiAgICAgICAgY29uc3Qgc3RyZWFtID0gcHVibGlzaGVyLnN0cmVhbTtcblxuICAgICAgICBpZiAoIXN0cmVhbS5jb25uZWN0aW9uKSB7XG4gICAgICAgICAgICBjb25zb2xlLmVycm9yKCdUaGUgYXNzb2NpYXRlZCBDb25uZWN0aW9uIG9iamVjdCBvZiB0aGlzIFB1Ymxpc2hlciBpcyBudWxsJywgc3RyZWFtKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfSBlbHNlIGlmIChzdHJlYW0uY29ubmVjdGlvbiAhPT0gdGhpcy5jb25uZWN0aW9uKSB7XG4gICAgICAgICAgICBjb25zb2xlLmVycm9yKCdUaGUgYXNzb2NpYXRlZCBDb25uZWN0aW9uIG9iamVjdCBvZiB0aGlzIFB1Ymxpc2hlciBpcyBub3QgeW91ciBsb2NhbCBDb25uZWN0aW9uLicgK1xuICAgICAgICAgICAgICAgIFwiT25seSBtb2RlcmF0b3JzIGNhbiBmb3JjZSB1bnB1Ymxpc2ggb24gcmVtb3RlIFN0cmVhbXMgdmlhICdmb3JjZVVucHVibGlzaCcgbWV0aG9kXCIsIHN0cmVhbSk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH0gZWxzZSB7XG5cbiAgICAgICAgICAgIGNvbnNvbGUuaW5mbygnVW5wdWJsaXNoaW5nIGxvY2FsIG1lZGlhICgnICsgc3RyZWFtLmNvbm5lY3Rpb24uY29ubmVjdGlvbklkICsgJyknKTtcblxuICAgICAgICAgICAgdGhpcy5vcGVudmlkdS5zZW5kUmVxdWVzdCgndW5wdWJsaXNoVmlkZW8nLCAoZXJyb3IsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoZXJyb3IpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbygnTWVkaWEgdW5wdWJsaXNoZWQgY29ycmVjdGx5Jyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIHN0cmVhbS5kaXNwb3NlV2ViUnRjUGVlcigpO1xuICAgICAgICAgICAgZGVsZXRlIHN0cmVhbS5jb25uZWN0aW9uLnN0cmVhbTtcblxuICAgICAgICAgICAgY29uc3Qgc3RyZWFtRXZlbnQgPSBuZXcgU3RyZWFtRXZlbnQodHJ1ZSwgcHVibGlzaGVyLCAnc3RyZWFtRGVzdHJveWVkJywgcHVibGlzaGVyLnN0cmVhbSwgJ3VucHVibGlzaCcpO1xuICAgICAgICAgICAgcHVibGlzaGVyLmVtaXRFdmVudCgnc3RyZWFtRGVzdHJveWVkJywgW3N0cmVhbUV2ZW50XSk7XG4gICAgICAgICAgICBzdHJlYW1FdmVudC5jYWxsRGVmYXVsdEJlaGF2aW9yKCk7XG4gICAgICAgIH1cbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIEZvcmNlcyBzb21lIHVzZXIgdG8gbGVhdmUgdGhlIHNlc3Npb25cbiAgICAgKlxuICAgICAqICMjIyMgRXZlbnRzIGRpc3BhdGNoZWRcbiAgICAgKlxuICAgICAqIFRoZSBiZWhhdmlvciBpcyB0aGUgc2FtZSBhcyB3aGVuIHNvbWUgdXNlciBjYWxscyBbW1Nlc3Npb24uZGlzY29ubmVjdF1dLCBidXQgYHJlYXNvbmAgcHJvcGVydHkgaW4gYWxsIGV2ZW50cyB3aWxsIGJlIGBcImZvcmNlRGlzY29ubmVjdEJ5VXNlclwiYC5cbiAgICAgKlxuICAgICAqIFRoZSBbW1Nlc3Npb25dXSBvYmplY3Qgb2YgZXZlcnkgcGFydGljaXBhbnQgd2lsbCBkaXNwYXRjaCBhIGBzdHJlYW1EZXN0cm95ZWRgIGV2ZW50IGlmIHRoZSBldmljdGVkIHVzZXIgd2FzIHB1Ymxpc2hpbmcgYSBzdHJlYW0sIHdpdGggcHJvcGVydHkgYHJlYXNvbmAgc2V0IHRvIGBcImZvcmNlRGlzY29ubmVjdEJ5VXNlclwiYC5cbiAgICAgKiBUaGUgW1tTZXNzaW9uXV0gb2JqZWN0IG9mIGV2ZXJ5IHBhcnRpY2lwYW50IGV4Y2VwdCB0aGUgZXZpY3RlZCBvbmUgd2lsbCBkaXNwYXRjaCBhIGBjb25uZWN0aW9uRGVzdHJveWVkYCBldmVudCBmb3IgdGhlIGV2aWN0ZWQgdXNlciwgd2l0aCBwcm9wZXJ0eSBgcmVhc29uYCBzZXQgdG8gYFwiZm9yY2VEaXNjb25uZWN0QnlVc2VyXCJgLlxuICAgICAqXG4gICAgICogSWYgYW55LCB0aGUgW1tQdWJsaXNoZXJdXSBvYmplY3Qgb2YgdGhlIGV2aWN0ZWQgcGFydGljaXBhbnQgd2lsbCBhbHNvIGRpc3BhdGNoIGEgYHN0cmVhbURlc3Ryb3llZGAgZXZlbnQgd2l0aCBwcm9wZXJ0eSBgcmVhc29uYCBzZXQgdG8gYFwiZm9yY2VEaXNjb25uZWN0QnlVc2VyXCJgLlxuICAgICAqIFRoZSBbW1Nlc3Npb25dXSBvYmplY3Qgb2YgdGhlIGV2aWN0ZWQgcGFydGljaXBhbnQgd2lsbCBkaXNwYXRjaCBhIGBzZXNzaW9uRGlzY29ubmVjdGVkYCBldmVudCB3aXRoIHByb3BlcnR5IGByZWFzb25gIHNldCB0byBgXCJmb3JjZURpc2Nvbm5lY3RCeVVzZXJcImAuXG4gICAgICpcbiAgICAgKiBTZWUgW1tTdHJlYW1FdmVudF1dLCBbW0Nvbm5lY3Rpb25FdmVudF1dIGFuZCBbW1Nlc3Npb25EaXNjb25uZWN0ZWRFdmVudF1dIHRvIGxlYXJuIG1vcmUuXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyBBIFByb21pc2UgKHRvIHdoaWNoIHlvdSBjYW4gb3B0aW9uYWxseSBzdWJzY3JpYmUgdG8pIHRoYXQgaXMgcmVzb2x2ZWQgb25seSBhZnRlciB0aGUgcGFydGljaXBhbnQgaGFzIGJlZW4gc3VjY2Vzc2Z1bGx5IGV2aWN0ZWQgZnJvbSB0aGUgc2Vzc2lvbiBhbmQgcmVqZWN0ZWQgd2l0aCBhbiBFcnJvciBvYmplY3QgaWYgbm90XG4gICAgICovXG4gICAgZm9yY2VEaXNjb25uZWN0KGNvbm5lY3Rpb246IENvbm5lY3Rpb24pOiBQcm9taXNlPGFueT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgY29uc29sZS5pbmZvKCdGb3JjaW5nIGRpc2Nvbm5lY3QgZm9yIGNvbm5lY3Rpb24gJyArIGNvbm5lY3Rpb24uY29ubmVjdGlvbklkKTtcbiAgICAgICAgICAgIHRoaXMub3BlbnZpZHUuc2VuZFJlcXVlc3QoXG4gICAgICAgICAgICAgICAgJ2ZvcmNlRGlzY29ubmVjdCcsXG4gICAgICAgICAgICAgICAgeyBjb25uZWN0aW9uSWQ6IGNvbm5lY3Rpb24uY29ubmVjdGlvbklkIH0sXG4gICAgICAgICAgICAgICAgKGVycm9yLCByZXNwb25zZSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBpZiAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ0Vycm9yIGZvcmNpbmcgZGlzY29ubmVjdCBmb3IgQ29ubmVjdGlvbiAnICsgY29ubmVjdGlvbi5jb25uZWN0aW9uSWQsIGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChlcnJvci5jb2RlID09PSA0MDEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWplY3QobmV3IE9wZW5WaWR1RXJyb3IoT3BlblZpZHVFcnJvck5hbWUuT1BFTlZJRFVfUEVSTUlTU0lPTl9ERU5JRUQsIFwiWW91IGRvbid0IGhhdmUgcGVybWlzc2lvbnMgdG8gZm9yY2UgYSBkaXNjb25uZWN0aW9uXCIpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbygnRm9yY2luZyBkaXNjb25uZWN0IGNvcnJlY3RseSBmb3IgQ29ubmVjdGlvbiAnICsgY29ubmVjdGlvbi5jb25uZWN0aW9uSWQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBGb3JjZXMgc29tZSB1c2VyIHRvIHVucHVibGlzaCBhIFN0cmVhbVxuICAgICAqXG4gICAgICogIyMjIyBFdmVudHMgZGlzcGF0Y2hlZFxuICAgICAqXG4gICAgICogVGhlIGJlaGF2aW9yIGlzIHRoZSBzYW1lIGFzIHdoZW4gc29tZSB1c2VyIGNhbGxzIFtbU2Vzc2lvbi51bnB1Ymxpc2hdXSwgYnV0IGByZWFzb25gIHByb3BlcnR5IGluIGFsbCBldmVudHMgd2lsbCBiZSBgXCJmb3JjZVVucHVibGlzaEJ5VXNlclwiYFxuICAgICAqXG4gICAgICogVGhlIFtbU2Vzc2lvbl1dIG9iamVjdCBvZiBldmVyeSBwYXJ0aWNpcGFudCB3aWxsIGRpc3BhdGNoIGEgYHN0cmVhbURlc3Ryb3llZGAgZXZlbnQgd2l0aCBwcm9wZXJ0eSBgcmVhc29uYCBzZXQgdG8gYFwiZm9yY2VEaXNjb25uZWN0QnlVc2VyXCJgXG4gICAgICpcbiAgICAgKiBUaGUgW1tQdWJsaXNoZXJdXSBvYmplY3Qgb2YgdGhlIGFmZmVjdGVkIHBhcnRpY2lwYW50IHdpbGwgYWxzbyBkaXNwYXRjaCBhIGBzdHJlYW1EZXN0cm95ZWRgIGV2ZW50IHdpdGggcHJvcGVydHkgYHJlYXNvbmAgc2V0IHRvIGBcImZvcmNlRGlzY29ubmVjdEJ5VXNlclwiYFxuICAgICAqXG4gICAgICogU2VlIFtbU3RyZWFtRXZlbnRdXSB0byBsZWFybiBtb3JlLlxuICAgICAqXG4gICAgICogQHJldHVybnMgQSBQcm9taXNlICh0byB3aGljaCB5b3UgY2FuIG9wdGlvbmFsbHkgc3Vic2NyaWJlIHRvKSB0aGF0IGlzIHJlc29sdmVkIG9ubHkgYWZ0ZXIgdGhlIHJlbW90ZSBTdHJlYW0gaGFzIGJlZW4gc3VjY2Vzc2Z1bGx5IHVucHVibGlzaGVkIGZyb20gdGhlIHNlc3Npb24gYW5kIHJlamVjdGVkIHdpdGggYW4gRXJyb3Igb2JqZWN0IGlmIG5vdFxuICAgICAqL1xuICAgIGZvcmNlVW5wdWJsaXNoKHN0cmVhbTogU3RyZWFtKTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIGNvbnNvbGUuaW5mbygnRm9yY2luZyB1bnB1Ymxpc2ggZm9yIHN0cmVhbSAnICsgc3RyZWFtLnN0cmVhbUlkKTtcbiAgICAgICAgICAgIHRoaXMub3BlbnZpZHUuc2VuZFJlcXVlc3QoXG4gICAgICAgICAgICAgICAgJ2ZvcmNlVW5wdWJsaXNoJyxcbiAgICAgICAgICAgICAgICB7IHN0cmVhbUlkOiBzdHJlYW0uc3RyZWFtSWQgfSxcbiAgICAgICAgICAgICAgICAoZXJyb3IsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcignRXJyb3IgZm9yY2luZyB1bnB1Ymxpc2ggZm9yIFN0cmVhbSAnICsgc3RyZWFtLnN0cmVhbUlkLCBlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZXJyb3IuY29kZSA9PT0gNDAxKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KG5ldyBPcGVuVmlkdUVycm9yKE9wZW5WaWR1RXJyb3JOYW1lLk9QRU5WSURVX1BFUk1JU1NJT05fREVOSUVELCBcIllvdSBkb24ndCBoYXZlIHBlcm1pc3Npb25zIHRvIGZvcmNlIGFuIHVucHVibGlzaGluZ1wiKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oJ0ZvcmNpbmcgdW5wdWJsaXNoIGNvcnJlY3RseSBmb3IgU3RyZWFtICcgKyBzdHJlYW0uc3RyZWFtSWQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBTZW5kcyBvbmUgc2lnbmFsLiBgc2lnbmFsYCBvYmplY3QgaGFzIHRoZSBmb2xsb3dpbmcgb3B0aW9uYWwgcHJvcGVydGllczpcbiAgICAgKiBgYGBqc29uXG4gICAgICoge2RhdGE6c3RyaW5nLCB0bzpDb25uZWN0aW9uW10sIHR5cGU6c3RyaW5nfVxuICAgICAqIGBgYFxuICAgICAqIEFsbCB1c2VycyBzdWJzY3JpYmVkIHRvIHRoYXQgc2lnbmFsIChgc2Vzc2lvbi5vbignc2lnbmFsOnR5cGUnLCAuLi4pYCBvciBgc2Vzc2lvbi5vbignc2lnbmFsJywgLi4uKWAgZm9yIGFsbCBzaWduYWxzKSBhbmQgd2hvc2UgQ29ubmVjdGlvbiBvYmplY3RzIGFyZSBpbiBgdG9gIGFycmF5IHdpbGwgcmVjZWl2ZSBpdC4gVGhlaXIgbG9jYWxcbiAgICAgKiBTZXNzaW9uIG9iamVjdHMgd2lsbCBkaXNwYXRjaCBhIGBzaWduYWxgIG9yIGBzaWduYWw6dHlwZWAgZXZlbnQuIFNlZSBbW1NpZ25hbEV2ZW50XV0gdG8gbGVhcm4gbW9yZS5cbiAgICAgKlxuICAgICAqIEByZXR1cm5zIEEgUHJvbWlzZSAodG8gd2hpY2ggeW91IGNhbiBvcHRpb25hbGx5IHN1YnNjcmliZSB0bykgdGhhdCBpcyByZXNvbHZlZCBpZiB0aGUgbWVzc2FnZSBzdWNjZXNzZnVsbHkgcmVhY2hlZCBvcGVudmlkdS1zZXJ2ZXIgYW5kIHJlamVjdGVkIHdpdGggYW4gRXJyb3Igb2JqZWN0IGlmIG5vdC4gX1RoaXMgZG9lc24ndFxuICAgICAqIG1lYW4gdGhhdCBvcGVudmlkdS1zZXJ2ZXIgY291bGQgcmVzZW5kIHRoZSBtZXNzYWdlIHRvIGFsbCB0aGUgbGlzdGVkIHJlY2VpdmVycy5fXG4gICAgICovXG4gICAgLyogdHNsaW50OmRpc2FibGU6bm8tc3RyaW5nLWxpdGVyYWwgKi9cbiAgICBzaWduYWwoc2lnbmFsOiBTaWduYWxPcHRpb25zKTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcblxuICAgICAgICAgICAgY29uc3Qgc2lnbmFsTWVzc2FnZSA9IHt9O1xuXG4gICAgICAgICAgICBpZiAoc2lnbmFsLnRvICYmIHNpZ25hbC50by5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgY29ubmVjdGlvbklkczogc3RyaW5nW10gPSBbXTtcblxuICAgICAgICAgICAgICAgIHNpZ25hbC50by5mb3JFYWNoKGNvbm5lY3Rpb24gPT4ge1xuICAgICAgICAgICAgICAgICAgICBjb25uZWN0aW9uSWRzLnB1c2goY29ubmVjdGlvbi5jb25uZWN0aW9uSWQpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIHNpZ25hbE1lc3NhZ2VbJ3RvJ10gPSBjb25uZWN0aW9uSWRzO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBzaWduYWxNZXNzYWdlWyd0byddID0gW107XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHNpZ25hbE1lc3NhZ2VbJ2RhdGEnXSA9IHNpZ25hbC5kYXRhID8gc2lnbmFsLmRhdGEgOiAnJztcbiAgICAgICAgICAgIHNpZ25hbE1lc3NhZ2VbJ3R5cGUnXSA9IHNpZ25hbC50eXBlID8gc2lnbmFsLnR5cGUgOiAnJztcblxuICAgICAgICAgICAgdGhpcy5vcGVudmlkdS5zZW5kUmVxdWVzdCgnc2VuZE1lc3NhZ2UnLCB7XG4gICAgICAgICAgICAgICAgbWVzc2FnZTogSlNPTi5zdHJpbmdpZnkoc2lnbmFsTWVzc2FnZSlcbiAgICAgICAgICAgIH0sIChlcnJvciwgcmVzcG9uc2UpID0+IHtcbiAgICAgICAgICAgICAgICBpZiAoISFlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgfVxuICAgIC8qIHRzbGludDplbmFibGU6bm8tc3RyaW5nLWxpdGVyYWwgKi9cblxuXG4gICAgLyoqXG4gICAgICogU2VlIFtbRXZlbnREaXNwYXRjaGVyLm9uXV1cbiAgICAgKi9cbiAgICBvbih0eXBlOiBzdHJpbmcsIGhhbmRsZXI6IChldmVudDogU2Vzc2lvbkRpc2Nvbm5lY3RlZEV2ZW50IHwgU2lnbmFsRXZlbnQgfCBTdHJlYW1FdmVudCB8IENvbm5lY3Rpb25FdmVudCB8IFB1Ymxpc2hlclNwZWFraW5nRXZlbnQgfCBSZWNvcmRpbmdFdmVudCkgPT4gdm9pZCk6IEV2ZW50RGlzcGF0Y2hlciB7XG5cbiAgICAgICAgdGhpcy5lZS5vbih0eXBlLCBldmVudCA9PiB7XG4gICAgICAgICAgICBpZiAoZXZlbnQpIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oXCJFdmVudCAnXCIgKyB0eXBlICsgXCInIHRyaWdnZXJlZCBieSAnU2Vzc2lvbidcIiwgZXZlbnQpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oXCJFdmVudCAnXCIgKyB0eXBlICsgXCInIHRyaWdnZXJlZCBieSAnU2Vzc2lvbidcIik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBoYW5kbGVyKGV2ZW50KTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgaWYgKHR5cGUgPT09ICdwdWJsaXNoZXJTdGFydFNwZWFraW5nJyB8fCB0eXBlID09PSAncHVibGlzaGVyU3RvcFNwZWFraW5nJykge1xuICAgICAgICAgICAgdGhpcy5zcGVha2luZ0V2ZW50c0VuYWJsZWQgPSB0cnVlO1xuICAgICAgICAgICAgLy8gSWYgdGhlcmUgYXJlIGFscmVhZHkgYXZhaWxhYmxlIHJlbW90ZSBzdHJlYW1zLCBlbmFibGUgaGFyayAnc3BlYWtpbmcnIGV2ZW50IGluIGFsbCBvZiB0aGVtXG4gICAgICAgICAgICBmb3IgKGNvbnN0IGNvbm5lY3Rpb25JZCBpbiB0aGlzLnJlbW90ZUNvbm5lY3Rpb25zKSB7XG4gICAgICAgICAgICAgICAgY29uc3Qgc3RyID0gdGhpcy5yZW1vdGVDb25uZWN0aW9uc1tjb25uZWN0aW9uSWRdLnN0cmVhbTtcbiAgICAgICAgICAgICAgICBpZiAoISFzdHIgJiYgIXN0ci5zcGVlY2hFdmVudCAmJiBzdHIuaGFzQXVkaW8pIHtcbiAgICAgICAgICAgICAgICAgICAgc3RyLmVuYWJsZVNwZWFraW5nRXZlbnRzKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBTZWUgW1tFdmVudERpc3BhdGNoZXIub25jZV1dXG4gICAgICovXG4gICAgb25jZSh0eXBlOiBzdHJpbmcsIGhhbmRsZXI6IChldmVudDogU2Vzc2lvbkRpc2Nvbm5lY3RlZEV2ZW50IHwgU2lnbmFsRXZlbnQgfCBTdHJlYW1FdmVudCB8IENvbm5lY3Rpb25FdmVudCB8IFB1Ymxpc2hlclNwZWFraW5nRXZlbnQgfCBSZWNvcmRpbmdFdmVudCkgPT4gdm9pZCk6IFNlc3Npb24ge1xuICAgICAgICB0aGlzLmVlLm9uY2UodHlwZSwgZXZlbnQgPT4ge1xuICAgICAgICAgICAgaWYgKGV2ZW50KSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5pbmZvKFwiRXZlbnQgJ1wiICsgdHlwZSArIFwiJyB0cmlnZ2VyZWQgYnkgJ1Nlc3Npb24nXCIsIGV2ZW50KTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5pbmZvKFwiRXZlbnQgJ1wiICsgdHlwZSArIFwiJyB0cmlnZ2VyZWQgYnkgJ1Nlc3Npb24nXCIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaGFuZGxlcihldmVudCk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGlmICh0eXBlID09PSAncHVibGlzaGVyU3RhcnRTcGVha2luZycgfHwgdHlwZSA9PT0gJ3B1Ymxpc2hlclN0b3BTcGVha2luZycpIHtcbiAgICAgICAgICAgIHRoaXMuc3BlYWtpbmdFdmVudHNFbmFibGVkID0gdHJ1ZTtcblxuICAgICAgICAgICAgLy8gSWYgdGhlcmUgYXJlIGFscmVhZHkgYXZhaWxhYmxlIHJlbW90ZSBzdHJlYW1zLCBlbmFibGUgaGFyayBpbiBhbGwgb2YgdGhlbVxuICAgICAgICAgICAgZm9yIChjb25zdCBjb25uZWN0aW9uSWQgaW4gdGhpcy5yZW1vdGVDb25uZWN0aW9ucykge1xuICAgICAgICAgICAgICAgIGNvbnN0IHN0ciA9IHRoaXMucmVtb3RlQ29ubmVjdGlvbnNbY29ubmVjdGlvbklkXS5zdHJlYW07XG4gICAgICAgICAgICAgICAgaWYgKCEhc3RyICYmICFzdHIuc3BlZWNoRXZlbnQgJiYgc3RyLmhhc0F1ZGlvKSB7XG4gICAgICAgICAgICAgICAgICAgIHN0ci5lbmFibGVPbmNlU3BlYWtpbmdFdmVudHMoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFNlZSBbW0V2ZW50RGlzcGF0Y2hlci5vZmZdXVxuICAgICAqL1xuICAgIG9mZih0eXBlOiBzdHJpbmcsIGhhbmRsZXI/OiAoZXZlbnQ6IFNlc3Npb25EaXNjb25uZWN0ZWRFdmVudCB8IFNpZ25hbEV2ZW50IHwgU3RyZWFtRXZlbnQgfCBDb25uZWN0aW9uRXZlbnQgfCBQdWJsaXNoZXJTcGVha2luZ0V2ZW50IHwgUmVjb3JkaW5nRXZlbnQpID0+IHZvaWQpOiBTZXNzaW9uIHtcblxuICAgICAgICBpZiAoIWhhbmRsZXIpIHtcbiAgICAgICAgICAgIHRoaXMuZWUucmVtb3ZlQWxsTGlzdGVuZXJzKHR5cGUpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5lZS5vZmYodHlwZSwgaGFuZGxlcik7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodHlwZSA9PT0gJ3B1Ymxpc2hlclN0YXJ0U3BlYWtpbmcnIHx8IHR5cGUgPT09ICdwdWJsaXNoZXJTdG9wU3BlYWtpbmcnKSB7XG4gICAgICAgICAgICB0aGlzLnNwZWFraW5nRXZlbnRzRW5hYmxlZCA9IGZhbHNlO1xuXG4gICAgICAgICAgICAvLyBJZiB0aGVyZSBhcmUgYWxyZWFkeSBhdmFpbGFibGUgcmVtb3RlIHN0cmVhbXMsIGRpc2FibGFlIGhhcmsgaW4gYWxsIG9mIHRoZW1cbiAgICAgICAgICAgIGZvciAoY29uc3QgY29ubmVjdGlvbklkIGluIHRoaXMucmVtb3RlQ29ubmVjdGlvbnMpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBzdHIgPSB0aGlzLnJlbW90ZUNvbm5lY3Rpb25zW2Nvbm5lY3Rpb25JZF0uc3RyZWFtO1xuICAgICAgICAgICAgICAgIGlmICghIXN0ciAmJiAhIXN0ci5zcGVlY2hFdmVudCkge1xuICAgICAgICAgICAgICAgICAgICBzdHIuZGlzYWJsZVNwZWFraW5nRXZlbnRzKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuXG4gICAgLyogSGlkZGVuIG1ldGhvZHMgKi9cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvblBhcnRpY2lwYW50Sm9pbmVkKHJlc3BvbnNlOiBDb25uZWN0aW9uT3B0aW9ucyk6IHZvaWQge1xuICAgICAgICAvLyBDb25uZWN0aW9uIHNob3VsZG4ndCBleGlzdFxuICAgICAgICB0aGlzLmdldENvbm5lY3Rpb24ocmVzcG9uc2UuaWQsICcnKVxuXG4gICAgICAgICAgICAudGhlbihjb25uZWN0aW9uID0+IHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLndhcm4oJ0Nvbm5lY3Rpb24gJyArIHJlc3BvbnNlLmlkICsgJyBhbHJlYWR5IGV4aXN0cyBpbiBjb25uZWN0aW9ucyBsaXN0Jyk7XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLmNhdGNoKG9wZW5WaWR1RXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IGNvbm5lY3Rpb24gPSBuZXcgQ29ubmVjdGlvbih0aGlzLCByZXNwb25zZSk7XG4gICAgICAgICAgICAgICAgdGhpcy5yZW1vdGVDb25uZWN0aW9uc1tyZXNwb25zZS5pZF0gPSBjb25uZWN0aW9uO1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdjb25uZWN0aW9uQ3JlYXRlZCcsIFtuZXcgQ29ubmVjdGlvbkV2ZW50KGZhbHNlLCB0aGlzLCAnY29ubmVjdGlvbkNyZWF0ZWQnLCBjb25uZWN0aW9uLCAnJyldKTtcbiAgICAgICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvblBhcnRpY2lwYW50TGVmdChtc2cpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5nZXRSZW1vdGVDb25uZWN0aW9uKG1zZy5jb25uZWN0aW9uSWQsICdSZW1vdGUgY29ubmVjdGlvbiAnICsgbXNnLmNvbm5lY3Rpb25JZCArIFwiIHVua25vd24gd2hlbiAnb25QYXJ0aWNpcGFudExlZnQnLiBcIiArXG4gICAgICAgICAgICAnRXhpc3RpbmcgcmVtb3RlIGNvbm5lY3Rpb25zOiAnICsgSlNPTi5zdHJpbmdpZnkoT2JqZWN0LmtleXModGhpcy5yZW1vdGVDb25uZWN0aW9ucykpKVxuXG4gICAgICAgICAgICAudGhlbihjb25uZWN0aW9uID0+IHtcbiAgICAgICAgICAgICAgICBpZiAoISFjb25uZWN0aW9uLnN0cmVhbSkge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBzdHJlYW0gPSBjb25uZWN0aW9uLnN0cmVhbTtcblxuICAgICAgICAgICAgICAgICAgICBjb25zdCBzdHJlYW1FdmVudCA9IG5ldyBTdHJlYW1FdmVudCh0cnVlLCB0aGlzLCAnc3RyZWFtRGVzdHJveWVkJywgc3RyZWFtLCBtc2cucmVhc29uKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3N0cmVhbURlc3Ryb3llZCcsIFtzdHJlYW1FdmVudF0pO1xuICAgICAgICAgICAgICAgICAgICBzdHJlYW1FdmVudC5jYWxsRGVmYXVsdEJlaGF2aW9yKCk7XG5cbiAgICAgICAgICAgICAgICAgICAgZGVsZXRlIHRoaXMucmVtb3RlU3RyZWFtc0NyZWF0ZWRbc3RyZWFtLnN0cmVhbUlkXTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZGVsZXRlIHRoaXMucmVtb3RlQ29ubmVjdGlvbnNbY29ubmVjdGlvbi5jb25uZWN0aW9uSWRdO1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdjb25uZWN0aW9uRGVzdHJveWVkJywgW25ldyBDb25uZWN0aW9uRXZlbnQoZmFsc2UsIHRoaXMsICdjb25uZWN0aW9uRGVzdHJveWVkJywgY29ubmVjdGlvbiwgbXNnLnJlYXNvbildKTtcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAuY2F0Y2gob3BlblZpZHVFcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihvcGVuVmlkdUVycm9yKTtcbiAgICAgICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvblBhcnRpY2lwYW50UHVibGlzaGVkKHJlc3BvbnNlOiBDb25uZWN0aW9uT3B0aW9ucyk6IHZvaWQge1xuXG4gICAgICAgIGNvbnN0IGFmdGVyQ29ubmVjdGlvbkZvdW5kID0gKGNvbm5lY3Rpb24pID0+IHtcbiAgICAgICAgICAgIHRoaXMucmVtb3RlQ29ubmVjdGlvbnNbY29ubmVjdGlvbi5jb25uZWN0aW9uSWRdID0gY29ubmVjdGlvbjtcblxuICAgICAgICAgICAgaWYgKCF0aGlzLnJlbW90ZVN0cmVhbXNDcmVhdGVkW2Nvbm5lY3Rpb24uc3RyZWFtLnN0cmVhbUlkXSkge1xuICAgICAgICAgICAgICAgIC8vIEF2b2lkIHJhY2UgY29uZGl0aW9uIGJldHdlZW4gc3RyZWFtLnN1YnNjcmliZSgpIGluIFwib25QYXJ0aWNpcGFudFB1Ymxpc2hlZFwiIGFuZCBpbiBcImpvaW5Sb29tXCIgcnBjIGNhbGxiYWNrXG4gICAgICAgICAgICAgICAgLy8gVGhpcyBjb25kaXRpb24gaXMgZmFsc2UgaWYgb3BlbnZpZHUtc2VydmVyIHNlbmRzIFwicGFydGljaXBhbnRQdWJsaXNoZWRcIiBldmVudCB0byBhIHN1YnNjcmliZXIgcGFydGljaXBhbnQgdGhhdCBoYXNcbiAgICAgICAgICAgICAgICAvLyBhbHJlYWR5IHN1YnNjcmliZWQgdG8gY2VydGFpbiBzdHJlYW0gaW4gdGhlIGNhbGxiYWNrIG9mIFwiam9pblJvb21cIiBtZXRob2RcblxuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdzdHJlYW1DcmVhdGVkJywgW25ldyBTdHJlYW1FdmVudChmYWxzZSwgdGhpcywgJ3N0cmVhbUNyZWF0ZWQnLCBjb25uZWN0aW9uLnN0cmVhbSwgJycpXSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMucmVtb3RlU3RyZWFtc0NyZWF0ZWRbY29ubmVjdGlvbi5zdHJlYW0uc3RyZWFtSWRdID0gdHJ1ZTtcbiAgICAgICAgfTtcblxuICAgICAgICAvLyBHZXQgdGhlIGV4aXN0aW5nIENvbm5lY3Rpb24gY3JlYXRlZCBvbiAnb25QYXJ0aWNpcGFudEpvaW5lZCcgZm9yXG4gICAgICAgIC8vIGV4aXN0aW5nIHBhcnRpY2lwYW50cyBvciBjcmVhdGUgYSBuZXcgb25lIGZvciBuZXcgcGFydGljaXBhbnRzXG4gICAgICAgIGxldCBjb25uZWN0aW9uOiBDb25uZWN0aW9uO1xuICAgICAgICB0aGlzLmdldFJlbW90ZUNvbm5lY3Rpb24ocmVzcG9uc2UuaWQsIFwiUmVtb3RlIGNvbm5lY3Rpb24gJ1wiICsgcmVzcG9uc2UuaWQgKyBcIicgdW5rbm93biB3aGVuICdvblBhcnRpY2lwYW50UHVibGlzaGVkJy4gXCIgK1xuICAgICAgICAgICAgJ0V4aXN0aW5nIHJlbW90ZSBjb25uZWN0aW9uczogJyArIEpTT04uc3RyaW5naWZ5KE9iamVjdC5rZXlzKHRoaXMucmVtb3RlQ29ubmVjdGlvbnMpKSlcblxuICAgICAgICAgICAgLnRoZW4oY29uID0+IHtcbiAgICAgICAgICAgICAgICAvLyBVcGRhdGUgZXhpc3RpbmcgQ29ubmVjdGlvblxuICAgICAgICAgICAgICAgIGNvbm5lY3Rpb24gPSBjb247XG4gICAgICAgICAgICAgICAgcmVzcG9uc2UubWV0YWRhdGEgPSBjb24uZGF0YTtcbiAgICAgICAgICAgICAgICBjb25uZWN0aW9uLm9wdGlvbnMgPSByZXNwb25zZTtcbiAgICAgICAgICAgICAgICBjb25uZWN0aW9uLmluaXRSZW1vdGVTdHJlYW1zKHJlc3BvbnNlLnN0cmVhbXMpO1xuICAgICAgICAgICAgICAgIGFmdGVyQ29ubmVjdGlvbkZvdW5kKGNvbm5lY3Rpb24pO1xuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIC5jYXRjaChvcGVuVmlkdUVycm9yID0+IHtcbiAgICAgICAgICAgICAgICAvLyBDcmVhdGUgbmV3IENvbm5lY3Rpb25cbiAgICAgICAgICAgICAgICBjb25uZWN0aW9uID0gbmV3IENvbm5lY3Rpb24odGhpcywgcmVzcG9uc2UpO1xuICAgICAgICAgICAgICAgIGFmdGVyQ29ubmVjdGlvbkZvdW5kKGNvbm5lY3Rpb24pO1xuICAgICAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIG9uUGFydGljaXBhbnRVbnB1Ymxpc2hlZChtc2cpOiB2b2lkIHtcbiAgICAgICAgaWYgKG1zZy5jb25uZWN0aW9uSWQgPT09IHRoaXMuY29ubmVjdGlvbi5jb25uZWN0aW9uSWQpIHtcbiAgICAgICAgICAgIC8vIFlvdXIgc3RyZWFtIGhhcyBiZWVuIGZvcmNlZGx5IHVucHVibGlzaGVkIGZyb20gdGhlIHNlc3Npb25cbiAgICAgICAgICAgIHRoaXMuc3RvcFB1Ymxpc2hlclN0cmVhbShtc2cucmVhc29uKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuZ2V0UmVtb3RlQ29ubmVjdGlvbihtc2cuY29ubmVjdGlvbklkLCBcIlJlbW90ZSBjb25uZWN0aW9uICdcIiArIG1zZy5jb25uZWN0aW9uSWQgKyBcIicgdW5rbm93biB3aGVuICdvblBhcnRpY2lwYW50VW5wdWJsaXNoZWQnLiBcIiArXG4gICAgICAgICAgICAgICAgJ0V4aXN0aW5nIHJlbW90ZSBjb25uZWN0aW9uczogJyArIEpTT04uc3RyaW5naWZ5KE9iamVjdC5rZXlzKHRoaXMucmVtb3RlQ29ubmVjdGlvbnMpKSlcblxuICAgICAgICAgICAgICAgIC50aGVuKGNvbm5lY3Rpb24gPT4ge1xuXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHN0cmVhbUV2ZW50ID0gbmV3IFN0cmVhbUV2ZW50KHRydWUsIHRoaXMsICdzdHJlYW1EZXN0cm95ZWQnLCBjb25uZWN0aW9uLnN0cmVhbSwgbXNnLnJlYXNvbik7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdzdHJlYW1EZXN0cm95ZWQnLCBbc3RyZWFtRXZlbnRdKTtcbiAgICAgICAgICAgICAgICAgICAgc3RyZWFtRXZlbnQuY2FsbERlZmF1bHRCZWhhdmlvcigpO1xuXG4gICAgICAgICAgICAgICAgICAgIC8vIERlbGV0aW5nIHRoZSByZW1vdGUgc3RyZWFtXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHN0cmVhbUlkOiBzdHJpbmcgPSBjb25uZWN0aW9uLnN0cmVhbS5zdHJlYW1JZDtcbiAgICAgICAgICAgICAgICAgICAgZGVsZXRlIHRoaXMucmVtb3RlU3RyZWFtc0NyZWF0ZWRbc3RyZWFtSWRdO1xuICAgICAgICAgICAgICAgICAgICBjb25uZWN0aW9uLnJlbW92ZVN0cmVhbShzdHJlYW1JZCk7XG4gICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAuY2F0Y2gob3BlblZpZHVFcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3Iob3BlblZpZHVFcnJvcik7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgb25QYXJ0aWNpcGFudEV2aWN0ZWQobXNnKTogdm9pZCB7XG4gICAgICAgIGlmIChtc2cuY29ubmVjdGlvbklkID09PSB0aGlzLmNvbm5lY3Rpb24uY29ubmVjdGlvbklkKSB7XG4gICAgICAgICAgICAvLyBZb3UgaGF2ZSBiZWVuIGV2aWN0ZWQgZnJvbSB0aGUgc2Vzc2lvblxuICAgICAgICAgICAgaWYgKCEhdGhpcy5zZXNzaW9uSWQgJiYgIXRoaXMuY29ubmVjdGlvbi5kaXNwb3NlZCkge1xuICAgICAgICAgICAgICAgIHRoaXMubGVhdmUodHJ1ZSwgbXNnLnJlYXNvbik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgb25OZXdNZXNzYWdlKG1zZyk6IHZvaWQge1xuXG4gICAgICAgIGNvbnNvbGUuaW5mbygnTmV3IHNpZ25hbDogJyArIEpTT04uc3RyaW5naWZ5KG1zZykpO1xuXG4gICAgICAgIHRoaXMuZ2V0Q29ubmVjdGlvbihtc2cuZnJvbSwgXCJDb25uZWN0aW9uICdcIiArIG1zZy5mcm9tICsgXCInIHVua25vdyB3aGVuICdvbk5ld01lc3NhZ2UnLiBFeGlzdGluZyByZW1vdGUgY29ubmVjdGlvbnM6IFwiXG4gICAgICAgICAgICArIEpTT04uc3RyaW5naWZ5KE9iamVjdC5rZXlzKHRoaXMucmVtb3RlQ29ubmVjdGlvbnMpKSArICcuIEV4aXN0aW5nIGxvY2FsIGNvbm5lY3Rpb246ICcgKyB0aGlzLmNvbm5lY3Rpb24uY29ubmVjdGlvbklkKVxuXG4gICAgICAgICAgICAudGhlbihjb25uZWN0aW9uID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnc2lnbmFsJywgW25ldyBTaWduYWxFdmVudCh0aGlzLCBtc2cudHlwZSwgbXNnLmRhdGEsIGNvbm5lY3Rpb24pXSk7XG4gICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3NpZ25hbDonICsgbXNnLnR5cGUsIFtuZXcgU2lnbmFsRXZlbnQodGhpcywgbXNnLnR5cGUsIG1zZy5kYXRhLCBjb25uZWN0aW9uKV0pO1xuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIC5jYXRjaChvcGVuVmlkdUVycm9yID0+IHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKG9wZW5WaWR1RXJyb3IpO1xuICAgICAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIG9uU3RyZWFtUHJvcGVydHlDaGFuZ2VkKG1zZyk6IHZvaWQge1xuICAgICAgICB0aGlzLmdldFJlbW90ZUNvbm5lY3Rpb24obXNnLmNvbm5lY3Rpb25JZCwgJ1JlbW90ZSBjb25uZWN0aW9uICcgKyBtc2cuY29ubmVjdGlvbklkICsgXCIgdW5rbm93biB3aGVuICdvblN0cmVhbVByb3BlcnR5Q2hhbmdlZCcuIFwiICtcbiAgICAgICAgICAgICdFeGlzdGluZyByZW1vdGUgY29ubmVjdGlvbnM6ICcgKyBKU09OLnN0cmluZ2lmeShPYmplY3Qua2V5cyh0aGlzLnJlbW90ZUNvbm5lY3Rpb25zKSkpXG5cbiAgICAgICAgICAgIC50aGVuKGNvbm5lY3Rpb24gPT4ge1xuICAgICAgICAgICAgICAgIGlmICghIWNvbm5lY3Rpb24uc3RyZWFtICYmIGNvbm5lY3Rpb24uc3RyZWFtLnN0cmVhbUlkID09PSBtc2cuc3RyZWFtSWQpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3Qgc3RyZWFtID0gY29ubmVjdGlvbi5zdHJlYW07XG4gICAgICAgICAgICAgICAgICAgIGxldCBvbGRWYWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgc3dpdGNoIChtc2cucHJvcGVydHkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJ2F1ZGlvQWN0aXZlJzpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvbGRWYWx1ZSA9IHN0cmVhbS5hdWRpb0FjdGl2ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtc2cubmV3VmFsdWUgPSBtc2cubmV3VmFsdWUgPT09ICd0cnVlJztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJlYW0uYXVkaW9BY3RpdmUgPSBtc2cubmV3VmFsdWU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlICd2aWRlb0FjdGl2ZSc6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgb2xkVmFsdWUgPSBzdHJlYW0udmlkZW9BY3RpdmU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbXNnLm5ld1ZhbHVlID0gbXNnLm5ld1ZhbHVlID09PSAndHJ1ZSc7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyZWFtLnZpZGVvQWN0aXZlID0gbXNnLm5ld1ZhbHVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAndmlkZW9EaW1lbnNpb25zJzpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvbGRWYWx1ZSA9IHN0cmVhbS52aWRlb0RpbWVuc2lvbnM7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbXNnLm5ld1ZhbHVlID0gSlNPTi5wYXJzZShKU09OLnBhcnNlKG1zZy5uZXdWYWx1ZSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cmVhbS52aWRlb0RpbWVuc2lvbnMgPSBtc2cubmV3VmFsdWU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnc3RyZWFtUHJvcGVydHlDaGFuZ2VkJywgW25ldyBTdHJlYW1Qcm9wZXJ0eUNoYW5nZWRFdmVudCh0aGlzLCBzdHJlYW0sIG1zZy5wcm9wZXJ0eSwgbXNnLm5ld1ZhbHVlLCBvbGRWYWx1ZSwgbXNnLnJlYXNvbildKTtcbiAgICAgICAgICAgICAgICAgICAgc3RyZWFtLnN0cmVhbU1hbmFnZXIuZW1pdEV2ZW50KCdzdHJlYW1Qcm9wZXJ0eUNoYW5nZWQnLCBbbmV3IFN0cmVhbVByb3BlcnR5Q2hhbmdlZEV2ZW50KHN0cmVhbS5zdHJlYW1NYW5hZ2VyLCBzdHJlYW0sIG1zZy5wcm9wZXJ0eSwgbXNnLm5ld1ZhbHVlLCBvbGRWYWx1ZSwgbXNnLnJlYXNvbildKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKFwiTm8gc3RyZWFtIHdpdGggc3RyZWFtSWQgJ1wiICsgbXNnLnN0cmVhbUlkICsgXCInIGZvdW5kIGZvciBjb25uZWN0aW9uICdcIiArIG1zZy5jb25uZWN0aW9uSWQgKyBcIicgb24gJ3N0cmVhbVByb3BlcnR5Q2hhbmdlZCcgZXZlbnRcIik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIC5jYXRjaChvcGVuVmlkdUVycm9yID0+IHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKG9wZW5WaWR1RXJyb3IpO1xuICAgICAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHJlY3ZJY2VDYW5kaWRhdGUobXNnKTogdm9pZCB7XG4gICAgICAgIGNvbnN0IGNhbmRpZGF0ZSA9IHtcbiAgICAgICAgICAgIGNhbmRpZGF0ZTogbXNnLmNhbmRpZGF0ZSxcbiAgICAgICAgICAgIHNkcE1pZDogbXNnLnNkcE1pZCxcbiAgICAgICAgICAgIHNkcE1MaW5lSW5kZXg6IG1zZy5zZHBNTGluZUluZGV4LFxuICAgICAgICAgICAgdG9KU09OOiAoKSA9PiB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHsgY2FuZGlkYXRlOiBtc2cuY2FuZGlkYXRlIH07XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuZ2V0Q29ubmVjdGlvbihtc2cuZW5kcG9pbnROYW1lLCAnQ29ubmVjdGlvbiBub3QgZm91bmQgZm9yIGVuZHBvaW50ICcgKyBtc2cuZW5kcG9pbnROYW1lICsgJy4gSWNlIGNhbmRpZGF0ZSB3aWxsIGJlIGlnbm9yZWQ6ICcgKyBjYW5kaWRhdGUpXG4gICAgICAgICAgICAudGhlbihjb25uZWN0aW9uID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCBzdHJlYW0gPSBjb25uZWN0aW9uLnN0cmVhbTtcbiAgICAgICAgICAgICAgICBzdHJlYW0uZ2V0V2ViUnRjUGVlcigpLmFkZEljZUNhbmRpZGF0ZShjYW5kaWRhdGUpLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcignRXJyb3IgYWRkaW5nIGNhbmRpZGF0ZSBmb3IgJyArIHN0cmVhbS5zdHJlYW1JZFxuICAgICAgICAgICAgICAgICAgICAgICAgKyAnIHN0cmVhbSBvZiBlbmRwb2ludCAnICsgbXNnLmVuZHBvaW50TmFtZSArICc6ICcgKyBlcnJvcik7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLmNhdGNoKG9wZW5WaWR1RXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3Iob3BlblZpZHVFcnJvcik7XG4gICAgICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgb25TZXNzaW9uQ2xvc2VkKG1zZyk6IHZvaWQge1xuICAgICAgICBjb25zb2xlLmluZm8oJ1Nlc3Npb24gY2xvc2VkOiAnICsgSlNPTi5zdHJpbmdpZnkobXNnKSk7XG4gICAgICAgIGNvbnN0IHMgPSBtc2cuc2Vzc2lvbklkO1xuICAgICAgICBpZiAocyAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnc2Vzc2lvbi1jbG9zZWQnLCBbe1xuICAgICAgICAgICAgICAgIHNlc3Npb246IHNcbiAgICAgICAgICAgIH1dKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvbnNvbGUud2FybignU2Vzc2lvbiB1bmRlZmluZWQgb24gc2Vzc2lvbiBjbG9zZWQnLCBtc2cpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIG9uTG9zdENvbm5lY3Rpb24oKTogdm9pZCB7XG5cbiAgICAgICAgLyppZiAoIXRoaXMuY29ubmVjdGlvbikge1xuXG4gICAgICAgICAgICBjb25zb2xlLndhcm4oJ05vdCBjb25uZWN0ZWQgdG8gc2Vzc2lvbjogaWYgeW91IGFyZSBub3QgZGVidWdnaW5nLCB0aGlzIGlzIHByb2JhYmx5IGEgY2VydGlmaWNhdGUgZXJyb3InKTtcblxuICAgICAgICAgICAgY29uc3QgdXJsID0gJ2h0dHBzOi8vJyArIHRoaXMub3BlbnZpZHUuZ2V0V3NVcmkoKS5zcGxpdCgnd3NzOi8vJylbMV0uc3BsaXQoJy9vcGVudmlkdScpWzBdO1xuICAgICAgICAgICAgaWYgKHdpbmRvdy5jb25maXJtKCdJZiB5b3UgYXJlIG5vdCBkZWJ1Z2dpbmcsIHRoaXMgaXMgcHJvYmFibHkgYSBjZXJ0aWZpY2F0ZSBlcnJvciBhdCBcXFwiJyArIHVybCArICdcXFwiXFxuXFxuQ2xpY2sgT0sgdG8gbmF2aWdhdGUgYW5kIGFjY2VwdCBpdCcpKSB7XG4gICAgICAgICAgICAgICAgbG9jYXRpb24uYXNzaWduKHVybCArICcvYWNjZXB0LWNlcnRpZmljYXRlJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH0qL1xuXG4gICAgICAgIGNvbnNvbGUud2FybignTG9zdCBjb25uZWN0aW9uIGluIFNlc3Npb24gJyArIHRoaXMuc2Vzc2lvbklkKTtcbiAgICAgICAgaWYgKCEhdGhpcy5zZXNzaW9uSWQgJiYgIXRoaXMuY29ubmVjdGlvbi5kaXNwb3NlZCkge1xuICAgICAgICAgICAgdGhpcy5sZWF2ZSh0cnVlLCAnbmV0d29ya0Rpc2Nvbm5lY3QnKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvblJlY292ZXJlZENvbm5lY3Rpb24oKTogdm9pZCB7XG4gICAgICAgIGNvbnNvbGUud2FybignUmVjb3ZlcmVkIGNvbm5lY3Rpb24gaW4gU2Vzc2lvbiAnICsgdGhpcy5zZXNzaW9uSWQpO1xuICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnY29ubmVjdGlvblJlY292ZXJlZCcsIFtdKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgb25NZWRpYUVycm9yKHBhcmFtcyk6IHZvaWQge1xuXG4gICAgICAgIGNvbnNvbGUuZXJyb3IoJ01lZGlhIGVycm9yOiAnICsgSlNPTi5zdHJpbmdpZnkocGFyYW1zKSk7XG4gICAgICAgIGNvbnN0IGVyciA9IHBhcmFtcy5lcnJvcjtcbiAgICAgICAgaWYgKGVycikge1xuICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ2Vycm9yLW1lZGlhJywgW3tcbiAgICAgICAgICAgICAgICBlcnJvcjogZXJyXG4gICAgICAgICAgICB9XSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjb25zb2xlLndhcm4oJ1JlY2VpdmVkIHVuZGVmaW5lZCBtZWRpYSBlcnJvci4gUGFyYW1zOicsIHBhcmFtcyk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgb25SZWNvcmRpbmdTdGFydGVkKHJlc3BvbnNlKTogdm9pZCB7XG4gICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdyZWNvcmRpbmdTdGFydGVkJywgW25ldyBSZWNvcmRpbmdFdmVudCh0aGlzLCAncmVjb3JkaW5nU3RhcnRlZCcsIHJlc3BvbnNlLmlkLCByZXNwb25zZS5uYW1lKV0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvblJlY29yZGluZ1N0b3BwZWQocmVzcG9uc2UpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3JlY29yZGluZ1N0b3BwZWQnLCBbbmV3IFJlY29yZGluZ0V2ZW50KHRoaXMsICdyZWNvcmRpbmdTdG9wcGVkJywgcmVzcG9uc2UuaWQsIHJlc3BvbnNlLm5hbWUpXSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGVtaXRFdmVudCh0eXBlOiBzdHJpbmcsIGV2ZW50QXJyYXk6IGFueVtdKTogdm9pZCB7XG4gICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KHR5cGUsIGV2ZW50QXJyYXkpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBsZWF2ZShmb3JjZWQ6IGJvb2xlYW4sIHJlYXNvbjogc3RyaW5nKTogdm9pZCB7XG5cbiAgICAgICAgZm9yY2VkID0gISFmb3JjZWQ7XG4gICAgICAgIGNvbnNvbGUuaW5mbygnTGVhdmluZyBTZXNzaW9uIChmb3JjZWQ9JyArIGZvcmNlZCArICcpJyk7XG5cbiAgICAgICAgaWYgKCEhdGhpcy5jb25uZWN0aW9uKSB7XG4gICAgICAgICAgICBpZiAoIXRoaXMuY29ubmVjdGlvbi5kaXNwb3NlZCAmJiAhZm9yY2VkKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5vcGVudmlkdS5zZW5kUmVxdWVzdCgnbGVhdmVSb29tJywgKGVycm9yLCByZXNwb25zZSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBpZiAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHRoaXMub3BlbnZpZHUuY2xvc2VXcygpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLm9wZW52aWR1LmNsb3NlV3MoKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5zdG9wUHVibGlzaGVyU3RyZWFtKHJlYXNvbik7XG5cbiAgICAgICAgICAgIGlmICghdGhpcy5jb25uZWN0aW9uLmRpc3Bvc2VkKSB7XG4gICAgICAgICAgICAgICAgLy8gTWFrZSBTZXNzaW9uIG9iamVjdCBkaXNwYXRjaCAnc2Vzc2lvbkRpc2Nvbm5lY3RlZCcgZXZlbnQgKGlmIGl0IGlzIG5vdCBhbHJlYWR5IGRpc3Bvc2VkKVxuICAgICAgICAgICAgICAgIGNvbnN0IHNlc3Npb25EaXNjb25uZWN0RXZlbnQgPSBuZXcgU2Vzc2lvbkRpc2Nvbm5lY3RlZEV2ZW50KHRoaXMsIHJlYXNvbik7XG4gICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3Nlc3Npb25EaXNjb25uZWN0ZWQnLCBbc2Vzc2lvbkRpc2Nvbm5lY3RFdmVudF0pO1xuICAgICAgICAgICAgICAgIHNlc3Npb25EaXNjb25uZWN0RXZlbnQuY2FsbERlZmF1bHRCZWhhdmlvcigpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY29uc29sZS53YXJuKCdZb3Ugd2VyZSBub3QgY29ubmVjdGVkIHRvIHRoZSBzZXNzaW9uICcgKyB0aGlzLnNlc3Npb25JZCk7XG4gICAgICAgIH1cbiAgICB9XG5cblxuICAgIC8qIFByaXZhdGUgbWV0aG9kcyAqL1xuXG4gICAgcHJpdmF0ZSBjb25uZWN0QXV4KHRva2VuOiBzdHJpbmcpOiBQcm9taXNlPGFueT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5vcGVudmlkdS5zdGFydFdzKChlcnJvcikgPT4ge1xuICAgICAgICAgICAgICAgIGlmICghIWVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcblxuICAgICAgICAgICAgICAgICAgICBjb25zdCBqb2luUGFyYW1zID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgdG9rZW46ICghIXRva2VuKSA/IHRva2VuIDogJycsXG4gICAgICAgICAgICAgICAgICAgICAgICBzZXNzaW9uOiB0aGlzLnNlc3Npb25JZCxcbiAgICAgICAgICAgICAgICAgICAgICAgIG1ldGFkYXRhOiAhIXRoaXMub3B0aW9ucy5tZXRhZGF0YSA/IHRoaXMub3B0aW9ucy5tZXRhZGF0YSA6ICcnLFxuICAgICAgICAgICAgICAgICAgICAgICAgc2VjcmV0OiB0aGlzLm9wZW52aWR1LmdldFNlY3JldCgpLFxuICAgICAgICAgICAgICAgICAgICAgICAgcmVjb3JkZXI6IHRoaXMub3BlbnZpZHUuZ2V0UmVjb3JkZXIoKSxcbiAgICAgICAgICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgICAgICAgICB0aGlzLm9wZW52aWR1LnNlbmRSZXF1ZXN0KCdqb2luUm9vbScsIGpvaW5QYXJhbXMsIChlcnJvciwgcmVzcG9uc2UpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghIWVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBJbml0aWFsaXplIGNhcGFiaWxpdGllcyBvYmplY3Qgd2l0aCB0aGUgcm9sZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY2FwYWJpbGl0aWVzID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdWJzY3JpYmU6IHRydWUsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHB1Ymxpc2g6IHRoaXMub3BlbnZpZHUucm9sZSAhPT0gJ1NVQlNDUklCRVInLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3JjZVVucHVibGlzaDogdGhpcy5vcGVudmlkdS5yb2xlID09PSAnTU9ERVJBVE9SJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yY2VEaXNjb25uZWN0OiB0aGlzLm9wZW52aWR1LnJvbGUgPT09ICdNT0RFUkFUT1InXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEluaXRpYWxpemUgbG9jYWwgQ29ubmVjdGlvbiBvYmplY3Qgd2l0aCB2YWx1ZXMgcmV0dXJuZWQgYnkgb3BlbnZpZHUtc2VydmVyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jb25uZWN0aW9uID0gbmV3IENvbm5lY3Rpb24odGhpcyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jb25uZWN0aW9uLmNvbm5lY3Rpb25JZCA9IHJlc3BvbnNlLmlkO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY29ubmVjdGlvbi5kYXRhID0gcmVzcG9uc2UubWV0YWRhdGE7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBJbml0aWFsaXplIHJlbW90ZSBDb25uZWN0aW9ucyB3aXRoIHZhbHVlIHJldHVybmVkIGJ5IG9wZW52aWR1LXNlcnZlclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGV2ZW50cyA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29ubmVjdGlvbnM6IG5ldyBBcnJheTxDb25uZWN0aW9uPigpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJlYW1zOiBuZXcgQXJyYXk8U3RyZWFtPigpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBleGlzdGluZ1BhcnRpY2lwYW50czogQ29ubmVjdGlvbk9wdGlvbnNbXSA9IHJlc3BvbnNlLnZhbHVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV4aXN0aW5nUGFydGljaXBhbnRzLmZvckVhY2gocGFydGljaXBhbnQgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBjb25uZWN0aW9uID0gbmV3IENvbm5lY3Rpb24odGhpcywgcGFydGljaXBhbnQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnJlbW90ZUNvbm5lY3Rpb25zW2Nvbm5lY3Rpb24uY29ubmVjdGlvbklkXSA9IGNvbm5lY3Rpb247XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV2ZW50cy5jb25uZWN0aW9ucy5wdXNoKGNvbm5lY3Rpb24pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoISFjb25uZWN0aW9uLnN0cmVhbSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5yZW1vdGVTdHJlYW1zQ3JlYXRlZFtjb25uZWN0aW9uLnN0cmVhbS5zdHJlYW1JZF0gPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXZlbnRzLnN0cmVhbXMucHVzaChjb25uZWN0aW9uLnN0cmVhbSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIE93biAnY29ubmVjdGlvbkNyZWF0ZWQnIGV2ZW50XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ2Nvbm5lY3Rpb25DcmVhdGVkJywgW25ldyBDb25uZWN0aW9uRXZlbnQoZmFsc2UsIHRoaXMsICdjb25uZWN0aW9uQ3JlYXRlZCcsIHRoaXMuY29ubmVjdGlvbiwgJycpXSk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBPbmUgJ2Nvbm5lY3Rpb25DcmVhdGVkJyBldmVudCBmb3IgZWFjaCBleGlzdGluZyBjb25uZWN0aW9uIGluIHRoZSBzZXNzaW9uXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZXZlbnRzLmNvbm5lY3Rpb25zLmZvckVhY2goY29ubmVjdGlvbiA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdjb25uZWN0aW9uQ3JlYXRlZCcsIFtuZXcgQ29ubmVjdGlvbkV2ZW50KGZhbHNlLCB0aGlzLCAnY29ubmVjdGlvbkNyZWF0ZWQnLCBjb25uZWN0aW9uLCAnJyldKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIE9uZSAnc3RyZWFtQ3JlYXRlZCcgZXZlbnQgZm9yIGVhY2ggYWN0aXZlIHN0cmVhbSBpbiB0aGUgc2Vzc2lvblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV2ZW50cy5zdHJlYW1zLmZvckVhY2goc3RyZWFtID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3N0cmVhbUNyZWF0ZWQnLCBbbmV3IFN0cmVhbUV2ZW50KGZhbHNlLCB0aGlzLCAnc3RyZWFtQ3JlYXRlZCcsIHN0cmVhbSwgJycpXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBwcml2YXRlIHN0b3BQdWJsaXNoZXJTdHJlYW0ocmVhc29uOiBzdHJpbmcpIHtcbiAgICAgICAgaWYgKCEhdGhpcy5jb25uZWN0aW9uLnN0cmVhbSkge1xuICAgICAgICAgICAgLy8gRGlzcG9zZSBQdWJsaXNoZXIncyAgbG9jYWwgc3RyZWFtXG4gICAgICAgICAgICB0aGlzLmNvbm5lY3Rpb24uc3RyZWFtLmRpc3Bvc2VXZWJSdGNQZWVyKCk7XG4gICAgICAgICAgICBpZiAodGhpcy5jb25uZWN0aW9uLnN0cmVhbS5pc0xvY2FsU3RyZWFtUHVibGlzaGVkKSB7XG4gICAgICAgICAgICAgICAgLy8gTWFrZSBQdWJsaXNoZXIgb2JqZWN0IGRpc3BhdGNoICdzdHJlYW1EZXN0cm95ZWQnIGV2ZW50IGlmIHRoZSBTdHJlYW0gd2FzIHB1Ymxpc2hlZFxuICAgICAgICAgICAgICAgIHRoaXMuY29ubmVjdGlvbi5zdHJlYW0uZWUuZW1pdEV2ZW50KCdsb2NhbC1zdHJlYW0tZGVzdHJveWVkJywgW3JlYXNvbl0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBzdHJpbmdDbGllbnRNZXRhZGF0YShtZXRhZGF0YTogYW55KTogc3RyaW5nIHtcbiAgICAgICAgaWYgKHR5cGVvZiBtZXRhZGF0YSAhPT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgIHJldHVybiBKU09OLnN0cmluZ2lmeShtZXRhZGF0YSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gbWV0YWRhdGE7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIGdldENvbm5lY3Rpb24oY29ubmVjdGlvbklkOiBzdHJpbmcsIGVycm9yTWVzc2FnZTogc3RyaW5nKTogUHJvbWlzZTxDb25uZWN0aW9uPiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZTxDb25uZWN0aW9uPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICBjb25zdCBjb25uZWN0aW9uID0gdGhpcy5yZW1vdGVDb25uZWN0aW9uc1tjb25uZWN0aW9uSWRdO1xuICAgICAgICAgICAgaWYgKCEhY29ubmVjdGlvbikge1xuICAgICAgICAgICAgICAgIC8vIFJlc29sdmUgcmVtb3RlIGNvbm5lY3Rpb25cbiAgICAgICAgICAgICAgICByZXNvbHZlKGNvbm5lY3Rpb24pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5jb25uZWN0aW9uLmNvbm5lY3Rpb25JZCA9PT0gY29ubmVjdGlvbklkKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIFJlc29sdmUgbG9jYWwgY29ubmVjdGlvblxuICAgICAgICAgICAgICAgICAgICByZXNvbHZlKHRoaXMuY29ubmVjdGlvbik7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gQ29ubmVjdGlvbiBub3QgZm91bmQuIFJlamVjdCB3aXRoIE9wZW5WaWR1RXJyb3JcbiAgICAgICAgICAgICAgICAgICAgcmVqZWN0KG5ldyBPcGVuVmlkdUVycm9yKE9wZW5WaWR1RXJyb3JOYW1lLkdFTkVSSUNfRVJST1IsIGVycm9yTWVzc2FnZSkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBnZXRSZW1vdGVDb25uZWN0aW9uKGNvbm5lY3Rpb25JZDogc3RyaW5nLCBlcnJvck1lc3NhZ2U6IHN0cmluZyk6IFByb21pc2U8Q29ubmVjdGlvbj4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2U8Q29ubmVjdGlvbj4oKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgY29uc3QgY29ubmVjdGlvbiA9IHRoaXMucmVtb3RlQ29ubmVjdGlvbnNbY29ubmVjdGlvbklkXTtcbiAgICAgICAgICAgIGlmICghIWNvbm5lY3Rpb24pIHtcbiAgICAgICAgICAgICAgICAvLyBSZXNvbHZlIHJlbW90ZSBjb25uZWN0aW9uXG4gICAgICAgICAgICAgICAgcmVzb2x2ZShjb25uZWN0aW9uKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgLy8gUmVtb3RlIGNvbm5lY3Rpb24gbm90IGZvdW5kLiBSZWplY3Qgd2l0aCBPcGVuVmlkdUVycm9yXG4gICAgICAgICAgICAgICAgcmVqZWN0KG5ldyBPcGVuVmlkdUVycm9yKE9wZW5WaWR1RXJyb3JOYW1lLkdFTkVSSUNfRVJST1IsIGVycm9yTWVzc2FnZSkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBwcml2YXRlIHByb2Nlc3NUb2tlbih0b2tlbjogc3RyaW5nKTogdm9pZCB7XG4gICAgICAgIGNvbnN0IHVybCA9IG5ldyBVUkwodG9rZW4pO1xuICAgICAgICB0aGlzLnNlc3Npb25JZCA9IDxzdHJpbmc+dXJsLnNlYXJjaFBhcmFtcy5nZXQoJ3Nlc3Npb25JZCcpO1xuICAgICAgICBjb25zdCBzZWNyZXQgPSB1cmwuc2VhcmNoUGFyYW1zLmdldCgnc2VjcmV0Jyk7XG4gICAgICAgIGNvbnN0IHJlY29yZGVyID0gdXJsLnNlYXJjaFBhcmFtcy5nZXQoJ3JlY29yZGVyJyk7XG4gICAgICAgIGNvbnN0IHR1cm5Vc2VybmFtZSA9IHVybC5zZWFyY2hQYXJhbXMuZ2V0KCd0dXJuVXNlcm5hbWUnKTtcbiAgICAgICAgY29uc3QgdHVybkNyZWRlbnRpYWwgPSB1cmwuc2VhcmNoUGFyYW1zLmdldCgndHVybkNyZWRlbnRpYWwnKTtcbiAgICAgICAgY29uc3Qgcm9sZSA9IHVybC5zZWFyY2hQYXJhbXMuZ2V0KCdyb2xlJyk7XG5cbiAgICAgICAgaWYgKCEhc2VjcmV0KSB7XG4gICAgICAgICAgICB0aGlzLm9wZW52aWR1LnNlY3JldCA9IHNlY3JldDtcbiAgICAgICAgfVxuICAgICAgICBpZiAoISFyZWNvcmRlcikge1xuICAgICAgICAgICAgdGhpcy5vcGVudmlkdS5yZWNvcmRlciA9IHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCEhdHVyblVzZXJuYW1lICYmICEhdHVybkNyZWRlbnRpYWwpIHtcbiAgICAgICAgICAgIGNvbnN0IHN0dW5VcmwgPSAnc3R1bjonICsgdXJsLmhvc3RuYW1lICsgJzozNDc4JztcbiAgICAgICAgICAgIGNvbnN0IHR1cm5VcmwxID0gJ3R1cm46JyArIHVybC5ob3N0bmFtZSArICc6MzQ3OCc7XG4gICAgICAgICAgICBjb25zdCB0dXJuVXJsMiA9IHR1cm5VcmwxICsgJz90cmFuc3BvcnQ9dGNwJztcbiAgICAgICAgICAgIHRoaXMub3BlbnZpZHUuaWNlU2VydmVycyA9IFtcbiAgICAgICAgICAgICAgICB7IHVybHM6IFtzdHVuVXJsXSB9LFxuICAgICAgICAgICAgICAgIHsgdXJsczogW3R1cm5VcmwxLCB0dXJuVXJsMl0sIHVzZXJuYW1lOiB0dXJuVXNlcm5hbWUsIGNyZWRlbnRpYWw6IHR1cm5DcmVkZW50aWFsIH1cbiAgICAgICAgICAgIF07XG4gICAgICAgICAgICBjb25zb2xlLmxvZygnVFVSTiB0ZW1wIGNyZWRlbnRpYWxzIFsnICsgdHVyblVzZXJuYW1lICsgJzonICsgdHVybkNyZWRlbnRpYWwgKyAnXScpO1xuICAgICAgICB9XG4gICAgICAgIGlmICghIXJvbGUpIHtcbiAgICAgICAgICAgIHRoaXMub3BlbnZpZHUucm9sZSA9IHJvbGU7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLm9wZW52aWR1LndzVXJpID0gJ3dzczovLycgKyB1cmwuaG9zdCArICcvb3BlbnZpZHUnO1xuICAgIH1cblxufSIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTctMjAxOCBPcGVuVmlkdSAoaHR0cHM6Ly9vcGVudmlkdS5pby8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuaW1wb3J0IHsgQ29ubmVjdGlvbiB9IGZyb20gJy4vQ29ubmVjdGlvbic7XG5pbXBvcnQgeyBTZXNzaW9uIH0gZnJvbSAnLi9TZXNzaW9uJztcbmltcG9ydCB7IFN0cmVhbU1hbmFnZXIgfSBmcm9tICcuL1N0cmVhbU1hbmFnZXInO1xuaW1wb3J0IHsgSW5ib3VuZFN0cmVhbU9wdGlvbnMgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHJpdmF0ZS9JbmJvdW5kU3RyZWFtT3B0aW9ucyc7XG5pbXBvcnQgeyBPdXRib3VuZFN0cmVhbU9wdGlvbnMgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHJpdmF0ZS9PdXRib3VuZFN0cmVhbU9wdGlvbnMnO1xuaW1wb3J0IHsgV2ViUnRjUGVlciwgV2ViUnRjUGVlclNlbmRvbmx5LCBXZWJSdGNQZWVyUmVjdm9ubHksIFdlYlJ0Y1BlZXJTZW5kcmVjdiB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvV2ViUnRjUGVlci9XZWJSdGNQZWVyJztcbmltcG9ydCB7IFdlYlJ0Y1N0YXRzIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9XZWJSdGNTdGF0cy9XZWJSdGNTdGF0cyc7XG5pbXBvcnQgeyBQdWJsaXNoZXJTcGVha2luZ0V2ZW50IH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvUHVibGlzaGVyU3BlYWtpbmdFdmVudCc7XG5cbmltcG9ydCBFdmVudEVtaXR0ZXIgPSByZXF1aXJlKCd3b2xmeTg3LWV2ZW50ZW1pdHRlcicpO1xuaW1wb3J0IGhhcmsgPSByZXF1aXJlKCdoYXJrJyk7XG5pbXBvcnQgeyBPcGVuVmlkdUVycm9yLCBPcGVuVmlkdUVycm9yTmFtZSB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRW51bXMvT3BlblZpZHVFcnJvcic7XG5cblxuLyoqXG4gKiBSZXByZXNlbnRzIGVhY2ggb25lIG9mIHRoZSBtZWRpYSBzdHJlYW1zIGF2YWlsYWJsZSBpbiBPcGVuVmlkdSBTZXJ2ZXIgZm9yIGNlcnRhaW4gc2Vzc2lvbi5cbiAqIEVhY2ggW1tQdWJsaXNoZXJdXSBhbmQgW1tTdWJzY3JpYmVyXV0gaGFzIGFuIGF0dHJpYnV0ZSBvZiB0eXBlIFN0cmVhbSwgYXMgdGhleSBnaXZlIGFjY2Vzc1xuICogdG8gb25lIG9mIHRoZW0gKHNlbmRpbmcgYW5kIHJlY2VpdmluZyBpdCwgcmVzcGVjdGl2ZWx5KVxuICovXG5leHBvcnQgY2xhc3MgU3RyZWFtIHtcblxuICAgIC8qKlxuICAgICAqIFRoZSBDb25uZWN0aW9uIG9iamVjdCB0aGF0IGlzIHB1Ymxpc2hpbmcgdGhlIHN0cmVhbVxuICAgICAqL1xuICAgIGNvbm5lY3Rpb246IENvbm5lY3Rpb247XG5cbiAgICAvKipcbiAgICAgKiBGcmFtZSByYXRlIG9mIHRoZSB2aWRlbyBpbiBmcmFtZXMgcGVyIHNlY29uZC4gVGhpcyBwcm9wZXJ0eSBpcyBvbmx5IGRlZmluZWQgaWYgdGhlIFtbUHVibGlzaGVyXV0gb2ZcbiAgICAgKiB0aGUgc3RyZWFtIHdhcyBpbml0aWFsaXplZCBwYXNzaW5nIGEgX2ZyYW1lUmF0ZV8gcHJvcGVydHkgb24gW1tPcGVuVmlkdS5pbml0UHVibGlzaGVyXV0gbWV0aG9kXG4gICAgICovXG4gICAgZnJhbWVSYXRlPzogbnVtYmVyO1xuXG4gICAgLyoqXG4gICAgICogV2hldGhlciB0aGUgc3RyZWFtIGhhcyBhIHZpZGVvIHRyYWNrIG9yIG5vdFxuICAgICAqL1xuICAgIGhhc1ZpZGVvOiBib29sZWFuO1xuXG4gICAgLyoqXG4gICAgICogV2hldGhlciB0aGUgc3RyZWFtIGhhcyBhbiBhdWRpbyB0cmFjayBvciBub3RcbiAgICAgKi9cbiAgICBoYXNBdWRpbzogYm9vbGVhbjtcblxuICAgIC8qKlxuICAgICAqIFdoZXRoZXIgdGhlIHN0cmVhbSBoYXMgdGhlIHZpZGVvIHRyYWNrIG11dGVkIG9yIHVubXV0ZWQuIElmIFtbaGFzVmlkZW9dXSBpcyBmYWxzZSwgdGhpcyBwcm9wZXJ0eSBpcyB1bmRlZmluZWQuXG4gICAgICpcbiAgICAgKiBUaGlzIHByb3BlcnR5IG1heSBjaGFuZ2UgaWYgdGhlIFB1Ymxpc2hlciBwdWJsaXNoaW5nIHRoZSBzdHJlYW0gY2FsbHMgW1tQdWJsaXNoZXIucHVibGlzaFZpZGVvXV0uIFdoZW5ldmVyIHRoaXMgaGFwcGVucyBhIFtbU3RyZWFtUHJvcGVydHlDaGFuZ2VkRXZlbnRdXSB3aWxsIGJlIGRpc3BhdGNoZWRcbiAgICAgKiBieSB0aGUgU2Vzc2lvbiBvYmplY3QgYXMgd2VsbCBhcyBieSB0aGUgYWZmZWN0ZWQgU3Vic2NyaWJlci9QdWJsaXNoZXIgb2JqZWN0XG4gICAgICovXG4gICAgdmlkZW9BY3RpdmU6IGJvb2xlYW47XG5cbiAgICAvKipcbiAgICAgKiBXaGV0aGVyIHRoZSBzdHJlYW0gaGFzIHRoZSBhdWRpbyB0cmFjayBtdXRlZCBvciB1bm11dGVkLiBJZiBbW2hhc0F1ZGlvXV0gaXMgZmFsc2UsIHRoaXMgcHJvcGVydHkgaXMgdW5kZWZpbmVkXG4gICAgICpcbiAgICAgKiBUaGlzIHByb3BlcnR5IG1heSBjaGFuZ2UgaWYgdGhlIFB1Ymxpc2hlciBwdWJsaXNoaW5nIHRoZSBzdHJlYW0gY2FsbHMgW1tQdWJsaXNoZXIucHVibGlzaEF1ZGlvXV0uIFdoZW5ldmVyIHRoaXMgaGFwcGVucyBhIFtbU3RyZWFtUHJvcGVydHlDaGFuZ2VkRXZlbnRdXSB3aWxsIGJlIGRpc3BhdGNoZWRcbiAgICAgKiBieSB0aGUgU2Vzc2lvbiBvYmplY3QgYXMgd2VsbCBhcyBieSB0aGUgYWZmZWN0ZWQgU3Vic2NyaWJlci9QdWJsaXNoZXIgb2JqZWN0XG4gICAgICovXG4gICAgYXVkaW9BY3RpdmU6IGJvb2xlYW47XG5cbiAgICAvKipcbiAgICAgKiBVbmlxdWUgaWRlbnRpZmllciBvZiB0aGUgc3RyZWFtXG4gICAgICovXG4gICAgc3RyZWFtSWQ6IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIGBcIkNBTUVSQVwiYCwgYFwiU0NSRUVOXCJgIG9yIGBcIkNVU1RPTVwiYCAodGhlIGxhdHRlciB3aGVuIFtbUHVibGlzaGVyUHJvcGVydGllcy52aWRlb1NvdXJjZV1dIGlzIGEgTWVkaWFTdHJlYW1UcmFjayB3aGVuIGNhbGxpbmcgW1tPcGVuVmlkdS5pbml0UHVibGlzaGVyXV0pLlxuICAgICAqIElmIFtbaGFzVmlkZW9dXSBpcyBmYWxzZSwgdGhpcyBwcm9wZXJ0eSBpcyB1bmRlZmluZWRcbiAgICAgKi9cbiAgICB0eXBlT2ZWaWRlbz86IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIFN0cmVhbU1hbmFnZXIgb2JqZWN0IChbW1B1Ymxpc2hlcl1dIG9yIFtbU3Vic2NyaWJlcl1dKSBpbiBjaGFyZ2Ugb2YgZGlzcGxheWluZyB0aGlzIHN0cmVhbSBpbiB0aGUgRE9NXG4gICAgICovXG4gICAgc3RyZWFtTWFuYWdlcjogU3RyZWFtTWFuYWdlcjtcblxuICAgIC8qKlxuICAgICAqIFdpZHRoIGFuZCBoZWlnaHQgaW4gcGl4ZWxzIG9mIHRoZSBlbmNvZGVkIHZpZGVvIHN0cmVhbS4gSWYgW1toYXNWaWRlb11dIGlzIGZhbHNlLCB0aGlzIHByb3BlcnR5IGlzIHVuZGVmaW5lZFxuICAgICAqXG4gICAgICogVGhpcyBwcm9wZXJ0eSBtYXkgY2hhbmdlIGlmIHRoZSBQdWJsaXNoZXIgdGhhdCBpcyBwdWJsaXNoaW5nOlxuICAgICAqIC0gSWYgaXQgaXMgYSBtb2JpbGUgZGV2aWNlLCB3aGVuZXZlciB0aGUgdXNlciByb3RhdGVzIHRoZSBkZXZpY2UuXG4gICAgICogLSBJZiBpdCBpcyBzY3JlZW4tc2hhcmluZywgd2hlbmV2ZXIgdGhlIHVzZXIgY2hhbmdlcyB0aGUgc2l6ZSBvZiB0aGUgY2FwdHVyZWQgd2luZG93LlxuICAgICAqXG4gICAgICogV2hlbmV2ZXIgdGhpcyBoYXBwZW5zIGEgW1tTdHJlYW1Qcm9wZXJ0eUNoYW5nZWRFdmVudF1dIHdpbGwgYmUgZGlzcGF0Y2hlZCBieSB0aGUgU2Vzc2lvbiBvYmplY3QgYXMgd2VsbCBhcyBieSB0aGUgYWZmZWN0ZWQgU3Vic2NyaWJlci9QdWJsaXNoZXIgb2JqZWN0XG4gICAgICovXG4gICAgdmlkZW9EaW1lbnNpb25zOiB7IHdpZHRoOiBudW1iZXIsIGhlaWdodDogbnVtYmVyIH07XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgZWUgPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG5cbiAgICBwcml2YXRlIHdlYlJ0Y1BlZXI6IFdlYlJ0Y1BlZXI7XG4gICAgcHJpdmF0ZSBtZWRpYVN0cmVhbTogTWVkaWFTdHJlYW07XG4gICAgcHJpdmF0ZSB3ZWJSdGNTdGF0czogV2ViUnRjU3RhdHM7XG5cbiAgICBwcml2YXRlIGlzU3Vic2NyaWJlVG9SZW1vdGUgPSBmYWxzZTtcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBpc0xvY2FsU3RyZWFtUmVhZHlUb1B1Ymxpc2ggPSBmYWxzZTtcbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgaXNMb2NhbFN0cmVhbVB1Ymxpc2hlZCA9IGZhbHNlO1xuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBwdWJsaXNoZWRPbmNlID0gZmFsc2U7XG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHNlc3Npb246IFNlc3Npb247XG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGluYm91bmRTdHJlYW1PcHRzOiBJbmJvdW5kU3RyZWFtT3B0aW9ucztcbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgb3V0Ym91bmRTdHJlYW1PcHRzOiBPdXRib3VuZFN0cmVhbU9wdGlvbnM7XG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHNwZWVjaEV2ZW50OiBhbnk7XG5cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3RvcihzZXNzaW9uOiBTZXNzaW9uLCBvcHRpb25zOiBJbmJvdW5kU3RyZWFtT3B0aW9ucyB8IE91dGJvdW5kU3RyZWFtT3B0aW9ucyB8IHt9KSB7XG5cbiAgICAgICAgdGhpcy5zZXNzaW9uID0gc2Vzc2lvbjtcblxuICAgICAgICBpZiAob3B0aW9ucy5oYXNPd25Qcm9wZXJ0eSgnaWQnKSkge1xuICAgICAgICAgICAgLy8gSW5ib3VuZFN0cmVhbU9wdGlvbnM6IHN0cmVhbSBiZWxvbmdzIHRvIGEgU3Vic2NyaWJlclxuICAgICAgICAgICAgdGhpcy5pbmJvdW5kU3RyZWFtT3B0cyA9IDxJbmJvdW5kU3RyZWFtT3B0aW9ucz5vcHRpb25zO1xuICAgICAgICAgICAgdGhpcy5zdHJlYW1JZCA9IHRoaXMuaW5ib3VuZFN0cmVhbU9wdHMuaWQ7XG4gICAgICAgICAgICB0aGlzLmhhc0F1ZGlvID0gdGhpcy5pbmJvdW5kU3RyZWFtT3B0cy5oYXNBdWRpbztcbiAgICAgICAgICAgIHRoaXMuaGFzVmlkZW8gPSB0aGlzLmluYm91bmRTdHJlYW1PcHRzLmhhc1ZpZGVvO1xuICAgICAgICAgICAgaWYgKHRoaXMuaGFzQXVkaW8pIHtcbiAgICAgICAgICAgICAgICB0aGlzLmF1ZGlvQWN0aXZlID0gdGhpcy5pbmJvdW5kU3RyZWFtT3B0cy5hdWRpb0FjdGl2ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0aGlzLmhhc1ZpZGVvKSB7XG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb0FjdGl2ZSA9IHRoaXMuaW5ib3VuZFN0cmVhbU9wdHMudmlkZW9BY3RpdmU7XG4gICAgICAgICAgICAgICAgdGhpcy50eXBlT2ZWaWRlbyA9ICghdGhpcy5pbmJvdW5kU3RyZWFtT3B0cy50eXBlT2ZWaWRlbykgPyB1bmRlZmluZWQgOiB0aGlzLmluYm91bmRTdHJlYW1PcHRzLnR5cGVPZlZpZGVvO1xuICAgICAgICAgICAgICAgIHRoaXMuZnJhbWVSYXRlID0gKHRoaXMuaW5ib3VuZFN0cmVhbU9wdHMuZnJhbWVSYXRlID09PSAtMSkgPyB1bmRlZmluZWQgOiB0aGlzLmluYm91bmRTdHJlYW1PcHRzLmZyYW1lUmF0ZTtcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvRGltZW5zaW9ucyA9IHRoaXMuaW5ib3VuZFN0cmVhbU9wdHMudmlkZW9EaW1lbnNpb25zO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gT3V0Ym91bmRTdHJlYW1PcHRpb25zOiBzdHJlYW0gYmVsb25ncyB0byBhIFB1Ymxpc2hlclxuICAgICAgICAgICAgdGhpcy5vdXRib3VuZFN0cmVhbU9wdHMgPSA8T3V0Ym91bmRTdHJlYW1PcHRpb25zPm9wdGlvbnM7XG5cbiAgICAgICAgICAgIHRoaXMuaGFzQXVkaW8gPSB0aGlzLmlzU2VuZEF1ZGlvKCk7XG4gICAgICAgICAgICB0aGlzLmhhc1ZpZGVvID0gdGhpcy5pc1NlbmRWaWRlbygpO1xuXG4gICAgICAgICAgICBpZiAodGhpcy5oYXNBdWRpbykge1xuICAgICAgICAgICAgICAgIHRoaXMuYXVkaW9BY3RpdmUgPSAhIXRoaXMub3V0Ym91bmRTdHJlYW1PcHRzLnB1Ymxpc2hlclByb3BlcnRpZXMucHVibGlzaEF1ZGlvO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRoaXMuaGFzVmlkZW8pIHtcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvQWN0aXZlID0gISF0aGlzLm91dGJvdW5kU3RyZWFtT3B0cy5wdWJsaXNoZXJQcm9wZXJ0aWVzLnB1Ymxpc2hWaWRlbztcbiAgICAgICAgICAgICAgICB0aGlzLmZyYW1lUmF0ZSA9IHRoaXMub3V0Ym91bmRTdHJlYW1PcHRzLnB1Ymxpc2hlclByb3BlcnRpZXMuZnJhbWVSYXRlO1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLm91dGJvdW5kU3RyZWFtT3B0cy5wdWJsaXNoZXJQcm9wZXJ0aWVzLnZpZGVvU291cmNlIGluc3RhbmNlb2YgTWVkaWFTdHJlYW1UcmFjaykge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnR5cGVPZlZpZGVvID0gJ0NVU1RPTSc7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy50eXBlT2ZWaWRlbyA9IHRoaXMuaXNTZW5kU2NyZWVuKCkgPyAnU0NSRUVOJyA6ICdDQU1FUkEnO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuZWUub24oJ21lZGlhc3RyZWFtLXVwZGF0ZWQnLCAoKSA9PiB7XG4gICAgICAgICAgICB0aGlzLnN0cmVhbU1hbmFnZXIudXBkYXRlTWVkaWFTdHJlYW0odGhpcy5tZWRpYVN0cmVhbSk7XG4gICAgICAgICAgICBjb25zb2xlLmRlYnVnKCdWaWRlbyBzcmNPYmplY3QgWycgKyB0aGlzLm1lZGlhU3RyZWFtICsgJ10gdXBkYXRlZCBpbiBzdHJlYW0gWycgKyB0aGlzLnN0cmVhbUlkICsgJ10nKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG5cbiAgICAvKiBIaWRkZW4gbWV0aG9kcyAqL1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGdldE1lZGlhU3RyZWFtKCk6IE1lZGlhU3RyZWFtIHtcbiAgICAgICAgcmV0dXJuIHRoaXMubWVkaWFTdHJlYW07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHNldE1lZGlhU3RyZWFtKG1lZGlhU3RyZWFtOiBNZWRpYVN0cmVhbSk6IHZvaWQge1xuICAgICAgICB0aGlzLm1lZGlhU3RyZWFtID0gbWVkaWFTdHJlYW07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHVwZGF0ZU1lZGlhU3RyZWFtSW5WaWRlb3MoKSB7XG4gICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdtZWRpYXN0cmVhbS11cGRhdGVkJyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGdldFdlYlJ0Y1BlZXIoKTogV2ViUnRjUGVlciB7XG4gICAgICAgIHJldHVybiB0aGlzLndlYlJ0Y1BlZXI7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGdldFJUQ1BlZXJDb25uZWN0aW9uKCk6IFJUQ1BlZXJDb25uZWN0aW9uIHtcbiAgICAgICAgcmV0dXJuIHRoaXMud2ViUnRjUGVlci5wYztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgc3Vic2NyaWJlVG9NeVJlbW90ZSh2YWx1ZTogYm9vbGVhbik6IHZvaWQge1xuICAgICAgICB0aGlzLmlzU3Vic2NyaWJlVG9SZW1vdGUgPSB2YWx1ZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgc2V0T3V0Ym91bmRTdHJlYW1PcHRpb25zKG91dGJvdW5kU3RyZWFtT3B0czogT3V0Ym91bmRTdHJlYW1PcHRpb25zKTogdm9pZCB7XG4gICAgICAgIHRoaXMub3V0Ym91bmRTdHJlYW1PcHRzID0gb3V0Ym91bmRTdHJlYW1PcHRzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBzdWJzY3JpYmUoKTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIHRoaXMuaW5pdFdlYlJ0Y1BlZXJSZWNlaXZlKClcbiAgICAgICAgICAgICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBwdWJsaXNoKCk6IFByb21pc2U8YW55PiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICBpZiAodGhpcy5pc0xvY2FsU3RyZWFtUmVhZHlUb1B1Ymxpc2gpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmluaXRXZWJSdGNQZWVyU2VuZCgpXG4gICAgICAgICAgICAgICAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLm9uY2UoJ3N0cmVhbS1yZWFkeS10by1wdWJsaXNoJywgKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnB1Ymxpc2goKVxuICAgICAgICAgICAgICAgICAgICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgICAgICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGRpc3Bvc2VXZWJSdGNQZWVyKCk6IHZvaWQge1xuICAgICAgICBpZiAodGhpcy53ZWJSdGNQZWVyKSB7XG4gICAgICAgICAgICB0aGlzLndlYlJ0Y1BlZXIuZGlzcG9zZSgpO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLnNwZWVjaEV2ZW50KSB7XG4gICAgICAgICAgICB0aGlzLnNwZWVjaEV2ZW50LnN0b3AoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuc3RvcFdlYlJ0Y1N0YXRzKCk7XG5cbiAgICAgICAgY29uc29sZS5pbmZvKCghIXRoaXMub3V0Ym91bmRTdHJlYW1PcHRzID8gJ091dGJvdW5kICcgOiAnSW5ib3VuZCAnKSArIFwiV2ViUlRDUGVlciBmcm9tICdTdHJlYW0nIHdpdGggaWQgW1wiICsgdGhpcy5zdHJlYW1JZCArICddIGlzIG5vdyBjbG9zZWQnKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgZGlzcG9zZU1lZGlhU3RyZWFtKCk6IHZvaWQge1xuICAgICAgICBpZiAodGhpcy5tZWRpYVN0cmVhbSkge1xuICAgICAgICAgICAgdGhpcy5tZWRpYVN0cmVhbS5nZXRBdWRpb1RyYWNrcygpLmZvckVhY2goKHRyYWNrKSA9PiB7XG4gICAgICAgICAgICAgICAgdHJhY2suc3RvcCgpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB0aGlzLm1lZGlhU3RyZWFtLmdldFZpZGVvVHJhY2tzKCkuZm9yRWFjaCgodHJhY2spID0+IHtcbiAgICAgICAgICAgICAgICB0cmFjay5zdG9wKCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGRlbGV0ZSB0aGlzLm1lZGlhU3RyZWFtO1xuICAgICAgICB9XG4gICAgICAgIGNvbnNvbGUuaW5mbygoISF0aGlzLm91dGJvdW5kU3RyZWFtT3B0cyA/ICdMb2NhbCAnIDogJ1JlbW90ZSAnKSArIFwiTWVkaWFTdHJlYW0gZnJvbSAnU3RyZWFtJyB3aXRoIGlkIFtcIiArIHRoaXMuc3RyZWFtSWQgKyAnXSBpcyBub3cgZGlzcG9zZWQnKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgZGlzcGxheU15UmVtb3RlKCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gdGhpcy5pc1N1YnNjcmliZVRvUmVtb3RlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBpc1NlbmRBdWRpbygpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuICghIXRoaXMub3V0Ym91bmRTdHJlYW1PcHRzICYmXG4gICAgICAgICAgICB0aGlzLm91dGJvdW5kU3RyZWFtT3B0cy5wdWJsaXNoZXJQcm9wZXJ0aWVzLmF1ZGlvU291cmNlICE9PSBudWxsICYmXG4gICAgICAgICAgICB0aGlzLm91dGJvdW5kU3RyZWFtT3B0cy5wdWJsaXNoZXJQcm9wZXJ0aWVzLmF1ZGlvU291cmNlICE9PSBmYWxzZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGlzU2VuZFZpZGVvKCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gKCEhdGhpcy5vdXRib3VuZFN0cmVhbU9wdHMgJiZcbiAgICAgICAgICAgIHRoaXMub3V0Ym91bmRTdHJlYW1PcHRzLnB1Ymxpc2hlclByb3BlcnRpZXMudmlkZW9Tb3VyY2UgIT09IG51bGwgJiZcbiAgICAgICAgICAgIHRoaXMub3V0Ym91bmRTdHJlYW1PcHRzLnB1Ymxpc2hlclByb3BlcnRpZXMudmlkZW9Tb3VyY2UgIT09IGZhbHNlKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgaXNTZW5kU2NyZWVuKCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gKCEhdGhpcy5vdXRib3VuZFN0cmVhbU9wdHMgJiZcbiAgICAgICAgICAgIHRoaXMub3V0Ym91bmRTdHJlYW1PcHRzLnB1Ymxpc2hlclByb3BlcnRpZXMudmlkZW9Tb3VyY2UgPT09ICdzY3JlZW4nKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgc2V0U3BlZWNoRXZlbnRJZk5vdEV4aXN0cygpOiB2b2lkIHtcbiAgICAgICAgaWYgKCF0aGlzLnNwZWVjaEV2ZW50KSB7XG4gICAgICAgICAgICBjb25zdCBoYXJrT3B0aW9ucyA9IHRoaXMuc2Vzc2lvbi5vcGVudmlkdS5hZHZhbmNlZENvbmZpZ3VyYXRpb24ucHVibGlzaGVyU3BlYWtpbmdFdmVudHNPcHRpb25zIHx8IHt9O1xuICAgICAgICAgICAgaGFya09wdGlvbnMuaW50ZXJ2YWwgPSAodHlwZW9mIGhhcmtPcHRpb25zLmludGVydmFsID09PSAnbnVtYmVyJykgPyBoYXJrT3B0aW9ucy5pbnRlcnZhbCA6IDUwO1xuICAgICAgICAgICAgaGFya09wdGlvbnMudGhyZXNob2xkID0gKHR5cGVvZiBoYXJrT3B0aW9ucy50aHJlc2hvbGQgPT09ICdudW1iZXInKSA/IGhhcmtPcHRpb25zLnRocmVzaG9sZCA6IC01MDtcblxuICAgICAgICAgICAgdGhpcy5zcGVlY2hFdmVudCA9IGhhcmsodGhpcy5tZWRpYVN0cmVhbSwgaGFya09wdGlvbnMpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGVuYWJsZVNwZWFraW5nRXZlbnRzKCk6IHZvaWQge1xuICAgICAgICB0aGlzLnNldFNwZWVjaEV2ZW50SWZOb3RFeGlzdHMoKTtcbiAgICAgICAgdGhpcy5zcGVlY2hFdmVudC5vbignc3BlYWtpbmcnLCAoKSA9PiB7XG4gICAgICAgICAgICB0aGlzLnNlc3Npb24uZW1pdEV2ZW50KCdwdWJsaXNoZXJTdGFydFNwZWFraW5nJywgW25ldyBQdWJsaXNoZXJTcGVha2luZ0V2ZW50KHRoaXMuc2Vzc2lvbiwgJ3B1Ymxpc2hlclN0YXJ0U3BlYWtpbmcnLCB0aGlzLmNvbm5lY3Rpb24sIHRoaXMuc3RyZWFtSWQpXSk7XG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLnNwZWVjaEV2ZW50Lm9uKCdzdG9wcGVkX3NwZWFraW5nJywgKCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5zZXNzaW9uLmVtaXRFdmVudCgncHVibGlzaGVyU3RvcFNwZWFraW5nJywgW25ldyBQdWJsaXNoZXJTcGVha2luZ0V2ZW50KHRoaXMuc2Vzc2lvbiwgJ3B1Ymxpc2hlclN0b3BTcGVha2luZycsIHRoaXMuY29ubmVjdGlvbiwgdGhpcy5zdHJlYW1JZCldKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGVuYWJsZU9uY2VTcGVha2luZ0V2ZW50cygpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5zZXRTcGVlY2hFdmVudElmTm90RXhpc3RzKCk7XG4gICAgICAgIHRoaXMuc3BlZWNoRXZlbnQub24oJ3NwZWFraW5nJywgKCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5zZXNzaW9uLmVtaXRFdmVudCgncHVibGlzaGVyU3RhcnRTcGVha2luZycsIFtuZXcgUHVibGlzaGVyU3BlYWtpbmdFdmVudCh0aGlzLnNlc3Npb24sICdwdWJsaXNoZXJTdGFydFNwZWFraW5nJywgdGhpcy5jb25uZWN0aW9uLCB0aGlzLnN0cmVhbUlkKV0pO1xuICAgICAgICAgICAgdGhpcy5kaXNhYmxlU3BlYWtpbmdFdmVudHMoKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMuc3BlZWNoRXZlbnQub24oJ3N0b3BwZWRfc3BlYWtpbmcnLCAoKSA9PiB7XG4gICAgICAgICAgICB0aGlzLnNlc3Npb24uZW1pdEV2ZW50KCdwdWJsaXNoZXJTdG9wU3BlYWtpbmcnLCBbbmV3IFB1Ymxpc2hlclNwZWFraW5nRXZlbnQodGhpcy5zZXNzaW9uLCAncHVibGlzaGVyU3RvcFNwZWFraW5nJywgdGhpcy5jb25uZWN0aW9uLCB0aGlzLnN0cmVhbUlkKV0pO1xuICAgICAgICAgICAgdGhpcy5kaXNhYmxlU3BlYWtpbmdFdmVudHMoKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGRpc2FibGVTcGVha2luZ0V2ZW50cygpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5zcGVlY2hFdmVudC5zdG9wKCk7XG4gICAgICAgIHRoaXMuc3BlZWNoRXZlbnQgPSB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGlzTG9jYWwoKTogYm9vbGVhbiB7XG4gICAgICAgIC8vIGluYm91bmQgb3B0aW9ucyB1bmRlZmluZWQgYW5kIG91dGJvdW5kIG9wdGlvbnMgZGVmaW5lZFxuICAgICAgICByZXR1cm4gKCF0aGlzLmluYm91bmRTdHJlYW1PcHRzICYmICEhdGhpcy5vdXRib3VuZFN0cmVhbU9wdHMpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBnZXRTZWxlY3RlZEljZUNhbmRpZGF0ZSgpOiBQcm9taXNlPGFueT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgdGhpcy53ZWJSdGNTdGF0cy5nZXRTZWxlY3RlZEljZUNhbmRpZGF0ZUluZm8oKVxuICAgICAgICAgICAgICAgIC50aGVuKHJlcG9ydCA9PiByZXNvbHZlKHJlcG9ydCkpXG4gICAgICAgICAgICAgICAgLmNhdGNoKGVycm9yID0+IHJlamVjdChlcnJvcikpO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgZ2V0UmVtb3RlSWNlQ2FuZGlkYXRlTGlzdCgpOiBSVENJY2VDYW5kaWRhdGVbXSB7XG4gICAgICAgIHJldHVybiB0aGlzLndlYlJ0Y1BlZXIucmVtb3RlQ2FuZGlkYXRlc1F1ZXVlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBnZXRMb2NhbEljZUNhbmRpZGF0ZUxpc3QoKTogUlRDSWNlQ2FuZGlkYXRlW10ge1xuICAgICAgICByZXR1cm4gdGhpcy53ZWJSdGNQZWVyLmxvY2FsQ2FuZGlkYXRlc1F1ZXVlO1xuICAgIH1cblxuICAgIC8qIFByaXZhdGUgbWV0aG9kcyAqL1xuXG4gICAgcHJpdmF0ZSBpbml0V2ViUnRjUGVlclNlbmQoKTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcblxuICAgICAgICAgICAgY29uc3QgdXNlck1lZGlhQ29uc3RyYWludHMgPSB7XG4gICAgICAgICAgICAgICAgYXVkaW86IHRoaXMuaXNTZW5kQXVkaW8oKSxcbiAgICAgICAgICAgICAgICB2aWRlbzogdGhpcy5pc1NlbmRWaWRlbygpXG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICBjb25zdCBvcHRpb25zID0ge1xuICAgICAgICAgICAgICAgIG1lZGlhU3RyZWFtOiB0aGlzLm1lZGlhU3RyZWFtLFxuICAgICAgICAgICAgICAgIG1lZGlhQ29uc3RyYWludHM6IHVzZXJNZWRpYUNvbnN0cmFpbnRzLFxuICAgICAgICAgICAgICAgIG9uaWNlY2FuZGlkYXRlOiB0aGlzLmNvbm5lY3Rpb24uc2VuZEljZUNhbmRpZGF0ZS5iaW5kKHRoaXMuY29ubmVjdGlvbiksXG4gICAgICAgICAgICAgICAgaWNlU2VydmVyczogdGhpcy5nZXRJY2VTZXJ2ZXJzQ29uZigpLFxuICAgICAgICAgICAgICAgIHNpbXVsY2FzdDogZmFsc2VcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIGNvbnN0IHN1Y2Nlc3NDYWxsYmFjayA9IChzZHBPZmZlclBhcmFtKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5kZWJ1ZygnU2VuZGluZyBTRFAgb2ZmZXIgdG8gcHVibGlzaCBhcyAnXG4gICAgICAgICAgICAgICAgICAgICsgdGhpcy5zdHJlYW1JZCwgc2RwT2ZmZXJQYXJhbSk7XG5cbiAgICAgICAgICAgICAgICBsZXQgdHlwZU9mVmlkZW8gPSAnJztcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5pc1NlbmRWaWRlbygpKSB7XG4gICAgICAgICAgICAgICAgICAgIHR5cGVPZlZpZGVvID0gdGhpcy5vdXRib3VuZFN0cmVhbU9wdHMucHVibGlzaGVyUHJvcGVydGllcy52aWRlb1NvdXJjZSBpbnN0YW5jZW9mIE1lZGlhU3RyZWFtVHJhY2sgPyAnQ1VTVE9NJyA6ICh0aGlzLmlzU2VuZFNjcmVlbigpID8gJ1NDUkVFTicgOiAnQ0FNRVJBJyk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdGhpcy5zZXNzaW9uLm9wZW52aWR1LnNlbmRSZXF1ZXN0KCdwdWJsaXNoVmlkZW8nLCB7XG4gICAgICAgICAgICAgICAgICAgIHNkcE9mZmVyOiBzZHBPZmZlclBhcmFtLFxuICAgICAgICAgICAgICAgICAgICBkb0xvb3BiYWNrOiB0aGlzLmRpc3BsYXlNeVJlbW90ZSgpIHx8IGZhbHNlLFxuICAgICAgICAgICAgICAgICAgICBoYXNBdWRpbzogdGhpcy5pc1NlbmRBdWRpbygpLFxuICAgICAgICAgICAgICAgICAgICBoYXNWaWRlbzogdGhpcy5pc1NlbmRWaWRlbygpLFxuICAgICAgICAgICAgICAgICAgICBhdWRpb0FjdGl2ZTogdGhpcy5hdWRpb0FjdGl2ZSxcbiAgICAgICAgICAgICAgICAgICAgdmlkZW9BY3RpdmU6IHRoaXMudmlkZW9BY3RpdmUsXG4gICAgICAgICAgICAgICAgICAgIHR5cGVPZlZpZGVvLFxuICAgICAgICAgICAgICAgICAgICBmcmFtZVJhdGU6ICEhdGhpcy5mcmFtZVJhdGUgPyB0aGlzLmZyYW1lUmF0ZSA6IC0xLFxuICAgICAgICAgICAgICAgICAgICB2aWRlb0RpbWVuc2lvbnM6IEpTT04uc3RyaW5naWZ5KHRoaXMudmlkZW9EaW1lbnNpb25zKVxuICAgICAgICAgICAgICAgIH0sIChlcnJvciwgcmVzcG9uc2UpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZXJyb3IuY29kZSA9PT0gNDAxKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KG5ldyBPcGVuVmlkdUVycm9yKE9wZW5WaWR1RXJyb3JOYW1lLk9QRU5WSURVX1BFUk1JU1NJT05fREVOSUVELCBcIllvdSBkb24ndCBoYXZlIHBlcm1pc3Npb25zIHRvIHB1Ymxpc2hcIikpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWplY3QoJ0Vycm9yIG9uIHB1Ymxpc2hWaWRlbzogJyArIEpTT04uc3RyaW5naWZ5KGVycm9yKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLndlYlJ0Y1BlZXIucHJvY2Vzc0Fuc3dlcihyZXNwb25zZS5zZHBBbnN3ZXIpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbUlkID0gcmVzcG9uc2UuaWQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuaXNMb2NhbFN0cmVhbVB1Ymxpc2hlZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucHVibGlzaGVkT25jZSA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLmRpc3BsYXlNeVJlbW90ZSgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnJlbW90ZVBlZXJTdWNjZXNzZnVsbHlFc3RhYmxpc2hlZCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdzdHJlYW0tY3JlYXRlZC1ieS1wdWJsaXNoZXInKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5pbml0V2ViUnRjU3RhdHMoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbyhcIidQdWJsaXNoZXInIHN1Y2Nlc3NmdWxseSBwdWJsaXNoZWQgdG8gc2Vzc2lvblwiKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgaWYgKHRoaXMuZGlzcGxheU15UmVtb3RlKCkpIHtcbiAgICAgICAgICAgICAgICB0aGlzLndlYlJ0Y1BlZXIgPSBuZXcgV2ViUnRjUGVlclNlbmRyZWN2KG9wdGlvbnMpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLndlYlJ0Y1BlZXIgPSBuZXcgV2ViUnRjUGVlclNlbmRvbmx5KG9wdGlvbnMpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy53ZWJSdGNQZWVyLmdlbmVyYXRlT2ZmZXIoKS50aGVuKG9mZmVyID0+IHtcbiAgICAgICAgICAgICAgICBzdWNjZXNzQ2FsbGJhY2sob2ZmZXIpO1xuICAgICAgICAgICAgfSkuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgIHJlamVjdChuZXcgRXJyb3IoJyhwdWJsaXNoKSBTRFAgb2ZmZXIgZXJyb3I6ICcgKyBKU09OLnN0cmluZ2lmeShlcnJvcikpKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGluaXRXZWJSdGNQZWVyUmVjZWl2ZSgpOiBQcm9taXNlPGFueT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuXG4gICAgICAgICAgICBjb25zdCBvZmZlckNvbnN0cmFpbnRzID0ge1xuICAgICAgICAgICAgICAgIGF1ZGlvOiB0aGlzLmluYm91bmRTdHJlYW1PcHRzLmhhc0F1ZGlvLFxuICAgICAgICAgICAgICAgIHZpZGVvOiB0aGlzLmluYm91bmRTdHJlYW1PcHRzLmhhc1ZpZGVvXG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgY29uc29sZS5kZWJ1ZyhcIidTZXNzaW9uLnN1YnNjcmliZShTdHJlYW0pJyBjYWxsZWQuIENvbnN0cmFpbnRzIG9mIGdlbmVyYXRlIFNEUCBvZmZlclwiLFxuICAgICAgICAgICAgICAgIG9mZmVyQ29uc3RyYWludHMpO1xuICAgICAgICAgICAgY29uc3Qgb3B0aW9ucyA9IHtcbiAgICAgICAgICAgICAgICBvbmljZWNhbmRpZGF0ZTogdGhpcy5jb25uZWN0aW9uLnNlbmRJY2VDYW5kaWRhdGUuYmluZCh0aGlzLmNvbm5lY3Rpb24pLFxuICAgICAgICAgICAgICAgIG1lZGlhQ29uc3RyYWludHM6IG9mZmVyQ29uc3RyYWludHMsXG4gICAgICAgICAgICAgICAgaWNlU2VydmVyczogdGhpcy5nZXRJY2VTZXJ2ZXJzQ29uZigpLFxuICAgICAgICAgICAgICAgIHNpbXVsY2FzdDogZmFsc2VcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIGNvbnN0IHN1Y2Nlc3NDYWxsYmFjayA9IChzZHBPZmZlclBhcmFtKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5kZWJ1ZygnU2VuZGluZyBTRFAgb2ZmZXIgdG8gc3Vic2NyaWJlIHRvICdcbiAgICAgICAgICAgICAgICAgICAgKyB0aGlzLnN0cmVhbUlkLCBzZHBPZmZlclBhcmFtKTtcbiAgICAgICAgICAgICAgICB0aGlzLnNlc3Npb24ub3BlbnZpZHUuc2VuZFJlcXVlc3QoJ3JlY2VpdmVWaWRlb0Zyb20nLCB7XG4gICAgICAgICAgICAgICAgICAgIHNlbmRlcjogdGhpcy5zdHJlYW1JZCxcbiAgICAgICAgICAgICAgICAgICAgc2RwT2ZmZXI6IHNkcE9mZmVyUGFyYW1cbiAgICAgICAgICAgICAgICB9LCAoZXJyb3IsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KG5ldyBFcnJvcignRXJyb3Igb24gcmVjdlZpZGVvRnJvbTogJyArIEpTT04uc3RyaW5naWZ5KGVycm9yKSkpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy53ZWJSdGNQZWVyLnByb2Nlc3NBbnN3ZXIocmVzcG9uc2Uuc2RwQW5zd2VyKS50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnJlbW90ZVBlZXJTdWNjZXNzZnVsbHlFc3RhYmxpc2hlZCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuaW5pdFdlYlJ0Y1N0YXRzKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSkuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgdGhpcy53ZWJSdGNQZWVyID0gbmV3IFdlYlJ0Y1BlZXJSZWN2b25seShvcHRpb25zKTtcbiAgICAgICAgICAgIHRoaXMud2ViUnRjUGVlci5nZW5lcmF0ZU9mZmVyKClcbiAgICAgICAgICAgICAgICAudGhlbihvZmZlciA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHN1Y2Nlc3NDYWxsYmFjayhvZmZlcik7XG4gICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgICAgICByZWplY3QobmV3IEVycm9yKCcoc3Vic2NyaWJlKSBTRFAgb2ZmZXIgZXJyb3I6ICcgKyBKU09OLnN0cmluZ2lmeShlcnJvcikpKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSByZW1vdGVQZWVyU3VjY2Vzc2Z1bGx5RXN0YWJsaXNoZWQoKTogdm9pZCB7XG4gICAgICAgIHRoaXMubWVkaWFTdHJlYW0gPSB0aGlzLndlYlJ0Y1BlZXIucGMuZ2V0UmVtb3RlU3RyZWFtcygpWzBdO1xuICAgICAgICBjb25zb2xlLmRlYnVnKCdQZWVyIHJlbW90ZSBzdHJlYW0nLCB0aGlzLm1lZGlhU3RyZWFtKTtcblxuICAgICAgICBpZiAoISF0aGlzLm1lZGlhU3RyZWFtKSB7XG4gICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnbWVkaWFzdHJlYW0tdXBkYXRlZCcpO1xuICAgICAgICAgICAgaWYgKCF0aGlzLmRpc3BsYXlNeVJlbW90ZSgpICYmICEhdGhpcy5tZWRpYVN0cmVhbS5nZXRBdWRpb1RyYWNrcygpWzBdICYmIHRoaXMuc2Vzc2lvbi5zcGVha2luZ0V2ZW50c0VuYWJsZWQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVuYWJsZVNwZWFraW5nRXZlbnRzKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIGluaXRXZWJSdGNTdGF0cygpOiB2b2lkIHtcbiAgICAgICAgdGhpcy53ZWJSdGNTdGF0cyA9IG5ldyBXZWJSdGNTdGF0cyh0aGlzKTtcbiAgICAgICAgdGhpcy53ZWJSdGNTdGF0cy5pbml0V2ViUnRjU3RhdHMoKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIHN0b3BXZWJSdGNTdGF0cygpOiB2b2lkIHtcbiAgICAgICAgaWYgKCEhdGhpcy53ZWJSdGNTdGF0cyAmJiB0aGlzLndlYlJ0Y1N0YXRzLmlzRW5hYmxlZCgpKSB7XG4gICAgICAgICAgICB0aGlzLndlYlJ0Y1N0YXRzLnN0b3BXZWJSdGNTdGF0cygpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBnZXRJY2VTZXJ2ZXJzQ29uZigpOiBSVENJY2VTZXJ2ZXJbXSB8IHVuZGVmaW5lZCB7XG4gICAgICAgIGxldCByZXR1cm5WYWx1ZTtcbiAgICAgICAgaWYgKCEhdGhpcy5zZXNzaW9uLm9wZW52aWR1LmFkdmFuY2VkQ29uZmlndXJhdGlvbi5pY2VTZXJ2ZXJzKSB7XG4gICAgICAgICAgICByZXR1cm5WYWx1ZSA9IHRoaXMuc2Vzc2lvbi5vcGVudmlkdS5hZHZhbmNlZENvbmZpZ3VyYXRpb24uaWNlU2VydmVycyA9PT0gJ2ZyZWVpY2UnID9cbiAgICAgICAgICAgICAgICB1bmRlZmluZWQgOlxuICAgICAgICAgICAgICAgIHRoaXMuc2Vzc2lvbi5vcGVudmlkdS5hZHZhbmNlZENvbmZpZ3VyYXRpb24uaWNlU2VydmVycztcbiAgICAgICAgfSBlbHNlIGlmICh0aGlzLnNlc3Npb24ub3BlbnZpZHUuaWNlU2VydmVycykge1xuICAgICAgICAgICAgcmV0dXJuVmFsdWUgPSB0aGlzLnNlc3Npb24ub3BlbnZpZHUuaWNlU2VydmVycztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVyblZhbHVlID0gdW5kZWZpbmVkO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZXR1cm5WYWx1ZTtcbiAgICB9XG5cbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IFN0cmVhbSB9IGZyb20gJy4vU3RyZWFtJztcbmltcG9ydCB7IEV2ZW50RGlzcGF0Y2hlciB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvSW50ZXJmYWNlcy9QdWJsaWMvRXZlbnREaXNwYXRjaGVyJztcbmltcG9ydCB7IFN0cmVhbU1hbmFnZXJWaWRlbyB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvSW50ZXJmYWNlcy9QdWJsaWMvU3RyZWFtTWFuYWdlclZpZGVvJztcbmltcG9ydCB7IEV2ZW50IH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvRXZlbnQnO1xuaW1wb3J0IHsgU3RyZWFtTWFuYWdlckV2ZW50IH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvU3RyZWFtTWFuYWdlckV2ZW50JztcbmltcG9ydCB7IFZpZGVvRWxlbWVudEV2ZW50IH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvVmlkZW9FbGVtZW50RXZlbnQnO1xuaW1wb3J0IHsgVmlkZW9JbnNlcnRNb2RlIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FbnVtcy9WaWRlb0luc2VydE1vZGUnO1xuXG5pbXBvcnQgRXZlbnRFbWl0dGVyID0gcmVxdWlyZSgnd29sZnk4Ny1ldmVudGVtaXR0ZXInKTtcblxuXG4vKipcbiAqIEludGVyZmFjZSBpbiBjaGFyZ2Ugb2YgZGlzcGxheWluZyB0aGUgbWVkaWEgc3RyZWFtcyBpbiB0aGUgSFRNTCBET00uIFRoaXMgd3JhcHMgYW55IFtbUHVibGlzaGVyXV0gYW5kIFtbU3Vic2NyaWJlcl1dIG9iamVjdC5cbiAqIFlvdSBjYW4gaW5zZXJ0IGFzIG1hbnkgdmlkZW8gcGxheWVycyBmbyB0aGUgc2FtZSBTdHJlYW0gYXMgeW91IHdhbnQgYnkgY2FsbGluZyBbW1N0cmVhbU1hbmFnZXIuYWRkVmlkZW9FbGVtZW50XV0gb3JcbiAqIFtbU3RyZWFtTWFuYWdlci5jcmVhdGVWaWRlb0VsZW1lbnRdXS5cbiAqXG4gKiBUaGUgdXNlIG9mIFN0cmVhbU1hbmFnZXIgd3JhcHBlciBpcyBwYXJ0aWN1bGFybHkgdXNlZnVsIHdoZW4geW91IGRvbid0IG5lZWQgdG8gZGlmZmVyZW50aWF0ZSBiZXR3ZWVuIFB1Ymxpc2hlciBvciBTdWJzY3JpYmVyIHN0cmVhbXMgb3IganVzdFxuICogd2FudCB0byBkaXJlY3RseSBtYW5hZ2UgeW91ciBvd24gdmlkZW8gZWxlbWVudHMgKGV2ZW4gbW9yZSB0aGFuIG9uZSB2aWRlbyBlbGVtZW50IHBlciBTdHJlYW0pLiBUaGlzIHNjZW5hcmlvIGlzIHByZXR0eSBjb21tb24gaW5cbiAqIGRlY2xhcmF0aXZlLCBNVkMgZnJvbnRlbmQgZnJhbWV3b3JrcyBzdWNoIGFzIEFuZ3VsYXIsIFJlYWN0IG9yIFZ1ZS5qc1xuICovXG5leHBvcnQgY2xhc3MgU3RyZWFtTWFuYWdlciBpbXBsZW1lbnRzIEV2ZW50RGlzcGF0Y2hlciB7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgU3RyZWFtIHJlcHJlc2VudGVkIGluIHRoZSBET00gYnkgdGhlIFB1Ymxpc2hlci9TdWJzY3JpYmVyXG4gICAgICovXG4gICAgc3RyZWFtOiBTdHJlYW07XG5cbiAgICAvKipcbiAgICAgKiBBbGwgdGhlIHZpZGVvcyBkaXNwbGF5aW5nIHRoZSBTdHJlYW0gb2YgdGhpcyBQdWJsaXNoZXIvU3Vic2NyaWJlclxuICAgICAqL1xuICAgIHZpZGVvczogU3RyZWFtTWFuYWdlclZpZGVvW10gPSBbXTtcblxuICAgIC8qKlxuICAgICAqIFdoZXRoZXIgdGhlIFN0cmVhbSByZXByZXNlbnRlZCBpbiB0aGUgRE9NIGlzIGxvY2FsIG9yIHJlbW90ZVxuICAgICAqIC0gYGZhbHNlYCBmb3IgW1tQdWJsaXNoZXJdXVxuICAgICAqIC0gYHRydWVgIGZvciBbW1N1YnNjcmliZXJdXVxuICAgICAqL1xuICAgIHJlbW90ZTogYm9vbGVhbjtcblxuICAgIC8qKlxuICAgICAqIFRoZSBET00gSFRNTEVsZW1lbnQgYXNzaWduZWQgYXMgdGFyZ2V0IGVsZW1lbnQgd2hlbiBjcmVhdGluZyB0aGUgdmlkZW8gZm9yIHRoZSBQdWJsaXNoZXIvU3Vic2NyaWJlci4gVGhpcyBwcm9wZXJ0eSBpcyBvbmx5IGRlZmluZWQgaWY6XG4gICAgICogLSBbW1B1Ymxpc2hlcl1dIGhhcyBiZWVuIGluaXRpYWxpemVkIGJ5IGNhbGxpbmcgbWV0aG9kIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dIHdpdGggYSB2YWxpZCBgdGFyZ2V0RWxlbWVudGAgcGFyYW1ldGVyXG4gICAgICogLSBbW1N1YnNjcmliZXJdXSBoYXMgYmVlbiBpbml0aWFsaXplZCBieSBjYWxsaW5nIG1ldGhvZCBbW1Nlc3Npb24uc3Vic2NyaWJlXV0gd2l0aCBhIHZhbGlkIGB0YXJnZXRFbGVtZW50YCBwYXJhbWV0ZXJcbiAgICAgKi9cbiAgICB0YXJnZXRFbGVtZW50OiBIVE1MRWxlbWVudDtcblxuICAgIC8qKlxuICAgICAqIGBpZGAgYXR0cmlidXRlIG9mIHRoZSBET00gdmlkZW8gZWxlbWVudCBkaXNwbGF5aW5nIHRoZSBQdWJsaXNoZXIvU3Vic2NyaWJlcidzIHN0cmVhbS4gVGhpcyBwcm9wZXJ0eSBpcyBvbmx5IGRlZmluZWQgaWY6XG4gICAgICogLSBbW1B1Ymxpc2hlcl1dIGhhcyBiZWVuIGluaXRpYWxpemVkIGJ5IGNhbGxpbmcgbWV0aG9kIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dIHdpdGggYSB2YWxpZCBgdGFyZ2V0RWxlbWVudGAgcGFyYW1ldGVyXG4gICAgICogLSBbW1N1YnNjcmliZXJdXSBoYXMgYmVlbiBpbml0aWFsaXplZCBieSBjYWxsaW5nIG1ldGhvZCBbW1Nlc3Npb24uc3Vic2NyaWJlXV0gd2l0aCBhIHZhbGlkIGB0YXJnZXRFbGVtZW50YCBwYXJhbWV0ZXJcbiAgICAgKi9cbiAgICBpZDogc3RyaW5nO1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGZpcnN0VmlkZW9FbGVtZW50OiBTdHJlYW1NYW5hZ2VyVmlkZW87XG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGxhenlMYXVuY2hWaWRlb0VsZW1lbnRDcmVhdGVkRXZlbnQgPSBmYWxzZTtcbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgZWxlbWVudDogSFRNTEVsZW1lbnQ7XG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHByb3RlY3RlZCBlZSA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgcHJvdGVjdGVkIGNhblBsYXlMaXN0ZW5lcjogRXZlbnRMaXN0ZW5lck9yRXZlbnRMaXN0ZW5lck9iamVjdDtcblxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHN0cmVhbTogU3RyZWFtLCB0YXJnZXRFbGVtZW50PzogSFRNTEVsZW1lbnQgfCBzdHJpbmcpIHtcbiAgICAgICAgdGhpcy5zdHJlYW0gPSBzdHJlYW07XG4gICAgICAgIHRoaXMuc3RyZWFtLnN0cmVhbU1hbmFnZXIgPSB0aGlzO1xuICAgICAgICB0aGlzLnJlbW90ZSA9ICF0aGlzLnN0cmVhbS5pc0xvY2FsKCk7XG5cbiAgICAgICAgaWYgKCEhdGFyZ2V0RWxlbWVudCkge1xuICAgICAgICAgICAgbGV0IHRhcmdFbDtcbiAgICAgICAgICAgIGlmICh0eXBlb2YgdGFyZ2V0RWxlbWVudCA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgICAgICB0YXJnRWwgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCh0YXJnZXRFbGVtZW50KTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAodGFyZ2V0RWxlbWVudCBpbnN0YW5jZW9mIEhUTUxFbGVtZW50KSB7XG4gICAgICAgICAgICAgICAgdGFyZ0VsID0gdGFyZ2V0RWxlbWVudDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKCEhdGFyZ0VsKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5maXJzdFZpZGVvRWxlbWVudCA9IHtcbiAgICAgICAgICAgICAgICAgICAgdGFyZ2V0RWxlbWVudDogdGFyZ0VsLFxuICAgICAgICAgICAgICAgICAgICB2aWRlbzogZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgndmlkZW8nKSxcbiAgICAgICAgICAgICAgICAgICAgaWQ6ICcnXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB0aGlzLnRhcmdldEVsZW1lbnQgPSB0YXJnRWw7XG4gICAgICAgICAgICAgICAgdGhpcy5lbGVtZW50ID0gdGFyZ0VsO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHRoaXMuY2FuUGxheUxpc3RlbmVyID0gKCkgPT4ge1xuICAgICAgICAgICAgaWYgKHRoaXMuc3RyZWFtLmlzTG9jYWwoKSkge1xuICAgICAgICAgICAgICAgIGlmICghdGhpcy5zdHJlYW0uZGlzcGxheU15UmVtb3RlKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS5pbmZvKFwiWW91ciBsb2NhbCAnU3RyZWFtJyB3aXRoIGlkIFtcIiArIHRoaXMuc3RyZWFtLnN0cmVhbUlkICsgJ10gdmlkZW8gaXMgbm93IHBsYXlpbmcnKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3ZpZGVvUGxheWluZycsIFtuZXcgVmlkZW9FbGVtZW50RXZlbnQodGhpcy52aWRlb3NbMF0udmlkZW8sIHRoaXMsICd2aWRlb1BsYXlpbmcnKV0pO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbyhcIllvdXIgb3duIHJlbW90ZSAnU3RyZWFtJyB3aXRoIGlkIFtcIiArIHRoaXMuc3RyZWFtLnN0cmVhbUlkICsgJ10gdmlkZW8gaXMgbm93IHBsYXlpbmcnKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3JlbW90ZVZpZGVvUGxheWluZycsIFtuZXcgVmlkZW9FbGVtZW50RXZlbnQodGhpcy52aWRlb3NbMF0udmlkZW8sIHRoaXMsICdyZW1vdGVWaWRlb1BsYXlpbmcnKV0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5pbmZvKFwiUmVtb3RlICdTdHJlYW0nIHdpdGggaWQgW1wiICsgdGhpcy5zdHJlYW0uc3RyZWFtSWQgKyAnXSB2aWRlbyBpcyBub3cgcGxheWluZycpO1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCd2aWRlb1BsYXlpbmcnLCBbbmV3IFZpZGVvRWxlbWVudEV2ZW50KHRoaXMudmlkZW9zWzBdLnZpZGVvLCB0aGlzLCAndmlkZW9QbGF5aW5nJyldKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdzdHJlYW1QbGF5aW5nJywgW25ldyBTdHJlYW1NYW5hZ2VyRXZlbnQodGhpcyldKTtcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZWUgW1tFdmVudERpc3BhdGNoZXIub25dXVxuICAgICAqL1xuICAgIG9uKHR5cGU6IHN0cmluZywgaGFuZGxlcjogKGV2ZW50OiBFdmVudCkgPT4gdm9pZCk6IEV2ZW50RGlzcGF0Y2hlciB7XG4gICAgICAgIHRoaXMuZWUub24odHlwZSwgZXZlbnQgPT4ge1xuICAgICAgICAgICAgaWYgKGV2ZW50KSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5pbmZvKFwiRXZlbnQgJ1wiICsgdHlwZSArIFwiJyB0cmlnZ2VyZWQgYnkgJ1wiICsgKHRoaXMucmVtb3RlID8gJ1N1YnNjcmliZXInIDogJ1B1Ymxpc2hlcicpICsgXCInXCIsIGV2ZW50KTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5pbmZvKFwiRXZlbnQgJ1wiICsgdHlwZSArIFwiJyB0cmlnZ2VyZWQgYnkgJ1wiICsgKHRoaXMucmVtb3RlID8gJ1N1YnNjcmliZXInIDogJ1B1Ymxpc2hlcicpICsgXCInXCIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaGFuZGxlcihldmVudCk7XG4gICAgICAgIH0pO1xuICAgICAgICBpZiAodHlwZSA9PT0gJ3ZpZGVvRWxlbWVudENyZWF0ZWQnKSB7XG4gICAgICAgICAgICBpZiAoISF0aGlzLnN0cmVhbSAmJiB0aGlzLmxhenlMYXVuY2hWaWRlb0VsZW1lbnRDcmVhdGVkRXZlbnQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgndmlkZW9FbGVtZW50Q3JlYXRlZCcsIFtuZXcgVmlkZW9FbGVtZW50RXZlbnQodGhpcy52aWRlb3NbMF0udmlkZW8sIHRoaXMsICd2aWRlb0VsZW1lbnRDcmVhdGVkJyldKTtcbiAgICAgICAgICAgICAgICB0aGlzLmxhenlMYXVuY2hWaWRlb0VsZW1lbnRDcmVhdGVkRXZlbnQgPSBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAodHlwZSA9PT0gJ3N0cmVhbVBsYXlpbmcnIHx8IHR5cGUgPT09ICd2aWRlb1BsYXlpbmcnKSB7XG4gICAgICAgICAgICBpZiAodGhpcy52aWRlb3NbMF0gJiYgdGhpcy52aWRlb3NbMF0udmlkZW8gJiZcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvc1swXS52aWRlby5jdXJyZW50VGltZSA+IDAgJiZcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvc1swXS52aWRlby5wYXVzZWQgPT09IGZhbHNlICYmXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8uZW5kZWQgPT09IGZhbHNlICYmXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8ucmVhZHlTdGF0ZSA9PT0gNCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdzdHJlYW1QbGF5aW5nJywgW25ldyBTdHJlYW1NYW5hZ2VyRXZlbnQodGhpcyldKTtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgndmlkZW9QbGF5aW5nJywgW25ldyBWaWRlb0VsZW1lbnRFdmVudCh0aGlzLnZpZGVvc1swXS52aWRlbywgdGhpcywgJ3ZpZGVvUGxheWluZycpXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2VlIFtbRXZlbnREaXNwYXRjaGVyLm9uY2VdXVxuICAgICAqL1xuICAgIG9uY2UodHlwZTogc3RyaW5nLCBoYW5kbGVyOiAoZXZlbnQ6IEV2ZW50KSA9PiB2b2lkKTogU3RyZWFtTWFuYWdlciB7XG4gICAgICAgIHRoaXMuZWUub25jZSh0eXBlLCBldmVudCA9PiB7XG4gICAgICAgICAgICBpZiAoZXZlbnQpIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oXCJFdmVudCAnXCIgKyB0eXBlICsgXCInIHRyaWdnZXJlZCBvbmNlXCIsIGV2ZW50KTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5pbmZvKFwiRXZlbnQgJ1wiICsgdHlwZSArIFwiJyB0cmlnZ2VyZWQgb25jZVwiKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGhhbmRsZXIoZXZlbnQpO1xuICAgICAgICB9KTtcbiAgICAgICAgaWYgKHR5cGUgPT09ICd2aWRlb0VsZW1lbnRDcmVhdGVkJykge1xuICAgICAgICAgICAgaWYgKCEhdGhpcy5zdHJlYW0gJiYgdGhpcy5sYXp5TGF1bmNoVmlkZW9FbGVtZW50Q3JlYXRlZEV2ZW50KSB7XG4gICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3ZpZGVvRWxlbWVudENyZWF0ZWQnLCBbbmV3IFZpZGVvRWxlbWVudEV2ZW50KHRoaXMudmlkZW9zWzBdLnZpZGVvLCB0aGlzLCAndmlkZW9FbGVtZW50Q3JlYXRlZCcpXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHR5cGUgPT09ICdzdHJlYW1QbGF5aW5nJyB8fCB0eXBlID09PSAndmlkZW9QbGF5aW5nJykge1xuICAgICAgICAgICAgaWYgKHRoaXMudmlkZW9zWzBdICYmIHRoaXMudmlkZW9zWzBdLnZpZGVvICYmXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8uY3VycmVudFRpbWUgPiAwICYmXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8ucGF1c2VkID09PSBmYWxzZSAmJlxuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9zWzBdLnZpZGVvLmVuZGVkID09PSBmYWxzZSAmJlxuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9zWzBdLnZpZGVvLnJlYWR5U3RhdGUgPT09IDQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnc3RyZWFtUGxheWluZycsIFtuZXcgU3RyZWFtTWFuYWdlckV2ZW50KHRoaXMpXSk7XG4gICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3ZpZGVvUGxheWluZycsIFtuZXcgVmlkZW9FbGVtZW50RXZlbnQodGhpcy52aWRlb3NbMF0udmlkZW8sIHRoaXMsICd2aWRlb1BsYXlpbmcnKV0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNlZSBbW0V2ZW50RGlzcGF0Y2hlci5vZmZdXVxuICAgICAqL1xuICAgIG9mZih0eXBlOiBzdHJpbmcsIGhhbmRsZXI/OiAoZXZlbnQ6IEV2ZW50KSA9PiB2b2lkKTogU3RyZWFtTWFuYWdlciB7XG4gICAgICAgIGlmICghaGFuZGxlcikge1xuICAgICAgICAgICAgdGhpcy5lZS5yZW1vdmVBbGxMaXN0ZW5lcnModHlwZSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLmVlLm9mZih0eXBlLCBoYW5kbGVyKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBNYWtlcyBgdmlkZW9gIGVsZW1lbnQgcGFyYW1ldGVyIGRpc3BsYXkgdGhpcyBbW3N0cmVhbV1dLiBUaGlzIGlzIHVzZWZ1bCB3aGVuIHlvdSBhcmVcbiAgICAgKiBbbWFuYWdpbmcgdGhlIHZpZGVvIGVsZW1lbnRzIG9uIHlvdXIgb3duXSgvZG9jcy9ob3ctZG8taS9tYW5hZ2UtdmlkZW9zLyN5b3UtdGFrZS1jYXJlLW9mLXRoZS12aWRlby1wbGF5ZXJzKVxuICAgICAqXG4gICAgICogQ2FsbGluZyB0aGlzIG1ldGhvZCB3aXRoIGEgdmlkZW8gYWxyZWFkeSBhZGRlZCB0byBvdGhlciBQdWJsaXNoZXIvU3Vic2NyaWJlciB3aWxsIGNhdXNlIHRoZSB2aWRlbyBlbGVtZW50IHRvIGJlXG4gICAgICogZGlzYXNzb2NpYXRlZCBmcm9tIHRoYXQgcHJldmlvdXMgUHVibGlzaGVyL1N1YnNjcmliZXIgYW5kIHRvIGJlIGFzc29jaWF0ZWQgdG8gdGhpcyBvbmUuXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyAxIGlmIHRoZSB2aWRlbyB3YXNuJ3QgYXNzb2NpYXRlZCB0byBhbnkgb3RoZXIgUHVibGlzaGVyL1N1YnNjcmliZXIgYW5kIGhhcyBiZWVuIHN1Y2Nlc3NmdWxseSBhZGRlZCB0byB0aGlzIG9uZS5cbiAgICAgKiAwIGlmIHRoZSB2aWRlbyB3YXMgYWxyZWFkeSBhZGRlZCB0byB0aGlzIFB1Ymxpc2hlci9TdWJzY3JpYmVyLiAtMSBpZiB0aGUgdmlkZW8gd2FzIHByZXZpb3VzbHkgYXNzb2NpYXRlZCB0byBhbnkgb3RoZXJcbiAgICAgKiBQdWJsaXNoZXIvU3Vic2NyaWJlciBhbmQgaGFzIGJlZW4gc3VjY2Vzc2Z1bGx5IGRpc2Fzc29jaWF0ZWQgZnJvbSB0aGF0IG9uZSBhbmQgcHJvcGVybHkgYWRkZWQgdG8gdGhpcyBvbmUuXG4gICAgICovXG4gICAgYWRkVmlkZW9FbGVtZW50KHZpZGVvOiBIVE1MVmlkZW9FbGVtZW50KTogbnVtYmVyIHtcblxuICAgICAgICB0aGlzLmluaXRpYWxpemVWaWRlb1Byb3BlcnRpZXModmlkZW8pO1xuXG4gICAgICAgIC8vIElmIHRoZSB2aWRlbyBlbGVtZW50IGlzIGFscmVhZHkgcGFydCBvZiB0aGlzIFN0cmVhbU1hbmFnZXIgZG8gbm90aGluZ1xuICAgICAgICBmb3IgKGNvbnN0IHYgb2YgdGhpcy52aWRlb3MpIHtcbiAgICAgICAgICAgIGlmICh2LnZpZGVvID09PSB2aWRlbykge1xuICAgICAgICAgICAgICAgIHJldHVybiAwO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgbGV0IHJldHVybk51bWJlciA9IDE7XG5cbiAgICAgICAgZm9yIChjb25zdCBzdHJlYW1NYW5hZ2VyIG9mIHRoaXMuc3RyZWFtLnNlc3Npb24uc3RyZWFtTWFuYWdlcnMpIHtcbiAgICAgICAgICAgIGlmIChzdHJlYW1NYW5hZ2VyLmRpc2Fzc29jaWF0ZVZpZGVvKHZpZGVvKSkge1xuICAgICAgICAgICAgICAgIHJldHVybk51bWJlciA9IC0xO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5zdHJlYW0uc2Vzc2lvbi5zdHJlYW1NYW5hZ2Vycy5mb3JFYWNoKHN0cmVhbU1hbmFnZXIgPT4ge1xuICAgICAgICAgICAgc3RyZWFtTWFuYWdlci5kaXNhc3NvY2lhdGVWaWRlbyh2aWRlbyk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHRoaXMucHVzaE5ld1N0cmVhbU1hbmFnZXJWaWRlbyh7XG4gICAgICAgICAgICB2aWRlbyxcbiAgICAgICAgICAgIGlkOiB2aWRlby5pZFxuICAgICAgICB9KTtcblxuICAgICAgICBjb25zb2xlLmluZm8oJ05ldyB2aWRlbyBlbGVtZW50IGFzc29jaWF0ZWQgdG8gJywgdGhpcyk7XG5cbiAgICAgICAgcmV0dXJuIHJldHVybk51bWJlcjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgbmV3IHZpZGVvIGVsZW1lbnQgZGlzcGxheWluZyB0aGlzIFtbc3RyZWFtXV0uIFRoaXMgYWxsb3dzIHlvdSB0byBoYXZlIG11bHRpcGxlIHZpZGVvIGVsZW1lbnRzIGRpc3BsYXlpbmcgdGhlIHNhbWUgbWVkaWEgc3RyZWFtLlxuICAgICAqXG4gICAgICogIyMjIyBFdmVudHMgZGlzcGF0Y2hlZFxuICAgICAqXG4gICAgICogVGhlIFB1Ymxpc2hlci9TdWJzY3JpYmVyIG9iamVjdCB3aWxsIGRpc3BhdGNoIGEgYHZpZGVvRWxlbWVudENyZWF0ZWRgIGV2ZW50IG9uY2UgdGhlIEhUTUwgdmlkZW8gZWxlbWVudCBoYXMgYmVlbiBhZGRlZCB0byBET00uIFNlZSBbW1ZpZGVvRWxlbWVudEV2ZW50XV1cbiAgICAgKlxuICAgICAqIEBwYXJhbSB0YXJnZXRFbGVtZW50IEhUTUwgRE9NIGVsZW1lbnQgKG9yIGl0cyBgaWRgIGF0dHJpYnV0ZSkgaW4gd2hpY2ggdGhlIHZpZGVvIGVsZW1lbnQgb2YgdGhlIFB1Ymxpc2hlci9TdWJzY3JpYmVyIHdpbGwgYmUgaW5zZXJ0ZWRcbiAgICAgKiBAcGFyYW0gaW5zZXJ0TW9kZSBIb3cgdGhlIHZpZGVvIGVsZW1lbnQgd2lsbCBiZSBpbnNlcnRlZCBhY2NvcmRpbmdseSB0byBgdGFyZ2V0RWxlbWV0YFxuICAgICAqL1xuICAgIGNyZWF0ZVZpZGVvRWxlbWVudCh0YXJnZXRFbGVtZW50Pzogc3RyaW5nIHwgSFRNTEVsZW1lbnQsIGluc2VydE1vZGU/OiBWaWRlb0luc2VydE1vZGUpOiBIVE1MVmlkZW9FbGVtZW50IHtcbiAgICAgICAgbGV0IHRhcmdFbDtcbiAgICAgICAgaWYgKHR5cGVvZiB0YXJnZXRFbGVtZW50ID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgdGFyZ0VsID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQodGFyZ0VsKTtcbiAgICAgICAgICAgIGlmICghdGFyZ0VsKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiVGhlIHByb3ZpZGVkICd0YXJnZXRFbGVtZW50JyBjb3VsZG4ndCBiZSByZXNvbHZlZCB0byBhbnkgSFRNTCBlbGVtZW50OiBcIiArIHRhcmdldEVsZW1lbnQpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2UgaWYgKHRhcmdldEVsZW1lbnQgaW5zdGFuY2VvZiBIVE1MRWxlbWVudCkge1xuICAgICAgICAgICAgdGFyZ0VsID0gdGFyZ2V0RWxlbWVudDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIlRoZSBwcm92aWRlZCAndGFyZ2V0RWxlbWVudCcgY291bGRuJ3QgYmUgcmVzb2x2ZWQgdG8gYW55IEhUTUwgZWxlbWVudDogXCIgKyB0YXJnZXRFbGVtZW50KTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHZpZGVvID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgndmlkZW8nKTtcbiAgICAgICAgdGhpcy5pbml0aWFsaXplVmlkZW9Qcm9wZXJ0aWVzKHZpZGVvKTtcblxuICAgICAgICBsZXQgaW5zTW9kZSA9ICEhaW5zZXJ0TW9kZSA/IGluc2VydE1vZGUgOiBWaWRlb0luc2VydE1vZGUuQVBQRU5EO1xuICAgICAgICBzd2l0Y2ggKGluc01vZGUpIHtcbiAgICAgICAgICAgIGNhc2UgVmlkZW9JbnNlcnRNb2RlLkFGVEVSOlxuICAgICAgICAgICAgICAgIHRhcmdFbC5wYXJlbnROb2RlISEuaW5zZXJ0QmVmb3JlKHZpZGVvLCB0YXJnRWwubmV4dFNpYmxpbmcpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBWaWRlb0luc2VydE1vZGUuQVBQRU5EOlxuICAgICAgICAgICAgICAgIHRhcmdFbC5hcHBlbmRDaGlsZCh2aWRlbyk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIFZpZGVvSW5zZXJ0TW9kZS5CRUZPUkU6XG4gICAgICAgICAgICAgICAgdGFyZ0VsLnBhcmVudE5vZGUhIS5pbnNlcnRCZWZvcmUodmlkZW8sIHRhcmdFbCk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIFZpZGVvSW5zZXJ0TW9kZS5QUkVQRU5EOlxuICAgICAgICAgICAgICAgIHRhcmdFbC5pbnNlcnRCZWZvcmUodmlkZW8sIHRhcmdFbC5jaGlsZE5vZGVzWzBdKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgVmlkZW9JbnNlcnRNb2RlLlJFUExBQ0U6XG4gICAgICAgICAgICAgICAgdGFyZ0VsLnBhcmVudE5vZGUhIS5yZXBsYWNlQ2hpbGQodmlkZW8sIHRhcmdFbCk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgIGluc01vZGUgPSBWaWRlb0luc2VydE1vZGUuQVBQRU5EO1xuICAgICAgICAgICAgICAgIHRhcmdFbC5hcHBlbmRDaGlsZCh2aWRlbyk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCB2OiBTdHJlYW1NYW5hZ2VyVmlkZW8gPSB7XG4gICAgICAgICAgICB0YXJnZXRFbGVtZW50OiB0YXJnRWwsXG4gICAgICAgICAgICB2aWRlbyxcbiAgICAgICAgICAgIGluc2VydE1vZGU6IGluc01vZGUsXG4gICAgICAgICAgICBpZDogdmlkZW8uaWRcbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5wdXNoTmV3U3RyZWFtTWFuYWdlclZpZGVvKHYpO1xuXG4gICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCd2aWRlb0VsZW1lbnRDcmVhdGVkJywgW25ldyBWaWRlb0VsZW1lbnRFdmVudCh2LnZpZGVvLCB0aGlzLCAndmlkZW9FbGVtZW50Q3JlYXRlZCcpXSk7XG5cbiAgICAgICAgdGhpcy5sYXp5TGF1bmNoVmlkZW9FbGVtZW50Q3JlYXRlZEV2ZW50ID0gISF0aGlzLmZpcnN0VmlkZW9FbGVtZW50O1xuXG4gICAgICAgIHJldHVybiB2aWRlbztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgaW5pdGlhbGl6ZVZpZGVvUHJvcGVydGllcyh2aWRlbzogSFRNTFZpZGVvRWxlbWVudCk6IHZvaWQge1xuICAgICAgICBpZiAoISh0aGlzLnN0cmVhbS5pc0xvY2FsKCkgJiYgdGhpcy5zdHJlYW0uZGlzcGxheU15UmVtb3RlKCkpKSB7XG4gICAgICAgICAgICAvLyBBdm9pZCBzZXR0aW5nIHRoZSBNZWRpYVN0cmVhbSBpbnRvIHRoZSBzcmNPYmplY3QgaWYgcmVtb3RlIHN1YnNjcmlwdGlvbiBiZWZvcmUgcHVibGlzaGluZ1xuICAgICAgICAgICAgdmlkZW8uc3JjT2JqZWN0ID0gdGhpcy5zdHJlYW0uZ2V0TWVkaWFTdHJlYW0oKTtcbiAgICAgICAgfVxuICAgICAgICB2aWRlby5hdXRvcGxheSA9IHRydWU7XG4gICAgICAgIHZpZGVvLmNvbnRyb2xzID0gZmFsc2U7XG4gICAgICAgIGlmICghdmlkZW8uaWQpIHtcbiAgICAgICAgICAgIHZpZGVvLmlkID0gKHRoaXMucmVtb3RlID8gJ3JlbW90ZS0nIDogJ2xvY2FsLScpICsgJ3ZpZGVvLScgKyB0aGlzLnN0cmVhbS5zdHJlYW1JZDtcbiAgICAgICAgICAgIC8vIERFUFJFQ0FURUQgcHJvcGVydHk6IGFzc2lnbiBvbmNlIHRoZSBwcm9wZXJ0eSBpZCBpZiB0aGUgdXNlciBwcm92aWRlZCBhIHZhbGlkIHRhcmdldEVsZW1lbnRcbiAgICAgICAgICAgIGlmICghdGhpcy5pZCAmJiAhIXRoaXMudGFyZ2V0RWxlbWVudCkge1xuICAgICAgICAgICAgICAgIHRoaXMuaWQgPSB2aWRlby5pZDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAoIXRoaXMucmVtb3RlICYmICF0aGlzLnN0cmVhbS5kaXNwbGF5TXlSZW1vdGUoKSkge1xuICAgICAgICAgICAgdmlkZW8ubXV0ZWQgPSB0cnVlO1xuICAgICAgICAgICAgaWYgKHRoaXMuc3RyZWFtLm91dGJvdW5kU3RyZWFtT3B0cy5wdWJsaXNoZXJQcm9wZXJ0aWVzLm1pcnJvcikge1xuICAgICAgICAgICAgICAgIHRoaXMubWlycm9yVmlkZW8odmlkZW8pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHJlbW92ZUFsbFZpZGVvcygpOiB2b2lkIHtcbiAgICAgICAgZm9yIChsZXQgaSA9IHRoaXMuc3RyZWFtLnNlc3Npb24uc3RyZWFtTWFuYWdlcnMubGVuZ3RoIC0gMTsgaSA+PSAwOyAtLWkpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLnN0cmVhbS5zZXNzaW9uLnN0cmVhbU1hbmFnZXJzW2ldID09PSB0aGlzKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5zdHJlYW0uc2Vzc2lvbi5zdHJlYW1NYW5hZ2Vycy5zcGxpY2UoaSwgMSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLnZpZGVvcy5zbGljZSgpLnJldmVyc2UoKS5mb3JFYWNoKChzdHJlYW1NYW5hZ2VyVmlkZW8sIGluZGV4LCB2aWRlb3MpID0+IHtcbiAgICAgICAgICAgIC8vIFJlbW92ZSBvbmNhbnBsYXkgZXZlbnQgbGlzdGVuZXIgKG9ubHkgT3BlblZpZHUgYnJvd3NlciBvbmUsIG5vdCB0aGUgdXNlciBvbmVzKVxuICAgICAgICAgICAgc3RyZWFtTWFuYWdlclZpZGVvLnZpZGVvLnJlbW92ZUV2ZW50TGlzdGVuZXIoJ2NhbnBsYXknLCB0aGlzLmNhblBsYXlMaXN0ZW5lcik7XG4gICAgICAgICAgICBpZiAoISFzdHJlYW1NYW5hZ2VyVmlkZW8udGFyZ2V0RWxlbWVudCkge1xuICAgICAgICAgICAgICAgIC8vIE9ubHkgcmVtb3ZlIHZpZGVvcyBjcmVhdGVkIGJ5IE9wZW5WaWR1IEJyb3dzZXIgKHRob3NlIGdlbmVyYXRlZCBieSBwYXNzaW5nIGEgdmFsaWQgdGFyZ2V0RWxlbWVudCBpbiBPcGVuVmlkdS5pbml0UHVibGlzaGVyIGFuZCBTZXNzaW9uLnN1YnNjcmliZVxuICAgICAgICAgICAgICAgIC8vIG9yIHRob3NlIGNyZWF0ZWQgYnkgU3RyZWFtTWFuYWdlci5jcmVhdGVWaWRlb0VsZW1lbnQpLiBUaGVzZSBhcmUgYWxzbyB0aGUgdmlkZW9zIHRoYXQgdHJpZ2dlcmVkIGEgdmlkZW9FbGVtZW50Q3JlYXRlZCBldmVudFxuICAgICAgICAgICAgICAgIHN0cmVhbU1hbmFnZXJWaWRlby52aWRlby5wYXJlbnROb2RlIS5yZW1vdmVDaGlsZChzdHJlYW1NYW5hZ2VyVmlkZW8udmlkZW8pO1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCd2aWRlb0VsZW1lbnREZXN0cm95ZWQnLCBbbmV3IFZpZGVvRWxlbWVudEV2ZW50KHN0cmVhbU1hbmFnZXJWaWRlby52aWRlbywgdGhpcywgJ3ZpZGVvRWxlbWVudERlc3Ryb3llZCcpXSk7XG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3Muc3BsaWNlKHZpZGVvcy5sZW5ndGggLSAxIC0gaW5kZXgsIDEpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAvLyBSZW1vdmUgc3JjT2JqZWN0IGluIGFsbCB2aWRlb3MgbWFuYWdlZCBieSB0aGUgdXNlclxuICAgICAgICAgICAgICAgIHN0cmVhbU1hbmFnZXJWaWRlby52aWRlby5zcmNPYmplY3QgPSBudWxsO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgZGlzYXNzb2NpYXRlVmlkZW8odmlkZW86IEhUTUxWaWRlb0VsZW1lbnQpOiBib29sZWFuIHtcbiAgICAgICAgbGV0IGRpc2Fzc29jaWF0ZWQgPSBmYWxzZTtcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLnZpZGVvcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgaWYgKHRoaXMudmlkZW9zW2ldLnZpZGVvID09PSB2aWRlbykge1xuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9zLnNwbGljZShpLCAxKTtcbiAgICAgICAgICAgICAgICBkaXNhc3NvY2lhdGVkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oJ1ZpZGVvIGVsZW1lbnQgZGlzYXNzb2NpYXRlZCBmcm9tICcsIHRoaXMpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBkaXNhc3NvY2lhdGVkO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBhZGRQbGF5RXZlbnRUb0ZpcnN0VmlkZW8oKSB7XG4gICAgICAgIGlmICgoISF0aGlzLnZpZGVvc1swXSkgJiYgKCEhdGhpcy52aWRlb3NbMF0udmlkZW8pICYmICh0aGlzLnZpZGVvc1swXS52aWRlby5vbmNhbnBsYXkgPT09IG51bGwpKSB7XG4gICAgICAgICAgICB0aGlzLnZpZGVvc1swXS52aWRlby5hZGRFdmVudExpc3RlbmVyKCdjYW5wbGF5JywgdGhpcy5jYW5QbGF5TGlzdGVuZXIpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHVwZGF0ZU1lZGlhU3RyZWFtKG1lZGlhU3RyZWFtOiBNZWRpYVN0cmVhbSkge1xuICAgICAgICB0aGlzLnZpZGVvcy5mb3JFYWNoKHN0cmVhbU1hbmFnZXJWaWRlbyA9PiB7XG4gICAgICAgICAgICBzdHJlYW1NYW5hZ2VyVmlkZW8udmlkZW8uc3JjT2JqZWN0ID0gbWVkaWFTdHJlYW07XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBlbWl0RXZlbnQodHlwZTogc3RyaW5nLCBldmVudEFycmF5OiBhbnlbXSk6IHZvaWQge1xuICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCh0eXBlLCBldmVudEFycmF5KTtcbiAgICB9XG5cbiAgICBwcml2YXRlIHB1c2hOZXdTdHJlYW1NYW5hZ2VyVmlkZW8oc3RyZWFtTWFuYWdlclZpZGVvOiBTdHJlYW1NYW5hZ2VyVmlkZW8pIHtcbiAgICAgICAgdGhpcy52aWRlb3MucHVzaChzdHJlYW1NYW5hZ2VyVmlkZW8pO1xuICAgICAgICB0aGlzLmFkZFBsYXlFdmVudFRvRmlyc3RWaWRlbygpO1xuICAgICAgICBpZiAodGhpcy5zdHJlYW0uc2Vzc2lvbi5zdHJlYW1NYW5hZ2Vycy5pbmRleE9mKHRoaXMpID09PSAtMSkge1xuICAgICAgICAgICAgdGhpcy5zdHJlYW0uc2Vzc2lvbi5zdHJlYW1NYW5hZ2Vycy5wdXNoKHRoaXMpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBtaXJyb3JWaWRlbyh2aWRlbyk6IHZvaWQge1xuICAgICAgICB2aWRlby5zdHlsZS50cmFuc2Zvcm0gPSAncm90YXRlWSgxODBkZWcpJztcbiAgICAgICAgdmlkZW8uc3R5bGUud2Via2l0VHJhbnNmb3JtID0gJ3JvdGF0ZVkoMTgwZGVnKSc7XG4gICAgfVxuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBTdHJlYW0gfSBmcm9tICcuL1N0cmVhbSc7XG5pbXBvcnQgeyBTdHJlYW1NYW5hZ2VyIH0gZnJvbSAnLi9TdHJlYW1NYW5hZ2VyJztcbmltcG9ydCB7IFN1YnNjcmliZXJQcm9wZXJ0aWVzIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9JbnRlcmZhY2VzL1B1YmxpYy9TdWJzY3JpYmVyUHJvcGVydGllcyc7XG5cblxuLyoqXG4gKiBQYWNrcyByZW1vdGUgbWVkaWEgc3RyZWFtcy4gUGFydGljaXBhbnRzIGF1dG9tYXRpY2FsbHkgcmVjZWl2ZSB0aGVtIHdoZW4gb3RoZXJzIHB1Ymxpc2ggdGhlaXIgc3RyZWFtcy4gSW5pdGlhbGl6ZWQgd2l0aCBbW1Nlc3Npb24uc3Vic2NyaWJlXV0gbWV0aG9kXG4gKi9cbmV4cG9ydCBjbGFzcyBTdWJzY3JpYmVyIGV4dGVuZHMgU3RyZWFtTWFuYWdlciB7XG5cbiAgICBwcml2YXRlIHByb3BlcnRpZXM6IFN1YnNjcmliZXJQcm9wZXJ0aWVzO1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHN0cmVhbTogU3RyZWFtLCB0YXJnRWw6IHN0cmluZyB8IEhUTUxFbGVtZW50LCBwcm9wZXJ0aWVzOiBTdWJzY3JpYmVyUHJvcGVydGllcykge1xuICAgICAgICBzdXBlcihzdHJlYW0sIHRhcmdFbCk7XG4gICAgICAgIHRoaXMuZWxlbWVudCA9IHRoaXMudGFyZ2V0RWxlbWVudDtcbiAgICAgICAgdGhpcy5zdHJlYW0gPSBzdHJlYW07XG4gICAgICAgIHRoaXMucHJvcGVydGllcyA9IHByb3BlcnRpZXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU3Vic2NyaWJlIG9yIHVuc3Vic2NyaWJlIGZyb20gdGhlIGF1ZGlvIHN0cmVhbSAoaWYgYXZhaWxhYmxlKS4gQ2FsbGluZyB0aGlzIG1ldGhvZCB0d2ljZSBpbiBhIHJvdyBwYXNzaW5nIHNhbWUgdmFsdWUgd2lsbCBoYXZlIG5vIGVmZmVjdFxuICAgICAqIEBwYXJhbSB2YWx1ZSBgdHJ1ZWAgdG8gc3Vic2NyaWJlIHRvIHRoZSBhdWRpbyBzdHJlYW0sIGBmYWxzZWAgdG8gdW5zdWJzY3JpYmUgZnJvbSBpdFxuICAgICAqL1xuICAgIHN1YnNjcmliZVRvQXVkaW8odmFsdWU6IGJvb2xlYW4pOiBTdWJzY3JpYmVyIHtcbiAgICAgICAgdGhpcy5zdHJlYW0uZ2V0TWVkaWFTdHJlYW0oKS5nZXRBdWRpb1RyYWNrcygpLmZvckVhY2goKHRyYWNrKSA9PiB7XG4gICAgICAgICAgICB0cmFjay5lbmFibGVkID0gdmFsdWU7XG4gICAgICAgIH0pO1xuICAgICAgICBjb25zb2xlLmluZm8oXCInU3Vic2NyaWJlcicgaGFzIFwiICsgKHZhbHVlID8gJ3N1YnNjcmliZWQgdG8nIDogJ3Vuc3Vic2NyaWJlZCBmcm9tJykgKyAnIGl0cyBhdWRpbyBzdHJlYW0nKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU3Vic2NyaWJlIG9yIHVuc3Vic2NyaWJlIGZyb20gdGhlIHZpZGVvIHN0cmVhbSAoaWYgYXZhaWxhYmxlKS4gQ2FsbGluZyB0aGlzIG1ldGhvZCB0d2ljZSBpbiBhIHJvdyBwYXNzaW5nIHNhbWUgdmFsdWUgd2lsbCBoYXZlIG5vIGVmZmVjdFxuICAgICAqIEBwYXJhbSB2YWx1ZSBgdHJ1ZWAgdG8gc3Vic2NyaWJlIHRvIHRoZSB2aWRlbyBzdHJlYW0sIGBmYWxzZWAgdG8gdW5zdWJzY3JpYmUgZnJvbSBpdFxuICAgICAqL1xuICAgIHN1YnNjcmliZVRvVmlkZW8odmFsdWU6IGJvb2xlYW4pOiBTdWJzY3JpYmVyIHtcbiAgICAgICAgdGhpcy5zdHJlYW0uZ2V0TWVkaWFTdHJlYW0oKS5nZXRWaWRlb1RyYWNrcygpLmZvckVhY2goKHRyYWNrKSA9PiB7XG4gICAgICAgICAgICB0cmFjay5lbmFibGVkID0gdmFsdWU7XG4gICAgICAgIH0pO1xuICAgICAgICBjb25zb2xlLmluZm8oXCInU3Vic2NyaWJlcicgaGFzIFwiICsgKHZhbHVlID8gJ3N1YnNjcmliZWQgdG8nIDogJ3Vuc3Vic2NyaWJlZCBmcm9tJykgKyAnIGl0cyB2aWRlbyBzdHJlYW0nKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5leHBvcnQgZW51bSBMb2NhbFJlY29yZGVyU3RhdGUge1xuICAgIFJFQURZID0gJ1JFQURZJyxcbiAgICBSRUNPUkRJTkcgPSAnUkVDT1JESU5HJyxcbiAgICBQQVVTRUQgPSAnUEFVU0VEJyxcbiAgICBGSU5JU0hFRCA9ICdGSU5JU0hFRCdcbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbi8qKlxuICogRGVmaW5lcyBwcm9wZXJ0eSBbW09wZW5WaWR1RXJyb3IubmFtZV1dXG4gKi9cbmV4cG9ydCBlbnVtIE9wZW5WaWR1RXJyb3JOYW1lIHtcblxuICAgIC8qKlxuICAgICAqIEJyb3dzZXIgaXMgbm90IHN1cHBvcnRlZCBieSBPcGVuVmlkdS5cbiAgICAgKiBSZXR1cm5lZCB1cG9uIHVuc3VjY2Vzc2Z1bCBbW1Nlc3Npb24uY29ubmVjdF1dXG4gICAgICovXG4gICAgQlJPV1NFUl9OT1RfU1VQUE9SVEVEID0gJ0JST1dTRVJfTk9UX1NVUFBPUlRFRCcsXG5cbiAgICAvKipcbiAgICAgKiBUaGUgdXNlciBoYXNuJ3QgZ3JhbnRlZCBwZXJtaXNzaW9ucyB0byB0aGUgcmVxdWlyZWQgaW5wdXQgZGV2aWNlIHdoZW4gdGhlIGJyb3dzZXIgYXNrZWQgZm9yIHRoZW0uXG4gICAgICogUmV0dXJuZWQgdXBvbiB1bnN1Y2Nlc3NmdWwgW1tPcGVuVmlkdS5pbml0UHVibGlzaGVyXV0gb3IgW1tPcGVuVmlkdS5nZXRVc2VyTWVkaWFdXVxuICAgICAqL1xuICAgIERFVklDRV9BQ0NFU1NfREVOSUVEID0gJ0RFVklDRV9BQ0NFU1NfREVOSUVEJyxcblxuICAgIC8qKlxuICAgICAqIFRoZSB1c2VyIGhhc24ndCBncmFudGVkIHBlcm1pc3Npb25zIHRvIGNhcHR1cmUgc29tZSBkZXNrdG9wIHNjcmVlbiB3aGVuIHRoZSBicm93c2VyIGFza2VkIGZvciB0aGVtLlxuICAgICAqIFJldHVybmVkIHVwb24gdW5zdWNjZXNzZnVsIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dIG9yIFtbT3BlblZpZHUuZ2V0VXNlck1lZGlhXV1cbiAgICAgKi9cbiAgICBTQ1JFRU5fQ0FQVFVSRV9ERU5JRUQgPSAnU0NSRUVOX0NBUFRVUkVfREVOSUVEJyxcblxuICAgIC8qKlxuICAgICAqIEJyb3dzZXIgZG9lcyBub3Qgc3VwcG9ydCBzY3JlZW4gc2hhcmluZy5cbiAgICAgKiBSZXR1cm5lZCB1cG9uIHVuc3VjY2Vzc2Z1bCBbW09wZW5WaWR1LmluaXRQdWJsaXNoZXJdXVxuICAgICAqL1xuICAgIFNDUkVFTl9TSEFSSU5HX05PVF9TVVBQT1JURUQgPSAnU0NSRUVOX1NIQVJJTkdfTk9UX1NVUFBPUlRFRCcsXG5cbiAgICAvKipcbiAgICAgKiBPbmx5IGZvciBDaHJvbWUsIHRoZXJlJ3Mgbm8gc2NyZWVuIHNoYXJpbmcgZXh0ZW5zaW9uIGluc3RhbGxlZFxuICAgICAqIFJldHVybmVkIHVwb24gdW5zdWNjZXNzZnVsIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dXG4gICAgICovXG4gICAgU0NSRUVOX0VYVEVOU0lPTl9OT1RfSU5TVEFMTEVEID0gJ1NDUkVFTl9FWFRFTlNJT05fTk9UX0lOU1RBTExFRCcsXG5cbiAgICAvKipcbiAgICAgKiBPbmx5IGZvciBDaHJvbWUsIHRoZSBzY3JlZW4gc2hhcmluZyBleHRlbnNpb24gaXMgaW5zdGFsbGVkIGJ1dCBpcyBkaXNhYmxlZFxuICAgICAqIFJldHVybmVkIHVwb24gdW5zdWNjZXNzZnVsIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dXG4gICAgICovXG4gICAgU0NSRUVOX0VYVEVOU0lPTl9ESVNBQkxFRCA9ICdTQ1JFRU5fRVhURU5TSU9OX0RJU0FCTEVEJyxcblxuICAgIC8qKlxuICAgICAqIE5vIHZpZGVvIGlucHV0IGRldmljZSBmb3VuZCB3aXRoIHRoZSBwcm92aWRlZCBkZXZpY2VJZCAocHJvcGVydHkgW1tQdWJsaXNoZXJQcm9wZXJ0aWVzLnZpZGVvU291cmNlXV0pXG4gICAgICogUmV0dXJuZWQgdXBvbiB1bnN1Y2Nlc3NmdWwgW1tPcGVuVmlkdS5pbml0UHVibGlzaGVyXV1cbiAgICAgKi9cbiAgICBJTlBVVF9WSURFT19ERVZJQ0VfTk9UX0ZPVU5EID0gJ0lOUFVUX1ZJREVPX0RFVklDRV9OT1RfRk9VTkQnLFxuXG4gICAgLyoqXG4gICAgICogTm8gYXVkaW8gaW5wdXQgZGV2aWNlIGZvdW5kIHdpdGggdGhlIHByb3ZpZGVkIGRldmljZUlkIChwcm9wZXJ0eSBbW1B1Ymxpc2hlclByb3BlcnRpZXMuYXVkaW9Tb3VyY2VdXSlcbiAgICAgKiBSZXR1cm5lZCB1cG9uIHVuc3VjY2Vzc2Z1bCBbW09wZW5WaWR1LmluaXRQdWJsaXNoZXJdXVxuICAgICAqL1xuICAgIElOUFVUX0FVRElPX0RFVklDRV9OT1RfRk9VTkQgPSAnSU5QVVRfQVVESU9fREVWSUNFX05PVF9GT1VORCcsXG5cbiAgICAvKipcbiAgICAgKiBNZXRob2QgW1tPcGVuVmlkdS5pbml0UHVibGlzaGVyXV0gaGFzIGJlZW4gY2FsbGVkIHdpdGggcHJvcGVydGllcyBgdmlkZW9Tb3VyY2VgIGFuZCBgYXVkaW9Tb3VyY2VgIG9mXG4gICAgICogW1tQdWJsaXNoZXJQcm9wZXJ0aWVzXV0gcGFyYW1ldGVyIGJvdGggc2V0IHRvICpmYWxzZSogb3IgKm51bGwqXG4gICAgICovXG4gICAgTk9fSU5QVVRfU09VUkNFX1NFVCA9ICdOT19JTlBVVF9TT1VSQ0VfU0VUJyxcblxuICAgIC8qKlxuICAgICAqIFNvbWUgbWVkaWEgcHJvcGVydHkgb2YgW1tQdWJsaXNoZXJQcm9wZXJ0aWVzXV0gc3VjaCBhcyBgZnJhbWVSYXRlYCBvciBgcmVzb2x1dGlvbmAgaXMgbm90IHN1cHBvcnRlZFxuICAgICAqIGJ5IHRoZSBpbnB1dCBkZXZpY2VzICh3aGVuZXZlciBpdCBpcyBwb3NzaWJsZSB0aGV5IGFyZSBhdXRvbWF0aWNhbGx5IGFkanVzdGVkIHRvIHRoZSBtb3N0IHNpbWlsYXIgdmFsdWUpLlxuICAgICAqIFJldHVybmVkIHVwb24gdW5zdWNjZXNzZnVsIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dXG4gICAgICovXG4gICAgUFVCTElTSEVSX1BST1BFUlRJRVNfRVJST1IgPSAnUFVCTElTSEVSX1BST1BFUlRJRVNfRVJST1InLFxuXG4gICAgLyoqXG4gICAgICogVGhlIGNsaWVudCB0cmllZCB0byBjYWxsIGEgbWV0aG9kIHdpdGhvdXQgdGhlIHJlcXVpcmVkIHBlcm1pc3Npb25zLiBUaGlzIGNhbiBvY2N1ciBmb3IgbWV0aG9kcyBbW1Nlc3Npb24ucHVibGlzaF1dLFxuICAgICAqIFtbU2Vzc2lvbi5mb3JjZVVucHVibGlzaF1dIGFuZCBbW1Nlc3Npb24uZm9yY2VEaXNjb25uZWN0XV1cbiAgICAgKi9cbiAgICBPUEVOVklEVV9QRVJNSVNTSU9OX0RFTklFRCA9ICdPUEVOVklEVV9QRVJNSVNTSU9OX0RFTklFRCcsXG5cbiAgICAvKipcbiAgICAgKiBfTm90IGluIHVzZSB5ZXRfXG4gICAgICovXG4gICAgT1BFTlZJRFVfTk9UX0NPTk5FQ1RFRCA9ICdPUEVOVklEVV9OT1RfQ09OTkVDVEVEJyxcblxuICAgIC8qKlxuICAgICAqIF9Ob3QgaW4gdXNlIHlldF9cbiAgICAgKi9cbiAgICBHRU5FUklDX0VSUk9SID0gJ0dFTkVSSUNfRVJST1InXG59XG5cbi8qKlxuICogU2ltcGxlIG9iamVjdCB0byBpZGVudGlmeSBydW50aW1lIGVycm9ycyBvbiB0aGUgY2xpZW50IHNpZGVcbiAqL1xuZXhwb3J0IGNsYXNzIE9wZW5WaWR1RXJyb3Ige1xuXG4gICAgbmFtZTogT3BlblZpZHVFcnJvck5hbWU7XG4gICAgbWVzc2FnZTogc3RyaW5nO1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKG5hbWU6IE9wZW5WaWR1RXJyb3JOYW1lLCBtZXNzYWdlOiBzdHJpbmcpIHtcbiAgICAgICAgdGhpcy5uYW1lID0gbmFtZTtcbiAgICAgICAgdGhpcy5tZXNzYWdlID0gbWVzc2FnZTtcbiAgICB9XG5cbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbi8qKlxuICogSG93IHRoZSB2aWRlbyB3aWxsIGJlIGluc2VydGVkIGluIHRoZSBET00gZm9yIFB1Ymxpc2hlcnMgYW5kIFN1YnNjcmliZXJzLiBTZWUgW1tQdWJsaXNoZXJQcm9wZXJ0aWVzLmluc2VydE1vZGVdXSBhbmQgW1tTdWJzY3JpYmVyUHJvcGVydGllcy5pbnNlcnRNb2RlXV1cbiAqL1xuZXhwb3J0IGVudW0gVmlkZW9JbnNlcnRNb2RlIHtcblxuICAgIC8qKlxuICAgICAqIFZpZGVvIGluc2VydGVkIGFmdGVyIHRoZSB0YXJnZXQgZWxlbWVudCAoYXMgbmV4dCBzaWJsaW5nKVxuICAgICAqL1xuICAgIEFGVEVSID0gJ0FGVEVSJyxcbiAgICAvKipcbiAgICAgKiBWaWRlbyBpbnNlcnRlZCBhcyBsYXN0IGNoaWxkIG9mIHRoZSB0YXJnZXQgZWxlbWVudFxuICAgICAqL1xuICAgIEFQUEVORCA9ICdBUFBFTkQnLFxuICAgIC8qKlxuICAgICAqIFZpZGVvIGluc2VydGVkIGJlZm9yZSB0aGUgdGFyZ2V0IGVsZW1lbnQgKGFzIHByZXZpb3VzIHNpYmxpbmcpXG4gICAgICovXG4gICAgQkVGT1JFID0gJ0JFRk9SRScsXG4gICAgLyoqXG4gICAgICogVmlkZW8gaW5zZXJ0ZWQgYXMgZmlyc3QgY2hpbGQgb2YgdGhlIHRhcmdldCBlbGVtZW50XG4gICAgICovXG4gICAgUFJFUEVORCA9ICdQUkVQRU5EJyxcbiAgICAvKipcbiAgICAgKiBWaWRlbyByZXBsYWNlcyB0YXJnZXQgZWxlbWVudFxuICAgICAqL1xuICAgIFJFUExBQ0UgPSAnUkVQTEFDRSdcblxufSIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTctMjAxOCBPcGVuVmlkdSAoaHR0cHM6Ly9vcGVudmlkdS5pby8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuaW1wb3J0IHsgRXZlbnQgfSBmcm9tICcuL0V2ZW50JztcbmltcG9ydCB7IENvbm5lY3Rpb24gfSBmcm9tICcuLi8uLi9PcGVuVmlkdS9Db25uZWN0aW9uJztcbmltcG9ydCB7IFNlc3Npb24gfSBmcm9tICcuLi8uLi9PcGVuVmlkdS9TZXNzaW9uJztcblxuXG4vKipcbiAqIERlZmluZXMgdGhlIGZvbGxvd2luZyBldmVudHM6XG4gKiAtIGBjb25uZWN0aW9uQ3JlYXRlZGA6IGRpc3BhdGNoZWQgYnkgW1tTZXNzaW9uXV1cbiAqIC0gYGNvbm5lY3Rpb25EZXN0cm95ZWRgOiBkaXNwYXRjaGVkIGJ5IFtbU2Vzc2lvbl1dXG4gKi9cbmV4cG9ydCBjbGFzcyBDb25uZWN0aW9uRXZlbnQgZXh0ZW5kcyBFdmVudCB7XG5cbiAgICAvKipcbiAgICAgKiBDb25uZWN0aW9uIG9iamVjdCB0aGF0IHdhcyBjcmVhdGVkIG9yIGRlc3Ryb3llZFxuICAgICAqL1xuICAgIGNvbm5lY3Rpb246IENvbm5lY3Rpb247XG5cbiAgICAvKipcbiAgICAgKiBGb3IgJ2Nvbm5lY3Rpb25EZXN0cm95ZWQnIGV2ZW50OlxuICAgICAqIC0gXCJkaXNjb25uZWN0XCI6IHRoZSByZW1vdGUgdXNlciBoYXMgY2FsbGVkIGBTZXNzaW9uLmRpc2Nvbm5lY3QoKWBcbiAgICAgKiAtIFwiZm9yY2VEaXNjb25uZWN0QnlVc2VyXCI6IHRoZSByZW1vdGUgdXNlciBoYXMgYmVlbiBldmljdGVkIGZyb20gdGhlIFNlc3Npb24gYnkgb3RoZXIgdXNlciBjYWxsaW5nIGBTZXNzaW9uLmZvcmNlRGlzY29ubmVjdCgpYFxuICAgICAqIC0gXCJmb3JjZURpc2Nvbm5lY3RCeVNlcnZlclwiOiB0aGUgcmVtb3RlIHVzZXIgaGFzIGJlZW4gZXZpY3RlZCBmcm9tIHRoZSBTZXNzaW9uIGJ5IHRoZSBhcHBsaWNhdGlvblxuICAgICAqIC0gXCJzZXNzaW9uQ2xvc2VkQnlTZXJ2ZXJcIjogdGhlIFNlc3Npb24gaGFzIGJlZW4gY2xvc2VkIGJ5IHRoZSBhcHBsaWNhdGlvblxuICAgICAqIC0gXCJuZXR3b3JrRGlzY29ubmVjdFwiOiB0aGUgcmVtb3RlIHVzZXIgbmV0d29yayBjb25uZWN0aW9uIGhhcyBkcm9wcGVkXG4gICAgICpcbiAgICAgKiBGb3IgJ2Nvbm5lY3Rpb25DcmVhdGVkJyBlbXB0eSBzdHJpbmdcbiAgICAgKi9cbiAgICByZWFzb246IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3RvcihjYW5jZWxhYmxlOiBib29sZWFuLCB0YXJnZXQ6IFNlc3Npb24sIHR5cGU6IHN0cmluZywgY29ubmVjdGlvbjogQ29ubmVjdGlvbiwgcmVhc29uOiBzdHJpbmcpIHtcbiAgICAgICAgc3VwZXIoY2FuY2VsYWJsZSwgdGFyZ2V0LCB0eXBlKTtcbiAgICAgICAgdGhpcy5jb25uZWN0aW9uID0gY29ubmVjdGlvbjtcbiAgICAgICAgdGhpcy5yZWFzb24gPSByZWFzb247XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZTpuby1lbXB0eVxuICAgIGNhbGxEZWZhdWx0QmVoYXZpb3IoKSB7IH1cblxufSIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTctMjAxOCBPcGVuVmlkdSAoaHR0cHM6Ly9vcGVudmlkdS5pby8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuaW1wb3J0IHsgU3RyZWFtTWFuYWdlciB9IGZyb20gJy4uLy4uL09wZW5WaWR1L1N0cmVhbU1hbmFnZXInO1xuaW1wb3J0IHsgU2Vzc2lvbiB9IGZyb20gJy4uLy4uL09wZW5WaWR1L1Nlc3Npb24nO1xuXG5leHBvcnQgYWJzdHJhY3QgY2xhc3MgRXZlbnQge1xuXG4gICAgLyoqXG4gICAgICogV2hldGhlciB0aGUgZXZlbnQgaGFzIGEgZGVmYXVsdCBiZWhhdmlvciB0aGF0IG1heSBiZSBwcmV2ZW50ZWQgYnkgY2FsbGluZyBbW0V2ZW50LnByZXZlbnREZWZhdWx0XV1cbiAgICAgKi9cbiAgICBjYW5jZWxhYmxlOiBib29sZWFuO1xuXG4gICAgLyoqXG4gICAgICogVGhlIG9iamVjdCB0aGF0IGRpc3BhdGNoZWQgdGhlIGV2ZW50XG4gICAgICovXG4gICAgdGFyZ2V0OiBTZXNzaW9uIHwgU3RyZWFtTWFuYWdlcjtcblxuICAgIC8qKlxuICAgICAqIFRoZSB0eXBlIG9mIGV2ZW50LiBUaGlzIGlzIHRoZSBzYW1lIHN0cmluZyB5b3UgcGFzcyBhcyBmaXJzdCBwYXJhbWV0ZXIgd2hlbiBjYWxsaW5nIG1ldGhvZCBgb24oKWAgb2YgYW55IG9iamVjdCBpbXBsZW1lbnRpbmcgW1tFdmVudERpc3BhdGNoZXJdXSBpbnRlcmZhY2VcbiAgICAgKi9cbiAgICB0eXBlOiBzdHJpbmc7XG5cbiAgICBwcml2YXRlIGhhc0JlZW5QcmV2ZW50ZWQgPSBmYWxzZTtcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3RvcihjYW5jZWxhYmxlOiBib29sZWFuLCB0YXJnZXQ6IFNlc3Npb24gfCBTdHJlYW1NYW5hZ2VyLCB0eXBlOiBzdHJpbmcpIHtcbiAgICAgICAgdGhpcy5jYW5jZWxhYmxlID0gY2FuY2VsYWJsZTtcbiAgICAgICAgdGhpcy50YXJnZXQgPSB0YXJnZXQ7XG4gICAgICAgIHRoaXMudHlwZSA9IHR5cGU7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogV2hldGhlciB0aGUgZGVmYXVsdCBiZWFoaXZvdXIgb2YgdGhlIGV2ZW50IGhhcyBiZWVuIHByZXZlbnRlZCBvciBub3QuIENhbGwgW1tFdmVudC5wcmV2ZW50RGVmYXVsdF1dIHRvIHByZXZlbnQgaXRcbiAgICAgKi9cbiAgICBpc0RlZmF1bHRQcmV2ZW50ZWQoKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiB0aGlzLmhhc0JlZW5QcmV2ZW50ZWQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUHJldmVudHMgdGhlIGRlZmF1bHQgYmVoYXZpb3Igb2YgdGhlIGV2ZW50LiBUaGUgZm9sbG93aW5nIGV2ZW50cyBoYXZlIGEgZGVmYXVsdCBiZWhhdmlvcjpcbiAgICAgKlxuICAgICAqIC0gYHNlc3Npb25EaXNjb25uZWN0ZWRgOiBkaXNwYXRjaGVkIGJ5IFtbU2Vzc2lvbl1dIG9iamVjdCwgYXV0b21hdGljYWxseSB1bnN1YnNjcmliZXMgdGhlIGxlYXZpbmcgcGFydGljaXBhbnQgZnJvbSBldmVyeSBTdWJzY3JpYmVyIG9iamVjdCBvZiB0aGUgc2Vzc2lvbiAodGhpcyBpbmNsdWRlcyBjbG9zaW5nIHRoZSBXZWJSVENQZWVyIGNvbm5lY3Rpb24gYW5kIGRpc3Bvc2luZyBhbGwgTWVkaWFTdHJlYW1UcmFja3MpXG4gICAgICogYW5kIGFsc28gZGVsZXRlcyBhbnkgSFRNTCB2aWRlbyBlbGVtZW50IGFzc29jaWF0ZWQgdG8gZWFjaCBTdWJzY3JpYmVyIChvbmx5IHRob3NlIGNyZWF0ZWQgYnkgT3BlblZpZHUgQnJvd3NlciwgZWl0aGVyIGJ5IHBhc3NpbmcgYSB2YWxpZCBwYXJhbWV0ZXIgYXMgYHRhcmdldEVsZW1lbnRgIGluIG1ldGhvZCBbW1Nlc3Npb24uc3Vic2NyaWJlXV0gb3JcbiAgICAgKiBieSBjYWxsaW5nIFtbU3Vic2NyaWJlci5jcmVhdGVWaWRlb0VsZW1lbnRdXSkuIEZvciBldmVyeSB2aWRlbyByZW1vdmVkLCBlYWNoIFN1YnNjcmliZXIgb2JqZWN0IHdpbGwgYWxzbyBkaXNwYXRjaCBhIGB2aWRlb0VsZW1lbnREZXN0cm95ZWRgIGV2ZW50LlxuICAgICAqXG4gICAgICogLSBgc3RyZWFtRGVzdHJveWVkYDpcbiAgICAgKiAgIC0gSWYgZGlzcGF0Y2hlZCBieSBhIFtbUHVibGlzaGVyXV0gKCp5b3UqIGhhdmUgdW5wdWJsaXNoZWQpOiBhdXRvbWF0aWNhbGx5IHN0b3BzIGFsbCBtZWRpYSB0cmFja3MgYW5kIGRlbGV0ZXMgYW55IEhUTUwgdmlkZW8gZWxlbWVudCBhc3NvY2lhdGVkIHRvIGl0IChvbmx5IHRob3NlIGNyZWF0ZWQgYnkgT3BlblZpZHUgQnJvd3NlciwgZWl0aGVyIGJ5IHBhc3NpbmcgYSB2YWxpZCBwYXJhbWV0ZXIgYXMgYHRhcmdldEVsZW1lbnRgXG4gICAgICogaW4gbWV0aG9kIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dIG9yIGJ5IGNhbGxpbmcgW1tQdWJsaXNoZXIuY3JlYXRlVmlkZW9FbGVtZW50XV0pLiBGb3IgZXZlcnkgdmlkZW8gcmVtb3ZlZCwgdGhlIFB1Ymxpc2hlciBvYmplY3Qgd2lsbCBhbHNvIGRpc3BhdGNoIGEgYHZpZGVvRWxlbWVudERlc3Ryb3llZGAgZXZlbnQuXG4gICAgICogICAtIElmIGRpc3BhdGNoZWQgYnkgW1tTZXNzaW9uXV0gKCpvdGhlciB1c2VyKiBoYXMgdW5wdWJsaXNoZWQpOiBhdXRvbWF0aWNhbGx5IHVuc3Vic2NyaWJlcyB0aGUgcHJvcGVyIFN1YnNjcmliZXIgb2JqZWN0IGZyb20gdGhlIHNlc3Npb24gKHRoaXMgaW5jbHVkZXMgY2xvc2luZyB0aGUgV2ViUlRDUGVlciBjb25uZWN0aW9uIGFuZCBkaXNwb3NpbmcgYWxsIE1lZGlhU3RyZWFtVHJhY2tzKVxuICAgICAqIGFuZCBhbHNvIGRlbGV0ZXMgYW55IEhUTUwgdmlkZW8gZWxlbWVudCBhc3NvY2lhdGVkIHRvIHRoYXQgU3Vic2NyaWJlciAob25seSB0aG9zZSBjcmVhdGVkIGJ5IE9wZW5WaWR1IEJyb3dzZXIsIGVpdGhlciBieSBwYXNzaW5nIGEgdmFsaWQgcGFyYW1ldGVyIGFzIGB0YXJnZXRFbGVtZW50YCBpbiBtZXRob2QgW1tTZXNzaW9uLnN1YnNjcmliZV1dIG9yXG4gICAgICogYnkgY2FsbGluZyBbW1N1YnNjcmliZXIuY3JlYXRlVmlkZW9FbGVtZW50XV0pLiBGb3IgZXZlcnkgdmlkZW8gcmVtb3ZlZCwgdGhlIFN1YnNjcmliZXIgb2JqZWN0IHdpbGwgYWxzbyBkaXNwYXRjaCBhIGB2aWRlb0VsZW1lbnREZXN0cm95ZWRgIGV2ZW50LlxuICAgICAqL1xuICAgIHByZXZlbnREZWZhdWx0KCkge1xuICAgICAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6bm8tZW1wdHlcbiAgICAgICAgdGhpcy5jYWxsRGVmYXVsdEJlaGF2aW9yID0gKCkgPT4geyB9O1xuICAgICAgICB0aGlzLmhhc0JlZW5QcmV2ZW50ZWQgPSB0cnVlO1xuICAgIH1cblxuICAgIHByb3RlY3RlZCBhYnN0cmFjdCBjYWxsRGVmYXVsdEJlaGF2aW9yKCk7XG5cbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IEV2ZW50IH0gZnJvbSAnLi9FdmVudCc7XG5pbXBvcnQgeyBDb25uZWN0aW9uIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvQ29ubmVjdGlvbic7XG5pbXBvcnQgeyBTZXNzaW9uIH0gZnJvbSAnLi4vLi4nO1xuXG5cbi8qKlxuICogRGVmaW5lcyB0aGUgZm9sbG93aW5nIGV2ZW50czpcbiAqIC0gYHB1Ymxpc2hlclN0YXJ0U3BlYWtpbmdgOiBkaXNwYXRjaGVkIGJ5IFtbU2Vzc2lvbl1dXG4gKiAtIGBwdWJsaXNoZXJTdG9wU3BlYWtpbmdgOiBkaXNwYXRjaGVkIGJ5IFtbU2Vzc2lvbl1dXG4gKlxuICogTW9yZSBpbmZvcm1hdGlvbjpcbiAqIC0gVGhpcyBldmVudHMgd2lsbCBvbmx5IGJlIHRyaWdnZXJlZCBmb3IgKipyZW1vdGUgc3RyZWFtcyB0aGF0IGhhdmUgYXVkaW8gdHJhY2tzKipcbiAqIC0gQm90aCBldmVudHMgc2hhcmUgdGhlIHNhbWUgbGlmZWN5Y2xlLiBUaGF0IG1lYW5zIHRoYXQgeW91IGNhbiBzdWJzY3JpYmUgdG8gb25seSBvbmUgb2YgdGhlbSBpZiB5b3Ugd2FudCwgYnV0IGlmIHlvdSBjYWxsIGBTZXNzaW9uLm9mZigncHVibGlzaGVyU3RvcFNwZWFraW5nJylgLFxuICoga2VlcCBpbiBtaW5kIHRoYXQgdGhpcyB3aWxsIGFsc28gaW50ZXJuYWxseSByZW1vdmUgYW55ICdwdWJsaXNoZXJTdGFydFNwZWFraW5nJyBldmVudFxuICogLSBZb3UgY2FuIGZ1cnRoZXIgY29uZmlndXJlIGhvdyB0aGUgZXZlbnRzIGFyZSBkaXNwYXRjaGVkIGJ5IHNldHRpbmcgcHJvcGVydHkgYHB1Ymxpc2hlclNwZWFraW5nRXZlbnRzT3B0aW9uc2AgaW4gdGhlIGNhbGwgb2YgW1tPcGVuVmlkdS5zZXRBZHZhbmNlZENvbmZpZ3VyYXRpb25dXVxuICovXG5leHBvcnQgY2xhc3MgUHVibGlzaGVyU3BlYWtpbmdFdmVudCBleHRlbmRzIEV2ZW50IHtcblxuICAgIC8qKlxuICAgICAqIFRoZSBjbGllbnQgdGhhdCBzdGFydGVkIG9yIHN0b3BwZWQgc3BlYWtpbmdcbiAgICAgKi9cbiAgICBjb25uZWN0aW9uOiBDb25uZWN0aW9uO1xuXG4gICAgLyoqXG4gICAgICogVGhlIHN0cmVhbUlkIG9mIHRoZSBTdHJlYW0gYWZmZWN0ZWQgYnkgdGhlIHNwZWFraW5nIGV2ZW50XG4gICAgICovXG4gICAgc3RyZWFtSWQ6IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3Rvcih0YXJnZXQ6IFNlc3Npb24sIHR5cGU6IHN0cmluZywgY29ubmVjdGlvbjogQ29ubmVjdGlvbiwgc3RyZWFtSWQ6IHN0cmluZykge1xuICAgICAgICBzdXBlcihmYWxzZSwgdGFyZ2V0LCB0eXBlKTtcbiAgICAgICAgdGhpcy50eXBlID0gdHlwZTtcbiAgICAgICAgdGhpcy5jb25uZWN0aW9uID0gY29ubmVjdGlvbjtcbiAgICAgICAgdGhpcy5zdHJlYW1JZCA9IHN0cmVhbUlkO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6bm8tZW1wdHlcbiAgICBjYWxsRGVmYXVsdEJlaGF2aW9yKCkgeyB9XG5cbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IEV2ZW50IH0gZnJvbSAnLi9FdmVudCc7XG5pbXBvcnQgeyBTZXNzaW9uIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvU2Vzc2lvbic7XG5cblxuLyoqXG4gKiBEZWZpbmVzIHRoZSBmb2xsb3dpbmcgZXZlbnRzOlxuICogLSBgcmVjb3JkaW5nU3RhcnRlZGA6IGRpc3BhdGNoZWQgYnkgW1tTZXNzaW9uXV1cbiAqIC0gYHJlY29yZGluZ1N0b3BwZWRgOiBkaXNwYXRjaGVkIGJ5IFtbU2Vzc2lvbl1dXG4gKi9cbmV4cG9ydCBjbGFzcyBSZWNvcmRpbmdFdmVudCBleHRlbmRzIEV2ZW50IHtcblxuICAgIC8qKlxuICAgICAqIFRoZSByZWNvcmRpbmcgSUQgZ2VuZXJhdGVkIGluIG9wZW52aWR1LXNlcnZlclxuICAgICAqL1xuICAgIGlkOiBzdHJpbmc7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgcmVjb3JkaW5nIG5hbWUgeW91IHN1cHBsaWVkIHRvIG9wZW52aWR1LXNlcnZlci4gRm9yIGV4YW1wbGUsIHRvIG5hbWUgeW91ciByZWNvcmRpbmcgZmlsZSBNWV9SRUNPUkRJTkc6XG4gICAgICogLSBXaXRoICoqQVBJIFJFU1QqKjogUE9TVCB0byBgL2FwaS9yZWNvcmRpbmdzL3N0YXJ0YCBwYXNzaW5nIEpTT04gYm9keSBge1wic2Vzc2lvblwiOlwic2Vzc2lvbklkXCIsXCJuYW1lXCI6XCJNWV9SRUNPUkRJTkdcIn1gXG4gICAgICogLSBXaXRoICoqb3BlbnZpZHUtamF2YS1jbGllbnQqKjogYE9wZW5WaWR1LnN0YXJ0UmVjb3JkaW5nKHNlc3Npb25JZCwgXCJNWV9SRUNPUkRJTkdcIilgIG9yIGBPcGVuVmlkdS5zdGFydFJlY29yZGluZyhzZXNzaW9uSWQsIG5ldyBSZWNvcmRpbmdQcm9wZXJ0aWVzLkJ1aWxkZXIoKS5uYW1lKFwiTVlfUkVDT1JESU5HXCIpLmJ1aWxkKCkpYFxuICAgICAqIC0gV2l0aCAqKm9wZW52aWR1LW5vZGUtY2xpZW50Kio6IGBPcGVuVmlkdS5zdGFydFJlY29yZGluZyhzZXNzaW9uSWQsIFwiTVlfUkVDT1JESU5HXCIpYCBvciBgT3BlblZpZHUuc3RhcnRSZWNvcmRpbmcoc2Vzc2lvbklkLCB7bmFtZTogXCJNWV9SRUNPUkRJTkdcIn0pYFxuICAgICAqXG4gICAgICogSWYgbm8gbmFtZSBpcyBzdXBwbGllZCwgdGhpcyBwcm9wZXJ0eSB3aWxsIGJlIHVuZGVmaW5lZCBhbmQgdGhlIHJlY29yZGVkIGZpbGUgd2lsbCBiZSBuYW1lZCBhZnRlciBwcm9wZXJ0eSBbW2lkXV1cbiAgICAgKi9cbiAgICBuYW1lPzogc3RyaW5nO1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHRhcmdldDogU2Vzc2lvbiwgdHlwZTogc3RyaW5nLCBpZDogc3RyaW5nLCBuYW1lOiBzdHJpbmcpIHtcbiAgICAgICAgc3VwZXIoZmFsc2UsIHRhcmdldCwgdHlwZSk7XG4gICAgICAgIHRoaXMuaWQgPSBpZDtcbiAgICAgICAgaWYgKG5hbWUgIT09IGlkKSB7XG4gICAgICAgICAgICB0aGlzLm5hbWUgPSBuYW1lO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZTpuby1lbXB0eVxuICAgIGNhbGxEZWZhdWx0QmVoYXZpb3IoKSB7IH1cblxufSIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTctMjAxOCBPcGVuVmlkdSAoaHR0cHM6Ly9vcGVudmlkdS5pby8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuaW1wb3J0IHsgRXZlbnQgfSBmcm9tICcuL0V2ZW50JztcbmltcG9ydCB7IFNlc3Npb24gfSBmcm9tICcuLi8uLi9PcGVuVmlkdS9TZXNzaW9uJztcblxuXG4vKipcbiAqIERlZmluZXMgZXZlbnQgYHNlc3Npb25EaXNjb25uZWN0ZWRgIGRpc3BhdGNoZWQgYnkgW1tTZXNzaW9uXV1cbiAqL1xuZXhwb3J0IGNsYXNzIFNlc3Npb25EaXNjb25uZWN0ZWRFdmVudCBleHRlbmRzIEV2ZW50IHtcblxuICAgIC8qKlxuICAgICAqIC0gXCJkaXNjb25uZWN0XCI6IHlvdSBoYXZlIGNhbGxlZCBgU2Vzc2lvbi5kaXNjb25uZWN0KClgXG4gICAgICogLSBcImZvcmNlRGlzY29ubmVjdEJ5VXNlclwiOiB5b3UgaGF2ZSBiZWVuIGV2aWN0ZWQgZnJvbSB0aGUgU2Vzc2lvbiBieSBvdGhlciB1c2VyIGNhbGxpbmcgYFNlc3Npb24uZm9yY2VEaXNjb25uZWN0KClgXG4gICAgICogLSBcImZvcmNlRGlzY29ubmVjdEJ5U2VydmVyXCI6IHlvdSBoYXZlIGJlZW4gZXZpY3RlZCBmcm9tIHRoZSBTZXNzaW9uIGJ5IHRoZSBhcHBsaWNhdGlvblxuICAgICAqIC0gXCJzZXNzaW9uQ2xvc2VkQnlTZXJ2ZXJcIjogdGhlIFNlc3Npb24gaGFzIGJlZW4gY2xvc2VkIGJ5IHRoZSBhcHBsaWNhdGlvblxuICAgICAqIC0gXCJuZXR3b3JrRGlzY29ubmVjdFwiOiB5b3VyIG5ldHdvcmsgY29ubmVjdGlvbiBoYXMgZHJvcHBlZFxuICAgICAqL1xuICAgIHJlYXNvbjogc3RyaW5nO1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHRhcmdldDogU2Vzc2lvbiwgcmVhc29uOiBzdHJpbmcpIHtcbiAgICAgICAgc3VwZXIodHJ1ZSwgdGFyZ2V0LCAnc2Vzc2lvbkRpc2Nvbm5lY3RlZCcpO1xuICAgICAgICB0aGlzLnJlYXNvbiA9IHJlYXNvbjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgY2FsbERlZmF1bHRCZWhhdmlvcigpIHtcblxuICAgICAgICBjb25zb2xlLmluZm8oXCJDYWxsaW5nIGRlZmF1bHQgYmVoYXZpb3IgdXBvbiAnXCIgKyB0aGlzLnR5cGUgKyBcIicgZXZlbnQgZGlzcGF0Y2hlZCBieSAnU2Vzc2lvbidcIik7XG5cbiAgICAgICAgY29uc3Qgc2Vzc2lvbiA9IDxTZXNzaW9uPnRoaXMudGFyZ2V0O1xuXG4gICAgICAgIC8vIERpc3Bvc2UgYW5kIGRlbGV0ZSBhbGwgcmVtb3RlIENvbm5lY3Rpb25zXG4gICAgICAgIGZvciAoY29uc3QgY29ubmVjdGlvbklkIGluIHNlc3Npb24ucmVtb3RlQ29ubmVjdGlvbnMpIHtcbiAgICAgICAgICAgIGlmICghIXNlc3Npb24ucmVtb3RlQ29ubmVjdGlvbnNbY29ubmVjdGlvbklkXS5zdHJlYW0pIHtcbiAgICAgICAgICAgICAgICBzZXNzaW9uLnJlbW90ZUNvbm5lY3Rpb25zW2Nvbm5lY3Rpb25JZF0uc3RyZWFtLmRpc3Bvc2VXZWJSdGNQZWVyKCk7XG4gICAgICAgICAgICAgICAgc2Vzc2lvbi5yZW1vdGVDb25uZWN0aW9uc1tjb25uZWN0aW9uSWRdLnN0cmVhbS5kaXNwb3NlTWVkaWFTdHJlYW0oKTtcbiAgICAgICAgICAgICAgICBpZiAoc2Vzc2lvbi5yZW1vdGVDb25uZWN0aW9uc1tjb25uZWN0aW9uSWRdLnN0cmVhbS5zdHJlYW1NYW5hZ2VyKSB7XG4gICAgICAgICAgICAgICAgICAgIHNlc3Npb24ucmVtb3RlQ29ubmVjdGlvbnNbY29ubmVjdGlvbklkXS5zdHJlYW0uc3RyZWFtTWFuYWdlci5yZW1vdmVBbGxWaWRlb3MoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZGVsZXRlIHNlc3Npb24ucmVtb3RlU3RyZWFtc0NyZWF0ZWRbc2Vzc2lvbi5yZW1vdGVDb25uZWN0aW9uc1tjb25uZWN0aW9uSWRdLnN0cmVhbS5zdHJlYW1JZF07XG4gICAgICAgICAgICAgICAgc2Vzc2lvbi5yZW1vdGVDb25uZWN0aW9uc1tjb25uZWN0aW9uSWRdLmRpc3Bvc2UoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGRlbGV0ZSBzZXNzaW9uLnJlbW90ZUNvbm5lY3Rpb25zW2Nvbm5lY3Rpb25JZF07XG4gICAgICAgIH1cbiAgICB9XG5cbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IEV2ZW50IH0gZnJvbSAnLi9FdmVudCc7XG5pbXBvcnQgeyBDb25uZWN0aW9uIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvQ29ubmVjdGlvbic7XG5pbXBvcnQgeyBTZXNzaW9uIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvU2Vzc2lvbic7XG5cblxuLyoqXG4gKiBEZWZpbmVzIHRoZSBmb2xsb3dpbmcgZXZlbnRzOlxuICogLSBgc2lnbmFsYDogZGlzcGF0Y2hlZCBieSBbW1Nlc3Npb25dXVxuICogLSBgc2lnbmFsOlRZUEVgOiBkaXNwYXRjaGVkIGJ5IFtbU2Vzc2lvbl1dXG4gKi9cbmV4cG9ydCBjbGFzcyBTaWduYWxFdmVudCBleHRlbmRzIEV2ZW50IHtcblxuICAgIC8qKlxuICAgICAqIFRoZSB0eXBlIG9mIHNpZ25hbCAoY2FuIGJlIGVtcHR5KS5cbiAgICAgKlxuICAgICAqIFRoZSBjbGllbnQgbXVzdCBiZSBzdWJzY3JpYmVkIHRvIGBTZXNzaW9uLm9uKCdzaWduYWw6dHlwZScsIGZ1bmN0aW9uKHNpZ25hbEV2ZW50KSB7Li4ufSlgIHRvIHJlY2VpdmUgdGhpcyBvYmplY3QgaW4gdGhlIGNhbGxiYWNrLlxuICAgICAqXG4gICAgICogU3Vic2NyaWJpbmcgdG8gYFNlc3Npb24ub24oJ3NpZ25hbCcsIGZ1bmN0aW9uKHNpZ25hbEV2ZW50KSB7Li4ufSlgIHdpbGwgdHJpZ2dlciBhbGwgdHlwZXMgb2Ygc2lnbmFscy5cbiAgICAgKi9cbiAgICB0eXBlOiBzdHJpbmc7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgbWVzc2FnZSBvZiB0aGUgc2lnbmFsIChjYW4gYmUgZW10cHkpXG4gICAgICovXG4gICAgZGF0YTogc3RyaW5nO1xuXG4gICAgLyoqXG4gICAgICogVGhlIGNsaWVudCB0aGF0IHNlbnQgdGhlIHNpZ25hbFxuICAgICAqL1xuICAgIGZyb206IENvbm5lY3Rpb247XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgY29uc3RydWN0b3IodGFyZ2V0OiBTZXNzaW9uLCB0eXBlOiBzdHJpbmcsIGRhdGE6IHN0cmluZywgZnJvbTogQ29ubmVjdGlvbikge1xuICAgICAgICBzdXBlcihmYWxzZSwgdGFyZ2V0LCB0eXBlKTtcbiAgICAgICAgdGhpcy50eXBlID0gdHlwZTtcbiAgICAgICAgdGhpcy5kYXRhID0gZGF0YTtcbiAgICAgICAgdGhpcy5mcm9tID0gZnJvbTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lOm5vLWVtcHR5XG4gICAgY2FsbERlZmF1bHRCZWhhdmlvcigpIHsgfVxuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBFdmVudCB9IGZyb20gJy4vRXZlbnQnO1xuaW1wb3J0IHsgUHVibGlzaGVyIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvUHVibGlzaGVyJztcbmltcG9ydCB7IFNlc3Npb24gfSBmcm9tICcuLi8uLi9PcGVuVmlkdS9TZXNzaW9uJztcbmltcG9ydCB7IFN0cmVhbSB9IGZyb20gJy4uLy4uL09wZW5WaWR1L1N0cmVhbSc7XG5cblxuLyoqXG4gKiBEZWZpbmVzIHRoZSBmb2xsb3dpbmcgZXZlbnRzOlxuICogLSBgc3RyZWFtQ3JlYXRlZGA6IGRpc3BhdGNoZWQgYnkgW1tTZXNzaW9uXV0gYW5kIFtbUHVibGlzaGVyXV1cbiAqIC0gYHN0cmVhbURlc3Ryb3llZGA6IGRpc3BhdGNoZWQgYnkgW1tTZXNzaW9uXV0gYW5kIFtbUHVibGlzaGVyXV1cbiAqL1xuZXhwb3J0IGNsYXNzIFN0cmVhbUV2ZW50IGV4dGVuZHMgRXZlbnQge1xuXG4gICAgLyoqXG4gICAgICogU3RyZWFtIG9iamVjdCB0aGF0IHdhcyBjcmVhdGVkIG9yIGRlc3Ryb3llZFxuICAgICAqL1xuICAgIHN0cmVhbTogU3RyZWFtO1xuXG4gICAgLyoqXG4gICAgICogRm9yICdzdHJlYW1EZXN0cm95ZWQnIGV2ZW50OlxuICAgICAqIC0gXCJ1bnB1Ymxpc2hcIjogbWV0aG9kIGBTZXNzaW9uLnVucHVibGlzaCgpYCBoYXMgYmVlbiBjYWxsZWRcbiAgICAgKiAtIFwiZGlzY29ubmVjdFwiOiBtZXRob2QgYFNlc3Npb24uZGlzY29ubmVjdCgpYCBoYXMgYmVlbiBjYWxsZWRcbiAgICAgKiAtIFwiZm9yY2VVbnB1Ymxpc2hCeVVzZXJcIjogc29tZSB1c2VyIGhhcyBjYWxsZWQgYFNlc3Npb24uZm9yY2VVbnB1Ymxpc2goKWAgb3ZlciB0aGUgU3RyZWFtXG4gICAgICogLSBcImZvcmNlRGlzY29ubmVjdEJ5VXNlclwiOiBzb21lIHVzZXIgaGFzIGNhbGxlZCBgU2Vzc2lvbi5mb3JjZURpc2Nvbm5lY3QoKWAgb3ZlciB0aGUgU3RyZWFtXG4gICAgICogLSBcImZvcmNlVW5wdWJsaXNoQnlTZXJ2ZXJcIjogdGhlIHVzZXIncyBzdHJlYW0gaGFzIGJlZW4gdW5wdWJsaXNoZWQgZnJvbSB0aGUgU2Vzc2lvbiBieSB0aGUgYXBwbGljYXRpb25cbiAgICAgKiAtIFwiZm9yY2VEaXNjb25uZWN0QnlTZXJ2ZXJcIjogdGhlIHVzZXIgaGFzIGJlZW4gZXZpY3RlZCBmcm9tIHRoZSBTZXNzaW9uIGJ5IHRoZSBhcHBsaWNhdGlvblxuICAgICAqIC0gXCJzZXNzaW9uQ2xvc2VkQnlTZXJ2ZXJcIjogdGhlIFNlc3Npb24gaGFzIGJlZW4gY2xvc2VkIGJ5IHRoZSBhcHBsaWNhdGlvblxuICAgICAqIC0gXCJuZXR3b3JrRGlzY29ubmVjdFwiOiB0aGUgdXNlcidzIG5ldHdvcmsgY29ubmVjdGlvbiBoYXMgZHJvcHBlZFxuICAgICAqXG4gICAgICogRm9yICdzdHJlYW1DcmVhdGVkJyBlbXB0eSBzdHJpbmdcbiAgICAgKi9cbiAgICByZWFzb246IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3RvcihjYW5jZWxhYmxlOiBib29sZWFuLCB0YXJnZXQ6IFNlc3Npb24gfCBQdWJsaXNoZXIsIHR5cGU6IHN0cmluZywgc3RyZWFtOiBTdHJlYW0sIHJlYXNvbjogc3RyaW5nKSB7XG4gICAgICAgIHN1cGVyKGNhbmNlbGFibGUsIHRhcmdldCwgdHlwZSk7XG4gICAgICAgIHRoaXMuc3RyZWFtID0gc3RyZWFtO1xuICAgICAgICB0aGlzLnJlYXNvbiA9IHJlYXNvbjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgY2FsbERlZmF1bHRCZWhhdmlvcigpIHtcbiAgICAgICAgaWYgKHRoaXMudHlwZSA9PT0gJ3N0cmVhbURlc3Ryb3llZCcpIHtcblxuICAgICAgICAgICAgaWYgKHRoaXMudGFyZ2V0IGluc3RhbmNlb2YgU2Vzc2lvbikge1xuICAgICAgICAgICAgICAgIC8vIFJlbW90ZSBTdHJlYW1cbiAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oXCJDYWxsaW5nIGRlZmF1bHQgYmVoYXZpb3IgdXBvbiAnXCIgKyB0aGlzLnR5cGUgKyBcIicgZXZlbnQgZGlzcGF0Y2hlZCBieSAnU2Vzc2lvbidcIik7XG4gICAgICAgICAgICAgICAgdGhpcy5zdHJlYW0uZGlzcG9zZVdlYlJ0Y1BlZXIoKTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAodGhpcy50YXJnZXQgaW5zdGFuY2VvZiBQdWJsaXNoZXIpIHtcbiAgICAgICAgICAgICAgICAvLyBMb2NhbCBTdHJlYW1cbiAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oXCJDYWxsaW5nIGRlZmF1bHQgYmVoYXZpb3IgdXBvbiAnXCIgKyB0aGlzLnR5cGUgKyBcIicgZXZlbnQgZGlzcGF0Y2hlZCBieSAnUHVibGlzaGVyJ1wiKTtcbiAgICAgICAgICAgICAgICBjbGVhckludGVydmFsKCg8UHVibGlzaGVyPnRoaXMudGFyZ2V0KS5zY3JlZW5TaGFyZVJlc2l6ZUludGVydmFsKTtcbiAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbS5pc0xvY2FsU3RyZWFtUmVhZHlUb1B1Ymxpc2ggPSBmYWxzZTtcblxuICAgICAgICAgICAgICAgIC8vIERlbGV0ZSBQdWJsaXNoZXIgb2JqZWN0IGZyb20gT3BlblZpZHUgcHVibGlzaGVycyBhcnJheVxuICAgICAgICAgICAgICAgIGNvbnN0IG9wZW52aWR1UHVibGlzaGVycyA9ICg8UHVibGlzaGVyPnRoaXMudGFyZ2V0KS5vcGVudmlkdS5wdWJsaXNoZXJzO1xuICAgICAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgb3BlbnZpZHVQdWJsaXNoZXJzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChvcGVudmlkdVB1Ymxpc2hlcnNbaV0gPT09ICg8UHVibGlzaGVyPnRoaXMudGFyZ2V0KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgb3BlbnZpZHVQdWJsaXNoZXJzLnNwbGljZShpLCAxKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBEaXNwb3NlIHRoZSBNZWRpYVN0cmVhbSBsb2NhbCBvYmplY3RcbiAgICAgICAgICAgIHRoaXMuc3RyZWFtLmRpc3Bvc2VNZWRpYVN0cmVhbSgpO1xuXG4gICAgICAgICAgICAvLyBSZW1vdmUgZnJvbSBET00gYWxsIHZpZGVvIGVsZW1lbnRzIGFzc29jaWF0ZWQgdG8gdGhpcyBTdHJlYW0sIGlmIHRoZXJlJ3MgYSBTdHJlYW1NYW5hZ2VyIGRlZmluZWRcbiAgICAgICAgICAgIC8vIChtZXRob2QgU2Vzc2lvbi5zdWJzY3JpYmUgbXVzdCBoYXZlIGJlZW4gY2FsbGVkKVxuICAgICAgICAgICAgaWYgKHRoaXMuc3RyZWFtLnN0cmVhbU1hbmFnZXIpIHRoaXMuc3RyZWFtLnN0cmVhbU1hbmFnZXIucmVtb3ZlQWxsVmlkZW9zKCk7XG5cbiAgICAgICAgICAgIC8vIERlbGV0ZSBzdHJlYW0gZnJvbSBTZXNzaW9uLnJlbW90ZVN0cmVhbXNDcmVhdGVkIG1hcFxuICAgICAgICAgICAgZGVsZXRlIHRoaXMuc3RyZWFtLnNlc3Npb24ucmVtb3RlU3RyZWFtc0NyZWF0ZWRbdGhpcy5zdHJlYW0uc3RyZWFtSWRdO1xuXG4gICAgICAgICAgICAvLyBEZWxldGUgU3RyZWFtT3B0aW9uc1NlcnZlciBmcm9tIHJlbW90ZSBDb25uZWN0aW9uXG4gICAgICAgICAgICBjb25zdCByZW1vdGVDb25uZWN0aW9uID0gdGhpcy5zdHJlYW0uc2Vzc2lvbi5yZW1vdGVDb25uZWN0aW9uc1t0aGlzLnN0cmVhbS5jb25uZWN0aW9uLmNvbm5lY3Rpb25JZF07XG4gICAgICAgICAgICBpZiAoISFyZW1vdGVDb25uZWN0aW9uICYmICEhcmVtb3RlQ29ubmVjdGlvbi5vcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgY29uc3Qgc3RyZWFtT3B0aW9uc1NlcnZlciA9IHJlbW90ZUNvbm5lY3Rpb24ub3B0aW9ucy5zdHJlYW1zO1xuICAgICAgICAgICAgICAgIGZvciAobGV0IGkgPSBzdHJlYW1PcHRpb25zU2VydmVyLmxlbmd0aCAtIDE7IGkgPj0gMDsgLS1pKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChzdHJlYW1PcHRpb25zU2VydmVyW2ldLmlkID09PSB0aGlzLnN0cmVhbS5zdHJlYW1JZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgc3RyZWFtT3B0aW9uc1NlcnZlci5zcGxpY2UoaSwgMSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgfVxuICAgIH1cblxufSIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTctMjAxOCBPcGVuVmlkdSAoaHR0cHM6Ly9vcGVudmlkdS5pby8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuaW1wb3J0IHsgRXZlbnQgfSBmcm9tICcuL0V2ZW50JztcbmltcG9ydCB7IFN0cmVhbU1hbmFnZXIgfSBmcm9tICcuLi8uLi9PcGVuVmlkdS9TdHJlYW1NYW5hZ2VyJztcblxuLyoqXG4gKiBEZWZpbmVzIHRoZSBmb2xsb3dpbmcgZXZlbnRzOlxuICogLSBgc3RyZWFtUGxheWluZ2A6IGRpc3BhdGNoZWQgYnkgW1tTdHJlYW1NYW5hZ2VyXV0gKFtbUHVibGlzaGVyXV0gYW5kIFtbU3Vic2NyaWJlcl1dKVxuICovXG5leHBvcnQgY2xhc3MgU3RyZWFtTWFuYWdlckV2ZW50IGV4dGVuZHMgRXZlbnQge1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHRhcmdldDogU3RyZWFtTWFuYWdlcikge1xuICAgICAgICBzdXBlcihmYWxzZSwgdGFyZ2V0LCAnc3RyZWFtUGxheWluZycpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6bm8tZW1wdHlcbiAgICBjYWxsRGVmYXVsdEJlaGF2aW9yKCkgeyB9XG5cbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IEV2ZW50IH0gZnJvbSAnLi9FdmVudCc7XG5pbXBvcnQgeyBTZXNzaW9uIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvU2Vzc2lvbic7XG5pbXBvcnQgeyBTdHJlYW0gfSBmcm9tICcuLi8uLi9PcGVuVmlkdS9TdHJlYW0nO1xuaW1wb3J0IHsgU3RyZWFtTWFuYWdlciB9IGZyb20gJy4uLy4uL09wZW5WaWR1L1N0cmVhbU1hbmFnZXInO1xuXG4vKipcbiAqIERlZmluZXMgZXZlbnQgYHN0cmVhbVByb3BlcnR5Q2hhbmdlZGAgZGlzcGF0Y2hlZCBieSBbW1Nlc3Npb25dXSBhcyB3ZWxsIGFzIGJ5IFtbU3RyZWFtTWFuYWdlcl1dIChbW1B1Ymxpc2hlcl1dIGFuZCBbW1N1YnNjcmliZXJdXSkuXG4gKiBUaGlzIGV2ZW50IGlzIGZpcmVkIHdoZW4gYW55IHJlbW90ZSBzdHJlYW0gKG93bmVkIGJ5IGEgU3Vic2NyaWJlcikgb3IgbG9jYWwgc3RyZWFtIChvd25lZCBieSBhIFB1Ymxpc2hlcikgdW5kZXJnb2VzXG4gKiBhbnkgY2hhbmdlIGluIGFueSBvZiBpdHMgbXV0YWJsZSBwcm9wZXJ0aWVzIChzZWUgW1tjaGFuZ2VkUHJvcGVydHldXSkuXG4gKi9cbmV4cG9ydCBjbGFzcyBTdHJlYW1Qcm9wZXJ0eUNoYW5nZWRFdmVudCBleHRlbmRzIEV2ZW50IHtcblxuICAgIC8qKlxuICAgICAqIFRoZSBTdHJlYW0gd2hvc2UgcHJvcGVydHkgaGFzIGNoYW5nZWQuIFlvdSBjYW4gYWx3YXlzIGlkZW50aWZ5IHRoZSB1c2VyIHB1Ymxpc2hpbmcgdGhlIGNoYW5nZWQgc3RyZWFtIGJ5IGNvbnN1bHRpbmcgcHJvcGVydHkgW1tTdHJlYW0uY29ubmVjdGlvbl1dXG4gICAgICovXG4gICAgc3RyZWFtOiBTdHJlYW07XG5cbiAgICAvKipcbiAgICAgKiBUaGUgcHJvcGVydHkgb2YgdGhlIHN0cmVhbSB0aGF0IGNoYW5nZWQuIFRoaXMgdmFsdWUgaXMgZWl0aGVyIGBcInZpZGVvQWN0aXZlXCJgLCBgXCJhdWRpb0FjdGl2ZVwiYCBvciBgXCJ2aWRlb0RpbWVuc2lvbnNcImBcbiAgICAgKi9cbiAgICBjaGFuZ2VkUHJvcGVydHk6IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIENhdXNlIG9mIHRoZSBjaGFuZ2Ugb24gdGhlIHN0cmVhbSdzIHByb3BlcnR5OlxuICAgICAqIC0gRm9yIGB2aWRlb0FjdGl2ZWA6IGBcInB1Ymxpc2hWaWRlb1wiYFxuICAgICAqIC0gRm9yIGBhdWRpb0FjdGl2ZWA6IGBcInB1Ymxpc2hBdWRpb1wiYFxuICAgICAqIC0gRm9yIGB2aWRlb0RpbWVuc2lvbnNgOiBgXCJkZXZpY2VSb3RhdGVkXCJgIG9yIGBcInNjcmVlblJlc2l6ZWRcImBcbiAgICAgKi9cbiAgICByZWFzb246IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIE5ldyB2YWx1ZSBvZiB0aGUgcHJvcGVydHkgKGFmdGVyIGNoYW5nZSwgY3VycmVudCB2YWx1ZSlcbiAgICAgKi9cbiAgICBuZXdWYWx1ZTogT2JqZWN0O1xuXG4gICAgLyoqXG4gICAgICogUHJldmlvdXMgdmFsdWUgb2YgdGhlIHByb3BlcnR5IChiZWZvcmUgY2hhbmdlKVxuICAgICAqL1xuICAgIG9sZFZhbHVlOiBPYmplY3Q7XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgY29uc3RydWN0b3IodGFyZ2V0OiBTZXNzaW9uIHwgU3RyZWFtTWFuYWdlciwgc3RyZWFtOiBTdHJlYW0sIGNoYW5nZWRQcm9wZXJ0eTogc3RyaW5nLCBuZXdWYWx1ZTogT2JqZWN0LCBvbGRWYWx1ZTogT2JqZWN0LCByZWFzb246IHN0cmluZykge1xuICAgICAgICBzdXBlcihmYWxzZSwgdGFyZ2V0LCAnc3RyZWFtUHJvcGVydHlDaGFuZ2VkJyk7XG4gICAgICAgIHRoaXMuc3RyZWFtID0gc3RyZWFtO1xuICAgICAgICB0aGlzLmNoYW5nZWRQcm9wZXJ0eSA9IGNoYW5nZWRQcm9wZXJ0eTtcbiAgICAgICAgdGhpcy5uZXdWYWx1ZSA9IG5ld1ZhbHVlO1xuICAgICAgICB0aGlzLm9sZFZhbHVlID0gb2xkVmFsdWU7XG4gICAgICAgIHRoaXMucmVhc29uID0gcmVhc29uO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6bm8tZW1wdHlcbiAgICBjYWxsRGVmYXVsdEJlaGF2aW9yKCkgeyB9XG5cbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IEV2ZW50IH0gZnJvbSAnLi9FdmVudCc7XG5pbXBvcnQgeyBTdHJlYW1NYW5hZ2VyIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvU3RyZWFtTWFuYWdlcic7XG5cblxuLyoqXG4gKiBEZWZpbmVzIHRoZSBmb2xsb3dpbmcgZXZlbnRzOlxuICogLSBgdmlkZW9FbGVtZW50Q3JlYXRlZGA6IGRpc3BhdGNoZWQgYnkgW1tQdWJsaXNoZXJdXSBhbmQgW1tTdWJzY3JpYmVyXV0gd2hlbmV2ZXIgYSBuZXcgSFRNTCB2aWRlbyBlbGVtZW50IGhhcyBiZWVuIGluc2VydGVkIGludG8gRE9NIGJ5IE9wZW5WaWR1IEJyb3dzZXIgbGlicmFyeS4gU2VlXG4gKiBbTWFuYWdlIHZpZGVvIHBsYXllcnNdKC9kb2NzL2hvdy1kby1pL21hbmFnZS12aWRlb3MpIHNlY3Rpb24uXG4gKiAtIGB2aWRlb0VsZW1lbnREZXN0cm95ZWRgOiBkaXNwYXRjaGVkIGJ5IFtbUHVibGlzaGVyXV0gYW5kIFtbU3Vic2NyaWJlcl1dIHdoZW5ldmVyIGFuIEhUTUwgdmlkZW8gZWxlbWVudCBoYXMgYmVlbiByZW1vdmVkIGZyb20gRE9NIGJ5IE9wZW5WaWR1IEJyb3dzZXIgbGlicmFyeS5cbiAqL1xuZXhwb3J0IGNsYXNzIFZpZGVvRWxlbWVudEV2ZW50IGV4dGVuZHMgRXZlbnQge1xuXG4gICAgLyoqXG4gICAgICogVmlkZW8gZWxlbWVudCB0aGF0IHdhcyBjcmVhdGVkIG9yIGRlc3Ryb3llZFxuICAgICAqL1xuICAgIGVsZW1lbnQ6IEhUTUxWaWRlb0VsZW1lbnQ7XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgY29uc3RydWN0b3IoZWxlbWVudDogSFRNTFZpZGVvRWxlbWVudCwgdGFyZ2V0OiBTdHJlYW1NYW5hZ2VyLCB0eXBlOiBzdHJpbmcpIHtcbiAgICAgICAgc3VwZXIoZmFsc2UsIHRhcmdldCwgdHlwZSk7XG4gICAgICAgIHRoaXMuZWxlbWVudCA9IGVsZW1lbnQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZTpuby1lbXB0eVxuICAgIGNhbGxEZWZhdWx0QmVoYXZpb3IoKSB7IH1cblxufSIsImZ1bmN0aW9uIE1hcHBlcigpXG57XG4gIHZhciBzb3VyY2VzID0ge307XG5cblxuICB0aGlzLmZvckVhY2ggPSBmdW5jdGlvbihjYWxsYmFjaylcbiAge1xuICAgIGZvcih2YXIga2V5IGluIHNvdXJjZXMpXG4gICAge1xuICAgICAgdmFyIHNvdXJjZSA9IHNvdXJjZXNba2V5XTtcblxuICAgICAgZm9yKHZhciBrZXkyIGluIHNvdXJjZSlcbiAgICAgICAgY2FsbGJhY2soc291cmNlW2tleTJdKTtcbiAgICB9O1xuICB9O1xuXG4gIHRoaXMuZ2V0ID0gZnVuY3Rpb24oaWQsIHNvdXJjZSlcbiAge1xuICAgIHZhciBpZHMgPSBzb3VyY2VzW3NvdXJjZV07XG4gICAgaWYoaWRzID09IHVuZGVmaW5lZClcbiAgICAgIHJldHVybiB1bmRlZmluZWQ7XG5cbiAgICByZXR1cm4gaWRzW2lkXTtcbiAgfTtcblxuICB0aGlzLnJlbW92ZSA9IGZ1bmN0aW9uKGlkLCBzb3VyY2UpXG4gIHtcbiAgICB2YXIgaWRzID0gc291cmNlc1tzb3VyY2VdO1xuICAgIGlmKGlkcyA9PSB1bmRlZmluZWQpXG4gICAgICByZXR1cm47XG5cbiAgICBkZWxldGUgaWRzW2lkXTtcblxuICAgIC8vIENoZWNrIGl0J3MgZW1wdHlcbiAgICBmb3IodmFyIGkgaW4gaWRzKXtyZXR1cm4gZmFsc2V9XG5cbiAgICBkZWxldGUgc291cmNlc1tzb3VyY2VdO1xuICB9O1xuXG4gIHRoaXMuc2V0ID0gZnVuY3Rpb24odmFsdWUsIGlkLCBzb3VyY2UpXG4gIHtcbiAgICBpZih2YWx1ZSA9PSB1bmRlZmluZWQpXG4gICAgICByZXR1cm4gdGhpcy5yZW1vdmUoaWQsIHNvdXJjZSk7XG5cbiAgICB2YXIgaWRzID0gc291cmNlc1tzb3VyY2VdO1xuICAgIGlmKGlkcyA9PSB1bmRlZmluZWQpXG4gICAgICBzb3VyY2VzW3NvdXJjZV0gPSBpZHMgPSB7fTtcblxuICAgIGlkc1tpZF0gPSB2YWx1ZTtcbiAgfTtcbn07XG5cblxuTWFwcGVyLnByb3RvdHlwZS5wb3AgPSBmdW5jdGlvbihpZCwgc291cmNlKVxue1xuICB2YXIgdmFsdWUgPSB0aGlzLmdldChpZCwgc291cmNlKTtcbiAgaWYodmFsdWUgPT0gdW5kZWZpbmVkKVxuICAgIHJldHVybiB1bmRlZmluZWQ7XG5cbiAgdGhpcy5yZW1vdmUoaWQsIHNvdXJjZSk7XG5cbiAgcmV0dXJuIHZhbHVlO1xufTtcblxuXG5tb2R1bGUuZXhwb3J0cyA9IE1hcHBlcjtcbiIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTQgS3VyZW50byAoaHR0cDovL2t1cmVudG8ub3JnLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG52YXIgSnNvblJwY0NsaWVudCAgPSByZXF1aXJlKCcuL2pzb25ycGNjbGllbnQnKTtcblxuXG5leHBvcnRzLkpzb25ScGNDbGllbnQgID0gSnNvblJwY0NsaWVudDsiLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE0IEt1cmVudG8gKGh0dHA6Ly9rdXJlbnRvLm9yZy8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxudmFyIFJwY0J1aWxkZXIgPSByZXF1aXJlKCcuLi8nKTtcbnZhciBXZWJTb2NrZXRXaXRoUmVjb25uZWN0aW9uID0gcmVxdWlyZSgnLi90cmFuc3BvcnRzL3dlYlNvY2tldFdpdGhSZWNvbm5lY3Rpb24nKTtcblxuRGF0ZS5ub3cgPSBEYXRlLm5vdyB8fCBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gK25ldyBEYXRlO1xufTtcblxudmFyIFBJTkdfSU5URVJWQUwgPSA1MDAwO1xuXG52YXIgUkVDT05ORUNUSU5HID0gJ1JFQ09OTkVDVElORyc7XG52YXIgQ09OTkVDVEVEID0gJ0NPTk5FQ1RFRCc7XG52YXIgRElTQ09OTkVDVEVEID0gJ0RJU0NPTk5FQ1RFRCc7XG5cbnZhciBMb2dnZXIgPSBjb25zb2xlO1xuXG4vKipcbiAqXG4gKiBoZWFydGJlYXQ6IGludGVydmFsIGluIG1zIGZvciBlYWNoIGhlYXJ0YmVhdCBtZXNzYWdlLFxuICogc2VuZENsb3NlTWVzc2FnZSA6IHRydWUgLyBmYWxzZSwgYmVmb3JlIGNsb3NpbmcgdGhlIGNvbm5lY3Rpb24sIGl0IHNlbmRzIGEgY2xvc2VTZXNzaW9uIG1lc3NhZ2VcbiAqIDxwcmU+XG4gKiB3cyA6IHtcbiAqIFx0dXJpIDogVVJJIHRvIGNvbm50ZWN0IHRvLFxuICogIHVzZVNvY2tKUyA6IHRydWUgKHVzZSBTb2NrSlMpIC8gZmFsc2UgKHVzZSBXZWJTb2NrZXQpIGJ5IGRlZmF1bHQsXG4gKiBcdG9uY29ubmVjdGVkIDogY2FsbGJhY2sgbWV0aG9kIHRvIGludm9rZSB3aGVuIGNvbm5lY3Rpb24gaXMgc3VjY2Vzc2Z1bCxcbiAqIFx0b25kaXNjb25uZWN0IDogY2FsbGJhY2sgbWV0aG9kIHRvIGludm9rZSB3aGVuIHRoZSBjb25uZWN0aW9uIGlzIGxvc3QsXG4gKiBcdG9ucmVjb25uZWN0aW5nIDogY2FsbGJhY2sgbWV0aG9kIHRvIGludm9rZSB3aGVuIHRoZSBjbGllbnQgaXMgcmVjb25uZWN0aW5nLFxuICogXHRvbnJlY29ubmVjdGVkIDogY2FsbGJhY2sgbWV0aG9kIHRvIGludm9rZSB3aGVuIHRoZSBjbGllbnQgc3VjY2Vzc2Z1bGx5IHJlY29ubmVjdHMsXG4gKiBcdG9uZXJyb3IgOiBjYWxsYmFjayBtZXRob2QgdG8gaW52b2tlIHdoZW4gdGhlcmUgaXMgYW4gZXJyb3JcbiAqIH0sXG4gKiBycGMgOiB7XG4gKiBcdHJlcXVlc3RUaW1lb3V0IDogdGltZW91dCBmb3IgYSByZXF1ZXN0LFxuICogXHRzZXNzaW9uU3RhdHVzQ2hhbmdlZDogY2FsbGJhY2sgbWV0aG9kIGZvciBjaGFuZ2VzIGluIHNlc3Npb24gc3RhdHVzLFxuICogXHRtZWRpYVJlbmVnb3RpYXRpb246IG1lZGlhUmVuZWdvdGlhdGlvblxuICogfVxuICogPC9wcmU+XG4gKi9cbmZ1bmN0aW9uIEpzb25ScGNDbGllbnQoY29uZmlndXJhdGlvbikge1xuXG4gICAgdmFyIHNlbGYgPSB0aGlzO1xuXG4gICAgdmFyIHdzQ29uZmlnID0gY29uZmlndXJhdGlvbi53cztcblxuICAgIHZhciBub3RSZWNvbm5lY3RJZk51bUxlc3NUaGFuID0gLTE7XG5cbiAgICB2YXIgcGluZ05leHROdW0gPSAwO1xuICAgIHZhciBlbmFibGVkUGluZ3MgPSB0cnVlO1xuICAgIHZhciBwaW5nUG9uZ1N0YXJ0ZWQgPSBmYWxzZTtcbiAgICB2YXIgcGluZ0ludGVydmFsO1xuXG4gICAgdmFyIHN0YXR1cyA9IERJU0NPTk5FQ1RFRDtcblxuICAgIHZhciBvbnJlY29ubmVjdGluZyA9IHdzQ29uZmlnLm9ucmVjb25uZWN0aW5nO1xuICAgIHZhciBvbnJlY29ubmVjdGVkID0gd3NDb25maWcub25yZWNvbm5lY3RlZDtcbiAgICB2YXIgb25jb25uZWN0ZWQgPSB3c0NvbmZpZy5vbmNvbm5lY3RlZDtcbiAgICB2YXIgb25lcnJvciA9IHdzQ29uZmlnLm9uZXJyb3I7XG5cbiAgICBjb25maWd1cmF0aW9uLnJwYy5wdWxsID0gZnVuY3Rpb24ocGFyYW1zLCByZXF1ZXN0KSB7XG4gICAgICAgIHJlcXVlc3QucmVwbHkobnVsbCwgXCJwdXNoXCIpO1xuICAgIH1cblxuICAgIHdzQ29uZmlnLm9ucmVjb25uZWN0aW5nID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIExvZ2dlci5kZWJ1ZyhcIi0tLS0tLS0tLSBPTlJFQ09OTkVDVElORyAtLS0tLS0tLS0tLVwiKTtcbiAgICAgICAgaWYgKHN0YXR1cyA9PT0gUkVDT05ORUNUSU5HKSB7XG4gICAgICAgICAgICBMb2dnZXIuZXJyb3IoXCJXZWJzb2NrZXQgYWxyZWFkeSBpbiBSRUNPTk5FQ1RJTkcgc3RhdGUgd2hlbiByZWNlaXZpbmcgYSBuZXcgT05SRUNPTk5FQ1RJTkcgbWVzc2FnZS4gSWdub3JpbmcgaXRcIik7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBzdGF0dXMgPSBSRUNPTk5FQ1RJTkc7XG4gICAgICAgIGlmIChvbnJlY29ubmVjdGluZykge1xuICAgICAgICAgICAgb25yZWNvbm5lY3RpbmcoKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHdzQ29uZmlnLm9ucmVjb25uZWN0ZWQgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgTG9nZ2VyLmRlYnVnKFwiLS0tLS0tLS0tIE9OUkVDT05ORUNURUQgLS0tLS0tLS0tLS1cIik7XG4gICAgICAgIGlmIChzdGF0dXMgPT09IENPTk5FQ1RFRCkge1xuICAgICAgICAgICAgTG9nZ2VyLmVycm9yKFwiV2Vic29ja2V0IGFscmVhZHkgaW4gQ09OTkVDVEVEIHN0YXRlIHdoZW4gcmVjZWl2aW5nIGEgbmV3IE9OUkVDT05ORUNURUQgbWVzc2FnZS4gSWdub3JpbmcgaXRcIik7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgc3RhdHVzID0gQ09OTkVDVEVEO1xuXG4gICAgICAgIGVuYWJsZWRQaW5ncyA9IHRydWU7XG4gICAgICAgIHVwZGF0ZU5vdFJlY29ubmVjdElmTGVzc1RoYW4oKTtcbiAgICAgICAgdXNlUGluZygpO1xuXG4gICAgICAgIGlmIChvbnJlY29ubmVjdGVkKSB7XG4gICAgICAgICAgICBvbnJlY29ubmVjdGVkKCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB3c0NvbmZpZy5vbmNvbm5lY3RlZCA9IGZ1bmN0aW9uKCkge1xuICAgICAgICBMb2dnZXIuZGVidWcoXCItLS0tLS0tLS0gT05DT05ORUNURUQgLS0tLS0tLS0tLS1cIik7XG4gICAgICAgIGlmIChzdGF0dXMgPT09IENPTk5FQ1RFRCkge1xuICAgICAgICAgICAgTG9nZ2VyLmVycm9yKFwiV2Vic29ja2V0IGFscmVhZHkgaW4gQ09OTkVDVEVEIHN0YXRlIHdoZW4gcmVjZWl2aW5nIGEgbmV3IE9OQ09OTkVDVEVEIG1lc3NhZ2UuIElnbm9yaW5nIGl0XCIpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHN0YXR1cyA9IENPTk5FQ1RFRDtcblxuICAgICAgICBlbmFibGVkUGluZ3MgPSB0cnVlO1xuICAgICAgICB1c2VQaW5nKCk7XG5cbiAgICAgICAgaWYgKG9uY29ubmVjdGVkKSB7XG4gICAgICAgICAgICBvbmNvbm5lY3RlZCgpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgd3NDb25maWcub25lcnJvciA9IGZ1bmN0aW9uKGVycm9yKSB7XG4gICAgICAgIExvZ2dlci5kZWJ1ZyhcIi0tLS0tLS0tLSBPTkVSUk9SIC0tLS0tLS0tLS0tXCIpO1xuXG4gICAgICAgIHN0YXR1cyA9IERJU0NPTk5FQ1RFRDtcblxuICAgICAgICBpZiAob25lcnJvcikge1xuICAgICAgICAgICAgb25lcnJvcihlcnJvcik7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB2YXIgd3MgPSBuZXcgV2ViU29ja2V0V2l0aFJlY29ubmVjdGlvbih3c0NvbmZpZyk7XG5cbiAgICBMb2dnZXIuZGVidWcoJ0Nvbm5lY3Rpbmcgd2Vic29ja2V0IHRvIFVSSTogJyArIHdzQ29uZmlnLnVyaSk7XG5cbiAgICB2YXIgcnBjQnVpbGRlck9wdGlvbnMgPSB7XG4gICAgICAgIHJlcXVlc3RfdGltZW91dDogY29uZmlndXJhdGlvbi5ycGMucmVxdWVzdFRpbWVvdXQsXG4gICAgICAgIHBpbmdfcmVxdWVzdF90aW1lb3V0OiBjb25maWd1cmF0aW9uLnJwYy5oZWFydGJlYXRSZXF1ZXN0VGltZW91dFxuICAgIH07XG5cbiAgICB2YXIgcnBjID0gbmV3IFJwY0J1aWxkZXIoUnBjQnVpbGRlci5wYWNrZXJzLkpzb25SUEMsIHJwY0J1aWxkZXJPcHRpb25zLCB3cyxcbiAgICAgICAgZnVuY3Rpb24ocmVxdWVzdCkge1xuXG4gICAgICAgICAgICBMb2dnZXIuZGVidWcoJ1JlY2VpdmVkIHJlcXVlc3Q6ICcgKyBKU09OLnN0cmluZ2lmeShyZXF1ZXN0KSk7XG5cbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgdmFyIGZ1bmMgPSBjb25maWd1cmF0aW9uLnJwY1tyZXF1ZXN0Lm1ldGhvZF07XG5cbiAgICAgICAgICAgICAgICBpZiAoZnVuYyA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgIExvZ2dlci5lcnJvcihcIk1ldGhvZCBcIiArIHJlcXVlc3QubWV0aG9kICsgXCIgbm90IHJlZ2lzdGVyZWQgaW4gY2xpZW50XCIpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGZ1bmMocmVxdWVzdC5wYXJhbXMsIHJlcXVlc3QpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgICAgIExvZ2dlci5lcnJvcignRXhjZXB0aW9uIHByb2Nlc3NpbmcgcmVxdWVzdDogJyArIEpTT04uc3RyaW5naWZ5KHJlcXVlc3QpKTtcbiAgICAgICAgICAgICAgICBMb2dnZXIuZXJyb3IoZXJyKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG5cbiAgICB0aGlzLnNlbmQgPSBmdW5jdGlvbihtZXRob2QsIHBhcmFtcywgY2FsbGJhY2spIHtcbiAgICAgICAgaWYgKG1ldGhvZCAhPT0gJ3BpbmcnKSB7XG4gICAgICAgICAgICBMb2dnZXIuZGVidWcoJ1JlcXVlc3Q6IG1ldGhvZDonICsgbWV0aG9kICsgXCIgcGFyYW1zOlwiICsgSlNPTi5zdHJpbmdpZnkocGFyYW1zKSk7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgcmVxdWVzdFRpbWUgPSBEYXRlLm5vdygpO1xuXG4gICAgICAgIHJwYy5lbmNvZGUobWV0aG9kLCBwYXJhbXMsIGZ1bmN0aW9uKGVycm9yLCByZXN1bHQpIHtcbiAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgIExvZ2dlci5lcnJvcihcIkVSUk9SOlwiICsgZXJyb3IubWVzc2FnZSArIFwiIGluIFJlcXVlc3Q6IG1ldGhvZDpcIiArXG4gICAgICAgICAgICAgICAgICAgICAgICBtZXRob2QgKyBcIiBwYXJhbXM6XCIgKyBKU09OLnN0cmluZ2lmeShwYXJhbXMpICsgXCIgcmVxdWVzdDpcIiArXG4gICAgICAgICAgICAgICAgICAgICAgICBlcnJvci5yZXF1ZXN0KTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yLmRhdGEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIExvZ2dlci5lcnJvcihcIkVSUk9SIERBVEE6XCIgKyBKU09OLnN0cmluZ2lmeShlcnJvci5kYXRhKSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGNhdGNoIChlKSB7fVxuICAgICAgICAgICAgICAgIGVycm9yLnJlcXVlc3RUaW1lID0gcmVxdWVzdFRpbWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoY2FsbGJhY2spIHtcbiAgICAgICAgICAgICAgICBpZiAocmVzdWx0ICE9IHVuZGVmaW5lZCAmJiByZXN1bHQudmFsdWUgIT09ICdwb25nJykge1xuICAgICAgICAgICAgICAgICAgICBMb2dnZXIuZGVidWcoJ1Jlc3BvbnNlOiAnICsgSlNPTi5zdHJpbmdpZnkocmVzdWx0KSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNhbGxiYWNrKGVycm9yLCByZXN1bHQpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiB1cGRhdGVOb3RSZWNvbm5lY3RJZkxlc3NUaGFuKCkge1xuICAgICAgICBMb2dnZXIuZGVidWcoXCJub3RSZWNvbm5lY3RJZk51bUxlc3NUaGFuID0gXCIgKyBwaW5nTmV4dE51bSArICcgKG9sZD0nICtcbiAgICAgICAgICAgIG5vdFJlY29ubmVjdElmTnVtTGVzc1RoYW4gKyAnKScpO1xuICAgICAgICBub3RSZWNvbm5lY3RJZk51bUxlc3NUaGFuID0gcGluZ05leHROdW07XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gc2VuZFBpbmcoKSB7XG4gICAgICAgIGlmIChlbmFibGVkUGluZ3MpIHtcbiAgICAgICAgICAgIHZhciBwYXJhbXMgPSBudWxsO1xuICAgICAgICAgICAgaWYgKHBpbmdOZXh0TnVtID09IDAgfHwgcGluZ05leHROdW0gPT0gbm90UmVjb25uZWN0SWZOdW1MZXNzVGhhbikge1xuICAgICAgICAgICAgICAgIHBhcmFtcyA9IHtcbiAgICAgICAgICAgICAgICAgICAgaW50ZXJ2YWw6IGNvbmZpZ3VyYXRpb24uaGVhcnRiZWF0IHx8IFBJTkdfSU5URVJWQUxcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcGluZ05leHROdW0rKztcblxuICAgICAgICAgICAgc2VsZi5zZW5kKCdwaW5nJywgcGFyYW1zLCAoZnVuY3Rpb24ocGluZ051bSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmdW5jdGlvbihlcnJvciwgcmVzdWx0KSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFwiRXJyb3IgaW4gcGluZyByZXF1ZXN0ICNcIiArIHBpbmdOdW0gKyBcIiAoXCIgK1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yLm1lc3NhZ2UgKyBcIilcIik7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocGluZ051bSA+IG5vdFJlY29ubmVjdElmTnVtTGVzc1RoYW4pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbmFibGVkUGluZ3MgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB1cGRhdGVOb3RSZWNvbm5lY3RJZkxlc3NUaGFuKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFwiU2VydmVyIGRpZCBub3QgcmVzcG9uZCB0byBwaW5nIG1lc3NhZ2UgI1wiICtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGluZ051bSArIFwiLiBSZWNvbm5lY3RpbmcuLi4gXCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdzLnJlY29ubmVjdFdzKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KShwaW5nTmV4dE51bSkpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFwiVHJ5aW5nIHRvIHNlbmQgcGluZywgYnV0IHBpbmcgaXMgbm90IGVuYWJsZWRcIik7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKlxuICAgICogSWYgY29uZmlndXJhdGlvbi5oZWFyYmVhdCBoYXMgYW55IHZhbHVlLCB0aGUgcGluZy1wb25nIHdpbGwgd29yayB3aXRoIHRoZSBpbnRlcnZhbFxuICAgICogb2YgY29uZmlndXJhdGlvbi5oZWFyYmVhdFxuICAgICovXG4gICAgZnVuY3Rpb24gdXNlUGluZygpIHtcbiAgICAgICAgaWYgKCFwaW5nUG9uZ1N0YXJ0ZWQpIHtcbiAgICAgICAgICAgIExvZ2dlci5kZWJ1ZyhcIlN0YXJ0aW5nIHBpbmcgKGlmIGNvbmZpZ3VyZWQpXCIpXG4gICAgICAgICAgICBwaW5nUG9uZ1N0YXJ0ZWQgPSB0cnVlO1xuXG4gICAgICAgICAgICBpZiAoY29uZmlndXJhdGlvbi5oZWFydGJlYXQgIT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgcGluZ0ludGVydmFsID0gc2V0SW50ZXJ2YWwoc2VuZFBpbmcsIGNvbmZpZ3VyYXRpb24uaGVhcnRiZWF0KTtcbiAgICAgICAgICAgICAgICBzZW5kUGluZygpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgdGhpcy5jbG9zZSA9IGZ1bmN0aW9uKCkge1xuICAgICAgICBMb2dnZXIuZGVidWcoXCJDbG9zaW5nIGpzb25ScGNDbGllbnQgZXhwbGljaXRseSBieSBjbGllbnRcIik7XG5cbiAgICAgICAgaWYgKHBpbmdJbnRlcnZhbCAhPSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIExvZ2dlci5kZWJ1ZyhcIkNsZWFyaW5nIHBpbmcgaW50ZXJ2YWxcIik7XG4gICAgICAgICAgICBjbGVhckludGVydmFsKHBpbmdJbnRlcnZhbCk7XG4gICAgICAgIH1cbiAgICAgICAgcGluZ1BvbmdTdGFydGVkID0gZmFsc2U7XG4gICAgICAgIGVuYWJsZWRQaW5ncyA9IGZhbHNlO1xuXG4gICAgICAgIGlmIChjb25maWd1cmF0aW9uLnNlbmRDbG9zZU1lc3NhZ2UpIHtcbiAgICAgICAgICAgIExvZ2dlci5kZWJ1ZyhcIlNlbmRpbmcgY2xvc2UgbWVzc2FnZVwiKVxuICAgICAgICAgICAgdGhpcy5zZW5kKCdjbG9zZVNlc3Npb24nLCBudWxsLCBmdW5jdGlvbihlcnJvciwgcmVzdWx0KSB7XG4gICAgICAgICAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgIExvZ2dlci5lcnJvcihcIkVycm9yIHNlbmRpbmcgY2xvc2UgbWVzc2FnZTogXCIgKyBKU09OLnN0cmluZ2lmeShlcnJvcikpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB3cy5jbG9zZSgpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0gZWxzZSB7XG5cdFx0XHR3cy5jbG9zZSgpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gVGhpcyBtZXRob2QgaXMgb25seSBmb3IgdGVzdGluZ1xuICAgIHRoaXMuZm9yY2VDbG9zZSA9IGZ1bmN0aW9uKG1pbGxpcykge1xuICAgICAgICB3cy5mb3JjZUNsb3NlKG1pbGxpcyk7XG4gICAgfVxuXG4gICAgdGhpcy5yZWNvbm5lY3QgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgd3MucmVjb25uZWN0V3MoKTtcbiAgICB9XG59XG5cblxubW9kdWxlLmV4cG9ydHMgPSBKc29uUnBjQ2xpZW50O1xuIiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNCBLdXJlbnRvIChodHRwOi8va3VyZW50by5vcmcvKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbnZhciBXZWJTb2NrZXRXaXRoUmVjb25uZWN0aW9uICA9IHJlcXVpcmUoJy4vd2ViU29ja2V0V2l0aFJlY29ubmVjdGlvbicpO1xuXG5cbmV4cG9ydHMuV2ViU29ja2V0V2l0aFJlY29ubmVjdGlvbiAgPSBXZWJTb2NrZXRXaXRoUmVjb25uZWN0aW9uOyIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTMtMjAxNSBLdXJlbnRvIChodHRwOi8va3VyZW50by5vcmcvKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuXCJ1c2Ugc3RyaWN0XCI7XG5cbnZhciBCcm93c2VyV2ViU29ja2V0ID0gZ2xvYmFsLldlYlNvY2tldCB8fCBnbG9iYWwuTW96V2ViU29ja2V0O1xuXG52YXIgTG9nZ2VyID0gY29uc29sZTtcblxuLyoqXG4gKiBHZXQgZWl0aGVyIHRoZSBgV2ViU29ja2V0YCBvciBgTW96V2ViU29ja2V0YCBnbG9iYWxzXG4gKiBpbiB0aGUgYnJvd3NlciBvciB0cnkgdG8gcmVzb2x2ZSBXZWJTb2NrZXQtY29tcGF0aWJsZVxuICogaW50ZXJmYWNlIGV4cG9zZWQgYnkgYHdzYCBmb3IgTm9kZS1saWtlIGVudmlyb25tZW50LlxuICovXG5cbi8qdmFyIFdlYlNvY2tldCA9IEJyb3dzZXJXZWJTb2NrZXQ7XG5pZiAoIVdlYlNvY2tldCAmJiB0eXBlb2Ygd2luZG93ID09PSAndW5kZWZpbmVkJykge1xuICAgIHRyeSB7XG4gICAgICAgIFdlYlNvY2tldCA9IHJlcXVpcmUoJ3dzJyk7XG4gICAgfSBjYXRjaCAoZSkgeyB9XG59Ki9cblxuLy92YXIgU29ja0pTID0gcmVxdWlyZSgnc29ja2pzLWNsaWVudCcpO1xuXG52YXIgTUFYX1JFVFJJRVMgPSAyMDAwOyAvLyBGb3JldmVyLi4uXG52YXIgUkVUUllfVElNRV9NUyA9IDMwMDA7IC8vIEZJWE1FOiBJbXBsZW1lbnQgZXhwb25lbnRpYWwgd2FpdCB0aW1lcy4uLlxuXG52YXIgQ09OTkVDVElORyA9IDA7XG52YXIgT1BFTiA9IDE7XG52YXIgQ0xPU0lORyA9IDI7XG52YXIgQ0xPU0VEID0gMztcblxuLypcbmNvbmZpZyA9IHtcblx0XHR1cmkgOiB3c1VyaSxcblx0XHR1c2VTb2NrSlMgOiB0cnVlICh1c2UgU29ja0pTKSAvIGZhbHNlICh1c2UgV2ViU29ja2V0KSBieSBkZWZhdWx0LFxuXHRcdG9uY29ubmVjdGVkIDogY2FsbGJhY2sgbWV0aG9kIHRvIGludm9rZSB3aGVuIGNvbm5lY3Rpb24gaXMgc3VjY2Vzc2Z1bCxcblx0XHRvbmRpc2Nvbm5lY3QgOiBjYWxsYmFjayBtZXRob2QgdG8gaW52b2tlIHdoZW4gdGhlIGNvbm5lY3Rpb24gaXMgbG9zdCxcblx0XHRvbnJlY29ubmVjdGluZyA6IGNhbGxiYWNrIG1ldGhvZCB0byBpbnZva2Ugd2hlbiB0aGUgY2xpZW50IGlzIHJlY29ubmVjdGluZyxcblx0XHRvbnJlY29ubmVjdGVkIDogY2FsbGJhY2sgbWV0aG9kIHRvIGludm9rZSB3aGVuIHRoZSBjbGllbnQgc3VjY2Vzc2Z1bGx5IHJlY29ubmVjdHMsXG5cdH07XG4qL1xuZnVuY3Rpb24gV2ViU29ja2V0V2l0aFJlY29ubmVjdGlvbihjb25maWcpIHtcblxuICAgIHZhciBjbG9zaW5nID0gZmFsc2U7XG4gICAgdmFyIHJlZ2lzdGVyTWVzc2FnZUhhbmRsZXI7XG4gICAgdmFyIHdzVXJpID0gY29uZmlnLnVyaTtcbiAgICB2YXIgdXNlU29ja0pTID0gY29uZmlnLnVzZVNvY2tKUztcbiAgICB2YXIgcmVjb25uZWN0aW5nID0gZmFsc2U7XG5cbiAgICB2YXIgZm9yY2luZ0Rpc2Nvbm5lY3Rpb24gPSBmYWxzZTtcblxuICAgIHZhciB3cztcblxuICAgIGlmICh1c2VTb2NrSlMpIHtcbiAgICAgICAgd3MgPSBuZXcgU29ja0pTKHdzVXJpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICB3cyA9IG5ldyBXZWJTb2NrZXQod3NVcmkpO1xuICAgIH1cblxuICAgIHdzLm9ub3BlbiA9IGZ1bmN0aW9uKCkge1xuICAgICAgICBsb2dDb25uZWN0ZWQod3MsIHdzVXJpKTtcbiAgICAgICAgaWYgKGNvbmZpZy5vbmNvbm5lY3RlZCkge1xuICAgICAgICAgICAgY29uZmlnLm9uY29ubmVjdGVkKCk7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgd3Mub25lcnJvciA9IGZ1bmN0aW9uKGVycm9yKSB7XG4gICAgICAgIExvZ2dlci5lcnJvcihcIkNvdWxkIG5vdCBjb25uZWN0IHRvIFwiICsgd3NVcmkgKyBcIiAoaW52b2tpbmcgb25lcnJvciBpZiBkZWZpbmVkKVwiLCBlcnJvcik7XG4gICAgICAgIGlmIChjb25maWcub25lcnJvcikge1xuICAgICAgICAgICAgY29uZmlnLm9uZXJyb3IoZXJyb3IpO1xuICAgICAgICB9XG4gICAgfTtcblxuICAgIGZ1bmN0aW9uIGxvZ0Nvbm5lY3RlZCh3cywgd3NVcmkpIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIExvZ2dlci5kZWJ1ZyhcIldlYlNvY2tldCBjb25uZWN0ZWQgdG8gXCIgKyB3c1VyaSk7XG4gICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgIExvZ2dlci5lcnJvcihlKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHZhciByZWNvbm5lY3Rpb25PbkNsb3NlID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIGlmICh3cy5yZWFkeVN0YXRlID09PSBDTE9TRUQpIHtcbiAgICAgICAgICAgIGlmIChjbG9zaW5nKSB7XG4gICAgICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFwiQ29ubmVjdGlvbiBjbG9zZWQgYnkgdXNlclwiKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFwiQ29ubmVjdGlvbiBjbG9zZWQgdW5leHBlY3RlY2x5LiBSZWNvbm5lY3RpbmcuLi5cIik7XG4gICAgICAgICAgICAgICAgcmVjb25uZWN0VG9TYW1lVXJpKE1BWF9SRVRSSUVTLCAxKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIExvZ2dlci5kZWJ1ZyhcIkNsb3NlIGNhbGxiYWNrIGZyb20gcHJldmlvdXMgd2Vic29ja2V0LiBJZ25vcmluZyBpdFwiKTtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICB3cy5vbmNsb3NlID0gcmVjb25uZWN0aW9uT25DbG9zZTtcblxuICAgIGZ1bmN0aW9uIHJlY29ubmVjdFRvU2FtZVVyaShtYXhSZXRyaWVzLCBudW1SZXRyaWVzKSB7XG4gICAgICAgIExvZ2dlci5kZWJ1ZyhcInJlY29ubmVjdFRvU2FtZVVyaSAoYXR0ZW1wdCAjXCIgKyBudW1SZXRyaWVzICsgXCIsIG1heD1cIiArIG1heFJldHJpZXMgKyBcIilcIik7XG5cbiAgICAgICAgaWYgKG51bVJldHJpZXMgPT09IDEpIHtcbiAgICAgICAgICAgIGlmIChyZWNvbm5lY3RpbmcpIHtcbiAgICAgICAgICAgICAgICBMb2dnZXIud2FybihcIlRyeWluZyB0byByZWNvbm5lY3RUb05ld1VyaSB3aGVuIHJlY29ubmVjdGluZy4uLiBJZ25vcmluZyB0aGlzIHJlY29ubmVjdGlvbi5cIilcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJlY29ubmVjdGluZyA9IHRydWU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChjb25maWcub25yZWNvbm5lY3RpbmcpIHtcbiAgICAgICAgICAgICAgICBjb25maWcub25yZWNvbm5lY3RpbmcoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChmb3JjaW5nRGlzY29ubmVjdGlvbikge1xuICAgICAgICAgICAgcmVjb25uZWN0VG9OZXdVcmkobWF4UmV0cmllcywgbnVtUmV0cmllcywgd3NVcmkpO1xuXG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBpZiAoY29uZmlnLm5ld1dzVXJpT25SZWNvbm5lY3Rpb24pIHtcbiAgICAgICAgICAgICAgICBjb25maWcubmV3V3NVcmlPblJlY29ubmVjdGlvbihmdW5jdGlvbihlcnJvciwgbmV3V3NVcmkpIHtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIExvZ2dlci5kZWJ1ZyhlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlY29ubmVjdFRvU2FtZVVyaShtYXhSZXRyaWVzLCBudW1SZXRyaWVzICsgMSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9LCBSRVRSWV9USU1FX01TKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlY29ubmVjdFRvTmV3VXJpKG1heFJldHJpZXMsIG51bVJldHJpZXMsIG5ld1dzVXJpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJlY29ubmVjdFRvTmV3VXJpKG1heFJldHJpZXMsIG51bVJldHJpZXMsIHdzVXJpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIFRPRE8gVGVzdCByZXRyaWVzLiBIb3cgdG8gZm9yY2Ugbm90IGNvbm5lY3Rpb24/XG4gICAgZnVuY3Rpb24gcmVjb25uZWN0VG9OZXdVcmkobWF4UmV0cmllcywgbnVtUmV0cmllcywgcmVjb25uZWN0V3NVcmkpIHtcbiAgICAgICAgTG9nZ2VyLmRlYnVnKFwiUmVjb25uZWN0aW9uIGF0dGVtcHQgI1wiICsgbnVtUmV0cmllcyk7XG5cbiAgICAgICAgd3MuY2xvc2UoKTtcblxuICAgICAgICB3c1VyaSA9IHJlY29ubmVjdFdzVXJpIHx8IHdzVXJpO1xuXG4gICAgICAgIHZhciBuZXdXcztcbiAgICAgICAgaWYgKHVzZVNvY2tKUykge1xuICAgICAgICAgICAgbmV3V3MgPSBuZXcgU29ja0pTKHdzVXJpKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIG5ld1dzID0gbmV3IFdlYlNvY2tldCh3c1VyaSk7XG4gICAgICAgIH1cblxuICAgICAgICBuZXdXcy5vbm9wZW4gPSBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIExvZ2dlci5kZWJ1ZyhcIlJlY29ubmVjdGVkIGFmdGVyIFwiICsgbnVtUmV0cmllcyArIFwiIGF0dGVtcHRzLi4uXCIpO1xuICAgICAgICAgICAgbG9nQ29ubmVjdGVkKG5ld1dzLCB3c1VyaSk7XG4gICAgICAgICAgICByZWNvbm5lY3RpbmcgPSBmYWxzZTtcbiAgICAgICAgICAgIHJlZ2lzdGVyTWVzc2FnZUhhbmRsZXIoKTtcbiAgICAgICAgICAgIGlmIChjb25maWcub25yZWNvbm5lY3RlZCgpKSB7XG4gICAgICAgICAgICAgICAgY29uZmlnLm9ucmVjb25uZWN0ZWQoKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgbmV3V3Mub25jbG9zZSA9IHJlY29ubmVjdGlvbk9uQ2xvc2U7XG4gICAgICAgIH07XG5cbiAgICAgICAgdmFyIG9uRXJyb3JPckNsb3NlID0gZnVuY3Rpb24oZXJyb3IpIHtcbiAgICAgICAgICAgIExvZ2dlci53YXJuKFwiUmVjb25uZWN0aW9uIGVycm9yOiBcIiwgZXJyb3IpO1xuXG4gICAgICAgICAgICBpZiAobnVtUmV0cmllcyA9PT0gbWF4UmV0cmllcykge1xuICAgICAgICAgICAgICAgIGlmIChjb25maWcub25kaXNjb25uZWN0KSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbmZpZy5vbmRpc2Nvbm5lY3QoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlY29ubmVjdFRvU2FtZVVyaShtYXhSZXRyaWVzLCBudW1SZXRyaWVzICsgMSk7XG4gICAgICAgICAgICAgICAgfSwgUkVUUllfVElNRV9NUyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG5cbiAgICAgICAgbmV3V3Mub25lcnJvciA9IG9uRXJyb3JPckNsb3NlO1xuXG4gICAgICAgIHdzID0gbmV3V3M7XG4gICAgfVxuXG4gICAgdGhpcy5jbG9zZSA9IGZ1bmN0aW9uKCkge1xuICAgICAgICBjbG9zaW5nID0gdHJ1ZTtcbiAgICAgICAgd3MuY2xvc2UoKTtcbiAgICB9O1xuXG5cbiAgICAvLyBUaGlzIG1ldGhvZCBpcyBvbmx5IGZvciB0ZXN0aW5nXG4gICAgdGhpcy5mb3JjZUNsb3NlID0gZnVuY3Rpb24obWlsbGlzKSB7XG4gICAgICAgIExvZ2dlci5kZWJ1ZyhcIlRlc3Rpbmc6IEZvcmNlIFdlYlNvY2tldCBjbG9zZVwiKTtcblxuICAgICAgICBpZiAobWlsbGlzKSB7XG4gICAgICAgICAgICBMb2dnZXIuZGVidWcoXCJUZXN0aW5nOiBDaGFuZ2Ugd3NVcmkgZm9yIFwiICsgbWlsbGlzICsgXCIgbWlsbGlzIHRvIHNpbXVsYXRlIG5ldCBmYWlsdXJlXCIpO1xuICAgICAgICAgICAgdmFyIGdvb2RXc1VyaSA9IHdzVXJpO1xuICAgICAgICAgICAgd3NVcmkgPSBcIndzczovLzIxLjIzNC4xMi4zNC40OjQ0My9cIjtcblxuICAgICAgICAgICAgZm9yY2luZ0Rpc2Nvbm5lY3Rpb24gPSB0cnVlO1xuXG4gICAgICAgICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgIExvZ2dlci5kZWJ1ZyhcIlRlc3Rpbmc6IFJlY292ZXIgZ29vZCB3c1VyaSBcIiArIGdvb2RXc1VyaSk7XG4gICAgICAgICAgICAgICAgd3NVcmkgPSBnb29kV3NVcmk7XG5cbiAgICAgICAgICAgICAgICBmb3JjaW5nRGlzY29ubmVjdGlvbiA9IGZhbHNlO1xuXG4gICAgICAgICAgICB9LCBtaWxsaXMpO1xuICAgICAgICB9XG5cbiAgICAgICAgd3MuY2xvc2UoKTtcbiAgICB9O1xuXG4gICAgdGhpcy5yZWNvbm5lY3RXcyA9IGZ1bmN0aW9uKCkge1xuICAgICAgICBMb2dnZXIuZGVidWcoXCJyZWNvbm5lY3RXc1wiKTtcbiAgICAgICAgcmVjb25uZWN0VG9TYW1lVXJpKE1BWF9SRVRSSUVTLCAxLCB3c1VyaSk7XG4gICAgfTtcblxuICAgIHRoaXMuc2VuZCA9IGZ1bmN0aW9uKG1lc3NhZ2UpIHtcbiAgICAgICAgd3Muc2VuZChtZXNzYWdlKTtcbiAgICB9O1xuXG4gICAgdGhpcy5hZGRFdmVudExpc3RlbmVyID0gZnVuY3Rpb24odHlwZSwgY2FsbGJhY2spIHtcbiAgICAgICAgcmVnaXN0ZXJNZXNzYWdlSGFuZGxlciA9IGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgd3MuYWRkRXZlbnRMaXN0ZW5lcih0eXBlLCBjYWxsYmFjayk7XG4gICAgICAgIH07XG5cbiAgICAgICAgcmVnaXN0ZXJNZXNzYWdlSGFuZGxlcigpO1xuICAgIH07XG59XG5cbm1vZHVsZS5leHBvcnRzID0gV2ViU29ja2V0V2l0aFJlY29ubmVjdGlvbjtcbiIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTQgS3VyZW50byAoaHR0cDovL2t1cmVudG8ub3JnLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5cbnZhciBkZWZpbmVQcm9wZXJ0eV9JRTggPSBmYWxzZVxuaWYoT2JqZWN0LmRlZmluZVByb3BlcnR5KVxue1xuICB0cnlcbiAge1xuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh7fSwgXCJ4XCIsIHt9KTtcbiAgfVxuICBjYXRjaChlKVxuICB7XG4gICAgZGVmaW5lUHJvcGVydHlfSUU4ID0gdHJ1ZVxuICB9XG59XG5cbi8vIGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0phdmFTY3JpcHQvUmVmZXJlbmNlL0dsb2JhbF9PYmplY3RzL0Z1bmN0aW9uL2JpbmRcbmlmICghRnVuY3Rpb24ucHJvdG90eXBlLmJpbmQpIHtcbiAgRnVuY3Rpb24ucHJvdG90eXBlLmJpbmQgPSBmdW5jdGlvbihvVGhpcykge1xuICAgIGlmICh0eXBlb2YgdGhpcyAhPT0gJ2Z1bmN0aW9uJykge1xuICAgICAgLy8gY2xvc2VzdCB0aGluZyBwb3NzaWJsZSB0byB0aGUgRUNNQVNjcmlwdCA1XG4gICAgICAvLyBpbnRlcm5hbCBJc0NhbGxhYmxlIGZ1bmN0aW9uXG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdGdW5jdGlvbi5wcm90b3R5cGUuYmluZCAtIHdoYXQgaXMgdHJ5aW5nIHRvIGJlIGJvdW5kIGlzIG5vdCBjYWxsYWJsZScpO1xuICAgIH1cblxuICAgIHZhciBhQXJncyAgID0gQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzLCAxKSxcbiAgICAgICAgZlRvQmluZCA9IHRoaXMsXG4gICAgICAgIGZOT1AgICAgPSBmdW5jdGlvbigpIHt9LFxuICAgICAgICBmQm91bmQgID0gZnVuY3Rpb24oKSB7XG4gICAgICAgICAgcmV0dXJuIGZUb0JpbmQuYXBwbHkodGhpcyBpbnN0YW5jZW9mIGZOT1AgJiYgb1RoaXNcbiAgICAgICAgICAgICAgICAgPyB0aGlzXG4gICAgICAgICAgICAgICAgIDogb1RoaXMsXG4gICAgICAgICAgICAgICAgIGFBcmdzLmNvbmNhdChBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMpKSk7XG4gICAgICAgIH07XG5cbiAgICBmTk9QLnByb3RvdHlwZSA9IHRoaXMucHJvdG90eXBlO1xuICAgIGZCb3VuZC5wcm90b3R5cGUgPSBuZXcgZk5PUCgpO1xuXG4gICAgcmV0dXJuIGZCb3VuZDtcbiAgfTtcbn1cblxuXG52YXIgRXZlbnRFbWl0dGVyID0gcmVxdWlyZSgnZXZlbnRzJykuRXZlbnRFbWl0dGVyO1xuXG52YXIgaW5oZXJpdHMgPSByZXF1aXJlKCdpbmhlcml0cycpO1xuXG52YXIgcGFja2VycyA9IHJlcXVpcmUoJy4vcGFja2VycycpO1xudmFyIE1hcHBlciA9IHJlcXVpcmUoJy4vTWFwcGVyJyk7XG5cblxudmFyIEJBU0VfVElNRU9VVCA9IDUwMDA7XG5cblxuZnVuY3Rpb24gdW5pZnlSZXNwb25zZU1ldGhvZHMocmVzcG9uc2VNZXRob2RzKVxue1xuICBpZighcmVzcG9uc2VNZXRob2RzKSByZXR1cm4ge307XG5cbiAgZm9yKHZhciBrZXkgaW4gcmVzcG9uc2VNZXRob2RzKVxuICB7XG4gICAgdmFyIHZhbHVlID0gcmVzcG9uc2VNZXRob2RzW2tleV07XG5cbiAgICBpZih0eXBlb2YgdmFsdWUgPT0gJ3N0cmluZycpXG4gICAgICByZXNwb25zZU1ldGhvZHNba2V5XSA9XG4gICAgICB7XG4gICAgICAgIHJlc3BvbnNlOiB2YWx1ZVxuICAgICAgfVxuICB9O1xuXG4gIHJldHVybiByZXNwb25zZU1ldGhvZHM7XG59O1xuXG5mdW5jdGlvbiB1bmlmeVRyYW5zcG9ydCh0cmFuc3BvcnQpXG57XG4gIGlmKCF0cmFuc3BvcnQpIHJldHVybjtcblxuICAvLyBUcmFuc3BvcnQgYXMgYSBmdW5jdGlvblxuICBpZih0cmFuc3BvcnQgaW5zdGFuY2VvZiBGdW5jdGlvbilcbiAgICByZXR1cm4ge3NlbmQ6IHRyYW5zcG9ydH07XG5cbiAgLy8gV2ViU29ja2V0ICYgRGF0YUNoYW5uZWxcbiAgaWYodHJhbnNwb3J0LnNlbmQgaW5zdGFuY2VvZiBGdW5jdGlvbilcbiAgICByZXR1cm4gdHJhbnNwb3J0O1xuXG4gIC8vIE1lc3NhZ2UgQVBJIChJbnRlci13aW5kb3cgJiBXZWJXb3JrZXIpXG4gIGlmKHRyYW5zcG9ydC5wb3N0TWVzc2FnZSBpbnN0YW5jZW9mIEZ1bmN0aW9uKVxuICB7XG4gICAgdHJhbnNwb3J0LnNlbmQgPSB0cmFuc3BvcnQucG9zdE1lc3NhZ2U7XG4gICAgcmV0dXJuIHRyYW5zcG9ydDtcbiAgfVxuXG4gIC8vIFN0cmVhbSBBUElcbiAgaWYodHJhbnNwb3J0LndyaXRlIGluc3RhbmNlb2YgRnVuY3Rpb24pXG4gIHtcbiAgICB0cmFuc3BvcnQuc2VuZCA9IHRyYW5zcG9ydC53cml0ZTtcbiAgICByZXR1cm4gdHJhbnNwb3J0O1xuICB9XG5cbiAgLy8gVHJhbnNwb3J0cyB0aGF0IG9ubHkgY2FuIHJlY2VpdmUgbWVzc2FnZXMsIGJ1dCBub3Qgc2VuZFxuICBpZih0cmFuc3BvcnQub25tZXNzYWdlICE9PSB1bmRlZmluZWQpIHJldHVybjtcbiAgaWYodHJhbnNwb3J0LnBhdXNlIGluc3RhbmNlb2YgRnVuY3Rpb24pIHJldHVybjtcblxuICB0aHJvdyBuZXcgU3ludGF4RXJyb3IoXCJUcmFuc3BvcnQgaXMgbm90IGEgZnVuY3Rpb24gbm9yIGEgdmFsaWQgb2JqZWN0XCIpO1xufTtcblxuXG4vKipcbiAqIFJlcHJlc2VudGF0aW9uIG9mIGEgUlBDIG5vdGlmaWNhdGlvblxuICpcbiAqIEBjbGFzc1xuICpcbiAqIEBjb25zdHJ1Y3RvclxuICpcbiAqIEBwYXJhbSB7U3RyaW5nfSBtZXRob2QgLW1ldGhvZCBvZiB0aGUgbm90aWZpY2F0aW9uXG4gKiBAcGFyYW0gcGFyYW1zIC0gcGFyYW1ldGVycyBvZiB0aGUgbm90aWZpY2F0aW9uXG4gKi9cbmZ1bmN0aW9uIFJwY05vdGlmaWNhdGlvbihtZXRob2QsIHBhcmFtcylcbntcbiAgaWYoZGVmaW5lUHJvcGVydHlfSUU4KVxuICB7XG4gICAgdGhpcy5tZXRob2QgPSBtZXRob2RcbiAgICB0aGlzLnBhcmFtcyA9IHBhcmFtc1xuICB9XG4gIGVsc2VcbiAge1xuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0aGlzLCAnbWV0aG9kJywge3ZhbHVlOiBtZXRob2QsIGVudW1lcmFibGU6IHRydWV9KTtcbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkodGhpcywgJ3BhcmFtcycsIHt2YWx1ZTogcGFyYW1zLCBlbnVtZXJhYmxlOiB0cnVlfSk7XG4gIH1cbn07XG5cblxuLyoqXG4gKiBAY2xhc3NcbiAqXG4gKiBAY29uc3RydWN0b3JcbiAqXG4gKiBAcGFyYW0ge29iamVjdH0gcGFja2VyXG4gKlxuICogQHBhcmFtIHtvYmplY3R9IFtvcHRpb25zXVxuICpcbiAqIEBwYXJhbSB7b2JqZWN0fSBbdHJhbnNwb3J0XVxuICpcbiAqIEBwYXJhbSB7RnVuY3Rpb259IFtvblJlcXVlc3RdXG4gKi9cbmZ1bmN0aW9uIFJwY0J1aWxkZXIocGFja2VyLCBvcHRpb25zLCB0cmFuc3BvcnQsIG9uUmVxdWVzdClcbntcbiAgdmFyIHNlbGYgPSB0aGlzO1xuXG4gIGlmKCFwYWNrZXIpXG4gICAgdGhyb3cgbmV3IFN5bnRheEVycm9yKCdQYWNrZXIgaXMgbm90IGRlZmluZWQnKTtcblxuICBpZighcGFja2VyLnBhY2sgfHwgIXBhY2tlci51bnBhY2spXG4gICAgdGhyb3cgbmV3IFN5bnRheEVycm9yKCdQYWNrZXIgaXMgaW52YWxpZCcpO1xuXG4gIHZhciByZXNwb25zZU1ldGhvZHMgPSB1bmlmeVJlc3BvbnNlTWV0aG9kcyhwYWNrZXIucmVzcG9uc2VNZXRob2RzKTtcblxuXG4gIGlmKG9wdGlvbnMgaW5zdGFuY2VvZiBGdW5jdGlvbilcbiAge1xuICAgIGlmKHRyYW5zcG9ydCAhPSB1bmRlZmluZWQpXG4gICAgICB0aHJvdyBuZXcgU3ludGF4RXJyb3IoXCJUaGVyZSBjYW4ndCBiZSBwYXJhbWV0ZXJzIGFmdGVyIG9uUmVxdWVzdFwiKTtcblxuICAgIG9uUmVxdWVzdCA9IG9wdGlvbnM7XG4gICAgdHJhbnNwb3J0ID0gdW5kZWZpbmVkO1xuICAgIG9wdGlvbnMgICA9IHVuZGVmaW5lZDtcbiAgfTtcblxuICBpZihvcHRpb25zICYmIG9wdGlvbnMuc2VuZCBpbnN0YW5jZW9mIEZ1bmN0aW9uKVxuICB7XG4gICAgaWYodHJhbnNwb3J0ICYmICEodHJhbnNwb3J0IGluc3RhbmNlb2YgRnVuY3Rpb24pKVxuICAgICAgdGhyb3cgbmV3IFN5bnRheEVycm9yKFwiT25seSBhIGZ1bmN0aW9uIGNhbiBiZSBhZnRlciB0cmFuc3BvcnRcIik7XG5cbiAgICBvblJlcXVlc3QgPSB0cmFuc3BvcnQ7XG4gICAgdHJhbnNwb3J0ID0gb3B0aW9ucztcbiAgICBvcHRpb25zICAgPSB1bmRlZmluZWQ7XG4gIH07XG5cbiAgaWYodHJhbnNwb3J0IGluc3RhbmNlb2YgRnVuY3Rpb24pXG4gIHtcbiAgICBpZihvblJlcXVlc3QgIT0gdW5kZWZpbmVkKVxuICAgICAgdGhyb3cgbmV3IFN5bnRheEVycm9yKFwiVGhlcmUgY2FuJ3QgYmUgcGFyYW1ldGVycyBhZnRlciBvblJlcXVlc3RcIik7XG5cbiAgICBvblJlcXVlc3QgPSB0cmFuc3BvcnQ7XG4gICAgdHJhbnNwb3J0ID0gdW5kZWZpbmVkO1xuICB9O1xuXG4gIGlmKHRyYW5zcG9ydCAmJiB0cmFuc3BvcnQuc2VuZCBpbnN0YW5jZW9mIEZ1bmN0aW9uKVxuICAgIGlmKG9uUmVxdWVzdCAmJiAhKG9uUmVxdWVzdCBpbnN0YW5jZW9mIEZ1bmN0aW9uKSlcbiAgICAgIHRocm93IG5ldyBTeW50YXhFcnJvcihcIk9ubHkgYSBmdW5jdGlvbiBjYW4gYmUgYWZ0ZXIgdHJhbnNwb3J0XCIpO1xuXG4gIG9wdGlvbnMgPSBvcHRpb25zIHx8IHt9O1xuXG5cbiAgRXZlbnRFbWl0dGVyLmNhbGwodGhpcyk7XG5cbiAgaWYob25SZXF1ZXN0KVxuICAgIHRoaXMub24oJ3JlcXVlc3QnLCBvblJlcXVlc3QpO1xuXG5cbiAgaWYoZGVmaW5lUHJvcGVydHlfSUU4KVxuICAgIHRoaXMucGVlcklEID0gb3B0aW9ucy5wZWVySURcbiAgZWxzZVxuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0aGlzLCAncGVlcklEJywge3ZhbHVlOiBvcHRpb25zLnBlZXJJRH0pO1xuXG4gIHZhciBtYXhfcmV0cmllcyA9IG9wdGlvbnMubWF4X3JldHJpZXMgfHwgMDtcblxuXG4gIGZ1bmN0aW9uIHRyYW5zcG9ydE1lc3NhZ2UoZXZlbnQpXG4gIHtcbiAgICBzZWxmLmRlY29kZShldmVudC5kYXRhIHx8IGV2ZW50KTtcbiAgfTtcblxuICB0aGlzLmdldFRyYW5zcG9ydCA9IGZ1bmN0aW9uKClcbiAge1xuICAgIHJldHVybiB0cmFuc3BvcnQ7XG4gIH1cbiAgdGhpcy5zZXRUcmFuc3BvcnQgPSBmdW5jdGlvbih2YWx1ZSlcbiAge1xuICAgIC8vIFJlbW92ZSBsaXN0ZW5lciBmcm9tIG9sZCB0cmFuc3BvcnRcbiAgICBpZih0cmFuc3BvcnQpXG4gICAge1xuICAgICAgLy8gVzNDIHRyYW5zcG9ydHNcbiAgICAgIGlmKHRyYW5zcG9ydC5yZW1vdmVFdmVudExpc3RlbmVyKVxuICAgICAgICB0cmFuc3BvcnQucmVtb3ZlRXZlbnRMaXN0ZW5lcignbWVzc2FnZScsIHRyYW5zcG9ydE1lc3NhZ2UpO1xuXG4gICAgICAvLyBOb2RlLmpzIFN0cmVhbXMgQVBJXG4gICAgICBlbHNlIGlmKHRyYW5zcG9ydC5yZW1vdmVMaXN0ZW5lcilcbiAgICAgICAgdHJhbnNwb3J0LnJlbW92ZUxpc3RlbmVyKCdkYXRhJywgdHJhbnNwb3J0TWVzc2FnZSk7XG4gICAgfTtcblxuICAgIC8vIFNldCBsaXN0ZW5lciBvbiBuZXcgdHJhbnNwb3J0XG4gICAgaWYodmFsdWUpXG4gICAge1xuICAgICAgLy8gVzNDIHRyYW5zcG9ydHNcbiAgICAgIGlmKHZhbHVlLmFkZEV2ZW50TGlzdGVuZXIpXG4gICAgICAgIHZhbHVlLmFkZEV2ZW50TGlzdGVuZXIoJ21lc3NhZ2UnLCB0cmFuc3BvcnRNZXNzYWdlKTtcblxuICAgICAgLy8gTm9kZS5qcyBTdHJlYW1zIEFQSVxuICAgICAgZWxzZSBpZih2YWx1ZS5hZGRMaXN0ZW5lcilcbiAgICAgICAgdmFsdWUuYWRkTGlzdGVuZXIoJ2RhdGEnLCB0cmFuc3BvcnRNZXNzYWdlKTtcbiAgICB9O1xuXG4gICAgdHJhbnNwb3J0ID0gdW5pZnlUcmFuc3BvcnQodmFsdWUpO1xuICB9XG5cbiAgaWYoIWRlZmluZVByb3BlcnR5X0lFOClcbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkodGhpcywgJ3RyYW5zcG9ydCcsXG4gICAge1xuICAgICAgZ2V0OiB0aGlzLmdldFRyYW5zcG9ydC5iaW5kKHRoaXMpLFxuICAgICAgc2V0OiB0aGlzLnNldFRyYW5zcG9ydC5iaW5kKHRoaXMpXG4gICAgfSlcblxuICB0aGlzLnNldFRyYW5zcG9ydCh0cmFuc3BvcnQpO1xuXG5cbiAgdmFyIHJlcXVlc3RfdGltZW91dCAgICAgID0gb3B0aW9ucy5yZXF1ZXN0X3RpbWVvdXQgICAgICB8fCBCQVNFX1RJTUVPVVQ7XG4gIHZhciBwaW5nX3JlcXVlc3RfdGltZW91dCA9IG9wdGlvbnMucGluZ19yZXF1ZXN0X3RpbWVvdXQgfHwgcmVxdWVzdF90aW1lb3V0O1xuICB2YXIgcmVzcG9uc2VfdGltZW91dCAgICAgPSBvcHRpb25zLnJlc3BvbnNlX3RpbWVvdXQgICAgIHx8IEJBU0VfVElNRU9VVDtcbiAgdmFyIGR1cGxpY2F0ZXNfdGltZW91dCAgID0gb3B0aW9ucy5kdXBsaWNhdGVzX3RpbWVvdXQgICB8fCBCQVNFX1RJTUVPVVQ7XG5cblxuICB2YXIgcmVxdWVzdElEID0gMDtcblxuICB2YXIgcmVxdWVzdHMgID0gbmV3IE1hcHBlcigpO1xuICB2YXIgcmVzcG9uc2VzID0gbmV3IE1hcHBlcigpO1xuICB2YXIgcHJvY2Vzc2VkUmVzcG9uc2VzID0gbmV3IE1hcHBlcigpO1xuXG4gIHZhciBtZXNzYWdlMktleSA9IHt9O1xuXG5cbiAgLyoqXG4gICAqIFN0b3JlIHRoZSByZXNwb25zZSB0byBwcmV2ZW50IHRvIHByb2Nlc3MgZHVwbGljYXRlIHJlcXVlc3QgbGF0ZXJcbiAgICovXG4gIGZ1bmN0aW9uIHN0b3JlUmVzcG9uc2UobWVzc2FnZSwgaWQsIGRlc3QpXG4gIHtcbiAgICB2YXIgcmVzcG9uc2UgPVxuICAgIHtcbiAgICAgIG1lc3NhZ2U6IG1lc3NhZ2UsXG4gICAgICAvKiogVGltZW91dCB0byBhdXRvLWNsZWFuIG9sZCByZXNwb25zZXMgKi9cbiAgICAgIHRpbWVvdXQ6IHNldFRpbWVvdXQoZnVuY3Rpb24oKVxuICAgICAge1xuICAgICAgICByZXNwb25zZXMucmVtb3ZlKGlkLCBkZXN0KTtcbiAgICAgIH0sXG4gICAgICByZXNwb25zZV90aW1lb3V0KVxuICAgIH07XG5cbiAgICByZXNwb25zZXMuc2V0KHJlc3BvbnNlLCBpZCwgZGVzdCk7XG4gIH07XG5cbiAgLyoqXG4gICAqIFN0b3JlIHRoZSByZXNwb25zZSB0byBpZ25vcmUgZHVwbGljYXRlZCBtZXNzYWdlcyBsYXRlclxuICAgKi9cbiAgZnVuY3Rpb24gc3RvcmVQcm9jZXNzZWRSZXNwb25zZShhY2ssIGZyb20pXG4gIHtcbiAgICB2YXIgdGltZW91dCA9IHNldFRpbWVvdXQoZnVuY3Rpb24oKVxuICAgIHtcbiAgICAgIHByb2Nlc3NlZFJlc3BvbnNlcy5yZW1vdmUoYWNrLCBmcm9tKTtcbiAgICB9LFxuICAgIGR1cGxpY2F0ZXNfdGltZW91dCk7XG5cbiAgICBwcm9jZXNzZWRSZXNwb25zZXMuc2V0KHRpbWVvdXQsIGFjaywgZnJvbSk7XG4gIH07XG5cblxuICAvKipcbiAgICogUmVwcmVzZW50YXRpb24gb2YgYSBSUEMgcmVxdWVzdFxuICAgKlxuICAgKiBAY2xhc3NcbiAgICogQGV4dGVuZHMgUnBjTm90aWZpY2F0aW9uXG4gICAqXG4gICAqIEBjb25zdHJ1Y3RvclxuICAgKlxuICAgKiBAcGFyYW0ge1N0cmluZ30gbWV0aG9kIC1tZXRob2Qgb2YgdGhlIG5vdGlmaWNhdGlvblxuICAgKiBAcGFyYW0gcGFyYW1zIC0gcGFyYW1ldGVycyBvZiB0aGUgbm90aWZpY2F0aW9uXG4gICAqIEBwYXJhbSB7SW50ZWdlcn0gaWQgLSBpZGVudGlmaWVyIG9mIHRoZSByZXF1ZXN0XG4gICAqIEBwYXJhbSBbZnJvbV0gLSBzb3VyY2Ugb2YgdGhlIG5vdGlmaWNhdGlvblxuICAgKi9cbiAgZnVuY3Rpb24gUnBjUmVxdWVzdChtZXRob2QsIHBhcmFtcywgaWQsIGZyb20sIHRyYW5zcG9ydClcbiAge1xuICAgIFJwY05vdGlmaWNhdGlvbi5jYWxsKHRoaXMsIG1ldGhvZCwgcGFyYW1zKTtcblxuICAgIHRoaXMuZ2V0VHJhbnNwb3J0ID0gZnVuY3Rpb24oKVxuICAgIHtcbiAgICAgIHJldHVybiB0cmFuc3BvcnQ7XG4gICAgfVxuICAgIHRoaXMuc2V0VHJhbnNwb3J0ID0gZnVuY3Rpb24odmFsdWUpXG4gICAge1xuICAgICAgdHJhbnNwb3J0ID0gdW5pZnlUcmFuc3BvcnQodmFsdWUpO1xuICAgIH1cblxuICAgIGlmKCFkZWZpbmVQcm9wZXJ0eV9JRTgpXG4gICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkodGhpcywgJ3RyYW5zcG9ydCcsXG4gICAgICB7XG4gICAgICAgIGdldDogdGhpcy5nZXRUcmFuc3BvcnQuYmluZCh0aGlzKSxcbiAgICAgICAgc2V0OiB0aGlzLnNldFRyYW5zcG9ydC5iaW5kKHRoaXMpXG4gICAgICB9KVxuXG4gICAgdmFyIHJlc3BvbnNlID0gcmVzcG9uc2VzLmdldChpZCwgZnJvbSk7XG5cbiAgICAvKipcbiAgICAgKiBAY29uc3RhbnQge0Jvb2xlYW59IGR1cGxpY2F0ZWRcbiAgICAgKi9cbiAgICBpZighKHRyYW5zcG9ydCB8fCBzZWxmLmdldFRyYW5zcG9ydCgpKSlcbiAgICB7XG4gICAgICBpZihkZWZpbmVQcm9wZXJ0eV9JRTgpXG4gICAgICAgIHRoaXMuZHVwbGljYXRlZCA9IEJvb2xlYW4ocmVzcG9uc2UpXG4gICAgICBlbHNlXG4gICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0aGlzLCAnZHVwbGljYXRlZCcsXG4gICAgICAgIHtcbiAgICAgICAgICB2YWx1ZTogQm9vbGVhbihyZXNwb25zZSlcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgdmFyIHJlc3BvbnNlTWV0aG9kID0gcmVzcG9uc2VNZXRob2RzW21ldGhvZF07XG5cbiAgICB0aGlzLnBhY2sgPSBwYWNrZXIucGFjay5iaW5kKHBhY2tlciwgdGhpcywgaWQpXG5cbiAgICAvKipcbiAgICAgKiBHZW5lcmF0ZSBhIHJlc3BvbnNlIHRvIHRoaXMgcmVxdWVzdFxuICAgICAqXG4gICAgICogQHBhcmFtIHtFcnJvcn0gW2Vycm9yXVxuICAgICAqIEBwYXJhbSB7Kn0gW3Jlc3VsdF1cbiAgICAgKlxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9XG4gICAgICovXG4gICAgdGhpcy5yZXBseSA9IGZ1bmN0aW9uKGVycm9yLCByZXN1bHQsIHRyYW5zcG9ydClcbiAgICB7XG4gICAgICAvLyBGaXggb3B0aW9uYWwgcGFyYW1ldGVyc1xuICAgICAgaWYoZXJyb3IgaW5zdGFuY2VvZiBGdW5jdGlvbiB8fCBlcnJvciAmJiBlcnJvci5zZW5kIGluc3RhbmNlb2YgRnVuY3Rpb24pXG4gICAgICB7XG4gICAgICAgIGlmKHJlc3VsdCAhPSB1bmRlZmluZWQpXG4gICAgICAgICAgdGhyb3cgbmV3IFN5bnRheEVycm9yKFwiVGhlcmUgY2FuJ3QgYmUgcGFyYW1ldGVycyBhZnRlciBjYWxsYmFja1wiKTtcblxuICAgICAgICB0cmFuc3BvcnQgPSBlcnJvcjtcbiAgICAgICAgcmVzdWx0ID0gbnVsbDtcbiAgICAgICAgZXJyb3IgPSB1bmRlZmluZWQ7XG4gICAgICB9XG5cbiAgICAgIGVsc2UgaWYocmVzdWx0IGluc3RhbmNlb2YgRnVuY3Rpb25cbiAgICAgIHx8IHJlc3VsdCAmJiByZXN1bHQuc2VuZCBpbnN0YW5jZW9mIEZ1bmN0aW9uKVxuICAgICAge1xuICAgICAgICBpZih0cmFuc3BvcnQgIT0gdW5kZWZpbmVkKVxuICAgICAgICAgIHRocm93IG5ldyBTeW50YXhFcnJvcihcIlRoZXJlIGNhbid0IGJlIHBhcmFtZXRlcnMgYWZ0ZXIgY2FsbGJhY2tcIik7XG5cbiAgICAgICAgdHJhbnNwb3J0ID0gcmVzdWx0O1xuICAgICAgICByZXN1bHQgPSBudWxsO1xuICAgICAgfTtcblxuICAgICAgdHJhbnNwb3J0ID0gdW5pZnlUcmFuc3BvcnQodHJhbnNwb3J0KTtcblxuICAgICAgLy8gRHVwbGljYXRlZCByZXF1ZXN0LCByZW1vdmUgb2xkIHJlc3BvbnNlIHRpbWVvdXRcbiAgICAgIGlmKHJlc3BvbnNlKVxuICAgICAgICBjbGVhclRpbWVvdXQocmVzcG9uc2UudGltZW91dCk7XG5cbiAgICAgIGlmKGZyb20gIT0gdW5kZWZpbmVkKVxuICAgICAge1xuICAgICAgICBpZihlcnJvcilcbiAgICAgICAgICBlcnJvci5kZXN0ID0gZnJvbTtcblxuICAgICAgICBpZihyZXN1bHQpXG4gICAgICAgICAgcmVzdWx0LmRlc3QgPSBmcm9tO1xuICAgICAgfTtcblxuICAgICAgdmFyIG1lc3NhZ2U7XG5cbiAgICAgIC8vIE5ldyByZXF1ZXN0IG9yIG92ZXJyaWRlbiBvbmUsIGNyZWF0ZSBuZXcgcmVzcG9uc2Ugd2l0aCBwcm92aWRlZCBkYXRhXG4gICAgICBpZihlcnJvciB8fCByZXN1bHQgIT0gdW5kZWZpbmVkKVxuICAgICAge1xuICAgICAgICBpZihzZWxmLnBlZXJJRCAhPSB1bmRlZmluZWQpXG4gICAgICAgIHtcbiAgICAgICAgICBpZihlcnJvcilcbiAgICAgICAgICAgIGVycm9yLmZyb20gPSBzZWxmLnBlZXJJRDtcbiAgICAgICAgICBlbHNlXG4gICAgICAgICAgICByZXN1bHQuZnJvbSA9IHNlbGYucGVlcklEO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gUHJvdG9jb2wgaW5kaWNhdGVzIHRoYXQgcmVzcG9uc2VzIGhhcyBvd24gcmVxdWVzdCBtZXRob2RzXG4gICAgICAgIGlmKHJlc3BvbnNlTWV0aG9kKVxuICAgICAgICB7XG4gICAgICAgICAgaWYocmVzcG9uc2VNZXRob2QuZXJyb3IgPT0gdW5kZWZpbmVkICYmIGVycm9yKVxuICAgICAgICAgICAgbWVzc2FnZSA9XG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIGVycm9yOiBlcnJvclxuICAgICAgICAgICAgfTtcblxuICAgICAgICAgIGVsc2VcbiAgICAgICAgICB7XG4gICAgICAgICAgICB2YXIgbWV0aG9kID0gZXJyb3JcbiAgICAgICAgICAgICAgICAgICAgICAgPyByZXNwb25zZU1ldGhvZC5lcnJvclxuICAgICAgICAgICAgICAgICAgICAgICA6IHJlc3BvbnNlTWV0aG9kLnJlc3BvbnNlO1xuXG4gICAgICAgICAgICBtZXNzYWdlID1cbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgbWV0aG9kOiBtZXRob2QsXG4gICAgICAgICAgICAgIHBhcmFtczogZXJyb3IgfHwgcmVzdWx0XG4gICAgICAgICAgICB9O1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlXG4gICAgICAgICAgbWVzc2FnZSA9XG4gICAgICAgICAge1xuICAgICAgICAgICAgZXJyb3I6ICBlcnJvcixcbiAgICAgICAgICAgIHJlc3VsdDogcmVzdWx0XG4gICAgICAgICAgfTtcblxuICAgICAgICBtZXNzYWdlID0gcGFja2VyLnBhY2sobWVzc2FnZSwgaWQpO1xuICAgICAgfVxuXG4gICAgICAvLyBEdXBsaWNhdGUgJiBub3Qtb3ZlcnJpZGVuIHJlcXVlc3QsIHJlLXNlbmQgb2xkIHJlc3BvbnNlXG4gICAgICBlbHNlIGlmKHJlc3BvbnNlKVxuICAgICAgICBtZXNzYWdlID0gcmVzcG9uc2UubWVzc2FnZTtcblxuICAgICAgLy8gTmV3IGVtcHR5IHJlcGx5LCByZXNwb25zZSBudWxsIHZhbHVlXG4gICAgICBlbHNlXG4gICAgICAgIG1lc3NhZ2UgPSBwYWNrZXIucGFjayh7cmVzdWx0OiBudWxsfSwgaWQpO1xuXG4gICAgICAvLyBTdG9yZSB0aGUgcmVzcG9uc2UgdG8gcHJldmVudCB0byBwcm9jZXNzIGEgZHVwbGljYXRlZCByZXF1ZXN0IGxhdGVyXG4gICAgICBzdG9yZVJlc3BvbnNlKG1lc3NhZ2UsIGlkLCBmcm9tKTtcblxuICAgICAgLy8gUmV0dXJuIHRoZSBzdG9yZWQgcmVzcG9uc2Ugc28gaXQgY2FuIGJlIGRpcmVjdGx5IHNlbmQgYmFja1xuICAgICAgdHJhbnNwb3J0ID0gdHJhbnNwb3J0IHx8IHRoaXMuZ2V0VHJhbnNwb3J0KCkgfHwgc2VsZi5nZXRUcmFuc3BvcnQoKTtcblxuICAgICAgaWYodHJhbnNwb3J0KVxuICAgICAgICByZXR1cm4gdHJhbnNwb3J0LnNlbmQobWVzc2FnZSk7XG5cbiAgICAgIHJldHVybiBtZXNzYWdlO1xuICAgIH1cbiAgfTtcbiAgaW5oZXJpdHMoUnBjUmVxdWVzdCwgUnBjTm90aWZpY2F0aW9uKTtcblxuXG4gIGZ1bmN0aW9uIGNhbmNlbChtZXNzYWdlKVxuICB7XG4gICAgdmFyIGtleSA9IG1lc3NhZ2UyS2V5W21lc3NhZ2VdO1xuICAgIGlmKCFrZXkpIHJldHVybjtcblxuICAgIGRlbGV0ZSBtZXNzYWdlMktleVttZXNzYWdlXTtcblxuICAgIHZhciByZXF1ZXN0ID0gcmVxdWVzdHMucG9wKGtleS5pZCwga2V5LmRlc3QpO1xuICAgIGlmKCFyZXF1ZXN0KSByZXR1cm47XG5cbiAgICBjbGVhclRpbWVvdXQocmVxdWVzdC50aW1lb3V0KTtcblxuICAgIC8vIFN0YXJ0IGR1cGxpY2F0ZWQgcmVzcG9uc2VzIHRpbWVvdXRcbiAgICBzdG9yZVByb2Nlc3NlZFJlc3BvbnNlKGtleS5pZCwga2V5LmRlc3QpO1xuICB9O1xuXG4gIC8qKlxuICAgKiBBbGxvdyB0byBjYW5jZWwgYSByZXF1ZXN0IGFuZCBkb24ndCB3YWl0IGZvciBhIHJlc3BvbnNlXG4gICAqXG4gICAqIElmIGBtZXNzYWdlYCBpcyBub3QgZ2l2ZW4sIGNhbmNlbCBhbGwgdGhlIHJlcXVlc3RcbiAgICovXG4gIHRoaXMuY2FuY2VsID0gZnVuY3Rpb24obWVzc2FnZSlcbiAge1xuICAgIGlmKG1lc3NhZ2UpIHJldHVybiBjYW5jZWwobWVzc2FnZSk7XG5cbiAgICBmb3IodmFyIG1lc3NhZ2UgaW4gbWVzc2FnZTJLZXkpXG4gICAgICBjYW5jZWwobWVzc2FnZSk7XG4gIH07XG5cblxuICB0aGlzLmNsb3NlID0gZnVuY3Rpb24oKVxuICB7XG4gICAgLy8gUHJldmVudCB0byByZWNlaXZlIG5ldyBtZXNzYWdlc1xuICAgIHZhciB0cmFuc3BvcnQgPSB0aGlzLmdldFRyYW5zcG9ydCgpO1xuICAgIGlmKHRyYW5zcG9ydCAmJiB0cmFuc3BvcnQuY2xvc2UpXG4gICAgICAgdHJhbnNwb3J0LmNsb3NlKCk7XG5cbiAgICAvLyBSZXF1ZXN0ICYgcHJvY2Vzc2VkIHJlc3BvbnNlc1xuICAgIHRoaXMuY2FuY2VsKCk7XG5cbiAgICBwcm9jZXNzZWRSZXNwb25zZXMuZm9yRWFjaChjbGVhclRpbWVvdXQpO1xuXG4gICAgLy8gUmVzcG9uc2VzXG4gICAgcmVzcG9uc2VzLmZvckVhY2goZnVuY3Rpb24ocmVzcG9uc2UpXG4gICAge1xuICAgICAgY2xlYXJUaW1lb3V0KHJlc3BvbnNlLnRpbWVvdXQpO1xuICAgIH0pO1xuICB9O1xuXG5cbiAgLyoqXG4gICAqIEdlbmVyYXRlcyBhbmQgZW5jb2RlIGEgSnNvblJQQyAyLjAgbWVzc2FnZVxuICAgKlxuICAgKiBAcGFyYW0ge1N0cmluZ30gbWV0aG9kIC1tZXRob2Qgb2YgdGhlIG5vdGlmaWNhdGlvblxuICAgKiBAcGFyYW0gcGFyYW1zIC0gcGFyYW1ldGVycyBvZiB0aGUgbm90aWZpY2F0aW9uXG4gICAqIEBwYXJhbSBbZGVzdF0gLSBkZXN0aW5hdGlvbiBvZiB0aGUgbm90aWZpY2F0aW9uXG4gICAqIEBwYXJhbSB7b2JqZWN0fSBbdHJhbnNwb3J0XSAtIHRyYW5zcG9ydCB3aGVyZSB0byBzZW5kIHRoZSBtZXNzYWdlXG4gICAqIEBwYXJhbSBbY2FsbGJhY2tdIC0gZnVuY3Rpb24gY2FsbGVkIHdoZW4gYSByZXNwb25zZSB0byB0aGlzIHJlcXVlc3QgaXNcbiAgICogICByZWNlaXZlZC4gSWYgbm90IGRlZmluZWQsIGEgbm90aWZpY2F0aW9uIHdpbGwgYmUgc2VuZCBpbnN0ZWFkXG4gICAqXG4gICAqIEByZXR1cm5zIHtzdHJpbmd9IEEgcmF3IEpzb25SUEMgMi4wIHJlcXVlc3Qgb3Igbm90aWZpY2F0aW9uIHN0cmluZ1xuICAgKi9cbiAgdGhpcy5lbmNvZGUgPSBmdW5jdGlvbihtZXRob2QsIHBhcmFtcywgZGVzdCwgdHJhbnNwb3J0LCBjYWxsYmFjaylcbiAge1xuICAgIC8vIEZpeCBvcHRpb25hbCBwYXJhbWV0ZXJzXG4gICAgaWYocGFyYW1zIGluc3RhbmNlb2YgRnVuY3Rpb24pXG4gICAge1xuICAgICAgaWYoZGVzdCAhPSB1bmRlZmluZWQpXG4gICAgICAgIHRocm93IG5ldyBTeW50YXhFcnJvcihcIlRoZXJlIGNhbid0IGJlIHBhcmFtZXRlcnMgYWZ0ZXIgY2FsbGJhY2tcIik7XG5cbiAgICAgIGNhbGxiYWNrICA9IHBhcmFtcztcbiAgICAgIHRyYW5zcG9ydCA9IHVuZGVmaW5lZDtcbiAgICAgIGRlc3QgICAgICA9IHVuZGVmaW5lZDtcbiAgICAgIHBhcmFtcyAgICA9IHVuZGVmaW5lZDtcbiAgICB9XG5cbiAgICBlbHNlIGlmKGRlc3QgaW5zdGFuY2VvZiBGdW5jdGlvbilcbiAgICB7XG4gICAgICBpZih0cmFuc3BvcnQgIT0gdW5kZWZpbmVkKVxuICAgICAgICB0aHJvdyBuZXcgU3ludGF4RXJyb3IoXCJUaGVyZSBjYW4ndCBiZSBwYXJhbWV0ZXJzIGFmdGVyIGNhbGxiYWNrXCIpO1xuXG4gICAgICBjYWxsYmFjayAgPSBkZXN0O1xuICAgICAgdHJhbnNwb3J0ID0gdW5kZWZpbmVkO1xuICAgICAgZGVzdCAgICAgID0gdW5kZWZpbmVkO1xuICAgIH1cblxuICAgIGVsc2UgaWYodHJhbnNwb3J0IGluc3RhbmNlb2YgRnVuY3Rpb24pXG4gICAge1xuICAgICAgaWYoY2FsbGJhY2sgIT0gdW5kZWZpbmVkKVxuICAgICAgICB0aHJvdyBuZXcgU3ludGF4RXJyb3IoXCJUaGVyZSBjYW4ndCBiZSBwYXJhbWV0ZXJzIGFmdGVyIGNhbGxiYWNrXCIpO1xuXG4gICAgICBjYWxsYmFjayAgPSB0cmFuc3BvcnQ7XG4gICAgICB0cmFuc3BvcnQgPSB1bmRlZmluZWQ7XG4gICAgfTtcblxuICAgIGlmKHNlbGYucGVlcklEICE9IHVuZGVmaW5lZClcbiAgICB7XG4gICAgICBwYXJhbXMgPSBwYXJhbXMgfHwge307XG5cbiAgICAgIHBhcmFtcy5mcm9tID0gc2VsZi5wZWVySUQ7XG4gICAgfTtcblxuICAgIGlmKGRlc3QgIT0gdW5kZWZpbmVkKVxuICAgIHtcbiAgICAgIHBhcmFtcyA9IHBhcmFtcyB8fCB7fTtcblxuICAgICAgcGFyYW1zLmRlc3QgPSBkZXN0O1xuICAgIH07XG5cbiAgICAvLyBFbmNvZGUgbWVzc2FnZVxuICAgIHZhciBtZXNzYWdlID1cbiAgICB7XG4gICAgICBtZXRob2Q6IG1ldGhvZCxcbiAgICAgIHBhcmFtczogcGFyYW1zXG4gICAgfTtcblxuICAgIGlmKGNhbGxiYWNrKVxuICAgIHtcbiAgICAgIHZhciBpZCA9IHJlcXVlc3RJRCsrO1xuICAgICAgdmFyIHJldHJpZWQgPSAwO1xuXG4gICAgICBtZXNzYWdlID0gcGFja2VyLnBhY2sobWVzc2FnZSwgaWQpO1xuXG4gICAgICBmdW5jdGlvbiBkaXNwYXRjaENhbGxiYWNrKGVycm9yLCByZXN1bHQpXG4gICAgICB7XG4gICAgICAgIHNlbGYuY2FuY2VsKG1lc3NhZ2UpO1xuXG4gICAgICAgIGNhbGxiYWNrKGVycm9yLCByZXN1bHQpO1xuICAgICAgfTtcblxuICAgICAgdmFyIHJlcXVlc3QgPVxuICAgICAge1xuICAgICAgICBtZXNzYWdlOiAgICAgICAgIG1lc3NhZ2UsXG4gICAgICAgIGNhbGxiYWNrOiAgICAgICAgZGlzcGF0Y2hDYWxsYmFjayxcbiAgICAgICAgcmVzcG9uc2VNZXRob2RzOiByZXNwb25zZU1ldGhvZHNbbWV0aG9kXSB8fCB7fVxuICAgICAgfTtcblxuICAgICAgdmFyIGVuY29kZV90cmFuc3BvcnQgPSB1bmlmeVRyYW5zcG9ydCh0cmFuc3BvcnQpO1xuXG4gICAgICBmdW5jdGlvbiBzZW5kUmVxdWVzdCh0cmFuc3BvcnQpXG4gICAgICB7XG4gICAgICAgIHZhciBydCA9IChtZXRob2QgPT09ICdwaW5nJyA/IHBpbmdfcmVxdWVzdF90aW1lb3V0IDogcmVxdWVzdF90aW1lb3V0KTtcbiAgICAgICAgcmVxdWVzdC50aW1lb3V0ID0gc2V0VGltZW91dCh0aW1lb3V0LCBydCpNYXRoLnBvdygyLCByZXRyaWVkKyspKTtcbiAgICAgICAgbWVzc2FnZTJLZXlbbWVzc2FnZV0gPSB7aWQ6IGlkLCBkZXN0OiBkZXN0fTtcbiAgICAgICAgcmVxdWVzdHMuc2V0KHJlcXVlc3QsIGlkLCBkZXN0KTtcblxuICAgICAgICB0cmFuc3BvcnQgPSB0cmFuc3BvcnQgfHwgZW5jb2RlX3RyYW5zcG9ydCB8fCBzZWxmLmdldFRyYW5zcG9ydCgpO1xuICAgICAgICBpZih0cmFuc3BvcnQpXG4gICAgICAgICAgcmV0dXJuIHRyYW5zcG9ydC5zZW5kKG1lc3NhZ2UpO1xuXG4gICAgICAgIHJldHVybiBtZXNzYWdlO1xuICAgICAgfTtcblxuICAgICAgZnVuY3Rpb24gcmV0cnkodHJhbnNwb3J0KVxuICAgICAge1xuICAgICAgICB0cmFuc3BvcnQgPSB1bmlmeVRyYW5zcG9ydCh0cmFuc3BvcnQpO1xuXG4gICAgICAgIGNvbnNvbGUud2FybihyZXRyaWVkKycgcmV0cnkgZm9yIHJlcXVlc3QgbWVzc2FnZTonLG1lc3NhZ2UpO1xuXG4gICAgICAgIHZhciB0aW1lb3V0ID0gcHJvY2Vzc2VkUmVzcG9uc2VzLnBvcChpZCwgZGVzdCk7XG4gICAgICAgIGNsZWFyVGltZW91dCh0aW1lb3V0KTtcblxuICAgICAgICByZXR1cm4gc2VuZFJlcXVlc3QodHJhbnNwb3J0KTtcbiAgICAgIH07XG5cbiAgICAgIGZ1bmN0aW9uIHRpbWVvdXQoKVxuICAgICAge1xuICAgICAgICBpZihyZXRyaWVkIDwgbWF4X3JldHJpZXMpXG4gICAgICAgICAgcmV0dXJuIHJldHJ5KHRyYW5zcG9ydCk7XG5cbiAgICAgICAgdmFyIGVycm9yID0gbmV3IEVycm9yKCdSZXF1ZXN0IGhhcyB0aW1lZCBvdXQnKTtcbiAgICAgICAgICAgIGVycm9yLnJlcXVlc3QgPSBtZXNzYWdlO1xuXG4gICAgICAgIGVycm9yLnJldHJ5ID0gcmV0cnk7XG5cbiAgICAgICAgZGlzcGF0Y2hDYWxsYmFjayhlcnJvcilcbiAgICAgIH07XG5cbiAgICAgIHJldHVybiBzZW5kUmVxdWVzdCh0cmFuc3BvcnQpO1xuICAgIH07XG5cbiAgICAvLyBSZXR1cm4gdGhlIHBhY2tlZCBtZXNzYWdlXG4gICAgbWVzc2FnZSA9IHBhY2tlci5wYWNrKG1lc3NhZ2UpO1xuXG4gICAgdHJhbnNwb3J0ID0gdHJhbnNwb3J0IHx8IHRoaXMuZ2V0VHJhbnNwb3J0KCk7XG4gICAgaWYodHJhbnNwb3J0KVxuICAgICAgcmV0dXJuIHRyYW5zcG9ydC5zZW5kKG1lc3NhZ2UpO1xuXG4gICAgcmV0dXJuIG1lc3NhZ2U7XG4gIH07XG5cbiAgLyoqXG4gICAqIERlY29kZSBhbmQgcHJvY2VzcyBhIEpzb25SUEMgMi4wIG1lc3NhZ2VcbiAgICpcbiAgICogQHBhcmFtIHtzdHJpbmd9IG1lc3NhZ2UgLSBzdHJpbmcgd2l0aCB0aGUgY29udGVudCBvZiB0aGUgbWVzc2FnZVxuICAgKlxuICAgKiBAcmV0dXJucyB7UnBjTm90aWZpY2F0aW9ufFJwY1JlcXVlc3R8dW5kZWZpbmVkfSAtIHRoZSByZXByZXNlbnRhdGlvbiBvZiB0aGVcbiAgICogICBub3RpZmljYXRpb24gb3IgdGhlIHJlcXVlc3QuIElmIGEgcmVzcG9uc2Ugd2FzIHByb2Nlc3NlZCwgaXQgd2lsbCByZXR1cm5cbiAgICogICBgdW5kZWZpbmVkYCB0byBub3RpZnkgdGhhdCBpdCB3YXMgcHJvY2Vzc2VkXG4gICAqXG4gICAqIEB0aHJvd3Mge1R5cGVFcnJvcn0gLSBNZXNzYWdlIGlzIG5vdCBkZWZpbmVkXG4gICAqL1xuICB0aGlzLmRlY29kZSA9IGZ1bmN0aW9uKG1lc3NhZ2UsIHRyYW5zcG9ydClcbiAge1xuICAgIGlmKCFtZXNzYWdlKVxuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIk1lc3NhZ2UgaXMgbm90IGRlZmluZWRcIik7XG5cbiAgICB0cnlcbiAgICB7XG4gICAgICBtZXNzYWdlID0gcGFja2VyLnVucGFjayhtZXNzYWdlKTtcbiAgICB9XG4gICAgY2F0Y2goZSlcbiAgICB7XG4gICAgICAvLyBJZ25vcmUgaW52YWxpZCBtZXNzYWdlc1xuICAgICAgcmV0dXJuIGNvbnNvbGUuZGVidWcoZSwgbWVzc2FnZSk7XG4gICAgfTtcblxuICAgIHZhciBpZCAgICAgPSBtZXNzYWdlLmlkO1xuICAgIHZhciBhY2sgICAgPSBtZXNzYWdlLmFjaztcbiAgICB2YXIgbWV0aG9kID0gbWVzc2FnZS5tZXRob2Q7XG4gICAgdmFyIHBhcmFtcyA9IG1lc3NhZ2UucGFyYW1zIHx8IHt9O1xuXG4gICAgdmFyIGZyb20gPSBwYXJhbXMuZnJvbTtcbiAgICB2YXIgZGVzdCA9IHBhcmFtcy5kZXN0O1xuXG4gICAgLy8gSWdub3JlIG1lc3NhZ2VzIHNlbmQgYnkgdXNcbiAgICBpZihzZWxmLnBlZXJJRCAhPSB1bmRlZmluZWQgJiYgZnJvbSA9PSBzZWxmLnBlZXJJRCkgcmV0dXJuO1xuXG4gICAgLy8gTm90aWZpY2F0aW9uXG4gICAgaWYoaWQgPT0gdW5kZWZpbmVkICYmIGFjayA9PSB1bmRlZmluZWQpXG4gICAge1xuICAgICAgdmFyIG5vdGlmaWNhdGlvbiA9IG5ldyBScGNOb3RpZmljYXRpb24obWV0aG9kLCBwYXJhbXMpO1xuXG4gICAgICBpZihzZWxmLmVtaXQoJ3JlcXVlc3QnLCBub3RpZmljYXRpb24pKSByZXR1cm47XG4gICAgICByZXR1cm4gbm90aWZpY2F0aW9uO1xuICAgIH07XG5cblxuICAgIGZ1bmN0aW9uIHByb2Nlc3NSZXF1ZXN0KClcbiAgICB7XG4gICAgICAvLyBJZiB3ZSBoYXZlIGEgdHJhbnNwb3J0IGFuZCBpdCdzIGEgZHVwbGljYXRlZCByZXF1ZXN0LCByZXBseSBpbm1lZGlhdGx5XG4gICAgICB0cmFuc3BvcnQgPSB1bmlmeVRyYW5zcG9ydCh0cmFuc3BvcnQpIHx8IHNlbGYuZ2V0VHJhbnNwb3J0KCk7XG4gICAgICBpZih0cmFuc3BvcnQpXG4gICAgICB7XG4gICAgICAgIHZhciByZXNwb25zZSA9IHJlc3BvbnNlcy5nZXQoaWQsIGZyb20pO1xuICAgICAgICBpZihyZXNwb25zZSlcbiAgICAgICAgICByZXR1cm4gdHJhbnNwb3J0LnNlbmQocmVzcG9uc2UubWVzc2FnZSk7XG4gICAgICB9O1xuXG4gICAgICB2YXIgaWRBY2sgPSAoaWQgIT0gdW5kZWZpbmVkKSA/IGlkIDogYWNrO1xuICAgICAgdmFyIHJlcXVlc3QgPSBuZXcgUnBjUmVxdWVzdChtZXRob2QsIHBhcmFtcywgaWRBY2ssIGZyb20sIHRyYW5zcG9ydCk7XG5cbiAgICAgIGlmKHNlbGYuZW1pdCgncmVxdWVzdCcsIHJlcXVlc3QpKSByZXR1cm47XG4gICAgICByZXR1cm4gcmVxdWVzdDtcbiAgICB9O1xuXG4gICAgZnVuY3Rpb24gcHJvY2Vzc1Jlc3BvbnNlKHJlcXVlc3QsIGVycm9yLCByZXN1bHQpXG4gICAge1xuICAgICAgcmVxdWVzdC5jYWxsYmFjayhlcnJvciwgcmVzdWx0KTtcbiAgICB9O1xuXG4gICAgZnVuY3Rpb24gZHVwbGljYXRlZFJlc3BvbnNlKHRpbWVvdXQpXG4gICAge1xuICAgICAgY29uc29sZS53YXJuKFwiUmVzcG9uc2UgYWxyZWFkeSBwcm9jZXNzZWRcIiwgbWVzc2FnZSk7XG5cbiAgICAgIC8vIFVwZGF0ZSBkdXBsaWNhdGVkIHJlc3BvbnNlcyB0aW1lb3V0XG4gICAgICBjbGVhclRpbWVvdXQodGltZW91dCk7XG4gICAgICBzdG9yZVByb2Nlc3NlZFJlc3BvbnNlKGFjaywgZnJvbSk7XG4gICAgfTtcblxuXG4gICAgLy8gUmVxdWVzdCwgb3IgcmVzcG9uc2Ugd2l0aCBvd24gbWV0aG9kXG4gICAgaWYobWV0aG9kKVxuICAgIHtcbiAgICAgIC8vIENoZWNrIGlmIGl0J3MgYSByZXNwb25zZSB3aXRoIG93biBtZXRob2RcbiAgICAgIGlmKGRlc3QgPT0gdW5kZWZpbmVkIHx8IGRlc3QgPT0gc2VsZi5wZWVySUQpXG4gICAgICB7XG4gICAgICAgIHZhciByZXF1ZXN0ID0gcmVxdWVzdHMuZ2V0KGFjaywgZnJvbSk7XG4gICAgICAgIGlmKHJlcXVlc3QpXG4gICAgICAgIHtcbiAgICAgICAgICB2YXIgcmVzcG9uc2VNZXRob2RzID0gcmVxdWVzdC5yZXNwb25zZU1ldGhvZHM7XG5cbiAgICAgICAgICBpZihtZXRob2QgPT0gcmVzcG9uc2VNZXRob2RzLmVycm9yKVxuICAgICAgICAgICAgcmV0dXJuIHByb2Nlc3NSZXNwb25zZShyZXF1ZXN0LCBwYXJhbXMpO1xuXG4gICAgICAgICAgaWYobWV0aG9kID09IHJlc3BvbnNlTWV0aG9kcy5yZXNwb25zZSlcbiAgICAgICAgICAgIHJldHVybiBwcm9jZXNzUmVzcG9uc2UocmVxdWVzdCwgbnVsbCwgcGFyYW1zKTtcblxuICAgICAgICAgIHJldHVybiBwcm9jZXNzUmVxdWVzdCgpO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIHByb2Nlc3NlZCA9IHByb2Nlc3NlZFJlc3BvbnNlcy5nZXQoYWNrLCBmcm9tKTtcbiAgICAgICAgaWYocHJvY2Vzc2VkKVxuICAgICAgICAgIHJldHVybiBkdXBsaWNhdGVkUmVzcG9uc2UocHJvY2Vzc2VkKTtcbiAgICAgIH1cblxuICAgICAgLy8gUmVxdWVzdFxuICAgICAgcmV0dXJuIHByb2Nlc3NSZXF1ZXN0KCk7XG4gICAgfTtcblxuICAgIHZhciBlcnJvciAgPSBtZXNzYWdlLmVycm9yO1xuICAgIHZhciByZXN1bHQgPSBtZXNzYWdlLnJlc3VsdDtcblxuICAgIC8vIElnbm9yZSByZXNwb25zZXMgbm90IHNlbmQgdG8gdXNcbiAgICBpZihlcnJvciAgJiYgZXJyb3IuZGVzdCAgJiYgZXJyb3IuZGVzdCAgIT0gc2VsZi5wZWVySUQpIHJldHVybjtcbiAgICBpZihyZXN1bHQgJiYgcmVzdWx0LmRlc3QgJiYgcmVzdWx0LmRlc3QgIT0gc2VsZi5wZWVySUQpIHJldHVybjtcblxuICAgIC8vIFJlc3BvbnNlXG4gICAgdmFyIHJlcXVlc3QgPSByZXF1ZXN0cy5nZXQoYWNrLCBmcm9tKTtcbiAgICBpZighcmVxdWVzdClcbiAgICB7XG4gICAgICB2YXIgcHJvY2Vzc2VkID0gcHJvY2Vzc2VkUmVzcG9uc2VzLmdldChhY2ssIGZyb20pO1xuICAgICAgaWYocHJvY2Vzc2VkKVxuICAgICAgICByZXR1cm4gZHVwbGljYXRlZFJlc3BvbnNlKHByb2Nlc3NlZCk7XG5cbiAgICAgIHJldHVybiBjb25zb2xlLndhcm4oXCJObyBjYWxsYmFjayB3YXMgZGVmaW5lZCBmb3IgdGhpcyBtZXNzYWdlXCIsIG1lc3NhZ2UpO1xuICAgIH07XG5cbiAgICAvLyBQcm9jZXNzIHJlc3BvbnNlXG4gICAgcHJvY2Vzc1Jlc3BvbnNlKHJlcXVlc3QsIGVycm9yLCByZXN1bHQpO1xuICB9O1xufTtcbmluaGVyaXRzKFJwY0J1aWxkZXIsIEV2ZW50RW1pdHRlcik7XG5cblxuUnBjQnVpbGRlci5ScGNOb3RpZmljYXRpb24gPSBScGNOb3RpZmljYXRpb247XG5cblxubW9kdWxlLmV4cG9ydHMgPSBScGNCdWlsZGVyO1xuXG52YXIgY2xpZW50cyA9IHJlcXVpcmUoJy4vY2xpZW50cycpO1xudmFyIHRyYW5zcG9ydHMgPSByZXF1aXJlKCcuL2NsaWVudHMvdHJhbnNwb3J0cycpO1xuXG5ScGNCdWlsZGVyLmNsaWVudHMgPSBjbGllbnRzO1xuUnBjQnVpbGRlci5jbGllbnRzLnRyYW5zcG9ydHMgPSB0cmFuc3BvcnRzO1xuUnBjQnVpbGRlci5wYWNrZXJzID0gcGFja2VycztcbiIsIi8qKlxuICogSnNvblJQQyAyLjAgcGFja2VyXG4gKi9cblxuLyoqXG4gKiBQYWNrIGEgSnNvblJQQyAyLjAgbWVzc2FnZVxuICpcbiAqIEBwYXJhbSB7T2JqZWN0fSBtZXNzYWdlIC0gb2JqZWN0IHRvIGJlIHBhY2thZ2VkLiBJdCByZXF1aXJlcyB0byBoYXZlIGFsbCB0aGVcbiAqICAgZmllbGRzIG5lZWRlZCBieSB0aGUgSnNvblJQQyAyLjAgbWVzc2FnZSB0aGF0IGl0J3MgZ29pbmcgdG8gYmUgZ2VuZXJhdGVkXG4gKlxuICogQHJldHVybiB7U3RyaW5nfSAtIHRoZSBzdHJpbmdpZmllZCBKc29uUlBDIDIuMCBtZXNzYWdlXG4gKi9cbmZ1bmN0aW9uIHBhY2sobWVzc2FnZSwgaWQpXG57XG4gIHZhciByZXN1bHQgPVxuICB7XG4gICAganNvbnJwYzogXCIyLjBcIlxuICB9O1xuXG4gIC8vIFJlcXVlc3RcbiAgaWYobWVzc2FnZS5tZXRob2QpXG4gIHtcbiAgICByZXN1bHQubWV0aG9kID0gbWVzc2FnZS5tZXRob2Q7XG5cbiAgICBpZihtZXNzYWdlLnBhcmFtcylcbiAgICAgIHJlc3VsdC5wYXJhbXMgPSBtZXNzYWdlLnBhcmFtcztcblxuICAgIC8vIFJlcXVlc3QgaXMgYSBub3RpZmljYXRpb25cbiAgICBpZihpZCAhPSB1bmRlZmluZWQpXG4gICAgICByZXN1bHQuaWQgPSBpZDtcbiAgfVxuXG4gIC8vIFJlc3BvbnNlXG4gIGVsc2UgaWYoaWQgIT0gdW5kZWZpbmVkKVxuICB7XG4gICAgaWYobWVzc2FnZS5lcnJvcilcbiAgICB7XG4gICAgICBpZihtZXNzYWdlLnJlc3VsdCAhPT0gdW5kZWZpbmVkKVxuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQm90aCByZXN1bHQgYW5kIGVycm9yIGFyZSBkZWZpbmVkXCIpO1xuXG4gICAgICByZXN1bHQuZXJyb3IgPSBtZXNzYWdlLmVycm9yO1xuICAgIH1cbiAgICBlbHNlIGlmKG1lc3NhZ2UucmVzdWx0ICE9PSB1bmRlZmluZWQpXG4gICAgICByZXN1bHQucmVzdWx0ID0gbWVzc2FnZS5yZXN1bHQ7XG4gICAgZWxzZVxuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIk5vIHJlc3VsdCBvciBlcnJvciBpcyBkZWZpbmVkXCIpO1xuXG4gICAgcmVzdWx0LmlkID0gaWQ7XG4gIH07XG5cbiAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KHJlc3VsdCk7XG59O1xuXG4vKipcbiAqIFVucGFjayBhIEpzb25SUEMgMi4wIG1lc3NhZ2VcbiAqXG4gKiBAcGFyYW0ge1N0cmluZ30gbWVzc2FnZSAtIHN0cmluZyB3aXRoIHRoZSBjb250ZW50IG9mIHRoZSBKc29uUlBDIDIuMCBtZXNzYWdlXG4gKlxuICogQHRocm93cyB7VHlwZUVycm9yfSAtIEludmFsaWQgSnNvblJQQyB2ZXJzaW9uXG4gKlxuICogQHJldHVybiB7T2JqZWN0fSAtIG9iamVjdCBmaWxsZWQgd2l0aCB0aGUgSnNvblJQQyAyLjAgbWVzc2FnZSBjb250ZW50XG4gKi9cbmZ1bmN0aW9uIHVucGFjayhtZXNzYWdlKVxue1xuICB2YXIgcmVzdWx0ID0gbWVzc2FnZTtcblxuICBpZih0eXBlb2YgbWVzc2FnZSA9PT0gJ3N0cmluZycgfHwgbWVzc2FnZSBpbnN0YW5jZW9mIFN0cmluZykge1xuICAgIHJlc3VsdCA9IEpTT04ucGFyc2UobWVzc2FnZSk7XG4gIH1cblxuICAvLyBDaGVjayBpZiBpdCdzIGEgdmFsaWQgbWVzc2FnZVxuXG4gIHZhciB2ZXJzaW9uID0gcmVzdWx0Lmpzb25ycGM7XG4gIGlmKHZlcnNpb24gIT09ICcyLjAnKVxuICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJJbnZhbGlkIEpzb25SUEMgdmVyc2lvbiAnXCIgKyB2ZXJzaW9uICsgXCInOiBcIiArIG1lc3NhZ2UpO1xuXG4gIC8vIFJlc3BvbnNlXG4gIGlmKHJlc3VsdC5tZXRob2QgPT0gdW5kZWZpbmVkKVxuICB7XG4gICAgaWYocmVzdWx0LmlkID09IHVuZGVmaW5lZClcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJJbnZhbGlkIG1lc3NhZ2U6IFwiK21lc3NhZ2UpO1xuXG4gICAgdmFyIHJlc3VsdF9kZWZpbmVkID0gcmVzdWx0LnJlc3VsdCAhPT0gdW5kZWZpbmVkO1xuICAgIHZhciBlcnJvcl9kZWZpbmVkICA9IHJlc3VsdC5lcnJvciAgIT09IHVuZGVmaW5lZDtcblxuICAgIC8vIENoZWNrIG9ubHkgcmVzdWx0IG9yIGVycm9yIGlzIGRlZmluZWQsIG5vdCBib3RoIG9yIG5vbmVcbiAgICBpZihyZXN1bHRfZGVmaW5lZCAmJiBlcnJvcl9kZWZpbmVkKVxuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkJvdGggcmVzdWx0IGFuZCBlcnJvciBhcmUgZGVmaW5lZDogXCIrbWVzc2FnZSk7XG5cbiAgICBpZighcmVzdWx0X2RlZmluZWQgJiYgIWVycm9yX2RlZmluZWQpXG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiTm8gcmVzdWx0IG9yIGVycm9yIGlzIGRlZmluZWQ6IFwiK21lc3NhZ2UpO1xuXG4gICAgcmVzdWx0LmFjayA9IHJlc3VsdC5pZDtcbiAgICBkZWxldGUgcmVzdWx0LmlkO1xuICB9XG5cbiAgLy8gUmV0dXJuIHVucGFja2VkIG1lc3NhZ2VcbiAgcmV0dXJuIHJlc3VsdDtcbn07XG5cblxuZXhwb3J0cy5wYWNrICAgPSBwYWNrO1xuZXhwb3J0cy51bnBhY2sgPSB1bnBhY2s7XG4iLCJmdW5jdGlvbiBwYWNrKG1lc3NhZ2UpXG57XG4gIHRocm93IG5ldyBUeXBlRXJyb3IoXCJOb3QgeWV0IGltcGxlbWVudGVkXCIpO1xufTtcblxuZnVuY3Rpb24gdW5wYWNrKG1lc3NhZ2UpXG57XG4gIHRocm93IG5ldyBUeXBlRXJyb3IoXCJOb3QgeWV0IGltcGxlbWVudGVkXCIpO1xufTtcblxuXG5leHBvcnRzLnBhY2sgICA9IHBhY2s7XG5leHBvcnRzLnVucGFjayA9IHVucGFjaztcbiIsInZhciBKc29uUlBDID0gcmVxdWlyZSgnLi9Kc29uUlBDJyk7XG52YXIgWG1sUlBDICA9IHJlcXVpcmUoJy4vWG1sUlBDJyk7XG5cblxuZXhwb3J0cy5Kc29uUlBDID0gSnNvblJQQztcbmV4cG9ydHMuWG1sUlBDICA9IFhtbFJQQztcbiIsIi8vIExhc3QgdGltZSB1cGRhdGVkIG9uIEp1bmUgMDgsIDIwMThcblxuLy8gTGF0ZXN0IGZpbGUgY2FuIGJlIGZvdW5kIGhlcmU6IGh0dHBzOi8vY2RuLndlYnJ0Yy1leHBlcmltZW50LmNvbS9nZXRTY3JlZW5JZC5qc1xuXG4vLyBNdWF6IEtoYW4gICAgICAgICAtIHd3dy5NdWF6S2hhbi5jb21cbi8vIE1JVCBMaWNlbnNlICAgICAgIC0gd3d3LldlYlJUQy1FeHBlcmltZW50LmNvbS9saWNlbmNlXG4vLyBEb2N1bWVudGF0aW9uICAgICAtIGh0dHBzOi8vZ2l0aHViLmNvbS9tdWF6LWtoYW4vZ2V0U2NyZWVuSWQuXG5cbi8vIF9fX19fX19fX19fX19fXG4vLyBnZXRTY3JlZW5JZC5qc1xuXG4vKlxuZ2V0U2NyZWVuSWQoZnVuY3Rpb24gKGVycm9yLCBzb3VyY2VJZCwgc2NyZWVuX2NvbnN0cmFpbnRzKSB7XG4gICAgLy8gZXJyb3IgICAgPT0gbnVsbCB8fCAncGVybWlzc2lvbi1kZW5pZWQnIHx8ICdub3QtaW5zdGFsbGVkJyB8fCAnaW5zdGFsbGVkLWRpc2FibGVkJyB8fCAnbm90LWNocm9tZSdcbiAgICAvLyBzb3VyY2VJZCA9PSBudWxsIHx8ICdzdHJpbmcnIHx8ICdmaXJlZm94J1xuICAgIFxuICAgIGlmKG1pY3Jvc29mdEVkZ2UpIHtcbiAgICAgICAgbmF2aWdhdG9yLmdldERpc3BsYXlNZWRpYShzY3JlZW5fY29uc3RyYWludHMpLnRoZW4ob25TdWNjZXNzLCBvbkZhaWx1cmUpO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgbmF2aWdhdG9yLm1lZGlhRGV2aWNlcy5nZXRVc2VyTWVkaWEoc2NyZWVuX2NvbnN0cmFpbnRzKS50aGVuKG9uU3VjY2VzcyljYXRjaChvbkZhaWx1cmUpO1xuICAgIH1cbn0sICdwYXNzIHNlY29uZCBwYXJhbWV0ZXIgb25seSBpZiB5b3Ugd2FudCBzeXN0ZW0gYXVkaW8nKTtcbiovXG5cbndpbmRvdy5nZXRTY3JlZW5JZCA9IGZ1bmN0aW9uIChjYWxsYmFjaywgY3VzdG9tX3BhcmFtZXRlcikge1xuICAgIGlmIChuYXZpZ2F0b3IudXNlckFnZW50LmluZGV4T2YoJ0VkZ2UnKSAhPT0gLTEgJiYgKCEhbmF2aWdhdG9yLm1zU2F2ZU9yT3BlbkJsb2IgfHwgISFuYXZpZ2F0b3IubXNTYXZlQmxvYikpIHtcbiAgICAgICAgLy8gbWljcm9zb2Z0IGVkZ2UgPT4gbmF2aWdhdG9yLmdldERpc3BsYXlNZWRpYShzY3JlZW5fY29uc3RyYWludHMpLnRoZW4ob25TdWNjZXNzLCBvbkZhaWx1cmUpO1xuICAgICAgICBjYWxsYmFjayh7XG4gICAgICAgICAgICB2aWRlbzogdHJ1ZVxuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8vIGZvciBGaXJlZm94OlxuICAgIC8vIHNvdXJjZUlkID09ICdmaXJlZm94J1xuICAgIC8vIHNjcmVlbl9jb25zdHJhaW50cyA9IHsuLi59XG4gICAgaWYgKCEhbmF2aWdhdG9yLm1vekdldFVzZXJNZWRpYSkge1xuICAgICAgICBjYWxsYmFjayhudWxsLCAnZmlyZWZveCcsIHtcbiAgICAgICAgICAgIHZpZGVvOiB7XG4gICAgICAgICAgICAgICAgbW96TWVkaWFTb3VyY2U6ICd3aW5kb3cnLFxuICAgICAgICAgICAgICAgIG1lZGlhU291cmNlOiAnd2luZG93J1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdtZXNzYWdlJywgb25JRnJhbWVDYWxsYmFjayk7XG5cbiAgICBmdW5jdGlvbiBvbklGcmFtZUNhbGxiYWNrKGV2ZW50KSB7XG4gICAgICAgIGlmICghZXZlbnQuZGF0YSkgcmV0dXJuO1xuXG4gICAgICAgIGlmIChldmVudC5kYXRhLmNocm9tZU1lZGlhU291cmNlSWQpIHtcbiAgICAgICAgICAgIGlmIChldmVudC5kYXRhLmNocm9tZU1lZGlhU291cmNlSWQgPT09ICdQZXJtaXNzaW9uRGVuaWVkRXJyb3InKSB7XG4gICAgICAgICAgICAgICAgY2FsbGJhY2soJ3Blcm1pc3Npb24tZGVuaWVkJyk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGNhbGxiYWNrKG51bGwsIGV2ZW50LmRhdGEuY2hyb21lTWVkaWFTb3VyY2VJZCwgZ2V0U2NyZWVuQ29uc3RyYWludHMobnVsbCwgZXZlbnQuZGF0YS5jaHJvbWVNZWRpYVNvdXJjZUlkLCBldmVudC5kYXRhLmNhblJlcXVlc3RBdWRpb1RyYWNrKSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIHRoaXMgZXZlbnQgbGlzdGVuZXIgaXMgbm8gbW9yZSBuZWVkZWRcbiAgICAgICAgICAgIHdpbmRvdy5yZW1vdmVFdmVudExpc3RlbmVyKCdtZXNzYWdlJywgb25JRnJhbWVDYWxsYmFjayk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoZXZlbnQuZGF0YS5jaHJvbWVFeHRlbnNpb25TdGF0dXMpIHtcbiAgICAgICAgICAgIGNhbGxiYWNrKGV2ZW50LmRhdGEuY2hyb21lRXh0ZW5zaW9uU3RhdHVzLCBudWxsLCBnZXRTY3JlZW5Db25zdHJhaW50cyhldmVudC5kYXRhLmNocm9tZUV4dGVuc2lvblN0YXR1cykpO1xuXG4gICAgICAgICAgICAvLyB0aGlzIGV2ZW50IGxpc3RlbmVyIGlzIG5vIG1vcmUgbmVlZGVkXG4gICAgICAgICAgICB3aW5kb3cucmVtb3ZlRXZlbnRMaXN0ZW5lcignbWVzc2FnZScsIG9uSUZyYW1lQ2FsbGJhY2spO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgaWYgKCFjdXN0b21fcGFyYW1ldGVyKSB7XG4gICAgICAgIHNldFRpbWVvdXQocG9zdEdldFNvdXJjZUlkTWVzc2FnZSwgMTAwKTtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcG9zdEdldFNvdXJjZUlkTWVzc2FnZShjdXN0b21fcGFyYW1ldGVyKTtcbiAgICAgICAgfSwgMTAwKTtcbiAgICB9XG59O1xuXG5mdW5jdGlvbiBnZXRTY3JlZW5Db25zdHJhaW50cyhlcnJvciwgc291cmNlSWQsIGNhblJlcXVlc3RBdWRpb1RyYWNrKSB7XG4gICAgdmFyIHNjcmVlbl9jb25zdHJhaW50cyA9IHtcbiAgICAgICAgYXVkaW86IGZhbHNlLFxuICAgICAgICB2aWRlbzoge1xuICAgICAgICAgICAgbWFuZGF0b3J5OiB7XG4gICAgICAgICAgICAgICAgY2hyb21lTWVkaWFTb3VyY2U6IGVycm9yID8gJ3NjcmVlbicgOiAnZGVza3RvcCcsXG4gICAgICAgICAgICAgICAgbWF4V2lkdGg6IHdpbmRvdy5zY3JlZW4ud2lkdGggPiAxOTIwID8gd2luZG93LnNjcmVlbi53aWR0aCA6IDE5MjAsXG4gICAgICAgICAgICAgICAgbWF4SGVpZ2h0OiB3aW5kb3cuc2NyZWVuLmhlaWdodCA+IDEwODAgPyB3aW5kb3cuc2NyZWVuLmhlaWdodCA6IDEwODBcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBvcHRpb25hbDogW11cbiAgICAgICAgfVxuICAgIH07XG5cbiAgICBpZiAoISFjYW5SZXF1ZXN0QXVkaW9UcmFjaykge1xuICAgICAgICBzY3JlZW5fY29uc3RyYWludHMuYXVkaW8gPSB7XG4gICAgICAgICAgICBtYW5kYXRvcnk6IHtcbiAgICAgICAgICAgICAgICBjaHJvbWVNZWRpYVNvdXJjZTogZXJyb3IgPyAnc2NyZWVuJyA6ICdkZXNrdG9wJyxcbiAgICAgICAgICAgICAgICAvLyBlY2hvQ2FuY2VsbGF0aW9uOiB0cnVlXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgb3B0aW9uYWw6IFtdXG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgaWYgKHNvdXJjZUlkKSB7XG4gICAgICAgIHNjcmVlbl9jb25zdHJhaW50cy52aWRlby5tYW5kYXRvcnkuY2hyb21lTWVkaWFTb3VyY2VJZCA9IHNvdXJjZUlkO1xuXG4gICAgICAgIGlmIChzY3JlZW5fY29uc3RyYWludHMuYXVkaW8gJiYgc2NyZWVuX2NvbnN0cmFpbnRzLmF1ZGlvLm1hbmRhdG9yeSkge1xuICAgICAgICAgICAgc2NyZWVuX2NvbnN0cmFpbnRzLmF1ZGlvLm1hbmRhdG9yeS5jaHJvbWVNZWRpYVNvdXJjZUlkID0gc291cmNlSWQ7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gc2NyZWVuX2NvbnN0cmFpbnRzO1xufVxuXG5mdW5jdGlvbiBwb3N0R2V0U291cmNlSWRNZXNzYWdlKGN1c3RvbV9wYXJhbWV0ZXIpIHtcbiAgICBpZiAoIWlmcmFtZSkge1xuICAgICAgICBsb2FkSUZyYW1lKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHBvc3RHZXRTb3VyY2VJZE1lc3NhZ2UoY3VzdG9tX3BhcmFtZXRlcik7XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYgKCFpZnJhbWUuaXNMb2FkZWQpIHtcbiAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBwb3N0R2V0U291cmNlSWRNZXNzYWdlKGN1c3RvbV9wYXJhbWV0ZXIpO1xuICAgICAgICB9LCAxMDApO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYgKCFjdXN0b21fcGFyYW1ldGVyKSB7XG4gICAgICAgIGlmcmFtZS5jb250ZW50V2luZG93LnBvc3RNZXNzYWdlKHtcbiAgICAgICAgICAgIGNhcHR1cmVTb3VyY2VJZDogdHJ1ZVxuICAgICAgICB9LCAnKicpO1xuICAgIH1cbiAgICBlbHNlIGlmICghIWN1c3RvbV9wYXJhbWV0ZXIuZm9yRWFjaCkge1xuICAgICAgICBpZnJhbWUuY29udGVudFdpbmRvdy5wb3N0TWVzc2FnZSh7XG4gICAgICAgICAgICBjYXB0dXJlQ3VzdG9tU291cmNlSWQ6IGN1c3RvbV9wYXJhbWV0ZXJcbiAgICAgICAgfSwgJyonKTtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIGlmcmFtZS5jb250ZW50V2luZG93LnBvc3RNZXNzYWdlKHtcbiAgICAgICAgICAgIGNhcHR1cmVTb3VyY2VJZFdpdGhBdWRpbzogdHJ1ZVxuICAgICAgICB9LCAnKicpO1xuICAgIH1cbn1cblxudmFyIGlmcmFtZTtcblxuLy8gdGhpcyBmdW5jdGlvbiBpcyB1c2VkIGluIFJUQ011bHRpQ29ubmVjdGlvbiB2M1xud2luZG93LmdldFNjcmVlbkNvbnN0cmFpbnRzID0gZnVuY3Rpb24gKGNhbGxiYWNrKSB7XG4gICAgbG9hZElGcmFtZShmdW5jdGlvbiAoKSB7XG4gICAgICAgIGdldFNjcmVlbklkKGZ1bmN0aW9uIChlcnJvciwgc291cmNlSWQsIHNjcmVlbl9jb25zdHJhaW50cykge1xuICAgICAgICAgICAgaWYgKCFzY3JlZW5fY29uc3RyYWludHMpIHtcbiAgICAgICAgICAgICAgICBzY3JlZW5fY29uc3RyYWludHMgPSB7XG4gICAgICAgICAgICAgICAgICAgIHZpZGVvOiB0cnVlXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgY2FsbGJhY2soZXJyb3IsIHNjcmVlbl9jb25zdHJhaW50cy52aWRlbyk7XG4gICAgICAgIH0pO1xuICAgIH0pO1xufTtcblxuZnVuY3Rpb24gbG9hZElGcmFtZShsb2FkQ2FsbGJhY2spIHtcbiAgICBpZiAoaWZyYW1lKSB7XG4gICAgICAgIGxvYWRDYWxsYmFjaygpO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWZyYW1lID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnaWZyYW1lJyk7XG4gICAgaWZyYW1lLm9ubG9hZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWZyYW1lLmlzTG9hZGVkID0gdHJ1ZTtcbiAgICAgICAgbG9hZENhbGxiYWNrKCk7XG4gICAgfTtcbiAgICBpZnJhbWUuc3JjID0gJ2h0dHBzOi8vb3BlbnZpZHUuZ2l0aHViLmlvL29wZW52aWR1LXNjcmVlbi1zaGFyaW5nLWNocm9tZS1leHRlbnNpb24vJztcbiAgICBpZnJhbWUuc3R5bGUuZGlzcGxheSA9ICdub25lJztcbiAgICAoZG9jdW1lbnQuYm9keSB8fCBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQpLmFwcGVuZENoaWxkKGlmcmFtZSk7XG59XG5cbndpbmRvdy5nZXRDaHJvbWVFeHRlbnNpb25TdGF0dXMgPSBmdW5jdGlvbiAoY2FsbGJhY2spIHtcbiAgICAvLyBmb3IgRmlyZWZveDpcbiAgICBpZiAoISFuYXZpZ2F0b3IubW96R2V0VXNlck1lZGlhKSB7XG4gICAgICAgIGNhbGxiYWNrKCdpbnN0YWxsZWQtZW5hYmxlZCcpO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ21lc3NhZ2UnLCBvbklGcmFtZUNhbGxiYWNrKTtcblxuICAgIGZ1bmN0aW9uIG9uSUZyYW1lQ2FsbGJhY2soZXZlbnQpIHtcbiAgICAgICAgaWYgKCFldmVudC5kYXRhKSByZXR1cm47XG5cbiAgICAgICAgaWYgKGV2ZW50LmRhdGEuY2hyb21lRXh0ZW5zaW9uU3RhdHVzKSB7XG4gICAgICAgICAgICBjYWxsYmFjayhldmVudC5kYXRhLmNocm9tZUV4dGVuc2lvblN0YXR1cyk7XG5cbiAgICAgICAgICAgIC8vIHRoaXMgZXZlbnQgbGlzdGVuZXIgaXMgbm8gbW9yZSBuZWVkZWRcbiAgICAgICAgICAgIHdpbmRvdy5yZW1vdmVFdmVudExpc3RlbmVyKCdtZXNzYWdlJywgb25JRnJhbWVDYWxsYmFjayk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBzZXRUaW1lb3V0KHBvc3RHZXRDaHJvbWVFeHRlbnNpb25TdGF0dXNNZXNzYWdlLCAxMDApO1xufTtcblxuZnVuY3Rpb24gcG9zdEdldENocm9tZUV4dGVuc2lvblN0YXR1c01lc3NhZ2UoKSB7XG4gICAgaWYgKCFpZnJhbWUpIHtcbiAgICAgICAgbG9hZElGcmFtZShwb3N0R2V0Q2hyb21lRXh0ZW5zaW9uU3RhdHVzTWVzc2FnZSk7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAoIWlmcmFtZS5pc0xvYWRlZCkge1xuICAgICAgICBzZXRUaW1lb3V0KHBvc3RHZXRDaHJvbWVFeHRlbnNpb25TdGF0dXNNZXNzYWdlLCAxMDApO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWZyYW1lLmNvbnRlbnRXaW5kb3cucG9zdE1lc3NhZ2Uoe1xuICAgICAgICBnZXRDaHJvbWVFeHRlbnNpb25TdGF0dXM6IHRydWVcbiAgICB9LCAnKicpO1xufVxuXG5leHBvcnRzLmdldFNjcmVlbklkID0gZ2V0U2NyZWVuSWQ7IiwiLy8gZ2xvYmFsIHZhcmlhYmxlc1xudmFyIGNocm9tZU1lZGlhU291cmNlID0gJ3NjcmVlbic7XG52YXIgc291cmNlSWQ7XG52YXIgc2NyZWVuQ2FsbGJhY2s7XG52YXIgaXNGaXJlZm94ID0gdHlwZW9mIHdpbmRvdy5JbnN0YWxsVHJpZ2dlciAhPT0gJ3VuZGVmaW5lZCc7XG52YXIgaXNPcGVyYSA9ICEhd2luZG93Lm9wZXJhIHx8IG5hdmlnYXRvci51c2VyQWdlbnQuaW5kZXhPZignIE9QUi8nKSA+PSAwO1xudmFyIGlzQ2hyb21lID0gISF3aW5kb3cuY2hyb21lICYmICFpc09wZXJhO1xuXG53aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcignbWVzc2FnZScsIGZ1bmN0aW9uIChldmVudCkge1xuICAgIGlmIChldmVudC5vcmlnaW4gIT0gd2luZG93LmxvY2F0aW9uLm9yaWdpbikge1xuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIG9uTWVzc2FnZUNhbGxiYWNrKGV2ZW50LmRhdGEpO1xufSk7XG5cbi8vIGFuZCB0aGUgZnVuY3Rpb24gdGhhdCBoYW5kbGVzIHJlY2VpdmVkIG1lc3NhZ2VzXG5mdW5jdGlvbiBvbk1lc3NhZ2VDYWxsYmFjayhkYXRhKSB7XG4gICAgLy8gXCJjYW5jZWxcIiBidXR0b24gaXMgY2xpY2tlZFxuICAgIGlmIChkYXRhID09ICdQZXJtaXNzaW9uRGVuaWVkRXJyb3InKSB7XG4gICAgICAgIGlmIChzY3JlZW5DYWxsYmFjaylcbiAgICAgICAgICAgIHJldHVybiBzY3JlZW5DYWxsYmFjaygnUGVybWlzc2lvbkRlbmllZEVycm9yJyk7XG4gICAgICAgIGVsc2VcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignUGVybWlzc2lvbkRlbmllZEVycm9yJyk7XG4gICAgfVxuICAgIC8vIGV4dGVuc2lvbiBub3RpZmllZCBoaXMgcHJlc2VuY2VcbiAgICBpZiAoZGF0YSA9PSAncnRjbXVsdGljb25uZWN0aW9uLWV4dGVuc2lvbi1sb2FkZWQnKSB7XG4gICAgICAgIGNocm9tZU1lZGlhU291cmNlID0gJ2Rlc2t0b3AnO1xuICAgIH1cbiAgICAvLyBleHRlbnNpb24gc2hhcmVkIHRlbXAgc291cmNlSWRcbiAgICBpZiAoZGF0YS5zb3VyY2VJZCAmJiBzY3JlZW5DYWxsYmFjaykge1xuICAgICAgICBzY3JlZW5DYWxsYmFjayhzb3VyY2VJZCA9IGRhdGEuc291cmNlSWQsIGRhdGEuY2FuUmVxdWVzdEF1ZGlvVHJhY2sgPT09IHRydWUpO1xuICAgIH1cbn1cblxuLy8gdGhpcyBtZXRob2QgY2FuIGJlIHVzZWQgdG8gY2hlY2sgaWYgY2hyb21lIGV4dGVuc2lvbiBpcyBpbnN0YWxsZWQgJiBlbmFibGVkLlxuZnVuY3Rpb24gaXNDaHJvbWVFeHRlbnNpb25BdmFpbGFibGUoY2FsbGJhY2spIHtcbiAgICBpZiAoIWNhbGxiYWNrKSByZXR1cm47XG4gICAgaWYgKGNocm9tZU1lZGlhU291cmNlID09ICdkZXNrdG9wJykgcmV0dXJuIGNhbGxiYWNrKHRydWUpO1xuXG4gICAgLy8gYXNrIGV4dGVuc2lvbiBpZiBpdCBpcyBhdmFpbGFibGVcbiAgICB3aW5kb3cucG9zdE1lc3NhZ2UoJ2FyZS15b3UtdGhlcmUnLCAnKicpO1xuICAgIHNldFRpbWVvdXQoZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAoY2hyb21lTWVkaWFTb3VyY2UgPT0gJ3NjcmVlbicpIHtcbiAgICAgICAgICAgIGNhbGxiYWNrKGZhbHNlKTtcbiAgICAgICAgfSBlbHNlIGNhbGxiYWNrKHRydWUpO1xuICAgIH0sIDIwMDApO1xufVxuXG4vLyB0aGlzIGZ1bmN0aW9uIGNhbiBiZSB1c2VkIHRvIGdldCBcInNvdXJjZS1pZFwiIGZyb20gdGhlIGV4dGVuc2lvblxuZnVuY3Rpb24gZ2V0U291cmNlSWQoY2FsbGJhY2spIHtcbiAgICBpZiAoIWNhbGxiYWNrKVxuICAgICAgICB0aHJvdyAnXCJjYWxsYmFja1wiIHBhcmFtZXRlciBpcyBtYW5kYXRvcnkuJztcbiAgICBpZiAoc291cmNlSWQpXG4gICAgICAgIHJldHVybiBjYWxsYmFjayhzb3VyY2VJZCk7XG4gICAgc2NyZWVuQ2FsbGJhY2sgPSBjYWxsYmFjaztcbiAgICB3aW5kb3cucG9zdE1lc3NhZ2UoJ2dldC1zb3VyY2VJZCcsICcqJyk7XG59XG5cbi8vIHRoaXMgZnVuY3Rpb24gY2FuIGJlIHVzZWQgdG8gZ2V0IFwic291cmNlLWlkXCIgZnJvbSB0aGUgZXh0ZW5zaW9uXG5mdW5jdGlvbiBnZXRDdXN0b21Tb3VyY2VJZChhcnIsIGNhbGxiYWNrKSB7XG4gICAgaWYgKCFhcnIgfHwgIWFyci5mb3JFYWNoKSB0aHJvdyAnXCJhcnJcIiBwYXJhbWV0ZXIgaXMgbWFuZGF0b3J5IGFuZCBpdCBtdXN0IGJlIGFuIGFycmF5Lic7XG4gICAgaWYgKCFjYWxsYmFjaykgdGhyb3cgJ1wiY2FsbGJhY2tcIiBwYXJhbWV0ZXIgaXMgbWFuZGF0b3J5Lic7XG5cbiAgICBpZiAoc291cmNlSWQpIHJldHVybiBjYWxsYmFjayhzb3VyY2VJZCk7XG5cbiAgICBzY3JlZW5DYWxsYmFjayA9IGNhbGxiYWNrO1xuICAgIHdpbmRvdy5wb3N0TWVzc2FnZSh7XG4gICAgICAgICdnZXQtY3VzdG9tLXNvdXJjZUlkJzogYXJyXG4gICAgfSwgJyonKTtcbn1cblxuLy8gdGhpcyBmdW5jdGlvbiBjYW4gYmUgdXNlZCB0byBnZXQgXCJzb3VyY2UtaWRcIiBmcm9tIHRoZSBleHRlbnNpb25cbmZ1bmN0aW9uIGdldFNvdXJjZUlkV2l0aEF1ZGlvKGNhbGxiYWNrKSB7XG4gICAgaWYgKCFjYWxsYmFjaykgdGhyb3cgJ1wiY2FsbGJhY2tcIiBwYXJhbWV0ZXIgaXMgbWFuZGF0b3J5Lic7XG4gICAgaWYgKHNvdXJjZUlkKSByZXR1cm4gY2FsbGJhY2soc291cmNlSWQpO1xuXG4gICAgc2NyZWVuQ2FsbGJhY2sgPSBjYWxsYmFjaztcbiAgICB3aW5kb3cucG9zdE1lc3NhZ2UoJ2F1ZGlvLXBsdXMtdGFiJywgJyonKTtcbn1cblxuZnVuY3Rpb24gZ2V0Q2hyb21lRXh0ZW5zaW9uU3RhdHVzKGV4dGVuc2lvbmlkLCBjYWxsYmFjaykge1xuICAgIGlmIChpc0ZpcmVmb3gpXG4gICAgICAgIHJldHVybiBjYWxsYmFjaygnbm90LWNocm9tZScpO1xuICAgIGlmIChhcmd1bWVudHMubGVuZ3RoICE9IDIpIHtcbiAgICAgICAgY2FsbGJhY2sgPSBleHRlbnNpb25pZDtcbiAgICAgICAgZXh0ZW5zaW9uaWQgPSAnbGZjZ2ZlcGFmbm9iZGxvZWNjaG5mYWNsaWJlbmpvbGQnOyAvLyBkZWZhdWx0IGV4dGVuc2lvbi1pZFxuICAgIH1cbiAgICB2YXIgaW1hZ2UgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdpbWcnKTtcbiAgICBpbWFnZS5zcmMgPSAnY2hyb21lLWV4dGVuc2lvbjovLycgKyBleHRlbnNpb25pZCArICcvaWNvbi5wbmcnO1xuICAgIGltYWdlLm9ubG9hZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgY2hyb21lTWVkaWFTb3VyY2UgPSAnc2NyZWVuJztcbiAgICAgICAgd2luZG93LnBvc3RNZXNzYWdlKCdhcmUteW91LXRoZXJlJywgJyonKTtcbiAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBpZiAoY2hyb21lTWVkaWFTb3VyY2UgPT0gJ3NjcmVlbicpIHtcbiAgICAgICAgICAgICAgICBjYWxsYmFjaygnaW5zdGFsbGVkLWRpc2FibGVkJyk7XG4gICAgICAgICAgICB9IGVsc2VcbiAgICAgICAgICAgICAgICBjYWxsYmFjaygnaW5zdGFsbGVkLWVuYWJsZWQnKTtcbiAgICAgICAgfSwgMjAwMCk7XG4gICAgfTtcbiAgICBpbWFnZS5vbmVycm9yID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBjYWxsYmFjaygnbm90LWluc3RhbGxlZCcpO1xuICAgIH07XG59XG5cbmZ1bmN0aW9uIGdldFNjcmVlbkNvbnN0cmFpbnRzV2l0aEF1ZGlvKGNhbGxiYWNrKSB7XG4gICAgZ2V0U2NyZWVuQ29uc3RyYWludHMoY2FsbGJhY2ssIHRydWUpO1xufVxuXG4vLyB0aGlzIGZ1bmN0aW9uIGV4cGxhaW5zIGhvdyB0byB1c2UgYWJvdmUgbWV0aG9kcy9vYmplY3RzXG5mdW5jdGlvbiBnZXRTY3JlZW5Db25zdHJhaW50cyhjYWxsYmFjaywgY2FwdHVyZVNvdXJjZUlkV2l0aEF1ZGlvKSB7XG4gICAgc291cmNlSWQgPSAnJztcbiAgICB2YXIgZmlyZWZveFNjcmVlbkNvbnN0cmFpbnRzID0ge1xuICAgICAgICBtb3pNZWRpYVNvdXJjZTogJ3dpbmRvdycsXG4gICAgICAgIG1lZGlhU291cmNlOiAnd2luZG93J1xuICAgIH07XG4gICAgaWYgKGlzRmlyZWZveClcbiAgICAgICAgcmV0dXJuIGNhbGxiYWNrKG51bGwsIGZpcmVmb3hTY3JlZW5Db25zdHJhaW50cyk7XG4gICAgLy8gdGhpcyBzdGF0ZW1lbnQgZGVmaW5lcyBnZXRVc2VyTWVkaWEgY29uc3RyYWludHNcbiAgICAvLyB0aGF0IHdpbGwgYmUgdXNlZCB0byBjYXB0dXJlIGNvbnRlbnQgb2Ygc2NyZWVuXG4gICAgdmFyIHNjcmVlbl9jb25zdHJhaW50cyA9IHtcbiAgICAgICAgbWFuZGF0b3J5OiB7XG4gICAgICAgICAgICBjaHJvbWVNZWRpYVNvdXJjZTogY2hyb21lTWVkaWFTb3VyY2UsXG4gICAgICAgICAgICBtYXhXaWR0aDogc2NyZWVuLndpZHRoID4gMTkyMCA/IHNjcmVlbi53aWR0aCA6IDE5MjAsXG4gICAgICAgICAgICBtYXhIZWlnaHQ6IHNjcmVlbi5oZWlnaHQgPiAxMDgwID8gc2NyZWVuLmhlaWdodCA6IDEwODBcbiAgICAgICAgfSxcbiAgICAgICAgb3B0aW9uYWw6IFtdXG4gICAgfTtcbiAgICAvLyB0aGlzIHN0YXRlbWVudCB2ZXJpZmllcyBjaHJvbWUgZXh0ZW5zaW9uIGF2YWlsYWJpbGl0eVxuICAgIC8vIGlmIGluc3RhbGxlZCBhbmQgYXZhaWxhYmxlIHRoZW4gaXQgd2lsbCBpbnZva2UgZXh0ZW5zaW9uIEFQSVxuICAgIC8vIG90aGVyd2lzZSBpdCB3aWxsIGZhbGxiYWNrIHRvIGNvbW1hbmQtbGluZSBiYXNlZCBzY3JlZW4gY2FwdHVyaW5nIEFQSVxuICAgIGlmIChjaHJvbWVNZWRpYVNvdXJjZSA9PSAnZGVza3RvcCcgJiYgIXNvdXJjZUlkKSB7XG4gICAgICAgIGlmIChjYXB0dXJlU291cmNlSWRXaXRoQXVkaW8pIHtcbiAgICAgICAgICAgIGdldFNvdXJjZUlkV2l0aEF1ZGlvKGZ1bmN0aW9uIChzb3VyY2VJZCwgY2FuUmVxdWVzdEF1ZGlvVHJhY2spIHtcbiAgICAgICAgICAgICAgICBzY3JlZW5fY29uc3RyYWludHMubWFuZGF0b3J5LmNocm9tZU1lZGlhU291cmNlSWQgPSBzb3VyY2VJZDtcblxuICAgICAgICAgICAgICAgIGlmIChjYW5SZXF1ZXN0QXVkaW9UcmFjaykge1xuICAgICAgICAgICAgICAgICAgICBzY3JlZW5fY29uc3RyYWludHMuY2FuUmVxdWVzdEF1ZGlvVHJhY2sgPSB0cnVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjYWxsYmFjayhzb3VyY2VJZCA9PSAnUGVybWlzc2lvbkRlbmllZEVycm9yJyA/IHNvdXJjZUlkIDogbnVsbCwgc2NyZWVuX2NvbnN0cmFpbnRzKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgZ2V0U291cmNlSWQoZnVuY3Rpb24gKHNvdXJjZUlkKSB7XG4gICAgICAgICAgICAgICAgc2NyZWVuX2NvbnN0cmFpbnRzLm1hbmRhdG9yeS5jaHJvbWVNZWRpYVNvdXJjZUlkID0gc291cmNlSWQ7XG4gICAgICAgICAgICAgICAgY2FsbGJhY2soc291cmNlSWQgPT0gJ1Blcm1pc3Npb25EZW5pZWRFcnJvcicgPyBzb3VyY2VJZCA6IG51bGwsIHNjcmVlbl9jb25zdHJhaW50cyk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gdGhpcyBzdGF0ZW1lbnQgc2V0cyBnZXRzICdzb3VyY2VJZFwiIGFuZCBzZXRzIFwiY2hyb21lTWVkaWFTb3VyY2VJZFwiIFxuICAgIGlmIChjaHJvbWVNZWRpYVNvdXJjZSA9PSAnZGVza3RvcCcpIHtcbiAgICAgICAgc2NyZWVuX2NvbnN0cmFpbnRzLm1hbmRhdG9yeS5jaHJvbWVNZWRpYVNvdXJjZUlkID0gc291cmNlSWQ7XG4gICAgfVxuXG4gICAgLy8gbm93IGludm9raW5nIG5hdGl2ZSBnZXRVc2VyTWVkaWEgQVBJXG4gICAgY2FsbGJhY2sobnVsbCwgc2NyZWVuX2NvbnN0cmFpbnRzKTtcbn1cblxuZXhwb3J0cy5nZXRTY3JlZW5Db25zdHJhaW50cyA9IGdldFNjcmVlbkNvbnN0cmFpbnRzO1xuZXhwb3J0cy5nZXRTY3JlZW5Db25zdHJhaW50c1dpdGhBdWRpbyA9IGdldFNjcmVlbkNvbnN0cmFpbnRzV2l0aEF1ZGlvO1xuZXhwb3J0cy5pc0Nocm9tZUV4dGVuc2lvbkF2YWlsYWJsZSA9IGlzQ2hyb21lRXh0ZW5zaW9uQXZhaWxhYmxlO1xuZXhwb3J0cy5nZXRDaHJvbWVFeHRlbnNpb25TdGF0dXMgPSBnZXRDaHJvbWVFeHRlbnNpb25TdGF0dXM7XG5leHBvcnRzLmdldFNvdXJjZUlkID0gZ2V0U291cmNlSWQ7IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgZnJlZWljZSA9IHJlcXVpcmUoJ2ZyZWVpY2UnKTtcbmltcG9ydCB1dWlkID0gcmVxdWlyZSgndXVpZCcpO1xuaW1wb3J0IHBsYXRmb3JtID0gcmVxdWlyZSgncGxhdGZvcm0nKTtcblxuXG5leHBvcnQgaW50ZXJmYWNlIFdlYlJ0Y1BlZXJDb25maWd1cmF0aW9uIHtcbiAgICBtZWRpYUNvbnN0cmFpbnRzOiB7XG4gICAgICAgIGF1ZGlvOiBib29sZWFuLFxuICAgICAgICB2aWRlbzogYm9vbGVhblxuICAgIH07XG4gICAgc2ltdWxjYXN0OiBib29sZWFuO1xuICAgIG9uaWNlY2FuZGlkYXRlOiAoZXZlbnQpID0+IHZvaWQ7XG4gICAgaWNlU2VydmVyczogUlRDSWNlU2VydmVyW10gfCB1bmRlZmluZWQ7XG4gICAgbWVkaWFTdHJlYW0/OiBNZWRpYVN0cmVhbTtcbiAgICBtb2RlPzogc3RyaW5nOyAvLyBzZW5kb25seSwgcmVjb25seSwgc2VuZHJlY3ZcbiAgICBpZD86IHN0cmluZztcbn1cblxuZXhwb3J0IGNsYXNzIFdlYlJ0Y1BlZXIge1xuXG4gICAgcGM6IFJUQ1BlZXJDb25uZWN0aW9uO1xuICAgIGlkOiBzdHJpbmc7XG4gICAgcmVtb3RlQ2FuZGlkYXRlc1F1ZXVlOiBSVENJY2VDYW5kaWRhdGVbXSA9IFtdO1xuICAgIGxvY2FsQ2FuZGlkYXRlc1F1ZXVlOiBSVENJY2VDYW5kaWRhdGVbXSA9IFtdO1xuXG4gICAgaWNlQ2FuZGlkYXRlTGlzdDogUlRDSWNlQ2FuZGlkYXRlW10gPSBbXTtcblxuICAgIHByaXZhdGUgY2FuZGlkYXRlZ2F0aGVyaW5nZG9uZSA9IGZhbHNlO1xuXG4gICAgY29uc3RydWN0b3IocHJpdmF0ZSBjb25maWd1cmF0aW9uOiBXZWJSdGNQZWVyQ29uZmlndXJhdGlvbikge1xuICAgICAgICB0aGlzLmNvbmZpZ3VyYXRpb24uaWNlU2VydmVycyA9ICghIXRoaXMuY29uZmlndXJhdGlvbi5pY2VTZXJ2ZXJzICYmIHRoaXMuY29uZmlndXJhdGlvbi5pY2VTZXJ2ZXJzLmxlbmd0aCA+IDApID8gdGhpcy5jb25maWd1cmF0aW9uLmljZVNlcnZlcnMgOiBmcmVlaWNlKCk7XG5cbiAgICAgICAgdGhpcy5wYyA9IG5ldyBSVENQZWVyQ29ubmVjdGlvbih7IGljZVNlcnZlcnM6IHRoaXMuY29uZmlndXJhdGlvbi5pY2VTZXJ2ZXJzIH0pO1xuICAgICAgICB0aGlzLmlkID0gISFjb25maWd1cmF0aW9uLmlkID8gY29uZmlndXJhdGlvbi5pZCA6IHV1aWQudjQoKTtcblxuICAgICAgICB0aGlzLnBjLm9uaWNlY2FuZGlkYXRlID0gZXZlbnQgPT4ge1xuICAgICAgICAgICAgY29uc3QgY2FuZGlkYXRlOiBSVENJY2VDYW5kaWRhdGUgPSBldmVudC5jYW5kaWRhdGU7XG4gICAgICAgICAgICBpZiAoY2FuZGlkYXRlKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5sb2NhbENhbmRpZGF0ZXNRdWV1ZS5wdXNoKDxSVENJY2VDYW5kaWRhdGU+eyBjYW5kaWRhdGU6IGNhbmRpZGF0ZS5jYW5kaWRhdGUgfSk7XG4gICAgICAgICAgICAgICAgdGhpcy5jYW5kaWRhdGVnYXRoZXJpbmdkb25lID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgdGhpcy5jb25maWd1cmF0aW9uLm9uaWNlY2FuZGlkYXRlKGV2ZW50LmNhbmRpZGF0ZSk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKCF0aGlzLmNhbmRpZGF0ZWdhdGhlcmluZ2RvbmUpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmNhbmRpZGF0ZWdhdGhlcmluZ2RvbmUgPSB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuXG4gICAgICAgIHRoaXMucGMub25zaWduYWxpbmdzdGF0ZWNoYW5nZSA9ICgpID0+IHtcbiAgICAgICAgICAgIGlmICh0aGlzLnBjLnNpZ25hbGluZ1N0YXRlID09PSAnc3RhYmxlJykge1xuICAgICAgICAgICAgICAgIHdoaWxlICh0aGlzLmljZUNhbmRpZGF0ZUxpc3QubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnBjLmFkZEljZUNhbmRpZGF0ZSg8UlRDSWNlQ2FuZGlkYXRlPnRoaXMuaWNlQ2FuZGlkYXRlTGlzdC5zaGlmdCgpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG5cbiAgICAgICAgdGhpcy5zdGFydCgpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoaXMgZnVuY3Rpb24gY3JlYXRlcyB0aGUgUlRDUGVlckNvbm5lY3Rpb24gb2JqZWN0IHRha2luZyBpbnRvIGFjY291bnQgdGhlXG4gICAgICogcHJvcGVydGllcyByZWNlaXZlZCBpbiB0aGUgY29uc3RydWN0b3IuIEl0IHN0YXJ0cyB0aGUgU0RQIG5lZ290aWF0aW9uXG4gICAgICogcHJvY2VzczogZ2VuZXJhdGVzIHRoZSBTRFAgb2ZmZXIgYW5kIGludm9rZXMgdGhlIG9uc2Rwb2ZmZXIgY2FsbGJhY2suIFRoaXNcbiAgICAgKiBjYWxsYmFjayBpcyBleHBlY3RlZCB0byBzZW5kIHRoZSBTRFAgb2ZmZXIsIGluIG9yZGVyIHRvIG9idGFpbiBhbiBTRFBcbiAgICAgKiBhbnN3ZXIgZnJvbSBhbm90aGVyIHBlZXIuXG4gICAgICovXG4gICAgc3RhcnQoKTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIGlmICh0aGlzLnBjLnNpZ25hbGluZ1N0YXRlID09PSAnY2xvc2VkJykge1xuICAgICAgICAgICAgICAgIHJlamVjdCgnVGhlIHBlZXIgY29ubmVjdGlvbiBvYmplY3QgaXMgaW4gXCJjbG9zZWRcIiBzdGF0ZS4gVGhpcyBpcyBtb3N0IGxpa2VseSBkdWUgdG8gYW4gaW52b2NhdGlvbiBvZiB0aGUgZGlzcG9zZSBtZXRob2QgYmVmb3JlIGFjY2VwdGluZyBpbiB0aGUgZGlhbG9ndWUnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICghIXRoaXMuY29uZmlndXJhdGlvbi5tZWRpYVN0cmVhbSkge1xuICAgICAgICAgICAgICAgIHRoaXMucGMuYWRkU3RyZWFtKHRoaXMuY29uZmlndXJhdGlvbi5tZWRpYVN0cmVhbSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIFtIYWNrXSBodHRwczovL2NvZGUuZ29vZ2xlLmNvbS9wL2Nocm9taXVtL2lzc3Vlcy9kZXRhaWw/aWQ9NDQzNTU4XG4gICAgICAgICAgICBpZiAodGhpcy5jb25maWd1cmF0aW9uLm1vZGUgPT09ICdzZW5kb25seScgJiZcbiAgICAgICAgICAgICAgICAocGxhdGZvcm0ubmFtZSA9PT0gJ0Nocm9tZScgJiYgcGxhdGZvcm0udmVyc2lvbiEudG9TdHJpbmcoKS5zdWJzdHJpbmcoMCwgMikgPT09ICczOScpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5jb25maWd1cmF0aW9uLm1vZGUgPSAnc2VuZHJlY3YnO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoaXMgbWV0aG9kIGZyZWVzIHRoZSByZXNvdXJjZXMgdXNlZCBieSBXZWJSdGNQZWVyXG4gICAgICovXG4gICAgZGlzcG9zZSgpIHtcbiAgICAgICAgY29uc29sZS5kZWJ1ZygnRGlzcG9zaW5nIFdlYlJ0Y1BlZXInKTtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGlmICh0aGlzLnBjKSB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMucGMuc2lnbmFsaW5nU3RhdGUgPT09ICdjbG9zZWQnKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhpcy5yZW1vdGVDYW5kaWRhdGVzUXVldWUgPSBbXTtcbiAgICAgICAgICAgICAgICB0aGlzLmxvY2FsQ2FuZGlkYXRlc1F1ZXVlID0gW107XG5cbiAgICAgICAgICAgICAgICB0aGlzLnBjLmdldExvY2FsU3RyZWFtcygpLmZvckVhY2goc3RyID0+IHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5zdHJlYW1TdG9wKHN0cik7XG4gICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICAvLyBGSVhNRSBUaGlzIGlzIG5vdCB5ZXQgaW1wbGVtZW50ZWQgaW4gZmlyZWZveFxuICAgICAgICAgICAgICAgIC8vIGlmKHZpZGVvU3RyZWFtKSBwYy5yZW1vdmVTdHJlYW0odmlkZW9TdHJlYW0pO1xuICAgICAgICAgICAgICAgIC8vIGlmKGF1ZGlvU3RyZWFtKSBwYy5yZW1vdmVTdHJlYW0oYXVkaW9TdHJlYW0pO1xuXG4gICAgICAgICAgICAgICAgdGhpcy5wYy5jbG9zZSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAgIGNvbnNvbGUud2FybignRXhjZXB0aW9uIGRpc3Bvc2luZyB3ZWJydGMgcGVlciAnICsgZXJyKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIDEpIEZ1bmN0aW9uIHRoYXQgY3JlYXRlcyBhbiBvZmZlciwgc2V0cyBpdCBhcyBsb2NhbCBkZXNjcmlwdGlvbiBhbmQgcmV0dXJucyB0aGUgb2ZmZXIgcGFyYW1cbiAgICAgKiB0byBzZW5kIHRvIE9wZW5WaWR1IFNlcnZlciAod2lsbCBiZSB0aGUgcmVtb3RlIGRlc2NyaXB0aW9uIG9mIG90aGVyIHBlZXIpXG4gICAgICovXG4gICAgZ2VuZXJhdGVPZmZlcigpOiBQcm9taXNlPHN0cmluZz4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgbGV0IG9mZmVyQXVkaW8sIG9mZmVyVmlkZW8gPSB0cnVlO1xuXG4gICAgICAgICAgICAvLyBDb25zdHJhaW50cyBtdXN0IGhhdmUgYm90aCBibG9ja3NcbiAgICAgICAgICAgIGlmICghIXRoaXMuY29uZmlndXJhdGlvbi5tZWRpYUNvbnN0cmFpbnRzKSB7XG4gICAgICAgICAgICAgICAgb2ZmZXJBdWRpbyA9ICh0eXBlb2YgdGhpcy5jb25maWd1cmF0aW9uLm1lZGlhQ29uc3RyYWludHMuYXVkaW8gPT09ICdib29sZWFuJykgP1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbmZpZ3VyYXRpb24ubWVkaWFDb25zdHJhaW50cy5hdWRpbyA6IHRydWU7XG4gICAgICAgICAgICAgICAgb2ZmZXJWaWRlbyA9ICh0eXBlb2YgdGhpcy5jb25maWd1cmF0aW9uLm1lZGlhQ29uc3RyYWludHMudmlkZW8gPT09ICdib29sZWFuJykgP1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbmZpZ3VyYXRpb24ubWVkaWFDb25zdHJhaW50cy52aWRlbyA6IHRydWU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGNvbnN0IGNvbnN0cmFpbnRzOiBSVENPZmZlck9wdGlvbnMgPSB7XG4gICAgICAgICAgICAgICAgb2ZmZXJUb1JlY2VpdmVBdWRpbzogKyAodGhpcy5jb25maWd1cmF0aW9uLm1vZGUgIT09ICdzZW5kb25seScgJiYgb2ZmZXJBdWRpbyksXG4gICAgICAgICAgICAgICAgb2ZmZXJUb1JlY2VpdmVWaWRlbzogKyAodGhpcy5jb25maWd1cmF0aW9uLm1vZGUgIT09ICdzZW5kb25seScgJiYgb2ZmZXJWaWRlbylcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIGNvbnNvbGUuZGVidWcoJ1JUQ1BlZXJDb25uZWN0aW9uIGNvbnN0cmFpbnRzOiAnICsgSlNPTi5zdHJpbmdpZnkoY29uc3RyYWludHMpKTtcblxuICAgICAgICAgICAgdGhpcy5wYy5jcmVhdGVPZmZlcihjb25zdHJhaW50cykudGhlbihvZmZlciA9PiB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5kZWJ1ZygnQ3JlYXRlZCBTRFAgb2ZmZXInKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5wYy5zZXRMb2NhbERlc2NyaXB0aW9uKG9mZmVyKTtcbiAgICAgICAgICAgIH0pLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IGxvY2FsRGVzY3JpcHRpb24gPSB0aGlzLnBjLmxvY2FsRGVzY3JpcHRpb247XG4gICAgICAgICAgICAgICAgaWYgKCEhbG9jYWxEZXNjcmlwdGlvbikge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmRlYnVnKCdMb2NhbCBkZXNjcmlwdGlvbiBzZXQnLCBsb2NhbERlc2NyaXB0aW9uLnNkcCk7XG4gICAgICAgICAgICAgICAgICAgIHJlc29sdmUoPHN0cmluZz5sb2NhbERlc2NyaXB0aW9uLnNkcCk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcmVqZWN0KCdMb2NhbCBkZXNjcmlwdGlvbiBpcyBub3QgZGVmaW5lZCcpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pLmNhdGNoKGVycm9yID0+IHJlamVjdChlcnJvcikpO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiAyKSBGdW5jdGlvbiB0byBpbnZva2Ugd2hlbiBhIFNEUCBvZmZlciBpcyByZWNlaXZlZC4gU2V0cyBpdCBhcyByZW1vdGUgZGVzY3JpcHRpb24sXG4gICAgICogZ2VuZXJhdGVzIGFuZCBhbnN3ZXIgYW5kIHJldHVybnMgaXQgdG8gc2VuZCBpdCB0byBPcGVuVmlkdSBTZXJ2ZXJcbiAgICAgKi9cbiAgICBwcm9jZXNzT2ZmZXIoc2RwT2ZmZXI6IHN0cmluZyk6IFByb21pc2U8Q29uc3RyYWluRE9NU3RyaW5nPiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICBjb25zdCBvZmZlcjogUlRDU2Vzc2lvbkRlc2NyaXB0aW9uSW5pdCA9IHtcbiAgICAgICAgICAgICAgICB0eXBlOiAnb2ZmZXInLFxuICAgICAgICAgICAgICAgIHNkcDogc2RwT2ZmZXJcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIGNvbnNvbGUuZGVidWcoJ1NEUCBvZmZlciByZWNlaXZlZCwgc2V0dGluZyByZW1vdGUgZGVzY3JpcHRpb24nKTtcblxuICAgICAgICAgICAgaWYgKHRoaXMucGMuc2lnbmFsaW5nU3RhdGUgPT09ICdjbG9zZWQnKSB7XG4gICAgICAgICAgICAgICAgcmVqZWN0KCdQZWVyQ29ubmVjdGlvbiBpcyBjbG9zZWQnKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5wYy5zZXRSZW1vdGVEZXNjcmlwdGlvbihvZmZlcilcbiAgICAgICAgICAgICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLnBjLmNyZWF0ZUFuc3dlcigpO1xuICAgICAgICAgICAgICAgIH0pLnRoZW4oYW5zd2VyID0+IHtcbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS5kZWJ1ZygnQ3JlYXRlZCBTRFAgYW5zd2VyJyk7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLnBjLnNldExvY2FsRGVzY3JpcHRpb24oYW5zd2VyKTtcbiAgICAgICAgICAgICAgICB9KS50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgbG9jYWxEZXNjcmlwdGlvbiA9IHRoaXMucGMubG9jYWxEZXNjcmlwdGlvbjtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCEhbG9jYWxEZXNjcmlwdGlvbikge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5kZWJ1ZygnTG9jYWwgZGVzY3JpcHRpb24gc2V0JywgbG9jYWxEZXNjcmlwdGlvbi5zZHApO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSg8c3RyaW5nPmxvY2FsRGVzY3JpcHRpb24uc2RwKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdCgnTG9jYWwgZGVzY3JpcHRpb24gaXMgbm90IGRlZmluZWQnKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pLmNhdGNoKGVycm9yID0+IHJlamVjdChlcnJvcikpO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiAzKSBGdW5jdGlvbiBpbnZva2VkIHdoZW4gYSBTRFAgYW5zd2VyIGlzIHJlY2VpdmVkLiBGaW5hbCBzdGVwIGluIFNEUCBuZWdvdGlhdGlvbiwgdGhlIHBlZXJcbiAgICAgKiBqdXN0IG5lZWRzIHRvIHNldCB0aGUgYW5zd2VyIGFzIGl0cyByZW1vdGUgZGVzY3JpcHRpb25cbiAgICAgKi9cbiAgICBwcm9jZXNzQW5zd2VyKHNkcEFuc3dlcjogc3RyaW5nKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcblxuICAgICAgICAgICAgY29uc3QgYW5zd2VyOiBSVENTZXNzaW9uRGVzY3JpcHRpb25Jbml0ID0ge1xuICAgICAgICAgICAgICAgIHR5cGU6ICdhbnN3ZXInLFxuICAgICAgICAgICAgICAgIHNkcDogc2RwQW5zd2VyXG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICBjb25zb2xlLmRlYnVnKCdTRFAgYW5zd2VyIHJlY2VpdmVkLCBzZXR0aW5nIHJlbW90ZSBkZXNjcmlwdGlvbicpO1xuXG4gICAgICAgICAgICBpZiAodGhpcy5wYy5zaWduYWxpbmdTdGF0ZSA9PT0gJ2Nsb3NlZCcpIHtcbiAgICAgICAgICAgICAgICByZWplY3QoJ1JUQ1BlZXJDb25uZWN0aW9uIGlzIGNsb3NlZCcpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLnBjLnNldFJlbW90ZURlc2NyaXB0aW9uKGFuc3dlcikudGhlbigoKSA9PiByZXNvbHZlKCkpLmNhdGNoKGVycm9yID0+IHJlamVjdChlcnJvcikpO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDYWxsYmFjayBmdW5jdGlvbiBpbnZva2VkIHdoZW4gYW4gSUNFIGNhbmRpZGF0ZSBpcyByZWNlaXZlZFxuICAgICAqL1xuICAgIGFkZEljZUNhbmRpZGF0ZShpY2VDYW5kaWRhdGU6IFJUQ0ljZUNhbmRpZGF0ZSk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgY29uc29sZS5kZWJ1ZygnUmVtb3RlIElDRSBjYW5kaWRhdGUgcmVjZWl2ZWQnLCBpY2VDYW5kaWRhdGUpO1xuICAgICAgICAgICAgdGhpcy5yZW1vdGVDYW5kaWRhdGVzUXVldWUucHVzaChpY2VDYW5kaWRhdGUpO1xuICAgICAgICAgICAgc3dpdGNoICh0aGlzLnBjLnNpZ25hbGluZ1N0YXRlKSB7XG4gICAgICAgICAgICAgICAgY2FzZSAnY2xvc2VkJzpcbiAgICAgICAgICAgICAgICAgICAgcmVqZWN0KG5ldyBFcnJvcignUGVlckNvbm5lY3Rpb24gb2JqZWN0IGlzIGNsb3NlZCcpKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAnc3RhYmxlJzpcbiAgICAgICAgICAgICAgICAgICAgaWYgKCEhdGhpcy5wYy5yZW1vdGVEZXNjcmlwdGlvbikge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5wYy5hZGRJY2VDYW5kaWRhdGUoaWNlQ2FuZGlkYXRlKS50aGVuKCgpID0+IHJlc29sdmUoKSkuY2F0Y2goZXJyb3IgPT4gcmVqZWN0KGVycm9yKSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5pY2VDYW5kaWRhdGVMaXN0LnB1c2goaWNlQ2FuZGlkYXRlKTtcbiAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBwcml2YXRlIHN0cmVhbVN0b3Aoc3RyZWFtOiBNZWRpYVN0cmVhbSk6IHZvaWQge1xuICAgICAgICBzdHJlYW0uZ2V0VHJhY2tzKCkuZm9yRWFjaCh0cmFjayA9PiB7XG4gICAgICAgICAgICB0cmFjay5zdG9wKCk7XG4gICAgICAgICAgICBzdHJlYW0ucmVtb3ZlVHJhY2sodHJhY2spO1xuICAgICAgICB9KTtcbiAgICB9XG59XG5cblxuZXhwb3J0IGNsYXNzIFdlYlJ0Y1BlZXJSZWN2b25seSBleHRlbmRzIFdlYlJ0Y1BlZXIge1xuICAgIGNvbnN0cnVjdG9yKGNvbmZpZ3VyYXRpb246IFdlYlJ0Y1BlZXJDb25maWd1cmF0aW9uKSB7XG4gICAgICAgIGNvbmZpZ3VyYXRpb24ubW9kZSA9ICdyZWN2b25seSc7XG4gICAgICAgIHN1cGVyKGNvbmZpZ3VyYXRpb24pO1xuICAgIH1cbn1cblxuZXhwb3J0IGNsYXNzIFdlYlJ0Y1BlZXJTZW5kb25seSBleHRlbmRzIFdlYlJ0Y1BlZXIge1xuICAgIGNvbnN0cnVjdG9yKGNvbmZpZ3VyYXRpb246IFdlYlJ0Y1BlZXJDb25maWd1cmF0aW9uKSB7XG4gICAgICAgIGNvbmZpZ3VyYXRpb24ubW9kZSA9ICdzZW5kb25seSc7XG4gICAgICAgIHN1cGVyKGNvbmZpZ3VyYXRpb24pO1xuICAgIH1cbn1cblxuZXhwb3J0IGNsYXNzIFdlYlJ0Y1BlZXJTZW5kcmVjdiBleHRlbmRzIFdlYlJ0Y1BlZXIge1xuICAgIGNvbnN0cnVjdG9yKGNvbmZpZ3VyYXRpb246IFdlYlJ0Y1BlZXJDb25maWd1cmF0aW9uKSB7XG4gICAgICAgIGNvbmZpZ3VyYXRpb24ubW9kZSA9ICdzZW5kcmVjdic7XG4gICAgICAgIHN1cGVyKGNvbmZpZ3VyYXRpb24pO1xuICAgIH1cbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbi8vIHRzbGludDpkaXNhYmxlOm5vLXN0cmluZy1saXRlcmFsXG5cbmltcG9ydCB7IFN0cmVhbSB9IGZyb20gJy4uLy4uL09wZW5WaWR1L1N0cmVhbSc7XG5pbXBvcnQgcGxhdGZvcm0gPSByZXF1aXJlKCdwbGF0Zm9ybScpO1xuXG5leHBvcnQgY2xhc3MgV2ViUnRjU3RhdHMge1xuXG4gICAgcHJpdmF0ZSB3ZWJSdGNTdGF0c0VuYWJsZWQgPSBmYWxzZTtcbiAgICBwcml2YXRlIHdlYlJ0Y1N0YXRzSW50ZXJ2YWxJZDogTm9kZUpTLlRpbWVyO1xuICAgIHByaXZhdGUgc3RhdHNJbnRlcnZhbCA9IDE7XG4gICAgcHJpdmF0ZSBzdGF0czogYW55ID0ge1xuICAgICAgICBpbmJvdW5kOiB7XG4gICAgICAgICAgICBhdWRpbzoge1xuICAgICAgICAgICAgICAgIGJ5dGVzUmVjZWl2ZWQ6IDAsXG4gICAgICAgICAgICAgICAgcGFja2V0c1JlY2VpdmVkOiAwLFxuICAgICAgICAgICAgICAgIHBhY2tldHNMb3N0OiAwXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgdmlkZW86IHtcbiAgICAgICAgICAgICAgICBieXRlc1JlY2VpdmVkOiAwLFxuICAgICAgICAgICAgICAgIHBhY2tldHNSZWNlaXZlZDogMCxcbiAgICAgICAgICAgICAgICBwYWNrZXRzTG9zdDogMCxcbiAgICAgICAgICAgICAgICBmcmFtZXNEZWNvZGVkOiAwLFxuICAgICAgICAgICAgICAgIG5hY2tDb3VudDogMFxuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBvdXRib3VuZDoge1xuICAgICAgICAgICAgYXVkaW86IHtcbiAgICAgICAgICAgICAgICBieXRlc1NlbnQ6IDAsXG4gICAgICAgICAgICAgICAgcGFja2V0c1NlbnQ6IDAsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgdmlkZW86IHtcbiAgICAgICAgICAgICAgICBieXRlc1NlbnQ6IDAsXG4gICAgICAgICAgICAgICAgcGFja2V0c1NlbnQ6IDAsXG4gICAgICAgICAgICAgICAgZnJhbWVzRW5jb2RlZDogMCxcbiAgICAgICAgICAgICAgICBuYWNrQ291bnQ6IDBcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH07XG5cbiAgICBjb25zdHJ1Y3Rvcihwcml2YXRlIHN0cmVhbTogU3RyZWFtKSB7IH1cblxuICAgIHB1YmxpYyBpc0VuYWJsZWQoKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiB0aGlzLndlYlJ0Y1N0YXRzRW5hYmxlZDtcbiAgICB9XG5cbiAgICBwdWJsaWMgaW5pdFdlYlJ0Y1N0YXRzKCk6IHZvaWQge1xuXG4gICAgICAgIGNvbnN0IGVsYXN0ZXN0SW5zdHJ1bWVudGF0aW9uID0gbG9jYWxTdG9yYWdlLmdldEl0ZW0oJ2VsYXN0ZXN0LWluc3RydW1lbnRhdGlvbicpO1xuXG4gICAgICAgIGlmIChlbGFzdGVzdEluc3RydW1lbnRhdGlvbikge1xuICAgICAgICAgICAgLy8gRWxhc1Rlc3QgaW5zdHJ1bWVudGF0aW9uIG9iamVjdCBmb3VuZCBpbiBsb2NhbCBzdG9yYWdlXG5cbiAgICAgICAgICAgIGNvbnNvbGUud2FybignV2ViUnRjIHN0YXRzIGVuYWJsZWQgZm9yIHN0cmVhbSAnICsgdGhpcy5zdHJlYW0uc3RyZWFtSWQgKyAnIG9mIGNvbm5lY3Rpb24gJyArIHRoaXMuc3RyZWFtLmNvbm5lY3Rpb24uY29ubmVjdGlvbklkKTtcblxuICAgICAgICAgICAgdGhpcy53ZWJSdGNTdGF0c0VuYWJsZWQgPSB0cnVlO1xuXG4gICAgICAgICAgICBjb25zdCBpbnN0cnVtZW50YXRpb24gPSBKU09OLnBhcnNlKGVsYXN0ZXN0SW5zdHJ1bWVudGF0aW9uKTtcbiAgICAgICAgICAgIHRoaXMuc3RhdHNJbnRlcnZhbCA9IGluc3RydW1lbnRhdGlvbi53ZWJydGMuaW50ZXJ2YWw7ICAvLyBJbnRlcnZhbCBpbiBzZWNvbmRzXG5cbiAgICAgICAgICAgIGNvbnNvbGUud2FybignbG9jYWxTdG9yYWdlIGl0ZW06ICcgKyBKU09OLnN0cmluZ2lmeShpbnN0cnVtZW50YXRpb24pKTtcblxuICAgICAgICAgICAgdGhpcy53ZWJSdGNTdGF0c0ludGVydmFsSWQgPSBzZXRJbnRlcnZhbCgoKSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5zZW5kU3RhdHNUb0h0dHBFbmRwb2ludChpbnN0cnVtZW50YXRpb24pO1xuICAgICAgICAgICAgfSwgdGhpcy5zdGF0c0ludGVydmFsICogMTAwMCk7XG5cbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnNvbGUuZGVidWcoJ1dlYlJ0YyBzdGF0cyBub3QgZW5hYmxlZCcpO1xuICAgIH1cblxuICAgIHB1YmxpYyBzdG9wV2ViUnRjU3RhdHMoKSB7XG4gICAgICAgIGlmICh0aGlzLndlYlJ0Y1N0YXRzRW5hYmxlZCkge1xuICAgICAgICAgICAgY2xlYXJJbnRlcnZhbCh0aGlzLndlYlJ0Y1N0YXRzSW50ZXJ2YWxJZCk7XG4gICAgICAgICAgICBjb25zb2xlLndhcm4oJ1dlYlJ0YyBzdGF0cyBzdG9wcGVkIGZvciBkaXNwb3NlZCBzdHJlYW0gJyArIHRoaXMuc3RyZWFtLnN0cmVhbUlkICsgJyBvZiBjb25uZWN0aW9uICcgKyB0aGlzLnN0cmVhbS5jb25uZWN0aW9uLmNvbm5lY3Rpb25JZCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwdWJsaWMgZ2V0U2VsZWN0ZWRJY2VDYW5kaWRhdGVJbmZvKCk6IFByb21pc2U8YW55PiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICB0aGlzLmdldFN0YXRzQWdub3N0aWModGhpcy5zdHJlYW0uZ2V0UlRDUGVlckNvbm5lY3Rpb24oKSxcbiAgICAgICAgICAgICAgICAoc3RhdHMpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKChwbGF0Zm9ybS5uYW1lIS5pbmRleE9mKCdDaHJvbWUnKSAhPT0gLTEpIHx8IChwbGF0Zm9ybS5uYW1lIS5pbmRleE9mKCdPcGVyYScpICE9PSAtMSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBsb2NhbENhbmRpZGF0ZUlkLCByZW1vdGVDYW5kaWRhdGVJZCwgZ29vZ0NhbmRpZGF0ZVBhaXI7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBsb2NhbENhbmRpZGF0ZXMgPSB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHJlbW90ZUNhbmRpZGF0ZXMgPSB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAoY29uc3Qga2V5IGluIHN0YXRzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3Qgc3RhdCA9IHN0YXRzW2tleV07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHN0YXQudHlwZSA9PT0gJ2xvY2FsY2FuZGlkYXRlJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsb2NhbENhbmRpZGF0ZXNbc3RhdC5pZF0gPSBzdGF0O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoc3RhdC50eXBlID09PSAncmVtb3RlY2FuZGlkYXRlJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZW1vdGVDYW5kaWRhdGVzW3N0YXQuaWRdID0gc3RhdDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHN0YXQudHlwZSA9PT0gJ2dvb2dDYW5kaWRhdGVQYWlyJyAmJiAoc3RhdC5nb29nQWN0aXZlQ29ubmVjdGlvbiA9PT0gJ3RydWUnKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnb29nQ2FuZGlkYXRlUGFpciA9IHN0YXQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxvY2FsQ2FuZGlkYXRlSWQgPSBzdGF0LmxvY2FsQ2FuZGlkYXRlSWQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlbW90ZUNhbmRpZGF0ZUlkID0gc3RhdC5yZW1vdGVDYW5kaWRhdGVJZDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBsZXQgZmluYWxMb2NhbENhbmRpZGF0ZSA9IGxvY2FsQ2FuZGlkYXRlc1tsb2NhbENhbmRpZGF0ZUlkXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghIWZpbmFsTG9jYWxDYW5kaWRhdGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBjYW5kTGlzdCA9IHRoaXMuc3RyZWFtLmdldExvY2FsSWNlQ2FuZGlkYXRlTGlzdCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGNhbmQgPSBjYW5kTGlzdC5maWx0ZXIoKGM6IFJUQ0ljZUNhbmRpZGF0ZSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gKCEhYy5jYW5kaWRhdGUgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuY2FuZGlkYXRlLmluZGV4T2YoZmluYWxMb2NhbENhbmRpZGF0ZS5pcEFkZHJlc3MpID49IDAgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuY2FuZGlkYXRlLmluZGV4T2YoZmluYWxMb2NhbENhbmRpZGF0ZS5wb3J0TnVtYmVyKSA+PSAwICYmXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjLmNhbmRpZGF0ZS5pbmRleE9mKGZpbmFsTG9jYWxDYW5kaWRhdGUucHJpb3JpdHkpID49IDApO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbmFsTG9jYWxDYW5kaWRhdGUucmF3ID0gISFjYW5kWzBdID8gY2FuZFswXS5jYW5kaWRhdGUgOiAnRVJST1I6IENhbm5vdCBmaW5kIGxvY2FsIGNhbmRpZGF0ZSBpbiBsaXN0IG9mIHNlbnQgSUNFIGNhbmRpZGF0ZXMnO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaW5hbExvY2FsQ2FuZGlkYXRlID0gJ0VSUk9SOiBObyBhY3RpdmUgbG9jYWwgSUNFIGNhbmRpZGF0ZS4gUHJvYmFibHkgSUNFLVRDUCBpcyBiZWluZyB1c2VkJztcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGZpbmFsUmVtb3RlQ2FuZGlkYXRlID0gcmVtb3RlQ2FuZGlkYXRlc1tyZW1vdGVDYW5kaWRhdGVJZF07XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoISFmaW5hbFJlbW90ZUNhbmRpZGF0ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGNhbmRMaXN0ID0gdGhpcy5zdHJlYW0uZ2V0UmVtb3RlSWNlQ2FuZGlkYXRlTGlzdCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGNhbmQgPSBjYW5kTGlzdC5maWx0ZXIoKGM6IFJUQ0ljZUNhbmRpZGF0ZSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gKCEhYy5jYW5kaWRhdGUgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuY2FuZGlkYXRlLmluZGV4T2YoZmluYWxSZW1vdGVDYW5kaWRhdGUuaXBBZGRyZXNzKSA+PSAwICYmXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjLmNhbmRpZGF0ZS5pbmRleE9mKGZpbmFsUmVtb3RlQ2FuZGlkYXRlLnBvcnROdW1iZXIpID49IDAgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuY2FuZGlkYXRlLmluZGV4T2YoZmluYWxSZW1vdGVDYW5kaWRhdGUucHJpb3JpdHkpID49IDApO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbmFsUmVtb3RlQ2FuZGlkYXRlLnJhdyA9ICEhY2FuZFswXSA/IGNhbmRbMF0uY2FuZGlkYXRlIDogJ0VSUk9SOiBDYW5ub3QgZmluZCByZW1vdGUgY2FuZGlkYXRlIGluIGxpc3Qgb2YgcmVjZWl2ZWQgSUNFIGNhbmRpZGF0ZXMnO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaW5hbFJlbW90ZUNhbmRpZGF0ZSA9ICdFUlJPUjogTm8gYWN0aXZlIHJlbW90ZSBJQ0UgY2FuZGlkYXRlLiBQcm9iYWJseSBJQ0UtVENQIGlzIGJlaW5nIHVzZWQnO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICByZXNvbHZlKHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBnb29nQ2FuZGlkYXRlUGFpcixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsb2NhbENhbmRpZGF0ZTogZmluYWxMb2NhbENhbmRpZGF0ZSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZW1vdGVDYW5kaWRhdGU6IGZpbmFsUmVtb3RlQ2FuZGlkYXRlXG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdCgnU2VsZWN0ZWQgSUNFIGNhbmRpZGF0ZSBpbmZvIG9ubHkgYXZhaWxhYmxlIGZvciBDaHJvbWUnKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgKGVycm9yKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIHByaXZhdGUgc2VuZFN0YXRzVG9IdHRwRW5kcG9pbnQoaW5zdHJ1bWVudGF0aW9uKTogdm9pZCB7XG5cbiAgICAgICAgY29uc3Qgc2VuZFBvc3QgPSAoanNvbikgPT4ge1xuICAgICAgICAgICAgY29uc3QgaHR0cDogWE1MSHR0cFJlcXVlc3QgPSBuZXcgWE1MSHR0cFJlcXVlc3QoKTtcbiAgICAgICAgICAgIGNvbnN0IHVybDogc3RyaW5nID0gaW5zdHJ1bWVudGF0aW9uLndlYnJ0Yy5odHRwRW5kcG9pbnQ7XG4gICAgICAgICAgICBodHRwLm9wZW4oJ1BPU1QnLCB1cmwsIHRydWUpO1xuXG4gICAgICAgICAgICBodHRwLnNldFJlcXVlc3RIZWFkZXIoJ0NvbnRlbnQtdHlwZScsICdhcHBsaWNhdGlvbi9qc29uJyk7XG5cbiAgICAgICAgICAgIGh0dHAub25yZWFkeXN0YXRlY2hhbmdlID0gKCkgPT4geyAvLyBDYWxsIGEgZnVuY3Rpb24gd2hlbiB0aGUgc3RhdGUgY2hhbmdlcy5cbiAgICAgICAgICAgICAgICBpZiAoaHR0cC5yZWFkeVN0YXRlID09PSA0ICYmIGh0dHAuc3RhdHVzID09PSAyMDApIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS5sb2coJ1dlYlJ0YyBzdGF0cyBzdWNjZXNzZnVsbHkgc2VudCB0byAnICsgdXJsICsgJyBmb3Igc3RyZWFtICcgKyB0aGlzLnN0cmVhbS5zdHJlYW1JZCArICcgb2YgY29ubmVjdGlvbiAnICsgdGhpcy5zdHJlYW0uY29ubmVjdGlvbi5jb25uZWN0aW9uSWQpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBodHRwLnNlbmQoanNvbik7XG4gICAgICAgIH07XG5cbiAgICAgICAgY29uc3QgZiA9IChzdGF0cykgPT4ge1xuXG4gICAgICAgICAgICBpZiAocGxhdGZvcm0ubmFtZSEuaW5kZXhPZignRmlyZWZveCcpICE9PSAtMSkge1xuICAgICAgICAgICAgICAgIHN0YXRzLmZvckVhY2goKHN0YXQpID0+IHtcblxuICAgICAgICAgICAgICAgICAgICBsZXQganNvbiA9IHt9O1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICgoc3RhdC50eXBlID09PSAnaW5ib3VuZC1ydHAnKSAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEF2b2lkIGZpcmVmb3ggZW1wdHkgb3V0Ym91bmQtcnRwIHN0YXRpc3RpY3NcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGF0Lm5hY2tDb3VudCAhPT0gbnVsbCAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0YXQuaXNSZW1vdGUgPT09IGZhbHNlICYmXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhdC5pZC5zdGFydHNXaXRoKCdpbmJvdW5kJykgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGF0LnJlbW90ZUlkLnN0YXJ0c1dpdGgoJ2luYm91bmQnKVxuICAgICAgICAgICAgICAgICAgICAgICAgKSkge1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBtZXRyaWNJZCA9ICd3ZWJydGNfaW5ib3VuZF8nICsgc3RhdC5tZWRpYVR5cGUgKyAnXycgKyBzdGF0LnNzcmM7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBqaXQgPSBzdGF0LmppdHRlciAqIDEwMDA7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG1ldHJpY3MgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnl0ZXNSZWNlaXZlZDogKHN0YXQuYnl0ZXNSZWNlaXZlZCAtIHRoaXMuc3RhdHMuaW5ib3VuZFtzdGF0Lm1lZGlhVHlwZV0uYnl0ZXNSZWNlaXZlZCkgLyB0aGlzLnN0YXRzSW50ZXJ2YWwsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaml0dGVyOiBqaXQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFja2V0c1JlY2VpdmVkOiAoc3RhdC5wYWNrZXRzUmVjZWl2ZWQgLSB0aGlzLnN0YXRzLmluYm91bmRbc3RhdC5tZWRpYVR5cGVdLnBhY2tldHNSZWNlaXZlZCkgLyB0aGlzLnN0YXRzSW50ZXJ2YWwsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFja2V0c0xvc3Q6IChzdGF0LnBhY2tldHNMb3N0IC0gdGhpcy5zdGF0cy5pbmJvdW5kW3N0YXQubWVkaWFUeXBlXS5wYWNrZXRzTG9zdCkgLyB0aGlzLnN0YXRzSW50ZXJ2YWxcbiAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB1bml0cyA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBieXRlc1JlY2VpdmVkOiAnYnl0ZXMnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGppdHRlcjogJ21zJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYWNrZXRzUmVjZWl2ZWQ6ICdwYWNrZXRzJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYWNrZXRzTG9zdDogJ3BhY2tldHMnXG4gICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHN0YXQubWVkaWFUeXBlID09PSAndmlkZW8nKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbWV0cmljc1snZnJhbWVzRGVjb2RlZCddID0gKHN0YXQuZnJhbWVzRGVjb2RlZCAtIHRoaXMuc3RhdHMuaW5ib3VuZC52aWRlby5mcmFtZXNEZWNvZGVkKSAvIHRoaXMuc3RhdHNJbnRlcnZhbDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXRyaWNzWyduYWNrQ291bnQnXSA9IChzdGF0Lm5hY2tDb3VudCAtIHRoaXMuc3RhdHMuaW5ib3VuZC52aWRlby5uYWNrQ291bnQpIC8gdGhpcy5zdGF0c0ludGVydmFsO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVuaXRzWydmcmFtZXNEZWNvZGVkJ10gPSAnZnJhbWVzJztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB1bml0c1snbmFja0NvdW50J10gPSAncGFja2V0cyc7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXRzLmluYm91bmQudmlkZW8uZnJhbWVzRGVjb2RlZCA9IHN0YXQuZnJhbWVzRGVjb2RlZDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXRzLmluYm91bmQudmlkZW8ubmFja0NvdW50ID0gc3RhdC5uYWNrQ291bnQ7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdHMuaW5ib3VuZFtzdGF0Lm1lZGlhVHlwZV0uYnl0ZXNSZWNlaXZlZCA9IHN0YXQuYnl0ZXNSZWNlaXZlZDtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdHMuaW5ib3VuZFtzdGF0Lm1lZGlhVHlwZV0ucGFja2V0c1JlY2VpdmVkID0gc3RhdC5wYWNrZXRzUmVjZWl2ZWQ7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXRzLmluYm91bmRbc3RhdC5tZWRpYVR5cGVdLnBhY2tldHNMb3N0ID0gc3RhdC5wYWNrZXRzTG9zdDtcblxuICAgICAgICAgICAgICAgICAgICAgICAganNvbiA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAnQHRpbWVzdGFtcCc6IG5ldyBEYXRlKHN0YXQudGltZXN0YW1wKS50b0lTT1N0cmluZygpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICdleGVjJzogaW5zdHJ1bWVudGF0aW9uLmV4ZWMsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJ2NvbXBvbmVudCc6IGluc3RydW1lbnRhdGlvbi5jb21wb25lbnQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJ3N0cmVhbSc6ICd3ZWJSdGMnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICd0eXBlJzogbWV0cmljSWQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJ3N0cmVhbV90eXBlJzogJ2NvbXBvc2VkX21ldHJpY3MnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICd1bml0cyc6IHVuaXRzXG4gICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAganNvblttZXRyaWNJZF0gPSBtZXRyaWNzO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBzZW5kUG9zdChKU09OLnN0cmluZ2lmeShqc29uKSk7XG5cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICgoc3RhdC50eXBlID09PSAnb3V0Ym91bmQtcnRwJykgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgIChcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBBdm9pZCBmaXJlZm94IGVtcHR5IGluYm91bmQtcnRwIHN0YXRpc3RpY3NcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGF0LmlzUmVtb3RlID09PSBmYWxzZSAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0YXQuaWQudG9Mb3dlckNhc2UoKS5pbmNsdWRlcygnb3V0Ym91bmQnKVxuICAgICAgICAgICAgICAgICAgICAgICAgKSkge1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBtZXRyaWNJZCA9ICd3ZWJydGNfb3V0Ym91bmRfJyArIHN0YXQubWVkaWFUeXBlICsgJ18nICsgc3RhdC5zc3JjO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBtZXRyaWNzID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ5dGVzU2VudDogKHN0YXQuYnl0ZXNTZW50IC0gdGhpcy5zdGF0cy5vdXRib3VuZFtzdGF0Lm1lZGlhVHlwZV0uYnl0ZXNTZW50KSAvIHRoaXMuc3RhdHNJbnRlcnZhbCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYWNrZXRzU2VudDogKHN0YXQucGFja2V0c1NlbnQgLSB0aGlzLnN0YXRzLm91dGJvdW5kW3N0YXQubWVkaWFUeXBlXS5wYWNrZXRzU2VudCkgLyB0aGlzLnN0YXRzSW50ZXJ2YWxcbiAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB1bml0cyA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBieXRlc1NlbnQ6ICdieXRlcycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFja2V0c1NlbnQ6ICdwYWNrZXRzJ1xuICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzdGF0Lm1lZGlhVHlwZSA9PT0gJ3ZpZGVvJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1ldHJpY3NbJ2ZyYW1lc0VuY29kZWQnXSA9IChzdGF0LmZyYW1lc0VuY29kZWQgLSB0aGlzLnN0YXRzLm91dGJvdW5kLnZpZGVvLmZyYW1lc0VuY29kZWQpIC8gdGhpcy5zdGF0c0ludGVydmFsO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVuaXRzWydmcmFtZXNFbmNvZGVkJ10gPSAnZnJhbWVzJztcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdHMub3V0Ym91bmQudmlkZW8uZnJhbWVzRW5jb2RlZCA9IHN0YXQuZnJhbWVzRW5jb2RlZDtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0cy5vdXRib3VuZFtzdGF0Lm1lZGlhVHlwZV0uYnl0ZXNTZW50ID0gc3RhdC5ieXRlc1NlbnQ7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXRzLm91dGJvdW5kW3N0YXQubWVkaWFUeXBlXS5wYWNrZXRzU2VudCA9IHN0YXQucGFja2V0c1NlbnQ7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGpzb24gPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJ0B0aW1lc3RhbXAnOiBuZXcgRGF0ZShzdGF0LnRpbWVzdGFtcCkudG9JU09TdHJpbmcoKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAnZXhlYyc6IGluc3RydW1lbnRhdGlvbi5leGVjLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICdjb21wb25lbnQnOiBpbnN0cnVtZW50YXRpb24uY29tcG9uZW50LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICdzdHJlYW0nOiAnd2ViUnRjJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAndHlwZSc6IG1ldHJpY0lkLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICdzdHJlYW1fdHlwZSc6ICdjb21wb3NlZF9tZXRyaWNzJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAndW5pdHMnOiB1bml0c1xuICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGpzb25bbWV0cmljSWRdID0gbWV0cmljcztcblxuICAgICAgICAgICAgICAgICAgICAgICAgc2VuZFBvc3QoSlNPTi5zdHJpbmdpZnkoanNvbikpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKChwbGF0Zm9ybS5uYW1lIS5pbmRleE9mKCdDaHJvbWUnKSAhPT0gLTEpIHx8IChwbGF0Zm9ybS5uYW1lIS5pbmRleE9mKCdPcGVyYScpICE9PSAtMSkpIHtcbiAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IGtleSBvZiBPYmplY3Qua2V5cyhzdGF0cykpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3Qgc3RhdCA9IHN0YXRzW2tleV07XG4gICAgICAgICAgICAgICAgICAgIGlmIChzdGF0LnR5cGUgPT09ICdzc3JjJykge1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBsZXQganNvbiA9IHt9O1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoJ2J5dGVzUmVjZWl2ZWQnIGluIHN0YXQgJiYgKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIChzdGF0Lm1lZGlhVHlwZSA9PT0gJ2F1ZGlvJyAmJiAnYXVkaW9PdXRwdXRMZXZlbCcgaW4gc3RhdCkgfHxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAoc3RhdC5tZWRpYVR5cGUgPT09ICd2aWRlbycgJiYgJ3FwU3VtJyBpbiBzdGF0KVxuICAgICAgICAgICAgICAgICAgICAgICAgKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGluYm91bmQtcnRwXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgbWV0cmljSWQgPSAnd2VicnRjX2luYm91bmRfJyArIHN0YXQubWVkaWFUeXBlICsgJ18nICsgc3RhdC5zc3JjO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgbWV0cmljcyA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnl0ZXNSZWNlaXZlZDogKHN0YXQuYnl0ZXNSZWNlaXZlZCAtIHRoaXMuc3RhdHMuaW5ib3VuZFtzdGF0Lm1lZGlhVHlwZV0uYnl0ZXNSZWNlaXZlZCkgLyB0aGlzLnN0YXRzSW50ZXJ2YWwsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGppdHRlcjogc3RhdC5nb29nSml0dGVyQnVmZmVyTXMsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhY2tldHNSZWNlaXZlZDogKHN0YXQucGFja2V0c1JlY2VpdmVkIC0gdGhpcy5zdGF0cy5pbmJvdW5kW3N0YXQubWVkaWFUeXBlXS5wYWNrZXRzUmVjZWl2ZWQpIC8gdGhpcy5zdGF0c0ludGVydmFsLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYWNrZXRzTG9zdDogKHN0YXQucGFja2V0c0xvc3QgLSB0aGlzLnN0YXRzLmluYm91bmRbc3RhdC5tZWRpYVR5cGVdLnBhY2tldHNMb3N0KSAvIHRoaXMuc3RhdHNJbnRlcnZhbFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgdW5pdHMgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ5dGVzUmVjZWl2ZWQ6ICdieXRlcycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGppdHRlcjogJ21zJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFja2V0c1JlY2VpdmVkOiAncGFja2V0cycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhY2tldHNMb3N0OiAncGFja2V0cydcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzdGF0Lm1lZGlhVHlwZSA9PT0gJ3ZpZGVvJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXRyaWNzWydmcmFtZXNEZWNvZGVkJ10gPSAoc3RhdC5mcmFtZXNEZWNvZGVkIC0gdGhpcy5zdGF0cy5pbmJvdW5kLnZpZGVvLmZyYW1lc0RlY29kZWQpIC8gdGhpcy5zdGF0c0ludGVydmFsO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXRyaWNzWyduYWNrQ291bnQnXSA9IChzdGF0Lmdvb2dOYWNrc1NlbnQgLSB0aGlzLnN0YXRzLmluYm91bmQudmlkZW8ubmFja0NvdW50KSAvIHRoaXMuc3RhdHNJbnRlcnZhbDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdW5pdHNbJ2ZyYW1lc0RlY29kZWQnXSA9ICdmcmFtZXMnO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1bml0c1snbmFja0NvdW50J10gPSAncGFja2V0cyc7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0cy5pbmJvdW5kLnZpZGVvLmZyYW1lc0RlY29kZWQgPSBzdGF0LmZyYW1lc0RlY29kZWQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdHMuaW5ib3VuZC52aWRlby5uYWNrQ291bnQgPSBzdGF0Lmdvb2dOYWNrc1NlbnQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0cy5pbmJvdW5kW3N0YXQubWVkaWFUeXBlXS5ieXRlc1JlY2VpdmVkID0gc3RhdC5ieXRlc1JlY2VpdmVkO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdHMuaW5ib3VuZFtzdGF0Lm1lZGlhVHlwZV0ucGFja2V0c1JlY2VpdmVkID0gc3RhdC5wYWNrZXRzUmVjZWl2ZWQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0cy5pbmJvdW5kW3N0YXQubWVkaWFUeXBlXS5wYWNrZXRzTG9zdCA9IHN0YXQucGFja2V0c0xvc3Q7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBqc29uID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnQHRpbWVzdGFtcCc6IG5ldyBEYXRlKHN0YXQudGltZXN0YW1wKS50b0lTT1N0cmluZygpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnZXhlYyc6IGluc3RydW1lbnRhdGlvbi5leGVjLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnY29tcG9uZW50JzogaW5zdHJ1bWVudGF0aW9uLmNvbXBvbmVudCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ3N0cmVhbSc6ICd3ZWJSdGMnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAndHlwZSc6IG1ldHJpY0lkLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnc3RyZWFtX3R5cGUnOiAnY29tcG9zZWRfbWV0cmljcycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICd1bml0cyc6IHVuaXRzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBqc29uW21ldHJpY0lkXSA9IG1ldHJpY3M7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZW5kUG9zdChKU09OLnN0cmluZ2lmeShqc29uKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKCdieXRlc1NlbnQnIGluIHN0YXQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBvdXRib3VuZC1ydHBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBtZXRyaWNJZCA9ICd3ZWJydGNfb3V0Ym91bmRfJyArIHN0YXQubWVkaWFUeXBlICsgJ18nICsgc3RhdC5zc3JjO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgbWV0cmljcyA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnl0ZXNTZW50OiAoc3RhdC5ieXRlc1NlbnQgLSB0aGlzLnN0YXRzLm91dGJvdW5kW3N0YXQubWVkaWFUeXBlXS5ieXRlc1NlbnQpIC8gdGhpcy5zdGF0c0ludGVydmFsLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYWNrZXRzU2VudDogKHN0YXQucGFja2V0c1NlbnQgLSB0aGlzLnN0YXRzLm91dGJvdW5kW3N0YXQubWVkaWFUeXBlXS5wYWNrZXRzU2VudCkgLyB0aGlzLnN0YXRzSW50ZXJ2YWxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHVuaXRzID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBieXRlc1NlbnQ6ICdieXRlcycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhY2tldHNTZW50OiAncGFja2V0cydcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzdGF0Lm1lZGlhVHlwZSA9PT0gJ3ZpZGVvJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXRyaWNzWydmcmFtZXNFbmNvZGVkJ10gPSAoc3RhdC5mcmFtZXNFbmNvZGVkIC0gdGhpcy5zdGF0cy5vdXRib3VuZC52aWRlby5mcmFtZXNFbmNvZGVkKSAvIHRoaXMuc3RhdHNJbnRlcnZhbDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdW5pdHNbJ2ZyYW1lc0VuY29kZWQnXSA9ICdmcmFtZXMnO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdHMub3V0Ym91bmQudmlkZW8uZnJhbWVzRW5jb2RlZCA9IHN0YXQuZnJhbWVzRW5jb2RlZDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXRzLm91dGJvdW5kW3N0YXQubWVkaWFUeXBlXS5ieXRlc1NlbnQgPSBzdGF0LmJ5dGVzU2VudDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXRzLm91dGJvdW5kW3N0YXQubWVkaWFUeXBlXS5wYWNrZXRzU2VudCA9IHN0YXQucGFja2V0c1NlbnQ7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBqc29uID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnQHRpbWVzdGFtcCc6IG5ldyBEYXRlKHN0YXQudGltZXN0YW1wKS50b0lTT1N0cmluZygpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnZXhlYyc6IGluc3RydW1lbnRhdGlvbi5leGVjLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnY29tcG9uZW50JzogaW5zdHJ1bWVudGF0aW9uLmNvbXBvbmVudCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ3N0cmVhbSc6ICd3ZWJSdGMnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAndHlwZSc6IG1ldHJpY0lkLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnc3RyZWFtX3R5cGUnOiAnY29tcG9zZWRfbWV0cmljcycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICd1bml0cyc6IHVuaXRzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBqc29uW21ldHJpY0lkXSA9IG1ldHJpY3M7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZW5kUG9zdChKU09OLnN0cmluZ2lmeShqc29uKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG5cbiAgICAgICAgdGhpcy5nZXRTdGF0c0Fnbm9zdGljKHRoaXMuc3RyZWFtLmdldFJUQ1BlZXJDb25uZWN0aW9uKCksIGYsIChlcnJvcikgPT4geyBjb25zb2xlLmxvZyhlcnJvcik7IH0pO1xuICAgIH1cblxuICAgIHByaXZhdGUgc3RhbmRhcmRpemVSZXBvcnQocmVzcG9uc2UpIHtcbiAgICAgICAgY29uc29sZS5sb2cocmVzcG9uc2UpO1xuICAgICAgICBjb25zdCBzdGFuZGFyZFJlcG9ydCA9IHt9O1xuXG4gICAgICAgIGlmIChwbGF0Zm9ybS5uYW1lIS5pbmRleE9mKCdGaXJlZm94JykgIT09IC0xKSB7XG4gICAgICAgICAgICBPYmplY3Qua2V5cyhyZXNwb25zZSkuZm9yRWFjaChrZXkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKHJlc3BvbnNlW2tleV0pO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICByZXR1cm4gcmVzcG9uc2U7XG4gICAgICAgIH1cblxuICAgICAgICByZXNwb25zZS5yZXN1bHQoKS5mb3JFYWNoKHJlcG9ydCA9PiB7XG4gICAgICAgICAgICBjb25zdCBzdGFuZGFyZFN0YXRzID0ge1xuICAgICAgICAgICAgICAgIGlkOiByZXBvcnQuaWQsXG4gICAgICAgICAgICAgICAgdGltZXN0YW1wOiByZXBvcnQudGltZXN0YW1wLFxuICAgICAgICAgICAgICAgIHR5cGU6IHJlcG9ydC50eXBlXG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgcmVwb3J0Lm5hbWVzKCkuZm9yRWFjaCgobmFtZSkgPT4ge1xuICAgICAgICAgICAgICAgIHN0YW5kYXJkU3RhdHNbbmFtZV0gPSByZXBvcnQuc3RhdChuYW1lKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgc3RhbmRhcmRSZXBvcnRbc3RhbmRhcmRTdGF0cy5pZF0gPSBzdGFuZGFyZFN0YXRzO1xuICAgICAgICB9KTtcblxuICAgICAgICByZXR1cm4gc3RhbmRhcmRSZXBvcnQ7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBnZXRTdGF0c0Fnbm9zdGljKHBjLCBzdWNjZXNzQ2IsIGZhaWx1cmVDYikge1xuICAgICAgICBpZiAocGxhdGZvcm0ubmFtZSEuaW5kZXhPZignRmlyZWZveCcpICE9PSAtMSkge1xuICAgICAgICAgICAgLy8gZ2V0U3RhdHMgdGFrZXMgYXJncyBpbiBkaWZmZXJlbnQgb3JkZXIgaW4gQ2hyb21lIGFuZCBGaXJlZm94XG4gICAgICAgICAgICByZXR1cm4gcGMuZ2V0U3RhdHMobnVsbCkudGhlbihyZXNwb25zZSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3QgcmVwb3J0ID0gdGhpcy5zdGFuZGFyZGl6ZVJlcG9ydChyZXNwb25zZSk7XG4gICAgICAgICAgICAgICAgc3VjY2Vzc0NiKHJlcG9ydCk7XG4gICAgICAgICAgICB9KS5jYXRjaChmYWlsdXJlQ2IpO1xuICAgICAgICB9IGVsc2UgaWYgKChwbGF0Zm9ybS5uYW1lIS5pbmRleE9mKCdDaHJvbWUnKSAhPT0gLTEpIHx8IChwbGF0Zm9ybS5uYW1lIS5pbmRleE9mKCdPcGVyYScpICE9PSAtMSkpIHtcbiAgICAgICAgICAgIC8vIEluIENocm9tZSwgdGhlIGZpcnN0IHR3byBhcmd1bWVudHMgYXJlIHJldmVyc2VkXG4gICAgICAgICAgICByZXR1cm4gcGMuZ2V0U3RhdHMoKHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3QgcmVwb3J0ID0gdGhpcy5zdGFuZGFyZGl6ZVJlcG9ydChyZXNwb25zZSk7XG4gICAgICAgICAgICAgICAgc3VjY2Vzc0NiKHJlcG9ydCk7XG4gICAgICAgICAgICB9LCBudWxsLCBmYWlsdXJlQ2IpO1xuICAgICAgICB9XG4gICAgfVxuXG59Il19
diff --git a/openvidu-hello-world/web/openvidu-browser-2.4.0.js b/openvidu-hello-world/web/openvidu-browser-2.4.0.js
new file mode 100644
index 000000000..61298c941
--- /dev/null
+++ b/openvidu-hello-world/web/openvidu-browser-2.4.0.js
@@ -0,0 +1,7696 @@
+(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 1)
+ er = arguments[1];
+ if (er instanceof Error) {
+ throw er; // Unhandled 'error' event
+ } else {
+ // At least give some kind of context to the user
+ var err = new Error('Unhandled "error" event. (' + er + ')');
+ err.context = er;
+ throw err;
+ }
+ return false;
+ }
+
+ handler = events[type];
+
+ if (!handler)
+ return false;
+
+ var isFn = typeof handler === 'function';
+ len = arguments.length;
+ switch (len) {
+ // fast cases
+ case 1:
+ emitNone(handler, isFn, this);
+ break;
+ case 2:
+ emitOne(handler, isFn, this, arguments[1]);
+ break;
+ case 3:
+ emitTwo(handler, isFn, this, arguments[1], arguments[2]);
+ break;
+ case 4:
+ emitThree(handler, isFn, this, arguments[1], arguments[2], arguments[3]);
+ break;
+ // slower
+ default:
+ args = new Array(len - 1);
+ for (i = 1; i < len; i++)
+ args[i - 1] = arguments[i];
+ emitMany(handler, isFn, this, args);
+ }
+
+ return true;
+};
+
+function _addListener(target, type, listener, prepend) {
+ var m;
+ var events;
+ var existing;
+
+ if (typeof listener !== 'function')
+ throw new TypeError('"listener" argument must be a function');
+
+ events = target._events;
+ if (!events) {
+ events = target._events = objectCreate(null);
+ target._eventsCount = 0;
+ } else {
+ // To avoid recursion in the case that type === "newListener"! Before
+ // adding it to the listeners, first emit "newListener".
+ if (events.newListener) {
+ target.emit('newListener', type,
+ listener.listener ? listener.listener : listener);
+
+ // Re-assign `events` because a newListener handler could have caused the
+ // this._events to be assigned to a new object
+ events = target._events;
+ }
+ existing = events[type];
+ }
+
+ if (!existing) {
+ // Optimize the case of one listener. Don't need the extra array object.
+ existing = events[type] = listener;
+ ++target._eventsCount;
+ } else {
+ if (typeof existing === 'function') {
+ // Adding the second element, need to change to array.
+ existing = events[type] =
+ prepend ? [listener, existing] : [existing, listener];
+ } else {
+ // If we've already got an array, just append.
+ if (prepend) {
+ existing.unshift(listener);
+ } else {
+ existing.push(listener);
+ }
+ }
+
+ // Check for listener leak
+ if (!existing.warned) {
+ m = $getMaxListeners(target);
+ if (m && m > 0 && existing.length > m) {
+ existing.warned = true;
+ var w = new Error('Possible EventEmitter memory leak detected. ' +
+ existing.length + ' "' + String(type) + '" listeners ' +
+ 'added. Use emitter.setMaxListeners() to ' +
+ 'increase limit.');
+ w.name = 'MaxListenersExceededWarning';
+ w.emitter = target;
+ w.type = type;
+ w.count = existing.length;
+ if (typeof console === 'object' && console.warn) {
+ console.warn('%s: %s', w.name, w.message);
+ }
+ }
+ }
+ }
+
+ return target;
+}
+
+EventEmitter.prototype.addListener = function addListener(type, listener) {
+ return _addListener(this, type, listener, false);
+};
+
+EventEmitter.prototype.on = EventEmitter.prototype.addListener;
+
+EventEmitter.prototype.prependListener =
+ function prependListener(type, listener) {
+ return _addListener(this, type, listener, true);
+ };
+
+function onceWrapper() {
+ if (!this.fired) {
+ this.target.removeListener(this.type, this.wrapFn);
+ this.fired = true;
+ switch (arguments.length) {
+ case 0:
+ return this.listener.call(this.target);
+ case 1:
+ return this.listener.call(this.target, arguments[0]);
+ case 2:
+ return this.listener.call(this.target, arguments[0], arguments[1]);
+ case 3:
+ return this.listener.call(this.target, arguments[0], arguments[1],
+ arguments[2]);
+ default:
+ var args = new Array(arguments.length);
+ for (var i = 0; i < args.length; ++i)
+ args[i] = arguments[i];
+ this.listener.apply(this.target, args);
+ }
+ }
+}
+
+function _onceWrap(target, type, listener) {
+ var state = { fired: false, wrapFn: undefined, target: target, type: type, listener: listener };
+ var wrapped = bind.call(onceWrapper, state);
+ wrapped.listener = listener;
+ state.wrapFn = wrapped;
+ return wrapped;
+}
+
+EventEmitter.prototype.once = function once(type, listener) {
+ if (typeof listener !== 'function')
+ throw new TypeError('"listener" argument must be a function');
+ this.on(type, _onceWrap(this, type, listener));
+ return this;
+};
+
+EventEmitter.prototype.prependOnceListener =
+ function prependOnceListener(type, listener) {
+ if (typeof listener !== 'function')
+ throw new TypeError('"listener" argument must be a function');
+ this.prependListener(type, _onceWrap(this, type, listener));
+ return this;
+ };
+
+// Emits a 'removeListener' event if and only if the listener was removed.
+EventEmitter.prototype.removeListener =
+ function removeListener(type, listener) {
+ var list, events, position, i, originalListener;
+
+ if (typeof listener !== 'function')
+ throw new TypeError('"listener" argument must be a function');
+
+ events = this._events;
+ if (!events)
+ return this;
+
+ list = events[type];
+ if (!list)
+ return this;
+
+ if (list === listener || list.listener === listener) {
+ if (--this._eventsCount === 0)
+ this._events = objectCreate(null);
+ else {
+ delete events[type];
+ if (events.removeListener)
+ this.emit('removeListener', type, list.listener || listener);
+ }
+ } else if (typeof list !== 'function') {
+ position = -1;
+
+ for (i = list.length - 1; i >= 0; i--) {
+ if (list[i] === listener || list[i].listener === listener) {
+ originalListener = list[i].listener;
+ position = i;
+ break;
+ }
+ }
+
+ if (position < 0)
+ return this;
+
+ if (position === 0)
+ list.shift();
+ else
+ spliceOne(list, position);
+
+ if (list.length === 1)
+ events[type] = list[0];
+
+ if (events.removeListener)
+ this.emit('removeListener', type, originalListener || listener);
+ }
+
+ return this;
+ };
+
+EventEmitter.prototype.removeAllListeners =
+ function removeAllListeners(type) {
+ var listeners, events, i;
+
+ events = this._events;
+ if (!events)
+ return this;
+
+ // not listening for removeListener, no need to emit
+ if (!events.removeListener) {
+ if (arguments.length === 0) {
+ this._events = objectCreate(null);
+ this._eventsCount = 0;
+ } else if (events[type]) {
+ if (--this._eventsCount === 0)
+ this._events = objectCreate(null);
+ else
+ delete events[type];
+ }
+ return this;
+ }
+
+ // emit removeListener for all listeners on all events
+ if (arguments.length === 0) {
+ var keys = objectKeys(events);
+ var key;
+ for (i = 0; i < keys.length; ++i) {
+ key = keys[i];
+ if (key === 'removeListener') continue;
+ this.removeAllListeners(key);
+ }
+ this.removeAllListeners('removeListener');
+ this._events = objectCreate(null);
+ this._eventsCount = 0;
+ return this;
+ }
+
+ listeners = events[type];
+
+ if (typeof listeners === 'function') {
+ this.removeListener(type, listeners);
+ } else if (listeners) {
+ // LIFO order
+ for (i = listeners.length - 1; i >= 0; i--) {
+ this.removeListener(type, listeners[i]);
+ }
+ }
+
+ return this;
+ };
+
+function _listeners(target, type, unwrap) {
+ var events = target._events;
+
+ if (!events)
+ return [];
+
+ var evlistener = events[type];
+ if (!evlistener)
+ return [];
+
+ if (typeof evlistener === 'function')
+ return unwrap ? [evlistener.listener || evlistener] : [evlistener];
+
+ return unwrap ? unwrapListeners(evlistener) : arrayClone(evlistener, evlistener.length);
+}
+
+EventEmitter.prototype.listeners = function listeners(type) {
+ return _listeners(this, type, true);
+};
+
+EventEmitter.prototype.rawListeners = function rawListeners(type) {
+ return _listeners(this, type, false);
+};
+
+EventEmitter.listenerCount = function(emitter, type) {
+ if (typeof emitter.listenerCount === 'function') {
+ return emitter.listenerCount(type);
+ } else {
+ return listenerCount.call(emitter, type);
+ }
+};
+
+EventEmitter.prototype.listenerCount = listenerCount;
+function listenerCount(type) {
+ var events = this._events;
+
+ if (events) {
+ var evlistener = events[type];
+
+ if (typeof evlistener === 'function') {
+ return 1;
+ } else if (evlistener) {
+ return evlistener.length;
+ }
+ }
+
+ return 0;
+}
+
+EventEmitter.prototype.eventNames = function eventNames() {
+ return this._eventsCount > 0 ? Reflect.ownKeys(this._events) : [];
+};
+
+// About 1.5x faster than the two-arg version of Array#splice().
+function spliceOne(list, index) {
+ for (var i = index, k = i + 1, n = list.length; k < n; i += 1, k += 1)
+ list[i] = list[k];
+ list.pop();
+}
+
+function arrayClone(arr, n) {
+ var copy = new Array(n);
+ for (var i = 0; i < n; ++i)
+ copy[i] = arr[i];
+ return copy;
+}
+
+function unwrapListeners(arr) {
+ var ret = new Array(arr.length);
+ for (var i = 0; i < ret.length; ++i) {
+ ret[i] = arr[i].listener || arr[i];
+ }
+ return ret;
+}
+
+function objectCreatePolyfill(proto) {
+ var F = function() {};
+ F.prototype = proto;
+ return new F;
+}
+function objectKeysPolyfill(obj) {
+ var keys = [];
+ for (var k in obj) if (Object.prototype.hasOwnProperty.call(obj, k)) {
+ keys.push(k);
+ }
+ return k;
+}
+function functionBindPolyfill(context) {
+ var fn = this;
+ return function () {
+ return fn.apply(context, arguments);
+ };
+}
+
+},{}],2:[function(require,module,exports){
+/* jshint node: true */
+'use strict';
+
+var normalice = require('normalice');
+
+/**
+ # freeice
+
+ The `freeice` module is a simple way of getting random STUN or TURN server
+ for your WebRTC application. The list of servers (just STUN at this stage)
+ were sourced from this [gist](https://gist.github.com/zziuni/3741933).
+
+ ## Example Use
+
+ The following demonstrates how you can use `freeice` with
+ [rtc-quickconnect](https://github.com/rtc-io/rtc-quickconnect):
+
+ <<< examples/quickconnect.js
+
+ As the `freeice` module generates ice servers in a list compliant with the
+ WebRTC spec you will be able to use it with raw `RTCPeerConnection`
+ constructors and other WebRTC libraries.
+
+ ## Hey, don't use my STUN/TURN server!
+
+ If for some reason your free STUN or TURN server ends up in the
+ list of servers ([stun](https://github.com/DamonOehlman/freeice/blob/master/stun.json) or
+ [turn](https://github.com/DamonOehlman/freeice/blob/master/turn.json))
+ that is used in this module, you can feel
+ free to open an issue on this repository and those servers will be removed
+ within 24 hours (or sooner). This is the quickest and probably the most
+ polite way to have something removed (and provides us some visibility
+ if someone opens a pull request requesting that a server is added).
+
+ ## Please add my server!
+
+ If you have a server that you wish to add to the list, that's awesome! I'm
+ sure I speak on behalf of a whole pile of WebRTC developers who say thanks.
+ To get it into the list, feel free to either open a pull request or if you
+ find that process a bit daunting then just create an issue requesting
+ the addition of the server (make sure you provide all the details, and if
+ you have a Terms of Service then including that in the PR/issue would be
+ awesome).
+
+ ## I know of a free server, can I add it?
+
+ Sure, if you do your homework and make sure it is ok to use (I'm currently
+ in the process of reviewing the terms of those STUN servers included from
+ the original list). If it's ok to go, then please see the previous entry
+ for how to add it.
+
+ ## Current List of Servers
+
+ * current as at the time of last `README.md` file generation
+
+ ### STUN
+
+ <<< stun.json
+
+ ### TURN
+
+ <<< turn.json
+
+**/
+
+var freeice = module.exports = function(opts) {
+ // if a list of servers has been provided, then use it instead of defaults
+ var servers = {
+ stun: (opts || {}).stun || require('./stun.json'),
+ turn: (opts || {}).turn || require('./turn.json')
+ };
+
+ var stunCount = (opts || {}).stunCount || 2;
+ var turnCount = (opts || {}).turnCount || 0;
+ var selected;
+
+ function getServers(type, count) {
+ var out = [];
+ var input = [].concat(servers[type]);
+ var idx;
+
+ while (input.length && out.length < count) {
+ idx = (Math.random() * input.length) | 0;
+ out = out.concat(input.splice(idx, 1));
+ }
+
+ return out.map(function(url) {
+ //If it's a not a string, don't try to "normalice" it otherwise using type:url will screw it up
+ if ((typeof url !== 'string') && (! (url instanceof String))) {
+ return url;
+ } else {
+ return normalice(type + ':' + url);
+ }
+ });
+ }
+
+ // add stun servers
+ selected = [].concat(getServers('stun', stunCount));
+
+ if (turnCount) {
+ selected = selected.concat(getServers('turn', turnCount));
+ }
+
+ return selected;
+};
+
+},{"./stun.json":3,"./turn.json":4,"normalice":7}],3:[function(require,module,exports){
+module.exports=[
+ "stun.l.google.com:19302",
+ "stun1.l.google.com:19302",
+ "stun2.l.google.com:19302",
+ "stun3.l.google.com:19302",
+ "stun4.l.google.com:19302",
+ "stun.ekiga.net",
+ "stun.ideasip.com",
+ "stun.schlund.de",
+ "stun.stunprotocol.org:3478",
+ "stun.voiparound.com",
+ "stun.voipbuster.com",
+ "stun.voipstunt.com",
+ "stun.voxgratia.org",
+ "stun.services.mozilla.com"
+]
+
+},{}],4:[function(require,module,exports){
+module.exports=[]
+
+},{}],5:[function(require,module,exports){
+var WildEmitter = require('wildemitter');
+
+function getMaxVolume (analyser, fftBins) {
+ var maxVolume = -Infinity;
+ analyser.getFloatFrequencyData(fftBins);
+
+ for(var i=4, ii=fftBins.length; i < ii; i++) {
+ if (fftBins[i] > maxVolume && fftBins[i] < 0) {
+ maxVolume = fftBins[i];
+ }
+ };
+
+ return maxVolume;
+}
+
+
+var audioContextType;
+if (typeof window !== 'undefined') {
+ audioContextType = window.AudioContext || window.webkitAudioContext;
+}
+// use a single audio context due to hardware limits
+var audioContext = null;
+module.exports = function(stream, options) {
+ var harker = new WildEmitter();
+
+
+ // make it not break in non-supported browsers
+ if (!audioContextType) return harker;
+
+ //Config
+ var options = options || {},
+ smoothing = (options.smoothing || 0.1),
+ interval = (options.interval || 50),
+ threshold = options.threshold,
+ play = options.play,
+ history = options.history || 10,
+ running = true;
+
+ //Setup Audio Context
+ if (!audioContext) {
+ audioContext = new audioContextType();
+ }
+ var sourceNode, fftBins, analyser;
+
+ analyser = audioContext.createAnalyser();
+ analyser.fftSize = 512;
+ analyser.smoothingTimeConstant = smoothing;
+ fftBins = new Float32Array(analyser.frequencyBinCount);
+
+ if (stream.jquery) stream = stream[0];
+ if (stream instanceof HTMLAudioElement || stream instanceof HTMLVideoElement) {
+ //Audio Tag
+ sourceNode = audioContext.createMediaElementSource(stream);
+ if (typeof play === 'undefined') play = true;
+ threshold = threshold || -50;
+ } else {
+ //WebRTC Stream
+ sourceNode = audioContext.createMediaStreamSource(stream);
+ threshold = threshold || -50;
+ }
+
+ sourceNode.connect(analyser);
+ if (play) analyser.connect(audioContext.destination);
+
+ harker.speaking = false;
+
+ harker.suspend = function() {
+ audioContext.suspend();
+ }
+ harker.resume = function() {
+ audioContext.resume();
+ }
+ Object.defineProperty(harker, 'state', { get: function() {
+ return audioContext.state;
+ }});
+ audioContext.onstatechange = function() {
+ harker.emit('state_change', audioContext.state);
+ }
+
+ harker.setThreshold = function(t) {
+ threshold = t;
+ };
+
+ harker.setInterval = function(i) {
+ interval = i;
+ };
+
+ harker.stop = function() {
+ running = false;
+ harker.emit('volume_change', -100, threshold);
+ if (harker.speaking) {
+ harker.speaking = false;
+ harker.emit('stopped_speaking');
+ }
+ analyser.disconnect();
+ sourceNode.disconnect();
+ };
+ harker.speakingHistory = [];
+ for (var i = 0; i < history; i++) {
+ harker.speakingHistory.push(0);
+ }
+
+ // Poll the analyser node to determine if speaking
+ // and emit events if changed
+ var looper = function() {
+ setTimeout(function() {
+
+ //check if stop has been called
+ if(!running) {
+ return;
+ }
+
+ var currentVolume = getMaxVolume(analyser, fftBins);
+
+ harker.emit('volume_change', currentVolume, threshold);
+
+ var history = 0;
+ if (currentVolume > threshold && !harker.speaking) {
+ // trigger quickly, short history
+ for (var i = harker.speakingHistory.length - 3; i < harker.speakingHistory.length; i++) {
+ history += harker.speakingHistory[i];
+ }
+ if (history >= 2) {
+ harker.speaking = true;
+ harker.emit('speaking');
+ }
+ } else if (currentVolume < threshold && harker.speaking) {
+ for (var i = 0; i < harker.speakingHistory.length; i++) {
+ history += harker.speakingHistory[i];
+ }
+ if (history == 0) {
+ harker.speaking = false;
+ harker.emit('stopped_speaking');
+ }
+ }
+ harker.speakingHistory.shift();
+ harker.speakingHistory.push(0 + (currentVolume > threshold));
+
+ looper();
+ }, interval);
+ };
+ looper();
+
+
+ return harker;
+}
+
+},{"wildemitter":14}],6:[function(require,module,exports){
+if (typeof Object.create === 'function') {
+ // implementation from standard node.js 'util' module
+ module.exports = function inherits(ctor, superCtor) {
+ ctor.super_ = superCtor
+ ctor.prototype = Object.create(superCtor.prototype, {
+ constructor: {
+ value: ctor,
+ enumerable: false,
+ writable: true,
+ configurable: true
+ }
+ });
+ };
+} else {
+ // old school shim for old browsers
+ module.exports = function inherits(ctor, superCtor) {
+ ctor.super_ = superCtor
+ var TempCtor = function () {}
+ TempCtor.prototype = superCtor.prototype
+ ctor.prototype = new TempCtor()
+ ctor.prototype.constructor = ctor
+ }
+}
+
+},{}],7:[function(require,module,exports){
+/**
+ # normalice
+
+ Normalize an ice server configuration object (or plain old string) into a format
+ that is usable in all browsers supporting WebRTC. Primarily this module is designed
+ to help with the transition of the `url` attribute of the configuration object to
+ the `urls` attribute.
+
+ ## Example Usage
+
+ <<< examples/simple.js
+
+**/
+
+var protocols = [
+ 'stun:',
+ 'turn:'
+];
+
+module.exports = function(input) {
+ var url = (input || {}).url || input;
+ var protocol;
+ var parts;
+ var output = {};
+
+ // if we don't have a string url, then allow the input to passthrough
+ if (typeof url != 'string' && (! (url instanceof String))) {
+ return input;
+ }
+
+ // trim the url string, and convert to an array
+ url = url.trim();
+
+ // if the protocol is not known, then passthrough
+ protocol = protocols[protocols.indexOf(url.slice(0, 5))];
+ if (! protocol) {
+ return input;
+ }
+
+ // now let's attack the remaining url parts
+ url = url.slice(5);
+ parts = url.split('@');
+
+ output.username = input.username;
+ output.credential = input.credential;
+ // if we have an authentication part, then set the credentials
+ if (parts.length > 1) {
+ url = parts[1];
+ parts = parts[0].split(':');
+
+ // add the output credential and username
+ output.username = parts[0];
+ output.credential = (input || {}).credential || parts[1] || '';
+ }
+
+ output.url = protocol + url;
+ output.urls = [ output.url ];
+
+ return output;
+};
+
+},{}],8:[function(require,module,exports){
+(function (global){
+/*!
+ * Platform.js
+ * Copyright 2014-2018 Benjamin Tan
+ * Copyright 2011-2013 John-David Dalton
+ * Available under MIT license
+ */
+;(function() {
+ 'use strict';
+
+ /** Used to determine if values are of the language type `Object`. */
+ var objectTypes = {
+ 'function': true,
+ 'object': true
+ };
+
+ /** Used as a reference to the global object. */
+ var root = (objectTypes[typeof window] && window) || this;
+
+ /** Backup possible global object. */
+ var oldRoot = root;
+
+ /** Detect free variable `exports`. */
+ var freeExports = objectTypes[typeof exports] && exports;
+
+ /** Detect free variable `module`. */
+ var freeModule = objectTypes[typeof module] && module && !module.nodeType && module;
+
+ /** Detect free variable `global` from Node.js or Browserified code and use it as `root`. */
+ var freeGlobal = freeExports && freeModule && typeof global == 'object' && global;
+ if (freeGlobal && (freeGlobal.global === freeGlobal || freeGlobal.window === freeGlobal || freeGlobal.self === freeGlobal)) {
+ root = freeGlobal;
+ }
+
+ /**
+ * Used as the maximum length of an array-like object.
+ * See the [ES6 spec](http://people.mozilla.org/~jorendorff/es6-draft.html#sec-tolength)
+ * for more details.
+ */
+ var maxSafeInteger = Math.pow(2, 53) - 1;
+
+ /** Regular expression to detect Opera. */
+ var reOpera = /\bOpera/;
+
+ /** Possible global object. */
+ var thisBinding = this;
+
+ /** Used for native method references. */
+ var objectProto = Object.prototype;
+
+ /** Used to check for own properties of an object. */
+ var hasOwnProperty = objectProto.hasOwnProperty;
+
+ /** Used to resolve the internal `[[Class]]` of values. */
+ var toString = objectProto.toString;
+
+ /*--------------------------------------------------------------------------*/
+
+ /**
+ * Capitalizes a string value.
+ *
+ * @private
+ * @param {string} string The string to capitalize.
+ * @returns {string} The capitalized string.
+ */
+ function capitalize(string) {
+ string = String(string);
+ return string.charAt(0).toUpperCase() + string.slice(1);
+ }
+
+ /**
+ * A utility function to clean up the OS name.
+ *
+ * @private
+ * @param {string} os The OS name to clean up.
+ * @param {string} [pattern] A `RegExp` pattern matching the OS name.
+ * @param {string} [label] A label for the OS.
+ */
+ function cleanupOS(os, pattern, label) {
+ // Platform tokens are defined at:
+ // http://msdn.microsoft.com/en-us/library/ms537503(VS.85).aspx
+ // http://web.archive.org/web/20081122053950/http://msdn.microsoft.com/en-us/library/ms537503(VS.85).aspx
+ var data = {
+ '10.0': '10',
+ '6.4': '10 Technical Preview',
+ '6.3': '8.1',
+ '6.2': '8',
+ '6.1': 'Server 2008 R2 / 7',
+ '6.0': 'Server 2008 / Vista',
+ '5.2': 'Server 2003 / XP 64-bit',
+ '5.1': 'XP',
+ '5.01': '2000 SP1',
+ '5.0': '2000',
+ '4.0': 'NT',
+ '4.90': 'ME'
+ };
+ // Detect Windows version from platform tokens.
+ if (pattern && label && /^Win/i.test(os) && !/^Windows Phone /i.test(os) &&
+ (data = data[/[\d.]+$/.exec(os)])) {
+ os = 'Windows ' + data;
+ }
+ // Correct character case and cleanup string.
+ os = String(os);
+
+ if (pattern && label) {
+ os = os.replace(RegExp(pattern, 'i'), label);
+ }
+
+ os = format(
+ os.replace(/ ce$/i, ' CE')
+ .replace(/\bhpw/i, 'web')
+ .replace(/\bMacintosh\b/, 'Mac OS')
+ .replace(/_PowerPC\b/i, ' OS')
+ .replace(/\b(OS X) [^ \d]+/i, '$1')
+ .replace(/\bMac (OS X)\b/, '$1')
+ .replace(/\/(\d)/, ' $1')
+ .replace(/_/g, '.')
+ .replace(/(?: BePC|[ .]*fc[ \d.]+)$/i, '')
+ .replace(/\bx86\.64\b/gi, 'x86_64')
+ .replace(/\b(Windows Phone) OS\b/, '$1')
+ .replace(/\b(Chrome OS \w+) [\d.]+\b/, '$1')
+ .split(' on ')[0]
+ );
+
+ return os;
+ }
+
+ /**
+ * An iteration utility for arrays and objects.
+ *
+ * @private
+ * @param {Array|Object} object The object to iterate over.
+ * @param {Function} callback The function called per iteration.
+ */
+ function each(object, callback) {
+ var index = -1,
+ length = object ? object.length : 0;
+
+ if (typeof length == 'number' && length > -1 && length <= maxSafeInteger) {
+ while (++index < length) {
+ callback(object[index], index, object);
+ }
+ } else {
+ forOwn(object, callback);
+ }
+ }
+
+ /**
+ * Trim and conditionally capitalize string values.
+ *
+ * @private
+ * @param {string} string The string to format.
+ * @returns {string} The formatted string.
+ */
+ function format(string) {
+ string = trim(string);
+ return /^(?:webOS|i(?:OS|P))/.test(string)
+ ? string
+ : capitalize(string);
+ }
+
+ /**
+ * Iterates over an object's own properties, executing the `callback` for each.
+ *
+ * @private
+ * @param {Object} object The object to iterate over.
+ * @param {Function} callback The function executed per own property.
+ */
+ function forOwn(object, callback) {
+ for (var key in object) {
+ if (hasOwnProperty.call(object, key)) {
+ callback(object[key], key, object);
+ }
+ }
+ }
+
+ /**
+ * Gets the internal `[[Class]]` of a value.
+ *
+ * @private
+ * @param {*} value The value.
+ * @returns {string} The `[[Class]]`.
+ */
+ function getClassOf(value) {
+ return value == null
+ ? capitalize(value)
+ : toString.call(value).slice(8, -1);
+ }
+
+ /**
+ * Host objects can return type values that are different from their actual
+ * data type. The objects we are concerned with usually return non-primitive
+ * types of "object", "function", or "unknown".
+ *
+ * @private
+ * @param {*} object The owner of the property.
+ * @param {string} property The property to check.
+ * @returns {boolean} Returns `true` if the property value is a non-primitive, else `false`.
+ */
+ function isHostType(object, property) {
+ var type = object != null ? typeof object[property] : 'number';
+ return !/^(?:boolean|number|string|undefined)$/.test(type) &&
+ (type == 'object' ? !!object[property] : true);
+ }
+
+ /**
+ * Prepares a string for use in a `RegExp` by making hyphens and spaces optional.
+ *
+ * @private
+ * @param {string} string The string to qualify.
+ * @returns {string} The qualified string.
+ */
+ function qualify(string) {
+ return String(string).replace(/([ -])(?!$)/g, '$1?');
+ }
+
+ /**
+ * A bare-bones `Array#reduce` like utility function.
+ *
+ * @private
+ * @param {Array} array The array to iterate over.
+ * @param {Function} callback The function called per iteration.
+ * @returns {*} The accumulated result.
+ */
+ function reduce(array, callback) {
+ var accumulator = null;
+ each(array, function(value, index) {
+ accumulator = callback(accumulator, value, index, array);
+ });
+ return accumulator;
+ }
+
+ /**
+ * Removes leading and trailing whitespace from a string.
+ *
+ * @private
+ * @param {string} string The string to trim.
+ * @returns {string} The trimmed string.
+ */
+ function trim(string) {
+ return String(string).replace(/^ +| +$/g, '');
+ }
+
+ /*--------------------------------------------------------------------------*/
+
+ /**
+ * Creates a new platform object.
+ *
+ * @memberOf platform
+ * @param {Object|string} [ua=navigator.userAgent] The user agent string or
+ * context object.
+ * @returns {Object} A platform object.
+ */
+ function parse(ua) {
+
+ /** The environment context object. */
+ var context = root;
+
+ /** Used to flag when a custom context is provided. */
+ var isCustomContext = ua && typeof ua == 'object' && getClassOf(ua) != 'String';
+
+ // Juggle arguments.
+ if (isCustomContext) {
+ context = ua;
+ ua = null;
+ }
+
+ /** Browser navigator object. */
+ var nav = context.navigator || {};
+
+ /** Browser user agent string. */
+ var userAgent = nav.userAgent || '';
+
+ ua || (ua = userAgent);
+
+ /** Used to flag when `thisBinding` is the [ModuleScope]. */
+ var isModuleScope = isCustomContext || thisBinding == oldRoot;
+
+ /** Used to detect if browser is like Chrome. */
+ var likeChrome = isCustomContext
+ ? !!nav.likeChrome
+ : /\bChrome\b/.test(ua) && !/internal|\n/i.test(toString.toString());
+
+ /** Internal `[[Class]]` value shortcuts. */
+ var objectClass = 'Object',
+ airRuntimeClass = isCustomContext ? objectClass : 'ScriptBridgingProxyObject',
+ enviroClass = isCustomContext ? objectClass : 'Environment',
+ javaClass = (isCustomContext && context.java) ? 'JavaPackage' : getClassOf(context.java),
+ phantomClass = isCustomContext ? objectClass : 'RuntimeObject';
+
+ /** Detect Java environments. */
+ var java = /\bJava/.test(javaClass) && context.java;
+
+ /** Detect Rhino. */
+ var rhino = java && getClassOf(context.environment) == enviroClass;
+
+ /** A character to represent alpha. */
+ var alpha = java ? 'a' : '\u03b1';
+
+ /** A character to represent beta. */
+ var beta = java ? 'b' : '\u03b2';
+
+ /** Browser document object. */
+ var doc = context.document || {};
+
+ /**
+ * Detect Opera browser (Presto-based).
+ * http://www.howtocreate.co.uk/operaStuff/operaObject.html
+ * http://dev.opera.com/articles/view/opera-mini-web-content-authoring-guidelines/#operamini
+ */
+ var opera = context.operamini || context.opera;
+
+ /** Opera `[[Class]]`. */
+ var operaClass = reOpera.test(operaClass = (isCustomContext && opera) ? opera['[[Class]]'] : getClassOf(opera))
+ ? operaClass
+ : (opera = null);
+
+ /*------------------------------------------------------------------------*/
+
+ /** Temporary variable used over the script's lifetime. */
+ var data;
+
+ /** The CPU architecture. */
+ var arch = ua;
+
+ /** Platform description array. */
+ var description = [];
+
+ /** Platform alpha/beta indicator. */
+ var prerelease = null;
+
+ /** A flag to indicate that environment features should be used to resolve the platform. */
+ var useFeatures = ua == userAgent;
+
+ /** The browser/environment version. */
+ var version = useFeatures && opera && typeof opera.version == 'function' && opera.version();
+
+ /** A flag to indicate if the OS ends with "/ Version" */
+ var isSpecialCasedOS;
+
+ /* Detectable layout engines (order is important). */
+ var layout = getLayout([
+ { 'label': 'EdgeHTML', 'pattern': 'Edge' },
+ 'Trident',
+ { 'label': 'WebKit', 'pattern': 'AppleWebKit' },
+ 'iCab',
+ 'Presto',
+ 'NetFront',
+ 'Tasman',
+ 'KHTML',
+ 'Gecko'
+ ]);
+
+ /* Detectable browser names (order is important). */
+ var name = getName([
+ 'Adobe AIR',
+ 'Arora',
+ 'Avant Browser',
+ 'Breach',
+ 'Camino',
+ 'Electron',
+ 'Epiphany',
+ 'Fennec',
+ 'Flock',
+ 'Galeon',
+ 'GreenBrowser',
+ 'iCab',
+ 'Iceweasel',
+ 'K-Meleon',
+ 'Konqueror',
+ 'Lunascape',
+ 'Maxthon',
+ { 'label': 'Microsoft Edge', 'pattern': 'Edge' },
+ 'Midori',
+ 'Nook Browser',
+ 'PaleMoon',
+ 'PhantomJS',
+ 'Raven',
+ 'Rekonq',
+ 'RockMelt',
+ { 'label': 'Samsung Internet', 'pattern': 'SamsungBrowser' },
+ 'SeaMonkey',
+ { 'label': 'Silk', 'pattern': '(?:Cloud9|Silk-Accelerated)' },
+ 'Sleipnir',
+ 'SlimBrowser',
+ { 'label': 'SRWare Iron', 'pattern': 'Iron' },
+ 'Sunrise',
+ 'Swiftfox',
+ 'Waterfox',
+ 'WebPositive',
+ 'Opera Mini',
+ { 'label': 'Opera Mini', 'pattern': 'OPiOS' },
+ 'Opera',
+ { 'label': 'Opera', 'pattern': 'OPR' },
+ 'Chrome',
+ { 'label': 'Chrome Mobile', 'pattern': '(?:CriOS|CrMo)' },
+ { 'label': 'Firefox', 'pattern': '(?:Firefox|Minefield)' },
+ { 'label': 'Firefox for iOS', 'pattern': 'FxiOS' },
+ { 'label': 'IE', 'pattern': 'IEMobile' },
+ { 'label': 'IE', 'pattern': 'MSIE' },
+ 'Safari'
+ ]);
+
+ /* Detectable products (order is important). */
+ var product = getProduct([
+ { 'label': 'BlackBerry', 'pattern': 'BB10' },
+ 'BlackBerry',
+ { 'label': 'Galaxy S', 'pattern': 'GT-I9000' },
+ { 'label': 'Galaxy S2', 'pattern': 'GT-I9100' },
+ { 'label': 'Galaxy S3', 'pattern': 'GT-I9300' },
+ { 'label': 'Galaxy S4', 'pattern': 'GT-I9500' },
+ { 'label': 'Galaxy S5', 'pattern': 'SM-G900' },
+ { 'label': 'Galaxy S6', 'pattern': 'SM-G920' },
+ { 'label': 'Galaxy S6 Edge', 'pattern': 'SM-G925' },
+ { 'label': 'Galaxy S7', 'pattern': 'SM-G930' },
+ { 'label': 'Galaxy S7 Edge', 'pattern': 'SM-G935' },
+ 'Google TV',
+ 'Lumia',
+ 'iPad',
+ 'iPod',
+ 'iPhone',
+ 'Kindle',
+ { 'label': 'Kindle Fire', 'pattern': '(?:Cloud9|Silk-Accelerated)' },
+ 'Nexus',
+ 'Nook',
+ 'PlayBook',
+ 'PlayStation Vita',
+ 'PlayStation',
+ 'TouchPad',
+ 'Transformer',
+ { 'label': 'Wii U', 'pattern': 'WiiU' },
+ 'Wii',
+ 'Xbox One',
+ { 'label': 'Xbox 360', 'pattern': 'Xbox' },
+ 'Xoom'
+ ]);
+
+ /* Detectable manufacturers. */
+ var manufacturer = getManufacturer({
+ 'Apple': { 'iPad': 1, 'iPhone': 1, 'iPod': 1 },
+ 'Archos': {},
+ 'Amazon': { 'Kindle': 1, 'Kindle Fire': 1 },
+ 'Asus': { 'Transformer': 1 },
+ 'Barnes & Noble': { 'Nook': 1 },
+ 'BlackBerry': { 'PlayBook': 1 },
+ 'Google': { 'Google TV': 1, 'Nexus': 1 },
+ 'HP': { 'TouchPad': 1 },
+ 'HTC': {},
+ 'LG': {},
+ 'Microsoft': { 'Xbox': 1, 'Xbox One': 1 },
+ 'Motorola': { 'Xoom': 1 },
+ 'Nintendo': { 'Wii U': 1, 'Wii': 1 },
+ 'Nokia': { 'Lumia': 1 },
+ 'Samsung': { 'Galaxy S': 1, 'Galaxy S2': 1, 'Galaxy S3': 1, 'Galaxy S4': 1 },
+ 'Sony': { 'PlayStation': 1, 'PlayStation Vita': 1 }
+ });
+
+ /* Detectable operating systems (order is important). */
+ var os = getOS([
+ 'Windows Phone',
+ 'Android',
+ 'CentOS',
+ { 'label': 'Chrome OS', 'pattern': 'CrOS' },
+ 'Debian',
+ 'Fedora',
+ 'FreeBSD',
+ 'Gentoo',
+ 'Haiku',
+ 'Kubuntu',
+ 'Linux Mint',
+ 'OpenBSD',
+ 'Red Hat',
+ 'SuSE',
+ 'Ubuntu',
+ 'Xubuntu',
+ 'Cygwin',
+ 'Symbian OS',
+ 'hpwOS',
+ 'webOS ',
+ 'webOS',
+ 'Tablet OS',
+ 'Tizen',
+ 'Linux',
+ 'Mac OS X',
+ 'Macintosh',
+ 'Mac',
+ 'Windows 98;',
+ 'Windows '
+ ]);
+
+ /*------------------------------------------------------------------------*/
+
+ /**
+ * Picks the layout engine from an array of guesses.
+ *
+ * @private
+ * @param {Array} guesses An array of guesses.
+ * @returns {null|string} The detected layout engine.
+ */
+ function getLayout(guesses) {
+ return reduce(guesses, function(result, guess) {
+ return result || RegExp('\\b' + (
+ guess.pattern || qualify(guess)
+ ) + '\\b', 'i').exec(ua) && (guess.label || guess);
+ });
+ }
+
+ /**
+ * Picks the manufacturer from an array of guesses.
+ *
+ * @private
+ * @param {Array} guesses An object of guesses.
+ * @returns {null|string} The detected manufacturer.
+ */
+ function getManufacturer(guesses) {
+ return reduce(guesses, function(result, value, key) {
+ // Lookup the manufacturer by product or scan the UA for the manufacturer.
+ return result || (
+ value[product] ||
+ value[/^[a-z]+(?: +[a-z]+\b)*/i.exec(product)] ||
+ RegExp('\\b' + qualify(key) + '(?:\\b|\\w*\\d)', 'i').exec(ua)
+ ) && key;
+ });
+ }
+
+ /**
+ * Picks the browser name from an array of guesses.
+ *
+ * @private
+ * @param {Array} guesses An array of guesses.
+ * @returns {null|string} The detected browser name.
+ */
+ function getName(guesses) {
+ return reduce(guesses, function(result, guess) {
+ return result || RegExp('\\b' + (
+ guess.pattern || qualify(guess)
+ ) + '\\b', 'i').exec(ua) && (guess.label || guess);
+ });
+ }
+
+ /**
+ * Picks the OS name from an array of guesses.
+ *
+ * @private
+ * @param {Array} guesses An array of guesses.
+ * @returns {null|string} The detected OS name.
+ */
+ function getOS(guesses) {
+ return reduce(guesses, function(result, guess) {
+ var pattern = guess.pattern || qualify(guess);
+ if (!result && (result =
+ RegExp('\\b' + pattern + '(?:/[\\d.]+|[ \\w.]*)', 'i').exec(ua)
+ )) {
+ result = cleanupOS(result, pattern, guess.label || guess);
+ }
+ return result;
+ });
+ }
+
+ /**
+ * Picks the product name from an array of guesses.
+ *
+ * @private
+ * @param {Array} guesses An array of guesses.
+ * @returns {null|string} The detected product name.
+ */
+ function getProduct(guesses) {
+ return reduce(guesses, function(result, guess) {
+ var pattern = guess.pattern || qualify(guess);
+ if (!result && (result =
+ RegExp('\\b' + pattern + ' *\\d+[.\\w_]*', 'i').exec(ua) ||
+ RegExp('\\b' + pattern + ' *\\w+-[\\w]*', 'i').exec(ua) ||
+ RegExp('\\b' + pattern + '(?:; *(?:[a-z]+[_-])?[a-z]+\\d+|[^ ();-]*)', 'i').exec(ua)
+ )) {
+ // Split by forward slash and append product version if needed.
+ if ((result = String((guess.label && !RegExp(pattern, 'i').test(guess.label)) ? guess.label : result).split('/'))[1] && !/[\d.]+/.test(result[0])) {
+ result[0] += ' ' + result[1];
+ }
+ // Correct character case and cleanup string.
+ guess = guess.label || guess;
+ result = format(result[0]
+ .replace(RegExp(pattern, 'i'), guess)
+ .replace(RegExp('; *(?:' + guess + '[_-])?', 'i'), ' ')
+ .replace(RegExp('(' + guess + ')[-_.]?(\\w)', 'i'), '$1 $2'));
+ }
+ return result;
+ });
+ }
+
+ /**
+ * Resolves the version using an array of UA patterns.
+ *
+ * @private
+ * @param {Array} patterns An array of UA patterns.
+ * @returns {null|string} The detected version.
+ */
+ function getVersion(patterns) {
+ return reduce(patterns, function(result, pattern) {
+ return result || (RegExp(pattern +
+ '(?:-[\\d.]+/|(?: for [\\w-]+)?[ /-])([\\d.]+[^ ();/_-]*)', 'i').exec(ua) || 0)[1] || null;
+ });
+ }
+
+ /**
+ * Returns `platform.description` when the platform object is coerced to a string.
+ *
+ * @name toString
+ * @memberOf platform
+ * @returns {string} Returns `platform.description` if available, else an empty string.
+ */
+ function toStringPlatform() {
+ return this.description || '';
+ }
+
+ /*------------------------------------------------------------------------*/
+
+ // Convert layout to an array so we can add extra details.
+ layout && (layout = [layout]);
+
+ // Detect product names that contain their manufacturer's name.
+ if (manufacturer && !product) {
+ product = getProduct([manufacturer]);
+ }
+ // Clean up Google TV.
+ if ((data = /\bGoogle TV\b/.exec(product))) {
+ product = data[0];
+ }
+ // Detect simulators.
+ if (/\bSimulator\b/i.test(ua)) {
+ product = (product ? product + ' ' : '') + 'Simulator';
+ }
+ // Detect Opera Mini 8+ running in Turbo/Uncompressed mode on iOS.
+ if (name == 'Opera Mini' && /\bOPiOS\b/.test(ua)) {
+ description.push('running in Turbo/Uncompressed mode');
+ }
+ // Detect IE Mobile 11.
+ if (name == 'IE' && /\blike iPhone OS\b/.test(ua)) {
+ data = parse(ua.replace(/like iPhone OS/, ''));
+ manufacturer = data.manufacturer;
+ product = data.product;
+ }
+ // Detect iOS.
+ else if (/^iP/.test(product)) {
+ name || (name = 'Safari');
+ os = 'iOS' + ((data = / OS ([\d_]+)/i.exec(ua))
+ ? ' ' + data[1].replace(/_/g, '.')
+ : '');
+ }
+ // Detect Kubuntu.
+ else if (name == 'Konqueror' && !/buntu/i.test(os)) {
+ os = 'Kubuntu';
+ }
+ // Detect Android browsers.
+ else if ((manufacturer && manufacturer != 'Google' &&
+ ((/Chrome/.test(name) && !/\bMobile Safari\b/i.test(ua)) || /\bVita\b/.test(product))) ||
+ (/\bAndroid\b/.test(os) && /^Chrome/.test(name) && /\bVersion\//i.test(ua))) {
+ name = 'Android Browser';
+ os = /\bAndroid\b/.test(os) ? os : 'Android';
+ }
+ // Detect Silk desktop/accelerated modes.
+ else if (name == 'Silk') {
+ if (!/\bMobi/i.test(ua)) {
+ os = 'Android';
+ description.unshift('desktop mode');
+ }
+ if (/Accelerated *= *true/i.test(ua)) {
+ description.unshift('accelerated');
+ }
+ }
+ // Detect PaleMoon identifying as Firefox.
+ else if (name == 'PaleMoon' && (data = /\bFirefox\/([\d.]+)\b/.exec(ua))) {
+ description.push('identifying as Firefox ' + data[1]);
+ }
+ // Detect Firefox OS and products running Firefox.
+ else if (name == 'Firefox' && (data = /\b(Mobile|Tablet|TV)\b/i.exec(ua))) {
+ os || (os = 'Firefox OS');
+ product || (product = data[1]);
+ }
+ // Detect false positives for Firefox/Safari.
+ else if (!name || (data = !/\bMinefield\b/i.test(ua) && /\b(?:Firefox|Safari)\b/.exec(name))) {
+ // Escape the `/` for Firefox 1.
+ if (name && !product && /[\/,]|^[^(]+?\)/.test(ua.slice(ua.indexOf(data + '/') + 8))) {
+ // Clear name of false positives.
+ name = null;
+ }
+ // Reassign a generic name.
+ if ((data = product || manufacturer || os) &&
+ (product || manufacturer || /\b(?:Android|Symbian OS|Tablet OS|webOS)\b/.test(os))) {
+ name = /[a-z]+(?: Hat)?/i.exec(/\bAndroid\b/.test(os) ? os : data) + ' Browser';
+ }
+ }
+ // Add Chrome version to description for Electron.
+ else if (name == 'Electron' && (data = (/\bChrome\/([\d.]+)\b/.exec(ua) || 0)[1])) {
+ description.push('Chromium ' + data);
+ }
+ // Detect non-Opera (Presto-based) versions (order is important).
+ if (!version) {
+ version = getVersion([
+ '(?:Cloud9|CriOS|CrMo|Edge|FxiOS|IEMobile|Iron|Opera ?Mini|OPiOS|OPR|Raven|SamsungBrowser|Silk(?!/[\\d.]+$))',
+ 'Version',
+ qualify(name),
+ '(?:Firefox|Minefield|NetFront)'
+ ]);
+ }
+ // Detect stubborn layout engines.
+ if ((data =
+ layout == 'iCab' && parseFloat(version) > 3 && 'WebKit' ||
+ /\bOpera\b/.test(name) && (/\bOPR\b/.test(ua) ? 'Blink' : 'Presto') ||
+ /\b(?:Midori|Nook|Safari)\b/i.test(ua) && !/^(?:Trident|EdgeHTML)$/.test(layout) && 'WebKit' ||
+ !layout && /\bMSIE\b/i.test(ua) && (os == 'Mac OS' ? 'Tasman' : 'Trident') ||
+ layout == 'WebKit' && /\bPlayStation\b(?! Vita\b)/i.test(name) && 'NetFront'
+ )) {
+ layout = [data];
+ }
+ // Detect Windows Phone 7 desktop mode.
+ if (name == 'IE' && (data = (/; *(?:XBLWP|ZuneWP)(\d+)/i.exec(ua) || 0)[1])) {
+ name += ' Mobile';
+ os = 'Windows Phone ' + (/\+$/.test(data) ? data : data + '.x');
+ description.unshift('desktop mode');
+ }
+ // Detect Windows Phone 8.x desktop mode.
+ else if (/\bWPDesktop\b/i.test(ua)) {
+ name = 'IE Mobile';
+ os = 'Windows Phone 8.x';
+ description.unshift('desktop mode');
+ version || (version = (/\brv:([\d.]+)/.exec(ua) || 0)[1]);
+ }
+ // Detect IE 11 identifying as other browsers.
+ else if (name != 'IE' && layout == 'Trident' && (data = /\brv:([\d.]+)/.exec(ua))) {
+ if (name) {
+ description.push('identifying as ' + name + (version ? ' ' + version : ''));
+ }
+ name = 'IE';
+ version = data[1];
+ }
+ // Leverage environment features.
+ if (useFeatures) {
+ // Detect server-side environments.
+ // Rhino has a global function while others have a global object.
+ if (isHostType(context, 'global')) {
+ if (java) {
+ data = java.lang.System;
+ arch = data.getProperty('os.arch');
+ os = os || data.getProperty('os.name') + ' ' + data.getProperty('os.version');
+ }
+ if (rhino) {
+ try {
+ version = context.require('ringo/engine').version.join('.');
+ name = 'RingoJS';
+ } catch(e) {
+ if ((data = context.system) && data.global.system == context.system) {
+ name = 'Narwhal';
+ os || (os = data[0].os || null);
+ }
+ }
+ if (!name) {
+ name = 'Rhino';
+ }
+ }
+ else if (
+ typeof context.process == 'object' && !context.process.browser &&
+ (data = context.process)
+ ) {
+ if (typeof data.versions == 'object') {
+ if (typeof data.versions.electron == 'string') {
+ description.push('Node ' + data.versions.node);
+ name = 'Electron';
+ version = data.versions.electron;
+ } else if (typeof data.versions.nw == 'string') {
+ description.push('Chromium ' + version, 'Node ' + data.versions.node);
+ name = 'NW.js';
+ version = data.versions.nw;
+ }
+ }
+ if (!name) {
+ name = 'Node.js';
+ arch = data.arch;
+ os = data.platform;
+ version = /[\d.]+/.exec(data.version);
+ version = version ? version[0] : null;
+ }
+ }
+ }
+ // Detect Adobe AIR.
+ else if (getClassOf((data = context.runtime)) == airRuntimeClass) {
+ name = 'Adobe AIR';
+ os = data.flash.system.Capabilities.os;
+ }
+ // Detect PhantomJS.
+ else if (getClassOf((data = context.phantom)) == phantomClass) {
+ name = 'PhantomJS';
+ version = (data = data.version || null) && (data.major + '.' + data.minor + '.' + data.patch);
+ }
+ // Detect IE compatibility modes.
+ else if (typeof doc.documentMode == 'number' && (data = /\bTrident\/(\d+)/i.exec(ua))) {
+ // We're in compatibility mode when the Trident version + 4 doesn't
+ // equal the document mode.
+ version = [version, doc.documentMode];
+ if ((data = +data[1] + 4) != version[1]) {
+ description.push('IE ' + version[1] + ' mode');
+ layout && (layout[1] = '');
+ version[1] = data;
+ }
+ version = name == 'IE' ? String(version[1].toFixed(1)) : version[0];
+ }
+ // Detect IE 11 masking as other browsers.
+ else if (typeof doc.documentMode == 'number' && /^(?:Chrome|Firefox)\b/.test(name)) {
+ description.push('masking as ' + name + ' ' + version);
+ name = 'IE';
+ version = '11.0';
+ layout = ['Trident'];
+ os = 'Windows';
+ }
+ os = os && format(os);
+ }
+ // Detect prerelease phases.
+ if (version && (data =
+ /(?:[ab]|dp|pre|[ab]\d+pre)(?:\d+\+?)?$/i.exec(version) ||
+ /(?:alpha|beta)(?: ?\d)?/i.exec(ua + ';' + (useFeatures && nav.appMinorVersion)) ||
+ /\bMinefield\b/i.test(ua) && 'a'
+ )) {
+ prerelease = /b/i.test(data) ? 'beta' : 'alpha';
+ version = version.replace(RegExp(data + '\\+?$'), '') +
+ (prerelease == 'beta' ? beta : alpha) + (/\d+\+?/.exec(data) || '');
+ }
+ // Detect Firefox Mobile.
+ if (name == 'Fennec' || name == 'Firefox' && /\b(?:Android|Firefox OS)\b/.test(os)) {
+ name = 'Firefox Mobile';
+ }
+ // Obscure Maxthon's unreliable version.
+ else if (name == 'Maxthon' && version) {
+ version = version.replace(/\.[\d.]+/, '.x');
+ }
+ // Detect Xbox 360 and Xbox One.
+ else if (/\bXbox\b/i.test(product)) {
+ if (product == 'Xbox 360') {
+ os = null;
+ }
+ if (product == 'Xbox 360' && /\bIEMobile\b/.test(ua)) {
+ description.unshift('mobile mode');
+ }
+ }
+ // Add mobile postfix.
+ else if ((/^(?:Chrome|IE|Opera)$/.test(name) || name && !product && !/Browser|Mobi/.test(name)) &&
+ (os == 'Windows CE' || /Mobi/i.test(ua))) {
+ name += ' Mobile';
+ }
+ // Detect IE platform preview.
+ else if (name == 'IE' && useFeatures) {
+ try {
+ if (context.external === null) {
+ description.unshift('platform preview');
+ }
+ } catch(e) {
+ description.unshift('embedded');
+ }
+ }
+ // Detect BlackBerry OS version.
+ // http://docs.blackberry.com/en/developers/deliverables/18169/HTTP_headers_sent_by_BB_Browser_1234911_11.jsp
+ else if ((/\bBlackBerry\b/.test(product) || /\bBB10\b/.test(ua)) && (data =
+ (RegExp(product.replace(/ +/g, ' *') + '/([.\\d]+)', 'i').exec(ua) || 0)[1] ||
+ version
+ )) {
+ data = [data, /BB10/.test(ua)];
+ os = (data[1] ? (product = null, manufacturer = 'BlackBerry') : 'Device Software') + ' ' + data[0];
+ version = null;
+ }
+ // Detect Opera identifying/masking itself as another browser.
+ // http://www.opera.com/support/kb/view/843/
+ else if (this != forOwn && product != 'Wii' && (
+ (useFeatures && opera) ||
+ (/Opera/.test(name) && /\b(?:MSIE|Firefox)\b/i.test(ua)) ||
+ (name == 'Firefox' && /\bOS X (?:\d+\.){2,}/.test(os)) ||
+ (name == 'IE' && (
+ (os && !/^Win/.test(os) && version > 5.5) ||
+ /\bWindows XP\b/.test(os) && version > 8 ||
+ version == 8 && !/\bTrident\b/.test(ua)
+ ))
+ ) && !reOpera.test((data = parse.call(forOwn, ua.replace(reOpera, '') + ';'))) && data.name) {
+ // When "identifying", the UA contains both Opera and the other browser's name.
+ data = 'ing as ' + data.name + ((data = data.version) ? ' ' + data : '');
+ if (reOpera.test(name)) {
+ if (/\bIE\b/.test(data) && os == 'Mac OS') {
+ os = null;
+ }
+ data = 'identify' + data;
+ }
+ // When "masking", the UA contains only the other browser's name.
+ else {
+ data = 'mask' + data;
+ if (operaClass) {
+ name = format(operaClass.replace(/([a-z])([A-Z])/g, '$1 $2'));
+ } else {
+ name = 'Opera';
+ }
+ if (/\bIE\b/.test(data)) {
+ os = null;
+ }
+ if (!useFeatures) {
+ version = null;
+ }
+ }
+ layout = ['Presto'];
+ description.push(data);
+ }
+ // Detect WebKit Nightly and approximate Chrome/Safari versions.
+ if ((data = (/\bAppleWebKit\/([\d.]+\+?)/i.exec(ua) || 0)[1])) {
+ // Correct build number for numeric comparison.
+ // (e.g. "532.5" becomes "532.05")
+ data = [parseFloat(data.replace(/\.(\d)$/, '.0$1')), data];
+ // Nightly builds are postfixed with a "+".
+ if (name == 'Safari' && data[1].slice(-1) == '+') {
+ name = 'WebKit Nightly';
+ prerelease = 'alpha';
+ version = data[1].slice(0, -1);
+ }
+ // Clear incorrect browser versions.
+ else if (version == data[1] ||
+ version == (data[2] = (/\bSafari\/([\d.]+\+?)/i.exec(ua) || 0)[1])) {
+ version = null;
+ }
+ // Use the full Chrome version when available.
+ data[1] = (/\bChrome\/([\d.]+)/i.exec(ua) || 0)[1];
+ // Detect Blink layout engine.
+ if (data[0] == 537.36 && data[2] == 537.36 && parseFloat(data[1]) >= 28 && layout == 'WebKit') {
+ layout = ['Blink'];
+ }
+ // Detect JavaScriptCore.
+ // http://stackoverflow.com/questions/6768474/how-can-i-detect-which-javascript-engine-v8-or-jsc-is-used-at-runtime-in-androi
+ if (!useFeatures || (!likeChrome && !data[1])) {
+ layout && (layout[1] = 'like Safari');
+ data = (data = data[0], data < 400 ? 1 : data < 500 ? 2 : data < 526 ? 3 : data < 533 ? 4 : data < 534 ? '4+' : data < 535 ? 5 : data < 537 ? 6 : data < 538 ? 7 : data < 601 ? 8 : '8');
+ } else {
+ layout && (layout[1] = 'like Chrome');
+ data = data[1] || (data = data[0], data < 530 ? 1 : data < 532 ? 2 : data < 532.05 ? 3 : data < 533 ? 4 : data < 534.03 ? 5 : data < 534.07 ? 6 : data < 534.10 ? 7 : data < 534.13 ? 8 : data < 534.16 ? 9 : data < 534.24 ? 10 : data < 534.30 ? 11 : data < 535.01 ? 12 : data < 535.02 ? '13+' : data < 535.07 ? 15 : data < 535.11 ? 16 : data < 535.19 ? 17 : data < 536.05 ? 18 : data < 536.10 ? 19 : data < 537.01 ? 20 : data < 537.11 ? '21+' : data < 537.13 ? 23 : data < 537.18 ? 24 : data < 537.24 ? 25 : data < 537.36 ? 26 : layout != 'Blink' ? '27' : '28');
+ }
+ // Add the postfix of ".x" or "+" for approximate versions.
+ layout && (layout[1] += ' ' + (data += typeof data == 'number' ? '.x' : /[.+]/.test(data) ? '' : '+'));
+ // Obscure version for some Safari 1-2 releases.
+ if (name == 'Safari' && (!version || parseInt(version) > 45)) {
+ version = data;
+ }
+ }
+ // Detect Opera desktop modes.
+ if (name == 'Opera' && (data = /\bzbov|zvav$/.exec(os))) {
+ name += ' ';
+ description.unshift('desktop mode');
+ if (data == 'zvav') {
+ name += 'Mini';
+ version = null;
+ } else {
+ name += 'Mobile';
+ }
+ os = os.replace(RegExp(' *' + data + '$'), '');
+ }
+ // Detect Chrome desktop mode.
+ else if (name == 'Safari' && /\bChrome\b/.exec(layout && layout[1])) {
+ description.unshift('desktop mode');
+ name = 'Chrome Mobile';
+ version = null;
+
+ if (/\bOS X\b/.test(os)) {
+ manufacturer = 'Apple';
+ os = 'iOS 4.3+';
+ } else {
+ os = null;
+ }
+ }
+ // Strip incorrect OS versions.
+ if (version && version.indexOf((data = /[\d.]+$/.exec(os))) == 0 &&
+ ua.indexOf('/' + data + '-') > -1) {
+ os = trim(os.replace(data, ''));
+ }
+ // Add layout engine.
+ if (layout && !/\b(?:Avant|Nook)\b/.test(name) && (
+ /Browser|Lunascape|Maxthon/.test(name) ||
+ name != 'Safari' && /^iOS/.test(os) && /\bSafari\b/.test(layout[1]) ||
+ /^(?:Adobe|Arora|Breach|Midori|Opera|Phantom|Rekonq|Rock|Samsung Internet|Sleipnir|Web)/.test(name) && layout[1])) {
+ // Don't add layout details to description if they are falsey.
+ (data = layout[layout.length - 1]) && description.push(data);
+ }
+ // Combine contextual information.
+ if (description.length) {
+ description = ['(' + description.join('; ') + ')'];
+ }
+ // Append manufacturer to description.
+ if (manufacturer && product && product.indexOf(manufacturer) < 0) {
+ description.push('on ' + manufacturer);
+ }
+ // Append product to description.
+ if (product) {
+ description.push((/^on /.test(description[description.length - 1]) ? '' : 'on ') + product);
+ }
+ // Parse the OS into an object.
+ if (os) {
+ data = / ([\d.+]+)$/.exec(os);
+ isSpecialCasedOS = data && os.charAt(os.length - data[0].length - 1) == '/';
+ os = {
+ 'architecture': 32,
+ 'family': (data && !isSpecialCasedOS) ? os.replace(data[0], '') : os,
+ 'version': data ? data[1] : null,
+ 'toString': function() {
+ var version = this.version;
+ return this.family + ((version && !isSpecialCasedOS) ? ' ' + version : '') + (this.architecture == 64 ? ' 64-bit' : '');
+ }
+ };
+ }
+ // Add browser/OS architecture.
+ if ((data = /\b(?:AMD|IA|Win|WOW|x86_|x)64\b/i.exec(arch)) && !/\bi686\b/i.test(arch)) {
+ if (os) {
+ os.architecture = 64;
+ os.family = os.family.replace(RegExp(' *' + data), '');
+ }
+ if (
+ name && (/\bWOW64\b/i.test(ua) ||
+ (useFeatures && /\w(?:86|32)$/.test(nav.cpuClass || nav.platform) && !/\bWin64; x64\b/i.test(ua)))
+ ) {
+ description.unshift('32-bit');
+ }
+ }
+ // Chrome 39 and above on OS X is always 64-bit.
+ else if (
+ os && /^OS X/.test(os.family) &&
+ name == 'Chrome' && parseFloat(version) >= 39
+ ) {
+ os.architecture = 64;
+ }
+
+ ua || (ua = null);
+
+ /*------------------------------------------------------------------------*/
+
+ /**
+ * The platform object.
+ *
+ * @name platform
+ * @type Object
+ */
+ var platform = {};
+
+ /**
+ * The platform description.
+ *
+ * @memberOf platform
+ * @type string|null
+ */
+ platform.description = ua;
+
+ /**
+ * The name of the browser's layout engine.
+ *
+ * The list of common layout engines include:
+ * "Blink", "EdgeHTML", "Gecko", "Trident" and "WebKit"
+ *
+ * @memberOf platform
+ * @type string|null
+ */
+ platform.layout = layout && layout[0];
+
+ /**
+ * The name of the product's manufacturer.
+ *
+ * The list of manufacturers include:
+ * "Apple", "Archos", "Amazon", "Asus", "Barnes & Noble", "BlackBerry",
+ * "Google", "HP", "HTC", "LG", "Microsoft", "Motorola", "Nintendo",
+ * "Nokia", "Samsung" and "Sony"
+ *
+ * @memberOf platform
+ * @type string|null
+ */
+ platform.manufacturer = manufacturer;
+
+ /**
+ * The name of the browser/environment.
+ *
+ * The list of common browser names include:
+ * "Chrome", "Electron", "Firefox", "Firefox for iOS", "IE",
+ * "Microsoft Edge", "PhantomJS", "Safari", "SeaMonkey", "Silk",
+ * "Opera Mini" and "Opera"
+ *
+ * Mobile versions of some browsers have "Mobile" appended to their name:
+ * eg. "Chrome Mobile", "Firefox Mobile", "IE Mobile" and "Opera Mobile"
+ *
+ * @memberOf platform
+ * @type string|null
+ */
+ platform.name = name;
+
+ /**
+ * The alpha/beta release indicator.
+ *
+ * @memberOf platform
+ * @type string|null
+ */
+ platform.prerelease = prerelease;
+
+ /**
+ * The name of the product hosting the browser.
+ *
+ * The list of common products include:
+ *
+ * "BlackBerry", "Galaxy S4", "Lumia", "iPad", "iPod", "iPhone", "Kindle",
+ * "Kindle Fire", "Nexus", "Nook", "PlayBook", "TouchPad" and "Transformer"
+ *
+ * @memberOf platform
+ * @type string|null
+ */
+ platform.product = product;
+
+ /**
+ * The browser's user agent string.
+ *
+ * @memberOf platform
+ * @type string|null
+ */
+ platform.ua = ua;
+
+ /**
+ * The browser/environment version.
+ *
+ * @memberOf platform
+ * @type string|null
+ */
+ platform.version = name && version;
+
+ /**
+ * The name of the operating system.
+ *
+ * @memberOf platform
+ * @type Object
+ */
+ platform.os = os || {
+
+ /**
+ * The CPU architecture the OS is built for.
+ *
+ * @memberOf platform.os
+ * @type number|null
+ */
+ 'architecture': null,
+
+ /**
+ * The family of the OS.
+ *
+ * Common values include:
+ * "Windows", "Windows Server 2008 R2 / 7", "Windows Server 2008 / Vista",
+ * "Windows XP", "OS X", "Ubuntu", "Debian", "Fedora", "Red Hat", "SuSE",
+ * "Android", "iOS" and "Windows Phone"
+ *
+ * @memberOf platform.os
+ * @type string|null
+ */
+ 'family': null,
+
+ /**
+ * The version of the OS.
+ *
+ * @memberOf platform.os
+ * @type string|null
+ */
+ 'version': null,
+
+ /**
+ * Returns the OS string.
+ *
+ * @memberOf platform.os
+ * @returns {string} The OS string.
+ */
+ 'toString': function() { return 'null'; }
+ };
+
+ platform.parse = parse;
+ platform.toString = toStringPlatform;
+
+ if (platform.version) {
+ description.unshift(version);
+ }
+ if (platform.name) {
+ description.unshift(name);
+ }
+ if (os && name && !(os == String(os).split(' ')[0] && (os == name.split(' ')[0] || product))) {
+ description.push(product ? '(' + os + ')' : 'on ' + os);
+ }
+ if (description.length) {
+ platform.description = description.join(' ');
+ }
+ return platform;
+ }
+
+ /*--------------------------------------------------------------------------*/
+
+ // Export platform.
+ var platform = parse();
+
+ // Some AMD build optimizers, like r.js, check for condition patterns like the following:
+ if (typeof define == 'function' && typeof define.amd == 'object' && define.amd) {
+ // Expose platform on the global object to prevent errors when platform is
+ // loaded by a script tag in the presence of an AMD loader.
+ // See http://requirejs.org/docs/errors.html#mismatch for more details.
+ root.platform = platform;
+
+ // Define as an anonymous module so platform can be aliased through path mapping.
+ define(function() {
+ return platform;
+ });
+ }
+ // Check for `exports` after `define` in case a build optimizer adds an `exports` object.
+ else if (freeExports && freeModule) {
+ // Export for CommonJS support.
+ forOwn(platform, function(value, key) {
+ freeExports[key] = value;
+ });
+ }
+ else {
+ // Export to the global object.
+ root.platform = platform;
+ }
+}.call(this));
+
+}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
+
+},{}],9:[function(require,module,exports){
+var v1 = require('./v1');
+var v4 = require('./v4');
+
+var uuid = v4;
+uuid.v1 = v1;
+uuid.v4 = v4;
+
+module.exports = uuid;
+
+},{"./v1":12,"./v4":13}],10:[function(require,module,exports){
+/**
+ * Convert array of 16 byte values to UUID string format of the form:
+ * XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
+ */
+var byteToHex = [];
+for (var i = 0; i < 256; ++i) {
+ byteToHex[i] = (i + 0x100).toString(16).substr(1);
+}
+
+function bytesToUuid(buf, offset) {
+ var i = offset || 0;
+ var bth = byteToHex;
+ // join used to fix memory issue caused by concatenation: https://bugs.chromium.org/p/v8/issues/detail?id=3175#c4
+ return ([bth[buf[i++]], bth[buf[i++]],
+ bth[buf[i++]], bth[buf[i++]], '-',
+ bth[buf[i++]], bth[buf[i++]], '-',
+ bth[buf[i++]], bth[buf[i++]], '-',
+ bth[buf[i++]], bth[buf[i++]], '-',
+ bth[buf[i++]], bth[buf[i++]],
+ bth[buf[i++]], bth[buf[i++]],
+ bth[buf[i++]], bth[buf[i++]]]).join('');
+}
+
+module.exports = bytesToUuid;
+
+},{}],11:[function(require,module,exports){
+// Unique ID creation requires a high quality random # generator. In the
+// browser this is a little complicated due to unknown quality of Math.random()
+// and inconsistent support for the `crypto` API. We do the best we can via
+// feature-detection
+
+// getRandomValues needs to be invoked in a context where "this" is a Crypto
+// implementation. Also, find the complete implementation of crypto on IE11.
+var getRandomValues = (typeof(crypto) != 'undefined' && crypto.getRandomValues && crypto.getRandomValues.bind(crypto)) ||
+ (typeof(msCrypto) != 'undefined' && typeof window.msCrypto.getRandomValues == 'function' && msCrypto.getRandomValues.bind(msCrypto));
+
+if (getRandomValues) {
+ // WHATWG crypto RNG - http://wiki.whatwg.org/wiki/Crypto
+ var rnds8 = new Uint8Array(16); // eslint-disable-line no-undef
+
+ module.exports = function whatwgRNG() {
+ getRandomValues(rnds8);
+ return rnds8;
+ };
+} else {
+ // Math.random()-based (RNG)
+ //
+ // If all else fails, use Math.random(). It's fast, but is of unspecified
+ // quality.
+ var rnds = new Array(16);
+
+ module.exports = function mathRNG() {
+ for (var i = 0, r; i < 16; i++) {
+ if ((i & 0x03) === 0) r = Math.random() * 0x100000000;
+ rnds[i] = r >>> ((i & 0x03) << 3) & 0xff;
+ }
+
+ return rnds;
+ };
+}
+
+},{}],12:[function(require,module,exports){
+var rng = require('./lib/rng');
+var bytesToUuid = require('./lib/bytesToUuid');
+
+// **`v1()` - Generate time-based UUID**
+//
+// Inspired by https://github.com/LiosK/UUID.js
+// and http://docs.python.org/library/uuid.html
+
+var _nodeId;
+var _clockseq;
+
+// Previous uuid creation time
+var _lastMSecs = 0;
+var _lastNSecs = 0;
+
+// See https://github.com/broofa/node-uuid for API details
+function v1(options, buf, offset) {
+ var i = buf && offset || 0;
+ var b = buf || [];
+
+ options = options || {};
+ var node = options.node || _nodeId;
+ var clockseq = options.clockseq !== undefined ? options.clockseq : _clockseq;
+
+ // node and clockseq need to be initialized to random values if they're not
+ // specified. We do this lazily to minimize issues related to insufficient
+ // system entropy. See #189
+ if (node == null || clockseq == null) {
+ var seedBytes = rng();
+ if (node == null) {
+ // Per 4.5, create and 48-bit node id, (47 random bits + multicast bit = 1)
+ node = _nodeId = [
+ seedBytes[0] | 0x01,
+ seedBytes[1], seedBytes[2], seedBytes[3], seedBytes[4], seedBytes[5]
+ ];
+ }
+ if (clockseq == null) {
+ // Per 4.2.2, randomize (14 bit) clockseq
+ clockseq = _clockseq = (seedBytes[6] << 8 | seedBytes[7]) & 0x3fff;
+ }
+ }
+
+ // UUID timestamps are 100 nano-second units since the Gregorian epoch,
+ // (1582-10-15 00:00). JSNumbers aren't precise enough for this, so
+ // time is handled internally as 'msecs' (integer milliseconds) and 'nsecs'
+ // (100-nanoseconds offset from msecs) since unix epoch, 1970-01-01 00:00.
+ var msecs = options.msecs !== undefined ? options.msecs : new Date().getTime();
+
+ // Per 4.2.1.2, use count of uuid's generated during the current clock
+ // cycle to simulate higher resolution clock
+ var nsecs = options.nsecs !== undefined ? options.nsecs : _lastNSecs + 1;
+
+ // Time since last uuid creation (in msecs)
+ var dt = (msecs - _lastMSecs) + (nsecs - _lastNSecs)/10000;
+
+ // Per 4.2.1.2, Bump clockseq on clock regression
+ if (dt < 0 && options.clockseq === undefined) {
+ clockseq = clockseq + 1 & 0x3fff;
+ }
+
+ // Reset nsecs if clock regresses (new clockseq) or we've moved onto a new
+ // time interval
+ if ((dt < 0 || msecs > _lastMSecs) && options.nsecs === undefined) {
+ nsecs = 0;
+ }
+
+ // Per 4.2.1.2 Throw error if too many uuids are requested
+ if (nsecs >= 10000) {
+ throw new Error('uuid.v1(): Can\'t create more than 10M uuids/sec');
+ }
+
+ _lastMSecs = msecs;
+ _lastNSecs = nsecs;
+ _clockseq = clockseq;
+
+ // Per 4.1.4 - Convert from unix epoch to Gregorian epoch
+ msecs += 12219292800000;
+
+ // `time_low`
+ var tl = ((msecs & 0xfffffff) * 10000 + nsecs) % 0x100000000;
+ b[i++] = tl >>> 24 & 0xff;
+ b[i++] = tl >>> 16 & 0xff;
+ b[i++] = tl >>> 8 & 0xff;
+ b[i++] = tl & 0xff;
+
+ // `time_mid`
+ var tmh = (msecs / 0x100000000 * 10000) & 0xfffffff;
+ b[i++] = tmh >>> 8 & 0xff;
+ b[i++] = tmh & 0xff;
+
+ // `time_high_and_version`
+ b[i++] = tmh >>> 24 & 0xf | 0x10; // include version
+ b[i++] = tmh >>> 16 & 0xff;
+
+ // `clock_seq_hi_and_reserved` (Per 4.2.2 - include variant)
+ b[i++] = clockseq >>> 8 | 0x80;
+
+ // `clock_seq_low`
+ b[i++] = clockseq & 0xff;
+
+ // `node`
+ for (var n = 0; n < 6; ++n) {
+ b[i + n] = node[n];
+ }
+
+ return buf ? buf : bytesToUuid(b);
+}
+
+module.exports = v1;
+
+},{"./lib/bytesToUuid":10,"./lib/rng":11}],13:[function(require,module,exports){
+var rng = require('./lib/rng');
+var bytesToUuid = require('./lib/bytesToUuid');
+
+function v4(options, buf, offset) {
+ var i = buf && offset || 0;
+
+ if (typeof(options) == 'string') {
+ buf = options === 'binary' ? new Array(16) : null;
+ options = null;
+ }
+ options = options || {};
+
+ var rnds = options.random || (options.rng || rng)();
+
+ // Per 4.4, set bits for version and `clock_seq_hi_and_reserved`
+ rnds[6] = (rnds[6] & 0x0f) | 0x40;
+ rnds[8] = (rnds[8] & 0x3f) | 0x80;
+
+ // Copy bytes to buffer, if provided
+ if (buf) {
+ for (var ii = 0; ii < 16; ++ii) {
+ buf[i + ii] = rnds[ii];
+ }
+ }
+
+ return buf || bytesToUuid(rnds);
+}
+
+module.exports = v4;
+
+},{"./lib/bytesToUuid":10,"./lib/rng":11}],14:[function(require,module,exports){
+/*
+WildEmitter.js is a slim little event emitter by @henrikjoreteg largely based
+on @visionmedia's Emitter from UI Kit.
+
+Why? I wanted it standalone.
+
+I also wanted support for wildcard emitters like this:
+
+emitter.on('*', function (eventName, other, event, payloads) {
+
+});
+
+emitter.on('somenamespace*', function (eventName, payloads) {
+
+});
+
+Please note that callbacks triggered by wildcard registered events also get
+the event name as the first argument.
+*/
+
+module.exports = WildEmitter;
+
+function WildEmitter() { }
+
+WildEmitter.mixin = function (constructor) {
+ var prototype = constructor.prototype || constructor;
+
+ prototype.isWildEmitter= true;
+
+ // Listen on the given `event` with `fn`. Store a group name if present.
+ prototype.on = function (event, groupName, fn) {
+ this.callbacks = this.callbacks || {};
+ var hasGroup = (arguments.length === 3),
+ group = hasGroup ? arguments[1] : undefined,
+ func = hasGroup ? arguments[2] : arguments[1];
+ func._groupName = group;
+ (this.callbacks[event] = this.callbacks[event] || []).push(func);
+ return this;
+ };
+
+ // Adds an `event` listener that will be invoked a single
+ // time then automatically removed.
+ prototype.once = function (event, groupName, fn) {
+ var self = this,
+ hasGroup = (arguments.length === 3),
+ group = hasGroup ? arguments[1] : undefined,
+ func = hasGroup ? arguments[2] : arguments[1];
+ function on() {
+ self.off(event, on);
+ func.apply(this, arguments);
+ }
+ this.on(event, group, on);
+ return this;
+ };
+
+ // Unbinds an entire group
+ prototype.releaseGroup = function (groupName) {
+ this.callbacks = this.callbacks || {};
+ var item, i, len, handlers;
+ for (item in this.callbacks) {
+ handlers = this.callbacks[item];
+ for (i = 0, len = handlers.length; i < len; i++) {
+ if (handlers[i]._groupName === groupName) {
+ //console.log('removing');
+ // remove it and shorten the array we're looping through
+ handlers.splice(i, 1);
+ i--;
+ len--;
+ }
+ }
+ }
+ return this;
+ };
+
+ // Remove the given callback for `event` or all
+ // registered callbacks.
+ prototype.off = function (event, fn) {
+ this.callbacks = this.callbacks || {};
+ var callbacks = this.callbacks[event],
+ i;
+
+ if (!callbacks) return this;
+
+ // remove all handlers
+ if (arguments.length === 1) {
+ delete this.callbacks[event];
+ return this;
+ }
+
+ // remove specific handler
+ i = callbacks.indexOf(fn);
+ callbacks.splice(i, 1);
+ if (callbacks.length === 0) {
+ delete this.callbacks[event];
+ }
+ return this;
+ };
+
+ /// Emit `event` with the given args.
+ // also calls any `*` handlers
+ prototype.emit = function (event) {
+ this.callbacks = this.callbacks || {};
+ var args = [].slice.call(arguments, 1),
+ callbacks = this.callbacks[event],
+ specialCallbacks = this.getWildcardCallbacks(event),
+ i,
+ len,
+ item,
+ listeners;
+
+ if (callbacks) {
+ listeners = callbacks.slice();
+ for (i = 0, len = listeners.length; i < len; ++i) {
+ if (!listeners[i]) {
+ break;
+ }
+ listeners[i].apply(this, args);
+ }
+ }
+
+ if (specialCallbacks) {
+ len = specialCallbacks.length;
+ listeners = specialCallbacks.slice();
+ for (i = 0, len = listeners.length; i < len; ++i) {
+ if (!listeners[i]) {
+ break;
+ }
+ listeners[i].apply(this, [event].concat(args));
+ }
+ }
+
+ return this;
+ };
+
+ // Helper for for finding special wildcard event handlers that match the event
+ prototype.getWildcardCallbacks = function (eventName) {
+ this.callbacks = this.callbacks || {};
+ var item,
+ split,
+ result = [];
+
+ for (item in this.callbacks) {
+ split = item.split('*');
+ if (item === '*' || (split.length === 2 && eventName.slice(0, split[0].length) === split[0])) {
+ result = result.concat(this.callbacks[item]);
+ }
+ }
+ return result;
+ };
+
+};
+
+WildEmitter.mixin(WildEmitter);
+
+},{}],15:[function(require,module,exports){
+/*!
+ * EventEmitter v5.2.5 - git.io/ee
+ * Unlicense - http://unlicense.org/
+ * Oliver Caldwell - http://oli.me.uk/
+ * @preserve
+ */
+
+;(function (exports) {
+ 'use strict';
+
+ /**
+ * Class for managing events.
+ * Can be extended to provide event functionality in other classes.
+ *
+ * @class EventEmitter Manages event registering and emitting.
+ */
+ function EventEmitter() {}
+
+ // Shortcuts to improve speed and size
+ var proto = EventEmitter.prototype;
+ var originalGlobalValue = exports.EventEmitter;
+
+ /**
+ * Finds the index of the listener for the event in its storage array.
+ *
+ * @param {Function[]} listeners Array of listeners to search through.
+ * @param {Function} listener Method to look for.
+ * @return {Number} Index of the specified listener, -1 if not found
+ * @api private
+ */
+ function indexOfListener(listeners, listener) {
+ var i = listeners.length;
+ while (i--) {
+ if (listeners[i].listener === listener) {
+ return i;
+ }
+ }
+
+ return -1;
+ }
+
+ /**
+ * Alias a method while keeping the context correct, to allow for overwriting of target method.
+ *
+ * @param {String} name The name of the target method.
+ * @return {Function} The aliased method
+ * @api private
+ */
+ function alias(name) {
+ return function aliasClosure() {
+ return this[name].apply(this, arguments);
+ };
+ }
+
+ /**
+ * Returns the listener array for the specified event.
+ * Will initialise the event object and listener arrays if required.
+ * Will return an object if you use a regex search. The object contains keys for each matched event. So /ba[rz]/ might return an object containing bar and baz. But only if you have either defined them with defineEvent or added some listeners to them.
+ * Each property in the object response is an array of listener functions.
+ *
+ * @param {String|RegExp} evt Name of the event to return the listeners from.
+ * @return {Function[]|Object} All listener functions for the event.
+ */
+ proto.getListeners = function getListeners(evt) {
+ var events = this._getEvents();
+ var response;
+ var key;
+
+ // Return a concatenated array of all matching events if
+ // the selector is a regular expression.
+ if (evt instanceof RegExp) {
+ response = {};
+ for (key in events) {
+ if (events.hasOwnProperty(key) && evt.test(key)) {
+ response[key] = events[key];
+ }
+ }
+ }
+ else {
+ response = events[evt] || (events[evt] = []);
+ }
+
+ return response;
+ };
+
+ /**
+ * Takes a list of listener objects and flattens it into a list of listener functions.
+ *
+ * @param {Object[]} listeners Raw listener objects.
+ * @return {Function[]} Just the listener functions.
+ */
+ proto.flattenListeners = function flattenListeners(listeners) {
+ var flatListeners = [];
+ var i;
+
+ for (i = 0; i < listeners.length; i += 1) {
+ flatListeners.push(listeners[i].listener);
+ }
+
+ return flatListeners;
+ };
+
+ /**
+ * Fetches the requested listeners via getListeners but will always return the results inside an object. This is mainly for internal use but others may find it useful.
+ *
+ * @param {String|RegExp} evt Name of the event to return the listeners from.
+ * @return {Object} All listener functions for an event in an object.
+ */
+ proto.getListenersAsObject = function getListenersAsObject(evt) {
+ var listeners = this.getListeners(evt);
+ var response;
+
+ if (listeners instanceof Array) {
+ response = {};
+ response[evt] = listeners;
+ }
+
+ return response || listeners;
+ };
+
+ function isValidListener (listener) {
+ if (typeof listener === 'function' || listener instanceof RegExp) {
+ return true
+ } else if (listener && typeof listener === 'object') {
+ return isValidListener(listener.listener)
+ } else {
+ return false
+ }
+ }
+
+ /**
+ * Adds a listener function to the specified event.
+ * The listener will not be added if it is a duplicate.
+ * If the listener returns true then it will be removed after it is called.
+ * If you pass a regular expression as the event name then the listener will be added to all events that match it.
+ *
+ * @param {String|RegExp} evt Name of the event to attach the listener to.
+ * @param {Function} listener Method to be called when the event is emitted. If the function returns true then it will be removed after calling.
+ * @return {Object} Current instance of EventEmitter for chaining.
+ */
+ proto.addListener = function addListener(evt, listener) {
+ if (!isValidListener(listener)) {
+ throw new TypeError('listener must be a function');
+ }
+
+ var listeners = this.getListenersAsObject(evt);
+ var listenerIsWrapped = typeof listener === 'object';
+ var key;
+
+ for (key in listeners) {
+ if (listeners.hasOwnProperty(key) && indexOfListener(listeners[key], listener) === -1) {
+ listeners[key].push(listenerIsWrapped ? listener : {
+ listener: listener,
+ once: false
+ });
+ }
+ }
+
+ return this;
+ };
+
+ /**
+ * Alias of addListener
+ */
+ proto.on = alias('addListener');
+
+ /**
+ * Semi-alias of addListener. It will add a listener that will be
+ * automatically removed after its first execution.
+ *
+ * @param {String|RegExp} evt Name of the event to attach the listener to.
+ * @param {Function} listener Method to be called when the event is emitted. If the function returns true then it will be removed after calling.
+ * @return {Object} Current instance of EventEmitter for chaining.
+ */
+ proto.addOnceListener = function addOnceListener(evt, listener) {
+ return this.addListener(evt, {
+ listener: listener,
+ once: true
+ });
+ };
+
+ /**
+ * Alias of addOnceListener.
+ */
+ proto.once = alias('addOnceListener');
+
+ /**
+ * Defines an event name. This is required if you want to use a regex to add a listener to multiple events at once. If you don't do this then how do you expect it to know what event to add to? Should it just add to every possible match for a regex? No. That is scary and bad.
+ * You need to tell it what event names should be matched by a regex.
+ *
+ * @param {String} evt Name of the event to create.
+ * @return {Object} Current instance of EventEmitter for chaining.
+ */
+ proto.defineEvent = function defineEvent(evt) {
+ this.getListeners(evt);
+ return this;
+ };
+
+ /**
+ * Uses defineEvent to define multiple events.
+ *
+ * @param {String[]} evts An array of event names to define.
+ * @return {Object} Current instance of EventEmitter for chaining.
+ */
+ proto.defineEvents = function defineEvents(evts) {
+ for (var i = 0; i < evts.length; i += 1) {
+ this.defineEvent(evts[i]);
+ }
+ return this;
+ };
+
+ /**
+ * Removes a listener function from the specified event.
+ * When passed a regular expression as the event name, it will remove the listener from all events that match it.
+ *
+ * @param {String|RegExp} evt Name of the event to remove the listener from.
+ * @param {Function} listener Method to remove from the event.
+ * @return {Object} Current instance of EventEmitter for chaining.
+ */
+ proto.removeListener = function removeListener(evt, listener) {
+ var listeners = this.getListenersAsObject(evt);
+ var index;
+ var key;
+
+ for (key in listeners) {
+ if (listeners.hasOwnProperty(key)) {
+ index = indexOfListener(listeners[key], listener);
+
+ if (index !== -1) {
+ listeners[key].splice(index, 1);
+ }
+ }
+ }
+
+ return this;
+ };
+
+ /**
+ * Alias of removeListener
+ */
+ proto.off = alias('removeListener');
+
+ /**
+ * Adds listeners in bulk using the manipulateListeners method.
+ * If you pass an object as the first argument you can add to multiple events at once. The object should contain key value pairs of events and listeners or listener arrays. You can also pass it an event name and an array of listeners to be added.
+ * You can also pass it a regular expression to add the array of listeners to all events that match it.
+ * Yeah, this function does quite a bit. That's probably a bad thing.
+ *
+ * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to add to multiple events at once.
+ * @param {Function[]} [listeners] An optional array of listener functions to add.
+ * @return {Object} Current instance of EventEmitter for chaining.
+ */
+ proto.addListeners = function addListeners(evt, listeners) {
+ // Pass through to manipulateListeners
+ return this.manipulateListeners(false, evt, listeners);
+ };
+
+ /**
+ * Removes listeners in bulk using the manipulateListeners method.
+ * If you pass an object as the first argument you can remove from multiple events at once. The object should contain key value pairs of events and listeners or listener arrays.
+ * You can also pass it an event name and an array of listeners to be removed.
+ * You can also pass it a regular expression to remove the listeners from all events that match it.
+ *
+ * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to remove from multiple events at once.
+ * @param {Function[]} [listeners] An optional array of listener functions to remove.
+ * @return {Object} Current instance of EventEmitter for chaining.
+ */
+ proto.removeListeners = function removeListeners(evt, listeners) {
+ // Pass through to manipulateListeners
+ return this.manipulateListeners(true, evt, listeners);
+ };
+
+ /**
+ * Edits listeners in bulk. The addListeners and removeListeners methods both use this to do their job. You should really use those instead, this is a little lower level.
+ * The first argument will determine if the listeners are removed (true) or added (false).
+ * If you pass an object as the second argument you can add/remove from multiple events at once. The object should contain key value pairs of events and listeners or listener arrays.
+ * You can also pass it an event name and an array of listeners to be added/removed.
+ * You can also pass it a regular expression to manipulate the listeners of all events that match it.
+ *
+ * @param {Boolean} remove True if you want to remove listeners, false if you want to add.
+ * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to add/remove from multiple events at once.
+ * @param {Function[]} [listeners] An optional array of listener functions to add/remove.
+ * @return {Object} Current instance of EventEmitter for chaining.
+ */
+ proto.manipulateListeners = function manipulateListeners(remove, evt, listeners) {
+ var i;
+ var value;
+ var single = remove ? this.removeListener : this.addListener;
+ var multiple = remove ? this.removeListeners : this.addListeners;
+
+ // If evt is an object then pass each of its properties to this method
+ if (typeof evt === 'object' && !(evt instanceof RegExp)) {
+ for (i in evt) {
+ if (evt.hasOwnProperty(i) && (value = evt[i])) {
+ // Pass the single listener straight through to the singular method
+ if (typeof value === 'function') {
+ single.call(this, i, value);
+ }
+ else {
+ // Otherwise pass back to the multiple function
+ multiple.call(this, i, value);
+ }
+ }
+ }
+ }
+ else {
+ // So evt must be a string
+ // And listeners must be an array of listeners
+ // Loop over it and pass each one to the multiple method
+ i = listeners.length;
+ while (i--) {
+ single.call(this, evt, listeners[i]);
+ }
+ }
+
+ return this;
+ };
+
+ /**
+ * Removes all listeners from a specified event.
+ * If you do not specify an event then all listeners will be removed.
+ * That means every event will be emptied.
+ * You can also pass a regex to remove all events that match it.
+ *
+ * @param {String|RegExp} [evt] Optional name of the event to remove all listeners for. Will remove from every event if not passed.
+ * @return {Object} Current instance of EventEmitter for chaining.
+ */
+ proto.removeEvent = function removeEvent(evt) {
+ var type = typeof evt;
+ var events = this._getEvents();
+ var key;
+
+ // Remove different things depending on the state of evt
+ if (type === 'string') {
+ // Remove all listeners for the specified event
+ delete events[evt];
+ }
+ else if (evt instanceof RegExp) {
+ // Remove all events matching the regex.
+ for (key in events) {
+ if (events.hasOwnProperty(key) && evt.test(key)) {
+ delete events[key];
+ }
+ }
+ }
+ else {
+ // Remove all listeners in all events
+ delete this._events;
+ }
+
+ return this;
+ };
+
+ /**
+ * Alias of removeEvent.
+ *
+ * Added to mirror the node API.
+ */
+ proto.removeAllListeners = alias('removeEvent');
+
+ /**
+ * Emits an event of your choice.
+ * When emitted, every listener attached to that event will be executed.
+ * If you pass the optional argument array then those arguments will be passed to every listener upon execution.
+ * Because it uses `apply`, your array of arguments will be passed as if you wrote them out separately.
+ * So they will not arrive within the array on the other side, they will be separate.
+ * You can also pass a regular expression to emit to all events that match it.
+ *
+ * @param {String|RegExp} evt Name of the event to emit and execute listeners for.
+ * @param {Array} [args] Optional array of arguments to be passed to each listener.
+ * @return {Object} Current instance of EventEmitter for chaining.
+ */
+ proto.emitEvent = function emitEvent(evt, args) {
+ var listenersMap = this.getListenersAsObject(evt);
+ var listeners;
+ var listener;
+ var i;
+ var key;
+ var response;
+
+ for (key in listenersMap) {
+ if (listenersMap.hasOwnProperty(key)) {
+ listeners = listenersMap[key].slice(0);
+
+ for (i = 0; i < listeners.length; i++) {
+ // If the listener returns true then it shall be removed from the event
+ // The function is executed either with a basic call or an apply if there is an args array
+ listener = listeners[i];
+
+ if (listener.once === true) {
+ this.removeListener(evt, listener.listener);
+ }
+
+ response = listener.listener.apply(this, args || []);
+
+ if (response === this._getOnceReturnValue()) {
+ this.removeListener(evt, listener.listener);
+ }
+ }
+ }
+ }
+
+ return this;
+ };
+
+ /**
+ * Alias of emitEvent
+ */
+ proto.trigger = alias('emitEvent');
+
+ /**
+ * Subtly different from emitEvent in that it will pass its arguments on to the listeners, as opposed to taking a single array of arguments to pass on.
+ * As with emitEvent, you can pass a regex in place of the event name to emit to all events that match it.
+ *
+ * @param {String|RegExp} evt Name of the event to emit and execute listeners for.
+ * @param {...*} Optional additional arguments to be passed to each listener.
+ * @return {Object} Current instance of EventEmitter for chaining.
+ */
+ proto.emit = function emit(evt) {
+ var args = Array.prototype.slice.call(arguments, 1);
+ return this.emitEvent(evt, args);
+ };
+
+ /**
+ * Sets the current value to check against when executing listeners. If a
+ * listeners return value matches the one set here then it will be removed
+ * after execution. This value defaults to true.
+ *
+ * @param {*} value The new value to check for when executing listeners.
+ * @return {Object} Current instance of EventEmitter for chaining.
+ */
+ proto.setOnceReturnValue = function setOnceReturnValue(value) {
+ this._onceReturnValue = value;
+ return this;
+ };
+
+ /**
+ * Fetches the current value to check against when executing listeners. If
+ * the listeners return value matches this one then it should be removed
+ * automatically. It will return true by default.
+ *
+ * @return {*|Boolean} The current value to check for or the default, true.
+ * @api private
+ */
+ proto._getOnceReturnValue = function _getOnceReturnValue() {
+ if (this.hasOwnProperty('_onceReturnValue')) {
+ return this._onceReturnValue;
+ }
+ else {
+ return true;
+ }
+ };
+
+ /**
+ * Fetches the events object and creates one if required.
+ *
+ * @return {Object} The events storage object.
+ * @api private
+ */
+ proto._getEvents = function _getEvents() {
+ return this._events || (this._events = {});
+ };
+
+ /**
+ * Reverts the global {@link EventEmitter} to its previous value and returns a reference to this version.
+ *
+ * @return {Function} Non conflicting EventEmitter class.
+ */
+ EventEmitter.noConflict = function noConflict() {
+ exports.EventEmitter = originalGlobalValue;
+ return EventEmitter;
+ };
+
+ // Expose the class either via AMD, CommonJS or the global object
+ if (typeof define === 'function' && define.amd) {
+ define(function () {
+ return EventEmitter;
+ });
+ }
+ else if (typeof module === 'object' && module.exports){
+ module.exports = EventEmitter;
+ }
+ else {
+ exports.EventEmitter = EventEmitter;
+ }
+}(typeof window !== 'undefined' ? window : this || {}));
+
+},{}],16:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+var OpenVidu_1 = require("./OpenVidu/OpenVidu");
+if (window) {
+ window['OpenVidu'] = OpenVidu_1.OpenVidu;
+}
+
+},{"./OpenVidu/OpenVidu":19}],17:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+var Stream_1 = require("./Stream");
+var Connection = (function () {
+ function Connection(session, opts) {
+ this.session = session;
+ this.disposed = false;
+ var msg = "'Connection' created ";
+ if (!!opts) {
+ msg += "(remote) with 'connectionId' [" + opts.id + ']';
+ }
+ else {
+ msg += '(local)';
+ }
+ console.info(msg);
+ this.options = opts;
+ if (!!opts) {
+ this.connectionId = opts.id;
+ if (opts.metadata) {
+ this.data = opts.metadata;
+ }
+ if (opts.streams) {
+ this.initRemoteStreams(opts.streams);
+ }
+ }
+ this.creationTime = new Date().getTime();
+ }
+ Connection.prototype.sendIceCandidate = function (candidate) {
+ console.debug((!!this.stream.outboundStreamOpts ? 'Local' : 'Remote'), 'candidate for', this.connectionId, JSON.stringify(candidate));
+ this.session.openvidu.sendRequest('onIceCandidate', {
+ endpointName: this.connectionId,
+ candidate: candidate.candidate,
+ sdpMid: candidate.sdpMid,
+ sdpMLineIndex: candidate.sdpMLineIndex
+ }, function (error, response) {
+ if (error) {
+ console.error('Error sending ICE candidate: '
+ + JSON.stringify(error));
+ }
+ });
+ };
+ Connection.prototype.initRemoteStreams = function (options) {
+ var _this = this;
+ options.forEach(function (opts) {
+ var streamOptions = {
+ id: opts.id,
+ connection: _this,
+ hasAudio: opts.hasAudio,
+ hasVideo: opts.hasVideo,
+ audioActive: opts.audioActive,
+ videoActive: opts.videoActive,
+ typeOfVideo: opts.typeOfVideo,
+ frameRate: opts.frameRate,
+ videoDimensions: !!opts.videoDimensions ? JSON.parse(opts.videoDimensions) : undefined
+ };
+ var stream = new Stream_1.Stream(_this.session, streamOptions);
+ _this.addStream(stream);
+ });
+ console.info("Remote 'Connection' with 'connectionId' [" + this.connectionId + '] is now configured for receiving Streams with options: ', this.stream.inboundStreamOpts);
+ };
+ Connection.prototype.addStream = function (stream) {
+ stream.connection = this;
+ this.stream = stream;
+ };
+ Connection.prototype.removeStream = function (streamId) {
+ delete this.stream;
+ };
+ Connection.prototype.dispose = function () {
+ if (!!this.stream) {
+ delete this.stream;
+ }
+ this.disposed = true;
+ };
+ return Connection;
+}());
+exports.Connection = Connection;
+
+},{"./Stream":22}],18:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+var LocalRecorderState_1 = require("../OpenViduInternal/Enums/LocalRecorderState");
+var LocalRecorder = (function () {
+ function LocalRecorder(stream) {
+ this.stream = stream;
+ this.chunks = [];
+ this.count = 0;
+ this.connectionId = (!!this.stream.connection) ? this.stream.connection.connectionId : 'default-connection';
+ this.id = this.stream.streamId + '_' + this.connectionId + '_localrecord';
+ this.state = LocalRecorderState_1.LocalRecorderState.READY;
+ }
+ LocalRecorder.prototype.record = function () {
+ var _this = this;
+ return new Promise(function (resolve, reject) {
+ try {
+ if (typeof MediaRecorder === 'undefined') {
+ console.error('MediaRecorder not supported on your browser. See compatibility in https://caniuse.com/#search=MediaRecorder');
+ throw (Error('MediaRecorder not supported on your browser. See compatibility in https://caniuse.com/#search=MediaRecorder'));
+ }
+ if (_this.state !== LocalRecorderState_1.LocalRecorderState.READY) {
+ throw (Error('\'LocalRecord.record()\' needs \'LocalRecord.state\' to be \'READY\' (current value: \'' + _this.state + '\'). Call \'LocalRecorder.clean()\' or init a new LocalRecorder before'));
+ }
+ console.log("Starting local recording of stream '" + _this.stream.streamId + "' of connection '" + _this.connectionId + "'");
+ if (typeof MediaRecorder.isTypeSupported === 'function') {
+ var options = void 0;
+ if (MediaRecorder.isTypeSupported('video/webm;codecs=vp9')) {
+ options = { mimeType: 'video/webm;codecs=vp9' };
+ }
+ else if (MediaRecorder.isTypeSupported('video/webm;codecs=h264')) {
+ options = { mimeType: 'video/webm;codecs=h264' };
+ }
+ else if (MediaRecorder.isTypeSupported('video/webm;codecs=vp8')) {
+ options = { mimeType: 'video/webm;codecs=vp8' };
+ }
+ console.log('Using mimeType ' + options.mimeType);
+ _this.mediaRecorder = new MediaRecorder(_this.stream.getMediaStream(), options);
+ }
+ else {
+ console.warn('isTypeSupported is not supported, using default codecs for browser');
+ _this.mediaRecorder = new MediaRecorder(_this.stream.getMediaStream());
+ }
+ _this.mediaRecorder.start(10);
+ }
+ catch (err) {
+ reject(err);
+ }
+ _this.mediaRecorder.ondataavailable = function (e) {
+ _this.chunks.push(e.data);
+ };
+ _this.mediaRecorder.onerror = function (e) {
+ console.error('MediaRecorder error: ', e);
+ };
+ _this.mediaRecorder.onstart = function () {
+ console.log('MediaRecorder started (state=' + _this.mediaRecorder.state + ')');
+ };
+ _this.mediaRecorder.onstop = function () {
+ _this.onStopDefault();
+ };
+ _this.mediaRecorder.onpause = function () {
+ console.log('MediaRecorder paused (state=' + _this.mediaRecorder.state + ')');
+ };
+ _this.mediaRecorder.onresume = function () {
+ console.log('MediaRecorder resumed (state=' + _this.mediaRecorder.state + ')');
+ };
+ _this.mediaRecorder.onwarning = function (e) {
+ console.log('MediaRecorder warning: ' + e);
+ };
+ _this.state = LocalRecorderState_1.LocalRecorderState.RECORDING;
+ resolve();
+ });
+ };
+ LocalRecorder.prototype.stop = function () {
+ var _this = this;
+ return new Promise(function (resolve, reject) {
+ try {
+ if (_this.state === LocalRecorderState_1.LocalRecorderState.READY || _this.state === LocalRecorderState_1.LocalRecorderState.FINISHED) {
+ throw (Error('\'LocalRecord.stop()\' needs \'LocalRecord.state\' to be \'RECORDING\' or \'PAUSED\' (current value: \'' + _this.state + '\'). Call \'LocalRecorder.start()\' before'));
+ }
+ _this.mediaRecorder.onstop = function () {
+ _this.onStopDefault();
+ resolve();
+ };
+ _this.mediaRecorder.stop();
+ }
+ catch (e) {
+ reject(e);
+ }
+ });
+ };
+ LocalRecorder.prototype.pause = function () {
+ var _this = this;
+ return new Promise(function (resolve, reject) {
+ try {
+ if (_this.state !== LocalRecorderState_1.LocalRecorderState.RECORDING) {
+ reject(Error('\'LocalRecord.pause()\' needs \'LocalRecord.state\' to be \'RECORDING\' (current value: \'' + _this.state + '\'). Call \'LocalRecorder.start()\' or \'LocalRecorder.resume()\' before'));
+ }
+ _this.mediaRecorder.pause();
+ _this.state = LocalRecorderState_1.LocalRecorderState.PAUSED;
+ }
+ catch (error) {
+ reject(error);
+ }
+ });
+ };
+ LocalRecorder.prototype.resume = function () {
+ var _this = this;
+ return new Promise(function (resolve, reject) {
+ try {
+ if (_this.state !== LocalRecorderState_1.LocalRecorderState.PAUSED) {
+ throw (Error('\'LocalRecord.resume()\' needs \'LocalRecord.state\' to be \'PAUSED\' (current value: \'' + _this.state + '\'). Call \'LocalRecorder.pause()\' before'));
+ }
+ _this.mediaRecorder.resume();
+ _this.state = LocalRecorderState_1.LocalRecorderState.RECORDING;
+ }
+ catch (error) {
+ reject(error);
+ }
+ });
+ };
+ LocalRecorder.prototype.preview = function (parentElement) {
+ if (this.state !== LocalRecorderState_1.LocalRecorderState.FINISHED) {
+ throw (Error('\'LocalRecord.preview()\' needs \'LocalRecord.state\' to be \'FINISHED\' (current value: \'' + this.state + '\'). Call \'LocalRecorder.stop()\' before'));
+ }
+ this.videoPreview = document.createElement('video');
+ this.videoPreview.id = this.id;
+ this.videoPreview.autoplay = true;
+ if (typeof parentElement === 'string') {
+ this.htmlParentElementId = parentElement;
+ var parentElementDom = document.getElementById(parentElement);
+ if (parentElementDom) {
+ this.videoPreview = parentElementDom.appendChild(this.videoPreview);
+ }
+ }
+ else {
+ this.htmlParentElementId = parentElement.id;
+ this.videoPreview = parentElement.appendChild(this.videoPreview);
+ }
+ this.videoPreview.src = this.videoPreviewSrc;
+ return this.videoPreview;
+ };
+ LocalRecorder.prototype.clean = function () {
+ var _this = this;
+ var f = function () {
+ delete _this.blob;
+ _this.chunks = [];
+ _this.count = 0;
+ delete _this.mediaRecorder;
+ _this.state = LocalRecorderState_1.LocalRecorderState.READY;
+ };
+ if (this.state === LocalRecorderState_1.LocalRecorderState.RECORDING || this.state === LocalRecorderState_1.LocalRecorderState.PAUSED) {
+ this.stop().then(function () { return f(); }).catch(function () { return f(); });
+ }
+ else {
+ f();
+ }
+ };
+ LocalRecorder.prototype.download = function () {
+ if (this.state !== LocalRecorderState_1.LocalRecorderState.FINISHED) {
+ throw (Error('\'LocalRecord.download()\' needs \'LocalRecord.state\' to be \'FINISHED\' (current value: \'' + this.state + '\'). Call \'LocalRecorder.stop()\' before'));
+ }
+ else {
+ var a = document.createElement('a');
+ a.style.display = 'none';
+ document.body.appendChild(a);
+ var url = window.URL.createObjectURL(this.blob);
+ a.href = url;
+ a.download = this.id + '.webm';
+ a.click();
+ window.URL.revokeObjectURL(url);
+ document.body.removeChild(a);
+ }
+ };
+ LocalRecorder.prototype.getBlob = function () {
+ if (this.state !== LocalRecorderState_1.LocalRecorderState.FINISHED) {
+ throw (Error('Call \'LocalRecord.stop()\' before getting Blob file'));
+ }
+ else {
+ return this.blob;
+ }
+ };
+ LocalRecorder.prototype.uploadAsBinary = function (endpoint, headers) {
+ var _this = this;
+ return new Promise(function (resolve, reject) {
+ if (_this.state !== LocalRecorderState_1.LocalRecorderState.FINISHED) {
+ reject(Error('\'LocalRecord.uploadAsBinary()\' needs \'LocalRecord.state\' to be \'FINISHED\' (current value: \'' + _this.state + '\'). Call \'LocalRecorder.stop()\' before'));
+ }
+ else {
+ var http_1 = new XMLHttpRequest();
+ http_1.open('POST', endpoint, true);
+ if (typeof headers === 'object') {
+ for (var _i = 0, _a = Object.keys(headers); _i < _a.length; _i++) {
+ var key = _a[_i];
+ http_1.setRequestHeader(key, headers[key]);
+ }
+ }
+ http_1.onreadystatechange = function () {
+ if (http_1.readyState === 4) {
+ if (http_1.status.toString().charAt(0) === '2') {
+ resolve(http_1.responseText);
+ }
+ else {
+ reject(http_1.status);
+ }
+ }
+ };
+ http_1.send(_this.blob);
+ }
+ });
+ };
+ LocalRecorder.prototype.uploadAsMultipartfile = function (endpoint, headers) {
+ var _this = this;
+ return new Promise(function (resolve, reject) {
+ if (_this.state !== LocalRecorderState_1.LocalRecorderState.FINISHED) {
+ reject(Error('\'LocalRecord.uploadAsMultipartfile()\' needs \'LocalRecord.state\' to be \'FINISHED\' (current value: \'' + _this.state + '\'). Call \'LocalRecorder.stop()\' before'));
+ }
+ else {
+ var http_2 = new XMLHttpRequest();
+ http_2.open('POST', endpoint, true);
+ if (typeof headers === 'object') {
+ for (var _i = 0, _a = Object.keys(headers); _i < _a.length; _i++) {
+ var key = _a[_i];
+ http_2.setRequestHeader(key, headers[key]);
+ }
+ }
+ var sendable = new FormData();
+ sendable.append('file', _this.blob, _this.id + '.webm');
+ http_2.onreadystatechange = function () {
+ if (http_2.readyState === 4) {
+ if (http_2.status.toString().charAt(0) === '2') {
+ resolve(http_2.responseText);
+ }
+ else {
+ reject(http_2.status);
+ }
+ }
+ };
+ http_2.send(sendable);
+ }
+ });
+ };
+ LocalRecorder.prototype.onStopDefault = function () {
+ console.log('MediaRecorder stopped (state=' + this.mediaRecorder.state + ')');
+ this.blob = new Blob(this.chunks, { type: 'video/webm' });
+ this.chunks = [];
+ this.videoPreviewSrc = window.URL.createObjectURL(this.blob);
+ this.state = LocalRecorderState_1.LocalRecorderState.FINISHED;
+ };
+ return LocalRecorder;
+}());
+exports.LocalRecorder = LocalRecorder;
+
+},{"../OpenViduInternal/Enums/LocalRecorderState":25}],19:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+var LocalRecorder_1 = require("./LocalRecorder");
+var Publisher_1 = require("./Publisher");
+var Session_1 = require("./Session");
+var StreamPropertyChangedEvent_1 = require("../OpenViduInternal/Events/StreamPropertyChangedEvent");
+var OpenViduError_1 = require("../OpenViduInternal/Enums/OpenViduError");
+var VideoInsertMode_1 = require("../OpenViduInternal/Enums/VideoInsertMode");
+var screenSharingAuto = require("../OpenViduInternal/ScreenSharing/Screen-Capturing-Auto");
+var screenSharing = require("../OpenViduInternal/ScreenSharing/Screen-Capturing");
+var RpcBuilder = require("../OpenViduInternal/KurentoUtils/kurento-jsonrpc");
+var platform = require("platform");
+var OpenVidu = (function () {
+ function OpenVidu() {
+ var _this = this;
+ this.publishers = [];
+ this.secret = '';
+ this.recorder = false;
+ this.advancedConfiguration = {};
+ console.info("'OpenVidu' initialized");
+ if (platform.name.toLowerCase().indexOf('mobile') !== -1) {
+ window.onorientationchange = function () {
+ _this.publishers.forEach(function (publisher) {
+ if (!!publisher.stream && !!publisher.stream.hasVideo && !!publisher.stream.streamManager.videos[0]) {
+ var attempts_1 = 0;
+ var oldWidth_1 = publisher.stream.videoDimensions.width;
+ var oldHeight_1 = publisher.stream.videoDimensions.height;
+ var firefoxSettings_1 = publisher.stream.getMediaStream().getVideoTracks()[0].getSettings();
+ var newWidth_1 = (platform.name.toLowerCase().indexOf('firefox') !== -1) ? firefoxSettings_1.width : publisher.videoReference.videoWidth;
+ var newHeight_1 = (platform.name.toLowerCase().indexOf('firefox') !== -1) ? firefoxSettings_1.height : publisher.videoReference.videoHeight;
+ var repeatUntilChange_1 = setInterval(function () {
+ firefoxSettings_1 = publisher.stream.getMediaStream().getVideoTracks()[0].getSettings();
+ newWidth_1 = (platform.name.toLowerCase().indexOf('firefox') !== -1) ? firefoxSettings_1.width : publisher.videoReference.videoWidth;
+ newHeight_1 = (platform.name.toLowerCase().indexOf('firefox') !== -1) ? firefoxSettings_1.height : publisher.videoReference.videoHeight;
+ sendStreamPropertyChangedEvent_1(oldWidth_1, oldHeight_1, newWidth_1, newHeight_1);
+ }, 100);
+ var sendStreamPropertyChangedEvent_1 = function (oldWidth, oldHeight, newWidth, newHeight) {
+ attempts_1++;
+ if (attempts_1 > 4) {
+ clearTimeout(repeatUntilChange_1);
+ }
+ if (newWidth !== oldWidth || newHeight !== oldHeight) {
+ publisher.stream.videoDimensions = {
+ width: newWidth || 0,
+ height: newHeight || 0
+ };
+ _this.sendRequest('streamPropertyChanged', {
+ streamId: publisher.stream.streamId,
+ property: 'videoDimensions',
+ newValue: JSON.stringify(publisher.stream.videoDimensions),
+ reason: 'deviceRotated'
+ }, function (error, response) {
+ if (error) {
+ console.error("Error sending 'streamPropertyChanged' event", error);
+ }
+ else {
+ _this.session.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent_1.StreamPropertyChangedEvent(_this.session, publisher.stream, 'videoDimensions', publisher.stream.videoDimensions, { width: oldWidth, height: oldHeight }, 'deviceRotated')]);
+ publisher.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent_1.StreamPropertyChangedEvent(publisher, publisher.stream, 'videoDimensions', publisher.stream.videoDimensions, { width: oldWidth, height: oldHeight }, 'deviceRotated')]);
+ }
+ });
+ clearTimeout(repeatUntilChange_1);
+ }
+ };
+ }
+ });
+ };
+ }
+ }
+ OpenVidu.prototype.initSession = function () {
+ this.session = new Session_1.Session(this);
+ return this.session;
+ };
+ OpenVidu.prototype.initPublisher = function (targetElement, param2, param3) {
+ var properties;
+ if (!!param2 && (typeof param2 !== 'function')) {
+ properties = param2;
+ properties = {
+ audioSource: (typeof properties.audioSource !== 'undefined') ? properties.audioSource : undefined,
+ frameRate: this.isMediaStreamTrack(properties.videoSource) ? undefined : ((typeof properties.frameRate !== 'undefined') ? properties.frameRate : undefined),
+ insertMode: (typeof properties.insertMode !== 'undefined') ? ((typeof properties.insertMode === 'string') ? VideoInsertMode_1.VideoInsertMode[properties.insertMode] : properties.insertMode) : VideoInsertMode_1.VideoInsertMode.APPEND,
+ mirror: (typeof properties.mirror !== 'undefined') ? properties.mirror : true,
+ publishAudio: (typeof properties.publishAudio !== 'undefined') ? properties.publishAudio : true,
+ publishVideo: (typeof properties.publishVideo !== 'undefined') ? properties.publishVideo : true,
+ resolution: this.isMediaStreamTrack(properties.videoSource) ? undefined : ((typeof properties.resolution !== 'undefined') ? properties.resolution : '640x480'),
+ videoSource: (typeof properties.videoSource !== 'undefined') ? properties.videoSource : undefined
+ };
+ }
+ else {
+ properties = {
+ insertMode: VideoInsertMode_1.VideoInsertMode.APPEND,
+ mirror: true,
+ publishAudio: true,
+ publishVideo: true,
+ resolution: '640x480'
+ };
+ }
+ var publisher = new Publisher_1.Publisher(targetElement, properties, this);
+ var completionHandler;
+ if (!!param2 && (typeof param2 === 'function')) {
+ completionHandler = param2;
+ }
+ else if (!!param3) {
+ completionHandler = param3;
+ }
+ publisher.initialize()
+ .then(function () {
+ if (completionHandler !== undefined) {
+ completionHandler(undefined);
+ }
+ publisher.emitEvent('accessAllowed', []);
+ }).catch(function (error) {
+ if (completionHandler !== undefined) {
+ completionHandler(error);
+ }
+ publisher.emitEvent('accessDenied', []);
+ });
+ this.publishers.push(publisher);
+ return publisher;
+ };
+ OpenVidu.prototype.initPublisherAsync = function (targetElement, properties) {
+ var _this = this;
+ return new Promise(function (resolve, reject) {
+ var publisher;
+ var callback = function (error) {
+ if (!!error) {
+ reject(error);
+ }
+ else {
+ resolve(publisher);
+ }
+ };
+ if (!!properties) {
+ publisher = _this.initPublisher(targetElement, properties, callback);
+ }
+ else {
+ publisher = _this.initPublisher(targetElement, callback);
+ }
+ });
+ };
+ OpenVidu.prototype.initLocalRecorder = function (stream) {
+ return new LocalRecorder_1.LocalRecorder(stream);
+ };
+ OpenVidu.prototype.checkSystemRequirements = function () {
+ var browser = platform.name;
+ var version = platform.version;
+ if ((browser !== 'Chrome') && (browser !== 'Chrome Mobile') &&
+ (browser !== 'Firefox') && (browser !== 'Firefox Mobile') && (browser !== 'Firefox for iOS') &&
+ (browser !== 'Opera') && (browser !== 'Opera Mobile') &&
+ (browser !== 'Safari')) {
+ return 0;
+ }
+ else {
+ return 1;
+ }
+ };
+ OpenVidu.prototype.getDevices = function () {
+ return new Promise(function (resolve, reject) {
+ navigator.mediaDevices.enumerateDevices().then(function (deviceInfos) {
+ var devices = [];
+ deviceInfos.forEach(function (deviceInfo) {
+ if (deviceInfo.kind === 'audioinput' || deviceInfo.kind === 'videoinput') {
+ devices.push({
+ kind: deviceInfo.kind,
+ deviceId: deviceInfo.deviceId,
+ label: deviceInfo.label
+ });
+ }
+ });
+ resolve(devices);
+ }).catch(function (error) {
+ console.error('Error getting devices', error);
+ reject(error);
+ });
+ });
+ };
+ OpenVidu.prototype.getUserMedia = function (options) {
+ var _this = this;
+ return new Promise(function (resolve, reject) {
+ _this.generateMediaConstraints(options)
+ .then(function (constraints) {
+ navigator.mediaDevices.getUserMedia(constraints)
+ .then(function (mediaStream) {
+ resolve(mediaStream);
+ })
+ .catch(function (error) {
+ var errorName;
+ var errorMessage = error.toString();
+ if (!(options.videoSource === 'screen')) {
+ errorName = OpenViduError_1.OpenViduErrorName.DEVICE_ACCESS_DENIED;
+ }
+ else {
+ errorName = OpenViduError_1.OpenViduErrorName.SCREEN_CAPTURE_DENIED;
+ }
+ reject(new OpenViduError_1.OpenViduError(errorName, errorMessage));
+ });
+ })
+ .catch(function (error) {
+ reject(error);
+ });
+ });
+ };
+ OpenVidu.prototype.enableProdMode = function () {
+ console.log = function () { };
+ console.debug = function () { };
+ console.info = function () { };
+ console.warn = function () { };
+ };
+ OpenVidu.prototype.setAdvancedConfiguration = function (configuration) {
+ this.advancedConfiguration = configuration;
+ };
+ OpenVidu.prototype.generateMediaConstraints = function (publisherProperties) {
+ var _this = this;
+ return new Promise(function (resolve, reject) {
+ var audio, video;
+ if (publisherProperties.audioSource === null || publisherProperties.audioSource === false) {
+ audio = false;
+ }
+ else if (publisherProperties.audioSource === undefined) {
+ audio = true;
+ }
+ else {
+ audio = publisherProperties.audioSource;
+ }
+ if (publisherProperties.videoSource === null || publisherProperties.videoSource === false) {
+ video = false;
+ }
+ else {
+ video = {
+ height: {
+ ideal: 480
+ },
+ width: {
+ ideal: 640
+ }
+ };
+ }
+ var mediaConstraints = {
+ audio: audio,
+ video: video
+ };
+ if (typeof mediaConstraints.audio === 'string') {
+ mediaConstraints.audio = { deviceId: { exact: mediaConstraints.audio } };
+ }
+ if (mediaConstraints.video) {
+ if (!!publisherProperties.resolution) {
+ var widthAndHeight = publisherProperties.resolution.toLowerCase().split('x');
+ var width = Number(widthAndHeight[0]);
+ var height = Number(widthAndHeight[1]);
+ mediaConstraints.video.width.ideal = width;
+ mediaConstraints.video.height.ideal = height;
+ }
+ if (!!publisherProperties.frameRate) {
+ mediaConstraints.video.frameRate = { ideal: publisherProperties.frameRate };
+ }
+ if (!!publisherProperties.videoSource && typeof publisherProperties.videoSource === 'string') {
+ if (publisherProperties.videoSource === 'screen') {
+ if (platform.name !== 'Chrome' && platform.name.indexOf('Firefox') === -1) {
+ var error = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_SHARING_NOT_SUPPORTED, 'You can only screen share in desktop Chrome and Firefox. Detected browser: ' + platform.name);
+ console.error(error);
+ reject(error);
+ }
+ else {
+ if (!!_this.advancedConfiguration.screenShareChromeExtension && !(platform.name.indexOf('Firefox') !== -1)) {
+ screenSharing.getScreenConstraints(function (error, screenConstraints) {
+ if (!!error || !!screenConstraints.mandatory && screenConstraints.mandatory.chromeMediaSource === 'screen') {
+ if (error === 'permission-denied' || error === 'PermissionDeniedError') {
+ var error_1 = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_CAPTURE_DENIED, 'You must allow access to one window of your desktop');
+ console.error(error_1);
+ reject(error_1);
+ }
+ else {
+ var extensionId = _this.advancedConfiguration.screenShareChromeExtension.split('/').pop().trim();
+ screenSharing.getChromeExtensionStatus(extensionId, function (status) {
+ if (status === 'installed-disabled') {
+ var error_2 = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_EXTENSION_DISABLED, 'You must enable the screen extension');
+ console.error(error_2);
+ reject(error_2);
+ }
+ if (status === 'not-installed') {
+ var error_3 = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_EXTENSION_NOT_INSTALLED, _this.advancedConfiguration.screenShareChromeExtension);
+ console.error(error_3);
+ reject(error_3);
+ }
+ });
+ }
+ }
+ else {
+ mediaConstraints.video = screenConstraints;
+ resolve(mediaConstraints);
+ }
+ });
+ }
+ else {
+ screenSharingAuto.getScreenId(function (error, sourceId, screenConstraints) {
+ if (!!error) {
+ if (error === 'not-installed') {
+ var extensionUrl = !!_this.advancedConfiguration.screenShareChromeExtension ? _this.advancedConfiguration.screenShareChromeExtension :
+ 'https://chrome.google.com/webstore/detail/openvidu-screensharing/lfcgfepafnobdloecchnfaclibenjold';
+ var error_4 = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_EXTENSION_NOT_INSTALLED, extensionUrl);
+ console.error(error_4);
+ reject(error_4);
+ }
+ else if (error === 'installed-disabled') {
+ var error_5 = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_EXTENSION_DISABLED, 'You must enable the screen extension');
+ console.error(error_5);
+ reject(error_5);
+ }
+ else if (error === 'permission-denied') {
+ var error_6 = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_CAPTURE_DENIED, 'You must allow access to one window of your desktop');
+ console.error(error_6);
+ reject(error_6);
+ }
+ }
+ else {
+ mediaConstraints.video = screenConstraints.video;
+ resolve(mediaConstraints);
+ }
+ });
+ }
+ publisherProperties.videoSource = 'screen';
+ }
+ }
+ else {
+ mediaConstraints.video['deviceId'] = { exact: publisherProperties.videoSource };
+ resolve(mediaConstraints);
+ }
+ }
+ else {
+ resolve(mediaConstraints);
+ }
+ }
+ else {
+ resolve(mediaConstraints);
+ }
+ });
+ };
+ OpenVidu.prototype.startWs = function (onConnectSucces) {
+ var config = {
+ heartbeat: 5000,
+ sendCloseMessage: false,
+ ws: {
+ uri: this.wsUri,
+ useSockJS: false,
+ onconnected: onConnectSucces,
+ ondisconnect: this.disconnectCallback.bind(this),
+ onreconnecting: this.reconnectingCallback.bind(this),
+ onreconnected: this.reconnectedCallback.bind(this)
+ },
+ rpc: {
+ requestTimeout: 10000,
+ participantJoined: this.session.onParticipantJoined.bind(this.session),
+ participantPublished: this.session.onParticipantPublished.bind(this.session),
+ participantUnpublished: this.session.onParticipantUnpublished.bind(this.session),
+ participantLeft: this.session.onParticipantLeft.bind(this.session),
+ participantEvicted: this.session.onParticipantEvicted.bind(this.session),
+ recordingStarted: this.session.onRecordingStarted.bind(this.session),
+ recordingStopped: this.session.onRecordingStopped.bind(this.session),
+ sendMessage: this.session.onNewMessage.bind(this.session),
+ streamPropertyChanged: this.session.onStreamPropertyChanged.bind(this.session),
+ iceCandidate: this.session.recvIceCandidate.bind(this.session),
+ mediaError: this.session.onMediaError.bind(this.session)
+ }
+ };
+ this.jsonRpcClient = new RpcBuilder.clients.JsonRpcClient(config);
+ };
+ OpenVidu.prototype.closeWs = function () {
+ this.jsonRpcClient.close();
+ };
+ OpenVidu.prototype.sendRequest = function (method, params, callback) {
+ if (params && params instanceof Function) {
+ callback = params;
+ params = {};
+ }
+ console.debug('Sending request: {method:"' + method + '", params: ' + JSON.stringify(params) + '}');
+ this.jsonRpcClient.send(method, params, callback);
+ };
+ OpenVidu.prototype.isMediaStreamTrack = function (mediaSource) {
+ var is = (!!mediaSource &&
+ mediaSource.enabled !== undefined && typeof mediaSource.enabled === 'boolean' &&
+ mediaSource.id !== undefined && typeof mediaSource.id === 'string' &&
+ mediaSource.kind !== undefined && typeof mediaSource.kind === 'string' &&
+ mediaSource.label !== undefined && typeof mediaSource.label === 'string' &&
+ mediaSource.muted !== undefined && typeof mediaSource.muted === 'boolean' &&
+ mediaSource.readyState !== undefined && typeof mediaSource.readyState === 'string');
+ return is;
+ };
+ OpenVidu.prototype.getWsUri = function () {
+ return this.wsUri;
+ };
+ OpenVidu.prototype.getSecret = function () {
+ return this.secret;
+ };
+ OpenVidu.prototype.getRecorder = function () {
+ return this.recorder;
+ };
+ OpenVidu.prototype.disconnectCallback = function () {
+ console.warn('Websocket connection lost');
+ if (this.isRoomAvailable()) {
+ this.session.onLostConnection();
+ }
+ else {
+ alert('Connection error. Please reload page.');
+ }
+ };
+ OpenVidu.prototype.reconnectingCallback = function () {
+ console.warn('Websocket connection lost (reconnecting)');
+ if (this.isRoomAvailable()) {
+ this.session.onLostConnection();
+ }
+ else {
+ alert('Connection error. Please reload page.');
+ }
+ };
+ OpenVidu.prototype.reconnectedCallback = function () {
+ console.warn('Websocket reconnected');
+ if (this.isRoomAvailable()) {
+ this.session.onRecoveredConnection();
+ }
+ else {
+ alert('Connection error. Please reload page.');
+ }
+ };
+ OpenVidu.prototype.isRoomAvailable = function () {
+ if (this.session !== undefined && this.session instanceof Session_1.Session) {
+ return true;
+ }
+ else {
+ console.warn('Session instance not found');
+ return false;
+ }
+ };
+ return OpenVidu;
+}());
+exports.OpenVidu = OpenVidu;
+
+},{"../OpenViduInternal/Enums/OpenViduError":26,"../OpenViduInternal/Enums/VideoInsertMode":27,"../OpenViduInternal/Events/StreamPropertyChangedEvent":36,"../OpenViduInternal/KurentoUtils/kurento-jsonrpc":43,"../OpenViduInternal/ScreenSharing/Screen-Capturing":48,"../OpenViduInternal/ScreenSharing/Screen-Capturing-Auto":47,"./LocalRecorder":18,"./Publisher":20,"./Session":21,"platform":8}],20:[function(require,module,exports){
+"use strict";
+var __extends = (this && this.__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 __());
+ };
+})();
+Object.defineProperty(exports, "__esModule", { value: true });
+var Session_1 = require("./Session");
+var Stream_1 = require("./Stream");
+var StreamManager_1 = require("./StreamManager");
+var StreamEvent_1 = require("../OpenViduInternal/Events/StreamEvent");
+var StreamPropertyChangedEvent_1 = require("../OpenViduInternal/Events/StreamPropertyChangedEvent");
+var VideoElementEvent_1 = require("../OpenViduInternal/Events/VideoElementEvent");
+var OpenViduError_1 = require("../OpenViduInternal/Enums/OpenViduError");
+var platform = require("platform");
+var Publisher = (function (_super) {
+ __extends(Publisher, _super);
+ function Publisher(targEl, properties, openvidu) {
+ var _this = _super.call(this, new Stream_1.Stream((!!openvidu.session) ? openvidu.session : new Session_1.Session(openvidu), { publisherProperties: properties, mediaConstraints: {} }), targEl) || this;
+ _this.accessAllowed = false;
+ _this.isSubscribedToRemote = false;
+ _this.accessDenied = false;
+ _this.properties = properties;
+ _this.openvidu = openvidu;
+ _this.stream.ee.on('local-stream-destroyed', function (reason) {
+ _this.stream.isLocalStreamPublished = false;
+ var streamEvent = new StreamEvent_1.StreamEvent(true, _this, 'streamDestroyed', _this.stream, reason);
+ _this.emitEvent('streamDestroyed', [streamEvent]);
+ streamEvent.callDefaultBehavior();
+ });
+ return _this;
+ }
+ Publisher.prototype.publishAudio = function (value) {
+ var _this = this;
+ if (this.stream.audioActive !== value) {
+ this.stream.getMediaStream().getAudioTracks().forEach(function (track) {
+ track.enabled = value;
+ });
+ this.session.openvidu.sendRequest('streamPropertyChanged', {
+ streamId: this.stream.streamId,
+ property: 'audioActive',
+ newValue: value,
+ reason: 'publishAudio'
+ }, function (error, response) {
+ if (error) {
+ console.error("Error sending 'streamPropertyChanged' event", error);
+ }
+ else {
+ _this.session.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent_1.StreamPropertyChangedEvent(_this.session, _this.stream, 'audioActive', value, !value, 'publishAudio')]);
+ _this.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent_1.StreamPropertyChangedEvent(_this, _this.stream, 'audioActive', value, !value, 'publishAudio')]);
+ }
+ });
+ this.stream.audioActive = value;
+ console.info("'Publisher' has " + (value ? 'published' : 'unpublished') + ' its audio stream');
+ }
+ };
+ Publisher.prototype.publishVideo = function (value) {
+ var _this = this;
+ if (this.stream.videoActive !== value) {
+ this.stream.getMediaStream().getVideoTracks().forEach(function (track) {
+ track.enabled = value;
+ });
+ this.session.openvidu.sendRequest('streamPropertyChanged', {
+ streamId: this.stream.streamId,
+ property: 'videoActive',
+ newValue: value,
+ reason: 'publishVideo'
+ }, function (error, response) {
+ if (error) {
+ console.error("Error sending 'streamPropertyChanged' event", error);
+ }
+ else {
+ _this.session.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent_1.StreamPropertyChangedEvent(_this.session, _this.stream, 'videoActive', value, !value, 'publishVideo')]);
+ _this.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent_1.StreamPropertyChangedEvent(_this, _this.stream, 'videoActive', value, !value, 'publishVideo')]);
+ }
+ });
+ this.stream.videoActive = value;
+ console.info("'Publisher' has " + (value ? 'published' : 'unpublished') + ' its video stream');
+ }
+ };
+ Publisher.prototype.subscribeToRemote = function (value) {
+ value = (value !== undefined) ? value : true;
+ this.isSubscribedToRemote = value;
+ this.stream.subscribeToMyRemote(value);
+ };
+ Publisher.prototype.on = function (type, handler) {
+ var _this = this;
+ _super.prototype.on.call(this, type, handler);
+ if (type === 'streamCreated') {
+ if (!!this.stream && this.stream.isLocalStreamPublished) {
+ this.emitEvent('streamCreated', [new StreamEvent_1.StreamEvent(false, this, 'streamCreated', this.stream, '')]);
+ }
+ else {
+ this.stream.ee.on('stream-created-by-publisher', function () {
+ _this.emitEvent('streamCreated', [new StreamEvent_1.StreamEvent(false, _this, 'streamCreated', _this.stream, '')]);
+ });
+ }
+ }
+ if (type === 'remoteVideoPlaying') {
+ if (this.stream.displayMyRemote() && this.videos[0] && this.videos[0].video &&
+ this.videos[0].video.currentTime > 0 &&
+ this.videos[0].video.paused === false &&
+ this.videos[0].video.ended === false &&
+ this.videos[0].video.readyState === 4) {
+ this.emitEvent('remoteVideoPlaying', [new VideoElementEvent_1.VideoElementEvent(this.videos[0].video, this, 'remoteVideoPlaying')]);
+ }
+ }
+ if (type === 'accessAllowed') {
+ if (this.accessAllowed) {
+ this.emitEvent('accessAllowed', []);
+ }
+ }
+ if (type === 'accessDenied') {
+ if (this.accessDenied) {
+ this.emitEvent('accessDenied', []);
+ }
+ }
+ return this;
+ };
+ Publisher.prototype.once = function (type, handler) {
+ var _this = this;
+ _super.prototype.once.call(this, type, handler);
+ if (type === 'streamCreated') {
+ if (!!this.stream && this.stream.isLocalStreamPublished) {
+ this.emitEvent('streamCreated', [new StreamEvent_1.StreamEvent(false, this, 'streamCreated', this.stream, '')]);
+ }
+ else {
+ this.stream.ee.once('stream-created-by-publisher', function () {
+ _this.emitEvent('streamCreated', [new StreamEvent_1.StreamEvent(false, _this, 'streamCreated', _this.stream, '')]);
+ });
+ }
+ }
+ if (type === 'remoteVideoPlaying') {
+ if (this.stream.displayMyRemote() && this.videos[0] && this.videos[0].video &&
+ this.videos[0].video.currentTime > 0 &&
+ this.videos[0].video.paused === false &&
+ this.videos[0].video.ended === false &&
+ this.videos[0].video.readyState === 4) {
+ this.emitEvent('remoteVideoPlaying', [new VideoElementEvent_1.VideoElementEvent(this.videos[0].video, this, 'remoteVideoPlaying')]);
+ }
+ }
+ if (type === 'accessAllowed') {
+ if (this.accessAllowed) {
+ this.emitEvent('accessAllowed', []);
+ }
+ }
+ if (type === 'accessDenied') {
+ if (this.accessDenied) {
+ this.emitEvent('accessDenied', []);
+ }
+ }
+ return this;
+ };
+ Publisher.prototype.initialize = function () {
+ var _this = this;
+ return new Promise(function (resolve, reject) {
+ var errorCallback = function (openViduError) {
+ _this.accessDenied = true;
+ _this.accessAllowed = false;
+ reject(openViduError);
+ };
+ var successCallback = function (mediaStream) {
+ _this.accessAllowed = true;
+ _this.accessDenied = false;
+ if (_this.openvidu.isMediaStreamTrack(_this.properties.audioSource)) {
+ mediaStream.removeTrack(mediaStream.getAudioTracks()[0]);
+ mediaStream.addTrack(_this.properties.audioSource);
+ }
+ if (_this.openvidu.isMediaStreamTrack(_this.properties.videoSource)) {
+ mediaStream.removeTrack(mediaStream.getVideoTracks()[0]);
+ mediaStream.addTrack(_this.properties.videoSource);
+ }
+ if (!!mediaStream.getAudioTracks()[0]) {
+ var enabled = (_this.stream.audioActive !== undefined && _this.stream.audioActive !== null) ? _this.stream.audioActive : !!_this.stream.outboundStreamOpts.publisherProperties.publishAudio;
+ mediaStream.getAudioTracks()[0].enabled = enabled;
+ }
+ if (!!mediaStream.getVideoTracks()[0]) {
+ var enabled = (_this.stream.videoActive !== undefined && _this.stream.videoActive !== null) ? _this.stream.videoActive : !!_this.stream.outboundStreamOpts.publisherProperties.publishVideo;
+ mediaStream.getVideoTracks()[0].enabled = enabled;
+ }
+ _this.videoReference = document.createElement('video');
+ _this.videoReference.srcObject = mediaStream;
+ _this.stream.setMediaStream(mediaStream);
+ if (!_this.stream.displayMyRemote()) {
+ _this.stream.updateMediaStreamInVideos();
+ }
+ if (!!_this.firstVideoElement) {
+ _this.createVideoElement(_this.firstVideoElement.targetElement, _this.properties.insertMode);
+ }
+ delete _this.firstVideoElement;
+ if (_this.stream.isSendVideo()) {
+ if (!_this.stream.isSendScreen()) {
+ var _a = mediaStream.getVideoTracks()[0].getSettings(), width = _a.width, height = _a.height;
+ if (platform.name.toLowerCase().indexOf('mobile') !== -1 && (window.innerHeight > window.innerWidth)) {
+ _this.stream.videoDimensions = {
+ width: height || 0,
+ height: width || 0
+ };
+ }
+ else {
+ _this.stream.videoDimensions = {
+ width: width || 0,
+ height: height || 0
+ };
+ }
+ _this.stream.isLocalStreamReadyToPublish = true;
+ _this.stream.ee.emitEvent('stream-ready-to-publish', []);
+ }
+ else {
+ _this.videoReference.onloadedmetadata = function () {
+ _this.stream.videoDimensions = {
+ width: _this.videoReference.videoWidth,
+ height: _this.videoReference.videoHeight
+ };
+ _this.screenShareResizeInterval = setInterval(function () {
+ var firefoxSettings = mediaStream.getVideoTracks()[0].getSettings();
+ var newWidth = (platform.name === 'Chrome') ? _this.videoReference.videoWidth : firefoxSettings.width;
+ var newHeight = (platform.name === 'Chrome') ? _this.videoReference.videoHeight : firefoxSettings.height;
+ if (_this.stream.isLocalStreamPublished &&
+ (newWidth !== _this.stream.videoDimensions.width ||
+ newHeight !== _this.stream.videoDimensions.height)) {
+ var oldValue_1 = { width: _this.stream.videoDimensions.width, height: _this.stream.videoDimensions.height };
+ _this.stream.videoDimensions = {
+ width: newWidth || 0,
+ height: newHeight || 0
+ };
+ _this.session.openvidu.sendRequest('streamPropertyChanged', {
+ streamId: _this.stream.streamId,
+ property: 'videoDimensions',
+ newValue: JSON.stringify(_this.stream.videoDimensions),
+ reason: 'screenResized'
+ }, function (error, response) {
+ if (error) {
+ console.error("Error sending 'streamPropertyChanged' event", error);
+ }
+ else {
+ _this.session.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent_1.StreamPropertyChangedEvent(_this.session, _this.stream, 'videoDimensions', _this.stream.videoDimensions, oldValue_1, 'screenResized')]);
+ _this.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent_1.StreamPropertyChangedEvent(_this, _this.stream, 'videoDimensions', _this.stream.videoDimensions, oldValue_1, 'screenResized')]);
+ }
+ });
+ }
+ }, 500);
+ _this.stream.isLocalStreamReadyToPublish = true;
+ _this.stream.ee.emitEvent('stream-ready-to-publish', []);
+ };
+ }
+ }
+ else {
+ _this.stream.isLocalStreamReadyToPublish = true;
+ _this.stream.ee.emitEvent('stream-ready-to-publish', []);
+ }
+ resolve();
+ };
+ _this.openvidu.generateMediaConstraints(_this.properties)
+ .then(function (constraints) {
+ var outboundStreamOptions = {
+ mediaConstraints: constraints,
+ publisherProperties: _this.properties
+ };
+ _this.stream.setOutboundStreamOptions(outboundStreamOptions);
+ var constraintsAux = {};
+ var timeForDialogEvent = 1250;
+ if (_this.stream.isSendVideo() || _this.stream.isSendAudio()) {
+ var definedAudioConstraint_1 = ((constraints.audio === undefined) ? true : constraints.audio);
+ constraintsAux.audio = _this.stream.isSendScreen() ? false : definedAudioConstraint_1;
+ constraintsAux.video = constraints.video;
+ var startTime_1 = Date.now();
+ _this.setPermissionDialogTimer(timeForDialogEvent);
+ navigator.mediaDevices.getUserMedia(constraintsAux)
+ .then(function (mediaStream) {
+ _this.clearPermissionDialogTimer(startTime_1, timeForDialogEvent);
+ if (_this.stream.isSendScreen() && _this.stream.isSendAudio()) {
+ constraintsAux.audio = definedAudioConstraint_1;
+ constraintsAux.video = false;
+ startTime_1 = Date.now();
+ _this.setPermissionDialogTimer(timeForDialogEvent);
+ navigator.mediaDevices.getUserMedia(constraintsAux)
+ .then(function (audioOnlyStream) {
+ _this.clearPermissionDialogTimer(startTime_1, timeForDialogEvent);
+ mediaStream.addTrack(audioOnlyStream.getAudioTracks()[0]);
+ successCallback(mediaStream);
+ })
+ .catch(function (error) {
+ _this.clearPermissionDialogTimer(startTime_1, timeForDialogEvent);
+ var errorName, errorMessage;
+ switch (error.name.toLowerCase()) {
+ case 'notfounderror':
+ errorName = OpenViduError_1.OpenViduErrorName.INPUT_AUDIO_DEVICE_NOT_FOUND;
+ errorMessage = error.toString();
+ errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage));
+ break;
+ case 'notallowederror':
+ errorName = OpenViduError_1.OpenViduErrorName.DEVICE_ACCESS_DENIED;
+ errorMessage = error.toString();
+ errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage));
+ break;
+ case 'overconstrainederror':
+ if (error.constraint.toLowerCase() === 'deviceid') {
+ errorName = OpenViduError_1.OpenViduErrorName.INPUT_AUDIO_DEVICE_NOT_FOUND;
+ errorMessage = "Audio input device with deviceId '" + constraints.video.deviceId.exact + "' not found";
+ }
+ else {
+ errorName = OpenViduError_1.OpenViduErrorName.PUBLISHER_PROPERTIES_ERROR;
+ errorMessage = "Audio input device doesn't support the value passed for constraint '" + error.constraint + "'";
+ }
+ errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage));
+ break;
+ }
+ });
+ }
+ else {
+ successCallback(mediaStream);
+ }
+ })
+ .catch(function (error) {
+ _this.clearPermissionDialogTimer(startTime_1, timeForDialogEvent);
+ var errorName, errorMessage;
+ switch (error.name.toLowerCase()) {
+ case 'notfounderror':
+ navigator.mediaDevices.getUserMedia({
+ audio: false,
+ video: constraints.video
+ })
+ .then(function (mediaStream) {
+ mediaStream.getVideoTracks().forEach(function (track) {
+ track.stop();
+ });
+ errorName = OpenViduError_1.OpenViduErrorName.INPUT_AUDIO_DEVICE_NOT_FOUND;
+ errorMessage = error.toString();
+ errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage));
+ }).catch(function (e) {
+ errorName = OpenViduError_1.OpenViduErrorName.INPUT_VIDEO_DEVICE_NOT_FOUND;
+ errorMessage = error.toString();
+ errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage));
+ });
+ break;
+ case 'notallowederror':
+ errorName = _this.stream.isSendScreen() ? OpenViduError_1.OpenViduErrorName.SCREEN_CAPTURE_DENIED : OpenViduError_1.OpenViduErrorName.DEVICE_ACCESS_DENIED;
+ errorMessage = error.toString();
+ errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage));
+ break;
+ case 'overconstrainederror':
+ navigator.mediaDevices.getUserMedia({
+ audio: false,
+ video: constraints.video
+ })
+ .then(function (mediaStream) {
+ mediaStream.getVideoTracks().forEach(function (track) {
+ track.stop();
+ });
+ if (error.constraint.toLowerCase() === 'deviceid') {
+ errorName = OpenViduError_1.OpenViduErrorName.INPUT_AUDIO_DEVICE_NOT_FOUND;
+ errorMessage = "Audio input device with deviceId '" + constraints.audio.deviceId.exact + "' not found";
+ }
+ else {
+ errorName = OpenViduError_1.OpenViduErrorName.PUBLISHER_PROPERTIES_ERROR;
+ errorMessage = "Audio input device doesn't support the value passed for constraint '" + error.constraint + "'";
+ }
+ errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage));
+ }).catch(function (e) {
+ if (error.constraint.toLowerCase() === 'deviceid') {
+ errorName = OpenViduError_1.OpenViduErrorName.INPUT_VIDEO_DEVICE_NOT_FOUND;
+ errorMessage = "Video input device with deviceId '" + constraints.video.deviceId.exact + "' not found";
+ }
+ else {
+ errorName = OpenViduError_1.OpenViduErrorName.PUBLISHER_PROPERTIES_ERROR;
+ errorMessage = "Video input device doesn't support the value passed for constraint '" + error.constraint + "'";
+ }
+ errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage));
+ });
+ break;
+ }
+ });
+ }
+ else {
+ reject(new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.NO_INPUT_SOURCE_SET, "Properties 'audioSource' and 'videoSource' cannot be set to false or null at the same time when calling 'OpenVidu.initPublisher'"));
+ }
+ })
+ .catch(function (error) {
+ errorCallback(error);
+ });
+ });
+ };
+ Publisher.prototype.reestablishStreamPlayingEvent = function () {
+ if (this.ee.getListeners('streamPlaying').length > 0) {
+ this.addPlayEventToFirstVideo();
+ }
+ };
+ Publisher.prototype.setPermissionDialogTimer = function (waitTime) {
+ var _this = this;
+ this.permissionDialogTimeout = setTimeout(function () {
+ _this.emitEvent('accessDialogOpened', []);
+ }, waitTime);
+ };
+ Publisher.prototype.clearPermissionDialogTimer = function (startTime, waitTime) {
+ clearTimeout(this.permissionDialogTimeout);
+ if ((Date.now() - startTime) > waitTime) {
+ this.emitEvent('accessDialogClosed', []);
+ }
+ };
+ return Publisher;
+}(StreamManager_1.StreamManager));
+exports.Publisher = Publisher;
+
+},{"../OpenViduInternal/Enums/OpenViduError":26,"../OpenViduInternal/Events/StreamEvent":34,"../OpenViduInternal/Events/StreamPropertyChangedEvent":36,"../OpenViduInternal/Events/VideoElementEvent":37,"./Session":21,"./Stream":22,"./StreamManager":23,"platform":8}],21:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+var Connection_1 = require("./Connection");
+var Subscriber_1 = require("./Subscriber");
+var ConnectionEvent_1 = require("../OpenViduInternal/Events/ConnectionEvent");
+var RecordingEvent_1 = require("../OpenViduInternal/Events/RecordingEvent");
+var SessionDisconnectedEvent_1 = require("../OpenViduInternal/Events/SessionDisconnectedEvent");
+var SignalEvent_1 = require("../OpenViduInternal/Events/SignalEvent");
+var StreamEvent_1 = require("../OpenViduInternal/Events/StreamEvent");
+var StreamPropertyChangedEvent_1 = require("../OpenViduInternal/Events/StreamPropertyChangedEvent");
+var OpenViduError_1 = require("../OpenViduInternal/Enums/OpenViduError");
+var VideoInsertMode_1 = require("../OpenViduInternal/Enums/VideoInsertMode");
+var platform = require("platform");
+var EventEmitter = require("wolfy87-eventemitter");
+var Session = (function () {
+ function Session(openvidu) {
+ this.streamManagers = [];
+ this.remoteStreamsCreated = {};
+ this.remoteConnections = {};
+ this.speakingEventsEnabled = false;
+ this.ee = new EventEmitter();
+ this.openvidu = openvidu;
+ }
+ Session.prototype.connect = function (token, metadata) {
+ var _this = this;
+ return new Promise(function (resolve, reject) {
+ _this.processToken(token);
+ if (_this.openvidu.checkSystemRequirements()) {
+ _this.options = {
+ sessionId: _this.sessionId,
+ participantId: token,
+ metadata: !!metadata ? _this.stringClientMetadata(metadata) : ''
+ };
+ _this.connectAux(token).then(function () {
+ resolve();
+ }).catch(function (error) {
+ reject(error);
+ });
+ }
+ else {
+ reject(new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.BROWSER_NOT_SUPPORTED, 'Browser ' + platform.name + ' ' + platform.version + ' is not supported in OpenVidu'));
+ }
+ });
+ };
+ Session.prototype.disconnect = function () {
+ this.leave(false, 'disconnect');
+ };
+ Session.prototype.subscribe = function (stream, targetElement, param3, param4) {
+ var properties = {};
+ if (!!param3 && typeof param3 !== 'function') {
+ properties = {
+ insertMode: (typeof param3.insertMode !== 'undefined') ? ((typeof param3.insertMode === 'string') ? VideoInsertMode_1.VideoInsertMode[param3.insertMode] : properties.insertMode) : VideoInsertMode_1.VideoInsertMode.APPEND,
+ subscribeToAudio: (typeof param3.subscribeToAudio !== 'undefined') ? param3.subscribeToAudio : true,
+ subscribeToVideo: (typeof param3.subscribeToVideo !== 'undefined') ? param3.subscribeToVideo : true
+ };
+ }
+ else {
+ properties = {
+ insertMode: VideoInsertMode_1.VideoInsertMode.APPEND,
+ subscribeToAudio: true,
+ subscribeToVideo: true
+ };
+ }
+ var completionHandler;
+ if (!!param3 && (typeof param3 === 'function')) {
+ completionHandler = param3;
+ }
+ else if (!!param4) {
+ completionHandler = param4;
+ }
+ console.info('Subscribing to ' + stream.connection.connectionId);
+ stream.subscribe()
+ .then(function () {
+ console.info('Subscribed correctly to ' + stream.connection.connectionId);
+ if (completionHandler !== undefined) {
+ completionHandler(undefined);
+ }
+ })
+ .catch(function (error) {
+ if (completionHandler !== undefined) {
+ completionHandler(error);
+ }
+ });
+ var subscriber = new Subscriber_1.Subscriber(stream, targetElement, properties);
+ if (!!subscriber.targetElement) {
+ stream.streamManager.createVideoElement(subscriber.targetElement, properties.insertMode);
+ }
+ return subscriber;
+ };
+ Session.prototype.subscribeAsync = function (stream, targetElement, properties) {
+ var _this = this;
+ return new Promise(function (resolve, reject) {
+ var subscriber;
+ var callback = function (error) {
+ if (!!error) {
+ reject(error);
+ }
+ else {
+ resolve(subscriber);
+ }
+ };
+ if (!!properties) {
+ subscriber = _this.subscribe(stream, targetElement, properties, callback);
+ }
+ else {
+ subscriber = _this.subscribe(stream, targetElement, callback);
+ }
+ });
+ };
+ Session.prototype.unsubscribe = function (subscriber) {
+ var connectionId = subscriber.stream.connection.connectionId;
+ console.info('Unsubscribing from ' + connectionId);
+ this.openvidu.sendRequest('unsubscribeFromVideo', { sender: subscriber.stream.connection.connectionId }, function (error, response) {
+ if (error) {
+ console.error('Error unsubscribing from ' + connectionId, error);
+ }
+ else {
+ console.info('Unsubscribed correctly from ' + connectionId);
+ }
+ subscriber.stream.disposeWebRtcPeer();
+ subscriber.stream.disposeMediaStream();
+ });
+ subscriber.stream.streamManager.removeAllVideos();
+ };
+ Session.prototype.publish = function (publisher) {
+ var _this = this;
+ return new Promise(function (resolve, reject) {
+ publisher.session = _this;
+ publisher.stream.session = _this;
+ if (!publisher.stream.publishedOnce) {
+ _this.connection.addStream(publisher.stream);
+ publisher.stream.publish()
+ .then(function () {
+ resolve();
+ })
+ .catch(function (error) {
+ reject(error);
+ });
+ }
+ else {
+ publisher.initialize()
+ .then(function () {
+ _this.connection.addStream(publisher.stream);
+ publisher.reestablishStreamPlayingEvent();
+ publisher.stream.publish()
+ .then(function () {
+ resolve();
+ })
+ .catch(function (error) {
+ reject(error);
+ });
+ }).catch(function (error) {
+ reject(error);
+ });
+ }
+ });
+ };
+ Session.prototype.unpublish = function (publisher) {
+ var stream = publisher.stream;
+ if (!stream.connection) {
+ console.error('The associated Connection object of this Publisher is null', stream);
+ return;
+ }
+ else if (stream.connection !== this.connection) {
+ console.error('The associated Connection object of this Publisher is not your local Connection.' +
+ "Only moderators can force unpublish on remote Streams via 'forceUnpublish' method", stream);
+ return;
+ }
+ else {
+ console.info('Unpublishing local media (' + stream.connection.connectionId + ')');
+ this.openvidu.sendRequest('unpublishVideo', function (error, response) {
+ if (error) {
+ console.error(error);
+ }
+ else {
+ console.info('Media unpublished correctly');
+ }
+ });
+ stream.disposeWebRtcPeer();
+ delete stream.connection.stream;
+ var streamEvent = new StreamEvent_1.StreamEvent(true, publisher, 'streamDestroyed', publisher.stream, 'unpublish');
+ publisher.emitEvent('streamDestroyed', [streamEvent]);
+ streamEvent.callDefaultBehavior();
+ }
+ };
+ Session.prototype.forceDisconnect = function (connection) {
+ var _this = this;
+ return new Promise(function (resolve, reject) {
+ console.info('Forcing disconnect for connection ' + connection.connectionId);
+ _this.openvidu.sendRequest('forceDisconnect', { connectionId: connection.connectionId }, function (error, response) {
+ if (error) {
+ console.error('Error forcing disconnect for Connection ' + connection.connectionId, error);
+ if (error.code === 401) {
+ reject(new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.OPENVIDU_PERMISSION_DENIED, "You don't have permissions to force a disconnection"));
+ }
+ else {
+ reject(error);
+ }
+ }
+ else {
+ console.info('Forcing disconnect correctly for Connection ' + connection.connectionId);
+ resolve();
+ }
+ });
+ });
+ };
+ Session.prototype.forceUnpublish = function (stream) {
+ var _this = this;
+ return new Promise(function (resolve, reject) {
+ console.info('Forcing unpublish for stream ' + stream.streamId);
+ _this.openvidu.sendRequest('forceUnpublish', { streamId: stream.streamId }, function (error, response) {
+ if (error) {
+ console.error('Error forcing unpublish for Stream ' + stream.streamId, error);
+ if (error.code === 401) {
+ reject(new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.OPENVIDU_PERMISSION_DENIED, "You don't have permissions to force an unpublishing"));
+ }
+ else {
+ reject(error);
+ }
+ }
+ else {
+ console.info('Forcing unpublish correctly for Stream ' + stream.streamId);
+ resolve();
+ }
+ });
+ });
+ };
+ Session.prototype.signal = function (signal) {
+ var _this = this;
+ return new Promise(function (resolve, reject) {
+ var signalMessage = {};
+ if (signal.to && signal.to.length > 0) {
+ var connectionIds_1 = [];
+ signal.to.forEach(function (connection) {
+ connectionIds_1.push(connection.connectionId);
+ });
+ signalMessage['to'] = connectionIds_1;
+ }
+ else {
+ signalMessage['to'] = [];
+ }
+ signalMessage['data'] = signal.data ? signal.data : '';
+ signalMessage['type'] = signal.type ? signal.type : '';
+ _this.openvidu.sendRequest('sendMessage', {
+ message: JSON.stringify(signalMessage)
+ }, function (error, response) {
+ if (!!error) {
+ reject(error);
+ }
+ else {
+ resolve();
+ }
+ });
+ });
+ };
+ Session.prototype.on = function (type, handler) {
+ this.ee.on(type, function (event) {
+ if (event) {
+ console.info("Event '" + type + "' triggered by 'Session'", event);
+ }
+ else {
+ console.info("Event '" + type + "' triggered by 'Session'");
+ }
+ handler(event);
+ });
+ if (type === 'publisherStartSpeaking' || type === 'publisherStopSpeaking') {
+ this.speakingEventsEnabled = true;
+ for (var connectionId in this.remoteConnections) {
+ var str = this.remoteConnections[connectionId].stream;
+ if (!!str && !str.speechEvent && str.hasAudio) {
+ str.enableSpeakingEvents();
+ }
+ }
+ }
+ return this;
+ };
+ Session.prototype.once = function (type, handler) {
+ this.ee.once(type, function (event) {
+ if (event) {
+ console.info("Event '" + type + "' triggered by 'Session'", event);
+ }
+ else {
+ console.info("Event '" + type + "' triggered by 'Session'");
+ }
+ handler(event);
+ });
+ if (type === 'publisherStartSpeaking' || type === 'publisherStopSpeaking') {
+ this.speakingEventsEnabled = true;
+ for (var connectionId in this.remoteConnections) {
+ var str = this.remoteConnections[connectionId].stream;
+ if (!!str && !str.speechEvent && str.hasAudio) {
+ str.enableOnceSpeakingEvents();
+ }
+ }
+ }
+ return this;
+ };
+ Session.prototype.off = function (type, handler) {
+ if (!handler) {
+ this.ee.removeAllListeners(type);
+ }
+ else {
+ this.ee.off(type, handler);
+ }
+ if (type === 'publisherStartSpeaking' || type === 'publisherStopSpeaking') {
+ this.speakingEventsEnabled = false;
+ for (var connectionId in this.remoteConnections) {
+ var str = this.remoteConnections[connectionId].stream;
+ if (!!str && !!str.speechEvent) {
+ str.disableSpeakingEvents();
+ }
+ }
+ }
+ return this;
+ };
+ Session.prototype.onParticipantJoined = function (response) {
+ var _this = this;
+ this.getConnection(response.id, '')
+ .then(function (connection) {
+ console.warn('Connection ' + response.id + ' already exists in connections list');
+ })
+ .catch(function (openViduError) {
+ var connection = new Connection_1.Connection(_this, response);
+ _this.remoteConnections[response.id] = connection;
+ _this.ee.emitEvent('connectionCreated', [new ConnectionEvent_1.ConnectionEvent(false, _this, 'connectionCreated', connection, '')]);
+ });
+ };
+ Session.prototype.onParticipantLeft = function (msg) {
+ var _this = this;
+ this.getRemoteConnection(msg.connectionId, 'Remote connection ' + msg.connectionId + " unknown when 'onParticipantLeft'. " +
+ 'Existing remote connections: ' + JSON.stringify(Object.keys(this.remoteConnections)))
+ .then(function (connection) {
+ if (!!connection.stream) {
+ var stream = connection.stream;
+ var streamEvent = new StreamEvent_1.StreamEvent(true, _this, 'streamDestroyed', stream, msg.reason);
+ _this.ee.emitEvent('streamDestroyed', [streamEvent]);
+ streamEvent.callDefaultBehavior();
+ delete _this.remoteStreamsCreated[stream.streamId];
+ }
+ delete _this.remoteConnections[connection.connectionId];
+ _this.ee.emitEvent('connectionDestroyed', [new ConnectionEvent_1.ConnectionEvent(false, _this, 'connectionDestroyed', connection, msg.reason)]);
+ })
+ .catch(function (openViduError) {
+ console.error(openViduError);
+ });
+ };
+ Session.prototype.onParticipantPublished = function (response) {
+ var _this = this;
+ var afterConnectionFound = function (connection) {
+ _this.remoteConnections[connection.connectionId] = connection;
+ if (!_this.remoteStreamsCreated[connection.stream.streamId]) {
+ _this.ee.emitEvent('streamCreated', [new StreamEvent_1.StreamEvent(false, _this, 'streamCreated', connection.stream, '')]);
+ }
+ _this.remoteStreamsCreated[connection.stream.streamId] = true;
+ };
+ var connection;
+ this.getRemoteConnection(response.id, "Remote connection '" + response.id + "' unknown when 'onParticipantPublished'. " +
+ 'Existing remote connections: ' + JSON.stringify(Object.keys(this.remoteConnections)))
+ .then(function (con) {
+ connection = con;
+ response.metadata = con.data;
+ connection.options = response;
+ connection.initRemoteStreams(response.streams);
+ afterConnectionFound(connection);
+ })
+ .catch(function (openViduError) {
+ connection = new Connection_1.Connection(_this, response);
+ afterConnectionFound(connection);
+ });
+ };
+ Session.prototype.onParticipantUnpublished = function (msg) {
+ var _this = this;
+ if (msg.connectionId === this.connection.connectionId) {
+ this.stopPublisherStream(msg.reason);
+ }
+ else {
+ this.getRemoteConnection(msg.connectionId, "Remote connection '" + msg.connectionId + "' unknown when 'onParticipantUnpublished'. " +
+ 'Existing remote connections: ' + JSON.stringify(Object.keys(this.remoteConnections)))
+ .then(function (connection) {
+ var streamEvent = new StreamEvent_1.StreamEvent(true, _this, 'streamDestroyed', connection.stream, msg.reason);
+ _this.ee.emitEvent('streamDestroyed', [streamEvent]);
+ streamEvent.callDefaultBehavior();
+ var streamId = connection.stream.streamId;
+ delete _this.remoteStreamsCreated[streamId];
+ connection.removeStream(streamId);
+ })
+ .catch(function (openViduError) {
+ console.error(openViduError);
+ });
+ }
+ };
+ Session.prototype.onParticipantEvicted = function (msg) {
+ if (msg.connectionId === this.connection.connectionId) {
+ if (!!this.sessionId && !this.connection.disposed) {
+ this.leave(true, msg.reason);
+ }
+ }
+ };
+ Session.prototype.onNewMessage = function (msg) {
+ var _this = this;
+ console.info('New signal: ' + JSON.stringify(msg));
+ this.getConnection(msg.from, "Connection '" + msg.from + "' unknow when 'onNewMessage'. Existing remote connections: "
+ + JSON.stringify(Object.keys(this.remoteConnections)) + '. Existing local connection: ' + this.connection.connectionId)
+ .then(function (connection) {
+ _this.ee.emitEvent('signal', [new SignalEvent_1.SignalEvent(_this, msg.type, msg.data, connection)]);
+ _this.ee.emitEvent('signal:' + msg.type, [new SignalEvent_1.SignalEvent(_this, msg.type, msg.data, connection)]);
+ })
+ .catch(function (openViduError) {
+ console.error(openViduError);
+ });
+ };
+ Session.prototype.onStreamPropertyChanged = function (msg) {
+ var _this = this;
+ this.getRemoteConnection(msg.connectionId, 'Remote connection ' + msg.connectionId + " unknown when 'onStreamPropertyChanged'. " +
+ 'Existing remote connections: ' + JSON.stringify(Object.keys(this.remoteConnections)))
+ .then(function (connection) {
+ if (!!connection.stream && connection.stream.streamId === msg.streamId) {
+ var stream = connection.stream;
+ var oldValue = void 0;
+ switch (msg.property) {
+ case 'audioActive':
+ oldValue = stream.audioActive;
+ msg.newValue = msg.newValue === 'true';
+ stream.audioActive = msg.newValue;
+ break;
+ case 'videoActive':
+ oldValue = stream.videoActive;
+ msg.newValue = msg.newValue === 'true';
+ stream.videoActive = msg.newValue;
+ break;
+ case 'videoDimensions':
+ oldValue = stream.videoDimensions;
+ msg.newValue = JSON.parse(JSON.parse(msg.newValue));
+ stream.videoDimensions = msg.newValue;
+ break;
+ }
+ _this.ee.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent_1.StreamPropertyChangedEvent(_this, stream, msg.property, msg.newValue, oldValue, msg.reason)]);
+ stream.streamManager.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent_1.StreamPropertyChangedEvent(stream.streamManager, stream, msg.property, msg.newValue, oldValue, msg.reason)]);
+ }
+ else {
+ console.error("No stream with streamId '" + msg.streamId + "' found for connection '" + msg.connectionId + "' on 'streamPropertyChanged' event");
+ }
+ })
+ .catch(function (openViduError) {
+ console.error(openViduError);
+ });
+ };
+ Session.prototype.recvIceCandidate = function (msg) {
+ var candidate = {
+ candidate: msg.candidate,
+ sdpMid: msg.sdpMid,
+ sdpMLineIndex: msg.sdpMLineIndex,
+ toJSON: function () {
+ return { candidate: msg.candidate };
+ }
+ };
+ this.getConnection(msg.endpointName, 'Connection not found for endpoint ' + msg.endpointName + '. Ice candidate will be ignored: ' + candidate)
+ .then(function (connection) {
+ var stream = connection.stream;
+ stream.getWebRtcPeer().addIceCandidate(candidate).catch(function (error) {
+ console.error('Error adding candidate for ' + stream.streamId
+ + ' stream of endpoint ' + msg.endpointName + ': ' + error);
+ });
+ })
+ .catch(function (openViduError) {
+ console.error(openViduError);
+ });
+ };
+ Session.prototype.onSessionClosed = function (msg) {
+ console.info('Session closed: ' + JSON.stringify(msg));
+ var s = msg.sessionId;
+ if (s !== undefined) {
+ this.ee.emitEvent('session-closed', [{
+ session: s
+ }]);
+ }
+ else {
+ console.warn('Session undefined on session closed', msg);
+ }
+ };
+ Session.prototype.onLostConnection = function () {
+ console.warn('Lost connection in Session ' + this.sessionId);
+ if (!!this.sessionId && !this.connection.disposed) {
+ this.leave(true, 'networkDisconnect');
+ }
+ };
+ Session.prototype.onRecoveredConnection = function () {
+ console.warn('Recovered connection in Session ' + this.sessionId);
+ this.ee.emitEvent('connectionRecovered', []);
+ };
+ Session.prototype.onMediaError = function (params) {
+ console.error('Media error: ' + JSON.stringify(params));
+ var err = params.error;
+ if (err) {
+ this.ee.emitEvent('error-media', [{
+ error: err
+ }]);
+ }
+ else {
+ console.warn('Received undefined media error. Params:', params);
+ }
+ };
+ Session.prototype.onRecordingStarted = function (response) {
+ this.ee.emitEvent('recordingStarted', [new RecordingEvent_1.RecordingEvent(this, 'recordingStarted', response.id, response.name)]);
+ };
+ Session.prototype.onRecordingStopped = function (response) {
+ this.ee.emitEvent('recordingStopped', [new RecordingEvent_1.RecordingEvent(this, 'recordingStopped', response.id, response.name)]);
+ };
+ Session.prototype.emitEvent = function (type, eventArray) {
+ this.ee.emitEvent(type, eventArray);
+ };
+ Session.prototype.leave = function (forced, reason) {
+ var _this = this;
+ forced = !!forced;
+ console.info('Leaving Session (forced=' + forced + ')');
+ if (!!this.connection) {
+ if (!this.connection.disposed && !forced) {
+ this.openvidu.sendRequest('leaveRoom', function (error, response) {
+ if (error) {
+ console.error(error);
+ }
+ _this.openvidu.closeWs();
+ });
+ }
+ else {
+ this.openvidu.closeWs();
+ }
+ this.stopPublisherStream(reason);
+ if (!this.connection.disposed) {
+ var sessionDisconnectEvent = new SessionDisconnectedEvent_1.SessionDisconnectedEvent(this, reason);
+ this.ee.emitEvent('sessionDisconnected', [sessionDisconnectEvent]);
+ sessionDisconnectEvent.callDefaultBehavior();
+ }
+ }
+ else {
+ console.warn('You were not connected to the session ' + this.sessionId);
+ }
+ };
+ Session.prototype.connectAux = function (token) {
+ var _this = this;
+ return new Promise(function (resolve, reject) {
+ _this.openvidu.startWs(function (error) {
+ if (!!error) {
+ reject(error);
+ }
+ else {
+ var joinParams = {
+ token: (!!token) ? token : '',
+ session: _this.sessionId,
+ metadata: !!_this.options.metadata ? _this.options.metadata : '',
+ secret: _this.openvidu.getSecret(),
+ recorder: _this.openvidu.getRecorder(),
+ };
+ _this.openvidu.sendRequest('joinRoom', joinParams, function (error, response) {
+ if (!!error) {
+ reject(error);
+ }
+ else {
+ _this.capabilities = {
+ subscribe: true,
+ publish: _this.openvidu.role !== 'SUBSCRIBER',
+ forceUnpublish: _this.openvidu.role === 'MODERATOR',
+ forceDisconnect: _this.openvidu.role === 'MODERATOR'
+ };
+ _this.connection = new Connection_1.Connection(_this);
+ _this.connection.connectionId = response.id;
+ _this.connection.data = response.metadata;
+ var events_1 = {
+ connections: new Array(),
+ streams: new Array()
+ };
+ var existingParticipants = response.value;
+ existingParticipants.forEach(function (participant) {
+ var connection = new Connection_1.Connection(_this, participant);
+ _this.remoteConnections[connection.connectionId] = connection;
+ events_1.connections.push(connection);
+ if (!!connection.stream) {
+ _this.remoteStreamsCreated[connection.stream.streamId] = true;
+ events_1.streams.push(connection.stream);
+ }
+ });
+ _this.ee.emitEvent('connectionCreated', [new ConnectionEvent_1.ConnectionEvent(false, _this, 'connectionCreated', _this.connection, '')]);
+ events_1.connections.forEach(function (connection) {
+ _this.ee.emitEvent('connectionCreated', [new ConnectionEvent_1.ConnectionEvent(false, _this, 'connectionCreated', connection, '')]);
+ });
+ events_1.streams.forEach(function (stream) {
+ _this.ee.emitEvent('streamCreated', [new StreamEvent_1.StreamEvent(false, _this, 'streamCreated', stream, '')]);
+ });
+ resolve();
+ }
+ });
+ }
+ });
+ });
+ };
+ Session.prototype.stopPublisherStream = function (reason) {
+ if (!!this.connection.stream) {
+ this.connection.stream.disposeWebRtcPeer();
+ if (this.connection.stream.isLocalStreamPublished) {
+ this.connection.stream.ee.emitEvent('local-stream-destroyed', [reason]);
+ }
+ }
+ };
+ Session.prototype.stringClientMetadata = function (metadata) {
+ if (typeof metadata !== 'string') {
+ return JSON.stringify(metadata);
+ }
+ else {
+ return metadata;
+ }
+ };
+ Session.prototype.getConnection = function (connectionId, errorMessage) {
+ var _this = this;
+ return new Promise(function (resolve, reject) {
+ var connection = _this.remoteConnections[connectionId];
+ if (!!connection) {
+ resolve(connection);
+ }
+ else {
+ if (_this.connection.connectionId === connectionId) {
+ resolve(_this.connection);
+ }
+ else {
+ reject(new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.GENERIC_ERROR, errorMessage));
+ }
+ }
+ });
+ };
+ Session.prototype.getRemoteConnection = function (connectionId, errorMessage) {
+ var _this = this;
+ return new Promise(function (resolve, reject) {
+ var connection = _this.remoteConnections[connectionId];
+ if (!!connection) {
+ resolve(connection);
+ }
+ else {
+ reject(new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.GENERIC_ERROR, errorMessage));
+ }
+ });
+ };
+ Session.prototype.processToken = function (token) {
+ var url = new URL(token);
+ this.sessionId = url.searchParams.get('sessionId');
+ var secret = url.searchParams.get('secret');
+ var recorder = url.searchParams.get('recorder');
+ var turnUsername = url.searchParams.get('turnUsername');
+ var turnCredential = url.searchParams.get('turnCredential');
+ var role = url.searchParams.get('role');
+ if (!!secret) {
+ this.openvidu.secret = secret;
+ }
+ if (!!recorder) {
+ this.openvidu.recorder = true;
+ }
+ if (!!turnUsername && !!turnCredential) {
+ var stunUrl = 'stun:' + url.hostname + ':3478';
+ var turnUrl1 = 'turn:' + url.hostname + ':3478';
+ var turnUrl2 = turnUrl1 + '?transport=tcp';
+ this.openvidu.iceServers = [
+ { urls: [stunUrl] },
+ { urls: [turnUrl1, turnUrl2], username: turnUsername, credential: turnCredential }
+ ];
+ console.log('TURN temp credentials [' + turnUsername + ':' + turnCredential + ']');
+ }
+ if (!!role) {
+ this.openvidu.role = role;
+ }
+ this.openvidu.wsUri = 'wss://' + url.host + '/openvidu';
+ };
+ return Session;
+}());
+exports.Session = Session;
+
+},{"../OpenViduInternal/Enums/OpenViduError":26,"../OpenViduInternal/Enums/VideoInsertMode":27,"../OpenViduInternal/Events/ConnectionEvent":28,"../OpenViduInternal/Events/RecordingEvent":31,"../OpenViduInternal/Events/SessionDisconnectedEvent":32,"../OpenViduInternal/Events/SignalEvent":33,"../OpenViduInternal/Events/StreamEvent":34,"../OpenViduInternal/Events/StreamPropertyChangedEvent":36,"./Connection":17,"./Subscriber":24,"platform":8,"wolfy87-eventemitter":15}],22:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+var WebRtcPeer_1 = require("../OpenViduInternal/WebRtcPeer/WebRtcPeer");
+var WebRtcStats_1 = require("../OpenViduInternal/WebRtcStats/WebRtcStats");
+var PublisherSpeakingEvent_1 = require("../OpenViduInternal/Events/PublisherSpeakingEvent");
+var EventEmitter = require("wolfy87-eventemitter");
+var hark = require("hark");
+var OpenViduError_1 = require("../OpenViduInternal/Enums/OpenViduError");
+var Stream = (function () {
+ function Stream(session, options) {
+ var _this = this;
+ this.ee = new EventEmitter();
+ this.isSubscribeToRemote = false;
+ this.isLocalStreamReadyToPublish = false;
+ this.isLocalStreamPublished = false;
+ this.publishedOnce = false;
+ this.session = session;
+ if (options.hasOwnProperty('id')) {
+ this.inboundStreamOpts = options;
+ this.streamId = this.inboundStreamOpts.id;
+ this.hasAudio = this.inboundStreamOpts.hasAudio;
+ this.hasVideo = this.inboundStreamOpts.hasVideo;
+ if (this.hasAudio) {
+ this.audioActive = this.inboundStreamOpts.audioActive;
+ }
+ if (this.hasVideo) {
+ this.videoActive = this.inboundStreamOpts.videoActive;
+ this.typeOfVideo = (!this.inboundStreamOpts.typeOfVideo) ? undefined : this.inboundStreamOpts.typeOfVideo;
+ this.frameRate = (this.inboundStreamOpts.frameRate === -1) ? undefined : this.inboundStreamOpts.frameRate;
+ this.videoDimensions = this.inboundStreamOpts.videoDimensions;
+ }
+ }
+ else {
+ this.outboundStreamOpts = options;
+ this.hasAudio = this.isSendAudio();
+ this.hasVideo = this.isSendVideo();
+ if (this.hasAudio) {
+ this.audioActive = !!this.outboundStreamOpts.publisherProperties.publishAudio;
+ }
+ if (this.hasVideo) {
+ this.videoActive = !!this.outboundStreamOpts.publisherProperties.publishVideo;
+ this.frameRate = this.outboundStreamOpts.publisherProperties.frameRate;
+ if (this.outboundStreamOpts.publisherProperties.videoSource instanceof MediaStreamTrack) {
+ this.typeOfVideo = 'CUSTOM';
+ }
+ else {
+ this.typeOfVideo = this.isSendScreen() ? 'SCREEN' : 'CAMERA';
+ }
+ }
+ }
+ this.ee.on('mediastream-updated', function () {
+ _this.streamManager.updateMediaStream(_this.mediaStream);
+ console.debug('Video srcObject [' + _this.mediaStream + '] updated in stream [' + _this.streamId + ']');
+ });
+ }
+ Stream.prototype.getMediaStream = function () {
+ return this.mediaStream;
+ };
+ Stream.prototype.setMediaStream = function (mediaStream) {
+ this.mediaStream = mediaStream;
+ };
+ Stream.prototype.updateMediaStreamInVideos = function () {
+ this.ee.emitEvent('mediastream-updated');
+ };
+ Stream.prototype.getWebRtcPeer = function () {
+ return this.webRtcPeer;
+ };
+ Stream.prototype.getRTCPeerConnection = function () {
+ return this.webRtcPeer.pc;
+ };
+ Stream.prototype.subscribeToMyRemote = function (value) {
+ this.isSubscribeToRemote = value;
+ };
+ Stream.prototype.setOutboundStreamOptions = function (outboundStreamOpts) {
+ this.outboundStreamOpts = outboundStreamOpts;
+ };
+ Stream.prototype.subscribe = function () {
+ var _this = this;
+ return new Promise(function (resolve, reject) {
+ _this.initWebRtcPeerReceive()
+ .then(function () {
+ resolve();
+ })
+ .catch(function (error) {
+ reject(error);
+ });
+ });
+ };
+ Stream.prototype.publish = function () {
+ var _this = this;
+ return new Promise(function (resolve, reject) {
+ if (_this.isLocalStreamReadyToPublish) {
+ _this.initWebRtcPeerSend()
+ .then(function () {
+ resolve();
+ })
+ .catch(function (error) {
+ reject(error);
+ });
+ }
+ else {
+ _this.ee.once('stream-ready-to-publish', function () {
+ _this.publish()
+ .then(function () {
+ resolve();
+ })
+ .catch(function (error) {
+ reject(error);
+ });
+ });
+ }
+ });
+ };
+ Stream.prototype.disposeWebRtcPeer = function () {
+ if (this.webRtcPeer) {
+ this.webRtcPeer.dispose();
+ }
+ if (this.speechEvent) {
+ this.speechEvent.stop();
+ }
+ this.stopWebRtcStats();
+ console.info((!!this.outboundStreamOpts ? 'Outbound ' : 'Inbound ') + "WebRTCPeer from 'Stream' with id [" + this.streamId + '] is now closed');
+ };
+ Stream.prototype.disposeMediaStream = function () {
+ if (this.mediaStream) {
+ this.mediaStream.getAudioTracks().forEach(function (track) {
+ track.stop();
+ });
+ this.mediaStream.getVideoTracks().forEach(function (track) {
+ track.stop();
+ });
+ delete this.mediaStream;
+ }
+ console.info((!!this.outboundStreamOpts ? 'Local ' : 'Remote ') + "MediaStream from 'Stream' with id [" + this.streamId + '] is now disposed');
+ };
+ Stream.prototype.displayMyRemote = function () {
+ return this.isSubscribeToRemote;
+ };
+ Stream.prototype.isSendAudio = function () {
+ return (!!this.outboundStreamOpts &&
+ this.outboundStreamOpts.publisherProperties.audioSource !== null &&
+ this.outboundStreamOpts.publisherProperties.audioSource !== false);
+ };
+ Stream.prototype.isSendVideo = function () {
+ return (!!this.outboundStreamOpts &&
+ this.outboundStreamOpts.publisherProperties.videoSource !== null &&
+ this.outboundStreamOpts.publisherProperties.videoSource !== false);
+ };
+ Stream.prototype.isSendScreen = function () {
+ return (!!this.outboundStreamOpts &&
+ this.outboundStreamOpts.publisherProperties.videoSource === 'screen');
+ };
+ Stream.prototype.setSpeechEventIfNotExists = function () {
+ if (!this.speechEvent) {
+ var harkOptions = this.session.openvidu.advancedConfiguration.publisherSpeakingEventsOptions || {};
+ harkOptions.interval = (typeof harkOptions.interval === 'number') ? harkOptions.interval : 50;
+ harkOptions.threshold = (typeof harkOptions.threshold === 'number') ? harkOptions.threshold : -50;
+ this.speechEvent = hark(this.mediaStream, harkOptions);
+ }
+ };
+ Stream.prototype.enableSpeakingEvents = function () {
+ var _this = this;
+ this.setSpeechEventIfNotExists();
+ this.speechEvent.on('speaking', function () {
+ _this.session.emitEvent('publisherStartSpeaking', [new PublisherSpeakingEvent_1.PublisherSpeakingEvent(_this.session, 'publisherStartSpeaking', _this.connection, _this.streamId)]);
+ });
+ this.speechEvent.on('stopped_speaking', function () {
+ _this.session.emitEvent('publisherStopSpeaking', [new PublisherSpeakingEvent_1.PublisherSpeakingEvent(_this.session, 'publisherStopSpeaking', _this.connection, _this.streamId)]);
+ });
+ };
+ Stream.prototype.enableOnceSpeakingEvents = function () {
+ var _this = this;
+ this.setSpeechEventIfNotExists();
+ this.speechEvent.on('speaking', function () {
+ _this.session.emitEvent('publisherStartSpeaking', [new PublisherSpeakingEvent_1.PublisherSpeakingEvent(_this.session, 'publisherStartSpeaking', _this.connection, _this.streamId)]);
+ _this.disableSpeakingEvents();
+ });
+ this.speechEvent.on('stopped_speaking', function () {
+ _this.session.emitEvent('publisherStopSpeaking', [new PublisherSpeakingEvent_1.PublisherSpeakingEvent(_this.session, 'publisherStopSpeaking', _this.connection, _this.streamId)]);
+ _this.disableSpeakingEvents();
+ });
+ };
+ Stream.prototype.disableSpeakingEvents = function () {
+ this.speechEvent.stop();
+ this.speechEvent = undefined;
+ };
+ Stream.prototype.isLocal = function () {
+ return (!this.inboundStreamOpts && !!this.outboundStreamOpts);
+ };
+ Stream.prototype.getSelectedIceCandidate = function () {
+ var _this = this;
+ return new Promise(function (resolve, reject) {
+ _this.webRtcStats.getSelectedIceCandidateInfo()
+ .then(function (report) { return resolve(report); })
+ .catch(function (error) { return reject(error); });
+ });
+ };
+ Stream.prototype.getRemoteIceCandidateList = function () {
+ return this.webRtcPeer.remoteCandidatesQueue;
+ };
+ Stream.prototype.getLocalIceCandidateList = function () {
+ return this.webRtcPeer.localCandidatesQueue;
+ };
+ Stream.prototype.initWebRtcPeerSend = function () {
+ var _this = this;
+ return new Promise(function (resolve, reject) {
+ var userMediaConstraints = {
+ audio: _this.isSendAudio(),
+ video: _this.isSendVideo()
+ };
+ var options = {
+ mediaStream: _this.mediaStream,
+ mediaConstraints: userMediaConstraints,
+ onicecandidate: _this.connection.sendIceCandidate.bind(_this.connection),
+ iceServers: _this.getIceServersConf(),
+ simulcast: false
+ };
+ var successCallback = function (sdpOfferParam) {
+ console.debug('Sending SDP offer to publish as '
+ + _this.streamId, sdpOfferParam);
+ var typeOfVideo = '';
+ if (_this.isSendVideo()) {
+ typeOfVideo = _this.outboundStreamOpts.publisherProperties.videoSource instanceof MediaStreamTrack ? 'CUSTOM' : (_this.isSendScreen() ? 'SCREEN' : 'CAMERA');
+ }
+ _this.session.openvidu.sendRequest('publishVideo', {
+ sdpOffer: sdpOfferParam,
+ doLoopback: _this.displayMyRemote() || false,
+ hasAudio: _this.isSendAudio(),
+ hasVideo: _this.isSendVideo(),
+ audioActive: _this.audioActive,
+ videoActive: _this.videoActive,
+ typeOfVideo: typeOfVideo,
+ frameRate: !!_this.frameRate ? _this.frameRate : -1,
+ videoDimensions: JSON.stringify(_this.videoDimensions)
+ }, function (error, response) {
+ if (error) {
+ if (error.code === 401) {
+ reject(new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.OPENVIDU_PERMISSION_DENIED, "You don't have permissions to publish"));
+ }
+ else {
+ reject('Error on publishVideo: ' + JSON.stringify(error));
+ }
+ }
+ else {
+ _this.webRtcPeer.processAnswer(response.sdpAnswer)
+ .then(function () {
+ _this.streamId = response.id;
+ _this.isLocalStreamPublished = true;
+ _this.publishedOnce = true;
+ if (_this.displayMyRemote()) {
+ _this.remotePeerSuccessfullyEstablished();
+ }
+ _this.ee.emitEvent('stream-created-by-publisher');
+ _this.initWebRtcStats();
+ resolve();
+ })
+ .catch(function (error) {
+ reject(error);
+ });
+ console.info("'Publisher' successfully published to session");
+ }
+ });
+ };
+ if (_this.displayMyRemote()) {
+ _this.webRtcPeer = new WebRtcPeer_1.WebRtcPeerSendrecv(options);
+ }
+ else {
+ _this.webRtcPeer = new WebRtcPeer_1.WebRtcPeerSendonly(options);
+ }
+ _this.webRtcPeer.generateOffer().then(function (offer) {
+ successCallback(offer);
+ }).catch(function (error) {
+ reject(new Error('(publish) SDP offer error: ' + JSON.stringify(error)));
+ });
+ });
+ };
+ Stream.prototype.initWebRtcPeerReceive = function () {
+ var _this = this;
+ return new Promise(function (resolve, reject) {
+ var offerConstraints = {
+ audio: _this.inboundStreamOpts.hasAudio,
+ video: _this.inboundStreamOpts.hasVideo
+ };
+ console.debug("'Session.subscribe(Stream)' called. Constraints of generate SDP offer", offerConstraints);
+ var options = {
+ onicecandidate: _this.connection.sendIceCandidate.bind(_this.connection),
+ mediaConstraints: offerConstraints,
+ iceServers: _this.getIceServersConf(),
+ simulcast: false
+ };
+ var successCallback = function (sdpOfferParam) {
+ console.debug('Sending SDP offer to subscribe to '
+ + _this.streamId, sdpOfferParam);
+ _this.session.openvidu.sendRequest('receiveVideoFrom', {
+ sender: _this.streamId,
+ sdpOffer: sdpOfferParam
+ }, function (error, response) {
+ if (error) {
+ reject(new Error('Error on recvVideoFrom: ' + JSON.stringify(error)));
+ }
+ else {
+ _this.webRtcPeer.processAnswer(response.sdpAnswer).then(function () {
+ _this.remotePeerSuccessfullyEstablished();
+ _this.initWebRtcStats();
+ resolve();
+ }).catch(function (error) {
+ reject(error);
+ });
+ }
+ });
+ };
+ _this.webRtcPeer = new WebRtcPeer_1.WebRtcPeerRecvonly(options);
+ _this.webRtcPeer.generateOffer()
+ .then(function (offer) {
+ successCallback(offer);
+ })
+ .catch(function (error) {
+ reject(new Error('(subscribe) SDP offer error: ' + JSON.stringify(error)));
+ });
+ });
+ };
+ Stream.prototype.remotePeerSuccessfullyEstablished = function () {
+ this.mediaStream = this.webRtcPeer.pc.getRemoteStreams()[0];
+ console.debug('Peer remote stream', this.mediaStream);
+ if (!!this.mediaStream) {
+ this.ee.emitEvent('mediastream-updated');
+ if (!this.displayMyRemote() && !!this.mediaStream.getAudioTracks()[0] && this.session.speakingEventsEnabled) {
+ this.enableSpeakingEvents();
+ }
+ }
+ };
+ Stream.prototype.initWebRtcStats = function () {
+ this.webRtcStats = new WebRtcStats_1.WebRtcStats(this);
+ this.webRtcStats.initWebRtcStats();
+ };
+ Stream.prototype.stopWebRtcStats = function () {
+ if (!!this.webRtcStats && this.webRtcStats.isEnabled()) {
+ this.webRtcStats.stopWebRtcStats();
+ }
+ };
+ Stream.prototype.getIceServersConf = function () {
+ var returnValue;
+ if (!!this.session.openvidu.advancedConfiguration.iceServers) {
+ returnValue = this.session.openvidu.advancedConfiguration.iceServers === 'freeice' ?
+ undefined :
+ this.session.openvidu.advancedConfiguration.iceServers;
+ }
+ else if (this.session.openvidu.iceServers) {
+ returnValue = this.session.openvidu.iceServers;
+ }
+ else {
+ returnValue = undefined;
+ }
+ return returnValue;
+ };
+ return Stream;
+}());
+exports.Stream = Stream;
+
+},{"../OpenViduInternal/Enums/OpenViduError":26,"../OpenViduInternal/Events/PublisherSpeakingEvent":30,"../OpenViduInternal/WebRtcPeer/WebRtcPeer":49,"../OpenViduInternal/WebRtcStats/WebRtcStats":50,"hark":5,"wolfy87-eventemitter":15}],23:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+var StreamManagerEvent_1 = require("../OpenViduInternal/Events/StreamManagerEvent");
+var VideoElementEvent_1 = require("../OpenViduInternal/Events/VideoElementEvent");
+var VideoInsertMode_1 = require("../OpenViduInternal/Enums/VideoInsertMode");
+var EventEmitter = require("wolfy87-eventemitter");
+var StreamManager = (function () {
+ function StreamManager(stream, targetElement) {
+ var _this = this;
+ this.videos = [];
+ this.lazyLaunchVideoElementCreatedEvent = false;
+ this.ee = new EventEmitter();
+ this.stream = stream;
+ this.stream.streamManager = this;
+ this.remote = !this.stream.isLocal();
+ if (!!targetElement) {
+ var targEl = void 0;
+ if (typeof targetElement === 'string') {
+ targEl = document.getElementById(targetElement);
+ }
+ else if (targetElement instanceof HTMLElement) {
+ targEl = targetElement;
+ }
+ if (!!targEl) {
+ this.firstVideoElement = {
+ targetElement: targEl,
+ video: document.createElement('video'),
+ id: ''
+ };
+ this.targetElement = targEl;
+ this.element = targEl;
+ }
+ }
+ this.canPlayListener = function () {
+ if (_this.stream.isLocal()) {
+ if (!_this.stream.displayMyRemote()) {
+ console.info("Your local 'Stream' with id [" + _this.stream.streamId + '] video is now playing');
+ _this.ee.emitEvent('videoPlaying', [new VideoElementEvent_1.VideoElementEvent(_this.videos[0].video, _this, 'videoPlaying')]);
+ }
+ else {
+ console.info("Your own remote 'Stream' with id [" + _this.stream.streamId + '] video is now playing');
+ _this.ee.emitEvent('remoteVideoPlaying', [new VideoElementEvent_1.VideoElementEvent(_this.videos[0].video, _this, 'remoteVideoPlaying')]);
+ }
+ }
+ else {
+ console.info("Remote 'Stream' with id [" + _this.stream.streamId + '] video is now playing');
+ _this.ee.emitEvent('videoPlaying', [new VideoElementEvent_1.VideoElementEvent(_this.videos[0].video, _this, 'videoPlaying')]);
+ }
+ _this.ee.emitEvent('streamPlaying', [new StreamManagerEvent_1.StreamManagerEvent(_this)]);
+ };
+ }
+ StreamManager.prototype.on = function (type, handler) {
+ var _this = this;
+ this.ee.on(type, function (event) {
+ if (event) {
+ console.info("Event '" + type + "' triggered by '" + (_this.remote ? 'Subscriber' : 'Publisher') + "'", event);
+ }
+ else {
+ console.info("Event '" + type + "' triggered by '" + (_this.remote ? 'Subscriber' : 'Publisher') + "'");
+ }
+ handler(event);
+ });
+ if (type === 'videoElementCreated') {
+ if (!!this.stream && this.lazyLaunchVideoElementCreatedEvent) {
+ this.ee.emitEvent('videoElementCreated', [new VideoElementEvent_1.VideoElementEvent(this.videos[0].video, this, 'videoElementCreated')]);
+ this.lazyLaunchVideoElementCreatedEvent = false;
+ }
+ }
+ if (type === 'streamPlaying' || type === 'videoPlaying') {
+ if (this.videos[0] && this.videos[0].video &&
+ this.videos[0].video.currentTime > 0 &&
+ this.videos[0].video.paused === false &&
+ this.videos[0].video.ended === false &&
+ this.videos[0].video.readyState === 4) {
+ this.ee.emitEvent('streamPlaying', [new StreamManagerEvent_1.StreamManagerEvent(this)]);
+ this.ee.emitEvent('videoPlaying', [new VideoElementEvent_1.VideoElementEvent(this.videos[0].video, this, 'videoPlaying')]);
+ }
+ }
+ return this;
+ };
+ StreamManager.prototype.once = function (type, handler) {
+ this.ee.once(type, function (event) {
+ if (event) {
+ console.info("Event '" + type + "' triggered once", event);
+ }
+ else {
+ console.info("Event '" + type + "' triggered once");
+ }
+ handler(event);
+ });
+ if (type === 'videoElementCreated') {
+ if (!!this.stream && this.lazyLaunchVideoElementCreatedEvent) {
+ this.ee.emitEvent('videoElementCreated', [new VideoElementEvent_1.VideoElementEvent(this.videos[0].video, this, 'videoElementCreated')]);
+ }
+ }
+ if (type === 'streamPlaying' || type === 'videoPlaying') {
+ if (this.videos[0] && this.videos[0].video &&
+ this.videos[0].video.currentTime > 0 &&
+ this.videos[0].video.paused === false &&
+ this.videos[0].video.ended === false &&
+ this.videos[0].video.readyState === 4) {
+ this.ee.emitEvent('streamPlaying', [new StreamManagerEvent_1.StreamManagerEvent(this)]);
+ this.ee.emitEvent('videoPlaying', [new VideoElementEvent_1.VideoElementEvent(this.videos[0].video, this, 'videoPlaying')]);
+ }
+ }
+ return this;
+ };
+ StreamManager.prototype.off = function (type, handler) {
+ if (!handler) {
+ this.ee.removeAllListeners(type);
+ }
+ else {
+ this.ee.off(type, handler);
+ }
+ return this;
+ };
+ StreamManager.prototype.addVideoElement = function (video) {
+ this.initializeVideoProperties(video);
+ for (var _i = 0, _a = this.videos; _i < _a.length; _i++) {
+ var v = _a[_i];
+ if (v.video === video) {
+ return 0;
+ }
+ }
+ var returnNumber = 1;
+ for (var _b = 0, _c = this.stream.session.streamManagers; _b < _c.length; _b++) {
+ var streamManager = _c[_b];
+ if (streamManager.disassociateVideo(video)) {
+ returnNumber = -1;
+ break;
+ }
+ }
+ this.stream.session.streamManagers.forEach(function (streamManager) {
+ streamManager.disassociateVideo(video);
+ });
+ this.pushNewStreamManagerVideo({
+ video: video,
+ id: video.id
+ });
+ console.info('New video element associated to ', this);
+ return returnNumber;
+ };
+ StreamManager.prototype.createVideoElement = function (targetElement, insertMode) {
+ var targEl;
+ if (typeof targetElement === 'string') {
+ targEl = document.getElementById(targEl);
+ if (!targEl) {
+ throw new Error("The provided 'targetElement' couldn't be resolved to any HTML element: " + targetElement);
+ }
+ }
+ else if (targetElement instanceof HTMLElement) {
+ targEl = targetElement;
+ }
+ else {
+ throw new Error("The provided 'targetElement' couldn't be resolved to any HTML element: " + targetElement);
+ }
+ var video = document.createElement('video');
+ this.initializeVideoProperties(video);
+ var insMode = !!insertMode ? insertMode : VideoInsertMode_1.VideoInsertMode.APPEND;
+ switch (insMode) {
+ case VideoInsertMode_1.VideoInsertMode.AFTER:
+ targEl.parentNode.insertBefore(video, targEl.nextSibling);
+ break;
+ case VideoInsertMode_1.VideoInsertMode.APPEND:
+ targEl.appendChild(video);
+ break;
+ case VideoInsertMode_1.VideoInsertMode.BEFORE:
+ targEl.parentNode.insertBefore(video, targEl);
+ break;
+ case VideoInsertMode_1.VideoInsertMode.PREPEND:
+ targEl.insertBefore(video, targEl.childNodes[0]);
+ break;
+ case VideoInsertMode_1.VideoInsertMode.REPLACE:
+ targEl.parentNode.replaceChild(video, targEl);
+ break;
+ default:
+ insMode = VideoInsertMode_1.VideoInsertMode.APPEND;
+ targEl.appendChild(video);
+ break;
+ }
+ var v = {
+ targetElement: targEl,
+ video: video,
+ insertMode: insMode,
+ id: video.id
+ };
+ this.pushNewStreamManagerVideo(v);
+ this.ee.emitEvent('videoElementCreated', [new VideoElementEvent_1.VideoElementEvent(v.video, this, 'videoElementCreated')]);
+ this.lazyLaunchVideoElementCreatedEvent = !!this.firstVideoElement;
+ return video;
+ };
+ StreamManager.prototype.initializeVideoProperties = function (video) {
+ if (!(this.stream.isLocal() && this.stream.displayMyRemote())) {
+ video.srcObject = this.stream.getMediaStream();
+ }
+ video.autoplay = true;
+ video.controls = false;
+ if (!video.id) {
+ video.id = (this.remote ? 'remote-' : 'local-') + 'video-' + this.stream.streamId;
+ if (!this.id && !!this.targetElement) {
+ this.id = video.id;
+ }
+ }
+ if (!this.remote && !this.stream.displayMyRemote()) {
+ video.muted = true;
+ if (this.stream.outboundStreamOpts.publisherProperties.mirror) {
+ this.mirrorVideo(video);
+ }
+ }
+ };
+ StreamManager.prototype.removeAllVideos = function () {
+ var _this = this;
+ for (var i = this.stream.session.streamManagers.length - 1; i >= 0; --i) {
+ if (this.stream.session.streamManagers[i] === this) {
+ this.stream.session.streamManagers.splice(i, 1);
+ }
+ }
+ this.videos.forEach(function (streamManagerVideo) {
+ streamManagerVideo.video.removeEventListener('canplay', _this.canPlayListener);
+ if (!!streamManagerVideo.targetElement) {
+ streamManagerVideo.video.parentNode.removeChild(streamManagerVideo.video);
+ _this.ee.emitEvent('videoElementDestroyed', [new VideoElementEvent_1.VideoElementEvent(streamManagerVideo.video, _this, 'videoElementDestroyed')]);
+ }
+ streamManagerVideo.video.srcObject = null;
+ _this.videos.filter(function (v) { return !v.targetElement; });
+ });
+ };
+ StreamManager.prototype.disassociateVideo = function (video) {
+ var disassociated = false;
+ for (var i = 0; i < this.videos.length; i++) {
+ if (this.videos[i].video === video) {
+ this.videos.splice(i, 1);
+ disassociated = true;
+ console.info('Video element disassociated from ', this);
+ break;
+ }
+ }
+ return disassociated;
+ };
+ StreamManager.prototype.addPlayEventToFirstVideo = function () {
+ if ((!!this.videos[0]) && (!!this.videos[0].video) && (this.videos[0].video.oncanplay === null)) {
+ this.videos[0].video.addEventListener('canplay', this.canPlayListener);
+ }
+ };
+ StreamManager.prototype.updateMediaStream = function (mediaStream) {
+ this.videos.forEach(function (streamManagerVideo) {
+ streamManagerVideo.video.srcObject = mediaStream;
+ });
+ };
+ StreamManager.prototype.emitEvent = function (type, eventArray) {
+ this.ee.emitEvent(type, eventArray);
+ };
+ StreamManager.prototype.pushNewStreamManagerVideo = function (streamManagerVideo) {
+ this.videos.push(streamManagerVideo);
+ this.addPlayEventToFirstVideo();
+ if (this.stream.session.streamManagers.indexOf(this) === -1) {
+ this.stream.session.streamManagers.push(this);
+ }
+ };
+ StreamManager.prototype.mirrorVideo = function (video) {
+ video.style.transform = 'rotateY(180deg)';
+ video.style.webkitTransform = 'rotateY(180deg)';
+ };
+ return StreamManager;
+}());
+exports.StreamManager = StreamManager;
+
+},{"../OpenViduInternal/Enums/VideoInsertMode":27,"../OpenViduInternal/Events/StreamManagerEvent":35,"../OpenViduInternal/Events/VideoElementEvent":37,"wolfy87-eventemitter":15}],24:[function(require,module,exports){
+"use strict";
+var __extends = (this && this.__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 __());
+ };
+})();
+Object.defineProperty(exports, "__esModule", { value: true });
+var StreamManager_1 = require("./StreamManager");
+var Subscriber = (function (_super) {
+ __extends(Subscriber, _super);
+ function Subscriber(stream, targEl, properties) {
+ var _this = _super.call(this, stream, targEl) || this;
+ _this.element = _this.targetElement;
+ _this.stream = stream;
+ _this.properties = properties;
+ return _this;
+ }
+ Subscriber.prototype.subscribeToAudio = function (value) {
+ this.stream.getMediaStream().getAudioTracks().forEach(function (track) {
+ track.enabled = value;
+ });
+ console.info("'Subscriber' has " + (value ? 'subscribed to' : 'unsubscribed from') + ' its audio stream');
+ return this;
+ };
+ Subscriber.prototype.subscribeToVideo = function (value) {
+ this.stream.getMediaStream().getVideoTracks().forEach(function (track) {
+ track.enabled = value;
+ });
+ console.info("'Subscriber' has " + (value ? 'subscribed to' : 'unsubscribed from') + ' its video stream');
+ return this;
+ };
+ return Subscriber;
+}(StreamManager_1.StreamManager));
+exports.Subscriber = Subscriber;
+
+},{"./StreamManager":23}],25:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+var LocalRecorderState;
+(function (LocalRecorderState) {
+ LocalRecorderState["READY"] = "READY";
+ LocalRecorderState["RECORDING"] = "RECORDING";
+ LocalRecorderState["PAUSED"] = "PAUSED";
+ LocalRecorderState["FINISHED"] = "FINISHED";
+})(LocalRecorderState = exports.LocalRecorderState || (exports.LocalRecorderState = {}));
+
+},{}],26:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+var OpenViduErrorName;
+(function (OpenViduErrorName) {
+ OpenViduErrorName["BROWSER_NOT_SUPPORTED"] = "BROWSER_NOT_SUPPORTED";
+ OpenViduErrorName["DEVICE_ACCESS_DENIED"] = "DEVICE_ACCESS_DENIED";
+ OpenViduErrorName["SCREEN_CAPTURE_DENIED"] = "SCREEN_CAPTURE_DENIED";
+ OpenViduErrorName["SCREEN_SHARING_NOT_SUPPORTED"] = "SCREEN_SHARING_NOT_SUPPORTED";
+ OpenViduErrorName["SCREEN_EXTENSION_NOT_INSTALLED"] = "SCREEN_EXTENSION_NOT_INSTALLED";
+ OpenViduErrorName["SCREEN_EXTENSION_DISABLED"] = "SCREEN_EXTENSION_DISABLED";
+ OpenViduErrorName["INPUT_VIDEO_DEVICE_NOT_FOUND"] = "INPUT_VIDEO_DEVICE_NOT_FOUND";
+ OpenViduErrorName["INPUT_AUDIO_DEVICE_NOT_FOUND"] = "INPUT_AUDIO_DEVICE_NOT_FOUND";
+ OpenViduErrorName["NO_INPUT_SOURCE_SET"] = "NO_INPUT_SOURCE_SET";
+ OpenViduErrorName["PUBLISHER_PROPERTIES_ERROR"] = "PUBLISHER_PROPERTIES_ERROR";
+ OpenViduErrorName["OPENVIDU_PERMISSION_DENIED"] = "OPENVIDU_PERMISSION_DENIED";
+ OpenViduErrorName["OPENVIDU_NOT_CONNECTED"] = "OPENVIDU_NOT_CONNECTED";
+ OpenViduErrorName["GENERIC_ERROR"] = "GENERIC_ERROR";
+})(OpenViduErrorName = exports.OpenViduErrorName || (exports.OpenViduErrorName = {}));
+var OpenViduError = (function () {
+ function OpenViduError(name, message) {
+ this.name = name;
+ this.message = message;
+ }
+ return OpenViduError;
+}());
+exports.OpenViduError = OpenViduError;
+
+},{}],27:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+var VideoInsertMode;
+(function (VideoInsertMode) {
+ VideoInsertMode["AFTER"] = "AFTER";
+ VideoInsertMode["APPEND"] = "APPEND";
+ VideoInsertMode["BEFORE"] = "BEFORE";
+ VideoInsertMode["PREPEND"] = "PREPEND";
+ VideoInsertMode["REPLACE"] = "REPLACE";
+})(VideoInsertMode = exports.VideoInsertMode || (exports.VideoInsertMode = {}));
+
+},{}],28:[function(require,module,exports){
+"use strict";
+var __extends = (this && this.__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 __());
+ };
+})();
+Object.defineProperty(exports, "__esModule", { value: true });
+var Event_1 = require("./Event");
+var ConnectionEvent = (function (_super) {
+ __extends(ConnectionEvent, _super);
+ function ConnectionEvent(cancelable, target, type, connection, reason) {
+ var _this = _super.call(this, cancelable, target, type) || this;
+ _this.connection = connection;
+ _this.reason = reason;
+ return _this;
+ }
+ ConnectionEvent.prototype.callDefaultBehavior = function () { };
+ return ConnectionEvent;
+}(Event_1.Event));
+exports.ConnectionEvent = ConnectionEvent;
+
+},{"./Event":29}],29:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+var Event = (function () {
+ function Event(cancelable, target, type) {
+ this.hasBeenPrevented = false;
+ this.cancelable = cancelable;
+ this.target = target;
+ this.type = type;
+ }
+ Event.prototype.isDefaultPrevented = function () {
+ return this.hasBeenPrevented;
+ };
+ Event.prototype.preventDefault = function () {
+ this.callDefaultBehavior = function () { };
+ this.hasBeenPrevented = true;
+ };
+ return Event;
+}());
+exports.Event = Event;
+
+},{}],30:[function(require,module,exports){
+"use strict";
+var __extends = (this && this.__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 __());
+ };
+})();
+Object.defineProperty(exports, "__esModule", { value: true });
+var Event_1 = require("./Event");
+var PublisherSpeakingEvent = (function (_super) {
+ __extends(PublisherSpeakingEvent, _super);
+ function PublisherSpeakingEvent(target, type, connection, streamId) {
+ var _this = _super.call(this, false, target, type) || this;
+ _this.type = type;
+ _this.connection = connection;
+ _this.streamId = streamId;
+ return _this;
+ }
+ PublisherSpeakingEvent.prototype.callDefaultBehavior = function () { };
+ return PublisherSpeakingEvent;
+}(Event_1.Event));
+exports.PublisherSpeakingEvent = PublisherSpeakingEvent;
+
+},{"./Event":29}],31:[function(require,module,exports){
+"use strict";
+var __extends = (this && this.__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 __());
+ };
+})();
+Object.defineProperty(exports, "__esModule", { value: true });
+var Event_1 = require("./Event");
+var RecordingEvent = (function (_super) {
+ __extends(RecordingEvent, _super);
+ function RecordingEvent(target, type, id, name) {
+ var _this = _super.call(this, false, target, type) || this;
+ _this.id = id;
+ if (name !== id) {
+ _this.name = name;
+ }
+ return _this;
+ }
+ RecordingEvent.prototype.callDefaultBehavior = function () { };
+ return RecordingEvent;
+}(Event_1.Event));
+exports.RecordingEvent = RecordingEvent;
+
+},{"./Event":29}],32:[function(require,module,exports){
+"use strict";
+var __extends = (this && this.__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 __());
+ };
+})();
+Object.defineProperty(exports, "__esModule", { value: true });
+var Event_1 = require("./Event");
+var SessionDisconnectedEvent = (function (_super) {
+ __extends(SessionDisconnectedEvent, _super);
+ function SessionDisconnectedEvent(target, reason) {
+ var _this = _super.call(this, true, target, 'sessionDisconnected') || this;
+ _this.reason = reason;
+ return _this;
+ }
+ SessionDisconnectedEvent.prototype.callDefaultBehavior = function () {
+ console.info("Calling default behavior upon '" + this.type + "' event dispatched by 'Session'");
+ var session = this.target;
+ for (var connectionId in session.remoteConnections) {
+ if (!!session.remoteConnections[connectionId].stream) {
+ session.remoteConnections[connectionId].stream.disposeWebRtcPeer();
+ session.remoteConnections[connectionId].stream.disposeMediaStream();
+ if (session.remoteConnections[connectionId].stream.streamManager) {
+ session.remoteConnections[connectionId].stream.streamManager.removeAllVideos();
+ }
+ delete session.remoteStreamsCreated[session.remoteConnections[connectionId].stream.streamId];
+ session.remoteConnections[connectionId].dispose();
+ }
+ delete session.remoteConnections[connectionId];
+ }
+ };
+ return SessionDisconnectedEvent;
+}(Event_1.Event));
+exports.SessionDisconnectedEvent = SessionDisconnectedEvent;
+
+},{"./Event":29}],33:[function(require,module,exports){
+"use strict";
+var __extends = (this && this.__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 __());
+ };
+})();
+Object.defineProperty(exports, "__esModule", { value: true });
+var Event_1 = require("./Event");
+var SignalEvent = (function (_super) {
+ __extends(SignalEvent, _super);
+ function SignalEvent(target, type, data, from) {
+ var _this = _super.call(this, false, target, type) || this;
+ _this.type = type;
+ _this.data = data;
+ _this.from = from;
+ return _this;
+ }
+ SignalEvent.prototype.callDefaultBehavior = function () { };
+ return SignalEvent;
+}(Event_1.Event));
+exports.SignalEvent = SignalEvent;
+
+},{"./Event":29}],34:[function(require,module,exports){
+"use strict";
+var __extends = (this && this.__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 __());
+ };
+})();
+Object.defineProperty(exports, "__esModule", { value: true });
+var Event_1 = require("./Event");
+var Publisher_1 = require("../../OpenVidu/Publisher");
+var Session_1 = require("../../OpenVidu/Session");
+var StreamEvent = (function (_super) {
+ __extends(StreamEvent, _super);
+ function StreamEvent(cancelable, target, type, stream, reason) {
+ var _this = _super.call(this, cancelable, target, type) || this;
+ _this.stream = stream;
+ _this.reason = reason;
+ return _this;
+ }
+ StreamEvent.prototype.callDefaultBehavior = function () {
+ if (this.type === 'streamDestroyed') {
+ if (this.target instanceof Session_1.Session) {
+ console.info("Calling default behavior upon '" + this.type + "' event dispatched by 'Session'");
+ this.stream.disposeWebRtcPeer();
+ }
+ else if (this.target instanceof Publisher_1.Publisher) {
+ console.info("Calling default behavior upon '" + this.type + "' event dispatched by 'Publisher'");
+ clearInterval(this.target.screenShareResizeInterval);
+ this.stream.isLocalStreamReadyToPublish = false;
+ var openviduPublishers = this.target.openvidu.publishers;
+ for (var i = 0; i < openviduPublishers.length; i++) {
+ if (openviduPublishers[i] === this.target) {
+ openviduPublishers.splice(i, 1);
+ break;
+ }
+ }
+ }
+ this.stream.disposeMediaStream();
+ if (this.stream.streamManager)
+ this.stream.streamManager.removeAllVideos();
+ delete this.stream.session.remoteStreamsCreated[this.stream.streamId];
+ var remoteConnection = this.stream.session.remoteConnections[this.stream.connection.connectionId];
+ if (!!remoteConnection && !!remoteConnection.options) {
+ var streamOptionsServer = remoteConnection.options.streams;
+ for (var i = streamOptionsServer.length - 1; i >= 0; --i) {
+ if (streamOptionsServer[i].id === this.stream.streamId) {
+ streamOptionsServer.splice(i, 1);
+ }
+ }
+ }
+ }
+ };
+ return StreamEvent;
+}(Event_1.Event));
+exports.StreamEvent = StreamEvent;
+
+},{"../../OpenVidu/Publisher":20,"../../OpenVidu/Session":21,"./Event":29}],35:[function(require,module,exports){
+"use strict";
+var __extends = (this && this.__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 __());
+ };
+})();
+Object.defineProperty(exports, "__esModule", { value: true });
+var Event_1 = require("./Event");
+var StreamManagerEvent = (function (_super) {
+ __extends(StreamManagerEvent, _super);
+ function StreamManagerEvent(target) {
+ return _super.call(this, false, target, 'streamPlaying') || this;
+ }
+ StreamManagerEvent.prototype.callDefaultBehavior = function () { };
+ return StreamManagerEvent;
+}(Event_1.Event));
+exports.StreamManagerEvent = StreamManagerEvent;
+
+},{"./Event":29}],36:[function(require,module,exports){
+"use strict";
+var __extends = (this && this.__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 __());
+ };
+})();
+Object.defineProperty(exports, "__esModule", { value: true });
+var Event_1 = require("./Event");
+var StreamPropertyChangedEvent = (function (_super) {
+ __extends(StreamPropertyChangedEvent, _super);
+ function StreamPropertyChangedEvent(target, stream, changedProperty, newValue, oldValue, reason) {
+ var _this = _super.call(this, false, target, 'streamPropertyChanged') || this;
+ _this.stream = stream;
+ _this.changedProperty = changedProperty;
+ _this.newValue = newValue;
+ _this.oldValue = oldValue;
+ _this.reason = reason;
+ return _this;
+ }
+ StreamPropertyChangedEvent.prototype.callDefaultBehavior = function () { };
+ return StreamPropertyChangedEvent;
+}(Event_1.Event));
+exports.StreamPropertyChangedEvent = StreamPropertyChangedEvent;
+
+},{"./Event":29}],37:[function(require,module,exports){
+"use strict";
+var __extends = (this && this.__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 __());
+ };
+})();
+Object.defineProperty(exports, "__esModule", { value: true });
+var Event_1 = require("./Event");
+var VideoElementEvent = (function (_super) {
+ __extends(VideoElementEvent, _super);
+ function VideoElementEvent(element, target, type) {
+ var _this = _super.call(this, false, target, type) || this;
+ _this.element = element;
+ return _this;
+ }
+ VideoElementEvent.prototype.callDefaultBehavior = function () { };
+ return VideoElementEvent;
+}(Event_1.Event));
+exports.VideoElementEvent = VideoElementEvent;
+
+},{"./Event":29}],38:[function(require,module,exports){
+function Mapper() {
+ var sources = {};
+ this.forEach = function (callback) {
+ for (var key in sources) {
+ var source = sources[key];
+ for (var key2 in source)
+ callback(source[key2]);
+ }
+ ;
+ };
+ this.get = function (id, source) {
+ var ids = sources[source];
+ if (ids == undefined)
+ return undefined;
+ return ids[id];
+ };
+ this.remove = function (id, source) {
+ var ids = sources[source];
+ if (ids == undefined)
+ return;
+ delete ids[id];
+ for (var i in ids) {
+ return false;
+ }
+ delete sources[source];
+ };
+ this.set = function (value, id, source) {
+ if (value == undefined)
+ return this.remove(id, source);
+ var ids = sources[source];
+ if (ids == undefined)
+ sources[source] = ids = {};
+ ids[id] = value;
+ };
+}
+;
+Mapper.prototype.pop = function (id, source) {
+ var value = this.get(id, source);
+ if (value == undefined)
+ return undefined;
+ this.remove(id, source);
+ return value;
+};
+module.exports = Mapper;
+
+},{}],39:[function(require,module,exports){
+var JsonRpcClient = require('./jsonrpcclient');
+exports.JsonRpcClient = JsonRpcClient;
+
+},{"./jsonrpcclient":40}],40:[function(require,module,exports){
+var RpcBuilder = require('../');
+var WebSocketWithReconnection = require('./transports/webSocketWithReconnection');
+Date.now = Date.now || function () {
+ return +new Date;
+};
+var PING_INTERVAL = 5000;
+var RECONNECTING = 'RECONNECTING';
+var CONNECTED = 'CONNECTED';
+var DISCONNECTED = 'DISCONNECTED';
+var Logger = console;
+function JsonRpcClient(configuration) {
+ var self = this;
+ var wsConfig = configuration.ws;
+ var notReconnectIfNumLessThan = -1;
+ var pingNextNum = 0;
+ var enabledPings = true;
+ var pingPongStarted = false;
+ var pingInterval;
+ var status = DISCONNECTED;
+ var onreconnecting = wsConfig.onreconnecting;
+ var onreconnected = wsConfig.onreconnected;
+ var onconnected = wsConfig.onconnected;
+ var onerror = wsConfig.onerror;
+ configuration.rpc.pull = function (params, request) {
+ request.reply(null, "push");
+ };
+ wsConfig.onreconnecting = function () {
+ Logger.debug("--------- ONRECONNECTING -----------");
+ if (status === RECONNECTING) {
+ Logger.error("Websocket already in RECONNECTING state when receiving a new ONRECONNECTING message. Ignoring it");
+ return;
+ }
+ status = RECONNECTING;
+ if (onreconnecting) {
+ onreconnecting();
+ }
+ };
+ wsConfig.onreconnected = function () {
+ Logger.debug("--------- ONRECONNECTED -----------");
+ if (status === CONNECTED) {
+ Logger.error("Websocket already in CONNECTED state when receiving a new ONRECONNECTED message. Ignoring it");
+ return;
+ }
+ status = CONNECTED;
+ enabledPings = true;
+ updateNotReconnectIfLessThan();
+ usePing();
+ if (onreconnected) {
+ onreconnected();
+ }
+ };
+ wsConfig.onconnected = function () {
+ Logger.debug("--------- ONCONNECTED -----------");
+ if (status === CONNECTED) {
+ Logger.error("Websocket already in CONNECTED state when receiving a new ONCONNECTED message. Ignoring it");
+ return;
+ }
+ status = CONNECTED;
+ enabledPings = true;
+ usePing();
+ if (onconnected) {
+ onconnected();
+ }
+ };
+ wsConfig.onerror = function (error) {
+ Logger.debug("--------- ONERROR -----------");
+ status = DISCONNECTED;
+ if (onerror) {
+ onerror(error);
+ }
+ };
+ var ws = new WebSocketWithReconnection(wsConfig);
+ Logger.debug('Connecting websocket to URI: ' + wsConfig.uri);
+ var rpcBuilderOptions = {
+ request_timeout: configuration.rpc.requestTimeout,
+ ping_request_timeout: configuration.rpc.heartbeatRequestTimeout
+ };
+ var rpc = new RpcBuilder(RpcBuilder.packers.JsonRPC, rpcBuilderOptions, ws, function (request) {
+ Logger.debug('Received request: ' + JSON.stringify(request));
+ try {
+ var func = configuration.rpc[request.method];
+ if (func === undefined) {
+ Logger.error("Method " + request.method + " not registered in client");
+ }
+ else {
+ func(request.params, request);
+ }
+ }
+ catch (err) {
+ Logger.error('Exception processing request: ' + JSON.stringify(request));
+ Logger.error(err);
+ }
+ });
+ this.send = function (method, params, callback) {
+ if (method !== 'ping') {
+ Logger.debug('Request: method:' + method + " params:" + JSON.stringify(params));
+ }
+ var requestTime = Date.now();
+ rpc.encode(method, params, function (error, result) {
+ if (error) {
+ try {
+ Logger.error("ERROR:" + error.message + " in Request: method:" +
+ method + " params:" + JSON.stringify(params) + " request:" +
+ error.request);
+ if (error.data) {
+ Logger.error("ERROR DATA:" + JSON.stringify(error.data));
+ }
+ }
+ catch (e) { }
+ error.requestTime = requestTime;
+ }
+ if (callback) {
+ if (result != undefined && result.value !== 'pong') {
+ Logger.debug('Response: ' + JSON.stringify(result));
+ }
+ callback(error, result);
+ }
+ });
+ };
+ function updateNotReconnectIfLessThan() {
+ Logger.debug("notReconnectIfNumLessThan = " + pingNextNum + ' (old=' +
+ notReconnectIfNumLessThan + ')');
+ notReconnectIfNumLessThan = pingNextNum;
+ }
+ function sendPing() {
+ if (enabledPings) {
+ var params = null;
+ if (pingNextNum == 0 || pingNextNum == notReconnectIfNumLessThan) {
+ params = {
+ interval: configuration.heartbeat || PING_INTERVAL
+ };
+ }
+ pingNextNum++;
+ self.send('ping', params, (function (pingNum) {
+ return function (error, result) {
+ if (error) {
+ Logger.debug("Error in ping request #" + pingNum + " (" +
+ error.message + ")");
+ if (pingNum > notReconnectIfNumLessThan) {
+ enabledPings = false;
+ updateNotReconnectIfLessThan();
+ Logger.debug("Server did not respond to ping message #" +
+ pingNum + ". Reconnecting... ");
+ ws.reconnectWs();
+ }
+ }
+ };
+ })(pingNextNum));
+ }
+ else {
+ Logger.debug("Trying to send ping, but ping is not enabled");
+ }
+ }
+ function usePing() {
+ if (!pingPongStarted) {
+ Logger.debug("Starting ping (if configured)");
+ pingPongStarted = true;
+ if (configuration.heartbeat != undefined) {
+ pingInterval = setInterval(sendPing, configuration.heartbeat);
+ sendPing();
+ }
+ }
+ }
+ this.close = function () {
+ Logger.debug("Closing jsonRpcClient explicitly by client");
+ if (pingInterval != undefined) {
+ Logger.debug("Clearing ping interval");
+ clearInterval(pingInterval);
+ }
+ pingPongStarted = false;
+ enabledPings = false;
+ if (configuration.sendCloseMessage) {
+ Logger.debug("Sending close message");
+ this.send('closeSession', null, function (error, result) {
+ if (error) {
+ Logger.error("Error sending close message: " + JSON.stringify(error));
+ }
+ ws.close();
+ });
+ }
+ else {
+ ws.close();
+ }
+ };
+ this.forceClose = function (millis) {
+ ws.forceClose(millis);
+ };
+ this.reconnect = function () {
+ ws.reconnectWs();
+ };
+}
+module.exports = JsonRpcClient;
+
+},{"../":43,"./transports/webSocketWithReconnection":42}],41:[function(require,module,exports){
+var WebSocketWithReconnection = require('./webSocketWithReconnection');
+exports.WebSocketWithReconnection = WebSocketWithReconnection;
+
+},{"./webSocketWithReconnection":42}],42:[function(require,module,exports){
+(function (global){
+"use strict";
+var BrowserWebSocket = global.WebSocket || global.MozWebSocket;
+var Logger = console;
+var MAX_RETRIES = 2000;
+var RETRY_TIME_MS = 3000;
+var CONNECTING = 0;
+var OPEN = 1;
+var CLOSING = 2;
+var CLOSED = 3;
+function WebSocketWithReconnection(config) {
+ var closing = false;
+ var registerMessageHandler;
+ var wsUri = config.uri;
+ var useSockJS = config.useSockJS;
+ var reconnecting = false;
+ var forcingDisconnection = false;
+ var ws;
+ if (useSockJS) {
+ ws = new SockJS(wsUri);
+ }
+ else {
+ ws = new WebSocket(wsUri);
+ }
+ ws.onopen = function () {
+ logConnected(ws, wsUri);
+ if (config.onconnected) {
+ config.onconnected();
+ }
+ };
+ ws.onerror = function (error) {
+ Logger.error("Could not connect to " + wsUri + " (invoking onerror if defined)", error);
+ if (config.onerror) {
+ config.onerror(error);
+ }
+ };
+ function logConnected(ws, wsUri) {
+ try {
+ Logger.debug("WebSocket connected to " + wsUri);
+ }
+ catch (e) {
+ Logger.error(e);
+ }
+ }
+ var reconnectionOnClose = function () {
+ if (ws.readyState === CLOSED) {
+ if (closing) {
+ Logger.debug("Connection closed by user");
+ }
+ else {
+ Logger.debug("Connection closed unexpectecly. Reconnecting...");
+ reconnectToSameUri(MAX_RETRIES, 1);
+ }
+ }
+ else {
+ Logger.debug("Close callback from previous websocket. Ignoring it");
+ }
+ };
+ ws.onclose = reconnectionOnClose;
+ function reconnectToSameUri(maxRetries, numRetries) {
+ Logger.debug("reconnectToSameUri (attempt #" + numRetries + ", max=" + maxRetries + ")");
+ if (numRetries === 1) {
+ if (reconnecting) {
+ Logger.warn("Trying to reconnectToNewUri when reconnecting... Ignoring this reconnection.");
+ return;
+ }
+ else {
+ reconnecting = true;
+ }
+ if (config.onreconnecting) {
+ config.onreconnecting();
+ }
+ }
+ if (forcingDisconnection) {
+ reconnectToNewUri(maxRetries, numRetries, wsUri);
+ }
+ else {
+ if (config.newWsUriOnReconnection) {
+ config.newWsUriOnReconnection(function (error, newWsUri) {
+ if (error) {
+ Logger.debug(error);
+ setTimeout(function () {
+ reconnectToSameUri(maxRetries, numRetries + 1);
+ }, RETRY_TIME_MS);
+ }
+ else {
+ reconnectToNewUri(maxRetries, numRetries, newWsUri);
+ }
+ });
+ }
+ else {
+ reconnectToNewUri(maxRetries, numRetries, wsUri);
+ }
+ }
+ }
+ function reconnectToNewUri(maxRetries, numRetries, reconnectWsUri) {
+ Logger.debug("Reconnection attempt #" + numRetries);
+ ws.close();
+ wsUri = reconnectWsUri || wsUri;
+ var newWs;
+ if (useSockJS) {
+ newWs = new SockJS(wsUri);
+ }
+ else {
+ newWs = new WebSocket(wsUri);
+ }
+ newWs.onopen = function () {
+ Logger.debug("Reconnected after " + numRetries + " attempts...");
+ logConnected(newWs, wsUri);
+ reconnecting = false;
+ registerMessageHandler();
+ if (config.onreconnected()) {
+ config.onreconnected();
+ }
+ newWs.onclose = reconnectionOnClose;
+ };
+ var onErrorOrClose = function (error) {
+ Logger.warn("Reconnection error: ", error);
+ if (numRetries === maxRetries) {
+ if (config.ondisconnect) {
+ config.ondisconnect();
+ }
+ }
+ else {
+ setTimeout(function () {
+ reconnectToSameUri(maxRetries, numRetries + 1);
+ }, RETRY_TIME_MS);
+ }
+ };
+ newWs.onerror = onErrorOrClose;
+ ws = newWs;
+ }
+ this.close = function () {
+ closing = true;
+ ws.close();
+ };
+ this.forceClose = function (millis) {
+ Logger.debug("Testing: Force WebSocket close");
+ if (millis) {
+ Logger.debug("Testing: Change wsUri for " + millis + " millis to simulate net failure");
+ var goodWsUri = wsUri;
+ wsUri = "wss://21.234.12.34.4:443/";
+ forcingDisconnection = true;
+ setTimeout(function () {
+ Logger.debug("Testing: Recover good wsUri " + goodWsUri);
+ wsUri = goodWsUri;
+ forcingDisconnection = false;
+ }, millis);
+ }
+ ws.close();
+ };
+ this.reconnectWs = function () {
+ Logger.debug("reconnectWs");
+ reconnectToSameUri(MAX_RETRIES, 1);
+ };
+ this.send = function (message) {
+ ws.send(message);
+ };
+ this.addEventListener = function (type, callback) {
+ registerMessageHandler = function () {
+ ws.addEventListener(type, callback);
+ };
+ registerMessageHandler();
+ };
+}
+module.exports = WebSocketWithReconnection;
+
+}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
+
+},{}],43:[function(require,module,exports){
+var defineProperty_IE8 = false;
+if (Object.defineProperty) {
+ try {
+ Object.defineProperty({}, "x", {});
+ }
+ catch (e) {
+ defineProperty_IE8 = true;
+ }
+}
+if (!Function.prototype.bind) {
+ Function.prototype.bind = function (oThis) {
+ if (typeof this !== 'function') {
+ throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable');
+ }
+ var aArgs = Array.prototype.slice.call(arguments, 1), fToBind = this, fNOP = function () { }, fBound = function () {
+ return fToBind.apply(this instanceof fNOP && oThis
+ ? this
+ : oThis, aArgs.concat(Array.prototype.slice.call(arguments)));
+ };
+ fNOP.prototype = this.prototype;
+ fBound.prototype = new fNOP();
+ return fBound;
+ };
+}
+var EventEmitter = require('events').EventEmitter;
+var inherits = require('inherits');
+var packers = require('./packers');
+var Mapper = require('./Mapper');
+var BASE_TIMEOUT = 5000;
+function unifyResponseMethods(responseMethods) {
+ if (!responseMethods)
+ return {};
+ for (var key in responseMethods) {
+ var value = responseMethods[key];
+ if (typeof value == 'string')
+ responseMethods[key] =
+ {
+ response: value
+ };
+ }
+ ;
+ return responseMethods;
+}
+;
+function unifyTransport(transport) {
+ if (!transport)
+ return;
+ if (transport instanceof Function)
+ return { send: transport };
+ if (transport.send instanceof Function)
+ return transport;
+ if (transport.postMessage instanceof Function) {
+ transport.send = transport.postMessage;
+ return transport;
+ }
+ if (transport.write instanceof Function) {
+ transport.send = transport.write;
+ return transport;
+ }
+ if (transport.onmessage !== undefined)
+ return;
+ if (transport.pause instanceof Function)
+ return;
+ throw new SyntaxError("Transport is not a function nor a valid object");
+}
+;
+function RpcNotification(method, params) {
+ if (defineProperty_IE8) {
+ this.method = method;
+ this.params = params;
+ }
+ else {
+ Object.defineProperty(this, 'method', { value: method, enumerable: true });
+ Object.defineProperty(this, 'params', { value: params, enumerable: true });
+ }
+}
+;
+function RpcBuilder(packer, options, transport, onRequest) {
+ var self = this;
+ if (!packer)
+ throw new SyntaxError('Packer is not defined');
+ if (!packer.pack || !packer.unpack)
+ throw new SyntaxError('Packer is invalid');
+ var responseMethods = unifyResponseMethods(packer.responseMethods);
+ if (options instanceof Function) {
+ if (transport != undefined)
+ throw new SyntaxError("There can't be parameters after onRequest");
+ onRequest = options;
+ transport = undefined;
+ options = undefined;
+ }
+ ;
+ if (options && options.send instanceof Function) {
+ if (transport && !(transport instanceof Function))
+ throw new SyntaxError("Only a function can be after transport");
+ onRequest = transport;
+ transport = options;
+ options = undefined;
+ }
+ ;
+ if (transport instanceof Function) {
+ if (onRequest != undefined)
+ throw new SyntaxError("There can't be parameters after onRequest");
+ onRequest = transport;
+ transport = undefined;
+ }
+ ;
+ if (transport && transport.send instanceof Function)
+ if (onRequest && !(onRequest instanceof Function))
+ throw new SyntaxError("Only a function can be after transport");
+ options = options || {};
+ EventEmitter.call(this);
+ if (onRequest)
+ this.on('request', onRequest);
+ if (defineProperty_IE8)
+ this.peerID = options.peerID;
+ else
+ Object.defineProperty(this, 'peerID', { value: options.peerID });
+ var max_retries = options.max_retries || 0;
+ function transportMessage(event) {
+ self.decode(event.data || event);
+ }
+ ;
+ this.getTransport = function () {
+ return transport;
+ };
+ this.setTransport = function (value) {
+ if (transport) {
+ if (transport.removeEventListener)
+ transport.removeEventListener('message', transportMessage);
+ else if (transport.removeListener)
+ transport.removeListener('data', transportMessage);
+ }
+ ;
+ if (value) {
+ if (value.addEventListener)
+ value.addEventListener('message', transportMessage);
+ else if (value.addListener)
+ value.addListener('data', transportMessage);
+ }
+ ;
+ transport = unifyTransport(value);
+ };
+ if (!defineProperty_IE8)
+ Object.defineProperty(this, 'transport', {
+ get: this.getTransport.bind(this),
+ set: this.setTransport.bind(this)
+ });
+ this.setTransport(transport);
+ var request_timeout = options.request_timeout || BASE_TIMEOUT;
+ var ping_request_timeout = options.ping_request_timeout || request_timeout;
+ var response_timeout = options.response_timeout || BASE_TIMEOUT;
+ var duplicates_timeout = options.duplicates_timeout || BASE_TIMEOUT;
+ var requestID = 0;
+ var requests = new Mapper();
+ var responses = new Mapper();
+ var processedResponses = new Mapper();
+ var message2Key = {};
+ function storeResponse(message, id, dest) {
+ var response = {
+ message: message,
+ timeout: setTimeout(function () {
+ responses.remove(id, dest);
+ }, response_timeout)
+ };
+ responses.set(response, id, dest);
+ }
+ ;
+ function storeProcessedResponse(ack, from) {
+ var timeout = setTimeout(function () {
+ processedResponses.remove(ack, from);
+ }, duplicates_timeout);
+ processedResponses.set(timeout, ack, from);
+ }
+ ;
+ function RpcRequest(method, params, id, from, transport) {
+ RpcNotification.call(this, method, params);
+ this.getTransport = function () {
+ return transport;
+ };
+ this.setTransport = function (value) {
+ transport = unifyTransport(value);
+ };
+ if (!defineProperty_IE8)
+ Object.defineProperty(this, 'transport', {
+ get: this.getTransport.bind(this),
+ set: this.setTransport.bind(this)
+ });
+ var response = responses.get(id, from);
+ if (!(transport || self.getTransport())) {
+ if (defineProperty_IE8)
+ this.duplicated = Boolean(response);
+ else
+ Object.defineProperty(this, 'duplicated', {
+ value: Boolean(response)
+ });
+ }
+ var responseMethod = responseMethods[method];
+ this.pack = packer.pack.bind(packer, this, id);
+ this.reply = function (error, result, transport) {
+ if (error instanceof Function || error && error.send instanceof Function) {
+ if (result != undefined)
+ throw new SyntaxError("There can't be parameters after callback");
+ transport = error;
+ result = null;
+ error = undefined;
+ }
+ else if (result instanceof Function
+ || result && result.send instanceof Function) {
+ if (transport != undefined)
+ throw new SyntaxError("There can't be parameters after callback");
+ transport = result;
+ result = null;
+ }
+ ;
+ transport = unifyTransport(transport);
+ if (response)
+ clearTimeout(response.timeout);
+ if (from != undefined) {
+ if (error)
+ error.dest = from;
+ if (result)
+ result.dest = from;
+ }
+ ;
+ var message;
+ if (error || result != undefined) {
+ if (self.peerID != undefined) {
+ if (error)
+ error.from = self.peerID;
+ else
+ result.from = self.peerID;
+ }
+ if (responseMethod) {
+ if (responseMethod.error == undefined && error)
+ message =
+ {
+ error: error
+ };
+ else {
+ var method = error
+ ? responseMethod.error
+ : responseMethod.response;
+ message =
+ {
+ method: method,
+ params: error || result
+ };
+ }
+ }
+ else
+ message =
+ {
+ error: error,
+ result: result
+ };
+ message = packer.pack(message, id);
+ }
+ else if (response)
+ message = response.message;
+ else
+ message = packer.pack({ result: null }, id);
+ storeResponse(message, id, from);
+ transport = transport || this.getTransport() || self.getTransport();
+ if (transport)
+ return transport.send(message);
+ return message;
+ };
+ }
+ ;
+ inherits(RpcRequest, RpcNotification);
+ function cancel(message) {
+ var key = message2Key[message];
+ if (!key)
+ return;
+ delete message2Key[message];
+ var request = requests.pop(key.id, key.dest);
+ if (!request)
+ return;
+ clearTimeout(request.timeout);
+ storeProcessedResponse(key.id, key.dest);
+ }
+ ;
+ this.cancel = function (message) {
+ if (message)
+ return cancel(message);
+ for (var message in message2Key)
+ cancel(message);
+ };
+ this.close = function () {
+ var transport = this.getTransport();
+ if (transport && transport.close)
+ transport.close();
+ this.cancel();
+ processedResponses.forEach(clearTimeout);
+ responses.forEach(function (response) {
+ clearTimeout(response.timeout);
+ });
+ };
+ this.encode = function (method, params, dest, transport, callback) {
+ if (params instanceof Function) {
+ if (dest != undefined)
+ throw new SyntaxError("There can't be parameters after callback");
+ callback = params;
+ transport = undefined;
+ dest = undefined;
+ params = undefined;
+ }
+ else if (dest instanceof Function) {
+ if (transport != undefined)
+ throw new SyntaxError("There can't be parameters after callback");
+ callback = dest;
+ transport = undefined;
+ dest = undefined;
+ }
+ else if (transport instanceof Function) {
+ if (callback != undefined)
+ throw new SyntaxError("There can't be parameters after callback");
+ callback = transport;
+ transport = undefined;
+ }
+ ;
+ if (self.peerID != undefined) {
+ params = params || {};
+ params.from = self.peerID;
+ }
+ ;
+ if (dest != undefined) {
+ params = params || {};
+ params.dest = dest;
+ }
+ ;
+ var message = {
+ method: method,
+ params: params
+ };
+ if (callback) {
+ var id = requestID++;
+ var retried = 0;
+ message = packer.pack(message, id);
+ function dispatchCallback(error, result) {
+ self.cancel(message);
+ callback(error, result);
+ }
+ ;
+ var request = {
+ message: message,
+ callback: dispatchCallback,
+ responseMethods: responseMethods[method] || {}
+ };
+ var encode_transport = unifyTransport(transport);
+ function sendRequest(transport) {
+ var rt = (method === 'ping' ? ping_request_timeout : request_timeout);
+ request.timeout = setTimeout(timeout, rt * Math.pow(2, retried++));
+ message2Key[message] = { id: id, dest: dest };
+ requests.set(request, id, dest);
+ transport = transport || encode_transport || self.getTransport();
+ if (transport)
+ return transport.send(message);
+ return message;
+ }
+ ;
+ function retry(transport) {
+ transport = unifyTransport(transport);
+ console.warn(retried + ' retry for request message:', message);
+ var timeout = processedResponses.pop(id, dest);
+ clearTimeout(timeout);
+ return sendRequest(transport);
+ }
+ ;
+ function timeout() {
+ if (retried < max_retries)
+ return retry(transport);
+ var error = new Error('Request has timed out');
+ error.request = message;
+ error.retry = retry;
+ dispatchCallback(error);
+ }
+ ;
+ return sendRequest(transport);
+ }
+ ;
+ message = packer.pack(message);
+ transport = transport || this.getTransport();
+ if (transport)
+ return transport.send(message);
+ return message;
+ };
+ this.decode = function (message, transport) {
+ if (!message)
+ throw new TypeError("Message is not defined");
+ try {
+ message = packer.unpack(message);
+ }
+ catch (e) {
+ return console.debug(e, message);
+ }
+ ;
+ var id = message.id;
+ var ack = message.ack;
+ var method = message.method;
+ var params = message.params || {};
+ var from = params.from;
+ var dest = params.dest;
+ if (self.peerID != undefined && from == self.peerID)
+ return;
+ if (id == undefined && ack == undefined) {
+ var notification = new RpcNotification(method, params);
+ if (self.emit('request', notification))
+ return;
+ return notification;
+ }
+ ;
+ function processRequest() {
+ transport = unifyTransport(transport) || self.getTransport();
+ if (transport) {
+ var response = responses.get(id, from);
+ if (response)
+ return transport.send(response.message);
+ }
+ ;
+ var idAck = (id != undefined) ? id : ack;
+ var request = new RpcRequest(method, params, idAck, from, transport);
+ if (self.emit('request', request))
+ return;
+ return request;
+ }
+ ;
+ function processResponse(request, error, result) {
+ request.callback(error, result);
+ }
+ ;
+ function duplicatedResponse(timeout) {
+ console.warn("Response already processed", message);
+ clearTimeout(timeout);
+ storeProcessedResponse(ack, from);
+ }
+ ;
+ if (method) {
+ if (dest == undefined || dest == self.peerID) {
+ var request = requests.get(ack, from);
+ if (request) {
+ var responseMethods = request.responseMethods;
+ if (method == responseMethods.error)
+ return processResponse(request, params);
+ if (method == responseMethods.response)
+ return processResponse(request, null, params);
+ return processRequest();
+ }
+ var processed = processedResponses.get(ack, from);
+ if (processed)
+ return duplicatedResponse(processed);
+ }
+ return processRequest();
+ }
+ ;
+ var error = message.error;
+ var result = message.result;
+ if (error && error.dest && error.dest != self.peerID)
+ return;
+ if (result && result.dest && result.dest != self.peerID)
+ return;
+ var request = requests.get(ack, from);
+ if (!request) {
+ var processed = processedResponses.get(ack, from);
+ if (processed)
+ return duplicatedResponse(processed);
+ return console.warn("No callback was defined for this message", message);
+ }
+ ;
+ processResponse(request, error, result);
+ };
+}
+;
+inherits(RpcBuilder, EventEmitter);
+RpcBuilder.RpcNotification = RpcNotification;
+module.exports = RpcBuilder;
+var clients = require('./clients');
+var transports = require('./clients/transports');
+RpcBuilder.clients = clients;
+RpcBuilder.clients.transports = transports;
+RpcBuilder.packers = packers;
+
+},{"./Mapper":38,"./clients":39,"./clients/transports":41,"./packers":46,"events":1,"inherits":6}],44:[function(require,module,exports){
+function pack(message, id) {
+ var result = {
+ jsonrpc: "2.0"
+ };
+ if (message.method) {
+ result.method = message.method;
+ if (message.params)
+ result.params = message.params;
+ if (id != undefined)
+ result.id = id;
+ }
+ else if (id != undefined) {
+ if (message.error) {
+ if (message.result !== undefined)
+ throw new TypeError("Both result and error are defined");
+ result.error = message.error;
+ }
+ else if (message.result !== undefined)
+ result.result = message.result;
+ else
+ throw new TypeError("No result or error is defined");
+ result.id = id;
+ }
+ ;
+ return JSON.stringify(result);
+}
+;
+function unpack(message) {
+ var result = message;
+ if (typeof message === 'string' || message instanceof String) {
+ result = JSON.parse(message);
+ }
+ var version = result.jsonrpc;
+ if (version !== '2.0')
+ throw new TypeError("Invalid JsonRPC version '" + version + "': " + message);
+ if (result.method == undefined) {
+ if (result.id == undefined)
+ throw new TypeError("Invalid message: " + message);
+ var result_defined = result.result !== undefined;
+ var error_defined = result.error !== undefined;
+ if (result_defined && error_defined)
+ throw new TypeError("Both result and error are defined: " + message);
+ if (!result_defined && !error_defined)
+ throw new TypeError("No result or error is defined: " + message);
+ result.ack = result.id;
+ delete result.id;
+ }
+ return result;
+}
+;
+exports.pack = pack;
+exports.unpack = unpack;
+
+},{}],45:[function(require,module,exports){
+function pack(message) {
+ throw new TypeError("Not yet implemented");
+}
+;
+function unpack(message) {
+ throw new TypeError("Not yet implemented");
+}
+;
+exports.pack = pack;
+exports.unpack = unpack;
+
+},{}],46:[function(require,module,exports){
+var JsonRPC = require('./JsonRPC');
+var XmlRPC = require('./XmlRPC');
+exports.JsonRPC = JsonRPC;
+exports.XmlRPC = XmlRPC;
+
+},{"./JsonRPC":44,"./XmlRPC":45}],47:[function(require,module,exports){
+window.getScreenId = function (callback, custom_parameter) {
+ if (navigator.userAgent.indexOf('Edge') !== -1 && (!!navigator.msSaveOrOpenBlob || !!navigator.msSaveBlob)) {
+ callback({
+ video: true
+ });
+ return;
+ }
+ if (!!navigator.mozGetUserMedia) {
+ callback(null, 'firefox', {
+ video: {
+ mozMediaSource: 'window',
+ mediaSource: 'window'
+ }
+ });
+ return;
+ }
+ window.addEventListener('message', onIFrameCallback);
+ function onIFrameCallback(event) {
+ if (!event.data)
+ return;
+ if (event.data.chromeMediaSourceId) {
+ if (event.data.chromeMediaSourceId === 'PermissionDeniedError') {
+ callback('permission-denied');
+ }
+ else {
+ callback(null, event.data.chromeMediaSourceId, getScreenConstraints(null, event.data.chromeMediaSourceId, event.data.canRequestAudioTrack));
+ }
+ window.removeEventListener('message', onIFrameCallback);
+ }
+ if (event.data.chromeExtensionStatus) {
+ callback(event.data.chromeExtensionStatus, null, getScreenConstraints(event.data.chromeExtensionStatus));
+ window.removeEventListener('message', onIFrameCallback);
+ }
+ }
+ if (!custom_parameter) {
+ setTimeout(postGetSourceIdMessage, 100);
+ }
+ else {
+ setTimeout(function () {
+ postGetSourceIdMessage(custom_parameter);
+ }, 100);
+ }
+};
+function getScreenConstraints(error, sourceId, canRequestAudioTrack) {
+ var screen_constraints = {
+ audio: false,
+ video: {
+ mandatory: {
+ chromeMediaSource: error ? 'screen' : 'desktop',
+ maxWidth: window.screen.width > 1920 ? window.screen.width : 1920,
+ maxHeight: window.screen.height > 1080 ? window.screen.height : 1080
+ },
+ optional: []
+ }
+ };
+ if (!!canRequestAudioTrack) {
+ screen_constraints.audio = {
+ mandatory: {
+ chromeMediaSource: error ? 'screen' : 'desktop',
+ },
+ optional: []
+ };
+ }
+ if (sourceId) {
+ screen_constraints.video.mandatory.chromeMediaSourceId = sourceId;
+ if (screen_constraints.audio && screen_constraints.audio.mandatory) {
+ screen_constraints.audio.mandatory.chromeMediaSourceId = sourceId;
+ }
+ }
+ return screen_constraints;
+}
+function postGetSourceIdMessage(custom_parameter) {
+ if (!iframe) {
+ loadIFrame(function () {
+ postGetSourceIdMessage(custom_parameter);
+ });
+ return;
+ }
+ if (!iframe.isLoaded) {
+ setTimeout(function () {
+ postGetSourceIdMessage(custom_parameter);
+ }, 100);
+ return;
+ }
+ if (!custom_parameter) {
+ iframe.contentWindow.postMessage({
+ captureSourceId: true
+ }, '*');
+ }
+ else if (!!custom_parameter.forEach) {
+ iframe.contentWindow.postMessage({
+ captureCustomSourceId: custom_parameter
+ }, '*');
+ }
+ else {
+ iframe.contentWindow.postMessage({
+ captureSourceIdWithAudio: true
+ }, '*');
+ }
+}
+var iframe;
+window.getScreenConstraints = function (callback) {
+ loadIFrame(function () {
+ getScreenId(function (error, sourceId, screen_constraints) {
+ if (!screen_constraints) {
+ screen_constraints = {
+ video: true
+ };
+ }
+ callback(error, screen_constraints.video);
+ });
+ });
+};
+function loadIFrame(loadCallback) {
+ if (iframe) {
+ loadCallback();
+ return;
+ }
+ iframe = document.createElement('iframe');
+ iframe.onload = function () {
+ iframe.isLoaded = true;
+ loadCallback();
+ };
+ iframe.src = 'https://openvidu.github.io/openvidu-screen-sharing-chrome-extension/';
+ iframe.style.display = 'none';
+ (document.body || document.documentElement).appendChild(iframe);
+}
+window.getChromeExtensionStatus = function (callback) {
+ if (!!navigator.mozGetUserMedia) {
+ callback('installed-enabled');
+ return;
+ }
+ window.addEventListener('message', onIFrameCallback);
+ function onIFrameCallback(event) {
+ if (!event.data)
+ return;
+ if (event.data.chromeExtensionStatus) {
+ callback(event.data.chromeExtensionStatus);
+ window.removeEventListener('message', onIFrameCallback);
+ }
+ }
+ setTimeout(postGetChromeExtensionStatusMessage, 100);
+};
+function postGetChromeExtensionStatusMessage() {
+ if (!iframe) {
+ loadIFrame(postGetChromeExtensionStatusMessage);
+ return;
+ }
+ if (!iframe.isLoaded) {
+ setTimeout(postGetChromeExtensionStatusMessage, 100);
+ return;
+ }
+ iframe.contentWindow.postMessage({
+ getChromeExtensionStatus: true
+ }, '*');
+}
+exports.getScreenId = getScreenId;
+
+},{}],48:[function(require,module,exports){
+var chromeMediaSource = 'screen';
+var sourceId;
+var screenCallback;
+var isFirefox = typeof window.InstallTrigger !== 'undefined';
+var isOpera = !!window.opera || navigator.userAgent.indexOf(' OPR/') >= 0;
+var isChrome = !!window.chrome && !isOpera;
+window.addEventListener('message', function (event) {
+ if (event.origin != window.location.origin) {
+ return;
+ }
+ onMessageCallback(event.data);
+});
+function onMessageCallback(data) {
+ if (data == 'PermissionDeniedError') {
+ if (screenCallback)
+ return screenCallback('PermissionDeniedError');
+ else
+ throw new Error('PermissionDeniedError');
+ }
+ if (data == 'rtcmulticonnection-extension-loaded') {
+ chromeMediaSource = 'desktop';
+ }
+ if (data.sourceId && screenCallback) {
+ screenCallback(sourceId = data.sourceId, data.canRequestAudioTrack === true);
+ }
+}
+function isChromeExtensionAvailable(callback) {
+ if (!callback)
+ return;
+ if (chromeMediaSource == 'desktop')
+ return callback(true);
+ window.postMessage('are-you-there', '*');
+ setTimeout(function () {
+ if (chromeMediaSource == 'screen') {
+ callback(false);
+ }
+ else
+ callback(true);
+ }, 2000);
+}
+function getSourceId(callback) {
+ if (!callback)
+ throw '"callback" parameter is mandatory.';
+ if (sourceId)
+ return callback(sourceId);
+ screenCallback = callback;
+ window.postMessage('get-sourceId', '*');
+}
+function getCustomSourceId(arr, callback) {
+ if (!arr || !arr.forEach)
+ throw '"arr" parameter is mandatory and it must be an array.';
+ if (!callback)
+ throw '"callback" parameter is mandatory.';
+ if (sourceId)
+ return callback(sourceId);
+ screenCallback = callback;
+ window.postMessage({
+ 'get-custom-sourceId': arr
+ }, '*');
+}
+function getSourceIdWithAudio(callback) {
+ if (!callback)
+ throw '"callback" parameter is mandatory.';
+ if (sourceId)
+ return callback(sourceId);
+ screenCallback = callback;
+ window.postMessage('audio-plus-tab', '*');
+}
+function getChromeExtensionStatus(extensionid, callback) {
+ if (isFirefox)
+ return callback('not-chrome');
+ if (arguments.length != 2) {
+ callback = extensionid;
+ extensionid = 'lfcgfepafnobdloecchnfaclibenjold';
+ }
+ var image = document.createElement('img');
+ image.src = 'chrome-extension://' + extensionid + '/icon.png';
+ image.onload = function () {
+ chromeMediaSource = 'screen';
+ window.postMessage('are-you-there', '*');
+ setTimeout(function () {
+ if (chromeMediaSource == 'screen') {
+ callback('installed-disabled');
+ }
+ else
+ callback('installed-enabled');
+ }, 2000);
+ };
+ image.onerror = function () {
+ callback('not-installed');
+ };
+}
+function getScreenConstraintsWithAudio(callback) {
+ getScreenConstraints(callback, true);
+}
+function getScreenConstraints(callback, captureSourceIdWithAudio) {
+ sourceId = '';
+ var firefoxScreenConstraints = {
+ mozMediaSource: 'window',
+ mediaSource: 'window'
+ };
+ if (isFirefox)
+ return callback(null, firefoxScreenConstraints);
+ var screen_constraints = {
+ mandatory: {
+ chromeMediaSource: chromeMediaSource,
+ maxWidth: screen.width > 1920 ? screen.width : 1920,
+ maxHeight: screen.height > 1080 ? screen.height : 1080
+ },
+ optional: []
+ };
+ if (chromeMediaSource == 'desktop' && !sourceId) {
+ if (captureSourceIdWithAudio) {
+ getSourceIdWithAudio(function (sourceId, canRequestAudioTrack) {
+ screen_constraints.mandatory.chromeMediaSourceId = sourceId;
+ if (canRequestAudioTrack) {
+ screen_constraints.canRequestAudioTrack = true;
+ }
+ callback(sourceId == 'PermissionDeniedError' ? sourceId : null, screen_constraints);
+ });
+ }
+ else {
+ getSourceId(function (sourceId) {
+ screen_constraints.mandatory.chromeMediaSourceId = sourceId;
+ callback(sourceId == 'PermissionDeniedError' ? sourceId : null, screen_constraints);
+ });
+ }
+ return;
+ }
+ if (chromeMediaSource == 'desktop') {
+ screen_constraints.mandatory.chromeMediaSourceId = sourceId;
+ }
+ callback(null, screen_constraints);
+}
+exports.getScreenConstraints = getScreenConstraints;
+exports.getScreenConstraintsWithAudio = getScreenConstraintsWithAudio;
+exports.isChromeExtensionAvailable = isChromeExtensionAvailable;
+exports.getChromeExtensionStatus = getChromeExtensionStatus;
+exports.getSourceId = getSourceId;
+
+},{}],49:[function(require,module,exports){
+"use strict";
+var __extends = (this && this.__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 __());
+ };
+})();
+Object.defineProperty(exports, "__esModule", { value: true });
+var freeice = require("freeice");
+var uuid = require("uuid");
+var platform = require("platform");
+var WebRtcPeer = (function () {
+ function WebRtcPeer(configuration) {
+ var _this = this;
+ this.configuration = configuration;
+ this.remoteCandidatesQueue = [];
+ this.localCandidatesQueue = [];
+ this.iceCandidateList = [];
+ this.candidategatheringdone = false;
+ this.configuration.iceServers = (!!this.configuration.iceServers && this.configuration.iceServers.length > 0) ? this.configuration.iceServers : freeice();
+ this.pc = new RTCPeerConnection({ iceServers: this.configuration.iceServers });
+ this.id = !!configuration.id ? configuration.id : uuid.v4();
+ this.pc.onicecandidate = function (event) {
+ var candidate = event.candidate;
+ if (candidate) {
+ _this.localCandidatesQueue.push({ candidate: candidate.candidate });
+ _this.candidategatheringdone = false;
+ _this.configuration.onicecandidate(event.candidate);
+ }
+ else if (!_this.candidategatheringdone) {
+ _this.candidategatheringdone = true;
+ }
+ };
+ this.pc.onsignalingstatechange = function () {
+ if (_this.pc.signalingState === 'stable') {
+ while (_this.iceCandidateList.length > 0) {
+ _this.pc.addIceCandidate(_this.iceCandidateList.shift());
+ }
+ }
+ };
+ this.start();
+ }
+ WebRtcPeer.prototype.start = function () {
+ var _this = this;
+ return new Promise(function (resolve, reject) {
+ if (_this.pc.signalingState === 'closed') {
+ reject('The peer connection object is in "closed" state. This is most likely due to an invocation of the dispose method before accepting in the dialogue');
+ }
+ if (!!_this.configuration.mediaStream) {
+ _this.pc.addStream(_this.configuration.mediaStream);
+ }
+ if (_this.configuration.mode === 'sendonly' &&
+ (platform.name === 'Chrome' && platform.version.toString().substring(0, 2) === '39')) {
+ _this.configuration.mode = 'sendrecv';
+ }
+ resolve();
+ });
+ };
+ WebRtcPeer.prototype.dispose = function () {
+ var _this = this;
+ console.debug('Disposing WebRtcPeer');
+ try {
+ if (this.pc) {
+ if (this.pc.signalingState === 'closed') {
+ return;
+ }
+ this.remoteCandidatesQueue = [];
+ this.localCandidatesQueue = [];
+ this.pc.getLocalStreams().forEach(function (str) {
+ _this.streamStop(str);
+ });
+ this.pc.close();
+ }
+ }
+ catch (err) {
+ console.warn('Exception disposing webrtc peer ' + err);
+ }
+ };
+ WebRtcPeer.prototype.generateOffer = function () {
+ var _this = this;
+ return new Promise(function (resolve, reject) {
+ var offerAudio, offerVideo = true;
+ if (!!_this.configuration.mediaConstraints) {
+ offerAudio = (typeof _this.configuration.mediaConstraints.audio === 'boolean') ?
+ _this.configuration.mediaConstraints.audio : true;
+ offerVideo = (typeof _this.configuration.mediaConstraints.video === 'boolean') ?
+ _this.configuration.mediaConstraints.video : true;
+ }
+ var constraints = {
+ offerToReceiveAudio: +(_this.configuration.mode !== 'sendonly' && offerAudio),
+ offerToReceiveVideo: +(_this.configuration.mode !== 'sendonly' && offerVideo)
+ };
+ console.debug('RTCPeerConnection constraints: ' + JSON.stringify(constraints));
+ _this.pc.createOffer(constraints).then(function (offer) {
+ console.debug('Created SDP offer');
+ return _this.pc.setLocalDescription(offer);
+ }).then(function () {
+ var localDescription = _this.pc.localDescription;
+ if (!!localDescription) {
+ console.debug('Local description set', localDescription.sdp);
+ resolve(localDescription.sdp);
+ }
+ else {
+ reject('Local description is not defined');
+ }
+ }).catch(function (error) { return reject(error); });
+ });
+ };
+ WebRtcPeer.prototype.processOffer = function (sdpOffer) {
+ var _this = this;
+ return new Promise(function (resolve, reject) {
+ var offer = {
+ type: 'offer',
+ sdp: sdpOffer
+ };
+ console.debug('SDP offer received, setting remote description');
+ if (_this.pc.signalingState === 'closed') {
+ reject('PeerConnection is closed');
+ }
+ _this.pc.setRemoteDescription(offer)
+ .then(function () {
+ return _this.pc.createAnswer();
+ }).then(function (answer) {
+ console.debug('Created SDP answer');
+ return _this.pc.setLocalDescription(answer);
+ }).then(function () {
+ var localDescription = _this.pc.localDescription;
+ if (!!localDescription) {
+ console.debug('Local description set', localDescription.sdp);
+ resolve(localDescription.sdp);
+ }
+ else {
+ reject('Local description is not defined');
+ }
+ }).catch(function (error) { return reject(error); });
+ });
+ };
+ WebRtcPeer.prototype.processAnswer = function (sdpAnswer) {
+ var _this = this;
+ return new Promise(function (resolve, reject) {
+ var answer = {
+ type: 'answer',
+ sdp: sdpAnswer
+ };
+ console.debug('SDP answer received, setting remote description');
+ if (_this.pc.signalingState === 'closed') {
+ reject('RTCPeerConnection is closed');
+ }
+ _this.pc.setRemoteDescription(answer).then(function () { return resolve(); }).catch(function (error) { return reject(error); });
+ });
+ };
+ WebRtcPeer.prototype.addIceCandidate = function (iceCandidate) {
+ var _this = this;
+ return new Promise(function (resolve, reject) {
+ console.debug('Remote ICE candidate received', iceCandidate);
+ _this.remoteCandidatesQueue.push(iceCandidate);
+ switch (_this.pc.signalingState) {
+ case 'closed':
+ reject(new Error('PeerConnection object is closed'));
+ break;
+ case 'stable':
+ if (!!_this.pc.remoteDescription) {
+ _this.pc.addIceCandidate(iceCandidate).then(function () { return resolve(); }).catch(function (error) { return reject(error); });
+ }
+ break;
+ default:
+ _this.iceCandidateList.push(iceCandidate);
+ resolve();
+ }
+ });
+ };
+ WebRtcPeer.prototype.streamStop = function (stream) {
+ stream.getTracks().forEach(function (track) {
+ track.stop();
+ stream.removeTrack(track);
+ });
+ };
+ return WebRtcPeer;
+}());
+exports.WebRtcPeer = WebRtcPeer;
+var WebRtcPeerRecvonly = (function (_super) {
+ __extends(WebRtcPeerRecvonly, _super);
+ function WebRtcPeerRecvonly(configuration) {
+ var _this = this;
+ configuration.mode = 'recvonly';
+ _this = _super.call(this, configuration) || this;
+ return _this;
+ }
+ return WebRtcPeerRecvonly;
+}(WebRtcPeer));
+exports.WebRtcPeerRecvonly = WebRtcPeerRecvonly;
+var WebRtcPeerSendonly = (function (_super) {
+ __extends(WebRtcPeerSendonly, _super);
+ function WebRtcPeerSendonly(configuration) {
+ var _this = this;
+ configuration.mode = 'sendonly';
+ _this = _super.call(this, configuration) || this;
+ return _this;
+ }
+ return WebRtcPeerSendonly;
+}(WebRtcPeer));
+exports.WebRtcPeerSendonly = WebRtcPeerSendonly;
+var WebRtcPeerSendrecv = (function (_super) {
+ __extends(WebRtcPeerSendrecv, _super);
+ function WebRtcPeerSendrecv(configuration) {
+ var _this = this;
+ configuration.mode = 'sendrecv';
+ _this = _super.call(this, configuration) || this;
+ return _this;
+ }
+ return WebRtcPeerSendrecv;
+}(WebRtcPeer));
+exports.WebRtcPeerSendrecv = WebRtcPeerSendrecv;
+
+},{"freeice":2,"platform":8,"uuid":9}],50:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+var platform = require("platform");
+var WebRtcStats = (function () {
+ function WebRtcStats(stream) {
+ this.stream = stream;
+ this.webRtcStatsEnabled = false;
+ this.statsInterval = 1;
+ this.stats = {
+ inbound: {
+ audio: {
+ bytesReceived: 0,
+ packetsReceived: 0,
+ packetsLost: 0
+ },
+ video: {
+ bytesReceived: 0,
+ packetsReceived: 0,
+ packetsLost: 0,
+ framesDecoded: 0,
+ nackCount: 0
+ }
+ },
+ outbound: {
+ audio: {
+ bytesSent: 0,
+ packetsSent: 0,
+ },
+ video: {
+ bytesSent: 0,
+ packetsSent: 0,
+ framesEncoded: 0,
+ nackCount: 0
+ }
+ }
+ };
+ }
+ WebRtcStats.prototype.isEnabled = function () {
+ return this.webRtcStatsEnabled;
+ };
+ WebRtcStats.prototype.initWebRtcStats = function () {
+ var _this = this;
+ var elastestInstrumentation = localStorage.getItem('elastest-instrumentation');
+ if (elastestInstrumentation) {
+ console.warn('WebRtc stats enabled for stream ' + this.stream.streamId + ' of connection ' + this.stream.connection.connectionId);
+ this.webRtcStatsEnabled = true;
+ var instrumentation_1 = JSON.parse(elastestInstrumentation);
+ this.statsInterval = instrumentation_1.webrtc.interval;
+ console.warn('localStorage item: ' + JSON.stringify(instrumentation_1));
+ this.webRtcStatsIntervalId = setInterval(function () {
+ _this.sendStatsToHttpEndpoint(instrumentation_1);
+ }, this.statsInterval * 1000);
+ return;
+ }
+ console.debug('WebRtc stats not enabled');
+ };
+ WebRtcStats.prototype.stopWebRtcStats = function () {
+ if (this.webRtcStatsEnabled) {
+ clearInterval(this.webRtcStatsIntervalId);
+ console.warn('WebRtc stats stopped for disposed stream ' + this.stream.streamId + ' of connection ' + this.stream.connection.connectionId);
+ }
+ };
+ WebRtcStats.prototype.getSelectedIceCandidateInfo = function () {
+ var _this = this;
+ return new Promise(function (resolve, reject) {
+ _this.getStatsAgnostic(_this.stream.getRTCPeerConnection(), function (stats) {
+ if ((platform.name.indexOf('Chrome') !== -1) || (platform.name.indexOf('Opera') !== -1)) {
+ var localCandidateId = void 0, remoteCandidateId = void 0, googCandidatePair = void 0;
+ var localCandidates = {};
+ var remoteCandidates = {};
+ for (var key in stats) {
+ var stat = stats[key];
+ if (stat.type === 'localcandidate') {
+ localCandidates[stat.id] = stat;
+ }
+ else if (stat.type === 'remotecandidate') {
+ remoteCandidates[stat.id] = stat;
+ }
+ else if (stat.type === 'googCandidatePair' && (stat.googActiveConnection === 'true')) {
+ googCandidatePair = stat;
+ localCandidateId = stat.localCandidateId;
+ remoteCandidateId = stat.remoteCandidateId;
+ }
+ }
+ var finalLocalCandidate_1 = localCandidates[localCandidateId];
+ if (!!finalLocalCandidate_1) {
+ var candList = _this.stream.getLocalIceCandidateList();
+ var cand = candList.filter(function (c) {
+ return (!!c.candidate &&
+ c.candidate.indexOf(finalLocalCandidate_1.ipAddress) >= 0 &&
+ c.candidate.indexOf(finalLocalCandidate_1.portNumber) >= 0 &&
+ c.candidate.indexOf(finalLocalCandidate_1.priority) >= 0);
+ });
+ finalLocalCandidate_1.raw = !!cand[0] ? cand[0].candidate : 'ERROR: Cannot find local candidate in list of sent ICE candidates';
+ }
+ else {
+ finalLocalCandidate_1 = 'ERROR: No active local ICE candidate. Probably ICE-TCP is being used';
+ }
+ var finalRemoteCandidate_1 = remoteCandidates[remoteCandidateId];
+ if (!!finalRemoteCandidate_1) {
+ var candList = _this.stream.getRemoteIceCandidateList();
+ var cand = candList.filter(function (c) {
+ return (!!c.candidate &&
+ c.candidate.indexOf(finalRemoteCandidate_1.ipAddress) >= 0 &&
+ c.candidate.indexOf(finalRemoteCandidate_1.portNumber) >= 0 &&
+ c.candidate.indexOf(finalRemoteCandidate_1.priority) >= 0);
+ });
+ finalRemoteCandidate_1.raw = !!cand[0] ? cand[0].candidate : 'ERROR: Cannot find remote candidate in list of received ICE candidates';
+ }
+ else {
+ finalRemoteCandidate_1 = 'ERROR: No active remote ICE candidate. Probably ICE-TCP is being used';
+ }
+ resolve({
+ googCandidatePair: googCandidatePair,
+ localCandidate: finalLocalCandidate_1,
+ remoteCandidate: finalRemoteCandidate_1
+ });
+ }
+ else {
+ reject('Selected ICE candidate info only available for Chrome');
+ }
+ }, function (error) {
+ reject(error);
+ });
+ });
+ };
+ WebRtcStats.prototype.sendStatsToHttpEndpoint = function (instrumentation) {
+ var _this = this;
+ var sendPost = function (json) {
+ var http = new XMLHttpRequest();
+ var url = instrumentation.webrtc.httpEndpoint;
+ http.open('POST', url, true);
+ http.setRequestHeader('Content-type', 'application/json');
+ http.onreadystatechange = function () {
+ if (http.readyState === 4 && http.status === 200) {
+ console.log('WebRtc stats successfully sent to ' + url + ' for stream ' + _this.stream.streamId + ' of connection ' + _this.stream.connection.connectionId);
+ }
+ };
+ http.send(json);
+ };
+ var f = function (stats) {
+ if (platform.name.indexOf('Firefox') !== -1) {
+ stats.forEach(function (stat) {
+ var json = {};
+ if ((stat.type === 'inbound-rtp') &&
+ (stat.nackCount !== null &&
+ stat.isRemote === false &&
+ stat.id.startsWith('inbound') &&
+ stat.remoteId.startsWith('inbound'))) {
+ var metricId = 'webrtc_inbound_' + stat.mediaType + '_' + stat.ssrc;
+ var jit = stat.jitter * 1000;
+ var metrics = {
+ bytesReceived: (stat.bytesReceived - _this.stats.inbound[stat.mediaType].bytesReceived) / _this.statsInterval,
+ jitter: jit,
+ packetsReceived: (stat.packetsReceived - _this.stats.inbound[stat.mediaType].packetsReceived) / _this.statsInterval,
+ packetsLost: (stat.packetsLost - _this.stats.inbound[stat.mediaType].packetsLost) / _this.statsInterval
+ };
+ var units = {
+ bytesReceived: 'bytes',
+ jitter: 'ms',
+ packetsReceived: 'packets',
+ packetsLost: 'packets'
+ };
+ if (stat.mediaType === 'video') {
+ metrics['framesDecoded'] = (stat.framesDecoded - _this.stats.inbound.video.framesDecoded) / _this.statsInterval;
+ metrics['nackCount'] = (stat.nackCount - _this.stats.inbound.video.nackCount) / _this.statsInterval;
+ units['framesDecoded'] = 'frames';
+ units['nackCount'] = 'packets';
+ _this.stats.inbound.video.framesDecoded = stat.framesDecoded;
+ _this.stats.inbound.video.nackCount = stat.nackCount;
+ }
+ _this.stats.inbound[stat.mediaType].bytesReceived = stat.bytesReceived;
+ _this.stats.inbound[stat.mediaType].packetsReceived = stat.packetsReceived;
+ _this.stats.inbound[stat.mediaType].packetsLost = stat.packetsLost;
+ json = {
+ '@timestamp': new Date(stat.timestamp).toISOString(),
+ 'exec': instrumentation.exec,
+ 'component': instrumentation.component,
+ 'stream': 'webRtc',
+ 'type': metricId,
+ 'stream_type': 'composed_metrics',
+ 'units': units
+ };
+ json[metricId] = metrics;
+ sendPost(JSON.stringify(json));
+ }
+ else if ((stat.type === 'outbound-rtp') &&
+ (stat.isRemote === false &&
+ stat.id.toLowerCase().includes('outbound'))) {
+ var metricId = 'webrtc_outbound_' + stat.mediaType + '_' + stat.ssrc;
+ var metrics = {
+ bytesSent: (stat.bytesSent - _this.stats.outbound[stat.mediaType].bytesSent) / _this.statsInterval,
+ packetsSent: (stat.packetsSent - _this.stats.outbound[stat.mediaType].packetsSent) / _this.statsInterval
+ };
+ var units = {
+ bytesSent: 'bytes',
+ packetsSent: 'packets'
+ };
+ if (stat.mediaType === 'video') {
+ metrics['framesEncoded'] = (stat.framesEncoded - _this.stats.outbound.video.framesEncoded) / _this.statsInterval;
+ units['framesEncoded'] = 'frames';
+ _this.stats.outbound.video.framesEncoded = stat.framesEncoded;
+ }
+ _this.stats.outbound[stat.mediaType].bytesSent = stat.bytesSent;
+ _this.stats.outbound[stat.mediaType].packetsSent = stat.packetsSent;
+ json = {
+ '@timestamp': new Date(stat.timestamp).toISOString(),
+ 'exec': instrumentation.exec,
+ 'component': instrumentation.component,
+ 'stream': 'webRtc',
+ 'type': metricId,
+ 'stream_type': 'composed_metrics',
+ 'units': units
+ };
+ json[metricId] = metrics;
+ sendPost(JSON.stringify(json));
+ }
+ });
+ }
+ else if ((platform.name.indexOf('Chrome') !== -1) || (platform.name.indexOf('Opera') !== -1)) {
+ for (var _i = 0, _a = Object.keys(stats); _i < _a.length; _i++) {
+ var key = _a[_i];
+ var stat = stats[key];
+ if (stat.type === 'ssrc') {
+ var json = {};
+ if ('bytesReceived' in stat && ((stat.mediaType === 'audio' && 'audioOutputLevel' in stat) ||
+ (stat.mediaType === 'video' && 'qpSum' in stat))) {
+ var metricId = 'webrtc_inbound_' + stat.mediaType + '_' + stat.ssrc;
+ var metrics = {
+ bytesReceived: (stat.bytesReceived - _this.stats.inbound[stat.mediaType].bytesReceived) / _this.statsInterval,
+ jitter: stat.googJitterBufferMs,
+ packetsReceived: (stat.packetsReceived - _this.stats.inbound[stat.mediaType].packetsReceived) / _this.statsInterval,
+ packetsLost: (stat.packetsLost - _this.stats.inbound[stat.mediaType].packetsLost) / _this.statsInterval
+ };
+ var units = {
+ bytesReceived: 'bytes',
+ jitter: 'ms',
+ packetsReceived: 'packets',
+ packetsLost: 'packets'
+ };
+ if (stat.mediaType === 'video') {
+ metrics['framesDecoded'] = (stat.framesDecoded - _this.stats.inbound.video.framesDecoded) / _this.statsInterval;
+ metrics['nackCount'] = (stat.googNacksSent - _this.stats.inbound.video.nackCount) / _this.statsInterval;
+ units['framesDecoded'] = 'frames';
+ units['nackCount'] = 'packets';
+ _this.stats.inbound.video.framesDecoded = stat.framesDecoded;
+ _this.stats.inbound.video.nackCount = stat.googNacksSent;
+ }
+ _this.stats.inbound[stat.mediaType].bytesReceived = stat.bytesReceived;
+ _this.stats.inbound[stat.mediaType].packetsReceived = stat.packetsReceived;
+ _this.stats.inbound[stat.mediaType].packetsLost = stat.packetsLost;
+ json = {
+ '@timestamp': new Date(stat.timestamp).toISOString(),
+ 'exec': instrumentation.exec,
+ 'component': instrumentation.component,
+ 'stream': 'webRtc',
+ 'type': metricId,
+ 'stream_type': 'composed_metrics',
+ 'units': units
+ };
+ json[metricId] = metrics;
+ sendPost(JSON.stringify(json));
+ }
+ else if ('bytesSent' in stat) {
+ var metricId = 'webrtc_outbound_' + stat.mediaType + '_' + stat.ssrc;
+ var metrics = {
+ bytesSent: (stat.bytesSent - _this.stats.outbound[stat.mediaType].bytesSent) / _this.statsInterval,
+ packetsSent: (stat.packetsSent - _this.stats.outbound[stat.mediaType].packetsSent) / _this.statsInterval
+ };
+ var units = {
+ bytesSent: 'bytes',
+ packetsSent: 'packets'
+ };
+ if (stat.mediaType === 'video') {
+ metrics['framesEncoded'] = (stat.framesEncoded - _this.stats.outbound.video.framesEncoded) / _this.statsInterval;
+ units['framesEncoded'] = 'frames';
+ _this.stats.outbound.video.framesEncoded = stat.framesEncoded;
+ }
+ _this.stats.outbound[stat.mediaType].bytesSent = stat.bytesSent;
+ _this.stats.outbound[stat.mediaType].packetsSent = stat.packetsSent;
+ json = {
+ '@timestamp': new Date(stat.timestamp).toISOString(),
+ 'exec': instrumentation.exec,
+ 'component': instrumentation.component,
+ 'stream': 'webRtc',
+ 'type': metricId,
+ 'stream_type': 'composed_metrics',
+ 'units': units
+ };
+ json[metricId] = metrics;
+ sendPost(JSON.stringify(json));
+ }
+ }
+ }
+ }
+ };
+ this.getStatsAgnostic(this.stream.getRTCPeerConnection(), f, function (error) { console.log(error); });
+ };
+ WebRtcStats.prototype.standardizeReport = function (response) {
+ console.log(response);
+ var standardReport = {};
+ if (platform.name.indexOf('Firefox') !== -1) {
+ Object.keys(response).forEach(function (key) {
+ console.log(response[key]);
+ });
+ return response;
+ }
+ response.result().forEach(function (report) {
+ var standardStats = {
+ id: report.id,
+ timestamp: report.timestamp,
+ type: report.type
+ };
+ report.names().forEach(function (name) {
+ standardStats[name] = report.stat(name);
+ });
+ standardReport[standardStats.id] = standardStats;
+ });
+ return standardReport;
+ };
+ WebRtcStats.prototype.getStatsAgnostic = function (pc, successCb, failureCb) {
+ var _this = this;
+ if (platform.name.indexOf('Firefox') !== -1) {
+ return pc.getStats(null).then(function (response) {
+ var report = _this.standardizeReport(response);
+ successCb(report);
+ }).catch(failureCb);
+ }
+ else if ((platform.name.indexOf('Chrome') !== -1) || (platform.name.indexOf('Opera') !== -1)) {
+ return pc.getStats(function (response) {
+ var report = _this.standardizeReport(response);
+ successCb(report);
+ }, null, failureCb);
+ }
+ };
+ return WebRtcStats;
+}());
+exports.WebRtcStats = WebRtcStats;
+
+},{"platform":8}]},{},[16])
+//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL25vZGVfbW9kdWxlcy9icm93c2VyLXBhY2svX3ByZWx1ZGUuanMiLCIuLi9ub2RlX21vZHVsZXMvZXZlbnRzL2V2ZW50cy5qcyIsIi4uL25vZGVfbW9kdWxlcy9mcmVlaWNlL2luZGV4LmpzIiwiLi4vbm9kZV9tb2R1bGVzL2ZyZWVpY2Uvc3R1bi5qc29uIiwiLi4vbm9kZV9tb2R1bGVzL2ZyZWVpY2UvdHVybi5qc29uIiwiLi4vbm9kZV9tb2R1bGVzL2hhcmsvaGFyay5qcyIsIi4uL25vZGVfbW9kdWxlcy9pbmhlcml0cy9pbmhlcml0c19icm93c2VyLmpzIiwiLi4vbm9kZV9tb2R1bGVzL25vcm1hbGljZS9pbmRleC5qcyIsIi4uL25vZGVfbW9kdWxlcy9wbGF0Zm9ybS9wbGF0Zm9ybS5qcyIsIi4uL25vZGVfbW9kdWxlcy91dWlkL2luZGV4LmpzIiwiLi4vbm9kZV9tb2R1bGVzL3V1aWQvbGliL2J5dGVzVG9VdWlkLmpzIiwiLi4vbm9kZV9tb2R1bGVzL3V1aWQvbGliL3JuZy1icm93c2VyLmpzIiwiLi4vbm9kZV9tb2R1bGVzL3V1aWQvdjEuanMiLCIuLi9ub2RlX21vZHVsZXMvdXVpZC92NC5qcyIsIi4uL25vZGVfbW9kdWxlcy93aWxkZW1pdHRlci93aWxkZW1pdHRlci5qcyIsIi4uL25vZGVfbW9kdWxlcy93b2xmeTg3LWV2ZW50ZW1pdHRlci9FdmVudEVtaXR0ZXIuanMiLCJNYWluLnRzIiwiT3BlblZpZHUvQ29ubmVjdGlvbi50cyIsIk9wZW5WaWR1L0xvY2FsUmVjb3JkZXIudHMiLCJPcGVuVmlkdS9PcGVuVmlkdS50cyIsIk9wZW5WaWR1L1B1Ymxpc2hlci50cyIsIk9wZW5WaWR1L1Nlc3Npb24udHMiLCJPcGVuVmlkdS9TdHJlYW0udHMiLCJPcGVuVmlkdS9TdHJlYW1NYW5hZ2VyLnRzIiwiT3BlblZpZHUvU3Vic2NyaWJlci50cyIsIk9wZW5WaWR1SW50ZXJuYWwvRW51bXMvTG9jYWxSZWNvcmRlclN0YXRlLnRzIiwiT3BlblZpZHVJbnRlcm5hbC9FbnVtcy9PcGVuVmlkdUVycm9yLnRzIiwiT3BlblZpZHVJbnRlcm5hbC9FbnVtcy9WaWRlb0luc2VydE1vZGUudHMiLCJPcGVuVmlkdUludGVybmFsL0V2ZW50cy9Db25uZWN0aW9uRXZlbnQudHMiLCJPcGVuVmlkdUludGVybmFsL0V2ZW50cy9FdmVudC50cyIsIk9wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1B1Ymxpc2hlclNwZWFraW5nRXZlbnQudHMiLCJPcGVuVmlkdUludGVybmFsL0V2ZW50cy9SZWNvcmRpbmdFdmVudC50cyIsIk9wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1Nlc3Npb25EaXNjb25uZWN0ZWRFdmVudC50cyIsIk9wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1NpZ25hbEV2ZW50LnRzIiwiT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvU3RyZWFtRXZlbnQudHMiLCJPcGVuVmlkdUludGVybmFsL0V2ZW50cy9TdHJlYW1NYW5hZ2VyRXZlbnQudHMiLCJPcGVuVmlkdUludGVybmFsL0V2ZW50cy9TdHJlYW1Qcm9wZXJ0eUNoYW5nZWRFdmVudC50cyIsIk9wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1ZpZGVvRWxlbWVudEV2ZW50LnRzIiwiT3BlblZpZHVJbnRlcm5hbC9LdXJlbnRvVXRpbHMva3VyZW50by1qc29ucnBjL01hcHBlci5qcyIsIk9wZW5WaWR1SW50ZXJuYWwvS3VyZW50b1V0aWxzL2t1cmVudG8tanNvbnJwYy9jbGllbnRzL2luZGV4LmpzIiwiT3BlblZpZHVJbnRlcm5hbC9LdXJlbnRvVXRpbHMva3VyZW50by1qc29ucnBjL2NsaWVudHMvanNvbnJwY2NsaWVudC5qcyIsIk9wZW5WaWR1SW50ZXJuYWwvS3VyZW50b1V0aWxzL2t1cmVudG8tanNvbnJwYy9jbGllbnRzL3RyYW5zcG9ydHMvaW5kZXguanMiLCJPcGVuVmlkdUludGVybmFsL0t1cmVudG9VdGlscy9rdXJlbnRvLWpzb25ycGMvY2xpZW50cy90cmFuc3BvcnRzL3dlYlNvY2tldFdpdGhSZWNvbm5lY3Rpb24uanMiLCJPcGVuVmlkdUludGVybmFsL0t1cmVudG9VdGlscy9rdXJlbnRvLWpzb25ycGMvaW5kZXguanMiLCJPcGVuVmlkdUludGVybmFsL0t1cmVudG9VdGlscy9rdXJlbnRvLWpzb25ycGMvcGFja2Vycy9Kc29uUlBDLmpzIiwiT3BlblZpZHVJbnRlcm5hbC9LdXJlbnRvVXRpbHMva3VyZW50by1qc29ucnBjL3BhY2tlcnMvWG1sUlBDLmpzIiwiT3BlblZpZHVJbnRlcm5hbC9LdXJlbnRvVXRpbHMva3VyZW50by1qc29ucnBjL3BhY2tlcnMvaW5kZXguanMiLCJPcGVuVmlkdUludGVybmFsL1NjcmVlblNoYXJpbmcvU2NyZWVuLUNhcHR1cmluZy1BdXRvLmpzIiwiT3BlblZpZHVJbnRlcm5hbC9TY3JlZW5TaGFyaW5nL1NjcmVlbi1DYXB0dXJpbmcuanMiLCJPcGVuVmlkdUludGVybmFsL1dlYlJ0Y1BlZXIvV2ViUnRjUGVlci50cyIsIk9wZW5WaWR1SW50ZXJuYWwvV2ViUnRjU3RhdHMvV2ViUnRjU3RhdHMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7QUNBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzNnQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDekdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDaEJBO0FBQ0E7O0FDREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2xKQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdkJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUM1REE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7O0FDanNDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDUkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDeEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbENBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDN0dBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM3QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDekpBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7O0FDdGVBLGdEQUErQztBQUUvQyxJQUFJLE1BQU0s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bigpe2Z1bmN0aW9uIHIoZSxuLHQpe2Z1bmN0aW9uIG8oaSxmKXtpZighbltpXSl7aWYoIWVbaV0pe3ZhciBjPVwiZnVuY3Rpb25cIj09dHlwZW9mIHJlcXVpcmUmJnJlcXVpcmU7aWYoIWYmJmMpcmV0dXJuIGMoaSwhMCk7aWYodSlyZXR1cm4gdShpLCEwKTt2YXIgYT1uZXcgRXJyb3IoXCJDYW5ub3QgZmluZCBtb2R1bGUgJ1wiK2krXCInXCIpO3Rocm93IGEuY29kZT1cIk1PRFVMRV9OT1RfRk9VTkRcIixhfXZhciBwPW5baV09e2V4cG9ydHM6e319O2VbaV1bMF0uY2FsbChwLmV4cG9ydHMsZnVuY3Rpb24ocil7dmFyIG49ZVtpXVsxXVtyXTtyZXR1cm4gbyhufHxyKX0scCxwLmV4cG9ydHMscixlLG4sdCl9cmV0dXJuIG5baV0uZXhwb3J0c31mb3IodmFyIHU9XCJmdW5jdGlvblwiPT10eXBlb2YgcmVxdWlyZSYmcmVxdWlyZSxpPTA7aTx0Lmxlbmd0aDtpKyspbyh0W2ldKTtyZXR1cm4gb31yZXR1cm4gcn0pKCkiLCIvLyBDb3B5cmlnaHQgSm95ZW50LCBJbmMuIGFuZCBvdGhlciBOb2RlIGNvbnRyaWJ1dG9ycy5cbi8vXG4vLyBQZXJtaXNzaW9uIGlzIGhlcmVieSBncmFudGVkLCBmcmVlIG9mIGNoYXJnZSwgdG8gYW55IHBlcnNvbiBvYnRhaW5pbmcgYVxuLy8gY29weSBvZiB0aGlzIHNvZnR3YXJlIGFuZCBhc3NvY2lhdGVkIGRvY3VtZW50YXRpb24gZmlsZXMgKHRoZVxuLy8gXCJTb2Z0d2FyZVwiKSwgdG8gZGVhbCBpbiB0aGUgU29mdHdhcmUgd2l0aG91dCByZXN0cmljdGlvbiwgaW5jbHVkaW5nXG4vLyB3aXRob3V0IGxpbWl0YXRpb24gdGhlIHJpZ2h0cyB0byB1c2UsIGNvcHksIG1vZGlmeSwgbWVyZ2UsIHB1Ymxpc2gsXG4vLyBkaXN0cmlidXRlLCBzdWJsaWNlbnNlLCBhbmQvb3Igc2VsbCBjb3BpZXMgb2YgdGhlIFNvZnR3YXJlLCBhbmQgdG8gcGVybWl0XG4vLyBwZXJzb25zIHRvIHdob20gdGhlIFNvZnR3YXJlIGlzIGZ1cm5pc2hlZCB0byBkbyBzbywgc3ViamVjdCB0byB0aGVcbi8vIGZvbGxvd2luZyBjb25kaXRpb25zOlxuLy9cbi8vIFRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlIGFuZCB0aGlzIHBlcm1pc3Npb24gbm90aWNlIHNoYWxsIGJlIGluY2x1ZGVkXG4vLyBpbiBhbGwgY29waWVzIG9yIHN1YnN0YW50aWFsIHBvcnRpb25zIG9mIHRoZSBTb2Z0d2FyZS5cbi8vXG4vLyBUSEUgU09GVFdBUkUgSVMgUFJPVklERUQgXCJBUyBJU1wiLCBXSVRIT1VUIFdBUlJBTlRZIE9GIEFOWSBLSU5ELCBFWFBSRVNTXG4vLyBPUiBJTVBMSUVELCBJTkNMVURJTkcgQlVUIE5PVCBMSU1JVEVEIFRPIFRIRSBXQVJSQU5USUVTIE9GXG4vLyBNRVJDSEFOVEFCSUxJVFksIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFORCBOT05JTkZSSU5HRU1FTlQuIElOXG4vLyBOTyBFVkVOVCBTSEFMTCBUSEUgQVVUSE9SUyBPUiBDT1BZUklHSFQgSE9MREVSUyBCRSBMSUFCTEUgRk9SIEFOWSBDTEFJTSxcbi8vIERBTUFHRVMgT1IgT1RIRVIgTElBQklMSVRZLCBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgVE9SVCBPUlxuLy8gT1RIRVJXSVNFLCBBUklTSU5HIEZST00sIE9VVCBPRiBPUiBJTiBDT05ORUNUSU9OIFdJVEggVEhFIFNPRlRXQVJFIE9SIFRIRVxuLy8gVVNFIE9SIE9USEVSIERFQUxJTkdTIElOIFRIRSBTT0ZUV0FSRS5cblxudmFyIG9iamVjdENyZWF0ZSA9IE9iamVjdC5jcmVhdGUgfHwgb2JqZWN0Q3JlYXRlUG9seWZpbGxcbnZhciBvYmplY3RLZXlzID0gT2JqZWN0LmtleXMgfHwgb2JqZWN0S2V5c1BvbHlmaWxsXG52YXIgYmluZCA9IEZ1bmN0aW9uLnByb3RvdHlwZS5iaW5kIHx8IGZ1bmN0aW9uQmluZFBvbHlmaWxsXG5cbmZ1bmN0aW9uIEV2ZW50RW1pdHRlcigpIHtcbiAgaWYgKCF0aGlzLl9ldmVudHMgfHwgIU9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbCh0aGlzLCAnX2V2ZW50cycpKSB7XG4gICAgdGhpcy5fZXZlbnRzID0gb2JqZWN0Q3JlYXRlKG51bGwpO1xuICAgIHRoaXMuX2V2ZW50c0NvdW50ID0gMDtcbiAgfVxuXG4gIHRoaXMuX21heExpc3RlbmVycyA9IHRoaXMuX21heExpc3RlbmVycyB8fCB1bmRlZmluZWQ7XG59XG5tb2R1bGUuZXhwb3J0cyA9IEV2ZW50RW1pdHRlcjtcblxuLy8gQmFja3dhcmRzLWNvbXBhdCB3aXRoIG5vZGUgMC4xMC54XG5FdmVudEVtaXR0ZXIuRXZlbnRFbWl0dGVyID0gRXZlbnRFbWl0dGVyO1xuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLl9ldmVudHMgPSB1bmRlZmluZWQ7XG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLl9tYXhMaXN0ZW5lcnMgPSB1bmRlZmluZWQ7XG5cbi8vIEJ5IGRlZmF1bHQgRXZlbnRFbWl0dGVycyB3aWxsIHByaW50IGEgd2FybmluZyBpZiBtb3JlIHRoYW4gMTAgbGlzdGVuZXJzIGFyZVxuLy8gYWRkZWQgdG8gaXQuIFRoaXMgaXMgYSB1c2VmdWwgZGVmYXVsdCB3aGljaCBoZWxwcyBmaW5kaW5nIG1lbW9yeSBsZWFrcy5cbnZhciBkZWZhdWx0TWF4TGlzdGVuZXJzID0gMTA7XG5cbnZhciBoYXNEZWZpbmVQcm9wZXJ0eTtcbnRyeSB7XG4gIHZhciBvID0ge307XG4gIGlmIChPYmplY3QuZGVmaW5lUHJvcGVydHkpIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShvLCAneCcsIHsgdmFsdWU6IDAgfSk7XG4gIGhhc0RlZmluZVByb3BlcnR5ID0gby54ID09PSAwO1xufSBjYXRjaCAoZXJyKSB7IGhhc0RlZmluZVByb3BlcnR5ID0gZmFsc2UgfVxuaWYgKGhhc0RlZmluZVByb3BlcnR5KSB7XG4gIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShFdmVudEVtaXR0ZXIsICdkZWZhdWx0TWF4TGlzdGVuZXJzJywge1xuICAgIGVudW1lcmFibGU6IHRydWUsXG4gICAgZ2V0OiBmdW5jdGlvbigpIHtcbiAgICAgIHJldHVybiBkZWZhdWx0TWF4TGlzdGVuZXJzO1xuICAgIH0sXG4gICAgc2V0OiBmdW5jdGlvbihhcmcpIHtcbiAgICAgIC8vIGNoZWNrIHdoZXRoZXIgdGhlIGlucHV0IGlzIGEgcG9zaXRpdmUgbnVtYmVyICh3aG9zZSB2YWx1ZSBpcyB6ZXJvIG9yXG4gICAgICAvLyBncmVhdGVyIGFuZCBub3QgYSBOYU4pLlxuICAgICAgaWYgKHR5cGVvZiBhcmcgIT09ICdudW1iZXInIHx8IGFyZyA8IDAgfHwgYXJnICE9PSBhcmcpXG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ1wiZGVmYXVsdE1heExpc3RlbmVyc1wiIG11c3QgYmUgYSBwb3NpdGl2ZSBudW1iZXInKTtcbiAgICAgIGRlZmF1bHRNYXhMaXN0ZW5lcnMgPSBhcmc7XG4gICAgfVxuICB9KTtcbn0gZWxzZSB7XG4gIEV2ZW50RW1pdHRlci5kZWZhdWx0TWF4TGlzdGVuZXJzID0gZGVmYXVsdE1heExpc3RlbmVycztcbn1cblxuLy8gT2J2aW91c2x5IG5vdCBhbGwgRW1pdHRlcnMgc2hvdWxkIGJlIGxpbWl0ZWQgdG8gMTAuIFRoaXMgZnVuY3Rpb24gYWxsb3dzXG4vLyB0aGF0IHRvIGJlIGluY3JlYXNlZC4gU2V0IHRvIHplcm8gZm9yIHVubGltaXRlZC5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUuc2V0TWF4TGlzdGVuZXJzID0gZnVuY3Rpb24gc2V0TWF4TGlzdGVuZXJzKG4pIHtcbiAgaWYgKHR5cGVvZiBuICE9PSAnbnVtYmVyJyB8fCBuIDwgMCB8fCBpc05hTihuKSlcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdcIm5cIiBhcmd1bWVudCBtdXN0IGJlIGEgcG9zaXRpdmUgbnVtYmVyJyk7XG4gIHRoaXMuX21heExpc3RlbmVycyA9IG47XG4gIHJldHVybiB0aGlzO1xufTtcblxuZnVuY3Rpb24gJGdldE1heExpc3RlbmVycyh0aGF0KSB7XG4gIGlmICh0aGF0Ll9tYXhMaXN0ZW5lcnMgPT09IHVuZGVmaW5lZClcbiAgICByZXR1cm4gRXZlbnRFbWl0dGVyLmRlZmF1bHRNYXhMaXN0ZW5lcnM7XG4gIHJldHVybiB0aGF0Ll9tYXhMaXN0ZW5lcnM7XG59XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUuZ2V0TWF4TGlzdGVuZXJzID0gZnVuY3Rpb24gZ2V0TWF4TGlzdGVuZXJzKCkge1xuICByZXR1cm4gJGdldE1heExpc3RlbmVycyh0aGlzKTtcbn07XG5cbi8vIFRoZXNlIHN0YW5kYWxvbmUgZW1pdCogZnVuY3Rpb25zIGFyZSB1c2VkIHRvIG9wdGltaXplIGNhbGxpbmcgb2YgZXZlbnRcbi8vIGhhbmRsZXJzIGZvciBmYXN0IGNhc2VzIGJlY2F1c2UgZW1pdCgpIGl0c2VsZiBvZnRlbiBoYXMgYSB2YXJpYWJsZSBudW1iZXIgb2Zcbi8vIGFyZ3VtZW50cyBhbmQgY2FuIGJlIGRlb3B0aW1pemVkIGJlY2F1c2Ugb2YgdGhhdC4gVGhlc2UgZnVuY3Rpb25zIGFsd2F5cyBoYXZlXG4vLyB0aGUgc2FtZSBudW1iZXIgb2YgYXJndW1lbnRzIGFuZCB0aHVzIGRvIG5vdCBnZXQgZGVvcHRpbWl6ZWQsIHNvIHRoZSBjb2RlXG4vLyBpbnNpZGUgdGhlbSBjYW4gZXhlY3V0ZSBmYXN0ZXIuXG5mdW5jdGlvbiBlbWl0Tm9uZShoYW5kbGVyLCBpc0ZuLCBzZWxmKSB7XG4gIGlmIChpc0ZuKVxuICAgIGhhbmRsZXIuY2FsbChzZWxmKTtcbiAgZWxzZSB7XG4gICAgdmFyIGxlbiA9IGhhbmRsZXIubGVuZ3RoO1xuICAgIHZhciBsaXN0ZW5lcnMgPSBhcnJheUNsb25lKGhhbmRsZXIsIGxlbik7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW47ICsraSlcbiAgICAgIGxpc3RlbmVyc1tpXS5jYWxsKHNlbGYpO1xuICB9XG59XG5mdW5jdGlvbiBlbWl0T25lKGhhbmRsZXIsIGlzRm4sIHNlbGYsIGFyZzEpIHtcbiAgaWYgKGlzRm4pXG4gICAgaGFuZGxlci5jYWxsKHNlbGYsIGFyZzEpO1xuICBlbHNlIHtcbiAgICB2YXIgbGVuID0gaGFuZGxlci5sZW5ndGg7XG4gICAgdmFyIGxpc3RlbmVycyA9IGFycmF5Q2xvbmUoaGFuZGxlciwgbGVuKTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgKytpKVxuICAgICAgbGlzdGVuZXJzW2ldLmNhbGwoc2VsZiwgYXJnMSk7XG4gIH1cbn1cbmZ1bmN0aW9uIGVtaXRUd28oaGFuZGxlciwgaXNGbiwgc2VsZiwgYXJnMSwgYXJnMikge1xuICBpZiAoaXNGbilcbiAgICBoYW5kbGVyLmNhbGwoc2VsZiwgYXJnMSwgYXJnMik7XG4gIGVsc2Uge1xuICAgIHZhciBsZW4gPSBoYW5kbGVyLmxlbmd0aDtcbiAgICB2YXIgbGlzdGVuZXJzID0gYXJyYXlDbG9uZShoYW5kbGVyLCBsZW4pO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuOyArK2kpXG4gICAgICBsaXN0ZW5lcnNbaV0uY2FsbChzZWxmLCBhcmcxLCBhcmcyKTtcbiAgfVxufVxuZnVuY3Rpb24gZW1pdFRocmVlKGhhbmRsZXIsIGlzRm4sIHNlbGYsIGFyZzEsIGFyZzIsIGFyZzMpIHtcbiAgaWYgKGlzRm4pXG4gICAgaGFuZGxlci5jYWxsKHNlbGYsIGFyZzEsIGFyZzIsIGFyZzMpO1xuICBlbHNlIHtcbiAgICB2YXIgbGVuID0gaGFuZGxlci5sZW5ndGg7XG4gICAgdmFyIGxpc3RlbmVycyA9IGFycmF5Q2xvbmUoaGFuZGxlciwgbGVuKTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgKytpKVxuICAgICAgbGlzdGVuZXJzW2ldLmNhbGwoc2VsZiwgYXJnMSwgYXJnMiwgYXJnMyk7XG4gIH1cbn1cblxuZnVuY3Rpb24gZW1pdE1hbnkoaGFuZGxlciwgaXNGbiwgc2VsZiwgYXJncykge1xuICBpZiAoaXNGbilcbiAgICBoYW5kbGVyLmFwcGx5KHNlbGYsIGFyZ3MpO1xuICBlbHNlIHtcbiAgICB2YXIgbGVuID0gaGFuZGxlci5sZW5ndGg7XG4gICAgdmFyIGxpc3RlbmVycyA9IGFycmF5Q2xvbmUoaGFuZGxlciwgbGVuKTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgKytpKVxuICAgICAgbGlzdGVuZXJzW2ldLmFwcGx5KHNlbGYsIGFyZ3MpO1xuICB9XG59XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUuZW1pdCA9IGZ1bmN0aW9uIGVtaXQodHlwZSkge1xuICB2YXIgZXIsIGhhbmRsZXIsIGxlbiwgYXJncywgaSwgZXZlbnRzO1xuICB2YXIgZG9FcnJvciA9ICh0eXBlID09PSAnZXJyb3InKTtcblxuICBldmVudHMgPSB0aGlzLl9ldmVudHM7XG4gIGlmIChldmVudHMpXG4gICAgZG9FcnJvciA9IChkb0Vycm9yICYmIGV2ZW50cy5lcnJvciA9PSBudWxsKTtcbiAgZWxzZSBpZiAoIWRvRXJyb3IpXG4gICAgcmV0dXJuIGZhbHNlO1xuXG4gIC8vIElmIHRoZXJlIGlzIG5vICdlcnJvcicgZXZlbnQgbGlzdGVuZXIgdGhlbiB0aHJvdy5cbiAgaWYgKGRvRXJyb3IpIHtcbiAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA+IDEpXG4gICAgICBlciA9IGFyZ3VtZW50c1sxXTtcbiAgICBpZiAoZXIgaW5zdGFuY2VvZiBFcnJvcikge1xuICAgICAgdGhyb3cgZXI7IC8vIFVuaGFuZGxlZCAnZXJyb3InIGV2ZW50XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIEF0IGxlYXN0IGdpdmUgc29tZSBraW5kIG9mIGNvbnRleHQgdG8gdGhlIHVzZXJcbiAgICAgIHZhciBlcnIgPSBuZXcgRXJyb3IoJ1VuaGFuZGxlZCBcImVycm9yXCIgZXZlbnQuICgnICsgZXIgKyAnKScpO1xuICAgICAgZXJyLmNvbnRleHQgPSBlcjtcbiAgICAgIHRocm93IGVycjtcbiAgICB9XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgaGFuZGxlciA9IGV2ZW50c1t0eXBlXTtcblxuICBpZiAoIWhhbmRsZXIpXG4gICAgcmV0dXJuIGZhbHNlO1xuXG4gIHZhciBpc0ZuID0gdHlwZW9mIGhhbmRsZXIgPT09ICdmdW5jdGlvbic7XG4gIGxlbiA9IGFyZ3VtZW50cy5sZW5ndGg7XG4gIHN3aXRjaCAobGVuKSB7XG4gICAgICAvLyBmYXN0IGNhc2VzXG4gICAgY2FzZSAxOlxuICAgICAgZW1pdE5vbmUoaGFuZGxlciwgaXNGbiwgdGhpcyk7XG4gICAgICBicmVhaztcbiAgICBjYXNlIDI6XG4gICAgICBlbWl0T25lKGhhbmRsZXIsIGlzRm4sIHRoaXMsIGFyZ3VtZW50c1sxXSk7XG4gICAgICBicmVhaztcbiAgICBjYXNlIDM6XG4gICAgICBlbWl0VHdvKGhhbmRsZXIsIGlzRm4sIHRoaXMsIGFyZ3VtZW50c1sxXSwgYXJndW1lbnRzWzJdKTtcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgNDpcbiAgICAgIGVtaXRUaHJlZShoYW5kbGVyLCBpc0ZuLCB0aGlzLCBhcmd1bWVudHNbMV0sIGFyZ3VtZW50c1syXSwgYXJndW1lbnRzWzNdKTtcbiAgICAgIGJyZWFrO1xuICAgICAgLy8gc2xvd2VyXG4gICAgZGVmYXVsdDpcbiAgICAgIGFyZ3MgPSBuZXcgQXJyYXkobGVuIC0gMSk7XG4gICAgICBmb3IgKGkgPSAxOyBpIDwgbGVuOyBpKyspXG4gICAgICAgIGFyZ3NbaSAtIDFdID0gYXJndW1lbnRzW2ldO1xuICAgICAgZW1pdE1hbnkoaGFuZGxlciwgaXNGbiwgdGhpcywgYXJncyk7XG4gIH1cblxuICByZXR1cm4gdHJ1ZTtcbn07XG5cbmZ1bmN0aW9uIF9hZGRMaXN0ZW5lcih0YXJnZXQsIHR5cGUsIGxpc3RlbmVyLCBwcmVwZW5kKSB7XG4gIHZhciBtO1xuICB2YXIgZXZlbnRzO1xuICB2YXIgZXhpc3Rpbmc7XG5cbiAgaWYgKHR5cGVvZiBsaXN0ZW5lciAhPT0gJ2Z1bmN0aW9uJylcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdcImxpc3RlbmVyXCIgYXJndW1lbnQgbXVzdCBiZSBhIGZ1bmN0aW9uJyk7XG5cbiAgZXZlbnRzID0gdGFyZ2V0Ll9ldmVudHM7XG4gIGlmICghZXZlbnRzKSB7XG4gICAgZXZlbnRzID0gdGFyZ2V0Ll9ldmVudHMgPSBvYmplY3RDcmVhdGUobnVsbCk7XG4gICAgdGFyZ2V0Ll9ldmVudHNDb3VudCA9IDA7XG4gIH0gZWxzZSB7XG4gICAgLy8gVG8gYXZvaWQgcmVjdXJzaW9uIGluIHRoZSBjYXNlIHRoYXQgdHlwZSA9PT0gXCJuZXdMaXN0ZW5lclwiISBCZWZvcmVcbiAgICAvLyBhZGRpbmcgaXQgdG8gdGhlIGxpc3RlbmVycywgZmlyc3QgZW1pdCBcIm5ld0xpc3RlbmVyXCIuXG4gICAgaWYgKGV2ZW50cy5uZXdMaXN0ZW5lcikge1xuICAgICAgdGFyZ2V0LmVtaXQoJ25ld0xpc3RlbmVyJywgdHlwZSxcbiAgICAgICAgICBsaXN0ZW5lci5saXN0ZW5lciA/IGxpc3RlbmVyLmxpc3RlbmVyIDogbGlzdGVuZXIpO1xuXG4gICAgICAvLyBSZS1hc3NpZ24gYGV2ZW50c2AgYmVjYXVzZSBhIG5ld0xpc3RlbmVyIGhhbmRsZXIgY291bGQgaGF2ZSBjYXVzZWQgdGhlXG4gICAgICAvLyB0aGlzLl9ldmVudHMgdG8gYmUgYXNzaWduZWQgdG8gYSBuZXcgb2JqZWN0XG4gICAgICBldmVudHMgPSB0YXJnZXQuX2V2ZW50cztcbiAgICB9XG4gICAgZXhpc3RpbmcgPSBldmVudHNbdHlwZV07XG4gIH1cblxuICBpZiAoIWV4aXN0aW5nKSB7XG4gICAgLy8gT3B0aW1pemUgdGhlIGNhc2Ugb2Ygb25lIGxpc3RlbmVyLiBEb24ndCBuZWVkIHRoZSBleHRyYSBhcnJheSBvYmplY3QuXG4gICAgZXhpc3RpbmcgPSBldmVudHNbdHlwZV0gPSBsaXN0ZW5lcjtcbiAgICArK3RhcmdldC5fZXZlbnRzQ291bnQ7XG4gIH0gZWxzZSB7XG4gICAgaWYgKHR5cGVvZiBleGlzdGluZyA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgLy8gQWRkaW5nIHRoZSBzZWNvbmQgZWxlbWVudCwgbmVlZCB0byBjaGFuZ2UgdG8gYXJyYXkuXG4gICAgICBleGlzdGluZyA9IGV2ZW50c1t0eXBlXSA9XG4gICAgICAgICAgcHJlcGVuZCA/IFtsaXN0ZW5lciwgZXhpc3RpbmddIDogW2V4aXN0aW5nLCBsaXN0ZW5lcl07XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIElmIHdlJ3ZlIGFscmVhZHkgZ290IGFuIGFycmF5LCBqdXN0IGFwcGVuZC5cbiAgICAgIGlmIChwcmVwZW5kKSB7XG4gICAgICAgIGV4aXN0aW5nLnVuc2hpZnQobGlzdGVuZXIpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgZXhpc3RpbmcucHVzaChsaXN0ZW5lcik7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gQ2hlY2sgZm9yIGxpc3RlbmVyIGxlYWtcbiAgICBpZiAoIWV4aXN0aW5nLndhcm5lZCkge1xuICAgICAgbSA9ICRnZXRNYXhMaXN0ZW5lcnModGFyZ2V0KTtcbiAgICAgIGlmIChtICYmIG0gPiAwICYmIGV4aXN0aW5nLmxlbmd0aCA+IG0pIHtcbiAgICAgICAgZXhpc3Rpbmcud2FybmVkID0gdHJ1ZTtcbiAgICAgICAgdmFyIHcgPSBuZXcgRXJyb3IoJ1Bvc3NpYmxlIEV2ZW50RW1pdHRlciBtZW1vcnkgbGVhayBkZXRlY3RlZC4gJyArXG4gICAgICAgICAgICBleGlzdGluZy5sZW5ndGggKyAnIFwiJyArIFN0cmluZyh0eXBlKSArICdcIiBsaXN0ZW5lcnMgJyArXG4gICAgICAgICAgICAnYWRkZWQuIFVzZSBlbWl0dGVyLnNldE1heExpc3RlbmVycygpIHRvICcgK1xuICAgICAgICAgICAgJ2luY3JlYXNlIGxpbWl0LicpO1xuICAgICAgICB3Lm5hbWUgPSAnTWF4TGlzdGVuZXJzRXhjZWVkZWRXYXJuaW5nJztcbiAgICAgICAgdy5lbWl0dGVyID0gdGFyZ2V0O1xuICAgICAgICB3LnR5cGUgPSB0eXBlO1xuICAgICAgICB3LmNvdW50ID0gZXhpc3RpbmcubGVuZ3RoO1xuICAgICAgICBpZiAodHlwZW9mIGNvbnNvbGUgPT09ICdvYmplY3QnICYmIGNvbnNvbGUud2Fybikge1xuICAgICAgICAgIGNvbnNvbGUud2FybignJXM6ICVzJywgdy5uYW1lLCB3Lm1lc3NhZ2UpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHRhcmdldDtcbn1cblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5hZGRMaXN0ZW5lciA9IGZ1bmN0aW9uIGFkZExpc3RlbmVyKHR5cGUsIGxpc3RlbmVyKSB7XG4gIHJldHVybiBfYWRkTGlzdGVuZXIodGhpcywgdHlwZSwgbGlzdGVuZXIsIGZhbHNlKTtcbn07XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUub24gPSBFdmVudEVtaXR0ZXIucHJvdG90eXBlLmFkZExpc3RlbmVyO1xuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLnByZXBlbmRMaXN0ZW5lciA9XG4gICAgZnVuY3Rpb24gcHJlcGVuZExpc3RlbmVyKHR5cGUsIGxpc3RlbmVyKSB7XG4gICAgICByZXR1cm4gX2FkZExpc3RlbmVyKHRoaXMsIHR5cGUsIGxpc3RlbmVyLCB0cnVlKTtcbiAgICB9O1xuXG5mdW5jdGlvbiBvbmNlV3JhcHBlcigpIHtcbiAgaWYgKCF0aGlzLmZpcmVkKSB7XG4gICAgdGhpcy50YXJnZXQucmVtb3ZlTGlzdGVuZXIodGhpcy50eXBlLCB0aGlzLndyYXBGbik7XG4gICAgdGhpcy5maXJlZCA9IHRydWU7XG4gICAgc3dpdGNoIChhcmd1bWVudHMubGVuZ3RoKSB7XG4gICAgICBjYXNlIDA6XG4gICAgICAgIHJldHVybiB0aGlzLmxpc3RlbmVyLmNhbGwodGhpcy50YXJnZXQpO1xuICAgICAgY2FzZSAxOlxuICAgICAgICByZXR1cm4gdGhpcy5saXN0ZW5lci5jYWxsKHRoaXMudGFyZ2V0LCBhcmd1bWVudHNbMF0pO1xuICAgICAgY2FzZSAyOlxuICAgICAgICByZXR1cm4gdGhpcy5saXN0ZW5lci5jYWxsKHRoaXMudGFyZ2V0LCBhcmd1bWVudHNbMF0sIGFyZ3VtZW50c1sxXSk7XG4gICAgICBjYXNlIDM6XG4gICAgICAgIHJldHVybiB0aGlzLmxpc3RlbmVyLmNhbGwodGhpcy50YXJnZXQsIGFyZ3VtZW50c1swXSwgYXJndW1lbnRzWzFdLFxuICAgICAgICAgICAgYXJndW1lbnRzWzJdKTtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHZhciBhcmdzID0gbmV3IEFycmF5KGFyZ3VtZW50cy5sZW5ndGgpO1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGFyZ3MubGVuZ3RoOyArK2kpXG4gICAgICAgICAgYXJnc1tpXSA9IGFyZ3VtZW50c1tpXTtcbiAgICAgICAgdGhpcy5saXN0ZW5lci5hcHBseSh0aGlzLnRhcmdldCwgYXJncyk7XG4gICAgfVxuICB9XG59XG5cbmZ1bmN0aW9uIF9vbmNlV3JhcCh0YXJnZXQsIHR5cGUsIGxpc3RlbmVyKSB7XG4gIHZhciBzdGF0ZSA9IHsgZmlyZWQ6IGZhbHNlLCB3cmFwRm46IHVuZGVmaW5lZCwgdGFyZ2V0OiB0YXJnZXQsIHR5cGU6IHR5cGUsIGxpc3RlbmVyOiBsaXN0ZW5lciB9O1xuICB2YXIgd3JhcHBlZCA9IGJpbmQuY2FsbChvbmNlV3JhcHBlciwgc3RhdGUpO1xuICB3cmFwcGVkLmxpc3RlbmVyID0gbGlzdGVuZXI7XG4gIHN0YXRlLndyYXBGbiA9IHdyYXBwZWQ7XG4gIHJldHVybiB3cmFwcGVkO1xufVxuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLm9uY2UgPSBmdW5jdGlvbiBvbmNlKHR5cGUsIGxpc3RlbmVyKSB7XG4gIGlmICh0eXBlb2YgbGlzdGVuZXIgIT09ICdmdW5jdGlvbicpXG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcignXCJsaXN0ZW5lclwiIGFyZ3VtZW50IG11c3QgYmUgYSBmdW5jdGlvbicpO1xuICB0aGlzLm9uKHR5cGUsIF9vbmNlV3JhcCh0aGlzLCB0eXBlLCBsaXN0ZW5lcikpO1xuICByZXR1cm4gdGhpcztcbn07XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUucHJlcGVuZE9uY2VMaXN0ZW5lciA9XG4gICAgZnVuY3Rpb24gcHJlcGVuZE9uY2VMaXN0ZW5lcih0eXBlLCBsaXN0ZW5lcikge1xuICAgICAgaWYgKHR5cGVvZiBsaXN0ZW5lciAhPT0gJ2Z1bmN0aW9uJylcbiAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignXCJsaXN0ZW5lclwiIGFyZ3VtZW50IG11c3QgYmUgYSBmdW5jdGlvbicpO1xuICAgICAgdGhpcy5wcmVwZW5kTGlzdGVuZXIodHlwZSwgX29uY2VXcmFwKHRoaXMsIHR5cGUsIGxpc3RlbmVyKSk7XG4gICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuXG4vLyBFbWl0cyBhICdyZW1vdmVMaXN0ZW5lcicgZXZlbnQgaWYgYW5kIG9ubHkgaWYgdGhlIGxpc3RlbmVyIHdhcyByZW1vdmVkLlxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5yZW1vdmVMaXN0ZW5lciA9XG4gICAgZnVuY3Rpb24gcmVtb3ZlTGlzdGVuZXIodHlwZSwgbGlzdGVuZXIpIHtcbiAgICAgIHZhciBsaXN0LCBldmVudHMsIHBvc2l0aW9uLCBpLCBvcmlnaW5hbExpc3RlbmVyO1xuXG4gICAgICBpZiAodHlwZW9mIGxpc3RlbmVyICE9PSAnZnVuY3Rpb24nKVxuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdcImxpc3RlbmVyXCIgYXJndW1lbnQgbXVzdCBiZSBhIGZ1bmN0aW9uJyk7XG5cbiAgICAgIGV2ZW50cyA9IHRoaXMuX2V2ZW50cztcbiAgICAgIGlmICghZXZlbnRzKVxuICAgICAgICByZXR1cm4gdGhpcztcblxuICAgICAgbGlzdCA9IGV2ZW50c1t0eXBlXTtcbiAgICAgIGlmICghbGlzdClcbiAgICAgICAgcmV0dXJuIHRoaXM7XG5cbiAgICAgIGlmIChsaXN0ID09PSBsaXN0ZW5lciB8fCBsaXN0Lmxpc3RlbmVyID09PSBsaXN0ZW5lcikge1xuICAgICAgICBpZiAoLS10aGlzLl9ldmVudHNDb3VudCA9PT0gMClcbiAgICAgICAgICB0aGlzLl9ldmVudHMgPSBvYmplY3RDcmVhdGUobnVsbCk7XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgIGRlbGV0ZSBldmVudHNbdHlwZV07XG4gICAgICAgICAgaWYgKGV2ZW50cy5yZW1vdmVMaXN0ZW5lcilcbiAgICAgICAgICAgIHRoaXMuZW1pdCgncmVtb3ZlTGlzdGVuZXInLCB0eXBlLCBsaXN0Lmxpc3RlbmVyIHx8IGxpc3RlbmVyKTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIGlmICh0eXBlb2YgbGlzdCAhPT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICBwb3NpdGlvbiA9IC0xO1xuXG4gICAgICAgIGZvciAoaSA9IGxpc3QubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgICAgICBpZiAobGlzdFtpXSA9PT0gbGlzdGVuZXIgfHwgbGlzdFtpXS5saXN0ZW5lciA9PT0gbGlzdGVuZXIpIHtcbiAgICAgICAgICAgIG9yaWdpbmFsTGlzdGVuZXIgPSBsaXN0W2ldLmxpc3RlbmVyO1xuICAgICAgICAgICAgcG9zaXRpb24gPSBpO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHBvc2l0aW9uIDwgMClcbiAgICAgICAgICByZXR1cm4gdGhpcztcblxuICAgICAgICBpZiAocG9zaXRpb24gPT09IDApXG4gICAgICAgICAgbGlzdC5zaGlmdCgpO1xuICAgICAgICBlbHNlXG4gICAgICAgICAgc3BsaWNlT25lKGxpc3QsIHBvc2l0aW9uKTtcblxuICAgICAgICBpZiAobGlzdC5sZW5ndGggPT09IDEpXG4gICAgICAgICAgZXZlbnRzW3R5cGVdID0gbGlzdFswXTtcblxuICAgICAgICBpZiAoZXZlbnRzLnJlbW92ZUxpc3RlbmVyKVxuICAgICAgICAgIHRoaXMuZW1pdCgncmVtb3ZlTGlzdGVuZXInLCB0eXBlLCBvcmlnaW5hbExpc3RlbmVyIHx8IGxpc3RlbmVyKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5yZW1vdmVBbGxMaXN0ZW5lcnMgPVxuICAgIGZ1bmN0aW9uIHJlbW92ZUFsbExpc3RlbmVycyh0eXBlKSB7XG4gICAgICB2YXIgbGlzdGVuZXJzLCBldmVudHMsIGk7XG5cbiAgICAgIGV2ZW50cyA9IHRoaXMuX2V2ZW50cztcbiAgICAgIGlmICghZXZlbnRzKVxuICAgICAgICByZXR1cm4gdGhpcztcblxuICAgICAgLy8gbm90IGxpc3RlbmluZyBmb3IgcmVtb3ZlTGlzdGVuZXIsIG5vIG5lZWQgdG8gZW1pdFxuICAgICAgaWYgKCFldmVudHMucmVtb3ZlTGlzdGVuZXIpIHtcbiAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICB0aGlzLl9ldmVudHMgPSBvYmplY3RDcmVhdGUobnVsbCk7XG4gICAgICAgICAgdGhpcy5fZXZlbnRzQ291bnQgPSAwO1xuICAgICAgICB9IGVsc2UgaWYgKGV2ZW50c1t0eXBlXSkge1xuICAgICAgICAgIGlmICgtLXRoaXMuX2V2ZW50c0NvdW50ID09PSAwKVxuICAgICAgICAgICAgdGhpcy5fZXZlbnRzID0gb2JqZWN0Q3JlYXRlKG51bGwpO1xuICAgICAgICAgIGVsc2VcbiAgICAgICAgICAgIGRlbGV0ZSBldmVudHNbdHlwZV07XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICB9XG5cbiAgICAgIC8vIGVtaXQgcmVtb3ZlTGlzdGVuZXIgZm9yIGFsbCBsaXN0ZW5lcnMgb24gYWxsIGV2ZW50c1xuICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgdmFyIGtleXMgPSBvYmplY3RLZXlzKGV2ZW50cyk7XG4gICAgICAgIHZhciBrZXk7XG4gICAgICAgIGZvciAoaSA9IDA7IGkgPCBrZXlzLmxlbmd0aDsgKytpKSB7XG4gICAgICAgICAga2V5ID0ga2V5c1tpXTtcbiAgICAgICAgICBpZiAoa2V5ID09PSAncmVtb3ZlTGlzdGVuZXInKSBjb250aW51ZTtcbiAgICAgICAgICB0aGlzLnJlbW92ZUFsbExpc3RlbmVycyhrZXkpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMucmVtb3ZlQWxsTGlzdGVuZXJzKCdyZW1vdmVMaXN0ZW5lcicpO1xuICAgICAgICB0aGlzLl9ldmVudHMgPSBvYmplY3RDcmVhdGUobnVsbCk7XG4gICAgICAgIHRoaXMuX2V2ZW50c0NvdW50ID0gMDtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICB9XG5cbiAgICAgIGxpc3RlbmVycyA9IGV2ZW50c1t0eXBlXTtcblxuICAgICAgaWYgKHR5cGVvZiBsaXN0ZW5lcnMgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgdGhpcy5yZW1vdmVMaXN0ZW5lcih0eXBlLCBsaXN0ZW5lcnMpO1xuICAgICAgfSBlbHNlIGlmIChsaXN0ZW5lcnMpIHtcbiAgICAgICAgLy8gTElGTyBvcmRlclxuICAgICAgICBmb3IgKGkgPSBsaXN0ZW5lcnMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgICAgICB0aGlzLnJlbW92ZUxpc3RlbmVyKHR5cGUsIGxpc3RlbmVyc1tpXSk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcblxuZnVuY3Rpb24gX2xpc3RlbmVycyh0YXJnZXQsIHR5cGUsIHVud3JhcCkge1xuICB2YXIgZXZlbnRzID0gdGFyZ2V0Ll9ldmVudHM7XG5cbiAgaWYgKCFldmVudHMpXG4gICAgcmV0dXJuIFtdO1xuXG4gIHZhciBldmxpc3RlbmVyID0gZXZlbnRzW3R5cGVdO1xuICBpZiAoIWV2bGlzdGVuZXIpXG4gICAgcmV0dXJuIFtdO1xuXG4gIGlmICh0eXBlb2YgZXZsaXN0ZW5lciA9PT0gJ2Z1bmN0aW9uJylcbiAgICByZXR1cm4gdW53cmFwID8gW2V2bGlzdGVuZXIubGlzdGVuZXIgfHwgZXZsaXN0ZW5lcl0gOiBbZXZsaXN0ZW5lcl07XG5cbiAgcmV0dXJuIHVud3JhcCA/IHVud3JhcExpc3RlbmVycyhldmxpc3RlbmVyKSA6IGFycmF5Q2xvbmUoZXZsaXN0ZW5lciwgZXZsaXN0ZW5lci5sZW5ndGgpO1xufVxuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLmxpc3RlbmVycyA9IGZ1bmN0aW9uIGxpc3RlbmVycyh0eXBlKSB7XG4gIHJldHVybiBfbGlzdGVuZXJzKHRoaXMsIHR5cGUsIHRydWUpO1xufTtcblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5yYXdMaXN0ZW5lcnMgPSBmdW5jdGlvbiByYXdMaXN0ZW5lcnModHlwZSkge1xuICByZXR1cm4gX2xpc3RlbmVycyh0aGlzLCB0eXBlLCBmYWxzZSk7XG59O1xuXG5FdmVudEVtaXR0ZXIubGlzdGVuZXJDb3VudCA9IGZ1bmN0aW9uKGVtaXR0ZXIsIHR5cGUpIHtcbiAgaWYgKHR5cGVvZiBlbWl0dGVyLmxpc3RlbmVyQ291bnQgPT09ICdmdW5jdGlvbicpIHtcbiAgICByZXR1cm4gZW1pdHRlci5saXN0ZW5lckNvdW50KHR5cGUpO1xuICB9IGVsc2Uge1xuICAgIHJldHVybiBsaXN0ZW5lckNvdW50LmNhbGwoZW1pdHRlciwgdHlwZSk7XG4gIH1cbn07XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUubGlzdGVuZXJDb3VudCA9IGxpc3RlbmVyQ291bnQ7XG5mdW5jdGlvbiBsaXN0ZW5lckNvdW50KHR5cGUpIHtcbiAgdmFyIGV2ZW50cyA9IHRoaXMuX2V2ZW50cztcblxuICBpZiAoZXZlbnRzKSB7XG4gICAgdmFyIGV2bGlzdGVuZXIgPSBldmVudHNbdHlwZV07XG5cbiAgICBpZiAodHlwZW9mIGV2bGlzdGVuZXIgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgIHJldHVybiAxO1xuICAgIH0gZWxzZSBpZiAoZXZsaXN0ZW5lcikge1xuICAgICAgcmV0dXJuIGV2bGlzdGVuZXIubGVuZ3RoO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiAwO1xufVxuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLmV2ZW50TmFtZXMgPSBmdW5jdGlvbiBldmVudE5hbWVzKCkge1xuICByZXR1cm4gdGhpcy5fZXZlbnRzQ291bnQgPiAwID8gUmVmbGVjdC5vd25LZXlzKHRoaXMuX2V2ZW50cykgOiBbXTtcbn07XG5cbi8vIEFib3V0IDEuNXggZmFzdGVyIHRoYW4gdGhlIHR3by1hcmcgdmVyc2lvbiBvZiBBcnJheSNzcGxpY2UoKS5cbmZ1bmN0aW9uIHNwbGljZU9uZShsaXN0LCBpbmRleCkge1xuICBmb3IgKHZhciBpID0gaW5kZXgsIGsgPSBpICsgMSwgbiA9IGxpc3QubGVuZ3RoOyBrIDwgbjsgaSArPSAxLCBrICs9IDEpXG4gICAgbGlzdFtpXSA9IGxpc3Rba107XG4gIGxpc3QucG9wKCk7XG59XG5cbmZ1bmN0aW9uIGFycmF5Q2xvbmUoYXJyLCBuKSB7XG4gIHZhciBjb3B5ID0gbmV3IEFycmF5KG4pO1xuICBmb3IgKHZhciBpID0gMDsgaSA8IG47ICsraSlcbiAgICBjb3B5W2ldID0gYXJyW2ldO1xuICByZXR1cm4gY29weTtcbn1cblxuZnVuY3Rpb24gdW53cmFwTGlzdGVuZXJzKGFycikge1xuICB2YXIgcmV0ID0gbmV3IEFycmF5KGFyci5sZW5ndGgpO1xuICBmb3IgKHZhciBpID0gMDsgaSA8IHJldC5sZW5ndGg7ICsraSkge1xuICAgIHJldFtpXSA9IGFycltpXS5saXN0ZW5lciB8fCBhcnJbaV07XG4gIH1cbiAgcmV0dXJuIHJldDtcbn1cblxuZnVuY3Rpb24gb2JqZWN0Q3JlYXRlUG9seWZpbGwocHJvdG8pIHtcbiAgdmFyIEYgPSBmdW5jdGlvbigpIHt9O1xuICBGLnByb3RvdHlwZSA9IHByb3RvO1xuICByZXR1cm4gbmV3IEY7XG59XG5mdW5jdGlvbiBvYmplY3RLZXlzUG9seWZpbGwob2JqKSB7XG4gIHZhciBrZXlzID0gW107XG4gIGZvciAodmFyIGsgaW4gb2JqKSBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKG9iaiwgaykpIHtcbiAgICBrZXlzLnB1c2goayk7XG4gIH1cbiAgcmV0dXJuIGs7XG59XG5mdW5jdGlvbiBmdW5jdGlvbkJpbmRQb2x5ZmlsbChjb250ZXh0KSB7XG4gIHZhciBmbiA9IHRoaXM7XG4gIHJldHVybiBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIGZuLmFwcGx5KGNvbnRleHQsIGFyZ3VtZW50cyk7XG4gIH07XG59XG4iLCIvKiBqc2hpbnQgbm9kZTogdHJ1ZSAqL1xuJ3VzZSBzdHJpY3QnO1xuXG52YXIgbm9ybWFsaWNlID0gcmVxdWlyZSgnbm9ybWFsaWNlJyk7XG5cbi8qKlxuICAjIGZyZWVpY2VcblxuICBUaGUgYGZyZWVpY2VgIG1vZHVsZSBpcyBhIHNpbXBsZSB3YXkgb2YgZ2V0dGluZyByYW5kb20gU1RVTiBvciBUVVJOIHNlcnZlclxuICBmb3IgeW91ciBXZWJSVEMgYXBwbGljYXRpb24uICBUaGUgbGlzdCBvZiBzZXJ2ZXJzIChqdXN0IFNUVU4gYXQgdGhpcyBzdGFnZSlcbiAgd2VyZSBzb3VyY2VkIGZyb20gdGhpcyBbZ2lzdF0oaHR0cHM6Ly9naXN0LmdpdGh1Yi5jb20venppdW5pLzM3NDE5MzMpLlxuXG4gICMjIEV4YW1wbGUgVXNlXG5cbiAgVGhlIGZvbGxvd2luZyBkZW1vbnN0cmF0ZXMgaG93IHlvdSBjYW4gdXNlIGBmcmVlaWNlYCB3aXRoXG4gIFtydGMtcXVpY2tjb25uZWN0XShodHRwczovL2dpdGh1Yi5jb20vcnRjLWlvL3J0Yy1xdWlja2Nvbm5lY3QpOlxuXG4gIDw8PCBleGFtcGxlcy9xdWlja2Nvbm5lY3QuanNcblxuICBBcyB0aGUgYGZyZWVpY2VgIG1vZHVsZSBnZW5lcmF0ZXMgaWNlIHNlcnZlcnMgaW4gYSBsaXN0IGNvbXBsaWFudCB3aXRoIHRoZVxuICBXZWJSVEMgc3BlYyB5b3Ugd2lsbCBiZSBhYmxlIHRvIHVzZSBpdCB3aXRoIHJhdyBgUlRDUGVlckNvbm5lY3Rpb25gXG4gIGNvbnN0cnVjdG9ycyBhbmQgb3RoZXIgV2ViUlRDIGxpYnJhcmllcy5cblxuICAjIyBIZXksIGRvbid0IHVzZSBteSBTVFVOL1RVUk4gc2VydmVyIVxuXG4gIElmIGZvciBzb21lIHJlYXNvbiB5b3VyIGZyZWUgU1RVTiBvciBUVVJOIHNlcnZlciBlbmRzIHVwIGluIHRoZVxuICBsaXN0IG9mIHNlcnZlcnMgKFtzdHVuXShodHRwczovL2dpdGh1Yi5jb20vRGFtb25PZWhsbWFuL2ZyZWVpY2UvYmxvYi9tYXN0ZXIvc3R1bi5qc29uKSBvclxuICBbdHVybl0oaHR0cHM6Ly9naXRodWIuY29tL0RhbW9uT2VobG1hbi9mcmVlaWNlL2Jsb2IvbWFzdGVyL3R1cm4uanNvbikpXG4gIHRoYXQgaXMgdXNlZCBpbiB0aGlzIG1vZHVsZSwgeW91IGNhbiBmZWVsXG4gIGZyZWUgdG8gb3BlbiBhbiBpc3N1ZSBvbiB0aGlzIHJlcG9zaXRvcnkgYW5kIHRob3NlIHNlcnZlcnMgd2lsbCBiZSByZW1vdmVkXG4gIHdpdGhpbiAyNCBob3VycyAob3Igc29vbmVyKS4gIFRoaXMgaXMgdGhlIHF1aWNrZXN0IGFuZCBwcm9iYWJseSB0aGUgbW9zdFxuICBwb2xpdGUgd2F5IHRvIGhhdmUgc29tZXRoaW5nIHJlbW92ZWQgKGFuZCBwcm92aWRlcyB1cyBzb21lIHZpc2liaWxpdHlcbiAgaWYgc29tZW9uZSBvcGVucyBhIHB1bGwgcmVxdWVzdCByZXF1ZXN0aW5nIHRoYXQgYSBzZXJ2ZXIgaXMgYWRkZWQpLlxuXG4gICMjIFBsZWFzZSBhZGQgbXkgc2VydmVyIVxuXG4gIElmIHlvdSBoYXZlIGEgc2VydmVyIHRoYXQgeW91IHdpc2ggdG8gYWRkIHRvIHRoZSBsaXN0LCB0aGF0J3MgYXdlc29tZSEgSSdtXG4gIHN1cmUgSSBzcGVhayBvbiBiZWhhbGYgb2YgYSB3aG9sZSBwaWxlIG9mIFdlYlJUQyBkZXZlbG9wZXJzIHdobyBzYXkgdGhhbmtzLlxuICBUbyBnZXQgaXQgaW50byB0aGUgbGlzdCwgZmVlbCBmcmVlIHRvIGVpdGhlciBvcGVuIGEgcHVsbCByZXF1ZXN0IG9yIGlmIHlvdVxuICBmaW5kIHRoYXQgcHJvY2VzcyBhIGJpdCBkYXVudGluZyB0aGVuIGp1c3QgY3JlYXRlIGFuIGlzc3VlIHJlcXVlc3RpbmdcbiAgdGhlIGFkZGl0aW9uIG9mIHRoZSBzZXJ2ZXIgKG1ha2Ugc3VyZSB5b3UgcHJvdmlkZSBhbGwgdGhlIGRldGFpbHMsIGFuZCBpZlxuICB5b3UgaGF2ZSBhIFRlcm1zIG9mIFNlcnZpY2UgdGhlbiBpbmNsdWRpbmcgdGhhdCBpbiB0aGUgUFIvaXNzdWUgd291bGQgYmVcbiAgYXdlc29tZSkuXG5cbiAgIyMgSSBrbm93IG9mIGEgZnJlZSBzZXJ2ZXIsIGNhbiBJIGFkZCBpdD9cblxuICBTdXJlLCBpZiB5b3UgZG8geW91ciBob21ld29yayBhbmQgbWFrZSBzdXJlIGl0IGlzIG9rIHRvIHVzZSAoSSdtIGN1cnJlbnRseVxuICBpbiB0aGUgcHJvY2VzcyBvZiByZXZpZXdpbmcgdGhlIHRlcm1zIG9mIHRob3NlIFNUVU4gc2VydmVycyBpbmNsdWRlZCBmcm9tXG4gIHRoZSBvcmlnaW5hbCBsaXN0KS4gIElmIGl0J3Mgb2sgdG8gZ28sIHRoZW4gcGxlYXNlIHNlZSB0aGUgcHJldmlvdXMgZW50cnlcbiAgZm9yIGhvdyB0byBhZGQgaXQuXG5cbiAgIyMgQ3VycmVudCBMaXN0IG9mIFNlcnZlcnNcblxuICAqIGN1cnJlbnQgYXMgYXQgdGhlIHRpbWUgb2YgbGFzdCBgUkVBRE1FLm1kYCBmaWxlIGdlbmVyYXRpb25cblxuICAjIyMgU1RVTlxuXG4gIDw8PCBzdHVuLmpzb25cblxuICAjIyMgVFVSTlxuXG4gIDw8PCB0dXJuLmpzb25cblxuKiovXG5cbnZhciBmcmVlaWNlID0gbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihvcHRzKSB7XG4gIC8vIGlmIGEgbGlzdCBvZiBzZXJ2ZXJzIGhhcyBiZWVuIHByb3ZpZGVkLCB0aGVuIHVzZSBpdCBpbnN0ZWFkIG9mIGRlZmF1bHRzXG4gIHZhciBzZXJ2ZXJzID0ge1xuICAgIHN0dW46IChvcHRzIHx8IHt9KS5zdHVuIHx8IHJlcXVpcmUoJy4vc3R1bi5qc29uJyksXG4gICAgdHVybjogKG9wdHMgfHwge30pLnR1cm4gfHwgcmVxdWlyZSgnLi90dXJuLmpzb24nKVxuICB9O1xuXG4gIHZhciBzdHVuQ291bnQgPSAob3B0cyB8fCB7fSkuc3R1bkNvdW50IHx8IDI7XG4gIHZhciB0dXJuQ291bnQgPSAob3B0cyB8fCB7fSkudHVybkNvdW50IHx8IDA7XG4gIHZhciBzZWxlY3RlZDtcblxuICBmdW5jdGlvbiBnZXRTZXJ2ZXJzKHR5cGUsIGNvdW50KSB7XG4gICAgdmFyIG91dCA9IFtdO1xuICAgIHZhciBpbnB1dCA9IFtdLmNvbmNhdChzZXJ2ZXJzW3R5cGVdKTtcbiAgICB2YXIgaWR4O1xuXG4gICAgd2hpbGUgKGlucHV0Lmxlbmd0aCAmJiBvdXQubGVuZ3RoIDwgY291bnQpIHtcbiAgICAgIGlkeCA9IChNYXRoLnJhbmRvbSgpICogaW5wdXQubGVuZ3RoKSB8IDA7XG4gICAgICBvdXQgPSBvdXQuY29uY2F0KGlucHV0LnNwbGljZShpZHgsIDEpKTtcbiAgICB9XG5cbiAgICByZXR1cm4gb3V0Lm1hcChmdW5jdGlvbih1cmwpIHtcbiAgICAgICAgLy9JZiBpdCdzIGEgbm90IGEgc3RyaW5nLCBkb24ndCB0cnkgdG8gXCJub3JtYWxpY2VcIiBpdCBvdGhlcndpc2UgdXNpbmcgdHlwZTp1cmwgd2lsbCBzY3JldyBpdCB1cFxuICAgICAgICBpZiAoKHR5cGVvZiB1cmwgIT09ICdzdHJpbmcnKSAmJiAoISAodXJsIGluc3RhbmNlb2YgU3RyaW5nKSkpIHtcbiAgICAgICAgICAgIHJldHVybiB1cmw7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gbm9ybWFsaWNlKHR5cGUgKyAnOicgKyB1cmwpO1xuICAgICAgICB9XG4gICAgfSk7XG4gIH1cblxuICAvLyBhZGQgc3R1biBzZXJ2ZXJzXG4gIHNlbGVjdGVkID0gW10uY29uY2F0KGdldFNlcnZlcnMoJ3N0dW4nLCBzdHVuQ291bnQpKTtcblxuICBpZiAodHVybkNvdW50KSB7XG4gICAgc2VsZWN0ZWQgPSBzZWxlY3RlZC5jb25jYXQoZ2V0U2VydmVycygndHVybicsIHR1cm5Db3VudCkpO1xuICB9XG5cbiAgcmV0dXJuIHNlbGVjdGVkO1xufTtcbiIsIm1vZHVsZS5leHBvcnRzPVtcbiAgXCJzdHVuLmwuZ29vZ2xlLmNvbToxOTMwMlwiLFxuICBcInN0dW4xLmwuZ29vZ2xlLmNvbToxOTMwMlwiLFxuICBcInN0dW4yLmwuZ29vZ2xlLmNvbToxOTMwMlwiLFxuICBcInN0dW4zLmwuZ29vZ2xlLmNvbToxOTMwMlwiLFxuICBcInN0dW40LmwuZ29vZ2xlLmNvbToxOTMwMlwiLFxuICBcInN0dW4uZWtpZ2EubmV0XCIsXG4gIFwic3R1bi5pZGVhc2lwLmNvbVwiLFxuICBcInN0dW4uc2NobHVuZC5kZVwiLFxuICBcInN0dW4uc3R1bnByb3RvY29sLm9yZzozNDc4XCIsXG4gIFwic3R1bi52b2lwYXJvdW5kLmNvbVwiLFxuICBcInN0dW4udm9pcGJ1c3Rlci5jb21cIixcbiAgXCJzdHVuLnZvaXBzdHVudC5jb21cIixcbiAgXCJzdHVuLnZveGdyYXRpYS5vcmdcIixcbiAgXCJzdHVuLnNlcnZpY2VzLm1vemlsbGEuY29tXCJcbl1cbiIsIm1vZHVsZS5leHBvcnRzPVtdXG4iLCJ2YXIgV2lsZEVtaXR0ZXIgPSByZXF1aXJlKCd3aWxkZW1pdHRlcicpO1xuXG5mdW5jdGlvbiBnZXRNYXhWb2x1bWUgKGFuYWx5c2VyLCBmZnRCaW5zKSB7XG4gIHZhciBtYXhWb2x1bWUgPSAtSW5maW5pdHk7XG4gIGFuYWx5c2VyLmdldEZsb2F0RnJlcXVlbmN5RGF0YShmZnRCaW5zKTtcblxuICBmb3IodmFyIGk9NCwgaWk9ZmZ0Qmlucy5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7XG4gICAgaWYgKGZmdEJpbnNbaV0gPiBtYXhWb2x1bWUgJiYgZmZ0Qmluc1tpXSA8IDApIHtcbiAgICAgIG1heFZvbHVtZSA9IGZmdEJpbnNbaV07XG4gICAgfVxuICB9O1xuXG4gIHJldHVybiBtYXhWb2x1bWU7XG59XG5cblxudmFyIGF1ZGlvQ29udGV4dFR5cGU7XG5pZiAodHlwZW9mIHdpbmRvdyAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgYXVkaW9Db250ZXh0VHlwZSA9IHdpbmRvdy5BdWRpb0NvbnRleHQgfHwgd2luZG93LndlYmtpdEF1ZGlvQ29udGV4dDtcbn1cbi8vIHVzZSBhIHNpbmdsZSBhdWRpbyBjb250ZXh0IGR1ZSB0byBoYXJkd2FyZSBsaW1pdHNcbnZhciBhdWRpb0NvbnRleHQgPSBudWxsO1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihzdHJlYW0sIG9wdGlvbnMpIHtcbiAgdmFyIGhhcmtlciA9IG5ldyBXaWxkRW1pdHRlcigpO1xuXG5cbiAgLy8gbWFrZSBpdCBub3QgYnJlYWsgaW4gbm9uLXN1cHBvcnRlZCBicm93c2Vyc1xuICBpZiAoIWF1ZGlvQ29udGV4dFR5cGUpIHJldHVybiBoYXJrZXI7XG5cbiAgLy9Db25maWdcbiAgdmFyIG9wdGlvbnMgPSBvcHRpb25zIHx8IHt9LFxuICAgICAgc21vb3RoaW5nID0gKG9wdGlvbnMuc21vb3RoaW5nIHx8IDAuMSksXG4gICAgICBpbnRlcnZhbCA9IChvcHRpb25zLmludGVydmFsIHx8IDUwKSxcbiAgICAgIHRocmVzaG9sZCA9IG9wdGlvbnMudGhyZXNob2xkLFxuICAgICAgcGxheSA9IG9wdGlvbnMucGxheSxcbiAgICAgIGhpc3RvcnkgPSBvcHRpb25zLmhpc3RvcnkgfHwgMTAsXG4gICAgICBydW5uaW5nID0gdHJ1ZTtcblxuICAvL1NldHVwIEF1ZGlvIENvbnRleHRcbiAgaWYgKCFhdWRpb0NvbnRleHQpIHtcbiAgICBhdWRpb0NvbnRleHQgPSBuZXcgYXVkaW9Db250ZXh0VHlwZSgpO1xuICB9XG4gIHZhciBzb3VyY2VOb2RlLCBmZnRCaW5zLCBhbmFseXNlcjtcblxuICBhbmFseXNlciA9IGF1ZGlvQ29udGV4dC5jcmVhdGVBbmFseXNlcigpO1xuICBhbmFseXNlci5mZnRTaXplID0gNTEyO1xuICBhbmFseXNlci5zbW9vdGhpbmdUaW1lQ29uc3RhbnQgPSBzbW9vdGhpbmc7XG4gIGZmdEJpbnMgPSBuZXcgRmxvYXQzMkFycmF5KGFuYWx5c2VyLmZyZXF1ZW5jeUJpbkNvdW50KTtcblxuICBpZiAoc3RyZWFtLmpxdWVyeSkgc3RyZWFtID0gc3RyZWFtWzBdO1xuICBpZiAoc3RyZWFtIGluc3RhbmNlb2YgSFRNTEF1ZGlvRWxlbWVudCB8fCBzdHJlYW0gaW5zdGFuY2VvZiBIVE1MVmlkZW9FbGVtZW50KSB7XG4gICAgLy9BdWRpbyBUYWdcbiAgICBzb3VyY2VOb2RlID0gYXVkaW9Db250ZXh0LmNyZWF0ZU1lZGlhRWxlbWVudFNvdXJjZShzdHJlYW0pO1xuICAgIGlmICh0eXBlb2YgcGxheSA9PT0gJ3VuZGVmaW5lZCcpIHBsYXkgPSB0cnVlO1xuICAgIHRocmVzaG9sZCA9IHRocmVzaG9sZCB8fCAtNTA7XG4gIH0gZWxzZSB7XG4gICAgLy9XZWJSVEMgU3RyZWFtXG4gICAgc291cmNlTm9kZSA9IGF1ZGlvQ29udGV4dC5jcmVhdGVNZWRpYVN0cmVhbVNvdXJjZShzdHJlYW0pO1xuICAgIHRocmVzaG9sZCA9IHRocmVzaG9sZCB8fCAtNTA7XG4gIH1cblxuICBzb3VyY2VOb2RlLmNvbm5lY3QoYW5hbHlzZXIpO1xuICBpZiAocGxheSkgYW5hbHlzZXIuY29ubmVjdChhdWRpb0NvbnRleHQuZGVzdGluYXRpb24pO1xuXG4gIGhhcmtlci5zcGVha2luZyA9IGZhbHNlO1xuXG4gIGhhcmtlci5zdXNwZW5kID0gZnVuY3Rpb24oKSB7XG4gICAgYXVkaW9Db250ZXh0LnN1c3BlbmQoKTtcbiAgfVxuICBoYXJrZXIucmVzdW1lID0gZnVuY3Rpb24oKSB7XG4gICAgYXVkaW9Db250ZXh0LnJlc3VtZSgpO1xuICB9XG4gIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShoYXJrZXIsICdzdGF0ZScsIHsgZ2V0OiBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gYXVkaW9Db250ZXh0LnN0YXRlO1xuICB9fSk7XG4gIGF1ZGlvQ29udGV4dC5vbnN0YXRlY2hhbmdlID0gZnVuY3Rpb24oKSB7XG4gICAgaGFya2VyLmVtaXQoJ3N0YXRlX2NoYW5nZScsIGF1ZGlvQ29udGV4dC5zdGF0ZSk7XG4gIH1cblxuICBoYXJrZXIuc2V0VGhyZXNob2xkID0gZnVuY3Rpb24odCkge1xuICAgIHRocmVzaG9sZCA9IHQ7XG4gIH07XG5cbiAgaGFya2VyLnNldEludGVydmFsID0gZnVuY3Rpb24oaSkge1xuICAgIGludGVydmFsID0gaTtcbiAgfTtcblxuICBoYXJrZXIuc3RvcCA9IGZ1bmN0aW9uKCkge1xuICAgIHJ1bm5pbmcgPSBmYWxzZTtcbiAgICBoYXJrZXIuZW1pdCgndm9sdW1lX2NoYW5nZScsIC0xMDAsIHRocmVzaG9sZCk7XG4gICAgaWYgKGhhcmtlci5zcGVha2luZykge1xuICAgICAgaGFya2VyLnNwZWFraW5nID0gZmFsc2U7XG4gICAgICBoYXJrZXIuZW1pdCgnc3RvcHBlZF9zcGVha2luZycpO1xuICAgIH1cbiAgICBhbmFseXNlci5kaXNjb25uZWN0KCk7XG4gICAgc291cmNlTm9kZS5kaXNjb25uZWN0KCk7XG4gIH07XG4gIGhhcmtlci5zcGVha2luZ0hpc3RvcnkgPSBbXTtcbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBoaXN0b3J5OyBpKyspIHtcbiAgICAgIGhhcmtlci5zcGVha2luZ0hpc3RvcnkucHVzaCgwKTtcbiAgfVxuXG4gIC8vIFBvbGwgdGhlIGFuYWx5c2VyIG5vZGUgdG8gZGV0ZXJtaW5lIGlmIHNwZWFraW5nXG4gIC8vIGFuZCBlbWl0IGV2ZW50cyBpZiBjaGFuZ2VkXG4gIHZhciBsb29wZXIgPSBmdW5jdGlvbigpIHtcbiAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uKCkge1xuXG4gICAgICAvL2NoZWNrIGlmIHN0b3AgaGFzIGJlZW4gY2FsbGVkXG4gICAgICBpZighcnVubmluZykge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIHZhciBjdXJyZW50Vm9sdW1lID0gZ2V0TWF4Vm9sdW1lKGFuYWx5c2VyLCBmZnRCaW5zKTtcblxuICAgICAgaGFya2VyLmVtaXQoJ3ZvbHVtZV9jaGFuZ2UnLCBjdXJyZW50Vm9sdW1lLCB0aHJlc2hvbGQpO1xuXG4gICAgICB2YXIgaGlzdG9yeSA9IDA7XG4gICAgICBpZiAoY3VycmVudFZvbHVtZSA+IHRocmVzaG9sZCAmJiAhaGFya2VyLnNwZWFraW5nKSB7XG4gICAgICAgIC8vIHRyaWdnZXIgcXVpY2tseSwgc2hvcnQgaGlzdG9yeVxuICAgICAgICBmb3IgKHZhciBpID0gaGFya2VyLnNwZWFraW5nSGlzdG9yeS5sZW5ndGggLSAzOyBpIDwgaGFya2VyLnNwZWFraW5nSGlzdG9yeS5sZW5ndGg7IGkrKykge1xuICAgICAgICAgIGhpc3RvcnkgKz0gaGFya2VyLnNwZWFraW5nSGlzdG9yeVtpXTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoaGlzdG9yeSA+PSAyKSB7XG4gICAgICAgICAgaGFya2VyLnNwZWFraW5nID0gdHJ1ZTtcbiAgICAgICAgICBoYXJrZXIuZW1pdCgnc3BlYWtpbmcnKTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIGlmIChjdXJyZW50Vm9sdW1lIDwgdGhyZXNob2xkICYmIGhhcmtlci5zcGVha2luZykge1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGhhcmtlci5zcGVha2luZ0hpc3RvcnkubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICBoaXN0b3J5ICs9IGhhcmtlci5zcGVha2luZ0hpc3RvcnlbaV07XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGhpc3RvcnkgPT0gMCkge1xuICAgICAgICAgIGhhcmtlci5zcGVha2luZyA9IGZhbHNlO1xuICAgICAgICAgIGhhcmtlci5lbWl0KCdzdG9wcGVkX3NwZWFraW5nJyk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGhhcmtlci5zcGVha2luZ0hpc3Rvcnkuc2hpZnQoKTtcbiAgICAgIGhhcmtlci5zcGVha2luZ0hpc3RvcnkucHVzaCgwICsgKGN1cnJlbnRWb2x1bWUgPiB0aHJlc2hvbGQpKTtcblxuICAgICAgbG9vcGVyKCk7XG4gICAgfSwgaW50ZXJ2YWwpO1xuICB9O1xuICBsb29wZXIoKTtcblxuXG4gIHJldHVybiBoYXJrZXI7XG59XG4iLCJpZiAodHlwZW9mIE9iamVjdC5jcmVhdGUgPT09ICdmdW5jdGlvbicpIHtcbiAgLy8gaW1wbGVtZW50YXRpb24gZnJvbSBzdGFuZGFyZCBub2RlLmpzICd1dGlsJyBtb2R1bGVcbiAgbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBpbmhlcml0cyhjdG9yLCBzdXBlckN0b3IpIHtcbiAgICBjdG9yLnN1cGVyXyA9IHN1cGVyQ3RvclxuICAgIGN0b3IucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShzdXBlckN0b3IucHJvdG90eXBlLCB7XG4gICAgICBjb25zdHJ1Y3Rvcjoge1xuICAgICAgICB2YWx1ZTogY3RvcixcbiAgICAgICAgZW51bWVyYWJsZTogZmFsc2UsXG4gICAgICAgIHdyaXRhYmxlOiB0cnVlLFxuICAgICAgICBjb25maWd1cmFibGU6IHRydWVcbiAgICAgIH1cbiAgICB9KTtcbiAgfTtcbn0gZWxzZSB7XG4gIC8vIG9sZCBzY2hvb2wgc2hpbSBmb3Igb2xkIGJyb3dzZXJzXG4gIG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gaW5oZXJpdHMoY3Rvciwgc3VwZXJDdG9yKSB7XG4gICAgY3Rvci5zdXBlcl8gPSBzdXBlckN0b3JcbiAgICB2YXIgVGVtcEN0b3IgPSBmdW5jdGlvbiAoKSB7fVxuICAgIFRlbXBDdG9yLnByb3RvdHlwZSA9IHN1cGVyQ3Rvci5wcm90b3R5cGVcbiAgICBjdG9yLnByb3RvdHlwZSA9IG5ldyBUZW1wQ3RvcigpXG4gICAgY3Rvci5wcm90b3R5cGUuY29uc3RydWN0b3IgPSBjdG9yXG4gIH1cbn1cbiIsIi8qKlxuICAjIG5vcm1hbGljZVxuXG4gIE5vcm1hbGl6ZSBhbiBpY2Ugc2VydmVyIGNvbmZpZ3VyYXRpb24gb2JqZWN0IChvciBwbGFpbiBvbGQgc3RyaW5nKSBpbnRvIGEgZm9ybWF0XG4gIHRoYXQgaXMgdXNhYmxlIGluIGFsbCBicm93c2VycyBzdXBwb3J0aW5nIFdlYlJUQy4gIFByaW1hcmlseSB0aGlzIG1vZHVsZSBpcyBkZXNpZ25lZFxuICB0byBoZWxwIHdpdGggdGhlIHRyYW5zaXRpb24gb2YgdGhlIGB1cmxgIGF0dHJpYnV0ZSBvZiB0aGUgY29uZmlndXJhdGlvbiBvYmplY3QgdG9cbiAgdGhlIGB1cmxzYCBhdHRyaWJ1dGUuXG5cbiAgIyMgRXhhbXBsZSBVc2FnZVxuXG4gIDw8PCBleGFtcGxlcy9zaW1wbGUuanNcblxuKiovXG5cbnZhciBwcm90b2NvbHMgPSBbXG4gICdzdHVuOicsXG4gICd0dXJuOidcbl07XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24oaW5wdXQpIHtcbiAgdmFyIHVybCA9IChpbnB1dCB8fCB7fSkudXJsIHx8IGlucHV0O1xuICB2YXIgcHJvdG9jb2w7XG4gIHZhciBwYXJ0cztcbiAgdmFyIG91dHB1dCA9IHt9O1xuXG4gIC8vIGlmIHdlIGRvbid0IGhhdmUgYSBzdHJpbmcgdXJsLCB0aGVuIGFsbG93IHRoZSBpbnB1dCB0byBwYXNzdGhyb3VnaFxuICBpZiAodHlwZW9mIHVybCAhPSAnc3RyaW5nJyAmJiAoISAodXJsIGluc3RhbmNlb2YgU3RyaW5nKSkpIHtcbiAgICByZXR1cm4gaW5wdXQ7XG4gIH1cblxuICAvLyB0cmltIHRoZSB1cmwgc3RyaW5nLCBhbmQgY29udmVydCB0byBhbiBhcnJheVxuICB1cmwgPSB1cmwudHJpbSgpO1xuXG4gIC8vIGlmIHRoZSBwcm90b2NvbCBpcyBub3Qga25vd24sIHRoZW4gcGFzc3Rocm91Z2hcbiAgcHJvdG9jb2wgPSBwcm90b2NvbHNbcHJvdG9jb2xzLmluZGV4T2YodXJsLnNsaWNlKDAsIDUpKV07XG4gIGlmICghIHByb3RvY29sKSB7XG4gICAgcmV0dXJuIGlucHV0O1xuICB9XG5cbiAgLy8gbm93IGxldCdzIGF0dGFjayB0aGUgcmVtYWluaW5nIHVybCBwYXJ0c1xuICB1cmwgPSB1cmwuc2xpY2UoNSk7XG4gIHBhcnRzID0gdXJsLnNwbGl0KCdAJyk7XG5cbiAgb3V0cHV0LnVzZXJuYW1lID0gaW5wdXQudXNlcm5hbWU7XG4gIG91dHB1dC5jcmVkZW50aWFsID0gaW5wdXQuY3JlZGVudGlhbDtcbiAgLy8gaWYgd2UgaGF2ZSBhbiBhdXRoZW50aWNhdGlvbiBwYXJ0LCB0aGVuIHNldCB0aGUgY3JlZGVudGlhbHNcbiAgaWYgKHBhcnRzLmxlbmd0aCA+IDEpIHtcbiAgICB1cmwgPSBwYXJ0c1sxXTtcbiAgICBwYXJ0cyA9IHBhcnRzWzBdLnNwbGl0KCc6Jyk7XG5cbiAgICAvLyBhZGQgdGhlIG91dHB1dCBjcmVkZW50aWFsIGFuZCB1c2VybmFtZVxuICAgIG91dHB1dC51c2VybmFtZSA9IHBhcnRzWzBdO1xuICAgIG91dHB1dC5jcmVkZW50aWFsID0gKGlucHV0IHx8IHt9KS5jcmVkZW50aWFsIHx8IHBhcnRzWzFdIHx8ICcnO1xuICB9XG5cbiAgb3V0cHV0LnVybCA9IHByb3RvY29sICsgdXJsO1xuICBvdXRwdXQudXJscyA9IFsgb3V0cHV0LnVybCBdO1xuXG4gIHJldHVybiBvdXRwdXQ7XG59O1xuIiwiLyohXG4gKiBQbGF0Zm9ybS5qcyA8aHR0cHM6Ly9tdGhzLmJlL3BsYXRmb3JtPlxuICogQ29weXJpZ2h0IDIwMTQtMjAxOCBCZW5qYW1pbiBUYW4gPGh0dHBzOi8vYm5qbW50NG4ubm93LnNoLz5cbiAqIENvcHlyaWdodCAyMDExLTIwMTMgSm9obi1EYXZpZCBEYWx0b24gPGh0dHA6Ly9hbGx5b3VjYW5sZWV0LmNvbS8+XG4gKiBBdmFpbGFibGUgdW5kZXIgTUlUIGxpY2Vuc2UgPGh0dHBzOi8vbXRocy5iZS9taXQ+XG4gKi9cbjsoZnVuY3Rpb24oKSB7XG4gICd1c2Ugc3RyaWN0JztcblxuICAvKiogVXNlZCB0byBkZXRlcm1pbmUgaWYgdmFsdWVzIGFyZSBvZiB0aGUgbGFuZ3VhZ2UgdHlwZSBgT2JqZWN0YC4gKi9cbiAgdmFyIG9iamVjdFR5cGVzID0ge1xuICAgICdmdW5jdGlvbic6IHRydWUsXG4gICAgJ29iamVjdCc6IHRydWVcbiAgfTtcblxuICAvKiogVXNlZCBhcyBhIHJlZmVyZW5jZSB0byB0aGUgZ2xvYmFsIG9iamVjdC4gKi9cbiAgdmFyIHJvb3QgPSAob2JqZWN0VHlwZXNbdHlwZW9mIHdpbmRvd10gJiYgd2luZG93KSB8fCB0aGlzO1xuXG4gIC8qKiBCYWNrdXAgcG9zc2libGUgZ2xvYmFsIG9iamVjdC4gKi9cbiAgdmFyIG9sZFJvb3QgPSByb290O1xuXG4gIC8qKiBEZXRlY3QgZnJlZSB2YXJpYWJsZSBgZXhwb3J0c2AuICovXG4gIHZhciBmcmVlRXhwb3J0cyA9IG9iamVjdFR5cGVzW3R5cGVvZiBleHBvcnRzXSAmJiBleHBvcnRzO1xuXG4gIC8qKiBEZXRlY3QgZnJlZSB2YXJpYWJsZSBgbW9kdWxlYC4gKi9cbiAgdmFyIGZyZWVNb2R1bGUgPSBvYmplY3RUeXBlc1t0eXBlb2YgbW9kdWxlXSAmJiBtb2R1bGUgJiYgIW1vZHVsZS5ub2RlVHlwZSAmJiBtb2R1bGU7XG5cbiAgLyoqIERldGVjdCBmcmVlIHZhcmlhYmxlIGBnbG9iYWxgIGZyb20gTm9kZS5qcyBvciBCcm93c2VyaWZpZWQgY29kZSBhbmQgdXNlIGl0IGFzIGByb290YC4gKi9cbiAgdmFyIGZyZWVHbG9iYWwgPSBmcmVlRXhwb3J0cyAmJiBmcmVlTW9kdWxlICYmIHR5cGVvZiBnbG9iYWwgPT0gJ29iamVjdCcgJiYgZ2xvYmFsO1xuICBpZiAoZnJlZUdsb2JhbCAmJiAoZnJlZUdsb2JhbC5nbG9iYWwgPT09IGZyZWVHbG9iYWwgfHwgZnJlZUdsb2JhbC53aW5kb3cgPT09IGZyZWVHbG9iYWwgfHwgZnJlZUdsb2JhbC5zZWxmID09PSBmcmVlR2xvYmFsKSkge1xuICAgIHJvb3QgPSBmcmVlR2xvYmFsO1xuICB9XG5cbiAgLyoqXG4gICAqIFVzZWQgYXMgdGhlIG1heGltdW0gbGVuZ3RoIG9mIGFuIGFycmF5LWxpa2Ugb2JqZWN0LlxuICAgKiBTZWUgdGhlIFtFUzYgc3BlY10oaHR0cDovL3Blb3BsZS5tb3ppbGxhLm9yZy9+am9yZW5kb3JmZi9lczYtZHJhZnQuaHRtbCNzZWMtdG9sZW5ndGgpXG4gICAqIGZvciBtb3JlIGRldGFpbHMuXG4gICAqL1xuICB2YXIgbWF4U2FmZUludGVnZXIgPSBNYXRoLnBvdygyLCA1MykgLSAxO1xuXG4gIC8qKiBSZWd1bGFyIGV4cHJlc3Npb24gdG8gZGV0ZWN0IE9wZXJhLiAqL1xuICB2YXIgcmVPcGVyYSA9IC9cXGJPcGVyYS87XG5cbiAgLyoqIFBvc3NpYmxlIGdsb2JhbCBvYmplY3QuICovXG4gIHZhciB0aGlzQmluZGluZyA9IHRoaXM7XG5cbiAgLyoqIFVzZWQgZm9yIG5hdGl2ZSBtZXRob2QgcmVmZXJlbmNlcy4gKi9cbiAgdmFyIG9iamVjdFByb3RvID0gT2JqZWN0LnByb3RvdHlwZTtcblxuICAvKiogVXNlZCB0byBjaGVjayBmb3Igb3duIHByb3BlcnRpZXMgb2YgYW4gb2JqZWN0LiAqL1xuICB2YXIgaGFzT3duUHJvcGVydHkgPSBvYmplY3RQcm90by5oYXNPd25Qcm9wZXJ0eTtcblxuICAvKiogVXNlZCB0byByZXNvbHZlIHRoZSBpbnRlcm5hbCBgW1tDbGFzc11dYCBvZiB2YWx1ZXMuICovXG4gIHZhciB0b1N0cmluZyA9IG9iamVjdFByb3RvLnRvU3RyaW5nO1xuXG4gIC8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuXG4gIC8qKlxuICAgKiBDYXBpdGFsaXplcyBhIHN0cmluZyB2YWx1ZS5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtzdHJpbmd9IHN0cmluZyBUaGUgc3RyaW5nIHRvIGNhcGl0YWxpemUuXG4gICAqIEByZXR1cm5zIHtzdHJpbmd9IFRoZSBjYXBpdGFsaXplZCBzdHJpbmcuXG4gICAqL1xuICBmdW5jdGlvbiBjYXBpdGFsaXplKHN0cmluZykge1xuICAgIHN0cmluZyA9IFN0cmluZyhzdHJpbmcpO1xuICAgIHJldHVybiBzdHJpbmcuY2hhckF0KDApLnRvVXBwZXJDYXNlKCkgKyBzdHJpbmcuc2xpY2UoMSk7XG4gIH1cblxuICAvKipcbiAgICogQSB1dGlsaXR5IGZ1bmN0aW9uIHRvIGNsZWFuIHVwIHRoZSBPUyBuYW1lLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gb3MgVGhlIE9TIG5hbWUgdG8gY2xlYW4gdXAuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbcGF0dGVybl0gQSBgUmVnRXhwYCBwYXR0ZXJuIG1hdGNoaW5nIHRoZSBPUyBuYW1lLlxuICAgKiBAcGFyYW0ge3N0cmluZ30gW2xhYmVsXSBBIGxhYmVsIGZvciB0aGUgT1MuXG4gICAqL1xuICBmdW5jdGlvbiBjbGVhbnVwT1Mob3MsIHBhdHRlcm4sIGxhYmVsKSB7XG4gICAgLy8gUGxhdGZvcm0gdG9rZW5zIGFyZSBkZWZpbmVkIGF0OlxuICAgIC8vIGh0dHA6Ly9tc2RuLm1pY3Jvc29mdC5jb20vZW4tdXMvbGlicmFyeS9tczUzNzUwMyhWUy44NSkuYXNweFxuICAgIC8vIGh0dHA6Ly93ZWIuYXJjaGl2ZS5vcmcvd2ViLzIwMDgxMTIyMDUzOTUwL2h0dHA6Ly9tc2RuLm1pY3Jvc29mdC5jb20vZW4tdXMvbGlicmFyeS9tczUzNzUwMyhWUy44NSkuYXNweFxuICAgIHZhciBkYXRhID0ge1xuICAgICAgJzEwLjAnOiAnMTAnLFxuICAgICAgJzYuNCc6ICAnMTAgVGVjaG5pY2FsIFByZXZpZXcnLFxuICAgICAgJzYuMyc6ICAnOC4xJyxcbiAgICAgICc2LjInOiAgJzgnLFxuICAgICAgJzYuMSc6ICAnU2VydmVyIDIwMDggUjIgLyA3JyxcbiAgICAgICc2LjAnOiAgJ1NlcnZlciAyMDA4IC8gVmlzdGEnLFxuICAgICAgJzUuMic6ICAnU2VydmVyIDIwMDMgLyBYUCA2NC1iaXQnLFxuICAgICAgJzUuMSc6ICAnWFAnLFxuICAgICAgJzUuMDEnOiAnMjAwMCBTUDEnLFxuICAgICAgJzUuMCc6ICAnMjAwMCcsXG4gICAgICAnNC4wJzogICdOVCcsXG4gICAgICAnNC45MCc6ICdNRSdcbiAgICB9O1xuICAgIC8vIERldGVjdCBXaW5kb3dzIHZlcnNpb24gZnJvbSBwbGF0Zm9ybSB0b2tlbnMuXG4gICAgaWYgKHBhdHRlcm4gJiYgbGFiZWwgJiYgL15XaW4vaS50ZXN0KG9zKSAmJiAhL15XaW5kb3dzIFBob25lIC9pLnRlc3Qob3MpICYmXG4gICAgICAgIChkYXRhID0gZGF0YVsvW1xcZC5dKyQvLmV4ZWMob3MpXSkpIHtcbiAgICAgIG9zID0gJ1dpbmRvd3MgJyArIGRhdGE7XG4gICAgfVxuICAgIC8vIENvcnJlY3QgY2hhcmFjdGVyIGNhc2UgYW5kIGNsZWFudXAgc3RyaW5nLlxuICAgIG9zID0gU3RyaW5nKG9zKTtcblxuICAgIGlmIChwYXR0ZXJuICYmIGxhYmVsKSB7XG4gICAgICBvcyA9IG9zLnJlcGxhY2UoUmVnRXhwKHBhdHRlcm4sICdpJyksIGxhYmVsKTtcbiAgICB9XG5cbiAgICBvcyA9IGZvcm1hdChcbiAgICAgIG9zLnJlcGxhY2UoLyBjZSQvaSwgJyBDRScpXG4gICAgICAgIC5yZXBsYWNlKC9cXGJocHcvaSwgJ3dlYicpXG4gICAgICAgIC5yZXBsYWNlKC9cXGJNYWNpbnRvc2hcXGIvLCAnTWFjIE9TJylcbiAgICAgICAgLnJlcGxhY2UoL19Qb3dlclBDXFxiL2ksICcgT1MnKVxuICAgICAgICAucmVwbGFjZSgvXFxiKE9TIFgpIFteIFxcZF0rL2ksICckMScpXG4gICAgICAgIC5yZXBsYWNlKC9cXGJNYWMgKE9TIFgpXFxiLywgJyQxJylcbiAgICAgICAgLnJlcGxhY2UoL1xcLyhcXGQpLywgJyAkMScpXG4gICAgICAgIC5yZXBsYWNlKC9fL2csICcuJylcbiAgICAgICAgLnJlcGxhY2UoLyg/OiBCZVBDfFsgLl0qZmNbIFxcZC5dKykkL2ksICcnKVxuICAgICAgICAucmVwbGFjZSgvXFxieDg2XFwuNjRcXGIvZ2ksICd4ODZfNjQnKVxuICAgICAgICAucmVwbGFjZSgvXFxiKFdpbmRvd3MgUGhvbmUpIE9TXFxiLywgJyQxJylcbiAgICAgICAgLnJlcGxhY2UoL1xcYihDaHJvbWUgT1MgXFx3KykgW1xcZC5dK1xcYi8sICckMScpXG4gICAgICAgIC5zcGxpdCgnIG9uICcpWzBdXG4gICAgKTtcblxuICAgIHJldHVybiBvcztcbiAgfVxuXG4gIC8qKlxuICAgKiBBbiBpdGVyYXRpb24gdXRpbGl0eSBmb3IgYXJyYXlzIGFuZCBvYmplY3RzLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge0FycmF5fE9iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gaXRlcmF0ZSBvdmVyLlxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBjYWxsYmFjayBUaGUgZnVuY3Rpb24gY2FsbGVkIHBlciBpdGVyYXRpb24uXG4gICAqL1xuICBmdW5jdGlvbiBlYWNoKG9iamVjdCwgY2FsbGJhY2spIHtcbiAgICB2YXIgaW5kZXggPSAtMSxcbiAgICAgICAgbGVuZ3RoID0gb2JqZWN0ID8gb2JqZWN0Lmxlbmd0aCA6IDA7XG5cbiAgICBpZiAodHlwZW9mIGxlbmd0aCA9PSAnbnVtYmVyJyAmJiBsZW5ndGggPiAtMSAmJiBsZW5ndGggPD0gbWF4U2FmZUludGVnZXIpIHtcbiAgICAgIHdoaWxlICgrK2luZGV4IDwgbGVuZ3RoKSB7XG4gICAgICAgIGNhbGxiYWNrKG9iamVjdFtpbmRleF0sIGluZGV4LCBvYmplY3QpO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBmb3JPd24ob2JqZWN0LCBjYWxsYmFjayk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFRyaW0gYW5kIGNvbmRpdGlvbmFsbHkgY2FwaXRhbGl6ZSBzdHJpbmcgdmFsdWVzLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gc3RyaW5nIFRoZSBzdHJpbmcgdG8gZm9ybWF0LlxuICAgKiBAcmV0dXJucyB7c3RyaW5nfSBUaGUgZm9ybWF0dGVkIHN0cmluZy5cbiAgICovXG4gIGZ1bmN0aW9uIGZvcm1hdChzdHJpbmcpIHtcbiAgICBzdHJpbmcgPSB0cmltKHN0cmluZyk7XG4gICAgcmV0dXJuIC9eKD86d2ViT1N8aSg/Ok9TfFApKS8udGVzdChzdHJpbmcpXG4gICAgICA/IHN0cmluZ1xuICAgICAgOiBjYXBpdGFsaXplKHN0cmluZyk7XG4gIH1cblxuICAvKipcbiAgICogSXRlcmF0ZXMgb3ZlciBhbiBvYmplY3QncyBvd24gcHJvcGVydGllcywgZXhlY3V0aW5nIHRoZSBgY2FsbGJhY2tgIGZvciBlYWNoLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gaXRlcmF0ZSBvdmVyLlxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBjYWxsYmFjayBUaGUgZnVuY3Rpb24gZXhlY3V0ZWQgcGVyIG93biBwcm9wZXJ0eS5cbiAgICovXG4gIGZ1bmN0aW9uIGZvck93bihvYmplY3QsIGNhbGxiYWNrKSB7XG4gICAgZm9yICh2YXIga2V5IGluIG9iamVjdCkge1xuICAgICAgaWYgKGhhc093blByb3BlcnR5LmNhbGwob2JqZWN0LCBrZXkpKSB7XG4gICAgICAgIGNhbGxiYWNrKG9iamVjdFtrZXldLCBrZXksIG9iamVjdCk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEdldHMgdGhlIGludGVybmFsIGBbW0NsYXNzXV1gIG9mIGEgdmFsdWUuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlLlxuICAgKiBAcmV0dXJucyB7c3RyaW5nfSBUaGUgYFtbQ2xhc3NdXWAuXG4gICAqL1xuICBmdW5jdGlvbiBnZXRDbGFzc09mKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlID09IG51bGxcbiAgICAgID8gY2FwaXRhbGl6ZSh2YWx1ZSlcbiAgICAgIDogdG9TdHJpbmcuY2FsbCh2YWx1ZSkuc2xpY2UoOCwgLTEpO1xuICB9XG5cbiAgLyoqXG4gICAqIEhvc3Qgb2JqZWN0cyBjYW4gcmV0dXJuIHR5cGUgdmFsdWVzIHRoYXQgYXJlIGRpZmZlcmVudCBmcm9tIHRoZWlyIGFjdHVhbFxuICAgKiBkYXRhIHR5cGUuIFRoZSBvYmplY3RzIHdlIGFyZSBjb25jZXJuZWQgd2l0aCB1c3VhbGx5IHJldHVybiBub24tcHJpbWl0aXZlXG4gICAqIHR5cGVzIG9mIFwib2JqZWN0XCIsIFwiZnVuY3Rpb25cIiwgb3IgXCJ1bmtub3duXCIuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7Kn0gb2JqZWN0IFRoZSBvd25lciBvZiB0aGUgcHJvcGVydHkuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBwcm9wZXJ0eSBUaGUgcHJvcGVydHkgdG8gY2hlY2suXG4gICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiB0aGUgcHJvcGVydHkgdmFsdWUgaXMgYSBub24tcHJpbWl0aXZlLCBlbHNlIGBmYWxzZWAuXG4gICAqL1xuICBmdW5jdGlvbiBpc0hvc3RUeXBlKG9iamVjdCwgcHJvcGVydHkpIHtcbiAgICB2YXIgdHlwZSA9IG9iamVjdCAhPSBudWxsID8gdHlwZW9mIG9iamVjdFtwcm9wZXJ0eV0gOiAnbnVtYmVyJztcbiAgICByZXR1cm4gIS9eKD86Ym9vbGVhbnxudW1iZXJ8c3RyaW5nfHVuZGVmaW5lZCkkLy50ZXN0KHR5cGUpICYmXG4gICAgICAodHlwZSA9PSAnb2JqZWN0JyA/ICEhb2JqZWN0W3Byb3BlcnR5XSA6IHRydWUpO1xuICB9XG5cbiAgLyoqXG4gICAqIFByZXBhcmVzIGEgc3RyaW5nIGZvciB1c2UgaW4gYSBgUmVnRXhwYCBieSBtYWtpbmcgaHlwaGVucyBhbmQgc3BhY2VzIG9wdGlvbmFsLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gc3RyaW5nIFRoZSBzdHJpbmcgdG8gcXVhbGlmeS5cbiAgICogQHJldHVybnMge3N0cmluZ30gVGhlIHF1YWxpZmllZCBzdHJpbmcuXG4gICAqL1xuICBmdW5jdGlvbiBxdWFsaWZ5KHN0cmluZykge1xuICAgIHJldHVybiBTdHJpbmcoc3RyaW5nKS5yZXBsYWNlKC8oWyAtXSkoPyEkKS9nLCAnJDE/Jyk7XG4gIH1cblxuICAvKipcbiAgICogQSBiYXJlLWJvbmVzIGBBcnJheSNyZWR1Y2VgIGxpa2UgdXRpbGl0eSBmdW5jdGlvbi5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIGl0ZXJhdGUgb3Zlci5cbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gY2FsbGJhY2sgVGhlIGZ1bmN0aW9uIGNhbGxlZCBwZXIgaXRlcmF0aW9uLlxuICAgKiBAcmV0dXJucyB7Kn0gVGhlIGFjY3VtdWxhdGVkIHJlc3VsdC5cbiAgICovXG4gIGZ1bmN0aW9uIHJlZHVjZShhcnJheSwgY2FsbGJhY2spIHtcbiAgICB2YXIgYWNjdW11bGF0b3IgPSBudWxsO1xuICAgIGVhY2goYXJyYXksIGZ1bmN0aW9uKHZhbHVlLCBpbmRleCkge1xuICAgICAgYWNjdW11bGF0b3IgPSBjYWxsYmFjayhhY2N1bXVsYXRvciwgdmFsdWUsIGluZGV4LCBhcnJheSk7XG4gICAgfSk7XG4gICAgcmV0dXJuIGFjY3VtdWxhdG9yO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlbW92ZXMgbGVhZGluZyBhbmQgdHJhaWxpbmcgd2hpdGVzcGFjZSBmcm9tIGEgc3RyaW5nLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gc3RyaW5nIFRoZSBzdHJpbmcgdG8gdHJpbS5cbiAgICogQHJldHVybnMge3N0cmluZ30gVGhlIHRyaW1tZWQgc3RyaW5nLlxuICAgKi9cbiAgZnVuY3Rpb24gdHJpbShzdHJpbmcpIHtcbiAgICByZXR1cm4gU3RyaW5nKHN0cmluZykucmVwbGFjZSgvXiArfCArJC9nLCAnJyk7XG4gIH1cblxuICAvKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cblxuICAvKipcbiAgICogQ3JlYXRlcyBhIG5ldyBwbGF0Zm9ybSBvYmplY3QuXG4gICAqXG4gICAqIEBtZW1iZXJPZiBwbGF0Zm9ybVxuICAgKiBAcGFyYW0ge09iamVjdHxzdHJpbmd9IFt1YT1uYXZpZ2F0b3IudXNlckFnZW50XSBUaGUgdXNlciBhZ2VudCBzdHJpbmcgb3JcbiAgICogIGNvbnRleHQgb2JqZWN0LlxuICAgKiBAcmV0dXJucyB7T2JqZWN0fSBBIHBsYXRmb3JtIG9iamVjdC5cbiAgICovXG4gIGZ1bmN0aW9uIHBhcnNlKHVhKSB7XG5cbiAgICAvKiogVGhlIGVudmlyb25tZW50IGNvbnRleHQgb2JqZWN0LiAqL1xuICAgIHZhciBjb250ZXh0ID0gcm9vdDtcblxuICAgIC8qKiBVc2VkIHRvIGZsYWcgd2hlbiBhIGN1c3RvbSBjb250ZXh0IGlzIHByb3ZpZGVkLiAqL1xuICAgIHZhciBpc0N1c3RvbUNvbnRleHQgPSB1YSAmJiB0eXBlb2YgdWEgPT0gJ29iamVjdCcgJiYgZ2V0Q2xhc3NPZih1YSkgIT0gJ1N0cmluZyc7XG5cbiAgICAvLyBKdWdnbGUgYXJndW1lbnRzLlxuICAgIGlmIChpc0N1c3RvbUNvbnRleHQpIHtcbiAgICAgIGNvbnRleHQgPSB1YTtcbiAgICAgIHVhID0gbnVsbDtcbiAgICB9XG5cbiAgICAvKiogQnJvd3NlciBuYXZpZ2F0b3Igb2JqZWN0LiAqL1xuICAgIHZhciBuYXYgPSBjb250ZXh0Lm5hdmlnYXRvciB8fCB7fTtcblxuICAgIC8qKiBCcm93c2VyIHVzZXIgYWdlbnQgc3RyaW5nLiAqL1xuICAgIHZhciB1c2VyQWdlbnQgPSBuYXYudXNlckFnZW50IHx8ICcnO1xuXG4gICAgdWEgfHwgKHVhID0gdXNlckFnZW50KTtcblxuICAgIC8qKiBVc2VkIHRvIGZsYWcgd2hlbiBgdGhpc0JpbmRpbmdgIGlzIHRoZSBbTW9kdWxlU2NvcGVdLiAqL1xuICAgIHZhciBpc01vZHVsZVNjb3BlID0gaXNDdXN0b21Db250ZXh0IHx8IHRoaXNCaW5kaW5nID09IG9sZFJvb3Q7XG5cbiAgICAvKiogVXNlZCB0byBkZXRlY3QgaWYgYnJvd3NlciBpcyBsaWtlIENocm9tZS4gKi9cbiAgICB2YXIgbGlrZUNocm9tZSA9IGlzQ3VzdG9tQ29udGV4dFxuICAgICAgPyAhIW5hdi5saWtlQ2hyb21lXG4gICAgICA6IC9cXGJDaHJvbWVcXGIvLnRlc3QodWEpICYmICEvaW50ZXJuYWx8XFxuL2kudGVzdCh0b1N0cmluZy50b1N0cmluZygpKTtcblxuICAgIC8qKiBJbnRlcm5hbCBgW1tDbGFzc11dYCB2YWx1ZSBzaG9ydGN1dHMuICovXG4gICAgdmFyIG9iamVjdENsYXNzID0gJ09iamVjdCcsXG4gICAgICAgIGFpclJ1bnRpbWVDbGFzcyA9IGlzQ3VzdG9tQ29udGV4dCA/IG9iamVjdENsYXNzIDogJ1NjcmlwdEJyaWRnaW5nUHJveHlPYmplY3QnLFxuICAgICAgICBlbnZpcm9DbGFzcyA9IGlzQ3VzdG9tQ29udGV4dCA/IG9iamVjdENsYXNzIDogJ0Vudmlyb25tZW50JyxcbiAgICAgICAgamF2YUNsYXNzID0gKGlzQ3VzdG9tQ29udGV4dCAmJiBjb250ZXh0LmphdmEpID8gJ0phdmFQYWNrYWdlJyA6IGdldENsYXNzT2YoY29udGV4dC5qYXZhKSxcbiAgICAgICAgcGhhbnRvbUNsYXNzID0gaXNDdXN0b21Db250ZXh0ID8gb2JqZWN0Q2xhc3MgOiAnUnVudGltZU9iamVjdCc7XG5cbiAgICAvKiogRGV0ZWN0IEphdmEgZW52aXJvbm1lbnRzLiAqL1xuICAgIHZhciBqYXZhID0gL1xcYkphdmEvLnRlc3QoamF2YUNsYXNzKSAmJiBjb250ZXh0LmphdmE7XG5cbiAgICAvKiogRGV0ZWN0IFJoaW5vLiAqL1xuICAgIHZhciByaGlubyA9IGphdmEgJiYgZ2V0Q2xhc3NPZihjb250ZXh0LmVudmlyb25tZW50KSA9PSBlbnZpcm9DbGFzcztcblxuICAgIC8qKiBBIGNoYXJhY3RlciB0byByZXByZXNlbnQgYWxwaGEuICovXG4gICAgdmFyIGFscGhhID0gamF2YSA/ICdhJyA6ICdcXHUwM2IxJztcblxuICAgIC8qKiBBIGNoYXJhY3RlciB0byByZXByZXNlbnQgYmV0YS4gKi9cbiAgICB2YXIgYmV0YSA9IGphdmEgPyAnYicgOiAnXFx1MDNiMic7XG5cbiAgICAvKiogQnJvd3NlciBkb2N1bWVudCBvYmplY3QuICovXG4gICAgdmFyIGRvYyA9IGNvbnRleHQuZG9jdW1lbnQgfHwge307XG5cbiAgICAvKipcbiAgICAgKiBEZXRlY3QgT3BlcmEgYnJvd3NlciAoUHJlc3RvLWJhc2VkKS5cbiAgICAgKiBodHRwOi8vd3d3Lmhvd3RvY3JlYXRlLmNvLnVrL29wZXJhU3R1ZmYvb3BlcmFPYmplY3QuaHRtbFxuICAgICAqIGh0dHA6Ly9kZXYub3BlcmEuY29tL2FydGljbGVzL3ZpZXcvb3BlcmEtbWluaS13ZWItY29udGVudC1hdXRob3JpbmctZ3VpZGVsaW5lcy8jb3BlcmFtaW5pXG4gICAgICovXG4gICAgdmFyIG9wZXJhID0gY29udGV4dC5vcGVyYW1pbmkgfHwgY29udGV4dC5vcGVyYTtcblxuICAgIC8qKiBPcGVyYSBgW1tDbGFzc11dYC4gKi9cbiAgICB2YXIgb3BlcmFDbGFzcyA9IHJlT3BlcmEudGVzdChvcGVyYUNsYXNzID0gKGlzQ3VzdG9tQ29udGV4dCAmJiBvcGVyYSkgPyBvcGVyYVsnW1tDbGFzc11dJ10gOiBnZXRDbGFzc09mKG9wZXJhKSlcbiAgICAgID8gb3BlcmFDbGFzc1xuICAgICAgOiAob3BlcmEgPSBudWxsKTtcblxuICAgIC8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cblxuICAgIC8qKiBUZW1wb3JhcnkgdmFyaWFibGUgdXNlZCBvdmVyIHRoZSBzY3JpcHQncyBsaWZldGltZS4gKi9cbiAgICB2YXIgZGF0YTtcblxuICAgIC8qKiBUaGUgQ1BVIGFyY2hpdGVjdHVyZS4gKi9cbiAgICB2YXIgYXJjaCA9IHVhO1xuXG4gICAgLyoqIFBsYXRmb3JtIGRlc2NyaXB0aW9uIGFycmF5LiAqL1xuICAgIHZhciBkZXNjcmlwdGlvbiA9IFtdO1xuXG4gICAgLyoqIFBsYXRmb3JtIGFscGhhL2JldGEgaW5kaWNhdG9yLiAqL1xuICAgIHZhciBwcmVyZWxlYXNlID0gbnVsbDtcblxuICAgIC8qKiBBIGZsYWcgdG8gaW5kaWNhdGUgdGhhdCBlbnZpcm9ubWVudCBmZWF0dXJlcyBzaG91bGQgYmUgdXNlZCB0byByZXNvbHZlIHRoZSBwbGF0Zm9ybS4gKi9cbiAgICB2YXIgdXNlRmVhdHVyZXMgPSB1YSA9PSB1c2VyQWdlbnQ7XG5cbiAgICAvKiogVGhlIGJyb3dzZXIvZW52aXJvbm1lbnQgdmVyc2lvbi4gKi9cbiAgICB2YXIgdmVyc2lvbiA9IHVzZUZlYXR1cmVzICYmIG9wZXJhICYmIHR5cGVvZiBvcGVyYS52ZXJzaW9uID09ICdmdW5jdGlvbicgJiYgb3BlcmEudmVyc2lvbigpO1xuXG4gICAgLyoqIEEgZmxhZyB0byBpbmRpY2F0ZSBpZiB0aGUgT1MgZW5kcyB3aXRoIFwiLyBWZXJzaW9uXCIgKi9cbiAgICB2YXIgaXNTcGVjaWFsQ2FzZWRPUztcblxuICAgIC8qIERldGVjdGFibGUgbGF5b3V0IGVuZ2luZXMgKG9yZGVyIGlzIGltcG9ydGFudCkuICovXG4gICAgdmFyIGxheW91dCA9IGdldExheW91dChbXG4gICAgICB7ICdsYWJlbCc6ICdFZGdlSFRNTCcsICdwYXR0ZXJuJzogJ0VkZ2UnIH0sXG4gICAgICAnVHJpZGVudCcsXG4gICAgICB7ICdsYWJlbCc6ICdXZWJLaXQnLCAncGF0dGVybic6ICdBcHBsZVdlYktpdCcgfSxcbiAgICAgICdpQ2FiJyxcbiAgICAgICdQcmVzdG8nLFxuICAgICAgJ05ldEZyb250JyxcbiAgICAgICdUYXNtYW4nLFxuICAgICAgJ0tIVE1MJyxcbiAgICAgICdHZWNrbydcbiAgICBdKTtcblxuICAgIC8qIERldGVjdGFibGUgYnJvd3NlciBuYW1lcyAob3JkZXIgaXMgaW1wb3J0YW50KS4gKi9cbiAgICB2YXIgbmFtZSA9IGdldE5hbWUoW1xuICAgICAgJ0Fkb2JlIEFJUicsXG4gICAgICAnQXJvcmEnLFxuICAgICAgJ0F2YW50IEJyb3dzZXInLFxuICAgICAgJ0JyZWFjaCcsXG4gICAgICAnQ2FtaW5vJyxcbiAgICAgICdFbGVjdHJvbicsXG4gICAgICAnRXBpcGhhbnknLFxuICAgICAgJ0Zlbm5lYycsXG4gICAgICAnRmxvY2snLFxuICAgICAgJ0dhbGVvbicsXG4gICAgICAnR3JlZW5Ccm93c2VyJyxcbiAgICAgICdpQ2FiJyxcbiAgICAgICdJY2V3ZWFzZWwnLFxuICAgICAgJ0stTWVsZW9uJyxcbiAgICAgICdLb25xdWVyb3InLFxuICAgICAgJ0x1bmFzY2FwZScsXG4gICAgICAnTWF4dGhvbicsXG4gICAgICB7ICdsYWJlbCc6ICdNaWNyb3NvZnQgRWRnZScsICdwYXR0ZXJuJzogJ0VkZ2UnIH0sXG4gICAgICAnTWlkb3JpJyxcbiAgICAgICdOb29rIEJyb3dzZXInLFxuICAgICAgJ1BhbGVNb29uJyxcbiAgICAgICdQaGFudG9tSlMnLFxuICAgICAgJ1JhdmVuJyxcbiAgICAgICdSZWtvbnEnLFxuICAgICAgJ1JvY2tNZWx0JyxcbiAgICAgIHsgJ2xhYmVsJzogJ1NhbXN1bmcgSW50ZXJuZXQnLCAncGF0dGVybic6ICdTYW1zdW5nQnJvd3NlcicgfSxcbiAgICAgICdTZWFNb25rZXknLFxuICAgICAgeyAnbGFiZWwnOiAnU2lsaycsICdwYXR0ZXJuJzogJyg/OkNsb3VkOXxTaWxrLUFjY2VsZXJhdGVkKScgfSxcbiAgICAgICdTbGVpcG5pcicsXG4gICAgICAnU2xpbUJyb3dzZXInLFxuICAgICAgeyAnbGFiZWwnOiAnU1JXYXJlIElyb24nLCAncGF0dGVybic6ICdJcm9uJyB9LFxuICAgICAgJ1N1bnJpc2UnLFxuICAgICAgJ1N3aWZ0Zm94JyxcbiAgICAgICdXYXRlcmZveCcsXG4gICAgICAnV2ViUG9zaXRpdmUnLFxuICAgICAgJ09wZXJhIE1pbmknLFxuICAgICAgeyAnbGFiZWwnOiAnT3BlcmEgTWluaScsICdwYXR0ZXJuJzogJ09QaU9TJyB9LFxuICAgICAgJ09wZXJhJyxcbiAgICAgIHsgJ2xhYmVsJzogJ09wZXJhJywgJ3BhdHRlcm4nOiAnT1BSJyB9LFxuICAgICAgJ0Nocm9tZScsXG4gICAgICB7ICdsYWJlbCc6ICdDaHJvbWUgTW9iaWxlJywgJ3BhdHRlcm4nOiAnKD86Q3JpT1N8Q3JNbyknIH0sXG4gICAgICB7ICdsYWJlbCc6ICdGaXJlZm94JywgJ3BhdHRlcm4nOiAnKD86RmlyZWZveHxNaW5lZmllbGQpJyB9LFxuICAgICAgeyAnbGFiZWwnOiAnRmlyZWZveCBmb3IgaU9TJywgJ3BhdHRlcm4nOiAnRnhpT1MnIH0sXG4gICAgICB7ICdsYWJlbCc6ICdJRScsICdwYXR0ZXJuJzogJ0lFTW9iaWxlJyB9LFxuICAgICAgeyAnbGFiZWwnOiAnSUUnLCAncGF0dGVybic6ICdNU0lFJyB9LFxuICAgICAgJ1NhZmFyaSdcbiAgICBdKTtcblxuICAgIC8qIERldGVjdGFibGUgcHJvZHVjdHMgKG9yZGVyIGlzIGltcG9ydGFudCkuICovXG4gICAgdmFyIHByb2R1Y3QgPSBnZXRQcm9kdWN0KFtcbiAgICAgIHsgJ2xhYmVsJzogJ0JsYWNrQmVycnknLCAncGF0dGVybic6ICdCQjEwJyB9LFxuICAgICAgJ0JsYWNrQmVycnknLFxuICAgICAgeyAnbGFiZWwnOiAnR2FsYXh5IFMnLCAncGF0dGVybic6ICdHVC1JOTAwMCcgfSxcbiAgICAgIHsgJ2xhYmVsJzogJ0dhbGF4eSBTMicsICdwYXR0ZXJuJzogJ0dULUk5MTAwJyB9LFxuICAgICAgeyAnbGFiZWwnOiAnR2FsYXh5IFMzJywgJ3BhdHRlcm4nOiAnR1QtSTkzMDAnIH0sXG4gICAgICB7ICdsYWJlbCc6ICdHYWxheHkgUzQnLCAncGF0dGVybic6ICdHVC1JOTUwMCcgfSxcbiAgICAgIHsgJ2xhYmVsJzogJ0dhbGF4eSBTNScsICdwYXR0ZXJuJzogJ1NNLUc5MDAnIH0sXG4gICAgICB7ICdsYWJlbCc6ICdHYWxheHkgUzYnLCAncGF0dGVybic6ICdTTS1HOTIwJyB9LFxuICAgICAgeyAnbGFiZWwnOiAnR2FsYXh5IFM2IEVkZ2UnLCAncGF0dGVybic6ICdTTS1HOTI1JyB9LFxuICAgICAgeyAnbGFiZWwnOiAnR2FsYXh5IFM3JywgJ3BhdHRlcm4nOiAnU00tRzkzMCcgfSxcbiAgICAgIHsgJ2xhYmVsJzogJ0dhbGF4eSBTNyBFZGdlJywgJ3BhdHRlcm4nOiAnU00tRzkzNScgfSxcbiAgICAgICdHb29nbGUgVFYnLFxuICAgICAgJ0x1bWlhJyxcbiAgICAgICdpUGFkJyxcbiAgICAgICdpUG9kJyxcbiAgICAgICdpUGhvbmUnLFxuICAgICAgJ0tpbmRsZScsXG4gICAgICB7ICdsYWJlbCc6ICdLaW5kbGUgRmlyZScsICdwYXR0ZXJuJzogJyg/OkNsb3VkOXxTaWxrLUFjY2VsZXJhdGVkKScgfSxcbiAgICAgICdOZXh1cycsXG4gICAgICAnTm9vaycsXG4gICAgICAnUGxheUJvb2snLFxuICAgICAgJ1BsYXlTdGF0aW9uIFZpdGEnLFxuICAgICAgJ1BsYXlTdGF0aW9uJyxcbiAgICAgICdUb3VjaFBhZCcsXG4gICAgICAnVHJhbnNmb3JtZXInLFxuICAgICAgeyAnbGFiZWwnOiAnV2lpIFUnLCAncGF0dGVybic6ICdXaWlVJyB9LFxuICAgICAgJ1dpaScsXG4gICAgICAnWGJveCBPbmUnLFxuICAgICAgeyAnbGFiZWwnOiAnWGJveCAzNjAnLCAncGF0dGVybic6ICdYYm94JyB9LFxuICAgICAgJ1hvb20nXG4gICAgXSk7XG5cbiAgICAvKiBEZXRlY3RhYmxlIG1hbnVmYWN0dXJlcnMuICovXG4gICAgdmFyIG1hbnVmYWN0dXJlciA9IGdldE1hbnVmYWN0dXJlcih7XG4gICAgICAnQXBwbGUnOiB7ICdpUGFkJzogMSwgJ2lQaG9uZSc6IDEsICdpUG9kJzogMSB9LFxuICAgICAgJ0FyY2hvcyc6IHt9LFxuICAgICAgJ0FtYXpvbic6IHsgJ0tpbmRsZSc6IDEsICdLaW5kbGUgRmlyZSc6IDEgfSxcbiAgICAgICdBc3VzJzogeyAnVHJhbnNmb3JtZXInOiAxIH0sXG4gICAgICAnQmFybmVzICYgTm9ibGUnOiB7ICdOb29rJzogMSB9LFxuICAgICAgJ0JsYWNrQmVycnknOiB7ICdQbGF5Qm9vayc6IDEgfSxcbiAgICAgICdHb29nbGUnOiB7ICdHb29nbGUgVFYnOiAxLCAnTmV4dXMnOiAxIH0sXG4gICAgICAnSFAnOiB7ICdUb3VjaFBhZCc6IDEgfSxcbiAgICAgICdIVEMnOiB7fSxcbiAgICAgICdMRyc6IHt9LFxuICAgICAgJ01pY3Jvc29mdCc6IHsgJ1hib3gnOiAxLCAnWGJveCBPbmUnOiAxIH0sXG4gICAgICAnTW90b3JvbGEnOiB7ICdYb29tJzogMSB9LFxuICAgICAgJ05pbnRlbmRvJzogeyAnV2lpIFUnOiAxLCAgJ1dpaSc6IDEgfSxcbiAgICAgICdOb2tpYSc6IHsgJ0x1bWlhJzogMSB9LFxuICAgICAgJ1NhbXN1bmcnOiB7ICdHYWxheHkgUyc6IDEsICdHYWxheHkgUzInOiAxLCAnR2FsYXh5IFMzJzogMSwgJ0dhbGF4eSBTNCc6IDEgfSxcbiAgICAgICdTb255JzogeyAnUGxheVN0YXRpb24nOiAxLCAnUGxheVN0YXRpb24gVml0YSc6IDEgfVxuICAgIH0pO1xuXG4gICAgLyogRGV0ZWN0YWJsZSBvcGVyYXRpbmcgc3lzdGVtcyAob3JkZXIgaXMgaW1wb3J0YW50KS4gKi9cbiAgICB2YXIgb3MgPSBnZXRPUyhbXG4gICAgICAnV2luZG93cyBQaG9uZScsXG4gICAgICAnQW5kcm9pZCcsXG4gICAgICAnQ2VudE9TJyxcbiAgICAgIHsgJ2xhYmVsJzogJ0Nocm9tZSBPUycsICdwYXR0ZXJuJzogJ0NyT1MnIH0sXG4gICAgICAnRGViaWFuJyxcbiAgICAgICdGZWRvcmEnLFxuICAgICAgJ0ZyZWVCU0QnLFxuICAgICAgJ0dlbnRvbycsXG4gICAgICAnSGFpa3UnLFxuICAgICAgJ0t1YnVudHUnLFxuICAgICAgJ0xpbnV4IE1pbnQnLFxuICAgICAgJ09wZW5CU0QnLFxuICAgICAgJ1JlZCBIYXQnLFxuICAgICAgJ1N1U0UnLFxuICAgICAgJ1VidW50dScsXG4gICAgICAnWHVidW50dScsXG4gICAgICAnQ3lnd2luJyxcbiAgICAgICdTeW1iaWFuIE9TJyxcbiAgICAgICdocHdPUycsXG4gICAgICAnd2ViT1MgJyxcbiAgICAgICd3ZWJPUycsXG4gICAgICAnVGFibGV0IE9TJyxcbiAgICAgICdUaXplbicsXG4gICAgICAnTGludXgnLFxuICAgICAgJ01hYyBPUyBYJyxcbiAgICAgICdNYWNpbnRvc2gnLFxuICAgICAgJ01hYycsXG4gICAgICAnV2luZG93cyA5ODsnLFxuICAgICAgJ1dpbmRvd3MgJ1xuICAgIF0pO1xuXG4gICAgLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuXG4gICAgLyoqXG4gICAgICogUGlja3MgdGhlIGxheW91dCBlbmdpbmUgZnJvbSBhbiBhcnJheSBvZiBndWVzc2VzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBndWVzc2VzIEFuIGFycmF5IG9mIGd1ZXNzZXMuXG4gICAgICogQHJldHVybnMge251bGx8c3RyaW5nfSBUaGUgZGV0ZWN0ZWQgbGF5b3V0IGVuZ2luZS5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBnZXRMYXlvdXQoZ3Vlc3Nlcykge1xuICAgICAgcmV0dXJuIHJlZHVjZShndWVzc2VzLCBmdW5jdGlvbihyZXN1bHQsIGd1ZXNzKSB7XG4gICAgICAgIHJldHVybiByZXN1bHQgfHwgUmVnRXhwKCdcXFxcYicgKyAoXG4gICAgICAgICAgZ3Vlc3MucGF0dGVybiB8fCBxdWFsaWZ5KGd1ZXNzKVxuICAgICAgICApICsgJ1xcXFxiJywgJ2knKS5leGVjKHVhKSAmJiAoZ3Vlc3MubGFiZWwgfHwgZ3Vlc3MpO1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUGlja3MgdGhlIG1hbnVmYWN0dXJlciBmcm9tIGFuIGFycmF5IG9mIGd1ZXNzZXMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGd1ZXNzZXMgQW4gb2JqZWN0IG9mIGd1ZXNzZXMuXG4gICAgICogQHJldHVybnMge251bGx8c3RyaW5nfSBUaGUgZGV0ZWN0ZWQgbWFudWZhY3R1cmVyLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGdldE1hbnVmYWN0dXJlcihndWVzc2VzKSB7XG4gICAgICByZXR1cm4gcmVkdWNlKGd1ZXNzZXMsIGZ1bmN0aW9uKHJlc3VsdCwgdmFsdWUsIGtleSkge1xuICAgICAgICAvLyBMb29rdXAgdGhlIG1hbnVmYWN0dXJlciBieSBwcm9kdWN0IG9yIHNjYW4gdGhlIFVBIGZvciB0aGUgbWFudWZhY3R1cmVyLlxuICAgICAgICByZXR1cm4gcmVzdWx0IHx8IChcbiAgICAgICAgICB2YWx1ZVtwcm9kdWN0XSB8fFxuICAgICAgICAgIHZhbHVlWy9eW2Etel0rKD86ICtbYS16XStcXGIpKi9pLmV4ZWMocHJvZHVjdCldIHx8XG4gICAgICAgICAgUmVnRXhwKCdcXFxcYicgKyBxdWFsaWZ5KGtleSkgKyAnKD86XFxcXGJ8XFxcXHcqXFxcXGQpJywgJ2knKS5leGVjKHVhKVxuICAgICAgICApICYmIGtleTtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFBpY2tzIHRoZSBicm93c2VyIG5hbWUgZnJvbSBhbiBhcnJheSBvZiBndWVzc2VzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBndWVzc2VzIEFuIGFycmF5IG9mIGd1ZXNzZXMuXG4gICAgICogQHJldHVybnMge251bGx8c3RyaW5nfSBUaGUgZGV0ZWN0ZWQgYnJvd3NlciBuYW1lLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGdldE5hbWUoZ3Vlc3Nlcykge1xuICAgICAgcmV0dXJuIHJlZHVjZShndWVzc2VzLCBmdW5jdGlvbihyZXN1bHQsIGd1ZXNzKSB7XG4gICAgICAgIHJldHVybiByZXN1bHQgfHwgUmVnRXhwKCdcXFxcYicgKyAoXG4gICAgICAgICAgZ3Vlc3MucGF0dGVybiB8fCBxdWFsaWZ5KGd1ZXNzKVxuICAgICAgICApICsgJ1xcXFxiJywgJ2knKS5leGVjKHVhKSAmJiAoZ3Vlc3MubGFiZWwgfHwgZ3Vlc3MpO1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUGlja3MgdGhlIE9TIG5hbWUgZnJvbSBhbiBhcnJheSBvZiBndWVzc2VzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBndWVzc2VzIEFuIGFycmF5IG9mIGd1ZXNzZXMuXG4gICAgICogQHJldHVybnMge251bGx8c3RyaW5nfSBUaGUgZGV0ZWN0ZWQgT1MgbmFtZS5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBnZXRPUyhndWVzc2VzKSB7XG4gICAgICByZXR1cm4gcmVkdWNlKGd1ZXNzZXMsIGZ1bmN0aW9uKHJlc3VsdCwgZ3Vlc3MpIHtcbiAgICAgICAgdmFyIHBhdHRlcm4gPSBndWVzcy5wYXR0ZXJuIHx8IHF1YWxpZnkoZ3Vlc3MpO1xuICAgICAgICBpZiAoIXJlc3VsdCAmJiAocmVzdWx0ID1cbiAgICAgICAgICAgICAgUmVnRXhwKCdcXFxcYicgKyBwYXR0ZXJuICsgJyg/Oi9bXFxcXGQuXSt8WyBcXFxcdy5dKiknLCAnaScpLmV4ZWModWEpXG4gICAgICAgICAgICApKSB7XG4gICAgICAgICAgcmVzdWx0ID0gY2xlYW51cE9TKHJlc3VsdCwgcGF0dGVybiwgZ3Vlc3MubGFiZWwgfHwgZ3Vlc3MpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBQaWNrcyB0aGUgcHJvZHVjdCBuYW1lIGZyb20gYW4gYXJyYXkgb2YgZ3Vlc3Nlcy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtBcnJheX0gZ3Vlc3NlcyBBbiBhcnJheSBvZiBndWVzc2VzLlxuICAgICAqIEByZXR1cm5zIHtudWxsfHN0cmluZ30gVGhlIGRldGVjdGVkIHByb2R1Y3QgbmFtZS5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBnZXRQcm9kdWN0KGd1ZXNzZXMpIHtcbiAgICAgIHJldHVybiByZWR1Y2UoZ3Vlc3NlcywgZnVuY3Rpb24ocmVzdWx0LCBndWVzcykge1xuICAgICAgICB2YXIgcGF0dGVybiA9IGd1ZXNzLnBhdHRlcm4gfHwgcXVhbGlmeShndWVzcyk7XG4gICAgICAgIGlmICghcmVzdWx0ICYmIChyZXN1bHQgPVxuICAgICAgICAgICAgICBSZWdFeHAoJ1xcXFxiJyArIHBhdHRlcm4gKyAnICpcXFxcZCtbLlxcXFx3X10qJywgJ2knKS5leGVjKHVhKSB8fFxuICAgICAgICAgICAgICBSZWdFeHAoJ1xcXFxiJyArIHBhdHRlcm4gKyAnICpcXFxcdystW1xcXFx3XSonLCAnaScpLmV4ZWModWEpIHx8XG4gICAgICAgICAgICAgIFJlZ0V4cCgnXFxcXGInICsgcGF0dGVybiArICcoPzo7ICooPzpbYS16XStbXy1dKT9bYS16XStcXFxcZCt8W14gKCk7LV0qKScsICdpJykuZXhlYyh1YSlcbiAgICAgICAgICAgICkpIHtcbiAgICAgICAgICAvLyBTcGxpdCBieSBmb3J3YXJkIHNsYXNoIGFuZCBhcHBlbmQgcHJvZHVjdCB2ZXJzaW9uIGlmIG5lZWRlZC5cbiAgICAgICAgICBpZiAoKHJlc3VsdCA9IFN0cmluZygoZ3Vlc3MubGFiZWwgJiYgIVJlZ0V4cChwYXR0ZXJuLCAnaScpLnRlc3QoZ3Vlc3MubGFiZWwpKSA/IGd1ZXNzLmxhYmVsIDogcmVzdWx0KS5zcGxpdCgnLycpKVsxXSAmJiAhL1tcXGQuXSsvLnRlc3QocmVzdWx0WzBdKSkge1xuICAgICAgICAgICAgcmVzdWx0WzBdICs9ICcgJyArIHJlc3VsdFsxXTtcbiAgICAgICAgICB9XG4gICAgICAgICAgLy8gQ29ycmVjdCBjaGFyYWN0ZXIgY2FzZSBhbmQgY2xlYW51cCBzdHJpbmcuXG4gICAgICAgICAgZ3Vlc3MgPSBndWVzcy5sYWJlbCB8fCBndWVzcztcbiAgICAgICAgICByZXN1bHQgPSBmb3JtYXQocmVzdWx0WzBdXG4gICAgICAgICAgICAucmVwbGFjZShSZWdFeHAocGF0dGVybiwgJ2knKSwgZ3Vlc3MpXG4gICAgICAgICAgICAucmVwbGFjZShSZWdFeHAoJzsgKig/OicgKyBndWVzcyArICdbXy1dKT8nLCAnaScpLCAnICcpXG4gICAgICAgICAgICAucmVwbGFjZShSZWdFeHAoJygnICsgZ3Vlc3MgKyAnKVstXy5dPyhcXFxcdyknLCAnaScpLCAnJDEgJDInKSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlc29sdmVzIHRoZSB2ZXJzaW9uIHVzaW5nIGFuIGFycmF5IG9mIFVBIHBhdHRlcm5zLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBwYXR0ZXJucyBBbiBhcnJheSBvZiBVQSBwYXR0ZXJucy5cbiAgICAgKiBAcmV0dXJucyB7bnVsbHxzdHJpbmd9IFRoZSBkZXRlY3RlZCB2ZXJzaW9uLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGdldFZlcnNpb24ocGF0dGVybnMpIHtcbiAgICAgIHJldHVybiByZWR1Y2UocGF0dGVybnMsIGZ1bmN0aW9uKHJlc3VsdCwgcGF0dGVybikge1xuICAgICAgICByZXR1cm4gcmVzdWx0IHx8IChSZWdFeHAocGF0dGVybiArXG4gICAgICAgICAgJyg/Oi1bXFxcXGQuXSsvfCg/OiBmb3IgW1xcXFx3LV0rKT9bIC8tXSkoW1xcXFxkLl0rW14gKCk7L18tXSopJywgJ2knKS5leGVjKHVhKSB8fCAwKVsxXSB8fCBudWxsO1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyBgcGxhdGZvcm0uZGVzY3JpcHRpb25gIHdoZW4gdGhlIHBsYXRmb3JtIG9iamVjdCBpcyBjb2VyY2VkIHRvIGEgc3RyaW5nLlxuICAgICAqXG4gICAgICogQG5hbWUgdG9TdHJpbmdcbiAgICAgKiBAbWVtYmVyT2YgcGxhdGZvcm1cbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfSBSZXR1cm5zIGBwbGF0Zm9ybS5kZXNjcmlwdGlvbmAgaWYgYXZhaWxhYmxlLCBlbHNlIGFuIGVtcHR5IHN0cmluZy5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiB0b1N0cmluZ1BsYXRmb3JtKCkge1xuICAgICAgcmV0dXJuIHRoaXMuZGVzY3JpcHRpb24gfHwgJyc7XG4gICAgfVxuXG4gICAgLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuXG4gICAgLy8gQ29udmVydCBsYXlvdXQgdG8gYW4gYXJyYXkgc28gd2UgY2FuIGFkZCBleHRyYSBkZXRhaWxzLlxuICAgIGxheW91dCAmJiAobGF5b3V0ID0gW2xheW91dF0pO1xuXG4gICAgLy8gRGV0ZWN0IHByb2R1Y3QgbmFtZXMgdGhhdCBjb250YWluIHRoZWlyIG1hbnVmYWN0dXJlcidzIG5hbWUuXG4gICAgaWYgKG1hbnVmYWN0dXJlciAmJiAhcHJvZHVjdCkge1xuICAgICAgcHJvZHVjdCA9IGdldFByb2R1Y3QoW21hbnVmYWN0dXJlcl0pO1xuICAgIH1cbiAgICAvLyBDbGVhbiB1cCBHb29nbGUgVFYuXG4gICAgaWYgKChkYXRhID0gL1xcYkdvb2dsZSBUVlxcYi8uZXhlYyhwcm9kdWN0KSkpIHtcbiAgICAgIHByb2R1Y3QgPSBkYXRhWzBdO1xuICAgIH1cbiAgICAvLyBEZXRlY3Qgc2ltdWxhdG9ycy5cbiAgICBpZiAoL1xcYlNpbXVsYXRvclxcYi9pLnRlc3QodWEpKSB7XG4gICAgICBwcm9kdWN0ID0gKHByb2R1Y3QgPyBwcm9kdWN0ICsgJyAnIDogJycpICsgJ1NpbXVsYXRvcic7XG4gICAgfVxuICAgIC8vIERldGVjdCBPcGVyYSBNaW5pIDgrIHJ1bm5pbmcgaW4gVHVyYm8vVW5jb21wcmVzc2VkIG1vZGUgb24gaU9TLlxuICAgIGlmIChuYW1lID09ICdPcGVyYSBNaW5pJyAmJiAvXFxiT1BpT1NcXGIvLnRlc3QodWEpKSB7XG4gICAgICBkZXNjcmlwdGlvbi5wdXNoKCdydW5uaW5nIGluIFR1cmJvL1VuY29tcHJlc3NlZCBtb2RlJyk7XG4gICAgfVxuICAgIC8vIERldGVjdCBJRSBNb2JpbGUgMTEuXG4gICAgaWYgKG5hbWUgPT0gJ0lFJyAmJiAvXFxibGlrZSBpUGhvbmUgT1NcXGIvLnRlc3QodWEpKSB7XG4gICAgICBkYXRhID0gcGFyc2UodWEucmVwbGFjZSgvbGlrZSBpUGhvbmUgT1MvLCAnJykpO1xuICAgICAgbWFudWZhY3R1cmVyID0gZGF0YS5tYW51ZmFjdHVyZXI7XG4gICAgICBwcm9kdWN0ID0gZGF0YS5wcm9kdWN0O1xuICAgIH1cbiAgICAvLyBEZXRlY3QgaU9TLlxuICAgIGVsc2UgaWYgKC9eaVAvLnRlc3QocHJvZHVjdCkpIHtcbiAgICAgIG5hbWUgfHwgKG5hbWUgPSAnU2FmYXJpJyk7XG4gICAgICBvcyA9ICdpT1MnICsgKChkYXRhID0gLyBPUyAoW1xcZF9dKykvaS5leGVjKHVhKSlcbiAgICAgICAgPyAnICcgKyBkYXRhWzFdLnJlcGxhY2UoL18vZywgJy4nKVxuICAgICAgICA6ICcnKTtcbiAgICB9XG4gICAgLy8gRGV0ZWN0IEt1YnVudHUuXG4gICAgZWxzZSBpZiAobmFtZSA9PSAnS29ucXVlcm9yJyAmJiAhL2J1bnR1L2kudGVzdChvcykpIHtcbiAgICAgIG9zID0gJ0t1YnVudHUnO1xuICAgIH1cbiAgICAvLyBEZXRlY3QgQW5kcm9pZCBicm93c2Vycy5cbiAgICBlbHNlIGlmICgobWFudWZhY3R1cmVyICYmIG1hbnVmYWN0dXJlciAhPSAnR29vZ2xlJyAmJlxuICAgICAgICAoKC9DaHJvbWUvLnRlc3QobmFtZSkgJiYgIS9cXGJNb2JpbGUgU2FmYXJpXFxiL2kudGVzdCh1YSkpIHx8IC9cXGJWaXRhXFxiLy50ZXN0KHByb2R1Y3QpKSkgfHxcbiAgICAgICAgKC9cXGJBbmRyb2lkXFxiLy50ZXN0KG9zKSAmJiAvXkNocm9tZS8udGVzdChuYW1lKSAmJiAvXFxiVmVyc2lvblxcLy9pLnRlc3QodWEpKSkge1xuICAgICAgbmFtZSA9ICdBbmRyb2lkIEJyb3dzZXInO1xuICAgICAgb3MgPSAvXFxiQW5kcm9pZFxcYi8udGVzdChvcykgPyBvcyA6ICdBbmRyb2lkJztcbiAgICB9XG4gICAgLy8gRGV0ZWN0IFNpbGsgZGVza3RvcC9hY2NlbGVyYXRlZCBtb2Rlcy5cbiAgICBlbHNlIGlmIChuYW1lID09ICdTaWxrJykge1xuICAgICAgaWYgKCEvXFxiTW9iaS9pLnRlc3QodWEpKSB7XG4gICAgICAgIG9zID0gJ0FuZHJvaWQnO1xuICAgICAgICBkZXNjcmlwdGlvbi51bnNoaWZ0KCdkZXNrdG9wIG1vZGUnKTtcbiAgICAgIH1cbiAgICAgIGlmICgvQWNjZWxlcmF0ZWQgKj0gKnRydWUvaS50ZXN0KHVhKSkge1xuICAgICAgICBkZXNjcmlwdGlvbi51bnNoaWZ0KCdhY2NlbGVyYXRlZCcpO1xuICAgICAgfVxuICAgIH1cbiAgICAvLyBEZXRlY3QgUGFsZU1vb24gaWRlbnRpZnlpbmcgYXMgRmlyZWZveC5cbiAgICBlbHNlIGlmIChuYW1lID09ICdQYWxlTW9vbicgJiYgKGRhdGEgPSAvXFxiRmlyZWZveFxcLyhbXFxkLl0rKVxcYi8uZXhlYyh1YSkpKSB7XG4gICAgICBkZXNjcmlwdGlvbi5wdXNoKCdpZGVudGlmeWluZyBhcyBGaXJlZm94ICcgKyBkYXRhWzFdKTtcbiAgICB9XG4gICAgLy8gRGV0ZWN0IEZpcmVmb3ggT1MgYW5kIHByb2R1Y3RzIHJ1bm5pbmcgRmlyZWZveC5cbiAgICBlbHNlIGlmIChuYW1lID09ICdGaXJlZm94JyAmJiAoZGF0YSA9IC9cXGIoTW9iaWxlfFRhYmxldHxUVilcXGIvaS5leGVjKHVhKSkpIHtcbiAgICAgIG9zIHx8IChvcyA9ICdGaXJlZm94IE9TJyk7XG4gICAgICBwcm9kdWN0IHx8IChwcm9kdWN0ID0gZGF0YVsxXSk7XG4gICAgfVxuICAgIC8vIERldGVjdCBmYWxzZSBwb3NpdGl2ZXMgZm9yIEZpcmVmb3gvU2FmYXJpLlxuICAgIGVsc2UgaWYgKCFuYW1lIHx8IChkYXRhID0gIS9cXGJNaW5lZmllbGRcXGIvaS50ZXN0KHVhKSAmJiAvXFxiKD86RmlyZWZveHxTYWZhcmkpXFxiLy5leGVjKG5hbWUpKSkge1xuICAgICAgLy8gRXNjYXBlIHRoZSBgL2AgZm9yIEZpcmVmb3ggMS5cbiAgICAgIGlmIChuYW1lICYmICFwcm9kdWN0ICYmIC9bXFwvLF18XlteKF0rP1xcKS8udGVzdCh1YS5zbGljZSh1YS5pbmRleE9mKGRhdGEgKyAnLycpICsgOCkpKSB7XG4gICAgICAgIC8vIENsZWFyIG5hbWUgb2YgZmFsc2UgcG9zaXRpdmVzLlxuICAgICAgICBuYW1lID0gbnVsbDtcbiAgICAgIH1cbiAgICAgIC8vIFJlYXNzaWduIGEgZ2VuZXJpYyBuYW1lLlxuICAgICAgaWYgKChkYXRhID0gcHJvZHVjdCB8fCBtYW51ZmFjdHVyZXIgfHwgb3MpICYmXG4gICAgICAgICAgKHByb2R1Y3QgfHwgbWFudWZhY3R1cmVyIHx8IC9cXGIoPzpBbmRyb2lkfFN5bWJpYW4gT1N8VGFibGV0IE9TfHdlYk9TKVxcYi8udGVzdChvcykpKSB7XG4gICAgICAgIG5hbWUgPSAvW2Etel0rKD86IEhhdCk/L2kuZXhlYygvXFxiQW5kcm9pZFxcYi8udGVzdChvcykgPyBvcyA6IGRhdGEpICsgJyBCcm93c2VyJztcbiAgICAgIH1cbiAgICB9XG4gICAgLy8gQWRkIENocm9tZSB2ZXJzaW9uIHRvIGRlc2NyaXB0aW9uIGZvciBFbGVjdHJvbi5cbiAgICBlbHNlIGlmIChuYW1lID09ICdFbGVjdHJvbicgJiYgKGRhdGEgPSAoL1xcYkNocm9tZVxcLyhbXFxkLl0rKVxcYi8uZXhlYyh1YSkgfHwgMClbMV0pKSB7XG4gICAgICBkZXNjcmlwdGlvbi5wdXNoKCdDaHJvbWl1bSAnICsgZGF0YSk7XG4gICAgfVxuICAgIC8vIERldGVjdCBub24tT3BlcmEgKFByZXN0by1iYXNlZCkgdmVyc2lvbnMgKG9yZGVyIGlzIGltcG9ydGFudCkuXG4gICAgaWYgKCF2ZXJzaW9uKSB7XG4gICAgICB2ZXJzaW9uID0gZ2V0VmVyc2lvbihbXG4gICAgICAgICcoPzpDbG91ZDl8Q3JpT1N8Q3JNb3xFZGdlfEZ4aU9TfElFTW9iaWxlfElyb258T3BlcmEgP01pbml8T1BpT1N8T1BSfFJhdmVufFNhbXN1bmdCcm93c2VyfFNpbGsoPyEvW1xcXFxkLl0rJCkpJyxcbiAgICAgICAgJ1ZlcnNpb24nLFxuICAgICAgICBxdWFsaWZ5KG5hbWUpLFxuICAgICAgICAnKD86RmlyZWZveHxNaW5lZmllbGR8TmV0RnJvbnQpJ1xuICAgICAgXSk7XG4gICAgfVxuICAgIC8vIERldGVjdCBzdHViYm9ybiBsYXlvdXQgZW5naW5lcy5cbiAgICBpZiAoKGRhdGEgPVxuICAgICAgICAgIGxheW91dCA9PSAnaUNhYicgJiYgcGFyc2VGbG9hdCh2ZXJzaW9uKSA+IDMgJiYgJ1dlYktpdCcgfHxcbiAgICAgICAgICAvXFxiT3BlcmFcXGIvLnRlc3QobmFtZSkgJiYgKC9cXGJPUFJcXGIvLnRlc3QodWEpID8gJ0JsaW5rJyA6ICdQcmVzdG8nKSB8fFxuICAgICAgICAgIC9cXGIoPzpNaWRvcml8Tm9va3xTYWZhcmkpXFxiL2kudGVzdCh1YSkgJiYgIS9eKD86VHJpZGVudHxFZGdlSFRNTCkkLy50ZXN0KGxheW91dCkgJiYgJ1dlYktpdCcgfHxcbiAgICAgICAgICAhbGF5b3V0ICYmIC9cXGJNU0lFXFxiL2kudGVzdCh1YSkgJiYgKG9zID09ICdNYWMgT1MnID8gJ1Rhc21hbicgOiAnVHJpZGVudCcpIHx8XG4gICAgICAgICAgbGF5b3V0ID09ICdXZWJLaXQnICYmIC9cXGJQbGF5U3RhdGlvblxcYig/ISBWaXRhXFxiKS9pLnRlc3QobmFtZSkgJiYgJ05ldEZyb250J1xuICAgICAgICApKSB7XG4gICAgICBsYXlvdXQgPSBbZGF0YV07XG4gICAgfVxuICAgIC8vIERldGVjdCBXaW5kb3dzIFBob25lIDcgZGVza3RvcCBtb2RlLlxuICAgIGlmIChuYW1lID09ICdJRScgJiYgKGRhdGEgPSAoLzsgKig/OlhCTFdQfFp1bmVXUCkoXFxkKykvaS5leGVjKHVhKSB8fCAwKVsxXSkpIHtcbiAgICAgIG5hbWUgKz0gJyBNb2JpbGUnO1xuICAgICAgb3MgPSAnV2luZG93cyBQaG9uZSAnICsgKC9cXCskLy50ZXN0KGRhdGEpID8gZGF0YSA6IGRhdGEgKyAnLngnKTtcbiAgICAgIGRlc2NyaXB0aW9uLnVuc2hpZnQoJ2Rlc2t0b3AgbW9kZScpO1xuICAgIH1cbiAgICAvLyBEZXRlY3QgV2luZG93cyBQaG9uZSA4LnggZGVza3RvcCBtb2RlLlxuICAgIGVsc2UgaWYgKC9cXGJXUERlc2t0b3BcXGIvaS50ZXN0KHVhKSkge1xuICAgICAgbmFtZSA9ICdJRSBNb2JpbGUnO1xuICAgICAgb3MgPSAnV2luZG93cyBQaG9uZSA4LngnO1xuICAgICAgZGVzY3JpcHRpb24udW5zaGlmdCgnZGVza3RvcCBtb2RlJyk7XG4gICAgICB2ZXJzaW9uIHx8ICh2ZXJzaW9uID0gKC9cXGJydjooW1xcZC5dKykvLmV4ZWModWEpIHx8IDApWzFdKTtcbiAgICB9XG4gICAgLy8gRGV0ZWN0IElFIDExIGlkZW50aWZ5aW5nIGFzIG90aGVyIGJyb3dzZXJzLlxuICAgIGVsc2UgaWYgKG5hbWUgIT0gJ0lFJyAmJiBsYXlvdXQgPT0gJ1RyaWRlbnQnICYmIChkYXRhID0gL1xcYnJ2OihbXFxkLl0rKS8uZXhlYyh1YSkpKSB7XG4gICAgICBpZiAobmFtZSkge1xuICAgICAgICBkZXNjcmlwdGlvbi5wdXNoKCdpZGVudGlmeWluZyBhcyAnICsgbmFtZSArICh2ZXJzaW9uID8gJyAnICsgdmVyc2lvbiA6ICcnKSk7XG4gICAgICB9XG4gICAgICBuYW1lID0gJ0lFJztcbiAgICAgIHZlcnNpb24gPSBkYXRhWzFdO1xuICAgIH1cbiAgICAvLyBMZXZlcmFnZSBlbnZpcm9ubWVudCBmZWF0dXJlcy5cbiAgICBpZiAodXNlRmVhdHVyZXMpIHtcbiAgICAgIC8vIERldGVjdCBzZXJ2ZXItc2lkZSBlbnZpcm9ubWVudHMuXG4gICAgICAvLyBSaGlubyBoYXMgYSBnbG9iYWwgZnVuY3Rpb24gd2hpbGUgb3RoZXJzIGhhdmUgYSBnbG9iYWwgb2JqZWN0LlxuICAgICAgaWYgKGlzSG9zdFR5cGUoY29udGV4dCwgJ2dsb2JhbCcpKSB7XG4gICAgICAgIGlmIChqYXZhKSB7XG4gICAgICAgICAgZGF0YSA9IGphdmEubGFuZy5TeXN0ZW07XG4gICAgICAgICAgYXJjaCA9IGRhdGEuZ2V0UHJvcGVydHkoJ29zLmFyY2gnKTtcbiAgICAgICAgICBvcyA9IG9zIHx8IGRhdGEuZ2V0UHJvcGVydHkoJ29zLm5hbWUnKSArICcgJyArIGRhdGEuZ2V0UHJvcGVydHkoJ29zLnZlcnNpb24nKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAocmhpbm8pIHtcbiAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgdmVyc2lvbiA9IGNvbnRleHQucmVxdWlyZSgncmluZ28vZW5naW5lJykudmVyc2lvbi5qb2luKCcuJyk7XG4gICAgICAgICAgICBuYW1lID0gJ1JpbmdvSlMnO1xuICAgICAgICAgIH0gY2F0Y2goZSkge1xuICAgICAgICAgICAgaWYgKChkYXRhID0gY29udGV4dC5zeXN0ZW0pICYmIGRhdGEuZ2xvYmFsLnN5c3RlbSA9PSBjb250ZXh0LnN5c3RlbSkge1xuICAgICAgICAgICAgICBuYW1lID0gJ05hcndoYWwnO1xuICAgICAgICAgICAgICBvcyB8fCAob3MgPSBkYXRhWzBdLm9zIHx8IG51bGwpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoIW5hbWUpIHtcbiAgICAgICAgICAgIG5hbWUgPSAnUmhpbm8nO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmIChcbiAgICAgICAgICB0eXBlb2YgY29udGV4dC5wcm9jZXNzID09ICdvYmplY3QnICYmICFjb250ZXh0LnByb2Nlc3MuYnJvd3NlciAmJlxuICAgICAgICAgIChkYXRhID0gY29udGV4dC5wcm9jZXNzKVxuICAgICAgICApIHtcbiAgICAgICAgICBpZiAodHlwZW9mIGRhdGEudmVyc2lvbnMgPT0gJ29iamVjdCcpIHtcbiAgICAgICAgICAgIGlmICh0eXBlb2YgZGF0YS52ZXJzaW9ucy5lbGVjdHJvbiA9PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgICBkZXNjcmlwdGlvbi5wdXNoKCdOb2RlICcgKyBkYXRhLnZlcnNpb25zLm5vZGUpO1xuICAgICAgICAgICAgICBuYW1lID0gJ0VsZWN0cm9uJztcbiAgICAgICAgICAgICAgdmVyc2lvbiA9IGRhdGEudmVyc2lvbnMuZWxlY3Ryb247XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHR5cGVvZiBkYXRhLnZlcnNpb25zLm53ID09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAgIGRlc2NyaXB0aW9uLnB1c2goJ0Nocm9taXVtICcgKyB2ZXJzaW9uLCAnTm9kZSAnICsgZGF0YS52ZXJzaW9ucy5ub2RlKTtcbiAgICAgICAgICAgICAgbmFtZSA9ICdOVy5qcyc7XG4gICAgICAgICAgICAgIHZlcnNpb24gPSBkYXRhLnZlcnNpb25zLm53O1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoIW5hbWUpIHtcbiAgICAgICAgICAgIG5hbWUgPSAnTm9kZS5qcyc7XG4gICAgICAgICAgICBhcmNoID0gZGF0YS5hcmNoO1xuICAgICAgICAgICAgb3MgPSBkYXRhLnBsYXRmb3JtO1xuICAgICAgICAgICAgdmVyc2lvbiA9IC9bXFxkLl0rLy5leGVjKGRhdGEudmVyc2lvbik7XG4gICAgICAgICAgICB2ZXJzaW9uID0gdmVyc2lvbiA/IHZlcnNpb25bMF0gOiBudWxsO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgLy8gRGV0ZWN0IEFkb2JlIEFJUi5cbiAgICAgIGVsc2UgaWYgKGdldENsYXNzT2YoKGRhdGEgPSBjb250ZXh0LnJ1bnRpbWUpKSA9PSBhaXJSdW50aW1lQ2xhc3MpIHtcbiAgICAgICAgbmFtZSA9ICdBZG9iZSBBSVInO1xuICAgICAgICBvcyA9IGRhdGEuZmxhc2guc3lzdGVtLkNhcGFiaWxpdGllcy5vcztcbiAgICAgIH1cbiAgICAgIC8vIERldGVjdCBQaGFudG9tSlMuXG4gICAgICBlbHNlIGlmIChnZXRDbGFzc09mKChkYXRhID0gY29udGV4dC5waGFudG9tKSkgPT0gcGhhbnRvbUNsYXNzKSB7XG4gICAgICAgIG5hbWUgPSAnUGhhbnRvbUpTJztcbiAgICAgICAgdmVyc2lvbiA9IChkYXRhID0gZGF0YS52ZXJzaW9uIHx8IG51bGwpICYmIChkYXRhLm1ham9yICsgJy4nICsgZGF0YS5taW5vciArICcuJyArIGRhdGEucGF0Y2gpO1xuICAgICAgfVxuICAgICAgLy8gRGV0ZWN0IElFIGNvbXBhdGliaWxpdHkgbW9kZXMuXG4gICAgICBlbHNlIGlmICh0eXBlb2YgZG9jLmRvY3VtZW50TW9kZSA9PSAnbnVtYmVyJyAmJiAoZGF0YSA9IC9cXGJUcmlkZW50XFwvKFxcZCspL2kuZXhlYyh1YSkpKSB7XG4gICAgICAgIC8vIFdlJ3JlIGluIGNvbXBhdGliaWxpdHkgbW9kZSB3aGVuIHRoZSBUcmlkZW50IHZlcnNpb24gKyA0IGRvZXNuJ3RcbiAgICAgICAgLy8gZXF1YWwgdGhlIGRvY3VtZW50IG1vZGUuXG4gICAgICAgIHZlcnNpb24gPSBbdmVyc2lvbiwgZG9jLmRvY3VtZW50TW9kZV07XG4gICAgICAgIGlmICgoZGF0YSA9ICtkYXRhWzFdICsgNCkgIT0gdmVyc2lvblsxXSkge1xuICAgICAgICAgIGRlc2NyaXB0aW9uLnB1c2goJ0lFICcgKyB2ZXJzaW9uWzFdICsgJyBtb2RlJyk7XG4gICAgICAgICAgbGF5b3V0ICYmIChsYXlvdXRbMV0gPSAnJyk7XG4gICAgICAgICAgdmVyc2lvblsxXSA9IGRhdGE7XG4gICAgICAgIH1cbiAgICAgICAgdmVyc2lvbiA9IG5hbWUgPT0gJ0lFJyA/IFN0cmluZyh2ZXJzaW9uWzFdLnRvRml4ZWQoMSkpIDogdmVyc2lvblswXTtcbiAgICAgIH1cbiAgICAgIC8vIERldGVjdCBJRSAxMSBtYXNraW5nIGFzIG90aGVyIGJyb3dzZXJzLlxuICAgICAgZWxzZSBpZiAodHlwZW9mIGRvYy5kb2N1bWVudE1vZGUgPT0gJ251bWJlcicgJiYgL14oPzpDaHJvbWV8RmlyZWZveClcXGIvLnRlc3QobmFtZSkpIHtcbiAgICAgICAgZGVzY3JpcHRpb24ucHVzaCgnbWFza2luZyBhcyAnICsgbmFtZSArICcgJyArIHZlcnNpb24pO1xuICAgICAgICBuYW1lID0gJ0lFJztcbiAgICAgICAgdmVyc2lvbiA9ICcxMS4wJztcbiAgICAgICAgbGF5b3V0ID0gWydUcmlkZW50J107XG4gICAgICAgIG9zID0gJ1dpbmRvd3MnO1xuICAgICAgfVxuICAgICAgb3MgPSBvcyAmJiBmb3JtYXQob3MpO1xuICAgIH1cbiAgICAvLyBEZXRlY3QgcHJlcmVsZWFzZSBwaGFzZXMuXG4gICAgaWYgKHZlcnNpb24gJiYgKGRhdGEgPVxuICAgICAgICAgIC8oPzpbYWJdfGRwfHByZXxbYWJdXFxkK3ByZSkoPzpcXGQrXFwrPyk/JC9pLmV4ZWModmVyc2lvbikgfHxcbiAgICAgICAgICAvKD86YWxwaGF8YmV0YSkoPzogP1xcZCk/L2kuZXhlYyh1YSArICc7JyArICh1c2VGZWF0dXJlcyAmJiBuYXYuYXBwTWlub3JWZXJzaW9uKSkgfHxcbiAgICAgICAgICAvXFxiTWluZWZpZWxkXFxiL2kudGVzdCh1YSkgJiYgJ2EnXG4gICAgICAgICkpIHtcbiAgICAgIHByZXJlbGVhc2UgPSAvYi9pLnRlc3QoZGF0YSkgPyAnYmV0YScgOiAnYWxwaGEnO1xuICAgICAgdmVyc2lvbiA9IHZlcnNpb24ucmVwbGFjZShSZWdFeHAoZGF0YSArICdcXFxcKz8kJyksICcnKSArXG4gICAgICAgIChwcmVyZWxlYXNlID09ICdiZXRhJyA/IGJldGEgOiBhbHBoYSkgKyAoL1xcZCtcXCs/Ly5leGVjKGRhdGEpIHx8ICcnKTtcbiAgICB9XG4gICAgLy8gRGV0ZWN0IEZpcmVmb3ggTW9iaWxlLlxuICAgIGlmIChuYW1lID09ICdGZW5uZWMnIHx8IG5hbWUgPT0gJ0ZpcmVmb3gnICYmIC9cXGIoPzpBbmRyb2lkfEZpcmVmb3ggT1MpXFxiLy50ZXN0KG9zKSkge1xuICAgICAgbmFtZSA9ICdGaXJlZm94IE1vYmlsZSc7XG4gICAgfVxuICAgIC8vIE9ic2N1cmUgTWF4dGhvbidzIHVucmVsaWFibGUgdmVyc2lvbi5cbiAgICBlbHNlIGlmIChuYW1lID09ICdNYXh0aG9uJyAmJiB2ZXJzaW9uKSB7XG4gICAgICB2ZXJzaW9uID0gdmVyc2lvbi5yZXBsYWNlKC9cXC5bXFxkLl0rLywgJy54Jyk7XG4gICAgfVxuICAgIC8vIERldGVjdCBYYm94IDM2MCBhbmQgWGJveCBPbmUuXG4gICAgZWxzZSBpZiAoL1xcYlhib3hcXGIvaS50ZXN0KHByb2R1Y3QpKSB7XG4gICAgICBpZiAocHJvZHVjdCA9PSAnWGJveCAzNjAnKSB7XG4gICAgICAgIG9zID0gbnVsbDtcbiAgICAgIH1cbiAgICAgIGlmIChwcm9kdWN0ID09ICdYYm94IDM2MCcgJiYgL1xcYklFTW9iaWxlXFxiLy50ZXN0KHVhKSkge1xuICAgICAgICBkZXNjcmlwdGlvbi51bnNoaWZ0KCdtb2JpbGUgbW9kZScpO1xuICAgICAgfVxuICAgIH1cbiAgICAvLyBBZGQgbW9iaWxlIHBvc3RmaXguXG4gICAgZWxzZSBpZiAoKC9eKD86Q2hyb21lfElFfE9wZXJhKSQvLnRlc3QobmFtZSkgfHwgbmFtZSAmJiAhcHJvZHVjdCAmJiAhL0Jyb3dzZXJ8TW9iaS8udGVzdChuYW1lKSkgJiZcbiAgICAgICAgKG9zID09ICdXaW5kb3dzIENFJyB8fCAvTW9iaS9pLnRlc3QodWEpKSkge1xuICAgICAgbmFtZSArPSAnIE1vYmlsZSc7XG4gICAgfVxuICAgIC8vIERldGVjdCBJRSBwbGF0Zm9ybSBwcmV2aWV3LlxuICAgIGVsc2UgaWYgKG5hbWUgPT0gJ0lFJyAmJiB1c2VGZWF0dXJlcykge1xuICAgICAgdHJ5IHtcbiAgICAgICAgaWYgKGNvbnRleHQuZXh0ZXJuYWwgPT09IG51bGwpIHtcbiAgICAgICAgICBkZXNjcmlwdGlvbi51bnNoaWZ0KCdwbGF0Zm9ybSBwcmV2aWV3Jyk7XG4gICAgICAgIH1cbiAgICAgIH0gY2F0Y2goZSkge1xuICAgICAgICBkZXNjcmlwdGlvbi51bnNoaWZ0KCdlbWJlZGRlZCcpO1xuICAgICAgfVxuICAgIH1cbiAgICAvLyBEZXRlY3QgQmxhY2tCZXJyeSBPUyB2ZXJzaW9uLlxuICAgIC8vIGh0dHA6Ly9kb2NzLmJsYWNrYmVycnkuY29tL2VuL2RldmVsb3BlcnMvZGVsaXZlcmFibGVzLzE4MTY5L0hUVFBfaGVhZGVyc19zZW50X2J5X0JCX0Jyb3dzZXJfMTIzNDkxMV8xMS5qc3BcbiAgICBlbHNlIGlmICgoL1xcYkJsYWNrQmVycnlcXGIvLnRlc3QocHJvZHVjdCkgfHwgL1xcYkJCMTBcXGIvLnRlc3QodWEpKSAmJiAoZGF0YSA9XG4gICAgICAgICAgKFJlZ0V4cChwcm9kdWN0LnJlcGxhY2UoLyArL2csICcgKicpICsgJy8oWy5cXFxcZF0rKScsICdpJykuZXhlYyh1YSkgfHwgMClbMV0gfHxcbiAgICAgICAgICB2ZXJzaW9uXG4gICAgICAgICkpIHtcbiAgICAgIGRhdGEgPSBbZGF0YSwgL0JCMTAvLnRlc3QodWEpXTtcbiAgICAgIG9zID0gKGRhdGFbMV0gPyAocHJvZHVjdCA9IG51bGwsIG1hbnVmYWN0dXJlciA9ICdCbGFja0JlcnJ5JykgOiAnRGV2aWNlIFNvZnR3YXJlJykgKyAnICcgKyBkYXRhWzBdO1xuICAgICAgdmVyc2lvbiA9IG51bGw7XG4gICAgfVxuICAgIC8vIERldGVjdCBPcGVyYSBpZGVudGlmeWluZy9tYXNraW5nIGl0c2VsZiBhcyBhbm90aGVyIGJyb3dzZXIuXG4gICAgLy8gaHR0cDovL3d3dy5vcGVyYS5jb20vc3VwcG9ydC9rYi92aWV3Lzg0My9cbiAgICBlbHNlIGlmICh0aGlzICE9IGZvck93biAmJiBwcm9kdWN0ICE9ICdXaWknICYmIChcbiAgICAgICAgICAodXNlRmVhdHVyZXMgJiYgb3BlcmEpIHx8XG4gICAgICAgICAgKC9PcGVyYS8udGVzdChuYW1lKSAmJiAvXFxiKD86TVNJRXxGaXJlZm94KVxcYi9pLnRlc3QodWEpKSB8fFxuICAgICAgICAgIChuYW1lID09ICdGaXJlZm94JyAmJiAvXFxiT1MgWCAoPzpcXGQrXFwuKXsyLH0vLnRlc3Qob3MpKSB8fFxuICAgICAgICAgIChuYW1lID09ICdJRScgJiYgKFxuICAgICAgICAgICAgKG9zICYmICEvXldpbi8udGVzdChvcykgJiYgdmVyc2lvbiA+IDUuNSkgfHxcbiAgICAgICAgICAgIC9cXGJXaW5kb3dzIFhQXFxiLy50ZXN0KG9zKSAmJiB2ZXJzaW9uID4gOCB8fFxuICAgICAgICAgICAgdmVyc2lvbiA9PSA4ICYmICEvXFxiVHJpZGVudFxcYi8udGVzdCh1YSlcbiAgICAgICAgICApKVxuICAgICAgICApICYmICFyZU9wZXJhLnRlc3QoKGRhdGEgPSBwYXJzZS5jYWxsKGZvck93biwgdWEucmVwbGFjZShyZU9wZXJhLCAnJykgKyAnOycpKSkgJiYgZGF0YS5uYW1lKSB7XG4gICAgICAvLyBXaGVuIFwiaWRlbnRpZnlpbmdcIiwgdGhlIFVBIGNvbnRhaW5zIGJvdGggT3BlcmEgYW5kIHRoZSBvdGhlciBicm93c2VyJ3MgbmFtZS5cbiAgICAgIGRhdGEgPSAnaW5nIGFzICcgKyBkYXRhLm5hbWUgKyAoKGRhdGEgPSBkYXRhLnZlcnNpb24pID8gJyAnICsgZGF0YSA6ICcnKTtcbiAgICAgIGlmIChyZU9wZXJhLnRlc3QobmFtZSkpIHtcbiAgICAgICAgaWYgKC9cXGJJRVxcYi8udGVzdChkYXRhKSAmJiBvcyA9PSAnTWFjIE9TJykge1xuICAgICAgICAgIG9zID0gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICBkYXRhID0gJ2lkZW50aWZ5JyArIGRhdGE7XG4gICAgICB9XG4gICAgICAvLyBXaGVuIFwibWFza2luZ1wiLCB0aGUgVUEgY29udGFpbnMgb25seSB0aGUgb3RoZXIgYnJvd3NlcidzIG5hbWUuXG4gICAgICBlbHNlIHtcbiAgICAgICAgZGF0YSA9ICdtYXNrJyArIGRhdGE7XG4gICAgICAgIGlmIChvcGVyYUNsYXNzKSB7XG4gICAgICAgICAgbmFtZSA9IGZvcm1hdChvcGVyYUNsYXNzLnJlcGxhY2UoLyhbYS16XSkoW0EtWl0pL2csICckMSAkMicpKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBuYW1lID0gJ09wZXJhJztcbiAgICAgICAgfVxuICAgICAgICBpZiAoL1xcYklFXFxiLy50ZXN0KGRhdGEpKSB7XG4gICAgICAgICAgb3MgPSBudWxsO1xuICAgICAgICB9XG4gICAgICAgIGlmICghdXNlRmVhdHVyZXMpIHtcbiAgICAgICAgICB2ZXJzaW9uID0gbnVsbDtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgbGF5b3V0ID0gWydQcmVzdG8nXTtcbiAgICAgIGRlc2NyaXB0aW9uLnB1c2goZGF0YSk7XG4gICAgfVxuICAgIC8vIERldGVjdCBXZWJLaXQgTmlnaHRseSBhbmQgYXBwcm94aW1hdGUgQ2hyb21lL1NhZmFyaSB2ZXJzaW9ucy5cbiAgICBpZiAoKGRhdGEgPSAoL1xcYkFwcGxlV2ViS2l0XFwvKFtcXGQuXStcXCs/KS9pLmV4ZWModWEpIHx8IDApWzFdKSkge1xuICAgICAgLy8gQ29ycmVjdCBidWlsZCBudW1iZXIgZm9yIG51bWVyaWMgY29tcGFyaXNvbi5cbiAgICAgIC8vIChlLmcuIFwiNTMyLjVcIiBiZWNvbWVzIFwiNTMyLjA1XCIpXG4gICAgICBkYXRhID0gW3BhcnNlRmxvYXQoZGF0YS5yZXBsYWNlKC9cXC4oXFxkKSQvLCAnLjAkMScpKSwgZGF0YV07XG4gICAgICAvLyBOaWdodGx5IGJ1aWxkcyBhcmUgcG9zdGZpeGVkIHdpdGggYSBcIitcIi5cbiAgICAgIGlmIChuYW1lID09ICdTYWZhcmknICYmIGRhdGFbMV0uc2xpY2UoLTEpID09ICcrJykge1xuICAgICAgICBuYW1lID0gJ1dlYktpdCBOaWdodGx5JztcbiAgICAgICAgcHJlcmVsZWFzZSA9ICdhbHBoYSc7XG4gICAgICAgIHZlcnNpb24gPSBkYXRhWzFdLnNsaWNlKDAsIC0xKTtcbiAgICAgIH1cbiAgICAgIC8vIENsZWFyIGluY29ycmVjdCBicm93c2VyIHZlcnNpb25zLlxuICAgICAgZWxzZSBpZiAodmVyc2lvbiA9PSBkYXRhWzFdIHx8XG4gICAgICAgICAgdmVyc2lvbiA9PSAoZGF0YVsyXSA9ICgvXFxiU2FmYXJpXFwvKFtcXGQuXStcXCs/KS9pLmV4ZWModWEpIHx8IDApWzFdKSkge1xuICAgICAgICB2ZXJzaW9uID0gbnVsbDtcbiAgICAgIH1cbiAgICAgIC8vIFVzZSB0aGUgZnVsbCBDaHJvbWUgdmVyc2lvbiB3aGVuIGF2YWlsYWJsZS5cbiAgICAgIGRhdGFbMV0gPSAoL1xcYkNocm9tZVxcLyhbXFxkLl0rKS9pLmV4ZWModWEpIHx8IDApWzFdO1xuICAgICAgLy8gRGV0ZWN0IEJsaW5rIGxheW91dCBlbmdpbmUuXG4gICAgICBpZiAoZGF0YVswXSA9PSA1MzcuMzYgJiYgZGF0YVsyXSA9PSA1MzcuMzYgJiYgcGFyc2VGbG9hdChkYXRhWzFdKSA+PSAyOCAmJiBsYXlvdXQgPT0gJ1dlYktpdCcpIHtcbiAgICAgICAgbGF5b3V0ID0gWydCbGluayddO1xuICAgICAgfVxuICAgICAgLy8gRGV0ZWN0IEphdmFTY3JpcHRDb3JlLlxuICAgICAgLy8gaHR0cDovL3N0YWNrb3ZlcmZsb3cuY29tL3F1ZXN0aW9ucy82NzY4NDc0L2hvdy1jYW4taS1kZXRlY3Qtd2hpY2gtamF2YXNjcmlwdC1lbmdpbmUtdjgtb3ItanNjLWlzLXVzZWQtYXQtcnVudGltZS1pbi1hbmRyb2lcbiAgICAgIGlmICghdXNlRmVhdHVyZXMgfHwgKCFsaWtlQ2hyb21lICYmICFkYXRhWzFdKSkge1xuICAgICAgICBsYXlvdXQgJiYgKGxheW91dFsxXSA9ICdsaWtlIFNhZmFyaScpO1xuICAgICAgICBkYXRhID0gKGRhdGEgPSBkYXRhWzBdLCBkYXRhIDwgNDAwID8gMSA6IGRhdGEgPCA1MDAgPyAyIDogZGF0YSA8IDUyNiA/IDMgOiBkYXRhIDwgNTMzID8gNCA6IGRhdGEgPCA1MzQgPyAnNCsnIDogZGF0YSA8IDUzNSA/IDUgOiBkYXRhIDwgNTM3ID8gNiA6IGRhdGEgPCA1MzggPyA3IDogZGF0YSA8IDYwMSA/IDggOiAnOCcpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbGF5b3V0ICYmIChsYXlvdXRbMV0gPSAnbGlrZSBDaHJvbWUnKTtcbiAgICAgICAgZGF0YSA9IGRhdGFbMV0gfHwgKGRhdGEgPSBkYXRhWzBdLCBkYXRhIDwgNTMwID8gMSA6IGRhdGEgPCA1MzIgPyAyIDogZGF0YSA8IDUzMi4wNSA/IDMgOiBkYXRhIDwgNTMzID8gNCA6IGRhdGEgPCA1MzQuMDMgPyA1IDogZGF0YSA8IDUzNC4wNyA/IDYgOiBkYXRhIDwgNTM0LjEwID8gNyA6IGRhdGEgPCA1MzQuMTMgPyA4IDogZGF0YSA8IDUzNC4xNiA/IDkgOiBkYXRhIDwgNTM0LjI0ID8gMTAgOiBkYXRhIDwgNTM0LjMwID8gMTEgOiBkYXRhIDwgNTM1LjAxID8gMTIgOiBkYXRhIDwgNTM1LjAyID8gJzEzKycgOiBkYXRhIDwgNTM1LjA3ID8gMTUgOiBkYXRhIDwgNTM1LjExID8gMTYgOiBkYXRhIDwgNTM1LjE5ID8gMTcgOiBkYXRhIDwgNTM2LjA1ID8gMTggOiBkYXRhIDwgNTM2LjEwID8gMTkgOiBkYXRhIDwgNTM3LjAxID8gMjAgOiBkYXRhIDwgNTM3LjExID8gJzIxKycgOiBkYXRhIDwgNTM3LjEzID8gMjMgOiBkYXRhIDwgNTM3LjE4ID8gMjQgOiBkYXRhIDwgNTM3LjI0ID8gMjUgOiBkYXRhIDwgNTM3LjM2ID8gMjYgOiBsYXlvdXQgIT0gJ0JsaW5rJyA/ICcyNycgOiAnMjgnKTtcbiAgICAgIH1cbiAgICAgIC8vIEFkZCB0aGUgcG9zdGZpeCBvZiBcIi54XCIgb3IgXCIrXCIgZm9yIGFwcHJveGltYXRlIHZlcnNpb25zLlxuICAgICAgbGF5b3V0ICYmIChsYXlvdXRbMV0gKz0gJyAnICsgKGRhdGEgKz0gdHlwZW9mIGRhdGEgPT0gJ251bWJlcicgPyAnLngnIDogL1suK10vLnRlc3QoZGF0YSkgPyAnJyA6ICcrJykpO1xuICAgICAgLy8gT2JzY3VyZSB2ZXJzaW9uIGZvciBzb21lIFNhZmFyaSAxLTIgcmVsZWFzZXMuXG4gICAgICBpZiAobmFtZSA9PSAnU2FmYXJpJyAmJiAoIXZlcnNpb24gfHwgcGFyc2VJbnQodmVyc2lvbikgPiA0NSkpIHtcbiAgICAgICAgdmVyc2lvbiA9IGRhdGE7XG4gICAgICB9XG4gICAgfVxuICAgIC8vIERldGVjdCBPcGVyYSBkZXNrdG9wIG1vZGVzLlxuICAgIGlmIChuYW1lID09ICdPcGVyYScgJiYgIChkYXRhID0gL1xcYnpib3Z8enZhdiQvLmV4ZWMob3MpKSkge1xuICAgICAgbmFtZSArPSAnICc7XG4gICAgICBkZXNjcmlwdGlvbi51bnNoaWZ0KCdkZXNrdG9wIG1vZGUnKTtcbiAgICAgIGlmIChkYXRhID09ICd6dmF2Jykge1xuICAgICAgICBuYW1lICs9ICdNaW5pJztcbiAgICAgICAgdmVyc2lvbiA9IG51bGw7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBuYW1lICs9ICdNb2JpbGUnO1xuICAgICAgfVxuICAgICAgb3MgPSBvcy5yZXBsYWNlKFJlZ0V4cCgnIConICsgZGF0YSArICckJyksICcnKTtcbiAgICB9XG4gICAgLy8gRGV0ZWN0IENocm9tZSBkZXNrdG9wIG1vZGUuXG4gICAgZWxzZSBpZiAobmFtZSA9PSAnU2FmYXJpJyAmJiAvXFxiQ2hyb21lXFxiLy5leGVjKGxheW91dCAmJiBsYXlvdXRbMV0pKSB7XG4gICAgICBkZXNjcmlwdGlvbi51bnNoaWZ0KCdkZXNrdG9wIG1vZGUnKTtcbiAgICAgIG5hbWUgPSAnQ2hyb21lIE1vYmlsZSc7XG4gICAgICB2ZXJzaW9uID0gbnVsbDtcblxuICAgICAgaWYgKC9cXGJPUyBYXFxiLy50ZXN0KG9zKSkge1xuICAgICAgICBtYW51ZmFjdHVyZXIgPSAnQXBwbGUnO1xuICAgICAgICBvcyA9ICdpT1MgNC4zKyc7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBvcyA9IG51bGw7XG4gICAgICB9XG4gICAgfVxuICAgIC8vIFN0cmlwIGluY29ycmVjdCBPUyB2ZXJzaW9ucy5cbiAgICBpZiAodmVyc2lvbiAmJiB2ZXJzaW9uLmluZGV4T2YoKGRhdGEgPSAvW1xcZC5dKyQvLmV4ZWMob3MpKSkgPT0gMCAmJlxuICAgICAgICB1YS5pbmRleE9mKCcvJyArIGRhdGEgKyAnLScpID4gLTEpIHtcbiAgICAgIG9zID0gdHJpbShvcy5yZXBsYWNlKGRhdGEsICcnKSk7XG4gICAgfVxuICAgIC8vIEFkZCBsYXlvdXQgZW5naW5lLlxuICAgIGlmIChsYXlvdXQgJiYgIS9cXGIoPzpBdmFudHxOb29rKVxcYi8udGVzdChuYW1lKSAmJiAoXG4gICAgICAgIC9Ccm93c2VyfEx1bmFzY2FwZXxNYXh0aG9uLy50ZXN0KG5hbWUpIHx8XG4gICAgICAgIG5hbWUgIT0gJ1NhZmFyaScgJiYgL15pT1MvLnRlc3Qob3MpICYmIC9cXGJTYWZhcmlcXGIvLnRlc3QobGF5b3V0WzFdKSB8fFxuICAgICAgICAvXig/OkFkb2JlfEFyb3JhfEJyZWFjaHxNaWRvcml8T3BlcmF8UGhhbnRvbXxSZWtvbnF8Um9ja3xTYW1zdW5nIEludGVybmV0fFNsZWlwbmlyfFdlYikvLnRlc3QobmFtZSkgJiYgbGF5b3V0WzFdKSkge1xuICAgICAgLy8gRG9uJ3QgYWRkIGxheW91dCBkZXRhaWxzIHRvIGRlc2NyaXB0aW9uIGlmIHRoZXkgYXJlIGZhbHNleS5cbiAgICAgIChkYXRhID0gbGF5b3V0W2xheW91dC5sZW5ndGggLSAxXSkgJiYgZGVzY3JpcHRpb24ucHVzaChkYXRhKTtcbiAgICB9XG4gICAgLy8gQ29tYmluZSBjb250ZXh0dWFsIGluZm9ybWF0aW9uLlxuICAgIGlmIChkZXNjcmlwdGlvbi5sZW5ndGgpIHtcbiAgICAgIGRlc2NyaXB0aW9uID0gWycoJyArIGRlc2NyaXB0aW9uLmpvaW4oJzsgJykgKyAnKSddO1xuICAgIH1cbiAgICAvLyBBcHBlbmQgbWFudWZhY3R1cmVyIHRvIGRlc2NyaXB0aW9uLlxuICAgIGlmIChtYW51ZmFjdHVyZXIgJiYgcHJvZHVjdCAmJiBwcm9kdWN0LmluZGV4T2YobWFudWZhY3R1cmVyKSA8IDApIHtcbiAgICAgIGRlc2NyaXB0aW9uLnB1c2goJ29uICcgKyBtYW51ZmFjdHVyZXIpO1xuICAgIH1cbiAgICAvLyBBcHBlbmQgcHJvZHVjdCB0byBkZXNjcmlwdGlvbi5cbiAgICBpZiAocHJvZHVjdCkge1xuICAgICAgZGVzY3JpcHRpb24ucHVzaCgoL15vbiAvLnRlc3QoZGVzY3JpcHRpb25bZGVzY3JpcHRpb24ubGVuZ3RoIC0gMV0pID8gJycgOiAnb24gJykgKyBwcm9kdWN0KTtcbiAgICB9XG4gICAgLy8gUGFyc2UgdGhlIE9TIGludG8gYW4gb2JqZWN0LlxuICAgIGlmIChvcykge1xuICAgICAgZGF0YSA9IC8gKFtcXGQuK10rKSQvLmV4ZWMob3MpO1xuICAgICAgaXNTcGVjaWFsQ2FzZWRPUyA9IGRhdGEgJiYgb3MuY2hhckF0KG9zLmxlbmd0aCAtIGRhdGFbMF0ubGVuZ3RoIC0gMSkgPT0gJy8nO1xuICAgICAgb3MgPSB7XG4gICAgICAgICdhcmNoaXRlY3R1cmUnOiAzMixcbiAgICAgICAgJ2ZhbWlseSc6IChkYXRhICYmICFpc1NwZWNpYWxDYXNlZE9TKSA/IG9zLnJlcGxhY2UoZGF0YVswXSwgJycpIDogb3MsXG4gICAgICAgICd2ZXJzaW9uJzogZGF0YSA/IGRhdGFbMV0gOiBudWxsLFxuICAgICAgICAndG9TdHJpbmcnOiBmdW5jdGlvbigpIHtcbiAgICAgICAgICB2YXIgdmVyc2lvbiA9IHRoaXMudmVyc2lvbjtcbiAgICAgICAgICByZXR1cm4gdGhpcy5mYW1pbHkgKyAoKHZlcnNpb24gJiYgIWlzU3BlY2lhbENhc2VkT1MpID8gJyAnICsgdmVyc2lvbiA6ICcnKSArICh0aGlzLmFyY2hpdGVjdHVyZSA9PSA2NCA/ICcgNjQtYml0JyA6ICcnKTtcbiAgICAgICAgfVxuICAgICAgfTtcbiAgICB9XG4gICAgLy8gQWRkIGJyb3dzZXIvT1MgYXJjaGl0ZWN0dXJlLlxuICAgIGlmICgoZGF0YSA9IC9cXGIoPzpBTUR8SUF8V2lufFdPV3x4ODZffHgpNjRcXGIvaS5leGVjKGFyY2gpKSAmJiAhL1xcYmk2ODZcXGIvaS50ZXN0KGFyY2gpKSB7XG4gICAgICBpZiAob3MpIHtcbiAgICAgICAgb3MuYXJjaGl0ZWN0dXJlID0gNjQ7XG4gICAgICAgIG9zLmZhbWlseSA9IG9zLmZhbWlseS5yZXBsYWNlKFJlZ0V4cCgnIConICsgZGF0YSksICcnKTtcbiAgICAgIH1cbiAgICAgIGlmIChcbiAgICAgICAgICBuYW1lICYmICgvXFxiV09XNjRcXGIvaS50ZXN0KHVhKSB8fFxuICAgICAgICAgICh1c2VGZWF0dXJlcyAmJiAvXFx3KD86ODZ8MzIpJC8udGVzdChuYXYuY3B1Q2xhc3MgfHwgbmF2LnBsYXRmb3JtKSAmJiAhL1xcYldpbjY0OyB4NjRcXGIvaS50ZXN0KHVhKSkpXG4gICAgICApIHtcbiAgICAgICAgZGVzY3JpcHRpb24udW5zaGlmdCgnMzItYml0Jyk7XG4gICAgICB9XG4gICAgfVxuICAgIC8vIENocm9tZSAzOSBhbmQgYWJvdmUgb24gT1MgWCBpcyBhbHdheXMgNjQtYml0LlxuICAgIGVsc2UgaWYgKFxuICAgICAgICBvcyAmJiAvXk9TIFgvLnRlc3Qob3MuZmFtaWx5KSAmJlxuICAgICAgICBuYW1lID09ICdDaHJvbWUnICYmIHBhcnNlRmxvYXQodmVyc2lvbikgPj0gMzlcbiAgICApIHtcbiAgICAgIG9zLmFyY2hpdGVjdHVyZSA9IDY0O1xuICAgIH1cblxuICAgIHVhIHx8ICh1YSA9IG51bGwpO1xuXG4gICAgLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuXG4gICAgLyoqXG4gICAgICogVGhlIHBsYXRmb3JtIG9iamVjdC5cbiAgICAgKlxuICAgICAqIEBuYW1lIHBsYXRmb3JtXG4gICAgICogQHR5cGUgT2JqZWN0XG4gICAgICovXG4gICAgdmFyIHBsYXRmb3JtID0ge307XG5cbiAgICAvKipcbiAgICAgKiBUaGUgcGxhdGZvcm0gZGVzY3JpcHRpb24uXG4gICAgICpcbiAgICAgKiBAbWVtYmVyT2YgcGxhdGZvcm1cbiAgICAgKiBAdHlwZSBzdHJpbmd8bnVsbFxuICAgICAqL1xuICAgIHBsYXRmb3JtLmRlc2NyaXB0aW9uID0gdWE7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgbmFtZSBvZiB0aGUgYnJvd3NlcidzIGxheW91dCBlbmdpbmUuXG4gICAgICpcbiAgICAgKiBUaGUgbGlzdCBvZiBjb21tb24gbGF5b3V0IGVuZ2luZXMgaW5jbHVkZTpcbiAgICAgKiBcIkJsaW5rXCIsIFwiRWRnZUhUTUxcIiwgXCJHZWNrb1wiLCBcIlRyaWRlbnRcIiBhbmQgXCJXZWJLaXRcIlxuICAgICAqXG4gICAgICogQG1lbWJlck9mIHBsYXRmb3JtXG4gICAgICogQHR5cGUgc3RyaW5nfG51bGxcbiAgICAgKi9cbiAgICBwbGF0Zm9ybS5sYXlvdXQgPSBsYXlvdXQgJiYgbGF5b3V0WzBdO1xuXG4gICAgLyoqXG4gICAgICogVGhlIG5hbWUgb2YgdGhlIHByb2R1Y3QncyBtYW51ZmFjdHVyZXIuXG4gICAgICpcbiAgICAgKiBUaGUgbGlzdCBvZiBtYW51ZmFjdHVyZXJzIGluY2x1ZGU6XG4gICAgICogXCJBcHBsZVwiLCBcIkFyY2hvc1wiLCBcIkFtYXpvblwiLCBcIkFzdXNcIiwgXCJCYXJuZXMgJiBOb2JsZVwiLCBcIkJsYWNrQmVycnlcIixcbiAgICAgKiBcIkdvb2dsZVwiLCBcIkhQXCIsIFwiSFRDXCIsIFwiTEdcIiwgXCJNaWNyb3NvZnRcIiwgXCJNb3Rvcm9sYVwiLCBcIk5pbnRlbmRvXCIsXG4gICAgICogXCJOb2tpYVwiLCBcIlNhbXN1bmdcIiBhbmQgXCJTb255XCJcbiAgICAgKlxuICAgICAqIEBtZW1iZXJPZiBwbGF0Zm9ybVxuICAgICAqIEB0eXBlIHN0cmluZ3xudWxsXG4gICAgICovXG4gICAgcGxhdGZvcm0ubWFudWZhY3R1cmVyID0gbWFudWZhY3R1cmVyO1xuXG4gICAgLyoqXG4gICAgICogVGhlIG5hbWUgb2YgdGhlIGJyb3dzZXIvZW52aXJvbm1lbnQuXG4gICAgICpcbiAgICAgKiBUaGUgbGlzdCBvZiBjb21tb24gYnJvd3NlciBuYW1lcyBpbmNsdWRlOlxuICAgICAqIFwiQ2hyb21lXCIsIFwiRWxlY3Ryb25cIiwgXCJGaXJlZm94XCIsIFwiRmlyZWZveCBmb3IgaU9TXCIsIFwiSUVcIixcbiAgICAgKiBcIk1pY3Jvc29mdCBFZGdlXCIsIFwiUGhhbnRvbUpTXCIsIFwiU2FmYXJpXCIsIFwiU2VhTW9ua2V5XCIsIFwiU2lsa1wiLFxuICAgICAqIFwiT3BlcmEgTWluaVwiIGFuZCBcIk9wZXJhXCJcbiAgICAgKlxuICAgICAqIE1vYmlsZSB2ZXJzaW9ucyBvZiBzb21lIGJyb3dzZXJzIGhhdmUgXCJNb2JpbGVcIiBhcHBlbmRlZCB0byB0aGVpciBuYW1lOlxuICAgICAqIGVnLiBcIkNocm9tZSBNb2JpbGVcIiwgXCJGaXJlZm94IE1vYmlsZVwiLCBcIklFIE1vYmlsZVwiIGFuZCBcIk9wZXJhIE1vYmlsZVwiXG4gICAgICpcbiAgICAgKiBAbWVtYmVyT2YgcGxhdGZvcm1cbiAgICAgKiBAdHlwZSBzdHJpbmd8bnVsbFxuICAgICAqL1xuICAgIHBsYXRmb3JtLm5hbWUgPSBuYW1lO1xuXG4gICAgLyoqXG4gICAgICogVGhlIGFscGhhL2JldGEgcmVsZWFzZSBpbmRpY2F0b3IuXG4gICAgICpcbiAgICAgKiBAbWVtYmVyT2YgcGxhdGZvcm1cbiAgICAgKiBAdHlwZSBzdHJpbmd8bnVsbFxuICAgICAqL1xuICAgIHBsYXRmb3JtLnByZXJlbGVhc2UgPSBwcmVyZWxlYXNlO1xuXG4gICAgLyoqXG4gICAgICogVGhlIG5hbWUgb2YgdGhlIHByb2R1Y3QgaG9zdGluZyB0aGUgYnJvd3Nlci5cbiAgICAgKlxuICAgICAqIFRoZSBsaXN0IG9mIGNvbW1vbiBwcm9kdWN0cyBpbmNsdWRlOlxuICAgICAqXG4gICAgICogXCJCbGFja0JlcnJ5XCIsIFwiR2FsYXh5IFM0XCIsIFwiTHVtaWFcIiwgXCJpUGFkXCIsIFwiaVBvZFwiLCBcImlQaG9uZVwiLCBcIktpbmRsZVwiLFxuICAgICAqIFwiS2luZGxlIEZpcmVcIiwgXCJOZXh1c1wiLCBcIk5vb2tcIiwgXCJQbGF5Qm9va1wiLCBcIlRvdWNoUGFkXCIgYW5kIFwiVHJhbnNmb3JtZXJcIlxuICAgICAqXG4gICAgICogQG1lbWJlck9mIHBsYXRmb3JtXG4gICAgICogQHR5cGUgc3RyaW5nfG51bGxcbiAgICAgKi9cbiAgICBwbGF0Zm9ybS5wcm9kdWN0ID0gcHJvZHVjdDtcblxuICAgIC8qKlxuICAgICAqIFRoZSBicm93c2VyJ3MgdXNlciBhZ2VudCBzdHJpbmcuXG4gICAgICpcbiAgICAgKiBAbWVtYmVyT2YgcGxhdGZvcm1cbiAgICAgKiBAdHlwZSBzdHJpbmd8bnVsbFxuICAgICAqL1xuICAgIHBsYXRmb3JtLnVhID0gdWE7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYnJvd3Nlci9lbnZpcm9ubWVudCB2ZXJzaW9uLlxuICAgICAqXG4gICAgICogQG1lbWJlck9mIHBsYXRmb3JtXG4gICAgICogQHR5cGUgc3RyaW5nfG51bGxcbiAgICAgKi9cbiAgICBwbGF0Zm9ybS52ZXJzaW9uID0gbmFtZSAmJiB2ZXJzaW9uO1xuXG4gICAgLyoqXG4gICAgICogVGhlIG5hbWUgb2YgdGhlIG9wZXJhdGluZyBzeXN0ZW0uXG4gICAgICpcbiAgICAgKiBAbWVtYmVyT2YgcGxhdGZvcm1cbiAgICAgKiBAdHlwZSBPYmplY3RcbiAgICAgKi9cbiAgICBwbGF0Zm9ybS5vcyA9IG9zIHx8IHtcblxuICAgICAgLyoqXG4gICAgICAgKiBUaGUgQ1BVIGFyY2hpdGVjdHVyZSB0aGUgT1MgaXMgYnVpbHQgZm9yLlxuICAgICAgICpcbiAgICAgICAqIEBtZW1iZXJPZiBwbGF0Zm9ybS5vc1xuICAgICAgICogQHR5cGUgbnVtYmVyfG51bGxcbiAgICAgICAqL1xuICAgICAgJ2FyY2hpdGVjdHVyZSc6IG51bGwsXG5cbiAgICAgIC8qKlxuICAgICAgICogVGhlIGZhbWlseSBvZiB0aGUgT1MuXG4gICAgICAgKlxuICAgICAgICogQ29tbW9uIHZhbHVlcyBpbmNsdWRlOlxuICAgICAgICogXCJXaW5kb3dzXCIsIFwiV2luZG93cyBTZXJ2ZXIgMjAwOCBSMiAvIDdcIiwgXCJXaW5kb3dzIFNlcnZlciAyMDA4IC8gVmlzdGFcIixcbiAgICAgICAqIFwiV2luZG93cyBYUFwiLCBcIk9TIFhcIiwgXCJVYnVudHVcIiwgXCJEZWJpYW5cIiwgXCJGZWRvcmFcIiwgXCJSZWQgSGF0XCIsIFwiU3VTRVwiLFxuICAgICAgICogXCJBbmRyb2lkXCIsIFwiaU9TXCIgYW5kIFwiV2luZG93cyBQaG9uZVwiXG4gICAgICAgKlxuICAgICAgICogQG1lbWJlck9mIHBsYXRmb3JtLm9zXG4gICAgICAgKiBAdHlwZSBzdHJpbmd8bnVsbFxuICAgICAgICovXG4gICAgICAnZmFtaWx5JzogbnVsbCxcblxuICAgICAgLyoqXG4gICAgICAgKiBUaGUgdmVyc2lvbiBvZiB0aGUgT1MuXG4gICAgICAgKlxuICAgICAgICogQG1lbWJlck9mIHBsYXRmb3JtLm9zXG4gICAgICAgKiBAdHlwZSBzdHJpbmd8bnVsbFxuICAgICAgICovXG4gICAgICAndmVyc2lvbic6IG51bGwsXG5cbiAgICAgIC8qKlxuICAgICAgICogUmV0dXJucyB0aGUgT1Mgc3RyaW5nLlxuICAgICAgICpcbiAgICAgICAqIEBtZW1iZXJPZiBwbGF0Zm9ybS5vc1xuICAgICAgICogQHJldHVybnMge3N0cmluZ30gVGhlIE9TIHN0cmluZy5cbiAgICAgICAqL1xuICAgICAgJ3RvU3RyaW5nJzogZnVuY3Rpb24oKSB7IHJldHVybiAnbnVsbCc7IH1cbiAgICB9O1xuXG4gICAgcGxhdGZvcm0ucGFyc2UgPSBwYXJzZTtcbiAgICBwbGF0Zm9ybS50b1N0cmluZyA9IHRvU3RyaW5nUGxhdGZvcm07XG5cbiAgICBpZiAocGxhdGZvcm0udmVyc2lvbikge1xuICAgICAgZGVzY3JpcHRpb24udW5zaGlmdCh2ZXJzaW9uKTtcbiAgICB9XG4gICAgaWYgKHBsYXRmb3JtLm5hbWUpIHtcbiAgICAgIGRlc2NyaXB0aW9uLnVuc2hpZnQobmFtZSk7XG4gICAgfVxuICAgIGlmIChvcyAmJiBuYW1lICYmICEob3MgPT0gU3RyaW5nKG9zKS5zcGxpdCgnICcpWzBdICYmIChvcyA9PSBuYW1lLnNwbGl0KCcgJylbMF0gfHwgcHJvZHVjdCkpKSB7XG4gICAgICBkZXNjcmlwdGlvbi5wdXNoKHByb2R1Y3QgPyAnKCcgKyBvcyArICcpJyA6ICdvbiAnICsgb3MpO1xuICAgIH1cbiAgICBpZiAoZGVzY3JpcHRpb24ubGVuZ3RoKSB7XG4gICAgICBwbGF0Zm9ybS5kZXNjcmlwdGlvbiA9IGRlc2NyaXB0aW9uLmpvaW4oJyAnKTtcbiAgICB9XG4gICAgcmV0dXJuIHBsYXRmb3JtO1xuICB9XG5cbiAgLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG5cbiAgLy8gRXhwb3J0IHBsYXRmb3JtLlxuICB2YXIgcGxhdGZvcm0gPSBwYXJzZSgpO1xuXG4gIC8vIFNvbWUgQU1EIGJ1aWxkIG9wdGltaXplcnMsIGxpa2Ugci5qcywgY2hlY2sgZm9yIGNvbmRpdGlvbiBwYXR0ZXJucyBsaWtlIHRoZSBmb2xsb3dpbmc6XG4gIGlmICh0eXBlb2YgZGVmaW5lID09ICdmdW5jdGlvbicgJiYgdHlwZW9mIGRlZmluZS5hbWQgPT0gJ29iamVjdCcgJiYgZGVmaW5lLmFtZCkge1xuICAgIC8vIEV4cG9zZSBwbGF0Zm9ybSBvbiB0aGUgZ2xvYmFsIG9iamVjdCB0byBwcmV2ZW50IGVycm9ycyB3aGVuIHBsYXRmb3JtIGlzXG4gICAgLy8gbG9hZGVkIGJ5IGEgc2NyaXB0IHRhZyBpbiB0aGUgcHJlc2VuY2Ugb2YgYW4gQU1EIGxvYWRlci5cbiAgICAvLyBTZWUgaHR0cDovL3JlcXVpcmVqcy5vcmcvZG9jcy9lcnJvcnMuaHRtbCNtaXNtYXRjaCBmb3IgbW9yZSBkZXRhaWxzLlxuICAgIHJvb3QucGxhdGZvcm0gPSBwbGF0Zm9ybTtcblxuICAgIC8vIERlZmluZSBhcyBhbiBhbm9ueW1vdXMgbW9kdWxlIHNvIHBsYXRmb3JtIGNhbiBiZSBhbGlhc2VkIHRocm91Z2ggcGF0aCBtYXBwaW5nLlxuICAgIGRlZmluZShmdW5jdGlvbigpIHtcbiAgICAgIHJldHVybiBwbGF0Zm9ybTtcbiAgICB9KTtcbiAgfVxuICAvLyBDaGVjayBmb3IgYGV4cG9ydHNgIGFmdGVyIGBkZWZpbmVgIGluIGNhc2UgYSBidWlsZCBvcHRpbWl6ZXIgYWRkcyBhbiBgZXhwb3J0c2Agb2JqZWN0LlxuICBlbHNlIGlmIChmcmVlRXhwb3J0cyAmJiBmcmVlTW9kdWxlKSB7XG4gICAgLy8gRXhwb3J0IGZvciBDb21tb25KUyBzdXBwb3J0LlxuICAgIGZvck93bihwbGF0Zm9ybSwgZnVuY3Rpb24odmFsdWUsIGtleSkge1xuICAgICAgZnJlZUV4cG9ydHNba2V5XSA9IHZhbHVlO1xuICAgIH0pO1xuICB9XG4gIGVsc2Uge1xuICAgIC8vIEV4cG9ydCB0byB0aGUgZ2xvYmFsIG9iamVjdC5cbiAgICByb290LnBsYXRmb3JtID0gcGxhdGZvcm07XG4gIH1cbn0uY2FsbCh0aGlzKSk7XG4iLCJ2YXIgdjEgPSByZXF1aXJlKCcuL3YxJyk7XG52YXIgdjQgPSByZXF1aXJlKCcuL3Y0Jyk7XG5cbnZhciB1dWlkID0gdjQ7XG51dWlkLnYxID0gdjE7XG51dWlkLnY0ID0gdjQ7XG5cbm1vZHVsZS5leHBvcnRzID0gdXVpZDtcbiIsIi8qKlxuICogQ29udmVydCBhcnJheSBvZiAxNiBieXRlIHZhbHVlcyB0byBVVUlEIHN0cmluZyBmb3JtYXQgb2YgdGhlIGZvcm06XG4gKiBYWFhYWFhYWC1YWFhYLVhYWFgtWFhYWC1YWFhYWFhYWFhYWFhcbiAqL1xudmFyIGJ5dGVUb0hleCA9IFtdO1xuZm9yICh2YXIgaSA9IDA7IGkgPCAyNTY7ICsraSkge1xuICBieXRlVG9IZXhbaV0gPSAoaSArIDB4MTAwKS50b1N0cmluZygxNikuc3Vic3RyKDEpO1xufVxuXG5mdW5jdGlvbiBieXRlc1RvVXVpZChidWYsIG9mZnNldCkge1xuICB2YXIgaSA9IG9mZnNldCB8fCAwO1xuICB2YXIgYnRoID0gYnl0ZVRvSGV4O1xuICAvLyBqb2luIHVzZWQgdG8gZml4IG1lbW9yeSBpc3N1ZSBjYXVzZWQgYnkgY29uY2F0ZW5hdGlvbjogaHR0cHM6Ly9idWdzLmNocm9taXVtLm9yZy9wL3Y4L2lzc3Vlcy9kZXRhaWw/aWQ9MzE3NSNjNFxuICByZXR1cm4gKFtidGhbYnVmW2krK11dLCBidGhbYnVmW2krK11dLCBcblx0YnRoW2J1ZltpKytdXSwgYnRoW2J1ZltpKytdXSwgJy0nLFxuXHRidGhbYnVmW2krK11dLCBidGhbYnVmW2krK11dLCAnLScsXG5cdGJ0aFtidWZbaSsrXV0sIGJ0aFtidWZbaSsrXV0sICctJyxcblx0YnRoW2J1ZltpKytdXSwgYnRoW2J1ZltpKytdXSwgJy0nLFxuXHRidGhbYnVmW2krK11dLCBidGhbYnVmW2krK11dLFxuXHRidGhbYnVmW2krK11dLCBidGhbYnVmW2krK11dLFxuXHRidGhbYnVmW2krK11dLCBidGhbYnVmW2krK11dXSkuam9pbignJyk7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gYnl0ZXNUb1V1aWQ7XG4iLCIvLyBVbmlxdWUgSUQgY3JlYXRpb24gcmVxdWlyZXMgYSBoaWdoIHF1YWxpdHkgcmFuZG9tICMgZ2VuZXJhdG9yLiAgSW4gdGhlXG4vLyBicm93c2VyIHRoaXMgaXMgYSBsaXR0bGUgY29tcGxpY2F0ZWQgZHVlIHRvIHVua25vd24gcXVhbGl0eSBvZiBNYXRoLnJhbmRvbSgpXG4vLyBhbmQgaW5jb25zaXN0ZW50IHN1cHBvcnQgZm9yIHRoZSBgY3J5cHRvYCBBUEkuICBXZSBkbyB0aGUgYmVzdCB3ZSBjYW4gdmlhXG4vLyBmZWF0dXJlLWRldGVjdGlvblxuXG4vLyBnZXRSYW5kb21WYWx1ZXMgbmVlZHMgdG8gYmUgaW52b2tlZCBpbiBhIGNvbnRleHQgd2hlcmUgXCJ0aGlzXCIgaXMgYSBDcnlwdG9cbi8vIGltcGxlbWVudGF0aW9uLiBBbHNvLCBmaW5kIHRoZSBjb21wbGV0ZSBpbXBsZW1lbnRhdGlvbiBvZiBjcnlwdG8gb24gSUUxMS5cbnZhciBnZXRSYW5kb21WYWx1ZXMgPSAodHlwZW9mKGNyeXB0bykgIT0gJ3VuZGVmaW5lZCcgJiYgY3J5cHRvLmdldFJhbmRvbVZhbHVlcyAmJiBjcnlwdG8uZ2V0UmFuZG9tVmFsdWVzLmJpbmQoY3J5cHRvKSkgfHxcbiAgICAgICAgICAgICAgICAgICAgICAodHlwZW9mKG1zQ3J5cHRvKSAhPSAndW5kZWZpbmVkJyAmJiB0eXBlb2Ygd2luZG93Lm1zQ3J5cHRvLmdldFJhbmRvbVZhbHVlcyA9PSAnZnVuY3Rpb24nICYmIG1zQ3J5cHRvLmdldFJhbmRvbVZhbHVlcy5iaW5kKG1zQ3J5cHRvKSk7XG5cbmlmIChnZXRSYW5kb21WYWx1ZXMpIHtcbiAgLy8gV0hBVFdHIGNyeXB0byBSTkcgLSBodHRwOi8vd2lraS53aGF0d2cub3JnL3dpa2kvQ3J5cHRvXG4gIHZhciBybmRzOCA9IG5ldyBVaW50OEFycmF5KDE2KTsgLy8gZXNsaW50LWRpc2FibGUtbGluZSBuby11bmRlZlxuXG4gIG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gd2hhdHdnUk5HKCkge1xuICAgIGdldFJhbmRvbVZhbHVlcyhybmRzOCk7XG4gICAgcmV0dXJuIHJuZHM4O1xuICB9O1xufSBlbHNlIHtcbiAgLy8gTWF0aC5yYW5kb20oKS1iYXNlZCAoUk5HKVxuICAvL1xuICAvLyBJZiBhbGwgZWxzZSBmYWlscywgdXNlIE1hdGgucmFuZG9tKCkuICBJdCdzIGZhc3QsIGJ1dCBpcyBvZiB1bnNwZWNpZmllZFxuICAvLyBxdWFsaXR5LlxuICB2YXIgcm5kcyA9IG5ldyBBcnJheSgxNik7XG5cbiAgbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBtYXRoUk5HKCkge1xuICAgIGZvciAodmFyIGkgPSAwLCByOyBpIDwgMTY7IGkrKykge1xuICAgICAgaWYgKChpICYgMHgwMykgPT09IDApIHIgPSBNYXRoLnJhbmRvbSgpICogMHgxMDAwMDAwMDA7XG4gICAgICBybmRzW2ldID0gciA+Pj4gKChpICYgMHgwMykgPDwgMykgJiAweGZmO1xuICAgIH1cblxuICAgIHJldHVybiBybmRzO1xuICB9O1xufVxuIiwidmFyIHJuZyA9IHJlcXVpcmUoJy4vbGliL3JuZycpO1xudmFyIGJ5dGVzVG9VdWlkID0gcmVxdWlyZSgnLi9saWIvYnl0ZXNUb1V1aWQnKTtcblxuLy8gKipgdjEoKWAgLSBHZW5lcmF0ZSB0aW1lLWJhc2VkIFVVSUQqKlxuLy9cbi8vIEluc3BpcmVkIGJ5IGh0dHBzOi8vZ2l0aHViLmNvbS9MaW9zSy9VVUlELmpzXG4vLyBhbmQgaHR0cDovL2RvY3MucHl0aG9uLm9yZy9saWJyYXJ5L3V1aWQuaHRtbFxuXG52YXIgX25vZGVJZDtcbnZhciBfY2xvY2tzZXE7XG5cbi8vIFByZXZpb3VzIHV1aWQgY3JlYXRpb24gdGltZVxudmFyIF9sYXN0TVNlY3MgPSAwO1xudmFyIF9sYXN0TlNlY3MgPSAwO1xuXG4vLyBTZWUgaHR0cHM6Ly9naXRodWIuY29tL2Jyb29mYS9ub2RlLXV1aWQgZm9yIEFQSSBkZXRhaWxzXG5mdW5jdGlvbiB2MShvcHRpb25zLCBidWYsIG9mZnNldCkge1xuICB2YXIgaSA9IGJ1ZiAmJiBvZmZzZXQgfHwgMDtcbiAgdmFyIGIgPSBidWYgfHwgW107XG5cbiAgb3B0aW9ucyA9IG9wdGlvbnMgfHwge307XG4gIHZhciBub2RlID0gb3B0aW9ucy5ub2RlIHx8IF9ub2RlSWQ7XG4gIHZhciBjbG9ja3NlcSA9IG9wdGlvbnMuY2xvY2tzZXEgIT09IHVuZGVmaW5lZCA/IG9wdGlvbnMuY2xvY2tzZXEgOiBfY2xvY2tzZXE7XG5cbiAgLy8gbm9kZSBhbmQgY2xvY2tzZXEgbmVlZCB0byBiZSBpbml0aWFsaXplZCB0byByYW5kb20gdmFsdWVzIGlmIHRoZXkncmUgbm90XG4gIC8vIHNwZWNpZmllZC4gIFdlIGRvIHRoaXMgbGF6aWx5IHRvIG1pbmltaXplIGlzc3VlcyByZWxhdGVkIHRvIGluc3VmZmljaWVudFxuICAvLyBzeXN0ZW0gZW50cm9weS4gIFNlZSAjMTg5XG4gIGlmIChub2RlID09IG51bGwgfHwgY2xvY2tzZXEgPT0gbnVsbCkge1xuICAgIHZhciBzZWVkQnl0ZXMgPSBybmcoKTtcbiAgICBpZiAobm9kZSA9PSBudWxsKSB7XG4gICAgICAvLyBQZXIgNC41LCBjcmVhdGUgYW5kIDQ4LWJpdCBub2RlIGlkLCAoNDcgcmFuZG9tIGJpdHMgKyBtdWx0aWNhc3QgYml0ID0gMSlcbiAgICAgIG5vZGUgPSBfbm9kZUlkID0gW1xuICAgICAgICBzZWVkQnl0ZXNbMF0gfCAweDAxLFxuICAgICAgICBzZWVkQnl0ZXNbMV0sIHNlZWRCeXRlc1syXSwgc2VlZEJ5dGVzWzNdLCBzZWVkQnl0ZXNbNF0sIHNlZWRCeXRlc1s1XVxuICAgICAgXTtcbiAgICB9XG4gICAgaWYgKGNsb2Nrc2VxID09IG51bGwpIHtcbiAgICAgIC8vIFBlciA0LjIuMiwgcmFuZG9taXplICgxNCBiaXQpIGNsb2Nrc2VxXG4gICAgICBjbG9ja3NlcSA9IF9jbG9ja3NlcSA9IChzZWVkQnl0ZXNbNl0gPDwgOCB8IHNlZWRCeXRlc1s3XSkgJiAweDNmZmY7XG4gICAgfVxuICB9XG5cbiAgLy8gVVVJRCB0aW1lc3RhbXBzIGFyZSAxMDAgbmFuby1zZWNvbmQgdW5pdHMgc2luY2UgdGhlIEdyZWdvcmlhbiBlcG9jaCxcbiAgLy8gKDE1ODItMTAtMTUgMDA6MDApLiAgSlNOdW1iZXJzIGFyZW4ndCBwcmVjaXNlIGVub3VnaCBmb3IgdGhpcywgc29cbiAgLy8gdGltZSBpcyBoYW5kbGVkIGludGVybmFsbHkgYXMgJ21zZWNzJyAoaW50ZWdlciBtaWxsaXNlY29uZHMpIGFuZCAnbnNlY3MnXG4gIC8vICgxMDAtbmFub3NlY29uZHMgb2Zmc2V0IGZyb20gbXNlY3MpIHNpbmNlIHVuaXggZXBvY2gsIDE5NzAtMDEtMDEgMDA6MDAuXG4gIHZhciBtc2VjcyA9IG9wdGlvbnMubXNlY3MgIT09IHVuZGVmaW5lZCA/IG9wdGlvbnMubXNlY3MgOiBuZXcgRGF0ZSgpLmdldFRpbWUoKTtcblxuICAvLyBQZXIgNC4yLjEuMiwgdXNlIGNvdW50IG9mIHV1aWQncyBnZW5lcmF0ZWQgZHVyaW5nIHRoZSBjdXJyZW50IGNsb2NrXG4gIC8vIGN5Y2xlIHRvIHNpbXVsYXRlIGhpZ2hlciByZXNvbHV0aW9uIGNsb2NrXG4gIHZhciBuc2VjcyA9IG9wdGlvbnMubnNlY3MgIT09IHVuZGVmaW5lZCA/IG9wdGlvbnMubnNlY3MgOiBfbGFzdE5TZWNzICsgMTtcblxuICAvLyBUaW1lIHNpbmNlIGxhc3QgdXVpZCBjcmVhdGlvbiAoaW4gbXNlY3MpXG4gIHZhciBkdCA9IChtc2VjcyAtIF9sYXN0TVNlY3MpICsgKG5zZWNzIC0gX2xhc3ROU2VjcykvMTAwMDA7XG5cbiAgLy8gUGVyIDQuMi4xLjIsIEJ1bXAgY2xvY2tzZXEgb24gY2xvY2sgcmVncmVzc2lvblxuICBpZiAoZHQgPCAwICYmIG9wdGlvbnMuY2xvY2tzZXEgPT09IHVuZGVmaW5lZCkge1xuICAgIGNsb2Nrc2VxID0gY2xvY2tzZXEgKyAxICYgMHgzZmZmO1xuICB9XG5cbiAgLy8gUmVzZXQgbnNlY3MgaWYgY2xvY2sgcmVncmVzc2VzIChuZXcgY2xvY2tzZXEpIG9yIHdlJ3ZlIG1vdmVkIG9udG8gYSBuZXdcbiAgLy8gdGltZSBpbnRlcnZhbFxuICBpZiAoKGR0IDwgMCB8fCBtc2VjcyA+IF9sYXN0TVNlY3MpICYmIG9wdGlvbnMubnNlY3MgPT09IHVuZGVmaW5lZCkge1xuICAgIG5zZWNzID0gMDtcbiAgfVxuXG4gIC8vIFBlciA0LjIuMS4yIFRocm93IGVycm9yIGlmIHRvbyBtYW55IHV1aWRzIGFyZSByZXF1ZXN0ZWRcbiAgaWYgKG5zZWNzID49IDEwMDAwKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCd1dWlkLnYxKCk6IENhblxcJ3QgY3JlYXRlIG1vcmUgdGhhbiAxME0gdXVpZHMvc2VjJyk7XG4gIH1cblxuICBfbGFzdE1TZWNzID0gbXNlY3M7XG4gIF9sYXN0TlNlY3MgPSBuc2VjcztcbiAgX2Nsb2Nrc2VxID0gY2xvY2tzZXE7XG5cbiAgLy8gUGVyIDQuMS40IC0gQ29udmVydCBmcm9tIHVuaXggZXBvY2ggdG8gR3JlZ29yaWFuIGVwb2NoXG4gIG1zZWNzICs9IDEyMjE5MjkyODAwMDAwO1xuXG4gIC8vIGB0aW1lX2xvd2BcbiAgdmFyIHRsID0gKChtc2VjcyAmIDB4ZmZmZmZmZikgKiAxMDAwMCArIG5zZWNzKSAlIDB4MTAwMDAwMDAwO1xuICBiW2krK10gPSB0bCA+Pj4gMjQgJiAweGZmO1xuICBiW2krK10gPSB0bCA+Pj4gMTYgJiAweGZmO1xuICBiW2krK10gPSB0bCA+Pj4gOCAmIDB4ZmY7XG4gIGJbaSsrXSA9IHRsICYgMHhmZjtcblxuICAvLyBgdGltZV9taWRgXG4gIHZhciB0bWggPSAobXNlY3MgLyAweDEwMDAwMDAwMCAqIDEwMDAwKSAmIDB4ZmZmZmZmZjtcbiAgYltpKytdID0gdG1oID4+PiA4ICYgMHhmZjtcbiAgYltpKytdID0gdG1oICYgMHhmZjtcblxuICAvLyBgdGltZV9oaWdoX2FuZF92ZXJzaW9uYFxuICBiW2krK10gPSB0bWggPj4+IDI0ICYgMHhmIHwgMHgxMDsgLy8gaW5jbHVkZSB2ZXJzaW9uXG4gIGJbaSsrXSA9IHRtaCA+Pj4gMTYgJiAweGZmO1xuXG4gIC8vIGBjbG9ja19zZXFfaGlfYW5kX3Jlc2VydmVkYCAoUGVyIDQuMi4yIC0gaW5jbHVkZSB2YXJpYW50KVxuICBiW2krK10gPSBjbG9ja3NlcSA+Pj4gOCB8IDB4ODA7XG5cbiAgLy8gYGNsb2NrX3NlcV9sb3dgXG4gIGJbaSsrXSA9IGNsb2Nrc2VxICYgMHhmZjtcblxuICAvLyBgbm9kZWBcbiAgZm9yICh2YXIgbiA9IDA7IG4gPCA2OyArK24pIHtcbiAgICBiW2kgKyBuXSA9IG5vZGVbbl07XG4gIH1cblxuICByZXR1cm4gYnVmID8gYnVmIDogYnl0ZXNUb1V1aWQoYik7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gdjE7XG4iLCJ2YXIgcm5nID0gcmVxdWlyZSgnLi9saWIvcm5nJyk7XG52YXIgYnl0ZXNUb1V1aWQgPSByZXF1aXJlKCcuL2xpYi9ieXRlc1RvVXVpZCcpO1xuXG5mdW5jdGlvbiB2NChvcHRpb25zLCBidWYsIG9mZnNldCkge1xuICB2YXIgaSA9IGJ1ZiAmJiBvZmZzZXQgfHwgMDtcblxuICBpZiAodHlwZW9mKG9wdGlvbnMpID09ICdzdHJpbmcnKSB7XG4gICAgYnVmID0gb3B0aW9ucyA9PT0gJ2JpbmFyeScgPyBuZXcgQXJyYXkoMTYpIDogbnVsbDtcbiAgICBvcHRpb25zID0gbnVsbDtcbiAgfVxuICBvcHRpb25zID0gb3B0aW9ucyB8fCB7fTtcblxuICB2YXIgcm5kcyA9IG9wdGlvbnMucmFuZG9tIHx8IChvcHRpb25zLnJuZyB8fCBybmcpKCk7XG5cbiAgLy8gUGVyIDQuNCwgc2V0IGJpdHMgZm9yIHZlcnNpb24gYW5kIGBjbG9ja19zZXFfaGlfYW5kX3Jlc2VydmVkYFxuICBybmRzWzZdID0gKHJuZHNbNl0gJiAweDBmKSB8IDB4NDA7XG4gIHJuZHNbOF0gPSAocm5kc1s4XSAmIDB4M2YpIHwgMHg4MDtcblxuICAvLyBDb3B5IGJ5dGVzIHRvIGJ1ZmZlciwgaWYgcHJvdmlkZWRcbiAgaWYgKGJ1Zikge1xuICAgIGZvciAodmFyIGlpID0gMDsgaWkgPCAxNjsgKytpaSkge1xuICAgICAgYnVmW2kgKyBpaV0gPSBybmRzW2lpXTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gYnVmIHx8IGJ5dGVzVG9VdWlkKHJuZHMpO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHY0O1xuIiwiLypcclxuV2lsZEVtaXR0ZXIuanMgaXMgYSBzbGltIGxpdHRsZSBldmVudCBlbWl0dGVyIGJ5IEBoZW5yaWtqb3JldGVnIGxhcmdlbHkgYmFzZWRcclxub24gQHZpc2lvbm1lZGlhJ3MgRW1pdHRlciBmcm9tIFVJIEtpdC5cclxuXHJcbldoeT8gSSB3YW50ZWQgaXQgc3RhbmRhbG9uZS5cclxuXHJcbkkgYWxzbyB3YW50ZWQgc3VwcG9ydCBmb3Igd2lsZGNhcmQgZW1pdHRlcnMgbGlrZSB0aGlzOlxyXG5cclxuZW1pdHRlci5vbignKicsIGZ1bmN0aW9uIChldmVudE5hbWUsIG90aGVyLCBldmVudCwgcGF5bG9hZHMpIHtcclxuXHJcbn0pO1xyXG5cclxuZW1pdHRlci5vbignc29tZW5hbWVzcGFjZSonLCBmdW5jdGlvbiAoZXZlbnROYW1lLCBwYXlsb2Fkcykge1xyXG5cclxufSk7XHJcblxyXG5QbGVhc2Ugbm90ZSB0aGF0IGNhbGxiYWNrcyB0cmlnZ2VyZWQgYnkgd2lsZGNhcmQgcmVnaXN0ZXJlZCBldmVudHMgYWxzbyBnZXRcclxudGhlIGV2ZW50IG5hbWUgYXMgdGhlIGZpcnN0IGFyZ3VtZW50LlxyXG4qL1xyXG5cclxubW9kdWxlLmV4cG9ydHMgPSBXaWxkRW1pdHRlcjtcclxuXHJcbmZ1bmN0aW9uIFdpbGRFbWl0dGVyKCkgeyB9XHJcblxyXG5XaWxkRW1pdHRlci5taXhpbiA9IGZ1bmN0aW9uIChjb25zdHJ1Y3Rvcikge1xyXG4gICAgdmFyIHByb3RvdHlwZSA9IGNvbnN0cnVjdG9yLnByb3RvdHlwZSB8fCBjb25zdHJ1Y3RvcjtcclxuXHJcbiAgICBwcm90b3R5cGUuaXNXaWxkRW1pdHRlcj0gdHJ1ZTtcclxuXHJcbiAgICAvLyBMaXN0ZW4gb24gdGhlIGdpdmVuIGBldmVudGAgd2l0aCBgZm5gLiBTdG9yZSBhIGdyb3VwIG5hbWUgaWYgcHJlc2VudC5cclxuICAgIHByb3RvdHlwZS5vbiA9IGZ1bmN0aW9uIChldmVudCwgZ3JvdXBOYW1lLCBmbikge1xyXG4gICAgICAgIHRoaXMuY2FsbGJhY2tzID0gdGhpcy5jYWxsYmFja3MgfHwge307XHJcbiAgICAgICAgdmFyIGhhc0dyb3VwID0gKGFyZ3VtZW50cy5sZW5ndGggPT09IDMpLFxyXG4gICAgICAgICAgICBncm91cCA9IGhhc0dyb3VwID8gYXJndW1lbnRzWzFdIDogdW5kZWZpbmVkLFxyXG4gICAgICAgICAgICBmdW5jID0gaGFzR3JvdXAgPyBhcmd1bWVudHNbMl0gOiBhcmd1bWVudHNbMV07XHJcbiAgICAgICAgZnVuYy5fZ3JvdXBOYW1lID0gZ3JvdXA7XHJcbiAgICAgICAgKHRoaXMuY2FsbGJhY2tzW2V2ZW50XSA9IHRoaXMuY2FsbGJhY2tzW2V2ZW50XSB8fCBbXSkucHVzaChmdW5jKTtcclxuICAgICAgICByZXR1cm4gdGhpcztcclxuICAgIH07XHJcblxyXG4gICAgLy8gQWRkcyBhbiBgZXZlbnRgIGxpc3RlbmVyIHRoYXQgd2lsbCBiZSBpbnZva2VkIGEgc2luZ2xlXHJcbiAgICAvLyB0aW1lIHRoZW4gYXV0b21hdGljYWxseSByZW1vdmVkLlxyXG4gICAgcHJvdG90eXBlLm9uY2UgPSBmdW5jdGlvbiAoZXZlbnQsIGdyb3VwTmFtZSwgZm4pIHtcclxuICAgICAgICB2YXIgc2VsZiA9IHRoaXMsXHJcbiAgICAgICAgICAgIGhhc0dyb3VwID0gKGFyZ3VtZW50cy5sZW5ndGggPT09IDMpLFxyXG4gICAgICAgICAgICBncm91cCA9IGhhc0dyb3VwID8gYXJndW1lbnRzWzFdIDogdW5kZWZpbmVkLFxyXG4gICAgICAgICAgICBmdW5jID0gaGFzR3JvdXAgPyBhcmd1bWVudHNbMl0gOiBhcmd1bWVudHNbMV07XHJcbiAgICAgICAgZnVuY3Rpb24gb24oKSB7XHJcbiAgICAgICAgICAgIHNlbGYub2ZmKGV2ZW50LCBvbik7XHJcbiAgICAgICAgICAgIGZ1bmMuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgdGhpcy5vbihldmVudCwgZ3JvdXAsIG9uKTtcclxuICAgICAgICByZXR1cm4gdGhpcztcclxuICAgIH07XHJcblxyXG4gICAgLy8gVW5iaW5kcyBhbiBlbnRpcmUgZ3JvdXBcclxuICAgIHByb3RvdHlwZS5yZWxlYXNlR3JvdXAgPSBmdW5jdGlvbiAoZ3JvdXBOYW1lKSB7XHJcbiAgICAgICAgdGhpcy5jYWxsYmFja3MgPSB0aGlzLmNhbGxiYWNrcyB8fCB7fTtcclxuICAgICAgICB2YXIgaXRlbSwgaSwgbGVuLCBoYW5kbGVycztcclxuICAgICAgICBmb3IgKGl0ZW0gaW4gdGhpcy5jYWxsYmFja3MpIHtcclxuICAgICAgICAgICAgaGFuZGxlcnMgPSB0aGlzLmNhbGxiYWNrc1tpdGVtXTtcclxuICAgICAgICAgICAgZm9yIChpID0gMCwgbGVuID0gaGFuZGxlcnMubGVuZ3RoOyBpIDwgbGVuOyBpKyspIHtcclxuICAgICAgICAgICAgICAgIGlmIChoYW5kbGVyc1tpXS5fZ3JvdXBOYW1lID09PSBncm91cE5hbWUpIHtcclxuICAgICAgICAgICAgICAgICAgICAvL2NvbnNvbGUubG9nKCdyZW1vdmluZycpO1xyXG4gICAgICAgICAgICAgICAgICAgIC8vIHJlbW92ZSBpdCBhbmQgc2hvcnRlbiB0aGUgYXJyYXkgd2UncmUgbG9vcGluZyB0aHJvdWdoXHJcbiAgICAgICAgICAgICAgICAgICAgaGFuZGxlcnMuc3BsaWNlKGksIDEpO1xyXG4gICAgICAgICAgICAgICAgICAgIGktLTtcclxuICAgICAgICAgICAgICAgICAgICBsZW4tLTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgICAgICByZXR1cm4gdGhpcztcclxuICAgIH07XHJcblxyXG4gICAgLy8gUmVtb3ZlIHRoZSBnaXZlbiBjYWxsYmFjayBmb3IgYGV2ZW50YCBvciBhbGxcclxuICAgIC8vIHJlZ2lzdGVyZWQgY2FsbGJhY2tzLlxyXG4gICAgcHJvdG90eXBlLm9mZiA9IGZ1bmN0aW9uIChldmVudCwgZm4pIHtcclxuICAgICAgICB0aGlzLmNhbGxiYWNrcyA9IHRoaXMuY2FsbGJhY2tzIHx8IHt9O1xyXG4gICAgICAgIHZhciBjYWxsYmFja3MgPSB0aGlzLmNhbGxiYWNrc1tldmVudF0sXHJcbiAgICAgICAgICAgIGk7XHJcblxyXG4gICAgICAgIGlmICghY2FsbGJhY2tzKSByZXR1cm4gdGhpcztcclxuXHJcbiAgICAgICAgLy8gcmVtb3ZlIGFsbCBoYW5kbGVyc1xyXG4gICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAxKSB7XHJcbiAgICAgICAgICAgIGRlbGV0ZSB0aGlzLmNhbGxiYWNrc1tldmVudF07XHJcbiAgICAgICAgICAgIHJldHVybiB0aGlzO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgLy8gcmVtb3ZlIHNwZWNpZmljIGhhbmRsZXJcclxuICAgICAgICBpID0gY2FsbGJhY2tzLmluZGV4T2YoZm4pO1xyXG4gICAgICAgIGNhbGxiYWNrcy5zcGxpY2UoaSwgMSk7XHJcbiAgICAgICAgaWYgKGNhbGxiYWNrcy5sZW5ndGggPT09IDApIHtcclxuICAgICAgICAgICAgZGVsZXRlIHRoaXMuY2FsbGJhY2tzW2V2ZW50XTtcclxuICAgICAgICB9XHJcbiAgICAgICAgcmV0dXJuIHRoaXM7XHJcbiAgICB9O1xyXG5cclxuICAgIC8vLyBFbWl0IGBldmVudGAgd2l0aCB0aGUgZ2l2ZW4gYXJncy5cclxuICAgIC8vIGFsc28gY2FsbHMgYW55IGAqYCBoYW5kbGVyc1xyXG4gICAgcHJvdG90eXBlLmVtaXQgPSBmdW5jdGlvbiAoZXZlbnQpIHtcclxuICAgICAgICB0aGlzLmNhbGxiYWNrcyA9IHRoaXMuY2FsbGJhY2tzIHx8IHt9O1xyXG4gICAgICAgIHZhciBhcmdzID0gW10uc2xpY2UuY2FsbChhcmd1bWVudHMsIDEpLFxyXG4gICAgICAgICAgICBjYWxsYmFja3MgPSB0aGlzLmNhbGxiYWNrc1tldmVudF0sXHJcbiAgICAgICAgICAgIHNwZWNpYWxDYWxsYmFja3MgPSB0aGlzLmdldFdpbGRjYXJkQ2FsbGJhY2tzKGV2ZW50KSxcclxuICAgICAgICAgICAgaSxcclxuICAgICAgICAgICAgbGVuLFxyXG4gICAgICAgICAgICBpdGVtLFxyXG4gICAgICAgICAgICBsaXN0ZW5lcnM7XHJcblxyXG4gICAgICAgIGlmIChjYWxsYmFja3MpIHtcclxuICAgICAgICAgICAgbGlzdGVuZXJzID0gY2FsbGJhY2tzLnNsaWNlKCk7XHJcbiAgICAgICAgICAgIGZvciAoaSA9IDAsIGxlbiA9IGxpc3RlbmVycy5sZW5ndGg7IGkgPCBsZW47ICsraSkge1xyXG4gICAgICAgICAgICAgICAgaWYgKCFsaXN0ZW5lcnNbaV0pIHtcclxuICAgICAgICAgICAgICAgICAgICBicmVhaztcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIGxpc3RlbmVyc1tpXS5hcHBseSh0aGlzLCBhcmdzKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgaWYgKHNwZWNpYWxDYWxsYmFja3MpIHtcclxuICAgICAgICAgICAgbGVuID0gc3BlY2lhbENhbGxiYWNrcy5sZW5ndGg7XHJcbiAgICAgICAgICAgIGxpc3RlbmVycyA9IHNwZWNpYWxDYWxsYmFja3Muc2xpY2UoKTtcclxuICAgICAgICAgICAgZm9yIChpID0gMCwgbGVuID0gbGlzdGVuZXJzLmxlbmd0aDsgaSA8IGxlbjsgKytpKSB7XHJcbiAgICAgICAgICAgICAgICBpZiAoIWxpc3RlbmVyc1tpXSkge1xyXG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgbGlzdGVuZXJzW2ldLmFwcGx5KHRoaXMsIFtldmVudF0uY29uY2F0KGFyZ3MpKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgcmV0dXJuIHRoaXM7XHJcbiAgICB9O1xyXG5cclxuICAgIC8vIEhlbHBlciBmb3IgZm9yIGZpbmRpbmcgc3BlY2lhbCB3aWxkY2FyZCBldmVudCBoYW5kbGVycyB0aGF0IG1hdGNoIHRoZSBldmVudFxyXG4gICAgcHJvdG90eXBlLmdldFdpbGRjYXJkQ2FsbGJhY2tzID0gZnVuY3Rpb24gKGV2ZW50TmFtZSkge1xyXG4gICAgICAgIHRoaXMuY2FsbGJhY2tzID0gdGhpcy5jYWxsYmFja3MgfHwge307XHJcbiAgICAgICAgdmFyIGl0ZW0sXHJcbiAgICAgICAgICAgIHNwbGl0LFxyXG4gICAgICAgICAgICByZXN1bHQgPSBbXTtcclxuXHJcbiAgICAgICAgZm9yIChpdGVtIGluIHRoaXMuY2FsbGJhY2tzKSB7XHJcbiAgICAgICAgICAgIHNwbGl0ID0gaXRlbS5zcGxpdCgnKicpO1xyXG4gICAgICAgICAgICBpZiAoaXRlbSA9PT0gJyonIHx8IChzcGxpdC5sZW5ndGggPT09IDIgJiYgZXZlbnROYW1lLnNsaWNlKDAsIHNwbGl0WzBdLmxlbmd0aCkgPT09IHNwbGl0WzBdKSkge1xyXG4gICAgICAgICAgICAgICAgcmVzdWx0ID0gcmVzdWx0LmNvbmNhdCh0aGlzLmNhbGxiYWNrc1tpdGVtXSk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcclxuICAgIH07XHJcblxyXG59O1xyXG5cclxuV2lsZEVtaXR0ZXIubWl4aW4oV2lsZEVtaXR0ZXIpO1xyXG4iLCIvKiFcbiAqIEV2ZW50RW1pdHRlciB2NS4yLjUgLSBnaXQuaW8vZWVcbiAqIFVubGljZW5zZSAtIGh0dHA6Ly91bmxpY2Vuc2Uub3JnL1xuICogT2xpdmVyIENhbGR3ZWxsIC0gaHR0cDovL29saS5tZS51ay9cbiAqIEBwcmVzZXJ2ZVxuICovXG5cbjsoZnVuY3Rpb24gKGV4cG9ydHMpIHtcbiAgICAndXNlIHN0cmljdCc7XG5cbiAgICAvKipcbiAgICAgKiBDbGFzcyBmb3IgbWFuYWdpbmcgZXZlbnRzLlxuICAgICAqIENhbiBiZSBleHRlbmRlZCB0byBwcm92aWRlIGV2ZW50IGZ1bmN0aW9uYWxpdHkgaW4gb3RoZXIgY2xhc3Nlcy5cbiAgICAgKlxuICAgICAqIEBjbGFzcyBFdmVudEVtaXR0ZXIgTWFuYWdlcyBldmVudCByZWdpc3RlcmluZyBhbmQgZW1pdHRpbmcuXG4gICAgICovXG4gICAgZnVuY3Rpb24gRXZlbnRFbWl0dGVyKCkge31cblxuICAgIC8vIFNob3J0Y3V0cyB0byBpbXByb3ZlIHNwZWVkIGFuZCBzaXplXG4gICAgdmFyIHByb3RvID0gRXZlbnRFbWl0dGVyLnByb3RvdHlwZTtcbiAgICB2YXIgb3JpZ2luYWxHbG9iYWxWYWx1ZSA9IGV4cG9ydHMuRXZlbnRFbWl0dGVyO1xuXG4gICAgLyoqXG4gICAgICogRmluZHMgdGhlIGluZGV4IG9mIHRoZSBsaXN0ZW5lciBmb3IgdGhlIGV2ZW50IGluIGl0cyBzdG9yYWdlIGFycmF5LlxuICAgICAqXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbltdfSBsaXN0ZW5lcnMgQXJyYXkgb2YgbGlzdGVuZXJzIHRvIHNlYXJjaCB0aHJvdWdoLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGxpc3RlbmVyIE1ldGhvZCB0byBsb29rIGZvci5cbiAgICAgKiBAcmV0dXJuIHtOdW1iZXJ9IEluZGV4IG9mIHRoZSBzcGVjaWZpZWQgbGlzdGVuZXIsIC0xIGlmIG5vdCBmb3VuZFxuICAgICAqIEBhcGkgcHJpdmF0ZVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGluZGV4T2ZMaXN0ZW5lcihsaXN0ZW5lcnMsIGxpc3RlbmVyKSB7XG4gICAgICAgIHZhciBpID0gbGlzdGVuZXJzLmxlbmd0aDtcbiAgICAgICAgd2hpbGUgKGktLSkge1xuICAgICAgICAgICAgaWYgKGxpc3RlbmVyc1tpXS5saXN0ZW5lciA9PT0gbGlzdGVuZXIpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiAtMTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBBbGlhcyBhIG1ldGhvZCB3aGlsZSBrZWVwaW5nIHRoZSBjb250ZXh0IGNvcnJlY3QsIHRvIGFsbG93IGZvciBvdmVyd3JpdGluZyBvZiB0YXJnZXQgbWV0aG9kLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtTdHJpbmd9IG5hbWUgVGhlIG5hbWUgb2YgdGhlIHRhcmdldCBtZXRob2QuXG4gICAgICogQHJldHVybiB7RnVuY3Rpb259IFRoZSBhbGlhc2VkIG1ldGhvZFxuICAgICAqIEBhcGkgcHJpdmF0ZVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGFsaWFzKG5hbWUpIHtcbiAgICAgICAgcmV0dXJuIGZ1bmN0aW9uIGFsaWFzQ2xvc3VyZSgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzW25hbWVdLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyB0aGUgbGlzdGVuZXIgYXJyYXkgZm9yIHRoZSBzcGVjaWZpZWQgZXZlbnQuXG4gICAgICogV2lsbCBpbml0aWFsaXNlIHRoZSBldmVudCBvYmplY3QgYW5kIGxpc3RlbmVyIGFycmF5cyBpZiByZXF1aXJlZC5cbiAgICAgKiBXaWxsIHJldHVybiBhbiBvYmplY3QgaWYgeW91IHVzZSBhIHJlZ2V4IHNlYXJjaC4gVGhlIG9iamVjdCBjb250YWlucyBrZXlzIGZvciBlYWNoIG1hdGNoZWQgZXZlbnQuIFNvIC9iYVtyel0vIG1pZ2h0IHJldHVybiBhbiBvYmplY3QgY29udGFpbmluZyBiYXIgYW5kIGJhei4gQnV0IG9ubHkgaWYgeW91IGhhdmUgZWl0aGVyIGRlZmluZWQgdGhlbSB3aXRoIGRlZmluZUV2ZW50IG9yIGFkZGVkIHNvbWUgbGlzdGVuZXJzIHRvIHRoZW0uXG4gICAgICogRWFjaCBwcm9wZXJ0eSBpbiB0aGUgb2JqZWN0IHJlc3BvbnNlIGlzIGFuIGFycmF5IG9mIGxpc3RlbmVyIGZ1bmN0aW9ucy5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfFJlZ0V4cH0gZXZ0IE5hbWUgb2YgdGhlIGV2ZW50IHRvIHJldHVybiB0aGUgbGlzdGVuZXJzIGZyb20uXG4gICAgICogQHJldHVybiB7RnVuY3Rpb25bXXxPYmplY3R9IEFsbCBsaXN0ZW5lciBmdW5jdGlvbnMgZm9yIHRoZSBldmVudC5cbiAgICAgKi9cbiAgICBwcm90by5nZXRMaXN0ZW5lcnMgPSBmdW5jdGlvbiBnZXRMaXN0ZW5lcnMoZXZ0KSB7XG4gICAgICAgIHZhciBldmVudHMgPSB0aGlzLl9nZXRFdmVudHMoKTtcbiAgICAgICAgdmFyIHJlc3BvbnNlO1xuICAgICAgICB2YXIga2V5O1xuXG4gICAgICAgIC8vIFJldHVybiBhIGNvbmNhdGVuYXRlZCBhcnJheSBvZiBhbGwgbWF0Y2hpbmcgZXZlbnRzIGlmXG4gICAgICAgIC8vIHRoZSBzZWxlY3RvciBpcyBhIHJlZ3VsYXIgZXhwcmVzc2lvbi5cbiAgICAgICAgaWYgKGV2dCBpbnN0YW5jZW9mIFJlZ0V4cCkge1xuICAgICAgICAgICAgcmVzcG9uc2UgPSB7fTtcbiAgICAgICAgICAgIGZvciAoa2V5IGluIGV2ZW50cykge1xuICAgICAgICAgICAgICAgIGlmIChldmVudHMuaGFzT3duUHJvcGVydHkoa2V5KSAmJiBldnQudGVzdChrZXkpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc3BvbnNlW2tleV0gPSBldmVudHNba2V5XTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICByZXNwb25zZSA9IGV2ZW50c1tldnRdIHx8IChldmVudHNbZXZ0XSA9IFtdKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiByZXNwb25zZTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogVGFrZXMgYSBsaXN0IG9mIGxpc3RlbmVyIG9iamVjdHMgYW5kIGZsYXR0ZW5zIGl0IGludG8gYSBsaXN0IG9mIGxpc3RlbmVyIGZ1bmN0aW9ucy5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7T2JqZWN0W119IGxpc3RlbmVycyBSYXcgbGlzdGVuZXIgb2JqZWN0cy5cbiAgICAgKiBAcmV0dXJuIHtGdW5jdGlvbltdfSBKdXN0IHRoZSBsaXN0ZW5lciBmdW5jdGlvbnMuXG4gICAgICovXG4gICAgcHJvdG8uZmxhdHRlbkxpc3RlbmVycyA9IGZ1bmN0aW9uIGZsYXR0ZW5MaXN0ZW5lcnMobGlzdGVuZXJzKSB7XG4gICAgICAgIHZhciBmbGF0TGlzdGVuZXJzID0gW107XG4gICAgICAgIHZhciBpO1xuXG4gICAgICAgIGZvciAoaSA9IDA7IGkgPCBsaXN0ZW5lcnMubGVuZ3RoOyBpICs9IDEpIHtcbiAgICAgICAgICAgIGZsYXRMaXN0ZW5lcnMucHVzaChsaXN0ZW5lcnNbaV0ubGlzdGVuZXIpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGZsYXRMaXN0ZW5lcnM7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEZldGNoZXMgdGhlIHJlcXVlc3RlZCBsaXN0ZW5lcnMgdmlhIGdldExpc3RlbmVycyBidXQgd2lsbCBhbHdheXMgcmV0dXJuIHRoZSByZXN1bHRzIGluc2lkZSBhbiBvYmplY3QuIFRoaXMgaXMgbWFpbmx5IGZvciBpbnRlcm5hbCB1c2UgYnV0IG90aGVycyBtYXkgZmluZCBpdCB1c2VmdWwuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1N0cmluZ3xSZWdFeHB9IGV2dCBOYW1lIG9mIHRoZSBldmVudCB0byByZXR1cm4gdGhlIGxpc3RlbmVycyBmcm9tLlxuICAgICAqIEByZXR1cm4ge09iamVjdH0gQWxsIGxpc3RlbmVyIGZ1bmN0aW9ucyBmb3IgYW4gZXZlbnQgaW4gYW4gb2JqZWN0LlxuICAgICAqL1xuICAgIHByb3RvLmdldExpc3RlbmVyc0FzT2JqZWN0ID0gZnVuY3Rpb24gZ2V0TGlzdGVuZXJzQXNPYmplY3QoZXZ0KSB7XG4gICAgICAgIHZhciBsaXN0ZW5lcnMgPSB0aGlzLmdldExpc3RlbmVycyhldnQpO1xuICAgICAgICB2YXIgcmVzcG9uc2U7XG5cbiAgICAgICAgaWYgKGxpc3RlbmVycyBpbnN0YW5jZW9mIEFycmF5KSB7XG4gICAgICAgICAgICByZXNwb25zZSA9IHt9O1xuICAgICAgICAgICAgcmVzcG9uc2VbZXZ0XSA9IGxpc3RlbmVycztcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiByZXNwb25zZSB8fCBsaXN0ZW5lcnM7XG4gICAgfTtcblxuICAgIGZ1bmN0aW9uIGlzVmFsaWRMaXN0ZW5lciAobGlzdGVuZXIpIHtcbiAgICAgICAgaWYgKHR5cGVvZiBsaXN0ZW5lciA9PT0gJ2Z1bmN0aW9uJyB8fCBsaXN0ZW5lciBpbnN0YW5jZW9mIFJlZ0V4cCkge1xuICAgICAgICAgICAgcmV0dXJuIHRydWVcbiAgICAgICAgfSBlbHNlIGlmIChsaXN0ZW5lciAmJiB0eXBlb2YgbGlzdGVuZXIgPT09ICdvYmplY3QnKSB7XG4gICAgICAgICAgICByZXR1cm4gaXNWYWxpZExpc3RlbmVyKGxpc3RlbmVyLmxpc3RlbmVyKVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlXG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBBZGRzIGEgbGlzdGVuZXIgZnVuY3Rpb24gdG8gdGhlIHNwZWNpZmllZCBldmVudC5cbiAgICAgKiBUaGUgbGlzdGVuZXIgd2lsbCBub3QgYmUgYWRkZWQgaWYgaXQgaXMgYSBkdXBsaWNhdGUuXG4gICAgICogSWYgdGhlIGxpc3RlbmVyIHJldHVybnMgdHJ1ZSB0aGVuIGl0IHdpbGwgYmUgcmVtb3ZlZCBhZnRlciBpdCBpcyBjYWxsZWQuXG4gICAgICogSWYgeW91IHBhc3MgYSByZWd1bGFyIGV4cHJlc3Npb24gYXMgdGhlIGV2ZW50IG5hbWUgdGhlbiB0aGUgbGlzdGVuZXIgd2lsbCBiZSBhZGRlZCB0byBhbGwgZXZlbnRzIHRoYXQgbWF0Y2ggaXQuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1N0cmluZ3xSZWdFeHB9IGV2dCBOYW1lIG9mIHRoZSBldmVudCB0byBhdHRhY2ggdGhlIGxpc3RlbmVyIHRvLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGxpc3RlbmVyIE1ldGhvZCB0byBiZSBjYWxsZWQgd2hlbiB0aGUgZXZlbnQgaXMgZW1pdHRlZC4gSWYgdGhlIGZ1bmN0aW9uIHJldHVybnMgdHJ1ZSB0aGVuIGl0IHdpbGwgYmUgcmVtb3ZlZCBhZnRlciBjYWxsaW5nLlxuICAgICAqIEByZXR1cm4ge09iamVjdH0gQ3VycmVudCBpbnN0YW5jZSBvZiBFdmVudEVtaXR0ZXIgZm9yIGNoYWluaW5nLlxuICAgICAqL1xuICAgIHByb3RvLmFkZExpc3RlbmVyID0gZnVuY3Rpb24gYWRkTGlzdGVuZXIoZXZ0LCBsaXN0ZW5lcikge1xuICAgICAgICBpZiAoIWlzVmFsaWRMaXN0ZW5lcihsaXN0ZW5lcikpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2xpc3RlbmVyIG11c3QgYmUgYSBmdW5jdGlvbicpO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIGxpc3RlbmVycyA9IHRoaXMuZ2V0TGlzdGVuZXJzQXNPYmplY3QoZXZ0KTtcbiAgICAgICAgdmFyIGxpc3RlbmVySXNXcmFwcGVkID0gdHlwZW9mIGxpc3RlbmVyID09PSAnb2JqZWN0JztcbiAgICAgICAgdmFyIGtleTtcblxuICAgICAgICBmb3IgKGtleSBpbiBsaXN0ZW5lcnMpIHtcbiAgICAgICAgICAgIGlmIChsaXN0ZW5lcnMuaGFzT3duUHJvcGVydHkoa2V5KSAmJiBpbmRleE9mTGlzdGVuZXIobGlzdGVuZXJzW2tleV0sIGxpc3RlbmVyKSA9PT0gLTEpIHtcbiAgICAgICAgICAgICAgICBsaXN0ZW5lcnNba2V5XS5wdXNoKGxpc3RlbmVySXNXcmFwcGVkID8gbGlzdGVuZXIgOiB7XG4gICAgICAgICAgICAgICAgICAgIGxpc3RlbmVyOiBsaXN0ZW5lcixcbiAgICAgICAgICAgICAgICAgICAgb25jZTogZmFsc2VcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBBbGlhcyBvZiBhZGRMaXN0ZW5lclxuICAgICAqL1xuICAgIHByb3RvLm9uID0gYWxpYXMoJ2FkZExpc3RlbmVyJyk7XG5cbiAgICAvKipcbiAgICAgKiBTZW1pLWFsaWFzIG9mIGFkZExpc3RlbmVyLiBJdCB3aWxsIGFkZCBhIGxpc3RlbmVyIHRoYXQgd2lsbCBiZVxuICAgICAqIGF1dG9tYXRpY2FsbHkgcmVtb3ZlZCBhZnRlciBpdHMgZmlyc3QgZXhlY3V0aW9uLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtTdHJpbmd8UmVnRXhwfSBldnQgTmFtZSBvZiB0aGUgZXZlbnQgdG8gYXR0YWNoIHRoZSBsaXN0ZW5lciB0by5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBsaXN0ZW5lciBNZXRob2QgdG8gYmUgY2FsbGVkIHdoZW4gdGhlIGV2ZW50IGlzIGVtaXR0ZWQuIElmIHRoZSBmdW5jdGlvbiByZXR1cm5zIHRydWUgdGhlbiBpdCB3aWxsIGJlIHJlbW92ZWQgYWZ0ZXIgY2FsbGluZy5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEN1cnJlbnQgaW5zdGFuY2Ugb2YgRXZlbnRFbWl0dGVyIGZvciBjaGFpbmluZy5cbiAgICAgKi9cbiAgICBwcm90by5hZGRPbmNlTGlzdGVuZXIgPSBmdW5jdGlvbiBhZGRPbmNlTGlzdGVuZXIoZXZ0LCBsaXN0ZW5lcikge1xuICAgICAgICByZXR1cm4gdGhpcy5hZGRMaXN0ZW5lcihldnQsIHtcbiAgICAgICAgICAgIGxpc3RlbmVyOiBsaXN0ZW5lcixcbiAgICAgICAgICAgIG9uY2U6IHRydWVcbiAgICAgICAgfSk7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEFsaWFzIG9mIGFkZE9uY2VMaXN0ZW5lci5cbiAgICAgKi9cbiAgICBwcm90by5vbmNlID0gYWxpYXMoJ2FkZE9uY2VMaXN0ZW5lcicpO1xuXG4gICAgLyoqXG4gICAgICogRGVmaW5lcyBhbiBldmVudCBuYW1lLiBUaGlzIGlzIHJlcXVpcmVkIGlmIHlvdSB3YW50IHRvIHVzZSBhIHJlZ2V4IHRvIGFkZCBhIGxpc3RlbmVyIHRvIG11bHRpcGxlIGV2ZW50cyBhdCBvbmNlLiBJZiB5b3UgZG9uJ3QgZG8gdGhpcyB0aGVuIGhvdyBkbyB5b3UgZXhwZWN0IGl0IHRvIGtub3cgd2hhdCBldmVudCB0byBhZGQgdG8/IFNob3VsZCBpdCBqdXN0IGFkZCB0byBldmVyeSBwb3NzaWJsZSBtYXRjaCBmb3IgYSByZWdleD8gTm8uIFRoYXQgaXMgc2NhcnkgYW5kIGJhZC5cbiAgICAgKiBZb3UgbmVlZCB0byB0ZWxsIGl0IHdoYXQgZXZlbnQgbmFtZXMgc2hvdWxkIGJlIG1hdGNoZWQgYnkgYSByZWdleC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfSBldnQgTmFtZSBvZiB0aGUgZXZlbnQgdG8gY3JlYXRlLlxuICAgICAqIEByZXR1cm4ge09iamVjdH0gQ3VycmVudCBpbnN0YW5jZSBvZiBFdmVudEVtaXR0ZXIgZm9yIGNoYWluaW5nLlxuICAgICAqL1xuICAgIHByb3RvLmRlZmluZUV2ZW50ID0gZnVuY3Rpb24gZGVmaW5lRXZlbnQoZXZ0KSB7XG4gICAgICAgIHRoaXMuZ2V0TGlzdGVuZXJzKGV2dCk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBVc2VzIGRlZmluZUV2ZW50IHRvIGRlZmluZSBtdWx0aXBsZSBldmVudHMuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1N0cmluZ1tdfSBldnRzIEFuIGFycmF5IG9mIGV2ZW50IG5hbWVzIHRvIGRlZmluZS5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEN1cnJlbnQgaW5zdGFuY2Ugb2YgRXZlbnRFbWl0dGVyIGZvciBjaGFpbmluZy5cbiAgICAgKi9cbiAgICBwcm90by5kZWZpbmVFdmVudHMgPSBmdW5jdGlvbiBkZWZpbmVFdmVudHMoZXZ0cykge1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGV2dHMubGVuZ3RoOyBpICs9IDEpIHtcbiAgICAgICAgICAgIHRoaXMuZGVmaW5lRXZlbnQoZXZ0c1tpXSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIFJlbW92ZXMgYSBsaXN0ZW5lciBmdW5jdGlvbiBmcm9tIHRoZSBzcGVjaWZpZWQgZXZlbnQuXG4gICAgICogV2hlbiBwYXNzZWQgYSByZWd1bGFyIGV4cHJlc3Npb24gYXMgdGhlIGV2ZW50IG5hbWUsIGl0IHdpbGwgcmVtb3ZlIHRoZSBsaXN0ZW5lciBmcm9tIGFsbCBldmVudHMgdGhhdCBtYXRjaCBpdC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfFJlZ0V4cH0gZXZ0IE5hbWUgb2YgdGhlIGV2ZW50IHRvIHJlbW92ZSB0aGUgbGlzdGVuZXIgZnJvbS5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBsaXN0ZW5lciBNZXRob2QgdG8gcmVtb3ZlIGZyb20gdGhlIGV2ZW50LlxuICAgICAqIEByZXR1cm4ge09iamVjdH0gQ3VycmVudCBpbnN0YW5jZSBvZiBFdmVudEVtaXR0ZXIgZm9yIGNoYWluaW5nLlxuICAgICAqL1xuICAgIHByb3RvLnJlbW92ZUxpc3RlbmVyID0gZnVuY3Rpb24gcmVtb3ZlTGlzdGVuZXIoZXZ0LCBsaXN0ZW5lcikge1xuICAgICAgICB2YXIgbGlzdGVuZXJzID0gdGhpcy5nZXRMaXN0ZW5lcnNBc09iamVjdChldnQpO1xuICAgICAgICB2YXIgaW5kZXg7XG4gICAgICAgIHZhciBrZXk7XG5cbiAgICAgICAgZm9yIChrZXkgaW4gbGlzdGVuZXJzKSB7XG4gICAgICAgICAgICBpZiAobGlzdGVuZXJzLmhhc093blByb3BlcnR5KGtleSkpIHtcbiAgICAgICAgICAgICAgICBpbmRleCA9IGluZGV4T2ZMaXN0ZW5lcihsaXN0ZW5lcnNba2V5XSwgbGlzdGVuZXIpO1xuXG4gICAgICAgICAgICAgICAgaWYgKGluZGV4ICE9PSAtMSkge1xuICAgICAgICAgICAgICAgICAgICBsaXN0ZW5lcnNba2V5XS5zcGxpY2UoaW5kZXgsIDEpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBBbGlhcyBvZiByZW1vdmVMaXN0ZW5lclxuICAgICAqL1xuICAgIHByb3RvLm9mZiA9IGFsaWFzKCdyZW1vdmVMaXN0ZW5lcicpO1xuXG4gICAgLyoqXG4gICAgICogQWRkcyBsaXN0ZW5lcnMgaW4gYnVsayB1c2luZyB0aGUgbWFuaXB1bGF0ZUxpc3RlbmVycyBtZXRob2QuXG4gICAgICogSWYgeW91IHBhc3MgYW4gb2JqZWN0IGFzIHRoZSBmaXJzdCBhcmd1bWVudCB5b3UgY2FuIGFkZCB0byBtdWx0aXBsZSBldmVudHMgYXQgb25jZS4gVGhlIG9iamVjdCBzaG91bGQgY29udGFpbiBrZXkgdmFsdWUgcGFpcnMgb2YgZXZlbnRzIGFuZCBsaXN0ZW5lcnMgb3IgbGlzdGVuZXIgYXJyYXlzLiBZb3UgY2FuIGFsc28gcGFzcyBpdCBhbiBldmVudCBuYW1lIGFuZCBhbiBhcnJheSBvZiBsaXN0ZW5lcnMgdG8gYmUgYWRkZWQuXG4gICAgICogWW91IGNhbiBhbHNvIHBhc3MgaXQgYSByZWd1bGFyIGV4cHJlc3Npb24gdG8gYWRkIHRoZSBhcnJheSBvZiBsaXN0ZW5lcnMgdG8gYWxsIGV2ZW50cyB0aGF0IG1hdGNoIGl0LlxuICAgICAqIFllYWgsIHRoaXMgZnVuY3Rpb24gZG9lcyBxdWl0ZSBhIGJpdC4gVGhhdCdzIHByb2JhYmx5IGEgYmFkIHRoaW5nLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtTdHJpbmd8T2JqZWN0fFJlZ0V4cH0gZXZ0IEFuIGV2ZW50IG5hbWUgaWYgeW91IHdpbGwgcGFzcyBhbiBhcnJheSBvZiBsaXN0ZW5lcnMgbmV4dC4gQW4gb2JqZWN0IGlmIHlvdSB3aXNoIHRvIGFkZCB0byBtdWx0aXBsZSBldmVudHMgYXQgb25jZS5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9uW119IFtsaXN0ZW5lcnNdIEFuIG9wdGlvbmFsIGFycmF5IG9mIGxpc3RlbmVyIGZ1bmN0aW9ucyB0byBhZGQuXG4gICAgICogQHJldHVybiB7T2JqZWN0fSBDdXJyZW50IGluc3RhbmNlIG9mIEV2ZW50RW1pdHRlciBmb3IgY2hhaW5pbmcuXG4gICAgICovXG4gICAgcHJvdG8uYWRkTGlzdGVuZXJzID0gZnVuY3Rpb24gYWRkTGlzdGVuZXJzKGV2dCwgbGlzdGVuZXJzKSB7XG4gICAgICAgIC8vIFBhc3MgdGhyb3VnaCB0byBtYW5pcHVsYXRlTGlzdGVuZXJzXG4gICAgICAgIHJldHVybiB0aGlzLm1hbmlwdWxhdGVMaXN0ZW5lcnMoZmFsc2UsIGV2dCwgbGlzdGVuZXJzKTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlcyBsaXN0ZW5lcnMgaW4gYnVsayB1c2luZyB0aGUgbWFuaXB1bGF0ZUxpc3RlbmVycyBtZXRob2QuXG4gICAgICogSWYgeW91IHBhc3MgYW4gb2JqZWN0IGFzIHRoZSBmaXJzdCBhcmd1bWVudCB5b3UgY2FuIHJlbW92ZSBmcm9tIG11bHRpcGxlIGV2ZW50cyBhdCBvbmNlLiBUaGUgb2JqZWN0IHNob3VsZCBjb250YWluIGtleSB2YWx1ZSBwYWlycyBvZiBldmVudHMgYW5kIGxpc3RlbmVycyBvciBsaXN0ZW5lciBhcnJheXMuXG4gICAgICogWW91IGNhbiBhbHNvIHBhc3MgaXQgYW4gZXZlbnQgbmFtZSBhbmQgYW4gYXJyYXkgb2YgbGlzdGVuZXJzIHRvIGJlIHJlbW92ZWQuXG4gICAgICogWW91IGNhbiBhbHNvIHBhc3MgaXQgYSByZWd1bGFyIGV4cHJlc3Npb24gdG8gcmVtb3ZlIHRoZSBsaXN0ZW5lcnMgZnJvbSBhbGwgZXZlbnRzIHRoYXQgbWF0Y2ggaXQuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1N0cmluZ3xPYmplY3R8UmVnRXhwfSBldnQgQW4gZXZlbnQgbmFtZSBpZiB5b3Ugd2lsbCBwYXNzIGFuIGFycmF5IG9mIGxpc3RlbmVycyBuZXh0LiBBbiBvYmplY3QgaWYgeW91IHdpc2ggdG8gcmVtb3ZlIGZyb20gbXVsdGlwbGUgZXZlbnRzIGF0IG9uY2UuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbltdfSBbbGlzdGVuZXJzXSBBbiBvcHRpb25hbCBhcnJheSBvZiBsaXN0ZW5lciBmdW5jdGlvbnMgdG8gcmVtb3ZlLlxuICAgICAqIEByZXR1cm4ge09iamVjdH0gQ3VycmVudCBpbnN0YW5jZSBvZiBFdmVudEVtaXR0ZXIgZm9yIGNoYWluaW5nLlxuICAgICAqL1xuICAgIHByb3RvLnJlbW92ZUxpc3RlbmVycyA9IGZ1bmN0aW9uIHJlbW92ZUxpc3RlbmVycyhldnQsIGxpc3RlbmVycykge1xuICAgICAgICAvLyBQYXNzIHRocm91Z2ggdG8gbWFuaXB1bGF0ZUxpc3RlbmVyc1xuICAgICAgICByZXR1cm4gdGhpcy5tYW5pcHVsYXRlTGlzdGVuZXJzKHRydWUsIGV2dCwgbGlzdGVuZXJzKTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogRWRpdHMgbGlzdGVuZXJzIGluIGJ1bGsuIFRoZSBhZGRMaXN0ZW5lcnMgYW5kIHJlbW92ZUxpc3RlbmVycyBtZXRob2RzIGJvdGggdXNlIHRoaXMgdG8gZG8gdGhlaXIgam9iLiBZb3Ugc2hvdWxkIHJlYWxseSB1c2UgdGhvc2UgaW5zdGVhZCwgdGhpcyBpcyBhIGxpdHRsZSBsb3dlciBsZXZlbC5cbiAgICAgKiBUaGUgZmlyc3QgYXJndW1lbnQgd2lsbCBkZXRlcm1pbmUgaWYgdGhlIGxpc3RlbmVycyBhcmUgcmVtb3ZlZCAodHJ1ZSkgb3IgYWRkZWQgKGZhbHNlKS5cbiAgICAgKiBJZiB5b3UgcGFzcyBhbiBvYmplY3QgYXMgdGhlIHNlY29uZCBhcmd1bWVudCB5b3UgY2FuIGFkZC9yZW1vdmUgZnJvbSBtdWx0aXBsZSBldmVudHMgYXQgb25jZS4gVGhlIG9iamVjdCBzaG91bGQgY29udGFpbiBrZXkgdmFsdWUgcGFpcnMgb2YgZXZlbnRzIGFuZCBsaXN0ZW5lcnMgb3IgbGlzdGVuZXIgYXJyYXlzLlxuICAgICAqIFlvdSBjYW4gYWxzbyBwYXNzIGl0IGFuIGV2ZW50IG5hbWUgYW5kIGFuIGFycmF5IG9mIGxpc3RlbmVycyB0byBiZSBhZGRlZC9yZW1vdmVkLlxuICAgICAqIFlvdSBjYW4gYWxzbyBwYXNzIGl0IGEgcmVndWxhciBleHByZXNzaW9uIHRvIG1hbmlwdWxhdGUgdGhlIGxpc3RlbmVycyBvZiBhbGwgZXZlbnRzIHRoYXQgbWF0Y2ggaXQuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0Jvb2xlYW59IHJlbW92ZSBUcnVlIGlmIHlvdSB3YW50IHRvIHJlbW92ZSBsaXN0ZW5lcnMsIGZhbHNlIGlmIHlvdSB3YW50IHRvIGFkZC5cbiAgICAgKiBAcGFyYW0ge1N0cmluZ3xPYmplY3R8UmVnRXhwfSBldnQgQW4gZXZlbnQgbmFtZSBpZiB5b3Ugd2lsbCBwYXNzIGFuIGFycmF5IG9mIGxpc3RlbmVycyBuZXh0LiBBbiBvYmplY3QgaWYgeW91IHdpc2ggdG8gYWRkL3JlbW92ZSBmcm9tIG11bHRpcGxlIGV2ZW50cyBhdCBvbmNlLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb25bXX0gW2xpc3RlbmVyc10gQW4gb3B0aW9uYWwgYXJyYXkgb2YgbGlzdGVuZXIgZnVuY3Rpb25zIHRvIGFkZC9yZW1vdmUuXG4gICAgICogQHJldHVybiB7T2JqZWN0fSBDdXJyZW50IGluc3RhbmNlIG9mIEV2ZW50RW1pdHRlciBmb3IgY2hhaW5pbmcuXG4gICAgICovXG4gICAgcHJvdG8ubWFuaXB1bGF0ZUxpc3RlbmVycyA9IGZ1bmN0aW9uIG1hbmlwdWxhdGVMaXN0ZW5lcnMocmVtb3ZlLCBldnQsIGxpc3RlbmVycykge1xuICAgICAgICB2YXIgaTtcbiAgICAgICAgdmFyIHZhbHVlO1xuICAgICAgICB2YXIgc2luZ2xlID0gcmVtb3ZlID8gdGhpcy5yZW1vdmVMaXN0ZW5lciA6IHRoaXMuYWRkTGlzdGVuZXI7XG4gICAgICAgIHZhciBtdWx0aXBsZSA9IHJlbW92ZSA/IHRoaXMucmVtb3ZlTGlzdGVuZXJzIDogdGhpcy5hZGRMaXN0ZW5lcnM7XG5cbiAgICAgICAgLy8gSWYgZXZ0IGlzIGFuIG9iamVjdCB0aGVuIHBhc3MgZWFjaCBvZiBpdHMgcHJvcGVydGllcyB0byB0aGlzIG1ldGhvZFxuICAgICAgICBpZiAodHlwZW9mIGV2dCA9PT0gJ29iamVjdCcgJiYgIShldnQgaW5zdGFuY2VvZiBSZWdFeHApKSB7XG4gICAgICAgICAgICBmb3IgKGkgaW4gZXZ0KSB7XG4gICAgICAgICAgICAgICAgaWYgKGV2dC5oYXNPd25Qcm9wZXJ0eShpKSAmJiAodmFsdWUgPSBldnRbaV0pKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIFBhc3MgdGhlIHNpbmdsZSBsaXN0ZW5lciBzdHJhaWdodCB0aHJvdWdoIHRvIHRoZSBzaW5ndWxhciBtZXRob2RcbiAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgc2luZ2xlLmNhbGwodGhpcywgaSwgdmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gT3RoZXJ3aXNlIHBhc3MgYmFjayB0byB0aGUgbXVsdGlwbGUgZnVuY3Rpb25cbiAgICAgICAgICAgICAgICAgICAgICAgIG11bHRpcGxlLmNhbGwodGhpcywgaSwgdmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgLy8gU28gZXZ0IG11c3QgYmUgYSBzdHJpbmdcbiAgICAgICAgICAgIC8vIEFuZCBsaXN0ZW5lcnMgbXVzdCBiZSBhbiBhcnJheSBvZiBsaXN0ZW5lcnNcbiAgICAgICAgICAgIC8vIExvb3Agb3ZlciBpdCBhbmQgcGFzcyBlYWNoIG9uZSB0byB0aGUgbXVsdGlwbGUgbWV0aG9kXG4gICAgICAgICAgICBpID0gbGlzdGVuZXJzLmxlbmd0aDtcbiAgICAgICAgICAgIHdoaWxlIChpLS0pIHtcbiAgICAgICAgICAgICAgICBzaW5nbGUuY2FsbCh0aGlzLCBldnQsIGxpc3RlbmVyc1tpXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlcyBhbGwgbGlzdGVuZXJzIGZyb20gYSBzcGVjaWZpZWQgZXZlbnQuXG4gICAgICogSWYgeW91IGRvIG5vdCBzcGVjaWZ5IGFuIGV2ZW50IHRoZW4gYWxsIGxpc3RlbmVycyB3aWxsIGJlIHJlbW92ZWQuXG4gICAgICogVGhhdCBtZWFucyBldmVyeSBldmVudCB3aWxsIGJlIGVtcHRpZWQuXG4gICAgICogWW91IGNhbiBhbHNvIHBhc3MgYSByZWdleCB0byByZW1vdmUgYWxsIGV2ZW50cyB0aGF0IG1hdGNoIGl0LlxuICAgICAqXG4gICAgICogQHBhcmFtIHtTdHJpbmd8UmVnRXhwfSBbZXZ0XSBPcHRpb25hbCBuYW1lIG9mIHRoZSBldmVudCB0byByZW1vdmUgYWxsIGxpc3RlbmVycyBmb3IuIFdpbGwgcmVtb3ZlIGZyb20gZXZlcnkgZXZlbnQgaWYgbm90IHBhc3NlZC5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEN1cnJlbnQgaW5zdGFuY2Ugb2YgRXZlbnRFbWl0dGVyIGZvciBjaGFpbmluZy5cbiAgICAgKi9cbiAgICBwcm90by5yZW1vdmVFdmVudCA9IGZ1bmN0aW9uIHJlbW92ZUV2ZW50KGV2dCkge1xuICAgICAgICB2YXIgdHlwZSA9IHR5cGVvZiBldnQ7XG4gICAgICAgIHZhciBldmVudHMgPSB0aGlzLl9nZXRFdmVudHMoKTtcbiAgICAgICAgdmFyIGtleTtcblxuICAgICAgICAvLyBSZW1vdmUgZGlmZmVyZW50IHRoaW5ncyBkZXBlbmRpbmcgb24gdGhlIHN0YXRlIG9mIGV2dFxuICAgICAgICBpZiAodHlwZSA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgIC8vIFJlbW92ZSBhbGwgbGlzdGVuZXJzIGZvciB0aGUgc3BlY2lmaWVkIGV2ZW50XG4gICAgICAgICAgICBkZWxldGUgZXZlbnRzW2V2dF07XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAoZXZ0IGluc3RhbmNlb2YgUmVnRXhwKSB7XG4gICAgICAgICAgICAvLyBSZW1vdmUgYWxsIGV2ZW50cyBtYXRjaGluZyB0aGUgcmVnZXguXG4gICAgICAgICAgICBmb3IgKGtleSBpbiBldmVudHMpIHtcbiAgICAgICAgICAgICAgICBpZiAoZXZlbnRzLmhhc093blByb3BlcnR5KGtleSkgJiYgZXZ0LnRlc3Qoa2V5KSkge1xuICAgICAgICAgICAgICAgICAgICBkZWxldGUgZXZlbnRzW2tleV07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgLy8gUmVtb3ZlIGFsbCBsaXN0ZW5lcnMgaW4gYWxsIGV2ZW50c1xuICAgICAgICAgICAgZGVsZXRlIHRoaXMuX2V2ZW50cztcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBBbGlhcyBvZiByZW1vdmVFdmVudC5cbiAgICAgKlxuICAgICAqIEFkZGVkIHRvIG1pcnJvciB0aGUgbm9kZSBBUEkuXG4gICAgICovXG4gICAgcHJvdG8ucmVtb3ZlQWxsTGlzdGVuZXJzID0gYWxpYXMoJ3JlbW92ZUV2ZW50Jyk7XG5cbiAgICAvKipcbiAgICAgKiBFbWl0cyBhbiBldmVudCBvZiB5b3VyIGNob2ljZS5cbiAgICAgKiBXaGVuIGVtaXR0ZWQsIGV2ZXJ5IGxpc3RlbmVyIGF0dGFjaGVkIHRvIHRoYXQgZXZlbnQgd2lsbCBiZSBleGVjdXRlZC5cbiAgICAgKiBJZiB5b3UgcGFzcyB0aGUgb3B0aW9uYWwgYXJndW1lbnQgYXJyYXkgdGhlbiB0aG9zZSBhcmd1bWVudHMgd2lsbCBiZSBwYXNzZWQgdG8gZXZlcnkgbGlzdGVuZXIgdXBvbiBleGVjdXRpb24uXG4gICAgICogQmVjYXVzZSBpdCB1c2VzIGBhcHBseWAsIHlvdXIgYXJyYXkgb2YgYXJndW1lbnRzIHdpbGwgYmUgcGFzc2VkIGFzIGlmIHlvdSB3cm90ZSB0aGVtIG91dCBzZXBhcmF0ZWx5LlxuICAgICAqIFNvIHRoZXkgd2lsbCBub3QgYXJyaXZlIHdpdGhpbiB0aGUgYXJyYXkgb24gdGhlIG90aGVyIHNpZGUsIHRoZXkgd2lsbCBiZSBzZXBhcmF0ZS5cbiAgICAgKiBZb3UgY2FuIGFsc28gcGFzcyBhIHJlZ3VsYXIgZXhwcmVzc2lvbiB0byBlbWl0IHRvIGFsbCBldmVudHMgdGhhdCBtYXRjaCBpdC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfFJlZ0V4cH0gZXZ0IE5hbWUgb2YgdGhlIGV2ZW50IHRvIGVtaXQgYW5kIGV4ZWN1dGUgbGlzdGVuZXJzIGZvci5cbiAgICAgKiBAcGFyYW0ge0FycmF5fSBbYXJnc10gT3B0aW9uYWwgYXJyYXkgb2YgYXJndW1lbnRzIHRvIGJlIHBhc3NlZCB0byBlYWNoIGxpc3RlbmVyLlxuICAgICAqIEByZXR1cm4ge09iamVjdH0gQ3VycmVudCBpbnN0YW5jZSBvZiBFdmVudEVtaXR0ZXIgZm9yIGNoYWluaW5nLlxuICAgICAqL1xuICAgIHByb3RvLmVtaXRFdmVudCA9IGZ1bmN0aW9uIGVtaXRFdmVudChldnQsIGFyZ3MpIHtcbiAgICAgICAgdmFyIGxpc3RlbmVyc01hcCA9IHRoaXMuZ2V0TGlzdGVuZXJzQXNPYmplY3QoZXZ0KTtcbiAgICAgICAgdmFyIGxpc3RlbmVycztcbiAgICAgICAgdmFyIGxpc3RlbmVyO1xuICAgICAgICB2YXIgaTtcbiAgICAgICAgdmFyIGtleTtcbiAgICAgICAgdmFyIHJlc3BvbnNlO1xuXG4gICAgICAgIGZvciAoa2V5IGluIGxpc3RlbmVyc01hcCkge1xuICAgICAgICAgICAgaWYgKGxpc3RlbmVyc01hcC5oYXNPd25Qcm9wZXJ0eShrZXkpKSB7XG4gICAgICAgICAgICAgICAgbGlzdGVuZXJzID0gbGlzdGVuZXJzTWFwW2tleV0uc2xpY2UoMCk7XG5cbiAgICAgICAgICAgICAgICBmb3IgKGkgPSAwOyBpIDwgbGlzdGVuZXJzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIElmIHRoZSBsaXN0ZW5lciByZXR1cm5zIHRydWUgdGhlbiBpdCBzaGFsbCBiZSByZW1vdmVkIGZyb20gdGhlIGV2ZW50XG4gICAgICAgICAgICAgICAgICAgIC8vIFRoZSBmdW5jdGlvbiBpcyBleGVjdXRlZCBlaXRoZXIgd2l0aCBhIGJhc2ljIGNhbGwgb3IgYW4gYXBwbHkgaWYgdGhlcmUgaXMgYW4gYXJncyBhcnJheVxuICAgICAgICAgICAgICAgICAgICBsaXN0ZW5lciA9IGxpc3RlbmVyc1tpXTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAobGlzdGVuZXIub25jZSA9PT0gdHJ1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5yZW1vdmVMaXN0ZW5lcihldnQsIGxpc3RlbmVyLmxpc3RlbmVyKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHJlc3BvbnNlID0gbGlzdGVuZXIubGlzdGVuZXIuYXBwbHkodGhpcywgYXJncyB8fCBbXSk7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKHJlc3BvbnNlID09PSB0aGlzLl9nZXRPbmNlUmV0dXJuVmFsdWUoKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5yZW1vdmVMaXN0ZW5lcihldnQsIGxpc3RlbmVyLmxpc3RlbmVyKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBBbGlhcyBvZiBlbWl0RXZlbnRcbiAgICAgKi9cbiAgICBwcm90by50cmlnZ2VyID0gYWxpYXMoJ2VtaXRFdmVudCcpO1xuXG4gICAgLyoqXG4gICAgICogU3VidGx5IGRpZmZlcmVudCBmcm9tIGVtaXRFdmVudCBpbiB0aGF0IGl0IHdpbGwgcGFzcyBpdHMgYXJndW1lbnRzIG9uIHRvIHRoZSBsaXN0ZW5lcnMsIGFzIG9wcG9zZWQgdG8gdGFraW5nIGEgc2luZ2xlIGFycmF5IG9mIGFyZ3VtZW50cyB0byBwYXNzIG9uLlxuICAgICAqIEFzIHdpdGggZW1pdEV2ZW50LCB5b3UgY2FuIHBhc3MgYSByZWdleCBpbiBwbGFjZSBvZiB0aGUgZXZlbnQgbmFtZSB0byBlbWl0IHRvIGFsbCBldmVudHMgdGhhdCBtYXRjaCBpdC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfFJlZ0V4cH0gZXZ0IE5hbWUgb2YgdGhlIGV2ZW50IHRvIGVtaXQgYW5kIGV4ZWN1dGUgbGlzdGVuZXJzIGZvci5cbiAgICAgKiBAcGFyYW0gey4uLip9IE9wdGlvbmFsIGFkZGl0aW9uYWwgYXJndW1lbnRzIHRvIGJlIHBhc3NlZCB0byBlYWNoIGxpc3RlbmVyLlxuICAgICAqIEByZXR1cm4ge09iamVjdH0gQ3VycmVudCBpbnN0YW5jZSBvZiBFdmVudEVtaXR0ZXIgZm9yIGNoYWluaW5nLlxuICAgICAqL1xuICAgIHByb3RvLmVtaXQgPSBmdW5jdGlvbiBlbWl0KGV2dCkge1xuICAgICAgICB2YXIgYXJncyA9IEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3VtZW50cywgMSk7XG4gICAgICAgIHJldHVybiB0aGlzLmVtaXRFdmVudChldnQsIGFyZ3MpO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBTZXRzIHRoZSBjdXJyZW50IHZhbHVlIHRvIGNoZWNrIGFnYWluc3Qgd2hlbiBleGVjdXRpbmcgbGlzdGVuZXJzLiBJZiBhXG4gICAgICogbGlzdGVuZXJzIHJldHVybiB2YWx1ZSBtYXRjaGVzIHRoZSBvbmUgc2V0IGhlcmUgdGhlbiBpdCB3aWxsIGJlIHJlbW92ZWRcbiAgICAgKiBhZnRlciBleGVjdXRpb24uIFRoaXMgdmFsdWUgZGVmYXVsdHMgdG8gdHJ1ZS5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIG5ldyB2YWx1ZSB0byBjaGVjayBmb3Igd2hlbiBleGVjdXRpbmcgbGlzdGVuZXJzLlxuICAgICAqIEByZXR1cm4ge09iamVjdH0gQ3VycmVudCBpbnN0YW5jZSBvZiBFdmVudEVtaXR0ZXIgZm9yIGNoYWluaW5nLlxuICAgICAqL1xuICAgIHByb3RvLnNldE9uY2VSZXR1cm5WYWx1ZSA9IGZ1bmN0aW9uIHNldE9uY2VSZXR1cm5WYWx1ZSh2YWx1ZSkge1xuICAgICAgICB0aGlzLl9vbmNlUmV0dXJuVmFsdWUgPSB2YWx1ZTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEZldGNoZXMgdGhlIGN1cnJlbnQgdmFsdWUgdG8gY2hlY2sgYWdhaW5zdCB3aGVuIGV4ZWN1dGluZyBsaXN0ZW5lcnMuIElmXG4gICAgICogdGhlIGxpc3RlbmVycyByZXR1cm4gdmFsdWUgbWF0Y2hlcyB0aGlzIG9uZSB0aGVuIGl0IHNob3VsZCBiZSByZW1vdmVkXG4gICAgICogYXV0b21hdGljYWxseS4gSXQgd2lsbCByZXR1cm4gdHJ1ZSBieSBkZWZhdWx0LlxuICAgICAqXG4gICAgICogQHJldHVybiB7KnxCb29sZWFufSBUaGUgY3VycmVudCB2YWx1ZSB0byBjaGVjayBmb3Igb3IgdGhlIGRlZmF1bHQsIHRydWUuXG4gICAgICogQGFwaSBwcml2YXRlXG4gICAgICovXG4gICAgcHJvdG8uX2dldE9uY2VSZXR1cm5WYWx1ZSA9IGZ1bmN0aW9uIF9nZXRPbmNlUmV0dXJuVmFsdWUoKSB7XG4gICAgICAgIGlmICh0aGlzLmhhc093blByb3BlcnR5KCdfb25jZVJldHVyblZhbHVlJykpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLl9vbmNlUmV0dXJuVmFsdWU7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBGZXRjaGVzIHRoZSBldmVudHMgb2JqZWN0IGFuZCBjcmVhdGVzIG9uZSBpZiByZXF1aXJlZC5cbiAgICAgKlxuICAgICAqIEByZXR1cm4ge09iamVjdH0gVGhlIGV2ZW50cyBzdG9yYWdlIG9iamVjdC5cbiAgICAgKiBAYXBpIHByaXZhdGVcbiAgICAgKi9cbiAgICBwcm90by5fZ2V0RXZlbnRzID0gZnVuY3Rpb24gX2dldEV2ZW50cygpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2V2ZW50cyB8fCAodGhpcy5fZXZlbnRzID0ge30pO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBSZXZlcnRzIHRoZSBnbG9iYWwge0BsaW5rIEV2ZW50RW1pdHRlcn0gdG8gaXRzIHByZXZpb3VzIHZhbHVlIGFuZCByZXR1cm5zIGEgcmVmZXJlbmNlIHRvIHRoaXMgdmVyc2lvbi5cbiAgICAgKlxuICAgICAqIEByZXR1cm4ge0Z1bmN0aW9ufSBOb24gY29uZmxpY3RpbmcgRXZlbnRFbWl0dGVyIGNsYXNzLlxuICAgICAqL1xuICAgIEV2ZW50RW1pdHRlci5ub0NvbmZsaWN0ID0gZnVuY3Rpb24gbm9Db25mbGljdCgpIHtcbiAgICAgICAgZXhwb3J0cy5FdmVudEVtaXR0ZXIgPSBvcmlnaW5hbEdsb2JhbFZhbHVlO1xuICAgICAgICByZXR1cm4gRXZlbnRFbWl0dGVyO1xuICAgIH07XG5cbiAgICAvLyBFeHBvc2UgdGhlIGNsYXNzIGVpdGhlciB2aWEgQU1ELCBDb21tb25KUyBvciB0aGUgZ2xvYmFsIG9iamVjdFxuICAgIGlmICh0eXBlb2YgZGVmaW5lID09PSAnZnVuY3Rpb24nICYmIGRlZmluZS5hbWQpIHtcbiAgICAgICAgZGVmaW5lKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiBFdmVudEVtaXR0ZXI7XG4gICAgICAgIH0pO1xuICAgIH1cbiAgICBlbHNlIGlmICh0eXBlb2YgbW9kdWxlID09PSAnb2JqZWN0JyAmJiBtb2R1bGUuZXhwb3J0cyl7XG4gICAgICAgIG1vZHVsZS5leHBvcnRzID0gRXZlbnRFbWl0dGVyO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgZXhwb3J0cy5FdmVudEVtaXR0ZXIgPSBFdmVudEVtaXR0ZXI7XG4gICAgfVxufSh0eXBlb2Ygd2luZG93ICE9PSAndW5kZWZpbmVkJyA/IHdpbmRvdyA6IHRoaXMgfHwge30pKTtcbiIsImltcG9ydCB7IE9wZW5WaWR1IH0gZnJvbSAnLi9PcGVuVmlkdS9PcGVuVmlkdSc7XG5cbmlmICh3aW5kb3cpIHtcbiAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6bm8tc3RyaW5nLWxpdGVyYWxcbiAgICB3aW5kb3dbJ09wZW5WaWR1J10gPSBPcGVuVmlkdTtcbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IFNlc3Npb24gfSBmcm9tICcuL1Nlc3Npb24nO1xuaW1wb3J0IHsgU3RyZWFtIH0gZnJvbSAnLi9TdHJlYW0nO1xuaW1wb3J0IHsgQ29ubmVjdGlvbk9wdGlvbnMgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHJpdmF0ZS9Db25uZWN0aW9uT3B0aW9ucyc7XG5pbXBvcnQgeyBJbmJvdW5kU3RyZWFtT3B0aW9ucyB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvSW50ZXJmYWNlcy9Qcml2YXRlL0luYm91bmRTdHJlYW1PcHRpb25zJztcbmltcG9ydCB7IFN0cmVhbU9wdGlvbnNTZXJ2ZXIgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHJpdmF0ZS9TdHJlYW1PcHRpb25zU2VydmVyJztcblxuXG4vKipcbiAqIFJlcHJlc2VudHMgZWFjaCBvbmUgb2YgdGhlIHVzZXIncyBjb25uZWN0aW9uIHRvIHRoZSBzZXNzaW9uICh0aGUgbG9jYWwgb25lIGFuZCBvdGhlciB1c2VyJ3MgY29ubmVjdGlvbnMpLlxuICogVGhlcmVmb3JlIGVhY2ggW1tTZXNzaW9uXV0gYW5kIFtbU3RyZWFtXV0gb2JqZWN0IGhhcyBhbiBhdHRyaWJ1dGUgb2YgdHlwZSBDb25uZWN0aW9uXG4gKi9cbmV4cG9ydCBjbGFzcyBDb25uZWN0aW9uIHtcblxuICAgIC8qKlxuICAgICAqIFVuaXF1ZSBpZGVudGlmaWVyIG9mIHRoZSBjb25uZWN0aW9uXG4gICAgICovXG4gICAgY29ubmVjdGlvbklkOiBzdHJpbmc7XG5cbiAgICAvKipcbiAgICAgKiBUaW1lIHdoZW4gdGhpcyBjb25uZWN0aW9uIHdhcyBjcmVhdGVkIChVVEMgbWlsbGlzZWNvbmRzKVxuICAgICAqL1xuICAgIGNyZWF0aW9uVGltZTogbnVtYmVyO1xuXG4gICAgLyoqXG4gICAgICogRGF0YSBhc3NvY2lhdGVkIHRvIHRoaXMgY29ubmVjdGlvbiAoYW5kIHRoZXJlZm9yZSB0byBjZXJ0YWluIHVzZXIpLiBUaGlzIGlzIGFuIGltcG9ydGFudCBmaWVsZDpcbiAgICAgKiBpdCBhbGxvd3MgeW91IHRvIGJyb2FkY2FzdCBhbGwgdGhlIGluZm9ybWF0aW9uIHlvdSB3YW50IGZvciBlYWNoIHVzZXIgKGEgdXNlcm5hbWUsIGZvciBleGFtcGxlKVxuICAgICAqL1xuICAgIGRhdGE6IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBzdHJlYW06IFN0cmVhbTtcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvcHRpb25zOiBDb25uZWN0aW9uT3B0aW9ucyB8IHVuZGVmaW5lZDtcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBkaXNwb3NlZCA9IGZhbHNlO1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHByaXZhdGUgc2Vzc2lvbjogU2Vzc2lvbiwgb3B0cz86IENvbm5lY3Rpb25PcHRpb25zKSB7XG5cbiAgICAgICAgbGV0IG1zZyA9IFwiJ0Nvbm5lY3Rpb24nIGNyZWF0ZWQgXCI7XG4gICAgICAgIGlmICghIW9wdHMpIHtcbiAgICAgICAgICAgIG1zZyArPSBcIihyZW1vdGUpIHdpdGggJ2Nvbm5lY3Rpb25JZCcgW1wiICsgb3B0cy5pZCArICddJztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIG1zZyArPSAnKGxvY2FsKSc7XG4gICAgICAgIH1cbiAgICAgICAgY29uc29sZS5pbmZvKG1zZyk7XG5cbiAgICAgICAgdGhpcy5vcHRpb25zID0gb3B0cztcblxuICAgICAgICBpZiAoISFvcHRzKSB7XG4gICAgICAgICAgICAvLyBDb25uZWN0aW9uIGlzIHJlbW90ZVxuICAgICAgICAgICAgdGhpcy5jb25uZWN0aW9uSWQgPSBvcHRzLmlkO1xuICAgICAgICAgICAgaWYgKG9wdHMubWV0YWRhdGEpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmRhdGEgPSBvcHRzLm1ldGFkYXRhO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG9wdHMuc3RyZWFtcykge1xuICAgICAgICAgICAgICAgIHRoaXMuaW5pdFJlbW90ZVN0cmVhbXMob3B0cy5zdHJlYW1zKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuY3JlYXRpb25UaW1lID0gbmV3IERhdGUoKS5nZXRUaW1lKCk7XG4gICAgfVxuXG5cbiAgICAvKiBIaWRkZW4gbWV0aG9kcyAqL1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHNlbmRJY2VDYW5kaWRhdGUoY2FuZGlkYXRlOiBSVENJY2VDYW5kaWRhdGUpOiB2b2lkIHtcblxuICAgICAgICBjb25zb2xlLmRlYnVnKCghIXRoaXMuc3RyZWFtLm91dGJvdW5kU3RyZWFtT3B0cyA/ICdMb2NhbCcgOiAnUmVtb3RlJyksICdjYW5kaWRhdGUgZm9yJyxcbiAgICAgICAgICAgIHRoaXMuY29ubmVjdGlvbklkLCBKU09OLnN0cmluZ2lmeShjYW5kaWRhdGUpKTtcblxuICAgICAgICB0aGlzLnNlc3Npb24ub3BlbnZpZHUuc2VuZFJlcXVlc3QoJ29uSWNlQ2FuZGlkYXRlJywge1xuICAgICAgICAgICAgZW5kcG9pbnROYW1lOiB0aGlzLmNvbm5lY3Rpb25JZCxcbiAgICAgICAgICAgIGNhbmRpZGF0ZTogY2FuZGlkYXRlLmNhbmRpZGF0ZSxcbiAgICAgICAgICAgIHNkcE1pZDogY2FuZGlkYXRlLnNkcE1pZCxcbiAgICAgICAgICAgIHNkcE1MaW5lSW5kZXg6IGNhbmRpZGF0ZS5zZHBNTGluZUluZGV4XG4gICAgICAgIH0sIChlcnJvciwgcmVzcG9uc2UpID0+IHtcbiAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ0Vycm9yIHNlbmRpbmcgSUNFIGNhbmRpZGF0ZTogJ1xuICAgICAgICAgICAgICAgICAgICArIEpTT04uc3RyaW5naWZ5KGVycm9yKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBpbml0UmVtb3RlU3RyZWFtcyhvcHRpb25zOiBTdHJlYW1PcHRpb25zU2VydmVyW10pOiB2b2lkIHtcblxuICAgICAgICAvLyBUaGlzIGlzIHJlYWR5IGZvciBzdXBwb3J0aW5nIG11bHRpcGxlIHN0cmVhbXMgcGVyIENvbm5lY3Rpb24gb2JqZWN0LiBSaWdodCBub3cgdGhlIGxvb3Agd2lsbCBhbHdheXMgcnVuIGp1c3Qgb25jZVxuICAgICAgICAvLyB0aGlzLnN0cmVhbSBzaG91bGQgYWxzbyBiZSByZXBsYWNlZCBieSBhIGNvbGxlY3Rpb24gb2Ygc3RyZWFtcyB0byBzdXBwb3J0IG11bHRpcGxlIHN0cmVhbXMgcGVyIENvbm5lY3Rpb25cbiAgICAgICAgb3B0aW9ucy5mb3JFYWNoKG9wdHMgPT4ge1xuICAgICAgICAgICAgY29uc3Qgc3RyZWFtT3B0aW9uczogSW5ib3VuZFN0cmVhbU9wdGlvbnMgPSB7XG4gICAgICAgICAgICAgICAgaWQ6IG9wdHMuaWQsXG4gICAgICAgICAgICAgICAgY29ubmVjdGlvbjogdGhpcyxcbiAgICAgICAgICAgICAgICBoYXNBdWRpbzogb3B0cy5oYXNBdWRpbyxcbiAgICAgICAgICAgICAgICBoYXNWaWRlbzogb3B0cy5oYXNWaWRlbyxcbiAgICAgICAgICAgICAgICBhdWRpb0FjdGl2ZTogb3B0cy5hdWRpb0FjdGl2ZSxcbiAgICAgICAgICAgICAgICB2aWRlb0FjdGl2ZTogb3B0cy52aWRlb0FjdGl2ZSxcbiAgICAgICAgICAgICAgICB0eXBlT2ZWaWRlbzogb3B0cy50eXBlT2ZWaWRlbyxcbiAgICAgICAgICAgICAgICBmcmFtZVJhdGU6IG9wdHMuZnJhbWVSYXRlLFxuICAgICAgICAgICAgICAgIHZpZGVvRGltZW5zaW9uczogISFvcHRzLnZpZGVvRGltZW5zaW9ucyA/IEpTT04ucGFyc2Uob3B0cy52aWRlb0RpbWVuc2lvbnMpIDogdW5kZWZpbmVkXG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgY29uc3Qgc3RyZWFtID0gbmV3IFN0cmVhbSh0aGlzLnNlc3Npb24sIHN0cmVhbU9wdGlvbnMpO1xuXG4gICAgICAgICAgICB0aGlzLmFkZFN0cmVhbShzdHJlYW0pO1xuICAgICAgICB9KTtcblxuICAgICAgICBjb25zb2xlLmluZm8oXCJSZW1vdGUgJ0Nvbm5lY3Rpb24nIHdpdGggJ2Nvbm5lY3Rpb25JZCcgW1wiICsgdGhpcy5jb25uZWN0aW9uSWQgKyAnXSBpcyBub3cgY29uZmlndXJlZCBmb3IgcmVjZWl2aW5nIFN0cmVhbXMgd2l0aCBvcHRpb25zOiAnLCB0aGlzLnN0cmVhbS5pbmJvdW5kU3RyZWFtT3B0cyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGFkZFN0cmVhbShzdHJlYW06IFN0cmVhbSk6IHZvaWQge1xuICAgICAgICBzdHJlYW0uY29ubmVjdGlvbiA9IHRoaXM7XG4gICAgICAgIHRoaXMuc3RyZWFtID0gc3RyZWFtO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICByZW1vdmVTdHJlYW0oc3RyZWFtSWQ6IHN0cmluZyk6IHZvaWQge1xuICAgICAgICBkZWxldGUgdGhpcy5zdHJlYW07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGRpc3Bvc2UoKTogdm9pZCB7XG4gICAgICAgIGlmICghIXRoaXMuc3RyZWFtKSB7XG4gICAgICAgICAgICBkZWxldGUgdGhpcy5zdHJlYW07XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5kaXNwb3NlZCA9IHRydWU7XG4gICAgfVxuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBTdHJlYW0gfSBmcm9tICcuL1N0cmVhbSc7XG5pbXBvcnQgeyBMb2NhbFJlY29yZGVyU3RhdGUgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0VudW1zL0xvY2FsUmVjb3JkZXJTdGF0ZSc7XG5cbi8qKlxuICogQGhpZGRlblxuICovXG5kZWNsYXJlIHZhciBNZWRpYVJlY29yZGVyOiBhbnk7XG5cblxuLyoqXG4gKiBFYXN5IHJlY29yZGluZyBvZiBbW1N0cmVhbV1dIG9iamVjdHMgc3RyYWlnaHRhd2F5IGZyb20gdGhlIGJyb3dzZXIuIEluaXRpYWxpemVkIHdpdGggW1tPcGVuVmlkdS5pbml0TG9jYWxSZWNvcmRlcl1dIG1ldGhvZFxuICpcbiAqID4gV0FSTklORzogUGVyZm9ybWluZyBicm93c2VyIGxvY2FsIHJlY29yZGluZyBvZiAqKnJlbW90ZSBzdHJlYW1zKiogbWF5IGNhdXNlIHNvbWUgdHJvdWJsZXMuIEEgbG9uZyB3YWl0aW5nIHRpbWUgbWF5IGJlIHJlcXVpcmVkIGFmdGVyIGNhbGxpbmcgX0xvY2FsUmVjb3JkZXIuc3RvcCgpXyBpbiB0aGlzIGNhc2VcbiAqL1xuZXhwb3J0IGNsYXNzIExvY2FsUmVjb3JkZXIge1xuXG4gICAgc3RhdGU6IExvY2FsUmVjb3JkZXJTdGF0ZTtcblxuICAgIHByaXZhdGUgY29ubmVjdGlvbklkOiBzdHJpbmc7XG4gICAgcHJpdmF0ZSBtZWRpYVJlY29yZGVyOiBhbnk7XG4gICAgcHJpdmF0ZSBjaHVua3M6IGFueVtdID0gW107XG4gICAgcHJpdmF0ZSBibG9iOiBCbG9iO1xuICAgIHByaXZhdGUgY291bnQgPSAwO1xuICAgIHByaXZhdGUgaWQ6IHN0cmluZztcbiAgICBwcml2YXRlIHZpZGVvUHJldmlld1NyYzogc3RyaW5nO1xuICAgIHByaXZhdGUgaHRtbFBhcmVudEVsZW1lbnRJZDogc3RyaW5nO1xuICAgIHByaXZhdGUgdmlkZW9QcmV2aWV3OiBIVE1MVmlkZW9FbGVtZW50O1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHByaXZhdGUgc3RyZWFtOiBTdHJlYW0pIHtcbiAgICAgICAgdGhpcy5jb25uZWN0aW9uSWQgPSAoISF0aGlzLnN0cmVhbS5jb25uZWN0aW9uKSA/IHRoaXMuc3RyZWFtLmNvbm5lY3Rpb24uY29ubmVjdGlvbklkIDogJ2RlZmF1bHQtY29ubmVjdGlvbic7XG4gICAgICAgIHRoaXMuaWQgPSB0aGlzLnN0cmVhbS5zdHJlYW1JZCArICdfJyArIHRoaXMuY29ubmVjdGlvbklkICsgJ19sb2NhbHJlY29yZCc7XG4gICAgICAgIHRoaXMuc3RhdGUgPSBMb2NhbFJlY29yZGVyU3RhdGUuUkVBRFk7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBTdGFydHMgdGhlIHJlY29yZGluZyBvZiB0aGUgU3RyZWFtLiBbW3N0YXRlXV0gcHJvcGVydHkgbXVzdCBiZSBgUkVBRFlgLiBBZnRlciBtZXRob2Qgc3VjY2VlZHMgaXMgc2V0IHRvIGBSRUNPUkRJTkdgXG4gICAgICogQHJldHVybnMgQSBQcm9taXNlICh0byB3aGljaCB5b3UgY2FuIG9wdGlvbmFsbHkgc3Vic2NyaWJlIHRvKSB0aGF0IGlzIHJlc29sdmVkIGlmIHRoZSByZWNvcmRpbmcgc3VjY2Vzc2Z1bGx5IHN0YXJ0ZWQgYW5kIHJlamVjdGVkIHdpdGggYW4gRXJyb3Igb2JqZWN0IGlmIG5vdFxuICAgICAqL1xuICAgIHJlY29yZCgpOiBQcm9taXNlPGFueT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuXG4gICAgICAgICAgICB0cnkge1xuXG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBNZWRpYVJlY29yZGVyID09PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKCdNZWRpYVJlY29yZGVyIG5vdCBzdXBwb3J0ZWQgb24geW91ciBicm93c2VyLiBTZWUgY29tcGF0aWJpbGl0eSBpbiBodHRwczovL2Nhbml1c2UuY29tLyNzZWFyY2g9TWVkaWFSZWNvcmRlcicpO1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyAoRXJyb3IoJ01lZGlhUmVjb3JkZXIgbm90IHN1cHBvcnRlZCBvbiB5b3VyIGJyb3dzZXIuIFNlZSBjb21wYXRpYmlsaXR5IGluIGh0dHBzOi8vY2FuaXVzZS5jb20vI3NlYXJjaD1NZWRpYVJlY29yZGVyJykpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAodGhpcy5zdGF0ZSAhPT0gTG9jYWxSZWNvcmRlclN0YXRlLlJFQURZKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IChFcnJvcignXFwnTG9jYWxSZWNvcmQucmVjb3JkKClcXCcgbmVlZHMgXFwnTG9jYWxSZWNvcmQuc3RhdGVcXCcgdG8gYmUgXFwnUkVBRFlcXCcgKGN1cnJlbnQgdmFsdWU6IFxcJycgKyB0aGlzLnN0YXRlICsgJ1xcJykuIENhbGwgXFwnTG9jYWxSZWNvcmRlci5jbGVhbigpXFwnIG9yIGluaXQgYSBuZXcgTG9jYWxSZWNvcmRlciBiZWZvcmUnKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKFwiU3RhcnRpbmcgbG9jYWwgcmVjb3JkaW5nIG9mIHN0cmVhbSAnXCIgKyB0aGlzLnN0cmVhbS5zdHJlYW1JZCArIFwiJyBvZiBjb25uZWN0aW9uICdcIiArIHRoaXMuY29ubmVjdGlvbklkICsgXCInXCIpO1xuXG5cbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIE1lZGlhUmVjb3JkZXIuaXNUeXBlU3VwcG9ydGVkID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICAgICAgICAgIGxldCBvcHRpb25zO1xuICAgICAgICAgICAgICAgICAgICBpZiAoTWVkaWFSZWNvcmRlci5pc1R5cGVTdXBwb3J0ZWQoJ3ZpZGVvL3dlYm07Y29kZWNzPXZwOScpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBvcHRpb25zID0geyBtaW1lVHlwZTogJ3ZpZGVvL3dlYm07Y29kZWNzPXZwOScgfTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChNZWRpYVJlY29yZGVyLmlzVHlwZVN1cHBvcnRlZCgndmlkZW8vd2VibTtjb2RlY3M9aDI2NCcpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBvcHRpb25zID0geyBtaW1lVHlwZTogJ3ZpZGVvL3dlYm07Y29kZWNzPWgyNjQnIH07XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoTWVkaWFSZWNvcmRlci5pc1R5cGVTdXBwb3J0ZWQoJ3ZpZGVvL3dlYm07Y29kZWNzPXZwOCcpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBvcHRpb25zID0geyBtaW1lVHlwZTogJ3ZpZGVvL3dlYm07Y29kZWNzPXZwOCcgfTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmxvZygnVXNpbmcgbWltZVR5cGUgJyArIG9wdGlvbnMubWltZVR5cGUpO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLm1lZGlhUmVjb3JkZXIgPSBuZXcgTWVkaWFSZWNvcmRlcih0aGlzLnN0cmVhbS5nZXRNZWRpYVN0cmVhbSgpLCBvcHRpb25zKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLndhcm4oJ2lzVHlwZVN1cHBvcnRlZCBpcyBub3Qgc3VwcG9ydGVkLCB1c2luZyBkZWZhdWx0IGNvZGVjcyBmb3IgYnJvd3NlcicpO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLm1lZGlhUmVjb3JkZXIgPSBuZXcgTWVkaWFSZWNvcmRlcih0aGlzLnN0cmVhbS5nZXRNZWRpYVN0cmVhbSgpKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB0aGlzLm1lZGlhUmVjb3JkZXIuc3RhcnQoMTApO1xuXG4gICAgICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAgICAgICByZWplY3QoZXJyKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5tZWRpYVJlY29yZGVyLm9uZGF0YWF2YWlsYWJsZSA9IChlKSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5jaHVua3MucHVzaChlLmRhdGEpO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgdGhpcy5tZWRpYVJlY29yZGVyLm9uZXJyb3IgPSAoZSkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ01lZGlhUmVjb3JkZXIgZXJyb3I6ICcsIGUpO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgdGhpcy5tZWRpYVJlY29yZGVyLm9uc3RhcnQgPSAoKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5sb2coJ01lZGlhUmVjb3JkZXIgc3RhcnRlZCAoc3RhdGU9JyArIHRoaXMubWVkaWFSZWNvcmRlci5zdGF0ZSArICcpJyk7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICB0aGlzLm1lZGlhUmVjb3JkZXIub25zdG9wID0gKCkgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMub25TdG9wRGVmYXVsdCgpO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgdGhpcy5tZWRpYVJlY29yZGVyLm9ucGF1c2UgPSAoKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5sb2coJ01lZGlhUmVjb3JkZXIgcGF1c2VkIChzdGF0ZT0nICsgdGhpcy5tZWRpYVJlY29yZGVyLnN0YXRlICsgJyknKTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIHRoaXMubWVkaWFSZWNvcmRlci5vbnJlc3VtZSA9ICgpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmxvZygnTWVkaWFSZWNvcmRlciByZXN1bWVkIChzdGF0ZT0nICsgdGhpcy5tZWRpYVJlY29yZGVyLnN0YXRlICsgJyknKTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIHRoaXMubWVkaWFSZWNvcmRlci5vbndhcm5pbmcgPSAoZSkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKCdNZWRpYVJlY29yZGVyIHdhcm5pbmc6ICcgKyBlKTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIHRoaXMuc3RhdGUgPSBMb2NhbFJlY29yZGVyU3RhdGUuUkVDT1JESU5HO1xuICAgICAgICAgICAgcmVzb2x2ZSgpO1xuXG4gICAgICAgIH0pO1xuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogRW5kcyB0aGUgcmVjb3JkaW5nIG9mIHRoZSBTdHJlYW0uIFtbc3RhdGVdXSBwcm9wZXJ0eSBtdXN0IGJlIGBSRUNPUkRJTkdgIG9yIGBQQVVTRURgLiBBZnRlciBtZXRob2Qgc3VjY2VlZHMgaXMgc2V0IHRvIGBGSU5JU0hFRGBcbiAgICAgKiBAcmV0dXJucyBBIFByb21pc2UgKHRvIHdoaWNoIHlvdSBjYW4gb3B0aW9uYWxseSBzdWJzY3JpYmUgdG8pIHRoYXQgaXMgcmVzb2x2ZWQgaWYgdGhlIHJlY29yZGluZyBzdWNjZXNzZnVsbHkgc3RvcHBlZCBhbmQgcmVqZWN0ZWQgd2l0aCBhbiBFcnJvciBvYmplY3QgaWYgbm90XG4gICAgICovXG4gICAgc3RvcCgpOiBQcm9taXNlPGFueT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5zdGF0ZSA9PT0gTG9jYWxSZWNvcmRlclN0YXRlLlJFQURZIHx8IHRoaXMuc3RhdGUgPT09IExvY2FsUmVjb3JkZXJTdGF0ZS5GSU5JU0hFRCkge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyAoRXJyb3IoJ1xcJ0xvY2FsUmVjb3JkLnN0b3AoKVxcJyBuZWVkcyBcXCdMb2NhbFJlY29yZC5zdGF0ZVxcJyB0byBiZSBcXCdSRUNPUkRJTkdcXCcgb3IgXFwnUEFVU0VEXFwnIChjdXJyZW50IHZhbHVlOiBcXCcnICsgdGhpcy5zdGF0ZSArICdcXCcpLiBDYWxsIFxcJ0xvY2FsUmVjb3JkZXIuc3RhcnQoKVxcJyBiZWZvcmUnKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRoaXMubWVkaWFSZWNvcmRlci5vbnN0b3AgPSAoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMub25TdG9wRGVmYXVsdCgpO1xuICAgICAgICAgICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB0aGlzLm1lZGlhUmVjb3JkZXIuc3RvcCgpO1xuICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICAgIHJlamVjdChlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBQYXVzZXMgdGhlIHJlY29yZGluZyBvZiB0aGUgU3RyZWFtLiBbW3N0YXRlXV0gcHJvcGVydHkgbXVzdCBiZSBgUkVDT1JESU5HYC4gQWZ0ZXIgbWV0aG9kIHN1Y2NlZWRzIGlzIHNldCB0byBgUEFVU0VEYFxuICAgICAqIEByZXR1cm5zIEEgUHJvbWlzZSAodG8gd2hpY2ggeW91IGNhbiBvcHRpb25hbGx5IHN1YnNjcmliZSB0bykgdGhhdCBpcyByZXNvbHZlZCBpZiB0aGUgcmVjb3JkaW5nIHdhcyBzdWNjZXNzZnVsbHkgcGF1c2VkIGFuZCByZWplY3RlZCB3aXRoIGFuIEVycm9yIG9iamVjdCBpZiBub3RcbiAgICAgKi9cbiAgICBwYXVzZSgpOiBQcm9taXNlPGFueT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5zdGF0ZSAhPT0gTG9jYWxSZWNvcmRlclN0YXRlLlJFQ09SRElORykge1xuICAgICAgICAgICAgICAgICAgICByZWplY3QoRXJyb3IoJ1xcJ0xvY2FsUmVjb3JkLnBhdXNlKClcXCcgbmVlZHMgXFwnTG9jYWxSZWNvcmQuc3RhdGVcXCcgdG8gYmUgXFwnUkVDT1JESU5HXFwnIChjdXJyZW50IHZhbHVlOiBcXCcnICsgdGhpcy5zdGF0ZSArICdcXCcpLiBDYWxsIFxcJ0xvY2FsUmVjb3JkZXIuc3RhcnQoKVxcJyBvciBcXCdMb2NhbFJlY29yZGVyLnJlc3VtZSgpXFwnIGJlZm9yZScpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhpcy5tZWRpYVJlY29yZGVyLnBhdXNlKCk7XG4gICAgICAgICAgICAgICAgdGhpcy5zdGF0ZSA9IExvY2FsUmVjb3JkZXJTdGF0ZS5QQVVTRUQ7XG4gICAgICAgICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlc3VtZXMgdGhlIHJlY29yZGluZyBvZiB0aGUgU3RyZWFtLiBbW3N0YXRlXV0gcHJvcGVydHkgbXVzdCBiZSBgUEFVU0VEYC4gQWZ0ZXIgbWV0aG9kIHN1Y2NlZWRzIGlzIHNldCB0byBgUkVDT1JESU5HYFxuICAgICAqIEByZXR1cm5zIEEgUHJvbWlzZSAodG8gd2hpY2ggeW91IGNhbiBvcHRpb25hbGx5IHN1YnNjcmliZSB0bykgdGhhdCBpcyByZXNvbHZlZCBpZiB0aGUgcmVjb3JkaW5nIHdhcyBzdWNjZXNzZnVsbHkgcmVzdW1lZCBhbmQgcmVqZWN0ZWQgd2l0aCBhbiBFcnJvciBvYmplY3QgaWYgbm90XG4gICAgICovXG4gICAgcmVzdW1lKCk6IFByb21pc2U8YW55PiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLnN0YXRlICE9PSBMb2NhbFJlY29yZGVyU3RhdGUuUEFVU0VEKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IChFcnJvcignXFwnTG9jYWxSZWNvcmQucmVzdW1lKClcXCcgbmVlZHMgXFwnTG9jYWxSZWNvcmQuc3RhdGVcXCcgdG8gYmUgXFwnUEFVU0VEXFwnIChjdXJyZW50IHZhbHVlOiBcXCcnICsgdGhpcy5zdGF0ZSArICdcXCcpLiBDYWxsIFxcJ0xvY2FsUmVjb3JkZXIucGF1c2UoKVxcJyBiZWZvcmUnKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRoaXMubWVkaWFSZWNvcmRlci5yZXN1bWUoKTtcbiAgICAgICAgICAgICAgICB0aGlzLnN0YXRlID0gTG9jYWxSZWNvcmRlclN0YXRlLlJFQ09SRElORztcbiAgICAgICAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBQcmV2aWV3cyB0aGUgcmVjb3JkaW5nLCBhcHBlbmRpbmcgYSBuZXcgSFRNTFZpZGVvRWxlbWVudCB0byBlbGVtZW50IHdpdGggaWQgYHBhcmVudElkYC4gW1tzdGF0ZV1dIHByb3BlcnR5IG11c3QgYmUgYEZJTklTSEVEYFxuICAgICAqL1xuICAgIHByZXZpZXcocGFyZW50RWxlbWVudCk6IEhUTUxWaWRlb0VsZW1lbnQge1xuXG4gICAgICAgIGlmICh0aGlzLnN0YXRlICE9PSBMb2NhbFJlY29yZGVyU3RhdGUuRklOSVNIRUQpIHtcbiAgICAgICAgICAgIHRocm93IChFcnJvcignXFwnTG9jYWxSZWNvcmQucHJldmlldygpXFwnIG5lZWRzIFxcJ0xvY2FsUmVjb3JkLnN0YXRlXFwnIHRvIGJlIFxcJ0ZJTklTSEVEXFwnIChjdXJyZW50IHZhbHVlOiBcXCcnICsgdGhpcy5zdGF0ZSArICdcXCcpLiBDYWxsIFxcJ0xvY2FsUmVjb3JkZXIuc3RvcCgpXFwnIGJlZm9yZScpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMudmlkZW9QcmV2aWV3ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgndmlkZW8nKTtcblxuICAgICAgICB0aGlzLnZpZGVvUHJldmlldy5pZCA9IHRoaXMuaWQ7XG4gICAgICAgIHRoaXMudmlkZW9QcmV2aWV3LmF1dG9wbGF5ID0gdHJ1ZTtcblxuICAgICAgICBpZiAodHlwZW9mIHBhcmVudEVsZW1lbnQgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICB0aGlzLmh0bWxQYXJlbnRFbGVtZW50SWQgPSBwYXJlbnRFbGVtZW50O1xuXG4gICAgICAgICAgICBjb25zdCBwYXJlbnRFbGVtZW50RG9tID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQocGFyZW50RWxlbWVudCk7XG4gICAgICAgICAgICBpZiAocGFyZW50RWxlbWVudERvbSkge1xuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9QcmV2aWV3ID0gcGFyZW50RWxlbWVudERvbS5hcHBlbmRDaGlsZCh0aGlzLnZpZGVvUHJldmlldyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLmh0bWxQYXJlbnRFbGVtZW50SWQgPSBwYXJlbnRFbGVtZW50LmlkO1xuICAgICAgICAgICAgdGhpcy52aWRlb1ByZXZpZXcgPSBwYXJlbnRFbGVtZW50LmFwcGVuZENoaWxkKHRoaXMudmlkZW9QcmV2aWV3KTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMudmlkZW9QcmV2aWV3LnNyYyA9IHRoaXMudmlkZW9QcmV2aWV3U3JjO1xuXG4gICAgICAgIHJldHVybiB0aGlzLnZpZGVvUHJldmlldztcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIEdyYWNlZnVsbHkgc3RvcHMgYW5kIGNsZWFucyB0aGUgY3VycmVudCByZWNvcmRpbmcgKFdBUk5JTkc6IGl0IGlzIGNvbXBsZXRlbHkgZGlzbWlzc2VkKS4gU2V0cyBbW3N0YXRlXV0gdG8gYFJFQURZYCBzbyB0aGUgcmVjb3JkaW5nIGNhbiBzdGFydCBhZ2FpblxuICAgICAqL1xuICAgIGNsZWFuKCk6IHZvaWQge1xuICAgICAgICBjb25zdCBmID0gKCkgPT4ge1xuICAgICAgICAgICAgZGVsZXRlIHRoaXMuYmxvYjtcbiAgICAgICAgICAgIHRoaXMuY2h1bmtzID0gW107XG4gICAgICAgICAgICB0aGlzLmNvdW50ID0gMDtcbiAgICAgICAgICAgIGRlbGV0ZSB0aGlzLm1lZGlhUmVjb3JkZXI7XG4gICAgICAgICAgICB0aGlzLnN0YXRlID0gTG9jYWxSZWNvcmRlclN0YXRlLlJFQURZO1xuICAgICAgICB9O1xuICAgICAgICBpZiAodGhpcy5zdGF0ZSA9PT0gTG9jYWxSZWNvcmRlclN0YXRlLlJFQ09SRElORyB8fCB0aGlzLnN0YXRlID09PSBMb2NhbFJlY29yZGVyU3RhdGUuUEFVU0VEKSB7XG4gICAgICAgICAgICB0aGlzLnN0b3AoKS50aGVuKCgpID0+IGYoKSkuY2F0Y2goKCkgPT4gZigpKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGYoKTtcbiAgICAgICAgfVxuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogRG93bmxvYWRzIHRoZSByZWNvcmRlZCB2aWRlbyB0aHJvdWdoIHRoZSBicm93c2VyLiBbW3N0YXRlXV0gcHJvcGVydHkgbXVzdCBiZSBgRklOSVNIRURgXG4gICAgICovXG4gICAgZG93bmxvYWQoKTogdm9pZCB7XG4gICAgICAgIGlmICh0aGlzLnN0YXRlICE9PSBMb2NhbFJlY29yZGVyU3RhdGUuRklOSVNIRUQpIHtcbiAgICAgICAgICAgIHRocm93IChFcnJvcignXFwnTG9jYWxSZWNvcmQuZG93bmxvYWQoKVxcJyBuZWVkcyBcXCdMb2NhbFJlY29yZC5zdGF0ZVxcJyB0byBiZSBcXCdGSU5JU0hFRFxcJyAoY3VycmVudCB2YWx1ZTogXFwnJyArIHRoaXMuc3RhdGUgKyAnXFwnKS4gQ2FsbCBcXCdMb2NhbFJlY29yZGVyLnN0b3AoKVxcJyBiZWZvcmUnKSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjb25zdCBhOiBIVE1MQW5jaG9yRWxlbWVudCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2EnKTtcbiAgICAgICAgICAgIGEuc3R5bGUuZGlzcGxheSA9ICdub25lJztcbiAgICAgICAgICAgIGRvY3VtZW50LmJvZHkuYXBwZW5kQ2hpbGQoYSk7XG5cbiAgICAgICAgICAgIGNvbnN0IHVybCA9IHdpbmRvdy5VUkwuY3JlYXRlT2JqZWN0VVJMKHRoaXMuYmxvYik7XG4gICAgICAgICAgICBhLmhyZWYgPSB1cmw7XG4gICAgICAgICAgICBhLmRvd25sb2FkID0gdGhpcy5pZCArICcud2VibSc7XG4gICAgICAgICAgICBhLmNsaWNrKCk7XG4gICAgICAgICAgICB3aW5kb3cuVVJMLnJldm9rZU9iamVjdFVSTCh1cmwpO1xuXG4gICAgICAgICAgICBkb2N1bWVudC5ib2R5LnJlbW92ZUNoaWxkKGEpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0cyB0aGUgcmF3IEJsb2IgZmlsZS4gTWV0aG9kcyBwcmV2aWV3LCBkb3dubG9hZCwgdXBsb2FkQXNCaW5hcnkgYW5kIHVwbG9hZEFzTXVsdGlwYXJ0ZmlsZSB1c2UgdGhpcyBzYW1lIGZpbGUgdG8gcGVyZm9ybSB0aGVpciBzcGVjaWZpYyBhY3Rpb25zLiBbW3N0YXRlXV0gcHJvcGVydHkgbXVzdCBiZSBgRklOSVNIRURgXG4gICAgICovXG4gICAgZ2V0QmxvYigpOiBCbG9iIHtcbiAgICAgICAgaWYgKHRoaXMuc3RhdGUgIT09IExvY2FsUmVjb3JkZXJTdGF0ZS5GSU5JU0hFRCkge1xuICAgICAgICAgICAgdGhyb3cgKEVycm9yKCdDYWxsIFxcJ0xvY2FsUmVjb3JkLnN0b3AoKVxcJyBiZWZvcmUgZ2V0dGluZyBCbG9iIGZpbGUnKSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5ibG9iO1xuICAgICAgICB9XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBVcGxvYWRzIHRoZSByZWNvcmRlZCB2aWRlbyBhcyBhIGJpbmFyeSBmaWxlIHBlcmZvcm1pbmcgYW4gSFRUUC9QT1NUIG9wZXJhdGlvbiB0byBVUkwgYGVuZHBvaW50YC4gW1tzdGF0ZV1dIHByb3BlcnR5IG11c3QgYmUgYEZJTklTSEVEYC4gT3B0aW9uYWwgSFRUUCBoZWFkZXJzIGNhbiBiZSBwYXNzZWQgYXMgc2Vjb25kIHBhcmFtZXRlci4gRm9yIGV4YW1wbGU6XG4gICAgICogYGBgXG4gICAgICogdmFyIGhlYWRlcnMgPSB7XG4gICAgICogIFwiQ29va2llXCI6IFwiJFZlcnNpb249MTsgU2tpbj1uZXc7XCIsXG4gICAgICogIFwiQXV0aG9yaXphdGlvblwiOlwiQmFzaWMgUVd4aFpHcGJqcHVJSE5sY3RaUT09XCJcbiAgICAgKiB9XG4gICAgICogYGBgXG4gICAgICogQHJldHVybnMgQSBQcm9taXNlICh0byB3aGljaCB5b3UgY2FuIG9wdGlvbmFsbHkgc3Vic2NyaWJlIHRvKSB0aGF0IGlzIHJlc29sdmVkIHdpdGggdGhlIGBodHRwLnJlc3BvbnNlVGV4dGAgZnJvbSBzZXJ2ZXIgaWYgdGhlIG9wZXJhdGlvbiB3YXMgc3VjY2Vzc2Z1bCBhbmQgcmVqZWN0ZWQgd2l0aCB0aGUgZmFpbGVkIGBodHRwLnN0YXR1c2AgaWYgbm90XG4gICAgICovXG4gICAgdXBsb2FkQXNCaW5hcnkoZW5kcG9pbnQ6IHN0cmluZywgaGVhZGVycz86IGFueSk6IFByb21pc2U8YW55PiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICBpZiAodGhpcy5zdGF0ZSAhPT0gTG9jYWxSZWNvcmRlclN0YXRlLkZJTklTSEVEKSB7XG4gICAgICAgICAgICAgICAgcmVqZWN0KEVycm9yKCdcXCdMb2NhbFJlY29yZC51cGxvYWRBc0JpbmFyeSgpXFwnIG5lZWRzIFxcJ0xvY2FsUmVjb3JkLnN0YXRlXFwnIHRvIGJlIFxcJ0ZJTklTSEVEXFwnIChjdXJyZW50IHZhbHVlOiBcXCcnICsgdGhpcy5zdGF0ZSArICdcXCcpLiBDYWxsIFxcJ0xvY2FsUmVjb3JkZXIuc3RvcCgpXFwnIGJlZm9yZScpKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY29uc3QgaHR0cCA9IG5ldyBYTUxIdHRwUmVxdWVzdCgpO1xuICAgICAgICAgICAgICAgIGh0dHAub3BlbignUE9TVCcsIGVuZHBvaW50LCB0cnVlKTtcblxuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgaGVhZGVycyA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgICAgICAgICAgICAgZm9yIChjb25zdCBrZXkgb2YgT2JqZWN0LmtleXMoaGVhZGVycykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGh0dHAuc2V0UmVxdWVzdEhlYWRlcihrZXksIGhlYWRlcnNba2V5XSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBodHRwLm9ucmVhZHlzdGF0ZWNoYW5nZSA9ICgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGh0dHAucmVhZHlTdGF0ZSA9PT0gNCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGh0dHAuc3RhdHVzLnRvU3RyaW5nKCkuY2hhckF0KDApID09PSAnMicpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBTdWNjZXNzIHJlc3BvbnNlIGZyb20gc2VydmVyIChIVFRQIHN0YXR1cyBzdGFuZGFyZDogMlhYIGlzIHN1Y2Nlc3MpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZShodHRwLnJlc3BvbnNlVGV4dCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChodHRwLnN0YXR1cyk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIGh0dHAuc2VuZCh0aGlzLmJsb2IpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFVwbG9hZHMgdGhlIHJlY29yZGVkIHZpZGVvIGFzIGEgbXVsdGlwYXJ0IGZpbGUgcGVyZm9ybWluZyBhbiBIVFRQL1BPU1Qgb3BlcmF0aW9uIHRvIFVSTCBgZW5kcG9pbnRgLiBbW3N0YXRlXV0gcHJvcGVydHkgbXVzdCBiZSBgRklOSVNIRURgLiBPcHRpb25hbCBIVFRQIGhlYWRlcnMgY2FuIGJlIHBhc3NlZCBhcyBzZWNvbmQgcGFyYW1ldGVyLiBGb3IgZXhhbXBsZTpcbiAgICAgKiBgYGBcbiAgICAgKiB2YXIgaGVhZGVycyA9IHtcbiAgICAgKiAgXCJDb29raWVcIjogXCIkVmVyc2lvbj0xOyBTa2luPW5ldztcIixcbiAgICAgKiAgXCJBdXRob3JpemF0aW9uXCI6XCJCYXNpYyBRV3hoWkdwYmpwdUlITmxjdFpRPT1cIlxuICAgICAqIH1cbiAgICAgKiBgYGBcbiAgICAgKiBAcmV0dXJucyBBIFByb21pc2UgKHRvIHdoaWNoIHlvdSBjYW4gb3B0aW9uYWxseSBzdWJzY3JpYmUgdG8pIHRoYXQgaXMgcmVzb2x2ZWQgd2l0aCB0aGUgYGh0dHAucmVzcG9uc2VUZXh0YCBmcm9tIHNlcnZlciBpZiB0aGUgb3BlcmF0aW9uIHdhcyBzdWNjZXNzZnVsIGFuZCByZWplY3RlZCB3aXRoIHRoZSBmYWlsZWQgYGh0dHAuc3RhdHVzYCBpZiBub3Q6XG4gICAgICovXG4gICAgdXBsb2FkQXNNdWx0aXBhcnRmaWxlKGVuZHBvaW50OiBzdHJpbmcsIGhlYWRlcnM/OiBhbnkpOiBQcm9taXNlPGFueT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgaWYgKHRoaXMuc3RhdGUgIT09IExvY2FsUmVjb3JkZXJTdGF0ZS5GSU5JU0hFRCkge1xuICAgICAgICAgICAgICAgIHJlamVjdChFcnJvcignXFwnTG9jYWxSZWNvcmQudXBsb2FkQXNNdWx0aXBhcnRmaWxlKClcXCcgbmVlZHMgXFwnTG9jYWxSZWNvcmQuc3RhdGVcXCcgdG8gYmUgXFwnRklOSVNIRURcXCcgKGN1cnJlbnQgdmFsdWU6IFxcJycgKyB0aGlzLnN0YXRlICsgJ1xcJykuIENhbGwgXFwnTG9jYWxSZWNvcmRlci5zdG9wKClcXCcgYmVmb3JlJykpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBjb25zdCBodHRwID0gbmV3IFhNTEh0dHBSZXF1ZXN0KCk7XG4gICAgICAgICAgICAgICAgaHR0cC5vcGVuKCdQT1NUJywgZW5kcG9pbnQsIHRydWUpO1xuXG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBoZWFkZXJzID09PSAnb2JqZWN0Jykge1xuICAgICAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IGtleSBvZiBPYmplY3Qua2V5cyhoZWFkZXJzKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaHR0cC5zZXRSZXF1ZXN0SGVhZGVyKGtleSwgaGVhZGVyc1trZXldKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGNvbnN0IHNlbmRhYmxlID0gbmV3IEZvcm1EYXRhKCk7XG4gICAgICAgICAgICAgICAgc2VuZGFibGUuYXBwZW5kKCdmaWxlJywgdGhpcy5ibG9iLCB0aGlzLmlkICsgJy53ZWJtJyk7XG5cbiAgICAgICAgICAgICAgICBodHRwLm9ucmVhZHlzdGF0ZWNoYW5nZSA9ICgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGh0dHAucmVhZHlTdGF0ZSA9PT0gNCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGh0dHAuc3RhdHVzLnRvU3RyaW5nKCkuY2hhckF0KDApID09PSAnMicpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBTdWNjZXNzIHJlc3BvbnNlIGZyb20gc2VydmVyIChIVFRQIHN0YXR1cyBzdGFuZGFyZDogMlhYIGlzIHN1Y2Nlc3MpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZShodHRwLnJlc3BvbnNlVGV4dCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChodHRwLnN0YXR1cyk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICAgICAgaHR0cC5zZW5kKHNlbmRhYmxlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG5cbiAgICAvKiBQcml2YXRlIG1ldGhvZHMgKi9cblxuICAgIHByaXZhdGUgb25TdG9wRGVmYXVsdCgpOiB2b2lkIHtcbiAgICAgICAgY29uc29sZS5sb2coJ01lZGlhUmVjb3JkZXIgc3RvcHBlZCAgKHN0YXRlPScgKyB0aGlzLm1lZGlhUmVjb3JkZXIuc3RhdGUgKyAnKScpO1xuXG4gICAgICAgIHRoaXMuYmxvYiA9IG5ldyBCbG9iKHRoaXMuY2h1bmtzLCB7IHR5cGU6ICd2aWRlby93ZWJtJyB9KTtcbiAgICAgICAgdGhpcy5jaHVua3MgPSBbXTtcblxuICAgICAgICB0aGlzLnZpZGVvUHJldmlld1NyYyA9IHdpbmRvdy5VUkwuY3JlYXRlT2JqZWN0VVJMKHRoaXMuYmxvYik7XG5cbiAgICAgICAgdGhpcy5zdGF0ZSA9IExvY2FsUmVjb3JkZXJTdGF0ZS5GSU5JU0hFRDtcbiAgICB9XG5cbn1cbiIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTctMjAxOCBPcGVuVmlkdSAoaHR0cHM6Ly9vcGVudmlkdS5pby8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuaW1wb3J0IHsgTG9jYWxSZWNvcmRlciB9IGZyb20gJy4vTG9jYWxSZWNvcmRlcic7XG5pbXBvcnQgeyBQdWJsaXNoZXIgfSBmcm9tICcuL1B1Ymxpc2hlcic7XG5pbXBvcnQgeyBTZXNzaW9uIH0gZnJvbSAnLi9TZXNzaW9uJztcbmltcG9ydCB7IFN0cmVhbSB9IGZyb20gJy4vU3RyZWFtJztcbmltcG9ydCB7IFN0cmVhbVByb3BlcnR5Q2hhbmdlZEV2ZW50IH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvU3RyZWFtUHJvcGVydHlDaGFuZ2VkRXZlbnQnO1xuaW1wb3J0IHsgRGV2aWNlIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9JbnRlcmZhY2VzL1B1YmxpYy9EZXZpY2UnO1xuaW1wb3J0IHsgT3BlblZpZHVBZHZhbmNlZENvbmZpZ3VyYXRpb24gfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHVibGljL09wZW5WaWR1QWR2YW5jZWRDb25maWd1cmF0aW9uJztcbmltcG9ydCB7IFB1Ymxpc2hlclByb3BlcnRpZXMgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHVibGljL1B1Ymxpc2hlclByb3BlcnRpZXMnO1xuaW1wb3J0IHsgT3BlblZpZHVFcnJvciwgT3BlblZpZHVFcnJvck5hbWUgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0VudW1zL09wZW5WaWR1RXJyb3InO1xuaW1wb3J0IHsgVmlkZW9JbnNlcnRNb2RlIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FbnVtcy9WaWRlb0luc2VydE1vZGUnO1xuXG5pbXBvcnQgKiBhcyBzY3JlZW5TaGFyaW5nQXV0byBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL1NjcmVlblNoYXJpbmcvU2NyZWVuLUNhcHR1cmluZy1BdXRvJztcbmltcG9ydCAqIGFzIHNjcmVlblNoYXJpbmcgZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9TY3JlZW5TaGFyaW5nL1NjcmVlbi1DYXB0dXJpbmcnO1xuXG5pbXBvcnQgUnBjQnVpbGRlciA9IHJlcXVpcmUoJy4uL09wZW5WaWR1SW50ZXJuYWwvS3VyZW50b1V0aWxzL2t1cmVudG8tanNvbnJwYycpO1xuaW1wb3J0IHBsYXRmb3JtID0gcmVxdWlyZSgncGxhdGZvcm0nKTtcblxuXG4vKipcbiAqIEVudHJ5cG9pbnQgb2YgT3BlblZpZHUgQnJvd3NlciBsaWJyYXJ5LlxuICogVXNlIGl0IHRvIGluaXRpYWxpemUgb2JqZWN0cyBvZiB0eXBlIFtbU2Vzc2lvbl1dLCBbW1B1Ymxpc2hlcl1dIGFuZCBbW0xvY2FsUmVjb3JkZXJdXVxuICovXG5leHBvcnQgY2xhc3MgT3BlblZpZHUge1xuXG4gIHByaXZhdGUganNvblJwY0NsaWVudDogYW55O1xuXG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICBzZXNzaW9uOiBTZXNzaW9uO1xuICAvKipcbiAgICogQGhpZGRlblxuICAgKi9cbiAgcHVibGlzaGVyczogUHVibGlzaGVyW10gPSBbXTtcbiAgLyoqXG4gICAqIEBoaWRkZW5cbiAgICovXG4gIHdzVXJpOiBzdHJpbmc7XG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICBzZWNyZXQgPSAnJztcbiAgLyoqXG4gICAqIEBoaWRkZW5cbiAgICovXG4gIHJlY29yZGVyID0gZmFsc2U7XG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICBpY2VTZXJ2ZXJzOiBSVENJY2VTZXJ2ZXJbXTtcbiAgLyoqXG4gICAqIEBoaWRkZW5cbiAgICovXG4gIHJvbGU6IHN0cmluZztcbiAgLyoqXG4gICAqIEBoaWRkZW5cbiAgICovXG4gIGFkdmFuY2VkQ29uZmlndXJhdGlvbjogT3BlblZpZHVBZHZhbmNlZENvbmZpZ3VyYXRpb24gPSB7fTtcblxuICBjb25zdHJ1Y3RvcigpIHtcbiAgICBjb25zb2xlLmluZm8oXCInT3BlblZpZHUnIGluaXRpYWxpemVkXCIpO1xuXG4gICAgaWYgKHBsYXRmb3JtLm5hbWUhIS50b0xvd2VyQ2FzZSgpLmluZGV4T2YoJ21vYmlsZScpICE9PSAtMSkge1xuICAgICAgLy8gTGlzdGVuIHRvIG9yaWVudGF0aW9uY2hhbmdlIG9ubHkgb24gbW9iaWxlIGJyb3dzZXJzXG4gICAgICAoPGFueT53aW5kb3cpLm9ub3JpZW50YXRpb25jaGFuZ2UgPSAoKSA9PiB7XG4gICAgICAgIHRoaXMucHVibGlzaGVycy5mb3JFYWNoKHB1Ymxpc2hlciA9PiB7XG4gICAgICAgICAgaWYgKCEhcHVibGlzaGVyLnN0cmVhbSAmJiAhIXB1Ymxpc2hlci5zdHJlYW0uaGFzVmlkZW8gJiYgISFwdWJsaXNoZXIuc3RyZWFtLnN0cmVhbU1hbmFnZXIudmlkZW9zWzBdKSB7XG5cbiAgICAgICAgICAgIGxldCBhdHRlbXB0cyA9IDA7XG5cbiAgICAgICAgICAgIGNvbnN0IG9sZFdpZHRoID0gcHVibGlzaGVyLnN0cmVhbS52aWRlb0RpbWVuc2lvbnMud2lkdGg7XG4gICAgICAgICAgICBjb25zdCBvbGRIZWlnaHQgPSBwdWJsaXNoZXIuc3RyZWFtLnZpZGVvRGltZW5zaW9ucy5oZWlnaHQ7XG4gICAgICAgICAgICAvLyBOZXcgcmVzb2x1dGlvbiBnb3QgZnJvbSBkaWZmZXJlbnQgcGxhY2VzIGZvciBDaHJvbWUgYW5kIEZpcmVmb3guIENocm9tZSBuZWVkcyBhIHZpZGVvV2lkdGggYW5kIHZpZGVvSGVpZ2h0IG9mIGEgdmlkZW9FbGVtZW50LlxuICAgICAgICAgICAgLy8gRmlyZWZveCBuZWVkcyBnZXRTZXR0aW5ncyBmcm9tIHRoZSB2aWRlb1RyYWNrXG4gICAgICAgICAgICBsZXQgZmlyZWZveFNldHRpbmdzID0gcHVibGlzaGVyLnN0cmVhbS5nZXRNZWRpYVN0cmVhbSgpLmdldFZpZGVvVHJhY2tzKClbMF0uZ2V0U2V0dGluZ3MoKTtcbiAgICAgICAgICAgIGxldCBuZXdXaWR0aCA9IChwbGF0Zm9ybS5uYW1lISEudG9Mb3dlckNhc2UoKS5pbmRleE9mKCdmaXJlZm94JykgIT09IC0xKSA/IGZpcmVmb3hTZXR0aW5ncy53aWR0aCA6IHB1Ymxpc2hlci52aWRlb1JlZmVyZW5jZS52aWRlb1dpZHRoO1xuICAgICAgICAgICAgbGV0IG5ld0hlaWdodCA9IChwbGF0Zm9ybS5uYW1lISEudG9Mb3dlckNhc2UoKS5pbmRleE9mKCdmaXJlZm94JykgIT09IC0xKSA/IGZpcmVmb3hTZXR0aW5ncy5oZWlnaHQgOiBwdWJsaXNoZXIudmlkZW9SZWZlcmVuY2UudmlkZW9IZWlnaHQ7XG5cbiAgICAgICAgICAgIGNvbnN0IHJlcGVhdFVudGlsQ2hhbmdlID0gc2V0SW50ZXJ2YWwoKCkgPT4ge1xuICAgICAgICAgICAgICBmaXJlZm94U2V0dGluZ3MgPSBwdWJsaXNoZXIuc3RyZWFtLmdldE1lZGlhU3RyZWFtKCkuZ2V0VmlkZW9UcmFja3MoKVswXS5nZXRTZXR0aW5ncygpO1xuICAgICAgICAgICAgICBuZXdXaWR0aCA9IChwbGF0Zm9ybS5uYW1lISEudG9Mb3dlckNhc2UoKS5pbmRleE9mKCdmaXJlZm94JykgIT09IC0xKSA/IGZpcmVmb3hTZXR0aW5ncy53aWR0aCA6IHB1Ymxpc2hlci52aWRlb1JlZmVyZW5jZS52aWRlb1dpZHRoO1xuICAgICAgICAgICAgICBuZXdIZWlnaHQgPSAocGxhdGZvcm0ubmFtZSEhLnRvTG93ZXJDYXNlKCkuaW5kZXhPZignZmlyZWZveCcpICE9PSAtMSkgPyBmaXJlZm94U2V0dGluZ3MuaGVpZ2h0IDogcHVibGlzaGVyLnZpZGVvUmVmZXJlbmNlLnZpZGVvSGVpZ2h0O1xuICAgICAgICAgICAgICBzZW5kU3RyZWFtUHJvcGVydHlDaGFuZ2VkRXZlbnQob2xkV2lkdGgsIG9sZEhlaWdodCwgbmV3V2lkdGgsIG5ld0hlaWdodCk7XG4gICAgICAgICAgICB9LCAxMDApO1xuXG4gICAgICAgICAgICBjb25zdCBzZW5kU3RyZWFtUHJvcGVydHlDaGFuZ2VkRXZlbnQgPSAob2xkV2lkdGgsIG9sZEhlaWdodCwgbmV3V2lkdGgsIG5ld0hlaWdodCkgPT4ge1xuICAgICAgICAgICAgICBhdHRlbXB0cysrO1xuICAgICAgICAgICAgICBpZiAoYXR0ZW1wdHMgPiA0KSB7XG4gICAgICAgICAgICAgICAgY2xlYXJUaW1lb3V0KHJlcGVhdFVudGlsQ2hhbmdlKTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICBpZiAobmV3V2lkdGggIT09IG9sZFdpZHRoIHx8IG5ld0hlaWdodCAhPT0gb2xkSGVpZ2h0KSB7XG4gICAgICAgICAgICAgICAgcHVibGlzaGVyLnN0cmVhbS52aWRlb0RpbWVuc2lvbnMgPSB7XG4gICAgICAgICAgICAgICAgICB3aWR0aDogbmV3V2lkdGggfHwgMCxcbiAgICAgICAgICAgICAgICAgIGhlaWdodDogbmV3SGVpZ2h0IHx8IDBcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIHRoaXMuc2VuZFJlcXVlc3QoXG4gICAgICAgICAgICAgICAgICAnc3RyZWFtUHJvcGVydHlDaGFuZ2VkJyxcbiAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgc3RyZWFtSWQ6IHB1Ymxpc2hlci5zdHJlYW0uc3RyZWFtSWQsXG4gICAgICAgICAgICAgICAgICAgIHByb3BlcnR5OiAndmlkZW9EaW1lbnNpb25zJyxcbiAgICAgICAgICAgICAgICAgICAgbmV3VmFsdWU6IEpTT04uc3RyaW5naWZ5KHB1Ymxpc2hlci5zdHJlYW0udmlkZW9EaW1lbnNpb25zKSxcbiAgICAgICAgICAgICAgICAgICAgcmVhc29uOiAnZGV2aWNlUm90YXRlZCdcbiAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAoZXJyb3IsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoXCJFcnJvciBzZW5kaW5nICdzdHJlYW1Qcm9wZXJ0eUNoYW5nZWQnIGV2ZW50XCIsIGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICB0aGlzLnNlc3Npb24uZW1pdEV2ZW50KCdzdHJlYW1Qcm9wZXJ0eUNoYW5nZWQnLCBbbmV3IFN0cmVhbVByb3BlcnR5Q2hhbmdlZEV2ZW50KHRoaXMuc2Vzc2lvbiwgcHVibGlzaGVyLnN0cmVhbSwgJ3ZpZGVvRGltZW5zaW9ucycsIHB1Ymxpc2hlci5zdHJlYW0udmlkZW9EaW1lbnNpb25zLCB7IHdpZHRoOiBvbGRXaWR0aCwgaGVpZ2h0OiBvbGRIZWlnaHQgfSwgJ2RldmljZVJvdGF0ZWQnKV0pO1xuICAgICAgICAgICAgICAgICAgICAgIHB1Ymxpc2hlci5lbWl0RXZlbnQoJ3N0cmVhbVByb3BlcnR5Q2hhbmdlZCcsIFtuZXcgU3RyZWFtUHJvcGVydHlDaGFuZ2VkRXZlbnQocHVibGlzaGVyLCBwdWJsaXNoZXIuc3RyZWFtLCAndmlkZW9EaW1lbnNpb25zJywgcHVibGlzaGVyLnN0cmVhbS52aWRlb0RpbWVuc2lvbnMsIHsgd2lkdGg6IG9sZFdpZHRoLCBoZWlnaHQ6IG9sZEhlaWdodCB9LCAnZGV2aWNlUm90YXRlZCcpXSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIGNsZWFyVGltZW91dChyZXBlYXRVbnRpbENoYW5nZSk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH07XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgIH07XG4gICAgfVxuICB9XG5cblxuICAvKipcbiAgICogUmV0dXJucyBuZXcgc2Vzc2lvblxuICAgKi9cbiAgaW5pdFNlc3Npb24oKTogU2Vzc2lvbiB7XG4gICAgdGhpcy5zZXNzaW9uID0gbmV3IFNlc3Npb24odGhpcyk7XG4gICAgcmV0dXJuIHRoaXMuc2Vzc2lvbjtcbiAgfVxuXG5cbiAgaW5pdFB1Ymxpc2hlcih0YXJnZXRFbGVtZW50OiBzdHJpbmcgfCBIVE1MRWxlbWVudCk6IFB1Ymxpc2hlcjtcbiAgaW5pdFB1Ymxpc2hlcih0YXJnZXRFbGVtZW50OiBzdHJpbmcgfCBIVE1MRWxlbWVudCwgcHJvcGVydGllczogUHVibGlzaGVyUHJvcGVydGllcyk6IFB1Ymxpc2hlcjtcbiAgaW5pdFB1Ymxpc2hlcih0YXJnZXRFbGVtZW50OiBzdHJpbmcgfCBIVE1MRWxlbWVudCwgY29tcGxldGlvbkhhbmRsZXI6IChlcnJvcjogRXJyb3IgfCB1bmRlZmluZWQpID0+IHZvaWQpOiBQdWJsaXNoZXI7XG4gIGluaXRQdWJsaXNoZXIodGFyZ2V0RWxlbWVudDogc3RyaW5nIHwgSFRNTEVsZW1lbnQsIHByb3BlcnRpZXM6IFB1Ymxpc2hlclByb3BlcnRpZXMsIGNvbXBsZXRpb25IYW5kbGVyOiAoZXJyb3I6IEVycm9yIHwgdW5kZWZpbmVkKSA9PiB2b2lkKTogUHVibGlzaGVyO1xuXG4gIC8qKlxuICAgKiBSZXR1cm5zIGEgbmV3IHB1Ymxpc2hlclxuICAgKlxuICAgKiAjIyMjIEV2ZW50cyBkaXNwYXRjaGVkXG4gICAqXG4gICAqIFRoZSBbW1B1Ymxpc2hlcl1dIG9iamVjdCB3aWxsIGRpc3BhdGNoIGFuIGBhY2Nlc3NEaWFsb2dPcGVuZWRgIGV2ZW50LCBvbmx5IGlmIHRoZSBwb3AtdXAgc2hvd24gYnkgdGhlIGJyb3dzZXIgdG8gcmVxdWVzdCBwZXJtaXNzaW9ucyBmb3IgdGhlIGNhbWVyYSBpcyBvcGVuZWQuIFlvdSBjYW4gdXNlIHRoaXMgZXZlbnQgdG8gYWxlcnQgdGhlIHVzZXIgYWJvdXQgZ3JhbnRpbmcgcGVybWlzc2lvbnNcbiAgICogZm9yIHlvdXIgd2Vic2l0ZS4gQW4gYGFjY2Vzc0RpYWxvZ0Nsb3NlZGAgZXZlbnQgd2lsbCBhbHNvIGJlIGRpc3BhdGNoZWQgYWZ0ZXIgdXNlciBjbGlja3Mgb24gXCJBbGxvd1wiIG9yIFwiQmxvY2tcIiBpbiB0aGUgcG9wLXVwLlxuICAgKlxuICAgKiBUaGUgW1tQdWJsaXNoZXJdXSBvYmplY3Qgd2lsbCBkaXNwYXRjaCBhbiBgYWNjZXNzQWxsb3dlZGAgb3IgYGFjY2Vzc0RlbmllZGAgZXZlbnQgb25jZSBpdCBoYXMgYmVlbiBncmFudGVkIGFjY2VzcyB0byB0aGUgcmVxdWVzdGVkIGlucHV0IGRldmljZXMgb3Igbm90LlxuICAgKlxuICAgKiBUaGUgW1tQdWJsaXNoZXJdXSBvYmplY3Qgd2lsbCBkaXNwYXRjaCBhIGB2aWRlb0VsZW1lbnRDcmVhdGVkYCBldmVudCBvbmNlIGEgSFRNTCB2aWRlbyBlbGVtZW50IGhhcyBiZWVuIGFkZGVkIHRvIERPTSAob25seSBpZiB5b3VcbiAgICogW2xldCBPcGVuVmlkdSB0YWtlIGNhcmUgb2YgdGhlIHZpZGVvIHBsYXllcnNdKC9kb2NzL2hvdy1kby1pL21hbmFnZS12aWRlb3MvI2xldC1vcGVudmlkdS10YWtlLWNhcmUtb2YtdGhlLXZpZGVvLXBsYXllcnMpKS4gU2VlIFtbVmlkZW9FbGVtZW50RXZlbnRdXSB0byBsZWFybiBtb3JlLlxuICAgKlxuICAgKiBUaGUgW1tQdWJsaXNoZXJdXSBvYmplY3Qgd2lsbCBkaXNwYXRjaCBhIGBzdHJlYW1QbGF5aW5nYCBldmVudCBvbmNlIHRoZSBsb2NhbCBzdHJlYW1zIHN0YXJ0cyBwbGF5aW5nLiBTZWUgW1tTdHJlYW1NYW5hZ2VyRXZlbnRdXSB0byBsZWFybiBtb3JlLlxuICAgKlxuICAgKiBAcGFyYW0gdGFyZ2V0RWxlbWVudCAgSFRNTCBET00gZWxlbWVudCAob3IgaXRzIGBpZGAgYXR0cmlidXRlKSBpbiB3aGljaCB0aGUgdmlkZW8gZWxlbWVudCBvZiB0aGUgUHVibGlzaGVyIHdpbGwgYmUgaW5zZXJ0ZWQgKHNlZSBbW1B1Ymxpc2hlclByb3BlcnRpZXMuaW5zZXJ0TW9kZV1dKS4gSWYgKm51bGwqIG9yICp1bmRlZmluZWQqIG5vIGRlZmF1bHQgdmlkZW8gd2lsbCBiZSBjcmVhdGVkIGZvciB0aGlzIFB1Ymxpc2hlci5cbiAgICogWW91IGNhbiBhbHdheXMgY2FsbCBtZXRob2QgW1tQdWJsaXNoZXIuYWRkVmlkZW9FbGVtZW50XV0gb3IgW1tQdWJsaXNoZXIuY3JlYXRlVmlkZW9FbGVtZW50XV0gdG8gbWFuYWdlIHRoZSB2aWRlbyBlbGVtZW50cyBvbiB5b3VyIG93biAoc2VlIFtNYW5hZ2UgdmlkZW8gcGxheWVyc10oL2RvY3MvaG93LWRvLWkvbWFuYWdlLXZpZGVvcykgc2VjdGlvbilcbiAgICogQHBhcmFtIGNvbXBsZXRpb25IYW5kbGVyIGBlcnJvcmAgcGFyYW1ldGVyIGlzIG51bGwgaWYgYGluaXRQdWJsaXNoZXJgIHN1Y2NlZWRzLCBhbmQgaXMgZGVmaW5lZCBpZiBpdCBmYWlscy5cbiAgICogICAgICAgICAgICAgICAgICAgICAgICAgIGBjb21wbGV0aW9uSGFuZGxlcmAgZnVuY3Rpb24gaXMgY2FsbGVkIGJlZm9yZSB0aGUgUHVibGlzaGVyIGRpc3BhdGNoZXMgYW4gYGFjY2Vzc0FsbG93ZWRgIG9yIGFuIGBhY2Nlc3NEZW5pZWRgIGV2ZW50XG4gICAqL1xuICBpbml0UHVibGlzaGVyKHRhcmdldEVsZW1lbnQ6IHN0cmluZyB8IEhUTUxFbGVtZW50LCBwYXJhbTI/LCBwYXJhbTM/KTogUHVibGlzaGVyIHtcblxuICAgIGxldCBwcm9wZXJ0aWVzOiBQdWJsaXNoZXJQcm9wZXJ0aWVzO1xuXG4gICAgaWYgKCEhcGFyYW0yICYmICh0eXBlb2YgcGFyYW0yICE9PSAnZnVuY3Rpb24nKSkge1xuXG4gICAgICAvLyBNYXRjaGVzICdpbml0UHVibGlzaGVyKHRhcmdldEVsZW1lbnQsIHByb3BlcnRpZXMpJyBvciAnaW5pdFB1Ymxpc2hlcih0YXJnZXRFbGVtZW50LCBwcm9wZXJ0aWVzLCBjb21wbGV0aW9uSGFuZGxlciknXG5cbiAgICAgIHByb3BlcnRpZXMgPSAoPFB1Ymxpc2hlclByb3BlcnRpZXM+cGFyYW0yKTtcblxuICAgICAgcHJvcGVydGllcyA9IHtcbiAgICAgICAgYXVkaW9Tb3VyY2U6ICh0eXBlb2YgcHJvcGVydGllcy5hdWRpb1NvdXJjZSAhPT0gJ3VuZGVmaW5lZCcpID8gcHJvcGVydGllcy5hdWRpb1NvdXJjZSA6IHVuZGVmaW5lZCxcbiAgICAgICAgZnJhbWVSYXRlOiB0aGlzLmlzTWVkaWFTdHJlYW1UcmFjayhwcm9wZXJ0aWVzLnZpZGVvU291cmNlKSA/IHVuZGVmaW5lZCA6ICgodHlwZW9mIHByb3BlcnRpZXMuZnJhbWVSYXRlICE9PSAndW5kZWZpbmVkJykgPyBwcm9wZXJ0aWVzLmZyYW1lUmF0ZSA6IHVuZGVmaW5lZCksXG4gICAgICAgIGluc2VydE1vZGU6ICh0eXBlb2YgcHJvcGVydGllcy5pbnNlcnRNb2RlICE9PSAndW5kZWZpbmVkJykgPyAoKHR5cGVvZiBwcm9wZXJ0aWVzLmluc2VydE1vZGUgPT09ICdzdHJpbmcnKSA/IFZpZGVvSW5zZXJ0TW9kZVtwcm9wZXJ0aWVzLmluc2VydE1vZGVdIDogcHJvcGVydGllcy5pbnNlcnRNb2RlKSA6IFZpZGVvSW5zZXJ0TW9kZS5BUFBFTkQsXG4gICAgICAgIG1pcnJvcjogKHR5cGVvZiBwcm9wZXJ0aWVzLm1pcnJvciAhPT0gJ3VuZGVmaW5lZCcpID8gcHJvcGVydGllcy5taXJyb3IgOiB0cnVlLFxuICAgICAgICBwdWJsaXNoQXVkaW86ICh0eXBlb2YgcHJvcGVydGllcy5wdWJsaXNoQXVkaW8gIT09ICd1bmRlZmluZWQnKSA/IHByb3BlcnRpZXMucHVibGlzaEF1ZGlvIDogdHJ1ZSxcbiAgICAgICAgcHVibGlzaFZpZGVvOiAodHlwZW9mIHByb3BlcnRpZXMucHVibGlzaFZpZGVvICE9PSAndW5kZWZpbmVkJykgPyBwcm9wZXJ0aWVzLnB1Ymxpc2hWaWRlbyA6IHRydWUsXG4gICAgICAgIHJlc29sdXRpb246IHRoaXMuaXNNZWRpYVN0cmVhbVRyYWNrKHByb3BlcnRpZXMudmlkZW9Tb3VyY2UpID8gdW5kZWZpbmVkIDogKCh0eXBlb2YgcHJvcGVydGllcy5yZXNvbHV0aW9uICE9PSAndW5kZWZpbmVkJykgPyBwcm9wZXJ0aWVzLnJlc29sdXRpb24gOiAnNjQweDQ4MCcpLFxuICAgICAgICB2aWRlb1NvdXJjZTogKHR5cGVvZiBwcm9wZXJ0aWVzLnZpZGVvU291cmNlICE9PSAndW5kZWZpbmVkJykgPyBwcm9wZXJ0aWVzLnZpZGVvU291cmNlIDogdW5kZWZpbmVkXG4gICAgICB9O1xuICAgIH0gZWxzZSB7XG5cbiAgICAgIC8vIE1hdGNoZXMgJ2luaXRQdWJsaXNoZXIodGFyZ2V0RWxlbWVudCknIG9yICdpbml0UHVibGlzaGVyKHRhcmdldEVsZW1lbnQsIGNvbXBsZXRpb25IYW5kbGVyKSdcblxuICAgICAgcHJvcGVydGllcyA9IHtcbiAgICAgICAgaW5zZXJ0TW9kZTogVmlkZW9JbnNlcnRNb2RlLkFQUEVORCxcbiAgICAgICAgbWlycm9yOiB0cnVlLFxuICAgICAgICBwdWJsaXNoQXVkaW86IHRydWUsXG4gICAgICAgIHB1Ymxpc2hWaWRlbzogdHJ1ZSxcbiAgICAgICAgcmVzb2x1dGlvbjogJzY0MHg0ODAnXG4gICAgICB9O1xuICAgIH1cblxuICAgIGNvbnN0IHB1Ymxpc2hlcjogUHVibGlzaGVyID0gbmV3IFB1Ymxpc2hlcih0YXJnZXRFbGVtZW50LCBwcm9wZXJ0aWVzLCB0aGlzKTtcblxuICAgIGxldCBjb21wbGV0aW9uSGFuZGxlcjogKGVycm9yOiBFcnJvciB8IHVuZGVmaW5lZCkgPT4gdm9pZDtcbiAgICBpZiAoISFwYXJhbTIgJiYgKHR5cGVvZiBwYXJhbTIgPT09ICdmdW5jdGlvbicpKSB7XG4gICAgICBjb21wbGV0aW9uSGFuZGxlciA9IHBhcmFtMjtcbiAgICB9IGVsc2UgaWYgKCEhcGFyYW0zKSB7XG4gICAgICBjb21wbGV0aW9uSGFuZGxlciA9IHBhcmFtMztcbiAgICB9XG5cbiAgICBwdWJsaXNoZXIuaW5pdGlhbGl6ZSgpXG4gICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgIGlmIChjb21wbGV0aW9uSGFuZGxlciAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgY29tcGxldGlvbkhhbmRsZXIodW5kZWZpbmVkKTtcbiAgICAgICAgfVxuICAgICAgICBwdWJsaXNoZXIuZW1pdEV2ZW50KCdhY2Nlc3NBbGxvd2VkJywgW10pO1xuICAgICAgfSkuY2F0Y2goKGVycm9yKSA9PiB7XG4gICAgICAgIGlmIChjb21wbGV0aW9uSGFuZGxlciAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgY29tcGxldGlvbkhhbmRsZXIoZXJyb3IpO1xuICAgICAgICB9XG4gICAgICAgIHB1Ymxpc2hlci5lbWl0RXZlbnQoJ2FjY2Vzc0RlbmllZCcsIFtdKTtcbiAgICAgIH0pO1xuXG4gICAgdGhpcy5wdWJsaXNoZXJzLnB1c2gocHVibGlzaGVyKTtcbiAgICByZXR1cm4gcHVibGlzaGVyO1xuICB9XG5cblxuICAvKipcbiAgICogUHJvbWlzaWZpZWQgdmVyc2lvbiBvZiBbW09wZW5WaWR1LmluaXRQdWJsaXNoZXJdXVxuICAgKlxuICAgKiA+IFdBUk5JTkc6IGV2ZW50cyBgYWNjZXNzRGlhbG9nT3BlbmVkYCBhbmQgYGFjY2Vzc0RpYWxvZ0Nsb3NlZGAgd2lsbCBub3QgYmUgZGlzcGF0Y2hlZCBpZiB1c2luZyB0aGlzIG1ldGhvZCBpbnN0ZWFkIG9mIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dXG4gICAqL1xuICBpbml0UHVibGlzaGVyQXN5bmModGFyZ2V0RWxlbWVudDogc3RyaW5nIHwgSFRNTEVsZW1lbnQpOiBQcm9taXNlPFB1Ymxpc2hlcj47XG4gIGluaXRQdWJsaXNoZXJBc3luYyh0YXJnZXRFbGVtZW50OiBzdHJpbmcgfCBIVE1MRWxlbWVudCwgcHJvcGVydGllczogUHVibGlzaGVyUHJvcGVydGllcyk6IFByb21pc2U8UHVibGlzaGVyPjtcblxuICBpbml0UHVibGlzaGVyQXN5bmModGFyZ2V0RWxlbWVudDogc3RyaW5nIHwgSFRNTEVsZW1lbnQsIHByb3BlcnRpZXM/OiBQdWJsaXNoZXJQcm9wZXJ0aWVzKTogUHJvbWlzZTxQdWJsaXNoZXI+IHtcbiAgICByZXR1cm4gbmV3IFByb21pc2U8UHVibGlzaGVyPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG5cbiAgICAgIGxldCBwdWJsaXNoZXI6IFB1Ymxpc2hlcjtcblxuICAgICAgY29uc3QgY2FsbGJhY2sgPSAoZXJyb3I6IEVycm9yKSA9PiB7XG4gICAgICAgIGlmICghIWVycm9yKSB7XG4gICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICByZXNvbHZlKHB1Ymxpc2hlcik7XG4gICAgICAgIH1cbiAgICAgIH07XG5cbiAgICAgIGlmICghIXByb3BlcnRpZXMpIHtcbiAgICAgICAgcHVibGlzaGVyID0gdGhpcy5pbml0UHVibGlzaGVyKHRhcmdldEVsZW1lbnQsIHByb3BlcnRpZXMsIGNhbGxiYWNrKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHB1Ymxpc2hlciA9IHRoaXMuaW5pdFB1Ymxpc2hlcih0YXJnZXRFbGVtZW50LCBjYWxsYmFjayk7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIGEgbmV3IGxvY2FsIHJlY29yZGVyIGZvciByZWNvcmRpbmcgc3RyZWFtcyBzdHJhaWdodCBhd2F5IGZyb20gdGhlIGJyb3dzZXJcbiAgICogQHBhcmFtIHN0cmVhbSAgU3RyZWFtIHRvIHJlY29yZFxuICAgKi9cbiAgaW5pdExvY2FsUmVjb3JkZXIoc3RyZWFtOiBTdHJlYW0pOiBMb2NhbFJlY29yZGVyIHtcbiAgICByZXR1cm4gbmV3IExvY2FsUmVjb3JkZXIoc3RyZWFtKTtcbiAgfVxuXG5cbiAgLyoqXG4gICAqIENoZWNrcyBpZiB0aGUgYnJvd3NlciBzdXBwb3J0cyBPcGVuVmlkdVxuICAgKiBAcmV0dXJucyAxIGlmIHRoZSBicm93c2VyIHN1cHBvcnRzIE9wZW5WaWR1LCAwIG90aGVyd2lzZVxuICAgKi9cbiAgY2hlY2tTeXN0ZW1SZXF1aXJlbWVudHMoKTogbnVtYmVyIHtcbiAgICBjb25zdCBicm93c2VyID0gcGxhdGZvcm0ubmFtZTtcbiAgICBjb25zdCB2ZXJzaW9uID0gcGxhdGZvcm0udmVyc2lvbjtcblxuICAgIGlmICgoYnJvd3NlciAhPT0gJ0Nocm9tZScpICYmIChicm93c2VyICE9PSAnQ2hyb21lIE1vYmlsZScpICYmXG4gICAgICAoYnJvd3NlciAhPT0gJ0ZpcmVmb3gnKSAmJiAoYnJvd3NlciAhPT0gJ0ZpcmVmb3ggTW9iaWxlJykgJiYgKGJyb3dzZXIgIT09ICdGaXJlZm94IGZvciBpT1MnKSAmJlxuICAgICAgKGJyb3dzZXIgIT09ICdPcGVyYScpICYmIChicm93c2VyICE9PSAnT3BlcmEgTW9iaWxlJykgJiZcbiAgICAgIChicm93c2VyICE9PSAnU2FmYXJpJykpIHtcbiAgICAgIHJldHVybiAwO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gMTtcbiAgICB9XG4gIH1cblxuXG4gIC8qKlxuICAgKiBDb2xsZWN0cyBpbmZvcm1hdGlvbiBhYm91dCB0aGUgbWVkaWEgaW5wdXQgZGV2aWNlcyBhdmFpbGFibGUgb24gdGhlIHN5c3RlbS4gWW91IGNhbiBwYXNzIHByb3BlcnR5IGBkZXZpY2VJZGAgb2YgYSBbW0RldmljZV1dIG9iamVjdCBhcyB2YWx1ZSBvZiBgYXVkaW9Tb3VyY2VgIG9yIGB2aWRlb1NvdXJjZWAgcHJvcGVydGllcyBpbiBbW2luaXRQdWJsaXNoZXJdXSBtZXRob2RcbiAgICovXG4gIGdldERldmljZXMoKTogUHJvbWlzZTxEZXZpY2VbXT4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZTxEZXZpY2VbXT4oKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgbmF2aWdhdG9yLm1lZGlhRGV2aWNlcy5lbnVtZXJhdGVEZXZpY2VzKCkudGhlbigoZGV2aWNlSW5mb3MpID0+IHtcbiAgICAgICAgY29uc3QgZGV2aWNlczogRGV2aWNlW10gPSBbXTtcbiAgICAgICAgZGV2aWNlSW5mb3MuZm9yRWFjaChkZXZpY2VJbmZvID0+IHtcbiAgICAgICAgICBpZiAoZGV2aWNlSW5mby5raW5kID09PSAnYXVkaW9pbnB1dCcgfHwgZGV2aWNlSW5mby5raW5kID09PSAndmlkZW9pbnB1dCcpIHtcbiAgICAgICAgICAgIGRldmljZXMucHVzaCh7XG4gICAgICAgICAgICAgIGtpbmQ6IGRldmljZUluZm8ua2luZCxcbiAgICAgICAgICAgICAgZGV2aWNlSWQ6IGRldmljZUluZm8uZGV2aWNlSWQsXG4gICAgICAgICAgICAgIGxhYmVsOiBkZXZpY2VJbmZvLmxhYmVsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICByZXNvbHZlKGRldmljZXMpO1xuICAgICAgfSkuY2F0Y2goKGVycm9yKSA9PiB7XG4gICAgICAgIGNvbnNvbGUuZXJyb3IoJ0Vycm9yIGdldHRpbmcgZGV2aWNlcycsIGVycm9yKTtcbiAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9XG5cblxuICAvKipcbiAgICogR2V0IGEgTWVkaWFTdHJlYW0gb2JqZWN0IHRoYXQgeW91IGNhbiBjdXN0b21pemUgYmVmb3JlIGNhbGxpbmcgW1tpbml0UHVibGlzaGVyXV0gKHBhc3MgX01lZGlhU3RyZWFtVHJhY2tfIHByb3BlcnR5IG9mIHRoZSBfTWVkaWFTdHJlYW1fIHZhbHVlIHJlc29sdmVkIGJ5IHRoZSBQcm9taXNlIGFzIGBhdWRpb1NvdXJjZWAgb3IgYHZpZGVvU291cmNlYCBwcm9wZXJ0aWVzIGluIFtbaW5pdFB1Ymxpc2hlcl1dKVxuICAgKlxuICAgKiBQYXJhbWV0ZXIgYG9wdGlvbnNgIGlzIHRoZSBzYW1lIGFzIGluIFtbaW5pdFB1Ymxpc2hlcl1dIHNlY29uZCBwYXJhbWV0ZXIgKG9mIHR5cGUgW1tQdWJsaXNoZXJQcm9wZXJ0aWVzXV0pLCBidXQgb25seSB0aGUgZm9sbG93aW5nIHByb3BlcnRpZXMgd2lsbCBiZSBhcHBsaWVkOiBgYXVkaW9Tb3VyY2VgLCBgdmlkZW9Tb3VyY2VgLCBgZnJhbWVSYXRlYCwgYHJlc29sdXRpb25gXG4gICAqXG4gICAqIFRvIGN1c3RvbWl6ZSB0aGUgUHVibGlzaGVyJ3MgdmlkZW8sIHRoZSBBUEkgZm9yIEhUTUxDYW52YXNFbGVtZW50IGlzIHZlcnkgdXNlZnVsLiBGb3IgZXhhbXBsZSwgdG8gZ2V0IGEgYmxhY2stYW5kLXdoaXRlIHZpZGVvIGF0IDEwIGZwcyBhbmQgSEQgcmVzb2x1dGlvbiB3aXRoIG5vIHNvdW5kOlxuICAgKiBgYGBcbiAgICogdmFyIE9WID0gbmV3IE9wZW5WaWR1KCk7XG4gICAqIHZhciBGUkFNRV9SQVRFID0gMTA7XG4gICAqXG4gICAqIE9WLmdldFVzZXJNZWRpYSh7XG4gICAqICAgIGF1ZGlvU291cmNlOiBmYWxzZTtcbiAgICogICAgdmlkZW9Tb3VyY2U6IHVuZGVmaW5lZCxcbiAgICogICAgcmVzb2x1dGlvbjogJzEyODB4NzIwJyxcbiAgICogICAgZnJhbWVSYXRlOiBGUkFNRV9SQVRFXG4gICAqIH0pXG4gICAqIC50aGVuKG1lZGlhU3RyZWFtID0+IHtcbiAgICpcbiAgICogICAgdmFyIHZpZGVvVHJhY2sgPSBtZWRpYVN0cmVhbS5nZXRWaWRlb1RyYWNrcygpWzBdO1xuICAgKiAgICB2YXIgdmlkZW8gPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCd2aWRlbycpO1xuICAgKiAgICB2aWRlby5zcmNPYmplY3QgPSBuZXcgTWVkaWFTdHJlYW0oW3ZpZGVvVHJhY2tdKTtcbiAgICpcbiAgICogICAgdmFyIGNhbnZhcyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2NhbnZhcycpO1xuICAgKiAgICB2YXIgY3R4ID0gY2FudmFzLmdldENvbnRleHQoJzJkJyk7XG4gICAqICAgIGN0eC5maWx0ZXIgPSAnZ3JheXNjYWxlKDEwMCUpJztcbiAgICpcbiAgICogICAgdmlkZW8uYWRkRXZlbnRMaXN0ZW5lcigncGxheScsICgpID0+IHtcbiAgICogICAgICB2YXIgbG9vcCA9ICgpID0+IHtcbiAgICogICAgICAgIGlmICghdmlkZW8ucGF1c2VkICYmICF2aWRlby5lbmRlZCkge1xuICAgKiAgICAgICAgICBjdHguZHJhd0ltYWdlKHZpZGVvLCAwLCAwLCAzMDAsIDE3MCk7XG4gICAqICAgICAgICAgIHNldFRpbWVvdXQobG9vcCwgMTAwMC8gRlJBTUVfUkFURSk7IC8vIERyYXdpbmcgYXQgMTAgZnBzXG4gICAqICAgICAgICB9XG4gICAqICAgICAgfTtcbiAgICogICAgICBsb29wKCk7XG4gICAqICAgIH0pO1xuICAgKiAgICB2aWRlby5wbGF5KCk7XG4gICAqXG4gICAqICAgIHZhciBncmF5VmlkZW9UcmFjayA9IGNhbnZhcy5jYXB0dXJlU3RyZWFtKEZSQU1FX1JBVEUpLmdldFZpZGVvVHJhY2tzKClbMF07XG4gICAqICAgIHZhciBwdWJsaXNoZXIgPSB0aGlzLk9WLmluaXRQdWJsaXNoZXIoXG4gICAqICAgICAgbXlIdG1sVGFyZ2V0LFxuICAgKiAgICAgIHtcbiAgICogICAgICAgIGF1ZGlvU291cmNlOiBmYWxzZSxcbiAgICogICAgICAgIHZpZGVvU291cmNlOiBncmF5VmlkZW9UcmFja1xuICAgKiAgICAgIH0pO1xuICAgKiB9KTtcbiAgICogYGBgXG4gICAqL1xuICBnZXRVc2VyTWVkaWEob3B0aW9uczogUHVibGlzaGVyUHJvcGVydGllcyk6IFByb21pc2U8TWVkaWFTdHJlYW0+IHtcbiAgICByZXR1cm4gbmV3IFByb21pc2U8TWVkaWFTdHJlYW0+KChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIHRoaXMuZ2VuZXJhdGVNZWRpYUNvbnN0cmFpbnRzKG9wdGlvbnMpXG4gICAgICAgIC50aGVuKGNvbnN0cmFpbnRzID0+IHtcbiAgICAgICAgICBuYXZpZ2F0b3IubWVkaWFEZXZpY2VzLmdldFVzZXJNZWRpYShjb25zdHJhaW50cylcbiAgICAgICAgICAgIC50aGVuKG1lZGlhU3RyZWFtID0+IHtcbiAgICAgICAgICAgICAgcmVzb2x2ZShtZWRpYVN0cmVhbSk7XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICAgICAgbGV0IGVycm9yTmFtZTogT3BlblZpZHVFcnJvck5hbWU7XG4gICAgICAgICAgICAgIGNvbnN0IGVycm9yTWVzc2FnZSA9IGVycm9yLnRvU3RyaW5nKCk7XG4gICAgICAgICAgICAgIGlmICghKG9wdGlvbnMudmlkZW9Tb3VyY2UgPT09ICdzY3JlZW4nKSkge1xuICAgICAgICAgICAgICAgIGVycm9yTmFtZSA9IE9wZW5WaWR1RXJyb3JOYW1lLkRFVklDRV9BQ0NFU1NfREVOSUVEO1xuICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGVycm9yTmFtZSA9IE9wZW5WaWR1RXJyb3JOYW1lLlNDUkVFTl9DQVBUVVJFX0RFTklFRDtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICByZWplY3QobmV3IE9wZW5WaWR1RXJyb3IoZXJyb3JOYW1lLCBlcnJvck1lc3NhZ2UpKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KVxuICAgICAgICAuY2F0Y2goKGVycm9yOiBPcGVuVmlkdUVycm9yKSA9PiB7XG4gICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgfSk7XG4gICAgfSk7XG4gIH1cblxuXG4gIC8qIHRzbGludDpkaXNhYmxlOm5vLWVtcHR5ICovXG4gIC8qKlxuICAgKiBEaXNhYmxlIGFsbCBsb2dnaW5nIGV4Y2VwdCBlcnJvciBsZXZlbFxuICAgKi9cbiAgZW5hYmxlUHJvZE1vZGUoKTogdm9pZCB7XG4gICAgY29uc29sZS5sb2cgPSAoKSA9PiB7IH07XG4gICAgY29uc29sZS5kZWJ1ZyA9ICgpID0+IHsgfTtcbiAgICBjb25zb2xlLmluZm8gPSAoKSA9PiB7IH07XG4gICAgY29uc29sZS53YXJuID0gKCkgPT4geyB9O1xuICB9XG4gIC8qIHRzbGludDplbmFibGU6bm8tZW1wdHkgKi9cblxuXG4gIC8qKlxuICAgKiBTZXQgT3BlblZpZHUgYWR2YW5jZWQgY29uZmlndXJhdGlvbiBvcHRpb25zLiBDdXJyZW50bHkgYGNvbmZpZ3VyYXRpb25gIGlzIGFuIG9iamVjdCB3aXRoIHRoZSBmb2xsb3dpbmcgb3B0aW9uYWwgcHJvcGVydGllcyAoc2VlIFtbT3BlblZpZHVBZHZhbmNlZENvbmZpZ3VyYXRpb25dXSBmb3IgbW9yZSBkZXRhaWxzKTpcbiAgICogLSBgaWNlU2VydmVyc2A6IHNldCBjdXN0b20gU1RVTi9UVVJOIHNlcnZlcnMgdG8gYmUgdXNlZCBieSBPcGVuVmlkdSBCcm93c2VyXG4gICAqIC0gYHNjcmVlblNoYXJlQ2hyb21lRXh0ZW5zaW9uYDogdXJsIHRvIGEgY3VzdG9tIHNjcmVlbiBzaGFyZSBleHRlbnNpb24gZm9yIENocm9tZSB0byBiZSB1c2VkIGluc3RlYWQgb2YgdGhlIGRlZmF1bHQgb25lLCBiYXNlZCBvbiBvdXJzIFtodHRwczovL2dpdGh1Yi5jb20vT3BlblZpZHUvb3BlbnZpZHUtc2NyZWVuLXNoYXJpbmctY2hyb21lLWV4dGVuc2lvbl0oaHR0cHM6Ly9naXRodWIuY29tL09wZW5WaWR1L29wZW52aWR1LXNjcmVlbi1zaGFyaW5nLWNocm9tZS1leHRlbnNpb24pXG4gICAqIC0gYHB1Ymxpc2hlclNwZWFraW5nRXZlbnRzT3B0aW9uc2A6IGN1c3RvbSBjb25maWd1cmF0aW9uIGZvciB0aGUgW1tQdWJsaXNoZXJTcGVha2luZ0V2ZW50XV0gZmVhdHVyZVxuICAgKi9cbiAgc2V0QWR2YW5jZWRDb25maWd1cmF0aW9uKGNvbmZpZ3VyYXRpb246IE9wZW5WaWR1QWR2YW5jZWRDb25maWd1cmF0aW9uKTogdm9pZCB7XG4gICAgdGhpcy5hZHZhbmNlZENvbmZpZ3VyYXRpb24gPSBjb25maWd1cmF0aW9uO1xuICB9XG5cblxuICAvKiBIaWRkZW4gbWV0aG9kcyAqL1xuXG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICBnZW5lcmF0ZU1lZGlhQ29uc3RyYWludHMocHVibGlzaGVyUHJvcGVydGllczogUHVibGlzaGVyUHJvcGVydGllcyk6IFByb21pc2U8TWVkaWFTdHJlYW1Db25zdHJhaW50cz4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZTxNZWRpYVN0cmVhbUNvbnN0cmFpbnRzPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICBsZXQgYXVkaW8sIHZpZGVvO1xuXG4gICAgICBpZiAocHVibGlzaGVyUHJvcGVydGllcy5hdWRpb1NvdXJjZSA9PT0gbnVsbCB8fCBwdWJsaXNoZXJQcm9wZXJ0aWVzLmF1ZGlvU291cmNlID09PSBmYWxzZSkge1xuICAgICAgICBhdWRpbyA9IGZhbHNlO1xuICAgICAgfSBlbHNlIGlmIChwdWJsaXNoZXJQcm9wZXJ0aWVzLmF1ZGlvU291cmNlID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgYXVkaW8gPSB0cnVlO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgYXVkaW8gPSBwdWJsaXNoZXJQcm9wZXJ0aWVzLmF1ZGlvU291cmNlO1xuICAgICAgfVxuXG4gICAgICBpZiAocHVibGlzaGVyUHJvcGVydGllcy52aWRlb1NvdXJjZSA9PT0gbnVsbCB8fCBwdWJsaXNoZXJQcm9wZXJ0aWVzLnZpZGVvU291cmNlID09PSBmYWxzZSkge1xuICAgICAgICB2aWRlbyA9IGZhbHNlO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdmlkZW8gPSB7XG4gICAgICAgICAgaGVpZ2h0OiB7XG4gICAgICAgICAgICBpZGVhbDogNDgwXG4gICAgICAgICAgfSxcbiAgICAgICAgICB3aWR0aDoge1xuICAgICAgICAgICAgaWRlYWw6IDY0MFxuICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgbWVkaWFDb25zdHJhaW50czogTWVkaWFTdHJlYW1Db25zdHJhaW50cyA9IHtcbiAgICAgICAgYXVkaW8sXG4gICAgICAgIHZpZGVvXG4gICAgICB9O1xuXG4gICAgICBpZiAodHlwZW9mIG1lZGlhQ29uc3RyYWludHMuYXVkaW8gPT09ICdzdHJpbmcnKSB7XG4gICAgICAgIG1lZGlhQ29uc3RyYWludHMuYXVkaW8gPSB7IGRldmljZUlkOiB7IGV4YWN0OiBtZWRpYUNvbnN0cmFpbnRzLmF1ZGlvIH0gfTtcbiAgICAgIH1cblxuICAgICAgaWYgKG1lZGlhQ29uc3RyYWludHMudmlkZW8pIHtcblxuICAgICAgICBpZiAoISFwdWJsaXNoZXJQcm9wZXJ0aWVzLnJlc29sdXRpb24pIHtcbiAgICAgICAgICBjb25zdCB3aWR0aEFuZEhlaWdodCA9IHB1Ymxpc2hlclByb3BlcnRpZXMucmVzb2x1dGlvbi50b0xvd2VyQ2FzZSgpLnNwbGl0KCd4Jyk7XG4gICAgICAgICAgY29uc3Qgd2lkdGggPSBOdW1iZXIod2lkdGhBbmRIZWlnaHRbMF0pO1xuICAgICAgICAgIGNvbnN0IGhlaWdodCA9IE51bWJlcih3aWR0aEFuZEhlaWdodFsxXSk7XG4gICAgICAgICAgKG1lZGlhQ29uc3RyYWludHMudmlkZW8gYXMgYW55KS53aWR0aC5pZGVhbCA9IHdpZHRoO1xuICAgICAgICAgIChtZWRpYUNvbnN0cmFpbnRzLnZpZGVvIGFzIGFueSkuaGVpZ2h0LmlkZWFsID0gaGVpZ2h0O1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCEhcHVibGlzaGVyUHJvcGVydGllcy5mcmFtZVJhdGUpIHtcbiAgICAgICAgICAobWVkaWFDb25zdHJhaW50cy52aWRlbyBhcyBhbnkpLmZyYW1lUmF0ZSA9IHsgaWRlYWw6IHB1Ymxpc2hlclByb3BlcnRpZXMuZnJhbWVSYXRlIH07XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoISFwdWJsaXNoZXJQcm9wZXJ0aWVzLnZpZGVvU291cmNlICYmIHR5cGVvZiBwdWJsaXNoZXJQcm9wZXJ0aWVzLnZpZGVvU291cmNlID09PSAnc3RyaW5nJykge1xuXG4gICAgICAgICAgaWYgKHB1Ymxpc2hlclByb3BlcnRpZXMudmlkZW9Tb3VyY2UgPT09ICdzY3JlZW4nKSB7XG5cbiAgICAgICAgICAgIGlmIChwbGF0Zm9ybS5uYW1lICE9PSAnQ2hyb21lJyAmJiBwbGF0Zm9ybS5uYW1lIS5pbmRleE9mKCdGaXJlZm94JykgPT09IC0xKSB7XG4gICAgICAgICAgICAgIGNvbnN0IGVycm9yID0gbmV3IE9wZW5WaWR1RXJyb3IoT3BlblZpZHVFcnJvck5hbWUuU0NSRUVOX1NIQVJJTkdfTk9UX1NVUFBPUlRFRCwgJ1lvdSBjYW4gb25seSBzY3JlZW4gc2hhcmUgaW4gZGVza3RvcCBDaHJvbWUgYW5kIEZpcmVmb3guIERldGVjdGVkIGJyb3dzZXI6ICcgKyBwbGF0Zm9ybS5uYW1lKTtcbiAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihlcnJvcik7XG4gICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICB9IGVsc2Uge1xuXG4gICAgICAgICAgICAgIGlmICghIXRoaXMuYWR2YW5jZWRDb25maWd1cmF0aW9uLnNjcmVlblNoYXJlQ2hyb21lRXh0ZW5zaW9uICYmICEocGxhdGZvcm0ubmFtZSEuaW5kZXhPZignRmlyZWZveCcpICE9PSAtMSkpIHtcblxuICAgICAgICAgICAgICAgIC8vIEN1c3RvbSBzY3JlZW4gc2hhcmluZyBleHRlbnNpb24gZm9yIENocm9tZVxuXG4gICAgICAgICAgICAgICAgc2NyZWVuU2hhcmluZy5nZXRTY3JlZW5Db25zdHJhaW50cygoZXJyb3IsIHNjcmVlbkNvbnN0cmFpbnRzKSA9PiB7XG4gICAgICAgICAgICAgICAgICBpZiAoISFlcnJvciB8fCAhIXNjcmVlbkNvbnN0cmFpbnRzLm1hbmRhdG9yeSAmJiBzY3JlZW5Db25zdHJhaW50cy5tYW5kYXRvcnkuY2hyb21lTWVkaWFTb3VyY2UgPT09ICdzY3JlZW4nKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnJvciA9PT0gJ3Blcm1pc3Npb24tZGVuaWVkJyB8fCBlcnJvciA9PT0gJ1Blcm1pc3Npb25EZW5pZWRFcnJvcicpIHtcbiAgICAgICAgICAgICAgICAgICAgICBjb25zdCBlcnJvciA9IG5ldyBPcGVuVmlkdUVycm9yKE9wZW5WaWR1RXJyb3JOYW1lLlNDUkVFTl9DQVBUVVJFX0RFTklFRCwgJ1lvdSBtdXN0IGFsbG93IGFjY2VzcyB0byBvbmUgd2luZG93IG9mIHlvdXIgZGVza3RvcCcpO1xuICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgY29uc3QgZXh0ZW5zaW9uSWQgPSB0aGlzLmFkdmFuY2VkQ29uZmlndXJhdGlvbi5zY3JlZW5TaGFyZUNocm9tZUV4dGVuc2lvbiEuc3BsaXQoJy8nKS5wb3AoKSEhLnRyaW0oKTtcbiAgICAgICAgICAgICAgICAgICAgICBzY3JlZW5TaGFyaW5nLmdldENocm9tZUV4dGVuc2lvblN0YXR1cyhleHRlbnNpb25JZCwgKHN0YXR1cykgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHN0YXR1cyA9PT0gJ2luc3RhbGxlZC1kaXNhYmxlZCcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZXJyb3IgPSBuZXcgT3BlblZpZHVFcnJvcihPcGVuVmlkdUVycm9yTmFtZS5TQ1JFRU5fRVhURU5TSU9OX0RJU0FCTEVELCAnWW91IG11c3QgZW5hYmxlIHRoZSBzY3JlZW4gZXh0ZW5zaW9uJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHN0YXR1cyA9PT0gJ25vdC1pbnN0YWxsZWQnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGVycm9yID0gbmV3IE9wZW5WaWR1RXJyb3IoT3BlblZpZHVFcnJvck5hbWUuU0NSRUVOX0VYVEVOU0lPTl9OT1RfSU5TVEFMTEVELCAoPHN0cmluZz50aGlzLmFkdmFuY2VkQ29uZmlndXJhdGlvbi5zY3JlZW5TaGFyZUNocm9tZUV4dGVuc2lvbikpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgbWVkaWFDb25zdHJhaW50cy52aWRlbyA9IHNjcmVlbkNvbnN0cmFpbnRzO1xuICAgICAgICAgICAgICAgICAgICByZXNvbHZlKG1lZGlhQ29uc3RyYWludHMpO1xuICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICB9IGVsc2Uge1xuXG4gICAgICAgICAgICAgICAgLy8gRGVmYXVsdCBzY3JlZW4gc2hhcmluZyBleHRlbnNpb24gZm9yIENocm9tZVxuXG4gICAgICAgICAgICAgICAgc2NyZWVuU2hhcmluZ0F1dG8uZ2V0U2NyZWVuSWQoKGVycm9yLCBzb3VyY2VJZCwgc2NyZWVuQ29uc3RyYWludHMpID0+IHtcbiAgICAgICAgICAgICAgICAgIGlmICghIWVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnJvciA9PT0gJ25vdC1pbnN0YWxsZWQnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgY29uc3QgZXh0ZW5zaW9uVXJsID0gISF0aGlzLmFkdmFuY2VkQ29uZmlndXJhdGlvbi5zY3JlZW5TaGFyZUNocm9tZUV4dGVuc2lvbiA/IHRoaXMuYWR2YW5jZWRDb25maWd1cmF0aW9uLnNjcmVlblNoYXJlQ2hyb21lRXh0ZW5zaW9uIDpcbiAgICAgICAgICAgICAgICAgICAgICAgICdodHRwczovL2Nocm9tZS5nb29nbGUuY29tL3dlYnN0b3JlL2RldGFpbC9vcGVudmlkdS1zY3JlZW5zaGFyaW5nL2xmY2dmZXBhZm5vYmRsb2VjY2huZmFjbGliZW5qb2xkJztcbiAgICAgICAgICAgICAgICAgICAgICBjb25zdCBlcnJvciA9IG5ldyBPcGVuVmlkdUVycm9yKE9wZW5WaWR1RXJyb3JOYW1lLlNDUkVFTl9FWFRFTlNJT05fTk9UX0lOU1RBTExFRCwgZXh0ZW5zaW9uVXJsKTtcbiAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGVycm9yID09PSAnaW5zdGFsbGVkLWRpc2FibGVkJykge1xuICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGVycm9yID0gbmV3IE9wZW5WaWR1RXJyb3IoT3BlblZpZHVFcnJvck5hbWUuU0NSRUVOX0VYVEVOU0lPTl9ESVNBQkxFRCwgJ1lvdSBtdXN0IGVuYWJsZSB0aGUgc2NyZWVuIGV4dGVuc2lvbicpO1xuICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoZXJyb3IgPT09ICdwZXJtaXNzaW9uLWRlbmllZCcpIHtcbiAgICAgICAgICAgICAgICAgICAgICBjb25zdCBlcnJvciA9IG5ldyBPcGVuVmlkdUVycm9yKE9wZW5WaWR1RXJyb3JOYW1lLlNDUkVFTl9DQVBUVVJFX0RFTklFRCwgJ1lvdSBtdXN0IGFsbG93IGFjY2VzcyB0byBvbmUgd2luZG93IG9mIHlvdXIgZGVza3RvcCcpO1xuICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIG1lZGlhQ29uc3RyYWludHMudmlkZW8gPSBzY3JlZW5Db25zdHJhaW50cy52aWRlbztcbiAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZShtZWRpYUNvbnN0cmFpbnRzKTtcbiAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgIHB1Ymxpc2hlclByb3BlcnRpZXMudmlkZW9Tb3VyY2UgPSAnc2NyZWVuJztcblxuICAgICAgICAgICAgfVxuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6bm8tc3RyaW5nLWxpdGVyYWxcbiAgICAgICAgICAgIG1lZGlhQ29uc3RyYWludHMudmlkZW9bJ2RldmljZUlkJ10gPSB7IGV4YWN0OiBwdWJsaXNoZXJQcm9wZXJ0aWVzLnZpZGVvU291cmNlIH07XG4gICAgICAgICAgICByZXNvbHZlKG1lZGlhQ29uc3RyYWludHMpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICByZXNvbHZlKG1lZGlhQ29uc3RyYWludHMpO1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXNvbHZlKG1lZGlhQ29uc3RyYWludHMpO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIEBoaWRkZW5cbiAgICovXG4gIHN0YXJ0V3Mob25Db25uZWN0U3VjY2VzOiAoZXJyb3I6IEVycm9yKSA9PiB2b2lkKTogdm9pZCB7XG4gICAgY29uc3QgY29uZmlnID0ge1xuICAgICAgaGVhcnRiZWF0OiA1MDAwLFxuICAgICAgc2VuZENsb3NlTWVzc2FnZTogZmFsc2UsXG4gICAgICB3czoge1xuICAgICAgICB1cmk6IHRoaXMud3NVcmksXG4gICAgICAgIHVzZVNvY2tKUzogZmFsc2UsXG4gICAgICAgIG9uY29ubmVjdGVkOiBvbkNvbm5lY3RTdWNjZXMsXG4gICAgICAgIG9uZGlzY29ubmVjdDogdGhpcy5kaXNjb25uZWN0Q2FsbGJhY2suYmluZCh0aGlzKSxcbiAgICAgICAgb25yZWNvbm5lY3Rpbmc6IHRoaXMucmVjb25uZWN0aW5nQ2FsbGJhY2suYmluZCh0aGlzKSxcbiAgICAgICAgb25yZWNvbm5lY3RlZDogdGhpcy5yZWNvbm5lY3RlZENhbGxiYWNrLmJpbmQodGhpcylcbiAgICAgIH0sXG4gICAgICBycGM6IHtcbiAgICAgICAgcmVxdWVzdFRpbWVvdXQ6IDEwMDAwLFxuICAgICAgICBwYXJ0aWNpcGFudEpvaW5lZDogdGhpcy5zZXNzaW9uLm9uUGFydGljaXBhbnRKb2luZWQuYmluZCh0aGlzLnNlc3Npb24pLFxuICAgICAgICBwYXJ0aWNpcGFudFB1Ymxpc2hlZDogdGhpcy5zZXNzaW9uLm9uUGFydGljaXBhbnRQdWJsaXNoZWQuYmluZCh0aGlzLnNlc3Npb24pLFxuICAgICAgICBwYXJ0aWNpcGFudFVucHVibGlzaGVkOiB0aGlzLnNlc3Npb24ub25QYXJ0aWNpcGFudFVucHVibGlzaGVkLmJpbmQodGhpcy5zZXNzaW9uKSxcbiAgICAgICAgcGFydGljaXBhbnRMZWZ0OiB0aGlzLnNlc3Npb24ub25QYXJ0aWNpcGFudExlZnQuYmluZCh0aGlzLnNlc3Npb24pLFxuICAgICAgICBwYXJ0aWNpcGFudEV2aWN0ZWQ6IHRoaXMuc2Vzc2lvbi5vblBhcnRpY2lwYW50RXZpY3RlZC5iaW5kKHRoaXMuc2Vzc2lvbiksXG4gICAgICAgIHJlY29yZGluZ1N0YXJ0ZWQ6IHRoaXMuc2Vzc2lvbi5vblJlY29yZGluZ1N0YXJ0ZWQuYmluZCh0aGlzLnNlc3Npb24pLFxuICAgICAgICByZWNvcmRpbmdTdG9wcGVkOiB0aGlzLnNlc3Npb24ub25SZWNvcmRpbmdTdG9wcGVkLmJpbmQodGhpcy5zZXNzaW9uKSxcbiAgICAgICAgc2VuZE1lc3NhZ2U6IHRoaXMuc2Vzc2lvbi5vbk5ld01lc3NhZ2UuYmluZCh0aGlzLnNlc3Npb24pLFxuICAgICAgICBzdHJlYW1Qcm9wZXJ0eUNoYW5nZWQ6IHRoaXMuc2Vzc2lvbi5vblN0cmVhbVByb3BlcnR5Q2hhbmdlZC5iaW5kKHRoaXMuc2Vzc2lvbiksXG4gICAgICAgIGljZUNhbmRpZGF0ZTogdGhpcy5zZXNzaW9uLnJlY3ZJY2VDYW5kaWRhdGUuYmluZCh0aGlzLnNlc3Npb24pLFxuICAgICAgICBtZWRpYUVycm9yOiB0aGlzLnNlc3Npb24ub25NZWRpYUVycm9yLmJpbmQodGhpcy5zZXNzaW9uKVxuICAgICAgfVxuICAgIH07XG4gICAgdGhpcy5qc29uUnBjQ2xpZW50ID0gbmV3IFJwY0J1aWxkZXIuY2xpZW50cy5Kc29uUnBjQ2xpZW50KGNvbmZpZyk7XG4gIH1cblxuICAvKipcbiAgICogQGhpZGRlblxuICAgKi9cbiAgY2xvc2VXcygpOiB2b2lkIHtcbiAgICB0aGlzLmpzb25ScGNDbGllbnQuY2xvc2UoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICBzZW5kUmVxdWVzdChtZXRob2Q6IHN0cmluZywgcGFyYW1zOiBhbnksIGNhbGxiYWNrPyk6IHZvaWQge1xuICAgIGlmIChwYXJhbXMgJiYgcGFyYW1zIGluc3RhbmNlb2YgRnVuY3Rpb24pIHtcbiAgICAgIGNhbGxiYWNrID0gcGFyYW1zO1xuICAgICAgcGFyYW1zID0ge307XG4gICAgfVxuICAgIGNvbnNvbGUuZGVidWcoJ1NlbmRpbmcgcmVxdWVzdDoge21ldGhvZDpcIicgKyBtZXRob2QgKyAnXCIsIHBhcmFtczogJyArIEpTT04uc3RyaW5naWZ5KHBhcmFtcykgKyAnfScpO1xuICAgIHRoaXMuanNvblJwY0NsaWVudC5zZW5kKG1ldGhvZCwgcGFyYW1zLCBjYWxsYmFjayk7XG4gIH1cblxuICAvKipcbiAgICogQGhpZGRlblxuICAgKi9cbiAgaXNNZWRpYVN0cmVhbVRyYWNrKG1lZGlhU291cmNlOiBhbnkpOiBib29sZWFuIHtcbiAgICBjb25zdCBpcyA9ICghIW1lZGlhU291cmNlICYmXG4gICAgICBtZWRpYVNvdXJjZS5lbmFibGVkICE9PSB1bmRlZmluZWQgJiYgdHlwZW9mIG1lZGlhU291cmNlLmVuYWJsZWQgPT09ICdib29sZWFuJyAmJlxuICAgICAgbWVkaWFTb3VyY2UuaWQgIT09IHVuZGVmaW5lZCAmJiB0eXBlb2YgbWVkaWFTb3VyY2UuaWQgPT09ICdzdHJpbmcnICYmXG4gICAgICBtZWRpYVNvdXJjZS5raW5kICE9PSB1bmRlZmluZWQgJiYgdHlwZW9mIG1lZGlhU291cmNlLmtpbmQgPT09ICdzdHJpbmcnICYmXG4gICAgICBtZWRpYVNvdXJjZS5sYWJlbCAhPT0gdW5kZWZpbmVkICYmIHR5cGVvZiBtZWRpYVNvdXJjZS5sYWJlbCA9PT0gJ3N0cmluZycgJiZcbiAgICAgIG1lZGlhU291cmNlLm11dGVkICE9PSB1bmRlZmluZWQgJiYgdHlwZW9mIG1lZGlhU291cmNlLm11dGVkID09PSAnYm9vbGVhbicgJiZcbiAgICAgIG1lZGlhU291cmNlLnJlYWR5U3RhdGUgIT09IHVuZGVmaW5lZCAmJiB0eXBlb2YgbWVkaWFTb3VyY2UucmVhZHlTdGF0ZSA9PT0gJ3N0cmluZycpO1xuICAgIHJldHVybiBpcztcbiAgfVxuXG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICBnZXRXc1VyaSgpOiBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLndzVXJpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBoaWRkZW5cbiAgICovXG4gIGdldFNlY3JldCgpOiBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLnNlY3JldDtcbiAgfVxuXG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICBnZXRSZWNvcmRlcigpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5yZWNvcmRlcjtcbiAgfVxuXG5cbiAgLyogUHJpdmF0ZSBtZXRob2RzICovXG5cbiAgcHJpdmF0ZSBkaXNjb25uZWN0Q2FsbGJhY2soKTogdm9pZCB7XG4gICAgY29uc29sZS53YXJuKCdXZWJzb2NrZXQgY29ubmVjdGlvbiBsb3N0Jyk7XG4gICAgaWYgKHRoaXMuaXNSb29tQXZhaWxhYmxlKCkpIHtcbiAgICAgIHRoaXMuc2Vzc2lvbi5vbkxvc3RDb25uZWN0aW9uKCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGFsZXJ0KCdDb25uZWN0aW9uIGVycm9yLiBQbGVhc2UgcmVsb2FkIHBhZ2UuJyk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSByZWNvbm5lY3RpbmdDYWxsYmFjaygpOiB2b2lkIHtcbiAgICBjb25zb2xlLndhcm4oJ1dlYnNvY2tldCBjb25uZWN0aW9uIGxvc3QgKHJlY29ubmVjdGluZyknKTtcbiAgICBpZiAodGhpcy5pc1Jvb21BdmFpbGFibGUoKSkge1xuICAgICAgdGhpcy5zZXNzaW9uLm9uTG9zdENvbm5lY3Rpb24oKTtcbiAgICB9IGVsc2Uge1xuICAgICAgYWxlcnQoJ0Nvbm5lY3Rpb24gZXJyb3IuIFBsZWFzZSByZWxvYWQgcGFnZS4nKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIHJlY29ubmVjdGVkQ2FsbGJhY2soKTogdm9pZCB7XG4gICAgY29uc29sZS53YXJuKCdXZWJzb2NrZXQgcmVjb25uZWN0ZWQnKTtcbiAgICBpZiAodGhpcy5pc1Jvb21BdmFpbGFibGUoKSkge1xuICAgICAgdGhpcy5zZXNzaW9uLm9uUmVjb3ZlcmVkQ29ubmVjdGlvbigpO1xuICAgIH0gZWxzZSB7XG4gICAgICBhbGVydCgnQ29ubmVjdGlvbiBlcnJvci4gUGxlYXNlIHJlbG9hZCBwYWdlLicpO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgaXNSb29tQXZhaWxhYmxlKCk6IGJvb2xlYW4ge1xuICAgIGlmICh0aGlzLnNlc3Npb24gIT09IHVuZGVmaW5lZCAmJiB0aGlzLnNlc3Npb24gaW5zdGFuY2VvZiBTZXNzaW9uKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9IGVsc2Uge1xuICAgICAgY29uc29sZS53YXJuKCdTZXNzaW9uIGluc3RhbmNlIG5vdCBmb3VuZCcpO1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfVxuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBPcGVuVmlkdSB9IGZyb20gJy4vT3BlblZpZHUnO1xuaW1wb3J0IHsgU2Vzc2lvbiB9IGZyb20gJy4vU2Vzc2lvbic7XG5pbXBvcnQgeyBTdHJlYW0gfSBmcm9tICcuL1N0cmVhbSc7XG5pbXBvcnQgeyBTdHJlYW1NYW5hZ2VyIH0gZnJvbSAnLi9TdHJlYW1NYW5hZ2VyJztcbmltcG9ydCB7IEV2ZW50RGlzcGF0Y2hlciB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvSW50ZXJmYWNlcy9QdWJsaWMvRXZlbnREaXNwYXRjaGVyJztcbmltcG9ydCB7IFB1Ymxpc2hlclByb3BlcnRpZXMgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHVibGljL1B1Ymxpc2hlclByb3BlcnRpZXMnO1xuaW1wb3J0IHsgRXZlbnQgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0V2ZW50cy9FdmVudCc7XG5pbXBvcnQgeyBTdHJlYW1FdmVudCB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1N0cmVhbUV2ZW50JztcbmltcG9ydCB7IFN0cmVhbVByb3BlcnR5Q2hhbmdlZEV2ZW50IH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvU3RyZWFtUHJvcGVydHlDaGFuZ2VkRXZlbnQnO1xuaW1wb3J0IHsgVmlkZW9FbGVtZW50RXZlbnQgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0V2ZW50cy9WaWRlb0VsZW1lbnRFdmVudCc7XG5pbXBvcnQgeyBPcGVuVmlkdUVycm9yLCBPcGVuVmlkdUVycm9yTmFtZSB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRW51bXMvT3BlblZpZHVFcnJvcic7XG5pbXBvcnQgeyBWaWRlb0luc2VydE1vZGUgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0VudW1zL1ZpZGVvSW5zZXJ0TW9kZSc7XG5cbmltcG9ydCBwbGF0Zm9ybSA9IHJlcXVpcmUoJ3BsYXRmb3JtJyk7XG5cblxuLyoqXG4gKiBQYWNrcyBsb2NhbCBtZWRpYSBzdHJlYW1zLiBQYXJ0aWNpcGFudHMgY2FuIHB1Ymxpc2ggaXQgdG8gYSBzZXNzaW9uLiBJbml0aWFsaXplZCB3aXRoIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dIG1ldGhvZFxuICovXG5leHBvcnQgY2xhc3MgUHVibGlzaGVyIGV4dGVuZHMgU3RyZWFtTWFuYWdlciB7XG5cbiAgICAvKipcbiAgICAgKiBXaGV0aGVyIHRoZSBQdWJsaXNoZXIgaGFzIGJlZW4gZ3JhbnRlZCBhY2Nlc3MgdG8gdGhlIHJlcXVlc3RlZCBpbnB1dCBkZXZpY2VzIG9yIG5vdFxuICAgICAqL1xuICAgIGFjY2Vzc0FsbG93ZWQgPSBmYWxzZTtcblxuICAgIC8qKlxuICAgICAqIFdoZXRoZXIgeW91IGhhdmUgY2FsbGVkIFtbUHVibGlzaGVyLnN1YnNjcmliZVRvUmVtb3RlXV0gd2l0aCB2YWx1ZSBgdHJ1ZWAgb3IgYGZhbHNlYCAoKmZhbHNlKiBieSBkZWZhdWx0KVxuICAgICAqL1xuICAgIGlzU3Vic2NyaWJlZFRvUmVtb3RlID0gZmFsc2U7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgW1tTZXNzaW9uXV0gdG8gd2hpY2ggdGhlIFB1Ymxpc2hlciBiZWxvbmdzXG4gICAgICovXG4gICAgc2Vzc2lvbjogU2Vzc2lvbjsgLy8gSW5pdGlhbGl6ZWQgYnkgU2Vzc2lvbi5wdWJsaXNoKFB1Ymxpc2hlcilcblxuICAgIHByaXZhdGUgYWNjZXNzRGVuaWVkID0gZmFsc2U7XG4gICAgcHJpdmF0ZSBwcm9wZXJ0aWVzOiBQdWJsaXNoZXJQcm9wZXJ0aWVzO1xuICAgIHByaXZhdGUgcGVybWlzc2lvbkRpYWxvZ1RpbWVvdXQ6IE5vZGVKUy5UaW1lcjtcblxuICAgIC8qKlxuICAgICAqIGhpZGRlblxuICAgICAqL1xuICAgIG9wZW52aWR1OiBPcGVuVmlkdTtcbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgdmlkZW9SZWZlcmVuY2U6IEhUTUxWaWRlb0VsZW1lbnQ7XG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHNjcmVlblNoYXJlUmVzaXplSW50ZXJ2YWw6IE5vZGVKUy5UaW1lcjtcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3Rvcih0YXJnRWw6IHN0cmluZyB8IEhUTUxFbGVtZW50LCBwcm9wZXJ0aWVzOiBQdWJsaXNoZXJQcm9wZXJ0aWVzLCBvcGVudmlkdTogT3BlblZpZHUpIHtcbiAgICAgICAgc3VwZXIobmV3IFN0cmVhbSgoISFvcGVudmlkdS5zZXNzaW9uKSA/IG9wZW52aWR1LnNlc3Npb24gOiBuZXcgU2Vzc2lvbihvcGVudmlkdSksIHsgcHVibGlzaGVyUHJvcGVydGllczogcHJvcGVydGllcywgbWVkaWFDb25zdHJhaW50czoge30gfSksIHRhcmdFbCk7XG4gICAgICAgIHRoaXMucHJvcGVydGllcyA9IHByb3BlcnRpZXM7XG4gICAgICAgIHRoaXMub3BlbnZpZHUgPSBvcGVudmlkdTtcblxuICAgICAgICB0aGlzLnN0cmVhbS5lZS5vbignbG9jYWwtc3RyZWFtLWRlc3Ryb3llZCcsIChyZWFzb246IHN0cmluZykgPT4ge1xuICAgICAgICAgICAgdGhpcy5zdHJlYW0uaXNMb2NhbFN0cmVhbVB1Ymxpc2hlZCA9IGZhbHNlO1xuICAgICAgICAgICAgY29uc3Qgc3RyZWFtRXZlbnQgPSBuZXcgU3RyZWFtRXZlbnQodHJ1ZSwgdGhpcywgJ3N0cmVhbURlc3Ryb3llZCcsIHRoaXMuc3RyZWFtLCByZWFzb24pO1xuICAgICAgICAgICAgdGhpcy5lbWl0RXZlbnQoJ3N0cmVhbURlc3Ryb3llZCcsIFtzdHJlYW1FdmVudF0pO1xuICAgICAgICAgICAgc3RyZWFtRXZlbnQuY2FsbERlZmF1bHRCZWhhdmlvcigpO1xuICAgICAgICB9KTtcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFB1Ymxpc2ggb3IgdW5wdWJsaXNoIHRoZSBhdWRpbyBzdHJlYW0gKGlmIGF2YWlsYWJsZSkuIENhbGxpbmcgdGhpcyBtZXRob2QgdHdpY2UgaW4gYSByb3cgcGFzc2luZyBzYW1lIHZhbHVlIHdpbGwgaGF2ZSBubyBlZmZlY3RcbiAgICAgKlxuICAgICAqICMjIyMgRXZlbnRzIGRpc3BhdGNoZWRcbiAgICAgKlxuICAgICAqIFRoZSBbW1Nlc3Npb25dXSBvYmplY3Qgb2YgdGhlIGxvY2FsIHBhcnRpY2lwYW50IHdpbGwgZGlzcGF0Y2ggYSBgc3RyZWFtUHJvcGVydHlDaGFuZ2VkYCBldmVudCB3aXRoIGBjaGFuZ2VkUHJvcGVydHlgIHNldCB0byBgXCJhdWRpb0FjdGl2ZVwiYCBhbmQgYHJlYXNvbmAgc2V0IHRvIGBcInB1Ymxpc2hBdWRpb1wiYFxuICAgICAqIFRoZSBbW1B1Ymxpc2hlcl1dIG9iamVjdCBvZiB0aGUgbG9jYWwgcGFydGljaXBhbnQgd2lsbCBhbHNvIGRpc3BhdGNoIHRoZSBleGFjdCBzYW1lIGV2ZW50XG4gICAgICpcbiAgICAgKiBUaGUgW1tTZXNzaW9uXV0gb2JqZWN0IG9mIGV2ZXJ5IG90aGVyIHBhcnRpY2lwYW50IGNvbm5lY3RlZCB0byB0aGUgc2Vzc2lvbiB3aWxsIGRpc3BhdGNoIGEgYHN0cmVhbVByb3BlcnR5Q2hhbmdlZGAgZXZlbnQgd2l0aCBgY2hhbmdlZFByb3BlcnR5YCBzZXQgdG8gYFwiYXVkaW9BY3RpdmVcImAgYW5kIGByZWFzb25gIHNldCB0byBgXCJwdWJsaXNoQXVkaW9cImBcbiAgICAgKiBUaGUgcmVzcGVjdGl2ZSBbW1N1YnNjcmliZXJdXSBvYmplY3Qgb2YgZXZlcnkgb3RoZXIgcGFydGljaXBhbnQgcmVjZWl2aW5nIHRoaXMgUHVibGlzaGVyJ3Mgc3RyZWFtIHdpbGwgYWxzbyBkaXNwYXRjaCB0aGUgZXhhY3Qgc2FtZSBldmVudFxuICAgICAqXG4gICAgICogU2VlIFtbU3RyZWFtUHJvcGVydHlDaGFuZ2VkRXZlbnRdXSB0byBsZWFybiBtb3JlLlxuICAgICAqXG4gICAgICogQHBhcmFtIHZhbHVlIGB0cnVlYCB0byBwdWJsaXNoIHRoZSBhdWRpbyBzdHJlYW0sIGBmYWxzZWAgdG8gdW5wdWJsaXNoIGl0XG4gICAgICovXG4gICAgcHVibGlzaEF1ZGlvKHZhbHVlOiBib29sZWFuKTogdm9pZCB7XG4gICAgICAgIGlmICh0aGlzLnN0cmVhbS5hdWRpb0FjdGl2ZSAhPT0gdmFsdWUpIHtcbiAgICAgICAgICAgIHRoaXMuc3RyZWFtLmdldE1lZGlhU3RyZWFtKCkuZ2V0QXVkaW9UcmFja3MoKS5mb3JFYWNoKCh0cmFjaykgPT4ge1xuICAgICAgICAgICAgICAgIHRyYWNrLmVuYWJsZWQgPSB2YWx1ZTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgdGhpcy5zZXNzaW9uLm9wZW52aWR1LnNlbmRSZXF1ZXN0KFxuICAgICAgICAgICAgICAgICdzdHJlYW1Qcm9wZXJ0eUNoYW5nZWQnLFxuICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgc3RyZWFtSWQ6IHRoaXMuc3RyZWFtLnN0cmVhbUlkLFxuICAgICAgICAgICAgICAgICAgICBwcm9wZXJ0eTogJ2F1ZGlvQWN0aXZlJyxcbiAgICAgICAgICAgICAgICAgICAgbmV3VmFsdWU6IHZhbHVlLFxuICAgICAgICAgICAgICAgICAgICByZWFzb246ICdwdWJsaXNoQXVkaW8nXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAoZXJyb3IsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihcIkVycm9yIHNlbmRpbmcgJ3N0cmVhbVByb3BlcnR5Q2hhbmdlZCcgZXZlbnRcIiwgZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXNzaW9uLmVtaXRFdmVudCgnc3RyZWFtUHJvcGVydHlDaGFuZ2VkJywgW25ldyBTdHJlYW1Qcm9wZXJ0eUNoYW5nZWRFdmVudCh0aGlzLnNlc3Npb24sIHRoaXMuc3RyZWFtLCAnYXVkaW9BY3RpdmUnLCB2YWx1ZSwgIXZhbHVlLCAncHVibGlzaEF1ZGlvJyldKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZW1pdEV2ZW50KCdzdHJlYW1Qcm9wZXJ0eUNoYW5nZWQnLCBbbmV3IFN0cmVhbVByb3BlcnR5Q2hhbmdlZEV2ZW50KHRoaXMsIHRoaXMuc3RyZWFtLCAnYXVkaW9BY3RpdmUnLCB2YWx1ZSwgIXZhbHVlLCAncHVibGlzaEF1ZGlvJyldKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgdGhpcy5zdHJlYW0uYXVkaW9BY3RpdmUgPSB2YWx1ZTtcbiAgICAgICAgICAgIGNvbnNvbGUuaW5mbyhcIidQdWJsaXNoZXInIGhhcyBcIiArICh2YWx1ZSA/ICdwdWJsaXNoZWQnIDogJ3VucHVibGlzaGVkJykgKyAnIGl0cyBhdWRpbyBzdHJlYW0nKTtcbiAgICAgICAgfVxuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogUHVibGlzaCBvciB1bnB1Ymxpc2ggdGhlIHZpZGVvIHN0cmVhbSAoaWYgYXZhaWxhYmxlKS4gQ2FsbGluZyB0aGlzIG1ldGhvZCB0d2ljZSBpbiBhIHJvdyBwYXNzaW5nIHNhbWUgdmFsdWUgd2lsbCBoYXZlIG5vIGVmZmVjdFxuICAgICAqXG4gICAgICogIyMjIyBFdmVudHMgZGlzcGF0Y2hlZFxuICAgICAqXG4gICAgICogVGhlIFtbU2Vzc2lvbl1dIG9iamVjdCBvZiB0aGUgbG9jYWwgcGFydGljaXBhbnQgd2lsbCBkaXNwYXRjaCBhIGBzdHJlYW1Qcm9wZXJ0eUNoYW5nZWRgIGV2ZW50IHdpdGggYGNoYW5nZWRQcm9wZXJ0eWAgc2V0IHRvIGBcInZpZGVvQWN0aXZlXCJgIGFuZCBgcmVhc29uYCBzZXQgdG8gYFwicHVibGlzaFZpZGVvXCJgXG4gICAgICogVGhlIFtbUHVibGlzaGVyXV0gb2JqZWN0IG9mIHRoZSBsb2NhbCBwYXJ0aWNpcGFudCB3aWxsIGFsc28gZGlzcGF0Y2ggdGhlIGV4YWN0IHNhbWUgZXZlbnRcbiAgICAgKlxuICAgICAqIFRoZSBbW1Nlc3Npb25dXSBvYmplY3Qgb2YgZXZlcnkgb3RoZXIgcGFydGljaXBhbnQgY29ubmVjdGVkIHRvIHRoZSBzZXNzaW9uIHdpbGwgZGlzcGF0Y2ggYSBgc3RyZWFtUHJvcGVydHlDaGFuZ2VkYCBldmVudCB3aXRoIGBjaGFuZ2VkUHJvcGVydHlgIHNldCB0byBgXCJ2aWRlb0FjdGl2ZVwiYCBhbmQgYHJlYXNvbmAgc2V0IHRvIGBcInB1Ymxpc2hWaWRlb1wiYFxuICAgICAqIFRoZSByZXNwZWN0aXZlIFtbU3Vic2NyaWJlcl1dIG9iamVjdCBvZiBldmVyeSBvdGhlciBwYXJ0aWNpcGFudCByZWNlaXZpbmcgdGhpcyBQdWJsaXNoZXIncyBzdHJlYW0gd2lsbCBhbHNvIGRpc3BhdGNoIHRoZSBleGFjdCBzYW1lIGV2ZW50XG4gICAgICpcbiAgICAgKiBTZWUgW1tTdHJlYW1Qcm9wZXJ0eUNoYW5nZWRFdmVudF1dIHRvIGxlYXJuIG1vcmUuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gdmFsdWUgYHRydWVgIHRvIHB1Ymxpc2ggdGhlIHZpZGVvIHN0cmVhbSwgYGZhbHNlYCB0byB1bnB1Ymxpc2ggaXRcbiAgICAgKi9cbiAgICBwdWJsaXNoVmlkZW8odmFsdWU6IGJvb2xlYW4pOiB2b2lkIHtcbiAgICAgICAgaWYgKHRoaXMuc3RyZWFtLnZpZGVvQWN0aXZlICE9PSB2YWx1ZSkge1xuICAgICAgICAgICAgdGhpcy5zdHJlYW0uZ2V0TWVkaWFTdHJlYW0oKS5nZXRWaWRlb1RyYWNrcygpLmZvckVhY2goKHRyYWNrKSA9PiB7XG4gICAgICAgICAgICAgICAgdHJhY2suZW5hYmxlZCA9IHZhbHVlO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB0aGlzLnNlc3Npb24ub3BlbnZpZHUuc2VuZFJlcXVlc3QoXG4gICAgICAgICAgICAgICAgJ3N0cmVhbVByb3BlcnR5Q2hhbmdlZCcsXG4gICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICBzdHJlYW1JZDogdGhpcy5zdHJlYW0uc3RyZWFtSWQsXG4gICAgICAgICAgICAgICAgICAgIHByb3BlcnR5OiAndmlkZW9BY3RpdmUnLFxuICAgICAgICAgICAgICAgICAgICBuZXdWYWx1ZTogdmFsdWUsXG4gICAgICAgICAgICAgICAgICAgIHJlYXNvbjogJ3B1Ymxpc2hWaWRlbydcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIChlcnJvciwgcmVzcG9uc2UpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKFwiRXJyb3Igc2VuZGluZyAnc3RyZWFtUHJvcGVydHlDaGFuZ2VkJyBldmVudFwiLCBlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnNlc3Npb24uZW1pdEV2ZW50KCdzdHJlYW1Qcm9wZXJ0eUNoYW5nZWQnLCBbbmV3IFN0cmVhbVByb3BlcnR5Q2hhbmdlZEV2ZW50KHRoaXMuc2Vzc2lvbiwgdGhpcy5zdHJlYW0sICd2aWRlb0FjdGl2ZScsIHZhbHVlLCAhdmFsdWUsICdwdWJsaXNoVmlkZW8nKV0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5lbWl0RXZlbnQoJ3N0cmVhbVByb3BlcnR5Q2hhbmdlZCcsIFtuZXcgU3RyZWFtUHJvcGVydHlDaGFuZ2VkRXZlbnQodGhpcywgdGhpcy5zdHJlYW0sICd2aWRlb0FjdGl2ZScsIHZhbHVlLCAhdmFsdWUsICdwdWJsaXNoVmlkZW8nKV0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB0aGlzLnN0cmVhbS52aWRlb0FjdGl2ZSA9IHZhbHVlO1xuICAgICAgICAgICAgY29uc29sZS5pbmZvKFwiJ1B1Ymxpc2hlcicgaGFzIFwiICsgKHZhbHVlID8gJ3B1Ymxpc2hlZCcgOiAndW5wdWJsaXNoZWQnKSArICcgaXRzIHZpZGVvIHN0cmVhbScpO1xuICAgICAgICB9XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBDYWxsIHRoaXMgbWV0aG9kIGJlZm9yZSBbW1Nlc3Npb24ucHVibGlzaF1dIGlmIHlvdSBwcmVmZXIgdG8gc3Vic2NyaWJlIHRvIHlvdXIgUHVibGlzaGVyJ3MgcmVtb3RlIHN0cmVhbSBpbnN0ZWFkIG9mIHVzaW5nIHRoZSBsb2NhbCBzdHJlYW0sIGFzIGFueSBvdGhlciB1c2VyIHdvdWxkIGRvLlxuICAgICAqL1xuICAgIHN1YnNjcmliZVRvUmVtb3RlKHZhbHVlPzogYm9vbGVhbik6IHZvaWQge1xuICAgICAgICB2YWx1ZSA9ICh2YWx1ZSAhPT0gdW5kZWZpbmVkKSA/IHZhbHVlIDogdHJ1ZTtcbiAgICAgICAgdGhpcy5pc1N1YnNjcmliZWRUb1JlbW90ZSA9IHZhbHVlO1xuICAgICAgICB0aGlzLnN0cmVhbS5zdWJzY3JpYmVUb015UmVtb3RlKHZhbHVlKTtcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFNlZSBbW0V2ZW50RGlzcGF0Y2hlci5vbl1dXG4gICAgICovXG4gICAgb24odHlwZTogc3RyaW5nLCBoYW5kbGVyOiAoZXZlbnQ6IEV2ZW50KSA9PiB2b2lkKTogRXZlbnREaXNwYXRjaGVyIHtcbiAgICAgICAgc3VwZXIub24odHlwZSwgaGFuZGxlcik7XG4gICAgICAgIGlmICh0eXBlID09PSAnc3RyZWFtQ3JlYXRlZCcpIHtcbiAgICAgICAgICAgIGlmICghIXRoaXMuc3RyZWFtICYmIHRoaXMuc3RyZWFtLmlzTG9jYWxTdHJlYW1QdWJsaXNoZWQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVtaXRFdmVudCgnc3RyZWFtQ3JlYXRlZCcsIFtuZXcgU3RyZWFtRXZlbnQoZmFsc2UsIHRoaXMsICdzdHJlYW1DcmVhdGVkJywgdGhpcy5zdHJlYW0sICcnKV0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbS5lZS5vbignc3RyZWFtLWNyZWF0ZWQtYnktcHVibGlzaGVyJywgKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmVtaXRFdmVudCgnc3RyZWFtQ3JlYXRlZCcsIFtuZXcgU3RyZWFtRXZlbnQoZmFsc2UsIHRoaXMsICdzdHJlYW1DcmVhdGVkJywgdGhpcy5zdHJlYW0sICcnKV0pO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmICh0eXBlID09PSAncmVtb3RlVmlkZW9QbGF5aW5nJykge1xuICAgICAgICAgICAgaWYgKHRoaXMuc3RyZWFtLmRpc3BsYXlNeVJlbW90ZSgpICYmIHRoaXMudmlkZW9zWzBdICYmIHRoaXMudmlkZW9zWzBdLnZpZGVvICYmXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8uY3VycmVudFRpbWUgPiAwICYmXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8ucGF1c2VkID09PSBmYWxzZSAmJlxuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9zWzBdLnZpZGVvLmVuZGVkID09PSBmYWxzZSAmJlxuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9zWzBdLnZpZGVvLnJlYWR5U3RhdGUgPT09IDQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVtaXRFdmVudCgncmVtb3RlVmlkZW9QbGF5aW5nJywgW25ldyBWaWRlb0VsZW1lbnRFdmVudCh0aGlzLnZpZGVvc1swXS52aWRlbywgdGhpcywgJ3JlbW90ZVZpZGVvUGxheWluZycpXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHR5cGUgPT09ICdhY2Nlc3NBbGxvd2VkJykge1xuICAgICAgICAgICAgaWYgKHRoaXMuYWNjZXNzQWxsb3dlZCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZW1pdEV2ZW50KCdhY2Nlc3NBbGxvd2VkJywgW10pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmICh0eXBlID09PSAnYWNjZXNzRGVuaWVkJykge1xuICAgICAgICAgICAgaWYgKHRoaXMuYWNjZXNzRGVuaWVkKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5lbWl0RXZlbnQoJ2FjY2Vzc0RlbmllZCcsIFtdKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFNlZSBbW0V2ZW50RGlzcGF0Y2hlci5vbmNlXV1cbiAgICAgKi9cbiAgICBvbmNlKHR5cGU6IHN0cmluZywgaGFuZGxlcjogKGV2ZW50OiBFdmVudCkgPT4gdm9pZCk6IFB1Ymxpc2hlciB7XG4gICAgICAgIHN1cGVyLm9uY2UodHlwZSwgaGFuZGxlcik7XG4gICAgICAgIGlmICh0eXBlID09PSAnc3RyZWFtQ3JlYXRlZCcpIHtcbiAgICAgICAgICAgIGlmICghIXRoaXMuc3RyZWFtICYmIHRoaXMuc3RyZWFtLmlzTG9jYWxTdHJlYW1QdWJsaXNoZWQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVtaXRFdmVudCgnc3RyZWFtQ3JlYXRlZCcsIFtuZXcgU3RyZWFtRXZlbnQoZmFsc2UsIHRoaXMsICdzdHJlYW1DcmVhdGVkJywgdGhpcy5zdHJlYW0sICcnKV0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbS5lZS5vbmNlKCdzdHJlYW0tY3JlYXRlZC1ieS1wdWJsaXNoZXInLCAoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZW1pdEV2ZW50KCdzdHJlYW1DcmVhdGVkJywgW25ldyBTdHJlYW1FdmVudChmYWxzZSwgdGhpcywgJ3N0cmVhbUNyZWF0ZWQnLCB0aGlzLnN0cmVhbSwgJycpXSk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHR5cGUgPT09ICdyZW1vdGVWaWRlb1BsYXlpbmcnKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5zdHJlYW0uZGlzcGxheU15UmVtb3RlKCkgJiYgdGhpcy52aWRlb3NbMF0gJiYgdGhpcy52aWRlb3NbMF0udmlkZW8gJiZcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvc1swXS52aWRlby5jdXJyZW50VGltZSA+IDAgJiZcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvc1swXS52aWRlby5wYXVzZWQgPT09IGZhbHNlICYmXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8uZW5kZWQgPT09IGZhbHNlICYmXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8ucmVhZHlTdGF0ZSA9PT0gNCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZW1pdEV2ZW50KCdyZW1vdGVWaWRlb1BsYXlpbmcnLCBbbmV3IFZpZGVvRWxlbWVudEV2ZW50KHRoaXMudmlkZW9zWzBdLnZpZGVvLCB0aGlzLCAncmVtb3RlVmlkZW9QbGF5aW5nJyldKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAodHlwZSA9PT0gJ2FjY2Vzc0FsbG93ZWQnKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5hY2Nlc3NBbGxvd2VkKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5lbWl0RXZlbnQoJ2FjY2Vzc0FsbG93ZWQnLCBbXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHR5cGUgPT09ICdhY2Nlc3NEZW5pZWQnKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5hY2Nlc3NEZW5pZWQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVtaXRFdmVudCgnYWNjZXNzRGVuaWVkJywgW10pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuXG4gICAgLyogSGlkZGVuIG1ldGhvZHMgKi9cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBpbml0aWFsaXplKCk6IFByb21pc2U8YW55PiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG5cbiAgICAgICAgICAgIGNvbnN0IGVycm9yQ2FsbGJhY2sgPSAob3BlblZpZHVFcnJvcjogT3BlblZpZHVFcnJvcikgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuYWNjZXNzRGVuaWVkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB0aGlzLmFjY2Vzc0FsbG93ZWQgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICByZWplY3Qob3BlblZpZHVFcnJvcik7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICBjb25zdCBzdWNjZXNzQ2FsbGJhY2sgPSAobWVkaWFTdHJlYW06IE1lZGlhU3RyZWFtKSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5hY2Nlc3NBbGxvd2VkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB0aGlzLmFjY2Vzc0RlbmllZCA9IGZhbHNlO1xuXG4gICAgICAgICAgICAgICAgaWYgKHRoaXMub3BlbnZpZHUuaXNNZWRpYVN0cmVhbVRyYWNrKHRoaXMucHJvcGVydGllcy5hdWRpb1NvdXJjZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgbWVkaWFTdHJlYW0ucmVtb3ZlVHJhY2sobWVkaWFTdHJlYW0uZ2V0QXVkaW9UcmFja3MoKVswXSk7XG4gICAgICAgICAgICAgICAgICAgIG1lZGlhU3RyZWFtLmFkZFRyYWNrKCg8TWVkaWFTdHJlYW1UcmFjaz50aGlzLnByb3BlcnRpZXMuYXVkaW9Tb3VyY2UpKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAodGhpcy5vcGVudmlkdS5pc01lZGlhU3RyZWFtVHJhY2sodGhpcy5wcm9wZXJ0aWVzLnZpZGVvU291cmNlKSkge1xuICAgICAgICAgICAgICAgICAgICBtZWRpYVN0cmVhbS5yZW1vdmVUcmFjayhtZWRpYVN0cmVhbS5nZXRWaWRlb1RyYWNrcygpWzBdKTtcbiAgICAgICAgICAgICAgICAgICAgbWVkaWFTdHJlYW0uYWRkVHJhY2soKDxNZWRpYVN0cmVhbVRyYWNrPnRoaXMucHJvcGVydGllcy52aWRlb1NvdXJjZSkpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIEFwcGx5IFB1Ymxpc2hlclByb3BlcnRpZXMucHVibGlzaEF1ZGlvIGFuZCBQdWJsaXNoZXJQcm9wZXJ0aWVzLnB1Ymxpc2hWaWRlb1xuICAgICAgICAgICAgICAgIGlmICghIW1lZGlhU3RyZWFtLmdldEF1ZGlvVHJhY2tzKClbMF0pIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgZW5hYmxlZCA9ICh0aGlzLnN0cmVhbS5hdWRpb0FjdGl2ZSAhPT0gdW5kZWZpbmVkICYmIHRoaXMuc3RyZWFtLmF1ZGlvQWN0aXZlICE9PSBudWxsKSA/IHRoaXMuc3RyZWFtLmF1ZGlvQWN0aXZlIDogISF0aGlzLnN0cmVhbS5vdXRib3VuZFN0cmVhbU9wdHMucHVibGlzaGVyUHJvcGVydGllcy5wdWJsaXNoQXVkaW87XG4gICAgICAgICAgICAgICAgICAgIG1lZGlhU3RyZWFtLmdldEF1ZGlvVHJhY2tzKClbMF0uZW5hYmxlZCA9IGVuYWJsZWQ7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmICghIW1lZGlhU3RyZWFtLmdldFZpZGVvVHJhY2tzKClbMF0pIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgZW5hYmxlZCA9ICh0aGlzLnN0cmVhbS52aWRlb0FjdGl2ZSAhPT0gdW5kZWZpbmVkICYmIHRoaXMuc3RyZWFtLnZpZGVvQWN0aXZlICE9PSBudWxsKSA/IHRoaXMuc3RyZWFtLnZpZGVvQWN0aXZlIDogISF0aGlzLnN0cmVhbS5vdXRib3VuZFN0cmVhbU9wdHMucHVibGlzaGVyUHJvcGVydGllcy5wdWJsaXNoVmlkZW87XG4gICAgICAgICAgICAgICAgICAgIG1lZGlhU3RyZWFtLmdldFZpZGVvVHJhY2tzKClbMF0uZW5hYmxlZCA9IGVuYWJsZWQ7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb1JlZmVyZW5jZSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3ZpZGVvJyk7XG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb1JlZmVyZW5jZS5zcmNPYmplY3QgPSBtZWRpYVN0cmVhbTtcblxuICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtLnNldE1lZGlhU3RyZWFtKG1lZGlhU3RyZWFtKTtcbiAgICAgICAgICAgICAgICBpZiAoIXRoaXMuc3RyZWFtLmRpc3BsYXlNeVJlbW90ZSgpKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIFdoZW4gd2UgYXJlIHN1YnNjcmliZWQgdG8gb3VyIHJlbW90ZSB3ZSBkb24ndCBzdGlsbCBzZXQgdGhlIE1lZGlhU3RyZWFtIG9iamVjdCBpbiB0aGUgdmlkZW8gZWxlbWVudHMgdG9cbiAgICAgICAgICAgICAgICAgICAgLy8gYXZvaWQgZWFybHkgJ3N0cmVhbVBsYXlpbmcnIGV2ZW50XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtLnVwZGF0ZU1lZGlhU3RyZWFtSW5WaWRlb3MoKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoISF0aGlzLmZpcnN0VmlkZW9FbGVtZW50KSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuY3JlYXRlVmlkZW9FbGVtZW50KHRoaXMuZmlyc3RWaWRlb0VsZW1lbnQudGFyZ2V0RWxlbWVudCwgPFZpZGVvSW5zZXJ0TW9kZT50aGlzLnByb3BlcnRpZXMuaW5zZXJ0TW9kZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGRlbGV0ZSB0aGlzLmZpcnN0VmlkZW9FbGVtZW50O1xuXG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuc3RyZWFtLmlzU2VuZFZpZGVvKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCF0aGlzLnN0cmVhbS5pc1NlbmRTY3JlZW4oKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gV2l0aCBubyBzY3JlZW4gc2hhcmUsIHZpZGVvIGRpbWVuc2lvbiBjYW4gYmUgc2V0IGRpcmVjdGx5IGZyb20gTWVkaWFTdHJlYW0gKGdldFNldHRpbmdzKVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gT3JpZW50YXRpb24gbXVzdCBiZSBjaGVja2VkIGZvciBtb2JpbGUgZGV2aWNlcyAod2lkdGggYW5kIGhlaWdodCBhcmUgcmV2ZXJzZWQpXG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB7IHdpZHRoLCBoZWlnaHQgfSA9IG1lZGlhU3RyZWFtLmdldFZpZGVvVHJhY2tzKClbMF0uZ2V0U2V0dGluZ3MoKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHBsYXRmb3JtLm5hbWUhIS50b0xvd2VyQ2FzZSgpLmluZGV4T2YoJ21vYmlsZScpICE9PSAtMSAmJiAod2luZG93LmlubmVySGVpZ2h0ID4gd2luZG93LmlubmVyV2lkdGgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gTW9iaWxlIHBvcnRyYWl0IG1vZGVcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbS52aWRlb0RpbWVuc2lvbnMgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdpZHRoOiBoZWlnaHQgfHwgMCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaGVpZ2h0OiB3aWR0aCB8fCAwXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdHJlYW0udmlkZW9EaW1lbnNpb25zID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3aWR0aDogd2lkdGggfHwgMCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaGVpZ2h0OiBoZWlnaHQgfHwgMFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbS5pc0xvY2FsU3RyZWFtUmVhZHlUb1B1Ymxpc2ggPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdHJlYW0uZWUuZW1pdEV2ZW50KCdzdHJlYW0tcmVhZHktdG8tcHVibGlzaCcsIFtdKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIFdpdGggc2NyZWVuIHNoYXJlLCB2aWRlbyBkaW1lbnNpb24gbXVzdCBiZSBnb3QgZnJvbSBhIHZpZGVvIGVsZW1lbnQgKG9ubG9hZGVkbWV0YWRhdGEgZXZlbnQpXG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnZpZGVvUmVmZXJlbmNlLm9ubG9hZGVkbWV0YWRhdGEgPSAoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdHJlYW0udmlkZW9EaW1lbnNpb25zID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3aWR0aDogdGhpcy52aWRlb1JlZmVyZW5jZS52aWRlb1dpZHRoLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBoZWlnaHQ6IHRoaXMudmlkZW9SZWZlcmVuY2UudmlkZW9IZWlnaHRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc2NyZWVuU2hhcmVSZXNpemVJbnRlcnZhbCA9IHNldEludGVydmFsKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZmlyZWZveFNldHRpbmdzID0gbWVkaWFTdHJlYW0uZ2V0VmlkZW9UcmFja3MoKVswXS5nZXRTZXR0aW5ncygpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBuZXdXaWR0aCA9IChwbGF0Zm9ybS5uYW1lID09PSAnQ2hyb21lJykgPyB0aGlzLnZpZGVvUmVmZXJlbmNlLnZpZGVvV2lkdGggOiBmaXJlZm94U2V0dGluZ3Mud2lkdGg7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG5ld0hlaWdodCA9IChwbGF0Zm9ybS5uYW1lID09PSAnQ2hyb21lJykgPyB0aGlzLnZpZGVvUmVmZXJlbmNlLnZpZGVvSGVpZ2h0IDogZmlyZWZveFNldHRpbmdzLmhlaWdodDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuc3RyZWFtLmlzTG9jYWxTdHJlYW1QdWJsaXNoZWQgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChuZXdXaWR0aCAhPT0gdGhpcy5zdHJlYW0udmlkZW9EaW1lbnNpb25zLndpZHRoIHx8XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3SGVpZ2h0ICE9PSB0aGlzLnN0cmVhbS52aWRlb0RpbWVuc2lvbnMuaGVpZ2h0KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3Qgb2xkVmFsdWUgPSB7IHdpZHRoOiB0aGlzLnN0cmVhbS52aWRlb0RpbWVuc2lvbnMud2lkdGgsIGhlaWdodDogdGhpcy5zdHJlYW0udmlkZW9EaW1lbnNpb25zLmhlaWdodCB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdHJlYW0udmlkZW9EaW1lbnNpb25zID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdpZHRoOiBuZXdXaWR0aCB8fCAwLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhlaWdodDogbmV3SGVpZ2h0IHx8IDBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnNlc3Npb24ub3BlbnZpZHUuc2VuZFJlcXVlc3QoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ3N0cmVhbVByb3BlcnR5Q2hhbmdlZCcsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJlYW1JZDogdGhpcy5zdHJlYW0uc3RyZWFtSWQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByb3BlcnR5OiAndmlkZW9EaW1lbnNpb25zJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3VmFsdWU6IEpTT04uc3RyaW5naWZ5KHRoaXMuc3RyZWFtLnZpZGVvRGltZW5zaW9ucyksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlYXNvbjogJ3NjcmVlblJlc2l6ZWQnXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoZXJyb3IsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihcIkVycm9yIHNlbmRpbmcgJ3N0cmVhbVByb3BlcnR5Q2hhbmdlZCcgZXZlbnRcIiwgZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXNzaW9uLmVtaXRFdmVudCgnc3RyZWFtUHJvcGVydHlDaGFuZ2VkJywgW25ldyBTdHJlYW1Qcm9wZXJ0eUNoYW5nZWRFdmVudCh0aGlzLnNlc3Npb24sIHRoaXMuc3RyZWFtLCAndmlkZW9EaW1lbnNpb25zJywgdGhpcy5zdHJlYW0udmlkZW9EaW1lbnNpb25zLCBvbGRWYWx1ZSwgJ3NjcmVlblJlc2l6ZWQnKV0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5lbWl0RXZlbnQoJ3N0cmVhbVByb3BlcnR5Q2hhbmdlZCcsIFtuZXcgU3RyZWFtUHJvcGVydHlDaGFuZ2VkRXZlbnQodGhpcywgdGhpcy5zdHJlYW0sICd2aWRlb0RpbWVuc2lvbnMnLCB0aGlzLnN0cmVhbS52aWRlb0RpbWVuc2lvbnMsIG9sZFZhbHVlLCAnc2NyZWVuUmVzaXplZCcpXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0sIDUwMCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdHJlYW0uaXNMb2NhbFN0cmVhbVJlYWR5VG9QdWJsaXNoID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbS5lZS5lbWl0RXZlbnQoJ3N0cmVhbS1yZWFkeS10by1wdWJsaXNoJywgW10pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtLmlzTG9jYWxTdHJlYW1SZWFkeVRvUHVibGlzaCA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtLmVlLmVtaXRFdmVudCgnc3RyZWFtLXJlYWR5LXRvLXB1Ymxpc2gnLCBbXSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIHRoaXMub3BlbnZpZHUuZ2VuZXJhdGVNZWRpYUNvbnN0cmFpbnRzKHRoaXMucHJvcGVydGllcylcbiAgICAgICAgICAgICAgICAudGhlbihjb25zdHJhaW50cyA9PiB7XG5cbiAgICAgICAgICAgICAgICAgICAgY29uc3Qgb3V0Ym91bmRTdHJlYW1PcHRpb25zID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgbWVkaWFDb25zdHJhaW50czogY29uc3RyYWludHMsXG4gICAgICAgICAgICAgICAgICAgICAgICBwdWJsaXNoZXJQcm9wZXJ0aWVzOiB0aGlzLnByb3BlcnRpZXNcbiAgICAgICAgICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbS5zZXRPdXRib3VuZFN0cmVhbU9wdGlvbnMob3V0Ym91bmRTdHJlYW1PcHRpb25zKTtcblxuICAgICAgICAgICAgICAgICAgICBjb25zdCBjb25zdHJhaW50c0F1eDogTWVkaWFTdHJlYW1Db25zdHJhaW50cyA9IHt9O1xuICAgICAgICAgICAgICAgICAgICBjb25zdCB0aW1lRm9yRGlhbG9nRXZlbnQgPSAxMjUwO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLnN0cmVhbS5pc1NlbmRWaWRlbygpIHx8IHRoaXMuc3RyZWFtLmlzU2VuZEF1ZGlvKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGRlZmluZWRBdWRpb0NvbnN0cmFpbnQgPSAoKGNvbnN0cmFpbnRzLmF1ZGlvID09PSB1bmRlZmluZWQpID8gdHJ1ZSA6IGNvbnN0cmFpbnRzLmF1ZGlvKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0cmFpbnRzQXV4LmF1ZGlvID0gdGhpcy5zdHJlYW0uaXNTZW5kU2NyZWVuKCkgPyBmYWxzZSA6IGRlZmluZWRBdWRpb0NvbnN0cmFpbnQ7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdHJhaW50c0F1eC52aWRlbyA9IGNvbnN0cmFpbnRzLnZpZGVvO1xuICAgICAgICAgICAgICAgICAgICAgICAgbGV0IHN0YXJ0VGltZSA9IERhdGUubm93KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnNldFBlcm1pc3Npb25EaWFsb2dUaW1lcih0aW1lRm9yRGlhbG9nRXZlbnQpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBuYXZpZ2F0b3IubWVkaWFEZXZpY2VzLmdldFVzZXJNZWRpYShjb25zdHJhaW50c0F1eClcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAudGhlbihtZWRpYVN0cmVhbSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY2xlYXJQZXJtaXNzaW9uRGlhbG9nVGltZXIoc3RhcnRUaW1lLCB0aW1lRm9yRGlhbG9nRXZlbnQpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLnN0cmVhbS5pc1NlbmRTY3JlZW4oKSAmJiB0aGlzLnN0cmVhbS5pc1NlbmRBdWRpbygpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBXaGVuIGdldHRpbmcgZGVza3RvcCBhcyB1c2VyIG1lZGlhIGF1ZGlvIGNvbnN0cmFpbnQgbXVzdCBiZSBmYWxzZS4gTm93IHdlIGNhbiBhc2sgZm9yIGl0IGlmIHJlcXVpcmVkXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdHJhaW50c0F1eC5hdWRpbyA9IGRlZmluZWRBdWRpb0NvbnN0cmFpbnQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdHJhaW50c0F1eC52aWRlbyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhcnRUaW1lID0gRGF0ZS5ub3coKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc2V0UGVybWlzc2lvbkRpYWxvZ1RpbWVyKHRpbWVGb3JEaWFsb2dFdmVudCk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hdmlnYXRvci5tZWRpYURldmljZXMuZ2V0VXNlck1lZGlhKGNvbnN0cmFpbnRzQXV4KVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC50aGVuKGF1ZGlvT25seVN0cmVhbSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY2xlYXJQZXJtaXNzaW9uRGlhbG9nVGltZXIoc3RhcnRUaW1lLCB0aW1lRm9yRGlhbG9nRXZlbnQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZWRpYVN0cmVhbS5hZGRUcmFjayhhdWRpb09ubHlTdHJlYW0uZ2V0QXVkaW9UcmFja3MoKVswXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN1Y2Nlc3NDYWxsYmFjayhtZWRpYVN0cmVhbSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNsZWFyUGVybWlzc2lvbkRpYWxvZ1RpbWVyKHN0YXJ0VGltZSwgdGltZUZvckRpYWxvZ0V2ZW50KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGVycm9yTmFtZSwgZXJyb3JNZXNzYWdlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzd2l0Y2ggKGVycm9yLm5hbWUudG9Mb3dlckNhc2UoKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAnbm90Zm91bmRlcnJvcic6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JOYW1lID0gT3BlblZpZHVFcnJvck5hbWUuSU5QVVRfQVVESU9fREVWSUNFX05PVF9GT1VORDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck1lc3NhZ2UgPSBlcnJvci50b1N0cmluZygpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yQ2FsbGJhY2sobmV3IE9wZW5WaWR1RXJyb3IoZXJyb3JOYW1lLCBlcnJvck1lc3NhZ2UpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJ25vdGFsbG93ZWRlcnJvcic6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JOYW1lID0gT3BlblZpZHVFcnJvck5hbWUuREVWSUNFX0FDQ0VTU19ERU5JRUQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JNZXNzYWdlID0gZXJyb3IudG9TdHJpbmcoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvckNhbGxiYWNrKG5ldyBPcGVuVmlkdUVycm9yKGVycm9yTmFtZSwgZXJyb3JNZXNzYWdlKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlICdvdmVyY29uc3RyYWluZWRlcnJvcic6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yLmNvbnN0cmFpbnQudG9Mb3dlckNhc2UoKSA9PT0gJ2RldmljZWlkJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck5hbWUgPSBPcGVuVmlkdUVycm9yTmFtZS5JTlBVVF9BVURJT19ERVZJQ0VfTk9UX0ZPVU5EO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck1lc3NhZ2UgPSBcIkF1ZGlvIGlucHV0IGRldmljZSB3aXRoIGRldmljZUlkICdcIiArICg8Q29uc3RyYWluRE9NU3RyaW5nUGFyYW1ldGVycz4oPE1lZGlhVHJhY2tDb25zdHJhaW50cz5jb25zdHJhaW50cy52aWRlbykuZGV2aWNlSWQhISkuZXhhY3QgKyBcIicgbm90IGZvdW5kXCI7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JOYW1lID0gT3BlblZpZHVFcnJvck5hbWUuUFVCTElTSEVSX1BST1BFUlRJRVNfRVJST1I7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yTWVzc2FnZSA9IFwiQXVkaW8gaW5wdXQgZGV2aWNlIGRvZXNuJ3Qgc3VwcG9ydCB0aGUgdmFsdWUgcGFzc2VkIGZvciBjb25zdHJhaW50ICdcIiArIGVycm9yLmNvbnN0cmFpbnQgKyBcIidcIjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JDYWxsYmFjayhuZXcgT3BlblZpZHVFcnJvcihlcnJvck5hbWUsIGVycm9yTWVzc2FnZSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdWNjZXNzQ2FsbGJhY2sobWVkaWFTdHJlYW0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNsZWFyUGVybWlzc2lvbkRpYWxvZ1RpbWVyKHN0YXJ0VGltZSwgdGltZUZvckRpYWxvZ0V2ZW50KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGVycm9yTmFtZSwgZXJyb3JNZXNzYWdlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzd2l0Y2ggKGVycm9yLm5hbWUudG9Mb3dlckNhc2UoKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAnbm90Zm91bmRlcnJvcic6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmF2aWdhdG9yLm1lZGlhRGV2aWNlcy5nZXRVc2VyTWVkaWEoe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhdWRpbzogZmFsc2UsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZpZGVvOiBjb25zdHJhaW50cy52aWRlb1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC50aGVuKG1lZGlhU3RyZWFtID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1lZGlhU3RyZWFtLmdldFZpZGVvVHJhY2tzKCkuZm9yRWFjaCgodHJhY2spID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cmFjay5zdG9wKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yTmFtZSA9IE9wZW5WaWR1RXJyb3JOYW1lLklOUFVUX0FVRElPX0RFVklDRV9OT1RfRk9VTkQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck1lc3NhZ2UgPSBlcnJvci50b1N0cmluZygpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JDYWxsYmFjayhuZXcgT3BlblZpZHVFcnJvcihlcnJvck5hbWUsIGVycm9yTWVzc2FnZSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KS5jYXRjaChlID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yTmFtZSA9IE9wZW5WaWR1RXJyb3JOYW1lLklOUFVUX1ZJREVPX0RFVklDRV9OT1RfRk9VTkQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck1lc3NhZ2UgPSBlcnJvci50b1N0cmluZygpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JDYWxsYmFjayhuZXcgT3BlblZpZHVFcnJvcihlcnJvck5hbWUsIGVycm9yTWVzc2FnZSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJ25vdGFsbG93ZWRlcnJvcic6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JOYW1lID0gdGhpcy5zdHJlYW0uaXNTZW5kU2NyZWVuKCkgPyBPcGVuVmlkdUVycm9yTmFtZS5TQ1JFRU5fQ0FQVFVSRV9ERU5JRUQgOiBPcGVuVmlkdUVycm9yTmFtZS5ERVZJQ0VfQUNDRVNTX0RFTklFRDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck1lc3NhZ2UgPSBlcnJvci50b1N0cmluZygpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yQ2FsbGJhY2sobmV3IE9wZW5WaWR1RXJyb3IoZXJyb3JOYW1lLCBlcnJvck1lc3NhZ2UpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJ292ZXJjb25zdHJhaW5lZGVycm9yJzpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYXZpZ2F0b3IubWVkaWFEZXZpY2VzLmdldFVzZXJNZWRpYSh7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGF1ZGlvOiBmYWxzZSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmlkZW86IGNvbnN0cmFpbnRzLnZpZGVvXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLnRoZW4obWVkaWFTdHJlYW0gPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWVkaWFTdHJlYW0uZ2V0VmlkZW9UcmFja3MoKS5mb3JFYWNoKCh0cmFjaykgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRyYWNrLnN0b3AoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yLmNvbnN0cmFpbnQudG9Mb3dlckNhc2UoKSA9PT0gJ2RldmljZWlkJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yTmFtZSA9IE9wZW5WaWR1RXJyb3JOYW1lLklOUFVUX0FVRElPX0RFVklDRV9OT1RfRk9VTkQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JNZXNzYWdlID0gXCJBdWRpbyBpbnB1dCBkZXZpY2Ugd2l0aCBkZXZpY2VJZCAnXCIgKyAoPENvbnN0cmFpbkRPTVN0cmluZ1BhcmFtZXRlcnM+KDxNZWRpYVRyYWNrQ29uc3RyYWludHM+Y29uc3RyYWludHMuYXVkaW8pLmRldmljZUlkISEpLmV4YWN0ICsgXCInIG5vdCBmb3VuZFwiO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck5hbWUgPSBPcGVuVmlkdUVycm9yTmFtZS5QVUJMSVNIRVJfUFJPUEVSVElFU19FUlJPUjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck1lc3NhZ2UgPSBcIkF1ZGlvIGlucHV0IGRldmljZSBkb2Vzbid0IHN1cHBvcnQgdGhlIHZhbHVlIHBhc3NlZCBmb3IgY29uc3RyYWludCAnXCIgKyBlcnJvci5jb25zdHJhaW50ICsgXCInXCI7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvckNhbGxiYWNrKG5ldyBPcGVuVmlkdUVycm9yKGVycm9yTmFtZSwgZXJyb3JNZXNzYWdlKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pLmNhdGNoKGUgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yLmNvbnN0cmFpbnQudG9Mb3dlckNhc2UoKSA9PT0gJ2RldmljZWlkJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yTmFtZSA9IE9wZW5WaWR1RXJyb3JOYW1lLklOUFVUX1ZJREVPX0RFVklDRV9OT1RfRk9VTkQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JNZXNzYWdlID0gXCJWaWRlbyBpbnB1dCBkZXZpY2Ugd2l0aCBkZXZpY2VJZCAnXCIgKyAoPENvbnN0cmFpbkRPTVN0cmluZ1BhcmFtZXRlcnM+KDxNZWRpYVRyYWNrQ29uc3RyYWludHM+Y29uc3RyYWludHMudmlkZW8pLmRldmljZUlkISEpLmV4YWN0ICsgXCInIG5vdCBmb3VuZFwiO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck5hbWUgPSBPcGVuVmlkdUVycm9yTmFtZS5QVUJMSVNIRVJfUFJPUEVSVElFU19FUlJPUjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck1lc3NhZ2UgPSBcIlZpZGVvIGlucHV0IGRldmljZSBkb2Vzbid0IHN1cHBvcnQgdGhlIHZhbHVlIHBhc3NlZCBmb3IgY29uc3RyYWludCAnXCIgKyBlcnJvci5jb25zdHJhaW50ICsgXCInXCI7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvckNhbGxiYWNrKG5ldyBPcGVuVmlkdUVycm9yKGVycm9yTmFtZSwgZXJyb3JNZXNzYWdlKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZWplY3QobmV3IE9wZW5WaWR1RXJyb3IoT3BlblZpZHVFcnJvck5hbWUuTk9fSU5QVVRfU09VUkNFX1NFVCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBcIlByb3BlcnRpZXMgJ2F1ZGlvU291cmNlJyBhbmQgJ3ZpZGVvU291cmNlJyBjYW5ub3QgYmUgc2V0IHRvIGZhbHNlIG9yIG51bGwgYXQgdGhlIHNhbWUgdGltZSB3aGVuIGNhbGxpbmcgJ09wZW5WaWR1LmluaXRQdWJsaXNoZXInXCIpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgLmNhdGNoKChlcnJvcjogT3BlblZpZHVFcnJvcikgPT4ge1xuICAgICAgICAgICAgICAgICAgICBlcnJvckNhbGxiYWNrKGVycm9yKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHJlZXN0YWJsaXNoU3RyZWFtUGxheWluZ0V2ZW50KCkge1xuICAgICAgICBpZiAodGhpcy5lZS5nZXRMaXN0ZW5lcnMoJ3N0cmVhbVBsYXlpbmcnKS5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICB0aGlzLmFkZFBsYXlFdmVudFRvRmlyc3RWaWRlbygpO1xuICAgICAgICB9XG4gICAgfVxuXG5cbiAgICAvKiBQcml2YXRlIG1ldGhvZHMgKi9cblxuICAgIHByaXZhdGUgc2V0UGVybWlzc2lvbkRpYWxvZ1RpbWVyKHdhaXRUaW1lOiBudW1iZXIpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5wZXJtaXNzaW9uRGlhbG9nVGltZW91dCA9IHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5lbWl0RXZlbnQoJ2FjY2Vzc0RpYWxvZ09wZW5lZCcsIFtdKTtcbiAgICAgICAgfSwgd2FpdFRpbWUpO1xuICAgIH1cblxuICAgIHByaXZhdGUgY2xlYXJQZXJtaXNzaW9uRGlhbG9nVGltZXIoc3RhcnRUaW1lOiBudW1iZXIsIHdhaXRUaW1lOiBudW1iZXIpOiB2b2lkIHtcbiAgICAgICAgY2xlYXJUaW1lb3V0KHRoaXMucGVybWlzc2lvbkRpYWxvZ1RpbWVvdXQpO1xuICAgICAgICBpZiAoKERhdGUubm93KCkgLSBzdGFydFRpbWUpID4gd2FpdFRpbWUpIHtcbiAgICAgICAgICAgIC8vIFBlcm1pc3Npb24gZGlhbG9nIHdhcyBzaG93biBhbmQgbm93IGlzIGNsb3NlZFxuICAgICAgICAgICAgdGhpcy5lbWl0RXZlbnQoJ2FjY2Vzc0RpYWxvZ0Nsb3NlZCcsIFtdKTtcbiAgICAgICAgfVxuICAgIH1cblxufSIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTctMjAxOCBPcGVuVmlkdSAoaHR0cHM6Ly9vcGVudmlkdS5pby8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuaW1wb3J0IHsgQ29ubmVjdGlvbiB9IGZyb20gJy4vQ29ubmVjdGlvbic7XG5pbXBvcnQgeyBPcGVuVmlkdSB9IGZyb20gJy4vT3BlblZpZHUnO1xuaW1wb3J0IHsgUHVibGlzaGVyIH0gZnJvbSAnLi9QdWJsaXNoZXInO1xuaW1wb3J0IHsgU3RyZWFtIH0gZnJvbSAnLi9TdHJlYW0nO1xuaW1wb3J0IHsgU3RyZWFtTWFuYWdlciB9IGZyb20gJy4vU3RyZWFtTWFuYWdlcic7XG5pbXBvcnQgeyBTdWJzY3JpYmVyIH0gZnJvbSAnLi9TdWJzY3JpYmVyJztcbmltcG9ydCB7IENhcGFiaWxpdGllcyB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvSW50ZXJmYWNlcy9QdWJsaWMvQ2FwYWJpbGl0aWVzJztcbmltcG9ydCB7IEV2ZW50RGlzcGF0Y2hlciB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvSW50ZXJmYWNlcy9QdWJsaWMvRXZlbnREaXNwYXRjaGVyJztcbmltcG9ydCB7IFNpZ25hbE9wdGlvbnMgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHVibGljL1NpZ25hbE9wdGlvbnMnO1xuaW1wb3J0IHsgU3Vic2NyaWJlclByb3BlcnRpZXMgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHVibGljL1N1YnNjcmliZXJQcm9wZXJ0aWVzJztcbmltcG9ydCB7IENvbm5lY3Rpb25PcHRpb25zIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9JbnRlcmZhY2VzL1ByaXZhdGUvQ29ubmVjdGlvbk9wdGlvbnMnO1xuaW1wb3J0IHsgT2JqTWFwIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9JbnRlcmZhY2VzL1ByaXZhdGUvT2JqTWFwJztcbmltcG9ydCB7IFNlc3Npb25PcHRpb25zIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9JbnRlcmZhY2VzL1ByaXZhdGUvU2Vzc2lvbk9wdGlvbnMnO1xuaW1wb3J0IHsgQ29ubmVjdGlvbkV2ZW50IH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvQ29ubmVjdGlvbkV2ZW50JztcbmltcG9ydCB7IFB1Ymxpc2hlclNwZWFraW5nRXZlbnQgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0V2ZW50cy9QdWJsaXNoZXJTcGVha2luZ0V2ZW50JztcbmltcG9ydCB7IFJlY29yZGluZ0V2ZW50IH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvUmVjb3JkaW5nRXZlbnQnO1xuaW1wb3J0IHsgU2Vzc2lvbkRpc2Nvbm5lY3RlZEV2ZW50IH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvU2Vzc2lvbkRpc2Nvbm5lY3RlZEV2ZW50JztcbmltcG9ydCB7IFNpZ25hbEV2ZW50IH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvU2lnbmFsRXZlbnQnO1xuaW1wb3J0IHsgU3RyZWFtRXZlbnQgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0V2ZW50cy9TdHJlYW1FdmVudCc7XG5pbXBvcnQgeyBTdHJlYW1Qcm9wZXJ0eUNoYW5nZWRFdmVudCB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1N0cmVhbVByb3BlcnR5Q2hhbmdlZEV2ZW50JztcbmltcG9ydCB7IE9wZW5WaWR1RXJyb3IsIE9wZW5WaWR1RXJyb3JOYW1lIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FbnVtcy9PcGVuVmlkdUVycm9yJztcbmltcG9ydCB7IFZpZGVvSW5zZXJ0TW9kZSB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRW51bXMvVmlkZW9JbnNlcnRNb2RlJztcblxuaW1wb3J0IHBsYXRmb3JtID0gcmVxdWlyZSgncGxhdGZvcm0nKTtcbmltcG9ydCBFdmVudEVtaXR0ZXIgPSByZXF1aXJlKCd3b2xmeTg3LWV2ZW50ZW1pdHRlcicpO1xuXG5cbi8qKlxuICogUmVwcmVzZW50cyBhIHZpZGVvIGNhbGwuIEl0IGNhbiBhbHNvIGJlIHNlZW4gYXMgYSB2aWRlb2NvbmZlcmVuY2Ugcm9vbSB3aGVyZSBtdWx0aXBsZSB1c2VycyBjYW4gY29ubmVjdC5cbiAqIFBhcnRpY2lwYW50cyB3aG8gcHVibGlzaCB0aGVpciB2aWRlb3MgdG8gYSBzZXNzaW9uIGNhbiBiZSBzZWVuIGJ5IHRoZSByZXN0IG9mIHVzZXJzIGNvbm5lY3RlZCB0byB0aGF0IHNwZWNpZmljIHNlc3Npb24uXG4gKiBJbml0aWFsaXplZCB3aXRoIFtbT3BlblZpZHUuaW5pdFNlc3Npb25dXSBtZXRob2RcbiAqL1xuZXhwb3J0IGNsYXNzIFNlc3Npb24gaW1wbGVtZW50cyBFdmVudERpc3BhdGNoZXIge1xuXG4gICAgLyoqXG4gICAgICogTG9jYWwgY29ubmVjdGlvbiB0byB0aGUgU2Vzc2lvbi4gVGhpcyBvYmplY3QgaXMgZGVmaW5lZCBvbmx5IGFmdGVyIFtbU2Vzc2lvbi5jb25uZWN0XV0gaGFzIGJlZW4gc3VjY2Vzc2Z1bGx5IGV4ZWN1dGVkLCBhbmQgY2FuIGJlIHJldHJpZXZlZCBzdWJzY3JpYmluZyB0byBgY29ubmVjdGlvbkNyZWF0ZWRgIGV2ZW50XG4gICAgICovXG4gICAgY29ubmVjdGlvbjogQ29ubmVjdGlvbjtcblxuICAgIC8qKlxuICAgICAqIFVuaXF1ZSBpZGVudGlmaWVyIG9mIHRoZSBTZXNzaW9uXG4gICAgICovXG4gICAgc2Vzc2lvbklkOiBzdHJpbmc7XG5cbiAgICAvKipcbiAgICAgKiBDb2xsZWN0aW9uIG9mIGFsbCBTdHJlYW1NYW5hZ2VycyBvZiB0aGlzIFNlc3Npb24gKFtbUHVibGlzaGVyXV0gYW5kIFtbU3Vic2NyaWJlcl1dKVxuICAgICAqL1xuICAgIHN0cmVhbU1hbmFnZXJzOiBTdHJlYW1NYW5hZ2VyW10gPSBbXTtcblxuICAgIC8qKlxuICAgICAqIE9iamVjdCBkZWZpbmluZyB0aGUgbWV0aG9kcyB0aGF0IHRoZSBjbGllbnQgaXMgYWJsZSB0byBjYWxsLiBUaGVzZSBhcmUgZGVmaW5lZCBieSB0aGUgcm9sZSBvZiB0aGUgdG9rZW4gdXNlZCB0byBjb25uZWN0IHRvIHRoZSBTZXNzaW9uLlxuICAgICAqIFRoaXMgb2JqZWN0IGlzIG9ubHkgZGVmaW5lZCBhZnRlciBbW1Nlc3Npb24uY29ubmVjdF1dIGhhcyBiZWVuIHN1Y2Nlc3NmdWxseSByZXNvbHZlZFxuICAgICAqL1xuICAgIGNhcGFiaWxpdGllczogQ2FwYWJpbGl0aWVzO1xuXG4gICAgLy8gVGhpcyBtYXAgaXMgb25seSB1c2VkIHRvIGF2b2lkIHJhY2UgY29uZGl0aW9uIGJldHdlZW4gJ2pvaW5Sb29tJyByZXNwb25zZSBhbmQgJ29uUGFydGljaXBhbnRQdWJsaXNoZWQnIG5vdGlmaWNhdGlvblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICByZW1vdGVTdHJlYW1zQ3JlYXRlZDogT2JqTWFwPGJvb2xlYW4+ID0ge307XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgcmVtb3RlQ29ubmVjdGlvbnM6IE9iak1hcDxDb25uZWN0aW9uPiA9IHt9O1xuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvcGVudmlkdTogT3BlblZpZHU7XG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIG9wdGlvbnM6IFNlc3Npb25PcHRpb25zO1xuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBzcGVha2luZ0V2ZW50c0VuYWJsZWQgPSBmYWxzZTtcblxuICAgIHByaXZhdGUgZWUgPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgY29uc3RydWN0b3Iob3BlbnZpZHU6IE9wZW5WaWR1KSB7XG4gICAgICAgIHRoaXMub3BlbnZpZHUgPSBvcGVudmlkdTtcbiAgICB9XG5cbiAgICBjb25uZWN0KHRva2VuOiBzdHJpbmcpOiBQcm9taXNlPGFueT47XG4gICAgY29ubmVjdCh0b2tlbjogc3RyaW5nLCBtZXRhZGF0YTogYW55KTogUHJvbWlzZTxhbnk+O1xuXG4gICAgLyoqXG4gICAgICogQ29ubmVjdHMgdG8gdGhlIHNlc3Npb24gdXNpbmcgYHRva2VuYC4gUGFyYW1ldGVyIGBtZXRhZGF0YWAgYWxsb3dzIHlvdSB0byBwYXNzIGV4dHJhIGRhdGEgdG8gc2hhcmUgd2l0aCBvdGhlciB1c2VycyB3aGVuXG4gICAgICogdGhleSByZWNlaXZlIGBzdHJlYW1DcmVhdGVkYCBldmVudC4gVGhlIHN0cnVjdHVyZSBvZiBgbWV0YWRhdGFgIHN0cmluZyBpcyB1cCB0byB5b3UgKG1heWJlIHNvbWUgc3RhbmRhcml6ZWQgZm9ybWF0XG4gICAgICogYXMgSlNPTiBvciBYTUwgaXMgYSBnb29kIGlkZWEpLCB0aGUgb25seSByZXN0cmljdGlvbiBpcyBhIG1heGltdW0gbGVuZ3RoIG9mIDEwMDAwIGNoYXJzLlxuICAgICAqXG4gICAgICogVGhpcyBtZXRhZGF0YSBpcyBub3QgY29uc2lkZXJlZCBzZWN1cmUsIGFzIGl0IGlzIGdlbmVyYXRlZCBpbiB0aGUgY2xpZW50IHNpZGUuIFRvIHBhc3Mgc2VjdXJpemVkIGRhdGEsIGFkZCBpdCBhcyBhIHBhcmFtZXRlciBpbiB0aGVcbiAgICAgKiB0b2tlbiBnZW5lcmF0aW9uIG9wZXJhdGlvbiAodGhyb3VnaCB0aGUgQVBJIFJFU1QsIG9wZW52aWR1LWphdmEtY2xpZW50IG9yIG9wZW52aWR1LW5vZGUtY2xpZW50KS5cbiAgICAgKlxuICAgICAqIE9ubHkgYWZ0ZXIgdGhlIHJldHVybmVkIFByb21pc2UgaXMgc3VjY2Vzc2Z1bGx5IHJlc29sdmVkIFtbU2Vzc2lvbi5jb25uZWN0aW9uXV0gb2JqZWN0IHdpbGwgYmUgYXZhaWxhYmxlIGFuZCBwcm9wZXJseSBkZWZpbmVkLlxuICAgICAqXG4gICAgICogIyMjIyBFdmVudHMgZGlzcGF0Y2hlZFxuICAgICAqXG4gICAgICogVGhlIFtbU2Vzc2lvbl1dIG9iamVjdCBvZiB0aGUgbG9jYWwgcGFydGljaXBhbnQgd2lsbCBmaXJzdCBkaXNwYXRjaCBvbmUgb3IgbW9yZSBgY29ubmVjdGlvbkNyZWF0ZWRgIGV2ZW50cyB1cG9uIHN1Y2Nlc3NmdWwgdGVybWluYXRpb24gb2YgdGhpcyBtZXRob2Q6XG4gICAgICogLSBGaXJzdCBvbmUgZm9yIHlvdXIgb3duIGxvY2FsIENvbm5lY3Rpb24gb2JqZWN0LCBzbyB5b3UgY2FuIHJldHJpZXZlIFtbU2Vzc2lvbi5jb25uZWN0aW9uXV0gcHJvcGVydHkuXG4gICAgICogLSBUaGVuIG9uZSBmb3IgZWFjaCByZW1vdGUgQ29ubmVjdGlvbiBwcmV2aW91c2x5IGNvbm5lY3RlZCB0byB0aGUgU2Vzc2lvbiwgaWYgYW55LiBBbnkgb3RoZXIgcmVtb3RlIHVzZXIgY29ubmVjdGluZyB0byB0aGUgU2Vzc2lvbiBhZnRlciB5b3UgaGF2ZVxuICAgICAqIHN1Y2Nlc3NmdWxseSBjb25uZWN0ZWQgd2lsbCBhbHNvIGRpc3BhdGNoIGEgYGNvbm5lY3Rpb25DcmVhdGVkYCBldmVudCB3aGVuIHRoZXkgZG8gc28uXG4gICAgICpcbiAgICAgKiBUaGUgW1tTZXNzaW9uXV0gb2JqZWN0IG9mIHRoZSBsb2NhbCBwYXJ0aWNpcGFudCB3aWxsIGFsc28gZGlzcGF0Y2ggYSBgc3RyZWFtQ3JlYXRlZGAgZXZlbnQgZm9yIGVhY2ggcmVtb3RlIGFjdGl2ZSBbW1B1Ymxpc2hlcl1dIHRoYXQgd2FzIGFscmVhZHkgc3RyZWFtaW5nXG4gICAgICogd2hlbiBjb25uZWN0aW5nLCBqdXN0IGFmdGVyIGRpc3BhdGNoaW5nIGFsbCByZW1vdGUgYGNvbm5lY3Rpb25DcmVhdGVkYCBldmVudHMuXG4gICAgICpcbiAgICAgKiBUaGUgW1tTZXNzaW9uXV0gb2JqZWN0IG9mIGV2ZXJ5IG90aGVyIHBhcnRpY2lwYW50IGNvbm5lY3RlZCB0byB0aGUgc2Vzc2lvbiB3aWxsIGRpc3BhdGNoIGEgYGNvbm5lY3Rpb25DcmVhdGVkYCBldmVudC5cbiAgICAgKlxuICAgICAqIFNlZSBbW0Nvbm5lY3Rpb25FdmVudF1dIGFuZCBbW1N0cmVhbUV2ZW50XV0gdG8gbGVhcm4gbW9yZS5cbiAgICAgKlxuICAgICAqIEByZXR1cm5zIEEgUHJvbWlzZSB0byB3aGljaCB5b3UgbXVzdCBzdWJzY3JpYmUgdGhhdCBpcyByZXNvbHZlZCBpZiB0aGUgdGhlIGNvbm5lY3Rpb24gdG8gdGhlIFNlc3Npb24gd2FzIHN1Y2Nlc3NmdWwgYW5kIHJlamVjdGVkIHdpdGggYW4gRXJyb3Igb2JqZWN0IGlmIG5vdFxuICAgICAqXG4gICAgICovXG4gICAgY29ubmVjdCh0b2tlbjogc3RyaW5nLCBtZXRhZGF0YT86IGFueSk6IFByb21pc2U8YW55PiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG5cbiAgICAgICAgICAgIHRoaXMucHJvY2Vzc1Rva2VuKHRva2VuKTtcblxuICAgICAgICAgICAgaWYgKHRoaXMub3BlbnZpZHUuY2hlY2tTeXN0ZW1SZXF1aXJlbWVudHMoKSkge1xuICAgICAgICAgICAgICAgIC8vIEVhcmx5IGNvbmZpZ3VyYXRpb24gdG8gZGVhY3RpdmF0ZSBhdXRvbWF0aWMgc3Vic2NyaXB0aW9uIHRvIHN0cmVhbXNcbiAgICAgICAgICAgICAgICB0aGlzLm9wdGlvbnMgPSB7XG4gICAgICAgICAgICAgICAgICAgIHNlc3Npb25JZDogdGhpcy5zZXNzaW9uSWQsXG4gICAgICAgICAgICAgICAgICAgIHBhcnRpY2lwYW50SWQ6IHRva2VuLFxuICAgICAgICAgICAgICAgICAgICBtZXRhZGF0YTogISFtZXRhZGF0YSA/IHRoaXMuc3RyaW5nQ2xpZW50TWV0YWRhdGEobWV0YWRhdGEpIDogJydcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIHRoaXMuY29ubmVjdEF1eCh0b2tlbikudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICB9KS5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJlamVjdChuZXcgT3BlblZpZHVFcnJvcihPcGVuVmlkdUVycm9yTmFtZS5CUk9XU0VSX05PVF9TVVBQT1JURUQsICdCcm93c2VyICcgKyBwbGF0Zm9ybS5uYW1lICsgJyAnICsgcGxhdGZvcm0udmVyc2lvbiArICcgaXMgbm90IHN1cHBvcnRlZCBpbiBPcGVuVmlkdScpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogTGVhdmVzIHRoZSBzZXNzaW9uLCBkZXN0cm95aW5nIGFsbCBzdHJlYW1zIGFuZCBkZWxldGluZyB0aGUgdXNlciBhcyBhIHBhcnRpY2lwYW50LlxuICAgICAqXG4gICAgICogIyMjIyBFdmVudHMgZGlzcGF0Y2hlZFxuICAgICAqXG4gICAgICogVGhlIFtbU2Vzc2lvbl1dIG9iamVjdCBvZiB0aGUgbG9jYWwgcGFydGljaXBhbnQgd2lsbCBkaXNwYXRjaCBhIGBzZXNzaW9uRGlzY29ubmVjdGVkYCBldmVudC5cbiAgICAgKiBUaGlzIGV2ZW50IHdpbGwgYXV0b21hdGljYWxseSB1bnN1YnNjcmliZSB0aGUgbGVhdmluZyBwYXJ0aWNpcGFudCBmcm9tIGV2ZXJ5IFN1YnNjcmliZXIgb2JqZWN0IG9mIHRoZSBzZXNzaW9uICh0aGlzIGluY2x1ZGVzIGNsb3NpbmcgdGhlIFdlYlJUQ1BlZXIgY29ubmVjdGlvbiBhbmQgZGlzcG9zaW5nIGFsbCBNZWRpYVN0cmVhbVRyYWNrcylcbiAgICAgKiBhbmQgYWxzbyBkZWxldGVzIGFueSBIVE1MIHZpZGVvIGVsZW1lbnQgYXNzb2NpYXRlZCB0byBlYWNoIFN1YnNjcmliZXIgKG9ubHkgdGhvc2UgW2NyZWF0ZWQgYnkgT3BlblZpZHUgQnJvd3Nlcl0oL2RvY3MvaG93LWRvLWkvbWFuYWdlLXZpZGVvcy8jbGV0LW9wZW52aWR1LXRha2UtY2FyZS1vZi10aGUtdmlkZW8tcGxheWVycykpLlxuICAgICAqIEZvciBldmVyeSB2aWRlbyByZW1vdmVkLCBlYWNoIFN1YnNjcmliZXIgb2JqZWN0IHdpbGwgZGlzcGF0Y2ggYSBgdmlkZW9FbGVtZW50RGVzdHJveWVkYCBldmVudC5cbiAgICAgKiBDYWxsIGBldmVudC5wcmV2ZW50RGVmYXVsdCgpYCB1cG9uIGV2ZW50IGBzZXNzaW9uRGlzY29ubmVjdGVkYCB0byBhdm9pZCB0aGlzIGJlaGF2aW9yIGFuZCB0YWtlIGNhcmUgb2YgZGlzcG9zaW5nIGFuZCBjbGVhbmluZyBhbGwgdGhlIFN1YnNjcmliZXIgb2JqZWN0cyB5b3Vyc2VsZi5cbiAgICAgKiBTZWUgW1tTZXNzaW9uRGlzY29ubmVjdGVkRXZlbnRdXSBhbmQgW1tWaWRlb0VsZW1lbnRFdmVudF1dIHRvIGxlYXJuIG1vcmUgdG8gbGVhcm4gbW9yZS5cbiAgICAgKlxuICAgICAqIFRoZSBbW1B1Ymxpc2hlcl1dIG9iamVjdCBvZiB0aGUgbG9jYWwgcGFydGljaXBhbnQgd2lsbCBkaXNwYXRjaCBhIGBzdHJlYW1EZXN0cm95ZWRgIGV2ZW50IGlmIHRoZXJlIGlzIGEgW1tQdWJsaXNoZXJdXSBvYmplY3QgcHVibGlzaGluZyB0byB0aGUgc2Vzc2lvbi5cbiAgICAgKiBUaGlzIGV2ZW50IHdpbGwgYXV0b21hdGljYWxseSBzdG9wIGFsbCBtZWRpYSB0cmFja3MgYW5kIGRlbGV0ZSBhbnkgSFRNTCB2aWRlbyBlbGVtZW50IGFzc29jaWF0ZWQgdG8gaXQgKG9ubHkgdGhvc2UgW2NyZWF0ZWQgYnkgT3BlblZpZHUgQnJvd3Nlcl0oL2RvY3MvaG93LWRvLWkvbWFuYWdlLXZpZGVvcy8jbGV0LW9wZW52aWR1LXRha2UtY2FyZS1vZi10aGUtdmlkZW8tcGxheWVycykpLlxuICAgICAqIEZvciBldmVyeSB2aWRlbyByZW1vdmVkLCB0aGUgUHVibGlzaGVyIG9iamVjdCB3aWxsIGRpc3BhdGNoIGEgYHZpZGVvRWxlbWVudERlc3Ryb3llZGAgZXZlbnQuXG4gICAgICogQ2FsbCBgZXZlbnQucHJldmVudERlZmF1bHQoKWAgdXBvbiBldmVudCBgc3RyZWFtRGVzdHJveWVkYCBpZiB5b3Ugd2FudCB0byBjbGVhbiB0aGUgUHVibGlzaGVyIG9iamVjdCBvbiB5b3VyIG93biBvciByZS1wdWJsaXNoIGl0IGluIGEgZGlmZmVyZW50IFNlc3Npb24gKHRvIGRvIHNvIGl0IGlzIGEgbWFuZGF0b3J5IHJlcXVpcmVtZW50IHRvIGNhbGwgYFNlc3Npb24udW5wdWJsaXNoKClgXG4gICAgICogb3IvYW5kIGBTZXNzaW9uLmRpc2Nvbm5lY3QoKWAgaW4gdGhlIHByZXZpb3VzIHNlc3Npb24pLiBTZWUgW1tTdHJlYW1FdmVudF1dIGFuZCBbW1ZpZGVvRWxlbWVudEV2ZW50XV0gdG8gbGVhcm4gbW9yZS5cbiAgICAgKlxuICAgICAqIFRoZSBbW1Nlc3Npb25dXSBvYmplY3Qgb2YgZXZlcnkgb3RoZXIgcGFydGljaXBhbnQgY29ubmVjdGVkIHRvIHRoZSBzZXNzaW9uIHdpbGwgZGlzcGF0Y2ggYSBgc3RyZWFtRGVzdHJveWVkYCBldmVudCBpZiB0aGUgZGlzY29ubmVjdGVkIHBhcnRpY2lwYW50IHdhcyBwdWJsaXNoaW5nLlxuICAgICAqIFRoaXMgZXZlbnQgd2lsbCBhdXRvbWF0aWNhbGx5IHVuc3Vic2NyaWJlIHRoZSBTdWJzY3JpYmVyIG9iamVjdCBmcm9tIHRoZSBzZXNzaW9uICh0aGlzIGluY2x1ZGVzIGNsb3NpbmcgdGhlIFdlYlJUQ1BlZXIgY29ubmVjdGlvbiBhbmQgZGlzcG9zaW5nIGFsbCBNZWRpYVN0cmVhbVRyYWNrcylcbiAgICAgKiBhbmQgYWxzbyBkZWxldGVzIGFueSBIVE1MIHZpZGVvIGVsZW1lbnQgYXNzb2NpYXRlZCB0byB0aGF0IFN1YnNjcmliZXIgKG9ubHkgdGhvc2UgW2NyZWF0ZWQgYnkgT3BlblZpZHUgQnJvd3Nlcl0oL2RvY3MvaG93LWRvLWkvbWFuYWdlLXZpZGVvcy8jbGV0LW9wZW52aWR1LXRha2UtY2FyZS1vZi10aGUtdmlkZW8tcGxheWVycykpLlxuICAgICAqIEZvciBldmVyeSB2aWRlbyByZW1vdmVkLCB0aGUgU3Vic2NyaWJlciBvYmplY3Qgd2lsbCBkaXNwYXRjaCBhIGB2aWRlb0VsZW1lbnREZXN0cm95ZWRgIGV2ZW50LlxuICAgICAqIENhbGwgYGV2ZW50LnByZXZlbnREZWZhdWx0KClgIHVwb24gZXZlbnQgYHN0cmVhbURlc3Ryb3llZGAgdG8gYXZvaWQgdGhpcyBkZWZhdWx0IGJlaGF2aW9yIGFuZCB0YWtlIGNhcmUgb2YgZGlzcG9zaW5nIGFuZCBjbGVhbmluZyB0aGUgU3Vic2NyaWJlciBvYmplY3QgeW91cnNlbGYuXG4gICAgICogU2VlIFtbU3RyZWFtRXZlbnRdXSBhbmQgW1tWaWRlb0VsZW1lbnRFdmVudF1dIHRvIGxlYXJuIG1vcmUuXG4gICAgICpcbiAgICAgKiBUaGUgW1tTZXNzaW9uXV0gb2JqZWN0IG9mIGV2ZXJ5IG90aGVyIHBhcnRpY2lwYW50IGNvbm5lY3RlZCB0byB0aGUgc2Vzc2lvbiB3aWxsIGRpc3BhdGNoIGEgYGNvbm5lY3Rpb25EZXN0cm95ZWRgIGV2ZW50IGluIGFueSBjYXNlLiBTZWUgW1tDb25uZWN0aW9uRXZlbnRdXSB0byBsZWFybiBtb3JlLlxuICAgICAqL1xuICAgIGRpc2Nvbm5lY3QoKTogdm9pZCB7XG4gICAgICAgIHRoaXMubGVhdmUoZmFsc2UsICdkaXNjb25uZWN0Jyk7XG4gICAgfVxuXG4gICAgc3Vic2NyaWJlKHN0cmVhbTogU3RyZWFtLCB0YXJnZXRFbGVtZW50OiBzdHJpbmcgfCBIVE1MRWxlbWVudCk6IFN1YnNjcmliZXI7XG4gICAgc3Vic2NyaWJlKHN0cmVhbTogU3RyZWFtLCB0YXJnZXRFbGVtZW50OiBzdHJpbmcgfCBIVE1MRWxlbWVudCwgcHJvcGVydGllczogU3Vic2NyaWJlclByb3BlcnRpZXMpOiBTdWJzY3JpYmVyO1xuICAgIHN1YnNjcmliZShzdHJlYW06IFN0cmVhbSwgdGFyZ2V0RWxlbWVudDogc3RyaW5nIHwgSFRNTEVsZW1lbnQsIGNvbXBsZXRpb25IYW5kbGVyOiAoZXJyb3I6IEVycm9yIHwgdW5kZWZpbmVkKSA9PiB2b2lkKTogU3Vic2NyaWJlcjtcbiAgICBzdWJzY3JpYmUoc3RyZWFtOiBTdHJlYW0sIHRhcmdldEVsZW1lbnQ6IHN0cmluZyB8IEhUTUxFbGVtZW50LCBwcm9wZXJ0aWVzOiBTdWJzY3JpYmVyUHJvcGVydGllcywgY29tcGxldGlvbkhhbmRsZXI6IChlcnJvcjogRXJyb3IgfCB1bmRlZmluZWQpID0+IHZvaWQpOiBTdWJzY3JpYmVyO1xuXG4gICAgLyoqXG4gICAgICogU3Vic2NyaWJlcyB0byBhIGBzdHJlYW1gLCBhZGRpbmcgYSBuZXcgSFRNTCB2aWRlbyBlbGVtZW50IHRvIERPTSB3aXRoIGBzdWJzY3JpYmVyUHJvcGVydGllc2Agc2V0dGluZ3MuIFRoaXMgbWV0aG9kIGlzIHVzdWFsbHkgY2FsbGVkIGluIHRoZSBjYWxsYmFjayBvZiBgc3RyZWFtQ3JlYXRlZGAgZXZlbnQuXG4gICAgICpcbiAgICAgKiAjIyMjIEV2ZW50cyBkaXNwYXRjaGVkXG4gICAgICpcbiAgICAgKiBUaGUgW1tTdWJzY3JpYmVyXV0gb2JqZWN0IHdpbGwgZGlzcGF0Y2ggYSBgdmlkZW9FbGVtZW50Q3JlYXRlZGAgZXZlbnQgb25jZSB0aGUgSFRNTCB2aWRlbyBlbGVtZW50IGhhcyBiZWVuIGFkZGVkIHRvIERPTSAob25seSBpZiB5b3VcbiAgICAgKiBbbGV0IE9wZW5WaWR1IHRha2UgY2FyZSBvZiB0aGUgdmlkZW8gcGxheWVyc10oL2RvY3MvaG93LWRvLWkvbWFuYWdlLXZpZGVvcy8jbGV0LW9wZW52aWR1LXRha2UtY2FyZS1vZi10aGUtdmlkZW8tcGxheWVycykpLiBTZWUgW1tWaWRlb0VsZW1lbnRFdmVudF1dIHRvIGxlYXJuIG1vcmUuXG4gICAgICpcbiAgICAgKiBUaGUgW1tTdWJzY3JpYmVyXV0gb2JqZWN0IHdpbGwgZGlzcGF0Y2ggYSBgc3RyZWFtUGxheWluZ2AgZXZlbnQgb25jZSB0aGUgcmVtb3RlIHN0cmVhbSBzdGFydHMgcGxheWluZy4gU2VlIFtbU3RyZWFtTWFuYWdlckV2ZW50XV0gdG8gbGVhcm4gbW9yZS5cbiAgICAgKlxuICAgICAqIEBwYXJhbSBzdHJlYW0gU3RyZWFtIG9iamVjdCB0byBzdWJzY3JpYmUgdG9cbiAgICAgKiBAcGFyYW0gdGFyZ2V0RWxlbWVudCBIVE1MIERPTSBlbGVtZW50IChvciBpdHMgYGlkYCBhdHRyaWJ1dGUpIGluIHdoaWNoIHRoZSB2aWRlbyBlbGVtZW50IG9mIHRoZSBTdWJzY3JpYmVyIHdpbGwgYmUgaW5zZXJ0ZWQgKHNlZSBbW1N1YnNjcmliZXJQcm9wZXJ0aWVzLmluc2VydE1vZGVdXSkuIElmICpudWxsKiBvciAqdW5kZWZpbmVkKiBubyBkZWZhdWx0IHZpZGVvIHdpbGwgYmUgY3JlYXRlZCBmb3IgdGhpcyBTdWJzY3JpYmVyLlxuICAgICAqIFlvdSBjYW4gYWx3YXlzIGNhbGwgbWV0aG9kIFtbU3Vic2NyaWJlci5hZGRWaWRlb0VsZW1lbnRdXSBvciBbW1N1YnNjcmliZXIuY3JlYXRlVmlkZW9FbGVtZW50XV0gdG8gbWFuYWdlIHRoZSB2aWRlbyBlbGVtZW50cyBvbiB5b3VyIG93biAoc2VlIFtNYW5hZ2UgdmlkZW8gcGxheWVyc10oL2RvY3MvaG93LWRvLWkvbWFuYWdlLXZpZGVvcykgc2VjdGlvbilcbiAgICAgKiBAcGFyYW0gY29tcGxldGlvbkhhbmRsZXIgYGVycm9yYCBwYXJhbWV0ZXIgaXMgbnVsbCBpZiBgc3Vic2NyaWJlYCBzdWNjZWVkcywgYW5kIGlzIGRlZmluZWQgaWYgaXQgZmFpbHMuXG4gICAgICovXG4gICAgc3Vic2NyaWJlKHN0cmVhbTogU3RyZWFtLCB0YXJnZXRFbGVtZW50OiBzdHJpbmcgfCBIVE1MRWxlbWVudCwgcGFyYW0zPzogKChlcnJvcjogRXJyb3IgfCB1bmRlZmluZWQpID0+IHZvaWQpIHwgU3Vic2NyaWJlclByb3BlcnRpZXMsIHBhcmFtND86ICgoZXJyb3I6IEVycm9yIHwgdW5kZWZpbmVkKSA9PiB2b2lkKSk6IFN1YnNjcmliZXIge1xuICAgICAgICBsZXQgcHJvcGVydGllczogU3Vic2NyaWJlclByb3BlcnRpZXMgPSB7fTtcbiAgICAgICAgaWYgKCEhcGFyYW0zICYmIHR5cGVvZiBwYXJhbTMgIT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgIHByb3BlcnRpZXMgPSB7XG4gICAgICAgICAgICAgICAgaW5zZXJ0TW9kZTogKHR5cGVvZiBwYXJhbTMuaW5zZXJ0TW9kZSAhPT0gJ3VuZGVmaW5lZCcpID8gKCh0eXBlb2YgcGFyYW0zLmluc2VydE1vZGUgPT09ICdzdHJpbmcnKSA/IFZpZGVvSW5zZXJ0TW9kZVtwYXJhbTMuaW5zZXJ0TW9kZV0gOiBwcm9wZXJ0aWVzLmluc2VydE1vZGUpIDogVmlkZW9JbnNlcnRNb2RlLkFQUEVORCxcbiAgICAgICAgICAgICAgICBzdWJzY3JpYmVUb0F1ZGlvOiAodHlwZW9mIHBhcmFtMy5zdWJzY3JpYmVUb0F1ZGlvICE9PSAndW5kZWZpbmVkJykgPyBwYXJhbTMuc3Vic2NyaWJlVG9BdWRpbyA6IHRydWUsXG4gICAgICAgICAgICAgICAgc3Vic2NyaWJlVG9WaWRlbzogKHR5cGVvZiBwYXJhbTMuc3Vic2NyaWJlVG9WaWRlbyAhPT0gJ3VuZGVmaW5lZCcpID8gcGFyYW0zLnN1YnNjcmliZVRvVmlkZW8gOiB0cnVlXG4gICAgICAgICAgICB9O1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcHJvcGVydGllcyA9IHtcbiAgICAgICAgICAgICAgICBpbnNlcnRNb2RlOiBWaWRlb0luc2VydE1vZGUuQVBQRU5ELFxuICAgICAgICAgICAgICAgIHN1YnNjcmliZVRvQXVkaW86IHRydWUsXG4gICAgICAgICAgICAgICAgc3Vic2NyaWJlVG9WaWRlbzogdHJ1ZVxuICAgICAgICAgICAgfTtcbiAgICAgICAgfVxuXG4gICAgICAgIGxldCBjb21wbGV0aW9uSGFuZGxlcjogKGVycm9yOiBFcnJvciB8IHVuZGVmaW5lZCkgPT4gdm9pZDtcbiAgICAgICAgaWYgKCEhcGFyYW0zICYmICh0eXBlb2YgcGFyYW0zID09PSAnZnVuY3Rpb24nKSkge1xuICAgICAgICAgICAgY29tcGxldGlvbkhhbmRsZXIgPSBwYXJhbTM7XG4gICAgICAgIH0gZWxzZSBpZiAoISFwYXJhbTQpIHtcbiAgICAgICAgICAgIGNvbXBsZXRpb25IYW5kbGVyID0gcGFyYW00O1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc29sZS5pbmZvKCdTdWJzY3JpYmluZyB0byAnICsgc3RyZWFtLmNvbm5lY3Rpb24uY29ubmVjdGlvbklkKTtcblxuICAgICAgICBzdHJlYW0uc3Vic2NyaWJlKClcbiAgICAgICAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oJ1N1YnNjcmliZWQgY29ycmVjdGx5IHRvICcgKyBzdHJlYW0uY29ubmVjdGlvbi5jb25uZWN0aW9uSWQpO1xuICAgICAgICAgICAgICAgIGlmIChjb21wbGV0aW9uSGFuZGxlciAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbXBsZXRpb25IYW5kbGVyKHVuZGVmaW5lZCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKGNvbXBsZXRpb25IYW5kbGVyICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgY29tcGxldGlvbkhhbmRsZXIoZXJyb3IpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICBjb25zdCBzdWJzY3JpYmVyID0gbmV3IFN1YnNjcmliZXIoc3RyZWFtLCB0YXJnZXRFbGVtZW50LCBwcm9wZXJ0aWVzKTtcbiAgICAgICAgaWYgKCEhc3Vic2NyaWJlci50YXJnZXRFbGVtZW50KSB7XG4gICAgICAgICAgICBzdHJlYW0uc3RyZWFtTWFuYWdlci5jcmVhdGVWaWRlb0VsZW1lbnQoc3Vic2NyaWJlci50YXJnZXRFbGVtZW50LCA8VmlkZW9JbnNlcnRNb2RlPnByb3BlcnRpZXMuaW5zZXJ0TW9kZSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHN1YnNjcmliZXI7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBQcm9taXNpZmllZCB2ZXJzaW9uIG9mIFtbU2Vzc2lvbi5zdWJzY3JpYmVdXVxuICAgICAqL1xuICAgIHN1YnNjcmliZUFzeW5jKHN0cmVhbTogU3RyZWFtLCB0YXJnZXRFbGVtZW50OiBzdHJpbmcgfCBIVE1MRWxlbWVudCk6IFByb21pc2U8U3Vic2NyaWJlcj47XG4gICAgc3Vic2NyaWJlQXN5bmMoc3RyZWFtOiBTdHJlYW0sIHRhcmdldEVsZW1lbnQ6IHN0cmluZyB8IEhUTUxFbGVtZW50LCBwcm9wZXJ0aWVzOiBTdWJzY3JpYmVyUHJvcGVydGllcyk6IFByb21pc2U8U3Vic2NyaWJlcj47XG5cbiAgICBzdWJzY3JpYmVBc3luYyhzdHJlYW06IFN0cmVhbSwgdGFyZ2V0RWxlbWVudDogc3RyaW5nIHwgSFRNTEVsZW1lbnQsIHByb3BlcnRpZXM/OiBTdWJzY3JpYmVyUHJvcGVydGllcyk6IFByb21pc2U8U3Vic2NyaWJlcj4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2U8U3Vic2NyaWJlcj4oKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuXG4gICAgICAgICAgICBsZXQgc3Vic2NyaWJlcjogU3Vic2NyaWJlcjtcblxuICAgICAgICAgICAgY29uc3QgY2FsbGJhY2sgPSAoZXJyb3I6IEVycm9yKSA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKCEhZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICByZXNvbHZlKHN1YnNjcmliZXIpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIGlmICghIXByb3BlcnRpZXMpIHtcbiAgICAgICAgICAgICAgICBzdWJzY3JpYmVyID0gdGhpcy5zdWJzY3JpYmUoc3RyZWFtLCB0YXJnZXRFbGVtZW50LCBwcm9wZXJ0aWVzLCBjYWxsYmFjayk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHN1YnNjcmliZXIgPSB0aGlzLnN1YnNjcmliZShzdHJlYW0sIHRhcmdldEVsZW1lbnQsIGNhbGxiYWNrKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICB9KTtcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFVuc3Vic2NyaWJlcyBmcm9tIGBzdWJzY3JpYmVyYCwgYXV0b21hdGljYWxseSByZW1vdmluZyBpdHMgYXNzb2NpYXRlZCBIVE1MIHZpZGVvIGVsZW1lbnRzLlxuICAgICAqXG4gICAgICogIyMjIyBFdmVudHMgZGlzcGF0Y2hlZFxuICAgICAqXG4gICAgICogVGhlIFtbU3Vic2NyaWJlcl1dIG9iamVjdCB3aWxsIGRpc3BhdGNoIGEgYHZpZGVvRWxlbWVudERlc3Ryb3llZGAgZXZlbnQgZm9yIGVhY2ggdmlkZW8gYXNzb2NpYXRlZCB0byBpdCB0aGF0IHdhcyByZW1vdmVkIGZyb20gRE9NLlxuICAgICAqIE9ubHkgdmlkZW9zIFtjcmVhdGVkIGJ5IE9wZW5WaWR1IEJyb3dzZXJdKC9kb2NzL2hvdy1kby1pL21hbmFnZS12aWRlb3MvI2xldC1vcGVudmlkdS10YWtlLWNhcmUtb2YtdGhlLXZpZGVvLXBsYXllcnMpKSB3aWxsIGJlIGF1dG9tYXRpY2FsbHkgcmVtb3ZlZFxuICAgICAqXG4gICAgICogU2VlIFtbVmlkZW9FbGVtZW50RXZlbnRdXSB0byBsZWFybiBtb3JlXG4gICAgICovXG4gICAgdW5zdWJzY3JpYmUoc3Vic2NyaWJlcjogU3Vic2NyaWJlcik6IHZvaWQge1xuICAgICAgICBjb25zdCBjb25uZWN0aW9uSWQgPSBzdWJzY3JpYmVyLnN0cmVhbS5jb25uZWN0aW9uLmNvbm5lY3Rpb25JZDtcblxuICAgICAgICBjb25zb2xlLmluZm8oJ1Vuc3Vic2NyaWJpbmcgZnJvbSAnICsgY29ubmVjdGlvbklkKTtcblxuICAgICAgICB0aGlzLm9wZW52aWR1LnNlbmRSZXF1ZXN0KFxuICAgICAgICAgICAgJ3Vuc3Vic2NyaWJlRnJvbVZpZGVvJyxcbiAgICAgICAgICAgIHsgc2VuZGVyOiBzdWJzY3JpYmVyLnN0cmVhbS5jb25uZWN0aW9uLmNvbm5lY3Rpb25JZCB9LFxuICAgICAgICAgICAgKGVycm9yLCByZXNwb25zZSkgPT4ge1xuICAgICAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKCdFcnJvciB1bnN1YnNjcmliaW5nIGZyb20gJyArIGNvbm5lY3Rpb25JZCwgZXJyb3IpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbygnVW5zdWJzY3JpYmVkIGNvcnJlY3RseSBmcm9tICcgKyBjb25uZWN0aW9uSWQpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBzdWJzY3JpYmVyLnN0cmVhbS5kaXNwb3NlV2ViUnRjUGVlcigpO1xuICAgICAgICAgICAgICAgIHN1YnNjcmliZXIuc3RyZWFtLmRpc3Bvc2VNZWRpYVN0cmVhbSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICApO1xuICAgICAgICBzdWJzY3JpYmVyLnN0cmVhbS5zdHJlYW1NYW5hZ2VyLnJlbW92ZUFsbFZpZGVvcygpO1xuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogUHVibGlzaGVzIHRvIHRoZSBTZXNzaW9uIHRoZSBQdWJsaXNoZXIgb2JqZWN0XG4gICAgICpcbiAgICAgKiAjIyMjIEV2ZW50cyBkaXNwYXRjaGVkXG4gICAgICpcbiAgICAgKiBUaGUgbG9jYWwgW1tQdWJsaXNoZXJdXSBvYmplY3Qgd2lsbCBkaXNwYXRjaCBhIGBzdHJlYW1DcmVhdGVkYCBldmVudCB1cG9uIHN1Y2Nlc3NmdWwgdGVybWluYXRpb24gb2YgdGhpcyBtZXRob2QuIFNlZSBbW1N0cmVhbUV2ZW50XV0gdG8gbGVhcm4gbW9yZS5cbiAgICAgKlxuICAgICAqIFRoZSBsb2NhbCBbW1B1Ymxpc2hlcl1dIG9iamVjdCB3aWxsIGRpc3BhdGNoIGEgYHN0cmVhbVBsYXlpbmdgIG9uY2UgdGhlIG1lZGlhIHN0cmVhbSBzdGFydHMgcGxheWluZy4gU2VlIFtbU3RyZWFtTWFuYWdlckV2ZW50XV0gdG8gbGVhcm4gbW9yZS5cbiAgICAgKlxuICAgICAqIFRoZSBbW1Nlc3Npb25dXSBvYmplY3Qgb2YgZXZlcnkgb3RoZXIgcGFydGljaXBhbnQgY29ubmVjdGVkIHRvIHRoZSBzZXNzaW9uIHdpbGwgZGlzcGF0Y2ggYSBgc3RyZWFtQ3JlYXRlZGAgZXZlbnQgc28gdGhleSBjYW4gc3Vic2NyaWJlIHRvIGl0LiBTZWUgW1tTdHJlYW1FdmVudF1dIHRvIGxlYXJuIG1vcmUuXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyBBIFByb21pc2UgKHRvIHdoaWNoIHlvdSBjYW4gb3B0aW9uYWxseSBzdWJzY3JpYmUgdG8pIHRoYXQgaXMgcmVzb2x2ZWQgb25seSBhZnRlciB0aGUgcHVibGlzaGVyIHdhcyBzdWNjZXNzZnVsbHkgcHVibGlzaGVkIGFuZCByZWplY3RlZCB3aXRoIGFuIEVycm9yIG9iamVjdCBpZiBub3RcbiAgICAgKi9cbiAgICBwdWJsaXNoKHB1Ymxpc2hlcjogUHVibGlzaGVyKTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIHB1Ymxpc2hlci5zZXNzaW9uID0gdGhpcztcbiAgICAgICAgICAgIHB1Ymxpc2hlci5zdHJlYW0uc2Vzc2lvbiA9IHRoaXM7XG5cbiAgICAgICAgICAgIGlmICghcHVibGlzaGVyLnN0cmVhbS5wdWJsaXNoZWRPbmNlKSB7XG4gICAgICAgICAgICAgICAgLy8gJ1Nlc3Npb24udW5wdWJsaXNoKFB1Ymxpc2hlciknIGhhcyBOT1QgYmVlbiBjYWxsZWRcbiAgICAgICAgICAgICAgICB0aGlzLmNvbm5lY3Rpb24uYWRkU3RyZWFtKHB1Ymxpc2hlci5zdHJlYW0pO1xuICAgICAgICAgICAgICAgIHB1Ymxpc2hlci5zdHJlYW0ucHVibGlzaCgpXG4gICAgICAgICAgICAgICAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAvLyAnU2Vzc2lvbi51bnB1Ymxpc2goUHVibGlzaGVyKScgaGFzIGJlZW4gY2FsbGVkLiBNdXN0IGluaXRpYWxpemUgYWdhaW4gUHVibGlzaGVyXG4gICAgICAgICAgICAgICAgcHVibGlzaGVyLmluaXRpYWxpemUoKVxuICAgICAgICAgICAgICAgICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbm5lY3Rpb24uYWRkU3RyZWFtKHB1Ymxpc2hlci5zdHJlYW0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgcHVibGlzaGVyLnJlZXN0YWJsaXNoU3RyZWFtUGxheWluZ0V2ZW50KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBwdWJsaXNoZXIuc3RyZWFtLnB1Ymxpc2goKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgfSkuY2F0Y2goKGVycm9yKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBVbnB1Ymxpc2hlcyBmcm9tIHRoZSBTZXNzaW9uIHRoZSBQdWJsaXNoZXIgb2JqZWN0LlxuICAgICAqXG4gICAgICogIyMjIyBFdmVudHMgZGlzcGF0Y2hlZFxuICAgICAqXG4gICAgICogVGhlIFtbUHVibGlzaGVyXV0gb2JqZWN0IG9mIHRoZSBsb2NhbCBwYXJ0aWNpcGFudCB3aWxsIGRpc3BhdGNoIGEgYHN0cmVhbURlc3Ryb3llZGAgZXZlbnQuXG4gICAgICogVGhpcyBldmVudCB3aWxsIGF1dG9tYXRpY2FsbHkgc3RvcCBhbGwgbWVkaWEgdHJhY2tzIGFuZCBkZWxldGUgYW55IEhUTUwgdmlkZW8gZWxlbWVudCBhc3NvY2lhdGVkIHRvIHRoaXMgUHVibGlzaGVyXG4gICAgICogKG9ubHkgdGhvc2UgdmlkZW9zIFtjcmVhdGVkIGJ5IE9wZW5WaWR1IEJyb3dzZXJdKC9kb2NzL2hvdy1kby1pL21hbmFnZS12aWRlb3MvI2xldC1vcGVudmlkdS10YWtlLWNhcmUtb2YtdGhlLXZpZGVvLXBsYXllcnMpKS5cbiAgICAgKiBGb3IgZXZlcnkgdmlkZW8gcmVtb3ZlZCwgdGhlIFB1Ymxpc2hlciBvYmplY3Qgd2lsbCBkaXNwYXRjaCBhIGB2aWRlb0VsZW1lbnREZXN0cm95ZWRgIGV2ZW50LlxuICAgICAqIENhbGwgYGV2ZW50LnByZXZlbnREZWZhdWx0KClgIHVwb24gZXZlbnQgYHN0cmVhbURlc3Ryb3llZGAgaWYgeW91IHdhbnQgdG8gY2xlYW4gdGhlIFB1Ymxpc2hlciBvYmplY3Qgb24geW91ciBvd24gb3IgcmUtcHVibGlzaCBpdCBpbiBhIGRpZmZlcmVudCBTZXNzaW9uLlxuICAgICAqXG4gICAgICogVGhlIFtbU2Vzc2lvbl1dIG9iamVjdCBvZiBldmVyeSBvdGhlciBwYXJ0aWNpcGFudCBjb25uZWN0ZWQgdG8gdGhlIHNlc3Npb24gd2lsbCBkaXNwYXRjaCBhIGBzdHJlYW1EZXN0cm95ZWRgIGV2ZW50LlxuICAgICAqIFRoaXMgZXZlbnQgd2lsbCBhdXRvbWF0aWNhbGx5IHVuc3Vic2NyaWJlIHRoZSBTdWJzY3JpYmVyIG9iamVjdCBmcm9tIHRoZSBzZXNzaW9uICh0aGlzIGluY2x1ZGVzIGNsb3NpbmcgdGhlIFdlYlJUQ1BlZXIgY29ubmVjdGlvbiBhbmQgZGlzcG9zaW5nIGFsbCBNZWRpYVN0cmVhbVRyYWNrcykgYW5kXG4gICAgICogZGVsZXRlIGFueSBIVE1MIHZpZGVvIGVsZW1lbnQgYXNzb2NpYXRlZCB0byBpdCAob25seSB0aG9zZSBbY3JlYXRlZCBieSBPcGVuVmlkdSBCcm93c2VyXSgvZG9jcy9ob3ctZG8taS9tYW5hZ2UtdmlkZW9zLyNsZXQtb3BlbnZpZHUtdGFrZS1jYXJlLW9mLXRoZS12aWRlby1wbGF5ZXJzKSkuXG4gICAgICogRm9yIGV2ZXJ5IHZpZGVvIHJlbW92ZWQsIHRoZSBTdWJzY3JpYmVyIG9iamVjdCB3aWxsIGRpc3BhdGNoIGEgYHZpZGVvRWxlbWVudERlc3Ryb3llZGAgZXZlbnQuXG4gICAgICogQ2FsbCBgZXZlbnQucHJldmVudERlZmF1bHQoKWAgdXBvbiBldmVudCBgc3RyZWFtRGVzdHJveWVkYCB0byBhdm9pZCB0aGlzIGRlZmF1bHQgYmVoYXZpb3IgYW5kIHRha2UgY2FyZSBvZiBkaXNwb3NpbmcgYW5kIGNsZWFuaW5nIHRoZSBTdWJzY3JpYmVyIG9iamVjdCBvbiB5b3VyIG93bi5cbiAgICAgKlxuICAgICAqIFNlZSBbW1N0cmVhbUV2ZW50XV0gYW5kIFtbVmlkZW9FbGVtZW50RXZlbnRdXSB0byBsZWFybiBtb3JlLlxuICAgICAqL1xuICAgIHVucHVibGlzaChwdWJsaXNoZXI6IFB1Ymxpc2hlcik6IHZvaWQge1xuXG4gICAgICAgIGNvbnN0IHN0cmVhbSA9IHB1Ymxpc2hlci5zdHJlYW07XG5cbiAgICAgICAgaWYgKCFzdHJlYW0uY29ubmVjdGlvbikge1xuICAgICAgICAgICAgY29uc29sZS5lcnJvcignVGhlIGFzc29jaWF0ZWQgQ29ubmVjdGlvbiBvYmplY3Qgb2YgdGhpcyBQdWJsaXNoZXIgaXMgbnVsbCcsIHN0cmVhbSk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH0gZWxzZSBpZiAoc3RyZWFtLmNvbm5lY3Rpb24gIT09IHRoaXMuY29ubmVjdGlvbikge1xuICAgICAgICAgICAgY29uc29sZS5lcnJvcignVGhlIGFzc29jaWF0ZWQgQ29ubmVjdGlvbiBvYmplY3Qgb2YgdGhpcyBQdWJsaXNoZXIgaXMgbm90IHlvdXIgbG9jYWwgQ29ubmVjdGlvbi4nICtcbiAgICAgICAgICAgICAgICBcIk9ubHkgbW9kZXJhdG9ycyBjYW4gZm9yY2UgdW5wdWJsaXNoIG9uIHJlbW90ZSBTdHJlYW1zIHZpYSAnZm9yY2VVbnB1Ymxpc2gnIG1ldGhvZFwiLCBzdHJlYW0pO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9IGVsc2Uge1xuXG4gICAgICAgICAgICBjb25zb2xlLmluZm8oJ1VucHVibGlzaGluZyBsb2NhbCBtZWRpYSAoJyArIHN0cmVhbS5jb25uZWN0aW9uLmNvbm5lY3Rpb25JZCArICcpJyk7XG5cbiAgICAgICAgICAgIHRoaXMub3BlbnZpZHUuc2VuZFJlcXVlc3QoJ3VucHVibGlzaFZpZGVvJywgKGVycm9yLCByZXNwb25zZSkgPT4ge1xuICAgICAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKGVycm9yKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oJ01lZGlhIHVucHVibGlzaGVkIGNvcnJlY3RseScpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICBzdHJlYW0uZGlzcG9zZVdlYlJ0Y1BlZXIoKTtcbiAgICAgICAgICAgIGRlbGV0ZSBzdHJlYW0uY29ubmVjdGlvbi5zdHJlYW07XG5cbiAgICAgICAgICAgIGNvbnN0IHN0cmVhbUV2ZW50ID0gbmV3IFN0cmVhbUV2ZW50KHRydWUsIHB1Ymxpc2hlciwgJ3N0cmVhbURlc3Ryb3llZCcsIHB1Ymxpc2hlci5zdHJlYW0sICd1bnB1Ymxpc2gnKTtcbiAgICAgICAgICAgIHB1Ymxpc2hlci5lbWl0RXZlbnQoJ3N0cmVhbURlc3Ryb3llZCcsIFtzdHJlYW1FdmVudF0pO1xuICAgICAgICAgICAgc3RyZWFtRXZlbnQuY2FsbERlZmF1bHRCZWhhdmlvcigpO1xuICAgICAgICB9XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBGb3JjZXMgc29tZSB1c2VyIHRvIGxlYXZlIHRoZSBzZXNzaW9uXG4gICAgICpcbiAgICAgKiAjIyMjIEV2ZW50cyBkaXNwYXRjaGVkXG4gICAgICpcbiAgICAgKiBUaGUgYmVoYXZpb3IgaXMgdGhlIHNhbWUgYXMgd2hlbiBzb21lIHVzZXIgY2FsbHMgW1tTZXNzaW9uLmRpc2Nvbm5lY3RdXSwgYnV0IGByZWFzb25gIHByb3BlcnR5IGluIGFsbCBldmVudHMgd2lsbCBiZSBgXCJmb3JjZURpc2Nvbm5lY3RCeVVzZXJcImAuXG4gICAgICpcbiAgICAgKiBUaGUgW1tTZXNzaW9uXV0gb2JqZWN0IG9mIGV2ZXJ5IHBhcnRpY2lwYW50IHdpbGwgZGlzcGF0Y2ggYSBgc3RyZWFtRGVzdHJveWVkYCBldmVudCBpZiB0aGUgZXZpY3RlZCB1c2VyIHdhcyBwdWJsaXNoaW5nIGEgc3RyZWFtLCB3aXRoIHByb3BlcnR5IGByZWFzb25gIHNldCB0byBgXCJmb3JjZURpc2Nvbm5lY3RCeVVzZXJcImAuXG4gICAgICogVGhlIFtbU2Vzc2lvbl1dIG9iamVjdCBvZiBldmVyeSBwYXJ0aWNpcGFudCBleGNlcHQgdGhlIGV2aWN0ZWQgb25lIHdpbGwgZGlzcGF0Y2ggYSBgY29ubmVjdGlvbkRlc3Ryb3llZGAgZXZlbnQgZm9yIHRoZSBldmljdGVkIHVzZXIsIHdpdGggcHJvcGVydHkgYHJlYXNvbmAgc2V0IHRvIGBcImZvcmNlRGlzY29ubmVjdEJ5VXNlclwiYC5cbiAgICAgKlxuICAgICAqIElmIGFueSwgdGhlIFtbUHVibGlzaGVyXV0gb2JqZWN0IG9mIHRoZSBldmljdGVkIHBhcnRpY2lwYW50IHdpbGwgYWxzbyBkaXNwYXRjaCBhIGBzdHJlYW1EZXN0cm95ZWRgIGV2ZW50IHdpdGggcHJvcGVydHkgYHJlYXNvbmAgc2V0IHRvIGBcImZvcmNlRGlzY29ubmVjdEJ5VXNlclwiYC5cbiAgICAgKiBUaGUgW1tTZXNzaW9uXV0gb2JqZWN0IG9mIHRoZSBldmljdGVkIHBhcnRpY2lwYW50IHdpbGwgZGlzcGF0Y2ggYSBgc2Vzc2lvbkRpc2Nvbm5lY3RlZGAgZXZlbnQgd2l0aCBwcm9wZXJ0eSBgcmVhc29uYCBzZXQgdG8gYFwiZm9yY2VEaXNjb25uZWN0QnlVc2VyXCJgLlxuICAgICAqXG4gICAgICogU2VlIFtbU3RyZWFtRXZlbnRdXSwgW1tDb25uZWN0aW9uRXZlbnRdXSBhbmQgW1tTZXNzaW9uRGlzY29ubmVjdGVkRXZlbnRdXSB0byBsZWFybiBtb3JlLlxuICAgICAqXG4gICAgICogQHJldHVybnMgQSBQcm9taXNlICh0byB3aGljaCB5b3UgY2FuIG9wdGlvbmFsbHkgc3Vic2NyaWJlIHRvKSB0aGF0IGlzIHJlc29sdmVkIG9ubHkgYWZ0ZXIgdGhlIHBhcnRpY2lwYW50IGhhcyBiZWVuIHN1Y2Nlc3NmdWxseSBldmljdGVkIGZyb20gdGhlIHNlc3Npb24gYW5kIHJlamVjdGVkIHdpdGggYW4gRXJyb3Igb2JqZWN0IGlmIG5vdFxuICAgICAqL1xuICAgIGZvcmNlRGlzY29ubmVjdChjb25uZWN0aW9uOiBDb25uZWN0aW9uKTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIGNvbnNvbGUuaW5mbygnRm9yY2luZyBkaXNjb25uZWN0IGZvciBjb25uZWN0aW9uICcgKyBjb25uZWN0aW9uLmNvbm5lY3Rpb25JZCk7XG4gICAgICAgICAgICB0aGlzLm9wZW52aWR1LnNlbmRSZXF1ZXN0KFxuICAgICAgICAgICAgICAgICdmb3JjZURpc2Nvbm5lY3QnLFxuICAgICAgICAgICAgICAgIHsgY29ubmVjdGlvbklkOiBjb25uZWN0aW9uLmNvbm5lY3Rpb25JZCB9LFxuICAgICAgICAgICAgICAgIChlcnJvciwgcmVzcG9uc2UpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKCdFcnJvciBmb3JjaW5nIGRpc2Nvbm5lY3QgZm9yIENvbm5lY3Rpb24gJyArIGNvbm5lY3Rpb24uY29ubmVjdGlvbklkLCBlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZXJyb3IuY29kZSA9PT0gNDAxKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KG5ldyBPcGVuVmlkdUVycm9yKE9wZW5WaWR1RXJyb3JOYW1lLk9QRU5WSURVX1BFUk1JU1NJT05fREVOSUVELCBcIllvdSBkb24ndCBoYXZlIHBlcm1pc3Npb25zIHRvIGZvcmNlIGEgZGlzY29ubmVjdGlvblwiKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oJ0ZvcmNpbmcgZGlzY29ubmVjdCBjb3JyZWN0bHkgZm9yIENvbm5lY3Rpb24gJyArIGNvbm5lY3Rpb24uY29ubmVjdGlvbklkKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogRm9yY2VzIHNvbWUgdXNlciB0byB1bnB1Ymxpc2ggYSBTdHJlYW1cbiAgICAgKlxuICAgICAqICMjIyMgRXZlbnRzIGRpc3BhdGNoZWRcbiAgICAgKlxuICAgICAqIFRoZSBiZWhhdmlvciBpcyB0aGUgc2FtZSBhcyB3aGVuIHNvbWUgdXNlciBjYWxscyBbW1Nlc3Npb24udW5wdWJsaXNoXV0sIGJ1dCBgcmVhc29uYCBwcm9wZXJ0eSBpbiBhbGwgZXZlbnRzIHdpbGwgYmUgYFwiZm9yY2VVbnB1Ymxpc2hCeVVzZXJcImBcbiAgICAgKlxuICAgICAqIFRoZSBbW1Nlc3Npb25dXSBvYmplY3Qgb2YgZXZlcnkgcGFydGljaXBhbnQgd2lsbCBkaXNwYXRjaCBhIGBzdHJlYW1EZXN0cm95ZWRgIGV2ZW50IHdpdGggcHJvcGVydHkgYHJlYXNvbmAgc2V0IHRvIGBcImZvcmNlRGlzY29ubmVjdEJ5VXNlclwiYFxuICAgICAqXG4gICAgICogVGhlIFtbUHVibGlzaGVyXV0gb2JqZWN0IG9mIHRoZSBhZmZlY3RlZCBwYXJ0aWNpcGFudCB3aWxsIGFsc28gZGlzcGF0Y2ggYSBgc3RyZWFtRGVzdHJveWVkYCBldmVudCB3aXRoIHByb3BlcnR5IGByZWFzb25gIHNldCB0byBgXCJmb3JjZURpc2Nvbm5lY3RCeVVzZXJcImBcbiAgICAgKlxuICAgICAqIFNlZSBbW1N0cmVhbUV2ZW50XV0gdG8gbGVhcm4gbW9yZS5cbiAgICAgKlxuICAgICAqIEByZXR1cm5zIEEgUHJvbWlzZSAodG8gd2hpY2ggeW91IGNhbiBvcHRpb25hbGx5IHN1YnNjcmliZSB0bykgdGhhdCBpcyByZXNvbHZlZCBvbmx5IGFmdGVyIHRoZSByZW1vdGUgU3RyZWFtIGhhcyBiZWVuIHN1Y2Nlc3NmdWxseSB1bnB1Ymxpc2hlZCBmcm9tIHRoZSBzZXNzaW9uIGFuZCByZWplY3RlZCB3aXRoIGFuIEVycm9yIG9iamVjdCBpZiBub3RcbiAgICAgKi9cbiAgICBmb3JjZVVucHVibGlzaChzdHJlYW06IFN0cmVhbSk6IFByb21pc2U8YW55PiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICBjb25zb2xlLmluZm8oJ0ZvcmNpbmcgdW5wdWJsaXNoIGZvciBzdHJlYW0gJyArIHN0cmVhbS5zdHJlYW1JZCk7XG4gICAgICAgICAgICB0aGlzLm9wZW52aWR1LnNlbmRSZXF1ZXN0KFxuICAgICAgICAgICAgICAgICdmb3JjZVVucHVibGlzaCcsXG4gICAgICAgICAgICAgICAgeyBzdHJlYW1JZDogc3RyZWFtLnN0cmVhbUlkIH0sXG4gICAgICAgICAgICAgICAgKGVycm9yLCByZXNwb25zZSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBpZiAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ0Vycm9yIGZvcmNpbmcgdW5wdWJsaXNoIGZvciBTdHJlYW0gJyArIHN0cmVhbS5zdHJlYW1JZCwgZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yLmNvZGUgPT09IDQwMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChuZXcgT3BlblZpZHVFcnJvcihPcGVuVmlkdUVycm9yTmFtZS5PUEVOVklEVV9QRVJNSVNTSU9OX0RFTklFRCwgXCJZb3UgZG9uJ3QgaGF2ZSBwZXJtaXNzaW9ucyB0byBmb3JjZSBhbiB1bnB1Ymxpc2hpbmdcIikpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5pbmZvKCdGb3JjaW5nIHVucHVibGlzaCBjb3JyZWN0bHkgZm9yIFN0cmVhbSAnICsgc3RyZWFtLnN0cmVhbUlkKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogU2VuZHMgb25lIHNpZ25hbC4gYHNpZ25hbGAgb2JqZWN0IGhhcyB0aGUgZm9sbG93aW5nIG9wdGlvbmFsIHByb3BlcnRpZXM6XG4gICAgICogYGBganNvblxuICAgICAqIHtkYXRhOnN0cmluZywgdG86Q29ubmVjdGlvbltdLCB0eXBlOnN0cmluZ31cbiAgICAgKiBgYGBcbiAgICAgKiBBbGwgdXNlcnMgc3Vic2NyaWJlZCB0byB0aGF0IHNpZ25hbCAoYHNlc3Npb24ub24oJ3NpZ25hbDp0eXBlJywgLi4uKWAgb3IgYHNlc3Npb24ub24oJ3NpZ25hbCcsIC4uLilgIGZvciBhbGwgc2lnbmFscykgYW5kIHdob3NlIENvbm5lY3Rpb24gb2JqZWN0cyBhcmUgaW4gYHRvYCBhcnJheSB3aWxsIHJlY2VpdmUgaXQuIFRoZWlyIGxvY2FsXG4gICAgICogU2Vzc2lvbiBvYmplY3RzIHdpbGwgZGlzcGF0Y2ggYSBgc2lnbmFsYCBvciBgc2lnbmFsOnR5cGVgIGV2ZW50LiBTZWUgW1tTaWduYWxFdmVudF1dIHRvIGxlYXJuIG1vcmUuXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyBBIFByb21pc2UgKHRvIHdoaWNoIHlvdSBjYW4gb3B0aW9uYWxseSBzdWJzY3JpYmUgdG8pIHRoYXQgaXMgcmVzb2x2ZWQgaWYgdGhlIG1lc3NhZ2Ugc3VjY2Vzc2Z1bGx5IHJlYWNoZWQgb3BlbnZpZHUtc2VydmVyIGFuZCByZWplY3RlZCB3aXRoIGFuIEVycm9yIG9iamVjdCBpZiBub3QuIF9UaGlzIGRvZXNuJ3RcbiAgICAgKiBtZWFuIHRoYXQgb3BlbnZpZHUtc2VydmVyIGNvdWxkIHJlc2VuZCB0aGUgbWVzc2FnZSB0byBhbGwgdGhlIGxpc3RlZCByZWNlaXZlcnMuX1xuICAgICAqL1xuICAgIC8qIHRzbGludDpkaXNhYmxlOm5vLXN0cmluZy1saXRlcmFsICovXG4gICAgc2lnbmFsKHNpZ25hbDogU2lnbmFsT3B0aW9ucyk6IFByb21pc2U8YW55PiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG5cbiAgICAgICAgICAgIGNvbnN0IHNpZ25hbE1lc3NhZ2UgPSB7fTtcblxuICAgICAgICAgICAgaWYgKHNpZ25hbC50byAmJiBzaWduYWwudG8ubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgICAgIGNvbnN0IGNvbm5lY3Rpb25JZHM6IHN0cmluZ1tdID0gW107XG5cbiAgICAgICAgICAgICAgICBzaWduYWwudG8uZm9yRWFjaChjb25uZWN0aW9uID0+IHtcbiAgICAgICAgICAgICAgICAgICAgY29ubmVjdGlvbklkcy5wdXNoKGNvbm5lY3Rpb24uY29ubmVjdGlvbklkKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICBzaWduYWxNZXNzYWdlWyd0byddID0gY29ubmVjdGlvbklkcztcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgc2lnbmFsTWVzc2FnZVsndG8nXSA9IFtdO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBzaWduYWxNZXNzYWdlWydkYXRhJ10gPSBzaWduYWwuZGF0YSA/IHNpZ25hbC5kYXRhIDogJyc7XG4gICAgICAgICAgICBzaWduYWxNZXNzYWdlWyd0eXBlJ10gPSBzaWduYWwudHlwZSA/IHNpZ25hbC50eXBlIDogJyc7XG5cbiAgICAgICAgICAgIHRoaXMub3BlbnZpZHUuc2VuZFJlcXVlc3QoJ3NlbmRNZXNzYWdlJywge1xuICAgICAgICAgICAgICAgIG1lc3NhZ2U6IEpTT04uc3RyaW5naWZ5KHNpZ25hbE1lc3NhZ2UpXG4gICAgICAgICAgICB9LCAoZXJyb3IsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKCEhZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgIH1cbiAgICAvKiB0c2xpbnQ6ZW5hYmxlOm5vLXN0cmluZy1saXRlcmFsICovXG5cblxuICAgIC8qKlxuICAgICAqIFNlZSBbW0V2ZW50RGlzcGF0Y2hlci5vbl1dXG4gICAgICovXG4gICAgb24odHlwZTogc3RyaW5nLCBoYW5kbGVyOiAoZXZlbnQ6IFNlc3Npb25EaXNjb25uZWN0ZWRFdmVudCB8IFNpZ25hbEV2ZW50IHwgU3RyZWFtRXZlbnQgfCBDb25uZWN0aW9uRXZlbnQgfCBQdWJsaXNoZXJTcGVha2luZ0V2ZW50IHwgUmVjb3JkaW5nRXZlbnQpID0+IHZvaWQpOiBFdmVudERpc3BhdGNoZXIge1xuXG4gICAgICAgIHRoaXMuZWUub24odHlwZSwgZXZlbnQgPT4ge1xuICAgICAgICAgICAgaWYgKGV2ZW50KSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5pbmZvKFwiRXZlbnQgJ1wiICsgdHlwZSArIFwiJyB0cmlnZ2VyZWQgYnkgJ1Nlc3Npb24nXCIsIGV2ZW50KTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5pbmZvKFwiRXZlbnQgJ1wiICsgdHlwZSArIFwiJyB0cmlnZ2VyZWQgYnkgJ1Nlc3Npb24nXCIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaGFuZGxlcihldmVudCk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGlmICh0eXBlID09PSAncHVibGlzaGVyU3RhcnRTcGVha2luZycgfHwgdHlwZSA9PT0gJ3B1Ymxpc2hlclN0b3BTcGVha2luZycpIHtcbiAgICAgICAgICAgIHRoaXMuc3BlYWtpbmdFdmVudHNFbmFibGVkID0gdHJ1ZTtcbiAgICAgICAgICAgIC8vIElmIHRoZXJlIGFyZSBhbHJlYWR5IGF2YWlsYWJsZSByZW1vdGUgc3RyZWFtcywgZW5hYmxlIGhhcmsgJ3NwZWFraW5nJyBldmVudCBpbiBhbGwgb2YgdGhlbVxuICAgICAgICAgICAgZm9yIChjb25zdCBjb25uZWN0aW9uSWQgaW4gdGhpcy5yZW1vdGVDb25uZWN0aW9ucykge1xuICAgICAgICAgICAgICAgIGNvbnN0IHN0ciA9IHRoaXMucmVtb3RlQ29ubmVjdGlvbnNbY29ubmVjdGlvbklkXS5zdHJlYW07XG4gICAgICAgICAgICAgICAgaWYgKCEhc3RyICYmICFzdHIuc3BlZWNoRXZlbnQgJiYgc3RyLmhhc0F1ZGlvKSB7XG4gICAgICAgICAgICAgICAgICAgIHN0ci5lbmFibGVTcGVha2luZ0V2ZW50cygpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogU2VlIFtbRXZlbnREaXNwYXRjaGVyLm9uY2VdXVxuICAgICAqL1xuICAgIG9uY2UodHlwZTogc3RyaW5nLCBoYW5kbGVyOiAoZXZlbnQ6IFNlc3Npb25EaXNjb25uZWN0ZWRFdmVudCB8IFNpZ25hbEV2ZW50IHwgU3RyZWFtRXZlbnQgfCBDb25uZWN0aW9uRXZlbnQgfCBQdWJsaXNoZXJTcGVha2luZ0V2ZW50IHwgUmVjb3JkaW5nRXZlbnQpID0+IHZvaWQpOiBTZXNzaW9uIHtcblxuICAgICAgICB0aGlzLmVlLm9uY2UodHlwZSwgZXZlbnQgPT4ge1xuICAgICAgICAgICAgaWYgKGV2ZW50KSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5pbmZvKFwiRXZlbnQgJ1wiICsgdHlwZSArIFwiJyB0cmlnZ2VyZWQgYnkgJ1Nlc3Npb24nXCIsIGV2ZW50KTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5pbmZvKFwiRXZlbnQgJ1wiICsgdHlwZSArIFwiJyB0cmlnZ2VyZWQgYnkgJ1Nlc3Npb24nXCIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaGFuZGxlcihldmVudCk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGlmICh0eXBlID09PSAncHVibGlzaGVyU3RhcnRTcGVha2luZycgfHwgdHlwZSA9PT0gJ3B1Ymxpc2hlclN0b3BTcGVha2luZycpIHtcbiAgICAgICAgICAgIHRoaXMuc3BlYWtpbmdFdmVudHNFbmFibGVkID0gdHJ1ZTtcbiAgICAgICAgICAgIC8vIElmIHRoZXJlIGFyZSBhbHJlYWR5IGF2YWlsYWJsZSByZW1vdGUgc3RyZWFtcywgZW5hYmxlIGhhcmsgaW4gYWxsIG9mIHRoZW1cbiAgICAgICAgICAgIGZvciAoY29uc3QgY29ubmVjdGlvbklkIGluIHRoaXMucmVtb3RlQ29ubmVjdGlvbnMpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBzdHIgPSB0aGlzLnJlbW90ZUNvbm5lY3Rpb25zW2Nvbm5lY3Rpb25JZF0uc3RyZWFtO1xuICAgICAgICAgICAgICAgIGlmICghIXN0ciAmJiAhc3RyLnNwZWVjaEV2ZW50ICYmIHN0ci5oYXNBdWRpbykge1xuICAgICAgICAgICAgICAgICAgICBzdHIuZW5hYmxlT25jZVNwZWFraW5nRXZlbnRzKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBTZWUgW1tFdmVudERpc3BhdGNoZXIub2ZmXV1cbiAgICAgKi9cbiAgICBvZmYodHlwZTogc3RyaW5nLCBoYW5kbGVyPzogKGV2ZW50OiBTZXNzaW9uRGlzY29ubmVjdGVkRXZlbnQgfCBTaWduYWxFdmVudCB8IFN0cmVhbUV2ZW50IHwgQ29ubmVjdGlvbkV2ZW50IHwgUHVibGlzaGVyU3BlYWtpbmdFdmVudCB8IFJlY29yZGluZ0V2ZW50KSA9PiB2b2lkKTogU2Vzc2lvbiB7XG5cbiAgICAgICAgaWYgKCFoYW5kbGVyKSB7XG4gICAgICAgICAgICB0aGlzLmVlLnJlbW92ZUFsbExpc3RlbmVycyh0eXBlKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuZWUub2ZmKHR5cGUsIGhhbmRsZXIpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHR5cGUgPT09ICdwdWJsaXNoZXJTdGFydFNwZWFraW5nJyB8fCB0eXBlID09PSAncHVibGlzaGVyU3RvcFNwZWFraW5nJykge1xuICAgICAgICAgICAgdGhpcy5zcGVha2luZ0V2ZW50c0VuYWJsZWQgPSBmYWxzZTtcblxuICAgICAgICAgICAgLy8gSWYgdGhlcmUgYXJlIGFscmVhZHkgYXZhaWxhYmxlIHJlbW90ZSBzdHJlYW1zLCBkaXNhYmxhZSBoYXJrIGluIGFsbCBvZiB0aGVtXG4gICAgICAgICAgICBmb3IgKGNvbnN0IGNvbm5lY3Rpb25JZCBpbiB0aGlzLnJlbW90ZUNvbm5lY3Rpb25zKSB7XG4gICAgICAgICAgICAgICAgY29uc3Qgc3RyID0gdGhpcy5yZW1vdGVDb25uZWN0aW9uc1tjb25uZWN0aW9uSWRdLnN0cmVhbTtcbiAgICAgICAgICAgICAgICBpZiAoISFzdHIgJiYgISFzdHIuc3BlZWNoRXZlbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgc3RyLmRpc2FibGVTcGVha2luZ0V2ZW50cygpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cblxuICAgIC8qIEhpZGRlbiBtZXRob2RzICovXG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgb25QYXJ0aWNpcGFudEpvaW5lZChyZXNwb25zZTogQ29ubmVjdGlvbk9wdGlvbnMpOiB2b2lkIHtcbiAgICAgICAgLy8gQ29ubmVjdGlvbiBzaG91bGRuJ3QgZXhpc3RcbiAgICAgICAgdGhpcy5nZXRDb25uZWN0aW9uKHJlc3BvbnNlLmlkLCAnJylcblxuICAgICAgICAgICAgLnRoZW4oY29ubmVjdGlvbiA9PiB7XG4gICAgICAgICAgICAgICAgY29uc29sZS53YXJuKCdDb25uZWN0aW9uICcgKyByZXNwb25zZS5pZCArICcgYWxyZWFkeSBleGlzdHMgaW4gY29ubmVjdGlvbnMgbGlzdCcpO1xuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIC5jYXRjaChvcGVuVmlkdUVycm9yID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCBjb25uZWN0aW9uID0gbmV3IENvbm5lY3Rpb24odGhpcywgcmVzcG9uc2UpO1xuICAgICAgICAgICAgICAgIHRoaXMucmVtb3RlQ29ubmVjdGlvbnNbcmVzcG9uc2UuaWRdID0gY29ubmVjdGlvbjtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnY29ubmVjdGlvbkNyZWF0ZWQnLCBbbmV3IENvbm5lY3Rpb25FdmVudChmYWxzZSwgdGhpcywgJ2Nvbm5lY3Rpb25DcmVhdGVkJywgY29ubmVjdGlvbiwgJycpXSk7XG4gICAgICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgb25QYXJ0aWNpcGFudExlZnQobXNnKTogdm9pZCB7XG4gICAgICAgIHRoaXMuZ2V0UmVtb3RlQ29ubmVjdGlvbihtc2cuY29ubmVjdGlvbklkLCAnUmVtb3RlIGNvbm5lY3Rpb24gJyArIG1zZy5jb25uZWN0aW9uSWQgKyBcIiB1bmtub3duIHdoZW4gJ29uUGFydGljaXBhbnRMZWZ0Jy4gXCIgK1xuICAgICAgICAgICAgJ0V4aXN0aW5nIHJlbW90ZSBjb25uZWN0aW9uczogJyArIEpTT04uc3RyaW5naWZ5KE9iamVjdC5rZXlzKHRoaXMucmVtb3RlQ29ubmVjdGlvbnMpKSlcblxuICAgICAgICAgICAgLnRoZW4oY29ubmVjdGlvbiA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKCEhY29ubmVjdGlvbi5zdHJlYW0pIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3Qgc3RyZWFtID0gY29ubmVjdGlvbi5zdHJlYW07XG5cbiAgICAgICAgICAgICAgICAgICAgY29uc3Qgc3RyZWFtRXZlbnQgPSBuZXcgU3RyZWFtRXZlbnQodHJ1ZSwgdGhpcywgJ3N0cmVhbURlc3Ryb3llZCcsIHN0cmVhbSwgbXNnLnJlYXNvbik7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdzdHJlYW1EZXN0cm95ZWQnLCBbc3RyZWFtRXZlbnRdKTtcbiAgICAgICAgICAgICAgICAgICAgc3RyZWFtRXZlbnQuY2FsbERlZmF1bHRCZWhhdmlvcigpO1xuXG4gICAgICAgICAgICAgICAgICAgIGRlbGV0ZSB0aGlzLnJlbW90ZVN0cmVhbXNDcmVhdGVkW3N0cmVhbS5zdHJlYW1JZF07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGRlbGV0ZSB0aGlzLnJlbW90ZUNvbm5lY3Rpb25zW2Nvbm5lY3Rpb24uY29ubmVjdGlvbklkXTtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnY29ubmVjdGlvbkRlc3Ryb3llZCcsIFtuZXcgQ29ubmVjdGlvbkV2ZW50KGZhbHNlLCB0aGlzLCAnY29ubmVjdGlvbkRlc3Ryb3llZCcsIGNvbm5lY3Rpb24sIG1zZy5yZWFzb24pXSk7XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLmNhdGNoKG9wZW5WaWR1RXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3Iob3BlblZpZHVFcnJvcik7XG4gICAgICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgb25QYXJ0aWNpcGFudFB1Ymxpc2hlZChyZXNwb25zZTogQ29ubmVjdGlvbk9wdGlvbnMpOiB2b2lkIHtcblxuICAgICAgICBjb25zdCBhZnRlckNvbm5lY3Rpb25Gb3VuZCA9IChjb25uZWN0aW9uKSA9PiB7XG4gICAgICAgICAgICB0aGlzLnJlbW90ZUNvbm5lY3Rpb25zW2Nvbm5lY3Rpb24uY29ubmVjdGlvbklkXSA9IGNvbm5lY3Rpb247XG5cbiAgICAgICAgICAgIGlmICghdGhpcy5yZW1vdGVTdHJlYW1zQ3JlYXRlZFtjb25uZWN0aW9uLnN0cmVhbS5zdHJlYW1JZF0pIHtcbiAgICAgICAgICAgICAgICAvLyBBdm9pZCByYWNlIGNvbmRpdGlvbiBiZXR3ZWVuIHN0cmVhbS5zdWJzY3JpYmUoKSBpbiBcIm9uUGFydGljaXBhbnRQdWJsaXNoZWRcIiBhbmQgaW4gXCJqb2luUm9vbVwiIHJwYyBjYWxsYmFja1xuICAgICAgICAgICAgICAgIC8vIFRoaXMgY29uZGl0aW9uIGlzIGZhbHNlIGlmIG9wZW52aWR1LXNlcnZlciBzZW5kcyBcInBhcnRpY2lwYW50UHVibGlzaGVkXCIgZXZlbnQgdG8gYSBzdWJzY3JpYmVyIHBhcnRpY2lwYW50IHRoYXQgaGFzXG4gICAgICAgICAgICAgICAgLy8gYWxyZWFkeSBzdWJzY3JpYmVkIHRvIGNlcnRhaW4gc3RyZWFtIGluIHRoZSBjYWxsYmFjayBvZiBcImpvaW5Sb29tXCIgbWV0aG9kXG5cbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnc3RyZWFtQ3JlYXRlZCcsIFtuZXcgU3RyZWFtRXZlbnQoZmFsc2UsIHRoaXMsICdzdHJlYW1DcmVhdGVkJywgY29ubmVjdGlvbi5zdHJlYW0sICcnKV0pO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLnJlbW90ZVN0cmVhbXNDcmVhdGVkW2Nvbm5lY3Rpb24uc3RyZWFtLnN0cmVhbUlkXSA9IHRydWU7XG4gICAgICAgIH07XG5cbiAgICAgICAgLy8gR2V0IHRoZSBleGlzdGluZyBDb25uZWN0aW9uIGNyZWF0ZWQgb24gJ29uUGFydGljaXBhbnRKb2luZWQnIGZvclxuICAgICAgICAvLyBleGlzdGluZyBwYXJ0aWNpcGFudHMgb3IgY3JlYXRlIGEgbmV3IG9uZSBmb3IgbmV3IHBhcnRpY2lwYW50c1xuICAgICAgICBsZXQgY29ubmVjdGlvbjogQ29ubmVjdGlvbjtcbiAgICAgICAgdGhpcy5nZXRSZW1vdGVDb25uZWN0aW9uKHJlc3BvbnNlLmlkLCBcIlJlbW90ZSBjb25uZWN0aW9uICdcIiArIHJlc3BvbnNlLmlkICsgXCInIHVua25vd24gd2hlbiAnb25QYXJ0aWNpcGFudFB1Ymxpc2hlZCcuIFwiICtcbiAgICAgICAgICAgICdFeGlzdGluZyByZW1vdGUgY29ubmVjdGlvbnM6ICcgKyBKU09OLnN0cmluZ2lmeShPYmplY3Qua2V5cyh0aGlzLnJlbW90ZUNvbm5lY3Rpb25zKSkpXG5cbiAgICAgICAgICAgIC50aGVuKGNvbiA9PiB7XG4gICAgICAgICAgICAgICAgLy8gVXBkYXRlIGV4aXN0aW5nIENvbm5lY3Rpb25cbiAgICAgICAgICAgICAgICBjb25uZWN0aW9uID0gY29uO1xuICAgICAgICAgICAgICAgIHJlc3BvbnNlLm1ldGFkYXRhID0gY29uLmRhdGE7XG4gICAgICAgICAgICAgICAgY29ubmVjdGlvbi5vcHRpb25zID0gcmVzcG9uc2U7XG4gICAgICAgICAgICAgICAgY29ubmVjdGlvbi5pbml0UmVtb3RlU3RyZWFtcyhyZXNwb25zZS5zdHJlYW1zKTtcbiAgICAgICAgICAgICAgICBhZnRlckNvbm5lY3Rpb25Gb3VuZChjb25uZWN0aW9uKTtcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAuY2F0Y2gob3BlblZpZHVFcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgLy8gQ3JlYXRlIG5ldyBDb25uZWN0aW9uXG4gICAgICAgICAgICAgICAgY29ubmVjdGlvbiA9IG5ldyBDb25uZWN0aW9uKHRoaXMsIHJlc3BvbnNlKTtcbiAgICAgICAgICAgICAgICBhZnRlckNvbm5lY3Rpb25Gb3VuZChjb25uZWN0aW9uKTtcbiAgICAgICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvblBhcnRpY2lwYW50VW5wdWJsaXNoZWQobXNnKTogdm9pZCB7XG4gICAgICAgIGlmIChtc2cuY29ubmVjdGlvbklkID09PSB0aGlzLmNvbm5lY3Rpb24uY29ubmVjdGlvbklkKSB7XG4gICAgICAgICAgICAvLyBZb3VyIHN0cmVhbSBoYXMgYmVlbiBmb3JjZWRseSB1bnB1Ymxpc2hlZCBmcm9tIHRoZSBzZXNzaW9uXG4gICAgICAgICAgICB0aGlzLnN0b3BQdWJsaXNoZXJTdHJlYW0obXNnLnJlYXNvbik7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLmdldFJlbW90ZUNvbm5lY3Rpb24obXNnLmNvbm5lY3Rpb25JZCwgXCJSZW1vdGUgY29ubmVjdGlvbiAnXCIgKyBtc2cuY29ubmVjdGlvbklkICsgXCInIHVua25vd24gd2hlbiAnb25QYXJ0aWNpcGFudFVucHVibGlzaGVkJy4gXCIgK1xuICAgICAgICAgICAgICAgICdFeGlzdGluZyByZW1vdGUgY29ubmVjdGlvbnM6ICcgKyBKU09OLnN0cmluZ2lmeShPYmplY3Qua2V5cyh0aGlzLnJlbW90ZUNvbm5lY3Rpb25zKSkpXG5cbiAgICAgICAgICAgICAgICAudGhlbihjb25uZWN0aW9uID0+IHtcblxuICAgICAgICAgICAgICAgICAgICBjb25zdCBzdHJlYW1FdmVudCA9IG5ldyBTdHJlYW1FdmVudCh0cnVlLCB0aGlzLCAnc3RyZWFtRGVzdHJveWVkJywgY29ubmVjdGlvbi5zdHJlYW0sIG1zZy5yZWFzb24pO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnc3RyZWFtRGVzdHJveWVkJywgW3N0cmVhbUV2ZW50XSk7XG4gICAgICAgICAgICAgICAgICAgIHN0cmVhbUV2ZW50LmNhbGxEZWZhdWx0QmVoYXZpb3IoKTtcblxuICAgICAgICAgICAgICAgICAgICAvLyBEZWxldGluZyB0aGUgcmVtb3RlIHN0cmVhbVxuICAgICAgICAgICAgICAgICAgICBjb25zdCBzdHJlYW1JZDogc3RyaW5nID0gY29ubmVjdGlvbi5zdHJlYW0uc3RyZWFtSWQ7XG4gICAgICAgICAgICAgICAgICAgIGRlbGV0ZSB0aGlzLnJlbW90ZVN0cmVhbXNDcmVhdGVkW3N0cmVhbUlkXTtcbiAgICAgICAgICAgICAgICAgICAgY29ubmVjdGlvbi5yZW1vdmVTdHJlYW0oc3RyZWFtSWQpO1xuICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgLmNhdGNoKG9wZW5WaWR1RXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKG9wZW5WaWR1RXJyb3IpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIG9uUGFydGljaXBhbnRFdmljdGVkKG1zZyk6IHZvaWQge1xuICAgICAgICBpZiAobXNnLmNvbm5lY3Rpb25JZCA9PT0gdGhpcy5jb25uZWN0aW9uLmNvbm5lY3Rpb25JZCkge1xuICAgICAgICAgICAgLy8gWW91IGhhdmUgYmVlbiBldmljdGVkIGZyb20gdGhlIHNlc3Npb25cbiAgICAgICAgICAgIGlmICghIXRoaXMuc2Vzc2lvbklkICYmICF0aGlzLmNvbm5lY3Rpb24uZGlzcG9zZWQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmxlYXZlKHRydWUsIG1zZy5yZWFzb24pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIG9uTmV3TWVzc2FnZShtc2cpOiB2b2lkIHtcblxuICAgICAgICBjb25zb2xlLmluZm8oJ05ldyBzaWduYWw6ICcgKyBKU09OLnN0cmluZ2lmeShtc2cpKTtcblxuICAgICAgICB0aGlzLmdldENvbm5lY3Rpb24obXNnLmZyb20sIFwiQ29ubmVjdGlvbiAnXCIgKyBtc2cuZnJvbSArIFwiJyB1bmtub3cgd2hlbiAnb25OZXdNZXNzYWdlJy4gRXhpc3RpbmcgcmVtb3RlIGNvbm5lY3Rpb25zOiBcIlxuICAgICAgICAgICAgKyBKU09OLnN0cmluZ2lmeShPYmplY3Qua2V5cyh0aGlzLnJlbW90ZUNvbm5lY3Rpb25zKSkgKyAnLiBFeGlzdGluZyBsb2NhbCBjb25uZWN0aW9uOiAnICsgdGhpcy5jb25uZWN0aW9uLmNvbm5lY3Rpb25JZClcblxuICAgICAgICAgICAgLnRoZW4oY29ubmVjdGlvbiA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3NpZ25hbCcsIFtuZXcgU2lnbmFsRXZlbnQodGhpcywgbXNnLnR5cGUsIG1zZy5kYXRhLCBjb25uZWN0aW9uKV0pO1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdzaWduYWw6JyArIG1zZy50eXBlLCBbbmV3IFNpZ25hbEV2ZW50KHRoaXMsIG1zZy50eXBlLCBtc2cuZGF0YSwgY29ubmVjdGlvbildKTtcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAuY2F0Y2gob3BlblZpZHVFcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihvcGVuVmlkdUVycm9yKTtcbiAgICAgICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvblN0cmVhbVByb3BlcnR5Q2hhbmdlZChtc2cpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5nZXRSZW1vdGVDb25uZWN0aW9uKG1zZy5jb25uZWN0aW9uSWQsICdSZW1vdGUgY29ubmVjdGlvbiAnICsgbXNnLmNvbm5lY3Rpb25JZCArIFwiIHVua25vd24gd2hlbiAnb25TdHJlYW1Qcm9wZXJ0eUNoYW5nZWQnLiBcIiArXG4gICAgICAgICAgICAnRXhpc3RpbmcgcmVtb3RlIGNvbm5lY3Rpb25zOiAnICsgSlNPTi5zdHJpbmdpZnkoT2JqZWN0LmtleXModGhpcy5yZW1vdGVDb25uZWN0aW9ucykpKVxuXG4gICAgICAgICAgICAudGhlbihjb25uZWN0aW9uID0+IHtcbiAgICAgICAgICAgICAgICBpZiAoISFjb25uZWN0aW9uLnN0cmVhbSAmJiBjb25uZWN0aW9uLnN0cmVhbS5zdHJlYW1JZCA9PT0gbXNnLnN0cmVhbUlkKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHN0cmVhbSA9IGNvbm5lY3Rpb24uc3RyZWFtO1xuICAgICAgICAgICAgICAgICAgICBsZXQgb2xkVmFsdWU7XG4gICAgICAgICAgICAgICAgICAgIHN3aXRjaCAobXNnLnByb3BlcnR5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlICdhdWRpb0FjdGl2ZSc6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgb2xkVmFsdWUgPSBzdHJlYW0uYXVkaW9BY3RpdmU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbXNnLm5ld1ZhbHVlID0gbXNnLm5ld1ZhbHVlID09PSAndHJ1ZSc7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyZWFtLmF1ZGlvQWN0aXZlID0gbXNnLm5ld1ZhbHVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAndmlkZW9BY3RpdmUnOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9sZFZhbHVlID0gc3RyZWFtLnZpZGVvQWN0aXZlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1zZy5uZXdWYWx1ZSA9IG1zZy5uZXdWYWx1ZSA9PT0gJ3RydWUnO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cmVhbS52aWRlb0FjdGl2ZSA9IG1zZy5uZXdWYWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJ3ZpZGVvRGltZW5zaW9ucyc6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgb2xkVmFsdWUgPSBzdHJlYW0udmlkZW9EaW1lbnNpb25zO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1zZy5uZXdWYWx1ZSA9IEpTT04ucGFyc2UoSlNPTi5wYXJzZShtc2cubmV3VmFsdWUpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJlYW0udmlkZW9EaW1lbnNpb25zID0gbXNnLm5ld1ZhbHVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3N0cmVhbVByb3BlcnR5Q2hhbmdlZCcsIFtuZXcgU3RyZWFtUHJvcGVydHlDaGFuZ2VkRXZlbnQodGhpcywgc3RyZWFtLCBtc2cucHJvcGVydHksIG1zZy5uZXdWYWx1ZSwgb2xkVmFsdWUsIG1zZy5yZWFzb24pXSk7XG4gICAgICAgICAgICAgICAgICAgIHN0cmVhbS5zdHJlYW1NYW5hZ2VyLmVtaXRFdmVudCgnc3RyZWFtUHJvcGVydHlDaGFuZ2VkJywgW25ldyBTdHJlYW1Qcm9wZXJ0eUNoYW5nZWRFdmVudChzdHJlYW0uc3RyZWFtTWFuYWdlciwgc3RyZWFtLCBtc2cucHJvcGVydHksIG1zZy5uZXdWYWx1ZSwgb2xkVmFsdWUsIG1zZy5yZWFzb24pXSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihcIk5vIHN0cmVhbSB3aXRoIHN0cmVhbUlkICdcIiArIG1zZy5zdHJlYW1JZCArIFwiJyBmb3VuZCBmb3IgY29ubmVjdGlvbiAnXCIgKyBtc2cuY29ubmVjdGlvbklkICsgXCInIG9uICdzdHJlYW1Qcm9wZXJ0eUNoYW5nZWQnIGV2ZW50XCIpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAuY2F0Y2gob3BlblZpZHVFcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihvcGVuVmlkdUVycm9yKTtcbiAgICAgICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICByZWN2SWNlQ2FuZGlkYXRlKG1zZyk6IHZvaWQge1xuICAgICAgICBjb25zdCBjYW5kaWRhdGUgPSB7XG4gICAgICAgICAgICBjYW5kaWRhdGU6IG1zZy5jYW5kaWRhdGUsXG4gICAgICAgICAgICBzZHBNaWQ6IG1zZy5zZHBNaWQsXG4gICAgICAgICAgICBzZHBNTGluZUluZGV4OiBtc2cuc2RwTUxpbmVJbmRleCxcbiAgICAgICAgICAgIHRvSlNPTjogKCkgPT4ge1xuICAgICAgICAgICAgICAgIHJldHVybiB7IGNhbmRpZGF0ZTogbXNnLmNhbmRpZGF0ZSB9O1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICB0aGlzLmdldENvbm5lY3Rpb24obXNnLmVuZHBvaW50TmFtZSwgJ0Nvbm5lY3Rpb24gbm90IGZvdW5kIGZvciBlbmRwb2ludCAnICsgbXNnLmVuZHBvaW50TmFtZSArICcuIEljZSBjYW5kaWRhdGUgd2lsbCBiZSBpZ25vcmVkOiAnICsgY2FuZGlkYXRlKVxuICAgICAgICAgICAgLnRoZW4oY29ubmVjdGlvbiA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3Qgc3RyZWFtID0gY29ubmVjdGlvbi5zdHJlYW07XG4gICAgICAgICAgICAgICAgc3RyZWFtLmdldFdlYlJ0Y1BlZXIoKS5hZGRJY2VDYW5kaWRhdGUoY2FuZGlkYXRlKS5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ0Vycm9yIGFkZGluZyBjYW5kaWRhdGUgZm9yICcgKyBzdHJlYW0uc3RyZWFtSWRcbiAgICAgICAgICAgICAgICAgICAgICAgICsgJyBzdHJlYW0gb2YgZW5kcG9pbnQgJyArIG1zZy5lbmRwb2ludE5hbWUgKyAnOiAnICsgZXJyb3IpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIC5jYXRjaChvcGVuVmlkdUVycm9yID0+IHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKG9wZW5WaWR1RXJyb3IpO1xuICAgICAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIG9uU2Vzc2lvbkNsb3NlZChtc2cpOiB2b2lkIHtcbiAgICAgICAgY29uc29sZS5pbmZvKCdTZXNzaW9uIGNsb3NlZDogJyArIEpTT04uc3RyaW5naWZ5KG1zZykpO1xuICAgICAgICBjb25zdCBzID0gbXNnLnNlc3Npb25JZDtcbiAgICAgICAgaWYgKHMgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3Nlc3Npb24tY2xvc2VkJywgW3tcbiAgICAgICAgICAgICAgICBzZXNzaW9uOiBzXG4gICAgICAgICAgICB9XSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjb25zb2xlLndhcm4oJ1Nlc3Npb24gdW5kZWZpbmVkIG9uIHNlc3Npb24gY2xvc2VkJywgbXNnKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvbkxvc3RDb25uZWN0aW9uKCk6IHZvaWQge1xuXG4gICAgICAgIC8qaWYgKCF0aGlzLmNvbm5lY3Rpb24pIHtcblxuICAgICAgICAgICAgY29uc29sZS53YXJuKCdOb3QgY29ubmVjdGVkIHRvIHNlc3Npb246IGlmIHlvdSBhcmUgbm90IGRlYnVnZ2luZywgdGhpcyBpcyBwcm9iYWJseSBhIGNlcnRpZmljYXRlIGVycm9yJyk7XG5cbiAgICAgICAgICAgIGNvbnN0IHVybCA9ICdodHRwczovLycgKyB0aGlzLm9wZW52aWR1LmdldFdzVXJpKCkuc3BsaXQoJ3dzczovLycpWzFdLnNwbGl0KCcvb3BlbnZpZHUnKVswXTtcbiAgICAgICAgICAgIGlmICh3aW5kb3cuY29uZmlybSgnSWYgeW91IGFyZSBub3QgZGVidWdnaW5nLCB0aGlzIGlzIHByb2JhYmx5IGEgY2VydGlmaWNhdGUgZXJyb3IgYXQgXFxcIicgKyB1cmwgKyAnXFxcIlxcblxcbkNsaWNrIE9LIHRvIG5hdmlnYXRlIGFuZCBhY2NlcHQgaXQnKSkge1xuICAgICAgICAgICAgICAgIGxvY2F0aW9uLmFzc2lnbih1cmwgKyAnL2FjY2VwdC1jZXJ0aWZpY2F0ZScpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9Ki9cblxuICAgICAgICBjb25zb2xlLndhcm4oJ0xvc3QgY29ubmVjdGlvbiBpbiBTZXNzaW9uICcgKyB0aGlzLnNlc3Npb25JZCk7XG4gICAgICAgIGlmICghIXRoaXMuc2Vzc2lvbklkICYmICF0aGlzLmNvbm5lY3Rpb24uZGlzcG9zZWQpIHtcbiAgICAgICAgICAgIHRoaXMubGVhdmUodHJ1ZSwgJ25ldHdvcmtEaXNjb25uZWN0Jyk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgb25SZWNvdmVyZWRDb25uZWN0aW9uKCk6IHZvaWQge1xuICAgICAgICBjb25zb2xlLndhcm4oJ1JlY292ZXJlZCBjb25uZWN0aW9uIGluIFNlc3Npb24gJyArIHRoaXMuc2Vzc2lvbklkKTtcbiAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ2Nvbm5lY3Rpb25SZWNvdmVyZWQnLCBbXSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIG9uTWVkaWFFcnJvcihwYXJhbXMpOiB2b2lkIHtcblxuICAgICAgICBjb25zb2xlLmVycm9yKCdNZWRpYSBlcnJvcjogJyArIEpTT04uc3RyaW5naWZ5KHBhcmFtcykpO1xuICAgICAgICBjb25zdCBlcnIgPSBwYXJhbXMuZXJyb3I7XG4gICAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdlcnJvci1tZWRpYScsIFt7XG4gICAgICAgICAgICAgICAgZXJyb3I6IGVyclxuICAgICAgICAgICAgfV0pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY29uc29sZS53YXJuKCdSZWNlaXZlZCB1bmRlZmluZWQgbWVkaWEgZXJyb3IuIFBhcmFtczonLCBwYXJhbXMpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIG9uUmVjb3JkaW5nU3RhcnRlZChyZXNwb25zZSk6IHZvaWQge1xuICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgncmVjb3JkaW5nU3RhcnRlZCcsIFtuZXcgUmVjb3JkaW5nRXZlbnQodGhpcywgJ3JlY29yZGluZ1N0YXJ0ZWQnLCByZXNwb25zZS5pZCwgcmVzcG9uc2UubmFtZSldKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgb25SZWNvcmRpbmdTdG9wcGVkKHJlc3BvbnNlKTogdm9pZCB7XG4gICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdyZWNvcmRpbmdTdG9wcGVkJywgW25ldyBSZWNvcmRpbmdFdmVudCh0aGlzLCAncmVjb3JkaW5nU3RvcHBlZCcsIHJlc3BvbnNlLmlkLCByZXNwb25zZS5uYW1lKV0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBlbWl0RXZlbnQodHlwZTogc3RyaW5nLCBldmVudEFycmF5OiBhbnlbXSk6IHZvaWQge1xuICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCh0eXBlLCBldmVudEFycmF5KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgbGVhdmUoZm9yY2VkOiBib29sZWFuLCByZWFzb246IHN0cmluZyk6IHZvaWQge1xuXG4gICAgICAgIGZvcmNlZCA9ICEhZm9yY2VkO1xuICAgICAgICBjb25zb2xlLmluZm8oJ0xlYXZpbmcgU2Vzc2lvbiAoZm9yY2VkPScgKyBmb3JjZWQgKyAnKScpO1xuXG4gICAgICAgIGlmICghIXRoaXMuY29ubmVjdGlvbikge1xuICAgICAgICAgICAgaWYgKCF0aGlzLmNvbm5lY3Rpb24uZGlzcG9zZWQgJiYgIWZvcmNlZCkge1xuICAgICAgICAgICAgICAgIHRoaXMub3BlbnZpZHUuc2VuZFJlcXVlc3QoJ2xlYXZlUm9vbScsIChlcnJvciwgcmVzcG9uc2UpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB0aGlzLm9wZW52aWR1LmNsb3NlV3MoKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy5vcGVudmlkdS5jbG9zZVdzKCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMuc3RvcFB1Ymxpc2hlclN0cmVhbShyZWFzb24pO1xuXG4gICAgICAgICAgICBpZiAoIXRoaXMuY29ubmVjdGlvbi5kaXNwb3NlZCkge1xuICAgICAgICAgICAgICAgIC8vIE1ha2UgU2Vzc2lvbiBvYmplY3QgZGlzcGF0Y2ggJ3Nlc3Npb25EaXNjb25uZWN0ZWQnIGV2ZW50IChpZiBpdCBpcyBub3QgYWxyZWFkeSBkaXNwb3NlZClcbiAgICAgICAgICAgICAgICBjb25zdCBzZXNzaW9uRGlzY29ubmVjdEV2ZW50ID0gbmV3IFNlc3Npb25EaXNjb25uZWN0ZWRFdmVudCh0aGlzLCByZWFzb24pO1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdzZXNzaW9uRGlzY29ubmVjdGVkJywgW3Nlc3Npb25EaXNjb25uZWN0RXZlbnRdKTtcbiAgICAgICAgICAgICAgICBzZXNzaW9uRGlzY29ubmVjdEV2ZW50LmNhbGxEZWZhdWx0QmVoYXZpb3IoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvbnNvbGUud2FybignWW91IHdlcmUgbm90IGNvbm5lY3RlZCB0byB0aGUgc2Vzc2lvbiAnICsgdGhpcy5zZXNzaW9uSWQpO1xuICAgICAgICB9XG4gICAgfVxuXG5cbiAgICAvKiBQcml2YXRlIG1ldGhvZHMgKi9cblxuICAgIHByaXZhdGUgY29ubmVjdEF1eCh0b2tlbjogc3RyaW5nKTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIHRoaXMub3BlbnZpZHUuc3RhcnRXcygoZXJyb3IpID0+IHtcbiAgICAgICAgICAgICAgICBpZiAoISFlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG5cbiAgICAgICAgICAgICAgICAgICAgY29uc3Qgam9pblBhcmFtcyA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRva2VuOiAoISF0b2tlbikgPyB0b2tlbiA6ICcnLFxuICAgICAgICAgICAgICAgICAgICAgICAgc2Vzc2lvbjogdGhpcy5zZXNzaW9uSWQsXG4gICAgICAgICAgICAgICAgICAgICAgICBtZXRhZGF0YTogISF0aGlzLm9wdGlvbnMubWV0YWRhdGEgPyB0aGlzLm9wdGlvbnMubWV0YWRhdGEgOiAnJyxcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlY3JldDogdGhpcy5vcGVudmlkdS5nZXRTZWNyZXQoKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlY29yZGVyOiB0aGlzLm9wZW52aWR1LmdldFJlY29yZGVyKCksXG4gICAgICAgICAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgICAgICAgICAgdGhpcy5vcGVudmlkdS5zZW5kUmVxdWVzdCgnam9pblJvb20nLCBqb2luUGFyYW1zLCAoZXJyb3IsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoISFlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gSW5pdGlhbGl6ZSBjYXBhYmlsaXRpZXMgb2JqZWN0IHdpdGggdGhlIHJvbGVcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNhcGFiaWxpdGllcyA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3Vic2NyaWJlOiB0cnVlLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwdWJsaXNoOiB0aGlzLm9wZW52aWR1LnJvbGUgIT09ICdTVUJTQ1JJQkVSJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yY2VVbnB1Ymxpc2g6IHRoaXMub3BlbnZpZHUucm9sZSA9PT0gJ01PREVSQVRPUicsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvcmNlRGlzY29ubmVjdDogdGhpcy5vcGVudmlkdS5yb2xlID09PSAnTU9ERVJBVE9SJ1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBJbml0aWFsaXplIGxvY2FsIENvbm5lY3Rpb24gb2JqZWN0IHdpdGggdmFsdWVzIHJldHVybmVkIGJ5IG9wZW52aWR1LXNlcnZlclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY29ubmVjdGlvbiA9IG5ldyBDb25uZWN0aW9uKHRoaXMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY29ubmVjdGlvbi5jb25uZWN0aW9uSWQgPSByZXNwb25zZS5pZDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbm5lY3Rpb24uZGF0YSA9IHJlc3BvbnNlLm1ldGFkYXRhO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gSW5pdGlhbGl6ZSByZW1vdGUgQ29ubmVjdGlvbnMgd2l0aCB2YWx1ZSByZXR1cm5lZCBieSBvcGVudmlkdS1zZXJ2ZXJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBldmVudHMgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbm5lY3Rpb25zOiBuZXcgQXJyYXk8Q29ubmVjdGlvbj4oKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyZWFtczogbmV3IEFycmF5PFN0cmVhbT4oKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZXhpc3RpbmdQYXJ0aWNpcGFudHM6IENvbm5lY3Rpb25PcHRpb25zW10gPSByZXNwb25zZS52YWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBleGlzdGluZ1BhcnRpY2lwYW50cy5mb3JFYWNoKHBhcnRpY2lwYW50ID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgY29ubmVjdGlvbiA9IG5ldyBDb25uZWN0aW9uKHRoaXMsIHBhcnRpY2lwYW50KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5yZW1vdGVDb25uZWN0aW9uc1tjb25uZWN0aW9uLmNvbm5lY3Rpb25JZF0gPSBjb25uZWN0aW9uO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBldmVudHMuY29ubmVjdGlvbnMucHVzaChjb25uZWN0aW9uKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCEhY29ubmVjdGlvbi5zdHJlYW0pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucmVtb3RlU3RyZWFtc0NyZWF0ZWRbY29ubmVjdGlvbi5zdHJlYW0uc3RyZWFtSWRdID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV2ZW50cy5zdHJlYW1zLnB1c2goY29ubmVjdGlvbi5zdHJlYW0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBPd24gJ2Nvbm5lY3Rpb25DcmVhdGVkJyBldmVudFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdjb25uZWN0aW9uQ3JlYXRlZCcsIFtuZXcgQ29ubmVjdGlvbkV2ZW50KGZhbHNlLCB0aGlzLCAnY29ubmVjdGlvbkNyZWF0ZWQnLCB0aGlzLmNvbm5lY3Rpb24sICcnKV0pO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gT25lICdjb25uZWN0aW9uQ3JlYXRlZCcgZXZlbnQgZm9yIGVhY2ggZXhpc3RpbmcgY29ubmVjdGlvbiBpbiB0aGUgc2Vzc2lvblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV2ZW50cy5jb25uZWN0aW9ucy5mb3JFYWNoKGNvbm5lY3Rpb24gPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnY29ubmVjdGlvbkNyZWF0ZWQnLCBbbmV3IENvbm5lY3Rpb25FdmVudChmYWxzZSwgdGhpcywgJ2Nvbm5lY3Rpb25DcmVhdGVkJywgY29ubmVjdGlvbiwgJycpXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBPbmUgJ3N0cmVhbUNyZWF0ZWQnIGV2ZW50IGZvciBlYWNoIGFjdGl2ZSBzdHJlYW0gaW4gdGhlIHNlc3Npb25cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBldmVudHMuc3RyZWFtcy5mb3JFYWNoKHN0cmVhbSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdzdHJlYW1DcmVhdGVkJywgW25ldyBTdHJlYW1FdmVudChmYWxzZSwgdGhpcywgJ3N0cmVhbUNyZWF0ZWQnLCBzdHJlYW0sICcnKV0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBzdG9wUHVibGlzaGVyU3RyZWFtKHJlYXNvbjogc3RyaW5nKSB7XG4gICAgICAgIGlmICghIXRoaXMuY29ubmVjdGlvbi5zdHJlYW0pIHtcbiAgICAgICAgICAgIC8vIERpc3Bvc2UgUHVibGlzaGVyJ3MgIGxvY2FsIHN0cmVhbVxuICAgICAgICAgICAgdGhpcy5jb25uZWN0aW9uLnN0cmVhbS5kaXNwb3NlV2ViUnRjUGVlcigpO1xuICAgICAgICAgICAgaWYgKHRoaXMuY29ubmVjdGlvbi5zdHJlYW0uaXNMb2NhbFN0cmVhbVB1Ymxpc2hlZCkge1xuICAgICAgICAgICAgICAgIC8vIE1ha2UgUHVibGlzaGVyIG9iamVjdCBkaXNwYXRjaCAnc3RyZWFtRGVzdHJveWVkJyBldmVudCBpZiB0aGUgU3RyZWFtIHdhcyBwdWJsaXNoZWRcbiAgICAgICAgICAgICAgICB0aGlzLmNvbm5lY3Rpb24uc3RyZWFtLmVlLmVtaXRFdmVudCgnbG9jYWwtc3RyZWFtLWRlc3Ryb3llZCcsIFtyZWFzb25dKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgc3RyaW5nQ2xpZW50TWV0YWRhdGEobWV0YWRhdGE6IGFueSk6IHN0cmluZyB7XG4gICAgICAgIGlmICh0eXBlb2YgbWV0YWRhdGEgIT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkobWV0YWRhdGEpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIG1ldGFkYXRhO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBnZXRDb25uZWN0aW9uKGNvbm5lY3Rpb25JZDogc3RyaW5nLCBlcnJvck1lc3NhZ2U6IHN0cmluZyk6IFByb21pc2U8Q29ubmVjdGlvbj4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2U8Q29ubmVjdGlvbj4oKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgY29uc3QgY29ubmVjdGlvbiA9IHRoaXMucmVtb3RlQ29ubmVjdGlvbnNbY29ubmVjdGlvbklkXTtcbiAgICAgICAgICAgIGlmICghIWNvbm5lY3Rpb24pIHtcbiAgICAgICAgICAgICAgICAvLyBSZXNvbHZlIHJlbW90ZSBjb25uZWN0aW9uXG4gICAgICAgICAgICAgICAgcmVzb2x2ZShjb25uZWN0aW9uKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuY29ubmVjdGlvbi5jb25uZWN0aW9uSWQgPT09IGNvbm5lY3Rpb25JZCkge1xuICAgICAgICAgICAgICAgICAgICAvLyBSZXNvbHZlIGxvY2FsIGNvbm5lY3Rpb25cbiAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSh0aGlzLmNvbm5lY3Rpb24pO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIENvbm5lY3Rpb24gbm90IGZvdW5kLiBSZWplY3Qgd2l0aCBPcGVuVmlkdUVycm9yXG4gICAgICAgICAgICAgICAgICAgIHJlamVjdChuZXcgT3BlblZpZHVFcnJvcihPcGVuVmlkdUVycm9yTmFtZS5HRU5FUklDX0VSUk9SLCBlcnJvck1lc3NhZ2UpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIHByaXZhdGUgZ2V0UmVtb3RlQ29ubmVjdGlvbihjb25uZWN0aW9uSWQ6IHN0cmluZywgZXJyb3JNZXNzYWdlOiBzdHJpbmcpOiBQcm9taXNlPENvbm5lY3Rpb24+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlPENvbm5lY3Rpb24+KChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGNvbm5lY3Rpb24gPSB0aGlzLnJlbW90ZUNvbm5lY3Rpb25zW2Nvbm5lY3Rpb25JZF07XG4gICAgICAgICAgICBpZiAoISFjb25uZWN0aW9uKSB7XG4gICAgICAgICAgICAgICAgLy8gUmVzb2x2ZSByZW1vdGUgY29ubmVjdGlvblxuICAgICAgICAgICAgICAgIHJlc29sdmUoY29ubmVjdGlvbik7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIC8vIFJlbW90ZSBjb25uZWN0aW9uIG5vdCBmb3VuZC4gUmVqZWN0IHdpdGggT3BlblZpZHVFcnJvclxuICAgICAgICAgICAgICAgIHJlamVjdChuZXcgT3BlblZpZHVFcnJvcihPcGVuVmlkdUVycm9yTmFtZS5HRU5FUklDX0VSUk9SLCBlcnJvck1lc3NhZ2UpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBwcm9jZXNzVG9rZW4odG9rZW46IHN0cmluZyk6IHZvaWQge1xuICAgICAgICBjb25zdCB1cmwgPSBuZXcgVVJMKHRva2VuKTtcbiAgICAgICAgdGhpcy5zZXNzaW9uSWQgPSA8c3RyaW5nPnVybC5zZWFyY2hQYXJhbXMuZ2V0KCdzZXNzaW9uSWQnKTtcbiAgICAgICAgY29uc3Qgc2VjcmV0ID0gdXJsLnNlYXJjaFBhcmFtcy5nZXQoJ3NlY3JldCcpO1xuICAgICAgICBjb25zdCByZWNvcmRlciA9IHVybC5zZWFyY2hQYXJhbXMuZ2V0KCdyZWNvcmRlcicpO1xuICAgICAgICBjb25zdCB0dXJuVXNlcm5hbWUgPSB1cmwuc2VhcmNoUGFyYW1zLmdldCgndHVyblVzZXJuYW1lJyk7XG4gICAgICAgIGNvbnN0IHR1cm5DcmVkZW50aWFsID0gdXJsLnNlYXJjaFBhcmFtcy5nZXQoJ3R1cm5DcmVkZW50aWFsJyk7XG4gICAgICAgIGNvbnN0IHJvbGUgPSB1cmwuc2VhcmNoUGFyYW1zLmdldCgncm9sZScpO1xuXG4gICAgICAgIGlmICghIXNlY3JldCkge1xuICAgICAgICAgICAgdGhpcy5vcGVudmlkdS5zZWNyZXQgPSBzZWNyZXQ7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCEhcmVjb3JkZXIpIHtcbiAgICAgICAgICAgIHRoaXMub3BlbnZpZHUucmVjb3JkZXIgPSB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIGlmICghIXR1cm5Vc2VybmFtZSAmJiAhIXR1cm5DcmVkZW50aWFsKSB7XG4gICAgICAgICAgICBjb25zdCBzdHVuVXJsID0gJ3N0dW46JyArIHVybC5ob3N0bmFtZSArICc6MzQ3OCc7XG4gICAgICAgICAgICBjb25zdCB0dXJuVXJsMSA9ICd0dXJuOicgKyB1cmwuaG9zdG5hbWUgKyAnOjM0NzgnO1xuICAgICAgICAgICAgY29uc3QgdHVyblVybDIgPSB0dXJuVXJsMSArICc/dHJhbnNwb3J0PXRjcCc7XG4gICAgICAgICAgICB0aGlzLm9wZW52aWR1LmljZVNlcnZlcnMgPSBbXG4gICAgICAgICAgICAgICAgeyB1cmxzOiBbc3R1blVybF0gfSxcbiAgICAgICAgICAgICAgICB7IHVybHM6IFt0dXJuVXJsMSwgdHVyblVybDJdLCB1c2VybmFtZTogdHVyblVzZXJuYW1lLCBjcmVkZW50aWFsOiB0dXJuQ3JlZGVudGlhbCB9XG4gICAgICAgICAgICBdO1xuICAgICAgICAgICAgY29uc29sZS5sb2coJ1RVUk4gdGVtcCBjcmVkZW50aWFscyBbJyArIHR1cm5Vc2VybmFtZSArICc6JyArIHR1cm5DcmVkZW50aWFsICsgJ10nKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoISFyb2xlKSB7XG4gICAgICAgICAgICB0aGlzLm9wZW52aWR1LnJvbGUgPSByb2xlO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5vcGVudmlkdS53c1VyaSA9ICd3c3M6Ly8nICsgdXJsLmhvc3QgKyAnL29wZW52aWR1JztcbiAgICB9XG5cbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IENvbm5lY3Rpb24gfSBmcm9tICcuL0Nvbm5lY3Rpb24nO1xuaW1wb3J0IHsgU2Vzc2lvbiB9IGZyb20gJy4vU2Vzc2lvbic7XG5pbXBvcnQgeyBTdHJlYW1NYW5hZ2VyIH0gZnJvbSAnLi9TdHJlYW1NYW5hZ2VyJztcbmltcG9ydCB7IEluYm91bmRTdHJlYW1PcHRpb25zIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9JbnRlcmZhY2VzL1ByaXZhdGUvSW5ib3VuZFN0cmVhbU9wdGlvbnMnO1xuaW1wb3J0IHsgT3V0Ym91bmRTdHJlYW1PcHRpb25zIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9JbnRlcmZhY2VzL1ByaXZhdGUvT3V0Ym91bmRTdHJlYW1PcHRpb25zJztcbmltcG9ydCB7IFdlYlJ0Y1BlZXIsIFdlYlJ0Y1BlZXJTZW5kb25seSwgV2ViUnRjUGVlclJlY3Zvbmx5LCBXZWJSdGNQZWVyU2VuZHJlY3YgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL1dlYlJ0Y1BlZXIvV2ViUnRjUGVlcic7XG5pbXBvcnQgeyBXZWJSdGNTdGF0cyB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvV2ViUnRjU3RhdHMvV2ViUnRjU3RhdHMnO1xuaW1wb3J0IHsgUHVibGlzaGVyU3BlYWtpbmdFdmVudCB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1B1Ymxpc2hlclNwZWFraW5nRXZlbnQnO1xuXG5pbXBvcnQgRXZlbnRFbWl0dGVyID0gcmVxdWlyZSgnd29sZnk4Ny1ldmVudGVtaXR0ZXInKTtcbmltcG9ydCBoYXJrID0gcmVxdWlyZSgnaGFyaycpO1xuaW1wb3J0IHsgT3BlblZpZHVFcnJvciwgT3BlblZpZHVFcnJvck5hbWUgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0VudW1zL09wZW5WaWR1RXJyb3InO1xuXG5cbi8qKlxuICogUmVwcmVzZW50cyBlYWNoIG9uZSBvZiB0aGUgbWVkaWEgc3RyZWFtcyBhdmFpbGFibGUgaW4gT3BlblZpZHUgU2VydmVyIGZvciBjZXJ0YWluIHNlc3Npb24uXG4gKiBFYWNoIFtbUHVibGlzaGVyXV0gYW5kIFtbU3Vic2NyaWJlcl1dIGhhcyBhbiBhdHRyaWJ1dGUgb2YgdHlwZSBTdHJlYW0sIGFzIHRoZXkgZ2l2ZSBhY2Nlc3NcbiAqIHRvIG9uZSBvZiB0aGVtIChzZW5kaW5nIGFuZCByZWNlaXZpbmcgaXQsIHJlc3BlY3RpdmVseSlcbiAqL1xuZXhwb3J0IGNsYXNzIFN0cmVhbSB7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgQ29ubmVjdGlvbiBvYmplY3QgdGhhdCBpcyBwdWJsaXNoaW5nIHRoZSBzdHJlYW1cbiAgICAgKi9cbiAgICBjb25uZWN0aW9uOiBDb25uZWN0aW9uO1xuXG4gICAgLyoqXG4gICAgICogRnJhbWUgcmF0ZSBvZiB0aGUgdmlkZW8gaW4gZnJhbWVzIHBlciBzZWNvbmQuIFRoaXMgcHJvcGVydHkgaXMgb25seSBkZWZpbmVkIGlmIHRoZSBbW1B1Ymxpc2hlcl1dIG9mXG4gICAgICogdGhlIHN0cmVhbSB3YXMgaW5pdGlhbGl6ZWQgcGFzc2luZyBhIF9mcmFtZVJhdGVfIHByb3BlcnR5IG9uIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dIG1ldGhvZFxuICAgICAqL1xuICAgIGZyYW1lUmF0ZT86IG51bWJlcjtcblxuICAgIC8qKlxuICAgICAqIFdoZXRoZXIgdGhlIHN0cmVhbSBoYXMgYSB2aWRlbyB0cmFjayBvciBub3RcbiAgICAgKi9cbiAgICBoYXNWaWRlbzogYm9vbGVhbjtcblxuICAgIC8qKlxuICAgICAqIFdoZXRoZXIgdGhlIHN0cmVhbSBoYXMgYW4gYXVkaW8gdHJhY2sgb3Igbm90XG4gICAgICovXG4gICAgaGFzQXVkaW86IGJvb2xlYW47XG5cbiAgICAvKipcbiAgICAgKiBXaGV0aGVyIHRoZSBzdHJlYW0gaGFzIHRoZSB2aWRlbyB0cmFjayBtdXRlZCBvciB1bm11dGVkLiBJZiBbW2hhc1ZpZGVvXV0gaXMgZmFsc2UsIHRoaXMgcHJvcGVydHkgaXMgdW5kZWZpbmVkLlxuICAgICAqXG4gICAgICogVGhpcyBwcm9wZXJ0eSBtYXkgY2hhbmdlIGlmIHRoZSBQdWJsaXNoZXIgcHVibGlzaGluZyB0aGUgc3RyZWFtIGNhbGxzIFtbUHVibGlzaGVyLnB1Ymxpc2hWaWRlb11dLiBXaGVuZXZlciB0aGlzIGhhcHBlbnMgYSBbW1N0cmVhbVByb3BlcnR5Q2hhbmdlZEV2ZW50XV0gd2lsbCBiZSBkaXNwYXRjaGVkXG4gICAgICogYnkgdGhlIFNlc3Npb24gb2JqZWN0IGFzIHdlbGwgYXMgYnkgdGhlIGFmZmVjdGVkIFN1YnNjcmliZXIvUHVibGlzaGVyIG9iamVjdFxuICAgICAqL1xuICAgIHZpZGVvQWN0aXZlOiBib29sZWFuO1xuXG4gICAgLyoqXG4gICAgICogV2hldGhlciB0aGUgc3RyZWFtIGhhcyB0aGUgYXVkaW8gdHJhY2sgbXV0ZWQgb3IgdW5tdXRlZC4gSWYgW1toYXNBdWRpb11dIGlzIGZhbHNlLCB0aGlzIHByb3BlcnR5IGlzIHVuZGVmaW5lZFxuICAgICAqXG4gICAgICogVGhpcyBwcm9wZXJ0eSBtYXkgY2hhbmdlIGlmIHRoZSBQdWJsaXNoZXIgcHVibGlzaGluZyB0aGUgc3RyZWFtIGNhbGxzIFtbUHVibGlzaGVyLnB1Ymxpc2hBdWRpb11dLiBXaGVuZXZlciB0aGlzIGhhcHBlbnMgYSBbW1N0cmVhbVByb3BlcnR5Q2hhbmdlZEV2ZW50XV0gd2lsbCBiZSBkaXNwYXRjaGVkXG4gICAgICogYnkgdGhlIFNlc3Npb24gb2JqZWN0IGFzIHdlbGwgYXMgYnkgdGhlIGFmZmVjdGVkIFN1YnNjcmliZXIvUHVibGlzaGVyIG9iamVjdFxuICAgICAqL1xuICAgIGF1ZGlvQWN0aXZlOiBib29sZWFuO1xuXG4gICAgLyoqXG4gICAgICogVW5pcXVlIGlkZW50aWZpZXIgb2YgdGhlIHN0cmVhbVxuICAgICAqL1xuICAgIHN0cmVhbUlkOiBzdHJpbmc7XG5cbiAgICAvKipcbiAgICAgKiBgXCJDQU1FUkFcImAsIGBcIlNDUkVFTlwiYCBvciBgXCJDVVNUT01cImAgKHRoZSBsYXR0ZXIgd2hlbiBbW1B1Ymxpc2hlclByb3BlcnRpZXMudmlkZW9Tb3VyY2VdXSBpcyBhIE1lZGlhU3RyZWFtVHJhY2sgd2hlbiBjYWxsaW5nIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dKS5cbiAgICAgKiBJZiBbW2hhc1ZpZGVvXV0gaXMgZmFsc2UsIHRoaXMgcHJvcGVydHkgaXMgdW5kZWZpbmVkXG4gICAgICovXG4gICAgdHlwZU9mVmlkZW8/OiBzdHJpbmc7XG5cbiAgICAvKipcbiAgICAgKiBTdHJlYW1NYW5hZ2VyIG9iamVjdCAoW1tQdWJsaXNoZXJdXSBvciBbW1N1YnNjcmliZXJdXSkgaW4gY2hhcmdlIG9mIGRpc3BsYXlpbmcgdGhpcyBzdHJlYW0gaW4gdGhlIERPTVxuICAgICAqL1xuICAgIHN0cmVhbU1hbmFnZXI6IFN0cmVhbU1hbmFnZXI7XG5cbiAgICAvKipcbiAgICAgKiBXaWR0aCBhbmQgaGVpZ2h0IGluIHBpeGVscyBvZiB0aGUgZW5jb2RlZCB2aWRlbyBzdHJlYW0uIElmIFtbaGFzVmlkZW9dXSBpcyBmYWxzZSwgdGhpcyBwcm9wZXJ0eSBpcyB1bmRlZmluZWRcbiAgICAgKlxuICAgICAqIFRoaXMgcHJvcGVydHkgbWF5IGNoYW5nZSBpZiB0aGUgUHVibGlzaGVyIHRoYXQgaXMgcHVibGlzaGluZzpcbiAgICAgKiAtIElmIGl0IGlzIGEgbW9iaWxlIGRldmljZSwgd2hlbmV2ZXIgdGhlIHVzZXIgcm90YXRlcyB0aGUgZGV2aWNlLlxuICAgICAqIC0gSWYgaXQgaXMgc2NyZWVuLXNoYXJpbmcsIHdoZW5ldmVyIHRoZSB1c2VyIGNoYW5nZXMgdGhlIHNpemUgb2YgdGhlIGNhcHR1cmVkIHdpbmRvdy5cbiAgICAgKlxuICAgICAqIFdoZW5ldmVyIHRoaXMgaGFwcGVucyBhIFtbU3RyZWFtUHJvcGVydHlDaGFuZ2VkRXZlbnRdXSB3aWxsIGJlIGRpc3BhdGNoZWQgYnkgdGhlIFNlc3Npb24gb2JqZWN0IGFzIHdlbGwgYXMgYnkgdGhlIGFmZmVjdGVkIFN1YnNjcmliZXIvUHVibGlzaGVyIG9iamVjdFxuICAgICAqL1xuICAgIHZpZGVvRGltZW5zaW9uczogeyB3aWR0aDogbnVtYmVyLCBoZWlnaHQ6IG51bWJlciB9O1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGVlID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuXG4gICAgcHJpdmF0ZSB3ZWJSdGNQZWVyOiBXZWJSdGNQZWVyO1xuICAgIHByaXZhdGUgbWVkaWFTdHJlYW06IE1lZGlhU3RyZWFtO1xuICAgIHByaXZhdGUgd2ViUnRjU3RhdHM6IFdlYlJ0Y1N0YXRzO1xuXG4gICAgcHJpdmF0ZSBpc1N1YnNjcmliZVRvUmVtb3RlID0gZmFsc2U7XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgaXNMb2NhbFN0cmVhbVJlYWR5VG9QdWJsaXNoID0gZmFsc2U7XG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGlzTG9jYWxTdHJlYW1QdWJsaXNoZWQgPSBmYWxzZTtcbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgcHVibGlzaGVkT25jZSA9IGZhbHNlO1xuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBzZXNzaW9uOiBTZXNzaW9uO1xuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBpbmJvdW5kU3RyZWFtT3B0czogSW5ib3VuZFN0cmVhbU9wdGlvbnM7XG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIG91dGJvdW5kU3RyZWFtT3B0czogT3V0Ym91bmRTdHJlYW1PcHRpb25zO1xuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBzcGVlY2hFdmVudDogYW55O1xuXG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgY29uc3RydWN0b3Ioc2Vzc2lvbjogU2Vzc2lvbiwgb3B0aW9uczogSW5ib3VuZFN0cmVhbU9wdGlvbnMgfCBPdXRib3VuZFN0cmVhbU9wdGlvbnMgfCB7fSkge1xuXG4gICAgICAgIHRoaXMuc2Vzc2lvbiA9IHNlc3Npb247XG5cbiAgICAgICAgaWYgKG9wdGlvbnMuaGFzT3duUHJvcGVydHkoJ2lkJykpIHtcbiAgICAgICAgICAgIC8vIEluYm91bmRTdHJlYW1PcHRpb25zOiBzdHJlYW0gYmVsb25ncyB0byBhIFN1YnNjcmliZXJcbiAgICAgICAgICAgIHRoaXMuaW5ib3VuZFN0cmVhbU9wdHMgPSA8SW5ib3VuZFN0cmVhbU9wdGlvbnM+b3B0aW9ucztcbiAgICAgICAgICAgIHRoaXMuc3RyZWFtSWQgPSB0aGlzLmluYm91bmRTdHJlYW1PcHRzLmlkO1xuICAgICAgICAgICAgdGhpcy5oYXNBdWRpbyA9IHRoaXMuaW5ib3VuZFN0cmVhbU9wdHMuaGFzQXVkaW87XG4gICAgICAgICAgICB0aGlzLmhhc1ZpZGVvID0gdGhpcy5pbmJvdW5kU3RyZWFtT3B0cy5oYXNWaWRlbztcbiAgICAgICAgICAgIGlmICh0aGlzLmhhc0F1ZGlvKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5hdWRpb0FjdGl2ZSA9IHRoaXMuaW5ib3VuZFN0cmVhbU9wdHMuYXVkaW9BY3RpdmU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodGhpcy5oYXNWaWRlbykge1xuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9BY3RpdmUgPSB0aGlzLmluYm91bmRTdHJlYW1PcHRzLnZpZGVvQWN0aXZlO1xuICAgICAgICAgICAgICAgIHRoaXMudHlwZU9mVmlkZW8gPSAoIXRoaXMuaW5ib3VuZFN0cmVhbU9wdHMudHlwZU9mVmlkZW8pID8gdW5kZWZpbmVkIDogdGhpcy5pbmJvdW5kU3RyZWFtT3B0cy50eXBlT2ZWaWRlbztcbiAgICAgICAgICAgICAgICB0aGlzLmZyYW1lUmF0ZSA9ICh0aGlzLmluYm91bmRTdHJlYW1PcHRzLmZyYW1lUmF0ZSA9PT0gLTEpID8gdW5kZWZpbmVkIDogdGhpcy5pbmJvdW5kU3RyZWFtT3B0cy5mcmFtZVJhdGU7XG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb0RpbWVuc2lvbnMgPSB0aGlzLmluYm91bmRTdHJlYW1PcHRzLnZpZGVvRGltZW5zaW9ucztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIE91dGJvdW5kU3RyZWFtT3B0aW9uczogc3RyZWFtIGJlbG9uZ3MgdG8gYSBQdWJsaXNoZXJcbiAgICAgICAgICAgIHRoaXMub3V0Ym91bmRTdHJlYW1PcHRzID0gPE91dGJvdW5kU3RyZWFtT3B0aW9ucz5vcHRpb25zO1xuXG4gICAgICAgICAgICB0aGlzLmhhc0F1ZGlvID0gdGhpcy5pc1NlbmRBdWRpbygpO1xuICAgICAgICAgICAgdGhpcy5oYXNWaWRlbyA9IHRoaXMuaXNTZW5kVmlkZW8oKTtcblxuICAgICAgICAgICAgaWYgKHRoaXMuaGFzQXVkaW8pIHtcbiAgICAgICAgICAgICAgICB0aGlzLmF1ZGlvQWN0aXZlID0gISF0aGlzLm91dGJvdW5kU3RyZWFtT3B0cy5wdWJsaXNoZXJQcm9wZXJ0aWVzLnB1Ymxpc2hBdWRpbztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0aGlzLmhhc1ZpZGVvKSB7XG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb0FjdGl2ZSA9ICEhdGhpcy5vdXRib3VuZFN0cmVhbU9wdHMucHVibGlzaGVyUHJvcGVydGllcy5wdWJsaXNoVmlkZW87XG4gICAgICAgICAgICAgICAgdGhpcy5mcmFtZVJhdGUgPSB0aGlzLm91dGJvdW5kU3RyZWFtT3B0cy5wdWJsaXNoZXJQcm9wZXJ0aWVzLmZyYW1lUmF0ZTtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5vdXRib3VuZFN0cmVhbU9wdHMucHVibGlzaGVyUHJvcGVydGllcy52aWRlb1NvdXJjZSBpbnN0YW5jZW9mIE1lZGlhU3RyZWFtVHJhY2spIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy50eXBlT2ZWaWRlbyA9ICdDVVNUT00nO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMudHlwZU9mVmlkZW8gPSB0aGlzLmlzU2VuZFNjcmVlbigpID8gJ1NDUkVFTicgOiAnQ0FNRVJBJztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLmVlLm9uKCdtZWRpYXN0cmVhbS11cGRhdGVkJywgKCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5zdHJlYW1NYW5hZ2VyLnVwZGF0ZU1lZGlhU3RyZWFtKHRoaXMubWVkaWFTdHJlYW0pO1xuICAgICAgICAgICAgY29uc29sZS5kZWJ1ZygnVmlkZW8gc3JjT2JqZWN0IFsnICsgdGhpcy5tZWRpYVN0cmVhbSArICddIHVwZGF0ZWQgaW4gc3RyZWFtIFsnICsgdGhpcy5zdHJlYW1JZCArICddJyk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuXG4gICAgLyogSGlkZGVuIG1ldGhvZHMgKi9cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBnZXRNZWRpYVN0cmVhbSgpOiBNZWRpYVN0cmVhbSB7XG4gICAgICAgIHJldHVybiB0aGlzLm1lZGlhU3RyZWFtO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBzZXRNZWRpYVN0cmVhbShtZWRpYVN0cmVhbTogTWVkaWFTdHJlYW0pOiB2b2lkIHtcbiAgICAgICAgdGhpcy5tZWRpYVN0cmVhbSA9IG1lZGlhU3RyZWFtO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICB1cGRhdGVNZWRpYVN0cmVhbUluVmlkZW9zKCkge1xuICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnbWVkaWFzdHJlYW0tdXBkYXRlZCcpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBnZXRXZWJSdGNQZWVyKCk6IFdlYlJ0Y1BlZXIge1xuICAgICAgICByZXR1cm4gdGhpcy53ZWJSdGNQZWVyO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBnZXRSVENQZWVyQ29ubmVjdGlvbigpOiBSVENQZWVyQ29ubmVjdGlvbiB7XG4gICAgICAgIHJldHVybiB0aGlzLndlYlJ0Y1BlZXIucGM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHN1YnNjcmliZVRvTXlSZW1vdGUodmFsdWU6IGJvb2xlYW4pOiB2b2lkIHtcbiAgICAgICAgdGhpcy5pc1N1YnNjcmliZVRvUmVtb3RlID0gdmFsdWU7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHNldE91dGJvdW5kU3RyZWFtT3B0aW9ucyhvdXRib3VuZFN0cmVhbU9wdHM6IE91dGJvdW5kU3RyZWFtT3B0aW9ucyk6IHZvaWQge1xuICAgICAgICB0aGlzLm91dGJvdW5kU3RyZWFtT3B0cyA9IG91dGJvdW5kU3RyZWFtT3B0cztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgc3Vic2NyaWJlKCk6IFByb21pc2U8YW55PiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICB0aGlzLmluaXRXZWJSdGNQZWVyUmVjZWl2ZSgpXG4gICAgICAgICAgICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgcHVibGlzaCgpOiBQcm9taXNlPGFueT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgaWYgKHRoaXMuaXNMb2NhbFN0cmVhbVJlYWR5VG9QdWJsaXNoKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5pbml0V2ViUnRjUGVlclNlbmQoKVxuICAgICAgICAgICAgICAgICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy5lZS5vbmNlKCdzdHJlYW0tcmVhZHktdG8tcHVibGlzaCcsICgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5wdWJsaXNoKClcbiAgICAgICAgICAgICAgICAgICAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgICAgICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBkaXNwb3NlV2ViUnRjUGVlcigpOiB2b2lkIHtcbiAgICAgICAgaWYgKHRoaXMud2ViUnRjUGVlcikge1xuICAgICAgICAgICAgdGhpcy53ZWJSdGNQZWVyLmRpc3Bvc2UoKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5zcGVlY2hFdmVudCkge1xuICAgICAgICAgICAgdGhpcy5zcGVlY2hFdmVudC5zdG9wKCk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLnN0b3BXZWJSdGNTdGF0cygpO1xuXG4gICAgICAgIGNvbnNvbGUuaW5mbygoISF0aGlzLm91dGJvdW5kU3RyZWFtT3B0cyA/ICdPdXRib3VuZCAnIDogJ0luYm91bmQgJykgKyBcIldlYlJUQ1BlZXIgZnJvbSAnU3RyZWFtJyB3aXRoIGlkIFtcIiArIHRoaXMuc3RyZWFtSWQgKyAnXSBpcyBub3cgY2xvc2VkJyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGRpc3Bvc2VNZWRpYVN0cmVhbSgpOiB2b2lkIHtcbiAgICAgICAgaWYgKHRoaXMubWVkaWFTdHJlYW0pIHtcbiAgICAgICAgICAgIHRoaXMubWVkaWFTdHJlYW0uZ2V0QXVkaW9UcmFja3MoKS5mb3JFYWNoKCh0cmFjaykgPT4ge1xuICAgICAgICAgICAgICAgIHRyYWNrLnN0b3AoKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgdGhpcy5tZWRpYVN0cmVhbS5nZXRWaWRlb1RyYWNrcygpLmZvckVhY2goKHRyYWNrKSA9PiB7XG4gICAgICAgICAgICAgICAgdHJhY2suc3RvcCgpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBkZWxldGUgdGhpcy5tZWRpYVN0cmVhbTtcbiAgICAgICAgfVxuICAgICAgICBjb25zb2xlLmluZm8oKCEhdGhpcy5vdXRib3VuZFN0cmVhbU9wdHMgPyAnTG9jYWwgJyA6ICdSZW1vdGUgJykgKyBcIk1lZGlhU3RyZWFtIGZyb20gJ1N0cmVhbScgd2l0aCBpZCBbXCIgKyB0aGlzLnN0cmVhbUlkICsgJ10gaXMgbm93IGRpc3Bvc2VkJyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGRpc3BsYXlNeVJlbW90ZSgpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuaXNTdWJzY3JpYmVUb1JlbW90ZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgaXNTZW5kQXVkaW8oKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiAoISF0aGlzLm91dGJvdW5kU3RyZWFtT3B0cyAmJlxuICAgICAgICAgICAgdGhpcy5vdXRib3VuZFN0cmVhbU9wdHMucHVibGlzaGVyUHJvcGVydGllcy5hdWRpb1NvdXJjZSAhPT0gbnVsbCAmJlxuICAgICAgICAgICAgdGhpcy5vdXRib3VuZFN0cmVhbU9wdHMucHVibGlzaGVyUHJvcGVydGllcy5hdWRpb1NvdXJjZSAhPT0gZmFsc2UpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBpc1NlbmRWaWRlbygpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuICghIXRoaXMub3V0Ym91bmRTdHJlYW1PcHRzICYmXG4gICAgICAgICAgICB0aGlzLm91dGJvdW5kU3RyZWFtT3B0cy5wdWJsaXNoZXJQcm9wZXJ0aWVzLnZpZGVvU291cmNlICE9PSBudWxsICYmXG4gICAgICAgICAgICB0aGlzLm91dGJvdW5kU3RyZWFtT3B0cy5wdWJsaXNoZXJQcm9wZXJ0aWVzLnZpZGVvU291cmNlICE9PSBmYWxzZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGlzU2VuZFNjcmVlbigpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuICghIXRoaXMub3V0Ym91bmRTdHJlYW1PcHRzICYmXG4gICAgICAgICAgICB0aGlzLm91dGJvdW5kU3RyZWFtT3B0cy5wdWJsaXNoZXJQcm9wZXJ0aWVzLnZpZGVvU291cmNlID09PSAnc2NyZWVuJyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHNldFNwZWVjaEV2ZW50SWZOb3RFeGlzdHMoKTogdm9pZCB7XG4gICAgICAgIGlmICghdGhpcy5zcGVlY2hFdmVudCkge1xuICAgICAgICAgICAgY29uc3QgaGFya09wdGlvbnMgPSB0aGlzLnNlc3Npb24ub3BlbnZpZHUuYWR2YW5jZWRDb25maWd1cmF0aW9uLnB1Ymxpc2hlclNwZWFraW5nRXZlbnRzT3B0aW9ucyB8fCB7fTtcbiAgICAgICAgICAgIGhhcmtPcHRpb25zLmludGVydmFsID0gKHR5cGVvZiBoYXJrT3B0aW9ucy5pbnRlcnZhbCA9PT0gJ251bWJlcicpID8gaGFya09wdGlvbnMuaW50ZXJ2YWwgOiA1MDtcbiAgICAgICAgICAgIGhhcmtPcHRpb25zLnRocmVzaG9sZCA9ICh0eXBlb2YgaGFya09wdGlvbnMudGhyZXNob2xkID09PSAnbnVtYmVyJykgPyBoYXJrT3B0aW9ucy50aHJlc2hvbGQgOiAtNTA7XG5cbiAgICAgICAgICAgIHRoaXMuc3BlZWNoRXZlbnQgPSBoYXJrKHRoaXMubWVkaWFTdHJlYW0sIGhhcmtPcHRpb25zKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBlbmFibGVTcGVha2luZ0V2ZW50cygpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5zZXRTcGVlY2hFdmVudElmTm90RXhpc3RzKCk7XG4gICAgICAgIHRoaXMuc3BlZWNoRXZlbnQub24oJ3NwZWFraW5nJywgKCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5zZXNzaW9uLmVtaXRFdmVudCgncHVibGlzaGVyU3RhcnRTcGVha2luZycsIFtuZXcgUHVibGlzaGVyU3BlYWtpbmdFdmVudCh0aGlzLnNlc3Npb24sICdwdWJsaXNoZXJTdGFydFNwZWFraW5nJywgdGhpcy5jb25uZWN0aW9uLCB0aGlzLnN0cmVhbUlkKV0pO1xuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy5zcGVlY2hFdmVudC5vbignc3RvcHBlZF9zcGVha2luZycsICgpID0+IHtcbiAgICAgICAgICAgIHRoaXMuc2Vzc2lvbi5lbWl0RXZlbnQoJ3B1Ymxpc2hlclN0b3BTcGVha2luZycsIFtuZXcgUHVibGlzaGVyU3BlYWtpbmdFdmVudCh0aGlzLnNlc3Npb24sICdwdWJsaXNoZXJTdG9wU3BlYWtpbmcnLCB0aGlzLmNvbm5lY3Rpb24sIHRoaXMuc3RyZWFtSWQpXSk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBlbmFibGVPbmNlU3BlYWtpbmdFdmVudHMoKTogdm9pZCB7XG4gICAgICAgIHRoaXMuc2V0U3BlZWNoRXZlbnRJZk5vdEV4aXN0cygpO1xuICAgICAgICB0aGlzLnNwZWVjaEV2ZW50Lm9uKCdzcGVha2luZycsICgpID0+IHtcbiAgICAgICAgICAgIHRoaXMuc2Vzc2lvbi5lbWl0RXZlbnQoJ3B1Ymxpc2hlclN0YXJ0U3BlYWtpbmcnLCBbbmV3IFB1Ymxpc2hlclNwZWFraW5nRXZlbnQodGhpcy5zZXNzaW9uLCAncHVibGlzaGVyU3RhcnRTcGVha2luZycsIHRoaXMuY29ubmVjdGlvbiwgdGhpcy5zdHJlYW1JZCldKTtcbiAgICAgICAgICAgIHRoaXMuZGlzYWJsZVNwZWFraW5nRXZlbnRzKCk7XG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLnNwZWVjaEV2ZW50Lm9uKCdzdG9wcGVkX3NwZWFraW5nJywgKCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5zZXNzaW9uLmVtaXRFdmVudCgncHVibGlzaGVyU3RvcFNwZWFraW5nJywgW25ldyBQdWJsaXNoZXJTcGVha2luZ0V2ZW50KHRoaXMuc2Vzc2lvbiwgJ3B1Ymxpc2hlclN0b3BTcGVha2luZycsIHRoaXMuY29ubmVjdGlvbiwgdGhpcy5zdHJlYW1JZCldKTtcbiAgICAgICAgICAgIHRoaXMuZGlzYWJsZVNwZWFraW5nRXZlbnRzKCk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBkaXNhYmxlU3BlYWtpbmdFdmVudHMoKTogdm9pZCB7XG4gICAgICAgIHRoaXMuc3BlZWNoRXZlbnQuc3RvcCgpO1xuICAgICAgICB0aGlzLnNwZWVjaEV2ZW50ID0gdW5kZWZpbmVkO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBpc0xvY2FsKCk6IGJvb2xlYW4ge1xuICAgICAgICAvLyBpbmJvdW5kIG9wdGlvbnMgdW5kZWZpbmVkIGFuZCBvdXRib3VuZCBvcHRpb25zIGRlZmluZWRcbiAgICAgICAgcmV0dXJuICghdGhpcy5pbmJvdW5kU3RyZWFtT3B0cyAmJiAhIXRoaXMub3V0Ym91bmRTdHJlYW1PcHRzKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgZ2V0U2VsZWN0ZWRJY2VDYW5kaWRhdGUoKTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIHRoaXMud2ViUnRjU3RhdHMuZ2V0U2VsZWN0ZWRJY2VDYW5kaWRhdGVJbmZvKClcbiAgICAgICAgICAgICAgICAudGhlbihyZXBvcnQgPT4gcmVzb2x2ZShyZXBvcnQpKVxuICAgICAgICAgICAgICAgIC5jYXRjaChlcnJvciA9PiByZWplY3QoZXJyb3IpKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGdldFJlbW90ZUljZUNhbmRpZGF0ZUxpc3QoKTogUlRDSWNlQ2FuZGlkYXRlW10ge1xuICAgICAgICByZXR1cm4gdGhpcy53ZWJSdGNQZWVyLnJlbW90ZUNhbmRpZGF0ZXNRdWV1ZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgZ2V0TG9jYWxJY2VDYW5kaWRhdGVMaXN0KCk6IFJUQ0ljZUNhbmRpZGF0ZVtdIHtcbiAgICAgICAgcmV0dXJuIHRoaXMud2ViUnRjUGVlci5sb2NhbENhbmRpZGF0ZXNRdWV1ZTtcbiAgICB9XG5cbiAgICAvKiBQcml2YXRlIG1ldGhvZHMgKi9cblxuICAgIHByaXZhdGUgaW5pdFdlYlJ0Y1BlZXJTZW5kKCk6IFByb21pc2U8YW55PiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG5cbiAgICAgICAgICAgIGNvbnN0IHVzZXJNZWRpYUNvbnN0cmFpbnRzID0ge1xuICAgICAgICAgICAgICAgIGF1ZGlvOiB0aGlzLmlzU2VuZEF1ZGlvKCksXG4gICAgICAgICAgICAgICAgdmlkZW86IHRoaXMuaXNTZW5kVmlkZW8oKVxuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgY29uc3Qgb3B0aW9ucyA9IHtcbiAgICAgICAgICAgICAgICBtZWRpYVN0cmVhbTogdGhpcy5tZWRpYVN0cmVhbSxcbiAgICAgICAgICAgICAgICBtZWRpYUNvbnN0cmFpbnRzOiB1c2VyTWVkaWFDb25zdHJhaW50cyxcbiAgICAgICAgICAgICAgICBvbmljZWNhbmRpZGF0ZTogdGhpcy5jb25uZWN0aW9uLnNlbmRJY2VDYW5kaWRhdGUuYmluZCh0aGlzLmNvbm5lY3Rpb24pLFxuICAgICAgICAgICAgICAgIGljZVNlcnZlcnM6IHRoaXMuZ2V0SWNlU2VydmVyc0NvbmYoKSxcbiAgICAgICAgICAgICAgICBzaW11bGNhc3Q6IGZhbHNlXG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICBjb25zdCBzdWNjZXNzQ2FsbGJhY2sgPSAoc2RwT2ZmZXJQYXJhbSkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuZGVidWcoJ1NlbmRpbmcgU0RQIG9mZmVyIHRvIHB1Ymxpc2ggYXMgJ1xuICAgICAgICAgICAgICAgICAgICArIHRoaXMuc3RyZWFtSWQsIHNkcE9mZmVyUGFyYW0pO1xuXG4gICAgICAgICAgICAgICAgbGV0IHR5cGVPZlZpZGVvID0gJyc7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuaXNTZW5kVmlkZW8oKSkge1xuICAgICAgICAgICAgICAgICAgICB0eXBlT2ZWaWRlbyA9IHRoaXMub3V0Ym91bmRTdHJlYW1PcHRzLnB1Ymxpc2hlclByb3BlcnRpZXMudmlkZW9Tb3VyY2UgaW5zdGFuY2VvZiBNZWRpYVN0cmVhbVRyYWNrID8gJ0NVU1RPTScgOiAodGhpcy5pc1NlbmRTY3JlZW4oKSA/ICdTQ1JFRU4nIDogJ0NBTUVSQScpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMuc2Vzc2lvbi5vcGVudmlkdS5zZW5kUmVxdWVzdCgncHVibGlzaFZpZGVvJywge1xuICAgICAgICAgICAgICAgICAgICBzZHBPZmZlcjogc2RwT2ZmZXJQYXJhbSxcbiAgICAgICAgICAgICAgICAgICAgZG9Mb29wYmFjazogdGhpcy5kaXNwbGF5TXlSZW1vdGUoKSB8fCBmYWxzZSxcbiAgICAgICAgICAgICAgICAgICAgaGFzQXVkaW86IHRoaXMuaXNTZW5kQXVkaW8oKSxcbiAgICAgICAgICAgICAgICAgICAgaGFzVmlkZW86IHRoaXMuaXNTZW5kVmlkZW8oKSxcbiAgICAgICAgICAgICAgICAgICAgYXVkaW9BY3RpdmU6IHRoaXMuYXVkaW9BY3RpdmUsXG4gICAgICAgICAgICAgICAgICAgIHZpZGVvQWN0aXZlOiB0aGlzLnZpZGVvQWN0aXZlLFxuICAgICAgICAgICAgICAgICAgICB0eXBlT2ZWaWRlbyxcbiAgICAgICAgICAgICAgICAgICAgZnJhbWVSYXRlOiAhIXRoaXMuZnJhbWVSYXRlID8gdGhpcy5mcmFtZVJhdGUgOiAtMSxcbiAgICAgICAgICAgICAgICAgICAgdmlkZW9EaW1lbnNpb25zOiBKU09OLnN0cmluZ2lmeSh0aGlzLnZpZGVvRGltZW5zaW9ucylcbiAgICAgICAgICAgICAgICB9LCAoZXJyb3IsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yLmNvZGUgPT09IDQwMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChuZXcgT3BlblZpZHVFcnJvcihPcGVuVmlkdUVycm9yTmFtZS5PUEVOVklEVV9QRVJNSVNTSU9OX0RFTklFRCwgXCJZb3UgZG9uJ3QgaGF2ZSBwZXJtaXNzaW9ucyB0byBwdWJsaXNoXCIpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KCdFcnJvciBvbiBwdWJsaXNoVmlkZW86ICcgKyBKU09OLnN0cmluZ2lmeShlcnJvcikpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy53ZWJSdGNQZWVyLnByb2Nlc3NBbnN3ZXIocmVzcG9uc2Uuc2RwQW5zd2VyKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdHJlYW1JZCA9IHJlc3BvbnNlLmlkO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmlzTG9jYWxTdHJlYW1QdWJsaXNoZWQgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnB1Ymxpc2hlZE9uY2UgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5kaXNwbGF5TXlSZW1vdGUoKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5yZW1vdGVQZWVyU3VjY2Vzc2Z1bGx5RXN0YWJsaXNoZWQoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnc3RyZWFtLWNyZWF0ZWQtYnktcHVibGlzaGVyJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuaW5pdFdlYlJ0Y1N0YXRzKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oXCInUHVibGlzaGVyJyBzdWNjZXNzZnVsbHkgcHVibGlzaGVkIHRvIHNlc3Npb25cIik7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIGlmICh0aGlzLmRpc3BsYXlNeVJlbW90ZSgpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy53ZWJSdGNQZWVyID0gbmV3IFdlYlJ0Y1BlZXJTZW5kcmVjdihvcHRpb25zKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy53ZWJSdGNQZWVyID0gbmV3IFdlYlJ0Y1BlZXJTZW5kb25seShvcHRpb25zKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMud2ViUnRjUGVlci5nZW5lcmF0ZU9mZmVyKCkudGhlbihvZmZlciA9PiB7XG4gICAgICAgICAgICAgICAgc3VjY2Vzc0NhbGxiYWNrKG9mZmVyKTtcbiAgICAgICAgICAgIH0pLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICAgICAgICByZWplY3QobmV3IEVycm9yKCcocHVibGlzaCkgU0RQIG9mZmVyIGVycm9yOiAnICsgSlNPTi5zdHJpbmdpZnkoZXJyb3IpKSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBpbml0V2ViUnRjUGVlclJlY2VpdmUoKTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcblxuICAgICAgICAgICAgY29uc3Qgb2ZmZXJDb25zdHJhaW50cyA9IHtcbiAgICAgICAgICAgICAgICBhdWRpbzogdGhpcy5pbmJvdW5kU3RyZWFtT3B0cy5oYXNBdWRpbyxcbiAgICAgICAgICAgICAgICB2aWRlbzogdGhpcy5pbmJvdW5kU3RyZWFtT3B0cy5oYXNWaWRlb1xuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGNvbnNvbGUuZGVidWcoXCInU2Vzc2lvbi5zdWJzY3JpYmUoU3RyZWFtKScgY2FsbGVkLiBDb25zdHJhaW50cyBvZiBnZW5lcmF0ZSBTRFAgb2ZmZXJcIixcbiAgICAgICAgICAgICAgICBvZmZlckNvbnN0cmFpbnRzKTtcbiAgICAgICAgICAgIGNvbnN0IG9wdGlvbnMgPSB7XG4gICAgICAgICAgICAgICAgb25pY2VjYW5kaWRhdGU6IHRoaXMuY29ubmVjdGlvbi5zZW5kSWNlQ2FuZGlkYXRlLmJpbmQodGhpcy5jb25uZWN0aW9uKSxcbiAgICAgICAgICAgICAgICBtZWRpYUNvbnN0cmFpbnRzOiBvZmZlckNvbnN0cmFpbnRzLFxuICAgICAgICAgICAgICAgIGljZVNlcnZlcnM6IHRoaXMuZ2V0SWNlU2VydmVyc0NvbmYoKSxcbiAgICAgICAgICAgICAgICBzaW11bGNhc3Q6IGZhbHNlXG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICBjb25zdCBzdWNjZXNzQ2FsbGJhY2sgPSAoc2RwT2ZmZXJQYXJhbSkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuZGVidWcoJ1NlbmRpbmcgU0RQIG9mZmVyIHRvIHN1YnNjcmliZSB0byAnXG4gICAgICAgICAgICAgICAgICAgICsgdGhpcy5zdHJlYW1JZCwgc2RwT2ZmZXJQYXJhbSk7XG4gICAgICAgICAgICAgICAgdGhpcy5zZXNzaW9uLm9wZW52aWR1LnNlbmRSZXF1ZXN0KCdyZWNlaXZlVmlkZW9Gcm9tJywge1xuICAgICAgICAgICAgICAgICAgICBzZW5kZXI6IHRoaXMuc3RyZWFtSWQsXG4gICAgICAgICAgICAgICAgICAgIHNkcE9mZmVyOiBzZHBPZmZlclBhcmFtXG4gICAgICAgICAgICAgICAgfSwgKGVycm9yLCByZXNwb25zZSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBpZiAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChuZXcgRXJyb3IoJ0Vycm9yIG9uIHJlY3ZWaWRlb0Zyb206ICcgKyBKU09OLnN0cmluZ2lmeShlcnJvcikpKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMud2ViUnRjUGVlci5wcm9jZXNzQW5zd2VyKHJlc3BvbnNlLnNkcEFuc3dlcikudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5yZW1vdGVQZWVyU3VjY2Vzc2Z1bGx5RXN0YWJsaXNoZWQoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmluaXRXZWJSdGNTdGF0cygpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIHRoaXMud2ViUnRjUGVlciA9IG5ldyBXZWJSdGNQZWVyUmVjdm9ubHkob3B0aW9ucyk7XG4gICAgICAgICAgICB0aGlzLndlYlJ0Y1BlZXIuZ2VuZXJhdGVPZmZlcigpXG4gICAgICAgICAgICAgICAgLnRoZW4ob2ZmZXIgPT4ge1xuICAgICAgICAgICAgICAgICAgICBzdWNjZXNzQ2FsbGJhY2sob2ZmZXIpO1xuICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICAgICAgICAgICAgcmVqZWN0KG5ldyBFcnJvcignKHN1YnNjcmliZSkgU0RQIG9mZmVyIGVycm9yOiAnICsgSlNPTi5zdHJpbmdpZnkoZXJyb3IpKSk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIHByaXZhdGUgcmVtb3RlUGVlclN1Y2Nlc3NmdWxseUVzdGFibGlzaGVkKCk6IHZvaWQge1xuICAgICAgICB0aGlzLm1lZGlhU3RyZWFtID0gdGhpcy53ZWJSdGNQZWVyLnBjLmdldFJlbW90ZVN0cmVhbXMoKVswXTtcbiAgICAgICAgY29uc29sZS5kZWJ1ZygnUGVlciByZW1vdGUgc3RyZWFtJywgdGhpcy5tZWRpYVN0cmVhbSk7XG5cbiAgICAgICAgaWYgKCEhdGhpcy5tZWRpYVN0cmVhbSkge1xuICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ21lZGlhc3RyZWFtLXVwZGF0ZWQnKTtcbiAgICAgICAgICAgIGlmICghdGhpcy5kaXNwbGF5TXlSZW1vdGUoKSAmJiAhIXRoaXMubWVkaWFTdHJlYW0uZ2V0QXVkaW9UcmFja3MoKVswXSAmJiB0aGlzLnNlc3Npb24uc3BlYWtpbmdFdmVudHNFbmFibGVkKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5lbmFibGVTcGVha2luZ0V2ZW50cygpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBpbml0V2ViUnRjU3RhdHMoKTogdm9pZCB7XG4gICAgICAgIHRoaXMud2ViUnRjU3RhdHMgPSBuZXcgV2ViUnRjU3RhdHModGhpcyk7XG4gICAgICAgIHRoaXMud2ViUnRjU3RhdHMuaW5pdFdlYlJ0Y1N0YXRzKCk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBzdG9wV2ViUnRjU3RhdHMoKTogdm9pZCB7XG4gICAgICAgIGlmICghIXRoaXMud2ViUnRjU3RhdHMgJiYgdGhpcy53ZWJSdGNTdGF0cy5pc0VuYWJsZWQoKSkge1xuICAgICAgICAgICAgdGhpcy53ZWJSdGNTdGF0cy5zdG9wV2ViUnRjU3RhdHMoKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgZ2V0SWNlU2VydmVyc0NvbmYoKTogUlRDSWNlU2VydmVyW10gfCB1bmRlZmluZWQge1xuICAgICAgICBsZXQgcmV0dXJuVmFsdWU7XG4gICAgICAgIGlmICghIXRoaXMuc2Vzc2lvbi5vcGVudmlkdS5hZHZhbmNlZENvbmZpZ3VyYXRpb24uaWNlU2VydmVycykge1xuICAgICAgICAgICAgcmV0dXJuVmFsdWUgPSB0aGlzLnNlc3Npb24ub3BlbnZpZHUuYWR2YW5jZWRDb25maWd1cmF0aW9uLmljZVNlcnZlcnMgPT09ICdmcmVlaWNlJyA/XG4gICAgICAgICAgICAgICAgdW5kZWZpbmVkIDpcbiAgICAgICAgICAgICAgICB0aGlzLnNlc3Npb24ub3BlbnZpZHUuYWR2YW5jZWRDb25maWd1cmF0aW9uLmljZVNlcnZlcnM7XG4gICAgICAgIH0gZWxzZSBpZiAodGhpcy5zZXNzaW9uLm9wZW52aWR1LmljZVNlcnZlcnMpIHtcbiAgICAgICAgICAgIHJldHVyblZhbHVlID0gdGhpcy5zZXNzaW9uLm9wZW52aWR1LmljZVNlcnZlcnM7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm5WYWx1ZSA9IHVuZGVmaW5lZDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcmV0dXJuVmFsdWU7XG4gICAgfVxuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBTdHJlYW0gfSBmcm9tICcuL1N0cmVhbSc7XG5pbXBvcnQgeyBFdmVudERpc3BhdGNoZXIgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHVibGljL0V2ZW50RGlzcGF0Y2hlcic7XG5pbXBvcnQgeyBTdHJlYW1NYW5hZ2VyVmlkZW8gfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHVibGljL1N0cmVhbU1hbmFnZXJWaWRlbyc7XG5pbXBvcnQgeyBFdmVudCB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL0V2ZW50JztcbmltcG9ydCB7IFN0cmVhbU1hbmFnZXJFdmVudCB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1N0cmVhbU1hbmFnZXJFdmVudCc7XG5pbXBvcnQgeyBWaWRlb0VsZW1lbnRFdmVudCB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1ZpZGVvRWxlbWVudEV2ZW50JztcbmltcG9ydCB7IFZpZGVvSW5zZXJ0TW9kZSB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRW51bXMvVmlkZW9JbnNlcnRNb2RlJztcblxuaW1wb3J0IEV2ZW50RW1pdHRlciA9IHJlcXVpcmUoJ3dvbGZ5ODctZXZlbnRlbWl0dGVyJyk7XG5cblxuLyoqXG4gKiBJbnRlcmZhY2UgaW4gY2hhcmdlIG9mIGRpc3BsYXlpbmcgdGhlIG1lZGlhIHN0cmVhbXMgaW4gdGhlIEhUTUwgRE9NLiBUaGlzIHdyYXBzIGFueSBbW1B1Ymxpc2hlcl1dIGFuZCBbW1N1YnNjcmliZXJdXSBvYmplY3QuXG4gKiBZb3UgY2FuIGluc2VydCBhcyBtYW55IHZpZGVvIHBsYXllcnMgZm8gdGhlIHNhbWUgU3RyZWFtIGFzIHlvdSB3YW50IGJ5IGNhbGxpbmcgW1tTdHJlYW1NYW5hZ2VyLmFkZFZpZGVvRWxlbWVudF1dIG9yXG4gKiBbW1N0cmVhbU1hbmFnZXIuY3JlYXRlVmlkZW9FbGVtZW50XV0uXG4gKlxuICogVGhlIHVzZSBvZiBTdHJlYW1NYW5hZ2VyIHdyYXBwZXIgaXMgcGFydGljdWxhcmx5IHVzZWZ1bCB3aGVuIHlvdSBkb24ndCBuZWVkIHRvIGRpZmZlcmVudGlhdGUgYmV0d2VlbiBQdWJsaXNoZXIgb3IgU3Vic2NyaWJlciBzdHJlYW1zIG9yIGp1c3RcbiAqIHdhbnQgdG8gZGlyZWN0bHkgbWFuYWdlIHlvdXIgb3duIHZpZGVvIGVsZW1lbnRzIChldmVuIG1vcmUgdGhhbiBvbmUgdmlkZW8gZWxlbWVudCBwZXIgU3RyZWFtKS4gVGhpcyBzY2VuYXJpbyBpcyBwcmV0dHkgY29tbW9uIGluXG4gKiBkZWNsYXJhdGl2ZSwgTVZDIGZyb250ZW5kIGZyYW1ld29ya3Mgc3VjaCBhcyBBbmd1bGFyLCBSZWFjdCBvciBWdWUuanNcbiAqL1xuZXhwb3J0IGNsYXNzIFN0cmVhbU1hbmFnZXIgaW1wbGVtZW50cyBFdmVudERpc3BhdGNoZXIge1xuXG4gICAgLyoqXG4gICAgICogVGhlIFN0cmVhbSByZXByZXNlbnRlZCBpbiB0aGUgRE9NIGJ5IHRoZSBQdWJsaXNoZXIvU3Vic2NyaWJlclxuICAgICAqL1xuICAgIHN0cmVhbTogU3RyZWFtO1xuXG4gICAgLyoqXG4gICAgICogQWxsIHRoZSB2aWRlb3MgZGlzcGxheWluZyB0aGUgU3RyZWFtIG9mIHRoaXMgUHVibGlzaGVyL1N1YnNjcmliZXJcbiAgICAgKi9cbiAgICB2aWRlb3M6IFN0cmVhbU1hbmFnZXJWaWRlb1tdID0gW107XG5cbiAgICAvKipcbiAgICAgKiBXaGV0aGVyIHRoZSBTdHJlYW0gcmVwcmVzZW50ZWQgaW4gdGhlIERPTSBpcyBsb2NhbCBvciByZW1vdGVcbiAgICAgKiAtIGBmYWxzZWAgZm9yIFtbUHVibGlzaGVyXV1cbiAgICAgKiAtIGB0cnVlYCBmb3IgW1tTdWJzY3JpYmVyXV1cbiAgICAgKi9cbiAgICByZW1vdGU6IGJvb2xlYW47XG5cbiAgICAvKipcbiAgICAgKiBUaGUgRE9NIEhUTUxFbGVtZW50IGFzc2lnbmVkIGFzIHRhcmdldCBlbGVtZW50IHdoZW4gY3JlYXRpbmcgdGhlIHZpZGVvIGZvciB0aGUgUHVibGlzaGVyL1N1YnNjcmliZXIuIFRoaXMgcHJvcGVydHkgaXMgb25seSBkZWZpbmVkIGlmOlxuICAgICAqIC0gW1tQdWJsaXNoZXJdXSBoYXMgYmVlbiBpbml0aWFsaXplZCBieSBjYWxsaW5nIG1ldGhvZCBbW09wZW5WaWR1LmluaXRQdWJsaXNoZXJdXSB3aXRoIGEgdmFsaWQgYHRhcmdldEVsZW1lbnRgIHBhcmFtZXRlclxuICAgICAqIC0gW1tTdWJzY3JpYmVyXV0gaGFzIGJlZW4gaW5pdGlhbGl6ZWQgYnkgY2FsbGluZyBtZXRob2QgW1tTZXNzaW9uLnN1YnNjcmliZV1dIHdpdGggYSB2YWxpZCBgdGFyZ2V0RWxlbWVudGAgcGFyYW1ldGVyXG4gICAgICovXG4gICAgdGFyZ2V0RWxlbWVudDogSFRNTEVsZW1lbnQ7XG5cbiAgICAvKipcbiAgICAgKiBgaWRgIGF0dHJpYnV0ZSBvZiB0aGUgRE9NIHZpZGVvIGVsZW1lbnQgZGlzcGxheWluZyB0aGUgUHVibGlzaGVyL1N1YnNjcmliZXIncyBzdHJlYW0uIFRoaXMgcHJvcGVydHkgaXMgb25seSBkZWZpbmVkIGlmOlxuICAgICAqIC0gW1tQdWJsaXNoZXJdXSBoYXMgYmVlbiBpbml0aWFsaXplZCBieSBjYWxsaW5nIG1ldGhvZCBbW09wZW5WaWR1LmluaXRQdWJsaXNoZXJdXSB3aXRoIGEgdmFsaWQgYHRhcmdldEVsZW1lbnRgIHBhcmFtZXRlclxuICAgICAqIC0gW1tTdWJzY3JpYmVyXV0gaGFzIGJlZW4gaW5pdGlhbGl6ZWQgYnkgY2FsbGluZyBtZXRob2QgW1tTZXNzaW9uLnN1YnNjcmliZV1dIHdpdGggYSB2YWxpZCBgdGFyZ2V0RWxlbWVudGAgcGFyYW1ldGVyXG4gICAgICovXG4gICAgaWQ6IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBmaXJzdFZpZGVvRWxlbWVudDogU3RyZWFtTWFuYWdlclZpZGVvO1xuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBsYXp5TGF1bmNoVmlkZW9FbGVtZW50Q3JlYXRlZEV2ZW50ID0gZmFsc2U7XG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGVsZW1lbnQ6IEhUTUxFbGVtZW50O1xuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgZWUgPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHByb3RlY3RlZCBjYW5QbGF5TGlzdGVuZXI6IEV2ZW50TGlzdGVuZXJPckV2ZW50TGlzdGVuZXJPYmplY3Q7XG5cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3RvcihzdHJlYW06IFN0cmVhbSwgdGFyZ2V0RWxlbWVudD86IEhUTUxFbGVtZW50IHwgc3RyaW5nKSB7XG4gICAgICAgIHRoaXMuc3RyZWFtID0gc3RyZWFtO1xuICAgICAgICB0aGlzLnN0cmVhbS5zdHJlYW1NYW5hZ2VyID0gdGhpcztcbiAgICAgICAgdGhpcy5yZW1vdGUgPSAhdGhpcy5zdHJlYW0uaXNMb2NhbCgpO1xuXG4gICAgICAgIGlmICghIXRhcmdldEVsZW1lbnQpIHtcbiAgICAgICAgICAgIGxldCB0YXJnRWw7XG4gICAgICAgICAgICBpZiAodHlwZW9mIHRhcmdldEVsZW1lbnQgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAgICAgdGFyZ0VsID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQodGFyZ2V0RWxlbWVudCk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHRhcmdldEVsZW1lbnQgaW5zdGFuY2VvZiBIVE1MRWxlbWVudCkge1xuICAgICAgICAgICAgICAgIHRhcmdFbCA9IHRhcmdldEVsZW1lbnQ7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICghIXRhcmdFbCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZmlyc3RWaWRlb0VsZW1lbnQgPSB7XG4gICAgICAgICAgICAgICAgICAgIHRhcmdldEVsZW1lbnQ6IHRhcmdFbCxcbiAgICAgICAgICAgICAgICAgICAgdmlkZW86IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3ZpZGVvJyksXG4gICAgICAgICAgICAgICAgICAgIGlkOiAnJ1xuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgdGhpcy50YXJnZXRFbGVtZW50ID0gdGFyZ0VsO1xuICAgICAgICAgICAgICAgIHRoaXMuZWxlbWVudCA9IHRhcmdFbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICB0aGlzLmNhblBsYXlMaXN0ZW5lciA9ICgpID0+IHtcbiAgICAgICAgICAgIGlmICh0aGlzLnN0cmVhbS5pc0xvY2FsKCkpIHtcbiAgICAgICAgICAgICAgICBpZiAoIXRoaXMuc3RyZWFtLmRpc3BsYXlNeVJlbW90ZSgpKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbyhcIllvdXIgbG9jYWwgJ1N0cmVhbScgd2l0aCBpZCBbXCIgKyB0aGlzLnN0cmVhbS5zdHJlYW1JZCArICddIHZpZGVvIGlzIG5vdyBwbGF5aW5nJyk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCd2aWRlb1BsYXlpbmcnLCBbbmV3IFZpZGVvRWxlbWVudEV2ZW50KHRoaXMudmlkZW9zWzBdLnZpZGVvLCB0aGlzLCAndmlkZW9QbGF5aW5nJyldKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oXCJZb3VyIG93biByZW1vdGUgJ1N0cmVhbScgd2l0aCBpZCBbXCIgKyB0aGlzLnN0cmVhbS5zdHJlYW1JZCArICddIHZpZGVvIGlzIG5vdyBwbGF5aW5nJyk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdyZW1vdGVWaWRlb1BsYXlpbmcnLCBbbmV3IFZpZGVvRWxlbWVudEV2ZW50KHRoaXMudmlkZW9zWzBdLnZpZGVvLCB0aGlzLCAncmVtb3RlVmlkZW9QbGF5aW5nJyldKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbyhcIlJlbW90ZSAnU3RyZWFtJyB3aXRoIGlkIFtcIiArIHRoaXMuc3RyZWFtLnN0cmVhbUlkICsgJ10gdmlkZW8gaXMgbm93IHBsYXlpbmcnKTtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgndmlkZW9QbGF5aW5nJywgW25ldyBWaWRlb0VsZW1lbnRFdmVudCh0aGlzLnZpZGVvc1swXS52aWRlbywgdGhpcywgJ3ZpZGVvUGxheWluZycpXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnc3RyZWFtUGxheWluZycsIFtuZXcgU3RyZWFtTWFuYWdlckV2ZW50KHRoaXMpXSk7XG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2VlIFtbRXZlbnREaXNwYXRjaGVyLm9uXV1cbiAgICAgKi9cbiAgICBvbih0eXBlOiBzdHJpbmcsIGhhbmRsZXI6IChldmVudDogRXZlbnQpID0+IHZvaWQpOiBFdmVudERpc3BhdGNoZXIge1xuICAgICAgICB0aGlzLmVlLm9uKHR5cGUsIGV2ZW50ID0+IHtcbiAgICAgICAgICAgIGlmIChldmVudCkge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbyhcIkV2ZW50ICdcIiArIHR5cGUgKyBcIicgdHJpZ2dlcmVkIGJ5ICdcIiArICh0aGlzLnJlbW90ZSA/ICdTdWJzY3JpYmVyJyA6ICdQdWJsaXNoZXInKSArIFwiJ1wiLCBldmVudCk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbyhcIkV2ZW50ICdcIiArIHR5cGUgKyBcIicgdHJpZ2dlcmVkIGJ5ICdcIiArICh0aGlzLnJlbW90ZSA/ICdTdWJzY3JpYmVyJyA6ICdQdWJsaXNoZXInKSArIFwiJ1wiKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGhhbmRsZXIoZXZlbnQpO1xuICAgICAgICB9KTtcbiAgICAgICAgaWYgKHR5cGUgPT09ICd2aWRlb0VsZW1lbnRDcmVhdGVkJykge1xuICAgICAgICAgICAgaWYgKCEhdGhpcy5zdHJlYW0gJiYgdGhpcy5sYXp5TGF1bmNoVmlkZW9FbGVtZW50Q3JlYXRlZEV2ZW50KSB7XG4gICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3ZpZGVvRWxlbWVudENyZWF0ZWQnLCBbbmV3IFZpZGVvRWxlbWVudEV2ZW50KHRoaXMudmlkZW9zWzBdLnZpZGVvLCB0aGlzLCAndmlkZW9FbGVtZW50Q3JlYXRlZCcpXSk7XG4gICAgICAgICAgICAgICAgdGhpcy5sYXp5TGF1bmNoVmlkZW9FbGVtZW50Q3JlYXRlZEV2ZW50ID0gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHR5cGUgPT09ICdzdHJlYW1QbGF5aW5nJyB8fCB0eXBlID09PSAndmlkZW9QbGF5aW5nJykge1xuICAgICAgICAgICAgaWYgKHRoaXMudmlkZW9zWzBdICYmIHRoaXMudmlkZW9zWzBdLnZpZGVvICYmXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8uY3VycmVudFRpbWUgPiAwICYmXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8ucGF1c2VkID09PSBmYWxzZSAmJlxuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9zWzBdLnZpZGVvLmVuZGVkID09PSBmYWxzZSAmJlxuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9zWzBdLnZpZGVvLnJlYWR5U3RhdGUgPT09IDQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnc3RyZWFtUGxheWluZycsIFtuZXcgU3RyZWFtTWFuYWdlckV2ZW50KHRoaXMpXSk7XG4gICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3ZpZGVvUGxheWluZycsIFtuZXcgVmlkZW9FbGVtZW50RXZlbnQodGhpcy52aWRlb3NbMF0udmlkZW8sIHRoaXMsICd2aWRlb1BsYXlpbmcnKV0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNlZSBbW0V2ZW50RGlzcGF0Y2hlci5vbmNlXV1cbiAgICAgKi9cbiAgICBvbmNlKHR5cGU6IHN0cmluZywgaGFuZGxlcjogKGV2ZW50OiBFdmVudCkgPT4gdm9pZCk6IFN0cmVhbU1hbmFnZXIge1xuICAgICAgICB0aGlzLmVlLm9uY2UodHlwZSwgZXZlbnQgPT4ge1xuICAgICAgICAgICAgaWYgKGV2ZW50KSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5pbmZvKFwiRXZlbnQgJ1wiICsgdHlwZSArIFwiJyB0cmlnZ2VyZWQgb25jZVwiLCBldmVudCk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbyhcIkV2ZW50ICdcIiArIHR5cGUgKyBcIicgdHJpZ2dlcmVkIG9uY2VcIik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBoYW5kbGVyKGV2ZW50KTtcbiAgICAgICAgfSk7XG4gICAgICAgIGlmICh0eXBlID09PSAndmlkZW9FbGVtZW50Q3JlYXRlZCcpIHtcbiAgICAgICAgICAgIGlmICghIXRoaXMuc3RyZWFtICYmIHRoaXMubGF6eUxhdW5jaFZpZGVvRWxlbWVudENyZWF0ZWRFdmVudCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCd2aWRlb0VsZW1lbnRDcmVhdGVkJywgW25ldyBWaWRlb0VsZW1lbnRFdmVudCh0aGlzLnZpZGVvc1swXS52aWRlbywgdGhpcywgJ3ZpZGVvRWxlbWVudENyZWF0ZWQnKV0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmICh0eXBlID09PSAnc3RyZWFtUGxheWluZycgfHwgdHlwZSA9PT0gJ3ZpZGVvUGxheWluZycpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLnZpZGVvc1swXSAmJiB0aGlzLnZpZGVvc1swXS52aWRlbyAmJlxuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9zWzBdLnZpZGVvLmN1cnJlbnRUaW1lID4gMCAmJlxuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9zWzBdLnZpZGVvLnBhdXNlZCA9PT0gZmFsc2UgJiZcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvc1swXS52aWRlby5lbmRlZCA9PT0gZmFsc2UgJiZcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvc1swXS52aWRlby5yZWFkeVN0YXRlID09PSA0KSB7XG4gICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3N0cmVhbVBsYXlpbmcnLCBbbmV3IFN0cmVhbU1hbmFnZXJFdmVudCh0aGlzKV0pO1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCd2aWRlb1BsYXlpbmcnLCBbbmV3IFZpZGVvRWxlbWVudEV2ZW50KHRoaXMudmlkZW9zWzBdLnZpZGVvLCB0aGlzLCAndmlkZW9QbGF5aW5nJyldKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZWUgW1tFdmVudERpc3BhdGNoZXIub2ZmXV1cbiAgICAgKi9cbiAgICBvZmYodHlwZTogc3RyaW5nLCBoYW5kbGVyPzogKGV2ZW50OiBFdmVudCkgPT4gdm9pZCk6IFN0cmVhbU1hbmFnZXIge1xuICAgICAgICBpZiAoIWhhbmRsZXIpIHtcbiAgICAgICAgICAgIHRoaXMuZWUucmVtb3ZlQWxsTGlzdGVuZXJzKHR5cGUpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5lZS5vZmYodHlwZSwgaGFuZGxlcik7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogTWFrZXMgYHZpZGVvYCBlbGVtZW50IHBhcmFtZXRlciBkaXNwbGF5IHRoaXMgW1tzdHJlYW1dXS4gVGhpcyBpcyB1c2VmdWwgd2hlbiB5b3UgYXJlXG4gICAgICogW21hbmFnaW5nIHRoZSB2aWRlbyBlbGVtZW50cyBvbiB5b3VyIG93bl0oL2RvY3MvaG93LWRvLWkvbWFuYWdlLXZpZGVvcy8jeW91LXRha2UtY2FyZS1vZi10aGUtdmlkZW8tcGxheWVycylcbiAgICAgKlxuICAgICAqIENhbGxpbmcgdGhpcyBtZXRob2Qgd2l0aCBhIHZpZGVvIGFscmVhZHkgYWRkZWQgdG8gb3RoZXIgUHVibGlzaGVyL1N1YnNjcmliZXIgd2lsbCBjYXVzZSB0aGUgdmlkZW8gZWxlbWVudCB0byBiZVxuICAgICAqIGRpc2Fzc29jaWF0ZWQgZnJvbSB0aGF0IHByZXZpb3VzIFB1Ymxpc2hlci9TdWJzY3JpYmVyIGFuZCB0byBiZSBhc3NvY2lhdGVkIHRvIHRoaXMgb25lLlxuICAgICAqXG4gICAgICogQHJldHVybnMgMSBpZiB0aGUgdmlkZW8gd2Fzbid0IGFzc29jaWF0ZWQgdG8gYW55IG90aGVyIFB1Ymxpc2hlci9TdWJzY3JpYmVyIGFuZCBoYXMgYmVlbiBzdWNjZXNzZnVsbHkgYWRkZWQgdG8gdGhpcyBvbmUuXG4gICAgICogMCBpZiB0aGUgdmlkZW8gd2FzIGFscmVhZHkgYWRkZWQgdG8gdGhpcyBQdWJsaXNoZXIvU3Vic2NyaWJlci4gLTEgaWYgdGhlIHZpZGVvIHdhcyBwcmV2aW91c2x5IGFzc29jaWF0ZWQgdG8gYW55IG90aGVyXG4gICAgICogUHVibGlzaGVyL1N1YnNjcmliZXIgYW5kIGhhcyBiZWVuIHN1Y2Nlc3NmdWxseSBkaXNhc3NvY2lhdGVkIGZyb20gdGhhdCBvbmUgYW5kIHByb3Blcmx5IGFkZGVkIHRvIHRoaXMgb25lLlxuICAgICAqL1xuICAgIGFkZFZpZGVvRWxlbWVudCh2aWRlbzogSFRNTFZpZGVvRWxlbWVudCk6IG51bWJlciB7XG5cbiAgICAgICAgdGhpcy5pbml0aWFsaXplVmlkZW9Qcm9wZXJ0aWVzKHZpZGVvKTtcblxuICAgICAgICAvLyBJZiB0aGUgdmlkZW8gZWxlbWVudCBpcyBhbHJlYWR5IHBhcnQgb2YgdGhpcyBTdHJlYW1NYW5hZ2VyIGRvIG5vdGhpbmdcbiAgICAgICAgZm9yIChjb25zdCB2IG9mIHRoaXMudmlkZW9zKSB7XG4gICAgICAgICAgICBpZiAodi52aWRlbyA9PT0gdmlkZW8pIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gMDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGxldCByZXR1cm5OdW1iZXIgPSAxO1xuXG4gICAgICAgIGZvciAoY29uc3Qgc3RyZWFtTWFuYWdlciBvZiB0aGlzLnN0cmVhbS5zZXNzaW9uLnN0cmVhbU1hbmFnZXJzKSB7XG4gICAgICAgICAgICBpZiAoc3RyZWFtTWFuYWdlci5kaXNhc3NvY2lhdGVWaWRlbyh2aWRlbykpIHtcbiAgICAgICAgICAgICAgICByZXR1cm5OdW1iZXIgPSAtMTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuc3RyZWFtLnNlc3Npb24uc3RyZWFtTWFuYWdlcnMuZm9yRWFjaChzdHJlYW1NYW5hZ2VyID0+IHtcbiAgICAgICAgICAgIHN0cmVhbU1hbmFnZXIuZGlzYXNzb2NpYXRlVmlkZW8odmlkZW8pO1xuICAgICAgICB9KTtcblxuICAgICAgICB0aGlzLnB1c2hOZXdTdHJlYW1NYW5hZ2VyVmlkZW8oe1xuICAgICAgICAgICAgdmlkZW8sXG4gICAgICAgICAgICBpZDogdmlkZW8uaWRcbiAgICAgICAgfSk7XG5cbiAgICAgICAgY29uc29sZS5pbmZvKCdOZXcgdmlkZW8gZWxlbWVudCBhc3NvY2lhdGVkIHRvICcsIHRoaXMpO1xuXG4gICAgICAgIHJldHVybiByZXR1cm5OdW1iZXI7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIG5ldyB2aWRlbyBlbGVtZW50IGRpc3BsYXlpbmcgdGhpcyBbW3N0cmVhbV1dLiBUaGlzIGFsbG93cyB5b3UgdG8gaGF2ZSBtdWx0aXBsZSB2aWRlbyBlbGVtZW50cyBkaXNwbGF5aW5nIHRoZSBzYW1lIG1lZGlhIHN0cmVhbS5cbiAgICAgKlxuICAgICAqICMjIyMgRXZlbnRzIGRpc3BhdGNoZWRcbiAgICAgKlxuICAgICAqIFRoZSBQdWJsaXNoZXIvU3Vic2NyaWJlciBvYmplY3Qgd2lsbCBkaXNwYXRjaCBhIGB2aWRlb0VsZW1lbnRDcmVhdGVkYCBldmVudCBvbmNlIHRoZSBIVE1MIHZpZGVvIGVsZW1lbnQgaGFzIGJlZW4gYWRkZWQgdG8gRE9NLiBTZWUgW1tWaWRlb0VsZW1lbnRFdmVudF1dXG4gICAgICpcbiAgICAgKiBAcGFyYW0gdGFyZ2V0RWxlbWVudCBIVE1MIERPTSBlbGVtZW50IChvciBpdHMgYGlkYCBhdHRyaWJ1dGUpIGluIHdoaWNoIHRoZSB2aWRlbyBlbGVtZW50IG9mIHRoZSBQdWJsaXNoZXIvU3Vic2NyaWJlciB3aWxsIGJlIGluc2VydGVkXG4gICAgICogQHBhcmFtIGluc2VydE1vZGUgSG93IHRoZSB2aWRlbyBlbGVtZW50IHdpbGwgYmUgaW5zZXJ0ZWQgYWNjb3JkaW5nbHkgdG8gYHRhcmdldEVsZW1ldGBcbiAgICAgKi9cbiAgICBjcmVhdGVWaWRlb0VsZW1lbnQodGFyZ2V0RWxlbWVudD86IHN0cmluZyB8IEhUTUxFbGVtZW50LCBpbnNlcnRNb2RlPzogVmlkZW9JbnNlcnRNb2RlKTogSFRNTFZpZGVvRWxlbWVudCB7XG4gICAgICAgIGxldCB0YXJnRWw7XG4gICAgICAgIGlmICh0eXBlb2YgdGFyZ2V0RWxlbWVudCA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgIHRhcmdFbCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKHRhcmdFbCk7XG4gICAgICAgICAgICBpZiAoIXRhcmdFbCkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIlRoZSBwcm92aWRlZCAndGFyZ2V0RWxlbWVudCcgY291bGRuJ3QgYmUgcmVzb2x2ZWQgdG8gYW55IEhUTUwgZWxlbWVudDogXCIgKyB0YXJnZXRFbGVtZW50KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIGlmICh0YXJnZXRFbGVtZW50IGluc3RhbmNlb2YgSFRNTEVsZW1lbnQpIHtcbiAgICAgICAgICAgIHRhcmdFbCA9IHRhcmdldEVsZW1lbnQ7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJUaGUgcHJvdmlkZWQgJ3RhcmdldEVsZW1lbnQnIGNvdWxkbid0IGJlIHJlc29sdmVkIHRvIGFueSBIVE1MIGVsZW1lbnQ6IFwiICsgdGFyZ2V0RWxlbWVudCk7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCB2aWRlbyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3ZpZGVvJyk7XG4gICAgICAgIHRoaXMuaW5pdGlhbGl6ZVZpZGVvUHJvcGVydGllcyh2aWRlbyk7XG5cbiAgICAgICAgbGV0IGluc01vZGUgPSAhIWluc2VydE1vZGUgPyBpbnNlcnRNb2RlIDogVmlkZW9JbnNlcnRNb2RlLkFQUEVORDtcbiAgICAgICAgc3dpdGNoIChpbnNNb2RlKSB7XG4gICAgICAgICAgICBjYXNlIFZpZGVvSW5zZXJ0TW9kZS5BRlRFUjpcbiAgICAgICAgICAgICAgICB0YXJnRWwucGFyZW50Tm9kZSEhLmluc2VydEJlZm9yZSh2aWRlbywgdGFyZ0VsLm5leHRTaWJsaW5nKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgVmlkZW9JbnNlcnRNb2RlLkFQUEVORDpcbiAgICAgICAgICAgICAgICB0YXJnRWwuYXBwZW5kQ2hpbGQodmlkZW8pO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBWaWRlb0luc2VydE1vZGUuQkVGT1JFOlxuICAgICAgICAgICAgICAgIHRhcmdFbC5wYXJlbnROb2RlISEuaW5zZXJ0QmVmb3JlKHZpZGVvLCB0YXJnRWwpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBWaWRlb0luc2VydE1vZGUuUFJFUEVORDpcbiAgICAgICAgICAgICAgICB0YXJnRWwuaW5zZXJ0QmVmb3JlKHZpZGVvLCB0YXJnRWwuY2hpbGROb2Rlc1swXSk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIFZpZGVvSW5zZXJ0TW9kZS5SRVBMQUNFOlxuICAgICAgICAgICAgICAgIHRhcmdFbC5wYXJlbnROb2RlISEucmVwbGFjZUNoaWxkKHZpZGVvLCB0YXJnRWwpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICBpbnNNb2RlID0gVmlkZW9JbnNlcnRNb2RlLkFQUEVORDtcbiAgICAgICAgICAgICAgICB0YXJnRWwuYXBwZW5kQ2hpbGQodmlkZW8pO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgdjogU3RyZWFtTWFuYWdlclZpZGVvID0ge1xuICAgICAgICAgICAgdGFyZ2V0RWxlbWVudDogdGFyZ0VsLFxuICAgICAgICAgICAgdmlkZW8sXG4gICAgICAgICAgICBpbnNlcnRNb2RlOiBpbnNNb2RlLFxuICAgICAgICAgICAgaWQ6IHZpZGVvLmlkXG4gICAgICAgIH07XG4gICAgICAgIHRoaXMucHVzaE5ld1N0cmVhbU1hbmFnZXJWaWRlbyh2KTtcblxuICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgndmlkZW9FbGVtZW50Q3JlYXRlZCcsIFtuZXcgVmlkZW9FbGVtZW50RXZlbnQodi52aWRlbywgdGhpcywgJ3ZpZGVvRWxlbWVudENyZWF0ZWQnKV0pO1xuXG4gICAgICAgIHRoaXMubGF6eUxhdW5jaFZpZGVvRWxlbWVudENyZWF0ZWRFdmVudCA9ICEhdGhpcy5maXJzdFZpZGVvRWxlbWVudDtcblxuICAgICAgICByZXR1cm4gdmlkZW87XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGluaXRpYWxpemVWaWRlb1Byb3BlcnRpZXModmlkZW86IEhUTUxWaWRlb0VsZW1lbnQpOiB2b2lkIHtcbiAgICAgICAgaWYgKCEodGhpcy5zdHJlYW0uaXNMb2NhbCgpICYmIHRoaXMuc3RyZWFtLmRpc3BsYXlNeVJlbW90ZSgpKSkge1xuICAgICAgICAgICAgLy8gQXZvaWQgc2V0dGluZyB0aGUgTWVkaWFTdHJlYW0gaW50byB0aGUgc3JjT2JqZWN0IGlmIHJlbW90ZSBzdWJzY3JpcHRpb24gYmVmb3JlIHB1Ymxpc2hpbmdcbiAgICAgICAgICAgIHZpZGVvLnNyY09iamVjdCA9IHRoaXMuc3RyZWFtLmdldE1lZGlhU3RyZWFtKCk7XG4gICAgICAgIH1cbiAgICAgICAgdmlkZW8uYXV0b3BsYXkgPSB0cnVlO1xuICAgICAgICB2aWRlby5jb250cm9scyA9IGZhbHNlO1xuICAgICAgICBpZiAoIXZpZGVvLmlkKSB7XG4gICAgICAgICAgICB2aWRlby5pZCA9ICh0aGlzLnJlbW90ZSA/ICdyZW1vdGUtJyA6ICdsb2NhbC0nKSArICd2aWRlby0nICsgdGhpcy5zdHJlYW0uc3RyZWFtSWQ7XG4gICAgICAgICAgICAvLyBERVBSRUNBVEVEIHByb3BlcnR5OiBhc3NpZ24gb25jZSB0aGUgcHJvcGVydHkgaWQgaWYgdGhlIHVzZXIgcHJvdmlkZWQgYSB2YWxpZCB0YXJnZXRFbGVtZW50XG4gICAgICAgICAgICBpZiAoIXRoaXMuaWQgJiYgISF0aGlzLnRhcmdldEVsZW1lbnQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmlkID0gdmlkZW8uaWQ7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCF0aGlzLnJlbW90ZSAmJiAhdGhpcy5zdHJlYW0uZGlzcGxheU15UmVtb3RlKCkpIHtcbiAgICAgICAgICAgIHZpZGVvLm11dGVkID0gdHJ1ZTtcbiAgICAgICAgICAgIGlmICh0aGlzLnN0cmVhbS5vdXRib3VuZFN0cmVhbU9wdHMucHVibGlzaGVyUHJvcGVydGllcy5taXJyb3IpIHtcbiAgICAgICAgICAgICAgICB0aGlzLm1pcnJvclZpZGVvKHZpZGVvKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICByZW1vdmVBbGxWaWRlb3MoKTogdm9pZCB7XG4gICAgICAgIGZvciAobGV0IGkgPSB0aGlzLnN0cmVhbS5zZXNzaW9uLnN0cmVhbU1hbmFnZXJzLmxlbmd0aCAtIDE7IGkgPj0gMDsgLS1pKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5zdHJlYW0uc2Vzc2lvbi5zdHJlYW1NYW5hZ2Vyc1tpXSA9PT0gdGhpcykge1xuICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtLnNlc3Npb24uc3RyZWFtTWFuYWdlcnMuc3BsaWNlKGksIDEpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy52aWRlb3MuZm9yRWFjaChzdHJlYW1NYW5hZ2VyVmlkZW8gPT4ge1xuICAgICAgICAgICAgLy8gUmVtb3ZlIG9uY2FucGxheSBldmVudCBsaXN0ZW5lciAob25seSBPcGVuVmlkdSBicm93c2VyIG9uZSwgbm90IHRoZSB1c2VyIG9uZXMpXG4gICAgICAgICAgICBzdHJlYW1NYW5hZ2VyVmlkZW8udmlkZW8ucmVtb3ZlRXZlbnRMaXN0ZW5lcignY2FucGxheScsIHRoaXMuY2FuUGxheUxpc3RlbmVyKTtcbiAgICAgICAgICAgIGlmICghIXN0cmVhbU1hbmFnZXJWaWRlby50YXJnZXRFbGVtZW50KSB7XG4gICAgICAgICAgICAgICAgLy8gT25seSByZW1vdmUgZnJvbSBET00gdmlkZW9zIGNyZWF0ZWQgYnkgT3BlblZpZHUgQnJvd3NlciAodGhvc2UgZ2VuZXJhdGVkIGJ5IHBhc3NpbmcgYSB2YWxpZCB0YXJnZXRFbGVtZW50IGluIE9wZW5WaWR1LmluaXRQdWJsaXNoZXJcbiAgICAgICAgICAgICAgICAvLyBhbmQgU2Vzc2lvbi5zdWJzY3JpYmUgb3IgdGhvc2UgY3JlYXRlZCBieSBTdHJlYW1NYW5hZ2VyLmNyZWF0ZVZpZGVvRWxlbWVudCkuIEFsbCB0aGlzIHZpZGVvcyB0cmlnZ2VyZWQgYSB2aWRlb0VsZW1lbnRDcmVhdGVkIGV2ZW50XG4gICAgICAgICAgICAgICAgc3RyZWFtTWFuYWdlclZpZGVvLnZpZGVvLnBhcmVudE5vZGUhLnJlbW92ZUNoaWxkKHN0cmVhbU1hbmFnZXJWaWRlby52aWRlbyk7XG4gICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3ZpZGVvRWxlbWVudERlc3Ryb3llZCcsIFtuZXcgVmlkZW9FbGVtZW50RXZlbnQoc3RyZWFtTWFuYWdlclZpZGVvLnZpZGVvLCB0aGlzLCAndmlkZW9FbGVtZW50RGVzdHJveWVkJyldKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIFJlbW92ZSBzcmNPYmplY3QgZnJvbSB0aGUgdmlkZW9cbiAgICAgICAgICAgIHN0cmVhbU1hbmFnZXJWaWRlby52aWRlby5zcmNPYmplY3QgPSBudWxsO1xuICAgICAgICAgICAgLy8gUmVtb3ZlIGZyb20gY29sbGVjdGlvbiBvZiB2aWRlb3MgZXZlcnkgdmlkZW8gbWFuYWdlZCBieSBPcGVuVmlkdSBCcm93c2VyXG4gICAgICAgICAgICB0aGlzLnZpZGVvcy5maWx0ZXIodiA9PiAhdi50YXJnZXRFbGVtZW50KTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGRpc2Fzc29jaWF0ZVZpZGVvKHZpZGVvOiBIVE1MVmlkZW9FbGVtZW50KTogYm9vbGVhbiB7XG4gICAgICAgIGxldCBkaXNhc3NvY2lhdGVkID0gZmFsc2U7XG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy52aWRlb3MubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGlmICh0aGlzLnZpZGVvc1tpXS52aWRlbyA9PT0gdmlkZW8pIHtcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvcy5zcGxpY2UoaSwgMSk7XG4gICAgICAgICAgICAgICAgZGlzYXNzb2NpYXRlZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgY29uc29sZS5pbmZvKCdWaWRlbyBlbGVtZW50IGRpc2Fzc29jaWF0ZWQgZnJvbSAnLCB0aGlzKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZGlzYXNzb2NpYXRlZDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgYWRkUGxheUV2ZW50VG9GaXJzdFZpZGVvKCkge1xuICAgICAgICBpZiAoKCEhdGhpcy52aWRlb3NbMF0pICYmICghIXRoaXMudmlkZW9zWzBdLnZpZGVvKSAmJiAodGhpcy52aWRlb3NbMF0udmlkZW8ub25jYW5wbGF5ID09PSBudWxsKSkge1xuICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8uYWRkRXZlbnRMaXN0ZW5lcignY2FucGxheScsIHRoaXMuY2FuUGxheUxpc3RlbmVyKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICB1cGRhdGVNZWRpYVN0cmVhbShtZWRpYVN0cmVhbTogTWVkaWFTdHJlYW0pIHtcbiAgICAgICAgdGhpcy52aWRlb3MuZm9yRWFjaChzdHJlYW1NYW5hZ2VyVmlkZW8gPT4ge1xuICAgICAgICAgICAgc3RyZWFtTWFuYWdlclZpZGVvLnZpZGVvLnNyY09iamVjdCA9IG1lZGlhU3RyZWFtO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgZW1pdEV2ZW50KHR5cGU6IHN0cmluZywgZXZlbnRBcnJheTogYW55W10pOiB2b2lkIHtcbiAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQodHlwZSwgZXZlbnRBcnJheSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBwdXNoTmV3U3RyZWFtTWFuYWdlclZpZGVvKHN0cmVhbU1hbmFnZXJWaWRlbzogU3RyZWFtTWFuYWdlclZpZGVvKSB7XG4gICAgICAgIHRoaXMudmlkZW9zLnB1c2goc3RyZWFtTWFuYWdlclZpZGVvKTtcbiAgICAgICAgdGhpcy5hZGRQbGF5RXZlbnRUb0ZpcnN0VmlkZW8oKTtcbiAgICAgICAgaWYgKHRoaXMuc3RyZWFtLnNlc3Npb24uc3RyZWFtTWFuYWdlcnMuaW5kZXhPZih0aGlzKSA9PT0gLTEpIHtcbiAgICAgICAgICAgIHRoaXMuc3RyZWFtLnNlc3Npb24uc3RyZWFtTWFuYWdlcnMucHVzaCh0aGlzKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgbWlycm9yVmlkZW8odmlkZW8pOiB2b2lkIHtcbiAgICAgICAgdmlkZW8uc3R5bGUudHJhbnNmb3JtID0gJ3JvdGF0ZVkoMTgwZGVnKSc7XG4gICAgICAgIHZpZGVvLnN0eWxlLndlYmtpdFRyYW5zZm9ybSA9ICdyb3RhdGVZKDE4MGRlZyknO1xuICAgIH1cblxufSIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTctMjAxOCBPcGVuVmlkdSAoaHR0cHM6Ly9vcGVudmlkdS5pby8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuaW1wb3J0IHsgU3RyZWFtIH0gZnJvbSAnLi9TdHJlYW0nO1xuaW1wb3J0IHsgU3RyZWFtTWFuYWdlciB9IGZyb20gJy4vU3RyZWFtTWFuYWdlcic7XG5pbXBvcnQgeyBTdWJzY3JpYmVyUHJvcGVydGllcyB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvSW50ZXJmYWNlcy9QdWJsaWMvU3Vic2NyaWJlclByb3BlcnRpZXMnO1xuXG5cbi8qKlxuICogUGFja3MgcmVtb3RlIG1lZGlhIHN0cmVhbXMuIFBhcnRpY2lwYW50cyBhdXRvbWF0aWNhbGx5IHJlY2VpdmUgdGhlbSB3aGVuIG90aGVycyBwdWJsaXNoIHRoZWlyIHN0cmVhbXMuIEluaXRpYWxpemVkIHdpdGggW1tTZXNzaW9uLnN1YnNjcmliZV1dIG1ldGhvZFxuICovXG5leHBvcnQgY2xhc3MgU3Vic2NyaWJlciBleHRlbmRzIFN0cmVhbU1hbmFnZXIge1xuXG4gICAgcHJpdmF0ZSBwcm9wZXJ0aWVzOiBTdWJzY3JpYmVyUHJvcGVydGllcztcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3RvcihzdHJlYW06IFN0cmVhbSwgdGFyZ0VsOiBzdHJpbmcgfCBIVE1MRWxlbWVudCwgcHJvcGVydGllczogU3Vic2NyaWJlclByb3BlcnRpZXMpIHtcbiAgICAgICAgc3VwZXIoc3RyZWFtLCB0YXJnRWwpO1xuICAgICAgICB0aGlzLmVsZW1lbnQgPSB0aGlzLnRhcmdldEVsZW1lbnQ7XG4gICAgICAgIHRoaXMuc3RyZWFtID0gc3RyZWFtO1xuICAgICAgICB0aGlzLnByb3BlcnRpZXMgPSBwcm9wZXJ0aWVzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFN1YnNjcmliZSBvciB1bnN1YnNjcmliZSBmcm9tIHRoZSBhdWRpbyBzdHJlYW0gKGlmIGF2YWlsYWJsZSkuIENhbGxpbmcgdGhpcyBtZXRob2QgdHdpY2UgaW4gYSByb3cgcGFzc2luZyBzYW1lIHZhbHVlIHdpbGwgaGF2ZSBubyBlZmZlY3RcbiAgICAgKiBAcGFyYW0gdmFsdWUgYHRydWVgIHRvIHN1YnNjcmliZSB0byB0aGUgYXVkaW8gc3RyZWFtLCBgZmFsc2VgIHRvIHVuc3Vic2NyaWJlIGZyb20gaXRcbiAgICAgKi9cbiAgICBzdWJzY3JpYmVUb0F1ZGlvKHZhbHVlOiBib29sZWFuKTogU3Vic2NyaWJlciB7XG4gICAgICAgIHRoaXMuc3RyZWFtLmdldE1lZGlhU3RyZWFtKCkuZ2V0QXVkaW9UcmFja3MoKS5mb3JFYWNoKCh0cmFjaykgPT4ge1xuICAgICAgICAgICAgdHJhY2suZW5hYmxlZCA9IHZhbHVlO1xuICAgICAgICB9KTtcbiAgICAgICAgY29uc29sZS5pbmZvKFwiJ1N1YnNjcmliZXInIGhhcyBcIiArICh2YWx1ZSA/ICdzdWJzY3JpYmVkIHRvJyA6ICd1bnN1YnNjcmliZWQgZnJvbScpICsgJyBpdHMgYXVkaW8gc3RyZWFtJyk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFN1YnNjcmliZSBvciB1bnN1YnNjcmliZSBmcm9tIHRoZSB2aWRlbyBzdHJlYW0gKGlmIGF2YWlsYWJsZSkuIENhbGxpbmcgdGhpcyBtZXRob2QgdHdpY2UgaW4gYSByb3cgcGFzc2luZyBzYW1lIHZhbHVlIHdpbGwgaGF2ZSBubyBlZmZlY3RcbiAgICAgKiBAcGFyYW0gdmFsdWUgYHRydWVgIHRvIHN1YnNjcmliZSB0byB0aGUgdmlkZW8gc3RyZWFtLCBgZmFsc2VgIHRvIHVuc3Vic2NyaWJlIGZyb20gaXRcbiAgICAgKi9cbiAgICBzdWJzY3JpYmVUb1ZpZGVvKHZhbHVlOiBib29sZWFuKTogU3Vic2NyaWJlciB7XG4gICAgICAgIHRoaXMuc3RyZWFtLmdldE1lZGlhU3RyZWFtKCkuZ2V0VmlkZW9UcmFja3MoKS5mb3JFYWNoKCh0cmFjaykgPT4ge1xuICAgICAgICAgICAgdHJhY2suZW5hYmxlZCA9IHZhbHVlO1xuICAgICAgICB9KTtcbiAgICAgICAgY29uc29sZS5pbmZvKFwiJ1N1YnNjcmliZXInIGhhcyBcIiArICh2YWx1ZSA/ICdzdWJzY3JpYmVkIHRvJyA6ICd1bnN1YnNjcmliZWQgZnJvbScpICsgJyBpdHMgdmlkZW8gc3RyZWFtJyk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxufSIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTctMjAxOCBPcGVuVmlkdSAoaHR0cHM6Ly9vcGVudmlkdS5pby8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuZXhwb3J0IGVudW0gTG9jYWxSZWNvcmRlclN0YXRlIHtcbiAgICBSRUFEWSA9ICdSRUFEWScsXG4gICAgUkVDT1JESU5HID0gJ1JFQ09SRElORycsXG4gICAgUEFVU0VEID0gJ1BBVVNFRCcsXG4gICAgRklOSVNIRUQgPSAnRklOSVNIRUQnXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG4vKipcbiAqIERlZmluZXMgcHJvcGVydHkgW1tPcGVuVmlkdUVycm9yLm5hbWVdXVxuICovXG5leHBvcnQgZW51bSBPcGVuVmlkdUVycm9yTmFtZSB7XG5cbiAgICAvKipcbiAgICAgKiBCcm93c2VyIGlzIG5vdCBzdXBwb3J0ZWQgYnkgT3BlblZpZHUuXG4gICAgICogUmV0dXJuZWQgdXBvbiB1bnN1Y2Nlc3NmdWwgW1tTZXNzaW9uLmNvbm5lY3RdXVxuICAgICAqL1xuICAgIEJST1dTRVJfTk9UX1NVUFBPUlRFRCA9ICdCUk9XU0VSX05PVF9TVVBQT1JURUQnLFxuXG4gICAgLyoqXG4gICAgICogVGhlIHVzZXIgaGFzbid0IGdyYW50ZWQgcGVybWlzc2lvbnMgdG8gdGhlIHJlcXVpcmVkIGlucHV0IGRldmljZSB3aGVuIHRoZSBicm93c2VyIGFza2VkIGZvciB0aGVtLlxuICAgICAqIFJldHVybmVkIHVwb24gdW5zdWNjZXNzZnVsIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dIG9yIFtbT3BlblZpZHUuZ2V0VXNlck1lZGlhXV1cbiAgICAgKi9cbiAgICBERVZJQ0VfQUNDRVNTX0RFTklFRCA9ICdERVZJQ0VfQUNDRVNTX0RFTklFRCcsXG5cbiAgICAvKipcbiAgICAgKiBUaGUgdXNlciBoYXNuJ3QgZ3JhbnRlZCBwZXJtaXNzaW9ucyB0byBjYXB0dXJlIHNvbWUgZGVza3RvcCBzY3JlZW4gd2hlbiB0aGUgYnJvd3NlciBhc2tlZCBmb3IgdGhlbS5cbiAgICAgKiBSZXR1cm5lZCB1cG9uIHVuc3VjY2Vzc2Z1bCBbW09wZW5WaWR1LmluaXRQdWJsaXNoZXJdXSBvciBbW09wZW5WaWR1LmdldFVzZXJNZWRpYV1dXG4gICAgICovXG4gICAgU0NSRUVOX0NBUFRVUkVfREVOSUVEID0gJ1NDUkVFTl9DQVBUVVJFX0RFTklFRCcsXG5cbiAgICAvKipcbiAgICAgKiBCcm93c2VyIGRvZXMgbm90IHN1cHBvcnQgc2NyZWVuIHNoYXJpbmcuXG4gICAgICogUmV0dXJuZWQgdXBvbiB1bnN1Y2Nlc3NmdWwgW1tPcGVuVmlkdS5pbml0UHVibGlzaGVyXV1cbiAgICAgKi9cbiAgICBTQ1JFRU5fU0hBUklOR19OT1RfU1VQUE9SVEVEID0gJ1NDUkVFTl9TSEFSSU5HX05PVF9TVVBQT1JURUQnLFxuXG4gICAgLyoqXG4gICAgICogT25seSBmb3IgQ2hyb21lLCB0aGVyZSdzIG5vIHNjcmVlbiBzaGFyaW5nIGV4dGVuc2lvbiBpbnN0YWxsZWRcbiAgICAgKiBSZXR1cm5lZCB1cG9uIHVuc3VjY2Vzc2Z1bCBbW09wZW5WaWR1LmluaXRQdWJsaXNoZXJdXVxuICAgICAqL1xuICAgIFNDUkVFTl9FWFRFTlNJT05fTk9UX0lOU1RBTExFRCA9ICdTQ1JFRU5fRVhURU5TSU9OX05PVF9JTlNUQUxMRUQnLFxuXG4gICAgLyoqXG4gICAgICogT25seSBmb3IgQ2hyb21lLCB0aGUgc2NyZWVuIHNoYXJpbmcgZXh0ZW5zaW9uIGlzIGluc3RhbGxlZCBidXQgaXMgZGlzYWJsZWRcbiAgICAgKiBSZXR1cm5lZCB1cG9uIHVuc3VjY2Vzc2Z1bCBbW09wZW5WaWR1LmluaXRQdWJsaXNoZXJdXVxuICAgICAqL1xuICAgIFNDUkVFTl9FWFRFTlNJT05fRElTQUJMRUQgPSAnU0NSRUVOX0VYVEVOU0lPTl9ESVNBQkxFRCcsXG5cbiAgICAvKipcbiAgICAgKiBObyB2aWRlbyBpbnB1dCBkZXZpY2UgZm91bmQgd2l0aCB0aGUgcHJvdmlkZWQgZGV2aWNlSWQgKHByb3BlcnR5IFtbUHVibGlzaGVyUHJvcGVydGllcy52aWRlb1NvdXJjZV1dKVxuICAgICAqIFJldHVybmVkIHVwb24gdW5zdWNjZXNzZnVsIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dXG4gICAgICovXG4gICAgSU5QVVRfVklERU9fREVWSUNFX05PVF9GT1VORCA9ICdJTlBVVF9WSURFT19ERVZJQ0VfTk9UX0ZPVU5EJyxcblxuICAgIC8qKlxuICAgICAqIE5vIGF1ZGlvIGlucHV0IGRldmljZSBmb3VuZCB3aXRoIHRoZSBwcm92aWRlZCBkZXZpY2VJZCAocHJvcGVydHkgW1tQdWJsaXNoZXJQcm9wZXJ0aWVzLmF1ZGlvU291cmNlXV0pXG4gICAgICogUmV0dXJuZWQgdXBvbiB1bnN1Y2Nlc3NmdWwgW1tPcGVuVmlkdS5pbml0UHVibGlzaGVyXV1cbiAgICAgKi9cbiAgICBJTlBVVF9BVURJT19ERVZJQ0VfTk9UX0ZPVU5EID0gJ0lOUFVUX0FVRElPX0RFVklDRV9OT1RfRk9VTkQnLFxuXG4gICAgLyoqXG4gICAgICogTWV0aG9kIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dIGhhcyBiZWVuIGNhbGxlZCB3aXRoIHByb3BlcnRpZXMgYHZpZGVvU291cmNlYCBhbmQgYGF1ZGlvU291cmNlYCBvZlxuICAgICAqIFtbUHVibGlzaGVyUHJvcGVydGllc11dIHBhcmFtZXRlciBib3RoIHNldCB0byAqZmFsc2UqIG9yICpudWxsKlxuICAgICAqL1xuICAgIE5PX0lOUFVUX1NPVVJDRV9TRVQgPSAnTk9fSU5QVVRfU09VUkNFX1NFVCcsXG5cbiAgICAvKipcbiAgICAgKiBTb21lIG1lZGlhIHByb3BlcnR5IG9mIFtbUHVibGlzaGVyUHJvcGVydGllc11dIHN1Y2ggYXMgYGZyYW1lUmF0ZWAgb3IgYHJlc29sdXRpb25gIGlzIG5vdCBzdXBwb3J0ZWRcbiAgICAgKiBieSB0aGUgaW5wdXQgZGV2aWNlcyAod2hlbmV2ZXIgaXQgaXMgcG9zc2libGUgdGhleSBhcmUgYXV0b21hdGljYWxseSBhZGp1c3RlZCB0byB0aGUgbW9zdCBzaW1pbGFyIHZhbHVlKS5cbiAgICAgKiBSZXR1cm5lZCB1cG9uIHVuc3VjY2Vzc2Z1bCBbW09wZW5WaWR1LmluaXRQdWJsaXNoZXJdXVxuICAgICAqL1xuICAgIFBVQkxJU0hFUl9QUk9QRVJUSUVTX0VSUk9SID0gJ1BVQkxJU0hFUl9QUk9QRVJUSUVTX0VSUk9SJyxcblxuICAgIC8qKlxuICAgICAqIFRoZSBjbGllbnQgdHJpZWQgdG8gY2FsbCBhIG1ldGhvZCB3aXRob3V0IHRoZSByZXF1aXJlZCBwZXJtaXNzaW9ucy4gVGhpcyBjYW4gb2NjdXIgZm9yIG1ldGhvZHMgW1tTZXNzaW9uLnB1Ymxpc2hdXSxcbiAgICAgKiBbW1Nlc3Npb24uZm9yY2VVbnB1Ymxpc2hdXSBhbmQgW1tTZXNzaW9uLmZvcmNlRGlzY29ubmVjdF1dXG4gICAgICovXG4gICAgT1BFTlZJRFVfUEVSTUlTU0lPTl9ERU5JRUQgPSAnT1BFTlZJRFVfUEVSTUlTU0lPTl9ERU5JRUQnLFxuXG4gICAgLyoqXG4gICAgICogX05vdCBpbiB1c2UgeWV0X1xuICAgICAqL1xuICAgIE9QRU5WSURVX05PVF9DT05ORUNURUQgPSAnT1BFTlZJRFVfTk9UX0NPTk5FQ1RFRCcsXG5cbiAgICAvKipcbiAgICAgKiBfTm90IGluIHVzZSB5ZXRfXG4gICAgICovXG4gICAgR0VORVJJQ19FUlJPUiA9ICdHRU5FUklDX0VSUk9SJ1xufVxuXG4vKipcbiAqIFNpbXBsZSBvYmplY3QgdG8gaWRlbnRpZnkgcnVudGltZSBlcnJvcnMgb24gdGhlIGNsaWVudCBzaWRlXG4gKi9cbmV4cG9ydCBjbGFzcyBPcGVuVmlkdUVycm9yIHtcblxuICAgIG5hbWU6IE9wZW5WaWR1RXJyb3JOYW1lO1xuICAgIG1lc3NhZ2U6IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3RvcihuYW1lOiBPcGVuVmlkdUVycm9yTmFtZSwgbWVzc2FnZTogc3RyaW5nKSB7XG4gICAgICAgIHRoaXMubmFtZSA9IG5hbWU7XG4gICAgICAgIHRoaXMubWVzc2FnZSA9IG1lc3NhZ2U7XG4gICAgfVxuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG4vKipcbiAqIEhvdyB0aGUgdmlkZW8gd2lsbCBiZSBpbnNlcnRlZCBpbiB0aGUgRE9NIGZvciBQdWJsaXNoZXJzIGFuZCBTdWJzY3JpYmVycy4gU2VlIFtbUHVibGlzaGVyUHJvcGVydGllcy5pbnNlcnRNb2RlXV0gYW5kIFtbU3Vic2NyaWJlclByb3BlcnRpZXMuaW5zZXJ0TW9kZV1dXG4gKi9cbmV4cG9ydCBlbnVtIFZpZGVvSW5zZXJ0TW9kZSB7XG5cbiAgICAvKipcbiAgICAgKiBWaWRlbyBpbnNlcnRlZCBhZnRlciB0aGUgdGFyZ2V0IGVsZW1lbnQgKGFzIG5leHQgc2libGluZylcbiAgICAgKi9cbiAgICBBRlRFUiA9ICdBRlRFUicsXG4gICAgLyoqXG4gICAgICogVmlkZW8gaW5zZXJ0ZWQgYXMgbGFzdCBjaGlsZCBvZiB0aGUgdGFyZ2V0IGVsZW1lbnRcbiAgICAgKi9cbiAgICBBUFBFTkQgPSAnQVBQRU5EJyxcbiAgICAvKipcbiAgICAgKiBWaWRlbyBpbnNlcnRlZCBiZWZvcmUgdGhlIHRhcmdldCBlbGVtZW50IChhcyBwcmV2aW91cyBzaWJsaW5nKVxuICAgICAqL1xuICAgIEJFRk9SRSA9ICdCRUZPUkUnLFxuICAgIC8qKlxuICAgICAqIFZpZGVvIGluc2VydGVkIGFzIGZpcnN0IGNoaWxkIG9mIHRoZSB0YXJnZXQgZWxlbWVudFxuICAgICAqL1xuICAgIFBSRVBFTkQgPSAnUFJFUEVORCcsXG4gICAgLyoqXG4gICAgICogVmlkZW8gcmVwbGFjZXMgdGFyZ2V0IGVsZW1lbnRcbiAgICAgKi9cbiAgICBSRVBMQUNFID0gJ1JFUExBQ0UnXG5cbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IEV2ZW50IH0gZnJvbSAnLi9FdmVudCc7XG5pbXBvcnQgeyBDb25uZWN0aW9uIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvQ29ubmVjdGlvbic7XG5pbXBvcnQgeyBTZXNzaW9uIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvU2Vzc2lvbic7XG5cblxuLyoqXG4gKiBEZWZpbmVzIHRoZSBmb2xsb3dpbmcgZXZlbnRzOlxuICogLSBgY29ubmVjdGlvbkNyZWF0ZWRgOiBkaXNwYXRjaGVkIGJ5IFtbU2Vzc2lvbl1dXG4gKiAtIGBjb25uZWN0aW9uRGVzdHJveWVkYDogZGlzcGF0Y2hlZCBieSBbW1Nlc3Npb25dXVxuICovXG5leHBvcnQgY2xhc3MgQ29ubmVjdGlvbkV2ZW50IGV4dGVuZHMgRXZlbnQge1xuXG4gICAgLyoqXG4gICAgICogQ29ubmVjdGlvbiBvYmplY3QgdGhhdCB3YXMgY3JlYXRlZCBvciBkZXN0cm95ZWRcbiAgICAgKi9cbiAgICBjb25uZWN0aW9uOiBDb25uZWN0aW9uO1xuXG4gICAgLyoqXG4gICAgICogRm9yICdjb25uZWN0aW9uRGVzdHJveWVkJyBldmVudDpcbiAgICAgKiAtIFwiZGlzY29ubmVjdFwiOiB0aGUgcmVtb3RlIHVzZXIgaGFzIGNhbGxlZCBgU2Vzc2lvbi5kaXNjb25uZWN0KClgXG4gICAgICogLSBcImZvcmNlRGlzY29ubmVjdEJ5VXNlclwiOiB0aGUgcmVtb3RlIHVzZXIgaGFzIGJlZW4gZXZpY3RlZCBmcm9tIHRoZSBTZXNzaW9uIGJ5IG90aGVyIHVzZXIgY2FsbGluZyBgU2Vzc2lvbi5mb3JjZURpc2Nvbm5lY3QoKWBcbiAgICAgKiAtIFwiZm9yY2VEaXNjb25uZWN0QnlTZXJ2ZXJcIjogdGhlIHJlbW90ZSB1c2VyIGhhcyBiZWVuIGV2aWN0ZWQgZnJvbSB0aGUgU2Vzc2lvbiBieSB0aGUgYXBwbGljYXRpb25cbiAgICAgKiAtIFwic2Vzc2lvbkNsb3NlZEJ5U2VydmVyXCI6IHRoZSBTZXNzaW9uIGhhcyBiZWVuIGNsb3NlZCBieSB0aGUgYXBwbGljYXRpb25cbiAgICAgKiAtIFwibmV0d29ya0Rpc2Nvbm5lY3RcIjogdGhlIHJlbW90ZSB1c2VyIG5ldHdvcmsgY29ubmVjdGlvbiBoYXMgZHJvcHBlZFxuICAgICAqXG4gICAgICogRm9yICdjb25uZWN0aW9uQ3JlYXRlZCcgZW1wdHkgc3RyaW5nXG4gICAgICovXG4gICAgcmVhc29uOiBzdHJpbmc7XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgY29uc3RydWN0b3IoY2FuY2VsYWJsZTogYm9vbGVhbiwgdGFyZ2V0OiBTZXNzaW9uLCB0eXBlOiBzdHJpbmcsIGNvbm5lY3Rpb246IENvbm5lY3Rpb24sIHJlYXNvbjogc3RyaW5nKSB7XG4gICAgICAgIHN1cGVyKGNhbmNlbGFibGUsIHRhcmdldCwgdHlwZSk7XG4gICAgICAgIHRoaXMuY29ubmVjdGlvbiA9IGNvbm5lY3Rpb247XG4gICAgICAgIHRoaXMucmVhc29uID0gcmVhc29uO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6bm8tZW1wdHlcbiAgICBjYWxsRGVmYXVsdEJlaGF2aW9yKCkgeyB9XG5cbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IFN0cmVhbU1hbmFnZXIgfSBmcm9tICcuLi8uLi9PcGVuVmlkdS9TdHJlYW1NYW5hZ2VyJztcbmltcG9ydCB7IFNlc3Npb24gfSBmcm9tICcuLi8uLi9PcGVuVmlkdS9TZXNzaW9uJztcblxuZXhwb3J0IGFic3RyYWN0IGNsYXNzIEV2ZW50IHtcblxuICAgIC8qKlxuICAgICAqIFdoZXRoZXIgdGhlIGV2ZW50IGhhcyBhIGRlZmF1bHQgYmVoYXZpb3IgdGhhdCBtYXkgYmUgcHJldmVudGVkIGJ5IGNhbGxpbmcgW1tFdmVudC5wcmV2ZW50RGVmYXVsdF1dXG4gICAgICovXG4gICAgY2FuY2VsYWJsZTogYm9vbGVhbjtcblxuICAgIC8qKlxuICAgICAqIFRoZSBvYmplY3QgdGhhdCBkaXNwYXRjaGVkIHRoZSBldmVudFxuICAgICAqL1xuICAgIHRhcmdldDogU2Vzc2lvbiB8IFN0cmVhbU1hbmFnZXI7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgdHlwZSBvZiBldmVudC4gVGhpcyBpcyB0aGUgc2FtZSBzdHJpbmcgeW91IHBhc3MgYXMgZmlyc3QgcGFyYW1ldGVyIHdoZW4gY2FsbGluZyBtZXRob2QgYG9uKClgIG9mIGFueSBvYmplY3QgaW1wbGVtZW50aW5nIFtbRXZlbnREaXNwYXRjaGVyXV0gaW50ZXJmYWNlXG4gICAgICovXG4gICAgdHlwZTogc3RyaW5nO1xuXG4gICAgcHJpdmF0ZSBoYXNCZWVuUHJldmVudGVkID0gZmFsc2U7XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgY29uc3RydWN0b3IoY2FuY2VsYWJsZTogYm9vbGVhbiwgdGFyZ2V0OiBTZXNzaW9uIHwgU3RyZWFtTWFuYWdlciwgdHlwZTogc3RyaW5nKSB7XG4gICAgICAgIHRoaXMuY2FuY2VsYWJsZSA9IGNhbmNlbGFibGU7XG4gICAgICAgIHRoaXMudGFyZ2V0ID0gdGFyZ2V0O1xuICAgICAgICB0aGlzLnR5cGUgPSB0eXBlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFdoZXRoZXIgdGhlIGRlZmF1bHQgYmVhaGl2b3VyIG9mIHRoZSBldmVudCBoYXMgYmVlbiBwcmV2ZW50ZWQgb3Igbm90LiBDYWxsIFtbRXZlbnQucHJldmVudERlZmF1bHRdXSB0byBwcmV2ZW50IGl0XG4gICAgICovXG4gICAgaXNEZWZhdWx0UHJldmVudGVkKCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gdGhpcy5oYXNCZWVuUHJldmVudGVkO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFByZXZlbnRzIHRoZSBkZWZhdWx0IGJlaGF2aW9yIG9mIHRoZSBldmVudC4gVGhlIGZvbGxvd2luZyBldmVudHMgaGF2ZSBhIGRlZmF1bHQgYmVoYXZpb3I6XG4gICAgICpcbiAgICAgKiAtIGBzZXNzaW9uRGlzY29ubmVjdGVkYDogZGlzcGF0Y2hlZCBieSBbW1Nlc3Npb25dXSBvYmplY3QsIGF1dG9tYXRpY2FsbHkgdW5zdWJzY3JpYmVzIHRoZSBsZWF2aW5nIHBhcnRpY2lwYW50IGZyb20gZXZlcnkgU3Vic2NyaWJlciBvYmplY3Qgb2YgdGhlIHNlc3Npb24gKHRoaXMgaW5jbHVkZXMgY2xvc2luZyB0aGUgV2ViUlRDUGVlciBjb25uZWN0aW9uIGFuZCBkaXNwb3NpbmcgYWxsIE1lZGlhU3RyZWFtVHJhY2tzKVxuICAgICAqIGFuZCBhbHNvIGRlbGV0ZXMgYW55IEhUTUwgdmlkZW8gZWxlbWVudCBhc3NvY2lhdGVkIHRvIGVhY2ggU3Vic2NyaWJlciAob25seSB0aG9zZSBjcmVhdGVkIGJ5IE9wZW5WaWR1IEJyb3dzZXIsIGVpdGhlciBieSBwYXNzaW5nIGEgdmFsaWQgcGFyYW1ldGVyIGFzIGB0YXJnZXRFbGVtZW50YCBpbiBtZXRob2QgW1tTZXNzaW9uLnN1YnNjcmliZV1dIG9yXG4gICAgICogYnkgY2FsbGluZyBbW1N1YnNjcmliZXIuY3JlYXRlVmlkZW9FbGVtZW50XV0pLiBGb3IgZXZlcnkgdmlkZW8gcmVtb3ZlZCwgZWFjaCBTdWJzY3JpYmVyIG9iamVjdCB3aWxsIGFsc28gZGlzcGF0Y2ggYSBgdmlkZW9FbGVtZW50RGVzdHJveWVkYCBldmVudC5cbiAgICAgKlxuICAgICAqIC0gYHN0cmVhbURlc3Ryb3llZGA6XG4gICAgICogICAtIElmIGRpc3BhdGNoZWQgYnkgYSBbW1B1Ymxpc2hlcl1dICgqeW91KiBoYXZlIHVucHVibGlzaGVkKTogYXV0b21hdGljYWxseSBzdG9wcyBhbGwgbWVkaWEgdHJhY2tzIGFuZCBkZWxldGVzIGFueSBIVE1MIHZpZGVvIGVsZW1lbnQgYXNzb2NpYXRlZCB0byBpdCAob25seSB0aG9zZSBjcmVhdGVkIGJ5IE9wZW5WaWR1IEJyb3dzZXIsIGVpdGhlciBieSBwYXNzaW5nIGEgdmFsaWQgcGFyYW1ldGVyIGFzIGB0YXJnZXRFbGVtZW50YFxuICAgICAqIGluIG1ldGhvZCBbW09wZW5WaWR1LmluaXRQdWJsaXNoZXJdXSBvciBieSBjYWxsaW5nIFtbUHVibGlzaGVyLmNyZWF0ZVZpZGVvRWxlbWVudF1dKS4gRm9yIGV2ZXJ5IHZpZGVvIHJlbW92ZWQsIHRoZSBQdWJsaXNoZXIgb2JqZWN0IHdpbGwgYWxzbyBkaXNwYXRjaCBhIGB2aWRlb0VsZW1lbnREZXN0cm95ZWRgIGV2ZW50LlxuICAgICAqICAgLSBJZiBkaXNwYXRjaGVkIGJ5IFtbU2Vzc2lvbl1dICgqb3RoZXIgdXNlciogaGFzIHVucHVibGlzaGVkKTogYXV0b21hdGljYWxseSB1bnN1YnNjcmliZXMgdGhlIHByb3BlciBTdWJzY3JpYmVyIG9iamVjdCBmcm9tIHRoZSBzZXNzaW9uICh0aGlzIGluY2x1ZGVzIGNsb3NpbmcgdGhlIFdlYlJUQ1BlZXIgY29ubmVjdGlvbiBhbmQgZGlzcG9zaW5nIGFsbCBNZWRpYVN0cmVhbVRyYWNrcylcbiAgICAgKiBhbmQgYWxzbyBkZWxldGVzIGFueSBIVE1MIHZpZGVvIGVsZW1lbnQgYXNzb2NpYXRlZCB0byB0aGF0IFN1YnNjcmliZXIgKG9ubHkgdGhvc2UgY3JlYXRlZCBieSBPcGVuVmlkdSBCcm93c2VyLCBlaXRoZXIgYnkgcGFzc2luZyBhIHZhbGlkIHBhcmFtZXRlciBhcyBgdGFyZ2V0RWxlbWVudGAgaW4gbWV0aG9kIFtbU2Vzc2lvbi5zdWJzY3JpYmVdXSBvclxuICAgICAqIGJ5IGNhbGxpbmcgW1tTdWJzY3JpYmVyLmNyZWF0ZVZpZGVvRWxlbWVudF1dKS4gRm9yIGV2ZXJ5IHZpZGVvIHJlbW92ZWQsIHRoZSBTdWJzY3JpYmVyIG9iamVjdCB3aWxsIGFsc28gZGlzcGF0Y2ggYSBgdmlkZW9FbGVtZW50RGVzdHJveWVkYCBldmVudC5cbiAgICAgKi9cbiAgICBwcmV2ZW50RGVmYXVsdCgpIHtcbiAgICAgICAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lOm5vLWVtcHR5XG4gICAgICAgIHRoaXMuY2FsbERlZmF1bHRCZWhhdmlvciA9ICgpID0+IHsgfTtcbiAgICAgICAgdGhpcy5oYXNCZWVuUHJldmVudGVkID0gdHJ1ZTtcbiAgICB9XG5cbiAgICBwcm90ZWN0ZWQgYWJzdHJhY3QgY2FsbERlZmF1bHRCZWhhdmlvcigpO1xuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBFdmVudCB9IGZyb20gJy4vRXZlbnQnO1xuaW1wb3J0IHsgQ29ubmVjdGlvbiB9IGZyb20gJy4uLy4uL09wZW5WaWR1L0Nvbm5lY3Rpb24nO1xuaW1wb3J0IHsgU2Vzc2lvbiB9IGZyb20gJy4uLy4uJztcblxuXG4vKipcbiAqIERlZmluZXMgdGhlIGZvbGxvd2luZyBldmVudHM6XG4gKiAtIGBwdWJsaXNoZXJTdGFydFNwZWFraW5nYDogZGlzcGF0Y2hlZCBieSBbW1Nlc3Npb25dXVxuICogLSBgcHVibGlzaGVyU3RvcFNwZWFraW5nYDogZGlzcGF0Y2hlZCBieSBbW1Nlc3Npb25dXVxuICpcbiAqIE1vcmUgaW5mb3JtYXRpb246XG4gKiAtIFRoaXMgZXZlbnRzIHdpbGwgb25seSBiZSB0cmlnZ2VyZWQgZm9yICoqcmVtb3RlIHN0cmVhbXMgdGhhdCBoYXZlIGF1ZGlvIHRyYWNrcyoqIChbW1N0cmVhbS5oYXNBdWRpb11dIG11c3QgYmUgdHJ1ZSlcbiAqIC0gQm90aCBldmVudHMgc2hhcmUgdGhlIHNhbWUgbGlmZWN5Y2xlLiBUaGF0IG1lYW5zIHRoYXQgeW91IGNhbiBzdWJzY3JpYmUgdG8gb25seSBvbmUgb2YgdGhlbSBpZiB5b3Ugd2FudCwgYnV0IGlmIHlvdSBjYWxsIGBTZXNzaW9uLm9mZigncHVibGlzaGVyU3RvcFNwZWFraW5nJylgLFxuICoga2VlcCBpbiBtaW5kIHRoYXQgdGhpcyB3aWxsIGFsc28gaW50ZXJuYWxseSByZW1vdmUgYW55ICdwdWJsaXNoZXJTdGFydFNwZWFraW5nJyBldmVudFxuICogLSBZb3UgY2FuIGZ1cnRoZXIgY29uZmlndXJlIGhvdyB0aGUgZXZlbnRzIGFyZSBkaXNwYXRjaGVkIGJ5IHNldHRpbmcgcHJvcGVydHkgYHB1Ymxpc2hlclNwZWFraW5nRXZlbnRzT3B0aW9uc2AgaW4gdGhlIGNhbGwgb2YgW1tPcGVuVmlkdS5zZXRBZHZhbmNlZENvbmZpZ3VyYXRpb25dXVxuICovXG5leHBvcnQgY2xhc3MgUHVibGlzaGVyU3BlYWtpbmdFdmVudCBleHRlbmRzIEV2ZW50IHtcblxuICAgIC8qKlxuICAgICAqIFRoZSBjbGllbnQgdGhhdCBzdGFydGVkIG9yIHN0b3BwZWQgc3BlYWtpbmdcbiAgICAgKi9cbiAgICBjb25uZWN0aW9uOiBDb25uZWN0aW9uO1xuXG4gICAgLyoqXG4gICAgICogVGhlIHN0cmVhbUlkIG9mIHRoZSBTdHJlYW0gYWZmZWN0ZWQgYnkgdGhlIHNwZWFraW5nIGV2ZW50XG4gICAgICovXG4gICAgc3RyZWFtSWQ6IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3Rvcih0YXJnZXQ6IFNlc3Npb24sIHR5cGU6IHN0cmluZywgY29ubmVjdGlvbjogQ29ubmVjdGlvbiwgc3RyZWFtSWQ6IHN0cmluZykge1xuICAgICAgICBzdXBlcihmYWxzZSwgdGFyZ2V0LCB0eXBlKTtcbiAgICAgICAgdGhpcy50eXBlID0gdHlwZTtcbiAgICAgICAgdGhpcy5jb25uZWN0aW9uID0gY29ubmVjdGlvbjtcbiAgICAgICAgdGhpcy5zdHJlYW1JZCA9IHN0cmVhbUlkO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6bm8tZW1wdHlcbiAgICBjYWxsRGVmYXVsdEJlaGF2aW9yKCkgeyB9XG5cbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IEV2ZW50IH0gZnJvbSAnLi9FdmVudCc7XG5pbXBvcnQgeyBTZXNzaW9uIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvU2Vzc2lvbic7XG5cblxuLyoqXG4gKiBEZWZpbmVzIHRoZSBmb2xsb3dpbmcgZXZlbnRzOlxuICogLSBgcmVjb3JkaW5nU3RhcnRlZGA6IGRpc3BhdGNoZWQgYnkgW1tTZXNzaW9uXV1cbiAqIC0gYHJlY29yZGluZ1N0b3BwZWRgOiBkaXNwYXRjaGVkIGJ5IFtbU2Vzc2lvbl1dXG4gKi9cbmV4cG9ydCBjbGFzcyBSZWNvcmRpbmdFdmVudCBleHRlbmRzIEV2ZW50IHtcblxuICAgIC8qKlxuICAgICAqIFRoZSByZWNvcmRpbmcgSUQgZ2VuZXJhdGVkIGluIG9wZW52aWR1LXNlcnZlclxuICAgICAqL1xuICAgIGlkOiBzdHJpbmc7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgcmVjb3JkaW5nIG5hbWUgeW91IHN1cHBsaWVkIHRvIG9wZW52aWR1LXNlcnZlci4gRm9yIGV4YW1wbGUsIHRvIG5hbWUgeW91ciByZWNvcmRpbmcgZmlsZSBNWV9SRUNPUkRJTkc6XG4gICAgICogLSBXaXRoICoqQVBJIFJFU1QqKjogUE9TVCB0byBgL2FwaS9yZWNvcmRpbmdzL3N0YXJ0YCBwYXNzaW5nIEpTT04gYm9keSBge1wic2Vzc2lvblwiOlwic2Vzc2lvbklkXCIsXCJuYW1lXCI6XCJNWV9SRUNPUkRJTkdcIn1gXG4gICAgICogLSBXaXRoICoqb3BlbnZpZHUtamF2YS1jbGllbnQqKjogYE9wZW5WaWR1LnN0YXJ0UmVjb3JkaW5nKHNlc3Npb25JZCwgXCJNWV9SRUNPUkRJTkdcIilgIG9yIGBPcGVuVmlkdS5zdGFydFJlY29yZGluZyhzZXNzaW9uSWQsIG5ldyBSZWNvcmRpbmdQcm9wZXJ0aWVzLkJ1aWxkZXIoKS5uYW1lKFwiTVlfUkVDT1JESU5HXCIpLmJ1aWxkKCkpYFxuICAgICAqIC0gV2l0aCAqKm9wZW52aWR1LW5vZGUtY2xpZW50Kio6IGBPcGVuVmlkdS5zdGFydFJlY29yZGluZyhzZXNzaW9uSWQsIFwiTVlfUkVDT1JESU5HXCIpYCBvciBgT3BlblZpZHUuc3RhcnRSZWNvcmRpbmcoc2Vzc2lvbklkLCB7bmFtZTogXCJNWV9SRUNPUkRJTkdcIn0pYFxuICAgICAqXG4gICAgICogSWYgbm8gbmFtZSBpcyBzdXBwbGllZCwgdGhpcyBwcm9wZXJ0eSB3aWxsIGJlIHVuZGVmaW5lZCBhbmQgdGhlIHJlY29yZGVkIGZpbGUgd2lsbCBiZSBuYW1lZCBhZnRlciBwcm9wZXJ0eSBbW2lkXV1cbiAgICAgKi9cbiAgICBuYW1lPzogc3RyaW5nO1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHRhcmdldDogU2Vzc2lvbiwgdHlwZTogc3RyaW5nLCBpZDogc3RyaW5nLCBuYW1lOiBzdHJpbmcpIHtcbiAgICAgICAgc3VwZXIoZmFsc2UsIHRhcmdldCwgdHlwZSk7XG4gICAgICAgIHRoaXMuaWQgPSBpZDtcbiAgICAgICAgaWYgKG5hbWUgIT09IGlkKSB7XG4gICAgICAgICAgICB0aGlzLm5hbWUgPSBuYW1lO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZTpuby1lbXB0eVxuICAgIGNhbGxEZWZhdWx0QmVoYXZpb3IoKSB7IH1cblxufSIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTctMjAxOCBPcGVuVmlkdSAoaHR0cHM6Ly9vcGVudmlkdS5pby8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuaW1wb3J0IHsgRXZlbnQgfSBmcm9tICcuL0V2ZW50JztcbmltcG9ydCB7IFNlc3Npb24gfSBmcm9tICcuLi8uLi9PcGVuVmlkdS9TZXNzaW9uJztcblxuXG4vKipcbiAqIERlZmluZXMgZXZlbnQgYHNlc3Npb25EaXNjb25uZWN0ZWRgIGRpc3BhdGNoZWQgYnkgW1tTZXNzaW9uXV1cbiAqL1xuZXhwb3J0IGNsYXNzIFNlc3Npb25EaXNjb25uZWN0ZWRFdmVudCBleHRlbmRzIEV2ZW50IHtcblxuICAgIC8qKlxuICAgICAqIC0gXCJkaXNjb25uZWN0XCI6IHlvdSBoYXZlIGNhbGxlZCBgU2Vzc2lvbi5kaXNjb25uZWN0KClgXG4gICAgICogLSBcImZvcmNlRGlzY29ubmVjdEJ5VXNlclwiOiB5b3UgaGF2ZSBiZWVuIGV2aWN0ZWQgZnJvbSB0aGUgU2Vzc2lvbiBieSBvdGhlciB1c2VyIGNhbGxpbmcgYFNlc3Npb24uZm9yY2VEaXNjb25uZWN0KClgXG4gICAgICogLSBcImZvcmNlRGlzY29ubmVjdEJ5U2VydmVyXCI6IHlvdSBoYXZlIGJlZW4gZXZpY3RlZCBmcm9tIHRoZSBTZXNzaW9uIGJ5IHRoZSBhcHBsaWNhdGlvblxuICAgICAqIC0gXCJzZXNzaW9uQ2xvc2VkQnlTZXJ2ZXJcIjogdGhlIFNlc3Npb24gaGFzIGJlZW4gY2xvc2VkIGJ5IHRoZSBhcHBsaWNhdGlvblxuICAgICAqIC0gXCJuZXR3b3JrRGlzY29ubmVjdFwiOiB5b3VyIG5ldHdvcmsgY29ubmVjdGlvbiBoYXMgZHJvcHBlZFxuICAgICAqL1xuICAgIHJlYXNvbjogc3RyaW5nO1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHRhcmdldDogU2Vzc2lvbiwgcmVhc29uOiBzdHJpbmcpIHtcbiAgICAgICAgc3VwZXIodHJ1ZSwgdGFyZ2V0LCAnc2Vzc2lvbkRpc2Nvbm5lY3RlZCcpO1xuICAgICAgICB0aGlzLnJlYXNvbiA9IHJlYXNvbjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgY2FsbERlZmF1bHRCZWhhdmlvcigpIHtcblxuICAgICAgICBjb25zb2xlLmluZm8oXCJDYWxsaW5nIGRlZmF1bHQgYmVoYXZpb3IgdXBvbiAnXCIgKyB0aGlzLnR5cGUgKyBcIicgZXZlbnQgZGlzcGF0Y2hlZCBieSAnU2Vzc2lvbidcIik7XG5cbiAgICAgICAgY29uc3Qgc2Vzc2lvbiA9IDxTZXNzaW9uPnRoaXMudGFyZ2V0O1xuXG4gICAgICAgIC8vIERpc3Bvc2UgYW5kIGRlbGV0ZSBhbGwgcmVtb3RlIENvbm5lY3Rpb25zXG4gICAgICAgIGZvciAoY29uc3QgY29ubmVjdGlvbklkIGluIHNlc3Npb24ucmVtb3RlQ29ubmVjdGlvbnMpIHtcbiAgICAgICAgICAgIGlmICghIXNlc3Npb24ucmVtb3RlQ29ubmVjdGlvbnNbY29ubmVjdGlvbklkXS5zdHJlYW0pIHtcbiAgICAgICAgICAgICAgICBzZXNzaW9uLnJlbW90ZUNvbm5lY3Rpb25zW2Nvbm5lY3Rpb25JZF0uc3RyZWFtLmRpc3Bvc2VXZWJSdGNQZWVyKCk7XG4gICAgICAgICAgICAgICAgc2Vzc2lvbi5yZW1vdGVDb25uZWN0aW9uc1tjb25uZWN0aW9uSWRdLnN0cmVhbS5kaXNwb3NlTWVkaWFTdHJlYW0oKTtcbiAgICAgICAgICAgICAgICBpZiAoc2Vzc2lvbi5yZW1vdGVDb25uZWN0aW9uc1tjb25uZWN0aW9uSWRdLnN0cmVhbS5zdHJlYW1NYW5hZ2VyKSB7XG4gICAgICAgICAgICAgICAgICAgIHNlc3Npb24ucmVtb3RlQ29ubmVjdGlvbnNbY29ubmVjdGlvbklkXS5zdHJlYW0uc3RyZWFtTWFuYWdlci5yZW1vdmVBbGxWaWRlb3MoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZGVsZXRlIHNlc3Npb24ucmVtb3RlU3RyZWFtc0NyZWF0ZWRbc2Vzc2lvbi5yZW1vdGVDb25uZWN0aW9uc1tjb25uZWN0aW9uSWRdLnN0cmVhbS5zdHJlYW1JZF07XG4gICAgICAgICAgICAgICAgc2Vzc2lvbi5yZW1vdGVDb25uZWN0aW9uc1tjb25uZWN0aW9uSWRdLmRpc3Bvc2UoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGRlbGV0ZSBzZXNzaW9uLnJlbW90ZUNvbm5lY3Rpb25zW2Nvbm5lY3Rpb25JZF07XG4gICAgICAgIH1cbiAgICB9XG5cbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IEV2ZW50IH0gZnJvbSAnLi9FdmVudCc7XG5pbXBvcnQgeyBDb25uZWN0aW9uIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvQ29ubmVjdGlvbic7XG5pbXBvcnQgeyBTZXNzaW9uIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvU2Vzc2lvbic7XG5cblxuLyoqXG4gKiBEZWZpbmVzIHRoZSBmb2xsb3dpbmcgZXZlbnRzOlxuICogLSBgc2lnbmFsYDogZGlzcGF0Y2hlZCBieSBbW1Nlc3Npb25dXVxuICogLSBgc2lnbmFsOlRZUEVgOiBkaXNwYXRjaGVkIGJ5IFtbU2Vzc2lvbl1dXG4gKi9cbmV4cG9ydCBjbGFzcyBTaWduYWxFdmVudCBleHRlbmRzIEV2ZW50IHtcblxuICAgIC8qKlxuICAgICAqIFRoZSB0eXBlIG9mIHNpZ25hbCAoY2FuIGJlIGVtcHR5KS5cbiAgICAgKlxuICAgICAqIFRoZSBjbGllbnQgbXVzdCBiZSBzdWJzY3JpYmVkIHRvIGBTZXNzaW9uLm9uKCdzaWduYWw6dHlwZScsIGZ1bmN0aW9uKHNpZ25hbEV2ZW50KSB7Li4ufSlgIHRvIHJlY2VpdmUgdGhpcyBvYmplY3QgaW4gdGhlIGNhbGxiYWNrLlxuICAgICAqXG4gICAgICogU3Vic2NyaWJpbmcgdG8gYFNlc3Npb24ub24oJ3NpZ25hbCcsIGZ1bmN0aW9uKHNpZ25hbEV2ZW50KSB7Li4ufSlgIHdpbGwgdHJpZ2dlciBhbGwgdHlwZXMgb2Ygc2lnbmFscy5cbiAgICAgKi9cbiAgICB0eXBlOiBzdHJpbmc7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgbWVzc2FnZSBvZiB0aGUgc2lnbmFsIChjYW4gYmUgZW10cHkpXG4gICAgICovXG4gICAgZGF0YTogc3RyaW5nO1xuXG4gICAgLyoqXG4gICAgICogVGhlIGNsaWVudCB0aGF0IHNlbnQgdGhlIHNpZ25hbFxuICAgICAqL1xuICAgIGZyb206IENvbm5lY3Rpb247XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgY29uc3RydWN0b3IodGFyZ2V0OiBTZXNzaW9uLCB0eXBlOiBzdHJpbmcsIGRhdGE6IHN0cmluZywgZnJvbTogQ29ubmVjdGlvbikge1xuICAgICAgICBzdXBlcihmYWxzZSwgdGFyZ2V0LCB0eXBlKTtcbiAgICAgICAgdGhpcy50eXBlID0gdHlwZTtcbiAgICAgICAgdGhpcy5kYXRhID0gZGF0YTtcbiAgICAgICAgdGhpcy5mcm9tID0gZnJvbTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lOm5vLWVtcHR5XG4gICAgY2FsbERlZmF1bHRCZWhhdmlvcigpIHsgfVxuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBFdmVudCB9IGZyb20gJy4vRXZlbnQnO1xuaW1wb3J0IHsgUHVibGlzaGVyIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvUHVibGlzaGVyJztcbmltcG9ydCB7IFNlc3Npb24gfSBmcm9tICcuLi8uLi9PcGVuVmlkdS9TZXNzaW9uJztcbmltcG9ydCB7IFN0cmVhbSB9IGZyb20gJy4uLy4uL09wZW5WaWR1L1N0cmVhbSc7XG5cblxuLyoqXG4gKiBEZWZpbmVzIHRoZSBmb2xsb3dpbmcgZXZlbnRzOlxuICogLSBgc3RyZWFtQ3JlYXRlZGA6IGRpc3BhdGNoZWQgYnkgW1tTZXNzaW9uXV0gYW5kIFtbUHVibGlzaGVyXV1cbiAqIC0gYHN0cmVhbURlc3Ryb3llZGA6IGRpc3BhdGNoZWQgYnkgW1tTZXNzaW9uXV0gYW5kIFtbUHVibGlzaGVyXV1cbiAqL1xuZXhwb3J0IGNsYXNzIFN0cmVhbUV2ZW50IGV4dGVuZHMgRXZlbnQge1xuXG4gICAgLyoqXG4gICAgICogU3RyZWFtIG9iamVjdCB0aGF0IHdhcyBjcmVhdGVkIG9yIGRlc3Ryb3llZFxuICAgICAqL1xuICAgIHN0cmVhbTogU3RyZWFtO1xuXG4gICAgLyoqXG4gICAgICogRm9yICdzdHJlYW1EZXN0cm95ZWQnIGV2ZW50OlxuICAgICAqIC0gXCJ1bnB1Ymxpc2hcIjogbWV0aG9kIGBTZXNzaW9uLnVucHVibGlzaCgpYCBoYXMgYmVlbiBjYWxsZWRcbiAgICAgKiAtIFwiZGlzY29ubmVjdFwiOiBtZXRob2QgYFNlc3Npb24uZGlzY29ubmVjdCgpYCBoYXMgYmVlbiBjYWxsZWRcbiAgICAgKiAtIFwiZm9yY2VVbnB1Ymxpc2hCeVVzZXJcIjogc29tZSB1c2VyIGhhcyBjYWxsZWQgYFNlc3Npb24uZm9yY2VVbnB1Ymxpc2goKWAgb3ZlciB0aGUgU3RyZWFtXG4gICAgICogLSBcImZvcmNlRGlzY29ubmVjdEJ5VXNlclwiOiBzb21lIHVzZXIgaGFzIGNhbGxlZCBgU2Vzc2lvbi5mb3JjZURpc2Nvbm5lY3QoKWAgb3ZlciB0aGUgU3RyZWFtXG4gICAgICogLSBcImZvcmNlVW5wdWJsaXNoQnlTZXJ2ZXJcIjogdGhlIHVzZXIncyBzdHJlYW0gaGFzIGJlZW4gdW5wdWJsaXNoZWQgZnJvbSB0aGUgU2Vzc2lvbiBieSB0aGUgYXBwbGljYXRpb25cbiAgICAgKiAtIFwiZm9yY2VEaXNjb25uZWN0QnlTZXJ2ZXJcIjogdGhlIHVzZXIgaGFzIGJlZW4gZXZpY3RlZCBmcm9tIHRoZSBTZXNzaW9uIGJ5IHRoZSBhcHBsaWNhdGlvblxuICAgICAqIC0gXCJzZXNzaW9uQ2xvc2VkQnlTZXJ2ZXJcIjogdGhlIFNlc3Npb24gaGFzIGJlZW4gY2xvc2VkIGJ5IHRoZSBhcHBsaWNhdGlvblxuICAgICAqIC0gXCJuZXR3b3JrRGlzY29ubmVjdFwiOiB0aGUgdXNlcidzIG5ldHdvcmsgY29ubmVjdGlvbiBoYXMgZHJvcHBlZFxuICAgICAqXG4gICAgICogRm9yICdzdHJlYW1DcmVhdGVkJyBlbXB0eSBzdHJpbmdcbiAgICAgKi9cbiAgICByZWFzb246IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3RvcihjYW5jZWxhYmxlOiBib29sZWFuLCB0YXJnZXQ6IFNlc3Npb24gfCBQdWJsaXNoZXIsIHR5cGU6IHN0cmluZywgc3RyZWFtOiBTdHJlYW0sIHJlYXNvbjogc3RyaW5nKSB7XG4gICAgICAgIHN1cGVyKGNhbmNlbGFibGUsIHRhcmdldCwgdHlwZSk7XG4gICAgICAgIHRoaXMuc3RyZWFtID0gc3RyZWFtO1xuICAgICAgICB0aGlzLnJlYXNvbiA9IHJlYXNvbjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgY2FsbERlZmF1bHRCZWhhdmlvcigpIHtcbiAgICAgICAgaWYgKHRoaXMudHlwZSA9PT0gJ3N0cmVhbURlc3Ryb3llZCcpIHtcblxuICAgICAgICAgICAgaWYgKHRoaXMudGFyZ2V0IGluc3RhbmNlb2YgU2Vzc2lvbikge1xuICAgICAgICAgICAgICAgIC8vIFJlbW90ZSBTdHJlYW1cbiAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oXCJDYWxsaW5nIGRlZmF1bHQgYmVoYXZpb3IgdXBvbiAnXCIgKyB0aGlzLnR5cGUgKyBcIicgZXZlbnQgZGlzcGF0Y2hlZCBieSAnU2Vzc2lvbidcIik7XG4gICAgICAgICAgICAgICAgdGhpcy5zdHJlYW0uZGlzcG9zZVdlYlJ0Y1BlZXIoKTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAodGhpcy50YXJnZXQgaW5zdGFuY2VvZiBQdWJsaXNoZXIpIHtcbiAgICAgICAgICAgICAgICAvLyBMb2NhbCBTdHJlYW1cbiAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oXCJDYWxsaW5nIGRlZmF1bHQgYmVoYXZpb3IgdXBvbiAnXCIgKyB0aGlzLnR5cGUgKyBcIicgZXZlbnQgZGlzcGF0Y2hlZCBieSAnUHVibGlzaGVyJ1wiKTtcbiAgICAgICAgICAgICAgICBjbGVhckludGVydmFsKCg8UHVibGlzaGVyPnRoaXMudGFyZ2V0KS5zY3JlZW5TaGFyZVJlc2l6ZUludGVydmFsKTtcbiAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbS5pc0xvY2FsU3RyZWFtUmVhZHlUb1B1Ymxpc2ggPSBmYWxzZTtcblxuICAgICAgICAgICAgICAgIC8vIERlbGV0ZSBQdWJsaXNoZXIgb2JqZWN0IGZyb20gT3BlblZpZHUgcHVibGlzaGVycyBhcnJheVxuICAgICAgICAgICAgICAgIGNvbnN0IG9wZW52aWR1UHVibGlzaGVycyA9ICg8UHVibGlzaGVyPnRoaXMudGFyZ2V0KS5vcGVudmlkdS5wdWJsaXNoZXJzO1xuICAgICAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgb3BlbnZpZHVQdWJsaXNoZXJzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChvcGVudmlkdVB1Ymxpc2hlcnNbaV0gPT09ICg8UHVibGlzaGVyPnRoaXMudGFyZ2V0KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgb3BlbnZpZHVQdWJsaXNoZXJzLnNwbGljZShpLCAxKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBEaXNwb3NlIHRoZSBNZWRpYVN0cmVhbSBsb2NhbCBvYmplY3RcbiAgICAgICAgICAgIHRoaXMuc3RyZWFtLmRpc3Bvc2VNZWRpYVN0cmVhbSgpO1xuXG4gICAgICAgICAgICAvLyBSZW1vdmUgZnJvbSBET00gYWxsIHZpZGVvIGVsZW1lbnRzIGFzc29jaWF0ZWQgdG8gdGhpcyBTdHJlYW0sIGlmIHRoZXJlJ3MgYSBTdHJlYW1NYW5hZ2VyIGRlZmluZWRcbiAgICAgICAgICAgIC8vIChtZXRob2QgU2Vzc2lvbi5zdWJzY3JpYmUgbXVzdCBoYXZlIGJlZW4gY2FsbGVkKVxuICAgICAgICAgICAgaWYgKHRoaXMuc3RyZWFtLnN0cmVhbU1hbmFnZXIpIHRoaXMuc3RyZWFtLnN0cmVhbU1hbmFnZXIucmVtb3ZlQWxsVmlkZW9zKCk7XG5cbiAgICAgICAgICAgIC8vIERlbGV0ZSBzdHJlYW0gZnJvbSBTZXNzaW9uLnJlbW90ZVN0cmVhbXNDcmVhdGVkIG1hcFxuICAgICAgICAgICAgZGVsZXRlIHRoaXMuc3RyZWFtLnNlc3Npb24ucmVtb3RlU3RyZWFtc0NyZWF0ZWRbdGhpcy5zdHJlYW0uc3RyZWFtSWRdO1xuXG4gICAgICAgICAgICAvLyBEZWxldGUgU3RyZWFtT3B0aW9uc1NlcnZlciBmcm9tIHJlbW90ZSBDb25uZWN0aW9uXG4gICAgICAgICAgICBjb25zdCByZW1vdGVDb25uZWN0aW9uID0gdGhpcy5zdHJlYW0uc2Vzc2lvbi5yZW1vdGVDb25uZWN0aW9uc1t0aGlzLnN0cmVhbS5jb25uZWN0aW9uLmNvbm5lY3Rpb25JZF07XG4gICAgICAgICAgICBpZiAoISFyZW1vdGVDb25uZWN0aW9uICYmICEhcmVtb3RlQ29ubmVjdGlvbi5vcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgY29uc3Qgc3RyZWFtT3B0aW9uc1NlcnZlciA9IHJlbW90ZUNvbm5lY3Rpb24ub3B0aW9ucy5zdHJlYW1zO1xuICAgICAgICAgICAgICAgIGZvciAobGV0IGkgPSBzdHJlYW1PcHRpb25zU2VydmVyLmxlbmd0aCAtIDE7IGkgPj0gMDsgLS1pKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChzdHJlYW1PcHRpb25zU2VydmVyW2ldLmlkID09PSB0aGlzLnN0cmVhbS5zdHJlYW1JZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgc3RyZWFtT3B0aW9uc1NlcnZlci5zcGxpY2UoaSwgMSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgfVxuICAgIH1cblxufSIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTctMjAxOCBPcGVuVmlkdSAoaHR0cHM6Ly9vcGVudmlkdS5pby8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuaW1wb3J0IHsgRXZlbnQgfSBmcm9tICcuL0V2ZW50JztcbmltcG9ydCB7IFN0cmVhbU1hbmFnZXIgfSBmcm9tICcuLi8uLi9PcGVuVmlkdS9TdHJlYW1NYW5hZ2VyJztcblxuLyoqXG4gKiBEZWZpbmVzIHRoZSBmb2xsb3dpbmcgZXZlbnRzOlxuICogLSBgc3RyZWFtUGxheWluZ2A6IGRpc3BhdGNoZWQgYnkgW1tTdHJlYW1NYW5hZ2VyXV0gKFtbUHVibGlzaGVyXV0gYW5kIFtbU3Vic2NyaWJlcl1dKVxuICovXG5leHBvcnQgY2xhc3MgU3RyZWFtTWFuYWdlckV2ZW50IGV4dGVuZHMgRXZlbnQge1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHRhcmdldDogU3RyZWFtTWFuYWdlcikge1xuICAgICAgICBzdXBlcihmYWxzZSwgdGFyZ2V0LCAnc3RyZWFtUGxheWluZycpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6bm8tZW1wdHlcbiAgICBjYWxsRGVmYXVsdEJlaGF2aW9yKCkgeyB9XG5cbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IEV2ZW50IH0gZnJvbSAnLi9FdmVudCc7XG5pbXBvcnQgeyBTZXNzaW9uIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvU2Vzc2lvbic7XG5pbXBvcnQgeyBTdHJlYW0gfSBmcm9tICcuLi8uLi9PcGVuVmlkdS9TdHJlYW0nO1xuaW1wb3J0IHsgU3RyZWFtTWFuYWdlciB9IGZyb20gJy4uLy4uL09wZW5WaWR1L1N0cmVhbU1hbmFnZXInO1xuXG4vKipcbiAqIERlZmluZXMgZXZlbnQgYHN0cmVhbVByb3BlcnR5Q2hhbmdlZGAgZGlzcGF0Y2hlZCBieSBbW1Nlc3Npb25dXSBhcyB3ZWxsIGFzIGJ5IFtbU3RyZWFtTWFuYWdlcl1dIChbW1B1Ymxpc2hlcl1dIGFuZCBbW1N1YnNjcmliZXJdXSkuXG4gKiBUaGlzIGV2ZW50IGlzIGZpcmVkIHdoZW4gYW55IHJlbW90ZSBzdHJlYW0gKG93bmVkIGJ5IGEgU3Vic2NyaWJlcikgb3IgbG9jYWwgc3RyZWFtIChvd25lZCBieSBhIFB1Ymxpc2hlcikgdW5kZXJnb2VzXG4gKiBhbnkgY2hhbmdlIGluIGFueSBvZiBpdHMgbXV0YWJsZSBwcm9wZXJ0aWVzIChzZWUgW1tjaGFuZ2VkUHJvcGVydHldXSkuXG4gKi9cbmV4cG9ydCBjbGFzcyBTdHJlYW1Qcm9wZXJ0eUNoYW5nZWRFdmVudCBleHRlbmRzIEV2ZW50IHtcblxuICAgIC8qKlxuICAgICAqIFRoZSBTdHJlYW0gd2hvc2UgcHJvcGVydHkgaGFzIGNoYW5nZWQuIFlvdSBjYW4gYWx3YXlzIGlkZW50aWZ5IHRoZSB1c2VyIHB1Ymxpc2hpbmcgdGhlIGNoYW5nZWQgc3RyZWFtIGJ5IGNvbnN1bHRpbmcgcHJvcGVydHkgW1tTdHJlYW0uY29ubmVjdGlvbl1dXG4gICAgICovXG4gICAgc3RyZWFtOiBTdHJlYW07XG5cbiAgICAvKipcbiAgICAgKiBUaGUgcHJvcGVydHkgb2YgdGhlIHN0cmVhbSB0aGF0IGNoYW5nZWQuIFRoaXMgdmFsdWUgaXMgZWl0aGVyIGBcInZpZGVvQWN0aXZlXCJgLCBgXCJhdWRpb0FjdGl2ZVwiYCBvciBgXCJ2aWRlb0RpbWVuc2lvbnNcImBcbiAgICAgKi9cbiAgICBjaGFuZ2VkUHJvcGVydHk6IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIENhdXNlIG9mIHRoZSBjaGFuZ2Ugb24gdGhlIHN0cmVhbSdzIHByb3BlcnR5OlxuICAgICAqIC0gRm9yIGB2aWRlb0FjdGl2ZWA6IGBcInB1Ymxpc2hWaWRlb1wiYFxuICAgICAqIC0gRm9yIGBhdWRpb0FjdGl2ZWA6IGBcInB1Ymxpc2hBdWRpb1wiYFxuICAgICAqIC0gRm9yIGB2aWRlb0RpbWVuc2lvbnNgOiBgXCJkZXZpY2VSb3RhdGVkXCJgIG9yIGBcInNjcmVlblJlc2l6ZWRcImBcbiAgICAgKi9cbiAgICByZWFzb246IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIE5ldyB2YWx1ZSBvZiB0aGUgcHJvcGVydHkgKGFmdGVyIGNoYW5nZSwgY3VycmVudCB2YWx1ZSlcbiAgICAgKi9cbiAgICBuZXdWYWx1ZTogT2JqZWN0O1xuXG4gICAgLyoqXG4gICAgICogUHJldmlvdXMgdmFsdWUgb2YgdGhlIHByb3BlcnR5IChiZWZvcmUgY2hhbmdlKVxuICAgICAqL1xuICAgIG9sZFZhbHVlOiBPYmplY3Q7XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgY29uc3RydWN0b3IodGFyZ2V0OiBTZXNzaW9uIHwgU3RyZWFtTWFuYWdlciwgc3RyZWFtOiBTdHJlYW0sIGNoYW5nZWRQcm9wZXJ0eTogc3RyaW5nLCBuZXdWYWx1ZTogT2JqZWN0LCBvbGRWYWx1ZTogT2JqZWN0LCByZWFzb246IHN0cmluZykge1xuICAgICAgICBzdXBlcihmYWxzZSwgdGFyZ2V0LCAnc3RyZWFtUHJvcGVydHlDaGFuZ2VkJyk7XG4gICAgICAgIHRoaXMuc3RyZWFtID0gc3RyZWFtO1xuICAgICAgICB0aGlzLmNoYW5nZWRQcm9wZXJ0eSA9IGNoYW5nZWRQcm9wZXJ0eTtcbiAgICAgICAgdGhpcy5uZXdWYWx1ZSA9IG5ld1ZhbHVlO1xuICAgICAgICB0aGlzLm9sZFZhbHVlID0gb2xkVmFsdWU7XG4gICAgICAgIHRoaXMucmVhc29uID0gcmVhc29uO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6bm8tZW1wdHlcbiAgICBjYWxsRGVmYXVsdEJlaGF2aW9yKCkgeyB9XG5cbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IEV2ZW50IH0gZnJvbSAnLi9FdmVudCc7XG5pbXBvcnQgeyBTdHJlYW1NYW5hZ2VyIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvU3RyZWFtTWFuYWdlcic7XG5cblxuLyoqXG4gKiBEZWZpbmVzIHRoZSBmb2xsb3dpbmcgZXZlbnRzOlxuICogLSBgdmlkZW9FbGVtZW50Q3JlYXRlZGA6IGRpc3BhdGNoZWQgYnkgW1tQdWJsaXNoZXJdXSBhbmQgW1tTdWJzY3JpYmVyXV0gd2hlbmV2ZXIgYSBuZXcgSFRNTCB2aWRlbyBlbGVtZW50IGhhcyBiZWVuIGluc2VydGVkIGludG8gRE9NIGJ5IE9wZW5WaWR1IEJyb3dzZXIgbGlicmFyeS4gU2VlXG4gKiBbTWFuYWdlIHZpZGVvIHBsYXllcnNdKC9kb2NzL2hvdy1kby1pL21hbmFnZS12aWRlb3MpIHNlY3Rpb24uXG4gKiAtIGB2aWRlb0VsZW1lbnREZXN0cm95ZWRgOiBkaXNwYXRjaGVkIGJ5IFtbUHVibGlzaGVyXV0gYW5kIFtbU3Vic2NyaWJlcl1dIHdoZW5ldmVyIGFuIEhUTUwgdmlkZW8gZWxlbWVudCBoYXMgYmVlbiByZW1vdmVkIGZyb20gRE9NIGJ5IE9wZW5WaWR1IEJyb3dzZXIgbGlicmFyeS5cbiAqL1xuZXhwb3J0IGNsYXNzIFZpZGVvRWxlbWVudEV2ZW50IGV4dGVuZHMgRXZlbnQge1xuXG4gICAgLyoqXG4gICAgICogVmlkZW8gZWxlbWVudCB0aGF0IHdhcyBjcmVhdGVkIG9yIGRlc3Ryb3llZFxuICAgICAqL1xuICAgIGVsZW1lbnQ6IEhUTUxWaWRlb0VsZW1lbnQ7XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgY29uc3RydWN0b3IoZWxlbWVudDogSFRNTFZpZGVvRWxlbWVudCwgdGFyZ2V0OiBTdHJlYW1NYW5hZ2VyLCB0eXBlOiBzdHJpbmcpIHtcbiAgICAgICAgc3VwZXIoZmFsc2UsIHRhcmdldCwgdHlwZSk7XG4gICAgICAgIHRoaXMuZWxlbWVudCA9IGVsZW1lbnQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZTpuby1lbXB0eVxuICAgIGNhbGxEZWZhdWx0QmVoYXZpb3IoKSB7IH1cblxufSIsImZ1bmN0aW9uIE1hcHBlcigpXG57XG4gIHZhciBzb3VyY2VzID0ge307XG5cblxuICB0aGlzLmZvckVhY2ggPSBmdW5jdGlvbihjYWxsYmFjaylcbiAge1xuICAgIGZvcih2YXIga2V5IGluIHNvdXJjZXMpXG4gICAge1xuICAgICAgdmFyIHNvdXJjZSA9IHNvdXJjZXNba2V5XTtcblxuICAgICAgZm9yKHZhciBrZXkyIGluIHNvdXJjZSlcbiAgICAgICAgY2FsbGJhY2soc291cmNlW2tleTJdKTtcbiAgICB9O1xuICB9O1xuXG4gIHRoaXMuZ2V0ID0gZnVuY3Rpb24oaWQsIHNvdXJjZSlcbiAge1xuICAgIHZhciBpZHMgPSBzb3VyY2VzW3NvdXJjZV07XG4gICAgaWYoaWRzID09IHVuZGVmaW5lZClcbiAgICAgIHJldHVybiB1bmRlZmluZWQ7XG5cbiAgICByZXR1cm4gaWRzW2lkXTtcbiAgfTtcblxuICB0aGlzLnJlbW92ZSA9IGZ1bmN0aW9uKGlkLCBzb3VyY2UpXG4gIHtcbiAgICB2YXIgaWRzID0gc291cmNlc1tzb3VyY2VdO1xuICAgIGlmKGlkcyA9PSB1bmRlZmluZWQpXG4gICAgICByZXR1cm47XG5cbiAgICBkZWxldGUgaWRzW2lkXTtcblxuICAgIC8vIENoZWNrIGl0J3MgZW1wdHlcbiAgICBmb3IodmFyIGkgaW4gaWRzKXtyZXR1cm4gZmFsc2V9XG5cbiAgICBkZWxldGUgc291cmNlc1tzb3VyY2VdO1xuICB9O1xuXG4gIHRoaXMuc2V0ID0gZnVuY3Rpb24odmFsdWUsIGlkLCBzb3VyY2UpXG4gIHtcbiAgICBpZih2YWx1ZSA9PSB1bmRlZmluZWQpXG4gICAgICByZXR1cm4gdGhpcy5yZW1vdmUoaWQsIHNvdXJjZSk7XG5cbiAgICB2YXIgaWRzID0gc291cmNlc1tzb3VyY2VdO1xuICAgIGlmKGlkcyA9PSB1bmRlZmluZWQpXG4gICAgICBzb3VyY2VzW3NvdXJjZV0gPSBpZHMgPSB7fTtcblxuICAgIGlkc1tpZF0gPSB2YWx1ZTtcbiAgfTtcbn07XG5cblxuTWFwcGVyLnByb3RvdHlwZS5wb3AgPSBmdW5jdGlvbihpZCwgc291cmNlKVxue1xuICB2YXIgdmFsdWUgPSB0aGlzLmdldChpZCwgc291cmNlKTtcbiAgaWYodmFsdWUgPT0gdW5kZWZpbmVkKVxuICAgIHJldHVybiB1bmRlZmluZWQ7XG5cbiAgdGhpcy5yZW1vdmUoaWQsIHNvdXJjZSk7XG5cbiAgcmV0dXJuIHZhbHVlO1xufTtcblxuXG5tb2R1bGUuZXhwb3J0cyA9IE1hcHBlcjtcbiIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTQgS3VyZW50byAoaHR0cDovL2t1cmVudG8ub3JnLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG52YXIgSnNvblJwY0NsaWVudCAgPSByZXF1aXJlKCcuL2pzb25ycGNjbGllbnQnKTtcblxuXG5leHBvcnRzLkpzb25ScGNDbGllbnQgID0gSnNvblJwY0NsaWVudDsiLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE0IEt1cmVudG8gKGh0dHA6Ly9rdXJlbnRvLm9yZy8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxudmFyIFJwY0J1aWxkZXIgPSByZXF1aXJlKCcuLi8nKTtcbnZhciBXZWJTb2NrZXRXaXRoUmVjb25uZWN0aW9uID0gcmVxdWlyZSgnLi90cmFuc3BvcnRzL3dlYlNvY2tldFdpdGhSZWNvbm5lY3Rpb24nKTtcblxuRGF0ZS5ub3cgPSBEYXRlLm5vdyB8fCBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gK25ldyBEYXRlO1xufTtcblxudmFyIFBJTkdfSU5URVJWQUwgPSA1MDAwO1xuXG52YXIgUkVDT05ORUNUSU5HID0gJ1JFQ09OTkVDVElORyc7XG52YXIgQ09OTkVDVEVEID0gJ0NPTk5FQ1RFRCc7XG52YXIgRElTQ09OTkVDVEVEID0gJ0RJU0NPTk5FQ1RFRCc7XG5cbnZhciBMb2dnZXIgPSBjb25zb2xlO1xuXG4vKipcbiAqXG4gKiBoZWFydGJlYXQ6IGludGVydmFsIGluIG1zIGZvciBlYWNoIGhlYXJ0YmVhdCBtZXNzYWdlLFxuICogc2VuZENsb3NlTWVzc2FnZSA6IHRydWUgLyBmYWxzZSwgYmVmb3JlIGNsb3NpbmcgdGhlIGNvbm5lY3Rpb24sIGl0IHNlbmRzIGEgY2xvc2VTZXNzaW9uIG1lc3NhZ2VcbiAqIDxwcmU+XG4gKiB3cyA6IHtcbiAqIFx0dXJpIDogVVJJIHRvIGNvbm50ZWN0IHRvLFxuICogIHVzZVNvY2tKUyA6IHRydWUgKHVzZSBTb2NrSlMpIC8gZmFsc2UgKHVzZSBXZWJTb2NrZXQpIGJ5IGRlZmF1bHQsXG4gKiBcdG9uY29ubmVjdGVkIDogY2FsbGJhY2sgbWV0aG9kIHRvIGludm9rZSB3aGVuIGNvbm5lY3Rpb24gaXMgc3VjY2Vzc2Z1bCxcbiAqIFx0b25kaXNjb25uZWN0IDogY2FsbGJhY2sgbWV0aG9kIHRvIGludm9rZSB3aGVuIHRoZSBjb25uZWN0aW9uIGlzIGxvc3QsXG4gKiBcdG9ucmVjb25uZWN0aW5nIDogY2FsbGJhY2sgbWV0aG9kIHRvIGludm9rZSB3aGVuIHRoZSBjbGllbnQgaXMgcmVjb25uZWN0aW5nLFxuICogXHRvbnJlY29ubmVjdGVkIDogY2FsbGJhY2sgbWV0aG9kIHRvIGludm9rZSB3aGVuIHRoZSBjbGllbnQgc3VjY2Vzc2Z1bGx5IHJlY29ubmVjdHMsXG4gKiBcdG9uZXJyb3IgOiBjYWxsYmFjayBtZXRob2QgdG8gaW52b2tlIHdoZW4gdGhlcmUgaXMgYW4gZXJyb3JcbiAqIH0sXG4gKiBycGMgOiB7XG4gKiBcdHJlcXVlc3RUaW1lb3V0IDogdGltZW91dCBmb3IgYSByZXF1ZXN0LFxuICogXHRzZXNzaW9uU3RhdHVzQ2hhbmdlZDogY2FsbGJhY2sgbWV0aG9kIGZvciBjaGFuZ2VzIGluIHNlc3Npb24gc3RhdHVzLFxuICogXHRtZWRpYVJlbmVnb3RpYXRpb246IG1lZGlhUmVuZWdvdGlhdGlvblxuICogfVxuICogPC9wcmU+XG4gKi9cbmZ1bmN0aW9uIEpzb25ScGNDbGllbnQoY29uZmlndXJhdGlvbikge1xuXG4gICAgdmFyIHNlbGYgPSB0aGlzO1xuXG4gICAgdmFyIHdzQ29uZmlnID0gY29uZmlndXJhdGlvbi53cztcblxuICAgIHZhciBub3RSZWNvbm5lY3RJZk51bUxlc3NUaGFuID0gLTE7XG5cbiAgICB2YXIgcGluZ05leHROdW0gPSAwO1xuICAgIHZhciBlbmFibGVkUGluZ3MgPSB0cnVlO1xuICAgIHZhciBwaW5nUG9uZ1N0YXJ0ZWQgPSBmYWxzZTtcbiAgICB2YXIgcGluZ0ludGVydmFsO1xuXG4gICAgdmFyIHN0YXR1cyA9IERJU0NPTk5FQ1RFRDtcblxuICAgIHZhciBvbnJlY29ubmVjdGluZyA9IHdzQ29uZmlnLm9ucmVjb25uZWN0aW5nO1xuICAgIHZhciBvbnJlY29ubmVjdGVkID0gd3NDb25maWcub25yZWNvbm5lY3RlZDtcbiAgICB2YXIgb25jb25uZWN0ZWQgPSB3c0NvbmZpZy5vbmNvbm5lY3RlZDtcbiAgICB2YXIgb25lcnJvciA9IHdzQ29uZmlnLm9uZXJyb3I7XG5cbiAgICBjb25maWd1cmF0aW9uLnJwYy5wdWxsID0gZnVuY3Rpb24ocGFyYW1zLCByZXF1ZXN0KSB7XG4gICAgICAgIHJlcXVlc3QucmVwbHkobnVsbCwgXCJwdXNoXCIpO1xuICAgIH1cblxuICAgIHdzQ29uZmlnLm9ucmVjb25uZWN0aW5nID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIExvZ2dlci5kZWJ1ZyhcIi0tLS0tLS0tLSBPTlJFQ09OTkVDVElORyAtLS0tLS0tLS0tLVwiKTtcbiAgICAgICAgaWYgKHN0YXR1cyA9PT0gUkVDT05ORUNUSU5HKSB7XG4gICAgICAgICAgICBMb2dnZXIuZXJyb3IoXCJXZWJzb2NrZXQgYWxyZWFkeSBpbiBSRUNPTk5FQ1RJTkcgc3RhdGUgd2hlbiByZWNlaXZpbmcgYSBuZXcgT05SRUNPTk5FQ1RJTkcgbWVzc2FnZS4gSWdub3JpbmcgaXRcIik7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBzdGF0dXMgPSBSRUNPTk5FQ1RJTkc7XG4gICAgICAgIGlmIChvbnJlY29ubmVjdGluZykge1xuICAgICAgICAgICAgb25yZWNvbm5lY3RpbmcoKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHdzQ29uZmlnLm9ucmVjb25uZWN0ZWQgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgTG9nZ2VyLmRlYnVnKFwiLS0tLS0tLS0tIE9OUkVDT05ORUNURUQgLS0tLS0tLS0tLS1cIik7XG4gICAgICAgIGlmIChzdGF0dXMgPT09IENPTk5FQ1RFRCkge1xuICAgICAgICAgICAgTG9nZ2VyLmVycm9yKFwiV2Vic29ja2V0IGFscmVhZHkgaW4gQ09OTkVDVEVEIHN0YXRlIHdoZW4gcmVjZWl2aW5nIGEgbmV3IE9OUkVDT05ORUNURUQgbWVzc2FnZS4gSWdub3JpbmcgaXRcIik7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgc3RhdHVzID0gQ09OTkVDVEVEO1xuXG4gICAgICAgIGVuYWJsZWRQaW5ncyA9IHRydWU7XG4gICAgICAgIHVwZGF0ZU5vdFJlY29ubmVjdElmTGVzc1RoYW4oKTtcbiAgICAgICAgdXNlUGluZygpO1xuXG4gICAgICAgIGlmIChvbnJlY29ubmVjdGVkKSB7XG4gICAgICAgICAgICBvbnJlY29ubmVjdGVkKCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB3c0NvbmZpZy5vbmNvbm5lY3RlZCA9IGZ1bmN0aW9uKCkge1xuICAgICAgICBMb2dnZXIuZGVidWcoXCItLS0tLS0tLS0gT05DT05ORUNURUQgLS0tLS0tLS0tLS1cIik7XG4gICAgICAgIGlmIChzdGF0dXMgPT09IENPTk5FQ1RFRCkge1xuICAgICAgICAgICAgTG9nZ2VyLmVycm9yKFwiV2Vic29ja2V0IGFscmVhZHkgaW4gQ09OTkVDVEVEIHN0YXRlIHdoZW4gcmVjZWl2aW5nIGEgbmV3IE9OQ09OTkVDVEVEIG1lc3NhZ2UuIElnbm9yaW5nIGl0XCIpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHN0YXR1cyA9IENPTk5FQ1RFRDtcblxuICAgICAgICBlbmFibGVkUGluZ3MgPSB0cnVlO1xuICAgICAgICB1c2VQaW5nKCk7XG5cbiAgICAgICAgaWYgKG9uY29ubmVjdGVkKSB7XG4gICAgICAgICAgICBvbmNvbm5lY3RlZCgpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgd3NDb25maWcub25lcnJvciA9IGZ1bmN0aW9uKGVycm9yKSB7XG4gICAgICAgIExvZ2dlci5kZWJ1ZyhcIi0tLS0tLS0tLSBPTkVSUk9SIC0tLS0tLS0tLS0tXCIpO1xuXG4gICAgICAgIHN0YXR1cyA9IERJU0NPTk5FQ1RFRDtcblxuICAgICAgICBpZiAob25lcnJvcikge1xuICAgICAgICAgICAgb25lcnJvcihlcnJvcik7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB2YXIgd3MgPSBuZXcgV2ViU29ja2V0V2l0aFJlY29ubmVjdGlvbih3c0NvbmZpZyk7XG5cbiAgICBMb2dnZXIuZGVidWcoJ0Nvbm5lY3Rpbmcgd2Vic29ja2V0IHRvIFVSSTogJyArIHdzQ29uZmlnLnVyaSk7XG5cbiAgICB2YXIgcnBjQnVpbGRlck9wdGlvbnMgPSB7XG4gICAgICAgIHJlcXVlc3RfdGltZW91dDogY29uZmlndXJhdGlvbi5ycGMucmVxdWVzdFRpbWVvdXQsXG4gICAgICAgIHBpbmdfcmVxdWVzdF90aW1lb3V0OiBjb25maWd1cmF0aW9uLnJwYy5oZWFydGJlYXRSZXF1ZXN0VGltZW91dFxuICAgIH07XG5cbiAgICB2YXIgcnBjID0gbmV3IFJwY0J1aWxkZXIoUnBjQnVpbGRlci5wYWNrZXJzLkpzb25SUEMsIHJwY0J1aWxkZXJPcHRpb25zLCB3cyxcbiAgICAgICAgZnVuY3Rpb24ocmVxdWVzdCkge1xuXG4gICAgICAgICAgICBMb2dnZXIuZGVidWcoJ1JlY2VpdmVkIHJlcXVlc3Q6ICcgKyBKU09OLnN0cmluZ2lmeShyZXF1ZXN0KSk7XG5cbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgdmFyIGZ1bmMgPSBjb25maWd1cmF0aW9uLnJwY1tyZXF1ZXN0Lm1ldGhvZF07XG5cbiAgICAgICAgICAgICAgICBpZiAoZnVuYyA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgIExvZ2dlci5lcnJvcihcIk1ldGhvZCBcIiArIHJlcXVlc3QubWV0aG9kICsgXCIgbm90IHJlZ2lzdGVyZWQgaW4gY2xpZW50XCIpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGZ1bmMocmVxdWVzdC5wYXJhbXMsIHJlcXVlc3QpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgICAgIExvZ2dlci5lcnJvcignRXhjZXB0aW9uIHByb2Nlc3NpbmcgcmVxdWVzdDogJyArIEpTT04uc3RyaW5naWZ5KHJlcXVlc3QpKTtcbiAgICAgICAgICAgICAgICBMb2dnZXIuZXJyb3IoZXJyKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG5cbiAgICB0aGlzLnNlbmQgPSBmdW5jdGlvbihtZXRob2QsIHBhcmFtcywgY2FsbGJhY2spIHtcbiAgICAgICAgaWYgKG1ldGhvZCAhPT0gJ3BpbmcnKSB7XG4gICAgICAgICAgICBMb2dnZXIuZGVidWcoJ1JlcXVlc3Q6IG1ldGhvZDonICsgbWV0aG9kICsgXCIgcGFyYW1zOlwiICsgSlNPTi5zdHJpbmdpZnkocGFyYW1zKSk7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgcmVxdWVzdFRpbWUgPSBEYXRlLm5vdygpO1xuXG4gICAgICAgIHJwYy5lbmNvZGUobWV0aG9kLCBwYXJhbXMsIGZ1bmN0aW9uKGVycm9yLCByZXN1bHQpIHtcbiAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgIExvZ2dlci5lcnJvcihcIkVSUk9SOlwiICsgZXJyb3IubWVzc2FnZSArIFwiIGluIFJlcXVlc3Q6IG1ldGhvZDpcIiArXG4gICAgICAgICAgICAgICAgICAgICAgICBtZXRob2QgKyBcIiBwYXJhbXM6XCIgKyBKU09OLnN0cmluZ2lmeShwYXJhbXMpICsgXCIgcmVxdWVzdDpcIiArXG4gICAgICAgICAgICAgICAgICAgICAgICBlcnJvci5yZXF1ZXN0KTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yLmRhdGEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIExvZ2dlci5lcnJvcihcIkVSUk9SIERBVEE6XCIgKyBKU09OLnN0cmluZ2lmeShlcnJvci5kYXRhKSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGNhdGNoIChlKSB7fVxuICAgICAgICAgICAgICAgIGVycm9yLnJlcXVlc3RUaW1lID0gcmVxdWVzdFRpbWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoY2FsbGJhY2spIHtcbiAgICAgICAgICAgICAgICBpZiAocmVzdWx0ICE9IHVuZGVmaW5lZCAmJiByZXN1bHQudmFsdWUgIT09ICdwb25nJykge1xuICAgICAgICAgICAgICAgICAgICBMb2dnZXIuZGVidWcoJ1Jlc3BvbnNlOiAnICsgSlNPTi5zdHJpbmdpZnkocmVzdWx0KSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNhbGxiYWNrKGVycm9yLCByZXN1bHQpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiB1cGRhdGVOb3RSZWNvbm5lY3RJZkxlc3NUaGFuKCkge1xuICAgICAgICBMb2dnZXIuZGVidWcoXCJub3RSZWNvbm5lY3RJZk51bUxlc3NUaGFuID0gXCIgKyBwaW5nTmV4dE51bSArICcgKG9sZD0nICtcbiAgICAgICAgICAgIG5vdFJlY29ubmVjdElmTnVtTGVzc1RoYW4gKyAnKScpO1xuICAgICAgICBub3RSZWNvbm5lY3RJZk51bUxlc3NUaGFuID0gcGluZ05leHROdW07XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gc2VuZFBpbmcoKSB7XG4gICAgICAgIGlmIChlbmFibGVkUGluZ3MpIHtcbiAgICAgICAgICAgIHZhciBwYXJhbXMgPSBudWxsO1xuICAgICAgICAgICAgaWYgKHBpbmdOZXh0TnVtID09IDAgfHwgcGluZ05leHROdW0gPT0gbm90UmVjb25uZWN0SWZOdW1MZXNzVGhhbikge1xuICAgICAgICAgICAgICAgIHBhcmFtcyA9IHtcbiAgICAgICAgICAgICAgICAgICAgaW50ZXJ2YWw6IGNvbmZpZ3VyYXRpb24uaGVhcnRiZWF0IHx8IFBJTkdfSU5URVJWQUxcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcGluZ05leHROdW0rKztcblxuICAgICAgICAgICAgc2VsZi5zZW5kKCdwaW5nJywgcGFyYW1zLCAoZnVuY3Rpb24ocGluZ051bSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmdW5jdGlvbihlcnJvciwgcmVzdWx0KSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFwiRXJyb3IgaW4gcGluZyByZXF1ZXN0ICNcIiArIHBpbmdOdW0gKyBcIiAoXCIgK1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yLm1lc3NhZ2UgKyBcIilcIik7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocGluZ051bSA+IG5vdFJlY29ubmVjdElmTnVtTGVzc1RoYW4pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbmFibGVkUGluZ3MgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB1cGRhdGVOb3RSZWNvbm5lY3RJZkxlc3NUaGFuKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFwiU2VydmVyIGRpZCBub3QgcmVzcG9uZCB0byBwaW5nIG1lc3NhZ2UgI1wiICtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGluZ051bSArIFwiLiBSZWNvbm5lY3RpbmcuLi4gXCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdzLnJlY29ubmVjdFdzKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KShwaW5nTmV4dE51bSkpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFwiVHJ5aW5nIHRvIHNlbmQgcGluZywgYnV0IHBpbmcgaXMgbm90IGVuYWJsZWRcIik7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKlxuICAgICogSWYgY29uZmlndXJhdGlvbi5oZWFyYmVhdCBoYXMgYW55IHZhbHVlLCB0aGUgcGluZy1wb25nIHdpbGwgd29yayB3aXRoIHRoZSBpbnRlcnZhbFxuICAgICogb2YgY29uZmlndXJhdGlvbi5oZWFyYmVhdFxuICAgICovXG4gICAgZnVuY3Rpb24gdXNlUGluZygpIHtcbiAgICAgICAgaWYgKCFwaW5nUG9uZ1N0YXJ0ZWQpIHtcbiAgICAgICAgICAgIExvZ2dlci5kZWJ1ZyhcIlN0YXJ0aW5nIHBpbmcgKGlmIGNvbmZpZ3VyZWQpXCIpXG4gICAgICAgICAgICBwaW5nUG9uZ1N0YXJ0ZWQgPSB0cnVlO1xuXG4gICAgICAgICAgICBpZiAoY29uZmlndXJhdGlvbi5oZWFydGJlYXQgIT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgcGluZ0ludGVydmFsID0gc2V0SW50ZXJ2YWwoc2VuZFBpbmcsIGNvbmZpZ3VyYXRpb24uaGVhcnRiZWF0KTtcbiAgICAgICAgICAgICAgICBzZW5kUGluZygpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgdGhpcy5jbG9zZSA9IGZ1bmN0aW9uKCkge1xuICAgICAgICBMb2dnZXIuZGVidWcoXCJDbG9zaW5nIGpzb25ScGNDbGllbnQgZXhwbGljaXRseSBieSBjbGllbnRcIik7XG5cbiAgICAgICAgaWYgKHBpbmdJbnRlcnZhbCAhPSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIExvZ2dlci5kZWJ1ZyhcIkNsZWFyaW5nIHBpbmcgaW50ZXJ2YWxcIik7XG4gICAgICAgICAgICBjbGVhckludGVydmFsKHBpbmdJbnRlcnZhbCk7XG4gICAgICAgIH1cbiAgICAgICAgcGluZ1BvbmdTdGFydGVkID0gZmFsc2U7XG4gICAgICAgIGVuYWJsZWRQaW5ncyA9IGZhbHNlO1xuXG4gICAgICAgIGlmIChjb25maWd1cmF0aW9uLnNlbmRDbG9zZU1lc3NhZ2UpIHtcbiAgICAgICAgICAgIExvZ2dlci5kZWJ1ZyhcIlNlbmRpbmcgY2xvc2UgbWVzc2FnZVwiKVxuICAgICAgICAgICAgdGhpcy5zZW5kKCdjbG9zZVNlc3Npb24nLCBudWxsLCBmdW5jdGlvbihlcnJvciwgcmVzdWx0KSB7XG4gICAgICAgICAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgIExvZ2dlci5lcnJvcihcIkVycm9yIHNlbmRpbmcgY2xvc2UgbWVzc2FnZTogXCIgKyBKU09OLnN0cmluZ2lmeShlcnJvcikpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB3cy5jbG9zZSgpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0gZWxzZSB7XG5cdFx0XHR3cy5jbG9zZSgpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gVGhpcyBtZXRob2QgaXMgb25seSBmb3IgdGVzdGluZ1xuICAgIHRoaXMuZm9yY2VDbG9zZSA9IGZ1bmN0aW9uKG1pbGxpcykge1xuICAgICAgICB3cy5mb3JjZUNsb3NlKG1pbGxpcyk7XG4gICAgfVxuXG4gICAgdGhpcy5yZWNvbm5lY3QgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgd3MucmVjb25uZWN0V3MoKTtcbiAgICB9XG59XG5cblxubW9kdWxlLmV4cG9ydHMgPSBKc29uUnBjQ2xpZW50O1xuIiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNCBLdXJlbnRvIChodHRwOi8va3VyZW50by5vcmcvKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbnZhciBXZWJTb2NrZXRXaXRoUmVjb25uZWN0aW9uICA9IHJlcXVpcmUoJy4vd2ViU29ja2V0V2l0aFJlY29ubmVjdGlvbicpO1xuXG5cbmV4cG9ydHMuV2ViU29ja2V0V2l0aFJlY29ubmVjdGlvbiAgPSBXZWJTb2NrZXRXaXRoUmVjb25uZWN0aW9uOyIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTMtMjAxNSBLdXJlbnRvIChodHRwOi8va3VyZW50by5vcmcvKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuXCJ1c2Ugc3RyaWN0XCI7XG5cbnZhciBCcm93c2VyV2ViU29ja2V0ID0gZ2xvYmFsLldlYlNvY2tldCB8fCBnbG9iYWwuTW96V2ViU29ja2V0O1xuXG52YXIgTG9nZ2VyID0gY29uc29sZTtcblxuLyoqXG4gKiBHZXQgZWl0aGVyIHRoZSBgV2ViU29ja2V0YCBvciBgTW96V2ViU29ja2V0YCBnbG9iYWxzXG4gKiBpbiB0aGUgYnJvd3NlciBvciB0cnkgdG8gcmVzb2x2ZSBXZWJTb2NrZXQtY29tcGF0aWJsZVxuICogaW50ZXJmYWNlIGV4cG9zZWQgYnkgYHdzYCBmb3IgTm9kZS1saWtlIGVudmlyb25tZW50LlxuICovXG5cbi8qdmFyIFdlYlNvY2tldCA9IEJyb3dzZXJXZWJTb2NrZXQ7XG5pZiAoIVdlYlNvY2tldCAmJiB0eXBlb2Ygd2luZG93ID09PSAndW5kZWZpbmVkJykge1xuICAgIHRyeSB7XG4gICAgICAgIFdlYlNvY2tldCA9IHJlcXVpcmUoJ3dzJyk7XG4gICAgfSBjYXRjaCAoZSkgeyB9XG59Ki9cblxuLy92YXIgU29ja0pTID0gcmVxdWlyZSgnc29ja2pzLWNsaWVudCcpO1xuXG52YXIgTUFYX1JFVFJJRVMgPSAyMDAwOyAvLyBGb3JldmVyLi4uXG52YXIgUkVUUllfVElNRV9NUyA9IDMwMDA7IC8vIEZJWE1FOiBJbXBsZW1lbnQgZXhwb25lbnRpYWwgd2FpdCB0aW1lcy4uLlxuXG52YXIgQ09OTkVDVElORyA9IDA7XG52YXIgT1BFTiA9IDE7XG52YXIgQ0xPU0lORyA9IDI7XG52YXIgQ0xPU0VEID0gMztcblxuLypcbmNvbmZpZyA9IHtcblx0XHR1cmkgOiB3c1VyaSxcblx0XHR1c2VTb2NrSlMgOiB0cnVlICh1c2UgU29ja0pTKSAvIGZhbHNlICh1c2UgV2ViU29ja2V0KSBieSBkZWZhdWx0LFxuXHRcdG9uY29ubmVjdGVkIDogY2FsbGJhY2sgbWV0aG9kIHRvIGludm9rZSB3aGVuIGNvbm5lY3Rpb24gaXMgc3VjY2Vzc2Z1bCxcblx0XHRvbmRpc2Nvbm5lY3QgOiBjYWxsYmFjayBtZXRob2QgdG8gaW52b2tlIHdoZW4gdGhlIGNvbm5lY3Rpb24gaXMgbG9zdCxcblx0XHRvbnJlY29ubmVjdGluZyA6IGNhbGxiYWNrIG1ldGhvZCB0byBpbnZva2Ugd2hlbiB0aGUgY2xpZW50IGlzIHJlY29ubmVjdGluZyxcblx0XHRvbnJlY29ubmVjdGVkIDogY2FsbGJhY2sgbWV0aG9kIHRvIGludm9rZSB3aGVuIHRoZSBjbGllbnQgc3VjY2Vzc2Z1bGx5IHJlY29ubmVjdHMsXG5cdH07XG4qL1xuZnVuY3Rpb24gV2ViU29ja2V0V2l0aFJlY29ubmVjdGlvbihjb25maWcpIHtcblxuICAgIHZhciBjbG9zaW5nID0gZmFsc2U7XG4gICAgdmFyIHJlZ2lzdGVyTWVzc2FnZUhhbmRsZXI7XG4gICAgdmFyIHdzVXJpID0gY29uZmlnLnVyaTtcbiAgICB2YXIgdXNlU29ja0pTID0gY29uZmlnLnVzZVNvY2tKUztcbiAgICB2YXIgcmVjb25uZWN0aW5nID0gZmFsc2U7XG5cbiAgICB2YXIgZm9yY2luZ0Rpc2Nvbm5lY3Rpb24gPSBmYWxzZTtcblxuICAgIHZhciB3cztcblxuICAgIGlmICh1c2VTb2NrSlMpIHtcbiAgICAgICAgd3MgPSBuZXcgU29ja0pTKHdzVXJpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICB3cyA9IG5ldyBXZWJTb2NrZXQod3NVcmkpO1xuICAgIH1cblxuICAgIHdzLm9ub3BlbiA9IGZ1bmN0aW9uKCkge1xuICAgICAgICBsb2dDb25uZWN0ZWQod3MsIHdzVXJpKTtcbiAgICAgICAgaWYgKGNvbmZpZy5vbmNvbm5lY3RlZCkge1xuICAgICAgICAgICAgY29uZmlnLm9uY29ubmVjdGVkKCk7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgd3Mub25lcnJvciA9IGZ1bmN0aW9uKGVycm9yKSB7XG4gICAgICAgIExvZ2dlci5lcnJvcihcIkNvdWxkIG5vdCBjb25uZWN0IHRvIFwiICsgd3NVcmkgKyBcIiAoaW52b2tpbmcgb25lcnJvciBpZiBkZWZpbmVkKVwiLCBlcnJvcik7XG4gICAgICAgIGlmIChjb25maWcub25lcnJvcikge1xuICAgICAgICAgICAgY29uZmlnLm9uZXJyb3IoZXJyb3IpO1xuICAgICAgICB9XG4gICAgfTtcblxuICAgIGZ1bmN0aW9uIGxvZ0Nvbm5lY3RlZCh3cywgd3NVcmkpIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIExvZ2dlci5kZWJ1ZyhcIldlYlNvY2tldCBjb25uZWN0ZWQgdG8gXCIgKyB3c1VyaSk7XG4gICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgIExvZ2dlci5lcnJvcihlKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHZhciByZWNvbm5lY3Rpb25PbkNsb3NlID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIGlmICh3cy5yZWFkeVN0YXRlID09PSBDTE9TRUQpIHtcbiAgICAgICAgICAgIGlmIChjbG9zaW5nKSB7XG4gICAgICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFwiQ29ubmVjdGlvbiBjbG9zZWQgYnkgdXNlclwiKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFwiQ29ubmVjdGlvbiBjbG9zZWQgdW5leHBlY3RlY2x5LiBSZWNvbm5lY3RpbmcuLi5cIik7XG4gICAgICAgICAgICAgICAgcmVjb25uZWN0VG9TYW1lVXJpKE1BWF9SRVRSSUVTLCAxKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIExvZ2dlci5kZWJ1ZyhcIkNsb3NlIGNhbGxiYWNrIGZyb20gcHJldmlvdXMgd2Vic29ja2V0LiBJZ25vcmluZyBpdFwiKTtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICB3cy5vbmNsb3NlID0gcmVjb25uZWN0aW9uT25DbG9zZTtcblxuICAgIGZ1bmN0aW9uIHJlY29ubmVjdFRvU2FtZVVyaShtYXhSZXRyaWVzLCBudW1SZXRyaWVzKSB7XG4gICAgICAgIExvZ2dlci5kZWJ1ZyhcInJlY29ubmVjdFRvU2FtZVVyaSAoYXR0ZW1wdCAjXCIgKyBudW1SZXRyaWVzICsgXCIsIG1heD1cIiArIG1heFJldHJpZXMgKyBcIilcIik7XG5cbiAgICAgICAgaWYgKG51bVJldHJpZXMgPT09IDEpIHtcbiAgICAgICAgICAgIGlmIChyZWNvbm5lY3RpbmcpIHtcbiAgICAgICAgICAgICAgICBMb2dnZXIud2FybihcIlRyeWluZyB0byByZWNvbm5lY3RUb05ld1VyaSB3aGVuIHJlY29ubmVjdGluZy4uLiBJZ25vcmluZyB0aGlzIHJlY29ubmVjdGlvbi5cIilcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJlY29ubmVjdGluZyA9IHRydWU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChjb25maWcub25yZWNvbm5lY3RpbmcpIHtcbiAgICAgICAgICAgICAgICBjb25maWcub25yZWNvbm5lY3RpbmcoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChmb3JjaW5nRGlzY29ubmVjdGlvbikge1xuICAgICAgICAgICAgcmVjb25uZWN0VG9OZXdVcmkobWF4UmV0cmllcywgbnVtUmV0cmllcywgd3NVcmkpO1xuXG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBpZiAoY29uZmlnLm5ld1dzVXJpT25SZWNvbm5lY3Rpb24pIHtcbiAgICAgICAgICAgICAgICBjb25maWcubmV3V3NVcmlPblJlY29ubmVjdGlvbihmdW5jdGlvbihlcnJvciwgbmV3V3NVcmkpIHtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIExvZ2dlci5kZWJ1ZyhlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlY29ubmVjdFRvU2FtZVVyaShtYXhSZXRyaWVzLCBudW1SZXRyaWVzICsgMSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9LCBSRVRSWV9USU1FX01TKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlY29ubmVjdFRvTmV3VXJpKG1heFJldHJpZXMsIG51bVJldHJpZXMsIG5ld1dzVXJpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJlY29ubmVjdFRvTmV3VXJpKG1heFJldHJpZXMsIG51bVJldHJpZXMsIHdzVXJpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIFRPRE8gVGVzdCByZXRyaWVzLiBIb3cgdG8gZm9yY2Ugbm90IGNvbm5lY3Rpb24/XG4gICAgZnVuY3Rpb24gcmVjb25uZWN0VG9OZXdVcmkobWF4UmV0cmllcywgbnVtUmV0cmllcywgcmVjb25uZWN0V3NVcmkpIHtcbiAgICAgICAgTG9nZ2VyLmRlYnVnKFwiUmVjb25uZWN0aW9uIGF0dGVtcHQgI1wiICsgbnVtUmV0cmllcyk7XG5cbiAgICAgICAgd3MuY2xvc2UoKTtcblxuICAgICAgICB3c1VyaSA9IHJlY29ubmVjdFdzVXJpIHx8IHdzVXJpO1xuXG4gICAgICAgIHZhciBuZXdXcztcbiAgICAgICAgaWYgKHVzZVNvY2tKUykge1xuICAgICAgICAgICAgbmV3V3MgPSBuZXcgU29ja0pTKHdzVXJpKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIG5ld1dzID0gbmV3IFdlYlNvY2tldCh3c1VyaSk7XG4gICAgICAgIH1cblxuICAgICAgICBuZXdXcy5vbm9wZW4gPSBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIExvZ2dlci5kZWJ1ZyhcIlJlY29ubmVjdGVkIGFmdGVyIFwiICsgbnVtUmV0cmllcyArIFwiIGF0dGVtcHRzLi4uXCIpO1xuICAgICAgICAgICAgbG9nQ29ubmVjdGVkKG5ld1dzLCB3c1VyaSk7XG4gICAgICAgICAgICByZWNvbm5lY3RpbmcgPSBmYWxzZTtcbiAgICAgICAgICAgIHJlZ2lzdGVyTWVzc2FnZUhhbmRsZXIoKTtcbiAgICAgICAgICAgIGlmIChjb25maWcub25yZWNvbm5lY3RlZCgpKSB7XG4gICAgICAgICAgICAgICAgY29uZmlnLm9ucmVjb25uZWN0ZWQoKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgbmV3V3Mub25jbG9zZSA9IHJlY29ubmVjdGlvbk9uQ2xvc2U7XG4gICAgICAgIH07XG5cbiAgICAgICAgdmFyIG9uRXJyb3JPckNsb3NlID0gZnVuY3Rpb24oZXJyb3IpIHtcbiAgICAgICAgICAgIExvZ2dlci53YXJuKFwiUmVjb25uZWN0aW9uIGVycm9yOiBcIiwgZXJyb3IpO1xuXG4gICAgICAgICAgICBpZiAobnVtUmV0cmllcyA9PT0gbWF4UmV0cmllcykge1xuICAgICAgICAgICAgICAgIGlmIChjb25maWcub25kaXNjb25uZWN0KSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbmZpZy5vbmRpc2Nvbm5lY3QoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlY29ubmVjdFRvU2FtZVVyaShtYXhSZXRyaWVzLCBudW1SZXRyaWVzICsgMSk7XG4gICAgICAgICAgICAgICAgfSwgUkVUUllfVElNRV9NUyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG5cbiAgICAgICAgbmV3V3Mub25lcnJvciA9IG9uRXJyb3JPckNsb3NlO1xuXG4gICAgICAgIHdzID0gbmV3V3M7XG4gICAgfVxuXG4gICAgdGhpcy5jbG9zZSA9IGZ1bmN0aW9uKCkge1xuICAgICAgICBjbG9zaW5nID0gdHJ1ZTtcbiAgICAgICAgd3MuY2xvc2UoKTtcbiAgICB9O1xuXG5cbiAgICAvLyBUaGlzIG1ldGhvZCBpcyBvbmx5IGZvciB0ZXN0aW5nXG4gICAgdGhpcy5mb3JjZUNsb3NlID0gZnVuY3Rpb24obWlsbGlzKSB7XG4gICAgICAgIExvZ2dlci5kZWJ1ZyhcIlRlc3Rpbmc6IEZvcmNlIFdlYlNvY2tldCBjbG9zZVwiKTtcblxuICAgICAgICBpZiAobWlsbGlzKSB7XG4gICAgICAgICAgICBMb2dnZXIuZGVidWcoXCJUZXN0aW5nOiBDaGFuZ2Ugd3NVcmkgZm9yIFwiICsgbWlsbGlzICsgXCIgbWlsbGlzIHRvIHNpbXVsYXRlIG5ldCBmYWlsdXJlXCIpO1xuICAgICAgICAgICAgdmFyIGdvb2RXc1VyaSA9IHdzVXJpO1xuICAgICAgICAgICAgd3NVcmkgPSBcIndzczovLzIxLjIzNC4xMi4zNC40OjQ0My9cIjtcblxuICAgICAgICAgICAgZm9yY2luZ0Rpc2Nvbm5lY3Rpb24gPSB0cnVlO1xuXG4gICAgICAgICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgIExvZ2dlci5kZWJ1ZyhcIlRlc3Rpbmc6IFJlY292ZXIgZ29vZCB3c1VyaSBcIiArIGdvb2RXc1VyaSk7XG4gICAgICAgICAgICAgICAgd3NVcmkgPSBnb29kV3NVcmk7XG5cbiAgICAgICAgICAgICAgICBmb3JjaW5nRGlzY29ubmVjdGlvbiA9IGZhbHNlO1xuXG4gICAgICAgICAgICB9LCBtaWxsaXMpO1xuICAgICAgICB9XG5cbiAgICAgICAgd3MuY2xvc2UoKTtcbiAgICB9O1xuXG4gICAgdGhpcy5yZWNvbm5lY3RXcyA9IGZ1bmN0aW9uKCkge1xuICAgICAgICBMb2dnZXIuZGVidWcoXCJyZWNvbm5lY3RXc1wiKTtcbiAgICAgICAgcmVjb25uZWN0VG9TYW1lVXJpKE1BWF9SRVRSSUVTLCAxKTtcbiAgICB9O1xuXG4gICAgdGhpcy5zZW5kID0gZnVuY3Rpb24obWVzc2FnZSkge1xuICAgICAgICB3cy5zZW5kKG1lc3NhZ2UpO1xuICAgIH07XG5cbiAgICB0aGlzLmFkZEV2ZW50TGlzdGVuZXIgPSBmdW5jdGlvbih0eXBlLCBjYWxsYmFjaykge1xuICAgICAgICByZWdpc3Rlck1lc3NhZ2VIYW5kbGVyID0gZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICB3cy5hZGRFdmVudExpc3RlbmVyKHR5cGUsIGNhbGxiYWNrKTtcbiAgICAgICAgfTtcblxuICAgICAgICByZWdpc3Rlck1lc3NhZ2VIYW5kbGVyKCk7XG4gICAgfTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBXZWJTb2NrZXRXaXRoUmVjb25uZWN0aW9uO1xuIiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNCBLdXJlbnRvIChodHRwOi8va3VyZW50by5vcmcvKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cblxudmFyIGRlZmluZVByb3BlcnR5X0lFOCA9IGZhbHNlXG5pZihPYmplY3QuZGVmaW5lUHJvcGVydHkpXG57XG4gIHRyeVxuICB7XG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHt9LCBcInhcIiwge30pO1xuICB9XG4gIGNhdGNoKGUpXG4gIHtcbiAgICBkZWZpbmVQcm9wZXJ0eV9JRTggPSB0cnVlXG4gIH1cbn1cblxuLy8gaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvSmF2YVNjcmlwdC9SZWZlcmVuY2UvR2xvYmFsX09iamVjdHMvRnVuY3Rpb24vYmluZFxuaWYgKCFGdW5jdGlvbi5wcm90b3R5cGUuYmluZCkge1xuICBGdW5jdGlvbi5wcm90b3R5cGUuYmluZCA9IGZ1bmN0aW9uKG9UaGlzKSB7XG4gICAgaWYgKHR5cGVvZiB0aGlzICE9PSAnZnVuY3Rpb24nKSB7XG4gICAgICAvLyBjbG9zZXN0IHRoaW5nIHBvc3NpYmxlIHRvIHRoZSBFQ01BU2NyaXB0IDVcbiAgICAgIC8vIGludGVybmFsIElzQ2FsbGFibGUgZnVuY3Rpb25cbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ0Z1bmN0aW9uLnByb3RvdHlwZS5iaW5kIC0gd2hhdCBpcyB0cnlpbmcgdG8gYmUgYm91bmQgaXMgbm90IGNhbGxhYmxlJyk7XG4gICAgfVxuXG4gICAgdmFyIGFBcmdzICAgPSBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMsIDEpLFxuICAgICAgICBmVG9CaW5kID0gdGhpcyxcbiAgICAgICAgZk5PUCAgICA9IGZ1bmN0aW9uKCkge30sXG4gICAgICAgIGZCb3VuZCAgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgICByZXR1cm4gZlRvQmluZC5hcHBseSh0aGlzIGluc3RhbmNlb2YgZk5PUCAmJiBvVGhpc1xuICAgICAgICAgICAgICAgICA/IHRoaXNcbiAgICAgICAgICAgICAgICAgOiBvVGhpcyxcbiAgICAgICAgICAgICAgICAgYUFyZ3MuY29uY2F0KEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3VtZW50cykpKTtcbiAgICAgICAgfTtcblxuICAgIGZOT1AucHJvdG90eXBlID0gdGhpcy5wcm90b3R5cGU7XG4gICAgZkJvdW5kLnByb3RvdHlwZSA9IG5ldyBmTk9QKCk7XG5cbiAgICByZXR1cm4gZkJvdW5kO1xuICB9O1xufVxuXG5cbnZhciBFdmVudEVtaXR0ZXIgPSByZXF1aXJlKCdldmVudHMnKS5FdmVudEVtaXR0ZXI7XG5cbnZhciBpbmhlcml0cyA9IHJlcXVpcmUoJ2luaGVyaXRzJyk7XG5cbnZhciBwYWNrZXJzID0gcmVxdWlyZSgnLi9wYWNrZXJzJyk7XG52YXIgTWFwcGVyID0gcmVxdWlyZSgnLi9NYXBwZXInKTtcblxuXG52YXIgQkFTRV9USU1FT1VUID0gNTAwMDtcblxuXG5mdW5jdGlvbiB1bmlmeVJlc3BvbnNlTWV0aG9kcyhyZXNwb25zZU1ldGhvZHMpXG57XG4gIGlmKCFyZXNwb25zZU1ldGhvZHMpIHJldHVybiB7fTtcblxuICBmb3IodmFyIGtleSBpbiByZXNwb25zZU1ldGhvZHMpXG4gIHtcbiAgICB2YXIgdmFsdWUgPSByZXNwb25zZU1ldGhvZHNba2V5XTtcblxuICAgIGlmKHR5cGVvZiB2YWx1ZSA9PSAnc3RyaW5nJylcbiAgICAgIHJlc3BvbnNlTWV0aG9kc1trZXldID1cbiAgICAgIHtcbiAgICAgICAgcmVzcG9uc2U6IHZhbHVlXG4gICAgICB9XG4gIH07XG5cbiAgcmV0dXJuIHJlc3BvbnNlTWV0aG9kcztcbn07XG5cbmZ1bmN0aW9uIHVuaWZ5VHJhbnNwb3J0KHRyYW5zcG9ydClcbntcbiAgaWYoIXRyYW5zcG9ydCkgcmV0dXJuO1xuXG4gIC8vIFRyYW5zcG9ydCBhcyBhIGZ1bmN0aW9uXG4gIGlmKHRyYW5zcG9ydCBpbnN0YW5jZW9mIEZ1bmN0aW9uKVxuICAgIHJldHVybiB7c2VuZDogdHJhbnNwb3J0fTtcblxuICAvLyBXZWJTb2NrZXQgJiBEYXRhQ2hhbm5lbFxuICBpZih0cmFuc3BvcnQuc2VuZCBpbnN0YW5jZW9mIEZ1bmN0aW9uKVxuICAgIHJldHVybiB0cmFuc3BvcnQ7XG5cbiAgLy8gTWVzc2FnZSBBUEkgKEludGVyLXdpbmRvdyAmIFdlYldvcmtlcilcbiAgaWYodHJhbnNwb3J0LnBvc3RNZXNzYWdlIGluc3RhbmNlb2YgRnVuY3Rpb24pXG4gIHtcbiAgICB0cmFuc3BvcnQuc2VuZCA9IHRyYW5zcG9ydC5wb3N0TWVzc2FnZTtcbiAgICByZXR1cm4gdHJhbnNwb3J0O1xuICB9XG5cbiAgLy8gU3RyZWFtIEFQSVxuICBpZih0cmFuc3BvcnQud3JpdGUgaW5zdGFuY2VvZiBGdW5jdGlvbilcbiAge1xuICAgIHRyYW5zcG9ydC5zZW5kID0gdHJhbnNwb3J0LndyaXRlO1xuICAgIHJldHVybiB0cmFuc3BvcnQ7XG4gIH1cblxuICAvLyBUcmFuc3BvcnRzIHRoYXQgb25seSBjYW4gcmVjZWl2ZSBtZXNzYWdlcywgYnV0IG5vdCBzZW5kXG4gIGlmKHRyYW5zcG9ydC5vbm1lc3NhZ2UgIT09IHVuZGVmaW5lZCkgcmV0dXJuO1xuICBpZih0cmFuc3BvcnQucGF1c2UgaW5zdGFuY2VvZiBGdW5jdGlvbikgcmV0dXJuO1xuXG4gIHRocm93IG5ldyBTeW50YXhFcnJvcihcIlRyYW5zcG9ydCBpcyBub3QgYSBmdW5jdGlvbiBub3IgYSB2YWxpZCBvYmplY3RcIik7XG59O1xuXG5cbi8qKlxuICogUmVwcmVzZW50YXRpb24gb2YgYSBSUEMgbm90aWZpY2F0aW9uXG4gKlxuICogQGNsYXNzXG4gKlxuICogQGNvbnN0cnVjdG9yXG4gKlxuICogQHBhcmFtIHtTdHJpbmd9IG1ldGhvZCAtbWV0aG9kIG9mIHRoZSBub3RpZmljYXRpb25cbiAqIEBwYXJhbSBwYXJhbXMgLSBwYXJhbWV0ZXJzIG9mIHRoZSBub3RpZmljYXRpb25cbiAqL1xuZnVuY3Rpb24gUnBjTm90aWZpY2F0aW9uKG1ldGhvZCwgcGFyYW1zKVxue1xuICBpZihkZWZpbmVQcm9wZXJ0eV9JRTgpXG4gIHtcbiAgICB0aGlzLm1ldGhvZCA9IG1ldGhvZFxuICAgIHRoaXMucGFyYW1zID0gcGFyYW1zXG4gIH1cbiAgZWxzZVxuICB7XG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRoaXMsICdtZXRob2QnLCB7dmFsdWU6IG1ldGhvZCwgZW51bWVyYWJsZTogdHJ1ZX0pO1xuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0aGlzLCAncGFyYW1zJywge3ZhbHVlOiBwYXJhbXMsIGVudW1lcmFibGU6IHRydWV9KTtcbiAgfVxufTtcblxuXG4vKipcbiAqIEBjbGFzc1xuICpcbiAqIEBjb25zdHJ1Y3RvclxuICpcbiAqIEBwYXJhbSB7b2JqZWN0fSBwYWNrZXJcbiAqXG4gKiBAcGFyYW0ge29iamVjdH0gW29wdGlvbnNdXG4gKlxuICogQHBhcmFtIHtvYmplY3R9IFt0cmFuc3BvcnRdXG4gKlxuICogQHBhcmFtIHtGdW5jdGlvbn0gW29uUmVxdWVzdF1cbiAqL1xuZnVuY3Rpb24gUnBjQnVpbGRlcihwYWNrZXIsIG9wdGlvbnMsIHRyYW5zcG9ydCwgb25SZXF1ZXN0KVxue1xuICB2YXIgc2VsZiA9IHRoaXM7XG5cbiAgaWYoIXBhY2tlcilcbiAgICB0aHJvdyBuZXcgU3ludGF4RXJyb3IoJ1BhY2tlciBpcyBub3QgZGVmaW5lZCcpO1xuXG4gIGlmKCFwYWNrZXIucGFjayB8fCAhcGFja2VyLnVucGFjaylcbiAgICB0aHJvdyBuZXcgU3ludGF4RXJyb3IoJ1BhY2tlciBpcyBpbnZhbGlkJyk7XG5cbiAgdmFyIHJlc3BvbnNlTWV0aG9kcyA9IHVuaWZ5UmVzcG9uc2VNZXRob2RzKHBhY2tlci5yZXNwb25zZU1ldGhvZHMpO1xuXG5cbiAgaWYob3B0aW9ucyBpbnN0YW5jZW9mIEZ1bmN0aW9uKVxuICB7XG4gICAgaWYodHJhbnNwb3J0ICE9IHVuZGVmaW5lZClcbiAgICAgIHRocm93IG5ldyBTeW50YXhFcnJvcihcIlRoZXJlIGNhbid0IGJlIHBhcmFtZXRlcnMgYWZ0ZXIgb25SZXF1ZXN0XCIpO1xuXG4gICAgb25SZXF1ZXN0ID0gb3B0aW9ucztcbiAgICB0cmFuc3BvcnQgPSB1bmRlZmluZWQ7XG4gICAgb3B0aW9ucyAgID0gdW5kZWZpbmVkO1xuICB9O1xuXG4gIGlmKG9wdGlvbnMgJiYgb3B0aW9ucy5zZW5kIGluc3RhbmNlb2YgRnVuY3Rpb24pXG4gIHtcbiAgICBpZih0cmFuc3BvcnQgJiYgISh0cmFuc3BvcnQgaW5zdGFuY2VvZiBGdW5jdGlvbikpXG4gICAgICB0aHJvdyBuZXcgU3ludGF4RXJyb3IoXCJPbmx5IGEgZnVuY3Rpb24gY2FuIGJlIGFmdGVyIHRyYW5zcG9ydFwiKTtcblxuICAgIG9uUmVxdWVzdCA9IHRyYW5zcG9ydDtcbiAgICB0cmFuc3BvcnQgPSBvcHRpb25zO1xuICAgIG9wdGlvbnMgICA9IHVuZGVmaW5lZDtcbiAgfTtcblxuICBpZih0cmFuc3BvcnQgaW5zdGFuY2VvZiBGdW5jdGlvbilcbiAge1xuICAgIGlmKG9uUmVxdWVzdCAhPSB1bmRlZmluZWQpXG4gICAgICB0aHJvdyBuZXcgU3ludGF4RXJyb3IoXCJUaGVyZSBjYW4ndCBiZSBwYXJhbWV0ZXJzIGFmdGVyIG9uUmVxdWVzdFwiKTtcblxuICAgIG9uUmVxdWVzdCA9IHRyYW5zcG9ydDtcbiAgICB0cmFuc3BvcnQgPSB1bmRlZmluZWQ7XG4gIH07XG5cbiAgaWYodHJhbnNwb3J0ICYmIHRyYW5zcG9ydC5zZW5kIGluc3RhbmNlb2YgRnVuY3Rpb24pXG4gICAgaWYob25SZXF1ZXN0ICYmICEob25SZXF1ZXN0IGluc3RhbmNlb2YgRnVuY3Rpb24pKVxuICAgICAgdGhyb3cgbmV3IFN5bnRheEVycm9yKFwiT25seSBhIGZ1bmN0aW9uIGNhbiBiZSBhZnRlciB0cmFuc3BvcnRcIik7XG5cbiAgb3B0aW9ucyA9IG9wdGlvbnMgfHwge307XG5cblxuICBFdmVudEVtaXR0ZXIuY2FsbCh0aGlzKTtcblxuICBpZihvblJlcXVlc3QpXG4gICAgdGhpcy5vbigncmVxdWVzdCcsIG9uUmVxdWVzdCk7XG5cblxuICBpZihkZWZpbmVQcm9wZXJ0eV9JRTgpXG4gICAgdGhpcy5wZWVySUQgPSBvcHRpb25zLnBlZXJJRFxuICBlbHNlXG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRoaXMsICdwZWVySUQnLCB7dmFsdWU6IG9wdGlvbnMucGVlcklEfSk7XG5cbiAgdmFyIG1heF9yZXRyaWVzID0gb3B0aW9ucy5tYXhfcmV0cmllcyB8fCAwO1xuXG5cbiAgZnVuY3Rpb24gdHJhbnNwb3J0TWVzc2FnZShldmVudClcbiAge1xuICAgIHNlbGYuZGVjb2RlKGV2ZW50LmRhdGEgfHwgZXZlbnQpO1xuICB9O1xuXG4gIHRoaXMuZ2V0VHJhbnNwb3J0ID0gZnVuY3Rpb24oKVxuICB7XG4gICAgcmV0dXJuIHRyYW5zcG9ydDtcbiAgfVxuICB0aGlzLnNldFRyYW5zcG9ydCA9IGZ1bmN0aW9uKHZhbHVlKVxuICB7XG4gICAgLy8gUmVtb3ZlIGxpc3RlbmVyIGZyb20gb2xkIHRyYW5zcG9ydFxuICAgIGlmKHRyYW5zcG9ydClcbiAgICB7XG4gICAgICAvLyBXM0MgdHJhbnNwb3J0c1xuICAgICAgaWYodHJhbnNwb3J0LnJlbW92ZUV2ZW50TGlzdGVuZXIpXG4gICAgICAgIHRyYW5zcG9ydC5yZW1vdmVFdmVudExpc3RlbmVyKCdtZXNzYWdlJywgdHJhbnNwb3J0TWVzc2FnZSk7XG5cbiAgICAgIC8vIE5vZGUuanMgU3RyZWFtcyBBUElcbiAgICAgIGVsc2UgaWYodHJhbnNwb3J0LnJlbW92ZUxpc3RlbmVyKVxuICAgICAgICB0cmFuc3BvcnQucmVtb3ZlTGlzdGVuZXIoJ2RhdGEnLCB0cmFuc3BvcnRNZXNzYWdlKTtcbiAgICB9O1xuXG4gICAgLy8gU2V0IGxpc3RlbmVyIG9uIG5ldyB0cmFuc3BvcnRcbiAgICBpZih2YWx1ZSlcbiAgICB7XG4gICAgICAvLyBXM0MgdHJhbnNwb3J0c1xuICAgICAgaWYodmFsdWUuYWRkRXZlbnRMaXN0ZW5lcilcbiAgICAgICAgdmFsdWUuYWRkRXZlbnRMaXN0ZW5lcignbWVzc2FnZScsIHRyYW5zcG9ydE1lc3NhZ2UpO1xuXG4gICAgICAvLyBOb2RlLmpzIFN0cmVhbXMgQVBJXG4gICAgICBlbHNlIGlmKHZhbHVlLmFkZExpc3RlbmVyKVxuICAgICAgICB2YWx1ZS5hZGRMaXN0ZW5lcignZGF0YScsIHRyYW5zcG9ydE1lc3NhZ2UpO1xuICAgIH07XG5cbiAgICB0cmFuc3BvcnQgPSB1bmlmeVRyYW5zcG9ydCh2YWx1ZSk7XG4gIH1cblxuICBpZighZGVmaW5lUHJvcGVydHlfSUU4KVxuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0aGlzLCAndHJhbnNwb3J0JyxcbiAgICB7XG4gICAgICBnZXQ6IHRoaXMuZ2V0VHJhbnNwb3J0LmJpbmQodGhpcyksXG4gICAgICBzZXQ6IHRoaXMuc2V0VHJhbnNwb3J0LmJpbmQodGhpcylcbiAgICB9KVxuXG4gIHRoaXMuc2V0VHJhbnNwb3J0KHRyYW5zcG9ydCk7XG5cblxuICB2YXIgcmVxdWVzdF90aW1lb3V0ICAgICAgPSBvcHRpb25zLnJlcXVlc3RfdGltZW91dCAgICAgIHx8IEJBU0VfVElNRU9VVDtcbiAgdmFyIHBpbmdfcmVxdWVzdF90aW1lb3V0ID0gb3B0aW9ucy5waW5nX3JlcXVlc3RfdGltZW91dCB8fCByZXF1ZXN0X3RpbWVvdXQ7XG4gIHZhciByZXNwb25zZV90aW1lb3V0ICAgICA9IG9wdGlvbnMucmVzcG9uc2VfdGltZW91dCAgICAgfHwgQkFTRV9USU1FT1VUO1xuICB2YXIgZHVwbGljYXRlc190aW1lb3V0ICAgPSBvcHRpb25zLmR1cGxpY2F0ZXNfdGltZW91dCAgIHx8IEJBU0VfVElNRU9VVDtcblxuXG4gIHZhciByZXF1ZXN0SUQgPSAwO1xuXG4gIHZhciByZXF1ZXN0cyAgPSBuZXcgTWFwcGVyKCk7XG4gIHZhciByZXNwb25zZXMgPSBuZXcgTWFwcGVyKCk7XG4gIHZhciBwcm9jZXNzZWRSZXNwb25zZXMgPSBuZXcgTWFwcGVyKCk7XG5cbiAgdmFyIG1lc3NhZ2UyS2V5ID0ge307XG5cblxuICAvKipcbiAgICogU3RvcmUgdGhlIHJlc3BvbnNlIHRvIHByZXZlbnQgdG8gcHJvY2VzcyBkdXBsaWNhdGUgcmVxdWVzdCBsYXRlclxuICAgKi9cbiAgZnVuY3Rpb24gc3RvcmVSZXNwb25zZShtZXNzYWdlLCBpZCwgZGVzdClcbiAge1xuICAgIHZhciByZXNwb25zZSA9XG4gICAge1xuICAgICAgbWVzc2FnZTogbWVzc2FnZSxcbiAgICAgIC8qKiBUaW1lb3V0IHRvIGF1dG8tY2xlYW4gb2xkIHJlc3BvbnNlcyAqL1xuICAgICAgdGltZW91dDogc2V0VGltZW91dChmdW5jdGlvbigpXG4gICAgICB7XG4gICAgICAgIHJlc3BvbnNlcy5yZW1vdmUoaWQsIGRlc3QpO1xuICAgICAgfSxcbiAgICAgIHJlc3BvbnNlX3RpbWVvdXQpXG4gICAgfTtcblxuICAgIHJlc3BvbnNlcy5zZXQocmVzcG9uc2UsIGlkLCBkZXN0KTtcbiAgfTtcblxuICAvKipcbiAgICogU3RvcmUgdGhlIHJlc3BvbnNlIHRvIGlnbm9yZSBkdXBsaWNhdGVkIG1lc3NhZ2VzIGxhdGVyXG4gICAqL1xuICBmdW5jdGlvbiBzdG9yZVByb2Nlc3NlZFJlc3BvbnNlKGFjaywgZnJvbSlcbiAge1xuICAgIHZhciB0aW1lb3V0ID0gc2V0VGltZW91dChmdW5jdGlvbigpXG4gICAge1xuICAgICAgcHJvY2Vzc2VkUmVzcG9uc2VzLnJlbW92ZShhY2ssIGZyb20pO1xuICAgIH0sXG4gICAgZHVwbGljYXRlc190aW1lb3V0KTtcblxuICAgIHByb2Nlc3NlZFJlc3BvbnNlcy5zZXQodGltZW91dCwgYWNrLCBmcm9tKTtcbiAgfTtcblxuXG4gIC8qKlxuICAgKiBSZXByZXNlbnRhdGlvbiBvZiBhIFJQQyByZXF1ZXN0XG4gICAqXG4gICAqIEBjbGFzc1xuICAgKiBAZXh0ZW5kcyBScGNOb3RpZmljYXRpb25cbiAgICpcbiAgICogQGNvbnN0cnVjdG9yXG4gICAqXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBtZXRob2QgLW1ldGhvZCBvZiB0aGUgbm90aWZpY2F0aW9uXG4gICAqIEBwYXJhbSBwYXJhbXMgLSBwYXJhbWV0ZXJzIG9mIHRoZSBub3RpZmljYXRpb25cbiAgICogQHBhcmFtIHtJbnRlZ2VyfSBpZCAtIGlkZW50aWZpZXIgb2YgdGhlIHJlcXVlc3RcbiAgICogQHBhcmFtIFtmcm9tXSAtIHNvdXJjZSBvZiB0aGUgbm90aWZpY2F0aW9uXG4gICAqL1xuICBmdW5jdGlvbiBScGNSZXF1ZXN0KG1ldGhvZCwgcGFyYW1zLCBpZCwgZnJvbSwgdHJhbnNwb3J0KVxuICB7XG4gICAgUnBjTm90aWZpY2F0aW9uLmNhbGwodGhpcywgbWV0aG9kLCBwYXJhbXMpO1xuXG4gICAgdGhpcy5nZXRUcmFuc3BvcnQgPSBmdW5jdGlvbigpXG4gICAge1xuICAgICAgcmV0dXJuIHRyYW5zcG9ydDtcbiAgICB9XG4gICAgdGhpcy5zZXRUcmFuc3BvcnQgPSBmdW5jdGlvbih2YWx1ZSlcbiAgICB7XG4gICAgICB0cmFuc3BvcnQgPSB1bmlmeVRyYW5zcG9ydCh2YWx1ZSk7XG4gICAgfVxuXG4gICAgaWYoIWRlZmluZVByb3BlcnR5X0lFOClcbiAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0aGlzLCAndHJhbnNwb3J0JyxcbiAgICAgIHtcbiAgICAgICAgZ2V0OiB0aGlzLmdldFRyYW5zcG9ydC5iaW5kKHRoaXMpLFxuICAgICAgICBzZXQ6IHRoaXMuc2V0VHJhbnNwb3J0LmJpbmQodGhpcylcbiAgICAgIH0pXG5cbiAgICB2YXIgcmVzcG9uc2UgPSByZXNwb25zZXMuZ2V0KGlkLCBmcm9tKTtcblxuICAgIC8qKlxuICAgICAqIEBjb25zdGFudCB7Qm9vbGVhbn0gZHVwbGljYXRlZFxuICAgICAqL1xuICAgIGlmKCEodHJhbnNwb3J0IHx8IHNlbGYuZ2V0VHJhbnNwb3J0KCkpKVxuICAgIHtcbiAgICAgIGlmKGRlZmluZVByb3BlcnR5X0lFOClcbiAgICAgICAgdGhpcy5kdXBsaWNhdGVkID0gQm9vbGVhbihyZXNwb25zZSlcbiAgICAgIGVsc2VcbiAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRoaXMsICdkdXBsaWNhdGVkJyxcbiAgICAgICAge1xuICAgICAgICAgIHZhbHVlOiBCb29sZWFuKHJlc3BvbnNlKVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICB2YXIgcmVzcG9uc2VNZXRob2QgPSByZXNwb25zZU1ldGhvZHNbbWV0aG9kXTtcblxuICAgIHRoaXMucGFjayA9IHBhY2tlci5wYWNrLmJpbmQocGFja2VyLCB0aGlzLCBpZClcblxuICAgIC8qKlxuICAgICAqIEdlbmVyYXRlIGEgcmVzcG9uc2UgdG8gdGhpcyByZXF1ZXN0XG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0Vycm9yfSBbZXJyb3JdXG4gICAgICogQHBhcmFtIHsqfSBbcmVzdWx0XVxuICAgICAqXG4gICAgICogQHJldHVybnMge3N0cmluZ31cbiAgICAgKi9cbiAgICB0aGlzLnJlcGx5ID0gZnVuY3Rpb24oZXJyb3IsIHJlc3VsdCwgdHJhbnNwb3J0KVxuICAgIHtcbiAgICAgIC8vIEZpeCBvcHRpb25hbCBwYXJhbWV0ZXJzXG4gICAgICBpZihlcnJvciBpbnN0YW5jZW9mIEZ1bmN0aW9uIHx8IGVycm9yICYmIGVycm9yLnNlbmQgaW5zdGFuY2VvZiBGdW5jdGlvbilcbiAgICAgIHtcbiAgICAgICAgaWYocmVzdWx0ICE9IHVuZGVmaW5lZClcbiAgICAgICAgICB0aHJvdyBuZXcgU3ludGF4RXJyb3IoXCJUaGVyZSBjYW4ndCBiZSBwYXJhbWV0ZXJzIGFmdGVyIGNhbGxiYWNrXCIpO1xuXG4gICAgICAgIHRyYW5zcG9ydCA9IGVycm9yO1xuICAgICAgICByZXN1bHQgPSBudWxsO1xuICAgICAgICBlcnJvciA9IHVuZGVmaW5lZDtcbiAgICAgIH1cblxuICAgICAgZWxzZSBpZihyZXN1bHQgaW5zdGFuY2VvZiBGdW5jdGlvblxuICAgICAgfHwgcmVzdWx0ICYmIHJlc3VsdC5zZW5kIGluc3RhbmNlb2YgRnVuY3Rpb24pXG4gICAgICB7XG4gICAgICAgIGlmKHRyYW5zcG9ydCAhPSB1bmRlZmluZWQpXG4gICAgICAgICAgdGhyb3cgbmV3IFN5bnRheEVycm9yKFwiVGhlcmUgY2FuJ3QgYmUgcGFyYW1ldGVycyBhZnRlciBjYWxsYmFja1wiKTtcblxuICAgICAgICB0cmFuc3BvcnQgPSByZXN1bHQ7XG4gICAgICAgIHJlc3VsdCA9IG51bGw7XG4gICAgICB9O1xuXG4gICAgICB0cmFuc3BvcnQgPSB1bmlmeVRyYW5zcG9ydCh0cmFuc3BvcnQpO1xuXG4gICAgICAvLyBEdXBsaWNhdGVkIHJlcXVlc3QsIHJlbW92ZSBvbGQgcmVzcG9uc2UgdGltZW91dFxuICAgICAgaWYocmVzcG9uc2UpXG4gICAgICAgIGNsZWFyVGltZW91dChyZXNwb25zZS50aW1lb3V0KTtcblxuICAgICAgaWYoZnJvbSAhPSB1bmRlZmluZWQpXG4gICAgICB7XG4gICAgICAgIGlmKGVycm9yKVxuICAgICAgICAgIGVycm9yLmRlc3QgPSBmcm9tO1xuXG4gICAgICAgIGlmKHJlc3VsdClcbiAgICAgICAgICByZXN1bHQuZGVzdCA9IGZyb207XG4gICAgICB9O1xuXG4gICAgICB2YXIgbWVzc2FnZTtcblxuICAgICAgLy8gTmV3IHJlcXVlc3Qgb3Igb3ZlcnJpZGVuIG9uZSwgY3JlYXRlIG5ldyByZXNwb25zZSB3aXRoIHByb3ZpZGVkIGRhdGFcbiAgICAgIGlmKGVycm9yIHx8IHJlc3VsdCAhPSB1bmRlZmluZWQpXG4gICAgICB7XG4gICAgICAgIGlmKHNlbGYucGVlcklEICE9IHVuZGVmaW5lZClcbiAgICAgICAge1xuICAgICAgICAgIGlmKGVycm9yKVxuICAgICAgICAgICAgZXJyb3IuZnJvbSA9IHNlbGYucGVlcklEO1xuICAgICAgICAgIGVsc2VcbiAgICAgICAgICAgIHJlc3VsdC5mcm9tID0gc2VsZi5wZWVySUQ7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBQcm90b2NvbCBpbmRpY2F0ZXMgdGhhdCByZXNwb25zZXMgaGFzIG93biByZXF1ZXN0IG1ldGhvZHNcbiAgICAgICAgaWYocmVzcG9uc2VNZXRob2QpXG4gICAgICAgIHtcbiAgICAgICAgICBpZihyZXNwb25zZU1ldGhvZC5lcnJvciA9PSB1bmRlZmluZWQgJiYgZXJyb3IpXG4gICAgICAgICAgICBtZXNzYWdlID1cbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgZXJyb3I6IGVycm9yXG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgZWxzZVxuICAgICAgICAgIHtcbiAgICAgICAgICAgIHZhciBtZXRob2QgPSBlcnJvclxuICAgICAgICAgICAgICAgICAgICAgICA/IHJlc3BvbnNlTWV0aG9kLmVycm9yXG4gICAgICAgICAgICAgICAgICAgICAgIDogcmVzcG9uc2VNZXRob2QucmVzcG9uc2U7XG5cbiAgICAgICAgICAgIG1lc3NhZ2UgPVxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICBtZXRob2Q6IG1ldGhvZCxcbiAgICAgICAgICAgICAgcGFyYW1zOiBlcnJvciB8fCByZXN1bHRcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGVsc2VcbiAgICAgICAgICBtZXNzYWdlID1cbiAgICAgICAgICB7XG4gICAgICAgICAgICBlcnJvcjogIGVycm9yLFxuICAgICAgICAgICAgcmVzdWx0OiByZXN1bHRcbiAgICAgICAgICB9O1xuXG4gICAgICAgIG1lc3NhZ2UgPSBwYWNrZXIucGFjayhtZXNzYWdlLCBpZCk7XG4gICAgICB9XG5cbiAgICAgIC8vIER1cGxpY2F0ZSAmIG5vdC1vdmVycmlkZW4gcmVxdWVzdCwgcmUtc2VuZCBvbGQgcmVzcG9uc2VcbiAgICAgIGVsc2UgaWYocmVzcG9uc2UpXG4gICAgICAgIG1lc3NhZ2UgPSByZXNwb25zZS5tZXNzYWdlO1xuXG4gICAgICAvLyBOZXcgZW1wdHkgcmVwbHksIHJlc3BvbnNlIG51bGwgdmFsdWVcbiAgICAgIGVsc2VcbiAgICAgICAgbWVzc2FnZSA9IHBhY2tlci5wYWNrKHtyZXN1bHQ6IG51bGx9LCBpZCk7XG5cbiAgICAgIC8vIFN0b3JlIHRoZSByZXNwb25zZSB0byBwcmV2ZW50IHRvIHByb2Nlc3MgYSBkdXBsaWNhdGVkIHJlcXVlc3QgbGF0ZXJcbiAgICAgIHN0b3JlUmVzcG9uc2UobWVzc2FnZSwgaWQsIGZyb20pO1xuXG4gICAgICAvLyBSZXR1cm4gdGhlIHN0b3JlZCByZXNwb25zZSBzbyBpdCBjYW4gYmUgZGlyZWN0bHkgc2VuZCBiYWNrXG4gICAgICB0cmFuc3BvcnQgPSB0cmFuc3BvcnQgfHwgdGhpcy5nZXRUcmFuc3BvcnQoKSB8fCBzZWxmLmdldFRyYW5zcG9ydCgpO1xuXG4gICAgICBpZih0cmFuc3BvcnQpXG4gICAgICAgIHJldHVybiB0cmFuc3BvcnQuc2VuZChtZXNzYWdlKTtcblxuICAgICAgcmV0dXJuIG1lc3NhZ2U7XG4gICAgfVxuICB9O1xuICBpbmhlcml0cyhScGNSZXF1ZXN0LCBScGNOb3RpZmljYXRpb24pO1xuXG5cbiAgZnVuY3Rpb24gY2FuY2VsKG1lc3NhZ2UpXG4gIHtcbiAgICB2YXIga2V5ID0gbWVzc2FnZTJLZXlbbWVzc2FnZV07XG4gICAgaWYoIWtleSkgcmV0dXJuO1xuXG4gICAgZGVsZXRlIG1lc3NhZ2UyS2V5W21lc3NhZ2VdO1xuXG4gICAgdmFyIHJlcXVlc3QgPSByZXF1ZXN0cy5wb3Aoa2V5LmlkLCBrZXkuZGVzdCk7XG4gICAgaWYoIXJlcXVlc3QpIHJldHVybjtcblxuICAgIGNsZWFyVGltZW91dChyZXF1ZXN0LnRpbWVvdXQpO1xuXG4gICAgLy8gU3RhcnQgZHVwbGljYXRlZCByZXNwb25zZXMgdGltZW91dFxuICAgIHN0b3JlUHJvY2Vzc2VkUmVzcG9uc2Uoa2V5LmlkLCBrZXkuZGVzdCk7XG4gIH07XG5cbiAgLyoqXG4gICAqIEFsbG93IHRvIGNhbmNlbCBhIHJlcXVlc3QgYW5kIGRvbid0IHdhaXQgZm9yIGEgcmVzcG9uc2VcbiAgICpcbiAgICogSWYgYG1lc3NhZ2VgIGlzIG5vdCBnaXZlbiwgY2FuY2VsIGFsbCB0aGUgcmVxdWVzdFxuICAgKi9cbiAgdGhpcy5jYW5jZWwgPSBmdW5jdGlvbihtZXNzYWdlKVxuICB7XG4gICAgaWYobWVzc2FnZSkgcmV0dXJuIGNhbmNlbChtZXNzYWdlKTtcblxuICAgIGZvcih2YXIgbWVzc2FnZSBpbiBtZXNzYWdlMktleSlcbiAgICAgIGNhbmNlbChtZXNzYWdlKTtcbiAgfTtcblxuXG4gIHRoaXMuY2xvc2UgPSBmdW5jdGlvbigpXG4gIHtcbiAgICAvLyBQcmV2ZW50IHRvIHJlY2VpdmUgbmV3IG1lc3NhZ2VzXG4gICAgdmFyIHRyYW5zcG9ydCA9IHRoaXMuZ2V0VHJhbnNwb3J0KCk7XG4gICAgaWYodHJhbnNwb3J0ICYmIHRyYW5zcG9ydC5jbG9zZSlcbiAgICAgICB0cmFuc3BvcnQuY2xvc2UoKTtcblxuICAgIC8vIFJlcXVlc3QgJiBwcm9jZXNzZWQgcmVzcG9uc2VzXG4gICAgdGhpcy5jYW5jZWwoKTtcblxuICAgIHByb2Nlc3NlZFJlc3BvbnNlcy5mb3JFYWNoKGNsZWFyVGltZW91dCk7XG5cbiAgICAvLyBSZXNwb25zZXNcbiAgICByZXNwb25zZXMuZm9yRWFjaChmdW5jdGlvbihyZXNwb25zZSlcbiAgICB7XG4gICAgICBjbGVhclRpbWVvdXQocmVzcG9uc2UudGltZW91dCk7XG4gICAgfSk7XG4gIH07XG5cblxuICAvKipcbiAgICogR2VuZXJhdGVzIGFuZCBlbmNvZGUgYSBKc29uUlBDIDIuMCBtZXNzYWdlXG4gICAqXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBtZXRob2QgLW1ldGhvZCBvZiB0aGUgbm90aWZpY2F0aW9uXG4gICAqIEBwYXJhbSBwYXJhbXMgLSBwYXJhbWV0ZXJzIG9mIHRoZSBub3RpZmljYXRpb25cbiAgICogQHBhcmFtIFtkZXN0XSAtIGRlc3RpbmF0aW9uIG9mIHRoZSBub3RpZmljYXRpb25cbiAgICogQHBhcmFtIHtvYmplY3R9IFt0cmFuc3BvcnRdIC0gdHJhbnNwb3J0IHdoZXJlIHRvIHNlbmQgdGhlIG1lc3NhZ2VcbiAgICogQHBhcmFtIFtjYWxsYmFja10gLSBmdW5jdGlvbiBjYWxsZWQgd2hlbiBhIHJlc3BvbnNlIHRvIHRoaXMgcmVxdWVzdCBpc1xuICAgKiAgIHJlY2VpdmVkLiBJZiBub3QgZGVmaW5lZCwgYSBub3RpZmljYXRpb24gd2lsbCBiZSBzZW5kIGluc3RlYWRcbiAgICpcbiAgICogQHJldHVybnMge3N0cmluZ30gQSByYXcgSnNvblJQQyAyLjAgcmVxdWVzdCBvciBub3RpZmljYXRpb24gc3RyaW5nXG4gICAqL1xuICB0aGlzLmVuY29kZSA9IGZ1bmN0aW9uKG1ldGhvZCwgcGFyYW1zLCBkZXN0LCB0cmFuc3BvcnQsIGNhbGxiYWNrKVxuICB7XG4gICAgLy8gRml4IG9wdGlvbmFsIHBhcmFtZXRlcnNcbiAgICBpZihwYXJhbXMgaW5zdGFuY2VvZiBGdW5jdGlvbilcbiAgICB7XG4gICAgICBpZihkZXN0ICE9IHVuZGVmaW5lZClcbiAgICAgICAgdGhyb3cgbmV3IFN5bnRheEVycm9yKFwiVGhlcmUgY2FuJ3QgYmUgcGFyYW1ldGVycyBhZnRlciBjYWxsYmFja1wiKTtcblxuICAgICAgY2FsbGJhY2sgID0gcGFyYW1zO1xuICAgICAgdHJhbnNwb3J0ID0gdW5kZWZpbmVkO1xuICAgICAgZGVzdCAgICAgID0gdW5kZWZpbmVkO1xuICAgICAgcGFyYW1zICAgID0gdW5kZWZpbmVkO1xuICAgIH1cblxuICAgIGVsc2UgaWYoZGVzdCBpbnN0YW5jZW9mIEZ1bmN0aW9uKVxuICAgIHtcbiAgICAgIGlmKHRyYW5zcG9ydCAhPSB1bmRlZmluZWQpXG4gICAgICAgIHRocm93IG5ldyBTeW50YXhFcnJvcihcIlRoZXJlIGNhbid0IGJlIHBhcmFtZXRlcnMgYWZ0ZXIgY2FsbGJhY2tcIik7XG5cbiAgICAgIGNhbGxiYWNrICA9IGRlc3Q7XG4gICAgICB0cmFuc3BvcnQgPSB1bmRlZmluZWQ7XG4gICAgICBkZXN0ICAgICAgPSB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgZWxzZSBpZih0cmFuc3BvcnQgaW5zdGFuY2VvZiBGdW5jdGlvbilcbiAgICB7XG4gICAgICBpZihjYWxsYmFjayAhPSB1bmRlZmluZWQpXG4gICAgICAgIHRocm93IG5ldyBTeW50YXhFcnJvcihcIlRoZXJlIGNhbid0IGJlIHBhcmFtZXRlcnMgYWZ0ZXIgY2FsbGJhY2tcIik7XG5cbiAgICAgIGNhbGxiYWNrICA9IHRyYW5zcG9ydDtcbiAgICAgIHRyYW5zcG9ydCA9IHVuZGVmaW5lZDtcbiAgICB9O1xuXG4gICAgaWYoc2VsZi5wZWVySUQgIT0gdW5kZWZpbmVkKVxuICAgIHtcbiAgICAgIHBhcmFtcyA9IHBhcmFtcyB8fCB7fTtcblxuICAgICAgcGFyYW1zLmZyb20gPSBzZWxmLnBlZXJJRDtcbiAgICB9O1xuXG4gICAgaWYoZGVzdCAhPSB1bmRlZmluZWQpXG4gICAge1xuICAgICAgcGFyYW1zID0gcGFyYW1zIHx8IHt9O1xuXG4gICAgICBwYXJhbXMuZGVzdCA9IGRlc3Q7XG4gICAgfTtcblxuICAgIC8vIEVuY29kZSBtZXNzYWdlXG4gICAgdmFyIG1lc3NhZ2UgPVxuICAgIHtcbiAgICAgIG1ldGhvZDogbWV0aG9kLFxuICAgICAgcGFyYW1zOiBwYXJhbXNcbiAgICB9O1xuXG4gICAgaWYoY2FsbGJhY2spXG4gICAge1xuICAgICAgdmFyIGlkID0gcmVxdWVzdElEKys7XG4gICAgICB2YXIgcmV0cmllZCA9IDA7XG5cbiAgICAgIG1lc3NhZ2UgPSBwYWNrZXIucGFjayhtZXNzYWdlLCBpZCk7XG5cbiAgICAgIGZ1bmN0aW9uIGRpc3BhdGNoQ2FsbGJhY2soZXJyb3IsIHJlc3VsdClcbiAgICAgIHtcbiAgICAgICAgc2VsZi5jYW5jZWwobWVzc2FnZSk7XG5cbiAgICAgICAgY2FsbGJhY2soZXJyb3IsIHJlc3VsdCk7XG4gICAgICB9O1xuXG4gICAgICB2YXIgcmVxdWVzdCA9XG4gICAgICB7XG4gICAgICAgIG1lc3NhZ2U6ICAgICAgICAgbWVzc2FnZSxcbiAgICAgICAgY2FsbGJhY2s6ICAgICAgICBkaXNwYXRjaENhbGxiYWNrLFxuICAgICAgICByZXNwb25zZU1ldGhvZHM6IHJlc3BvbnNlTWV0aG9kc1ttZXRob2RdIHx8IHt9XG4gICAgICB9O1xuXG4gICAgICB2YXIgZW5jb2RlX3RyYW5zcG9ydCA9IHVuaWZ5VHJhbnNwb3J0KHRyYW5zcG9ydCk7XG5cbiAgICAgIGZ1bmN0aW9uIHNlbmRSZXF1ZXN0KHRyYW5zcG9ydClcbiAgICAgIHtcbiAgICAgICAgdmFyIHJ0ID0gKG1ldGhvZCA9PT0gJ3BpbmcnID8gcGluZ19yZXF1ZXN0X3RpbWVvdXQgOiByZXF1ZXN0X3RpbWVvdXQpO1xuICAgICAgICByZXF1ZXN0LnRpbWVvdXQgPSBzZXRUaW1lb3V0KHRpbWVvdXQsIHJ0Kk1hdGgucG93KDIsIHJldHJpZWQrKykpO1xuICAgICAgICBtZXNzYWdlMktleVttZXNzYWdlXSA9IHtpZDogaWQsIGRlc3Q6IGRlc3R9O1xuICAgICAgICByZXF1ZXN0cy5zZXQocmVxdWVzdCwgaWQsIGRlc3QpO1xuXG4gICAgICAgIHRyYW5zcG9ydCA9IHRyYW5zcG9ydCB8fCBlbmNvZGVfdHJhbnNwb3J0IHx8IHNlbGYuZ2V0VHJhbnNwb3J0KCk7XG4gICAgICAgIGlmKHRyYW5zcG9ydClcbiAgICAgICAgICByZXR1cm4gdHJhbnNwb3J0LnNlbmQobWVzc2FnZSk7XG5cbiAgICAgICAgcmV0dXJuIG1lc3NhZ2U7XG4gICAgICB9O1xuXG4gICAgICBmdW5jdGlvbiByZXRyeSh0cmFuc3BvcnQpXG4gICAgICB7XG4gICAgICAgIHRyYW5zcG9ydCA9IHVuaWZ5VHJhbnNwb3J0KHRyYW5zcG9ydCk7XG5cbiAgICAgICAgY29uc29sZS53YXJuKHJldHJpZWQrJyByZXRyeSBmb3IgcmVxdWVzdCBtZXNzYWdlOicsbWVzc2FnZSk7XG5cbiAgICAgICAgdmFyIHRpbWVvdXQgPSBwcm9jZXNzZWRSZXNwb25zZXMucG9wKGlkLCBkZXN0KTtcbiAgICAgICAgY2xlYXJUaW1lb3V0KHRpbWVvdXQpO1xuXG4gICAgICAgIHJldHVybiBzZW5kUmVxdWVzdCh0cmFuc3BvcnQpO1xuICAgICAgfTtcblxuICAgICAgZnVuY3Rpb24gdGltZW91dCgpXG4gICAgICB7XG4gICAgICAgIGlmKHJldHJpZWQgPCBtYXhfcmV0cmllcylcbiAgICAgICAgICByZXR1cm4gcmV0cnkodHJhbnNwb3J0KTtcblxuICAgICAgICB2YXIgZXJyb3IgPSBuZXcgRXJyb3IoJ1JlcXVlc3QgaGFzIHRpbWVkIG91dCcpO1xuICAgICAgICAgICAgZXJyb3IucmVxdWVzdCA9IG1lc3NhZ2U7XG5cbiAgICAgICAgZXJyb3IucmV0cnkgPSByZXRyeTtcblxuICAgICAgICBkaXNwYXRjaENhbGxiYWNrKGVycm9yKVxuICAgICAgfTtcblxuICAgICAgcmV0dXJuIHNlbmRSZXF1ZXN0KHRyYW5zcG9ydCk7XG4gICAgfTtcblxuICAgIC8vIFJldHVybiB0aGUgcGFja2VkIG1lc3NhZ2VcbiAgICBtZXNzYWdlID0gcGFja2VyLnBhY2sobWVzc2FnZSk7XG5cbiAgICB0cmFuc3BvcnQgPSB0cmFuc3BvcnQgfHwgdGhpcy5nZXRUcmFuc3BvcnQoKTtcbiAgICBpZih0cmFuc3BvcnQpXG4gICAgICByZXR1cm4gdHJhbnNwb3J0LnNlbmQobWVzc2FnZSk7XG5cbiAgICByZXR1cm4gbWVzc2FnZTtcbiAgfTtcblxuICAvKipcbiAgICogRGVjb2RlIGFuZCBwcm9jZXNzIGEgSnNvblJQQyAyLjAgbWVzc2FnZVxuICAgKlxuICAgKiBAcGFyYW0ge3N0cmluZ30gbWVzc2FnZSAtIHN0cmluZyB3aXRoIHRoZSBjb250ZW50IG9mIHRoZSBtZXNzYWdlXG4gICAqXG4gICAqIEByZXR1cm5zIHtScGNOb3RpZmljYXRpb258UnBjUmVxdWVzdHx1bmRlZmluZWR9IC0gdGhlIHJlcHJlc2VudGF0aW9uIG9mIHRoZVxuICAgKiAgIG5vdGlmaWNhdGlvbiBvciB0aGUgcmVxdWVzdC4gSWYgYSByZXNwb25zZSB3YXMgcHJvY2Vzc2VkLCBpdCB3aWxsIHJldHVyblxuICAgKiAgIGB1bmRlZmluZWRgIHRvIG5vdGlmeSB0aGF0IGl0IHdhcyBwcm9jZXNzZWRcbiAgICpcbiAgICogQHRocm93cyB7VHlwZUVycm9yfSAtIE1lc3NhZ2UgaXMgbm90IGRlZmluZWRcbiAgICovXG4gIHRoaXMuZGVjb2RlID0gZnVuY3Rpb24obWVzc2FnZSwgdHJhbnNwb3J0KVxuICB7XG4gICAgaWYoIW1lc3NhZ2UpXG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiTWVzc2FnZSBpcyBub3QgZGVmaW5lZFwiKTtcblxuICAgIHRyeVxuICAgIHtcbiAgICAgIG1lc3NhZ2UgPSBwYWNrZXIudW5wYWNrKG1lc3NhZ2UpO1xuICAgIH1cbiAgICBjYXRjaChlKVxuICAgIHtcbiAgICAgIC8vIElnbm9yZSBpbnZhbGlkIG1lc3NhZ2VzXG4gICAgICByZXR1cm4gY29uc29sZS5kZWJ1ZyhlLCBtZXNzYWdlKTtcbiAgICB9O1xuXG4gICAgdmFyIGlkICAgICA9IG1lc3NhZ2UuaWQ7XG4gICAgdmFyIGFjayAgICA9IG1lc3NhZ2UuYWNrO1xuICAgIHZhciBtZXRob2QgPSBtZXNzYWdlLm1ldGhvZDtcbiAgICB2YXIgcGFyYW1zID0gbWVzc2FnZS5wYXJhbXMgfHwge307XG5cbiAgICB2YXIgZnJvbSA9IHBhcmFtcy5mcm9tO1xuICAgIHZhciBkZXN0ID0gcGFyYW1zLmRlc3Q7XG5cbiAgICAvLyBJZ25vcmUgbWVzc2FnZXMgc2VuZCBieSB1c1xuICAgIGlmKHNlbGYucGVlcklEICE9IHVuZGVmaW5lZCAmJiBmcm9tID09IHNlbGYucGVlcklEKSByZXR1cm47XG5cbiAgICAvLyBOb3RpZmljYXRpb25cbiAgICBpZihpZCA9PSB1bmRlZmluZWQgJiYgYWNrID09IHVuZGVmaW5lZClcbiAgICB7XG4gICAgICB2YXIgbm90aWZpY2F0aW9uID0gbmV3IFJwY05vdGlmaWNhdGlvbihtZXRob2QsIHBhcmFtcyk7XG5cbiAgICAgIGlmKHNlbGYuZW1pdCgncmVxdWVzdCcsIG5vdGlmaWNhdGlvbikpIHJldHVybjtcbiAgICAgIHJldHVybiBub3RpZmljYXRpb247XG4gICAgfTtcblxuXG4gICAgZnVuY3Rpb24gcHJvY2Vzc1JlcXVlc3QoKVxuICAgIHtcbiAgICAgIC8vIElmIHdlIGhhdmUgYSB0cmFuc3BvcnQgYW5kIGl0J3MgYSBkdXBsaWNhdGVkIHJlcXVlc3QsIHJlcGx5IGlubWVkaWF0bHlcbiAgICAgIHRyYW5zcG9ydCA9IHVuaWZ5VHJhbnNwb3J0KHRyYW5zcG9ydCkgfHwgc2VsZi5nZXRUcmFuc3BvcnQoKTtcbiAgICAgIGlmKHRyYW5zcG9ydClcbiAgICAgIHtcbiAgICAgICAgdmFyIHJlc3BvbnNlID0gcmVzcG9uc2VzLmdldChpZCwgZnJvbSk7XG4gICAgICAgIGlmKHJlc3BvbnNlKVxuICAgICAgICAgIHJldHVybiB0cmFuc3BvcnQuc2VuZChyZXNwb25zZS5tZXNzYWdlKTtcbiAgICAgIH07XG5cbiAgICAgIHZhciBpZEFjayA9IChpZCAhPSB1bmRlZmluZWQpID8gaWQgOiBhY2s7XG4gICAgICB2YXIgcmVxdWVzdCA9IG5ldyBScGNSZXF1ZXN0KG1ldGhvZCwgcGFyYW1zLCBpZEFjaywgZnJvbSwgdHJhbnNwb3J0KTtcblxuICAgICAgaWYoc2VsZi5lbWl0KCdyZXF1ZXN0JywgcmVxdWVzdCkpIHJldHVybjtcbiAgICAgIHJldHVybiByZXF1ZXN0O1xuICAgIH07XG5cbiAgICBmdW5jdGlvbiBwcm9jZXNzUmVzcG9uc2UocmVxdWVzdCwgZXJyb3IsIHJlc3VsdClcbiAgICB7XG4gICAgICByZXF1ZXN0LmNhbGxiYWNrKGVycm9yLCByZXN1bHQpO1xuICAgIH07XG5cbiAgICBmdW5jdGlvbiBkdXBsaWNhdGVkUmVzcG9uc2UodGltZW91dClcbiAgICB7XG4gICAgICBjb25zb2xlLndhcm4oXCJSZXNwb25zZSBhbHJlYWR5IHByb2Nlc3NlZFwiLCBtZXNzYWdlKTtcblxuICAgICAgLy8gVXBkYXRlIGR1cGxpY2F0ZWQgcmVzcG9uc2VzIHRpbWVvdXRcbiAgICAgIGNsZWFyVGltZW91dCh0aW1lb3V0KTtcbiAgICAgIHN0b3JlUHJvY2Vzc2VkUmVzcG9uc2UoYWNrLCBmcm9tKTtcbiAgICB9O1xuXG5cbiAgICAvLyBSZXF1ZXN0LCBvciByZXNwb25zZSB3aXRoIG93biBtZXRob2RcbiAgICBpZihtZXRob2QpXG4gICAge1xuICAgICAgLy8gQ2hlY2sgaWYgaXQncyBhIHJlc3BvbnNlIHdpdGggb3duIG1ldGhvZFxuICAgICAgaWYoZGVzdCA9PSB1bmRlZmluZWQgfHwgZGVzdCA9PSBzZWxmLnBlZXJJRClcbiAgICAgIHtcbiAgICAgICAgdmFyIHJlcXVlc3QgPSByZXF1ZXN0cy5nZXQoYWNrLCBmcm9tKTtcbiAgICAgICAgaWYocmVxdWVzdClcbiAgICAgICAge1xuICAgICAgICAgIHZhciByZXNwb25zZU1ldGhvZHMgPSByZXF1ZXN0LnJlc3BvbnNlTWV0aG9kcztcblxuICAgICAgICAgIGlmKG1ldGhvZCA9PSByZXNwb25zZU1ldGhvZHMuZXJyb3IpXG4gICAgICAgICAgICByZXR1cm4gcHJvY2Vzc1Jlc3BvbnNlKHJlcXVlc3QsIHBhcmFtcyk7XG5cbiAgICAgICAgICBpZihtZXRob2QgPT0gcmVzcG9uc2VNZXRob2RzLnJlc3BvbnNlKVxuICAgICAgICAgICAgcmV0dXJuIHByb2Nlc3NSZXNwb25zZShyZXF1ZXN0LCBudWxsLCBwYXJhbXMpO1xuXG4gICAgICAgICAgcmV0dXJuIHByb2Nlc3NSZXF1ZXN0KCk7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgcHJvY2Vzc2VkID0gcHJvY2Vzc2VkUmVzcG9uc2VzLmdldChhY2ssIGZyb20pO1xuICAgICAgICBpZihwcm9jZXNzZWQpXG4gICAgICAgICAgcmV0dXJuIGR1cGxpY2F0ZWRSZXNwb25zZShwcm9jZXNzZWQpO1xuICAgICAgfVxuXG4gICAgICAvLyBSZXF1ZXN0XG4gICAgICByZXR1cm4gcHJvY2Vzc1JlcXVlc3QoKTtcbiAgICB9O1xuXG4gICAgdmFyIGVycm9yICA9IG1lc3NhZ2UuZXJyb3I7XG4gICAgdmFyIHJlc3VsdCA9IG1lc3NhZ2UucmVzdWx0O1xuXG4gICAgLy8gSWdub3JlIHJlc3BvbnNlcyBub3Qgc2VuZCB0byB1c1xuICAgIGlmKGVycm9yICAmJiBlcnJvci5kZXN0ICAmJiBlcnJvci5kZXN0ICAhPSBzZWxmLnBlZXJJRCkgcmV0dXJuO1xuICAgIGlmKHJlc3VsdCAmJiByZXN1bHQuZGVzdCAmJiByZXN1bHQuZGVzdCAhPSBzZWxmLnBlZXJJRCkgcmV0dXJuO1xuXG4gICAgLy8gUmVzcG9uc2VcbiAgICB2YXIgcmVxdWVzdCA9IHJlcXVlc3RzLmdldChhY2ssIGZyb20pO1xuICAgIGlmKCFyZXF1ZXN0KVxuICAgIHtcbiAgICAgIHZhciBwcm9jZXNzZWQgPSBwcm9jZXNzZWRSZXNwb25zZXMuZ2V0KGFjaywgZnJvbSk7XG4gICAgICBpZihwcm9jZXNzZWQpXG4gICAgICAgIHJldHVybiBkdXBsaWNhdGVkUmVzcG9uc2UocHJvY2Vzc2VkKTtcblxuICAgICAgcmV0dXJuIGNvbnNvbGUud2FybihcIk5vIGNhbGxiYWNrIHdhcyBkZWZpbmVkIGZvciB0aGlzIG1lc3NhZ2VcIiwgbWVzc2FnZSk7XG4gICAgfTtcblxuICAgIC8vIFByb2Nlc3MgcmVzcG9uc2VcbiAgICBwcm9jZXNzUmVzcG9uc2UocmVxdWVzdCwgZXJyb3IsIHJlc3VsdCk7XG4gIH07XG59O1xuaW5oZXJpdHMoUnBjQnVpbGRlciwgRXZlbnRFbWl0dGVyKTtcblxuXG5ScGNCdWlsZGVyLlJwY05vdGlmaWNhdGlvbiA9IFJwY05vdGlmaWNhdGlvbjtcblxuXG5tb2R1bGUuZXhwb3J0cyA9IFJwY0J1aWxkZXI7XG5cbnZhciBjbGllbnRzID0gcmVxdWlyZSgnLi9jbGllbnRzJyk7XG52YXIgdHJhbnNwb3J0cyA9IHJlcXVpcmUoJy4vY2xpZW50cy90cmFuc3BvcnRzJyk7XG5cblJwY0J1aWxkZXIuY2xpZW50cyA9IGNsaWVudHM7XG5ScGNCdWlsZGVyLmNsaWVudHMudHJhbnNwb3J0cyA9IHRyYW5zcG9ydHM7XG5ScGNCdWlsZGVyLnBhY2tlcnMgPSBwYWNrZXJzO1xuIiwiLyoqXG4gKiBKc29uUlBDIDIuMCBwYWNrZXJcbiAqL1xuXG4vKipcbiAqIFBhY2sgYSBKc29uUlBDIDIuMCBtZXNzYWdlXG4gKlxuICogQHBhcmFtIHtPYmplY3R9IG1lc3NhZ2UgLSBvYmplY3QgdG8gYmUgcGFja2FnZWQuIEl0IHJlcXVpcmVzIHRvIGhhdmUgYWxsIHRoZVxuICogICBmaWVsZHMgbmVlZGVkIGJ5IHRoZSBKc29uUlBDIDIuMCBtZXNzYWdlIHRoYXQgaXQncyBnb2luZyB0byBiZSBnZW5lcmF0ZWRcbiAqXG4gKiBAcmV0dXJuIHtTdHJpbmd9IC0gdGhlIHN0cmluZ2lmaWVkIEpzb25SUEMgMi4wIG1lc3NhZ2VcbiAqL1xuZnVuY3Rpb24gcGFjayhtZXNzYWdlLCBpZClcbntcbiAgdmFyIHJlc3VsdCA9XG4gIHtcbiAgICBqc29ucnBjOiBcIjIuMFwiXG4gIH07XG5cbiAgLy8gUmVxdWVzdFxuICBpZihtZXNzYWdlLm1ldGhvZClcbiAge1xuICAgIHJlc3VsdC5tZXRob2QgPSBtZXNzYWdlLm1ldGhvZDtcblxuICAgIGlmKG1lc3NhZ2UucGFyYW1zKVxuICAgICAgcmVzdWx0LnBhcmFtcyA9IG1lc3NhZ2UucGFyYW1zO1xuXG4gICAgLy8gUmVxdWVzdCBpcyBhIG5vdGlmaWNhdGlvblxuICAgIGlmKGlkICE9IHVuZGVmaW5lZClcbiAgICAgIHJlc3VsdC5pZCA9IGlkO1xuICB9XG5cbiAgLy8gUmVzcG9uc2VcbiAgZWxzZSBpZihpZCAhPSB1bmRlZmluZWQpXG4gIHtcbiAgICBpZihtZXNzYWdlLmVycm9yKVxuICAgIHtcbiAgICAgIGlmKG1lc3NhZ2UucmVzdWx0ICE9PSB1bmRlZmluZWQpXG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJCb3RoIHJlc3VsdCBhbmQgZXJyb3IgYXJlIGRlZmluZWRcIik7XG5cbiAgICAgIHJlc3VsdC5lcnJvciA9IG1lc3NhZ2UuZXJyb3I7XG4gICAgfVxuICAgIGVsc2UgaWYobWVzc2FnZS5yZXN1bHQgIT09IHVuZGVmaW5lZClcbiAgICAgIHJlc3VsdC5yZXN1bHQgPSBtZXNzYWdlLnJlc3VsdDtcbiAgICBlbHNlXG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiTm8gcmVzdWx0IG9yIGVycm9yIGlzIGRlZmluZWRcIik7XG5cbiAgICByZXN1bHQuaWQgPSBpZDtcbiAgfTtcblxuICByZXR1cm4gSlNPTi5zdHJpbmdpZnkocmVzdWx0KTtcbn07XG5cbi8qKlxuICogVW5wYWNrIGEgSnNvblJQQyAyLjAgbWVzc2FnZVxuICpcbiAqIEBwYXJhbSB7U3RyaW5nfSBtZXNzYWdlIC0gc3RyaW5nIHdpdGggdGhlIGNvbnRlbnQgb2YgdGhlIEpzb25SUEMgMi4wIG1lc3NhZ2VcbiAqXG4gKiBAdGhyb3dzIHtUeXBlRXJyb3J9IC0gSW52YWxpZCBKc29uUlBDIHZlcnNpb25cbiAqXG4gKiBAcmV0dXJuIHtPYmplY3R9IC0gb2JqZWN0IGZpbGxlZCB3aXRoIHRoZSBKc29uUlBDIDIuMCBtZXNzYWdlIGNvbnRlbnRcbiAqL1xuZnVuY3Rpb24gdW5wYWNrKG1lc3NhZ2UpXG57XG4gIHZhciByZXN1bHQgPSBtZXNzYWdlO1xuXG4gIGlmKHR5cGVvZiBtZXNzYWdlID09PSAnc3RyaW5nJyB8fCBtZXNzYWdlIGluc3RhbmNlb2YgU3RyaW5nKSB7XG4gICAgcmVzdWx0ID0gSlNPTi5wYXJzZShtZXNzYWdlKTtcbiAgfVxuXG4gIC8vIENoZWNrIGlmIGl0J3MgYSB2YWxpZCBtZXNzYWdlXG5cbiAgdmFyIHZlcnNpb24gPSByZXN1bHQuanNvbnJwYztcbiAgaWYodmVyc2lvbiAhPT0gJzIuMCcpXG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkludmFsaWQgSnNvblJQQyB2ZXJzaW9uICdcIiArIHZlcnNpb24gKyBcIic6IFwiICsgbWVzc2FnZSk7XG5cbiAgLy8gUmVzcG9uc2VcbiAgaWYocmVzdWx0Lm1ldGhvZCA9PSB1bmRlZmluZWQpXG4gIHtcbiAgICBpZihyZXN1bHQuaWQgPT0gdW5kZWZpbmVkKVxuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkludmFsaWQgbWVzc2FnZTogXCIrbWVzc2FnZSk7XG5cbiAgICB2YXIgcmVzdWx0X2RlZmluZWQgPSByZXN1bHQucmVzdWx0ICE9PSB1bmRlZmluZWQ7XG4gICAgdmFyIGVycm9yX2RlZmluZWQgID0gcmVzdWx0LmVycm9yICAhPT0gdW5kZWZpbmVkO1xuXG4gICAgLy8gQ2hlY2sgb25seSByZXN1bHQgb3IgZXJyb3IgaXMgZGVmaW5lZCwgbm90IGJvdGggb3Igbm9uZVxuICAgIGlmKHJlc3VsdF9kZWZpbmVkICYmIGVycm9yX2RlZmluZWQpXG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQm90aCByZXN1bHQgYW5kIGVycm9yIGFyZSBkZWZpbmVkOiBcIittZXNzYWdlKTtcblxuICAgIGlmKCFyZXN1bHRfZGVmaW5lZCAmJiAhZXJyb3JfZGVmaW5lZClcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJObyByZXN1bHQgb3IgZXJyb3IgaXMgZGVmaW5lZDogXCIrbWVzc2FnZSk7XG5cbiAgICByZXN1bHQuYWNrID0gcmVzdWx0LmlkO1xuICAgIGRlbGV0ZSByZXN1bHQuaWQ7XG4gIH1cblxuICAvLyBSZXR1cm4gdW5wYWNrZWQgbWVzc2FnZVxuICByZXR1cm4gcmVzdWx0O1xufTtcblxuXG5leHBvcnRzLnBhY2sgICA9IHBhY2s7XG5leHBvcnRzLnVucGFjayA9IHVucGFjaztcbiIsImZ1bmN0aW9uIHBhY2sobWVzc2FnZSlcbntcbiAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIk5vdCB5ZXQgaW1wbGVtZW50ZWRcIik7XG59O1xuXG5mdW5jdGlvbiB1bnBhY2sobWVzc2FnZSlcbntcbiAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIk5vdCB5ZXQgaW1wbGVtZW50ZWRcIik7XG59O1xuXG5cbmV4cG9ydHMucGFjayAgID0gcGFjaztcbmV4cG9ydHMudW5wYWNrID0gdW5wYWNrO1xuIiwidmFyIEpzb25SUEMgPSByZXF1aXJlKCcuL0pzb25SUEMnKTtcbnZhciBYbWxSUEMgID0gcmVxdWlyZSgnLi9YbWxSUEMnKTtcblxuXG5leHBvcnRzLkpzb25SUEMgPSBKc29uUlBDO1xuZXhwb3J0cy5YbWxSUEMgID0gWG1sUlBDO1xuIiwiLy8gTGFzdCB0aW1lIHVwZGF0ZWQgb24gSnVuZSAwOCwgMjAxOFxuXG4vLyBMYXRlc3QgZmlsZSBjYW4gYmUgZm91bmQgaGVyZTogaHR0cHM6Ly9jZG4ud2VicnRjLWV4cGVyaW1lbnQuY29tL2dldFNjcmVlbklkLmpzXG5cbi8vIE11YXogS2hhbiAgICAgICAgIC0gd3d3Lk11YXpLaGFuLmNvbVxuLy8gTUlUIExpY2Vuc2UgICAgICAgLSB3d3cuV2ViUlRDLUV4cGVyaW1lbnQuY29tL2xpY2VuY2Vcbi8vIERvY3VtZW50YXRpb24gICAgIC0gaHR0cHM6Ly9naXRodWIuY29tL211YXota2hhbi9nZXRTY3JlZW5JZC5cblxuLy8gX19fX19fX19fX19fX19cbi8vIGdldFNjcmVlbklkLmpzXG5cbi8qXG5nZXRTY3JlZW5JZChmdW5jdGlvbiAoZXJyb3IsIHNvdXJjZUlkLCBzY3JlZW5fY29uc3RyYWludHMpIHtcbiAgICAvLyBlcnJvciAgICA9PSBudWxsIHx8ICdwZXJtaXNzaW9uLWRlbmllZCcgfHwgJ25vdC1pbnN0YWxsZWQnIHx8ICdpbnN0YWxsZWQtZGlzYWJsZWQnIHx8ICdub3QtY2hyb21lJ1xuICAgIC8vIHNvdXJjZUlkID09IG51bGwgfHwgJ3N0cmluZycgfHwgJ2ZpcmVmb3gnXG4gICAgXG4gICAgaWYobWljcm9zb2Z0RWRnZSkge1xuICAgICAgICBuYXZpZ2F0b3IuZ2V0RGlzcGxheU1lZGlhKHNjcmVlbl9jb25zdHJhaW50cykudGhlbihvblN1Y2Nlc3MsIG9uRmFpbHVyZSk7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICBuYXZpZ2F0b3IubWVkaWFEZXZpY2VzLmdldFVzZXJNZWRpYShzY3JlZW5fY29uc3RyYWludHMpLnRoZW4ob25TdWNjZXNzKWNhdGNoKG9uRmFpbHVyZSk7XG4gICAgfVxufSwgJ3Bhc3Mgc2Vjb25kIHBhcmFtZXRlciBvbmx5IGlmIHlvdSB3YW50IHN5c3RlbSBhdWRpbycpO1xuKi9cblxud2luZG93LmdldFNjcmVlbklkID0gZnVuY3Rpb24gKGNhbGxiYWNrLCBjdXN0b21fcGFyYW1ldGVyKSB7XG4gICAgaWYgKG5hdmlnYXRvci51c2VyQWdlbnQuaW5kZXhPZignRWRnZScpICE9PSAtMSAmJiAoISFuYXZpZ2F0b3IubXNTYXZlT3JPcGVuQmxvYiB8fCAhIW5hdmlnYXRvci5tc1NhdmVCbG9iKSkge1xuICAgICAgICAvLyBtaWNyb3NvZnQgZWRnZSA9PiBuYXZpZ2F0b3IuZ2V0RGlzcGxheU1lZGlhKHNjcmVlbl9jb25zdHJhaW50cykudGhlbihvblN1Y2Nlc3MsIG9uRmFpbHVyZSk7XG4gICAgICAgIGNhbGxiYWNrKHtcbiAgICAgICAgICAgIHZpZGVvOiB0cnVlXG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gZm9yIEZpcmVmb3g6XG4gICAgLy8gc291cmNlSWQgPT0gJ2ZpcmVmb3gnXG4gICAgLy8gc2NyZWVuX2NvbnN0cmFpbnRzID0gey4uLn1cbiAgICBpZiAoISFuYXZpZ2F0b3IubW96R2V0VXNlck1lZGlhKSB7XG4gICAgICAgIGNhbGxiYWNrKG51bGwsICdmaXJlZm94Jywge1xuICAgICAgICAgICAgdmlkZW86IHtcbiAgICAgICAgICAgICAgICBtb3pNZWRpYVNvdXJjZTogJ3dpbmRvdycsXG4gICAgICAgICAgICAgICAgbWVkaWFTb3VyY2U6ICd3aW5kb3cnXG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ21lc3NhZ2UnLCBvbklGcmFtZUNhbGxiYWNrKTtcblxuICAgIGZ1bmN0aW9uIG9uSUZyYW1lQ2FsbGJhY2soZXZlbnQpIHtcbiAgICAgICAgaWYgKCFldmVudC5kYXRhKSByZXR1cm47XG5cbiAgICAgICAgaWYgKGV2ZW50LmRhdGEuY2hyb21lTWVkaWFTb3VyY2VJZCkge1xuICAgICAgICAgICAgaWYgKGV2ZW50LmRhdGEuY2hyb21lTWVkaWFTb3VyY2VJZCA9PT0gJ1Blcm1pc3Npb25EZW5pZWRFcnJvcicpIHtcbiAgICAgICAgICAgICAgICBjYWxsYmFjaygncGVybWlzc2lvbi1kZW5pZWQnKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY2FsbGJhY2sobnVsbCwgZXZlbnQuZGF0YS5jaHJvbWVNZWRpYVNvdXJjZUlkLCBnZXRTY3JlZW5Db25zdHJhaW50cyhudWxsLCBldmVudC5kYXRhLmNocm9tZU1lZGlhU291cmNlSWQsIGV2ZW50LmRhdGEuY2FuUmVxdWVzdEF1ZGlvVHJhY2spKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gdGhpcyBldmVudCBsaXN0ZW5lciBpcyBubyBtb3JlIG5lZWRlZFxuICAgICAgICAgICAgd2luZG93LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ21lc3NhZ2UnLCBvbklGcmFtZUNhbGxiYWNrKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChldmVudC5kYXRhLmNocm9tZUV4dGVuc2lvblN0YXR1cykge1xuICAgICAgICAgICAgY2FsbGJhY2soZXZlbnQuZGF0YS5jaHJvbWVFeHRlbnNpb25TdGF0dXMsIG51bGwsIGdldFNjcmVlbkNvbnN0cmFpbnRzKGV2ZW50LmRhdGEuY2hyb21lRXh0ZW5zaW9uU3RhdHVzKSk7XG5cbiAgICAgICAgICAgIC8vIHRoaXMgZXZlbnQgbGlzdGVuZXIgaXMgbm8gbW9yZSBuZWVkZWRcbiAgICAgICAgICAgIHdpbmRvdy5yZW1vdmVFdmVudExpc3RlbmVyKCdtZXNzYWdlJywgb25JRnJhbWVDYWxsYmFjayk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoIWN1c3RvbV9wYXJhbWV0ZXIpIHtcbiAgICAgICAgc2V0VGltZW91dChwb3N0R2V0U291cmNlSWRNZXNzYWdlLCAxMDApO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBwb3N0R2V0U291cmNlSWRNZXNzYWdlKGN1c3RvbV9wYXJhbWV0ZXIpO1xuICAgICAgICB9LCAxMDApO1xuICAgIH1cbn07XG5cbmZ1bmN0aW9uIGdldFNjcmVlbkNvbnN0cmFpbnRzKGVycm9yLCBzb3VyY2VJZCwgY2FuUmVxdWVzdEF1ZGlvVHJhY2spIHtcbiAgICB2YXIgc2NyZWVuX2NvbnN0cmFpbnRzID0ge1xuICAgICAgICBhdWRpbzogZmFsc2UsXG4gICAgICAgIHZpZGVvOiB7XG4gICAgICAgICAgICBtYW5kYXRvcnk6IHtcbiAgICAgICAgICAgICAgICBjaHJvbWVNZWRpYVNvdXJjZTogZXJyb3IgPyAnc2NyZWVuJyA6ICdkZXNrdG9wJyxcbiAgICAgICAgICAgICAgICBtYXhXaWR0aDogd2luZG93LnNjcmVlbi53aWR0aCA+IDE5MjAgPyB3aW5kb3cuc2NyZWVuLndpZHRoIDogMTkyMCxcbiAgICAgICAgICAgICAgICBtYXhIZWlnaHQ6IHdpbmRvdy5zY3JlZW4uaGVpZ2h0ID4gMTA4MCA/IHdpbmRvdy5zY3JlZW4uaGVpZ2h0IDogMTA4MFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIG9wdGlvbmFsOiBbXVxuICAgICAgICB9XG4gICAgfTtcblxuICAgIGlmICghIWNhblJlcXVlc3RBdWRpb1RyYWNrKSB7XG4gICAgICAgIHNjcmVlbl9jb25zdHJhaW50cy5hdWRpbyA9IHtcbiAgICAgICAgICAgIG1hbmRhdG9yeToge1xuICAgICAgICAgICAgICAgIGNocm9tZU1lZGlhU291cmNlOiBlcnJvciA/ICdzY3JlZW4nIDogJ2Rlc2t0b3AnLFxuICAgICAgICAgICAgICAgIC8vIGVjaG9DYW5jZWxsYXRpb246IHRydWVcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBvcHRpb25hbDogW11cbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICBpZiAoc291cmNlSWQpIHtcbiAgICAgICAgc2NyZWVuX2NvbnN0cmFpbnRzLnZpZGVvLm1hbmRhdG9yeS5jaHJvbWVNZWRpYVNvdXJjZUlkID0gc291cmNlSWQ7XG5cbiAgICAgICAgaWYgKHNjcmVlbl9jb25zdHJhaW50cy5hdWRpbyAmJiBzY3JlZW5fY29uc3RyYWludHMuYXVkaW8ubWFuZGF0b3J5KSB7XG4gICAgICAgICAgICBzY3JlZW5fY29uc3RyYWludHMuYXVkaW8ubWFuZGF0b3J5LmNocm9tZU1lZGlhU291cmNlSWQgPSBzb3VyY2VJZDtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBzY3JlZW5fY29uc3RyYWludHM7XG59XG5cbmZ1bmN0aW9uIHBvc3RHZXRTb3VyY2VJZE1lc3NhZ2UoY3VzdG9tX3BhcmFtZXRlcikge1xuICAgIGlmICghaWZyYW1lKSB7XG4gICAgICAgIGxvYWRJRnJhbWUoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcG9zdEdldFNvdXJjZUlkTWVzc2FnZShjdXN0b21fcGFyYW1ldGVyKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAoIWlmcmFtZS5pc0xvYWRlZCkge1xuICAgICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHBvc3RHZXRTb3VyY2VJZE1lc3NhZ2UoY3VzdG9tX3BhcmFtZXRlcik7XG4gICAgICAgIH0sIDEwMCk7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAoIWN1c3RvbV9wYXJhbWV0ZXIpIHtcbiAgICAgICAgaWZyYW1lLmNvbnRlbnRXaW5kb3cucG9zdE1lc3NhZ2Uoe1xuICAgICAgICAgICAgY2FwdHVyZVNvdXJjZUlkOiB0cnVlXG4gICAgICAgIH0sICcqJyk7XG4gICAgfVxuICAgIGVsc2UgaWYgKCEhY3VzdG9tX3BhcmFtZXRlci5mb3JFYWNoKSB7XG4gICAgICAgIGlmcmFtZS5jb250ZW50V2luZG93LnBvc3RNZXNzYWdlKHtcbiAgICAgICAgICAgIGNhcHR1cmVDdXN0b21Tb3VyY2VJZDogY3VzdG9tX3BhcmFtZXRlclxuICAgICAgICB9LCAnKicpO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgaWZyYW1lLmNvbnRlbnRXaW5kb3cucG9zdE1lc3NhZ2Uoe1xuICAgICAgICAgICAgY2FwdHVyZVNvdXJjZUlkV2l0aEF1ZGlvOiB0cnVlXG4gICAgICAgIH0sICcqJyk7XG4gICAgfVxufVxuXG52YXIgaWZyYW1lO1xuXG4vLyB0aGlzIGZ1bmN0aW9uIGlzIHVzZWQgaW4gUlRDTXVsdGlDb25uZWN0aW9uIHYzXG53aW5kb3cuZ2V0U2NyZWVuQ29uc3RyYWludHMgPSBmdW5jdGlvbiAoY2FsbGJhY2spIHtcbiAgICBsb2FkSUZyYW1lKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgZ2V0U2NyZWVuSWQoZnVuY3Rpb24gKGVycm9yLCBzb3VyY2VJZCwgc2NyZWVuX2NvbnN0cmFpbnRzKSB7XG4gICAgICAgICAgICBpZiAoIXNjcmVlbl9jb25zdHJhaW50cykge1xuICAgICAgICAgICAgICAgIHNjcmVlbl9jb25zdHJhaW50cyA9IHtcbiAgICAgICAgICAgICAgICAgICAgdmlkZW86IHRydWVcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBjYWxsYmFjayhlcnJvciwgc2NyZWVuX2NvbnN0cmFpbnRzLnZpZGVvKTtcbiAgICAgICAgfSk7XG4gICAgfSk7XG59O1xuXG5mdW5jdGlvbiBsb2FkSUZyYW1lKGxvYWRDYWxsYmFjaykge1xuICAgIGlmIChpZnJhbWUpIHtcbiAgICAgICAgbG9hZENhbGxiYWNrKCk7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZnJhbWUgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdpZnJhbWUnKTtcbiAgICBpZnJhbWUub25sb2FkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZnJhbWUuaXNMb2FkZWQgPSB0cnVlO1xuICAgICAgICBsb2FkQ2FsbGJhY2soKTtcbiAgICB9O1xuICAgIGlmcmFtZS5zcmMgPSAnaHR0cHM6Ly9vcGVudmlkdS5naXRodWIuaW8vb3BlbnZpZHUtc2NyZWVuLXNoYXJpbmctY2hyb21lLWV4dGVuc2lvbi8nO1xuICAgIGlmcmFtZS5zdHlsZS5kaXNwbGF5ID0gJ25vbmUnO1xuICAgIChkb2N1bWVudC5ib2R5IHx8IGRvY3VtZW50LmRvY3VtZW50RWxlbWVudCkuYXBwZW5kQ2hpbGQoaWZyYW1lKTtcbn1cblxud2luZG93LmdldENocm9tZUV4dGVuc2lvblN0YXR1cyA9IGZ1bmN0aW9uIChjYWxsYmFjaykge1xuICAgIC8vIGZvciBGaXJlZm94OlxuICAgIGlmICghIW5hdmlnYXRvci5tb3pHZXRVc2VyTWVkaWEpIHtcbiAgICAgICAgY2FsbGJhY2soJ2luc3RhbGxlZC1lbmFibGVkJyk7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcignbWVzc2FnZScsIG9uSUZyYW1lQ2FsbGJhY2spO1xuXG4gICAgZnVuY3Rpb24gb25JRnJhbWVDYWxsYmFjayhldmVudCkge1xuICAgICAgICBpZiAoIWV2ZW50LmRhdGEpIHJldHVybjtcblxuICAgICAgICBpZiAoZXZlbnQuZGF0YS5jaHJvbWVFeHRlbnNpb25TdGF0dXMpIHtcbiAgICAgICAgICAgIGNhbGxiYWNrKGV2ZW50LmRhdGEuY2hyb21lRXh0ZW5zaW9uU3RhdHVzKTtcblxuICAgICAgICAgICAgLy8gdGhpcyBldmVudCBsaXN0ZW5lciBpcyBubyBtb3JlIG5lZWRlZFxuICAgICAgICAgICAgd2luZG93LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ21lc3NhZ2UnLCBvbklGcmFtZUNhbGxiYWNrKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHNldFRpbWVvdXQocG9zdEdldENocm9tZUV4dGVuc2lvblN0YXR1c01lc3NhZ2UsIDEwMCk7XG59O1xuXG5mdW5jdGlvbiBwb3N0R2V0Q2hyb21lRXh0ZW5zaW9uU3RhdHVzTWVzc2FnZSgpIHtcbiAgICBpZiAoIWlmcmFtZSkge1xuICAgICAgICBsb2FkSUZyYW1lKHBvc3RHZXRDaHJvbWVFeHRlbnNpb25TdGF0dXNNZXNzYWdlKTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmICghaWZyYW1lLmlzTG9hZGVkKSB7XG4gICAgICAgIHNldFRpbWVvdXQocG9zdEdldENocm9tZUV4dGVuc2lvblN0YXR1c01lc3NhZ2UsIDEwMCk7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZnJhbWUuY29udGVudFdpbmRvdy5wb3N0TWVzc2FnZSh7XG4gICAgICAgIGdldENocm9tZUV4dGVuc2lvblN0YXR1czogdHJ1ZVxuICAgIH0sICcqJyk7XG59XG5cbmV4cG9ydHMuZ2V0U2NyZWVuSWQgPSBnZXRTY3JlZW5JZDsiLCIvLyBnbG9iYWwgdmFyaWFibGVzXG52YXIgY2hyb21lTWVkaWFTb3VyY2UgPSAnc2NyZWVuJztcbnZhciBzb3VyY2VJZDtcbnZhciBzY3JlZW5DYWxsYmFjaztcbnZhciBpc0ZpcmVmb3ggPSB0eXBlb2Ygd2luZG93Lkluc3RhbGxUcmlnZ2VyICE9PSAndW5kZWZpbmVkJztcbnZhciBpc09wZXJhID0gISF3aW5kb3cub3BlcmEgfHwgbmF2aWdhdG9yLnVzZXJBZ2VudC5pbmRleE9mKCcgT1BSLycpID49IDA7XG52YXIgaXNDaHJvbWUgPSAhIXdpbmRvdy5jaHJvbWUgJiYgIWlzT3BlcmE7XG5cbndpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdtZXNzYWdlJywgZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgaWYgKGV2ZW50Lm9yaWdpbiAhPSB3aW5kb3cubG9jYXRpb24ub3JpZ2luKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgb25NZXNzYWdlQ2FsbGJhY2soZXZlbnQuZGF0YSk7XG59KTtcblxuLy8gYW5kIHRoZSBmdW5jdGlvbiB0aGF0IGhhbmRsZXMgcmVjZWl2ZWQgbWVzc2FnZXNcbmZ1bmN0aW9uIG9uTWVzc2FnZUNhbGxiYWNrKGRhdGEpIHtcbiAgICAvLyBcImNhbmNlbFwiIGJ1dHRvbiBpcyBjbGlja2VkXG4gICAgaWYgKGRhdGEgPT0gJ1Blcm1pc3Npb25EZW5pZWRFcnJvcicpIHtcbiAgICAgICAgaWYgKHNjcmVlbkNhbGxiYWNrKVxuICAgICAgICAgICAgcmV0dXJuIHNjcmVlbkNhbGxiYWNrKCdQZXJtaXNzaW9uRGVuaWVkRXJyb3InKTtcbiAgICAgICAgZWxzZVxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdQZXJtaXNzaW9uRGVuaWVkRXJyb3InKTtcbiAgICB9XG4gICAgLy8gZXh0ZW5zaW9uIG5vdGlmaWVkIGhpcyBwcmVzZW5jZVxuICAgIGlmIChkYXRhID09ICdydGNtdWx0aWNvbm5lY3Rpb24tZXh0ZW5zaW9uLWxvYWRlZCcpIHtcbiAgICAgICAgY2hyb21lTWVkaWFTb3VyY2UgPSAnZGVza3RvcCc7XG4gICAgfVxuICAgIC8vIGV4dGVuc2lvbiBzaGFyZWQgdGVtcCBzb3VyY2VJZFxuICAgIGlmIChkYXRhLnNvdXJjZUlkICYmIHNjcmVlbkNhbGxiYWNrKSB7XG4gICAgICAgIHNjcmVlbkNhbGxiYWNrKHNvdXJjZUlkID0gZGF0YS5zb3VyY2VJZCwgZGF0YS5jYW5SZXF1ZXN0QXVkaW9UcmFjayA9PT0gdHJ1ZSk7XG4gICAgfVxufVxuXG4vLyB0aGlzIG1ldGhvZCBjYW4gYmUgdXNlZCB0byBjaGVjayBpZiBjaHJvbWUgZXh0ZW5zaW9uIGlzIGluc3RhbGxlZCAmIGVuYWJsZWQuXG5mdW5jdGlvbiBpc0Nocm9tZUV4dGVuc2lvbkF2YWlsYWJsZShjYWxsYmFjaykge1xuICAgIGlmICghY2FsbGJhY2spIHJldHVybjtcbiAgICBpZiAoY2hyb21lTWVkaWFTb3VyY2UgPT0gJ2Rlc2t0b3AnKSByZXR1cm4gY2FsbGJhY2sodHJ1ZSk7XG5cbiAgICAvLyBhc2sgZXh0ZW5zaW9uIGlmIGl0IGlzIGF2YWlsYWJsZVxuICAgIHdpbmRvdy5wb3N0TWVzc2FnZSgnYXJlLXlvdS10aGVyZScsICcqJyk7XG4gICAgc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmIChjaHJvbWVNZWRpYVNvdXJjZSA9PSAnc2NyZWVuJykge1xuICAgICAgICAgICAgY2FsbGJhY2soZmFsc2UpO1xuICAgICAgICB9IGVsc2UgY2FsbGJhY2sodHJ1ZSk7XG4gICAgfSwgMjAwMCk7XG59XG5cbi8vIHRoaXMgZnVuY3Rpb24gY2FuIGJlIHVzZWQgdG8gZ2V0IFwic291cmNlLWlkXCIgZnJvbSB0aGUgZXh0ZW5zaW9uXG5mdW5jdGlvbiBnZXRTb3VyY2VJZChjYWxsYmFjaykge1xuICAgIGlmICghY2FsbGJhY2spXG4gICAgICAgIHRocm93ICdcImNhbGxiYWNrXCIgcGFyYW1ldGVyIGlzIG1hbmRhdG9yeS4nO1xuICAgIGlmIChzb3VyY2VJZClcbiAgICAgICAgcmV0dXJuIGNhbGxiYWNrKHNvdXJjZUlkKTtcbiAgICBzY3JlZW5DYWxsYmFjayA9IGNhbGxiYWNrO1xuICAgIHdpbmRvdy5wb3N0TWVzc2FnZSgnZ2V0LXNvdXJjZUlkJywgJyonKTtcbn1cblxuLy8gdGhpcyBmdW5jdGlvbiBjYW4gYmUgdXNlZCB0byBnZXQgXCJzb3VyY2UtaWRcIiBmcm9tIHRoZSBleHRlbnNpb25cbmZ1bmN0aW9uIGdldEN1c3RvbVNvdXJjZUlkKGFyciwgY2FsbGJhY2spIHtcbiAgICBpZiAoIWFyciB8fCAhYXJyLmZvckVhY2gpIHRocm93ICdcImFyclwiIHBhcmFtZXRlciBpcyBtYW5kYXRvcnkgYW5kIGl0IG11c3QgYmUgYW4gYXJyYXkuJztcbiAgICBpZiAoIWNhbGxiYWNrKSB0aHJvdyAnXCJjYWxsYmFja1wiIHBhcmFtZXRlciBpcyBtYW5kYXRvcnkuJztcblxuICAgIGlmIChzb3VyY2VJZCkgcmV0dXJuIGNhbGxiYWNrKHNvdXJjZUlkKTtcblxuICAgIHNjcmVlbkNhbGxiYWNrID0gY2FsbGJhY2s7XG4gICAgd2luZG93LnBvc3RNZXNzYWdlKHtcbiAgICAgICAgJ2dldC1jdXN0b20tc291cmNlSWQnOiBhcnJcbiAgICB9LCAnKicpO1xufVxuXG4vLyB0aGlzIGZ1bmN0aW9uIGNhbiBiZSB1c2VkIHRvIGdldCBcInNvdXJjZS1pZFwiIGZyb20gdGhlIGV4dGVuc2lvblxuZnVuY3Rpb24gZ2V0U291cmNlSWRXaXRoQXVkaW8oY2FsbGJhY2spIHtcbiAgICBpZiAoIWNhbGxiYWNrKSB0aHJvdyAnXCJjYWxsYmFja1wiIHBhcmFtZXRlciBpcyBtYW5kYXRvcnkuJztcbiAgICBpZiAoc291cmNlSWQpIHJldHVybiBjYWxsYmFjayhzb3VyY2VJZCk7XG5cbiAgICBzY3JlZW5DYWxsYmFjayA9IGNhbGxiYWNrO1xuICAgIHdpbmRvdy5wb3N0TWVzc2FnZSgnYXVkaW8tcGx1cy10YWInLCAnKicpO1xufVxuXG5mdW5jdGlvbiBnZXRDaHJvbWVFeHRlbnNpb25TdGF0dXMoZXh0ZW5zaW9uaWQsIGNhbGxiYWNrKSB7XG4gICAgaWYgKGlzRmlyZWZveClcbiAgICAgICAgcmV0dXJuIGNhbGxiYWNrKCdub3QtY2hyb21lJyk7XG4gICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggIT0gMikge1xuICAgICAgICBjYWxsYmFjayA9IGV4dGVuc2lvbmlkO1xuICAgICAgICBleHRlbnNpb25pZCA9ICdsZmNnZmVwYWZub2JkbG9lY2NobmZhY2xpYmVuam9sZCc7IC8vIGRlZmF1bHQgZXh0ZW5zaW9uLWlkXG4gICAgfVxuICAgIHZhciBpbWFnZSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2ltZycpO1xuICAgIGltYWdlLnNyYyA9ICdjaHJvbWUtZXh0ZW5zaW9uOi8vJyArIGV4dGVuc2lvbmlkICsgJy9pY29uLnBuZyc7XG4gICAgaW1hZ2Uub25sb2FkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBjaHJvbWVNZWRpYVNvdXJjZSA9ICdzY3JlZW4nO1xuICAgICAgICB3aW5kb3cucG9zdE1lc3NhZ2UoJ2FyZS15b3UtdGhlcmUnLCAnKicpO1xuICAgICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIGlmIChjaHJvbWVNZWRpYVNvdXJjZSA9PSAnc2NyZWVuJykge1xuICAgICAgICAgICAgICAgIGNhbGxiYWNrKCdpbnN0YWxsZWQtZGlzYWJsZWQnKTtcbiAgICAgICAgICAgIH0gZWxzZVxuICAgICAgICAgICAgICAgIGNhbGxiYWNrKCdpbnN0YWxsZWQtZW5hYmxlZCcpO1xuICAgICAgICB9LCAyMDAwKTtcbiAgICB9O1xuICAgIGltYWdlLm9uZXJyb3IgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGNhbGxiYWNrKCdub3QtaW5zdGFsbGVkJyk7XG4gICAgfTtcbn1cblxuZnVuY3Rpb24gZ2V0U2NyZWVuQ29uc3RyYWludHNXaXRoQXVkaW8oY2FsbGJhY2spIHtcbiAgICBnZXRTY3JlZW5Db25zdHJhaW50cyhjYWxsYmFjaywgdHJ1ZSk7XG59XG5cbi8vIHRoaXMgZnVuY3Rpb24gZXhwbGFpbnMgaG93IHRvIHVzZSBhYm92ZSBtZXRob2RzL29iamVjdHNcbmZ1bmN0aW9uIGdldFNjcmVlbkNvbnN0cmFpbnRzKGNhbGxiYWNrLCBjYXB0dXJlU291cmNlSWRXaXRoQXVkaW8pIHtcbiAgICBzb3VyY2VJZCA9ICcnO1xuICAgIHZhciBmaXJlZm94U2NyZWVuQ29uc3RyYWludHMgPSB7XG4gICAgICAgIG1vek1lZGlhU291cmNlOiAnd2luZG93JyxcbiAgICAgICAgbWVkaWFTb3VyY2U6ICd3aW5kb3cnXG4gICAgfTtcbiAgICBpZiAoaXNGaXJlZm94KVxuICAgICAgICByZXR1cm4gY2FsbGJhY2sobnVsbCwgZmlyZWZveFNjcmVlbkNvbnN0cmFpbnRzKTtcbiAgICAvLyB0aGlzIHN0YXRlbWVudCBkZWZpbmVzIGdldFVzZXJNZWRpYSBjb25zdHJhaW50c1xuICAgIC8vIHRoYXQgd2lsbCBiZSB1c2VkIHRvIGNhcHR1cmUgY29udGVudCBvZiBzY3JlZW5cbiAgICB2YXIgc2NyZWVuX2NvbnN0cmFpbnRzID0ge1xuICAgICAgICBtYW5kYXRvcnk6IHtcbiAgICAgICAgICAgIGNocm9tZU1lZGlhU291cmNlOiBjaHJvbWVNZWRpYVNvdXJjZSxcbiAgICAgICAgICAgIG1heFdpZHRoOiBzY3JlZW4ud2lkdGggPiAxOTIwID8gc2NyZWVuLndpZHRoIDogMTkyMCxcbiAgICAgICAgICAgIG1heEhlaWdodDogc2NyZWVuLmhlaWdodCA+IDEwODAgPyBzY3JlZW4uaGVpZ2h0IDogMTA4MFxuICAgICAgICB9LFxuICAgICAgICBvcHRpb25hbDogW11cbiAgICB9O1xuICAgIC8vIHRoaXMgc3RhdGVtZW50IHZlcmlmaWVzIGNocm9tZSBleHRlbnNpb24gYXZhaWxhYmlsaXR5XG4gICAgLy8gaWYgaW5zdGFsbGVkIGFuZCBhdmFpbGFibGUgdGhlbiBpdCB3aWxsIGludm9rZSBleHRlbnNpb24gQVBJXG4gICAgLy8gb3RoZXJ3aXNlIGl0IHdpbGwgZmFsbGJhY2sgdG8gY29tbWFuZC1saW5lIGJhc2VkIHNjcmVlbiBjYXB0dXJpbmcgQVBJXG4gICAgaWYgKGNocm9tZU1lZGlhU291cmNlID09ICdkZXNrdG9wJyAmJiAhc291cmNlSWQpIHtcbiAgICAgICAgaWYgKGNhcHR1cmVTb3VyY2VJZFdpdGhBdWRpbykge1xuICAgICAgICAgICAgZ2V0U291cmNlSWRXaXRoQXVkaW8oZnVuY3Rpb24gKHNvdXJjZUlkLCBjYW5SZXF1ZXN0QXVkaW9UcmFjaykge1xuICAgICAgICAgICAgICAgIHNjcmVlbl9jb25zdHJhaW50cy5tYW5kYXRvcnkuY2hyb21lTWVkaWFTb3VyY2VJZCA9IHNvdXJjZUlkO1xuXG4gICAgICAgICAgICAgICAgaWYgKGNhblJlcXVlc3RBdWRpb1RyYWNrKSB7XG4gICAgICAgICAgICAgICAgICAgIHNjcmVlbl9jb25zdHJhaW50cy5jYW5SZXF1ZXN0QXVkaW9UcmFjayA9IHRydWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNhbGxiYWNrKHNvdXJjZUlkID09ICdQZXJtaXNzaW9uRGVuaWVkRXJyb3InID8gc291cmNlSWQgOiBudWxsLCBzY3JlZW5fY29uc3RyYWludHMpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBnZXRTb3VyY2VJZChmdW5jdGlvbiAoc291cmNlSWQpIHtcbiAgICAgICAgICAgICAgICBzY3JlZW5fY29uc3RyYWludHMubWFuZGF0b3J5LmNocm9tZU1lZGlhU291cmNlSWQgPSBzb3VyY2VJZDtcbiAgICAgICAgICAgICAgICBjYWxsYmFjayhzb3VyY2VJZCA9PSAnUGVybWlzc2lvbkRlbmllZEVycm9yJyA/IHNvdXJjZUlkIDogbnVsbCwgc2NyZWVuX2NvbnN0cmFpbnRzKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyB0aGlzIHN0YXRlbWVudCBzZXRzIGdldHMgJ3NvdXJjZUlkXCIgYW5kIHNldHMgXCJjaHJvbWVNZWRpYVNvdXJjZUlkXCIgXG4gICAgaWYgKGNocm9tZU1lZGlhU291cmNlID09ICdkZXNrdG9wJykge1xuICAgICAgICBzY3JlZW5fY29uc3RyYWludHMubWFuZGF0b3J5LmNocm9tZU1lZGlhU291cmNlSWQgPSBzb3VyY2VJZDtcbiAgICB9XG5cbiAgICAvLyBub3cgaW52b2tpbmcgbmF0aXZlIGdldFVzZXJNZWRpYSBBUElcbiAgICBjYWxsYmFjayhudWxsLCBzY3JlZW5fY29uc3RyYWludHMpO1xufVxuXG5leHBvcnRzLmdldFNjcmVlbkNvbnN0cmFpbnRzID0gZ2V0U2NyZWVuQ29uc3RyYWludHM7XG5leHBvcnRzLmdldFNjcmVlbkNvbnN0cmFpbnRzV2l0aEF1ZGlvID0gZ2V0U2NyZWVuQ29uc3RyYWludHNXaXRoQXVkaW87XG5leHBvcnRzLmlzQ2hyb21lRXh0ZW5zaW9uQXZhaWxhYmxlID0gaXNDaHJvbWVFeHRlbnNpb25BdmFpbGFibGU7XG5leHBvcnRzLmdldENocm9tZUV4dGVuc2lvblN0YXR1cyA9IGdldENocm9tZUV4dGVuc2lvblN0YXR1cztcbmV4cG9ydHMuZ2V0U291cmNlSWQgPSBnZXRTb3VyY2VJZDsiLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCBmcmVlaWNlID0gcmVxdWlyZSgnZnJlZWljZScpO1xuaW1wb3J0IHV1aWQgPSByZXF1aXJlKCd1dWlkJyk7XG5pbXBvcnQgcGxhdGZvcm0gPSByZXF1aXJlKCdwbGF0Zm9ybScpO1xuXG5cbmV4cG9ydCBpbnRlcmZhY2UgV2ViUnRjUGVlckNvbmZpZ3VyYXRpb24ge1xuICAgIG1lZGlhQ29uc3RyYWludHM6IHtcbiAgICAgICAgYXVkaW86IGJvb2xlYW4sXG4gICAgICAgIHZpZGVvOiBib29sZWFuXG4gICAgfTtcbiAgICBzaW11bGNhc3Q6IGJvb2xlYW47XG4gICAgb25pY2VjYW5kaWRhdGU6IChldmVudCkgPT4gdm9pZDtcbiAgICBpY2VTZXJ2ZXJzOiBSVENJY2VTZXJ2ZXJbXSB8IHVuZGVmaW5lZDtcbiAgICBtZWRpYVN0cmVhbT86IE1lZGlhU3RyZWFtO1xuICAgIG1vZGU/OiBzdHJpbmc7IC8vIHNlbmRvbmx5LCByZWNvbmx5LCBzZW5kcmVjdlxuICAgIGlkPzogc3RyaW5nO1xufVxuXG5leHBvcnQgY2xhc3MgV2ViUnRjUGVlciB7XG5cbiAgICBwYzogUlRDUGVlckNvbm5lY3Rpb247XG4gICAgaWQ6IHN0cmluZztcbiAgICByZW1vdGVDYW5kaWRhdGVzUXVldWU6IFJUQ0ljZUNhbmRpZGF0ZVtdID0gW107XG4gICAgbG9jYWxDYW5kaWRhdGVzUXVldWU6IFJUQ0ljZUNhbmRpZGF0ZVtdID0gW107XG5cbiAgICBpY2VDYW5kaWRhdGVMaXN0OiBSVENJY2VDYW5kaWRhdGVbXSA9IFtdO1xuXG4gICAgcHJpdmF0ZSBjYW5kaWRhdGVnYXRoZXJpbmdkb25lID0gZmFsc2U7XG5cbiAgICBjb25zdHJ1Y3Rvcihwcml2YXRlIGNvbmZpZ3VyYXRpb246IFdlYlJ0Y1BlZXJDb25maWd1cmF0aW9uKSB7XG4gICAgICAgIHRoaXMuY29uZmlndXJhdGlvbi5pY2VTZXJ2ZXJzID0gKCEhdGhpcy5jb25maWd1cmF0aW9uLmljZVNlcnZlcnMgJiYgdGhpcy5jb25maWd1cmF0aW9uLmljZVNlcnZlcnMubGVuZ3RoID4gMCkgPyB0aGlzLmNvbmZpZ3VyYXRpb24uaWNlU2VydmVycyA6IGZyZWVpY2UoKTtcblxuICAgICAgICB0aGlzLnBjID0gbmV3IFJUQ1BlZXJDb25uZWN0aW9uKHsgaWNlU2VydmVyczogdGhpcy5jb25maWd1cmF0aW9uLmljZVNlcnZlcnMgfSk7XG4gICAgICAgIHRoaXMuaWQgPSAhIWNvbmZpZ3VyYXRpb24uaWQgPyBjb25maWd1cmF0aW9uLmlkIDogdXVpZC52NCgpO1xuXG4gICAgICAgIHRoaXMucGMub25pY2VjYW5kaWRhdGUgPSBldmVudCA9PiB7XG4gICAgICAgICAgICBjb25zdCBjYW5kaWRhdGU6IFJUQ0ljZUNhbmRpZGF0ZSA9IGV2ZW50LmNhbmRpZGF0ZTtcbiAgICAgICAgICAgIGlmIChjYW5kaWRhdGUpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmxvY2FsQ2FuZGlkYXRlc1F1ZXVlLnB1c2goPFJUQ0ljZUNhbmRpZGF0ZT57IGNhbmRpZGF0ZTogY2FuZGlkYXRlLmNhbmRpZGF0ZSB9KTtcbiAgICAgICAgICAgICAgICB0aGlzLmNhbmRpZGF0ZWdhdGhlcmluZ2RvbmUgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB0aGlzLmNvbmZpZ3VyYXRpb24ub25pY2VjYW5kaWRhdGUoZXZlbnQuY2FuZGlkYXRlKTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoIXRoaXMuY2FuZGlkYXRlZ2F0aGVyaW5nZG9uZSkge1xuICAgICAgICAgICAgICAgIHRoaXMuY2FuZGlkYXRlZ2F0aGVyaW5nZG9uZSA9IHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG5cbiAgICAgICAgdGhpcy5wYy5vbnNpZ25hbGluZ3N0YXRlY2hhbmdlID0gKCkgPT4ge1xuICAgICAgICAgICAgaWYgKHRoaXMucGMuc2lnbmFsaW5nU3RhdGUgPT09ICdzdGFibGUnKSB7XG4gICAgICAgICAgICAgICAgd2hpbGUgKHRoaXMuaWNlQ2FuZGlkYXRlTGlzdC5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMucGMuYWRkSWNlQ2FuZGlkYXRlKDxSVENJY2VDYW5kaWRhdGU+dGhpcy5pY2VDYW5kaWRhdGVMaXN0LnNoaWZ0KCkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcblxuICAgICAgICB0aGlzLnN0YXJ0KCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhpcyBmdW5jdGlvbiBjcmVhdGVzIHRoZSBSVENQZWVyQ29ubmVjdGlvbiBvYmplY3QgdGFraW5nIGludG8gYWNjb3VudCB0aGVcbiAgICAgKiBwcm9wZXJ0aWVzIHJlY2VpdmVkIGluIHRoZSBjb25zdHJ1Y3Rvci4gSXQgc3RhcnRzIHRoZSBTRFAgbmVnb3RpYXRpb25cbiAgICAgKiBwcm9jZXNzOiBnZW5lcmF0ZXMgdGhlIFNEUCBvZmZlciBhbmQgaW52b2tlcyB0aGUgb25zZHBvZmZlciBjYWxsYmFjay4gVGhpc1xuICAgICAqIGNhbGxiYWNrIGlzIGV4cGVjdGVkIHRvIHNlbmQgdGhlIFNEUCBvZmZlciwgaW4gb3JkZXIgdG8gb2J0YWluIGFuIFNEUFxuICAgICAqIGFuc3dlciBmcm9tIGFub3RoZXIgcGVlci5cbiAgICAgKi9cbiAgICBzdGFydCgpOiBQcm9taXNlPGFueT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgaWYgKHRoaXMucGMuc2lnbmFsaW5nU3RhdGUgPT09ICdjbG9zZWQnKSB7XG4gICAgICAgICAgICAgICAgcmVqZWN0KCdUaGUgcGVlciBjb25uZWN0aW9uIG9iamVjdCBpcyBpbiBcImNsb3NlZFwiIHN0YXRlLiBUaGlzIGlzIG1vc3QgbGlrZWx5IGR1ZSB0byBhbiBpbnZvY2F0aW9uIG9mIHRoZSBkaXNwb3NlIG1ldGhvZCBiZWZvcmUgYWNjZXB0aW5nIGluIHRoZSBkaWFsb2d1ZScpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCEhdGhpcy5jb25maWd1cmF0aW9uLm1lZGlhU3RyZWFtKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5wYy5hZGRTdHJlYW0odGhpcy5jb25maWd1cmF0aW9uLm1lZGlhU3RyZWFtKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gW0hhY2tdIGh0dHBzOi8vY29kZS5nb29nbGUuY29tL3AvY2hyb21pdW0vaXNzdWVzL2RldGFpbD9pZD00NDM1NThcbiAgICAgICAgICAgIGlmICh0aGlzLmNvbmZpZ3VyYXRpb24ubW9kZSA9PT0gJ3NlbmRvbmx5JyAmJlxuICAgICAgICAgICAgICAgIChwbGF0Zm9ybS5uYW1lID09PSAnQ2hyb21lJyAmJiBwbGF0Zm9ybS52ZXJzaW9uIS50b1N0cmluZygpLnN1YnN0cmluZygwLCAyKSA9PT0gJzM5JykpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmNvbmZpZ3VyYXRpb24ubW9kZSA9ICdzZW5kcmVjdic7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhpcyBtZXRob2QgZnJlZXMgdGhlIHJlc291cmNlcyB1c2VkIGJ5IFdlYlJ0Y1BlZXJcbiAgICAgKi9cbiAgICBkaXNwb3NlKCkge1xuICAgICAgICBjb25zb2xlLmRlYnVnKCdEaXNwb3NpbmcgV2ViUnRjUGVlcicpO1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgaWYgKHRoaXMucGMpIHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5wYy5zaWduYWxpbmdTdGF0ZSA9PT0gJ2Nsb3NlZCcpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLnJlbW90ZUNhbmRpZGF0ZXNRdWV1ZSA9IFtdO1xuICAgICAgICAgICAgICAgIHRoaXMubG9jYWxDYW5kaWRhdGVzUXVldWUgPSBbXTtcblxuICAgICAgICAgICAgICAgIHRoaXMucGMuZ2V0TG9jYWxTdHJlYW1zKCkuZm9yRWFjaChzdHIgPT4ge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbVN0b3Aoc3RyKTtcbiAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAgIC8vIEZJWE1FIFRoaXMgaXMgbm90IHlldCBpbXBsZW1lbnRlZCBpbiBmaXJlZm94XG4gICAgICAgICAgICAgICAgLy8gaWYodmlkZW9TdHJlYW0pIHBjLnJlbW92ZVN0cmVhbSh2aWRlb1N0cmVhbSk7XG4gICAgICAgICAgICAgICAgLy8gaWYoYXVkaW9TdHJlYW0pIHBjLnJlbW92ZVN0cmVhbShhdWRpb1N0cmVhbSk7XG5cbiAgICAgICAgICAgICAgICB0aGlzLnBjLmNsb3NlKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgY29uc29sZS53YXJuKCdFeGNlcHRpb24gZGlzcG9zaW5nIHdlYnJ0YyBwZWVyICcgKyBlcnIpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogMSkgRnVuY3Rpb24gdGhhdCBjcmVhdGVzIGFuIG9mZmVyLCBzZXRzIGl0IGFzIGxvY2FsIGRlc2NyaXB0aW9uIGFuZCByZXR1cm5zIHRoZSBvZmZlciBwYXJhbVxuICAgICAqIHRvIHNlbmQgdG8gT3BlblZpZHUgU2VydmVyICh3aWxsIGJlIHRoZSByZW1vdGUgZGVzY3JpcHRpb24gb2Ygb3RoZXIgcGVlcilcbiAgICAgKi9cbiAgICBnZW5lcmF0ZU9mZmVyKCk6IFByb21pc2U8c3RyaW5nPiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICBsZXQgb2ZmZXJBdWRpbywgb2ZmZXJWaWRlbyA9IHRydWU7XG5cbiAgICAgICAgICAgIC8vIENvbnN0cmFpbnRzIG11c3QgaGF2ZSBib3RoIGJsb2Nrc1xuICAgICAgICAgICAgaWYgKCEhdGhpcy5jb25maWd1cmF0aW9uLm1lZGlhQ29uc3RyYWludHMpIHtcbiAgICAgICAgICAgICAgICBvZmZlckF1ZGlvID0gKHR5cGVvZiB0aGlzLmNvbmZpZ3VyYXRpb24ubWVkaWFDb25zdHJhaW50cy5hdWRpbyA9PT0gJ2Jvb2xlYW4nKSA/XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuY29uZmlndXJhdGlvbi5tZWRpYUNvbnN0cmFpbnRzLmF1ZGlvIDogdHJ1ZTtcbiAgICAgICAgICAgICAgICBvZmZlclZpZGVvID0gKHR5cGVvZiB0aGlzLmNvbmZpZ3VyYXRpb24ubWVkaWFDb25zdHJhaW50cy52aWRlbyA9PT0gJ2Jvb2xlYW4nKSA/XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuY29uZmlndXJhdGlvbi5tZWRpYUNvbnN0cmFpbnRzLnZpZGVvIDogdHJ1ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgY29uc3QgY29uc3RyYWludHM6IFJUQ09mZmVyT3B0aW9ucyA9IHtcbiAgICAgICAgICAgICAgICBvZmZlclRvUmVjZWl2ZUF1ZGlvOiArICh0aGlzLmNvbmZpZ3VyYXRpb24ubW9kZSAhPT0gJ3NlbmRvbmx5JyAmJiBvZmZlckF1ZGlvKSxcbiAgICAgICAgICAgICAgICBvZmZlclRvUmVjZWl2ZVZpZGVvOiArICh0aGlzLmNvbmZpZ3VyYXRpb24ubW9kZSAhPT0gJ3NlbmRvbmx5JyAmJiBvZmZlclZpZGVvKVxuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgY29uc29sZS5kZWJ1ZygnUlRDUGVlckNvbm5lY3Rpb24gY29uc3RyYWludHM6ICcgKyBKU09OLnN0cmluZ2lmeShjb25zdHJhaW50cykpO1xuXG4gICAgICAgICAgICB0aGlzLnBjLmNyZWF0ZU9mZmVyKGNvbnN0cmFpbnRzKS50aGVuKG9mZmVyID0+IHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmRlYnVnKCdDcmVhdGVkIFNEUCBvZmZlcicpO1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLnBjLnNldExvY2FsRGVzY3JpcHRpb24ob2ZmZXIpO1xuICAgICAgICAgICAgfSkudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3QgbG9jYWxEZXNjcmlwdGlvbiA9IHRoaXMucGMubG9jYWxEZXNjcmlwdGlvbjtcbiAgICAgICAgICAgICAgICBpZiAoISFsb2NhbERlc2NyaXB0aW9uKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZGVidWcoJ0xvY2FsIGRlc2NyaXB0aW9uIHNldCcsIGxvY2FsRGVzY3JpcHRpb24uc2RwKTtcbiAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSg8c3RyaW5nPmxvY2FsRGVzY3JpcHRpb24uc2RwKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICByZWplY3QoJ0xvY2FsIGRlc2NyaXB0aW9uIGlzIG5vdCBkZWZpbmVkJyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSkuY2F0Y2goZXJyb3IgPT4gcmVqZWN0KGVycm9yKSk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIDIpIEZ1bmN0aW9uIHRvIGludm9rZSB3aGVuIGEgU0RQIG9mZmVyIGlzIHJlY2VpdmVkLiBTZXRzIGl0IGFzIHJlbW90ZSBkZXNjcmlwdGlvbixcbiAgICAgKiBnZW5lcmF0ZXMgYW5kIGFuc3dlciBhbmQgcmV0dXJucyBpdCB0byBzZW5kIGl0IHRvIE9wZW5WaWR1IFNlcnZlclxuICAgICAqL1xuICAgIHByb2Nlc3NPZmZlcihzZHBPZmZlcjogc3RyaW5nKTogUHJvbWlzZTxDb25zdHJhaW5ET01TdHJpbmc+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IG9mZmVyOiBSVENTZXNzaW9uRGVzY3JpcHRpb25Jbml0ID0ge1xuICAgICAgICAgICAgICAgIHR5cGU6ICdvZmZlcicsXG4gICAgICAgICAgICAgICAgc2RwOiBzZHBPZmZlclxuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgY29uc29sZS5kZWJ1ZygnU0RQIG9mZmVyIHJlY2VpdmVkLCBzZXR0aW5nIHJlbW90ZSBkZXNjcmlwdGlvbicpO1xuXG4gICAgICAgICAgICBpZiAodGhpcy5wYy5zaWduYWxpbmdTdGF0ZSA9PT0gJ2Nsb3NlZCcpIHtcbiAgICAgICAgICAgICAgICByZWplY3QoJ1BlZXJDb25uZWN0aW9uIGlzIGNsb3NlZCcpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLnBjLnNldFJlbW90ZURlc2NyaXB0aW9uKG9mZmVyKVxuICAgICAgICAgICAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMucGMuY3JlYXRlQW5zd2VyKCk7XG4gICAgICAgICAgICAgICAgfSkudGhlbihhbnN3ZXIgPT4ge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmRlYnVnKCdDcmVhdGVkIFNEUCBhbnN3ZXInKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMucGMuc2V0TG9jYWxEZXNjcmlwdGlvbihhbnN3ZXIpO1xuICAgICAgICAgICAgICAgIH0pLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBsb2NhbERlc2NyaXB0aW9uID0gdGhpcy5wYy5sb2NhbERlc2NyaXB0aW9uO1xuICAgICAgICAgICAgICAgICAgICBpZiAoISFsb2NhbERlc2NyaXB0aW9uKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmRlYnVnKCdMb2NhbCBkZXNjcmlwdGlvbiBzZXQnLCBsb2NhbERlc2NyaXB0aW9uLnNkcCk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXNvbHZlKDxzdHJpbmc+bG9jYWxEZXNjcmlwdGlvbi5zZHApO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KCdMb2NhbCBkZXNjcmlwdGlvbiBpcyBub3QgZGVmaW5lZCcpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSkuY2F0Y2goZXJyb3IgPT4gcmVqZWN0KGVycm9yKSk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIDMpIEZ1bmN0aW9uIGludm9rZWQgd2hlbiBhIFNEUCBhbnN3ZXIgaXMgcmVjZWl2ZWQuIEZpbmFsIHN0ZXAgaW4gU0RQIG5lZ290aWF0aW9uLCB0aGUgcGVlclxuICAgICAqIGp1c3QgbmVlZHMgdG8gc2V0IHRoZSBhbnN3ZXIgYXMgaXRzIHJlbW90ZSBkZXNjcmlwdGlvblxuICAgICAqL1xuICAgIHByb2Nlc3NBbnN3ZXIoc2RwQW5zd2VyOiBzdHJpbmcpOiBQcm9taXNlPHN0cmluZz4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuXG4gICAgICAgICAgICBjb25zdCBhbnN3ZXI6IFJUQ1Nlc3Npb25EZXNjcmlwdGlvbkluaXQgPSB7XG4gICAgICAgICAgICAgICAgdHlwZTogJ2Fuc3dlcicsXG4gICAgICAgICAgICAgICAgc2RwOiBzZHBBbnN3ZXJcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIGNvbnNvbGUuZGVidWcoJ1NEUCBhbnN3ZXIgcmVjZWl2ZWQsIHNldHRpbmcgcmVtb3RlIGRlc2NyaXB0aW9uJyk7XG5cbiAgICAgICAgICAgIGlmICh0aGlzLnBjLnNpZ25hbGluZ1N0YXRlID09PSAnY2xvc2VkJykge1xuICAgICAgICAgICAgICAgIHJlamVjdCgnUlRDUGVlckNvbm5lY3Rpb24gaXMgY2xvc2VkJyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMucGMuc2V0UmVtb3RlRGVzY3JpcHRpb24oYW5zd2VyKS50aGVuKCgpID0+IHJlc29sdmUoKSkuY2F0Y2goZXJyb3IgPT4gcmVqZWN0KGVycm9yKSk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENhbGxiYWNrIGZ1bmN0aW9uIGludm9rZWQgd2hlbiBhbiBJQ0UgY2FuZGlkYXRlIGlzIHJlY2VpdmVkXG4gICAgICovXG4gICAgYWRkSWNlQ2FuZGlkYXRlKGljZUNhbmRpZGF0ZTogUlRDSWNlQ2FuZGlkYXRlKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICBjb25zb2xlLmRlYnVnKCdSZW1vdGUgSUNFIGNhbmRpZGF0ZSByZWNlaXZlZCcsIGljZUNhbmRpZGF0ZSk7XG4gICAgICAgICAgICB0aGlzLnJlbW90ZUNhbmRpZGF0ZXNRdWV1ZS5wdXNoKGljZUNhbmRpZGF0ZSk7XG4gICAgICAgICAgICBzd2l0Y2ggKHRoaXMucGMuc2lnbmFsaW5nU3RhdGUpIHtcbiAgICAgICAgICAgICAgICBjYXNlICdjbG9zZWQnOlxuICAgICAgICAgICAgICAgICAgICByZWplY3QobmV3IEVycm9yKCdQZWVyQ29ubmVjdGlvbiBvYmplY3QgaXMgY2xvc2VkJykpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlICdzdGFibGUnOlxuICAgICAgICAgICAgICAgICAgICBpZiAoISF0aGlzLnBjLnJlbW90ZURlc2NyaXB0aW9uKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnBjLmFkZEljZUNhbmRpZGF0ZShpY2VDYW5kaWRhdGUpLnRoZW4oKCkgPT4gcmVzb2x2ZSgpKS5jYXRjaChlcnJvciA9PiByZWplY3QoZXJyb3IpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICB0aGlzLmljZUNhbmRpZGF0ZUxpc3QucHVzaChpY2VDYW5kaWRhdGUpO1xuICAgICAgICAgICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIHByaXZhdGUgc3RyZWFtU3RvcChzdHJlYW06IE1lZGlhU3RyZWFtKTogdm9pZCB7XG4gICAgICAgIHN0cmVhbS5nZXRUcmFja3MoKS5mb3JFYWNoKHRyYWNrID0+IHtcbiAgICAgICAgICAgIHRyYWNrLnN0b3AoKTtcbiAgICAgICAgICAgIHN0cmVhbS5yZW1vdmVUcmFjayh0cmFjayk7XG4gICAgICAgIH0pO1xuICAgIH1cbn1cblxuXG5leHBvcnQgY2xhc3MgV2ViUnRjUGVlclJlY3Zvbmx5IGV4dGVuZHMgV2ViUnRjUGVlciB7XG4gICAgY29uc3RydWN0b3IoY29uZmlndXJhdGlvbjogV2ViUnRjUGVlckNvbmZpZ3VyYXRpb24pIHtcbiAgICAgICAgY29uZmlndXJhdGlvbi5tb2RlID0gJ3JlY3Zvbmx5JztcbiAgICAgICAgc3VwZXIoY29uZmlndXJhdGlvbik7XG4gICAgfVxufVxuXG5leHBvcnQgY2xhc3MgV2ViUnRjUGVlclNlbmRvbmx5IGV4dGVuZHMgV2ViUnRjUGVlciB7XG4gICAgY29uc3RydWN0b3IoY29uZmlndXJhdGlvbjogV2ViUnRjUGVlckNvbmZpZ3VyYXRpb24pIHtcbiAgICAgICAgY29uZmlndXJhdGlvbi5tb2RlID0gJ3NlbmRvbmx5JztcbiAgICAgICAgc3VwZXIoY29uZmlndXJhdGlvbik7XG4gICAgfVxufVxuXG5leHBvcnQgY2xhc3MgV2ViUnRjUGVlclNlbmRyZWN2IGV4dGVuZHMgV2ViUnRjUGVlciB7XG4gICAgY29uc3RydWN0b3IoY29uZmlndXJhdGlvbjogV2ViUnRjUGVlckNvbmZpZ3VyYXRpb24pIHtcbiAgICAgICAgY29uZmlndXJhdGlvbi5tb2RlID0gJ3NlbmRyZWN2JztcbiAgICAgICAgc3VwZXIoY29uZmlndXJhdGlvbik7XG4gICAgfVxufSIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTctMjAxOCBPcGVuVmlkdSAoaHR0cHM6Ly9vcGVudmlkdS5pby8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuLy8gdHNsaW50OmRpc2FibGU6bm8tc3RyaW5nLWxpdGVyYWxcblxuaW1wb3J0IHsgU3RyZWFtIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvU3RyZWFtJztcbmltcG9ydCBwbGF0Zm9ybSA9IHJlcXVpcmUoJ3BsYXRmb3JtJyk7XG5cbmV4cG9ydCBjbGFzcyBXZWJSdGNTdGF0cyB7XG5cbiAgICBwcml2YXRlIHdlYlJ0Y1N0YXRzRW5hYmxlZCA9IGZhbHNlO1xuICAgIHByaXZhdGUgd2ViUnRjU3RhdHNJbnRlcnZhbElkOiBOb2RlSlMuVGltZXI7XG4gICAgcHJpdmF0ZSBzdGF0c0ludGVydmFsID0gMTtcbiAgICBwcml2YXRlIHN0YXRzOiBhbnkgPSB7XG4gICAgICAgIGluYm91bmQ6IHtcbiAgICAgICAgICAgIGF1ZGlvOiB7XG4gICAgICAgICAgICAgICAgYnl0ZXNSZWNlaXZlZDogMCxcbiAgICAgICAgICAgICAgICBwYWNrZXRzUmVjZWl2ZWQ6IDAsXG4gICAgICAgICAgICAgICAgcGFja2V0c0xvc3Q6IDBcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB2aWRlbzoge1xuICAgICAgICAgICAgICAgIGJ5dGVzUmVjZWl2ZWQ6IDAsXG4gICAgICAgICAgICAgICAgcGFja2V0c1JlY2VpdmVkOiAwLFxuICAgICAgICAgICAgICAgIHBhY2tldHNMb3N0OiAwLFxuICAgICAgICAgICAgICAgIGZyYW1lc0RlY29kZWQ6IDAsXG4gICAgICAgICAgICAgICAgbmFja0NvdW50OiAwXG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIG91dGJvdW5kOiB7XG4gICAgICAgICAgICBhdWRpbzoge1xuICAgICAgICAgICAgICAgIGJ5dGVzU2VudDogMCxcbiAgICAgICAgICAgICAgICBwYWNrZXRzU2VudDogMCxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB2aWRlbzoge1xuICAgICAgICAgICAgICAgIGJ5dGVzU2VudDogMCxcbiAgICAgICAgICAgICAgICBwYWNrZXRzU2VudDogMCxcbiAgICAgICAgICAgICAgICBmcmFtZXNFbmNvZGVkOiAwLFxuICAgICAgICAgICAgICAgIG5hY2tDb3VudDogMFxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfTtcblxuICAgIGNvbnN0cnVjdG9yKHByaXZhdGUgc3RyZWFtOiBTdHJlYW0pIHsgfVxuXG4gICAgcHVibGljIGlzRW5hYmxlZCgpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuIHRoaXMud2ViUnRjU3RhdHNFbmFibGVkO1xuICAgIH1cblxuICAgIHB1YmxpYyBpbml0V2ViUnRjU3RhdHMoKTogdm9pZCB7XG5cbiAgICAgICAgY29uc3QgZWxhc3Rlc3RJbnN0cnVtZW50YXRpb24gPSBsb2NhbFN0b3JhZ2UuZ2V0SXRlbSgnZWxhc3Rlc3QtaW5zdHJ1bWVudGF0aW9uJyk7XG5cbiAgICAgICAgaWYgKGVsYXN0ZXN0SW5zdHJ1bWVudGF0aW9uKSB7XG4gICAgICAgICAgICAvLyBFbGFzVGVzdCBpbnN0cnVtZW50YXRpb24gb2JqZWN0IGZvdW5kIGluIGxvY2FsIHN0b3JhZ2VcblxuICAgICAgICAgICAgY29uc29sZS53YXJuKCdXZWJSdGMgc3RhdHMgZW5hYmxlZCBmb3Igc3RyZWFtICcgKyB0aGlzLnN0cmVhbS5zdHJlYW1JZCArICcgb2YgY29ubmVjdGlvbiAnICsgdGhpcy5zdHJlYW0uY29ubmVjdGlvbi5jb25uZWN0aW9uSWQpO1xuXG4gICAgICAgICAgICB0aGlzLndlYlJ0Y1N0YXRzRW5hYmxlZCA9IHRydWU7XG5cbiAgICAgICAgICAgIGNvbnN0IGluc3RydW1lbnRhdGlvbiA9IEpTT04ucGFyc2UoZWxhc3Rlc3RJbnN0cnVtZW50YXRpb24pO1xuICAgICAgICAgICAgdGhpcy5zdGF0c0ludGVydmFsID0gaW5zdHJ1bWVudGF0aW9uLndlYnJ0Yy5pbnRlcnZhbDsgIC8vIEludGVydmFsIGluIHNlY29uZHNcblxuICAgICAgICAgICAgY29uc29sZS53YXJuKCdsb2NhbFN0b3JhZ2UgaXRlbTogJyArIEpTT04uc3RyaW5naWZ5KGluc3RydW1lbnRhdGlvbikpO1xuXG4gICAgICAgICAgICB0aGlzLndlYlJ0Y1N0YXRzSW50ZXJ2YWxJZCA9IHNldEludGVydmFsKCgpID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLnNlbmRTdGF0c1RvSHR0cEVuZHBvaW50KGluc3RydW1lbnRhdGlvbik7XG4gICAgICAgICAgICB9LCB0aGlzLnN0YXRzSW50ZXJ2YWwgKiAxMDAwKTtcblxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc29sZS5kZWJ1ZygnV2ViUnRjIHN0YXRzIG5vdCBlbmFibGVkJyk7XG4gICAgfVxuXG4gICAgcHVibGljIHN0b3BXZWJSdGNTdGF0cygpIHtcbiAgICAgICAgaWYgKHRoaXMud2ViUnRjU3RhdHNFbmFibGVkKSB7XG4gICAgICAgICAgICBjbGVhckludGVydmFsKHRoaXMud2ViUnRjU3RhdHNJbnRlcnZhbElkKTtcbiAgICAgICAgICAgIGNvbnNvbGUud2FybignV2ViUnRjIHN0YXRzIHN0b3BwZWQgZm9yIGRpc3Bvc2VkIHN0cmVhbSAnICsgdGhpcy5zdHJlYW0uc3RyZWFtSWQgKyAnIG9mIGNvbm5lY3Rpb24gJyArIHRoaXMuc3RyZWFtLmNvbm5lY3Rpb24uY29ubmVjdGlvbklkKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHB1YmxpYyBnZXRTZWxlY3RlZEljZUNhbmRpZGF0ZUluZm8oKTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIHRoaXMuZ2V0U3RhdHNBZ25vc3RpYyh0aGlzLnN0cmVhbS5nZXRSVENQZWVyQ29ubmVjdGlvbigpLFxuICAgICAgICAgICAgICAgIChzdGF0cykgPT4ge1xuICAgICAgICAgICAgICAgICAgICBpZiAoKHBsYXRmb3JtLm5hbWUhLmluZGV4T2YoJ0Nocm9tZScpICE9PSAtMSkgfHwgKHBsYXRmb3JtLm5hbWUhLmluZGV4T2YoJ09wZXJhJykgIT09IC0xKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGxvY2FsQ2FuZGlkYXRlSWQsIHJlbW90ZUNhbmRpZGF0ZUlkLCBnb29nQ2FuZGlkYXRlUGFpcjtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGxvY2FsQ2FuZGlkYXRlcyA9IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgcmVtb3RlQ2FuZGlkYXRlcyA9IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChjb25zdCBrZXkgaW4gc3RhdHMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBzdGF0ID0gc3RhdHNba2V5XTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoc3RhdC50eXBlID09PSAnbG9jYWxjYW5kaWRhdGUnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxvY2FsQ2FuZGlkYXRlc1tzdGF0LmlkXSA9IHN0YXQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChzdGF0LnR5cGUgPT09ICdyZW1vdGVjYW5kaWRhdGUnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlbW90ZUNhbmRpZGF0ZXNbc3RhdC5pZF0gPSBzdGF0O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoc3RhdC50eXBlID09PSAnZ29vZ0NhbmRpZGF0ZVBhaXInICYmIChzdGF0Lmdvb2dBY3RpdmVDb25uZWN0aW9uID09PSAndHJ1ZScpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdvb2dDYW5kaWRhdGVQYWlyID0gc3RhdDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbG9jYWxDYW5kaWRhdGVJZCA9IHN0YXQubG9jYWxDYW5kaWRhdGVJZDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3RlQ2FuZGlkYXRlSWQgPSBzdGF0LnJlbW90ZUNhbmRpZGF0ZUlkO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBmaW5hbExvY2FsQ2FuZGlkYXRlID0gbG9jYWxDYW5kaWRhdGVzW2xvY2FsQ2FuZGlkYXRlSWRdO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCEhZmluYWxMb2NhbENhbmRpZGF0ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGNhbmRMaXN0ID0gdGhpcy5zdHJlYW0uZ2V0TG9jYWxJY2VDYW5kaWRhdGVMaXN0KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgY2FuZCA9IGNhbmRMaXN0LmZpbHRlcigoYzogUlRDSWNlQ2FuZGlkYXRlKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAoISFjLmNhbmRpZGF0ZSAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5jYW5kaWRhdGUuaW5kZXhPZihmaW5hbExvY2FsQ2FuZGlkYXRlLmlwQWRkcmVzcykgPj0gMCAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5jYW5kaWRhdGUuaW5kZXhPZihmaW5hbExvY2FsQ2FuZGlkYXRlLnBvcnROdW1iZXIpID49IDAgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuY2FuZGlkYXRlLmluZGV4T2YoZmluYWxMb2NhbENhbmRpZGF0ZS5wcmlvcml0eSkgPj0gMCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZmluYWxMb2NhbENhbmRpZGF0ZS5yYXcgPSAhIWNhbmRbMF0gPyBjYW5kWzBdLmNhbmRpZGF0ZSA6ICdFUlJPUjogQ2Fubm90IGZpbmQgbG9jYWwgY2FuZGlkYXRlIGluIGxpc3Qgb2Ygc2VudCBJQ0UgY2FuZGlkYXRlcyc7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbmFsTG9jYWxDYW5kaWRhdGUgPSAnRVJST1I6IE5vIGFjdGl2ZSBsb2NhbCBJQ0UgY2FuZGlkYXRlLiBQcm9iYWJseSBJQ0UtVENQIGlzIGJlaW5nIHVzZWQnO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICBsZXQgZmluYWxSZW1vdGVDYW5kaWRhdGUgPSByZW1vdGVDYW5kaWRhdGVzW3JlbW90ZUNhbmRpZGF0ZUlkXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghIWZpbmFsUmVtb3RlQ2FuZGlkYXRlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgY2FuZExpc3QgPSB0aGlzLnN0cmVhbS5nZXRSZW1vdGVJY2VDYW5kaWRhdGVMaXN0KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgY2FuZCA9IGNhbmRMaXN0LmZpbHRlcigoYzogUlRDSWNlQ2FuZGlkYXRlKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAoISFjLmNhbmRpZGF0ZSAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5jYW5kaWRhdGUuaW5kZXhPZihmaW5hbFJlbW90ZUNhbmRpZGF0ZS5pcEFkZHJlc3MpID49IDAgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuY2FuZGlkYXRlLmluZGV4T2YoZmluYWxSZW1vdGVDYW5kaWRhdGUucG9ydE51bWJlcikgPj0gMCAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5jYW5kaWRhdGUuaW5kZXhPZihmaW5hbFJlbW90ZUNhbmRpZGF0ZS5wcmlvcml0eSkgPj0gMCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZmluYWxSZW1vdGVDYW5kaWRhdGUucmF3ID0gISFjYW5kWzBdID8gY2FuZFswXS5jYW5kaWRhdGUgOiAnRVJST1I6IENhbm5vdCBmaW5kIHJlbW90ZSBjYW5kaWRhdGUgaW4gbGlzdCBvZiByZWNlaXZlZCBJQ0UgY2FuZGlkYXRlcyc7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbmFsUmVtb3RlQ2FuZGlkYXRlID0gJ0VSUk9SOiBObyBhY3RpdmUgcmVtb3RlIElDRSBjYW5kaWRhdGUuIFByb2JhYmx5IElDRS1UQ1AgaXMgYmVpbmcgdXNlZCc7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdvb2dDYW5kaWRhdGVQYWlyLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxvY2FsQ2FuZGlkYXRlOiBmaW5hbExvY2FsQ2FuZGlkYXRlLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlbW90ZUNhbmRpZGF0ZTogZmluYWxSZW1vdGVDYW5kaWRhdGVcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KCdTZWxlY3RlZCBJQ0UgY2FuZGlkYXRlIGluZm8gb25seSBhdmFpbGFibGUgZm9yIENocm9tZScpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAoZXJyb3IpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBzZW5kU3RhdHNUb0h0dHBFbmRwb2ludChpbnN0cnVtZW50YXRpb24pOiB2b2lkIHtcblxuICAgICAgICBjb25zdCBzZW5kUG9zdCA9IChqc29uKSA9PiB7XG4gICAgICAgICAgICBjb25zdCBodHRwOiBYTUxIdHRwUmVxdWVzdCA9IG5ldyBYTUxIdHRwUmVxdWVzdCgpO1xuICAgICAgICAgICAgY29uc3QgdXJsOiBzdHJpbmcgPSBpbnN0cnVtZW50YXRpb24ud2VicnRjLmh0dHBFbmRwb2ludDtcbiAgICAgICAgICAgIGh0dHAub3BlbignUE9TVCcsIHVybCwgdHJ1ZSk7XG5cbiAgICAgICAgICAgIGh0dHAuc2V0UmVxdWVzdEhlYWRlcignQ29udGVudC10eXBlJywgJ2FwcGxpY2F0aW9uL2pzb24nKTtcblxuICAgICAgICAgICAgaHR0cC5vbnJlYWR5c3RhdGVjaGFuZ2UgPSAoKSA9PiB7IC8vIENhbGwgYSBmdW5jdGlvbiB3aGVuIHRoZSBzdGF0ZSBjaGFuZ2VzLlxuICAgICAgICAgICAgICAgIGlmIChodHRwLnJlYWR5U3RhdGUgPT09IDQgJiYgaHR0cC5zdGF0dXMgPT09IDIwMCkge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmxvZygnV2ViUnRjIHN0YXRzIHN1Y2Nlc3NmdWxseSBzZW50IHRvICcgKyB1cmwgKyAnIGZvciBzdHJlYW0gJyArIHRoaXMuc3RyZWFtLnN0cmVhbUlkICsgJyBvZiBjb25uZWN0aW9uICcgKyB0aGlzLnN0cmVhbS5jb25uZWN0aW9uLmNvbm5lY3Rpb25JZCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGh0dHAuc2VuZChqc29uKTtcbiAgICAgICAgfTtcblxuICAgICAgICBjb25zdCBmID0gKHN0YXRzKSA9PiB7XG5cbiAgICAgICAgICAgIGlmIChwbGF0Zm9ybS5uYW1lIS5pbmRleE9mKCdGaXJlZm94JykgIT09IC0xKSB7XG4gICAgICAgICAgICAgICAgc3RhdHMuZm9yRWFjaCgoc3RhdCkgPT4ge1xuXG4gICAgICAgICAgICAgICAgICAgIGxldCBqc29uID0ge307XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKChzdGF0LnR5cGUgPT09ICdpbmJvdW5kLXJ0cCcpICYmXG4gICAgICAgICAgICAgICAgICAgICAgICAoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gQXZvaWQgZmlyZWZveCBlbXB0eSBvdXRib3VuZC1ydHAgc3RhdGlzdGljc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0YXQubmFja0NvdW50ICE9PSBudWxsICYmXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhdC5pc1JlbW90ZSA9PT0gZmFsc2UgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGF0LmlkLnN0YXJ0c1dpdGgoJ2luYm91bmQnKSAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0YXQucmVtb3RlSWQuc3RhcnRzV2l0aCgnaW5ib3VuZCcpXG4gICAgICAgICAgICAgICAgICAgICAgICApKSB7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG1ldHJpY0lkID0gJ3dlYnJ0Y19pbmJvdW5kXycgKyBzdGF0Lm1lZGlhVHlwZSArICdfJyArIHN0YXQuc3NyYztcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGppdCA9IHN0YXQuaml0dGVyICogMTAwMDtcblxuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgbWV0cmljcyA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBieXRlc1JlY2VpdmVkOiAoc3RhdC5ieXRlc1JlY2VpdmVkIC0gdGhpcy5zdGF0cy5pbmJvdW5kW3N0YXQubWVkaWFUeXBlXS5ieXRlc1JlY2VpdmVkKSAvIHRoaXMuc3RhdHNJbnRlcnZhbCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBqaXR0ZXI6IGppdCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYWNrZXRzUmVjZWl2ZWQ6IChzdGF0LnBhY2tldHNSZWNlaXZlZCAtIHRoaXMuc3RhdHMuaW5ib3VuZFtzdGF0Lm1lZGlhVHlwZV0ucGFja2V0c1JlY2VpdmVkKSAvIHRoaXMuc3RhdHNJbnRlcnZhbCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYWNrZXRzTG9zdDogKHN0YXQucGFja2V0c0xvc3QgLSB0aGlzLnN0YXRzLmluYm91bmRbc3RhdC5tZWRpYVR5cGVdLnBhY2tldHNMb3N0KSAvIHRoaXMuc3RhdHNJbnRlcnZhbFxuICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHVuaXRzID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ5dGVzUmVjZWl2ZWQ6ICdieXRlcycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaml0dGVyOiAnbXMnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhY2tldHNSZWNlaXZlZDogJ3BhY2tldHMnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhY2tldHNMb3N0OiAncGFja2V0cydcbiAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoc3RhdC5tZWRpYVR5cGUgPT09ICd2aWRlbycpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXRyaWNzWydmcmFtZXNEZWNvZGVkJ10gPSAoc3RhdC5mcmFtZXNEZWNvZGVkIC0gdGhpcy5zdGF0cy5pbmJvdW5kLnZpZGVvLmZyYW1lc0RlY29kZWQpIC8gdGhpcy5zdGF0c0ludGVydmFsO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1ldHJpY3NbJ25hY2tDb3VudCddID0gKHN0YXQubmFja0NvdW50IC0gdGhpcy5zdGF0cy5pbmJvdW5kLnZpZGVvLm5hY2tDb3VudCkgLyB0aGlzLnN0YXRzSW50ZXJ2YWw7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdW5pdHNbJ2ZyYW1lc0RlY29kZWQnXSA9ICdmcmFtZXMnO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVuaXRzWyduYWNrQ291bnQnXSA9ICdwYWNrZXRzJztcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdHMuaW5ib3VuZC52aWRlby5mcmFtZXNEZWNvZGVkID0gc3RhdC5mcmFtZXNEZWNvZGVkO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdHMuaW5ib3VuZC52aWRlby5uYWNrQ291bnQgPSBzdGF0Lm5hY2tDb3VudDtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0cy5pbmJvdW5kW3N0YXQubWVkaWFUeXBlXS5ieXRlc1JlY2VpdmVkID0gc3RhdC5ieXRlc1JlY2VpdmVkO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0cy5pbmJvdW5kW3N0YXQubWVkaWFUeXBlXS5wYWNrZXRzUmVjZWl2ZWQgPSBzdGF0LnBhY2tldHNSZWNlaXZlZDtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdHMuaW5ib3VuZFtzdGF0Lm1lZGlhVHlwZV0ucGFja2V0c0xvc3QgPSBzdGF0LnBhY2tldHNMb3N0O1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBqc29uID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICdAdGltZXN0YW1wJzogbmV3IERhdGUoc3RhdC50aW1lc3RhbXApLnRvSVNPU3RyaW5nKCksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJ2V4ZWMnOiBpbnN0cnVtZW50YXRpb24uZXhlYyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAnY29tcG9uZW50JzogaW5zdHJ1bWVudGF0aW9uLmNvbXBvbmVudCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAnc3RyZWFtJzogJ3dlYlJ0YycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJ3R5cGUnOiBtZXRyaWNJZCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAnc3RyZWFtX3R5cGUnOiAnY29tcG9zZWRfbWV0cmljcycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJ3VuaXRzJzogdW5pdHNcbiAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICBqc29uW21ldHJpY0lkXSA9IG1ldHJpY3M7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIHNlbmRQb3N0KEpTT04uc3RyaW5naWZ5KGpzb24pKTtcblxuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKChzdGF0LnR5cGUgPT09ICdvdXRib3VuZC1ydHAnKSAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEF2b2lkIGZpcmVmb3ggZW1wdHkgaW5ib3VuZC1ydHAgc3RhdGlzdGljc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0YXQuaXNSZW1vdGUgPT09IGZhbHNlICYmXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhdC5pZC50b0xvd2VyQ2FzZSgpLmluY2x1ZGVzKCdvdXRib3VuZCcpXG4gICAgICAgICAgICAgICAgICAgICAgICApKSB7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG1ldHJpY0lkID0gJ3dlYnJ0Y19vdXRib3VuZF8nICsgc3RhdC5tZWRpYVR5cGUgKyAnXycgKyBzdGF0LnNzcmM7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG1ldHJpY3MgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnl0ZXNTZW50OiAoc3RhdC5ieXRlc1NlbnQgLSB0aGlzLnN0YXRzLm91dGJvdW5kW3N0YXQubWVkaWFUeXBlXS5ieXRlc1NlbnQpIC8gdGhpcy5zdGF0c0ludGVydmFsLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhY2tldHNTZW50OiAoc3RhdC5wYWNrZXRzU2VudCAtIHRoaXMuc3RhdHMub3V0Ym91bmRbc3RhdC5tZWRpYVR5cGVdLnBhY2tldHNTZW50KSAvIHRoaXMuc3RhdHNJbnRlcnZhbFxuICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHVuaXRzID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ5dGVzU2VudDogJ2J5dGVzJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYWNrZXRzU2VudDogJ3BhY2tldHMnXG4gICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHN0YXQubWVkaWFUeXBlID09PSAndmlkZW8nKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbWV0cmljc1snZnJhbWVzRW5jb2RlZCddID0gKHN0YXQuZnJhbWVzRW5jb2RlZCAtIHRoaXMuc3RhdHMub3V0Ym91bmQudmlkZW8uZnJhbWVzRW5jb2RlZCkgLyB0aGlzLnN0YXRzSW50ZXJ2YWw7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdW5pdHNbJ2ZyYW1lc0VuY29kZWQnXSA9ICdmcmFtZXMnO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0cy5vdXRib3VuZC52aWRlby5mcmFtZXNFbmNvZGVkID0gc3RhdC5mcmFtZXNFbmNvZGVkO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXRzLm91dGJvdW5kW3N0YXQubWVkaWFUeXBlXS5ieXRlc1NlbnQgPSBzdGF0LmJ5dGVzU2VudDtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdHMub3V0Ym91bmRbc3RhdC5tZWRpYVR5cGVdLnBhY2tldHNTZW50ID0gc3RhdC5wYWNrZXRzU2VudDtcblxuICAgICAgICAgICAgICAgICAgICAgICAganNvbiA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAnQHRpbWVzdGFtcCc6IG5ldyBEYXRlKHN0YXQudGltZXN0YW1wKS50b0lTT1N0cmluZygpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICdleGVjJzogaW5zdHJ1bWVudGF0aW9uLmV4ZWMsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJ2NvbXBvbmVudCc6IGluc3RydW1lbnRhdGlvbi5jb21wb25lbnQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJ3N0cmVhbSc6ICd3ZWJSdGMnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICd0eXBlJzogbWV0cmljSWQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJ3N0cmVhbV90eXBlJzogJ2NvbXBvc2VkX21ldHJpY3MnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICd1bml0cyc6IHVuaXRzXG4gICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAganNvblttZXRyaWNJZF0gPSBtZXRyaWNzO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBzZW5kUG9zdChKU09OLnN0cmluZ2lmeShqc29uKSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoKHBsYXRmb3JtLm5hbWUhLmluZGV4T2YoJ0Nocm9tZScpICE9PSAtMSkgfHwgKHBsYXRmb3JtLm5hbWUhLmluZGV4T2YoJ09wZXJhJykgIT09IC0xKSkge1xuICAgICAgICAgICAgICAgIGZvciAoY29uc3Qga2V5IG9mIE9iamVjdC5rZXlzKHN0YXRzKSkge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBzdGF0ID0gc3RhdHNba2V5XTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHN0YXQudHlwZSA9PT0gJ3NzcmMnKSB7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBqc29uID0ge307XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICgnYnl0ZXNSZWNlaXZlZCcgaW4gc3RhdCAmJiAoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKHN0YXQubWVkaWFUeXBlID09PSAnYXVkaW8nICYmICdhdWRpb091dHB1dExldmVsJyBpbiBzdGF0KSB8fFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIChzdGF0Lm1lZGlhVHlwZSA9PT0gJ3ZpZGVvJyAmJiAncXBTdW0nIGluIHN0YXQpXG4gICAgICAgICAgICAgICAgICAgICAgICApKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaW5ib3VuZC1ydHBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBtZXRyaWNJZCA9ICd3ZWJydGNfaW5ib3VuZF8nICsgc3RhdC5tZWRpYVR5cGUgKyAnXycgKyBzdGF0LnNzcmM7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBtZXRyaWNzID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBieXRlc1JlY2VpdmVkOiAoc3RhdC5ieXRlc1JlY2VpdmVkIC0gdGhpcy5zdGF0cy5pbmJvdW5kW3N0YXQubWVkaWFUeXBlXS5ieXRlc1JlY2VpdmVkKSAvIHRoaXMuc3RhdHNJbnRlcnZhbCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaml0dGVyOiBzdGF0Lmdvb2dKaXR0ZXJCdWZmZXJNcyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFja2V0c1JlY2VpdmVkOiAoc3RhdC5wYWNrZXRzUmVjZWl2ZWQgLSB0aGlzLnN0YXRzLmluYm91bmRbc3RhdC5tZWRpYVR5cGVdLnBhY2tldHNSZWNlaXZlZCkgLyB0aGlzLnN0YXRzSW50ZXJ2YWwsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhY2tldHNMb3N0OiAoc3RhdC5wYWNrZXRzTG9zdCAtIHRoaXMuc3RhdHMuaW5ib3VuZFtzdGF0Lm1lZGlhVHlwZV0ucGFja2V0c0xvc3QpIC8gdGhpcy5zdGF0c0ludGVydmFsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB1bml0cyA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnl0ZXNSZWNlaXZlZDogJ2J5dGVzJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaml0dGVyOiAnbXMnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYWNrZXRzUmVjZWl2ZWQ6ICdwYWNrZXRzJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFja2V0c0xvc3Q6ICdwYWNrZXRzJ1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHN0YXQubWVkaWFUeXBlID09PSAndmlkZW8nKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1ldHJpY3NbJ2ZyYW1lc0RlY29kZWQnXSA9IChzdGF0LmZyYW1lc0RlY29kZWQgLSB0aGlzLnN0YXRzLmluYm91bmQudmlkZW8uZnJhbWVzRGVjb2RlZCkgLyB0aGlzLnN0YXRzSW50ZXJ2YWw7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1ldHJpY3NbJ25hY2tDb3VudCddID0gKHN0YXQuZ29vZ05hY2tzU2VudCAtIHRoaXMuc3RhdHMuaW5ib3VuZC52aWRlby5uYWNrQ291bnQpIC8gdGhpcy5zdGF0c0ludGVydmFsO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1bml0c1snZnJhbWVzRGVjb2RlZCddID0gJ2ZyYW1lcyc7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVuaXRzWyduYWNrQ291bnQnXSA9ICdwYWNrZXRzJztcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXRzLmluYm91bmQudmlkZW8uZnJhbWVzRGVjb2RlZCA9IHN0YXQuZnJhbWVzRGVjb2RlZDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0cy5pbmJvdW5kLnZpZGVvLm5hY2tDb3VudCA9IHN0YXQuZ29vZ05hY2tzU2VudDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXRzLmluYm91bmRbc3RhdC5tZWRpYVR5cGVdLmJ5dGVzUmVjZWl2ZWQgPSBzdGF0LmJ5dGVzUmVjZWl2ZWQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0cy5pbmJvdW5kW3N0YXQubWVkaWFUeXBlXS5wYWNrZXRzUmVjZWl2ZWQgPSBzdGF0LnBhY2tldHNSZWNlaXZlZDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXRzLmluYm91bmRbc3RhdC5tZWRpYVR5cGVdLnBhY2tldHNMb3N0ID0gc3RhdC5wYWNrZXRzTG9zdDtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGpzb24gPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdAdGltZXN0YW1wJzogbmV3IERhdGUoc3RhdC50aW1lc3RhbXApLnRvSVNPU3RyaW5nKCksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdleGVjJzogaW5zdHJ1bWVudGF0aW9uLmV4ZWMsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdjb21wb25lbnQnOiBpbnN0cnVtZW50YXRpb24uY29tcG9uZW50LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnc3RyZWFtJzogJ3dlYlJ0YycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICd0eXBlJzogbWV0cmljSWQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdzdHJlYW1fdHlwZSc6ICdjb21wb3NlZF9tZXRyaWNzJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ3VuaXRzJzogdW5pdHNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGpzb25bbWV0cmljSWRdID0gbWV0cmljcztcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbmRQb3N0KEpTT04uc3RyaW5naWZ5KGpzb24pKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoJ2J5dGVzU2VudCcgaW4gc3RhdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIG91dGJvdW5kLXJ0cFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG1ldHJpY0lkID0gJ3dlYnJ0Y19vdXRib3VuZF8nICsgc3RhdC5tZWRpYVR5cGUgKyAnXycgKyBzdGF0LnNzcmM7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBtZXRyaWNzID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBieXRlc1NlbnQ6IChzdGF0LmJ5dGVzU2VudCAtIHRoaXMuc3RhdHMub3V0Ym91bmRbc3RhdC5tZWRpYVR5cGVdLmJ5dGVzU2VudCkgLyB0aGlzLnN0YXRzSW50ZXJ2YWwsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhY2tldHNTZW50OiAoc3RhdC5wYWNrZXRzU2VudCAtIHRoaXMuc3RhdHMub3V0Ym91bmRbc3RhdC5tZWRpYVR5cGVdLnBhY2tldHNTZW50KSAvIHRoaXMuc3RhdHNJbnRlcnZhbFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgdW5pdHMgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ5dGVzU2VudDogJ2J5dGVzJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFja2V0c1NlbnQ6ICdwYWNrZXRzJ1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHN0YXQubWVkaWFUeXBlID09PSAndmlkZW8nKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1ldHJpY3NbJ2ZyYW1lc0VuY29kZWQnXSA9IChzdGF0LmZyYW1lc0VuY29kZWQgLSB0aGlzLnN0YXRzLm91dGJvdW5kLnZpZGVvLmZyYW1lc0VuY29kZWQpIC8gdGhpcy5zdGF0c0ludGVydmFsO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1bml0c1snZnJhbWVzRW5jb2RlZCddID0gJ2ZyYW1lcyc7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0cy5vdXRib3VuZC52aWRlby5mcmFtZXNFbmNvZGVkID0gc3RhdC5mcmFtZXNFbmNvZGVkO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdHMub3V0Ym91bmRbc3RhdC5tZWRpYVR5cGVdLmJ5dGVzU2VudCA9IHN0YXQuYnl0ZXNTZW50O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdHMub3V0Ym91bmRbc3RhdC5tZWRpYVR5cGVdLnBhY2tldHNTZW50ID0gc3RhdC5wYWNrZXRzU2VudDtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGpzb24gPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdAdGltZXN0YW1wJzogbmV3IERhdGUoc3RhdC50aW1lc3RhbXApLnRvSVNPU3RyaW5nKCksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdleGVjJzogaW5zdHJ1bWVudGF0aW9uLmV4ZWMsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdjb21wb25lbnQnOiBpbnN0cnVtZW50YXRpb24uY29tcG9uZW50LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnc3RyZWFtJzogJ3dlYlJ0YycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICd0eXBlJzogbWV0cmljSWQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdzdHJlYW1fdHlwZSc6ICdjb21wb3NlZF9tZXRyaWNzJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ3VuaXRzJzogdW5pdHNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGpzb25bbWV0cmljSWRdID0gbWV0cmljcztcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbmRQb3N0KEpTT04uc3RyaW5naWZ5KGpzb24pKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcblxuICAgICAgICB0aGlzLmdldFN0YXRzQWdub3N0aWModGhpcy5zdHJlYW0uZ2V0UlRDUGVlckNvbm5lY3Rpb24oKSwgZiwgKGVycm9yKSA9PiB7IGNvbnNvbGUubG9nKGVycm9yKTsgfSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBzdGFuZGFyZGl6ZVJlcG9ydChyZXNwb25zZSkge1xuICAgICAgICBjb25zb2xlLmxvZyhyZXNwb25zZSk7XG4gICAgICAgIGNvbnN0IHN0YW5kYXJkUmVwb3J0ID0ge307XG5cbiAgICAgICAgaWYgKHBsYXRmb3JtLm5hbWUhLmluZGV4T2YoJ0ZpcmVmb3gnKSAhPT0gLTEpIHtcbiAgICAgICAgICAgIE9iamVjdC5rZXlzKHJlc3BvbnNlKS5mb3JFYWNoKGtleSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5sb2cocmVzcG9uc2Vba2V5XSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHJldHVybiByZXNwb25zZTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJlc3BvbnNlLnJlc3VsdCgpLmZvckVhY2gocmVwb3J0ID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHN0YW5kYXJkU3RhdHMgPSB7XG4gICAgICAgICAgICAgICAgaWQ6IHJlcG9ydC5pZCxcbiAgICAgICAgICAgICAgICB0aW1lc3RhbXA6IHJlcG9ydC50aW1lc3RhbXAsXG4gICAgICAgICAgICAgICAgdHlwZTogcmVwb3J0LnR5cGVcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICByZXBvcnQubmFtZXMoKS5mb3JFYWNoKChuYW1lKSA9PiB7XG4gICAgICAgICAgICAgICAgc3RhbmRhcmRTdGF0c1tuYW1lXSA9IHJlcG9ydC5zdGF0KG5hbWUpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBzdGFuZGFyZFJlcG9ydFtzdGFuZGFyZFN0YXRzLmlkXSA9IHN0YW5kYXJkU3RhdHM7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHJldHVybiBzdGFuZGFyZFJlcG9ydDtcbiAgICB9XG5cbiAgICBwcml2YXRlIGdldFN0YXRzQWdub3N0aWMocGMsIHN1Y2Nlc3NDYiwgZmFpbHVyZUNiKSB7XG4gICAgICAgIGlmIChwbGF0Zm9ybS5uYW1lIS5pbmRleE9mKCdGaXJlZm94JykgIT09IC0xKSB7XG4gICAgICAgICAgICAvLyBnZXRTdGF0cyB0YWtlcyBhcmdzIGluIGRpZmZlcmVudCBvcmRlciBpbiBDaHJvbWUgYW5kIEZpcmVmb3hcbiAgICAgICAgICAgIHJldHVybiBwYy5nZXRTdGF0cyhudWxsKS50aGVuKHJlc3BvbnNlID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCByZXBvcnQgPSB0aGlzLnN0YW5kYXJkaXplUmVwb3J0KHJlc3BvbnNlKTtcbiAgICAgICAgICAgICAgICBzdWNjZXNzQ2IocmVwb3J0KTtcbiAgICAgICAgICAgIH0pLmNhdGNoKGZhaWx1cmVDYik7XG4gICAgICAgIH0gZWxzZSBpZiAoKHBsYXRmb3JtLm5hbWUhLmluZGV4T2YoJ0Nocm9tZScpICE9PSAtMSkgfHwgKHBsYXRmb3JtLm5hbWUhLmluZGV4T2YoJ09wZXJhJykgIT09IC0xKSkge1xuICAgICAgICAgICAgLy8gSW4gQ2hyb21lLCB0aGUgZmlyc3QgdHdvIGFyZ3VtZW50cyBhcmUgcmV2ZXJzZWRcbiAgICAgICAgICAgIHJldHVybiBwYy5nZXRTdGF0cygocmVzcG9uc2UpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCByZXBvcnQgPSB0aGlzLnN0YW5kYXJkaXplUmVwb3J0KHJlc3BvbnNlKTtcbiAgICAgICAgICAgICAgICBzdWNjZXNzQ2IocmVwb3J0KTtcbiAgICAgICAgICAgIH0sIG51bGwsIGZhaWx1cmVDYik7XG4gICAgICAgIH1cbiAgICB9XG5cbn0iXX0=
diff --git a/openvidu-insecure-angular/package.json b/openvidu-insecure-angular/package.json
index 5775f2b62..32d860e09 100644
--- a/openvidu-insecure-angular/package.json
+++ b/openvidu-insecure-angular/package.json
@@ -14,7 +14,7 @@
"@angular/platform-browser": "6.0.9",
"@angular/platform-browser-dynamic": "6.0.9",
"core-js": "2.5.7",
- "openvidu-browser": "2.3.0",
+ "openvidu-browser": "2.4.0",
"zone.js": "0.8.26"
},
"devDependencies": {
diff --git a/openvidu-insecure-js/web/index.html b/openvidu-insecure-js/web/index.html
index bb0498021..a9799a158 100644
--- a/openvidu-insecure-js/web/index.html
+++ b/openvidu-insecure-js/web/index.html
@@ -14,7 +14,7 @@
-
+
diff --git a/openvidu-insecure-js/web/openvidu-browser-2.3.0.js b/openvidu-insecure-js/web/openvidu-browser-2.3.0.js
deleted file mode 100644
index 83a78adcf..000000000
--- a/openvidu-insecure-js/web/openvidu-browser-2.3.0.js
+++ /dev/null
@@ -1,7700 +0,0 @@
-(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 1)
- er = arguments[1];
- if (er instanceof Error) {
- throw er; // Unhandled 'error' event
- } else {
- // At least give some kind of context to the user
- var err = new Error('Unhandled "error" event. (' + er + ')');
- err.context = er;
- throw err;
- }
- return false;
- }
-
- handler = events[type];
-
- if (!handler)
- return false;
-
- var isFn = typeof handler === 'function';
- len = arguments.length;
- switch (len) {
- // fast cases
- case 1:
- emitNone(handler, isFn, this);
- break;
- case 2:
- emitOne(handler, isFn, this, arguments[1]);
- break;
- case 3:
- emitTwo(handler, isFn, this, arguments[1], arguments[2]);
- break;
- case 4:
- emitThree(handler, isFn, this, arguments[1], arguments[2], arguments[3]);
- break;
- // slower
- default:
- args = new Array(len - 1);
- for (i = 1; i < len; i++)
- args[i - 1] = arguments[i];
- emitMany(handler, isFn, this, args);
- }
-
- return true;
-};
-
-function _addListener(target, type, listener, prepend) {
- var m;
- var events;
- var existing;
-
- if (typeof listener !== 'function')
- throw new TypeError('"listener" argument must be a function');
-
- events = target._events;
- if (!events) {
- events = target._events = objectCreate(null);
- target._eventsCount = 0;
- } else {
- // To avoid recursion in the case that type === "newListener"! Before
- // adding it to the listeners, first emit "newListener".
- if (events.newListener) {
- target.emit('newListener', type,
- listener.listener ? listener.listener : listener);
-
- // Re-assign `events` because a newListener handler could have caused the
- // this._events to be assigned to a new object
- events = target._events;
- }
- existing = events[type];
- }
-
- if (!existing) {
- // Optimize the case of one listener. Don't need the extra array object.
- existing = events[type] = listener;
- ++target._eventsCount;
- } else {
- if (typeof existing === 'function') {
- // Adding the second element, need to change to array.
- existing = events[type] =
- prepend ? [listener, existing] : [existing, listener];
- } else {
- // If we've already got an array, just append.
- if (prepend) {
- existing.unshift(listener);
- } else {
- existing.push(listener);
- }
- }
-
- // Check for listener leak
- if (!existing.warned) {
- m = $getMaxListeners(target);
- if (m && m > 0 && existing.length > m) {
- existing.warned = true;
- var w = new Error('Possible EventEmitter memory leak detected. ' +
- existing.length + ' "' + String(type) + '" listeners ' +
- 'added. Use emitter.setMaxListeners() to ' +
- 'increase limit.');
- w.name = 'MaxListenersExceededWarning';
- w.emitter = target;
- w.type = type;
- w.count = existing.length;
- if (typeof console === 'object' && console.warn) {
- console.warn('%s: %s', w.name, w.message);
- }
- }
- }
- }
-
- return target;
-}
-
-EventEmitter.prototype.addListener = function addListener(type, listener) {
- return _addListener(this, type, listener, false);
-};
-
-EventEmitter.prototype.on = EventEmitter.prototype.addListener;
-
-EventEmitter.prototype.prependListener =
- function prependListener(type, listener) {
- return _addListener(this, type, listener, true);
- };
-
-function onceWrapper() {
- if (!this.fired) {
- this.target.removeListener(this.type, this.wrapFn);
- this.fired = true;
- switch (arguments.length) {
- case 0:
- return this.listener.call(this.target);
- case 1:
- return this.listener.call(this.target, arguments[0]);
- case 2:
- return this.listener.call(this.target, arguments[0], arguments[1]);
- case 3:
- return this.listener.call(this.target, arguments[0], arguments[1],
- arguments[2]);
- default:
- var args = new Array(arguments.length);
- for (var i = 0; i < args.length; ++i)
- args[i] = arguments[i];
- this.listener.apply(this.target, args);
- }
- }
-}
-
-function _onceWrap(target, type, listener) {
- var state = { fired: false, wrapFn: undefined, target: target, type: type, listener: listener };
- var wrapped = bind.call(onceWrapper, state);
- wrapped.listener = listener;
- state.wrapFn = wrapped;
- return wrapped;
-}
-
-EventEmitter.prototype.once = function once(type, listener) {
- if (typeof listener !== 'function')
- throw new TypeError('"listener" argument must be a function');
- this.on(type, _onceWrap(this, type, listener));
- return this;
-};
-
-EventEmitter.prototype.prependOnceListener =
- function prependOnceListener(type, listener) {
- if (typeof listener !== 'function')
- throw new TypeError('"listener" argument must be a function');
- this.prependListener(type, _onceWrap(this, type, listener));
- return this;
- };
-
-// Emits a 'removeListener' event if and only if the listener was removed.
-EventEmitter.prototype.removeListener =
- function removeListener(type, listener) {
- var list, events, position, i, originalListener;
-
- if (typeof listener !== 'function')
- throw new TypeError('"listener" argument must be a function');
-
- events = this._events;
- if (!events)
- return this;
-
- list = events[type];
- if (!list)
- return this;
-
- if (list === listener || list.listener === listener) {
- if (--this._eventsCount === 0)
- this._events = objectCreate(null);
- else {
- delete events[type];
- if (events.removeListener)
- this.emit('removeListener', type, list.listener || listener);
- }
- } else if (typeof list !== 'function') {
- position = -1;
-
- for (i = list.length - 1; i >= 0; i--) {
- if (list[i] === listener || list[i].listener === listener) {
- originalListener = list[i].listener;
- position = i;
- break;
- }
- }
-
- if (position < 0)
- return this;
-
- if (position === 0)
- list.shift();
- else
- spliceOne(list, position);
-
- if (list.length === 1)
- events[type] = list[0];
-
- if (events.removeListener)
- this.emit('removeListener', type, originalListener || listener);
- }
-
- return this;
- };
-
-EventEmitter.prototype.removeAllListeners =
- function removeAllListeners(type) {
- var listeners, events, i;
-
- events = this._events;
- if (!events)
- return this;
-
- // not listening for removeListener, no need to emit
- if (!events.removeListener) {
- if (arguments.length === 0) {
- this._events = objectCreate(null);
- this._eventsCount = 0;
- } else if (events[type]) {
- if (--this._eventsCount === 0)
- this._events = objectCreate(null);
- else
- delete events[type];
- }
- return this;
- }
-
- // emit removeListener for all listeners on all events
- if (arguments.length === 0) {
- var keys = objectKeys(events);
- var key;
- for (i = 0; i < keys.length; ++i) {
- key = keys[i];
- if (key === 'removeListener') continue;
- this.removeAllListeners(key);
- }
- this.removeAllListeners('removeListener');
- this._events = objectCreate(null);
- this._eventsCount = 0;
- return this;
- }
-
- listeners = events[type];
-
- if (typeof listeners === 'function') {
- this.removeListener(type, listeners);
- } else if (listeners) {
- // LIFO order
- for (i = listeners.length - 1; i >= 0; i--) {
- this.removeListener(type, listeners[i]);
- }
- }
-
- return this;
- };
-
-function _listeners(target, type, unwrap) {
- var events = target._events;
-
- if (!events)
- return [];
-
- var evlistener = events[type];
- if (!evlistener)
- return [];
-
- if (typeof evlistener === 'function')
- return unwrap ? [evlistener.listener || evlistener] : [evlistener];
-
- return unwrap ? unwrapListeners(evlistener) : arrayClone(evlistener, evlistener.length);
-}
-
-EventEmitter.prototype.listeners = function listeners(type) {
- return _listeners(this, type, true);
-};
-
-EventEmitter.prototype.rawListeners = function rawListeners(type) {
- return _listeners(this, type, false);
-};
-
-EventEmitter.listenerCount = function(emitter, type) {
- if (typeof emitter.listenerCount === 'function') {
- return emitter.listenerCount(type);
- } else {
- return listenerCount.call(emitter, type);
- }
-};
-
-EventEmitter.prototype.listenerCount = listenerCount;
-function listenerCount(type) {
- var events = this._events;
-
- if (events) {
- var evlistener = events[type];
-
- if (typeof evlistener === 'function') {
- return 1;
- } else if (evlistener) {
- return evlistener.length;
- }
- }
-
- return 0;
-}
-
-EventEmitter.prototype.eventNames = function eventNames() {
- return this._eventsCount > 0 ? Reflect.ownKeys(this._events) : [];
-};
-
-// About 1.5x faster than the two-arg version of Array#splice().
-function spliceOne(list, index) {
- for (var i = index, k = i + 1, n = list.length; k < n; i += 1, k += 1)
- list[i] = list[k];
- list.pop();
-}
-
-function arrayClone(arr, n) {
- var copy = new Array(n);
- for (var i = 0; i < n; ++i)
- copy[i] = arr[i];
- return copy;
-}
-
-function unwrapListeners(arr) {
- var ret = new Array(arr.length);
- for (var i = 0; i < ret.length; ++i) {
- ret[i] = arr[i].listener || arr[i];
- }
- return ret;
-}
-
-function objectCreatePolyfill(proto) {
- var F = function() {};
- F.prototype = proto;
- return new F;
-}
-function objectKeysPolyfill(obj) {
- var keys = [];
- for (var k in obj) if (Object.prototype.hasOwnProperty.call(obj, k)) {
- keys.push(k);
- }
- return k;
-}
-function functionBindPolyfill(context) {
- var fn = this;
- return function () {
- return fn.apply(context, arguments);
- };
-}
-
-},{}],2:[function(require,module,exports){
-/* jshint node: true */
-'use strict';
-
-var normalice = require('normalice');
-
-/**
- # freeice
-
- The `freeice` module is a simple way of getting random STUN or TURN server
- for your WebRTC application. The list of servers (just STUN at this stage)
- were sourced from this [gist](https://gist.github.com/zziuni/3741933).
-
- ## Example Use
-
- The following demonstrates how you can use `freeice` with
- [rtc-quickconnect](https://github.com/rtc-io/rtc-quickconnect):
-
- <<< examples/quickconnect.js
-
- As the `freeice` module generates ice servers in a list compliant with the
- WebRTC spec you will be able to use it with raw `RTCPeerConnection`
- constructors and other WebRTC libraries.
-
- ## Hey, don't use my STUN/TURN server!
-
- If for some reason your free STUN or TURN server ends up in the
- list of servers ([stun](https://github.com/DamonOehlman/freeice/blob/master/stun.json) or
- [turn](https://github.com/DamonOehlman/freeice/blob/master/turn.json))
- that is used in this module, you can feel
- free to open an issue on this repository and those servers will be removed
- within 24 hours (or sooner). This is the quickest and probably the most
- polite way to have something removed (and provides us some visibility
- if someone opens a pull request requesting that a server is added).
-
- ## Please add my server!
-
- If you have a server that you wish to add to the list, that's awesome! I'm
- sure I speak on behalf of a whole pile of WebRTC developers who say thanks.
- To get it into the list, feel free to either open a pull request or if you
- find that process a bit daunting then just create an issue requesting
- the addition of the server (make sure you provide all the details, and if
- you have a Terms of Service then including that in the PR/issue would be
- awesome).
-
- ## I know of a free server, can I add it?
-
- Sure, if you do your homework and make sure it is ok to use (I'm currently
- in the process of reviewing the terms of those STUN servers included from
- the original list). If it's ok to go, then please see the previous entry
- for how to add it.
-
- ## Current List of Servers
-
- * current as at the time of last `README.md` file generation
-
- ### STUN
-
- <<< stun.json
-
- ### TURN
-
- <<< turn.json
-
-**/
-
-var freeice = module.exports = function(opts) {
- // if a list of servers has been provided, then use it instead of defaults
- var servers = {
- stun: (opts || {}).stun || require('./stun.json'),
- turn: (opts || {}).turn || require('./turn.json')
- };
-
- var stunCount = (opts || {}).stunCount || 2;
- var turnCount = (opts || {}).turnCount || 0;
- var selected;
-
- function getServers(type, count) {
- var out = [];
- var input = [].concat(servers[type]);
- var idx;
-
- while (input.length && out.length < count) {
- idx = (Math.random() * input.length) | 0;
- out = out.concat(input.splice(idx, 1));
- }
-
- return out.map(function(url) {
- //If it's a not a string, don't try to "normalice" it otherwise using type:url will screw it up
- if ((typeof url !== 'string') && (! (url instanceof String))) {
- return url;
- } else {
- return normalice(type + ':' + url);
- }
- });
- }
-
- // add stun servers
- selected = [].concat(getServers('stun', stunCount));
-
- if (turnCount) {
- selected = selected.concat(getServers('turn', turnCount));
- }
-
- return selected;
-};
-
-},{"./stun.json":3,"./turn.json":4,"normalice":7}],3:[function(require,module,exports){
-module.exports=[
- "stun.l.google.com:19302",
- "stun1.l.google.com:19302",
- "stun2.l.google.com:19302",
- "stun3.l.google.com:19302",
- "stun4.l.google.com:19302",
- "stun.ekiga.net",
- "stun.ideasip.com",
- "stun.schlund.de",
- "stun.stunprotocol.org:3478",
- "stun.voiparound.com",
- "stun.voipbuster.com",
- "stun.voipstunt.com",
- "stun.voxgratia.org",
- "stun.services.mozilla.com"
-]
-
-},{}],4:[function(require,module,exports){
-module.exports=[]
-
-},{}],5:[function(require,module,exports){
-var WildEmitter = require('wildemitter');
-
-function getMaxVolume (analyser, fftBins) {
- var maxVolume = -Infinity;
- analyser.getFloatFrequencyData(fftBins);
-
- for(var i=4, ii=fftBins.length; i < ii; i++) {
- if (fftBins[i] > maxVolume && fftBins[i] < 0) {
- maxVolume = fftBins[i];
- }
- };
-
- return maxVolume;
-}
-
-
-var audioContextType;
-if (typeof window !== 'undefined') {
- audioContextType = window.AudioContext || window.webkitAudioContext;
-}
-// use a single audio context due to hardware limits
-var audioContext = null;
-module.exports = function(stream, options) {
- var harker = new WildEmitter();
-
-
- // make it not break in non-supported browsers
- if (!audioContextType) return harker;
-
- //Config
- var options = options || {},
- smoothing = (options.smoothing || 0.1),
- interval = (options.interval || 50),
- threshold = options.threshold,
- play = options.play,
- history = options.history || 10,
- running = true;
-
- //Setup Audio Context
- if (!audioContext) {
- audioContext = new audioContextType();
- }
- var sourceNode, fftBins, analyser;
-
- analyser = audioContext.createAnalyser();
- analyser.fftSize = 512;
- analyser.smoothingTimeConstant = smoothing;
- fftBins = new Float32Array(analyser.frequencyBinCount);
-
- if (stream.jquery) stream = stream[0];
- if (stream instanceof HTMLAudioElement || stream instanceof HTMLVideoElement) {
- //Audio Tag
- sourceNode = audioContext.createMediaElementSource(stream);
- if (typeof play === 'undefined') play = true;
- threshold = threshold || -50;
- } else {
- //WebRTC Stream
- sourceNode = audioContext.createMediaStreamSource(stream);
- threshold = threshold || -50;
- }
-
- sourceNode.connect(analyser);
- if (play) analyser.connect(audioContext.destination);
-
- harker.speaking = false;
-
- harker.suspend = function() {
- audioContext.suspend();
- }
- harker.resume = function() {
- audioContext.resume();
- }
- Object.defineProperty(harker, 'state', { get: function() {
- return audioContext.state;
- }});
- audioContext.onstatechange = function() {
- harker.emit('state_change', audioContext.state);
- }
-
- harker.setThreshold = function(t) {
- threshold = t;
- };
-
- harker.setInterval = function(i) {
- interval = i;
- };
-
- harker.stop = function() {
- running = false;
- harker.emit('volume_change', -100, threshold);
- if (harker.speaking) {
- harker.speaking = false;
- harker.emit('stopped_speaking');
- }
- analyser.disconnect();
- sourceNode.disconnect();
- };
- harker.speakingHistory = [];
- for (var i = 0; i < history; i++) {
- harker.speakingHistory.push(0);
- }
-
- // Poll the analyser node to determine if speaking
- // and emit events if changed
- var looper = function() {
- setTimeout(function() {
-
- //check if stop has been called
- if(!running) {
- return;
- }
-
- var currentVolume = getMaxVolume(analyser, fftBins);
-
- harker.emit('volume_change', currentVolume, threshold);
-
- var history = 0;
- if (currentVolume > threshold && !harker.speaking) {
- // trigger quickly, short history
- for (var i = harker.speakingHistory.length - 3; i < harker.speakingHistory.length; i++) {
- history += harker.speakingHistory[i];
- }
- if (history >= 2) {
- harker.speaking = true;
- harker.emit('speaking');
- }
- } else if (currentVolume < threshold && harker.speaking) {
- for (var i = 0; i < harker.speakingHistory.length; i++) {
- history += harker.speakingHistory[i];
- }
- if (history == 0) {
- harker.speaking = false;
- harker.emit('stopped_speaking');
- }
- }
- harker.speakingHistory.shift();
- harker.speakingHistory.push(0 + (currentVolume > threshold));
-
- looper();
- }, interval);
- };
- looper();
-
-
- return harker;
-}
-
-},{"wildemitter":14}],6:[function(require,module,exports){
-if (typeof Object.create === 'function') {
- // implementation from standard node.js 'util' module
- module.exports = function inherits(ctor, superCtor) {
- ctor.super_ = superCtor
- ctor.prototype = Object.create(superCtor.prototype, {
- constructor: {
- value: ctor,
- enumerable: false,
- writable: true,
- configurable: true
- }
- });
- };
-} else {
- // old school shim for old browsers
- module.exports = function inherits(ctor, superCtor) {
- ctor.super_ = superCtor
- var TempCtor = function () {}
- TempCtor.prototype = superCtor.prototype
- ctor.prototype = new TempCtor()
- ctor.prototype.constructor = ctor
- }
-}
-
-},{}],7:[function(require,module,exports){
-/**
- # normalice
-
- Normalize an ice server configuration object (or plain old string) into a format
- that is usable in all browsers supporting WebRTC. Primarily this module is designed
- to help with the transition of the `url` attribute of the configuration object to
- the `urls` attribute.
-
- ## Example Usage
-
- <<< examples/simple.js
-
-**/
-
-var protocols = [
- 'stun:',
- 'turn:'
-];
-
-module.exports = function(input) {
- var url = (input || {}).url || input;
- var protocol;
- var parts;
- var output = {};
-
- // if we don't have a string url, then allow the input to passthrough
- if (typeof url != 'string' && (! (url instanceof String))) {
- return input;
- }
-
- // trim the url string, and convert to an array
- url = url.trim();
-
- // if the protocol is not known, then passthrough
- protocol = protocols[protocols.indexOf(url.slice(0, 5))];
- if (! protocol) {
- return input;
- }
-
- // now let's attack the remaining url parts
- url = url.slice(5);
- parts = url.split('@');
-
- output.username = input.username;
- output.credential = input.credential;
- // if we have an authentication part, then set the credentials
- if (parts.length > 1) {
- url = parts[1];
- parts = parts[0].split(':');
-
- // add the output credential and username
- output.username = parts[0];
- output.credential = (input || {}).credential || parts[1] || '';
- }
-
- output.url = protocol + url;
- output.urls = [ output.url ];
-
- return output;
-};
-
-},{}],8:[function(require,module,exports){
-(function (global){
-/*!
- * Platform.js
- * Copyright 2014-2018 Benjamin Tan
- * Copyright 2011-2013 John-David Dalton
- * Available under MIT license
- */
-;(function() {
- 'use strict';
-
- /** Used to determine if values are of the language type `Object`. */
- var objectTypes = {
- 'function': true,
- 'object': true
- };
-
- /** Used as a reference to the global object. */
- var root = (objectTypes[typeof window] && window) || this;
-
- /** Backup possible global object. */
- var oldRoot = root;
-
- /** Detect free variable `exports`. */
- var freeExports = objectTypes[typeof exports] && exports;
-
- /** Detect free variable `module`. */
- var freeModule = objectTypes[typeof module] && module && !module.nodeType && module;
-
- /** Detect free variable `global` from Node.js or Browserified code and use it as `root`. */
- var freeGlobal = freeExports && freeModule && typeof global == 'object' && global;
- if (freeGlobal && (freeGlobal.global === freeGlobal || freeGlobal.window === freeGlobal || freeGlobal.self === freeGlobal)) {
- root = freeGlobal;
- }
-
- /**
- * Used as the maximum length of an array-like object.
- * See the [ES6 spec](http://people.mozilla.org/~jorendorff/es6-draft.html#sec-tolength)
- * for more details.
- */
- var maxSafeInteger = Math.pow(2, 53) - 1;
-
- /** Regular expression to detect Opera. */
- var reOpera = /\bOpera/;
-
- /** Possible global object. */
- var thisBinding = this;
-
- /** Used for native method references. */
- var objectProto = Object.prototype;
-
- /** Used to check for own properties of an object. */
- var hasOwnProperty = objectProto.hasOwnProperty;
-
- /** Used to resolve the internal `[[Class]]` of values. */
- var toString = objectProto.toString;
-
- /*--------------------------------------------------------------------------*/
-
- /**
- * Capitalizes a string value.
- *
- * @private
- * @param {string} string The string to capitalize.
- * @returns {string} The capitalized string.
- */
- function capitalize(string) {
- string = String(string);
- return string.charAt(0).toUpperCase() + string.slice(1);
- }
-
- /**
- * A utility function to clean up the OS name.
- *
- * @private
- * @param {string} os The OS name to clean up.
- * @param {string} [pattern] A `RegExp` pattern matching the OS name.
- * @param {string} [label] A label for the OS.
- */
- function cleanupOS(os, pattern, label) {
- // Platform tokens are defined at:
- // http://msdn.microsoft.com/en-us/library/ms537503(VS.85).aspx
- // http://web.archive.org/web/20081122053950/http://msdn.microsoft.com/en-us/library/ms537503(VS.85).aspx
- var data = {
- '10.0': '10',
- '6.4': '10 Technical Preview',
- '6.3': '8.1',
- '6.2': '8',
- '6.1': 'Server 2008 R2 / 7',
- '6.0': 'Server 2008 / Vista',
- '5.2': 'Server 2003 / XP 64-bit',
- '5.1': 'XP',
- '5.01': '2000 SP1',
- '5.0': '2000',
- '4.0': 'NT',
- '4.90': 'ME'
- };
- // Detect Windows version from platform tokens.
- if (pattern && label && /^Win/i.test(os) && !/^Windows Phone /i.test(os) &&
- (data = data[/[\d.]+$/.exec(os)])) {
- os = 'Windows ' + data;
- }
- // Correct character case and cleanup string.
- os = String(os);
-
- if (pattern && label) {
- os = os.replace(RegExp(pattern, 'i'), label);
- }
-
- os = format(
- os.replace(/ ce$/i, ' CE')
- .replace(/\bhpw/i, 'web')
- .replace(/\bMacintosh\b/, 'Mac OS')
- .replace(/_PowerPC\b/i, ' OS')
- .replace(/\b(OS X) [^ \d]+/i, '$1')
- .replace(/\bMac (OS X)\b/, '$1')
- .replace(/\/(\d)/, ' $1')
- .replace(/_/g, '.')
- .replace(/(?: BePC|[ .]*fc[ \d.]+)$/i, '')
- .replace(/\bx86\.64\b/gi, 'x86_64')
- .replace(/\b(Windows Phone) OS\b/, '$1')
- .replace(/\b(Chrome OS \w+) [\d.]+\b/, '$1')
- .split(' on ')[0]
- );
-
- return os;
- }
-
- /**
- * An iteration utility for arrays and objects.
- *
- * @private
- * @param {Array|Object} object The object to iterate over.
- * @param {Function} callback The function called per iteration.
- */
- function each(object, callback) {
- var index = -1,
- length = object ? object.length : 0;
-
- if (typeof length == 'number' && length > -1 && length <= maxSafeInteger) {
- while (++index < length) {
- callback(object[index], index, object);
- }
- } else {
- forOwn(object, callback);
- }
- }
-
- /**
- * Trim and conditionally capitalize string values.
- *
- * @private
- * @param {string} string The string to format.
- * @returns {string} The formatted string.
- */
- function format(string) {
- string = trim(string);
- return /^(?:webOS|i(?:OS|P))/.test(string)
- ? string
- : capitalize(string);
- }
-
- /**
- * Iterates over an object's own properties, executing the `callback` for each.
- *
- * @private
- * @param {Object} object The object to iterate over.
- * @param {Function} callback The function executed per own property.
- */
- function forOwn(object, callback) {
- for (var key in object) {
- if (hasOwnProperty.call(object, key)) {
- callback(object[key], key, object);
- }
- }
- }
-
- /**
- * Gets the internal `[[Class]]` of a value.
- *
- * @private
- * @param {*} value The value.
- * @returns {string} The `[[Class]]`.
- */
- function getClassOf(value) {
- return value == null
- ? capitalize(value)
- : toString.call(value).slice(8, -1);
- }
-
- /**
- * Host objects can return type values that are different from their actual
- * data type. The objects we are concerned with usually return non-primitive
- * types of "object", "function", or "unknown".
- *
- * @private
- * @param {*} object The owner of the property.
- * @param {string} property The property to check.
- * @returns {boolean} Returns `true` if the property value is a non-primitive, else `false`.
- */
- function isHostType(object, property) {
- var type = object != null ? typeof object[property] : 'number';
- return !/^(?:boolean|number|string|undefined)$/.test(type) &&
- (type == 'object' ? !!object[property] : true);
- }
-
- /**
- * Prepares a string for use in a `RegExp` by making hyphens and spaces optional.
- *
- * @private
- * @param {string} string The string to qualify.
- * @returns {string} The qualified string.
- */
- function qualify(string) {
- return String(string).replace(/([ -])(?!$)/g, '$1?');
- }
-
- /**
- * A bare-bones `Array#reduce` like utility function.
- *
- * @private
- * @param {Array} array The array to iterate over.
- * @param {Function} callback The function called per iteration.
- * @returns {*} The accumulated result.
- */
- function reduce(array, callback) {
- var accumulator = null;
- each(array, function(value, index) {
- accumulator = callback(accumulator, value, index, array);
- });
- return accumulator;
- }
-
- /**
- * Removes leading and trailing whitespace from a string.
- *
- * @private
- * @param {string} string The string to trim.
- * @returns {string} The trimmed string.
- */
- function trim(string) {
- return String(string).replace(/^ +| +$/g, '');
- }
-
- /*--------------------------------------------------------------------------*/
-
- /**
- * Creates a new platform object.
- *
- * @memberOf platform
- * @param {Object|string} [ua=navigator.userAgent] The user agent string or
- * context object.
- * @returns {Object} A platform object.
- */
- function parse(ua) {
-
- /** The environment context object. */
- var context = root;
-
- /** Used to flag when a custom context is provided. */
- var isCustomContext = ua && typeof ua == 'object' && getClassOf(ua) != 'String';
-
- // Juggle arguments.
- if (isCustomContext) {
- context = ua;
- ua = null;
- }
-
- /** Browser navigator object. */
- var nav = context.navigator || {};
-
- /** Browser user agent string. */
- var userAgent = nav.userAgent || '';
-
- ua || (ua = userAgent);
-
- /** Used to flag when `thisBinding` is the [ModuleScope]. */
- var isModuleScope = isCustomContext || thisBinding == oldRoot;
-
- /** Used to detect if browser is like Chrome. */
- var likeChrome = isCustomContext
- ? !!nav.likeChrome
- : /\bChrome\b/.test(ua) && !/internal|\n/i.test(toString.toString());
-
- /** Internal `[[Class]]` value shortcuts. */
- var objectClass = 'Object',
- airRuntimeClass = isCustomContext ? objectClass : 'ScriptBridgingProxyObject',
- enviroClass = isCustomContext ? objectClass : 'Environment',
- javaClass = (isCustomContext && context.java) ? 'JavaPackage' : getClassOf(context.java),
- phantomClass = isCustomContext ? objectClass : 'RuntimeObject';
-
- /** Detect Java environments. */
- var java = /\bJava/.test(javaClass) && context.java;
-
- /** Detect Rhino. */
- var rhino = java && getClassOf(context.environment) == enviroClass;
-
- /** A character to represent alpha. */
- var alpha = java ? 'a' : '\u03b1';
-
- /** A character to represent beta. */
- var beta = java ? 'b' : '\u03b2';
-
- /** Browser document object. */
- var doc = context.document || {};
-
- /**
- * Detect Opera browser (Presto-based).
- * http://www.howtocreate.co.uk/operaStuff/operaObject.html
- * http://dev.opera.com/articles/view/opera-mini-web-content-authoring-guidelines/#operamini
- */
- var opera = context.operamini || context.opera;
-
- /** Opera `[[Class]]`. */
- var operaClass = reOpera.test(operaClass = (isCustomContext && opera) ? opera['[[Class]]'] : getClassOf(opera))
- ? operaClass
- : (opera = null);
-
- /*------------------------------------------------------------------------*/
-
- /** Temporary variable used over the script's lifetime. */
- var data;
-
- /** The CPU architecture. */
- var arch = ua;
-
- /** Platform description array. */
- var description = [];
-
- /** Platform alpha/beta indicator. */
- var prerelease = null;
-
- /** A flag to indicate that environment features should be used to resolve the platform. */
- var useFeatures = ua == userAgent;
-
- /** The browser/environment version. */
- var version = useFeatures && opera && typeof opera.version == 'function' && opera.version();
-
- /** A flag to indicate if the OS ends with "/ Version" */
- var isSpecialCasedOS;
-
- /* Detectable layout engines (order is important). */
- var layout = getLayout([
- { 'label': 'EdgeHTML', 'pattern': 'Edge' },
- 'Trident',
- { 'label': 'WebKit', 'pattern': 'AppleWebKit' },
- 'iCab',
- 'Presto',
- 'NetFront',
- 'Tasman',
- 'KHTML',
- 'Gecko'
- ]);
-
- /* Detectable browser names (order is important). */
- var name = getName([
- 'Adobe AIR',
- 'Arora',
- 'Avant Browser',
- 'Breach',
- 'Camino',
- 'Electron',
- 'Epiphany',
- 'Fennec',
- 'Flock',
- 'Galeon',
- 'GreenBrowser',
- 'iCab',
- 'Iceweasel',
- 'K-Meleon',
- 'Konqueror',
- 'Lunascape',
- 'Maxthon',
- { 'label': 'Microsoft Edge', 'pattern': 'Edge' },
- 'Midori',
- 'Nook Browser',
- 'PaleMoon',
- 'PhantomJS',
- 'Raven',
- 'Rekonq',
- 'RockMelt',
- { 'label': 'Samsung Internet', 'pattern': 'SamsungBrowser' },
- 'SeaMonkey',
- { 'label': 'Silk', 'pattern': '(?:Cloud9|Silk-Accelerated)' },
- 'Sleipnir',
- 'SlimBrowser',
- { 'label': 'SRWare Iron', 'pattern': 'Iron' },
- 'Sunrise',
- 'Swiftfox',
- 'Waterfox',
- 'WebPositive',
- 'Opera Mini',
- { 'label': 'Opera Mini', 'pattern': 'OPiOS' },
- 'Opera',
- { 'label': 'Opera', 'pattern': 'OPR' },
- 'Chrome',
- { 'label': 'Chrome Mobile', 'pattern': '(?:CriOS|CrMo)' },
- { 'label': 'Firefox', 'pattern': '(?:Firefox|Minefield)' },
- { 'label': 'Firefox for iOS', 'pattern': 'FxiOS' },
- { 'label': 'IE', 'pattern': 'IEMobile' },
- { 'label': 'IE', 'pattern': 'MSIE' },
- 'Safari'
- ]);
-
- /* Detectable products (order is important). */
- var product = getProduct([
- { 'label': 'BlackBerry', 'pattern': 'BB10' },
- 'BlackBerry',
- { 'label': 'Galaxy S', 'pattern': 'GT-I9000' },
- { 'label': 'Galaxy S2', 'pattern': 'GT-I9100' },
- { 'label': 'Galaxy S3', 'pattern': 'GT-I9300' },
- { 'label': 'Galaxy S4', 'pattern': 'GT-I9500' },
- { 'label': 'Galaxy S5', 'pattern': 'SM-G900' },
- { 'label': 'Galaxy S6', 'pattern': 'SM-G920' },
- { 'label': 'Galaxy S6 Edge', 'pattern': 'SM-G925' },
- { 'label': 'Galaxy S7', 'pattern': 'SM-G930' },
- { 'label': 'Galaxy S7 Edge', 'pattern': 'SM-G935' },
- 'Google TV',
- 'Lumia',
- 'iPad',
- 'iPod',
- 'iPhone',
- 'Kindle',
- { 'label': 'Kindle Fire', 'pattern': '(?:Cloud9|Silk-Accelerated)' },
- 'Nexus',
- 'Nook',
- 'PlayBook',
- 'PlayStation Vita',
- 'PlayStation',
- 'TouchPad',
- 'Transformer',
- { 'label': 'Wii U', 'pattern': 'WiiU' },
- 'Wii',
- 'Xbox One',
- { 'label': 'Xbox 360', 'pattern': 'Xbox' },
- 'Xoom'
- ]);
-
- /* Detectable manufacturers. */
- var manufacturer = getManufacturer({
- 'Apple': { 'iPad': 1, 'iPhone': 1, 'iPod': 1 },
- 'Archos': {},
- 'Amazon': { 'Kindle': 1, 'Kindle Fire': 1 },
- 'Asus': { 'Transformer': 1 },
- 'Barnes & Noble': { 'Nook': 1 },
- 'BlackBerry': { 'PlayBook': 1 },
- 'Google': { 'Google TV': 1, 'Nexus': 1 },
- 'HP': { 'TouchPad': 1 },
- 'HTC': {},
- 'LG': {},
- 'Microsoft': { 'Xbox': 1, 'Xbox One': 1 },
- 'Motorola': { 'Xoom': 1 },
- 'Nintendo': { 'Wii U': 1, 'Wii': 1 },
- 'Nokia': { 'Lumia': 1 },
- 'Samsung': { 'Galaxy S': 1, 'Galaxy S2': 1, 'Galaxy S3': 1, 'Galaxy S4': 1 },
- 'Sony': { 'PlayStation': 1, 'PlayStation Vita': 1 }
- });
-
- /* Detectable operating systems (order is important). */
- var os = getOS([
- 'Windows Phone',
- 'Android',
- 'CentOS',
- { 'label': 'Chrome OS', 'pattern': 'CrOS' },
- 'Debian',
- 'Fedora',
- 'FreeBSD',
- 'Gentoo',
- 'Haiku',
- 'Kubuntu',
- 'Linux Mint',
- 'OpenBSD',
- 'Red Hat',
- 'SuSE',
- 'Ubuntu',
- 'Xubuntu',
- 'Cygwin',
- 'Symbian OS',
- 'hpwOS',
- 'webOS ',
- 'webOS',
- 'Tablet OS',
- 'Tizen',
- 'Linux',
- 'Mac OS X',
- 'Macintosh',
- 'Mac',
- 'Windows 98;',
- 'Windows '
- ]);
-
- /*------------------------------------------------------------------------*/
-
- /**
- * Picks the layout engine from an array of guesses.
- *
- * @private
- * @param {Array} guesses An array of guesses.
- * @returns {null|string} The detected layout engine.
- */
- function getLayout(guesses) {
- return reduce(guesses, function(result, guess) {
- return result || RegExp('\\b' + (
- guess.pattern || qualify(guess)
- ) + '\\b', 'i').exec(ua) && (guess.label || guess);
- });
- }
-
- /**
- * Picks the manufacturer from an array of guesses.
- *
- * @private
- * @param {Array} guesses An object of guesses.
- * @returns {null|string} The detected manufacturer.
- */
- function getManufacturer(guesses) {
- return reduce(guesses, function(result, value, key) {
- // Lookup the manufacturer by product or scan the UA for the manufacturer.
- return result || (
- value[product] ||
- value[/^[a-z]+(?: +[a-z]+\b)*/i.exec(product)] ||
- RegExp('\\b' + qualify(key) + '(?:\\b|\\w*\\d)', 'i').exec(ua)
- ) && key;
- });
- }
-
- /**
- * Picks the browser name from an array of guesses.
- *
- * @private
- * @param {Array} guesses An array of guesses.
- * @returns {null|string} The detected browser name.
- */
- function getName(guesses) {
- return reduce(guesses, function(result, guess) {
- return result || RegExp('\\b' + (
- guess.pattern || qualify(guess)
- ) + '\\b', 'i').exec(ua) && (guess.label || guess);
- });
- }
-
- /**
- * Picks the OS name from an array of guesses.
- *
- * @private
- * @param {Array} guesses An array of guesses.
- * @returns {null|string} The detected OS name.
- */
- function getOS(guesses) {
- return reduce(guesses, function(result, guess) {
- var pattern = guess.pattern || qualify(guess);
- if (!result && (result =
- RegExp('\\b' + pattern + '(?:/[\\d.]+|[ \\w.]*)', 'i').exec(ua)
- )) {
- result = cleanupOS(result, pattern, guess.label || guess);
- }
- return result;
- });
- }
-
- /**
- * Picks the product name from an array of guesses.
- *
- * @private
- * @param {Array} guesses An array of guesses.
- * @returns {null|string} The detected product name.
- */
- function getProduct(guesses) {
- return reduce(guesses, function(result, guess) {
- var pattern = guess.pattern || qualify(guess);
- if (!result && (result =
- RegExp('\\b' + pattern + ' *\\d+[.\\w_]*', 'i').exec(ua) ||
- RegExp('\\b' + pattern + ' *\\w+-[\\w]*', 'i').exec(ua) ||
- RegExp('\\b' + pattern + '(?:; *(?:[a-z]+[_-])?[a-z]+\\d+|[^ ();-]*)', 'i').exec(ua)
- )) {
- // Split by forward slash and append product version if needed.
- if ((result = String((guess.label && !RegExp(pattern, 'i').test(guess.label)) ? guess.label : result).split('/'))[1] && !/[\d.]+/.test(result[0])) {
- result[0] += ' ' + result[1];
- }
- // Correct character case and cleanup string.
- guess = guess.label || guess;
- result = format(result[0]
- .replace(RegExp(pattern, 'i'), guess)
- .replace(RegExp('; *(?:' + guess + '[_-])?', 'i'), ' ')
- .replace(RegExp('(' + guess + ')[-_.]?(\\w)', 'i'), '$1 $2'));
- }
- return result;
- });
- }
-
- /**
- * Resolves the version using an array of UA patterns.
- *
- * @private
- * @param {Array} patterns An array of UA patterns.
- * @returns {null|string} The detected version.
- */
- function getVersion(patterns) {
- return reduce(patterns, function(result, pattern) {
- return result || (RegExp(pattern +
- '(?:-[\\d.]+/|(?: for [\\w-]+)?[ /-])([\\d.]+[^ ();/_-]*)', 'i').exec(ua) || 0)[1] || null;
- });
- }
-
- /**
- * Returns `platform.description` when the platform object is coerced to a string.
- *
- * @name toString
- * @memberOf platform
- * @returns {string} Returns `platform.description` if available, else an empty string.
- */
- function toStringPlatform() {
- return this.description || '';
- }
-
- /*------------------------------------------------------------------------*/
-
- // Convert layout to an array so we can add extra details.
- layout && (layout = [layout]);
-
- // Detect product names that contain their manufacturer's name.
- if (manufacturer && !product) {
- product = getProduct([manufacturer]);
- }
- // Clean up Google TV.
- if ((data = /\bGoogle TV\b/.exec(product))) {
- product = data[0];
- }
- // Detect simulators.
- if (/\bSimulator\b/i.test(ua)) {
- product = (product ? product + ' ' : '') + 'Simulator';
- }
- // Detect Opera Mini 8+ running in Turbo/Uncompressed mode on iOS.
- if (name == 'Opera Mini' && /\bOPiOS\b/.test(ua)) {
- description.push('running in Turbo/Uncompressed mode');
- }
- // Detect IE Mobile 11.
- if (name == 'IE' && /\blike iPhone OS\b/.test(ua)) {
- data = parse(ua.replace(/like iPhone OS/, ''));
- manufacturer = data.manufacturer;
- product = data.product;
- }
- // Detect iOS.
- else if (/^iP/.test(product)) {
- name || (name = 'Safari');
- os = 'iOS' + ((data = / OS ([\d_]+)/i.exec(ua))
- ? ' ' + data[1].replace(/_/g, '.')
- : '');
- }
- // Detect Kubuntu.
- else if (name == 'Konqueror' && !/buntu/i.test(os)) {
- os = 'Kubuntu';
- }
- // Detect Android browsers.
- else if ((manufacturer && manufacturer != 'Google' &&
- ((/Chrome/.test(name) && !/\bMobile Safari\b/i.test(ua)) || /\bVita\b/.test(product))) ||
- (/\bAndroid\b/.test(os) && /^Chrome/.test(name) && /\bVersion\//i.test(ua))) {
- name = 'Android Browser';
- os = /\bAndroid\b/.test(os) ? os : 'Android';
- }
- // Detect Silk desktop/accelerated modes.
- else if (name == 'Silk') {
- if (!/\bMobi/i.test(ua)) {
- os = 'Android';
- description.unshift('desktop mode');
- }
- if (/Accelerated *= *true/i.test(ua)) {
- description.unshift('accelerated');
- }
- }
- // Detect PaleMoon identifying as Firefox.
- else if (name == 'PaleMoon' && (data = /\bFirefox\/([\d.]+)\b/.exec(ua))) {
- description.push('identifying as Firefox ' + data[1]);
- }
- // Detect Firefox OS and products running Firefox.
- else if (name == 'Firefox' && (data = /\b(Mobile|Tablet|TV)\b/i.exec(ua))) {
- os || (os = 'Firefox OS');
- product || (product = data[1]);
- }
- // Detect false positives for Firefox/Safari.
- else if (!name || (data = !/\bMinefield\b/i.test(ua) && /\b(?:Firefox|Safari)\b/.exec(name))) {
- // Escape the `/` for Firefox 1.
- if (name && !product && /[\/,]|^[^(]+?\)/.test(ua.slice(ua.indexOf(data + '/') + 8))) {
- // Clear name of false positives.
- name = null;
- }
- // Reassign a generic name.
- if ((data = product || manufacturer || os) &&
- (product || manufacturer || /\b(?:Android|Symbian OS|Tablet OS|webOS)\b/.test(os))) {
- name = /[a-z]+(?: Hat)?/i.exec(/\bAndroid\b/.test(os) ? os : data) + ' Browser';
- }
- }
- // Add Chrome version to description for Electron.
- else if (name == 'Electron' && (data = (/\bChrome\/([\d.]+)\b/.exec(ua) || 0)[1])) {
- description.push('Chromium ' + data);
- }
- // Detect non-Opera (Presto-based) versions (order is important).
- if (!version) {
- version = getVersion([
- '(?:Cloud9|CriOS|CrMo|Edge|FxiOS|IEMobile|Iron|Opera ?Mini|OPiOS|OPR|Raven|SamsungBrowser|Silk(?!/[\\d.]+$))',
- 'Version',
- qualify(name),
- '(?:Firefox|Minefield|NetFront)'
- ]);
- }
- // Detect stubborn layout engines.
- if ((data =
- layout == 'iCab' && parseFloat(version) > 3 && 'WebKit' ||
- /\bOpera\b/.test(name) && (/\bOPR\b/.test(ua) ? 'Blink' : 'Presto') ||
- /\b(?:Midori|Nook|Safari)\b/i.test(ua) && !/^(?:Trident|EdgeHTML)$/.test(layout) && 'WebKit' ||
- !layout && /\bMSIE\b/i.test(ua) && (os == 'Mac OS' ? 'Tasman' : 'Trident') ||
- layout == 'WebKit' && /\bPlayStation\b(?! Vita\b)/i.test(name) && 'NetFront'
- )) {
- layout = [data];
- }
- // Detect Windows Phone 7 desktop mode.
- if (name == 'IE' && (data = (/; *(?:XBLWP|ZuneWP)(\d+)/i.exec(ua) || 0)[1])) {
- name += ' Mobile';
- os = 'Windows Phone ' + (/\+$/.test(data) ? data : data + '.x');
- description.unshift('desktop mode');
- }
- // Detect Windows Phone 8.x desktop mode.
- else if (/\bWPDesktop\b/i.test(ua)) {
- name = 'IE Mobile';
- os = 'Windows Phone 8.x';
- description.unshift('desktop mode');
- version || (version = (/\brv:([\d.]+)/.exec(ua) || 0)[1]);
- }
- // Detect IE 11 identifying as other browsers.
- else if (name != 'IE' && layout == 'Trident' && (data = /\brv:([\d.]+)/.exec(ua))) {
- if (name) {
- description.push('identifying as ' + name + (version ? ' ' + version : ''));
- }
- name = 'IE';
- version = data[1];
- }
- // Leverage environment features.
- if (useFeatures) {
- // Detect server-side environments.
- // Rhino has a global function while others have a global object.
- if (isHostType(context, 'global')) {
- if (java) {
- data = java.lang.System;
- arch = data.getProperty('os.arch');
- os = os || data.getProperty('os.name') + ' ' + data.getProperty('os.version');
- }
- if (rhino) {
- try {
- version = context.require('ringo/engine').version.join('.');
- name = 'RingoJS';
- } catch(e) {
- if ((data = context.system) && data.global.system == context.system) {
- name = 'Narwhal';
- os || (os = data[0].os || null);
- }
- }
- if (!name) {
- name = 'Rhino';
- }
- }
- else if (
- typeof context.process == 'object' && !context.process.browser &&
- (data = context.process)
- ) {
- if (typeof data.versions == 'object') {
- if (typeof data.versions.electron == 'string') {
- description.push('Node ' + data.versions.node);
- name = 'Electron';
- version = data.versions.electron;
- } else if (typeof data.versions.nw == 'string') {
- description.push('Chromium ' + version, 'Node ' + data.versions.node);
- name = 'NW.js';
- version = data.versions.nw;
- }
- }
- if (!name) {
- name = 'Node.js';
- arch = data.arch;
- os = data.platform;
- version = /[\d.]+/.exec(data.version);
- version = version ? version[0] : null;
- }
- }
- }
- // Detect Adobe AIR.
- else if (getClassOf((data = context.runtime)) == airRuntimeClass) {
- name = 'Adobe AIR';
- os = data.flash.system.Capabilities.os;
- }
- // Detect PhantomJS.
- else if (getClassOf((data = context.phantom)) == phantomClass) {
- name = 'PhantomJS';
- version = (data = data.version || null) && (data.major + '.' + data.minor + '.' + data.patch);
- }
- // Detect IE compatibility modes.
- else if (typeof doc.documentMode == 'number' && (data = /\bTrident\/(\d+)/i.exec(ua))) {
- // We're in compatibility mode when the Trident version + 4 doesn't
- // equal the document mode.
- version = [version, doc.documentMode];
- if ((data = +data[1] + 4) != version[1]) {
- description.push('IE ' + version[1] + ' mode');
- layout && (layout[1] = '');
- version[1] = data;
- }
- version = name == 'IE' ? String(version[1].toFixed(1)) : version[0];
- }
- // Detect IE 11 masking as other browsers.
- else if (typeof doc.documentMode == 'number' && /^(?:Chrome|Firefox)\b/.test(name)) {
- description.push('masking as ' + name + ' ' + version);
- name = 'IE';
- version = '11.0';
- layout = ['Trident'];
- os = 'Windows';
- }
- os = os && format(os);
- }
- // Detect prerelease phases.
- if (version && (data =
- /(?:[ab]|dp|pre|[ab]\d+pre)(?:\d+\+?)?$/i.exec(version) ||
- /(?:alpha|beta)(?: ?\d)?/i.exec(ua + ';' + (useFeatures && nav.appMinorVersion)) ||
- /\bMinefield\b/i.test(ua) && 'a'
- )) {
- prerelease = /b/i.test(data) ? 'beta' : 'alpha';
- version = version.replace(RegExp(data + '\\+?$'), '') +
- (prerelease == 'beta' ? beta : alpha) + (/\d+\+?/.exec(data) || '');
- }
- // Detect Firefox Mobile.
- if (name == 'Fennec' || name == 'Firefox' && /\b(?:Android|Firefox OS)\b/.test(os)) {
- name = 'Firefox Mobile';
- }
- // Obscure Maxthon's unreliable version.
- else if (name == 'Maxthon' && version) {
- version = version.replace(/\.[\d.]+/, '.x');
- }
- // Detect Xbox 360 and Xbox One.
- else if (/\bXbox\b/i.test(product)) {
- if (product == 'Xbox 360') {
- os = null;
- }
- if (product == 'Xbox 360' && /\bIEMobile\b/.test(ua)) {
- description.unshift('mobile mode');
- }
- }
- // Add mobile postfix.
- else if ((/^(?:Chrome|IE|Opera)$/.test(name) || name && !product && !/Browser|Mobi/.test(name)) &&
- (os == 'Windows CE' || /Mobi/i.test(ua))) {
- name += ' Mobile';
- }
- // Detect IE platform preview.
- else if (name == 'IE' && useFeatures) {
- try {
- if (context.external === null) {
- description.unshift('platform preview');
- }
- } catch(e) {
- description.unshift('embedded');
- }
- }
- // Detect BlackBerry OS version.
- // http://docs.blackberry.com/en/developers/deliverables/18169/HTTP_headers_sent_by_BB_Browser_1234911_11.jsp
- else if ((/\bBlackBerry\b/.test(product) || /\bBB10\b/.test(ua)) && (data =
- (RegExp(product.replace(/ +/g, ' *') + '/([.\\d]+)', 'i').exec(ua) || 0)[1] ||
- version
- )) {
- data = [data, /BB10/.test(ua)];
- os = (data[1] ? (product = null, manufacturer = 'BlackBerry') : 'Device Software') + ' ' + data[0];
- version = null;
- }
- // Detect Opera identifying/masking itself as another browser.
- // http://www.opera.com/support/kb/view/843/
- else if (this != forOwn && product != 'Wii' && (
- (useFeatures && opera) ||
- (/Opera/.test(name) && /\b(?:MSIE|Firefox)\b/i.test(ua)) ||
- (name == 'Firefox' && /\bOS X (?:\d+\.){2,}/.test(os)) ||
- (name == 'IE' && (
- (os && !/^Win/.test(os) && version > 5.5) ||
- /\bWindows XP\b/.test(os) && version > 8 ||
- version == 8 && !/\bTrident\b/.test(ua)
- ))
- ) && !reOpera.test((data = parse.call(forOwn, ua.replace(reOpera, '') + ';'))) && data.name) {
- // When "identifying", the UA contains both Opera and the other browser's name.
- data = 'ing as ' + data.name + ((data = data.version) ? ' ' + data : '');
- if (reOpera.test(name)) {
- if (/\bIE\b/.test(data) && os == 'Mac OS') {
- os = null;
- }
- data = 'identify' + data;
- }
- // When "masking", the UA contains only the other browser's name.
- else {
- data = 'mask' + data;
- if (operaClass) {
- name = format(operaClass.replace(/([a-z])([A-Z])/g, '$1 $2'));
- } else {
- name = 'Opera';
- }
- if (/\bIE\b/.test(data)) {
- os = null;
- }
- if (!useFeatures) {
- version = null;
- }
- }
- layout = ['Presto'];
- description.push(data);
- }
- // Detect WebKit Nightly and approximate Chrome/Safari versions.
- if ((data = (/\bAppleWebKit\/([\d.]+\+?)/i.exec(ua) || 0)[1])) {
- // Correct build number for numeric comparison.
- // (e.g. "532.5" becomes "532.05")
- data = [parseFloat(data.replace(/\.(\d)$/, '.0$1')), data];
- // Nightly builds are postfixed with a "+".
- if (name == 'Safari' && data[1].slice(-1) == '+') {
- name = 'WebKit Nightly';
- prerelease = 'alpha';
- version = data[1].slice(0, -1);
- }
- // Clear incorrect browser versions.
- else if (version == data[1] ||
- version == (data[2] = (/\bSafari\/([\d.]+\+?)/i.exec(ua) || 0)[1])) {
- version = null;
- }
- // Use the full Chrome version when available.
- data[1] = (/\bChrome\/([\d.]+)/i.exec(ua) || 0)[1];
- // Detect Blink layout engine.
- if (data[0] == 537.36 && data[2] == 537.36 && parseFloat(data[1]) >= 28 && layout == 'WebKit') {
- layout = ['Blink'];
- }
- // Detect JavaScriptCore.
- // http://stackoverflow.com/questions/6768474/how-can-i-detect-which-javascript-engine-v8-or-jsc-is-used-at-runtime-in-androi
- if (!useFeatures || (!likeChrome && !data[1])) {
- layout && (layout[1] = 'like Safari');
- data = (data = data[0], data < 400 ? 1 : data < 500 ? 2 : data < 526 ? 3 : data < 533 ? 4 : data < 534 ? '4+' : data < 535 ? 5 : data < 537 ? 6 : data < 538 ? 7 : data < 601 ? 8 : '8');
- } else {
- layout && (layout[1] = 'like Chrome');
- data = data[1] || (data = data[0], data < 530 ? 1 : data < 532 ? 2 : data < 532.05 ? 3 : data < 533 ? 4 : data < 534.03 ? 5 : data < 534.07 ? 6 : data < 534.10 ? 7 : data < 534.13 ? 8 : data < 534.16 ? 9 : data < 534.24 ? 10 : data < 534.30 ? 11 : data < 535.01 ? 12 : data < 535.02 ? '13+' : data < 535.07 ? 15 : data < 535.11 ? 16 : data < 535.19 ? 17 : data < 536.05 ? 18 : data < 536.10 ? 19 : data < 537.01 ? 20 : data < 537.11 ? '21+' : data < 537.13 ? 23 : data < 537.18 ? 24 : data < 537.24 ? 25 : data < 537.36 ? 26 : layout != 'Blink' ? '27' : '28');
- }
- // Add the postfix of ".x" or "+" for approximate versions.
- layout && (layout[1] += ' ' + (data += typeof data == 'number' ? '.x' : /[.+]/.test(data) ? '' : '+'));
- // Obscure version for some Safari 1-2 releases.
- if (name == 'Safari' && (!version || parseInt(version) > 45)) {
- version = data;
- }
- }
- // Detect Opera desktop modes.
- if (name == 'Opera' && (data = /\bzbov|zvav$/.exec(os))) {
- name += ' ';
- description.unshift('desktop mode');
- if (data == 'zvav') {
- name += 'Mini';
- version = null;
- } else {
- name += 'Mobile';
- }
- os = os.replace(RegExp(' *' + data + '$'), '');
- }
- // Detect Chrome desktop mode.
- else if (name == 'Safari' && /\bChrome\b/.exec(layout && layout[1])) {
- description.unshift('desktop mode');
- name = 'Chrome Mobile';
- version = null;
-
- if (/\bOS X\b/.test(os)) {
- manufacturer = 'Apple';
- os = 'iOS 4.3+';
- } else {
- os = null;
- }
- }
- // Strip incorrect OS versions.
- if (version && version.indexOf((data = /[\d.]+$/.exec(os))) == 0 &&
- ua.indexOf('/' + data + '-') > -1) {
- os = trim(os.replace(data, ''));
- }
- // Add layout engine.
- if (layout && !/\b(?:Avant|Nook)\b/.test(name) && (
- /Browser|Lunascape|Maxthon/.test(name) ||
- name != 'Safari' && /^iOS/.test(os) && /\bSafari\b/.test(layout[1]) ||
- /^(?:Adobe|Arora|Breach|Midori|Opera|Phantom|Rekonq|Rock|Samsung Internet|Sleipnir|Web)/.test(name) && layout[1])) {
- // Don't add layout details to description if they are falsey.
- (data = layout[layout.length - 1]) && description.push(data);
- }
- // Combine contextual information.
- if (description.length) {
- description = ['(' + description.join('; ') + ')'];
- }
- // Append manufacturer to description.
- if (manufacturer && product && product.indexOf(manufacturer) < 0) {
- description.push('on ' + manufacturer);
- }
- // Append product to description.
- if (product) {
- description.push((/^on /.test(description[description.length - 1]) ? '' : 'on ') + product);
- }
- // Parse the OS into an object.
- if (os) {
- data = / ([\d.+]+)$/.exec(os);
- isSpecialCasedOS = data && os.charAt(os.length - data[0].length - 1) == '/';
- os = {
- 'architecture': 32,
- 'family': (data && !isSpecialCasedOS) ? os.replace(data[0], '') : os,
- 'version': data ? data[1] : null,
- 'toString': function() {
- var version = this.version;
- return this.family + ((version && !isSpecialCasedOS) ? ' ' + version : '') + (this.architecture == 64 ? ' 64-bit' : '');
- }
- };
- }
- // Add browser/OS architecture.
- if ((data = /\b(?:AMD|IA|Win|WOW|x86_|x)64\b/i.exec(arch)) && !/\bi686\b/i.test(arch)) {
- if (os) {
- os.architecture = 64;
- os.family = os.family.replace(RegExp(' *' + data), '');
- }
- if (
- name && (/\bWOW64\b/i.test(ua) ||
- (useFeatures && /\w(?:86|32)$/.test(nav.cpuClass || nav.platform) && !/\bWin64; x64\b/i.test(ua)))
- ) {
- description.unshift('32-bit');
- }
- }
- // Chrome 39 and above on OS X is always 64-bit.
- else if (
- os && /^OS X/.test(os.family) &&
- name == 'Chrome' && parseFloat(version) >= 39
- ) {
- os.architecture = 64;
- }
-
- ua || (ua = null);
-
- /*------------------------------------------------------------------------*/
-
- /**
- * The platform object.
- *
- * @name platform
- * @type Object
- */
- var platform = {};
-
- /**
- * The platform description.
- *
- * @memberOf platform
- * @type string|null
- */
- platform.description = ua;
-
- /**
- * The name of the browser's layout engine.
- *
- * The list of common layout engines include:
- * "Blink", "EdgeHTML", "Gecko", "Trident" and "WebKit"
- *
- * @memberOf platform
- * @type string|null
- */
- platform.layout = layout && layout[0];
-
- /**
- * The name of the product's manufacturer.
- *
- * The list of manufacturers include:
- * "Apple", "Archos", "Amazon", "Asus", "Barnes & Noble", "BlackBerry",
- * "Google", "HP", "HTC", "LG", "Microsoft", "Motorola", "Nintendo",
- * "Nokia", "Samsung" and "Sony"
- *
- * @memberOf platform
- * @type string|null
- */
- platform.manufacturer = manufacturer;
-
- /**
- * The name of the browser/environment.
- *
- * The list of common browser names include:
- * "Chrome", "Electron", "Firefox", "Firefox for iOS", "IE",
- * "Microsoft Edge", "PhantomJS", "Safari", "SeaMonkey", "Silk",
- * "Opera Mini" and "Opera"
- *
- * Mobile versions of some browsers have "Mobile" appended to their name:
- * eg. "Chrome Mobile", "Firefox Mobile", "IE Mobile" and "Opera Mobile"
- *
- * @memberOf platform
- * @type string|null
- */
- platform.name = name;
-
- /**
- * The alpha/beta release indicator.
- *
- * @memberOf platform
- * @type string|null
- */
- platform.prerelease = prerelease;
-
- /**
- * The name of the product hosting the browser.
- *
- * The list of common products include:
- *
- * "BlackBerry", "Galaxy S4", "Lumia", "iPad", "iPod", "iPhone", "Kindle",
- * "Kindle Fire", "Nexus", "Nook", "PlayBook", "TouchPad" and "Transformer"
- *
- * @memberOf platform
- * @type string|null
- */
- platform.product = product;
-
- /**
- * The browser's user agent string.
- *
- * @memberOf platform
- * @type string|null
- */
- platform.ua = ua;
-
- /**
- * The browser/environment version.
- *
- * @memberOf platform
- * @type string|null
- */
- platform.version = name && version;
-
- /**
- * The name of the operating system.
- *
- * @memberOf platform
- * @type Object
- */
- platform.os = os || {
-
- /**
- * The CPU architecture the OS is built for.
- *
- * @memberOf platform.os
- * @type number|null
- */
- 'architecture': null,
-
- /**
- * The family of the OS.
- *
- * Common values include:
- * "Windows", "Windows Server 2008 R2 / 7", "Windows Server 2008 / Vista",
- * "Windows XP", "OS X", "Ubuntu", "Debian", "Fedora", "Red Hat", "SuSE",
- * "Android", "iOS" and "Windows Phone"
- *
- * @memberOf platform.os
- * @type string|null
- */
- 'family': null,
-
- /**
- * The version of the OS.
- *
- * @memberOf platform.os
- * @type string|null
- */
- 'version': null,
-
- /**
- * Returns the OS string.
- *
- * @memberOf platform.os
- * @returns {string} The OS string.
- */
- 'toString': function() { return 'null'; }
- };
-
- platform.parse = parse;
- platform.toString = toStringPlatform;
-
- if (platform.version) {
- description.unshift(version);
- }
- if (platform.name) {
- description.unshift(name);
- }
- if (os && name && !(os == String(os).split(' ')[0] && (os == name.split(' ')[0] || product))) {
- description.push(product ? '(' + os + ')' : 'on ' + os);
- }
- if (description.length) {
- platform.description = description.join(' ');
- }
- return platform;
- }
-
- /*--------------------------------------------------------------------------*/
-
- // Export platform.
- var platform = parse();
-
- // Some AMD build optimizers, like r.js, check for condition patterns like the following:
- if (typeof define == 'function' && typeof define.amd == 'object' && define.amd) {
- // Expose platform on the global object to prevent errors when platform is
- // loaded by a script tag in the presence of an AMD loader.
- // See http://requirejs.org/docs/errors.html#mismatch for more details.
- root.platform = platform;
-
- // Define as an anonymous module so platform can be aliased through path mapping.
- define(function() {
- return platform;
- });
- }
- // Check for `exports` after `define` in case a build optimizer adds an `exports` object.
- else if (freeExports && freeModule) {
- // Export for CommonJS support.
- forOwn(platform, function(value, key) {
- freeExports[key] = value;
- });
- }
- else {
- // Export to the global object.
- root.platform = platform;
- }
-}.call(this));
-
-}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
-
-},{}],9:[function(require,module,exports){
-var v1 = require('./v1');
-var v4 = require('./v4');
-
-var uuid = v4;
-uuid.v1 = v1;
-uuid.v4 = v4;
-
-module.exports = uuid;
-
-},{"./v1":12,"./v4":13}],10:[function(require,module,exports){
-/**
- * Convert array of 16 byte values to UUID string format of the form:
- * XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
- */
-var byteToHex = [];
-for (var i = 0; i < 256; ++i) {
- byteToHex[i] = (i + 0x100).toString(16).substr(1);
-}
-
-function bytesToUuid(buf, offset) {
- var i = offset || 0;
- var bth = byteToHex;
- // join used to fix memory issue caused by concatenation: https://bugs.chromium.org/p/v8/issues/detail?id=3175#c4
- return ([bth[buf[i++]], bth[buf[i++]],
- bth[buf[i++]], bth[buf[i++]], '-',
- bth[buf[i++]], bth[buf[i++]], '-',
- bth[buf[i++]], bth[buf[i++]], '-',
- bth[buf[i++]], bth[buf[i++]], '-',
- bth[buf[i++]], bth[buf[i++]],
- bth[buf[i++]], bth[buf[i++]],
- bth[buf[i++]], bth[buf[i++]]]).join('');
-}
-
-module.exports = bytesToUuid;
-
-},{}],11:[function(require,module,exports){
-// Unique ID creation requires a high quality random # generator. In the
-// browser this is a little complicated due to unknown quality of Math.random()
-// and inconsistent support for the `crypto` API. We do the best we can via
-// feature-detection
-
-// getRandomValues needs to be invoked in a context where "this" is a Crypto
-// implementation. Also, find the complete implementation of crypto on IE11.
-var getRandomValues = (typeof(crypto) != 'undefined' && crypto.getRandomValues && crypto.getRandomValues.bind(crypto)) ||
- (typeof(msCrypto) != 'undefined' && typeof window.msCrypto.getRandomValues == 'function' && msCrypto.getRandomValues.bind(msCrypto));
-
-if (getRandomValues) {
- // WHATWG crypto RNG - http://wiki.whatwg.org/wiki/Crypto
- var rnds8 = new Uint8Array(16); // eslint-disable-line no-undef
-
- module.exports = function whatwgRNG() {
- getRandomValues(rnds8);
- return rnds8;
- };
-} else {
- // Math.random()-based (RNG)
- //
- // If all else fails, use Math.random(). It's fast, but is of unspecified
- // quality.
- var rnds = new Array(16);
-
- module.exports = function mathRNG() {
- for (var i = 0, r; i < 16; i++) {
- if ((i & 0x03) === 0) r = Math.random() * 0x100000000;
- rnds[i] = r >>> ((i & 0x03) << 3) & 0xff;
- }
-
- return rnds;
- };
-}
-
-},{}],12:[function(require,module,exports){
-var rng = require('./lib/rng');
-var bytesToUuid = require('./lib/bytesToUuid');
-
-// **`v1()` - Generate time-based UUID**
-//
-// Inspired by https://github.com/LiosK/UUID.js
-// and http://docs.python.org/library/uuid.html
-
-var _nodeId;
-var _clockseq;
-
-// Previous uuid creation time
-var _lastMSecs = 0;
-var _lastNSecs = 0;
-
-// See https://github.com/broofa/node-uuid for API details
-function v1(options, buf, offset) {
- var i = buf && offset || 0;
- var b = buf || [];
-
- options = options || {};
- var node = options.node || _nodeId;
- var clockseq = options.clockseq !== undefined ? options.clockseq : _clockseq;
-
- // node and clockseq need to be initialized to random values if they're not
- // specified. We do this lazily to minimize issues related to insufficient
- // system entropy. See #189
- if (node == null || clockseq == null) {
- var seedBytes = rng();
- if (node == null) {
- // Per 4.5, create and 48-bit node id, (47 random bits + multicast bit = 1)
- node = _nodeId = [
- seedBytes[0] | 0x01,
- seedBytes[1], seedBytes[2], seedBytes[3], seedBytes[4], seedBytes[5]
- ];
- }
- if (clockseq == null) {
- // Per 4.2.2, randomize (14 bit) clockseq
- clockseq = _clockseq = (seedBytes[6] << 8 | seedBytes[7]) & 0x3fff;
- }
- }
-
- // UUID timestamps are 100 nano-second units since the Gregorian epoch,
- // (1582-10-15 00:00). JSNumbers aren't precise enough for this, so
- // time is handled internally as 'msecs' (integer milliseconds) and 'nsecs'
- // (100-nanoseconds offset from msecs) since unix epoch, 1970-01-01 00:00.
- var msecs = options.msecs !== undefined ? options.msecs : new Date().getTime();
-
- // Per 4.2.1.2, use count of uuid's generated during the current clock
- // cycle to simulate higher resolution clock
- var nsecs = options.nsecs !== undefined ? options.nsecs : _lastNSecs + 1;
-
- // Time since last uuid creation (in msecs)
- var dt = (msecs - _lastMSecs) + (nsecs - _lastNSecs)/10000;
-
- // Per 4.2.1.2, Bump clockseq on clock regression
- if (dt < 0 && options.clockseq === undefined) {
- clockseq = clockseq + 1 & 0x3fff;
- }
-
- // Reset nsecs if clock regresses (new clockseq) or we've moved onto a new
- // time interval
- if ((dt < 0 || msecs > _lastMSecs) && options.nsecs === undefined) {
- nsecs = 0;
- }
-
- // Per 4.2.1.2 Throw error if too many uuids are requested
- if (nsecs >= 10000) {
- throw new Error('uuid.v1(): Can\'t create more than 10M uuids/sec');
- }
-
- _lastMSecs = msecs;
- _lastNSecs = nsecs;
- _clockseq = clockseq;
-
- // Per 4.1.4 - Convert from unix epoch to Gregorian epoch
- msecs += 12219292800000;
-
- // `time_low`
- var tl = ((msecs & 0xfffffff) * 10000 + nsecs) % 0x100000000;
- b[i++] = tl >>> 24 & 0xff;
- b[i++] = tl >>> 16 & 0xff;
- b[i++] = tl >>> 8 & 0xff;
- b[i++] = tl & 0xff;
-
- // `time_mid`
- var tmh = (msecs / 0x100000000 * 10000) & 0xfffffff;
- b[i++] = tmh >>> 8 & 0xff;
- b[i++] = tmh & 0xff;
-
- // `time_high_and_version`
- b[i++] = tmh >>> 24 & 0xf | 0x10; // include version
- b[i++] = tmh >>> 16 & 0xff;
-
- // `clock_seq_hi_and_reserved` (Per 4.2.2 - include variant)
- b[i++] = clockseq >>> 8 | 0x80;
-
- // `clock_seq_low`
- b[i++] = clockseq & 0xff;
-
- // `node`
- for (var n = 0; n < 6; ++n) {
- b[i + n] = node[n];
- }
-
- return buf ? buf : bytesToUuid(b);
-}
-
-module.exports = v1;
-
-},{"./lib/bytesToUuid":10,"./lib/rng":11}],13:[function(require,module,exports){
-var rng = require('./lib/rng');
-var bytesToUuid = require('./lib/bytesToUuid');
-
-function v4(options, buf, offset) {
- var i = buf && offset || 0;
-
- if (typeof(options) == 'string') {
- buf = options === 'binary' ? new Array(16) : null;
- options = null;
- }
- options = options || {};
-
- var rnds = options.random || (options.rng || rng)();
-
- // Per 4.4, set bits for version and `clock_seq_hi_and_reserved`
- rnds[6] = (rnds[6] & 0x0f) | 0x40;
- rnds[8] = (rnds[8] & 0x3f) | 0x80;
-
- // Copy bytes to buffer, if provided
- if (buf) {
- for (var ii = 0; ii < 16; ++ii) {
- buf[i + ii] = rnds[ii];
- }
- }
-
- return buf || bytesToUuid(rnds);
-}
-
-module.exports = v4;
-
-},{"./lib/bytesToUuid":10,"./lib/rng":11}],14:[function(require,module,exports){
-/*
-WildEmitter.js is a slim little event emitter by @henrikjoreteg largely based
-on @visionmedia's Emitter from UI Kit.
-
-Why? I wanted it standalone.
-
-I also wanted support for wildcard emitters like this:
-
-emitter.on('*', function (eventName, other, event, payloads) {
-
-});
-
-emitter.on('somenamespace*', function (eventName, payloads) {
-
-});
-
-Please note that callbacks triggered by wildcard registered events also get
-the event name as the first argument.
-*/
-
-module.exports = WildEmitter;
-
-function WildEmitter() { }
-
-WildEmitter.mixin = function (constructor) {
- var prototype = constructor.prototype || constructor;
-
- prototype.isWildEmitter= true;
-
- // Listen on the given `event` with `fn`. Store a group name if present.
- prototype.on = function (event, groupName, fn) {
- this.callbacks = this.callbacks || {};
- var hasGroup = (arguments.length === 3),
- group = hasGroup ? arguments[1] : undefined,
- func = hasGroup ? arguments[2] : arguments[1];
- func._groupName = group;
- (this.callbacks[event] = this.callbacks[event] || []).push(func);
- return this;
- };
-
- // Adds an `event` listener that will be invoked a single
- // time then automatically removed.
- prototype.once = function (event, groupName, fn) {
- var self = this,
- hasGroup = (arguments.length === 3),
- group = hasGroup ? arguments[1] : undefined,
- func = hasGroup ? arguments[2] : arguments[1];
- function on() {
- self.off(event, on);
- func.apply(this, arguments);
- }
- this.on(event, group, on);
- return this;
- };
-
- // Unbinds an entire group
- prototype.releaseGroup = function (groupName) {
- this.callbacks = this.callbacks || {};
- var item, i, len, handlers;
- for (item in this.callbacks) {
- handlers = this.callbacks[item];
- for (i = 0, len = handlers.length; i < len; i++) {
- if (handlers[i]._groupName === groupName) {
- //console.log('removing');
- // remove it and shorten the array we're looping through
- handlers.splice(i, 1);
- i--;
- len--;
- }
- }
- }
- return this;
- };
-
- // Remove the given callback for `event` or all
- // registered callbacks.
- prototype.off = function (event, fn) {
- this.callbacks = this.callbacks || {};
- var callbacks = this.callbacks[event],
- i;
-
- if (!callbacks) return this;
-
- // remove all handlers
- if (arguments.length === 1) {
- delete this.callbacks[event];
- return this;
- }
-
- // remove specific handler
- i = callbacks.indexOf(fn);
- callbacks.splice(i, 1);
- if (callbacks.length === 0) {
- delete this.callbacks[event];
- }
- return this;
- };
-
- /// Emit `event` with the given args.
- // also calls any `*` handlers
- prototype.emit = function (event) {
- this.callbacks = this.callbacks || {};
- var args = [].slice.call(arguments, 1),
- callbacks = this.callbacks[event],
- specialCallbacks = this.getWildcardCallbacks(event),
- i,
- len,
- item,
- listeners;
-
- if (callbacks) {
- listeners = callbacks.slice();
- for (i = 0, len = listeners.length; i < len; ++i) {
- if (!listeners[i]) {
- break;
- }
- listeners[i].apply(this, args);
- }
- }
-
- if (specialCallbacks) {
- len = specialCallbacks.length;
- listeners = specialCallbacks.slice();
- for (i = 0, len = listeners.length; i < len; ++i) {
- if (!listeners[i]) {
- break;
- }
- listeners[i].apply(this, [event].concat(args));
- }
- }
-
- return this;
- };
-
- // Helper for for finding special wildcard event handlers that match the event
- prototype.getWildcardCallbacks = function (eventName) {
- this.callbacks = this.callbacks || {};
- var item,
- split,
- result = [];
-
- for (item in this.callbacks) {
- split = item.split('*');
- if (item === '*' || (split.length === 2 && eventName.slice(0, split[0].length) === split[0])) {
- result = result.concat(this.callbacks[item]);
- }
- }
- return result;
- };
-
-};
-
-WildEmitter.mixin(WildEmitter);
-
-},{}],15:[function(require,module,exports){
-/*!
- * EventEmitter v5.2.5 - git.io/ee
- * Unlicense - http://unlicense.org/
- * Oliver Caldwell - http://oli.me.uk/
- * @preserve
- */
-
-;(function (exports) {
- 'use strict';
-
- /**
- * Class for managing events.
- * Can be extended to provide event functionality in other classes.
- *
- * @class EventEmitter Manages event registering and emitting.
- */
- function EventEmitter() {}
-
- // Shortcuts to improve speed and size
- var proto = EventEmitter.prototype;
- var originalGlobalValue = exports.EventEmitter;
-
- /**
- * Finds the index of the listener for the event in its storage array.
- *
- * @param {Function[]} listeners Array of listeners to search through.
- * @param {Function} listener Method to look for.
- * @return {Number} Index of the specified listener, -1 if not found
- * @api private
- */
- function indexOfListener(listeners, listener) {
- var i = listeners.length;
- while (i--) {
- if (listeners[i].listener === listener) {
- return i;
- }
- }
-
- return -1;
- }
-
- /**
- * Alias a method while keeping the context correct, to allow for overwriting of target method.
- *
- * @param {String} name The name of the target method.
- * @return {Function} The aliased method
- * @api private
- */
- function alias(name) {
- return function aliasClosure() {
- return this[name].apply(this, arguments);
- };
- }
-
- /**
- * Returns the listener array for the specified event.
- * Will initialise the event object and listener arrays if required.
- * Will return an object if you use a regex search. The object contains keys for each matched event. So /ba[rz]/ might return an object containing bar and baz. But only if you have either defined them with defineEvent or added some listeners to them.
- * Each property in the object response is an array of listener functions.
- *
- * @param {String|RegExp} evt Name of the event to return the listeners from.
- * @return {Function[]|Object} All listener functions for the event.
- */
- proto.getListeners = function getListeners(evt) {
- var events = this._getEvents();
- var response;
- var key;
-
- // Return a concatenated array of all matching events if
- // the selector is a regular expression.
- if (evt instanceof RegExp) {
- response = {};
- for (key in events) {
- if (events.hasOwnProperty(key) && evt.test(key)) {
- response[key] = events[key];
- }
- }
- }
- else {
- response = events[evt] || (events[evt] = []);
- }
-
- return response;
- };
-
- /**
- * Takes a list of listener objects and flattens it into a list of listener functions.
- *
- * @param {Object[]} listeners Raw listener objects.
- * @return {Function[]} Just the listener functions.
- */
- proto.flattenListeners = function flattenListeners(listeners) {
- var flatListeners = [];
- var i;
-
- for (i = 0; i < listeners.length; i += 1) {
- flatListeners.push(listeners[i].listener);
- }
-
- return flatListeners;
- };
-
- /**
- * Fetches the requested listeners via getListeners but will always return the results inside an object. This is mainly for internal use but others may find it useful.
- *
- * @param {String|RegExp} evt Name of the event to return the listeners from.
- * @return {Object} All listener functions for an event in an object.
- */
- proto.getListenersAsObject = function getListenersAsObject(evt) {
- var listeners = this.getListeners(evt);
- var response;
-
- if (listeners instanceof Array) {
- response = {};
- response[evt] = listeners;
- }
-
- return response || listeners;
- };
-
- function isValidListener (listener) {
- if (typeof listener === 'function' || listener instanceof RegExp) {
- return true
- } else if (listener && typeof listener === 'object') {
- return isValidListener(listener.listener)
- } else {
- return false
- }
- }
-
- /**
- * Adds a listener function to the specified event.
- * The listener will not be added if it is a duplicate.
- * If the listener returns true then it will be removed after it is called.
- * If you pass a regular expression as the event name then the listener will be added to all events that match it.
- *
- * @param {String|RegExp} evt Name of the event to attach the listener to.
- * @param {Function} listener Method to be called when the event is emitted. If the function returns true then it will be removed after calling.
- * @return {Object} Current instance of EventEmitter for chaining.
- */
- proto.addListener = function addListener(evt, listener) {
- if (!isValidListener(listener)) {
- throw new TypeError('listener must be a function');
- }
-
- var listeners = this.getListenersAsObject(evt);
- var listenerIsWrapped = typeof listener === 'object';
- var key;
-
- for (key in listeners) {
- if (listeners.hasOwnProperty(key) && indexOfListener(listeners[key], listener) === -1) {
- listeners[key].push(listenerIsWrapped ? listener : {
- listener: listener,
- once: false
- });
- }
- }
-
- return this;
- };
-
- /**
- * Alias of addListener
- */
- proto.on = alias('addListener');
-
- /**
- * Semi-alias of addListener. It will add a listener that will be
- * automatically removed after its first execution.
- *
- * @param {String|RegExp} evt Name of the event to attach the listener to.
- * @param {Function} listener Method to be called when the event is emitted. If the function returns true then it will be removed after calling.
- * @return {Object} Current instance of EventEmitter for chaining.
- */
- proto.addOnceListener = function addOnceListener(evt, listener) {
- return this.addListener(evt, {
- listener: listener,
- once: true
- });
- };
-
- /**
- * Alias of addOnceListener.
- */
- proto.once = alias('addOnceListener');
-
- /**
- * Defines an event name. This is required if you want to use a regex to add a listener to multiple events at once. If you don't do this then how do you expect it to know what event to add to? Should it just add to every possible match for a regex? No. That is scary and bad.
- * You need to tell it what event names should be matched by a regex.
- *
- * @param {String} evt Name of the event to create.
- * @return {Object} Current instance of EventEmitter for chaining.
- */
- proto.defineEvent = function defineEvent(evt) {
- this.getListeners(evt);
- return this;
- };
-
- /**
- * Uses defineEvent to define multiple events.
- *
- * @param {String[]} evts An array of event names to define.
- * @return {Object} Current instance of EventEmitter for chaining.
- */
- proto.defineEvents = function defineEvents(evts) {
- for (var i = 0; i < evts.length; i += 1) {
- this.defineEvent(evts[i]);
- }
- return this;
- };
-
- /**
- * Removes a listener function from the specified event.
- * When passed a regular expression as the event name, it will remove the listener from all events that match it.
- *
- * @param {String|RegExp} evt Name of the event to remove the listener from.
- * @param {Function} listener Method to remove from the event.
- * @return {Object} Current instance of EventEmitter for chaining.
- */
- proto.removeListener = function removeListener(evt, listener) {
- var listeners = this.getListenersAsObject(evt);
- var index;
- var key;
-
- for (key in listeners) {
- if (listeners.hasOwnProperty(key)) {
- index = indexOfListener(listeners[key], listener);
-
- if (index !== -1) {
- listeners[key].splice(index, 1);
- }
- }
- }
-
- return this;
- };
-
- /**
- * Alias of removeListener
- */
- proto.off = alias('removeListener');
-
- /**
- * Adds listeners in bulk using the manipulateListeners method.
- * If you pass an object as the first argument you can add to multiple events at once. The object should contain key value pairs of events and listeners or listener arrays. You can also pass it an event name and an array of listeners to be added.
- * You can also pass it a regular expression to add the array of listeners to all events that match it.
- * Yeah, this function does quite a bit. That's probably a bad thing.
- *
- * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to add to multiple events at once.
- * @param {Function[]} [listeners] An optional array of listener functions to add.
- * @return {Object} Current instance of EventEmitter for chaining.
- */
- proto.addListeners = function addListeners(evt, listeners) {
- // Pass through to manipulateListeners
- return this.manipulateListeners(false, evt, listeners);
- };
-
- /**
- * Removes listeners in bulk using the manipulateListeners method.
- * If you pass an object as the first argument you can remove from multiple events at once. The object should contain key value pairs of events and listeners or listener arrays.
- * You can also pass it an event name and an array of listeners to be removed.
- * You can also pass it a regular expression to remove the listeners from all events that match it.
- *
- * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to remove from multiple events at once.
- * @param {Function[]} [listeners] An optional array of listener functions to remove.
- * @return {Object} Current instance of EventEmitter for chaining.
- */
- proto.removeListeners = function removeListeners(evt, listeners) {
- // Pass through to manipulateListeners
- return this.manipulateListeners(true, evt, listeners);
- };
-
- /**
- * Edits listeners in bulk. The addListeners and removeListeners methods both use this to do their job. You should really use those instead, this is a little lower level.
- * The first argument will determine if the listeners are removed (true) or added (false).
- * If you pass an object as the second argument you can add/remove from multiple events at once. The object should contain key value pairs of events and listeners or listener arrays.
- * You can also pass it an event name and an array of listeners to be added/removed.
- * You can also pass it a regular expression to manipulate the listeners of all events that match it.
- *
- * @param {Boolean} remove True if you want to remove listeners, false if you want to add.
- * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to add/remove from multiple events at once.
- * @param {Function[]} [listeners] An optional array of listener functions to add/remove.
- * @return {Object} Current instance of EventEmitter for chaining.
- */
- proto.manipulateListeners = function manipulateListeners(remove, evt, listeners) {
- var i;
- var value;
- var single = remove ? this.removeListener : this.addListener;
- var multiple = remove ? this.removeListeners : this.addListeners;
-
- // If evt is an object then pass each of its properties to this method
- if (typeof evt === 'object' && !(evt instanceof RegExp)) {
- for (i in evt) {
- if (evt.hasOwnProperty(i) && (value = evt[i])) {
- // Pass the single listener straight through to the singular method
- if (typeof value === 'function') {
- single.call(this, i, value);
- }
- else {
- // Otherwise pass back to the multiple function
- multiple.call(this, i, value);
- }
- }
- }
- }
- else {
- // So evt must be a string
- // And listeners must be an array of listeners
- // Loop over it and pass each one to the multiple method
- i = listeners.length;
- while (i--) {
- single.call(this, evt, listeners[i]);
- }
- }
-
- return this;
- };
-
- /**
- * Removes all listeners from a specified event.
- * If you do not specify an event then all listeners will be removed.
- * That means every event will be emptied.
- * You can also pass a regex to remove all events that match it.
- *
- * @param {String|RegExp} [evt] Optional name of the event to remove all listeners for. Will remove from every event if not passed.
- * @return {Object} Current instance of EventEmitter for chaining.
- */
- proto.removeEvent = function removeEvent(evt) {
- var type = typeof evt;
- var events = this._getEvents();
- var key;
-
- // Remove different things depending on the state of evt
- if (type === 'string') {
- // Remove all listeners for the specified event
- delete events[evt];
- }
- else if (evt instanceof RegExp) {
- // Remove all events matching the regex.
- for (key in events) {
- if (events.hasOwnProperty(key) && evt.test(key)) {
- delete events[key];
- }
- }
- }
- else {
- // Remove all listeners in all events
- delete this._events;
- }
-
- return this;
- };
-
- /**
- * Alias of removeEvent.
- *
- * Added to mirror the node API.
- */
- proto.removeAllListeners = alias('removeEvent');
-
- /**
- * Emits an event of your choice.
- * When emitted, every listener attached to that event will be executed.
- * If you pass the optional argument array then those arguments will be passed to every listener upon execution.
- * Because it uses `apply`, your array of arguments will be passed as if you wrote them out separately.
- * So they will not arrive within the array on the other side, they will be separate.
- * You can also pass a regular expression to emit to all events that match it.
- *
- * @param {String|RegExp} evt Name of the event to emit and execute listeners for.
- * @param {Array} [args] Optional array of arguments to be passed to each listener.
- * @return {Object} Current instance of EventEmitter for chaining.
- */
- proto.emitEvent = function emitEvent(evt, args) {
- var listenersMap = this.getListenersAsObject(evt);
- var listeners;
- var listener;
- var i;
- var key;
- var response;
-
- for (key in listenersMap) {
- if (listenersMap.hasOwnProperty(key)) {
- listeners = listenersMap[key].slice(0);
-
- for (i = 0; i < listeners.length; i++) {
- // If the listener returns true then it shall be removed from the event
- // The function is executed either with a basic call or an apply if there is an args array
- listener = listeners[i];
-
- if (listener.once === true) {
- this.removeListener(evt, listener.listener);
- }
-
- response = listener.listener.apply(this, args || []);
-
- if (response === this._getOnceReturnValue()) {
- this.removeListener(evt, listener.listener);
- }
- }
- }
- }
-
- return this;
- };
-
- /**
- * Alias of emitEvent
- */
- proto.trigger = alias('emitEvent');
-
- /**
- * Subtly different from emitEvent in that it will pass its arguments on to the listeners, as opposed to taking a single array of arguments to pass on.
- * As with emitEvent, you can pass a regex in place of the event name to emit to all events that match it.
- *
- * @param {String|RegExp} evt Name of the event to emit and execute listeners for.
- * @param {...*} Optional additional arguments to be passed to each listener.
- * @return {Object} Current instance of EventEmitter for chaining.
- */
- proto.emit = function emit(evt) {
- var args = Array.prototype.slice.call(arguments, 1);
- return this.emitEvent(evt, args);
- };
-
- /**
- * Sets the current value to check against when executing listeners. If a
- * listeners return value matches the one set here then it will be removed
- * after execution. This value defaults to true.
- *
- * @param {*} value The new value to check for when executing listeners.
- * @return {Object} Current instance of EventEmitter for chaining.
- */
- proto.setOnceReturnValue = function setOnceReturnValue(value) {
- this._onceReturnValue = value;
- return this;
- };
-
- /**
- * Fetches the current value to check against when executing listeners. If
- * the listeners return value matches this one then it should be removed
- * automatically. It will return true by default.
- *
- * @return {*|Boolean} The current value to check for or the default, true.
- * @api private
- */
- proto._getOnceReturnValue = function _getOnceReturnValue() {
- if (this.hasOwnProperty('_onceReturnValue')) {
- return this._onceReturnValue;
- }
- else {
- return true;
- }
- };
-
- /**
- * Fetches the events object and creates one if required.
- *
- * @return {Object} The events storage object.
- * @api private
- */
- proto._getEvents = function _getEvents() {
- return this._events || (this._events = {});
- };
-
- /**
- * Reverts the global {@link EventEmitter} to its previous value and returns a reference to this version.
- *
- * @return {Function} Non conflicting EventEmitter class.
- */
- EventEmitter.noConflict = function noConflict() {
- exports.EventEmitter = originalGlobalValue;
- return EventEmitter;
- };
-
- // Expose the class either via AMD, CommonJS or the global object
- if (typeof define === 'function' && define.amd) {
- define(function () {
- return EventEmitter;
- });
- }
- else if (typeof module === 'object' && module.exports){
- module.exports = EventEmitter;
- }
- else {
- exports.EventEmitter = EventEmitter;
- }
-}(typeof window !== 'undefined' ? window : this || {}));
-
-},{}],16:[function(require,module,exports){
-"use strict";
-Object.defineProperty(exports, "__esModule", { value: true });
-var OpenVidu_1 = require("./OpenVidu/OpenVidu");
-if (window) {
- window['OpenVidu'] = OpenVidu_1.OpenVidu;
-}
-
-},{"./OpenVidu/OpenVidu":19}],17:[function(require,module,exports){
-"use strict";
-Object.defineProperty(exports, "__esModule", { value: true });
-var Stream_1 = require("./Stream");
-var Connection = (function () {
- function Connection(session, opts) {
- this.session = session;
- this.disposed = false;
- var msg = "'Connection' created ";
- if (!!opts) {
- msg += "(remote) with 'connectionId' [" + opts.id + ']';
- }
- else {
- msg += '(local)';
- }
- console.info(msg);
- this.options = opts;
- if (!!opts) {
- this.connectionId = opts.id;
- if (opts.metadata) {
- this.data = opts.metadata;
- }
- if (opts.streams) {
- this.initRemoteStreams(opts.streams);
- }
- }
- this.creationTime = new Date().getTime();
- }
- Connection.prototype.sendIceCandidate = function (candidate) {
- console.debug((!!this.stream.outboundStreamOpts ? 'Local' : 'Remote'), 'candidate for', this.connectionId, JSON.stringify(candidate));
- this.session.openvidu.sendRequest('onIceCandidate', {
- endpointName: this.connectionId,
- candidate: candidate.candidate,
- sdpMid: candidate.sdpMid,
- sdpMLineIndex: candidate.sdpMLineIndex
- }, function (error, response) {
- if (error) {
- console.error('Error sending ICE candidate: '
- + JSON.stringify(error));
- }
- });
- };
- Connection.prototype.initRemoteStreams = function (options) {
- var _this = this;
- options.forEach(function (opts) {
- var streamOptions = {
- id: opts.id,
- connection: _this,
- hasAudio: opts.hasAudio,
- hasVideo: opts.hasVideo,
- audioActive: opts.audioActive,
- videoActive: opts.videoActive,
- typeOfVideo: opts.typeOfVideo,
- frameRate: opts.frameRate,
- videoDimensions: !!opts.videoDimensions ? JSON.parse(opts.videoDimensions) : undefined
- };
- var stream = new Stream_1.Stream(_this.session, streamOptions);
- _this.addStream(stream);
- });
- console.info("Remote 'Connection' with 'connectionId' [" + this.connectionId + '] is now configured for receiving Streams with options: ', this.stream.inboundStreamOpts);
- };
- Connection.prototype.addStream = function (stream) {
- stream.connection = this;
- this.stream = stream;
- };
- Connection.prototype.removeStream = function (streamId) {
- delete this.stream;
- };
- Connection.prototype.dispose = function () {
- if (!!this.stream) {
- delete this.stream;
- }
- this.disposed = true;
- };
- return Connection;
-}());
-exports.Connection = Connection;
-
-},{"./Stream":22}],18:[function(require,module,exports){
-"use strict";
-Object.defineProperty(exports, "__esModule", { value: true });
-var LocalRecorderState_1 = require("../OpenViduInternal/Enums/LocalRecorderState");
-var LocalRecorder = (function () {
- function LocalRecorder(stream) {
- this.stream = stream;
- this.chunks = [];
- this.count = 0;
- this.connectionId = (!!this.stream.connection) ? this.stream.connection.connectionId : 'default-connection';
- this.id = this.stream.streamId + '_' + this.connectionId + '_localrecord';
- this.state = LocalRecorderState_1.LocalRecorderState.READY;
- }
- LocalRecorder.prototype.record = function () {
- var _this = this;
- return new Promise(function (resolve, reject) {
- try {
- if (typeof MediaRecorder === 'undefined') {
- console.error('MediaRecorder not supported on your browser. See compatibility in https://caniuse.com/#search=MediaRecorder');
- throw (Error('MediaRecorder not supported on your browser. See compatibility in https://caniuse.com/#search=MediaRecorder'));
- }
- if (_this.state !== LocalRecorderState_1.LocalRecorderState.READY) {
- throw (Error('\'LocalRecord.record()\' needs \'LocalRecord.state\' to be \'READY\' (current value: \'' + _this.state + '\'). Call \'LocalRecorder.clean()\' or init a new LocalRecorder before'));
- }
- console.log("Starting local recording of stream '" + _this.stream.streamId + "' of connection '" + _this.connectionId + "'");
- if (typeof MediaRecorder.isTypeSupported === 'function') {
- var options = void 0;
- if (MediaRecorder.isTypeSupported('video/webm;codecs=vp9')) {
- options = { mimeType: 'video/webm;codecs=vp9' };
- }
- else if (MediaRecorder.isTypeSupported('video/webm;codecs=h264')) {
- options = { mimeType: 'video/webm;codecs=h264' };
- }
- else if (MediaRecorder.isTypeSupported('video/webm;codecs=vp8')) {
- options = { mimeType: 'video/webm;codecs=vp8' };
- }
- console.log('Using mimeType ' + options.mimeType);
- _this.mediaRecorder = new MediaRecorder(_this.stream.getMediaStream(), options);
- }
- else {
- console.warn('isTypeSupported is not supported, using default codecs for browser');
- _this.mediaRecorder = new MediaRecorder(_this.stream.getMediaStream());
- }
- _this.mediaRecorder.start(10);
- }
- catch (err) {
- reject(err);
- }
- _this.mediaRecorder.ondataavailable = function (e) {
- _this.chunks.push(e.data);
- };
- _this.mediaRecorder.onerror = function (e) {
- console.error('MediaRecorder error: ', e);
- };
- _this.mediaRecorder.onstart = function () {
- console.log('MediaRecorder started (state=' + _this.mediaRecorder.state + ')');
- };
- _this.mediaRecorder.onstop = function () {
- _this.onStopDefault();
- };
- _this.mediaRecorder.onpause = function () {
- console.log('MediaRecorder paused (state=' + _this.mediaRecorder.state + ')');
- };
- _this.mediaRecorder.onresume = function () {
- console.log('MediaRecorder resumed (state=' + _this.mediaRecorder.state + ')');
- };
- _this.mediaRecorder.onwarning = function (e) {
- console.log('MediaRecorder warning: ' + e);
- };
- _this.state = LocalRecorderState_1.LocalRecorderState.RECORDING;
- resolve();
- });
- };
- LocalRecorder.prototype.stop = function () {
- var _this = this;
- return new Promise(function (resolve, reject) {
- try {
- if (_this.state === LocalRecorderState_1.LocalRecorderState.READY || _this.state === LocalRecorderState_1.LocalRecorderState.FINISHED) {
- throw (Error('\'LocalRecord.stop()\' needs \'LocalRecord.state\' to be \'RECORDING\' or \'PAUSED\' (current value: \'' + _this.state + '\'). Call \'LocalRecorder.start()\' before'));
- }
- _this.mediaRecorder.onstop = function () {
- _this.onStopDefault();
- resolve();
- };
- _this.mediaRecorder.stop();
- }
- catch (e) {
- reject(e);
- }
- });
- };
- LocalRecorder.prototype.pause = function () {
- var _this = this;
- return new Promise(function (resolve, reject) {
- try {
- if (_this.state !== LocalRecorderState_1.LocalRecorderState.RECORDING) {
- reject(Error('\'LocalRecord.pause()\' needs \'LocalRecord.state\' to be \'RECORDING\' (current value: \'' + _this.state + '\'). Call \'LocalRecorder.start()\' or \'LocalRecorder.resume()\' before'));
- }
- _this.mediaRecorder.pause();
- _this.state = LocalRecorderState_1.LocalRecorderState.PAUSED;
- }
- catch (error) {
- reject(error);
- }
- });
- };
- LocalRecorder.prototype.resume = function () {
- var _this = this;
- return new Promise(function (resolve, reject) {
- try {
- if (_this.state !== LocalRecorderState_1.LocalRecorderState.PAUSED) {
- throw (Error('\'LocalRecord.resume()\' needs \'LocalRecord.state\' to be \'PAUSED\' (current value: \'' + _this.state + '\'). Call \'LocalRecorder.pause()\' before'));
- }
- _this.mediaRecorder.resume();
- _this.state = LocalRecorderState_1.LocalRecorderState.RECORDING;
- }
- catch (error) {
- reject(error);
- }
- });
- };
- LocalRecorder.prototype.preview = function (parentElement) {
- if (this.state !== LocalRecorderState_1.LocalRecorderState.FINISHED) {
- throw (Error('\'LocalRecord.preview()\' needs \'LocalRecord.state\' to be \'FINISHED\' (current value: \'' + this.state + '\'). Call \'LocalRecorder.stop()\' before'));
- }
- this.videoPreview = document.createElement('video');
- this.videoPreview.id = this.id;
- this.videoPreview.autoplay = true;
- if (typeof parentElement === 'string') {
- this.htmlParentElementId = parentElement;
- var parentElementDom = document.getElementById(parentElement);
- if (parentElementDom) {
- this.videoPreview = parentElementDom.appendChild(this.videoPreview);
- }
- }
- else {
- this.htmlParentElementId = parentElement.id;
- this.videoPreview = parentElement.appendChild(this.videoPreview);
- }
- this.videoPreview.src = this.videoPreviewSrc;
- return this.videoPreview;
- };
- LocalRecorder.prototype.clean = function () {
- var _this = this;
- var f = function () {
- delete _this.blob;
- _this.chunks = [];
- _this.count = 0;
- delete _this.mediaRecorder;
- _this.state = LocalRecorderState_1.LocalRecorderState.READY;
- };
- if (this.state === LocalRecorderState_1.LocalRecorderState.RECORDING || this.state === LocalRecorderState_1.LocalRecorderState.PAUSED) {
- this.stop().then(function () { return f(); }).catch(function () { return f(); });
- }
- else {
- f();
- }
- };
- LocalRecorder.prototype.download = function () {
- if (this.state !== LocalRecorderState_1.LocalRecorderState.FINISHED) {
- throw (Error('\'LocalRecord.download()\' needs \'LocalRecord.state\' to be \'FINISHED\' (current value: \'' + this.state + '\'). Call \'LocalRecorder.stop()\' before'));
- }
- else {
- var a = document.createElement('a');
- a.style.display = 'none';
- document.body.appendChild(a);
- var url = window.URL.createObjectURL(this.blob);
- a.href = url;
- a.download = this.id + '.webm';
- a.click();
- window.URL.revokeObjectURL(url);
- document.body.removeChild(a);
- }
- };
- LocalRecorder.prototype.getBlob = function () {
- if (this.state !== LocalRecorderState_1.LocalRecorderState.FINISHED) {
- throw (Error('Call \'LocalRecord.stop()\' before getting Blob file'));
- }
- else {
- return this.blob;
- }
- };
- LocalRecorder.prototype.uploadAsBinary = function (endpoint, headers) {
- var _this = this;
- return new Promise(function (resolve, reject) {
- if (_this.state !== LocalRecorderState_1.LocalRecorderState.FINISHED) {
- reject(Error('\'LocalRecord.uploadAsBinary()\' needs \'LocalRecord.state\' to be \'FINISHED\' (current value: \'' + _this.state + '\'). Call \'LocalRecorder.stop()\' before'));
- }
- else {
- var http_1 = new XMLHttpRequest();
- http_1.open('POST', endpoint, true);
- if (typeof headers === 'object') {
- for (var _i = 0, _a = Object.keys(headers); _i < _a.length; _i++) {
- var key = _a[_i];
- http_1.setRequestHeader(key, headers[key]);
- }
- }
- http_1.onreadystatechange = function () {
- if (http_1.readyState === 4) {
- if (http_1.status.toString().charAt(0) === '2') {
- resolve(http_1.responseText);
- }
- else {
- reject(http_1.status);
- }
- }
- };
- http_1.send(_this.blob);
- }
- });
- };
- LocalRecorder.prototype.uploadAsMultipartfile = function (endpoint, headers) {
- var _this = this;
- return new Promise(function (resolve, reject) {
- if (_this.state !== LocalRecorderState_1.LocalRecorderState.FINISHED) {
- reject(Error('\'LocalRecord.uploadAsMultipartfile()\' needs \'LocalRecord.state\' to be \'FINISHED\' (current value: \'' + _this.state + '\'). Call \'LocalRecorder.stop()\' before'));
- }
- else {
- var http_2 = new XMLHttpRequest();
- http_2.open('POST', endpoint, true);
- if (typeof headers === 'object') {
- for (var _i = 0, _a = Object.keys(headers); _i < _a.length; _i++) {
- var key = _a[_i];
- http_2.setRequestHeader(key, headers[key]);
- }
- }
- var sendable = new FormData();
- sendable.append('file', _this.blob, _this.id + '.webm');
- http_2.onreadystatechange = function () {
- if (http_2.readyState === 4) {
- if (http_2.status.toString().charAt(0) === '2') {
- resolve(http_2.responseText);
- }
- else {
- reject(http_2.status);
- }
- }
- };
- http_2.send(sendable);
- }
- });
- };
- LocalRecorder.prototype.onStopDefault = function () {
- console.log('MediaRecorder stopped (state=' + this.mediaRecorder.state + ')');
- this.blob = new Blob(this.chunks, { type: 'video/webm' });
- this.chunks = [];
- this.videoPreviewSrc = window.URL.createObjectURL(this.blob);
- this.state = LocalRecorderState_1.LocalRecorderState.FINISHED;
- };
- return LocalRecorder;
-}());
-exports.LocalRecorder = LocalRecorder;
-
-},{"../OpenViduInternal/Enums/LocalRecorderState":25}],19:[function(require,module,exports){
-"use strict";
-Object.defineProperty(exports, "__esModule", { value: true });
-var LocalRecorder_1 = require("./LocalRecorder");
-var Publisher_1 = require("./Publisher");
-var Session_1 = require("./Session");
-var StreamPropertyChangedEvent_1 = require("../OpenViduInternal/Events/StreamPropertyChangedEvent");
-var OpenViduError_1 = require("../OpenViduInternal/Enums/OpenViduError");
-var VideoInsertMode_1 = require("../OpenViduInternal/Enums/VideoInsertMode");
-var screenSharingAuto = require("../OpenViduInternal/ScreenSharing/Screen-Capturing-Auto");
-var screenSharing = require("../OpenViduInternal/ScreenSharing/Screen-Capturing");
-var RpcBuilder = require("../OpenViduInternal/KurentoUtils/kurento-jsonrpc");
-var platform = require("platform");
-var OpenVidu = (function () {
- function OpenVidu() {
- var _this = this;
- this.publishers = [];
- this.secret = '';
- this.recorder = false;
- this.advancedConfiguration = {};
- console.info("'OpenVidu' initialized");
- if (platform.name.toLowerCase().indexOf('mobile') !== -1) {
- window.onorientationchange = function () {
- _this.publishers.forEach(function (publisher) {
- if (!!publisher.stream && !!publisher.stream.hasVideo && !!publisher.stream.streamManager.videos[0]) {
- var attempts_1 = 0;
- var oldWidth_1 = publisher.stream.videoDimensions.width;
- var oldHeight_1 = publisher.stream.videoDimensions.height;
- var firefoxSettings_1 = publisher.stream.getMediaStream().getVideoTracks()[0].getSettings();
- var newWidth_1 = (platform.name.toLowerCase().indexOf('firefox') !== -1) ? firefoxSettings_1.width : publisher.videoReference.videoWidth;
- var newHeight_1 = (platform.name.toLowerCase().indexOf('firefox') !== -1) ? firefoxSettings_1.height : publisher.videoReference.videoHeight;
- var repeatUntilChange_1 = setInterval(function () {
- firefoxSettings_1 = publisher.stream.getMediaStream().getVideoTracks()[0].getSettings();
- newWidth_1 = (platform.name.toLowerCase().indexOf('firefox') !== -1) ? firefoxSettings_1.width : publisher.videoReference.videoWidth;
- newHeight_1 = (platform.name.toLowerCase().indexOf('firefox') !== -1) ? firefoxSettings_1.height : publisher.videoReference.videoHeight;
- sendStreamPropertyChangedEvent_1(oldWidth_1, oldHeight_1, newWidth_1, newHeight_1);
- }, 100);
- var sendStreamPropertyChangedEvent_1 = function (oldWidth, oldHeight, newWidth, newHeight) {
- attempts_1++;
- if (attempts_1 > 4) {
- clearTimeout(repeatUntilChange_1);
- }
- if (newWidth !== oldWidth || newHeight !== oldHeight) {
- publisher.stream.videoDimensions = {
- width: newWidth || 0,
- height: newHeight || 0
- };
- _this.sendRequest('streamPropertyChanged', {
- streamId: publisher.stream.streamId,
- property: 'videoDimensions',
- newValue: JSON.stringify(publisher.stream.videoDimensions),
- reason: 'deviceRotated'
- }, function (error, response) {
- if (error) {
- console.error("Error sending 'streamPropertyChanged' event", error);
- }
- else {
- _this.session.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent_1.StreamPropertyChangedEvent(_this.session, publisher.stream, 'videoDimensions', publisher.stream.videoDimensions, { width: oldWidth, height: oldHeight }, 'deviceRotated')]);
- publisher.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent_1.StreamPropertyChangedEvent(publisher, publisher.stream, 'videoDimensions', publisher.stream.videoDimensions, { width: oldWidth, height: oldHeight }, 'deviceRotated')]);
- }
- });
- clearTimeout(repeatUntilChange_1);
- }
- };
- }
- });
- };
- }
- }
- OpenVidu.prototype.initSession = function () {
- this.session = new Session_1.Session(this);
- return this.session;
- };
- OpenVidu.prototype.initPublisher = function (targetElement, param2, param3) {
- var properties;
- if (!!param2 && (typeof param2 !== 'function')) {
- properties = param2;
- properties = {
- audioSource: (typeof properties.audioSource !== 'undefined') ? properties.audioSource : undefined,
- frameRate: this.isMediaStreamTrack(properties.videoSource) ? undefined : ((typeof properties.frameRate !== 'undefined') ? properties.frameRate : undefined),
- insertMode: (typeof properties.insertMode !== 'undefined') ? ((typeof properties.insertMode === 'string') ? VideoInsertMode_1.VideoInsertMode[properties.insertMode] : properties.insertMode) : VideoInsertMode_1.VideoInsertMode.APPEND,
- mirror: (typeof properties.mirror !== 'undefined') ? properties.mirror : true,
- publishAudio: (typeof properties.publishAudio !== 'undefined') ? properties.publishAudio : true,
- publishVideo: (typeof properties.publishVideo !== 'undefined') ? properties.publishVideo : true,
- resolution: this.isMediaStreamTrack(properties.videoSource) ? undefined : ((typeof properties.resolution !== 'undefined') ? properties.resolution : '640x480'),
- videoSource: (typeof properties.videoSource !== 'undefined') ? properties.videoSource : undefined
- };
- }
- else {
- properties = {
- insertMode: VideoInsertMode_1.VideoInsertMode.APPEND,
- mirror: true,
- publishAudio: true,
- publishVideo: true,
- resolution: '640x480'
- };
- }
- var publisher = new Publisher_1.Publisher(targetElement, properties, this);
- var completionHandler;
- if (!!param2 && (typeof param2 === 'function')) {
- completionHandler = param2;
- }
- else if (!!param3) {
- completionHandler = param3;
- }
- publisher.initialize()
- .then(function () {
- if (completionHandler !== undefined) {
- completionHandler(undefined);
- }
- publisher.emitEvent('accessAllowed', []);
- }).catch(function (error) {
- if (completionHandler !== undefined) {
- completionHandler(error);
- }
- publisher.emitEvent('accessDenied', []);
- });
- this.publishers.push(publisher);
- return publisher;
- };
- OpenVidu.prototype.initPublisherAsync = function (targetElement, properties) {
- var _this = this;
- return new Promise(function (resolve, reject) {
- var publisher;
- var callback = function (error) {
- if (!!error) {
- reject(error);
- }
- else {
- resolve(publisher);
- }
- };
- if (!!properties) {
- publisher = _this.initPublisher(targetElement, properties, callback);
- }
- else {
- publisher = _this.initPublisher(targetElement, callback);
- }
- });
- };
- OpenVidu.prototype.initLocalRecorder = function (stream) {
- return new LocalRecorder_1.LocalRecorder(stream);
- };
- OpenVidu.prototype.checkSystemRequirements = function () {
- var browser = platform.name;
- var version = platform.version;
- if ((browser !== 'Chrome') && (browser !== 'Chrome Mobile') &&
- (browser !== 'Firefox') && (browser !== 'Firefox Mobile') && (browser !== 'Firefox for iOS') &&
- (browser !== 'Opera') && (browser !== 'Opera Mobile') &&
- (browser !== 'Safari')) {
- return 0;
- }
- else {
- return 1;
- }
- };
- OpenVidu.prototype.getDevices = function () {
- return new Promise(function (resolve, reject) {
- navigator.mediaDevices.enumerateDevices().then(function (deviceInfos) {
- var devices = [];
- deviceInfos.forEach(function (deviceInfo) {
- if (deviceInfo.kind === 'audioinput' || deviceInfo.kind === 'videoinput') {
- devices.push({
- kind: deviceInfo.kind,
- deviceId: deviceInfo.deviceId,
- label: deviceInfo.label
- });
- }
- });
- resolve(devices);
- }).catch(function (error) {
- console.error('Error getting devices', error);
- reject(error);
- });
- });
- };
- OpenVidu.prototype.getUserMedia = function (options) {
- var _this = this;
- return new Promise(function (resolve, reject) {
- _this.generateMediaConstraints(options)
- .then(function (constraints) {
- navigator.mediaDevices.getUserMedia(constraints)
- .then(function (mediaStream) {
- resolve(mediaStream);
- })
- .catch(function (error) {
- var errorName;
- var errorMessage = error.toString();
- if (!(options.videoSource === 'screen')) {
- errorName = OpenViduError_1.OpenViduErrorName.DEVICE_ACCESS_DENIED;
- }
- else {
- errorName = OpenViduError_1.OpenViduErrorName.SCREEN_CAPTURE_DENIED;
- }
- reject(new OpenViduError_1.OpenViduError(errorName, errorMessage));
- });
- })
- .catch(function (error) {
- reject(error);
- });
- });
- };
- OpenVidu.prototype.enableProdMode = function () {
- console.log = function () { };
- console.debug = function () { };
- console.info = function () { };
- console.warn = function () { };
- };
- OpenVidu.prototype.setAdvancedConfiguration = function (configuration) {
- this.advancedConfiguration = configuration;
- };
- OpenVidu.prototype.generateMediaConstraints = function (publisherProperties) {
- var _this = this;
- return new Promise(function (resolve, reject) {
- var audio, video;
- if (publisherProperties.audioSource === null || publisherProperties.audioSource === false) {
- audio = false;
- }
- else if (publisherProperties.audioSource === undefined) {
- audio = true;
- }
- else {
- audio = publisherProperties.audioSource;
- }
- if (publisherProperties.videoSource === null || publisherProperties.videoSource === false) {
- video = false;
- }
- else {
- video = {
- height: {
- ideal: 480
- },
- width: {
- ideal: 640
- }
- };
- }
- var mediaConstraints = {
- audio: audio,
- video: video
- };
- if (typeof mediaConstraints.audio === 'string') {
- mediaConstraints.audio = { deviceId: { exact: mediaConstraints.audio } };
- }
- if (mediaConstraints.video) {
- if (!!publisherProperties.resolution) {
- var widthAndHeight = publisherProperties.resolution.toLowerCase().split('x');
- var width = Number(widthAndHeight[0]);
- var height = Number(widthAndHeight[1]);
- mediaConstraints.video.width.ideal = width;
- mediaConstraints.video.height.ideal = height;
- }
- if (!!publisherProperties.frameRate) {
- mediaConstraints.video.frameRate = { ideal: publisherProperties.frameRate };
- }
- if (!!publisherProperties.videoSource && typeof publisherProperties.videoSource === 'string') {
- if (publisherProperties.videoSource === 'screen') {
- if (platform.name !== 'Chrome' && platform.name.indexOf('Firefox') === -1) {
- var error = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_SHARING_NOT_SUPPORTED, 'You can only screen share in desktop Chrome and Firefox. Detected browser: ' + platform.name);
- console.error(error);
- reject(error);
- }
- else {
- if (!!_this.advancedConfiguration.screenShareChromeExtension && !(platform.name.indexOf('Firefox') !== -1)) {
- screenSharing.getScreenConstraints(function (error, screenConstraints) {
- if (!!error || !!screenConstraints.mandatory && screenConstraints.mandatory.chromeMediaSource === 'screen') {
- if (error === 'permission-denied' || error === 'PermissionDeniedError') {
- var error_1 = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_CAPTURE_DENIED, 'You must allow access to one window of your desktop');
- console.error(error_1);
- reject(error_1);
- }
- else {
- var extensionId = _this.advancedConfiguration.screenShareChromeExtension.split('/').pop().trim();
- screenSharing.getChromeExtensionStatus(extensionId, function (status) {
- if (status === 'installed-disabled') {
- var error_2 = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_EXTENSION_DISABLED, 'You must enable the screen extension');
- console.error(error_2);
- reject(error_2);
- }
- if (status === 'not-installed') {
- var error_3 = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_EXTENSION_NOT_INSTALLED, _this.advancedConfiguration.screenShareChromeExtension);
- console.error(error_3);
- reject(error_3);
- }
- });
- }
- }
- else {
- mediaConstraints.video = screenConstraints;
- resolve(mediaConstraints);
- }
- });
- }
- else {
- screenSharingAuto.getScreenId(function (error, sourceId, screenConstraints) {
- if (!!error) {
- if (error === 'not-installed') {
- var extensionUrl = !!_this.advancedConfiguration.screenShareChromeExtension ? _this.advancedConfiguration.screenShareChromeExtension :
- 'https://chrome.google.com/webstore/detail/openvidu-screensharing/lfcgfepafnobdloecchnfaclibenjold';
- var error_4 = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_EXTENSION_NOT_INSTALLED, extensionUrl);
- console.error(error_4);
- reject(error_4);
- }
- else if (error === 'installed-disabled') {
- var error_5 = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_EXTENSION_DISABLED, 'You must enable the screen extension');
- console.error(error_5);
- reject(error_5);
- }
- else if (error === 'permission-denied') {
- var error_6 = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_CAPTURE_DENIED, 'You must allow access to one window of your desktop');
- console.error(error_6);
- reject(error_6);
- }
- }
- else {
- mediaConstraints.video = screenConstraints.video;
- resolve(mediaConstraints);
- }
- });
- }
- publisherProperties.videoSource = 'screen';
- }
- }
- else {
- mediaConstraints.video['deviceId'] = { exact: publisherProperties.videoSource };
- resolve(mediaConstraints);
- }
- }
- else {
- resolve(mediaConstraints);
- }
- }
- else {
- resolve(mediaConstraints);
- }
- });
- };
- OpenVidu.prototype.startWs = function (onConnectSucces) {
- var config = {
- heartbeat: 5000,
- sendCloseMessage: false,
- ws: {
- uri: this.wsUri,
- useSockJS: false,
- onconnected: onConnectSucces,
- ondisconnect: this.disconnectCallback.bind(this),
- onreconnecting: this.reconnectingCallback.bind(this),
- onreconnected: this.reconnectedCallback.bind(this)
- },
- rpc: {
- requestTimeout: 10000,
- participantJoined: this.session.onParticipantJoined.bind(this.session),
- participantPublished: this.session.onParticipantPublished.bind(this.session),
- participantUnpublished: this.session.onParticipantUnpublished.bind(this.session),
- participantLeft: this.session.onParticipantLeft.bind(this.session),
- participantEvicted: this.session.onParticipantEvicted.bind(this.session),
- recordingStarted: this.session.onRecordingStarted.bind(this.session),
- recordingStopped: this.session.onRecordingStopped.bind(this.session),
- sendMessage: this.session.onNewMessage.bind(this.session),
- streamPropertyChanged: this.session.onStreamPropertyChanged.bind(this.session),
- iceCandidate: this.session.recvIceCandidate.bind(this.session),
- mediaError: this.session.onMediaError.bind(this.session)
- }
- };
- this.jsonRpcClient = new RpcBuilder.clients.JsonRpcClient(config);
- };
- OpenVidu.prototype.closeWs = function () {
- this.jsonRpcClient.close();
- };
- OpenVidu.prototype.sendRequest = function (method, params, callback) {
- if (params && params instanceof Function) {
- callback = params;
- params = {};
- }
- console.debug('Sending request: {method:"' + method + '", params: ' + JSON.stringify(params) + '}');
- this.jsonRpcClient.send(method, params, callback);
- };
- OpenVidu.prototype.isMediaStreamTrack = function (mediaSource) {
- var is = (!!mediaSource &&
- mediaSource.enabled !== undefined && typeof mediaSource.enabled === 'boolean' &&
- mediaSource.id !== undefined && typeof mediaSource.id === 'string' &&
- mediaSource.kind !== undefined && typeof mediaSource.kind === 'string' &&
- mediaSource.label !== undefined && typeof mediaSource.label === 'string' &&
- mediaSource.muted !== undefined && typeof mediaSource.muted === 'boolean' &&
- mediaSource.readyState !== undefined && typeof mediaSource.readyState === 'string');
- return is;
- };
- OpenVidu.prototype.getWsUri = function () {
- return this.wsUri;
- };
- OpenVidu.prototype.getSecret = function () {
- return this.secret;
- };
- OpenVidu.prototype.getRecorder = function () {
- return this.recorder;
- };
- OpenVidu.prototype.disconnectCallback = function () {
- console.warn('Websocket connection lost');
- if (this.isRoomAvailable()) {
- this.session.onLostConnection();
- }
- else {
- alert('Connection error. Please reload page.');
- }
- };
- OpenVidu.prototype.reconnectingCallback = function () {
- console.warn('Websocket connection lost (reconnecting)');
- if (this.isRoomAvailable()) {
- this.session.onLostConnection();
- }
- else {
- alert('Connection error. Please reload page.');
- }
- };
- OpenVidu.prototype.reconnectedCallback = function () {
- console.warn('Websocket reconnected');
- if (this.isRoomAvailable()) {
- this.session.onRecoveredConnection();
- }
- else {
- alert('Connection error. Please reload page.');
- }
- };
- OpenVidu.prototype.isRoomAvailable = function () {
- if (this.session !== undefined && this.session instanceof Session_1.Session) {
- return true;
- }
- else {
- console.warn('Session instance not found');
- return false;
- }
- };
- return OpenVidu;
-}());
-exports.OpenVidu = OpenVidu;
-
-},{"../OpenViduInternal/Enums/OpenViduError":26,"../OpenViduInternal/Enums/VideoInsertMode":27,"../OpenViduInternal/Events/StreamPropertyChangedEvent":36,"../OpenViduInternal/KurentoUtils/kurento-jsonrpc":43,"../OpenViduInternal/ScreenSharing/Screen-Capturing":48,"../OpenViduInternal/ScreenSharing/Screen-Capturing-Auto":47,"./LocalRecorder":18,"./Publisher":20,"./Session":21,"platform":8}],20:[function(require,module,exports){
-"use strict";
-var __extends = (this && this.__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 __());
- };
-})();
-Object.defineProperty(exports, "__esModule", { value: true });
-var Session_1 = require("./Session");
-var Stream_1 = require("./Stream");
-var StreamManager_1 = require("./StreamManager");
-var StreamEvent_1 = require("../OpenViduInternal/Events/StreamEvent");
-var StreamPropertyChangedEvent_1 = require("../OpenViduInternal/Events/StreamPropertyChangedEvent");
-var VideoElementEvent_1 = require("../OpenViduInternal/Events/VideoElementEvent");
-var OpenViduError_1 = require("../OpenViduInternal/Enums/OpenViduError");
-var platform = require("platform");
-var Publisher = (function (_super) {
- __extends(Publisher, _super);
- function Publisher(targEl, properties, openvidu) {
- var _this = _super.call(this, new Stream_1.Stream((!!openvidu.session) ? openvidu.session : new Session_1.Session(openvidu), { publisherProperties: properties, mediaConstraints: {} }), targEl) || this;
- _this.accessAllowed = false;
- _this.isSubscribedToRemote = false;
- _this.accessDenied = false;
- _this.properties = properties;
- _this.openvidu = openvidu;
- _this.stream.ee.on('local-stream-destroyed', function (reason) {
- _this.stream.isLocalStreamPublished = false;
- var streamEvent = new StreamEvent_1.StreamEvent(true, _this, 'streamDestroyed', _this.stream, reason);
- _this.emitEvent('streamDestroyed', [streamEvent]);
- streamEvent.callDefaultBehavior();
- });
- return _this;
- }
- Publisher.prototype.publishAudio = function (value) {
- var _this = this;
- if (this.stream.audioActive !== value) {
- this.stream.getMediaStream().getAudioTracks().forEach(function (track) {
- track.enabled = value;
- });
- this.session.openvidu.sendRequest('streamPropertyChanged', {
- streamId: this.stream.streamId,
- property: 'audioActive',
- newValue: value,
- reason: 'publishAudio'
- }, function (error, response) {
- if (error) {
- console.error("Error sending 'streamPropertyChanged' event", error);
- }
- else {
- _this.session.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent_1.StreamPropertyChangedEvent(_this.session, _this.stream, 'audioActive', value, !value, 'publishAudio')]);
- _this.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent_1.StreamPropertyChangedEvent(_this, _this.stream, 'audioActive', value, !value, 'publishAudio')]);
- }
- });
- this.stream.audioActive = value;
- console.info("'Publisher' has " + (value ? 'published' : 'unpublished') + ' its audio stream');
- }
- };
- Publisher.prototype.publishVideo = function (value) {
- var _this = this;
- if (this.stream.videoActive !== value) {
- this.stream.getMediaStream().getVideoTracks().forEach(function (track) {
- track.enabled = value;
- });
- this.session.openvidu.sendRequest('streamPropertyChanged', {
- streamId: this.stream.streamId,
- property: 'videoActive',
- newValue: value,
- reason: 'publishVideo'
- }, function (error, response) {
- if (error) {
- console.error("Error sending 'streamPropertyChanged' event", error);
- }
- else {
- _this.session.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent_1.StreamPropertyChangedEvent(_this.session, _this.stream, 'videoActive', value, !value, 'publishVideo')]);
- _this.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent_1.StreamPropertyChangedEvent(_this, _this.stream, 'videoActive', value, !value, 'publishVideo')]);
- }
- });
- this.stream.videoActive = value;
- console.info("'Publisher' has " + (value ? 'published' : 'unpublished') + ' its video stream');
- }
- };
- Publisher.prototype.subscribeToRemote = function (value) {
- value = (value !== undefined) ? value : true;
- this.isSubscribedToRemote = value;
- this.stream.subscribeToMyRemote(value);
- };
- Publisher.prototype.on = function (type, handler) {
- var _this = this;
- _super.prototype.on.call(this, type, handler);
- if (type === 'streamCreated') {
- if (!!this.stream && this.stream.isLocalStreamPublished) {
- this.emitEvent('streamCreated', [new StreamEvent_1.StreamEvent(false, this, 'streamCreated', this.stream, '')]);
- }
- else {
- this.stream.ee.on('stream-created-by-publisher', function () {
- _this.emitEvent('streamCreated', [new StreamEvent_1.StreamEvent(false, _this, 'streamCreated', _this.stream, '')]);
- });
- }
- }
- if (type === 'remoteVideoPlaying') {
- if (this.stream.displayMyRemote() && this.videos[0] && this.videos[0].video &&
- this.videos[0].video.currentTime > 0 &&
- this.videos[0].video.paused === false &&
- this.videos[0].video.ended === false &&
- this.videos[0].video.readyState === 4) {
- this.emitEvent('remoteVideoPlaying', [new VideoElementEvent_1.VideoElementEvent(this.videos[0].video, this, 'remoteVideoPlaying')]);
- }
- }
- if (type === 'accessAllowed') {
- if (this.accessAllowed) {
- this.emitEvent('accessAllowed', []);
- }
- }
- if (type === 'accessDenied') {
- if (this.accessDenied) {
- this.emitEvent('accessDenied', []);
- }
- }
- return this;
- };
- Publisher.prototype.once = function (type, handler) {
- var _this = this;
- _super.prototype.once.call(this, type, handler);
- if (type === 'streamCreated') {
- if (!!this.stream && this.stream.isLocalStreamPublished) {
- this.emitEvent('streamCreated', [new StreamEvent_1.StreamEvent(false, this, 'streamCreated', this.stream, '')]);
- }
- else {
- this.stream.ee.once('stream-created-by-publisher', function () {
- _this.emitEvent('streamCreated', [new StreamEvent_1.StreamEvent(false, _this, 'streamCreated', _this.stream, '')]);
- });
- }
- }
- if (type === 'remoteVideoPlaying') {
- if (this.stream.displayMyRemote() && this.videos[0] && this.videos[0].video &&
- this.videos[0].video.currentTime > 0 &&
- this.videos[0].video.paused === false &&
- this.videos[0].video.ended === false &&
- this.videos[0].video.readyState === 4) {
- this.emitEvent('remoteVideoPlaying', [new VideoElementEvent_1.VideoElementEvent(this.videos[0].video, this, 'remoteVideoPlaying')]);
- }
- }
- if (type === 'accessAllowed') {
- if (this.accessAllowed) {
- this.emitEvent('accessAllowed', []);
- }
- }
- if (type === 'accessDenied') {
- if (this.accessDenied) {
- this.emitEvent('accessDenied', []);
- }
- }
- return this;
- };
- Publisher.prototype.initialize = function () {
- var _this = this;
- return new Promise(function (resolve, reject) {
- var errorCallback = function (openViduError) {
- _this.accessDenied = true;
- _this.accessAllowed = false;
- reject(openViduError);
- };
- var successCallback = function (mediaStream) {
- _this.accessAllowed = true;
- _this.accessDenied = false;
- if (_this.openvidu.isMediaStreamTrack(_this.properties.audioSource)) {
- mediaStream.removeTrack(mediaStream.getAudioTracks()[0]);
- mediaStream.addTrack(_this.properties.audioSource);
- }
- if (_this.openvidu.isMediaStreamTrack(_this.properties.videoSource)) {
- mediaStream.removeTrack(mediaStream.getVideoTracks()[0]);
- mediaStream.addTrack(_this.properties.videoSource);
- }
- if (!!mediaStream.getAudioTracks()[0]) {
- mediaStream.getAudioTracks()[0].enabled = !!_this.stream.outboundStreamOpts.publisherProperties.publishAudio;
- }
- if (!!mediaStream.getVideoTracks()[0]) {
- mediaStream.getVideoTracks()[0].enabled = !!_this.stream.outboundStreamOpts.publisherProperties.publishVideo;
- }
- _this.videoReference = document.createElement('video');
- _this.videoReference.srcObject = mediaStream;
- _this.stream.setMediaStream(mediaStream);
- if (!_this.stream.displayMyRemote()) {
- _this.stream.updateMediaStreamInVideos();
- }
- if (!!_this.firstVideoElement) {
- _this.createVideoElement(_this.firstVideoElement.targetElement, _this.properties.insertMode);
- }
- delete _this.firstVideoElement;
- if (_this.stream.isSendVideo()) {
- if (!_this.stream.isSendScreen()) {
- var _a = mediaStream.getVideoTracks()[0].getSettings(), width = _a.width, height = _a.height;
- if (platform.name.toLowerCase().indexOf('mobile') !== -1 && (window.innerHeight > window.innerWidth)) {
- _this.stream.videoDimensions = {
- width: height || 0,
- height: width || 0
- };
- }
- else {
- _this.stream.videoDimensions = {
- width: width || 0,
- height: height || 0
- };
- }
- _this.stream.isLocalStreamReadyToPublish = true;
- _this.stream.ee.emitEvent('stream-ready-to-publish', []);
- }
- else {
- _this.videoReference.onloadedmetadata = function () {
- _this.stream.videoDimensions = {
- width: _this.videoReference.videoWidth,
- height: _this.videoReference.videoHeight
- };
- _this.screenShareResizeInterval = setInterval(function () {
- var firefoxSettings = mediaStream.getVideoTracks()[0].getSettings();
- var newWidth = (platform.name === 'Chrome') ? _this.videoReference.videoWidth : firefoxSettings.width;
- var newHeight = (platform.name === 'Chrome') ? _this.videoReference.videoHeight : firefoxSettings.height;
- if (_this.stream.isLocalStreamPublished &&
- (newWidth !== _this.stream.videoDimensions.width ||
- newHeight !== _this.stream.videoDimensions.height)) {
- var oldValue_1 = { width: _this.stream.videoDimensions.width, height: _this.stream.videoDimensions.height };
- _this.stream.videoDimensions = {
- width: newWidth || 0,
- height: newHeight || 0
- };
- _this.session.openvidu.sendRequest('streamPropertyChanged', {
- streamId: _this.stream.streamId,
- property: 'videoDimensions',
- newValue: JSON.stringify(_this.stream.videoDimensions),
- reason: 'screenResized'
- }, function (error, response) {
- if (error) {
- console.error("Error sending 'streamPropertyChanged' event", error);
- }
- else {
- _this.session.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent_1.StreamPropertyChangedEvent(_this.session, _this.stream, 'videoDimensions', _this.stream.videoDimensions, oldValue_1, 'screenResized')]);
- _this.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent_1.StreamPropertyChangedEvent(_this, _this.stream, 'videoDimensions', _this.stream.videoDimensions, oldValue_1, 'screenResized')]);
- }
- });
- }
- }, 500);
- _this.stream.isLocalStreamReadyToPublish = true;
- _this.stream.ee.emitEvent('stream-ready-to-publish', []);
- };
- }
- }
- else {
- _this.stream.isLocalStreamReadyToPublish = true;
- _this.stream.ee.emitEvent('stream-ready-to-publish', []);
- }
- resolve();
- };
- _this.openvidu.generateMediaConstraints(_this.properties)
- .then(function (constraints) {
- var outboundStreamOptions = {
- mediaConstraints: constraints,
- publisherProperties: _this.properties
- };
- _this.stream.setOutboundStreamOptions(outboundStreamOptions);
- var constraintsAux = {};
- var timeForDialogEvent = 1250;
- if (_this.stream.isSendVideo() || _this.stream.isSendAudio()) {
- var definedAudioConstraint_1 = ((constraints.audio === undefined) ? true : constraints.audio);
- constraintsAux.audio = _this.stream.isSendScreen() ? false : definedAudioConstraint_1;
- constraintsAux.video = constraints.video;
- var startTime_1 = Date.now();
- _this.setPermissionDialogTimer(timeForDialogEvent);
- navigator.mediaDevices.getUserMedia(constraintsAux)
- .then(function (mediaStream) {
- _this.clearPermissionDialogTimer(startTime_1, timeForDialogEvent);
- if (_this.stream.isSendScreen() && _this.stream.isSendAudio()) {
- constraintsAux.audio = definedAudioConstraint_1;
- constraintsAux.video = false;
- startTime_1 = Date.now();
- _this.setPermissionDialogTimer(timeForDialogEvent);
- navigator.mediaDevices.getUserMedia(constraintsAux)
- .then(function (audioOnlyStream) {
- _this.clearPermissionDialogTimer(startTime_1, timeForDialogEvent);
- mediaStream.addTrack(audioOnlyStream.getAudioTracks()[0]);
- successCallback(mediaStream);
- })
- .catch(function (error) {
- _this.clearPermissionDialogTimer(startTime_1, timeForDialogEvent);
- var errorName, errorMessage;
- switch (error.name.toLowerCase()) {
- case 'notfounderror':
- errorName = OpenViduError_1.OpenViduErrorName.INPUT_AUDIO_DEVICE_NOT_FOUND;
- errorMessage = error.toString();
- errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage));
- break;
- case 'notallowederror':
- errorName = OpenViduError_1.OpenViduErrorName.DEVICE_ACCESS_DENIED;
- errorMessage = error.toString();
- errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage));
- break;
- case 'overconstrainederror':
- if (error.constraint.toLowerCase() === 'deviceid') {
- errorName = OpenViduError_1.OpenViduErrorName.INPUT_AUDIO_DEVICE_NOT_FOUND;
- errorMessage = "Audio input device with deviceId '" + constraints.video.deviceId.exact + "' not found";
- }
- else {
- errorName = OpenViduError_1.OpenViduErrorName.PUBLISHER_PROPERTIES_ERROR;
- errorMessage = "Audio input device doesn't support the value passed for constraint '" + error.constraint + "'";
- }
- errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage));
- break;
- }
- });
- }
- else {
- successCallback(mediaStream);
- }
- })
- .catch(function (error) {
- _this.clearPermissionDialogTimer(startTime_1, timeForDialogEvent);
- var errorName, errorMessage;
- switch (error.name.toLowerCase()) {
- case 'notfounderror':
- navigator.mediaDevices.getUserMedia({
- audio: false,
- video: constraints.video
- })
- .then(function (mediaStream) {
- mediaStream.getVideoTracks().forEach(function (track) {
- track.stop();
- });
- errorName = OpenViduError_1.OpenViduErrorName.INPUT_AUDIO_DEVICE_NOT_FOUND;
- errorMessage = error.toString();
- errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage));
- }).catch(function (e) {
- errorName = OpenViduError_1.OpenViduErrorName.INPUT_VIDEO_DEVICE_NOT_FOUND;
- errorMessage = error.toString();
- errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage));
- });
- break;
- case 'notallowederror':
- errorName = _this.stream.isSendScreen() ? OpenViduError_1.OpenViduErrorName.SCREEN_CAPTURE_DENIED : OpenViduError_1.OpenViduErrorName.DEVICE_ACCESS_DENIED;
- errorMessage = error.toString();
- errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage));
- break;
- case 'overconstrainederror':
- navigator.mediaDevices.getUserMedia({
- audio: false,
- video: constraints.video
- })
- .then(function (mediaStream) {
- mediaStream.getVideoTracks().forEach(function (track) {
- track.stop();
- });
- if (error.constraint.toLowerCase() === 'deviceid') {
- errorName = OpenViduError_1.OpenViduErrorName.INPUT_AUDIO_DEVICE_NOT_FOUND;
- errorMessage = "Audio input device with deviceId '" + constraints.audio.deviceId.exact + "' not found";
- }
- else {
- errorName = OpenViduError_1.OpenViduErrorName.PUBLISHER_PROPERTIES_ERROR;
- errorMessage = "Audio input device doesn't support the value passed for constraint '" + error.constraint + "'";
- }
- errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage));
- }).catch(function (e) {
- if (error.constraint.toLowerCase() === 'deviceid') {
- errorName = OpenViduError_1.OpenViduErrorName.INPUT_VIDEO_DEVICE_NOT_FOUND;
- errorMessage = "Video input device with deviceId '" + constraints.video.deviceId.exact + "' not found";
- }
- else {
- errorName = OpenViduError_1.OpenViduErrorName.PUBLISHER_PROPERTIES_ERROR;
- errorMessage = "Video input device doesn't support the value passed for constraint '" + error.constraint + "'";
- }
- errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage));
- });
- break;
- }
- });
- }
- else {
- reject(new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.NO_INPUT_SOURCE_SET, "Properties 'audioSource' and 'videoSource' cannot be set to false or null at the same time when calling 'OpenVidu.initPublisher'"));
- }
- })
- .catch(function (error) {
- errorCallback(error);
- });
- });
- };
- Publisher.prototype.updateSession = function (session) {
- this.session = session;
- this.stream.session = session;
- };
- Publisher.prototype.reestablishStreamPlayingEvent = function () {
- if (this.ee.getListeners('streamPlaying').length > 0) {
- this.addPlayEventToFirstVideo();
- }
- };
- Publisher.prototype.setPermissionDialogTimer = function (waitTime) {
- var _this = this;
- this.permissionDialogTimeout = setTimeout(function () {
- _this.emitEvent('accessDialogOpened', []);
- }, waitTime);
- };
- Publisher.prototype.clearPermissionDialogTimer = function (startTime, waitTime) {
- clearTimeout(this.permissionDialogTimeout);
- if ((Date.now() - startTime) > waitTime) {
- this.emitEvent('accessDialogClosed', []);
- }
- };
- return Publisher;
-}(StreamManager_1.StreamManager));
-exports.Publisher = Publisher;
-
-},{"../OpenViduInternal/Enums/OpenViduError":26,"../OpenViduInternal/Events/StreamEvent":34,"../OpenViduInternal/Events/StreamPropertyChangedEvent":36,"../OpenViduInternal/Events/VideoElementEvent":37,"./Session":21,"./Stream":22,"./StreamManager":23,"platform":8}],21:[function(require,module,exports){
-"use strict";
-Object.defineProperty(exports, "__esModule", { value: true });
-var Connection_1 = require("./Connection");
-var Subscriber_1 = require("./Subscriber");
-var ConnectionEvent_1 = require("../OpenViduInternal/Events/ConnectionEvent");
-var RecordingEvent_1 = require("../OpenViduInternal/Events/RecordingEvent");
-var SessionDisconnectedEvent_1 = require("../OpenViduInternal/Events/SessionDisconnectedEvent");
-var SignalEvent_1 = require("../OpenViduInternal/Events/SignalEvent");
-var StreamEvent_1 = require("../OpenViduInternal/Events/StreamEvent");
-var StreamPropertyChangedEvent_1 = require("../OpenViduInternal/Events/StreamPropertyChangedEvent");
-var OpenViduError_1 = require("../OpenViduInternal/Enums/OpenViduError");
-var VideoInsertMode_1 = require("../OpenViduInternal/Enums/VideoInsertMode");
-var platform = require("platform");
-var EventEmitter = require("wolfy87-eventemitter");
-var Session = (function () {
- function Session(openvidu) {
- this.streamManagers = [];
- this.remoteStreamsCreated = {};
- this.remoteConnections = {};
- this.speakingEventsEnabled = false;
- this.ee = new EventEmitter();
- this.openvidu = openvidu;
- }
- Session.prototype.connect = function (token, metadata) {
- var _this = this;
- return new Promise(function (resolve, reject) {
- _this.processToken(token);
- if (_this.openvidu.checkSystemRequirements()) {
- _this.options = {
- sessionId: _this.sessionId,
- participantId: token,
- metadata: !!metadata ? _this.stringClientMetadata(metadata) : ''
- };
- _this.connectAux(token).then(function () {
- resolve();
- }).catch(function (error) {
- reject(error);
- });
- }
- else {
- reject(new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.BROWSER_NOT_SUPPORTED, 'Browser ' + platform.name + ' ' + platform.version + ' is not supported in OpenVidu'));
- }
- });
- };
- Session.prototype.disconnect = function () {
- this.leave(false, 'disconnect');
- };
- Session.prototype.subscribe = function (stream, targetElement, param3, param4) {
- var properties = {};
- if (!!param3 && typeof param3 !== 'function') {
- properties = {
- insertMode: (typeof param3.insertMode !== 'undefined') ? ((typeof param3.insertMode === 'string') ? VideoInsertMode_1.VideoInsertMode[param3.insertMode] : properties.insertMode) : VideoInsertMode_1.VideoInsertMode.APPEND,
- subscribeToAudio: (typeof param3.subscribeToAudio !== 'undefined') ? param3.subscribeToAudio : true,
- subscribeToVideo: (typeof param3.subscribeToVideo !== 'undefined') ? param3.subscribeToVideo : true
- };
- }
- else {
- properties = {
- insertMode: VideoInsertMode_1.VideoInsertMode.APPEND,
- subscribeToAudio: true,
- subscribeToVideo: true
- };
- }
- var completionHandler;
- if (!!param3 && (typeof param3 === 'function')) {
- completionHandler = param3;
- }
- else if (!!param4) {
- completionHandler = param4;
- }
- console.info('Subscribing to ' + stream.connection.connectionId);
- stream.subscribe()
- .then(function () {
- console.info('Subscribed correctly to ' + stream.connection.connectionId);
- if (completionHandler !== undefined) {
- completionHandler(undefined);
- }
- })
- .catch(function (error) {
- if (completionHandler !== undefined) {
- completionHandler(error);
- }
- });
- var subscriber = new Subscriber_1.Subscriber(stream, targetElement, properties);
- if (!!subscriber.targetElement) {
- stream.streamManager.createVideoElement(subscriber.targetElement, properties.insertMode);
- }
- return subscriber;
- };
- Session.prototype.subscribeAsync = function (stream, targetElement, properties) {
- var _this = this;
- return new Promise(function (resolve, reject) {
- var subscriber;
- var callback = function (error) {
- if (!!error) {
- reject(error);
- }
- else {
- resolve(subscriber);
- }
- };
- if (!!properties) {
- subscriber = _this.subscribe(stream, targetElement, properties, callback);
- }
- else {
- subscriber = _this.subscribe(stream, targetElement, callback);
- }
- });
- };
- Session.prototype.unsubscribe = function (subscriber) {
- var connectionId = subscriber.stream.connection.connectionId;
- console.info('Unsubscribing from ' + connectionId);
- this.openvidu.sendRequest('unsubscribeFromVideo', { sender: subscriber.stream.connection.connectionId }, function (error, response) {
- if (error) {
- console.error('Error unsubscribing from ' + connectionId, error);
- }
- else {
- console.info('Unsubscribed correctly from ' + connectionId);
- }
- subscriber.stream.disposeWebRtcPeer();
- subscriber.stream.disposeMediaStream();
- });
- subscriber.stream.streamManager.removeAllVideos();
- };
- Session.prototype.publish = function (publisher) {
- var _this = this;
- return new Promise(function (resolve, reject) {
- publisher.session = _this;
- publisher.stream.session = _this;
- if (!publisher.stream.publishedOnce) {
- _this.connection.addStream(publisher.stream);
- publisher.stream.publish()
- .then(function () {
- resolve();
- })
- .catch(function (error) {
- reject(error);
- });
- }
- else {
- publisher.initialize()
- .then(function () {
- _this.connection.addStream(publisher.stream);
- publisher.reestablishStreamPlayingEvent();
- publisher.stream.publish()
- .then(function () {
- resolve();
- })
- .catch(function (error) {
- reject(error);
- });
- }).catch(function (error) {
- reject(error);
- });
- }
- });
- };
- Session.prototype.unpublish = function (publisher) {
- var stream = publisher.stream;
- if (!stream.connection) {
- console.error('The associated Connection object of this Publisher is null', stream);
- return;
- }
- else if (stream.connection !== this.connection) {
- console.error('The associated Connection object of this Publisher is not your local Connection.' +
- "Only moderators can force unpublish on remote Streams via 'forceUnpublish' method", stream);
- return;
- }
- else {
- console.info('Unpublishing local media (' + stream.connection.connectionId + ')');
- this.openvidu.sendRequest('unpublishVideo', function (error, response) {
- if (error) {
- console.error(error);
- }
- else {
- console.info('Media unpublished correctly');
- }
- });
- stream.disposeWebRtcPeer();
- delete stream.connection.stream;
- var streamEvent = new StreamEvent_1.StreamEvent(true, publisher, 'streamDestroyed', publisher.stream, 'unpublish');
- publisher.emitEvent('streamDestroyed', [streamEvent]);
- streamEvent.callDefaultBehavior();
- }
- };
- Session.prototype.forceDisconnect = function (connection) {
- var _this = this;
- return new Promise(function (resolve, reject) {
- console.info('Forcing disconnect for connection ' + connection.connectionId);
- _this.openvidu.sendRequest('forceDisconnect', { connectionId: connection.connectionId }, function (error, response) {
- if (error) {
- console.error('Error forcing disconnect for Connection ' + connection.connectionId, error);
- if (error.code === 401) {
- reject(new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.OPENVIDU_PERMISSION_DENIED, "You don't have permissions to force a disconnection"));
- }
- else {
- reject(error);
- }
- }
- else {
- console.info('Forcing disconnect correctly for Connection ' + connection.connectionId);
- resolve();
- }
- });
- });
- };
- Session.prototype.forceUnpublish = function (stream) {
- var _this = this;
- return new Promise(function (resolve, reject) {
- console.info('Forcing unpublish for stream ' + stream.streamId);
- _this.openvidu.sendRequest('forceUnpublish', { streamId: stream.streamId }, function (error, response) {
- if (error) {
- console.error('Error forcing unpublish for Stream ' + stream.streamId, error);
- if (error.code === 401) {
- reject(new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.OPENVIDU_PERMISSION_DENIED, "You don't have permissions to force an unpublishing"));
- }
- else {
- reject(error);
- }
- }
- else {
- console.info('Forcing unpublish correctly for Stream ' + stream.streamId);
- resolve();
- }
- });
- });
- };
- Session.prototype.signal = function (signal) {
- var _this = this;
- return new Promise(function (resolve, reject) {
- var signalMessage = {};
- if (signal.to && signal.to.length > 0) {
- var connectionIds_1 = [];
- signal.to.forEach(function (connection) {
- connectionIds_1.push(connection.connectionId);
- });
- signalMessage['to'] = connectionIds_1;
- }
- else {
- signalMessage['to'] = [];
- }
- signalMessage['data'] = signal.data ? signal.data : '';
- signalMessage['type'] = signal.type ? signal.type : '';
- _this.openvidu.sendRequest('sendMessage', {
- message: JSON.stringify(signalMessage)
- }, function (error, response) {
- if (!!error) {
- reject(error);
- }
- else {
- resolve();
- }
- });
- });
- };
- Session.prototype.on = function (type, handler) {
- this.ee.on(type, function (event) {
- if (event) {
- console.info("Event '" + type + "' triggered by 'Session'", event);
- }
- else {
- console.info("Event '" + type + "' triggered by 'Session'");
- }
- handler(event);
- });
- if (type === 'publisherStartSpeaking' || type === 'publisherStopSpeaking') {
- this.speakingEventsEnabled = true;
- for (var connectionId in this.remoteConnections) {
- var str = this.remoteConnections[connectionId].stream;
- if (!!str && !str.speechEvent && str.hasAudio) {
- str.enableSpeakingEvents();
- }
- }
- }
- return this;
- };
- Session.prototype.once = function (type, handler) {
- this.ee.once(type, function (event) {
- if (event) {
- console.info("Event '" + type + "' triggered by 'Session'", event);
- }
- else {
- console.info("Event '" + type + "' triggered by 'Session'");
- }
- handler(event);
- });
- if (type === 'publisherStartSpeaking' || type === 'publisherStopSpeaking') {
- this.speakingEventsEnabled = true;
- for (var connectionId in this.remoteConnections) {
- var str = this.remoteConnections[connectionId].stream;
- if (!!str && !str.speechEvent && str.hasAudio) {
- str.enableOnceSpeakingEvents();
- }
- }
- }
- return this;
- };
- Session.prototype.off = function (type, handler) {
- if (!handler) {
- this.ee.removeAllListeners(type);
- }
- else {
- this.ee.off(type, handler);
- }
- if (type === 'publisherStartSpeaking' || type === 'publisherStopSpeaking') {
- this.speakingEventsEnabled = false;
- for (var connectionId in this.remoteConnections) {
- var str = this.remoteConnections[connectionId].stream;
- if (!!str && !!str.speechEvent) {
- str.disableSpeakingEvents();
- }
- }
- }
- return this;
- };
- Session.prototype.onParticipantJoined = function (response) {
- var _this = this;
- this.getConnection(response.id, '')
- .then(function (connection) {
- console.warn('Connection ' + response.id + ' already exists in connections list');
- })
- .catch(function (openViduError) {
- var connection = new Connection_1.Connection(_this, response);
- _this.remoteConnections[response.id] = connection;
- _this.ee.emitEvent('connectionCreated', [new ConnectionEvent_1.ConnectionEvent(false, _this, 'connectionCreated', connection, '')]);
- });
- };
- Session.prototype.onParticipantLeft = function (msg) {
- var _this = this;
- this.getRemoteConnection(msg.connectionId, 'Remote connection ' + msg.connectionId + " unknown when 'onParticipantLeft'. " +
- 'Existing remote connections: ' + JSON.stringify(Object.keys(this.remoteConnections)))
- .then(function (connection) {
- if (!!connection.stream) {
- var stream = connection.stream;
- var streamEvent = new StreamEvent_1.StreamEvent(true, _this, 'streamDestroyed', stream, msg.reason);
- _this.ee.emitEvent('streamDestroyed', [streamEvent]);
- streamEvent.callDefaultBehavior();
- delete _this.remoteStreamsCreated[stream.streamId];
- }
- delete _this.remoteConnections[connection.connectionId];
- _this.ee.emitEvent('connectionDestroyed', [new ConnectionEvent_1.ConnectionEvent(false, _this, 'connectionDestroyed', connection, msg.reason)]);
- })
- .catch(function (openViduError) {
- console.error(openViduError);
- });
- };
- Session.prototype.onParticipantPublished = function (response) {
- var _this = this;
- var afterConnectionFound = function (connection) {
- _this.remoteConnections[connection.connectionId] = connection;
- if (!_this.remoteStreamsCreated[connection.stream.streamId]) {
- _this.ee.emitEvent('streamCreated', [new StreamEvent_1.StreamEvent(false, _this, 'streamCreated', connection.stream, '')]);
- }
- _this.remoteStreamsCreated[connection.stream.streamId] = true;
- };
- var connection;
- this.getRemoteConnection(response.id, "Remote connection '" + response.id + "' unknown when 'onParticipantPublished'. " +
- 'Existing remote connections: ' + JSON.stringify(Object.keys(this.remoteConnections)))
- .then(function (con) {
- connection = con;
- response.metadata = con.data;
- connection.options = response;
- connection.initRemoteStreams(response.streams);
- afterConnectionFound(connection);
- })
- .catch(function (openViduError) {
- connection = new Connection_1.Connection(_this, response);
- afterConnectionFound(connection);
- });
- };
- Session.prototype.onParticipantUnpublished = function (msg) {
- var _this = this;
- if (msg.connectionId === this.connection.connectionId) {
- this.stopPublisherStream(msg.reason);
- }
- else {
- this.getRemoteConnection(msg.connectionId, "Remote connection '" + msg.connectionId + "' unknown when 'onParticipantUnpublished'. " +
- 'Existing remote connections: ' + JSON.stringify(Object.keys(this.remoteConnections)))
- .then(function (connection) {
- var streamEvent = new StreamEvent_1.StreamEvent(true, _this, 'streamDestroyed', connection.stream, msg.reason);
- _this.ee.emitEvent('streamDestroyed', [streamEvent]);
- streamEvent.callDefaultBehavior();
- var streamId = connection.stream.streamId;
- delete _this.remoteStreamsCreated[streamId];
- connection.removeStream(streamId);
- })
- .catch(function (openViduError) {
- console.error(openViduError);
- });
- }
- };
- Session.prototype.onParticipantEvicted = function (msg) {
- if (msg.connectionId === this.connection.connectionId) {
- if (!!this.sessionId && !this.connection.disposed) {
- this.leave(true, msg.reason);
- }
- }
- };
- Session.prototype.onNewMessage = function (msg) {
- var _this = this;
- console.info('New signal: ' + JSON.stringify(msg));
- this.getConnection(msg.from, "Connection '" + msg.from + "' unknow when 'onNewMessage'. Existing remote connections: "
- + JSON.stringify(Object.keys(this.remoteConnections)) + '. Existing local connection: ' + this.connection.connectionId)
- .then(function (connection) {
- _this.ee.emitEvent('signal', [new SignalEvent_1.SignalEvent(_this, msg.type, msg.data, connection)]);
- _this.ee.emitEvent('signal:' + msg.type, [new SignalEvent_1.SignalEvent(_this, msg.type, msg.data, connection)]);
- })
- .catch(function (openViduError) {
- console.error(openViduError);
- });
- };
- Session.prototype.onStreamPropertyChanged = function (msg) {
- var _this = this;
- this.getRemoteConnection(msg.connectionId, 'Remote connection ' + msg.connectionId + " unknown when 'onStreamPropertyChanged'. " +
- 'Existing remote connections: ' + JSON.stringify(Object.keys(this.remoteConnections)))
- .then(function (connection) {
- if (!!connection.stream && connection.stream.streamId === msg.streamId) {
- var stream = connection.stream;
- var oldValue = void 0;
- switch (msg.property) {
- case 'audioActive':
- oldValue = stream.audioActive;
- msg.newValue = msg.newValue === 'true';
- stream.audioActive = msg.newValue;
- break;
- case 'videoActive':
- oldValue = stream.videoActive;
- msg.newValue = msg.newValue === 'true';
- stream.videoActive = msg.newValue;
- break;
- case 'videoDimensions':
- oldValue = stream.videoDimensions;
- msg.newValue = JSON.parse(JSON.parse(msg.newValue));
- stream.videoDimensions = msg.newValue;
- break;
- }
- _this.ee.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent_1.StreamPropertyChangedEvent(_this, stream, msg.property, msg.newValue, oldValue, msg.reason)]);
- stream.streamManager.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent_1.StreamPropertyChangedEvent(stream.streamManager, stream, msg.property, msg.newValue, oldValue, msg.reason)]);
- }
- else {
- console.error("No stream with streamId '" + msg.streamId + "' found for connection '" + msg.connectionId + "' on 'streamPropertyChanged' event");
- }
- })
- .catch(function (openViduError) {
- console.error(openViduError);
- });
- };
- Session.prototype.recvIceCandidate = function (msg) {
- var candidate = {
- candidate: msg.candidate,
- sdpMid: msg.sdpMid,
- sdpMLineIndex: msg.sdpMLineIndex,
- toJSON: function () {
- return { candidate: msg.candidate };
- }
- };
- this.getConnection(msg.endpointName, 'Connection not found for endpoint ' + msg.endpointName + '. Ice candidate will be ignored: ' + candidate)
- .then(function (connection) {
- var stream = connection.stream;
- stream.getWebRtcPeer().addIceCandidate(candidate).catch(function (error) {
- console.error('Error adding candidate for ' + stream.streamId
- + ' stream of endpoint ' + msg.endpointName + ': ' + error);
- });
- })
- .catch(function (openViduError) {
- console.error(openViduError);
- });
- };
- Session.prototype.onSessionClosed = function (msg) {
- console.info('Session closed: ' + JSON.stringify(msg));
- var s = msg.sessionId;
- if (s !== undefined) {
- this.ee.emitEvent('session-closed', [{
- session: s
- }]);
- }
- else {
- console.warn('Session undefined on session closed', msg);
- }
- };
- Session.prototype.onLostConnection = function () {
- console.warn('Lost connection in Session ' + this.sessionId);
- if (!!this.sessionId && !this.connection.disposed) {
- this.leave(true, 'networkDisconnect');
- }
- };
- Session.prototype.onRecoveredConnection = function () {
- console.warn('Recovered connection in Session ' + this.sessionId);
- this.ee.emitEvent('connectionRecovered', []);
- };
- Session.prototype.onMediaError = function (params) {
- console.error('Media error: ' + JSON.stringify(params));
- var err = params.error;
- if (err) {
- this.ee.emitEvent('error-media', [{
- error: err
- }]);
- }
- else {
- console.warn('Received undefined media error. Params:', params);
- }
- };
- Session.prototype.onRecordingStarted = function (response) {
- this.ee.emitEvent('recordingStarted', [new RecordingEvent_1.RecordingEvent(this, 'recordingStarted', response.id, response.name)]);
- };
- Session.prototype.onRecordingStopped = function (response) {
- this.ee.emitEvent('recordingStopped', [new RecordingEvent_1.RecordingEvent(this, 'recordingStopped', response.id, response.name)]);
- };
- Session.prototype.emitEvent = function (type, eventArray) {
- this.ee.emitEvent(type, eventArray);
- };
- Session.prototype.leave = function (forced, reason) {
- var _this = this;
- forced = !!forced;
- console.info('Leaving Session (forced=' + forced + ')');
- if (!!this.connection) {
- if (!this.connection.disposed && !forced) {
- this.openvidu.sendRequest('leaveRoom', function (error, response) {
- if (error) {
- console.error(error);
- }
- _this.openvidu.closeWs();
- });
- }
- else {
- this.openvidu.closeWs();
- }
- this.stopPublisherStream(reason);
- if (!this.connection.disposed) {
- var sessionDisconnectEvent = new SessionDisconnectedEvent_1.SessionDisconnectedEvent(this, reason);
- this.ee.emitEvent('sessionDisconnected', [sessionDisconnectEvent]);
- sessionDisconnectEvent.callDefaultBehavior();
- }
- }
- else {
- console.warn('You were not connected to the session ' + this.sessionId);
- }
- };
- Session.prototype.connectAux = function (token) {
- var _this = this;
- return new Promise(function (resolve, reject) {
- _this.openvidu.startWs(function (error) {
- if (!!error) {
- reject(error);
- }
- else {
- var joinParams = {
- token: (!!token) ? token : '',
- session: _this.sessionId,
- metadata: !!_this.options.metadata ? _this.options.metadata : '',
- secret: _this.openvidu.getSecret(),
- recorder: _this.openvidu.getRecorder(),
- };
- _this.openvidu.sendRequest('joinRoom', joinParams, function (error, response) {
- if (!!error) {
- reject(error);
- }
- else {
- _this.capabilities = {
- subscribe: true,
- publish: _this.openvidu.role !== 'SUBSCRIBER',
- forceUnpublish: _this.openvidu.role === 'MODERATOR',
- forceDisconnect: _this.openvidu.role === 'MODERATOR'
- };
- _this.connection = new Connection_1.Connection(_this);
- _this.connection.connectionId = response.id;
- _this.connection.data = response.metadata;
- var events_1 = {
- connections: new Array(),
- streams: new Array()
- };
- var existingParticipants = response.value;
- existingParticipants.forEach(function (participant) {
- var connection = new Connection_1.Connection(_this, participant);
- _this.remoteConnections[connection.connectionId] = connection;
- events_1.connections.push(connection);
- if (!!connection.stream) {
- _this.remoteStreamsCreated[connection.stream.streamId] = true;
- events_1.streams.push(connection.stream);
- }
- });
- _this.ee.emitEvent('connectionCreated', [new ConnectionEvent_1.ConnectionEvent(false, _this, 'connectionCreated', _this.connection, '')]);
- events_1.connections.forEach(function (connection) {
- _this.ee.emitEvent('connectionCreated', [new ConnectionEvent_1.ConnectionEvent(false, _this, 'connectionCreated', connection, '')]);
- });
- events_1.streams.forEach(function (stream) {
- _this.ee.emitEvent('streamCreated', [new StreamEvent_1.StreamEvent(false, _this, 'streamCreated', stream, '')]);
- });
- resolve();
- }
- });
- }
- });
- });
- };
- Session.prototype.stopPublisherStream = function (reason) {
- if (!!this.connection.stream) {
- this.connection.stream.disposeWebRtcPeer();
- if (this.connection.stream.isLocalStreamPublished) {
- this.connection.stream.ee.emitEvent('local-stream-destroyed', [reason]);
- }
- }
- };
- Session.prototype.stringClientMetadata = function (metadata) {
- if (typeof metadata !== 'string') {
- return JSON.stringify(metadata);
- }
- else {
- return metadata;
- }
- };
- Session.prototype.getConnection = function (connectionId, errorMessage) {
- var _this = this;
- return new Promise(function (resolve, reject) {
- var connection = _this.remoteConnections[connectionId];
- if (!!connection) {
- resolve(connection);
- }
- else {
- if (_this.connection.connectionId === connectionId) {
- resolve(_this.connection);
- }
- else {
- reject(new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.GENERIC_ERROR, errorMessage));
- }
- }
- });
- };
- Session.prototype.getRemoteConnection = function (connectionId, errorMessage) {
- var _this = this;
- return new Promise(function (resolve, reject) {
- var connection = _this.remoteConnections[connectionId];
- if (!!connection) {
- resolve(connection);
- }
- else {
- reject(new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.GENERIC_ERROR, errorMessage));
- }
- });
- };
- Session.prototype.processToken = function (token) {
- var url = new URL(token);
- this.sessionId = url.searchParams.get('sessionId');
- var secret = url.searchParams.get('secret');
- var recorder = url.searchParams.get('recorder');
- var turnUsername = url.searchParams.get('turnUsername');
- var turnCredential = url.searchParams.get('turnCredential');
- var role = url.searchParams.get('role');
- if (!!secret) {
- this.openvidu.secret = secret;
- }
- if (!!recorder) {
- this.openvidu.recorder = true;
- }
- if (!!turnUsername && !!turnCredential) {
- var stunUrl = 'stun:' + url.hostname + ':3478';
- var turnUrl1 = 'turn:' + url.hostname + ':3478';
- var turnUrl2 = turnUrl1 + '?transport=tcp';
- this.openvidu.iceServers = [
- { urls: [stunUrl] },
- { urls: [turnUrl1, turnUrl2], username: turnUsername, credential: turnCredential }
- ];
- console.log('TURN temp credentials [' + turnUsername + ':' + turnCredential + ']');
- }
- if (!!role) {
- this.openvidu.role = role;
- }
- this.openvidu.wsUri = 'wss://' + url.host + '/openvidu';
- };
- return Session;
-}());
-exports.Session = Session;
-
-},{"../OpenViduInternal/Enums/OpenViduError":26,"../OpenViduInternal/Enums/VideoInsertMode":27,"../OpenViduInternal/Events/ConnectionEvent":28,"../OpenViduInternal/Events/RecordingEvent":31,"../OpenViduInternal/Events/SessionDisconnectedEvent":32,"../OpenViduInternal/Events/SignalEvent":33,"../OpenViduInternal/Events/StreamEvent":34,"../OpenViduInternal/Events/StreamPropertyChangedEvent":36,"./Connection":17,"./Subscriber":24,"platform":8,"wolfy87-eventemitter":15}],22:[function(require,module,exports){
-"use strict";
-Object.defineProperty(exports, "__esModule", { value: true });
-var WebRtcPeer_1 = require("../OpenViduInternal/WebRtcPeer/WebRtcPeer");
-var WebRtcStats_1 = require("../OpenViduInternal/WebRtcStats/WebRtcStats");
-var PublisherSpeakingEvent_1 = require("../OpenViduInternal/Events/PublisherSpeakingEvent");
-var EventEmitter = require("wolfy87-eventemitter");
-var hark = require("hark");
-var OpenViduError_1 = require("../OpenViduInternal/Enums/OpenViduError");
-var Stream = (function () {
- function Stream(session, options) {
- var _this = this;
- this.ee = new EventEmitter();
- this.isSubscribeToRemote = false;
- this.isLocalStreamReadyToPublish = false;
- this.isLocalStreamPublished = false;
- this.publishedOnce = false;
- this.session = session;
- if (options.hasOwnProperty('id')) {
- this.inboundStreamOpts = options;
- this.streamId = this.inboundStreamOpts.id;
- this.hasAudio = this.inboundStreamOpts.hasAudio;
- this.hasVideo = this.inboundStreamOpts.hasVideo;
- if (this.hasAudio) {
- this.audioActive = this.inboundStreamOpts.audioActive;
- }
- if (this.hasVideo) {
- this.videoActive = this.inboundStreamOpts.videoActive;
- this.typeOfVideo = (!this.inboundStreamOpts.typeOfVideo) ? undefined : this.inboundStreamOpts.typeOfVideo;
- this.frameRate = (this.inboundStreamOpts.frameRate === -1) ? undefined : this.inboundStreamOpts.frameRate;
- this.videoDimensions = this.inboundStreamOpts.videoDimensions;
- }
- }
- else {
- this.outboundStreamOpts = options;
- this.hasAudio = this.isSendAudio();
- this.hasVideo = this.isSendVideo();
- if (this.hasAudio) {
- this.audioActive = !!this.outboundStreamOpts.publisherProperties.publishAudio;
- }
- if (this.hasVideo) {
- this.videoActive = !!this.outboundStreamOpts.publisherProperties.publishVideo;
- this.frameRate = this.outboundStreamOpts.publisherProperties.frameRate;
- if (this.outboundStreamOpts.publisherProperties.videoSource instanceof MediaStreamTrack) {
- this.typeOfVideo = 'CUSTOM';
- }
- else {
- this.typeOfVideo = this.isSendScreen() ? 'SCREEN' : 'CAMERA';
- }
- }
- }
- this.ee.on('mediastream-updated', function () {
- _this.streamManager.updateMediaStream(_this.mediaStream);
- console.debug('Video srcObject [' + _this.mediaStream + '] updated in stream [' + _this.streamId + ']');
- });
- }
- Stream.prototype.getMediaStream = function () {
- return this.mediaStream;
- };
- Stream.prototype.setMediaStream = function (mediaStream) {
- this.mediaStream = mediaStream;
- };
- Stream.prototype.updateMediaStreamInVideos = function () {
- this.ee.emitEvent('mediastream-updated');
- };
- Stream.prototype.getWebRtcPeer = function () {
- return this.webRtcPeer;
- };
- Stream.prototype.getRTCPeerConnection = function () {
- return this.webRtcPeer.pc;
- };
- Stream.prototype.subscribeToMyRemote = function (value) {
- this.isSubscribeToRemote = value;
- };
- Stream.prototype.setOutboundStreamOptions = function (outboundStreamOpts) {
- this.outboundStreamOpts = outboundStreamOpts;
- };
- Stream.prototype.subscribe = function () {
- var _this = this;
- return new Promise(function (resolve, reject) {
- _this.initWebRtcPeerReceive()
- .then(function () {
- resolve();
- })
- .catch(function (error) {
- reject(error);
- });
- });
- };
- Stream.prototype.publish = function () {
- var _this = this;
- return new Promise(function (resolve, reject) {
- if (_this.isLocalStreamReadyToPublish) {
- _this.initWebRtcPeerSend()
- .then(function () {
- resolve();
- })
- .catch(function (error) {
- reject(error);
- });
- }
- else {
- _this.ee.once('stream-ready-to-publish', function () {
- _this.publish()
- .then(function () {
- resolve();
- })
- .catch(function (error) {
- reject(error);
- });
- });
- }
- });
- };
- Stream.prototype.disposeWebRtcPeer = function () {
- if (this.webRtcPeer) {
- this.webRtcPeer.dispose();
- }
- if (this.speechEvent) {
- this.speechEvent.stop();
- }
- this.stopWebRtcStats();
- console.info((!!this.outboundStreamOpts ? 'Outbound ' : 'Inbound ') + "WebRTCPeer from 'Stream' with id [" + this.streamId + '] is now closed');
- };
- Stream.prototype.disposeMediaStream = function () {
- if (this.mediaStream) {
- this.mediaStream.getAudioTracks().forEach(function (track) {
- track.stop();
- });
- this.mediaStream.getVideoTracks().forEach(function (track) {
- track.stop();
- });
- delete this.mediaStream;
- }
- console.info((!!this.outboundStreamOpts ? 'Local ' : 'Remote ') + "MediaStream from 'Stream' with id [" + this.streamId + '] is now disposed');
- };
- Stream.prototype.displayMyRemote = function () {
- return this.isSubscribeToRemote;
- };
- Stream.prototype.isSendAudio = function () {
- return (!!this.outboundStreamOpts &&
- this.outboundStreamOpts.publisherProperties.audioSource !== null &&
- this.outboundStreamOpts.publisherProperties.audioSource !== false);
- };
- Stream.prototype.isSendVideo = function () {
- return (!!this.outboundStreamOpts &&
- this.outboundStreamOpts.publisherProperties.videoSource !== null &&
- this.outboundStreamOpts.publisherProperties.videoSource !== false);
- };
- Stream.prototype.isSendScreen = function () {
- return (!!this.outboundStreamOpts &&
- this.outboundStreamOpts.publisherProperties.videoSource === 'screen');
- };
- Stream.prototype.setSpeechEventIfNotExists = function () {
- if (!this.speechEvent) {
- var harkOptions = this.session.openvidu.advancedConfiguration.publisherSpeakingEventsOptions || {};
- harkOptions.interval = (typeof harkOptions.interval === 'number') ? harkOptions.interval : 50;
- harkOptions.threshold = (typeof harkOptions.threshold === 'number') ? harkOptions.threshold : -50;
- this.speechEvent = hark(this.mediaStream, harkOptions);
- }
- };
- Stream.prototype.enableSpeakingEvents = function () {
- var _this = this;
- this.setSpeechEventIfNotExists();
- this.speechEvent.on('speaking', function () {
- _this.session.emitEvent('publisherStartSpeaking', [new PublisherSpeakingEvent_1.PublisherSpeakingEvent(_this.session, 'publisherStartSpeaking', _this.connection, _this.streamId)]);
- });
- this.speechEvent.on('stopped_speaking', function () {
- _this.session.emitEvent('publisherStopSpeaking', [new PublisherSpeakingEvent_1.PublisherSpeakingEvent(_this.session, 'publisherStopSpeaking', _this.connection, _this.streamId)]);
- });
- };
- Stream.prototype.enableOnceSpeakingEvents = function () {
- var _this = this;
- this.setSpeechEventIfNotExists();
- this.speechEvent.on('speaking', function () {
- _this.session.emitEvent('publisherStartSpeaking', [new PublisherSpeakingEvent_1.PublisherSpeakingEvent(_this.session, 'publisherStartSpeaking', _this.connection, _this.streamId)]);
- _this.disableSpeakingEvents();
- });
- this.speechEvent.on('stopped_speaking', function () {
- _this.session.emitEvent('publisherStopSpeaking', [new PublisherSpeakingEvent_1.PublisherSpeakingEvent(_this.session, 'publisherStopSpeaking', _this.connection, _this.streamId)]);
- _this.disableSpeakingEvents();
- });
- };
- Stream.prototype.disableSpeakingEvents = function () {
- this.speechEvent.stop();
- this.speechEvent = undefined;
- };
- Stream.prototype.isLocal = function () {
- return (!this.inboundStreamOpts && !!this.outboundStreamOpts);
- };
- Stream.prototype.getSelectedIceCandidate = function () {
- var _this = this;
- return new Promise(function (resolve, reject) {
- _this.webRtcStats.getSelectedIceCandidateInfo()
- .then(function (report) { return resolve(report); })
- .catch(function (error) { return reject(error); });
- });
- };
- Stream.prototype.getRemoteIceCandidateList = function () {
- return this.webRtcPeer.remoteCandidatesQueue;
- };
- Stream.prototype.getLocalIceCandidateList = function () {
- return this.webRtcPeer.localCandidatesQueue;
- };
- Stream.prototype.initWebRtcPeerSend = function () {
- var _this = this;
- return new Promise(function (resolve, reject) {
- var userMediaConstraints = {
- audio: _this.isSendAudio(),
- video: _this.isSendVideo()
- };
- var options = {
- mediaStream: _this.mediaStream,
- mediaConstraints: userMediaConstraints,
- onicecandidate: _this.connection.sendIceCandidate.bind(_this.connection),
- iceServers: _this.getIceServersConf(),
- simulcast: false
- };
- var successCallback = function (sdpOfferParam) {
- console.debug('Sending SDP offer to publish as '
- + _this.streamId, sdpOfferParam);
- var typeOfVideo = '';
- if (_this.isSendVideo()) {
- typeOfVideo = _this.outboundStreamOpts.publisherProperties.videoSource instanceof MediaStreamTrack ? 'CUSTOM' : (_this.isSendScreen() ? 'SCREEN' : 'CAMERA');
- }
- _this.session.openvidu.sendRequest('publishVideo', {
- sdpOffer: sdpOfferParam,
- doLoopback: _this.displayMyRemote() || false,
- hasAudio: _this.isSendAudio(),
- hasVideo: _this.isSendVideo(),
- audioActive: _this.audioActive,
- videoActive: _this.videoActive,
- typeOfVideo: typeOfVideo,
- frameRate: !!_this.frameRate ? _this.frameRate : -1,
- videoDimensions: JSON.stringify(_this.videoDimensions)
- }, function (error, response) {
- if (error) {
- if (error.code === 401) {
- reject(new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.OPENVIDU_PERMISSION_DENIED, "You don't have permissions to publish"));
- }
- else {
- reject('Error on publishVideo: ' + JSON.stringify(error));
- }
- }
- else {
- _this.webRtcPeer.processAnswer(response.sdpAnswer)
- .then(function () {
- _this.streamId = response.id;
- _this.isLocalStreamPublished = true;
- _this.publishedOnce = true;
- if (_this.displayMyRemote()) {
- _this.remotePeerSuccessfullyEstablished();
- }
- _this.ee.emitEvent('stream-created-by-publisher');
- _this.initWebRtcStats();
- resolve();
- })
- .catch(function (error) {
- reject(error);
- });
- console.info("'Publisher' successfully published to session");
- }
- });
- };
- if (_this.displayMyRemote()) {
- _this.webRtcPeer = new WebRtcPeer_1.WebRtcPeerSendrecv(options);
- }
- else {
- _this.webRtcPeer = new WebRtcPeer_1.WebRtcPeerSendonly(options);
- }
- _this.webRtcPeer.generateOffer().then(function (offer) {
- successCallback(offer);
- }).catch(function (error) {
- reject(new Error('(publish) SDP offer error: ' + JSON.stringify(error)));
- });
- });
- };
- Stream.prototype.initWebRtcPeerReceive = function () {
- var _this = this;
- return new Promise(function (resolve, reject) {
- var offerConstraints = {
- audio: _this.inboundStreamOpts.hasAudio,
- video: _this.inboundStreamOpts.hasVideo
- };
- console.debug("'Session.subscribe(Stream)' called. Constraints of generate SDP offer", offerConstraints);
- var options = {
- onicecandidate: _this.connection.sendIceCandidate.bind(_this.connection),
- mediaConstraints: offerConstraints,
- iceServers: _this.getIceServersConf(),
- simulcast: false
- };
- var successCallback = function (sdpOfferParam) {
- console.debug('Sending SDP offer to subscribe to '
- + _this.streamId, sdpOfferParam);
- _this.session.openvidu.sendRequest('receiveVideoFrom', {
- sender: _this.streamId,
- sdpOffer: sdpOfferParam
- }, function (error, response) {
- if (error) {
- reject(new Error('Error on recvVideoFrom: ' + JSON.stringify(error)));
- }
- else {
- _this.webRtcPeer.processAnswer(response.sdpAnswer).then(function () {
- _this.remotePeerSuccessfullyEstablished();
- _this.initWebRtcStats();
- resolve();
- }).catch(function (error) {
- reject(error);
- });
- }
- });
- };
- _this.webRtcPeer = new WebRtcPeer_1.WebRtcPeerRecvonly(options);
- _this.webRtcPeer.generateOffer()
- .then(function (offer) {
- successCallback(offer);
- })
- .catch(function (error) {
- reject(new Error('(subscribe) SDP offer error: ' + JSON.stringify(error)));
- });
- });
- };
- Stream.prototype.remotePeerSuccessfullyEstablished = function () {
- this.mediaStream = this.webRtcPeer.pc.getRemoteStreams()[0];
- console.debug('Peer remote stream', this.mediaStream);
- if (!!this.mediaStream) {
- this.ee.emitEvent('mediastream-updated');
- if (!this.displayMyRemote() && !!this.mediaStream.getAudioTracks()[0] && this.session.speakingEventsEnabled) {
- this.enableSpeakingEvents();
- }
- }
- };
- Stream.prototype.initWebRtcStats = function () {
- this.webRtcStats = new WebRtcStats_1.WebRtcStats(this);
- this.webRtcStats.initWebRtcStats();
- };
- Stream.prototype.stopWebRtcStats = function () {
- if (!!this.webRtcStats && this.webRtcStats.isEnabled()) {
- this.webRtcStats.stopWebRtcStats();
- }
- };
- Stream.prototype.getIceServersConf = function () {
- var returnValue;
- if (!!this.session.openvidu.advancedConfiguration.iceServers) {
- returnValue = this.session.openvidu.advancedConfiguration.iceServers === 'freeice' ?
- undefined :
- this.session.openvidu.advancedConfiguration.iceServers;
- }
- else if (this.session.openvidu.iceServers) {
- returnValue = this.session.openvidu.iceServers;
- }
- else {
- returnValue = undefined;
- }
- return returnValue;
- };
- return Stream;
-}());
-exports.Stream = Stream;
-
-},{"../OpenViduInternal/Enums/OpenViduError":26,"../OpenViduInternal/Events/PublisherSpeakingEvent":30,"../OpenViduInternal/WebRtcPeer/WebRtcPeer":49,"../OpenViduInternal/WebRtcStats/WebRtcStats":50,"hark":5,"wolfy87-eventemitter":15}],23:[function(require,module,exports){
-"use strict";
-Object.defineProperty(exports, "__esModule", { value: true });
-var StreamManagerEvent_1 = require("../OpenViduInternal/Events/StreamManagerEvent");
-var VideoElementEvent_1 = require("../OpenViduInternal/Events/VideoElementEvent");
-var VideoInsertMode_1 = require("../OpenViduInternal/Enums/VideoInsertMode");
-var EventEmitter = require("wolfy87-eventemitter");
-var StreamManager = (function () {
- function StreamManager(stream, targetElement) {
- var _this = this;
- this.videos = [];
- this.lazyLaunchVideoElementCreatedEvent = false;
- this.ee = new EventEmitter();
- this.stream = stream;
- this.stream.streamManager = this;
- this.remote = !this.stream.isLocal();
- if (!!targetElement) {
- var targEl = void 0;
- if (typeof targetElement === 'string') {
- targEl = document.getElementById(targetElement);
- }
- else if (targetElement instanceof HTMLElement) {
- targEl = targetElement;
- }
- if (!!targEl) {
- this.firstVideoElement = {
- targetElement: targEl,
- video: document.createElement('video'),
- id: ''
- };
- this.targetElement = targEl;
- this.element = targEl;
- }
- }
- this.canPlayListener = function () {
- if (_this.stream.isLocal()) {
- if (!_this.stream.displayMyRemote()) {
- console.info("Your local 'Stream' with id [" + _this.stream.streamId + '] video is now playing');
- _this.ee.emitEvent('videoPlaying', [new VideoElementEvent_1.VideoElementEvent(_this.videos[0].video, _this, 'videoPlaying')]);
- }
- else {
- console.info("Your own remote 'Stream' with id [" + _this.stream.streamId + '] video is now playing');
- _this.ee.emitEvent('remoteVideoPlaying', [new VideoElementEvent_1.VideoElementEvent(_this.videos[0].video, _this, 'remoteVideoPlaying')]);
- }
- }
- else {
- console.info("Remote 'Stream' with id [" + _this.stream.streamId + '] video is now playing');
- _this.ee.emitEvent('videoPlaying', [new VideoElementEvent_1.VideoElementEvent(_this.videos[0].video, _this, 'videoPlaying')]);
- }
- _this.ee.emitEvent('streamPlaying', [new StreamManagerEvent_1.StreamManagerEvent(_this)]);
- };
- }
- StreamManager.prototype.on = function (type, handler) {
- var _this = this;
- this.ee.on(type, function (event) {
- if (event) {
- console.info("Event '" + type + "' triggered by '" + (_this.remote ? 'Subscriber' : 'Publisher') + "'", event);
- }
- else {
- console.info("Event '" + type + "' triggered by '" + (_this.remote ? 'Subscriber' : 'Publisher') + "'");
- }
- handler(event);
- });
- if (type === 'videoElementCreated') {
- if (!!this.stream && this.lazyLaunchVideoElementCreatedEvent) {
- this.ee.emitEvent('videoElementCreated', [new VideoElementEvent_1.VideoElementEvent(this.videos[0].video, this, 'videoElementCreated')]);
- this.lazyLaunchVideoElementCreatedEvent = false;
- }
- }
- if (type === 'streamPlaying' || type === 'videoPlaying') {
- if (this.videos[0] && this.videos[0].video &&
- this.videos[0].video.currentTime > 0 &&
- this.videos[0].video.paused === false &&
- this.videos[0].video.ended === false &&
- this.videos[0].video.readyState === 4) {
- this.ee.emitEvent('streamPlaying', [new StreamManagerEvent_1.StreamManagerEvent(this)]);
- this.ee.emitEvent('videoPlaying', [new VideoElementEvent_1.VideoElementEvent(this.videos[0].video, this, 'videoPlaying')]);
- }
- }
- return this;
- };
- StreamManager.prototype.once = function (type, handler) {
- this.ee.once(type, function (event) {
- if (event) {
- console.info("Event '" + type + "' triggered once", event);
- }
- else {
- console.info("Event '" + type + "' triggered once");
- }
- handler(event);
- });
- if (type === 'videoElementCreated') {
- if (!!this.stream && this.lazyLaunchVideoElementCreatedEvent) {
- this.ee.emitEvent('videoElementCreated', [new VideoElementEvent_1.VideoElementEvent(this.videos[0].video, this, 'videoElementCreated')]);
- }
- }
- if (type === 'streamPlaying' || type === 'videoPlaying') {
- if (this.videos[0] && this.videos[0].video &&
- this.videos[0].video.currentTime > 0 &&
- this.videos[0].video.paused === false &&
- this.videos[0].video.ended === false &&
- this.videos[0].video.readyState === 4) {
- this.ee.emitEvent('streamPlaying', [new StreamManagerEvent_1.StreamManagerEvent(this)]);
- this.ee.emitEvent('videoPlaying', [new VideoElementEvent_1.VideoElementEvent(this.videos[0].video, this, 'videoPlaying')]);
- }
- }
- return this;
- };
- StreamManager.prototype.off = function (type, handler) {
- if (!handler) {
- this.ee.removeAllListeners(type);
- }
- else {
- this.ee.off(type, handler);
- }
- return this;
- };
- StreamManager.prototype.addVideoElement = function (video) {
- this.initializeVideoProperties(video);
- for (var _i = 0, _a = this.videos; _i < _a.length; _i++) {
- var v = _a[_i];
- if (v.video === video) {
- return 0;
- }
- }
- var returnNumber = 1;
- for (var _b = 0, _c = this.stream.session.streamManagers; _b < _c.length; _b++) {
- var streamManager = _c[_b];
- if (streamManager.disassociateVideo(video)) {
- returnNumber = -1;
- break;
- }
- }
- this.stream.session.streamManagers.forEach(function (streamManager) {
- streamManager.disassociateVideo(video);
- });
- this.pushNewStreamManagerVideo({
- video: video,
- id: video.id
- });
- console.info('New video element associated to ', this);
- return returnNumber;
- };
- StreamManager.prototype.createVideoElement = function (targetElement, insertMode) {
- var targEl;
- if (typeof targetElement === 'string') {
- targEl = document.getElementById(targEl);
- if (!targEl) {
- throw new Error("The provided 'targetElement' couldn't be resolved to any HTML element: " + targetElement);
- }
- }
- else if (targetElement instanceof HTMLElement) {
- targEl = targetElement;
- }
- else {
- throw new Error("The provided 'targetElement' couldn't be resolved to any HTML element: " + targetElement);
- }
- var video = document.createElement('video');
- this.initializeVideoProperties(video);
- var insMode = !!insertMode ? insertMode : VideoInsertMode_1.VideoInsertMode.APPEND;
- switch (insMode) {
- case VideoInsertMode_1.VideoInsertMode.AFTER:
- targEl.parentNode.insertBefore(video, targEl.nextSibling);
- break;
- case VideoInsertMode_1.VideoInsertMode.APPEND:
- targEl.appendChild(video);
- break;
- case VideoInsertMode_1.VideoInsertMode.BEFORE:
- targEl.parentNode.insertBefore(video, targEl);
- break;
- case VideoInsertMode_1.VideoInsertMode.PREPEND:
- targEl.insertBefore(video, targEl.childNodes[0]);
- break;
- case VideoInsertMode_1.VideoInsertMode.REPLACE:
- targEl.parentNode.replaceChild(video, targEl);
- break;
- default:
- insMode = VideoInsertMode_1.VideoInsertMode.APPEND;
- targEl.appendChild(video);
- break;
- }
- var v = {
- targetElement: targEl,
- video: video,
- insertMode: insMode,
- id: video.id
- };
- this.pushNewStreamManagerVideo(v);
- this.ee.emitEvent('videoElementCreated', [new VideoElementEvent_1.VideoElementEvent(v.video, this, 'videoElementCreated')]);
- this.lazyLaunchVideoElementCreatedEvent = !!this.firstVideoElement;
- return video;
- };
- StreamManager.prototype.initializeVideoProperties = function (video) {
- if (!(this.stream.isLocal() && this.stream.displayMyRemote())) {
- video.srcObject = this.stream.getMediaStream();
- }
- video.autoplay = true;
- video.controls = false;
- if (!video.id) {
- video.id = (this.remote ? 'remote-' : 'local-') + 'video-' + this.stream.streamId;
- if (!this.id && !!this.targetElement) {
- this.id = video.id;
- }
- }
- if (!this.remote && !this.stream.displayMyRemote()) {
- video.muted = true;
- if (this.stream.outboundStreamOpts.publisherProperties.mirror) {
- this.mirrorVideo(video);
- }
- }
- };
- StreamManager.prototype.removeAllVideos = function () {
- var _this = this;
- for (var i = this.stream.session.streamManagers.length - 1; i >= 0; --i) {
- if (this.stream.session.streamManagers[i] === this) {
- this.stream.session.streamManagers.splice(i, 1);
- }
- }
- this.videos.slice().reverse().forEach(function (streamManagerVideo, index, videos) {
- streamManagerVideo.video.removeEventListener('canplay', _this.canPlayListener);
- if (!!streamManagerVideo.targetElement) {
- streamManagerVideo.video.parentNode.removeChild(streamManagerVideo.video);
- _this.ee.emitEvent('videoElementDestroyed', [new VideoElementEvent_1.VideoElementEvent(streamManagerVideo.video, _this, 'videoElementDestroyed')]);
- _this.videos.splice(videos.length - 1 - index, 1);
- }
- else {
- streamManagerVideo.video.srcObject = null;
- }
- });
- };
- StreamManager.prototype.disassociateVideo = function (video) {
- var disassociated = false;
- for (var i = 0; i < this.videos.length; i++) {
- if (this.videos[i].video === video) {
- this.videos.splice(i, 1);
- disassociated = true;
- console.info('Video element disassociated from ', this);
- break;
- }
- }
- return disassociated;
- };
- StreamManager.prototype.addPlayEventToFirstVideo = function () {
- if ((!!this.videos[0]) && (!!this.videos[0].video) && (this.videos[0].video.oncanplay === null)) {
- this.videos[0].video.addEventListener('canplay', this.canPlayListener);
- }
- };
- StreamManager.prototype.updateMediaStream = function (mediaStream) {
- this.videos.forEach(function (streamManagerVideo) {
- streamManagerVideo.video.srcObject = mediaStream;
- });
- };
- StreamManager.prototype.emitEvent = function (type, eventArray) {
- this.ee.emitEvent(type, eventArray);
- };
- StreamManager.prototype.pushNewStreamManagerVideo = function (streamManagerVideo) {
- this.videos.push(streamManagerVideo);
- this.addPlayEventToFirstVideo();
- if (this.stream.session.streamManagers.indexOf(this) === -1) {
- this.stream.session.streamManagers.push(this);
- }
- };
- StreamManager.prototype.mirrorVideo = function (video) {
- video.style.transform = 'rotateY(180deg)';
- video.style.webkitTransform = 'rotateY(180deg)';
- };
- return StreamManager;
-}());
-exports.StreamManager = StreamManager;
-
-},{"../OpenViduInternal/Enums/VideoInsertMode":27,"../OpenViduInternal/Events/StreamManagerEvent":35,"../OpenViduInternal/Events/VideoElementEvent":37,"wolfy87-eventemitter":15}],24:[function(require,module,exports){
-"use strict";
-var __extends = (this && this.__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 __());
- };
-})();
-Object.defineProperty(exports, "__esModule", { value: true });
-var StreamManager_1 = require("./StreamManager");
-var Subscriber = (function (_super) {
- __extends(Subscriber, _super);
- function Subscriber(stream, targEl, properties) {
- var _this = _super.call(this, stream, targEl) || this;
- _this.element = _this.targetElement;
- _this.stream = stream;
- _this.properties = properties;
- return _this;
- }
- Subscriber.prototype.subscribeToAudio = function (value) {
- this.stream.getMediaStream().getAudioTracks().forEach(function (track) {
- track.enabled = value;
- });
- console.info("'Subscriber' has " + (value ? 'subscribed to' : 'unsubscribed from') + ' its audio stream');
- return this;
- };
- Subscriber.prototype.subscribeToVideo = function (value) {
- this.stream.getMediaStream().getVideoTracks().forEach(function (track) {
- track.enabled = value;
- });
- console.info("'Subscriber' has " + (value ? 'subscribed to' : 'unsubscribed from') + ' its video stream');
- return this;
- };
- return Subscriber;
-}(StreamManager_1.StreamManager));
-exports.Subscriber = Subscriber;
-
-},{"./StreamManager":23}],25:[function(require,module,exports){
-"use strict";
-Object.defineProperty(exports, "__esModule", { value: true });
-var LocalRecorderState;
-(function (LocalRecorderState) {
- LocalRecorderState["READY"] = "READY";
- LocalRecorderState["RECORDING"] = "RECORDING";
- LocalRecorderState["PAUSED"] = "PAUSED";
- LocalRecorderState["FINISHED"] = "FINISHED";
-})(LocalRecorderState = exports.LocalRecorderState || (exports.LocalRecorderState = {}));
-
-},{}],26:[function(require,module,exports){
-"use strict";
-Object.defineProperty(exports, "__esModule", { value: true });
-var OpenViduErrorName;
-(function (OpenViduErrorName) {
- OpenViduErrorName["BROWSER_NOT_SUPPORTED"] = "BROWSER_NOT_SUPPORTED";
- OpenViduErrorName["DEVICE_ACCESS_DENIED"] = "DEVICE_ACCESS_DENIED";
- OpenViduErrorName["SCREEN_CAPTURE_DENIED"] = "SCREEN_CAPTURE_DENIED";
- OpenViduErrorName["SCREEN_SHARING_NOT_SUPPORTED"] = "SCREEN_SHARING_NOT_SUPPORTED";
- OpenViduErrorName["SCREEN_EXTENSION_NOT_INSTALLED"] = "SCREEN_EXTENSION_NOT_INSTALLED";
- OpenViduErrorName["SCREEN_EXTENSION_DISABLED"] = "SCREEN_EXTENSION_DISABLED";
- OpenViduErrorName["INPUT_VIDEO_DEVICE_NOT_FOUND"] = "INPUT_VIDEO_DEVICE_NOT_FOUND";
- OpenViduErrorName["INPUT_AUDIO_DEVICE_NOT_FOUND"] = "INPUT_AUDIO_DEVICE_NOT_FOUND";
- OpenViduErrorName["NO_INPUT_SOURCE_SET"] = "NO_INPUT_SOURCE_SET";
- OpenViduErrorName["PUBLISHER_PROPERTIES_ERROR"] = "PUBLISHER_PROPERTIES_ERROR";
- OpenViduErrorName["OPENVIDU_PERMISSION_DENIED"] = "OPENVIDU_PERMISSION_DENIED";
- OpenViduErrorName["OPENVIDU_NOT_CONNECTED"] = "OPENVIDU_NOT_CONNECTED";
- OpenViduErrorName["GENERIC_ERROR"] = "GENERIC_ERROR";
-})(OpenViduErrorName = exports.OpenViduErrorName || (exports.OpenViduErrorName = {}));
-var OpenViduError = (function () {
- function OpenViduError(name, message) {
- this.name = name;
- this.message = message;
- }
- return OpenViduError;
-}());
-exports.OpenViduError = OpenViduError;
-
-},{}],27:[function(require,module,exports){
-"use strict";
-Object.defineProperty(exports, "__esModule", { value: true });
-var VideoInsertMode;
-(function (VideoInsertMode) {
- VideoInsertMode["AFTER"] = "AFTER";
- VideoInsertMode["APPEND"] = "APPEND";
- VideoInsertMode["BEFORE"] = "BEFORE";
- VideoInsertMode["PREPEND"] = "PREPEND";
- VideoInsertMode["REPLACE"] = "REPLACE";
-})(VideoInsertMode = exports.VideoInsertMode || (exports.VideoInsertMode = {}));
-
-},{}],28:[function(require,module,exports){
-"use strict";
-var __extends = (this && this.__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 __());
- };
-})();
-Object.defineProperty(exports, "__esModule", { value: true });
-var Event_1 = require("./Event");
-var ConnectionEvent = (function (_super) {
- __extends(ConnectionEvent, _super);
- function ConnectionEvent(cancelable, target, type, connection, reason) {
- var _this = _super.call(this, cancelable, target, type) || this;
- _this.connection = connection;
- _this.reason = reason;
- return _this;
- }
- ConnectionEvent.prototype.callDefaultBehavior = function () { };
- return ConnectionEvent;
-}(Event_1.Event));
-exports.ConnectionEvent = ConnectionEvent;
-
-},{"./Event":29}],29:[function(require,module,exports){
-"use strict";
-Object.defineProperty(exports, "__esModule", { value: true });
-var Event = (function () {
- function Event(cancelable, target, type) {
- this.hasBeenPrevented = false;
- this.cancelable = cancelable;
- this.target = target;
- this.type = type;
- }
- Event.prototype.isDefaultPrevented = function () {
- return this.hasBeenPrevented;
- };
- Event.prototype.preventDefault = function () {
- this.callDefaultBehavior = function () { };
- this.hasBeenPrevented = true;
- };
- return Event;
-}());
-exports.Event = Event;
-
-},{}],30:[function(require,module,exports){
-"use strict";
-var __extends = (this && this.__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 __());
- };
-})();
-Object.defineProperty(exports, "__esModule", { value: true });
-var Event_1 = require("./Event");
-var PublisherSpeakingEvent = (function (_super) {
- __extends(PublisherSpeakingEvent, _super);
- function PublisherSpeakingEvent(target, type, connection, streamId) {
- var _this = _super.call(this, false, target, type) || this;
- _this.type = type;
- _this.connection = connection;
- _this.streamId = streamId;
- return _this;
- }
- PublisherSpeakingEvent.prototype.callDefaultBehavior = function () { };
- return PublisherSpeakingEvent;
-}(Event_1.Event));
-exports.PublisherSpeakingEvent = PublisherSpeakingEvent;
-
-},{"./Event":29}],31:[function(require,module,exports){
-"use strict";
-var __extends = (this && this.__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 __());
- };
-})();
-Object.defineProperty(exports, "__esModule", { value: true });
-var Event_1 = require("./Event");
-var RecordingEvent = (function (_super) {
- __extends(RecordingEvent, _super);
- function RecordingEvent(target, type, id, name) {
- var _this = _super.call(this, false, target, type) || this;
- _this.id = id;
- if (name !== id) {
- _this.name = name;
- }
- return _this;
- }
- RecordingEvent.prototype.callDefaultBehavior = function () { };
- return RecordingEvent;
-}(Event_1.Event));
-exports.RecordingEvent = RecordingEvent;
-
-},{"./Event":29}],32:[function(require,module,exports){
-"use strict";
-var __extends = (this && this.__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 __());
- };
-})();
-Object.defineProperty(exports, "__esModule", { value: true });
-var Event_1 = require("./Event");
-var SessionDisconnectedEvent = (function (_super) {
- __extends(SessionDisconnectedEvent, _super);
- function SessionDisconnectedEvent(target, reason) {
- var _this = _super.call(this, true, target, 'sessionDisconnected') || this;
- _this.reason = reason;
- return _this;
- }
- SessionDisconnectedEvent.prototype.callDefaultBehavior = function () {
- console.info("Calling default behavior upon '" + this.type + "' event dispatched by 'Session'");
- var session = this.target;
- for (var connectionId in session.remoteConnections) {
- if (!!session.remoteConnections[connectionId].stream) {
- session.remoteConnections[connectionId].stream.disposeWebRtcPeer();
- session.remoteConnections[connectionId].stream.disposeMediaStream();
- if (session.remoteConnections[connectionId].stream.streamManager) {
- session.remoteConnections[connectionId].stream.streamManager.removeAllVideos();
- }
- delete session.remoteStreamsCreated[session.remoteConnections[connectionId].stream.streamId];
- session.remoteConnections[connectionId].dispose();
- }
- delete session.remoteConnections[connectionId];
- }
- };
- return SessionDisconnectedEvent;
-}(Event_1.Event));
-exports.SessionDisconnectedEvent = SessionDisconnectedEvent;
-
-},{"./Event":29}],33:[function(require,module,exports){
-"use strict";
-var __extends = (this && this.__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 __());
- };
-})();
-Object.defineProperty(exports, "__esModule", { value: true });
-var Event_1 = require("./Event");
-var SignalEvent = (function (_super) {
- __extends(SignalEvent, _super);
- function SignalEvent(target, type, data, from) {
- var _this = _super.call(this, false, target, type) || this;
- _this.type = type;
- _this.data = data;
- _this.from = from;
- return _this;
- }
- SignalEvent.prototype.callDefaultBehavior = function () { };
- return SignalEvent;
-}(Event_1.Event));
-exports.SignalEvent = SignalEvent;
-
-},{"./Event":29}],34:[function(require,module,exports){
-"use strict";
-var __extends = (this && this.__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 __());
- };
-})();
-Object.defineProperty(exports, "__esModule", { value: true });
-var Event_1 = require("./Event");
-var Publisher_1 = require("../../OpenVidu/Publisher");
-var Session_1 = require("../../OpenVidu/Session");
-var StreamEvent = (function (_super) {
- __extends(StreamEvent, _super);
- function StreamEvent(cancelable, target, type, stream, reason) {
- var _this = _super.call(this, cancelable, target, type) || this;
- _this.stream = stream;
- _this.reason = reason;
- return _this;
- }
- StreamEvent.prototype.callDefaultBehavior = function () {
- if (this.type === 'streamDestroyed') {
- if (this.target instanceof Session_1.Session) {
- console.info("Calling default behavior upon '" + this.type + "' event dispatched by 'Session'");
- this.stream.disposeWebRtcPeer();
- }
- else if (this.target instanceof Publisher_1.Publisher) {
- console.info("Calling default behavior upon '" + this.type + "' event dispatched by 'Publisher'");
- clearInterval(this.target.screenShareResizeInterval);
- this.stream.isLocalStreamReadyToPublish = false;
- var openviduPublishers = this.target.openvidu.publishers;
- for (var i = 0; i < openviduPublishers.length; i++) {
- if (openviduPublishers[i] === this.target) {
- openviduPublishers.splice(i, 1);
- break;
- }
- }
- }
- this.stream.disposeMediaStream();
- if (this.stream.streamManager)
- this.stream.streamManager.removeAllVideos();
- delete this.stream.session.remoteStreamsCreated[this.stream.streamId];
- var remoteConnection = this.stream.session.remoteConnections[this.stream.connection.connectionId];
- if (!!remoteConnection && !!remoteConnection.options) {
- var streamOptionsServer = remoteConnection.options.streams;
- for (var i = streamOptionsServer.length - 1; i >= 0; --i) {
- if (streamOptionsServer[i].id === this.stream.streamId) {
- streamOptionsServer.splice(i, 1);
- }
- }
- }
- }
- };
- return StreamEvent;
-}(Event_1.Event));
-exports.StreamEvent = StreamEvent;
-
-},{"../../OpenVidu/Publisher":20,"../../OpenVidu/Session":21,"./Event":29}],35:[function(require,module,exports){
-"use strict";
-var __extends = (this && this.__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 __());
- };
-})();
-Object.defineProperty(exports, "__esModule", { value: true });
-var Event_1 = require("./Event");
-var StreamManagerEvent = (function (_super) {
- __extends(StreamManagerEvent, _super);
- function StreamManagerEvent(target) {
- return _super.call(this, false, target, 'streamPlaying') || this;
- }
- StreamManagerEvent.prototype.callDefaultBehavior = function () { };
- return StreamManagerEvent;
-}(Event_1.Event));
-exports.StreamManagerEvent = StreamManagerEvent;
-
-},{"./Event":29}],36:[function(require,module,exports){
-"use strict";
-var __extends = (this && this.__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 __());
- };
-})();
-Object.defineProperty(exports, "__esModule", { value: true });
-var Event_1 = require("./Event");
-var StreamPropertyChangedEvent = (function (_super) {
- __extends(StreamPropertyChangedEvent, _super);
- function StreamPropertyChangedEvent(target, stream, changedProperty, newValue, oldValue, reason) {
- var _this = _super.call(this, false, target, 'streamPropertyChanged') || this;
- _this.stream = stream;
- _this.changedProperty = changedProperty;
- _this.newValue = newValue;
- _this.oldValue = oldValue;
- _this.reason = reason;
- return _this;
- }
- StreamPropertyChangedEvent.prototype.callDefaultBehavior = function () { };
- return StreamPropertyChangedEvent;
-}(Event_1.Event));
-exports.StreamPropertyChangedEvent = StreamPropertyChangedEvent;
-
-},{"./Event":29}],37:[function(require,module,exports){
-"use strict";
-var __extends = (this && this.__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 __());
- };
-})();
-Object.defineProperty(exports, "__esModule", { value: true });
-var Event_1 = require("./Event");
-var VideoElementEvent = (function (_super) {
- __extends(VideoElementEvent, _super);
- function VideoElementEvent(element, target, type) {
- var _this = _super.call(this, false, target, type) || this;
- _this.element = element;
- return _this;
- }
- VideoElementEvent.prototype.callDefaultBehavior = function () { };
- return VideoElementEvent;
-}(Event_1.Event));
-exports.VideoElementEvent = VideoElementEvent;
-
-},{"./Event":29}],38:[function(require,module,exports){
-function Mapper() {
- var sources = {};
- this.forEach = function (callback) {
- for (var key in sources) {
- var source = sources[key];
- for (var key2 in source)
- callback(source[key2]);
- }
- ;
- };
- this.get = function (id, source) {
- var ids = sources[source];
- if (ids == undefined)
- return undefined;
- return ids[id];
- };
- this.remove = function (id, source) {
- var ids = sources[source];
- if (ids == undefined)
- return;
- delete ids[id];
- for (var i in ids) {
- return false;
- }
- delete sources[source];
- };
- this.set = function (value, id, source) {
- if (value == undefined)
- return this.remove(id, source);
- var ids = sources[source];
- if (ids == undefined)
- sources[source] = ids = {};
- ids[id] = value;
- };
-}
-;
-Mapper.prototype.pop = function (id, source) {
- var value = this.get(id, source);
- if (value == undefined)
- return undefined;
- this.remove(id, source);
- return value;
-};
-module.exports = Mapper;
-
-},{}],39:[function(require,module,exports){
-var JsonRpcClient = require('./jsonrpcclient');
-exports.JsonRpcClient = JsonRpcClient;
-
-},{"./jsonrpcclient":40}],40:[function(require,module,exports){
-var RpcBuilder = require('../');
-var WebSocketWithReconnection = require('./transports/webSocketWithReconnection');
-Date.now = Date.now || function () {
- return +new Date;
-};
-var PING_INTERVAL = 5000;
-var RECONNECTING = 'RECONNECTING';
-var CONNECTED = 'CONNECTED';
-var DISCONNECTED = 'DISCONNECTED';
-var Logger = console;
-function JsonRpcClient(configuration) {
- var self = this;
- var wsConfig = configuration.ws;
- var notReconnectIfNumLessThan = -1;
- var pingNextNum = 0;
- var enabledPings = true;
- var pingPongStarted = false;
- var pingInterval;
- var status = DISCONNECTED;
- var onreconnecting = wsConfig.onreconnecting;
- var onreconnected = wsConfig.onreconnected;
- var onconnected = wsConfig.onconnected;
- var onerror = wsConfig.onerror;
- configuration.rpc.pull = function (params, request) {
- request.reply(null, "push");
- };
- wsConfig.onreconnecting = function () {
- Logger.debug("--------- ONRECONNECTING -----------");
- if (status === RECONNECTING) {
- Logger.error("Websocket already in RECONNECTING state when receiving a new ONRECONNECTING message. Ignoring it");
- return;
- }
- status = RECONNECTING;
- if (onreconnecting) {
- onreconnecting();
- }
- };
- wsConfig.onreconnected = function () {
- Logger.debug("--------- ONRECONNECTED -----------");
- if (status === CONNECTED) {
- Logger.error("Websocket already in CONNECTED state when receiving a new ONRECONNECTED message. Ignoring it");
- return;
- }
- status = CONNECTED;
- enabledPings = true;
- updateNotReconnectIfLessThan();
- usePing();
- if (onreconnected) {
- onreconnected();
- }
- };
- wsConfig.onconnected = function () {
- Logger.debug("--------- ONCONNECTED -----------");
- if (status === CONNECTED) {
- Logger.error("Websocket already in CONNECTED state when receiving a new ONCONNECTED message. Ignoring it");
- return;
- }
- status = CONNECTED;
- enabledPings = true;
- usePing();
- if (onconnected) {
- onconnected();
- }
- };
- wsConfig.onerror = function (error) {
- Logger.debug("--------- ONERROR -----------");
- status = DISCONNECTED;
- if (onerror) {
- onerror(error);
- }
- };
- var ws = new WebSocketWithReconnection(wsConfig);
- Logger.debug('Connecting websocket to URI: ' + wsConfig.uri);
- var rpcBuilderOptions = {
- request_timeout: configuration.rpc.requestTimeout,
- ping_request_timeout: configuration.rpc.heartbeatRequestTimeout
- };
- var rpc = new RpcBuilder(RpcBuilder.packers.JsonRPC, rpcBuilderOptions, ws, function (request) {
- Logger.debug('Received request: ' + JSON.stringify(request));
- try {
- var func = configuration.rpc[request.method];
- if (func === undefined) {
- Logger.error("Method " + request.method + " not registered in client");
- }
- else {
- func(request.params, request);
- }
- }
- catch (err) {
- Logger.error('Exception processing request: ' + JSON.stringify(request));
- Logger.error(err);
- }
- });
- this.send = function (method, params, callback) {
- if (method !== 'ping') {
- Logger.debug('Request: method:' + method + " params:" + JSON.stringify(params));
- }
- var requestTime = Date.now();
- rpc.encode(method, params, function (error, result) {
- if (error) {
- try {
- Logger.error("ERROR:" + error.message + " in Request: method:" +
- method + " params:" + JSON.stringify(params) + " request:" +
- error.request);
- if (error.data) {
- Logger.error("ERROR DATA:" + JSON.stringify(error.data));
- }
- }
- catch (e) { }
- error.requestTime = requestTime;
- }
- if (callback) {
- if (result != undefined && result.value !== 'pong') {
- Logger.debug('Response: ' + JSON.stringify(result));
- }
- callback(error, result);
- }
- });
- };
- function updateNotReconnectIfLessThan() {
- Logger.debug("notReconnectIfNumLessThan = " + pingNextNum + ' (old=' +
- notReconnectIfNumLessThan + ')');
- notReconnectIfNumLessThan = pingNextNum;
- }
- function sendPing() {
- if (enabledPings) {
- var params = null;
- if (pingNextNum == 0 || pingNextNum == notReconnectIfNumLessThan) {
- params = {
- interval: configuration.heartbeat || PING_INTERVAL
- };
- }
- pingNextNum++;
- self.send('ping', params, (function (pingNum) {
- return function (error, result) {
- if (error) {
- Logger.debug("Error in ping request #" + pingNum + " (" +
- error.message + ")");
- if (pingNum > notReconnectIfNumLessThan) {
- enabledPings = false;
- updateNotReconnectIfLessThan();
- Logger.debug("Server did not respond to ping message #" +
- pingNum + ". Reconnecting... ");
- ws.reconnectWs();
- }
- }
- };
- })(pingNextNum));
- }
- else {
- Logger.debug("Trying to send ping, but ping is not enabled");
- }
- }
- function usePing() {
- if (!pingPongStarted) {
- Logger.debug("Starting ping (if configured)");
- pingPongStarted = true;
- if (configuration.heartbeat != undefined) {
- pingInterval = setInterval(sendPing, configuration.heartbeat);
- sendPing();
- }
- }
- }
- this.close = function () {
- Logger.debug("Closing jsonRpcClient explicitly by client");
- if (pingInterval != undefined) {
- Logger.debug("Clearing ping interval");
- clearInterval(pingInterval);
- }
- pingPongStarted = false;
- enabledPings = false;
- if (configuration.sendCloseMessage) {
- Logger.debug("Sending close message");
- this.send('closeSession', null, function (error, result) {
- if (error) {
- Logger.error("Error sending close message: " + JSON.stringify(error));
- }
- ws.close();
- });
- }
- else {
- ws.close();
- }
- };
- this.forceClose = function (millis) {
- ws.forceClose(millis);
- };
- this.reconnect = function () {
- ws.reconnectWs();
- };
-}
-module.exports = JsonRpcClient;
-
-},{"../":43,"./transports/webSocketWithReconnection":42}],41:[function(require,module,exports){
-var WebSocketWithReconnection = require('./webSocketWithReconnection');
-exports.WebSocketWithReconnection = WebSocketWithReconnection;
-
-},{"./webSocketWithReconnection":42}],42:[function(require,module,exports){
-(function (global){
-"use strict";
-var BrowserWebSocket = global.WebSocket || global.MozWebSocket;
-var Logger = console;
-var MAX_RETRIES = 2000;
-var RETRY_TIME_MS = 3000;
-var CONNECTING = 0;
-var OPEN = 1;
-var CLOSING = 2;
-var CLOSED = 3;
-function WebSocketWithReconnection(config) {
- var closing = false;
- var registerMessageHandler;
- var wsUri = config.uri;
- var useSockJS = config.useSockJS;
- var reconnecting = false;
- var forcingDisconnection = false;
- var ws;
- if (useSockJS) {
- ws = new SockJS(wsUri);
- }
- else {
- ws = new WebSocket(wsUri);
- }
- ws.onopen = function () {
- logConnected(ws, wsUri);
- if (config.onconnected) {
- config.onconnected();
- }
- };
- ws.onerror = function (error) {
- Logger.error("Could not connect to " + wsUri + " (invoking onerror if defined)", error);
- if (config.onerror) {
- config.onerror(error);
- }
- };
- function logConnected(ws, wsUri) {
- try {
- Logger.debug("WebSocket connected to " + wsUri);
- }
- catch (e) {
- Logger.error(e);
- }
- }
- var reconnectionOnClose = function () {
- if (ws.readyState === CLOSED) {
- if (closing) {
- Logger.debug("Connection closed by user");
- }
- else {
- Logger.debug("Connection closed unexpectecly. Reconnecting...");
- reconnectToSameUri(MAX_RETRIES, 1);
- }
- }
- else {
- Logger.debug("Close callback from previous websocket. Ignoring it");
- }
- };
- ws.onclose = reconnectionOnClose;
- function reconnectToSameUri(maxRetries, numRetries) {
- Logger.debug("reconnectToSameUri (attempt #" + numRetries + ", max=" + maxRetries + ")");
- if (numRetries === 1) {
- if (reconnecting) {
- Logger.warn("Trying to reconnectToNewUri when reconnecting... Ignoring this reconnection.");
- return;
- }
- else {
- reconnecting = true;
- }
- if (config.onreconnecting) {
- config.onreconnecting();
- }
- }
- if (forcingDisconnection) {
- reconnectToNewUri(maxRetries, numRetries, wsUri);
- }
- else {
- if (config.newWsUriOnReconnection) {
- config.newWsUriOnReconnection(function (error, newWsUri) {
- if (error) {
- Logger.debug(error);
- setTimeout(function () {
- reconnectToSameUri(maxRetries, numRetries + 1);
- }, RETRY_TIME_MS);
- }
- else {
- reconnectToNewUri(maxRetries, numRetries, newWsUri);
- }
- });
- }
- else {
- reconnectToNewUri(maxRetries, numRetries, wsUri);
- }
- }
- }
- function reconnectToNewUri(maxRetries, numRetries, reconnectWsUri) {
- Logger.debug("Reconnection attempt #" + numRetries);
- ws.close();
- wsUri = reconnectWsUri || wsUri;
- var newWs;
- if (useSockJS) {
- newWs = new SockJS(wsUri);
- }
- else {
- newWs = new WebSocket(wsUri);
- }
- newWs.onopen = function () {
- Logger.debug("Reconnected after " + numRetries + " attempts...");
- logConnected(newWs, wsUri);
- reconnecting = false;
- registerMessageHandler();
- if (config.onreconnected()) {
- config.onreconnected();
- }
- newWs.onclose = reconnectionOnClose;
- };
- var onErrorOrClose = function (error) {
- Logger.warn("Reconnection error: ", error);
- if (numRetries === maxRetries) {
- if (config.ondisconnect) {
- config.ondisconnect();
- }
- }
- else {
- setTimeout(function () {
- reconnectToSameUri(maxRetries, numRetries + 1);
- }, RETRY_TIME_MS);
- }
- };
- newWs.onerror = onErrorOrClose;
- ws = newWs;
- }
- this.close = function () {
- closing = true;
- ws.close();
- };
- this.forceClose = function (millis) {
- Logger.debug("Testing: Force WebSocket close");
- if (millis) {
- Logger.debug("Testing: Change wsUri for " + millis + " millis to simulate net failure");
- var goodWsUri = wsUri;
- wsUri = "wss://21.234.12.34.4:443/";
- forcingDisconnection = true;
- setTimeout(function () {
- Logger.debug("Testing: Recover good wsUri " + goodWsUri);
- wsUri = goodWsUri;
- forcingDisconnection = false;
- }, millis);
- }
- ws.close();
- };
- this.reconnectWs = function () {
- Logger.debug("reconnectWs");
- reconnectToSameUri(MAX_RETRIES, 1, wsUri);
- };
- this.send = function (message) {
- ws.send(message);
- };
- this.addEventListener = function (type, callback) {
- registerMessageHandler = function () {
- ws.addEventListener(type, callback);
- };
- registerMessageHandler();
- };
-}
-module.exports = WebSocketWithReconnection;
-
-}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
-
-},{}],43:[function(require,module,exports){
-var defineProperty_IE8 = false;
-if (Object.defineProperty) {
- try {
- Object.defineProperty({}, "x", {});
- }
- catch (e) {
- defineProperty_IE8 = true;
- }
-}
-if (!Function.prototype.bind) {
- Function.prototype.bind = function (oThis) {
- if (typeof this !== 'function') {
- throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable');
- }
- var aArgs = Array.prototype.slice.call(arguments, 1), fToBind = this, fNOP = function () { }, fBound = function () {
- return fToBind.apply(this instanceof fNOP && oThis
- ? this
- : oThis, aArgs.concat(Array.prototype.slice.call(arguments)));
- };
- fNOP.prototype = this.prototype;
- fBound.prototype = new fNOP();
- return fBound;
- };
-}
-var EventEmitter = require('events').EventEmitter;
-var inherits = require('inherits');
-var packers = require('./packers');
-var Mapper = require('./Mapper');
-var BASE_TIMEOUT = 5000;
-function unifyResponseMethods(responseMethods) {
- if (!responseMethods)
- return {};
- for (var key in responseMethods) {
- var value = responseMethods[key];
- if (typeof value == 'string')
- responseMethods[key] =
- {
- response: value
- };
- }
- ;
- return responseMethods;
-}
-;
-function unifyTransport(transport) {
- if (!transport)
- return;
- if (transport instanceof Function)
- return { send: transport };
- if (transport.send instanceof Function)
- return transport;
- if (transport.postMessage instanceof Function) {
- transport.send = transport.postMessage;
- return transport;
- }
- if (transport.write instanceof Function) {
- transport.send = transport.write;
- return transport;
- }
- if (transport.onmessage !== undefined)
- return;
- if (transport.pause instanceof Function)
- return;
- throw new SyntaxError("Transport is not a function nor a valid object");
-}
-;
-function RpcNotification(method, params) {
- if (defineProperty_IE8) {
- this.method = method;
- this.params = params;
- }
- else {
- Object.defineProperty(this, 'method', { value: method, enumerable: true });
- Object.defineProperty(this, 'params', { value: params, enumerable: true });
- }
-}
-;
-function RpcBuilder(packer, options, transport, onRequest) {
- var self = this;
- if (!packer)
- throw new SyntaxError('Packer is not defined');
- if (!packer.pack || !packer.unpack)
- throw new SyntaxError('Packer is invalid');
- var responseMethods = unifyResponseMethods(packer.responseMethods);
- if (options instanceof Function) {
- if (transport != undefined)
- throw new SyntaxError("There can't be parameters after onRequest");
- onRequest = options;
- transport = undefined;
- options = undefined;
- }
- ;
- if (options && options.send instanceof Function) {
- if (transport && !(transport instanceof Function))
- throw new SyntaxError("Only a function can be after transport");
- onRequest = transport;
- transport = options;
- options = undefined;
- }
- ;
- if (transport instanceof Function) {
- if (onRequest != undefined)
- throw new SyntaxError("There can't be parameters after onRequest");
- onRequest = transport;
- transport = undefined;
- }
- ;
- if (transport && transport.send instanceof Function)
- if (onRequest && !(onRequest instanceof Function))
- throw new SyntaxError("Only a function can be after transport");
- options = options || {};
- EventEmitter.call(this);
- if (onRequest)
- this.on('request', onRequest);
- if (defineProperty_IE8)
- this.peerID = options.peerID;
- else
- Object.defineProperty(this, 'peerID', { value: options.peerID });
- var max_retries = options.max_retries || 0;
- function transportMessage(event) {
- self.decode(event.data || event);
- }
- ;
- this.getTransport = function () {
- return transport;
- };
- this.setTransport = function (value) {
- if (transport) {
- if (transport.removeEventListener)
- transport.removeEventListener('message', transportMessage);
- else if (transport.removeListener)
- transport.removeListener('data', transportMessage);
- }
- ;
- if (value) {
- if (value.addEventListener)
- value.addEventListener('message', transportMessage);
- else if (value.addListener)
- value.addListener('data', transportMessage);
- }
- ;
- transport = unifyTransport(value);
- };
- if (!defineProperty_IE8)
- Object.defineProperty(this, 'transport', {
- get: this.getTransport.bind(this),
- set: this.setTransport.bind(this)
- });
- this.setTransport(transport);
- var request_timeout = options.request_timeout || BASE_TIMEOUT;
- var ping_request_timeout = options.ping_request_timeout || request_timeout;
- var response_timeout = options.response_timeout || BASE_TIMEOUT;
- var duplicates_timeout = options.duplicates_timeout || BASE_TIMEOUT;
- var requestID = 0;
- var requests = new Mapper();
- var responses = new Mapper();
- var processedResponses = new Mapper();
- var message2Key = {};
- function storeResponse(message, id, dest) {
- var response = {
- message: message,
- timeout: setTimeout(function () {
- responses.remove(id, dest);
- }, response_timeout)
- };
- responses.set(response, id, dest);
- }
- ;
- function storeProcessedResponse(ack, from) {
- var timeout = setTimeout(function () {
- processedResponses.remove(ack, from);
- }, duplicates_timeout);
- processedResponses.set(timeout, ack, from);
- }
- ;
- function RpcRequest(method, params, id, from, transport) {
- RpcNotification.call(this, method, params);
- this.getTransport = function () {
- return transport;
- };
- this.setTransport = function (value) {
- transport = unifyTransport(value);
- };
- if (!defineProperty_IE8)
- Object.defineProperty(this, 'transport', {
- get: this.getTransport.bind(this),
- set: this.setTransport.bind(this)
- });
- var response = responses.get(id, from);
- if (!(transport || self.getTransport())) {
- if (defineProperty_IE8)
- this.duplicated = Boolean(response);
- else
- Object.defineProperty(this, 'duplicated', {
- value: Boolean(response)
- });
- }
- var responseMethod = responseMethods[method];
- this.pack = packer.pack.bind(packer, this, id);
- this.reply = function (error, result, transport) {
- if (error instanceof Function || error && error.send instanceof Function) {
- if (result != undefined)
- throw new SyntaxError("There can't be parameters after callback");
- transport = error;
- result = null;
- error = undefined;
- }
- else if (result instanceof Function
- || result && result.send instanceof Function) {
- if (transport != undefined)
- throw new SyntaxError("There can't be parameters after callback");
- transport = result;
- result = null;
- }
- ;
- transport = unifyTransport(transport);
- if (response)
- clearTimeout(response.timeout);
- if (from != undefined) {
- if (error)
- error.dest = from;
- if (result)
- result.dest = from;
- }
- ;
- var message;
- if (error || result != undefined) {
- if (self.peerID != undefined) {
- if (error)
- error.from = self.peerID;
- else
- result.from = self.peerID;
- }
- if (responseMethod) {
- if (responseMethod.error == undefined && error)
- message =
- {
- error: error
- };
- else {
- var method = error
- ? responseMethod.error
- : responseMethod.response;
- message =
- {
- method: method,
- params: error || result
- };
- }
- }
- else
- message =
- {
- error: error,
- result: result
- };
- message = packer.pack(message, id);
- }
- else if (response)
- message = response.message;
- else
- message = packer.pack({ result: null }, id);
- storeResponse(message, id, from);
- transport = transport || this.getTransport() || self.getTransport();
- if (transport)
- return transport.send(message);
- return message;
- };
- }
- ;
- inherits(RpcRequest, RpcNotification);
- function cancel(message) {
- var key = message2Key[message];
- if (!key)
- return;
- delete message2Key[message];
- var request = requests.pop(key.id, key.dest);
- if (!request)
- return;
- clearTimeout(request.timeout);
- storeProcessedResponse(key.id, key.dest);
- }
- ;
- this.cancel = function (message) {
- if (message)
- return cancel(message);
- for (var message in message2Key)
- cancel(message);
- };
- this.close = function () {
- var transport = this.getTransport();
- if (transport && transport.close)
- transport.close();
- this.cancel();
- processedResponses.forEach(clearTimeout);
- responses.forEach(function (response) {
- clearTimeout(response.timeout);
- });
- };
- this.encode = function (method, params, dest, transport, callback) {
- if (params instanceof Function) {
- if (dest != undefined)
- throw new SyntaxError("There can't be parameters after callback");
- callback = params;
- transport = undefined;
- dest = undefined;
- params = undefined;
- }
- else if (dest instanceof Function) {
- if (transport != undefined)
- throw new SyntaxError("There can't be parameters after callback");
- callback = dest;
- transport = undefined;
- dest = undefined;
- }
- else if (transport instanceof Function) {
- if (callback != undefined)
- throw new SyntaxError("There can't be parameters after callback");
- callback = transport;
- transport = undefined;
- }
- ;
- if (self.peerID != undefined) {
- params = params || {};
- params.from = self.peerID;
- }
- ;
- if (dest != undefined) {
- params = params || {};
- params.dest = dest;
- }
- ;
- var message = {
- method: method,
- params: params
- };
- if (callback) {
- var id = requestID++;
- var retried = 0;
- message = packer.pack(message, id);
- function dispatchCallback(error, result) {
- self.cancel(message);
- callback(error, result);
- }
- ;
- var request = {
- message: message,
- callback: dispatchCallback,
- responseMethods: responseMethods[method] || {}
- };
- var encode_transport = unifyTransport(transport);
- function sendRequest(transport) {
- var rt = (method === 'ping' ? ping_request_timeout : request_timeout);
- request.timeout = setTimeout(timeout, rt * Math.pow(2, retried++));
- message2Key[message] = { id: id, dest: dest };
- requests.set(request, id, dest);
- transport = transport || encode_transport || self.getTransport();
- if (transport)
- return transport.send(message);
- return message;
- }
- ;
- function retry(transport) {
- transport = unifyTransport(transport);
- console.warn(retried + ' retry for request message:', message);
- var timeout = processedResponses.pop(id, dest);
- clearTimeout(timeout);
- return sendRequest(transport);
- }
- ;
- function timeout() {
- if (retried < max_retries)
- return retry(transport);
- var error = new Error('Request has timed out');
- error.request = message;
- error.retry = retry;
- dispatchCallback(error);
- }
- ;
- return sendRequest(transport);
- }
- ;
- message = packer.pack(message);
- transport = transport || this.getTransport();
- if (transport)
- return transport.send(message);
- return message;
- };
- this.decode = function (message, transport) {
- if (!message)
- throw new TypeError("Message is not defined");
- try {
- message = packer.unpack(message);
- }
- catch (e) {
- return console.debug(e, message);
- }
- ;
- var id = message.id;
- var ack = message.ack;
- var method = message.method;
- var params = message.params || {};
- var from = params.from;
- var dest = params.dest;
- if (self.peerID != undefined && from == self.peerID)
- return;
- if (id == undefined && ack == undefined) {
- var notification = new RpcNotification(method, params);
- if (self.emit('request', notification))
- return;
- return notification;
- }
- ;
- function processRequest() {
- transport = unifyTransport(transport) || self.getTransport();
- if (transport) {
- var response = responses.get(id, from);
- if (response)
- return transport.send(response.message);
- }
- ;
- var idAck = (id != undefined) ? id : ack;
- var request = new RpcRequest(method, params, idAck, from, transport);
- if (self.emit('request', request))
- return;
- return request;
- }
- ;
- function processResponse(request, error, result) {
- request.callback(error, result);
- }
- ;
- function duplicatedResponse(timeout) {
- console.warn("Response already processed", message);
- clearTimeout(timeout);
- storeProcessedResponse(ack, from);
- }
- ;
- if (method) {
- if (dest == undefined || dest == self.peerID) {
- var request = requests.get(ack, from);
- if (request) {
- var responseMethods = request.responseMethods;
- if (method == responseMethods.error)
- return processResponse(request, params);
- if (method == responseMethods.response)
- return processResponse(request, null, params);
- return processRequest();
- }
- var processed = processedResponses.get(ack, from);
- if (processed)
- return duplicatedResponse(processed);
- }
- return processRequest();
- }
- ;
- var error = message.error;
- var result = message.result;
- if (error && error.dest && error.dest != self.peerID)
- return;
- if (result && result.dest && result.dest != self.peerID)
- return;
- var request = requests.get(ack, from);
- if (!request) {
- var processed = processedResponses.get(ack, from);
- if (processed)
- return duplicatedResponse(processed);
- return console.warn("No callback was defined for this message", message);
- }
- ;
- processResponse(request, error, result);
- };
-}
-;
-inherits(RpcBuilder, EventEmitter);
-RpcBuilder.RpcNotification = RpcNotification;
-module.exports = RpcBuilder;
-var clients = require('./clients');
-var transports = require('./clients/transports');
-RpcBuilder.clients = clients;
-RpcBuilder.clients.transports = transports;
-RpcBuilder.packers = packers;
-
-},{"./Mapper":38,"./clients":39,"./clients/transports":41,"./packers":46,"events":1,"inherits":6}],44:[function(require,module,exports){
-function pack(message, id) {
- var result = {
- jsonrpc: "2.0"
- };
- if (message.method) {
- result.method = message.method;
- if (message.params)
- result.params = message.params;
- if (id != undefined)
- result.id = id;
- }
- else if (id != undefined) {
- if (message.error) {
- if (message.result !== undefined)
- throw new TypeError("Both result and error are defined");
- result.error = message.error;
- }
- else if (message.result !== undefined)
- result.result = message.result;
- else
- throw new TypeError("No result or error is defined");
- result.id = id;
- }
- ;
- return JSON.stringify(result);
-}
-;
-function unpack(message) {
- var result = message;
- if (typeof message === 'string' || message instanceof String) {
- result = JSON.parse(message);
- }
- var version = result.jsonrpc;
- if (version !== '2.0')
- throw new TypeError("Invalid JsonRPC version '" + version + "': " + message);
- if (result.method == undefined) {
- if (result.id == undefined)
- throw new TypeError("Invalid message: " + message);
- var result_defined = result.result !== undefined;
- var error_defined = result.error !== undefined;
- if (result_defined && error_defined)
- throw new TypeError("Both result and error are defined: " + message);
- if (!result_defined && !error_defined)
- throw new TypeError("No result or error is defined: " + message);
- result.ack = result.id;
- delete result.id;
- }
- return result;
-}
-;
-exports.pack = pack;
-exports.unpack = unpack;
-
-},{}],45:[function(require,module,exports){
-function pack(message) {
- throw new TypeError("Not yet implemented");
-}
-;
-function unpack(message) {
- throw new TypeError("Not yet implemented");
-}
-;
-exports.pack = pack;
-exports.unpack = unpack;
-
-},{}],46:[function(require,module,exports){
-var JsonRPC = require('./JsonRPC');
-var XmlRPC = require('./XmlRPC');
-exports.JsonRPC = JsonRPC;
-exports.XmlRPC = XmlRPC;
-
-},{"./JsonRPC":44,"./XmlRPC":45}],47:[function(require,module,exports){
-window.getScreenId = function (callback, custom_parameter) {
- if (navigator.userAgent.indexOf('Edge') !== -1 && (!!navigator.msSaveOrOpenBlob || !!navigator.msSaveBlob)) {
- callback({
- video: true
- });
- return;
- }
- if (!!navigator.mozGetUserMedia) {
- callback(null, 'firefox', {
- video: {
- mozMediaSource: 'window',
- mediaSource: 'window'
- }
- });
- return;
- }
- window.addEventListener('message', onIFrameCallback);
- function onIFrameCallback(event) {
- if (!event.data)
- return;
- if (event.data.chromeMediaSourceId) {
- if (event.data.chromeMediaSourceId === 'PermissionDeniedError') {
- callback('permission-denied');
- }
- else {
- callback(null, event.data.chromeMediaSourceId, getScreenConstraints(null, event.data.chromeMediaSourceId, event.data.canRequestAudioTrack));
- }
- window.removeEventListener('message', onIFrameCallback);
- }
- if (event.data.chromeExtensionStatus) {
- callback(event.data.chromeExtensionStatus, null, getScreenConstraints(event.data.chromeExtensionStatus));
- window.removeEventListener('message', onIFrameCallback);
- }
- }
- if (!custom_parameter) {
- setTimeout(postGetSourceIdMessage, 100);
- }
- else {
- setTimeout(function () {
- postGetSourceIdMessage(custom_parameter);
- }, 100);
- }
-};
-function getScreenConstraints(error, sourceId, canRequestAudioTrack) {
- var screen_constraints = {
- audio: false,
- video: {
- mandatory: {
- chromeMediaSource: error ? 'screen' : 'desktop',
- maxWidth: window.screen.width > 1920 ? window.screen.width : 1920,
- maxHeight: window.screen.height > 1080 ? window.screen.height : 1080
- },
- optional: []
- }
- };
- if (!!canRequestAudioTrack) {
- screen_constraints.audio = {
- mandatory: {
- chromeMediaSource: error ? 'screen' : 'desktop',
- },
- optional: []
- };
- }
- if (sourceId) {
- screen_constraints.video.mandatory.chromeMediaSourceId = sourceId;
- if (screen_constraints.audio && screen_constraints.audio.mandatory) {
- screen_constraints.audio.mandatory.chromeMediaSourceId = sourceId;
- }
- }
- return screen_constraints;
-}
-function postGetSourceIdMessage(custom_parameter) {
- if (!iframe) {
- loadIFrame(function () {
- postGetSourceIdMessage(custom_parameter);
- });
- return;
- }
- if (!iframe.isLoaded) {
- setTimeout(function () {
- postGetSourceIdMessage(custom_parameter);
- }, 100);
- return;
- }
- if (!custom_parameter) {
- iframe.contentWindow.postMessage({
- captureSourceId: true
- }, '*');
- }
- else if (!!custom_parameter.forEach) {
- iframe.contentWindow.postMessage({
- captureCustomSourceId: custom_parameter
- }, '*');
- }
- else {
- iframe.contentWindow.postMessage({
- captureSourceIdWithAudio: true
- }, '*');
- }
-}
-var iframe;
-window.getScreenConstraints = function (callback) {
- loadIFrame(function () {
- getScreenId(function (error, sourceId, screen_constraints) {
- if (!screen_constraints) {
- screen_constraints = {
- video: true
- };
- }
- callback(error, screen_constraints.video);
- });
- });
-};
-function loadIFrame(loadCallback) {
- if (iframe) {
- loadCallback();
- return;
- }
- iframe = document.createElement('iframe');
- iframe.onload = function () {
- iframe.isLoaded = true;
- loadCallback();
- };
- iframe.src = 'https://openvidu.github.io/openvidu-screen-sharing-chrome-extension/';
- iframe.style.display = 'none';
- (document.body || document.documentElement).appendChild(iframe);
-}
-window.getChromeExtensionStatus = function (callback) {
- if (!!navigator.mozGetUserMedia) {
- callback('installed-enabled');
- return;
- }
- window.addEventListener('message', onIFrameCallback);
- function onIFrameCallback(event) {
- if (!event.data)
- return;
- if (event.data.chromeExtensionStatus) {
- callback(event.data.chromeExtensionStatus);
- window.removeEventListener('message', onIFrameCallback);
- }
- }
- setTimeout(postGetChromeExtensionStatusMessage, 100);
-};
-function postGetChromeExtensionStatusMessage() {
- if (!iframe) {
- loadIFrame(postGetChromeExtensionStatusMessage);
- return;
- }
- if (!iframe.isLoaded) {
- setTimeout(postGetChromeExtensionStatusMessage, 100);
- return;
- }
- iframe.contentWindow.postMessage({
- getChromeExtensionStatus: true
- }, '*');
-}
-exports.getScreenId = getScreenId;
-
-},{}],48:[function(require,module,exports){
-var chromeMediaSource = 'screen';
-var sourceId;
-var screenCallback;
-var isFirefox = typeof window.InstallTrigger !== 'undefined';
-var isOpera = !!window.opera || navigator.userAgent.indexOf(' OPR/') >= 0;
-var isChrome = !!window.chrome && !isOpera;
-window.addEventListener('message', function (event) {
- if (event.origin != window.location.origin) {
- return;
- }
- onMessageCallback(event.data);
-});
-function onMessageCallback(data) {
- if (data == 'PermissionDeniedError') {
- if (screenCallback)
- return screenCallback('PermissionDeniedError');
- else
- throw new Error('PermissionDeniedError');
- }
- if (data == 'rtcmulticonnection-extension-loaded') {
- chromeMediaSource = 'desktop';
- }
- if (data.sourceId && screenCallback) {
- screenCallback(sourceId = data.sourceId, data.canRequestAudioTrack === true);
- }
-}
-function isChromeExtensionAvailable(callback) {
- if (!callback)
- return;
- if (chromeMediaSource == 'desktop')
- return callback(true);
- window.postMessage('are-you-there', '*');
- setTimeout(function () {
- if (chromeMediaSource == 'screen') {
- callback(false);
- }
- else
- callback(true);
- }, 2000);
-}
-function getSourceId(callback) {
- if (!callback)
- throw '"callback" parameter is mandatory.';
- if (sourceId)
- return callback(sourceId);
- screenCallback = callback;
- window.postMessage('get-sourceId', '*');
-}
-function getCustomSourceId(arr, callback) {
- if (!arr || !arr.forEach)
- throw '"arr" parameter is mandatory and it must be an array.';
- if (!callback)
- throw '"callback" parameter is mandatory.';
- if (sourceId)
- return callback(sourceId);
- screenCallback = callback;
- window.postMessage({
- 'get-custom-sourceId': arr
- }, '*');
-}
-function getSourceIdWithAudio(callback) {
- if (!callback)
- throw '"callback" parameter is mandatory.';
- if (sourceId)
- return callback(sourceId);
- screenCallback = callback;
- window.postMessage('audio-plus-tab', '*');
-}
-function getChromeExtensionStatus(extensionid, callback) {
- if (isFirefox)
- return callback('not-chrome');
- if (arguments.length != 2) {
- callback = extensionid;
- extensionid = 'lfcgfepafnobdloecchnfaclibenjold';
- }
- var image = document.createElement('img');
- image.src = 'chrome-extension://' + extensionid + '/icon.png';
- image.onload = function () {
- chromeMediaSource = 'screen';
- window.postMessage('are-you-there', '*');
- setTimeout(function () {
- if (chromeMediaSource == 'screen') {
- callback('installed-disabled');
- }
- else
- callback('installed-enabled');
- }, 2000);
- };
- image.onerror = function () {
- callback('not-installed');
- };
-}
-function getScreenConstraintsWithAudio(callback) {
- getScreenConstraints(callback, true);
-}
-function getScreenConstraints(callback, captureSourceIdWithAudio) {
- sourceId = '';
- var firefoxScreenConstraints = {
- mozMediaSource: 'window',
- mediaSource: 'window'
- };
- if (isFirefox)
- return callback(null, firefoxScreenConstraints);
- var screen_constraints = {
- mandatory: {
- chromeMediaSource: chromeMediaSource,
- maxWidth: screen.width > 1920 ? screen.width : 1920,
- maxHeight: screen.height > 1080 ? screen.height : 1080
- },
- optional: []
- };
- if (chromeMediaSource == 'desktop' && !sourceId) {
- if (captureSourceIdWithAudio) {
- getSourceIdWithAudio(function (sourceId, canRequestAudioTrack) {
- screen_constraints.mandatory.chromeMediaSourceId = sourceId;
- if (canRequestAudioTrack) {
- screen_constraints.canRequestAudioTrack = true;
- }
- callback(sourceId == 'PermissionDeniedError' ? sourceId : null, screen_constraints);
- });
- }
- else {
- getSourceId(function (sourceId) {
- screen_constraints.mandatory.chromeMediaSourceId = sourceId;
- callback(sourceId == 'PermissionDeniedError' ? sourceId : null, screen_constraints);
- });
- }
- return;
- }
- if (chromeMediaSource == 'desktop') {
- screen_constraints.mandatory.chromeMediaSourceId = sourceId;
- }
- callback(null, screen_constraints);
-}
-exports.getScreenConstraints = getScreenConstraints;
-exports.getScreenConstraintsWithAudio = getScreenConstraintsWithAudio;
-exports.isChromeExtensionAvailable = isChromeExtensionAvailable;
-exports.getChromeExtensionStatus = getChromeExtensionStatus;
-exports.getSourceId = getSourceId;
-
-},{}],49:[function(require,module,exports){
-"use strict";
-var __extends = (this && this.__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 __());
- };
-})();
-Object.defineProperty(exports, "__esModule", { value: true });
-var freeice = require("freeice");
-var uuid = require("uuid");
-var platform = require("platform");
-var WebRtcPeer = (function () {
- function WebRtcPeer(configuration) {
- var _this = this;
- this.configuration = configuration;
- this.remoteCandidatesQueue = [];
- this.localCandidatesQueue = [];
- this.iceCandidateList = [];
- this.candidategatheringdone = false;
- this.configuration.iceServers = (!!this.configuration.iceServers && this.configuration.iceServers.length > 0) ? this.configuration.iceServers : freeice();
- this.pc = new RTCPeerConnection({ iceServers: this.configuration.iceServers });
- this.id = !!configuration.id ? configuration.id : uuid.v4();
- this.pc.onicecandidate = function (event) {
- var candidate = event.candidate;
- if (candidate) {
- _this.localCandidatesQueue.push({ candidate: candidate.candidate });
- _this.candidategatheringdone = false;
- _this.configuration.onicecandidate(event.candidate);
- }
- else if (!_this.candidategatheringdone) {
- _this.candidategatheringdone = true;
- }
- };
- this.pc.onsignalingstatechange = function () {
- if (_this.pc.signalingState === 'stable') {
- while (_this.iceCandidateList.length > 0) {
- _this.pc.addIceCandidate(_this.iceCandidateList.shift());
- }
- }
- };
- this.start();
- }
- WebRtcPeer.prototype.start = function () {
- var _this = this;
- return new Promise(function (resolve, reject) {
- if (_this.pc.signalingState === 'closed') {
- reject('The peer connection object is in "closed" state. This is most likely due to an invocation of the dispose method before accepting in the dialogue');
- }
- if (!!_this.configuration.mediaStream) {
- _this.pc.addStream(_this.configuration.mediaStream);
- }
- if (_this.configuration.mode === 'sendonly' &&
- (platform.name === 'Chrome' && platform.version.toString().substring(0, 2) === '39')) {
- _this.configuration.mode = 'sendrecv';
- }
- resolve();
- });
- };
- WebRtcPeer.prototype.dispose = function () {
- var _this = this;
- console.debug('Disposing WebRtcPeer');
- try {
- if (this.pc) {
- if (this.pc.signalingState === 'closed') {
- return;
- }
- this.remoteCandidatesQueue = [];
- this.localCandidatesQueue = [];
- this.pc.getLocalStreams().forEach(function (str) {
- _this.streamStop(str);
- });
- this.pc.close();
- }
- }
- catch (err) {
- console.warn('Exception disposing webrtc peer ' + err);
- }
- };
- WebRtcPeer.prototype.generateOffer = function () {
- var _this = this;
- return new Promise(function (resolve, reject) {
- var offerAudio, offerVideo = true;
- if (!!_this.configuration.mediaConstraints) {
- offerAudio = (typeof _this.configuration.mediaConstraints.audio === 'boolean') ?
- _this.configuration.mediaConstraints.audio : true;
- offerVideo = (typeof _this.configuration.mediaConstraints.video === 'boolean') ?
- _this.configuration.mediaConstraints.video : true;
- }
- var constraints = {
- offerToReceiveAudio: +(_this.configuration.mode !== 'sendonly' && offerAudio),
- offerToReceiveVideo: +(_this.configuration.mode !== 'sendonly' && offerVideo)
- };
- console.debug('RTCPeerConnection constraints: ' + JSON.stringify(constraints));
- _this.pc.createOffer(constraints).then(function (offer) {
- console.debug('Created SDP offer');
- return _this.pc.setLocalDescription(offer);
- }).then(function () {
- var localDescription = _this.pc.localDescription;
- if (!!localDescription) {
- console.debug('Local description set', localDescription.sdp);
- resolve(localDescription.sdp);
- }
- else {
- reject('Local description is not defined');
- }
- }).catch(function (error) { return reject(error); });
- });
- };
- WebRtcPeer.prototype.processOffer = function (sdpOffer) {
- var _this = this;
- return new Promise(function (resolve, reject) {
- var offer = {
- type: 'offer',
- sdp: sdpOffer
- };
- console.debug('SDP offer received, setting remote description');
- if (_this.pc.signalingState === 'closed') {
- reject('PeerConnection is closed');
- }
- _this.pc.setRemoteDescription(offer)
- .then(function () {
- return _this.pc.createAnswer();
- }).then(function (answer) {
- console.debug('Created SDP answer');
- return _this.pc.setLocalDescription(answer);
- }).then(function () {
- var localDescription = _this.pc.localDescription;
- if (!!localDescription) {
- console.debug('Local description set', localDescription.sdp);
- resolve(localDescription.sdp);
- }
- else {
- reject('Local description is not defined');
- }
- }).catch(function (error) { return reject(error); });
- });
- };
- WebRtcPeer.prototype.processAnswer = function (sdpAnswer) {
- var _this = this;
- return new Promise(function (resolve, reject) {
- var answer = {
- type: 'answer',
- sdp: sdpAnswer
- };
- console.debug('SDP answer received, setting remote description');
- if (_this.pc.signalingState === 'closed') {
- reject('RTCPeerConnection is closed');
- }
- _this.pc.setRemoteDescription(answer).then(function () { return resolve(); }).catch(function (error) { return reject(error); });
- });
- };
- WebRtcPeer.prototype.addIceCandidate = function (iceCandidate) {
- var _this = this;
- return new Promise(function (resolve, reject) {
- console.debug('Remote ICE candidate received', iceCandidate);
- _this.remoteCandidatesQueue.push(iceCandidate);
- switch (_this.pc.signalingState) {
- case 'closed':
- reject(new Error('PeerConnection object is closed'));
- break;
- case 'stable':
- if (!!_this.pc.remoteDescription) {
- _this.pc.addIceCandidate(iceCandidate).then(function () { return resolve(); }).catch(function (error) { return reject(error); });
- }
- break;
- default:
- _this.iceCandidateList.push(iceCandidate);
- resolve();
- }
- });
- };
- WebRtcPeer.prototype.streamStop = function (stream) {
- stream.getTracks().forEach(function (track) {
- track.stop();
- stream.removeTrack(track);
- });
- };
- return WebRtcPeer;
-}());
-exports.WebRtcPeer = WebRtcPeer;
-var WebRtcPeerRecvonly = (function (_super) {
- __extends(WebRtcPeerRecvonly, _super);
- function WebRtcPeerRecvonly(configuration) {
- var _this = this;
- configuration.mode = 'recvonly';
- _this = _super.call(this, configuration) || this;
- return _this;
- }
- return WebRtcPeerRecvonly;
-}(WebRtcPeer));
-exports.WebRtcPeerRecvonly = WebRtcPeerRecvonly;
-var WebRtcPeerSendonly = (function (_super) {
- __extends(WebRtcPeerSendonly, _super);
- function WebRtcPeerSendonly(configuration) {
- var _this = this;
- configuration.mode = 'sendonly';
- _this = _super.call(this, configuration) || this;
- return _this;
- }
- return WebRtcPeerSendonly;
-}(WebRtcPeer));
-exports.WebRtcPeerSendonly = WebRtcPeerSendonly;
-var WebRtcPeerSendrecv = (function (_super) {
- __extends(WebRtcPeerSendrecv, _super);
- function WebRtcPeerSendrecv(configuration) {
- var _this = this;
- configuration.mode = 'sendrecv';
- _this = _super.call(this, configuration) || this;
- return _this;
- }
- return WebRtcPeerSendrecv;
-}(WebRtcPeer));
-exports.WebRtcPeerSendrecv = WebRtcPeerSendrecv;
-
-},{"freeice":2,"platform":8,"uuid":9}],50:[function(require,module,exports){
-"use strict";
-Object.defineProperty(exports, "__esModule", { value: true });
-var platform = require("platform");
-var WebRtcStats = (function () {
- function WebRtcStats(stream) {
- this.stream = stream;
- this.webRtcStatsEnabled = false;
- this.statsInterval = 1;
- this.stats = {
- inbound: {
- audio: {
- bytesReceived: 0,
- packetsReceived: 0,
- packetsLost: 0
- },
- video: {
- bytesReceived: 0,
- packetsReceived: 0,
- packetsLost: 0,
- framesDecoded: 0,
- nackCount: 0
- }
- },
- outbound: {
- audio: {
- bytesSent: 0,
- packetsSent: 0,
- },
- video: {
- bytesSent: 0,
- packetsSent: 0,
- framesEncoded: 0,
- nackCount: 0
- }
- }
- };
- }
- WebRtcStats.prototype.isEnabled = function () {
- return this.webRtcStatsEnabled;
- };
- WebRtcStats.prototype.initWebRtcStats = function () {
- var _this = this;
- var elastestInstrumentation = localStorage.getItem('elastest-instrumentation');
- if (elastestInstrumentation) {
- console.warn('WebRtc stats enabled for stream ' + this.stream.streamId + ' of connection ' + this.stream.connection.connectionId);
- this.webRtcStatsEnabled = true;
- var instrumentation_1 = JSON.parse(elastestInstrumentation);
- this.statsInterval = instrumentation_1.webrtc.interval;
- console.warn('localStorage item: ' + JSON.stringify(instrumentation_1));
- this.webRtcStatsIntervalId = setInterval(function () {
- _this.sendStatsToHttpEndpoint(instrumentation_1);
- }, this.statsInterval * 1000);
- return;
- }
- console.debug('WebRtc stats not enabled');
- };
- WebRtcStats.prototype.stopWebRtcStats = function () {
- if (this.webRtcStatsEnabled) {
- clearInterval(this.webRtcStatsIntervalId);
- console.warn('WebRtc stats stopped for disposed stream ' + this.stream.streamId + ' of connection ' + this.stream.connection.connectionId);
- }
- };
- WebRtcStats.prototype.getSelectedIceCandidateInfo = function () {
- var _this = this;
- return new Promise(function (resolve, reject) {
- _this.getStatsAgnostic(_this.stream.getRTCPeerConnection(), function (stats) {
- if ((platform.name.indexOf('Chrome') !== -1) || (platform.name.indexOf('Opera') !== -1)) {
- var localCandidateId = void 0, remoteCandidateId = void 0, googCandidatePair = void 0;
- var localCandidates = {};
- var remoteCandidates = {};
- for (var key in stats) {
- var stat = stats[key];
- if (stat.type === 'localcandidate') {
- localCandidates[stat.id] = stat;
- }
- else if (stat.type === 'remotecandidate') {
- remoteCandidates[stat.id] = stat;
- }
- else if (stat.type === 'googCandidatePair' && (stat.googActiveConnection === 'true')) {
- googCandidatePair = stat;
- localCandidateId = stat.localCandidateId;
- remoteCandidateId = stat.remoteCandidateId;
- }
- }
- var finalLocalCandidate_1 = localCandidates[localCandidateId];
- if (!!finalLocalCandidate_1) {
- var candList = _this.stream.getLocalIceCandidateList();
- var cand = candList.filter(function (c) {
- return (!!c.candidate &&
- c.candidate.indexOf(finalLocalCandidate_1.ipAddress) >= 0 &&
- c.candidate.indexOf(finalLocalCandidate_1.portNumber) >= 0 &&
- c.candidate.indexOf(finalLocalCandidate_1.priority) >= 0);
- });
- finalLocalCandidate_1.raw = !!cand[0] ? cand[0].candidate : 'ERROR: Cannot find local candidate in list of sent ICE candidates';
- }
- else {
- finalLocalCandidate_1 = 'ERROR: No active local ICE candidate. Probably ICE-TCP is being used';
- }
- var finalRemoteCandidate_1 = remoteCandidates[remoteCandidateId];
- if (!!finalRemoteCandidate_1) {
- var candList = _this.stream.getRemoteIceCandidateList();
- var cand = candList.filter(function (c) {
- return (!!c.candidate &&
- c.candidate.indexOf(finalRemoteCandidate_1.ipAddress) >= 0 &&
- c.candidate.indexOf(finalRemoteCandidate_1.portNumber) >= 0 &&
- c.candidate.indexOf(finalRemoteCandidate_1.priority) >= 0);
- });
- finalRemoteCandidate_1.raw = !!cand[0] ? cand[0].candidate : 'ERROR: Cannot find remote candidate in list of received ICE candidates';
- }
- else {
- finalRemoteCandidate_1 = 'ERROR: No active remote ICE candidate. Probably ICE-TCP is being used';
- }
- resolve({
- googCandidatePair: googCandidatePair,
- localCandidate: finalLocalCandidate_1,
- remoteCandidate: finalRemoteCandidate_1
- });
- }
- else {
- reject('Selected ICE candidate info only available for Chrome');
- }
- }, function (error) {
- reject(error);
- });
- });
- };
- WebRtcStats.prototype.sendStatsToHttpEndpoint = function (instrumentation) {
- var _this = this;
- var sendPost = function (json) {
- var http = new XMLHttpRequest();
- var url = instrumentation.webrtc.httpEndpoint;
- http.open('POST', url, true);
- http.setRequestHeader('Content-type', 'application/json');
- http.onreadystatechange = function () {
- if (http.readyState === 4 && http.status === 200) {
- console.log('WebRtc stats successfully sent to ' + url + ' for stream ' + _this.stream.streamId + ' of connection ' + _this.stream.connection.connectionId);
- }
- };
- http.send(json);
- };
- var f = function (stats) {
- if (platform.name.indexOf('Firefox') !== -1) {
- stats.forEach(function (stat) {
- var json = {};
- if ((stat.type === 'inbound-rtp') &&
- (stat.nackCount !== null &&
- stat.isRemote === false &&
- stat.id.startsWith('inbound') &&
- stat.remoteId.startsWith('inbound'))) {
- var metricId = 'webrtc_inbound_' + stat.mediaType + '_' + stat.ssrc;
- var jit = stat.jitter * 1000;
- var metrics = {
- bytesReceived: (stat.bytesReceived - _this.stats.inbound[stat.mediaType].bytesReceived) / _this.statsInterval,
- jitter: jit,
- packetsReceived: (stat.packetsReceived - _this.stats.inbound[stat.mediaType].packetsReceived) / _this.statsInterval,
- packetsLost: (stat.packetsLost - _this.stats.inbound[stat.mediaType].packetsLost) / _this.statsInterval
- };
- var units = {
- bytesReceived: 'bytes',
- jitter: 'ms',
- packetsReceived: 'packets',
- packetsLost: 'packets'
- };
- if (stat.mediaType === 'video') {
- metrics['framesDecoded'] = (stat.framesDecoded - _this.stats.inbound.video.framesDecoded) / _this.statsInterval;
- metrics['nackCount'] = (stat.nackCount - _this.stats.inbound.video.nackCount) / _this.statsInterval;
- units['framesDecoded'] = 'frames';
- units['nackCount'] = 'packets';
- _this.stats.inbound.video.framesDecoded = stat.framesDecoded;
- _this.stats.inbound.video.nackCount = stat.nackCount;
- }
- _this.stats.inbound[stat.mediaType].bytesReceived = stat.bytesReceived;
- _this.stats.inbound[stat.mediaType].packetsReceived = stat.packetsReceived;
- _this.stats.inbound[stat.mediaType].packetsLost = stat.packetsLost;
- json = {
- '@timestamp': new Date(stat.timestamp).toISOString(),
- 'exec': instrumentation.exec,
- 'component': instrumentation.component,
- 'stream': 'webRtc',
- 'type': metricId,
- 'stream_type': 'composed_metrics',
- 'units': units
- };
- json[metricId] = metrics;
- sendPost(JSON.stringify(json));
- }
- else if ((stat.type === 'outbound-rtp') &&
- (stat.isRemote === false &&
- stat.id.toLowerCase().includes('outbound'))) {
- var metricId = 'webrtc_outbound_' + stat.mediaType + '_' + stat.ssrc;
- var metrics = {
- bytesSent: (stat.bytesSent - _this.stats.outbound[stat.mediaType].bytesSent) / _this.statsInterval,
- packetsSent: (stat.packetsSent - _this.stats.outbound[stat.mediaType].packetsSent) / _this.statsInterval
- };
- var units = {
- bytesSent: 'bytes',
- packetsSent: 'packets'
- };
- if (stat.mediaType === 'video') {
- metrics['framesEncoded'] = (stat.framesEncoded - _this.stats.outbound.video.framesEncoded) / _this.statsInterval;
- units['framesEncoded'] = 'frames';
- _this.stats.outbound.video.framesEncoded = stat.framesEncoded;
- }
- _this.stats.outbound[stat.mediaType].bytesSent = stat.bytesSent;
- _this.stats.outbound[stat.mediaType].packetsSent = stat.packetsSent;
- json = {
- '@timestamp': new Date(stat.timestamp).toISOString(),
- 'exec': instrumentation.exec,
- 'component': instrumentation.component,
- 'stream': 'webRtc',
- 'type': metricId,
- 'stream_type': 'composed_metrics',
- 'units': units
- };
- json[metricId] = metrics;
- sendPost(JSON.stringify(json));
- }
- });
- }
- else if ((platform.name.indexOf('Chrome') !== -1) || (platform.name.indexOf('Opera') !== -1)) {
- for (var _i = 0, _a = Object.keys(stats); _i < _a.length; _i++) {
- var key = _a[_i];
- var stat = stats[key];
- if (stat.type === 'ssrc') {
- var json = {};
- if ('bytesReceived' in stat && ((stat.mediaType === 'audio' && 'audioOutputLevel' in stat) ||
- (stat.mediaType === 'video' && 'qpSum' in stat))) {
- var metricId = 'webrtc_inbound_' + stat.mediaType + '_' + stat.ssrc;
- var metrics = {
- bytesReceived: (stat.bytesReceived - _this.stats.inbound[stat.mediaType].bytesReceived) / _this.statsInterval,
- jitter: stat.googJitterBufferMs,
- packetsReceived: (stat.packetsReceived - _this.stats.inbound[stat.mediaType].packetsReceived) / _this.statsInterval,
- packetsLost: (stat.packetsLost - _this.stats.inbound[stat.mediaType].packetsLost) / _this.statsInterval
- };
- var units = {
- bytesReceived: 'bytes',
- jitter: 'ms',
- packetsReceived: 'packets',
- packetsLost: 'packets'
- };
- if (stat.mediaType === 'video') {
- metrics['framesDecoded'] = (stat.framesDecoded - _this.stats.inbound.video.framesDecoded) / _this.statsInterval;
- metrics['nackCount'] = (stat.googNacksSent - _this.stats.inbound.video.nackCount) / _this.statsInterval;
- units['framesDecoded'] = 'frames';
- units['nackCount'] = 'packets';
- _this.stats.inbound.video.framesDecoded = stat.framesDecoded;
- _this.stats.inbound.video.nackCount = stat.googNacksSent;
- }
- _this.stats.inbound[stat.mediaType].bytesReceived = stat.bytesReceived;
- _this.stats.inbound[stat.mediaType].packetsReceived = stat.packetsReceived;
- _this.stats.inbound[stat.mediaType].packetsLost = stat.packetsLost;
- json = {
- '@timestamp': new Date(stat.timestamp).toISOString(),
- 'exec': instrumentation.exec,
- 'component': instrumentation.component,
- 'stream': 'webRtc',
- 'type': metricId,
- 'stream_type': 'composed_metrics',
- 'units': units
- };
- json[metricId] = metrics;
- sendPost(JSON.stringify(json));
- }
- else if ('bytesSent' in stat) {
- var metricId = 'webrtc_outbound_' + stat.mediaType + '_' + stat.ssrc;
- var metrics = {
- bytesSent: (stat.bytesSent - _this.stats.outbound[stat.mediaType].bytesSent) / _this.statsInterval,
- packetsSent: (stat.packetsSent - _this.stats.outbound[stat.mediaType].packetsSent) / _this.statsInterval
- };
- var units = {
- bytesSent: 'bytes',
- packetsSent: 'packets'
- };
- if (stat.mediaType === 'video') {
- metrics['framesEncoded'] = (stat.framesEncoded - _this.stats.outbound.video.framesEncoded) / _this.statsInterval;
- units['framesEncoded'] = 'frames';
- _this.stats.outbound.video.framesEncoded = stat.framesEncoded;
- }
- _this.stats.outbound[stat.mediaType].bytesSent = stat.bytesSent;
- _this.stats.outbound[stat.mediaType].packetsSent = stat.packetsSent;
- json = {
- '@timestamp': new Date(stat.timestamp).toISOString(),
- 'exec': instrumentation.exec,
- 'component': instrumentation.component,
- 'stream': 'webRtc',
- 'type': metricId,
- 'stream_type': 'composed_metrics',
- 'units': units
- };
- json[metricId] = metrics;
- sendPost(JSON.stringify(json));
- }
- }
- }
- }
- };
- this.getStatsAgnostic(this.stream.getRTCPeerConnection(), f, function (error) { console.log(error); });
- };
- WebRtcStats.prototype.standardizeReport = function (response) {
- console.log(response);
- var standardReport = {};
- if (platform.name.indexOf('Firefox') !== -1) {
- Object.keys(response).forEach(function (key) {
- console.log(response[key]);
- });
- return response;
- }
- response.result().forEach(function (report) {
- var standardStats = {
- id: report.id,
- timestamp: report.timestamp,
- type: report.type
- };
- report.names().forEach(function (name) {
- standardStats[name] = report.stat(name);
- });
- standardReport[standardStats.id] = standardStats;
- });
- return standardReport;
- };
- WebRtcStats.prototype.getStatsAgnostic = function (pc, successCb, failureCb) {
- var _this = this;
- if (platform.name.indexOf('Firefox') !== -1) {
- return pc.getStats(null).then(function (response) {
- var report = _this.standardizeReport(response);
- successCb(report);
- }).catch(failureCb);
- }
- else if ((platform.name.indexOf('Chrome') !== -1) || (platform.name.indexOf('Opera') !== -1)) {
- return pc.getStats(function (response) {
- var report = _this.standardizeReport(response);
- successCb(report);
- }, null, failureCb);
- }
- };
- return WebRtcStats;
-}());
-exports.WebRtcStats = WebRtcStats;
-
-},{"platform":8}]},{},[16])
-//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL25vZGVfbW9kdWxlcy9icm93c2VyLXBhY2svX3ByZWx1ZGUuanMiLCIuLi9ub2RlX21vZHVsZXMvZXZlbnRzL2V2ZW50cy5qcyIsIi4uL25vZGVfbW9kdWxlcy9mcmVlaWNlL2luZGV4LmpzIiwiLi4vbm9kZV9tb2R1bGVzL2ZyZWVpY2Uvc3R1bi5qc29uIiwiLi4vbm9kZV9tb2R1bGVzL2ZyZWVpY2UvdHVybi5qc29uIiwiLi4vbm9kZV9tb2R1bGVzL2hhcmsvaGFyay5qcyIsIi4uL25vZGVfbW9kdWxlcy9pbmhlcml0cy9pbmhlcml0c19icm93c2VyLmpzIiwiLi4vbm9kZV9tb2R1bGVzL25vcm1hbGljZS9pbmRleC5qcyIsIi4uL25vZGVfbW9kdWxlcy9wbGF0Zm9ybS9wbGF0Zm9ybS5qcyIsIi4uL25vZGVfbW9kdWxlcy91dWlkL2luZGV4LmpzIiwiLi4vbm9kZV9tb2R1bGVzL3V1aWQvbGliL2J5dGVzVG9VdWlkLmpzIiwiLi4vbm9kZV9tb2R1bGVzL3V1aWQvbGliL3JuZy1icm93c2VyLmpzIiwiLi4vbm9kZV9tb2R1bGVzL3V1aWQvdjEuanMiLCIuLi9ub2RlX21vZHVsZXMvdXVpZC92NC5qcyIsIi4uL25vZGVfbW9kdWxlcy93aWxkZW1pdHRlci93aWxkZW1pdHRlci5qcyIsIi4uL25vZGVfbW9kdWxlcy93b2xmeTg3LWV2ZW50ZW1pdHRlci9FdmVudEVtaXR0ZXIuanMiLCJNYWluLnRzIiwiT3BlblZpZHUvQ29ubmVjdGlvbi50cyIsIk9wZW5WaWR1L0xvY2FsUmVjb3JkZXIudHMiLCJPcGVuVmlkdS9PcGVuVmlkdS50cyIsIk9wZW5WaWR1L1B1Ymxpc2hlci50cyIsIk9wZW5WaWR1L1Nlc3Npb24udHMiLCJPcGVuVmlkdS9TdHJlYW0udHMiLCJPcGVuVmlkdS9TdHJlYW1NYW5hZ2VyLnRzIiwiT3BlblZpZHUvU3Vic2NyaWJlci50cyIsIk9wZW5WaWR1SW50ZXJuYWwvRW51bXMvTG9jYWxSZWNvcmRlclN0YXRlLnRzIiwiT3BlblZpZHVJbnRlcm5hbC9FbnVtcy9PcGVuVmlkdUVycm9yLnRzIiwiT3BlblZpZHVJbnRlcm5hbC9FbnVtcy9WaWRlb0luc2VydE1vZGUudHMiLCJPcGVuVmlkdUludGVybmFsL0V2ZW50cy9Db25uZWN0aW9uRXZlbnQudHMiLCJPcGVuVmlkdUludGVybmFsL0V2ZW50cy9FdmVudC50cyIsIk9wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1B1Ymxpc2hlclNwZWFraW5nRXZlbnQudHMiLCJPcGVuVmlkdUludGVybmFsL0V2ZW50cy9SZWNvcmRpbmdFdmVudC50cyIsIk9wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1Nlc3Npb25EaXNjb25uZWN0ZWRFdmVudC50cyIsIk9wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1NpZ25hbEV2ZW50LnRzIiwiT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvU3RyZWFtRXZlbnQudHMiLCJPcGVuVmlkdUludGVybmFsL0V2ZW50cy9TdHJlYW1NYW5hZ2VyRXZlbnQudHMiLCJPcGVuVmlkdUludGVybmFsL0V2ZW50cy9TdHJlYW1Qcm9wZXJ0eUNoYW5nZWRFdmVudC50cyIsIk9wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1ZpZGVvRWxlbWVudEV2ZW50LnRzIiwiT3BlblZpZHVJbnRlcm5hbC9LdXJlbnRvVXRpbHMva3VyZW50by1qc29ucnBjL01hcHBlci5qcyIsIk9wZW5WaWR1SW50ZXJuYWwvS3VyZW50b1V0aWxzL2t1cmVudG8tanNvbnJwYy9jbGllbnRzL2luZGV4LmpzIiwiT3BlblZpZHVJbnRlcm5hbC9LdXJlbnRvVXRpbHMva3VyZW50by1qc29ucnBjL2NsaWVudHMvanNvbnJwY2NsaWVudC5qcyIsIk9wZW5WaWR1SW50ZXJuYWwvS3VyZW50b1V0aWxzL2t1cmVudG8tanNvbnJwYy9jbGllbnRzL3RyYW5zcG9ydHMvaW5kZXguanMiLCJPcGVuVmlkdUludGVybmFsL0t1cmVudG9VdGlscy9rdXJlbnRvLWpzb25ycGMvY2xpZW50cy90cmFuc3BvcnRzL3dlYlNvY2tldFdpdGhSZWNvbm5lY3Rpb24uanMiLCJPcGVuVmlkdUludGVybmFsL0t1cmVudG9VdGlscy9rdXJlbnRvLWpzb25ycGMvaW5kZXguanMiLCJPcGVuVmlkdUludGVybmFsL0t1cmVudG9VdGlscy9rdXJlbnRvLWpzb25ycGMvcGFja2Vycy9Kc29uUlBDLmpzIiwiT3BlblZpZHVJbnRlcm5hbC9LdXJlbnRvVXRpbHMva3VyZW50by1qc29ucnBjL3BhY2tlcnMvWG1sUlBDLmpzIiwiT3BlblZpZHVJbnRlcm5hbC9LdXJlbnRvVXRpbHMva3VyZW50by1qc29ucnBjL3BhY2tlcnMvaW5kZXguanMiLCJPcGVuVmlkdUludGVybmFsL1NjcmVlblNoYXJpbmcvU2NyZWVuLUNhcHR1cmluZy1BdXRvLmpzIiwiT3BlblZpZHVJbnRlcm5hbC9TY3JlZW5TaGFyaW5nL1NjcmVlbi1DYXB0dXJpbmcuanMiLCJPcGVuVmlkdUludGVybmFsL1dlYlJ0Y1BlZXIvV2ViUnRjUGVlci50cyIsIk9wZW5WaWR1SW50ZXJuYWwvV2ViUnRjU3RhdHMvV2ViUnRjU3RhdHMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7QUNBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzNnQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDekdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDaEJBO0FBQ0E7O0FDREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2xKQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdkJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUM1REE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7O0FDanNDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDUkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDeEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbENBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDN0dBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM3QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDekpBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7O0FDdGVBLGdEQUErQztBQUUvQyxJQUFJLE1BQU0s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O1FBQWpELGlCQWNDO1FBYkcsSUFBSSxRQUFRLENBQUMsSUFBSyxDQUFDLE9BQU8sQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLENBQUMsRUFBRTtZQUUxQyxPQUFPLEVBQUUsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLENBQUMsSUFBSSxDQUFDLFVBQUEsUUFBUTtnQkFDbEMsSUFBTSxNQUFNLEdBQUcsS0FBSSxDQUFDLGlCQUFpQixDQUFDLFFBQVEsQ0FBQyxDQUFDO2dCQUNoRCxTQUFTLENBQUMsTUFBTSxDQUFDLENBQUM7WUFDdEIsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLFNBQVMsQ0FBQyxDQUFDO1NBQ3ZCO2FBQU0sSUFBSSxDQUFDLFFBQVEsQ0FBQyxJQUFLLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSyxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxFQUFFO1lBRTlGLE9BQU8sRUFBRSxDQUFDLFFBQVEsQ0FBQyxVQUFDLFFBQVE7Z0JBQ3hCLElBQU0sTUFBTSxHQUFHLEtBQUksQ0FBQyxpQkFBaUIsQ0FBQyxRQUFRLENBQUMsQ0FBQztnQkFDaEQsU0FBUyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1lBQ3RCLENBQUMsRUFBRSxJQUFJLEVBQUUsU0FBUyxDQUFDLENBQUM7U0FDdkI7SUFDTCxDQUFDO0lBRUwsa0JBQUM7QUFBRCxDQXJZQSxBQXFZQyxJQUFBO0FBcllZLGtDQUFXIiwiZmlsZSI6ImdlbmVyYXRlZC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzQ29udGVudCI6WyIoZnVuY3Rpb24oKXtmdW5jdGlvbiByKGUsbix0KXtmdW5jdGlvbiBvKGksZil7aWYoIW5baV0pe2lmKCFlW2ldKXt2YXIgYz1cImZ1bmN0aW9uXCI9PXR5cGVvZiByZXF1aXJlJiZyZXF1aXJlO2lmKCFmJiZjKXJldHVybiBjKGksITApO2lmKHUpcmV0dXJuIHUoaSwhMCk7dmFyIGE9bmV3IEVycm9yKFwiQ2Fubm90IGZpbmQgbW9kdWxlICdcIitpK1wiJ1wiKTt0aHJvdyBhLmNvZGU9XCJNT0RVTEVfTk9UX0ZPVU5EXCIsYX12YXIgcD1uW2ldPXtleHBvcnRzOnt9fTtlW2ldWzBdLmNhbGwocC5leHBvcnRzLGZ1bmN0aW9uKHIpe3ZhciBuPWVbaV1bMV1bcl07cmV0dXJuIG8obnx8cil9LHAscC5leHBvcnRzLHIsZSxuLHQpfXJldHVybiBuW2ldLmV4cG9ydHN9Zm9yKHZhciB1PVwiZnVuY3Rpb25cIj09dHlwZW9mIHJlcXVpcmUmJnJlcXVpcmUsaT0wO2k8dC5sZW5ndGg7aSsrKW8odFtpXSk7cmV0dXJuIG99cmV0dXJuIHJ9KSgpIiwiLy8gQ29weXJpZ2h0IEpveWVudCwgSW5jLiBhbmQgb3RoZXIgTm9kZSBjb250cmlidXRvcnMuXG4vL1xuLy8gUGVybWlzc2lvbiBpcyBoZXJlYnkgZ3JhbnRlZCwgZnJlZSBvZiBjaGFyZ2UsIHRvIGFueSBwZXJzb24gb2J0YWluaW5nIGFcbi8vIGNvcHkgb2YgdGhpcyBzb2Z0d2FyZSBhbmQgYXNzb2NpYXRlZCBkb2N1bWVudGF0aW9uIGZpbGVzICh0aGVcbi8vIFwiU29mdHdhcmVcIiksIHRvIGRlYWwgaW4gdGhlIFNvZnR3YXJlIHdpdGhvdXQgcmVzdHJpY3Rpb24sIGluY2x1ZGluZ1xuLy8gd2l0aG91dCBsaW1pdGF0aW9uIHRoZSByaWdodHMgdG8gdXNlLCBjb3B5LCBtb2RpZnksIG1lcmdlLCBwdWJsaXNoLFxuLy8gZGlzdHJpYnV0ZSwgc3VibGljZW5zZSwgYW5kL29yIHNlbGwgY29waWVzIG9mIHRoZSBTb2Z0d2FyZSwgYW5kIHRvIHBlcm1pdFxuLy8gcGVyc29ucyB0byB3aG9tIHRoZSBTb2Z0d2FyZSBpcyBmdXJuaXNoZWQgdG8gZG8gc28sIHN1YmplY3QgdG8gdGhlXG4vLyBmb2xsb3dpbmcgY29uZGl0aW9uczpcbi8vXG4vLyBUaGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSBhbmQgdGhpcyBwZXJtaXNzaW9uIG5vdGljZSBzaGFsbCBiZSBpbmNsdWRlZFxuLy8gaW4gYWxsIGNvcGllcyBvciBzdWJzdGFudGlhbCBwb3J0aW9ucyBvZiB0aGUgU29mdHdhcmUuXG4vL1xuLy8gVEhFIFNPRlRXQVJFIElTIFBST1ZJREVEIFwiQVMgSVNcIiwgV0lUSE9VVCBXQVJSQU5UWSBPRiBBTlkgS0lORCwgRVhQUkVTU1xuLy8gT1IgSU1QTElFRCwgSU5DTFVESU5HIEJVVCBOT1QgTElNSVRFRCBUTyBUSEUgV0FSUkFOVElFUyBPRlxuLy8gTUVSQ0hBTlRBQklMSVRZLCBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBTkQgTk9OSU5GUklOR0VNRU5ULiBJTlxuLy8gTk8gRVZFTlQgU0hBTEwgVEhFIEFVVEhPUlMgT1IgQ09QWVJJR0hUIEhPTERFUlMgQkUgTElBQkxFIEZPUiBBTlkgQ0xBSU0sXG4vLyBEQU1BR0VTIE9SIE9USEVSIExJQUJJTElUWSwgV0hFVEhFUiBJTiBBTiBBQ1RJT04gT0YgQ09OVFJBQ1QsIFRPUlQgT1Jcbi8vIE9USEVSV0lTRSwgQVJJU0lORyBGUk9NLCBPVVQgT0YgT1IgSU4gQ09OTkVDVElPTiBXSVRIIFRIRSBTT0ZUV0FSRSBPUiBUSEVcbi8vIFVTRSBPUiBPVEhFUiBERUFMSU5HUyBJTiBUSEUgU09GVFdBUkUuXG5cbnZhciBvYmplY3RDcmVhdGUgPSBPYmplY3QuY3JlYXRlIHx8IG9iamVjdENyZWF0ZVBvbHlmaWxsXG52YXIgb2JqZWN0S2V5cyA9IE9iamVjdC5rZXlzIHx8IG9iamVjdEtleXNQb2x5ZmlsbFxudmFyIGJpbmQgPSBGdW5jdGlvbi5wcm90b3R5cGUuYmluZCB8fCBmdW5jdGlvbkJpbmRQb2x5ZmlsbFxuXG5mdW5jdGlvbiBFdmVudEVtaXR0ZXIoKSB7XG4gIGlmICghdGhpcy5fZXZlbnRzIHx8ICFPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwodGhpcywgJ19ldmVudHMnKSkge1xuICAgIHRoaXMuX2V2ZW50cyA9IG9iamVjdENyZWF0ZShudWxsKTtcbiAgICB0aGlzLl9ldmVudHNDb3VudCA9IDA7XG4gIH1cblxuICB0aGlzLl9tYXhMaXN0ZW5lcnMgPSB0aGlzLl9tYXhMaXN0ZW5lcnMgfHwgdW5kZWZpbmVkO1xufVxubW9kdWxlLmV4cG9ydHMgPSBFdmVudEVtaXR0ZXI7XG5cbi8vIEJhY2t3YXJkcy1jb21wYXQgd2l0aCBub2RlIDAuMTAueFxuRXZlbnRFbWl0dGVyLkV2ZW50RW1pdHRlciA9IEV2ZW50RW1pdHRlcjtcblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5fZXZlbnRzID0gdW5kZWZpbmVkO1xuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5fbWF4TGlzdGVuZXJzID0gdW5kZWZpbmVkO1xuXG4vLyBCeSBkZWZhdWx0IEV2ZW50RW1pdHRlcnMgd2lsbCBwcmludCBhIHdhcm5pbmcgaWYgbW9yZSB0aGFuIDEwIGxpc3RlbmVycyBhcmVcbi8vIGFkZGVkIHRvIGl0LiBUaGlzIGlzIGEgdXNlZnVsIGRlZmF1bHQgd2hpY2ggaGVscHMgZmluZGluZyBtZW1vcnkgbGVha3MuXG52YXIgZGVmYXVsdE1heExpc3RlbmVycyA9IDEwO1xuXG52YXIgaGFzRGVmaW5lUHJvcGVydHk7XG50cnkge1xuICB2YXIgbyA9IHt9O1xuICBpZiAoT2JqZWN0LmRlZmluZVByb3BlcnR5KSBPYmplY3QuZGVmaW5lUHJvcGVydHkobywgJ3gnLCB7IHZhbHVlOiAwIH0pO1xuICBoYXNEZWZpbmVQcm9wZXJ0eSA9IG8ueCA9PT0gMDtcbn0gY2F0Y2ggKGVycikgeyBoYXNEZWZpbmVQcm9wZXJ0eSA9IGZhbHNlIH1cbmlmIChoYXNEZWZpbmVQcm9wZXJ0eSkge1xuICBPYmplY3QuZGVmaW5lUHJvcGVydHkoRXZlbnRFbWl0dGVyLCAnZGVmYXVsdE1heExpc3RlbmVycycsIHtcbiAgICBlbnVtZXJhYmxlOiB0cnVlLFxuICAgIGdldDogZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4gZGVmYXVsdE1heExpc3RlbmVycztcbiAgICB9LFxuICAgIHNldDogZnVuY3Rpb24oYXJnKSB7XG4gICAgICAvLyBjaGVjayB3aGV0aGVyIHRoZSBpbnB1dCBpcyBhIHBvc2l0aXZlIG51bWJlciAod2hvc2UgdmFsdWUgaXMgemVybyBvclxuICAgICAgLy8gZ3JlYXRlciBhbmQgbm90IGEgTmFOKS5cbiAgICAgIGlmICh0eXBlb2YgYXJnICE9PSAnbnVtYmVyJyB8fCBhcmcgPCAwIHx8IGFyZyAhPT0gYXJnKVxuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdcImRlZmF1bHRNYXhMaXN0ZW5lcnNcIiBtdXN0IGJlIGEgcG9zaXRpdmUgbnVtYmVyJyk7XG4gICAgICBkZWZhdWx0TWF4TGlzdGVuZXJzID0gYXJnO1xuICAgIH1cbiAgfSk7XG59IGVsc2Uge1xuICBFdmVudEVtaXR0ZXIuZGVmYXVsdE1heExpc3RlbmVycyA9IGRlZmF1bHRNYXhMaXN0ZW5lcnM7XG59XG5cbi8vIE9idmlvdXNseSBub3QgYWxsIEVtaXR0ZXJzIHNob3VsZCBiZSBsaW1pdGVkIHRvIDEwLiBUaGlzIGZ1bmN0aW9uIGFsbG93c1xuLy8gdGhhdCB0byBiZSBpbmNyZWFzZWQuIFNldCB0byB6ZXJvIGZvciB1bmxpbWl0ZWQuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLnNldE1heExpc3RlbmVycyA9IGZ1bmN0aW9uIHNldE1heExpc3RlbmVycyhuKSB7XG4gIGlmICh0eXBlb2YgbiAhPT0gJ251bWJlcicgfHwgbiA8IDAgfHwgaXNOYU4obikpXG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcignXCJuXCIgYXJndW1lbnQgbXVzdCBiZSBhIHBvc2l0aXZlIG51bWJlcicpO1xuICB0aGlzLl9tYXhMaXN0ZW5lcnMgPSBuO1xuICByZXR1cm4gdGhpcztcbn07XG5cbmZ1bmN0aW9uICRnZXRNYXhMaXN0ZW5lcnModGhhdCkge1xuICBpZiAodGhhdC5fbWF4TGlzdGVuZXJzID09PSB1bmRlZmluZWQpXG4gICAgcmV0dXJuIEV2ZW50RW1pdHRlci5kZWZhdWx0TWF4TGlzdGVuZXJzO1xuICByZXR1cm4gdGhhdC5fbWF4TGlzdGVuZXJzO1xufVxuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLmdldE1heExpc3RlbmVycyA9IGZ1bmN0aW9uIGdldE1heExpc3RlbmVycygpIHtcbiAgcmV0dXJuICRnZXRNYXhMaXN0ZW5lcnModGhpcyk7XG59O1xuXG4vLyBUaGVzZSBzdGFuZGFsb25lIGVtaXQqIGZ1bmN0aW9ucyBhcmUgdXNlZCB0byBvcHRpbWl6ZSBjYWxsaW5nIG9mIGV2ZW50XG4vLyBoYW5kbGVycyBmb3IgZmFzdCBjYXNlcyBiZWNhdXNlIGVtaXQoKSBpdHNlbGYgb2Z0ZW4gaGFzIGEgdmFyaWFibGUgbnVtYmVyIG9mXG4vLyBhcmd1bWVudHMgYW5kIGNhbiBiZSBkZW9wdGltaXplZCBiZWNhdXNlIG9mIHRoYXQuIFRoZXNlIGZ1bmN0aW9ucyBhbHdheXMgaGF2ZVxuLy8gdGhlIHNhbWUgbnVtYmVyIG9mIGFyZ3VtZW50cyBhbmQgdGh1cyBkbyBub3QgZ2V0IGRlb3B0aW1pemVkLCBzbyB0aGUgY29kZVxuLy8gaW5zaWRlIHRoZW0gY2FuIGV4ZWN1dGUgZmFzdGVyLlxuZnVuY3Rpb24gZW1pdE5vbmUoaGFuZGxlciwgaXNGbiwgc2VsZikge1xuICBpZiAoaXNGbilcbiAgICBoYW5kbGVyLmNhbGwoc2VsZik7XG4gIGVsc2Uge1xuICAgIHZhciBsZW4gPSBoYW5kbGVyLmxlbmd0aDtcbiAgICB2YXIgbGlzdGVuZXJzID0gYXJyYXlDbG9uZShoYW5kbGVyLCBsZW4pO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuOyArK2kpXG4gICAgICBsaXN0ZW5lcnNbaV0uY2FsbChzZWxmKTtcbiAgfVxufVxuZnVuY3Rpb24gZW1pdE9uZShoYW5kbGVyLCBpc0ZuLCBzZWxmLCBhcmcxKSB7XG4gIGlmIChpc0ZuKVxuICAgIGhhbmRsZXIuY2FsbChzZWxmLCBhcmcxKTtcbiAgZWxzZSB7XG4gICAgdmFyIGxlbiA9IGhhbmRsZXIubGVuZ3RoO1xuICAgIHZhciBsaXN0ZW5lcnMgPSBhcnJheUNsb25lKGhhbmRsZXIsIGxlbik7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW47ICsraSlcbiAgICAgIGxpc3RlbmVyc1tpXS5jYWxsKHNlbGYsIGFyZzEpO1xuICB9XG59XG5mdW5jdGlvbiBlbWl0VHdvKGhhbmRsZXIsIGlzRm4sIHNlbGYsIGFyZzEsIGFyZzIpIHtcbiAgaWYgKGlzRm4pXG4gICAgaGFuZGxlci5jYWxsKHNlbGYsIGFyZzEsIGFyZzIpO1xuICBlbHNlIHtcbiAgICB2YXIgbGVuID0gaGFuZGxlci5sZW5ndGg7XG4gICAgdmFyIGxpc3RlbmVycyA9IGFycmF5Q2xvbmUoaGFuZGxlciwgbGVuKTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgKytpKVxuICAgICAgbGlzdGVuZXJzW2ldLmNhbGwoc2VsZiwgYXJnMSwgYXJnMik7XG4gIH1cbn1cbmZ1bmN0aW9uIGVtaXRUaHJlZShoYW5kbGVyLCBpc0ZuLCBzZWxmLCBhcmcxLCBhcmcyLCBhcmczKSB7XG4gIGlmIChpc0ZuKVxuICAgIGhhbmRsZXIuY2FsbChzZWxmLCBhcmcxLCBhcmcyLCBhcmczKTtcbiAgZWxzZSB7XG4gICAgdmFyIGxlbiA9IGhhbmRsZXIubGVuZ3RoO1xuICAgIHZhciBsaXN0ZW5lcnMgPSBhcnJheUNsb25lKGhhbmRsZXIsIGxlbik7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW47ICsraSlcbiAgICAgIGxpc3RlbmVyc1tpXS5jYWxsKHNlbGYsIGFyZzEsIGFyZzIsIGFyZzMpO1xuICB9XG59XG5cbmZ1bmN0aW9uIGVtaXRNYW55KGhhbmRsZXIsIGlzRm4sIHNlbGYsIGFyZ3MpIHtcbiAgaWYgKGlzRm4pXG4gICAgaGFuZGxlci5hcHBseShzZWxmLCBhcmdzKTtcbiAgZWxzZSB7XG4gICAgdmFyIGxlbiA9IGhhbmRsZXIubGVuZ3RoO1xuICAgIHZhciBsaXN0ZW5lcnMgPSBhcnJheUNsb25lKGhhbmRsZXIsIGxlbik7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW47ICsraSlcbiAgICAgIGxpc3RlbmVyc1tpXS5hcHBseShzZWxmLCBhcmdzKTtcbiAgfVxufVxuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLmVtaXQgPSBmdW5jdGlvbiBlbWl0KHR5cGUpIHtcbiAgdmFyIGVyLCBoYW5kbGVyLCBsZW4sIGFyZ3MsIGksIGV2ZW50cztcbiAgdmFyIGRvRXJyb3IgPSAodHlwZSA9PT0gJ2Vycm9yJyk7XG5cbiAgZXZlbnRzID0gdGhpcy5fZXZlbnRzO1xuICBpZiAoZXZlbnRzKVxuICAgIGRvRXJyb3IgPSAoZG9FcnJvciAmJiBldmVudHMuZXJyb3IgPT0gbnVsbCk7XG4gIGVsc2UgaWYgKCFkb0Vycm9yKVxuICAgIHJldHVybiBmYWxzZTtcblxuICAvLyBJZiB0aGVyZSBpcyBubyAnZXJyb3InIGV2ZW50IGxpc3RlbmVyIHRoZW4gdGhyb3cuXG4gIGlmIChkb0Vycm9yKSB7XG4gICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPiAxKVxuICAgICAgZXIgPSBhcmd1bWVudHNbMV07XG4gICAgaWYgKGVyIGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICAgIHRocm93IGVyOyAvLyBVbmhhbmRsZWQgJ2Vycm9yJyBldmVudFxuICAgIH0gZWxzZSB7XG4gICAgICAvLyBBdCBsZWFzdCBnaXZlIHNvbWUga2luZCBvZiBjb250ZXh0IHRvIHRoZSB1c2VyXG4gICAgICB2YXIgZXJyID0gbmV3IEVycm9yKCdVbmhhbmRsZWQgXCJlcnJvclwiIGV2ZW50LiAoJyArIGVyICsgJyknKTtcbiAgICAgIGVyci5jb250ZXh0ID0gZXI7XG4gICAgICB0aHJvdyBlcnI7XG4gICAgfVxuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIGhhbmRsZXIgPSBldmVudHNbdHlwZV07XG5cbiAgaWYgKCFoYW5kbGVyKVxuICAgIHJldHVybiBmYWxzZTtcblxuICB2YXIgaXNGbiA9IHR5cGVvZiBoYW5kbGVyID09PSAnZnVuY3Rpb24nO1xuICBsZW4gPSBhcmd1bWVudHMubGVuZ3RoO1xuICBzd2l0Y2ggKGxlbikge1xuICAgICAgLy8gZmFzdCBjYXNlc1xuICAgIGNhc2UgMTpcbiAgICAgIGVtaXROb25lKGhhbmRsZXIsIGlzRm4sIHRoaXMpO1xuICAgICAgYnJlYWs7XG4gICAgY2FzZSAyOlxuICAgICAgZW1pdE9uZShoYW5kbGVyLCBpc0ZuLCB0aGlzLCBhcmd1bWVudHNbMV0pO1xuICAgICAgYnJlYWs7XG4gICAgY2FzZSAzOlxuICAgICAgZW1pdFR3byhoYW5kbGVyLCBpc0ZuLCB0aGlzLCBhcmd1bWVudHNbMV0sIGFyZ3VtZW50c1syXSk7XG4gICAgICBicmVhaztcbiAgICBjYXNlIDQ6XG4gICAgICBlbWl0VGhyZWUoaGFuZGxlciwgaXNGbiwgdGhpcywgYXJndW1lbnRzWzFdLCBhcmd1bWVudHNbMl0sIGFyZ3VtZW50c1szXSk7XG4gICAgICBicmVhaztcbiAgICAgIC8vIHNsb3dlclxuICAgIGRlZmF1bHQ6XG4gICAgICBhcmdzID0gbmV3IEFycmF5KGxlbiAtIDEpO1xuICAgICAgZm9yIChpID0gMTsgaSA8IGxlbjsgaSsrKVxuICAgICAgICBhcmdzW2kgLSAxXSA9IGFyZ3VtZW50c1tpXTtcbiAgICAgIGVtaXRNYW55KGhhbmRsZXIsIGlzRm4sIHRoaXMsIGFyZ3MpO1xuICB9XG5cbiAgcmV0dXJuIHRydWU7XG59O1xuXG5mdW5jdGlvbiBfYWRkTGlzdGVuZXIodGFyZ2V0LCB0eXBlLCBsaXN0ZW5lciwgcHJlcGVuZCkge1xuICB2YXIgbTtcbiAgdmFyIGV2ZW50cztcbiAgdmFyIGV4aXN0aW5nO1xuXG4gIGlmICh0eXBlb2YgbGlzdGVuZXIgIT09ICdmdW5jdGlvbicpXG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcignXCJsaXN0ZW5lclwiIGFyZ3VtZW50IG11c3QgYmUgYSBmdW5jdGlvbicpO1xuXG4gIGV2ZW50cyA9IHRhcmdldC5fZXZlbnRzO1xuICBpZiAoIWV2ZW50cykge1xuICAgIGV2ZW50cyA9IHRhcmdldC5fZXZlbnRzID0gb2JqZWN0Q3JlYXRlKG51bGwpO1xuICAgIHRhcmdldC5fZXZlbnRzQ291bnQgPSAwO1xuICB9IGVsc2Uge1xuICAgIC8vIFRvIGF2b2lkIHJlY3Vyc2lvbiBpbiB0aGUgY2FzZSB0aGF0IHR5cGUgPT09IFwibmV3TGlzdGVuZXJcIiEgQmVmb3JlXG4gICAgLy8gYWRkaW5nIGl0IHRvIHRoZSBsaXN0ZW5lcnMsIGZpcnN0IGVtaXQgXCJuZXdMaXN0ZW5lclwiLlxuICAgIGlmIChldmVudHMubmV3TGlzdGVuZXIpIHtcbiAgICAgIHRhcmdldC5lbWl0KCduZXdMaXN0ZW5lcicsIHR5cGUsXG4gICAgICAgICAgbGlzdGVuZXIubGlzdGVuZXIgPyBsaXN0ZW5lci5saXN0ZW5lciA6IGxpc3RlbmVyKTtcblxuICAgICAgLy8gUmUtYXNzaWduIGBldmVudHNgIGJlY2F1c2UgYSBuZXdMaXN0ZW5lciBoYW5kbGVyIGNvdWxkIGhhdmUgY2F1c2VkIHRoZVxuICAgICAgLy8gdGhpcy5fZXZlbnRzIHRvIGJlIGFzc2lnbmVkIHRvIGEgbmV3IG9iamVjdFxuICAgICAgZXZlbnRzID0gdGFyZ2V0Ll9ldmVudHM7XG4gICAgfVxuICAgIGV4aXN0aW5nID0gZXZlbnRzW3R5cGVdO1xuICB9XG5cbiAgaWYgKCFleGlzdGluZykge1xuICAgIC8vIE9wdGltaXplIHRoZSBjYXNlIG9mIG9uZSBsaXN0ZW5lci4gRG9uJ3QgbmVlZCB0aGUgZXh0cmEgYXJyYXkgb2JqZWN0LlxuICAgIGV4aXN0aW5nID0gZXZlbnRzW3R5cGVdID0gbGlzdGVuZXI7XG4gICAgKyt0YXJnZXQuX2V2ZW50c0NvdW50O1xuICB9IGVsc2Uge1xuICAgIGlmICh0eXBlb2YgZXhpc3RpbmcgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgIC8vIEFkZGluZyB0aGUgc2Vjb25kIGVsZW1lbnQsIG5lZWQgdG8gY2hhbmdlIHRvIGFycmF5LlxuICAgICAgZXhpc3RpbmcgPSBldmVudHNbdHlwZV0gPVxuICAgICAgICAgIHByZXBlbmQgPyBbbGlzdGVuZXIsIGV4aXN0aW5nXSA6IFtleGlzdGluZywgbGlzdGVuZXJdO1xuICAgIH0gZWxzZSB7XG4gICAgICAvLyBJZiB3ZSd2ZSBhbHJlYWR5IGdvdCBhbiBhcnJheSwganVzdCBhcHBlbmQuXG4gICAgICBpZiAocHJlcGVuZCkge1xuICAgICAgICBleGlzdGluZy51bnNoaWZ0KGxpc3RlbmVyKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGV4aXN0aW5nLnB1c2gobGlzdGVuZXIpO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIENoZWNrIGZvciBsaXN0ZW5lciBsZWFrXG4gICAgaWYgKCFleGlzdGluZy53YXJuZWQpIHtcbiAgICAgIG0gPSAkZ2V0TWF4TGlzdGVuZXJzKHRhcmdldCk7XG4gICAgICBpZiAobSAmJiBtID4gMCAmJiBleGlzdGluZy5sZW5ndGggPiBtKSB7XG4gICAgICAgIGV4aXN0aW5nLndhcm5lZCA9IHRydWU7XG4gICAgICAgIHZhciB3ID0gbmV3IEVycm9yKCdQb3NzaWJsZSBFdmVudEVtaXR0ZXIgbWVtb3J5IGxlYWsgZGV0ZWN0ZWQuICcgK1xuICAgICAgICAgICAgZXhpc3RpbmcubGVuZ3RoICsgJyBcIicgKyBTdHJpbmcodHlwZSkgKyAnXCIgbGlzdGVuZXJzICcgK1xuICAgICAgICAgICAgJ2FkZGVkLiBVc2UgZW1pdHRlci5zZXRNYXhMaXN0ZW5lcnMoKSB0byAnICtcbiAgICAgICAgICAgICdpbmNyZWFzZSBsaW1pdC4nKTtcbiAgICAgICAgdy5uYW1lID0gJ01heExpc3RlbmVyc0V4Y2VlZGVkV2FybmluZyc7XG4gICAgICAgIHcuZW1pdHRlciA9IHRhcmdldDtcbiAgICAgICAgdy50eXBlID0gdHlwZTtcbiAgICAgICAgdy5jb3VudCA9IGV4aXN0aW5nLmxlbmd0aDtcbiAgICAgICAgaWYgKHR5cGVvZiBjb25zb2xlID09PSAnb2JqZWN0JyAmJiBjb25zb2xlLndhcm4pIHtcbiAgICAgICAgICBjb25zb2xlLndhcm4oJyVzOiAlcycsIHcubmFtZSwgdy5tZXNzYWdlKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHJldHVybiB0YXJnZXQ7XG59XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUuYWRkTGlzdGVuZXIgPSBmdW5jdGlvbiBhZGRMaXN0ZW5lcih0eXBlLCBsaXN0ZW5lcikge1xuICByZXR1cm4gX2FkZExpc3RlbmVyKHRoaXMsIHR5cGUsIGxpc3RlbmVyLCBmYWxzZSk7XG59O1xuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLm9uID0gRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5hZGRMaXN0ZW5lcjtcblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5wcmVwZW5kTGlzdGVuZXIgPVxuICAgIGZ1bmN0aW9uIHByZXBlbmRMaXN0ZW5lcih0eXBlLCBsaXN0ZW5lcikge1xuICAgICAgcmV0dXJuIF9hZGRMaXN0ZW5lcih0aGlzLCB0eXBlLCBsaXN0ZW5lciwgdHJ1ZSk7XG4gICAgfTtcblxuZnVuY3Rpb24gb25jZVdyYXBwZXIoKSB7XG4gIGlmICghdGhpcy5maXJlZCkge1xuICAgIHRoaXMudGFyZ2V0LnJlbW92ZUxpc3RlbmVyKHRoaXMudHlwZSwgdGhpcy53cmFwRm4pO1xuICAgIHRoaXMuZmlyZWQgPSB0cnVlO1xuICAgIHN3aXRjaCAoYXJndW1lbnRzLmxlbmd0aCkge1xuICAgICAgY2FzZSAwOlxuICAgICAgICByZXR1cm4gdGhpcy5saXN0ZW5lci5jYWxsKHRoaXMudGFyZ2V0KTtcbiAgICAgIGNhc2UgMTpcbiAgICAgICAgcmV0dXJuIHRoaXMubGlzdGVuZXIuY2FsbCh0aGlzLnRhcmdldCwgYXJndW1lbnRzWzBdKTtcbiAgICAgIGNhc2UgMjpcbiAgICAgICAgcmV0dXJuIHRoaXMubGlzdGVuZXIuY2FsbCh0aGlzLnRhcmdldCwgYXJndW1lbnRzWzBdLCBhcmd1bWVudHNbMV0pO1xuICAgICAgY2FzZSAzOlxuICAgICAgICByZXR1cm4gdGhpcy5saXN0ZW5lci5jYWxsKHRoaXMudGFyZ2V0LCBhcmd1bWVudHNbMF0sIGFyZ3VtZW50c1sxXSxcbiAgICAgICAgICAgIGFyZ3VtZW50c1syXSk7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB2YXIgYXJncyA9IG5ldyBBcnJheShhcmd1bWVudHMubGVuZ3RoKTtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBhcmdzLmxlbmd0aDsgKytpKVxuICAgICAgICAgIGFyZ3NbaV0gPSBhcmd1bWVudHNbaV07XG4gICAgICAgIHRoaXMubGlzdGVuZXIuYXBwbHkodGhpcy50YXJnZXQsIGFyZ3MpO1xuICAgIH1cbiAgfVxufVxuXG5mdW5jdGlvbiBfb25jZVdyYXAodGFyZ2V0LCB0eXBlLCBsaXN0ZW5lcikge1xuICB2YXIgc3RhdGUgPSB7IGZpcmVkOiBmYWxzZSwgd3JhcEZuOiB1bmRlZmluZWQsIHRhcmdldDogdGFyZ2V0LCB0eXBlOiB0eXBlLCBsaXN0ZW5lcjogbGlzdGVuZXIgfTtcbiAgdmFyIHdyYXBwZWQgPSBiaW5kLmNhbGwob25jZVdyYXBwZXIsIHN0YXRlKTtcbiAgd3JhcHBlZC5saXN0ZW5lciA9IGxpc3RlbmVyO1xuICBzdGF0ZS53cmFwRm4gPSB3cmFwcGVkO1xuICByZXR1cm4gd3JhcHBlZDtcbn1cblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5vbmNlID0gZnVuY3Rpb24gb25jZSh0eXBlLCBsaXN0ZW5lcikge1xuICBpZiAodHlwZW9mIGxpc3RlbmVyICE9PSAnZnVuY3Rpb24nKVxuICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ1wibGlzdGVuZXJcIiBhcmd1bWVudCBtdXN0IGJlIGEgZnVuY3Rpb24nKTtcbiAgdGhpcy5vbih0eXBlLCBfb25jZVdyYXAodGhpcywgdHlwZSwgbGlzdGVuZXIpKTtcbiAgcmV0dXJuIHRoaXM7XG59O1xuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLnByZXBlbmRPbmNlTGlzdGVuZXIgPVxuICAgIGZ1bmN0aW9uIHByZXBlbmRPbmNlTGlzdGVuZXIodHlwZSwgbGlzdGVuZXIpIHtcbiAgICAgIGlmICh0eXBlb2YgbGlzdGVuZXIgIT09ICdmdW5jdGlvbicpXG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ1wibGlzdGVuZXJcIiBhcmd1bWVudCBtdXN0IGJlIGEgZnVuY3Rpb24nKTtcbiAgICAgIHRoaXMucHJlcGVuZExpc3RlbmVyKHR5cGUsIF9vbmNlV3JhcCh0aGlzLCB0eXBlLCBsaXN0ZW5lcikpO1xuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcblxuLy8gRW1pdHMgYSAncmVtb3ZlTGlzdGVuZXInIGV2ZW50IGlmIGFuZCBvbmx5IGlmIHRoZSBsaXN0ZW5lciB3YXMgcmVtb3ZlZC5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUucmVtb3ZlTGlzdGVuZXIgPVxuICAgIGZ1bmN0aW9uIHJlbW92ZUxpc3RlbmVyKHR5cGUsIGxpc3RlbmVyKSB7XG4gICAgICB2YXIgbGlzdCwgZXZlbnRzLCBwb3NpdGlvbiwgaSwgb3JpZ2luYWxMaXN0ZW5lcjtcblxuICAgICAgaWYgKHR5cGVvZiBsaXN0ZW5lciAhPT0gJ2Z1bmN0aW9uJylcbiAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignXCJsaXN0ZW5lclwiIGFyZ3VtZW50IG11c3QgYmUgYSBmdW5jdGlvbicpO1xuXG4gICAgICBldmVudHMgPSB0aGlzLl9ldmVudHM7XG4gICAgICBpZiAoIWV2ZW50cylcbiAgICAgICAgcmV0dXJuIHRoaXM7XG5cbiAgICAgIGxpc3QgPSBldmVudHNbdHlwZV07XG4gICAgICBpZiAoIWxpc3QpXG4gICAgICAgIHJldHVybiB0aGlzO1xuXG4gICAgICBpZiAobGlzdCA9PT0gbGlzdGVuZXIgfHwgbGlzdC5saXN0ZW5lciA9PT0gbGlzdGVuZXIpIHtcbiAgICAgICAgaWYgKC0tdGhpcy5fZXZlbnRzQ291bnQgPT09IDApXG4gICAgICAgICAgdGhpcy5fZXZlbnRzID0gb2JqZWN0Q3JlYXRlKG51bGwpO1xuICAgICAgICBlbHNlIHtcbiAgICAgICAgICBkZWxldGUgZXZlbnRzW3R5cGVdO1xuICAgICAgICAgIGlmIChldmVudHMucmVtb3ZlTGlzdGVuZXIpXG4gICAgICAgICAgICB0aGlzLmVtaXQoJ3JlbW92ZUxpc3RlbmVyJywgdHlwZSwgbGlzdC5saXN0ZW5lciB8fCBsaXN0ZW5lcik7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSBpZiAodHlwZW9mIGxpc3QgIT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgcG9zaXRpb24gPSAtMTtcblxuICAgICAgICBmb3IgKGkgPSBsaXN0Lmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgICAgICAgaWYgKGxpc3RbaV0gPT09IGxpc3RlbmVyIHx8IGxpc3RbaV0ubGlzdGVuZXIgPT09IGxpc3RlbmVyKSB7XG4gICAgICAgICAgICBvcmlnaW5hbExpc3RlbmVyID0gbGlzdFtpXS5saXN0ZW5lcjtcbiAgICAgICAgICAgIHBvc2l0aW9uID0gaTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChwb3NpdGlvbiA8IDApXG4gICAgICAgICAgcmV0dXJuIHRoaXM7XG5cbiAgICAgICAgaWYgKHBvc2l0aW9uID09PSAwKVxuICAgICAgICAgIGxpc3Quc2hpZnQoKTtcbiAgICAgICAgZWxzZVxuICAgICAgICAgIHNwbGljZU9uZShsaXN0LCBwb3NpdGlvbik7XG5cbiAgICAgICAgaWYgKGxpc3QubGVuZ3RoID09PSAxKVxuICAgICAgICAgIGV2ZW50c1t0eXBlXSA9IGxpc3RbMF07XG5cbiAgICAgICAgaWYgKGV2ZW50cy5yZW1vdmVMaXN0ZW5lcilcbiAgICAgICAgICB0aGlzLmVtaXQoJ3JlbW92ZUxpc3RlbmVyJywgdHlwZSwgb3JpZ2luYWxMaXN0ZW5lciB8fCBsaXN0ZW5lcik7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUucmVtb3ZlQWxsTGlzdGVuZXJzID1cbiAgICBmdW5jdGlvbiByZW1vdmVBbGxMaXN0ZW5lcnModHlwZSkge1xuICAgICAgdmFyIGxpc3RlbmVycywgZXZlbnRzLCBpO1xuXG4gICAgICBldmVudHMgPSB0aGlzLl9ldmVudHM7XG4gICAgICBpZiAoIWV2ZW50cylcbiAgICAgICAgcmV0dXJuIHRoaXM7XG5cbiAgICAgIC8vIG5vdCBsaXN0ZW5pbmcgZm9yIHJlbW92ZUxpc3RlbmVyLCBubyBuZWVkIHRvIGVtaXRcbiAgICAgIGlmICghZXZlbnRzLnJlbW92ZUxpc3RlbmVyKSB7XG4gICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgdGhpcy5fZXZlbnRzID0gb2JqZWN0Q3JlYXRlKG51bGwpO1xuICAgICAgICAgIHRoaXMuX2V2ZW50c0NvdW50ID0gMDtcbiAgICAgICAgfSBlbHNlIGlmIChldmVudHNbdHlwZV0pIHtcbiAgICAgICAgICBpZiAoLS10aGlzLl9ldmVudHNDb3VudCA9PT0gMClcbiAgICAgICAgICAgIHRoaXMuX2V2ZW50cyA9IG9iamVjdENyZWF0ZShudWxsKTtcbiAgICAgICAgICBlbHNlXG4gICAgICAgICAgICBkZWxldGUgZXZlbnRzW3R5cGVdO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgfVxuXG4gICAgICAvLyBlbWl0IHJlbW92ZUxpc3RlbmVyIGZvciBhbGwgbGlzdGVuZXJzIG9uIGFsbCBldmVudHNcbiAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgIHZhciBrZXlzID0gb2JqZWN0S2V5cyhldmVudHMpO1xuICAgICAgICB2YXIga2V5O1xuICAgICAgICBmb3IgKGkgPSAwOyBpIDwga2V5cy5sZW5ndGg7ICsraSkge1xuICAgICAgICAgIGtleSA9IGtleXNbaV07XG4gICAgICAgICAgaWYgKGtleSA9PT0gJ3JlbW92ZUxpc3RlbmVyJykgY29udGludWU7XG4gICAgICAgICAgdGhpcy5yZW1vdmVBbGxMaXN0ZW5lcnMoa2V5KTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnJlbW92ZUFsbExpc3RlbmVycygncmVtb3ZlTGlzdGVuZXInKTtcbiAgICAgICAgdGhpcy5fZXZlbnRzID0gb2JqZWN0Q3JlYXRlKG51bGwpO1xuICAgICAgICB0aGlzLl9ldmVudHNDb3VudCA9IDA7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgfVxuXG4gICAgICBsaXN0ZW5lcnMgPSBldmVudHNbdHlwZV07XG5cbiAgICAgIGlmICh0eXBlb2YgbGlzdGVuZXJzID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgIHRoaXMucmVtb3ZlTGlzdGVuZXIodHlwZSwgbGlzdGVuZXJzKTtcbiAgICAgIH0gZWxzZSBpZiAobGlzdGVuZXJzKSB7XG4gICAgICAgIC8vIExJRk8gb3JkZXJcbiAgICAgICAgZm9yIChpID0gbGlzdGVuZXJzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgICAgICAgdGhpcy5yZW1vdmVMaXN0ZW5lcih0eXBlLCBsaXN0ZW5lcnNbaV0pO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG5cbmZ1bmN0aW9uIF9saXN0ZW5lcnModGFyZ2V0LCB0eXBlLCB1bndyYXApIHtcbiAgdmFyIGV2ZW50cyA9IHRhcmdldC5fZXZlbnRzO1xuXG4gIGlmICghZXZlbnRzKVxuICAgIHJldHVybiBbXTtcblxuICB2YXIgZXZsaXN0ZW5lciA9IGV2ZW50c1t0eXBlXTtcbiAgaWYgKCFldmxpc3RlbmVyKVxuICAgIHJldHVybiBbXTtcblxuICBpZiAodHlwZW9mIGV2bGlzdGVuZXIgPT09ICdmdW5jdGlvbicpXG4gICAgcmV0dXJuIHVud3JhcCA/IFtldmxpc3RlbmVyLmxpc3RlbmVyIHx8IGV2bGlzdGVuZXJdIDogW2V2bGlzdGVuZXJdO1xuXG4gIHJldHVybiB1bndyYXAgPyB1bndyYXBMaXN0ZW5lcnMoZXZsaXN0ZW5lcikgOiBhcnJheUNsb25lKGV2bGlzdGVuZXIsIGV2bGlzdGVuZXIubGVuZ3RoKTtcbn1cblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5saXN0ZW5lcnMgPSBmdW5jdGlvbiBsaXN0ZW5lcnModHlwZSkge1xuICByZXR1cm4gX2xpc3RlbmVycyh0aGlzLCB0eXBlLCB0cnVlKTtcbn07XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUucmF3TGlzdGVuZXJzID0gZnVuY3Rpb24gcmF3TGlzdGVuZXJzKHR5cGUpIHtcbiAgcmV0dXJuIF9saXN0ZW5lcnModGhpcywgdHlwZSwgZmFsc2UpO1xufTtcblxuRXZlbnRFbWl0dGVyLmxpc3RlbmVyQ291bnQgPSBmdW5jdGlvbihlbWl0dGVyLCB0eXBlKSB7XG4gIGlmICh0eXBlb2YgZW1pdHRlci5saXN0ZW5lckNvdW50ID09PSAnZnVuY3Rpb24nKSB7XG4gICAgcmV0dXJuIGVtaXR0ZXIubGlzdGVuZXJDb3VudCh0eXBlKTtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gbGlzdGVuZXJDb3VudC5jYWxsKGVtaXR0ZXIsIHR5cGUpO1xuICB9XG59O1xuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLmxpc3RlbmVyQ291bnQgPSBsaXN0ZW5lckNvdW50O1xuZnVuY3Rpb24gbGlzdGVuZXJDb3VudCh0eXBlKSB7XG4gIHZhciBldmVudHMgPSB0aGlzLl9ldmVudHM7XG5cbiAgaWYgKGV2ZW50cykge1xuICAgIHZhciBldmxpc3RlbmVyID0gZXZlbnRzW3R5cGVdO1xuXG4gICAgaWYgKHR5cGVvZiBldmxpc3RlbmVyID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICByZXR1cm4gMTtcbiAgICB9IGVsc2UgaWYgKGV2bGlzdGVuZXIpIHtcbiAgICAgIHJldHVybiBldmxpc3RlbmVyLmxlbmd0aDtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gMDtcbn1cblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5ldmVudE5hbWVzID0gZnVuY3Rpb24gZXZlbnROYW1lcygpIHtcbiAgcmV0dXJuIHRoaXMuX2V2ZW50c0NvdW50ID4gMCA/IFJlZmxlY3Qub3duS2V5cyh0aGlzLl9ldmVudHMpIDogW107XG59O1xuXG4vLyBBYm91dCAxLjV4IGZhc3RlciB0aGFuIHRoZSB0d28tYXJnIHZlcnNpb24gb2YgQXJyYXkjc3BsaWNlKCkuXG5mdW5jdGlvbiBzcGxpY2VPbmUobGlzdCwgaW5kZXgpIHtcbiAgZm9yICh2YXIgaSA9IGluZGV4LCBrID0gaSArIDEsIG4gPSBsaXN0Lmxlbmd0aDsgayA8IG47IGkgKz0gMSwgayArPSAxKVxuICAgIGxpc3RbaV0gPSBsaXN0W2tdO1xuICBsaXN0LnBvcCgpO1xufVxuXG5mdW5jdGlvbiBhcnJheUNsb25lKGFyciwgbikge1xuICB2YXIgY29weSA9IG5ldyBBcnJheShuKTtcbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBuOyArK2kpXG4gICAgY29weVtpXSA9IGFycltpXTtcbiAgcmV0dXJuIGNvcHk7XG59XG5cbmZ1bmN0aW9uIHVud3JhcExpc3RlbmVycyhhcnIpIHtcbiAgdmFyIHJldCA9IG5ldyBBcnJheShhcnIubGVuZ3RoKTtcbiAgZm9yICh2YXIgaSA9IDA7IGkgPCByZXQubGVuZ3RoOyArK2kpIHtcbiAgICByZXRbaV0gPSBhcnJbaV0ubGlzdGVuZXIgfHwgYXJyW2ldO1xuICB9XG4gIHJldHVybiByZXQ7XG59XG5cbmZ1bmN0aW9uIG9iamVjdENyZWF0ZVBvbHlmaWxsKHByb3RvKSB7XG4gIHZhciBGID0gZnVuY3Rpb24oKSB7fTtcbiAgRi5wcm90b3R5cGUgPSBwcm90bztcbiAgcmV0dXJuIG5ldyBGO1xufVxuZnVuY3Rpb24gb2JqZWN0S2V5c1BvbHlmaWxsKG9iaikge1xuICB2YXIga2V5cyA9IFtdO1xuICBmb3IgKHZhciBrIGluIG9iaikgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChvYmosIGspKSB7XG4gICAga2V5cy5wdXNoKGspO1xuICB9XG4gIHJldHVybiBrO1xufVxuZnVuY3Rpb24gZnVuY3Rpb25CaW5kUG9seWZpbGwoY29udGV4dCkge1xuICB2YXIgZm4gPSB0aGlzO1xuICByZXR1cm4gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiBmbi5hcHBseShjb250ZXh0LCBhcmd1bWVudHMpO1xuICB9O1xufVxuIiwiLyoganNoaW50IG5vZGU6IHRydWUgKi9cbid1c2Ugc3RyaWN0JztcblxudmFyIG5vcm1hbGljZSA9IHJlcXVpcmUoJ25vcm1hbGljZScpO1xuXG4vKipcbiAgIyBmcmVlaWNlXG5cbiAgVGhlIGBmcmVlaWNlYCBtb2R1bGUgaXMgYSBzaW1wbGUgd2F5IG9mIGdldHRpbmcgcmFuZG9tIFNUVU4gb3IgVFVSTiBzZXJ2ZXJcbiAgZm9yIHlvdXIgV2ViUlRDIGFwcGxpY2F0aW9uLiAgVGhlIGxpc3Qgb2Ygc2VydmVycyAoanVzdCBTVFVOIGF0IHRoaXMgc3RhZ2UpXG4gIHdlcmUgc291cmNlZCBmcm9tIHRoaXMgW2dpc3RdKGh0dHBzOi8vZ2lzdC5naXRodWIuY29tL3p6aXVuaS8zNzQxOTMzKS5cblxuICAjIyBFeGFtcGxlIFVzZVxuXG4gIFRoZSBmb2xsb3dpbmcgZGVtb25zdHJhdGVzIGhvdyB5b3UgY2FuIHVzZSBgZnJlZWljZWAgd2l0aFxuICBbcnRjLXF1aWNrY29ubmVjdF0oaHR0cHM6Ly9naXRodWIuY29tL3J0Yy1pby9ydGMtcXVpY2tjb25uZWN0KTpcblxuICA8PDwgZXhhbXBsZXMvcXVpY2tjb25uZWN0LmpzXG5cbiAgQXMgdGhlIGBmcmVlaWNlYCBtb2R1bGUgZ2VuZXJhdGVzIGljZSBzZXJ2ZXJzIGluIGEgbGlzdCBjb21wbGlhbnQgd2l0aCB0aGVcbiAgV2ViUlRDIHNwZWMgeW91IHdpbGwgYmUgYWJsZSB0byB1c2UgaXQgd2l0aCByYXcgYFJUQ1BlZXJDb25uZWN0aW9uYFxuICBjb25zdHJ1Y3RvcnMgYW5kIG90aGVyIFdlYlJUQyBsaWJyYXJpZXMuXG5cbiAgIyMgSGV5LCBkb24ndCB1c2UgbXkgU1RVTi9UVVJOIHNlcnZlciFcblxuICBJZiBmb3Igc29tZSByZWFzb24geW91ciBmcmVlIFNUVU4gb3IgVFVSTiBzZXJ2ZXIgZW5kcyB1cCBpbiB0aGVcbiAgbGlzdCBvZiBzZXJ2ZXJzIChbc3R1bl0oaHR0cHM6Ly9naXRodWIuY29tL0RhbW9uT2VobG1hbi9mcmVlaWNlL2Jsb2IvbWFzdGVyL3N0dW4uanNvbikgb3JcbiAgW3R1cm5dKGh0dHBzOi8vZ2l0aHViLmNvbS9EYW1vbk9laGxtYW4vZnJlZWljZS9ibG9iL21hc3Rlci90dXJuLmpzb24pKVxuICB0aGF0IGlzIHVzZWQgaW4gdGhpcyBtb2R1bGUsIHlvdSBjYW4gZmVlbFxuICBmcmVlIHRvIG9wZW4gYW4gaXNzdWUgb24gdGhpcyByZXBvc2l0b3J5IGFuZCB0aG9zZSBzZXJ2ZXJzIHdpbGwgYmUgcmVtb3ZlZFxuICB3aXRoaW4gMjQgaG91cnMgKG9yIHNvb25lcikuICBUaGlzIGlzIHRoZSBxdWlja2VzdCBhbmQgcHJvYmFibHkgdGhlIG1vc3RcbiAgcG9saXRlIHdheSB0byBoYXZlIHNvbWV0aGluZyByZW1vdmVkIChhbmQgcHJvdmlkZXMgdXMgc29tZSB2aXNpYmlsaXR5XG4gIGlmIHNvbWVvbmUgb3BlbnMgYSBwdWxsIHJlcXVlc3QgcmVxdWVzdGluZyB0aGF0IGEgc2VydmVyIGlzIGFkZGVkKS5cblxuICAjIyBQbGVhc2UgYWRkIG15IHNlcnZlciFcblxuICBJZiB5b3UgaGF2ZSBhIHNlcnZlciB0aGF0IHlvdSB3aXNoIHRvIGFkZCB0byB0aGUgbGlzdCwgdGhhdCdzIGF3ZXNvbWUhIEknbVxuICBzdXJlIEkgc3BlYWsgb24gYmVoYWxmIG9mIGEgd2hvbGUgcGlsZSBvZiBXZWJSVEMgZGV2ZWxvcGVycyB3aG8gc2F5IHRoYW5rcy5cbiAgVG8gZ2V0IGl0IGludG8gdGhlIGxpc3QsIGZlZWwgZnJlZSB0byBlaXRoZXIgb3BlbiBhIHB1bGwgcmVxdWVzdCBvciBpZiB5b3VcbiAgZmluZCB0aGF0IHByb2Nlc3MgYSBiaXQgZGF1bnRpbmcgdGhlbiBqdXN0IGNyZWF0ZSBhbiBpc3N1ZSByZXF1ZXN0aW5nXG4gIHRoZSBhZGRpdGlvbiBvZiB0aGUgc2VydmVyIChtYWtlIHN1cmUgeW91IHByb3ZpZGUgYWxsIHRoZSBkZXRhaWxzLCBhbmQgaWZcbiAgeW91IGhhdmUgYSBUZXJtcyBvZiBTZXJ2aWNlIHRoZW4gaW5jbHVkaW5nIHRoYXQgaW4gdGhlIFBSL2lzc3VlIHdvdWxkIGJlXG4gIGF3ZXNvbWUpLlxuXG4gICMjIEkga25vdyBvZiBhIGZyZWUgc2VydmVyLCBjYW4gSSBhZGQgaXQ/XG5cbiAgU3VyZSwgaWYgeW91IGRvIHlvdXIgaG9tZXdvcmsgYW5kIG1ha2Ugc3VyZSBpdCBpcyBvayB0byB1c2UgKEknbSBjdXJyZW50bHlcbiAgaW4gdGhlIHByb2Nlc3Mgb2YgcmV2aWV3aW5nIHRoZSB0ZXJtcyBvZiB0aG9zZSBTVFVOIHNlcnZlcnMgaW5jbHVkZWQgZnJvbVxuICB0aGUgb3JpZ2luYWwgbGlzdCkuICBJZiBpdCdzIG9rIHRvIGdvLCB0aGVuIHBsZWFzZSBzZWUgdGhlIHByZXZpb3VzIGVudHJ5XG4gIGZvciBob3cgdG8gYWRkIGl0LlxuXG4gICMjIEN1cnJlbnQgTGlzdCBvZiBTZXJ2ZXJzXG5cbiAgKiBjdXJyZW50IGFzIGF0IHRoZSB0aW1lIG9mIGxhc3QgYFJFQURNRS5tZGAgZmlsZSBnZW5lcmF0aW9uXG5cbiAgIyMjIFNUVU5cblxuICA8PDwgc3R1bi5qc29uXG5cbiAgIyMjIFRVUk5cblxuICA8PDwgdHVybi5qc29uXG5cbioqL1xuXG52YXIgZnJlZWljZSA9IG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24ob3B0cykge1xuICAvLyBpZiBhIGxpc3Qgb2Ygc2VydmVycyBoYXMgYmVlbiBwcm92aWRlZCwgdGhlbiB1c2UgaXQgaW5zdGVhZCBvZiBkZWZhdWx0c1xuICB2YXIgc2VydmVycyA9IHtcbiAgICBzdHVuOiAob3B0cyB8fCB7fSkuc3R1biB8fCByZXF1aXJlKCcuL3N0dW4uanNvbicpLFxuICAgIHR1cm46IChvcHRzIHx8IHt9KS50dXJuIHx8IHJlcXVpcmUoJy4vdHVybi5qc29uJylcbiAgfTtcblxuICB2YXIgc3R1bkNvdW50ID0gKG9wdHMgfHwge30pLnN0dW5Db3VudCB8fCAyO1xuICB2YXIgdHVybkNvdW50ID0gKG9wdHMgfHwge30pLnR1cm5Db3VudCB8fCAwO1xuICB2YXIgc2VsZWN0ZWQ7XG5cbiAgZnVuY3Rpb24gZ2V0U2VydmVycyh0eXBlLCBjb3VudCkge1xuICAgIHZhciBvdXQgPSBbXTtcbiAgICB2YXIgaW5wdXQgPSBbXS5jb25jYXQoc2VydmVyc1t0eXBlXSk7XG4gICAgdmFyIGlkeDtcblxuICAgIHdoaWxlIChpbnB1dC5sZW5ndGggJiYgb3V0Lmxlbmd0aCA8IGNvdW50KSB7XG4gICAgICBpZHggPSAoTWF0aC5yYW5kb20oKSAqIGlucHV0Lmxlbmd0aCkgfCAwO1xuICAgICAgb3V0ID0gb3V0LmNvbmNhdChpbnB1dC5zcGxpY2UoaWR4LCAxKSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIG91dC5tYXAoZnVuY3Rpb24odXJsKSB7XG4gICAgICAgIC8vSWYgaXQncyBhIG5vdCBhIHN0cmluZywgZG9uJ3QgdHJ5IHRvIFwibm9ybWFsaWNlXCIgaXQgb3RoZXJ3aXNlIHVzaW5nIHR5cGU6dXJsIHdpbGwgc2NyZXcgaXQgdXBcbiAgICAgICAgaWYgKCh0eXBlb2YgdXJsICE9PSAnc3RyaW5nJykgJiYgKCEgKHVybCBpbnN0YW5jZW9mIFN0cmluZykpKSB7XG4gICAgICAgICAgICByZXR1cm4gdXJsO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIG5vcm1hbGljZSh0eXBlICsgJzonICsgdXJsKTtcbiAgICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgLy8gYWRkIHN0dW4gc2VydmVyc1xuICBzZWxlY3RlZCA9IFtdLmNvbmNhdChnZXRTZXJ2ZXJzKCdzdHVuJywgc3R1bkNvdW50KSk7XG5cbiAgaWYgKHR1cm5Db3VudCkge1xuICAgIHNlbGVjdGVkID0gc2VsZWN0ZWQuY29uY2F0KGdldFNlcnZlcnMoJ3R1cm4nLCB0dXJuQ291bnQpKTtcbiAgfVxuXG4gIHJldHVybiBzZWxlY3RlZDtcbn07XG4iLCJtb2R1bGUuZXhwb3J0cz1bXG4gIFwic3R1bi5sLmdvb2dsZS5jb206MTkzMDJcIixcbiAgXCJzdHVuMS5sLmdvb2dsZS5jb206MTkzMDJcIixcbiAgXCJzdHVuMi5sLmdvb2dsZS5jb206MTkzMDJcIixcbiAgXCJzdHVuMy5sLmdvb2dsZS5jb206MTkzMDJcIixcbiAgXCJzdHVuNC5sLmdvb2dsZS5jb206MTkzMDJcIixcbiAgXCJzdHVuLmVraWdhLm5ldFwiLFxuICBcInN0dW4uaWRlYXNpcC5jb21cIixcbiAgXCJzdHVuLnNjaGx1bmQuZGVcIixcbiAgXCJzdHVuLnN0dW5wcm90b2NvbC5vcmc6MzQ3OFwiLFxuICBcInN0dW4udm9pcGFyb3VuZC5jb21cIixcbiAgXCJzdHVuLnZvaXBidXN0ZXIuY29tXCIsXG4gIFwic3R1bi52b2lwc3R1bnQuY29tXCIsXG4gIFwic3R1bi52b3hncmF0aWEub3JnXCIsXG4gIFwic3R1bi5zZXJ2aWNlcy5tb3ppbGxhLmNvbVwiXG5dXG4iLCJtb2R1bGUuZXhwb3J0cz1bXVxuIiwidmFyIFdpbGRFbWl0dGVyID0gcmVxdWlyZSgnd2lsZGVtaXR0ZXInKTtcblxuZnVuY3Rpb24gZ2V0TWF4Vm9sdW1lIChhbmFseXNlciwgZmZ0Qmlucykge1xuICB2YXIgbWF4Vm9sdW1lID0gLUluZmluaXR5O1xuICBhbmFseXNlci5nZXRGbG9hdEZyZXF1ZW5jeURhdGEoZmZ0Qmlucyk7XG5cbiAgZm9yKHZhciBpPTQsIGlpPWZmdEJpbnMubGVuZ3RoOyBpIDwgaWk7IGkrKykge1xuICAgIGlmIChmZnRCaW5zW2ldID4gbWF4Vm9sdW1lICYmIGZmdEJpbnNbaV0gPCAwKSB7XG4gICAgICBtYXhWb2x1bWUgPSBmZnRCaW5zW2ldO1xuICAgIH1cbiAgfTtcblxuICByZXR1cm4gbWF4Vm9sdW1lO1xufVxuXG5cbnZhciBhdWRpb0NvbnRleHRUeXBlO1xuaWYgKHR5cGVvZiB3aW5kb3cgIT09ICd1bmRlZmluZWQnKSB7XG4gIGF1ZGlvQ29udGV4dFR5cGUgPSB3aW5kb3cuQXVkaW9Db250ZXh0IHx8IHdpbmRvdy53ZWJraXRBdWRpb0NvbnRleHQ7XG59XG4vLyB1c2UgYSBzaW5nbGUgYXVkaW8gY29udGV4dCBkdWUgdG8gaGFyZHdhcmUgbGltaXRzXG52YXIgYXVkaW9Db250ZXh0ID0gbnVsbDtcbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24oc3RyZWFtLCBvcHRpb25zKSB7XG4gIHZhciBoYXJrZXIgPSBuZXcgV2lsZEVtaXR0ZXIoKTtcblxuXG4gIC8vIG1ha2UgaXQgbm90IGJyZWFrIGluIG5vbi1zdXBwb3J0ZWQgYnJvd3NlcnNcbiAgaWYgKCFhdWRpb0NvbnRleHRUeXBlKSByZXR1cm4gaGFya2VyO1xuXG4gIC8vQ29uZmlnXG4gIHZhciBvcHRpb25zID0gb3B0aW9ucyB8fCB7fSxcbiAgICAgIHNtb290aGluZyA9IChvcHRpb25zLnNtb290aGluZyB8fCAwLjEpLFxuICAgICAgaW50ZXJ2YWwgPSAob3B0aW9ucy5pbnRlcnZhbCB8fCA1MCksXG4gICAgICB0aHJlc2hvbGQgPSBvcHRpb25zLnRocmVzaG9sZCxcbiAgICAgIHBsYXkgPSBvcHRpb25zLnBsYXksXG4gICAgICBoaXN0b3J5ID0gb3B0aW9ucy5oaXN0b3J5IHx8IDEwLFxuICAgICAgcnVubmluZyA9IHRydWU7XG5cbiAgLy9TZXR1cCBBdWRpbyBDb250ZXh0XG4gIGlmICghYXVkaW9Db250ZXh0KSB7XG4gICAgYXVkaW9Db250ZXh0ID0gbmV3IGF1ZGlvQ29udGV4dFR5cGUoKTtcbiAgfVxuICB2YXIgc291cmNlTm9kZSwgZmZ0QmlucywgYW5hbHlzZXI7XG5cbiAgYW5hbHlzZXIgPSBhdWRpb0NvbnRleHQuY3JlYXRlQW5hbHlzZXIoKTtcbiAgYW5hbHlzZXIuZmZ0U2l6ZSA9IDUxMjtcbiAgYW5hbHlzZXIuc21vb3RoaW5nVGltZUNvbnN0YW50ID0gc21vb3RoaW5nO1xuICBmZnRCaW5zID0gbmV3IEZsb2F0MzJBcnJheShhbmFseXNlci5mcmVxdWVuY3lCaW5Db3VudCk7XG5cbiAgaWYgKHN0cmVhbS5qcXVlcnkpIHN0cmVhbSA9IHN0cmVhbVswXTtcbiAgaWYgKHN0cmVhbSBpbnN0YW5jZW9mIEhUTUxBdWRpb0VsZW1lbnQgfHwgc3RyZWFtIGluc3RhbmNlb2YgSFRNTFZpZGVvRWxlbWVudCkge1xuICAgIC8vQXVkaW8gVGFnXG4gICAgc291cmNlTm9kZSA9IGF1ZGlvQ29udGV4dC5jcmVhdGVNZWRpYUVsZW1lbnRTb3VyY2Uoc3RyZWFtKTtcbiAgICBpZiAodHlwZW9mIHBsYXkgPT09ICd1bmRlZmluZWQnKSBwbGF5ID0gdHJ1ZTtcbiAgICB0aHJlc2hvbGQgPSB0aHJlc2hvbGQgfHwgLTUwO1xuICB9IGVsc2Uge1xuICAgIC8vV2ViUlRDIFN0cmVhbVxuICAgIHNvdXJjZU5vZGUgPSBhdWRpb0NvbnRleHQuY3JlYXRlTWVkaWFTdHJlYW1Tb3VyY2Uoc3RyZWFtKTtcbiAgICB0aHJlc2hvbGQgPSB0aHJlc2hvbGQgfHwgLTUwO1xuICB9XG5cbiAgc291cmNlTm9kZS5jb25uZWN0KGFuYWx5c2VyKTtcbiAgaWYgKHBsYXkpIGFuYWx5c2VyLmNvbm5lY3QoYXVkaW9Db250ZXh0LmRlc3RpbmF0aW9uKTtcblxuICBoYXJrZXIuc3BlYWtpbmcgPSBmYWxzZTtcblxuICBoYXJrZXIuc3VzcGVuZCA9IGZ1bmN0aW9uKCkge1xuICAgIGF1ZGlvQ29udGV4dC5zdXNwZW5kKCk7XG4gIH1cbiAgaGFya2VyLnJlc3VtZSA9IGZ1bmN0aW9uKCkge1xuICAgIGF1ZGlvQ29udGV4dC5yZXN1bWUoKTtcbiAgfVxuICBPYmplY3QuZGVmaW5lUHJvcGVydHkoaGFya2VyLCAnc3RhdGUnLCB7IGdldDogZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIGF1ZGlvQ29udGV4dC5zdGF0ZTtcbiAgfX0pO1xuICBhdWRpb0NvbnRleHQub25zdGF0ZWNoYW5nZSA9IGZ1bmN0aW9uKCkge1xuICAgIGhhcmtlci5lbWl0KCdzdGF0ZV9jaGFuZ2UnLCBhdWRpb0NvbnRleHQuc3RhdGUpO1xuICB9XG5cbiAgaGFya2VyLnNldFRocmVzaG9sZCA9IGZ1bmN0aW9uKHQpIHtcbiAgICB0aHJlc2hvbGQgPSB0O1xuICB9O1xuXG4gIGhhcmtlci5zZXRJbnRlcnZhbCA9IGZ1bmN0aW9uKGkpIHtcbiAgICBpbnRlcnZhbCA9IGk7XG4gIH07XG5cbiAgaGFya2VyLnN0b3AgPSBmdW5jdGlvbigpIHtcbiAgICBydW5uaW5nID0gZmFsc2U7XG4gICAgaGFya2VyLmVtaXQoJ3ZvbHVtZV9jaGFuZ2UnLCAtMTAwLCB0aHJlc2hvbGQpO1xuICAgIGlmIChoYXJrZXIuc3BlYWtpbmcpIHtcbiAgICAgIGhhcmtlci5zcGVha2luZyA9IGZhbHNlO1xuICAgICAgaGFya2VyLmVtaXQoJ3N0b3BwZWRfc3BlYWtpbmcnKTtcbiAgICB9XG4gICAgYW5hbHlzZXIuZGlzY29ubmVjdCgpO1xuICAgIHNvdXJjZU5vZGUuZGlzY29ubmVjdCgpO1xuICB9O1xuICBoYXJrZXIuc3BlYWtpbmdIaXN0b3J5ID0gW107XG4gIGZvciAodmFyIGkgPSAwOyBpIDwgaGlzdG9yeTsgaSsrKSB7XG4gICAgICBoYXJrZXIuc3BlYWtpbmdIaXN0b3J5LnB1c2goMCk7XG4gIH1cblxuICAvLyBQb2xsIHRoZSBhbmFseXNlciBub2RlIHRvIGRldGVybWluZSBpZiBzcGVha2luZ1xuICAvLyBhbmQgZW1pdCBldmVudHMgaWYgY2hhbmdlZFxuICB2YXIgbG9vcGVyID0gZnVuY3Rpb24oKSB7XG4gICAgc2V0VGltZW91dChmdW5jdGlvbigpIHtcblxuICAgICAgLy9jaGVjayBpZiBzdG9wIGhhcyBiZWVuIGNhbGxlZFxuICAgICAgaWYoIXJ1bm5pbmcpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICB2YXIgY3VycmVudFZvbHVtZSA9IGdldE1heFZvbHVtZShhbmFseXNlciwgZmZ0Qmlucyk7XG5cbiAgICAgIGhhcmtlci5lbWl0KCd2b2x1bWVfY2hhbmdlJywgY3VycmVudFZvbHVtZSwgdGhyZXNob2xkKTtcblxuICAgICAgdmFyIGhpc3RvcnkgPSAwO1xuICAgICAgaWYgKGN1cnJlbnRWb2x1bWUgPiB0aHJlc2hvbGQgJiYgIWhhcmtlci5zcGVha2luZykge1xuICAgICAgICAvLyB0cmlnZ2VyIHF1aWNrbHksIHNob3J0IGhpc3RvcnlcbiAgICAgICAgZm9yICh2YXIgaSA9IGhhcmtlci5zcGVha2luZ0hpc3RvcnkubGVuZ3RoIC0gMzsgaSA8IGhhcmtlci5zcGVha2luZ0hpc3RvcnkubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICBoaXN0b3J5ICs9IGhhcmtlci5zcGVha2luZ0hpc3RvcnlbaV07XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGhpc3RvcnkgPj0gMikge1xuICAgICAgICAgIGhhcmtlci5zcGVha2luZyA9IHRydWU7XG4gICAgICAgICAgaGFya2VyLmVtaXQoJ3NwZWFraW5nJyk7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSBpZiAoY3VycmVudFZvbHVtZSA8IHRocmVzaG9sZCAmJiBoYXJrZXIuc3BlYWtpbmcpIHtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBoYXJrZXIuc3BlYWtpbmdIaXN0b3J5Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgaGlzdG9yeSArPSBoYXJrZXIuc3BlYWtpbmdIaXN0b3J5W2ldO1xuICAgICAgICB9XG4gICAgICAgIGlmIChoaXN0b3J5ID09IDApIHtcbiAgICAgICAgICBoYXJrZXIuc3BlYWtpbmcgPSBmYWxzZTtcbiAgICAgICAgICBoYXJrZXIuZW1pdCgnc3RvcHBlZF9zcGVha2luZycpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBoYXJrZXIuc3BlYWtpbmdIaXN0b3J5LnNoaWZ0KCk7XG4gICAgICBoYXJrZXIuc3BlYWtpbmdIaXN0b3J5LnB1c2goMCArIChjdXJyZW50Vm9sdW1lID4gdGhyZXNob2xkKSk7XG5cbiAgICAgIGxvb3BlcigpO1xuICAgIH0sIGludGVydmFsKTtcbiAgfTtcbiAgbG9vcGVyKCk7XG5cblxuICByZXR1cm4gaGFya2VyO1xufVxuIiwiaWYgKHR5cGVvZiBPYmplY3QuY3JlYXRlID09PSAnZnVuY3Rpb24nKSB7XG4gIC8vIGltcGxlbWVudGF0aW9uIGZyb20gc3RhbmRhcmQgbm9kZS5qcyAndXRpbCcgbW9kdWxlXG4gIG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gaW5oZXJpdHMoY3Rvciwgc3VwZXJDdG9yKSB7XG4gICAgY3Rvci5zdXBlcl8gPSBzdXBlckN0b3JcbiAgICBjdG9yLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoc3VwZXJDdG9yLnByb3RvdHlwZSwge1xuICAgICAgY29uc3RydWN0b3I6IHtcbiAgICAgICAgdmFsdWU6IGN0b3IsXG4gICAgICAgIGVudW1lcmFibGU6IGZhbHNlLFxuICAgICAgICB3cml0YWJsZTogdHJ1ZSxcbiAgICAgICAgY29uZmlndXJhYmxlOiB0cnVlXG4gICAgICB9XG4gICAgfSk7XG4gIH07XG59IGVsc2Uge1xuICAvLyBvbGQgc2Nob29sIHNoaW0gZm9yIG9sZCBicm93c2Vyc1xuICBtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGluaGVyaXRzKGN0b3IsIHN1cGVyQ3Rvcikge1xuICAgIGN0b3Iuc3VwZXJfID0gc3VwZXJDdG9yXG4gICAgdmFyIFRlbXBDdG9yID0gZnVuY3Rpb24gKCkge31cbiAgICBUZW1wQ3Rvci5wcm90b3R5cGUgPSBzdXBlckN0b3IucHJvdG90eXBlXG4gICAgY3Rvci5wcm90b3R5cGUgPSBuZXcgVGVtcEN0b3IoKVxuICAgIGN0b3IucHJvdG90eXBlLmNvbnN0cnVjdG9yID0gY3RvclxuICB9XG59XG4iLCIvKipcbiAgIyBub3JtYWxpY2VcblxuICBOb3JtYWxpemUgYW4gaWNlIHNlcnZlciBjb25maWd1cmF0aW9uIG9iamVjdCAob3IgcGxhaW4gb2xkIHN0cmluZykgaW50byBhIGZvcm1hdFxuICB0aGF0IGlzIHVzYWJsZSBpbiBhbGwgYnJvd3NlcnMgc3VwcG9ydGluZyBXZWJSVEMuICBQcmltYXJpbHkgdGhpcyBtb2R1bGUgaXMgZGVzaWduZWRcbiAgdG8gaGVscCB3aXRoIHRoZSB0cmFuc2l0aW9uIG9mIHRoZSBgdXJsYCBhdHRyaWJ1dGUgb2YgdGhlIGNvbmZpZ3VyYXRpb24gb2JqZWN0IHRvXG4gIHRoZSBgdXJsc2AgYXR0cmlidXRlLlxuXG4gICMjIEV4YW1wbGUgVXNhZ2VcblxuICA8PDwgZXhhbXBsZXMvc2ltcGxlLmpzXG5cbioqL1xuXG52YXIgcHJvdG9jb2xzID0gW1xuICAnc3R1bjonLFxuICAndHVybjonXG5dO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKGlucHV0KSB7XG4gIHZhciB1cmwgPSAoaW5wdXQgfHwge30pLnVybCB8fCBpbnB1dDtcbiAgdmFyIHByb3RvY29sO1xuICB2YXIgcGFydHM7XG4gIHZhciBvdXRwdXQgPSB7fTtcblxuICAvLyBpZiB3ZSBkb24ndCBoYXZlIGEgc3RyaW5nIHVybCwgdGhlbiBhbGxvdyB0aGUgaW5wdXQgdG8gcGFzc3Rocm91Z2hcbiAgaWYgKHR5cGVvZiB1cmwgIT0gJ3N0cmluZycgJiYgKCEgKHVybCBpbnN0YW5jZW9mIFN0cmluZykpKSB7XG4gICAgcmV0dXJuIGlucHV0O1xuICB9XG5cbiAgLy8gdHJpbSB0aGUgdXJsIHN0cmluZywgYW5kIGNvbnZlcnQgdG8gYW4gYXJyYXlcbiAgdXJsID0gdXJsLnRyaW0oKTtcblxuICAvLyBpZiB0aGUgcHJvdG9jb2wgaXMgbm90IGtub3duLCB0aGVuIHBhc3N0aHJvdWdoXG4gIHByb3RvY29sID0gcHJvdG9jb2xzW3Byb3RvY29scy5pbmRleE9mKHVybC5zbGljZSgwLCA1KSldO1xuICBpZiAoISBwcm90b2NvbCkge1xuICAgIHJldHVybiBpbnB1dDtcbiAgfVxuXG4gIC8vIG5vdyBsZXQncyBhdHRhY2sgdGhlIHJlbWFpbmluZyB1cmwgcGFydHNcbiAgdXJsID0gdXJsLnNsaWNlKDUpO1xuICBwYXJ0cyA9IHVybC5zcGxpdCgnQCcpO1xuXG4gIG91dHB1dC51c2VybmFtZSA9IGlucHV0LnVzZXJuYW1lO1xuICBvdXRwdXQuY3JlZGVudGlhbCA9IGlucHV0LmNyZWRlbnRpYWw7XG4gIC8vIGlmIHdlIGhhdmUgYW4gYXV0aGVudGljYXRpb24gcGFydCwgdGhlbiBzZXQgdGhlIGNyZWRlbnRpYWxzXG4gIGlmIChwYXJ0cy5sZW5ndGggPiAxKSB7XG4gICAgdXJsID0gcGFydHNbMV07XG4gICAgcGFydHMgPSBwYXJ0c1swXS5zcGxpdCgnOicpO1xuXG4gICAgLy8gYWRkIHRoZSBvdXRwdXQgY3JlZGVudGlhbCBhbmQgdXNlcm5hbWVcbiAgICBvdXRwdXQudXNlcm5hbWUgPSBwYXJ0c1swXTtcbiAgICBvdXRwdXQuY3JlZGVudGlhbCA9IChpbnB1dCB8fCB7fSkuY3JlZGVudGlhbCB8fCBwYXJ0c1sxXSB8fCAnJztcbiAgfVxuXG4gIG91dHB1dC51cmwgPSBwcm90b2NvbCArIHVybDtcbiAgb3V0cHV0LnVybHMgPSBbIG91dHB1dC51cmwgXTtcblxuICByZXR1cm4gb3V0cHV0O1xufTtcbiIsIi8qIVxuICogUGxhdGZvcm0uanMgPGh0dHBzOi8vbXRocy5iZS9wbGF0Zm9ybT5cbiAqIENvcHlyaWdodCAyMDE0LTIwMTggQmVuamFtaW4gVGFuIDxodHRwczovL2Juam1udDRuLm5vdy5zaC8+XG4gKiBDb3B5cmlnaHQgMjAxMS0yMDEzIEpvaG4tRGF2aWQgRGFsdG9uIDxodHRwOi8vYWxseW91Y2FubGVldC5jb20vPlxuICogQXZhaWxhYmxlIHVuZGVyIE1JVCBsaWNlbnNlIDxodHRwczovL210aHMuYmUvbWl0PlxuICovXG47KGZ1bmN0aW9uKCkge1xuICAndXNlIHN0cmljdCc7XG5cbiAgLyoqIFVzZWQgdG8gZGV0ZXJtaW5lIGlmIHZhbHVlcyBhcmUgb2YgdGhlIGxhbmd1YWdlIHR5cGUgYE9iamVjdGAuICovXG4gIHZhciBvYmplY3RUeXBlcyA9IHtcbiAgICAnZnVuY3Rpb24nOiB0cnVlLFxuICAgICdvYmplY3QnOiB0cnVlXG4gIH07XG5cbiAgLyoqIFVzZWQgYXMgYSByZWZlcmVuY2UgdG8gdGhlIGdsb2JhbCBvYmplY3QuICovXG4gIHZhciByb290ID0gKG9iamVjdFR5cGVzW3R5cGVvZiB3aW5kb3ddICYmIHdpbmRvdykgfHwgdGhpcztcblxuICAvKiogQmFja3VwIHBvc3NpYmxlIGdsb2JhbCBvYmplY3QuICovXG4gIHZhciBvbGRSb290ID0gcm9vdDtcblxuICAvKiogRGV0ZWN0IGZyZWUgdmFyaWFibGUgYGV4cG9ydHNgLiAqL1xuICB2YXIgZnJlZUV4cG9ydHMgPSBvYmplY3RUeXBlc1t0eXBlb2YgZXhwb3J0c10gJiYgZXhwb3J0cztcblxuICAvKiogRGV0ZWN0IGZyZWUgdmFyaWFibGUgYG1vZHVsZWAuICovXG4gIHZhciBmcmVlTW9kdWxlID0gb2JqZWN0VHlwZXNbdHlwZW9mIG1vZHVsZV0gJiYgbW9kdWxlICYmICFtb2R1bGUubm9kZVR5cGUgJiYgbW9kdWxlO1xuXG4gIC8qKiBEZXRlY3QgZnJlZSB2YXJpYWJsZSBgZ2xvYmFsYCBmcm9tIE5vZGUuanMgb3IgQnJvd3NlcmlmaWVkIGNvZGUgYW5kIHVzZSBpdCBhcyBgcm9vdGAuICovXG4gIHZhciBmcmVlR2xvYmFsID0gZnJlZUV4cG9ydHMgJiYgZnJlZU1vZHVsZSAmJiB0eXBlb2YgZ2xvYmFsID09ICdvYmplY3QnICYmIGdsb2JhbDtcbiAgaWYgKGZyZWVHbG9iYWwgJiYgKGZyZWVHbG9iYWwuZ2xvYmFsID09PSBmcmVlR2xvYmFsIHx8IGZyZWVHbG9iYWwud2luZG93ID09PSBmcmVlR2xvYmFsIHx8IGZyZWVHbG9iYWwuc2VsZiA9PT0gZnJlZUdsb2JhbCkpIHtcbiAgICByb290ID0gZnJlZUdsb2JhbDtcbiAgfVxuXG4gIC8qKlxuICAgKiBVc2VkIGFzIHRoZSBtYXhpbXVtIGxlbmd0aCBvZiBhbiBhcnJheS1saWtlIG9iamVjdC5cbiAgICogU2VlIHRoZSBbRVM2IHNwZWNdKGh0dHA6Ly9wZW9wbGUubW96aWxsYS5vcmcvfmpvcmVuZG9yZmYvZXM2LWRyYWZ0Lmh0bWwjc2VjLXRvbGVuZ3RoKVxuICAgKiBmb3IgbW9yZSBkZXRhaWxzLlxuICAgKi9cbiAgdmFyIG1heFNhZmVJbnRlZ2VyID0gTWF0aC5wb3coMiwgNTMpIC0gMTtcblxuICAvKiogUmVndWxhciBleHByZXNzaW9uIHRvIGRldGVjdCBPcGVyYS4gKi9cbiAgdmFyIHJlT3BlcmEgPSAvXFxiT3BlcmEvO1xuXG4gIC8qKiBQb3NzaWJsZSBnbG9iYWwgb2JqZWN0LiAqL1xuICB2YXIgdGhpc0JpbmRpbmcgPSB0aGlzO1xuXG4gIC8qKiBVc2VkIGZvciBuYXRpdmUgbWV0aG9kIHJlZmVyZW5jZXMuICovXG4gIHZhciBvYmplY3RQcm90byA9IE9iamVjdC5wcm90b3R5cGU7XG5cbiAgLyoqIFVzZWQgdG8gY2hlY2sgZm9yIG93biBwcm9wZXJ0aWVzIG9mIGFuIG9iamVjdC4gKi9cbiAgdmFyIGhhc093blByb3BlcnR5ID0gb2JqZWN0UHJvdG8uaGFzT3duUHJvcGVydHk7XG5cbiAgLyoqIFVzZWQgdG8gcmVzb2x2ZSB0aGUgaW50ZXJuYWwgYFtbQ2xhc3NdXWAgb2YgdmFsdWVzLiAqL1xuICB2YXIgdG9TdHJpbmcgPSBvYmplY3RQcm90by50b1N0cmluZztcblxuICAvKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cblxuICAvKipcbiAgICogQ2FwaXRhbGl6ZXMgYSBzdHJpbmcgdmFsdWUuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBzdHJpbmcgVGhlIHN0cmluZyB0byBjYXBpdGFsaXplLlxuICAgKiBAcmV0dXJucyB7c3RyaW5nfSBUaGUgY2FwaXRhbGl6ZWQgc3RyaW5nLlxuICAgKi9cbiAgZnVuY3Rpb24gY2FwaXRhbGl6ZShzdHJpbmcpIHtcbiAgICBzdHJpbmcgPSBTdHJpbmcoc3RyaW5nKTtcbiAgICByZXR1cm4gc3RyaW5nLmNoYXJBdCgwKS50b1VwcGVyQ2FzZSgpICsgc3RyaW5nLnNsaWNlKDEpO1xuICB9XG5cbiAgLyoqXG4gICAqIEEgdXRpbGl0eSBmdW5jdGlvbiB0byBjbGVhbiB1cCB0aGUgT1MgbmFtZS5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtzdHJpbmd9IG9zIFRoZSBPUyBuYW1lIHRvIGNsZWFuIHVwLlxuICAgKiBAcGFyYW0ge3N0cmluZ30gW3BhdHRlcm5dIEEgYFJlZ0V4cGAgcGF0dGVybiBtYXRjaGluZyB0aGUgT1MgbmFtZS5cbiAgICogQHBhcmFtIHtzdHJpbmd9IFtsYWJlbF0gQSBsYWJlbCBmb3IgdGhlIE9TLlxuICAgKi9cbiAgZnVuY3Rpb24gY2xlYW51cE9TKG9zLCBwYXR0ZXJuLCBsYWJlbCkge1xuICAgIC8vIFBsYXRmb3JtIHRva2VucyBhcmUgZGVmaW5lZCBhdDpcbiAgICAvLyBodHRwOi8vbXNkbi5taWNyb3NvZnQuY29tL2VuLXVzL2xpYnJhcnkvbXM1Mzc1MDMoVlMuODUpLmFzcHhcbiAgICAvLyBodHRwOi8vd2ViLmFyY2hpdmUub3JnL3dlYi8yMDA4MTEyMjA1Mzk1MC9odHRwOi8vbXNkbi5taWNyb3NvZnQuY29tL2VuLXVzL2xpYnJhcnkvbXM1Mzc1MDMoVlMuODUpLmFzcHhcbiAgICB2YXIgZGF0YSA9IHtcbiAgICAgICcxMC4wJzogJzEwJyxcbiAgICAgICc2LjQnOiAgJzEwIFRlY2huaWNhbCBQcmV2aWV3JyxcbiAgICAgICc2LjMnOiAgJzguMScsXG4gICAgICAnNi4yJzogICc4JyxcbiAgICAgICc2LjEnOiAgJ1NlcnZlciAyMDA4IFIyIC8gNycsXG4gICAgICAnNi4wJzogICdTZXJ2ZXIgMjAwOCAvIFZpc3RhJyxcbiAgICAgICc1LjInOiAgJ1NlcnZlciAyMDAzIC8gWFAgNjQtYml0JyxcbiAgICAgICc1LjEnOiAgJ1hQJyxcbiAgICAgICc1LjAxJzogJzIwMDAgU1AxJyxcbiAgICAgICc1LjAnOiAgJzIwMDAnLFxuICAgICAgJzQuMCc6ICAnTlQnLFxuICAgICAgJzQuOTAnOiAnTUUnXG4gICAgfTtcbiAgICAvLyBEZXRlY3QgV2luZG93cyB2ZXJzaW9uIGZyb20gcGxhdGZvcm0gdG9rZW5zLlxuICAgIGlmIChwYXR0ZXJuICYmIGxhYmVsICYmIC9eV2luL2kudGVzdChvcykgJiYgIS9eV2luZG93cyBQaG9uZSAvaS50ZXN0KG9zKSAmJlxuICAgICAgICAoZGF0YSA9IGRhdGFbL1tcXGQuXSskLy5leGVjKG9zKV0pKSB7XG4gICAgICBvcyA9ICdXaW5kb3dzICcgKyBkYXRhO1xuICAgIH1cbiAgICAvLyBDb3JyZWN0IGNoYXJhY3RlciBjYXNlIGFuZCBjbGVhbnVwIHN0cmluZy5cbiAgICBvcyA9IFN0cmluZyhvcyk7XG5cbiAgICBpZiAocGF0dGVybiAmJiBsYWJlbCkge1xuICAgICAgb3MgPSBvcy5yZXBsYWNlKFJlZ0V4cChwYXR0ZXJuLCAnaScpLCBsYWJlbCk7XG4gICAgfVxuXG4gICAgb3MgPSBmb3JtYXQoXG4gICAgICBvcy5yZXBsYWNlKC8gY2UkL2ksICcgQ0UnKVxuICAgICAgICAucmVwbGFjZSgvXFxiaHB3L2ksICd3ZWInKVxuICAgICAgICAucmVwbGFjZSgvXFxiTWFjaW50b3NoXFxiLywgJ01hYyBPUycpXG4gICAgICAgIC5yZXBsYWNlKC9fUG93ZXJQQ1xcYi9pLCAnIE9TJylcbiAgICAgICAgLnJlcGxhY2UoL1xcYihPUyBYKSBbXiBcXGRdKy9pLCAnJDEnKVxuICAgICAgICAucmVwbGFjZSgvXFxiTWFjIChPUyBYKVxcYi8sICckMScpXG4gICAgICAgIC5yZXBsYWNlKC9cXC8oXFxkKS8sICcgJDEnKVxuICAgICAgICAucmVwbGFjZSgvXy9nLCAnLicpXG4gICAgICAgIC5yZXBsYWNlKC8oPzogQmVQQ3xbIC5dKmZjWyBcXGQuXSspJC9pLCAnJylcbiAgICAgICAgLnJlcGxhY2UoL1xcYng4NlxcLjY0XFxiL2dpLCAneDg2XzY0JylcbiAgICAgICAgLnJlcGxhY2UoL1xcYihXaW5kb3dzIFBob25lKSBPU1xcYi8sICckMScpXG4gICAgICAgIC5yZXBsYWNlKC9cXGIoQ2hyb21lIE9TIFxcdyspIFtcXGQuXStcXGIvLCAnJDEnKVxuICAgICAgICAuc3BsaXQoJyBvbiAnKVswXVxuICAgICk7XG5cbiAgICByZXR1cm4gb3M7XG4gIH1cblxuICAvKipcbiAgICogQW4gaXRlcmF0aW9uIHV0aWxpdHkgZm9yIGFycmF5cyBhbmQgb2JqZWN0cy5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtBcnJheXxPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIGl0ZXJhdGUgb3Zlci5cbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gY2FsbGJhY2sgVGhlIGZ1bmN0aW9uIGNhbGxlZCBwZXIgaXRlcmF0aW9uLlxuICAgKi9cbiAgZnVuY3Rpb24gZWFjaChvYmplY3QsIGNhbGxiYWNrKSB7XG4gICAgdmFyIGluZGV4ID0gLTEsXG4gICAgICAgIGxlbmd0aCA9IG9iamVjdCA/IG9iamVjdC5sZW5ndGggOiAwO1xuXG4gICAgaWYgKHR5cGVvZiBsZW5ndGggPT0gJ251bWJlcicgJiYgbGVuZ3RoID4gLTEgJiYgbGVuZ3RoIDw9IG1heFNhZmVJbnRlZ2VyKSB7XG4gICAgICB3aGlsZSAoKytpbmRleCA8IGxlbmd0aCkge1xuICAgICAgICBjYWxsYmFjayhvYmplY3RbaW5kZXhdLCBpbmRleCwgb2JqZWN0KTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgZm9yT3duKG9iamVjdCwgY2FsbGJhY2spO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBUcmltIGFuZCBjb25kaXRpb25hbGx5IGNhcGl0YWxpemUgc3RyaW5nIHZhbHVlcy5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtzdHJpbmd9IHN0cmluZyBUaGUgc3RyaW5nIHRvIGZvcm1hdC5cbiAgICogQHJldHVybnMge3N0cmluZ30gVGhlIGZvcm1hdHRlZCBzdHJpbmcuXG4gICAqL1xuICBmdW5jdGlvbiBmb3JtYXQoc3RyaW5nKSB7XG4gICAgc3RyaW5nID0gdHJpbShzdHJpbmcpO1xuICAgIHJldHVybiAvXig/OndlYk9TfGkoPzpPU3xQKSkvLnRlc3Qoc3RyaW5nKVxuICAgICAgPyBzdHJpbmdcbiAgICAgIDogY2FwaXRhbGl6ZShzdHJpbmcpO1xuICB9XG5cbiAgLyoqXG4gICAqIEl0ZXJhdGVzIG92ZXIgYW4gb2JqZWN0J3Mgb3duIHByb3BlcnRpZXMsIGV4ZWN1dGluZyB0aGUgYGNhbGxiYWNrYCBmb3IgZWFjaC5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIGl0ZXJhdGUgb3Zlci5cbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gY2FsbGJhY2sgVGhlIGZ1bmN0aW9uIGV4ZWN1dGVkIHBlciBvd24gcHJvcGVydHkuXG4gICAqL1xuICBmdW5jdGlvbiBmb3JPd24ob2JqZWN0LCBjYWxsYmFjaykge1xuICAgIGZvciAodmFyIGtleSBpbiBvYmplY3QpIHtcbiAgICAgIGlmIChoYXNPd25Qcm9wZXJ0eS5jYWxsKG9iamVjdCwga2V5KSkge1xuICAgICAgICBjYWxsYmFjayhvYmplY3Rba2V5XSwga2V5LCBvYmplY3QpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBHZXRzIHRoZSBpbnRlcm5hbCBgW1tDbGFzc11dYCBvZiBhIHZhbHVlLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZS5cbiAgICogQHJldHVybnMge3N0cmluZ30gVGhlIGBbW0NsYXNzXV1gLlxuICAgKi9cbiAgZnVuY3Rpb24gZ2V0Q2xhc3NPZih2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZSA9PSBudWxsXG4gICAgICA/IGNhcGl0YWxpemUodmFsdWUpXG4gICAgICA6IHRvU3RyaW5nLmNhbGwodmFsdWUpLnNsaWNlKDgsIC0xKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBIb3N0IG9iamVjdHMgY2FuIHJldHVybiB0eXBlIHZhbHVlcyB0aGF0IGFyZSBkaWZmZXJlbnQgZnJvbSB0aGVpciBhY3R1YWxcbiAgICogZGF0YSB0eXBlLiBUaGUgb2JqZWN0cyB3ZSBhcmUgY29uY2VybmVkIHdpdGggdXN1YWxseSByZXR1cm4gbm9uLXByaW1pdGl2ZVxuICAgKiB0eXBlcyBvZiBcIm9iamVjdFwiLCBcImZ1bmN0aW9uXCIsIG9yIFwidW5rbm93blwiLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0geyp9IG9iamVjdCBUaGUgb3duZXIgb2YgdGhlIHByb3BlcnR5LlxuICAgKiBAcGFyYW0ge3N0cmluZ30gcHJvcGVydHkgVGhlIHByb3BlcnR5IHRvIGNoZWNrLlxuICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgdGhlIHByb3BlcnR5IHZhbHVlIGlzIGEgbm9uLXByaW1pdGl2ZSwgZWxzZSBgZmFsc2VgLlxuICAgKi9cbiAgZnVuY3Rpb24gaXNIb3N0VHlwZShvYmplY3QsIHByb3BlcnR5KSB7XG4gICAgdmFyIHR5cGUgPSBvYmplY3QgIT0gbnVsbCA/IHR5cGVvZiBvYmplY3RbcHJvcGVydHldIDogJ251bWJlcic7XG4gICAgcmV0dXJuICEvXig/OmJvb2xlYW58bnVtYmVyfHN0cmluZ3x1bmRlZmluZWQpJC8udGVzdCh0eXBlKSAmJlxuICAgICAgKHR5cGUgPT0gJ29iamVjdCcgPyAhIW9iamVjdFtwcm9wZXJ0eV0gOiB0cnVlKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBQcmVwYXJlcyBhIHN0cmluZyBmb3IgdXNlIGluIGEgYFJlZ0V4cGAgYnkgbWFraW5nIGh5cGhlbnMgYW5kIHNwYWNlcyBvcHRpb25hbC5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtzdHJpbmd9IHN0cmluZyBUaGUgc3RyaW5nIHRvIHF1YWxpZnkuXG4gICAqIEByZXR1cm5zIHtzdHJpbmd9IFRoZSBxdWFsaWZpZWQgc3RyaW5nLlxuICAgKi9cbiAgZnVuY3Rpb24gcXVhbGlmeShzdHJpbmcpIHtcbiAgICByZXR1cm4gU3RyaW5nKHN0cmluZykucmVwbGFjZSgvKFsgLV0pKD8hJCkvZywgJyQxPycpO1xuICB9XG5cbiAgLyoqXG4gICAqIEEgYmFyZS1ib25lcyBgQXJyYXkjcmVkdWNlYCBsaWtlIHV0aWxpdHkgZnVuY3Rpb24uXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBpdGVyYXRlIG92ZXIuXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IGNhbGxiYWNrIFRoZSBmdW5jdGlvbiBjYWxsZWQgcGVyIGl0ZXJhdGlvbi5cbiAgICogQHJldHVybnMgeyp9IFRoZSBhY2N1bXVsYXRlZCByZXN1bHQuXG4gICAqL1xuICBmdW5jdGlvbiByZWR1Y2UoYXJyYXksIGNhbGxiYWNrKSB7XG4gICAgdmFyIGFjY3VtdWxhdG9yID0gbnVsbDtcbiAgICBlYWNoKGFycmF5LCBmdW5jdGlvbih2YWx1ZSwgaW5kZXgpIHtcbiAgICAgIGFjY3VtdWxhdG9yID0gY2FsbGJhY2soYWNjdW11bGF0b3IsIHZhbHVlLCBpbmRleCwgYXJyYXkpO1xuICAgIH0pO1xuICAgIHJldHVybiBhY2N1bXVsYXRvcjtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZW1vdmVzIGxlYWRpbmcgYW5kIHRyYWlsaW5nIHdoaXRlc3BhY2UgZnJvbSBhIHN0cmluZy5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtzdHJpbmd9IHN0cmluZyBUaGUgc3RyaW5nIHRvIHRyaW0uXG4gICAqIEByZXR1cm5zIHtzdHJpbmd9IFRoZSB0cmltbWVkIHN0cmluZy5cbiAgICovXG4gIGZ1bmN0aW9uIHRyaW0oc3RyaW5nKSB7XG4gICAgcmV0dXJuIFN0cmluZyhzdHJpbmcpLnJlcGxhY2UoL14gK3wgKyQvZywgJycpO1xuICB9XG5cbiAgLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG5cbiAgLyoqXG4gICAqIENyZWF0ZXMgYSBuZXcgcGxhdGZvcm0gb2JqZWN0LlxuICAgKlxuICAgKiBAbWVtYmVyT2YgcGxhdGZvcm1cbiAgICogQHBhcmFtIHtPYmplY3R8c3RyaW5nfSBbdWE9bmF2aWdhdG9yLnVzZXJBZ2VudF0gVGhlIHVzZXIgYWdlbnQgc3RyaW5nIG9yXG4gICAqICBjb250ZXh0IG9iamVjdC5cbiAgICogQHJldHVybnMge09iamVjdH0gQSBwbGF0Zm9ybSBvYmplY3QuXG4gICAqL1xuICBmdW5jdGlvbiBwYXJzZSh1YSkge1xuXG4gICAgLyoqIFRoZSBlbnZpcm9ubWVudCBjb250ZXh0IG9iamVjdC4gKi9cbiAgICB2YXIgY29udGV4dCA9IHJvb3Q7XG5cbiAgICAvKiogVXNlZCB0byBmbGFnIHdoZW4gYSBjdXN0b20gY29udGV4dCBpcyBwcm92aWRlZC4gKi9cbiAgICB2YXIgaXNDdXN0b21Db250ZXh0ID0gdWEgJiYgdHlwZW9mIHVhID09ICdvYmplY3QnICYmIGdldENsYXNzT2YodWEpICE9ICdTdHJpbmcnO1xuXG4gICAgLy8gSnVnZ2xlIGFyZ3VtZW50cy5cbiAgICBpZiAoaXNDdXN0b21Db250ZXh0KSB7XG4gICAgICBjb250ZXh0ID0gdWE7XG4gICAgICB1YSA9IG51bGw7XG4gICAgfVxuXG4gICAgLyoqIEJyb3dzZXIgbmF2aWdhdG9yIG9iamVjdC4gKi9cbiAgICB2YXIgbmF2ID0gY29udGV4dC5uYXZpZ2F0b3IgfHwge307XG5cbiAgICAvKiogQnJvd3NlciB1c2VyIGFnZW50IHN0cmluZy4gKi9cbiAgICB2YXIgdXNlckFnZW50ID0gbmF2LnVzZXJBZ2VudCB8fCAnJztcblxuICAgIHVhIHx8ICh1YSA9IHVzZXJBZ2VudCk7XG5cbiAgICAvKiogVXNlZCB0byBmbGFnIHdoZW4gYHRoaXNCaW5kaW5nYCBpcyB0aGUgW01vZHVsZVNjb3BlXS4gKi9cbiAgICB2YXIgaXNNb2R1bGVTY29wZSA9IGlzQ3VzdG9tQ29udGV4dCB8fCB0aGlzQmluZGluZyA9PSBvbGRSb290O1xuXG4gICAgLyoqIFVzZWQgdG8gZGV0ZWN0IGlmIGJyb3dzZXIgaXMgbGlrZSBDaHJvbWUuICovXG4gICAgdmFyIGxpa2VDaHJvbWUgPSBpc0N1c3RvbUNvbnRleHRcbiAgICAgID8gISFuYXYubGlrZUNocm9tZVxuICAgICAgOiAvXFxiQ2hyb21lXFxiLy50ZXN0KHVhKSAmJiAhL2ludGVybmFsfFxcbi9pLnRlc3QodG9TdHJpbmcudG9TdHJpbmcoKSk7XG5cbiAgICAvKiogSW50ZXJuYWwgYFtbQ2xhc3NdXWAgdmFsdWUgc2hvcnRjdXRzLiAqL1xuICAgIHZhciBvYmplY3RDbGFzcyA9ICdPYmplY3QnLFxuICAgICAgICBhaXJSdW50aW1lQ2xhc3MgPSBpc0N1c3RvbUNvbnRleHQgPyBvYmplY3RDbGFzcyA6ICdTY3JpcHRCcmlkZ2luZ1Byb3h5T2JqZWN0JyxcbiAgICAgICAgZW52aXJvQ2xhc3MgPSBpc0N1c3RvbUNvbnRleHQgPyBvYmplY3RDbGFzcyA6ICdFbnZpcm9ubWVudCcsXG4gICAgICAgIGphdmFDbGFzcyA9IChpc0N1c3RvbUNvbnRleHQgJiYgY29udGV4dC5qYXZhKSA/ICdKYXZhUGFja2FnZScgOiBnZXRDbGFzc09mKGNvbnRleHQuamF2YSksXG4gICAgICAgIHBoYW50b21DbGFzcyA9IGlzQ3VzdG9tQ29udGV4dCA/IG9iamVjdENsYXNzIDogJ1J1bnRpbWVPYmplY3QnO1xuXG4gICAgLyoqIERldGVjdCBKYXZhIGVudmlyb25tZW50cy4gKi9cbiAgICB2YXIgamF2YSA9IC9cXGJKYXZhLy50ZXN0KGphdmFDbGFzcykgJiYgY29udGV4dC5qYXZhO1xuXG4gICAgLyoqIERldGVjdCBSaGluby4gKi9cbiAgICB2YXIgcmhpbm8gPSBqYXZhICYmIGdldENsYXNzT2YoY29udGV4dC5lbnZpcm9ubWVudCkgPT0gZW52aXJvQ2xhc3M7XG5cbiAgICAvKiogQSBjaGFyYWN0ZXIgdG8gcmVwcmVzZW50IGFscGhhLiAqL1xuICAgIHZhciBhbHBoYSA9IGphdmEgPyAnYScgOiAnXFx1MDNiMSc7XG5cbiAgICAvKiogQSBjaGFyYWN0ZXIgdG8gcmVwcmVzZW50IGJldGEuICovXG4gICAgdmFyIGJldGEgPSBqYXZhID8gJ2InIDogJ1xcdTAzYjInO1xuXG4gICAgLyoqIEJyb3dzZXIgZG9jdW1lbnQgb2JqZWN0LiAqL1xuICAgIHZhciBkb2MgPSBjb250ZXh0LmRvY3VtZW50IHx8IHt9O1xuXG4gICAgLyoqXG4gICAgICogRGV0ZWN0IE9wZXJhIGJyb3dzZXIgKFByZXN0by1iYXNlZCkuXG4gICAgICogaHR0cDovL3d3dy5ob3d0b2NyZWF0ZS5jby51ay9vcGVyYVN0dWZmL29wZXJhT2JqZWN0Lmh0bWxcbiAgICAgKiBodHRwOi8vZGV2Lm9wZXJhLmNvbS9hcnRpY2xlcy92aWV3L29wZXJhLW1pbmktd2ViLWNvbnRlbnQtYXV0aG9yaW5nLWd1aWRlbGluZXMvI29wZXJhbWluaVxuICAgICAqL1xuICAgIHZhciBvcGVyYSA9IGNvbnRleHQub3BlcmFtaW5pIHx8IGNvbnRleHQub3BlcmE7XG5cbiAgICAvKiogT3BlcmEgYFtbQ2xhc3NdXWAuICovXG4gICAgdmFyIG9wZXJhQ2xhc3MgPSByZU9wZXJhLnRlc3Qob3BlcmFDbGFzcyA9IChpc0N1c3RvbUNvbnRleHQgJiYgb3BlcmEpID8gb3BlcmFbJ1tbQ2xhc3NdXSddIDogZ2V0Q2xhc3NPZihvcGVyYSkpXG4gICAgICA/IG9wZXJhQ2xhc3NcbiAgICAgIDogKG9wZXJhID0gbnVsbCk7XG5cbiAgICAvKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG5cbiAgICAvKiogVGVtcG9yYXJ5IHZhcmlhYmxlIHVzZWQgb3ZlciB0aGUgc2NyaXB0J3MgbGlmZXRpbWUuICovXG4gICAgdmFyIGRhdGE7XG5cbiAgICAvKiogVGhlIENQVSBhcmNoaXRlY3R1cmUuICovXG4gICAgdmFyIGFyY2ggPSB1YTtcblxuICAgIC8qKiBQbGF0Zm9ybSBkZXNjcmlwdGlvbiBhcnJheS4gKi9cbiAgICB2YXIgZGVzY3JpcHRpb24gPSBbXTtcblxuICAgIC8qKiBQbGF0Zm9ybSBhbHBoYS9iZXRhIGluZGljYXRvci4gKi9cbiAgICB2YXIgcHJlcmVsZWFzZSA9IG51bGw7XG5cbiAgICAvKiogQSBmbGFnIHRvIGluZGljYXRlIHRoYXQgZW52aXJvbm1lbnQgZmVhdHVyZXMgc2hvdWxkIGJlIHVzZWQgdG8gcmVzb2x2ZSB0aGUgcGxhdGZvcm0uICovXG4gICAgdmFyIHVzZUZlYXR1cmVzID0gdWEgPT0gdXNlckFnZW50O1xuXG4gICAgLyoqIFRoZSBicm93c2VyL2Vudmlyb25tZW50IHZlcnNpb24uICovXG4gICAgdmFyIHZlcnNpb24gPSB1c2VGZWF0dXJlcyAmJiBvcGVyYSAmJiB0eXBlb2Ygb3BlcmEudmVyc2lvbiA9PSAnZnVuY3Rpb24nICYmIG9wZXJhLnZlcnNpb24oKTtcblxuICAgIC8qKiBBIGZsYWcgdG8gaW5kaWNhdGUgaWYgdGhlIE9TIGVuZHMgd2l0aCBcIi8gVmVyc2lvblwiICovXG4gICAgdmFyIGlzU3BlY2lhbENhc2VkT1M7XG5cbiAgICAvKiBEZXRlY3RhYmxlIGxheW91dCBlbmdpbmVzIChvcmRlciBpcyBpbXBvcnRhbnQpLiAqL1xuICAgIHZhciBsYXlvdXQgPSBnZXRMYXlvdXQoW1xuICAgICAgeyAnbGFiZWwnOiAnRWRnZUhUTUwnLCAncGF0dGVybic6ICdFZGdlJyB9LFxuICAgICAgJ1RyaWRlbnQnLFxuICAgICAgeyAnbGFiZWwnOiAnV2ViS2l0JywgJ3BhdHRlcm4nOiAnQXBwbGVXZWJLaXQnIH0sXG4gICAgICAnaUNhYicsXG4gICAgICAnUHJlc3RvJyxcbiAgICAgICdOZXRGcm9udCcsXG4gICAgICAnVGFzbWFuJyxcbiAgICAgICdLSFRNTCcsXG4gICAgICAnR2Vja28nXG4gICAgXSk7XG5cbiAgICAvKiBEZXRlY3RhYmxlIGJyb3dzZXIgbmFtZXMgKG9yZGVyIGlzIGltcG9ydGFudCkuICovXG4gICAgdmFyIG5hbWUgPSBnZXROYW1lKFtcbiAgICAgICdBZG9iZSBBSVInLFxuICAgICAgJ0Fyb3JhJyxcbiAgICAgICdBdmFudCBCcm93c2VyJyxcbiAgICAgICdCcmVhY2gnLFxuICAgICAgJ0NhbWlubycsXG4gICAgICAnRWxlY3Ryb24nLFxuICAgICAgJ0VwaXBoYW55JyxcbiAgICAgICdGZW5uZWMnLFxuICAgICAgJ0Zsb2NrJyxcbiAgICAgICdHYWxlb24nLFxuICAgICAgJ0dyZWVuQnJvd3NlcicsXG4gICAgICAnaUNhYicsXG4gICAgICAnSWNld2Vhc2VsJyxcbiAgICAgICdLLU1lbGVvbicsXG4gICAgICAnS29ucXVlcm9yJyxcbiAgICAgICdMdW5hc2NhcGUnLFxuICAgICAgJ01heHRob24nLFxuICAgICAgeyAnbGFiZWwnOiAnTWljcm9zb2Z0IEVkZ2UnLCAncGF0dGVybic6ICdFZGdlJyB9LFxuICAgICAgJ01pZG9yaScsXG4gICAgICAnTm9vayBCcm93c2VyJyxcbiAgICAgICdQYWxlTW9vbicsXG4gICAgICAnUGhhbnRvbUpTJyxcbiAgICAgICdSYXZlbicsXG4gICAgICAnUmVrb25xJyxcbiAgICAgICdSb2NrTWVsdCcsXG4gICAgICB7ICdsYWJlbCc6ICdTYW1zdW5nIEludGVybmV0JywgJ3BhdHRlcm4nOiAnU2Ftc3VuZ0Jyb3dzZXInIH0sXG4gICAgICAnU2VhTW9ua2V5JyxcbiAgICAgIHsgJ2xhYmVsJzogJ1NpbGsnLCAncGF0dGVybic6ICcoPzpDbG91ZDl8U2lsay1BY2NlbGVyYXRlZCknIH0sXG4gICAgICAnU2xlaXBuaXInLFxuICAgICAgJ1NsaW1Ccm93c2VyJyxcbiAgICAgIHsgJ2xhYmVsJzogJ1NSV2FyZSBJcm9uJywgJ3BhdHRlcm4nOiAnSXJvbicgfSxcbiAgICAgICdTdW5yaXNlJyxcbiAgICAgICdTd2lmdGZveCcsXG4gICAgICAnV2F0ZXJmb3gnLFxuICAgICAgJ1dlYlBvc2l0aXZlJyxcbiAgICAgICdPcGVyYSBNaW5pJyxcbiAgICAgIHsgJ2xhYmVsJzogJ09wZXJhIE1pbmknLCAncGF0dGVybic6ICdPUGlPUycgfSxcbiAgICAgICdPcGVyYScsXG4gICAgICB7ICdsYWJlbCc6ICdPcGVyYScsICdwYXR0ZXJuJzogJ09QUicgfSxcbiAgICAgICdDaHJvbWUnLFxuICAgICAgeyAnbGFiZWwnOiAnQ2hyb21lIE1vYmlsZScsICdwYXR0ZXJuJzogJyg/OkNyaU9TfENyTW8pJyB9LFxuICAgICAgeyAnbGFiZWwnOiAnRmlyZWZveCcsICdwYXR0ZXJuJzogJyg/OkZpcmVmb3h8TWluZWZpZWxkKScgfSxcbiAgICAgIHsgJ2xhYmVsJzogJ0ZpcmVmb3ggZm9yIGlPUycsICdwYXR0ZXJuJzogJ0Z4aU9TJyB9LFxuICAgICAgeyAnbGFiZWwnOiAnSUUnLCAncGF0dGVybic6ICdJRU1vYmlsZScgfSxcbiAgICAgIHsgJ2xhYmVsJzogJ0lFJywgJ3BhdHRlcm4nOiAnTVNJRScgfSxcbiAgICAgICdTYWZhcmknXG4gICAgXSk7XG5cbiAgICAvKiBEZXRlY3RhYmxlIHByb2R1Y3RzIChvcmRlciBpcyBpbXBvcnRhbnQpLiAqL1xuICAgIHZhciBwcm9kdWN0ID0gZ2V0UHJvZHVjdChbXG4gICAgICB7ICdsYWJlbCc6ICdCbGFja0JlcnJ5JywgJ3BhdHRlcm4nOiAnQkIxMCcgfSxcbiAgICAgICdCbGFja0JlcnJ5JyxcbiAgICAgIHsgJ2xhYmVsJzogJ0dhbGF4eSBTJywgJ3BhdHRlcm4nOiAnR1QtSTkwMDAnIH0sXG4gICAgICB7ICdsYWJlbCc6ICdHYWxheHkgUzInLCAncGF0dGVybic6ICdHVC1JOTEwMCcgfSxcbiAgICAgIHsgJ2xhYmVsJzogJ0dhbGF4eSBTMycsICdwYXR0ZXJuJzogJ0dULUk5MzAwJyB9LFxuICAgICAgeyAnbGFiZWwnOiAnR2FsYXh5IFM0JywgJ3BhdHRlcm4nOiAnR1QtSTk1MDAnIH0sXG4gICAgICB7ICdsYWJlbCc6ICdHYWxheHkgUzUnLCAncGF0dGVybic6ICdTTS1HOTAwJyB9LFxuICAgICAgeyAnbGFiZWwnOiAnR2FsYXh5IFM2JywgJ3BhdHRlcm4nOiAnU00tRzkyMCcgfSxcbiAgICAgIHsgJ2xhYmVsJzogJ0dhbGF4eSBTNiBFZGdlJywgJ3BhdHRlcm4nOiAnU00tRzkyNScgfSxcbiAgICAgIHsgJ2xhYmVsJzogJ0dhbGF4eSBTNycsICdwYXR0ZXJuJzogJ1NNLUc5MzAnIH0sXG4gICAgICB7ICdsYWJlbCc6ICdHYWxheHkgUzcgRWRnZScsICdwYXR0ZXJuJzogJ1NNLUc5MzUnIH0sXG4gICAgICAnR29vZ2xlIFRWJyxcbiAgICAgICdMdW1pYScsXG4gICAgICAnaVBhZCcsXG4gICAgICAnaVBvZCcsXG4gICAgICAnaVBob25lJyxcbiAgICAgICdLaW5kbGUnLFxuICAgICAgeyAnbGFiZWwnOiAnS2luZGxlIEZpcmUnLCAncGF0dGVybic6ICcoPzpDbG91ZDl8U2lsay1BY2NlbGVyYXRlZCknIH0sXG4gICAgICAnTmV4dXMnLFxuICAgICAgJ05vb2snLFxuICAgICAgJ1BsYXlCb29rJyxcbiAgICAgICdQbGF5U3RhdGlvbiBWaXRhJyxcbiAgICAgICdQbGF5U3RhdGlvbicsXG4gICAgICAnVG91Y2hQYWQnLFxuICAgICAgJ1RyYW5zZm9ybWVyJyxcbiAgICAgIHsgJ2xhYmVsJzogJ1dpaSBVJywgJ3BhdHRlcm4nOiAnV2lpVScgfSxcbiAgICAgICdXaWknLFxuICAgICAgJ1hib3ggT25lJyxcbiAgICAgIHsgJ2xhYmVsJzogJ1hib3ggMzYwJywgJ3BhdHRlcm4nOiAnWGJveCcgfSxcbiAgICAgICdYb29tJ1xuICAgIF0pO1xuXG4gICAgLyogRGV0ZWN0YWJsZSBtYW51ZmFjdHVyZXJzLiAqL1xuICAgIHZhciBtYW51ZmFjdHVyZXIgPSBnZXRNYW51ZmFjdHVyZXIoe1xuICAgICAgJ0FwcGxlJzogeyAnaVBhZCc6IDEsICdpUGhvbmUnOiAxLCAnaVBvZCc6IDEgfSxcbiAgICAgICdBcmNob3MnOiB7fSxcbiAgICAgICdBbWF6b24nOiB7ICdLaW5kbGUnOiAxLCAnS2luZGxlIEZpcmUnOiAxIH0sXG4gICAgICAnQXN1cyc6IHsgJ1RyYW5zZm9ybWVyJzogMSB9LFxuICAgICAgJ0Jhcm5lcyAmIE5vYmxlJzogeyAnTm9vayc6IDEgfSxcbiAgICAgICdCbGFja0JlcnJ5JzogeyAnUGxheUJvb2snOiAxIH0sXG4gICAgICAnR29vZ2xlJzogeyAnR29vZ2xlIFRWJzogMSwgJ05leHVzJzogMSB9LFxuICAgICAgJ0hQJzogeyAnVG91Y2hQYWQnOiAxIH0sXG4gICAgICAnSFRDJzoge30sXG4gICAgICAnTEcnOiB7fSxcbiAgICAgICdNaWNyb3NvZnQnOiB7ICdYYm94JzogMSwgJ1hib3ggT25lJzogMSB9LFxuICAgICAgJ01vdG9yb2xhJzogeyAnWG9vbSc6IDEgfSxcbiAgICAgICdOaW50ZW5kbyc6IHsgJ1dpaSBVJzogMSwgICdXaWknOiAxIH0sXG4gICAgICAnTm9raWEnOiB7ICdMdW1pYSc6IDEgfSxcbiAgICAgICdTYW1zdW5nJzogeyAnR2FsYXh5IFMnOiAxLCAnR2FsYXh5IFMyJzogMSwgJ0dhbGF4eSBTMyc6IDEsICdHYWxheHkgUzQnOiAxIH0sXG4gICAgICAnU29ueSc6IHsgJ1BsYXlTdGF0aW9uJzogMSwgJ1BsYXlTdGF0aW9uIFZpdGEnOiAxIH1cbiAgICB9KTtcblxuICAgIC8qIERldGVjdGFibGUgb3BlcmF0aW5nIHN5c3RlbXMgKG9yZGVyIGlzIGltcG9ydGFudCkuICovXG4gICAgdmFyIG9zID0gZ2V0T1MoW1xuICAgICAgJ1dpbmRvd3MgUGhvbmUnLFxuICAgICAgJ0FuZHJvaWQnLFxuICAgICAgJ0NlbnRPUycsXG4gICAgICB7ICdsYWJlbCc6ICdDaHJvbWUgT1MnLCAncGF0dGVybic6ICdDck9TJyB9LFxuICAgICAgJ0RlYmlhbicsXG4gICAgICAnRmVkb3JhJyxcbiAgICAgICdGcmVlQlNEJyxcbiAgICAgICdHZW50b28nLFxuICAgICAgJ0hhaWt1JyxcbiAgICAgICdLdWJ1bnR1JyxcbiAgICAgICdMaW51eCBNaW50JyxcbiAgICAgICdPcGVuQlNEJyxcbiAgICAgICdSZWQgSGF0JyxcbiAgICAgICdTdVNFJyxcbiAgICAgICdVYnVudHUnLFxuICAgICAgJ1h1YnVudHUnLFxuICAgICAgJ0N5Z3dpbicsXG4gICAgICAnU3ltYmlhbiBPUycsXG4gICAgICAnaHB3T1MnLFxuICAgICAgJ3dlYk9TICcsXG4gICAgICAnd2ViT1MnLFxuICAgICAgJ1RhYmxldCBPUycsXG4gICAgICAnVGl6ZW4nLFxuICAgICAgJ0xpbnV4JyxcbiAgICAgICdNYWMgT1MgWCcsXG4gICAgICAnTWFjaW50b3NoJyxcbiAgICAgICdNYWMnLFxuICAgICAgJ1dpbmRvd3MgOTg7JyxcbiAgICAgICdXaW5kb3dzICdcbiAgICBdKTtcblxuICAgIC8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cblxuICAgIC8qKlxuICAgICAqIFBpY2tzIHRoZSBsYXlvdXQgZW5naW5lIGZyb20gYW4gYXJyYXkgb2YgZ3Vlc3Nlcy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtBcnJheX0gZ3Vlc3NlcyBBbiBhcnJheSBvZiBndWVzc2VzLlxuICAgICAqIEByZXR1cm5zIHtudWxsfHN0cmluZ30gVGhlIGRldGVjdGVkIGxheW91dCBlbmdpbmUuXG4gICAgICovXG4gICAgZnVuY3Rpb24gZ2V0TGF5b3V0KGd1ZXNzZXMpIHtcbiAgICAgIHJldHVybiByZWR1Y2UoZ3Vlc3NlcywgZnVuY3Rpb24ocmVzdWx0LCBndWVzcykge1xuICAgICAgICByZXR1cm4gcmVzdWx0IHx8IFJlZ0V4cCgnXFxcXGInICsgKFxuICAgICAgICAgIGd1ZXNzLnBhdHRlcm4gfHwgcXVhbGlmeShndWVzcylcbiAgICAgICAgKSArICdcXFxcYicsICdpJykuZXhlYyh1YSkgJiYgKGd1ZXNzLmxhYmVsIHx8IGd1ZXNzKTtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFBpY2tzIHRoZSBtYW51ZmFjdHVyZXIgZnJvbSBhbiBhcnJheSBvZiBndWVzc2VzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBndWVzc2VzIEFuIG9iamVjdCBvZiBndWVzc2VzLlxuICAgICAqIEByZXR1cm5zIHtudWxsfHN0cmluZ30gVGhlIGRldGVjdGVkIG1hbnVmYWN0dXJlci5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBnZXRNYW51ZmFjdHVyZXIoZ3Vlc3Nlcykge1xuICAgICAgcmV0dXJuIHJlZHVjZShndWVzc2VzLCBmdW5jdGlvbihyZXN1bHQsIHZhbHVlLCBrZXkpIHtcbiAgICAgICAgLy8gTG9va3VwIHRoZSBtYW51ZmFjdHVyZXIgYnkgcHJvZHVjdCBvciBzY2FuIHRoZSBVQSBmb3IgdGhlIG1hbnVmYWN0dXJlci5cbiAgICAgICAgcmV0dXJuIHJlc3VsdCB8fCAoXG4gICAgICAgICAgdmFsdWVbcHJvZHVjdF0gfHxcbiAgICAgICAgICB2YWx1ZVsvXlthLXpdKyg/OiArW2Etel0rXFxiKSovaS5leGVjKHByb2R1Y3QpXSB8fFxuICAgICAgICAgIFJlZ0V4cCgnXFxcXGInICsgcXVhbGlmeShrZXkpICsgJyg/OlxcXFxifFxcXFx3KlxcXFxkKScsICdpJykuZXhlYyh1YSlcbiAgICAgICAgKSAmJiBrZXk7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBQaWNrcyB0aGUgYnJvd3NlciBuYW1lIGZyb20gYW4gYXJyYXkgb2YgZ3Vlc3Nlcy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtBcnJheX0gZ3Vlc3NlcyBBbiBhcnJheSBvZiBndWVzc2VzLlxuICAgICAqIEByZXR1cm5zIHtudWxsfHN0cmluZ30gVGhlIGRldGVjdGVkIGJyb3dzZXIgbmFtZS5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBnZXROYW1lKGd1ZXNzZXMpIHtcbiAgICAgIHJldHVybiByZWR1Y2UoZ3Vlc3NlcywgZnVuY3Rpb24ocmVzdWx0LCBndWVzcykge1xuICAgICAgICByZXR1cm4gcmVzdWx0IHx8IFJlZ0V4cCgnXFxcXGInICsgKFxuICAgICAgICAgIGd1ZXNzLnBhdHRlcm4gfHwgcXVhbGlmeShndWVzcylcbiAgICAgICAgKSArICdcXFxcYicsICdpJykuZXhlYyh1YSkgJiYgKGd1ZXNzLmxhYmVsIHx8IGd1ZXNzKTtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFBpY2tzIHRoZSBPUyBuYW1lIGZyb20gYW4gYXJyYXkgb2YgZ3Vlc3Nlcy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtBcnJheX0gZ3Vlc3NlcyBBbiBhcnJheSBvZiBndWVzc2VzLlxuICAgICAqIEByZXR1cm5zIHtudWxsfHN0cmluZ30gVGhlIGRldGVjdGVkIE9TIG5hbWUuXG4gICAgICovXG4gICAgZnVuY3Rpb24gZ2V0T1MoZ3Vlc3Nlcykge1xuICAgICAgcmV0dXJuIHJlZHVjZShndWVzc2VzLCBmdW5jdGlvbihyZXN1bHQsIGd1ZXNzKSB7XG4gICAgICAgIHZhciBwYXR0ZXJuID0gZ3Vlc3MucGF0dGVybiB8fCBxdWFsaWZ5KGd1ZXNzKTtcbiAgICAgICAgaWYgKCFyZXN1bHQgJiYgKHJlc3VsdCA9XG4gICAgICAgICAgICAgIFJlZ0V4cCgnXFxcXGInICsgcGF0dGVybiArICcoPzovW1xcXFxkLl0rfFsgXFxcXHcuXSopJywgJ2knKS5leGVjKHVhKVxuICAgICAgICAgICAgKSkge1xuICAgICAgICAgIHJlc3VsdCA9IGNsZWFudXBPUyhyZXN1bHQsIHBhdHRlcm4sIGd1ZXNzLmxhYmVsIHx8IGd1ZXNzKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUGlja3MgdGhlIHByb2R1Y3QgbmFtZSBmcm9tIGFuIGFycmF5IG9mIGd1ZXNzZXMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGd1ZXNzZXMgQW4gYXJyYXkgb2YgZ3Vlc3Nlcy5cbiAgICAgKiBAcmV0dXJucyB7bnVsbHxzdHJpbmd9IFRoZSBkZXRlY3RlZCBwcm9kdWN0IG5hbWUuXG4gICAgICovXG4gICAgZnVuY3Rpb24gZ2V0UHJvZHVjdChndWVzc2VzKSB7XG4gICAgICByZXR1cm4gcmVkdWNlKGd1ZXNzZXMsIGZ1bmN0aW9uKHJlc3VsdCwgZ3Vlc3MpIHtcbiAgICAgICAgdmFyIHBhdHRlcm4gPSBndWVzcy5wYXR0ZXJuIHx8IHF1YWxpZnkoZ3Vlc3MpO1xuICAgICAgICBpZiAoIXJlc3VsdCAmJiAocmVzdWx0ID1cbiAgICAgICAgICAgICAgUmVnRXhwKCdcXFxcYicgKyBwYXR0ZXJuICsgJyAqXFxcXGQrWy5cXFxcd19dKicsICdpJykuZXhlYyh1YSkgfHxcbiAgICAgICAgICAgICAgUmVnRXhwKCdcXFxcYicgKyBwYXR0ZXJuICsgJyAqXFxcXHcrLVtcXFxcd10qJywgJ2knKS5leGVjKHVhKSB8fFxuICAgICAgICAgICAgICBSZWdFeHAoJ1xcXFxiJyArIHBhdHRlcm4gKyAnKD86OyAqKD86W2Etel0rW18tXSk/W2Etel0rXFxcXGQrfFteICgpOy1dKiknLCAnaScpLmV4ZWModWEpXG4gICAgICAgICAgICApKSB7XG4gICAgICAgICAgLy8gU3BsaXQgYnkgZm9yd2FyZCBzbGFzaCBhbmQgYXBwZW5kIHByb2R1Y3QgdmVyc2lvbiBpZiBuZWVkZWQuXG4gICAgICAgICAgaWYgKChyZXN1bHQgPSBTdHJpbmcoKGd1ZXNzLmxhYmVsICYmICFSZWdFeHAocGF0dGVybiwgJ2knKS50ZXN0KGd1ZXNzLmxhYmVsKSkgPyBndWVzcy5sYWJlbCA6IHJlc3VsdCkuc3BsaXQoJy8nKSlbMV0gJiYgIS9bXFxkLl0rLy50ZXN0KHJlc3VsdFswXSkpIHtcbiAgICAgICAgICAgIHJlc3VsdFswXSArPSAnICcgKyByZXN1bHRbMV07XG4gICAgICAgICAgfVxuICAgICAgICAgIC8vIENvcnJlY3QgY2hhcmFjdGVyIGNhc2UgYW5kIGNsZWFudXAgc3RyaW5nLlxuICAgICAgICAgIGd1ZXNzID0gZ3Vlc3MubGFiZWwgfHwgZ3Vlc3M7XG4gICAgICAgICAgcmVzdWx0ID0gZm9ybWF0KHJlc3VsdFswXVxuICAgICAgICAgICAgLnJlcGxhY2UoUmVnRXhwKHBhdHRlcm4sICdpJyksIGd1ZXNzKVxuICAgICAgICAgICAgLnJlcGxhY2UoUmVnRXhwKCc7ICooPzonICsgZ3Vlc3MgKyAnW18tXSk/JywgJ2knKSwgJyAnKVxuICAgICAgICAgICAgLnJlcGxhY2UoUmVnRXhwKCcoJyArIGd1ZXNzICsgJylbLV8uXT8oXFxcXHcpJywgJ2knKSwgJyQxICQyJykpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXNvbHZlcyB0aGUgdmVyc2lvbiB1c2luZyBhbiBhcnJheSBvZiBVQSBwYXR0ZXJucy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtBcnJheX0gcGF0dGVybnMgQW4gYXJyYXkgb2YgVUEgcGF0dGVybnMuXG4gICAgICogQHJldHVybnMge251bGx8c3RyaW5nfSBUaGUgZGV0ZWN0ZWQgdmVyc2lvbi5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBnZXRWZXJzaW9uKHBhdHRlcm5zKSB7XG4gICAgICByZXR1cm4gcmVkdWNlKHBhdHRlcm5zLCBmdW5jdGlvbihyZXN1bHQsIHBhdHRlcm4pIHtcbiAgICAgICAgcmV0dXJuIHJlc3VsdCB8fCAoUmVnRXhwKHBhdHRlcm4gK1xuICAgICAgICAgICcoPzotW1xcXFxkLl0rL3woPzogZm9yIFtcXFxcdy1dKyk/WyAvLV0pKFtcXFxcZC5dK1teICgpOy9fLV0qKScsICdpJykuZXhlYyh1YSkgfHwgMClbMV0gfHwgbnVsbDtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgYHBsYXRmb3JtLmRlc2NyaXB0aW9uYCB3aGVuIHRoZSBwbGF0Zm9ybSBvYmplY3QgaXMgY29lcmNlZCB0byBhIHN0cmluZy5cbiAgICAgKlxuICAgICAqIEBuYW1lIHRvU3RyaW5nXG4gICAgICogQG1lbWJlck9mIHBsYXRmb3JtXG4gICAgICogQHJldHVybnMge3N0cmluZ30gUmV0dXJucyBgcGxhdGZvcm0uZGVzY3JpcHRpb25gIGlmIGF2YWlsYWJsZSwgZWxzZSBhbiBlbXB0eSBzdHJpbmcuXG4gICAgICovXG4gICAgZnVuY3Rpb24gdG9TdHJpbmdQbGF0Zm9ybSgpIHtcbiAgICAgIHJldHVybiB0aGlzLmRlc2NyaXB0aW9uIHx8ICcnO1xuICAgIH1cblxuICAgIC8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cblxuICAgIC8vIENvbnZlcnQgbGF5b3V0IHRvIGFuIGFycmF5IHNvIHdlIGNhbiBhZGQgZXh0cmEgZGV0YWlscy5cbiAgICBsYXlvdXQgJiYgKGxheW91dCA9IFtsYXlvdXRdKTtcblxuICAgIC8vIERldGVjdCBwcm9kdWN0IG5hbWVzIHRoYXQgY29udGFpbiB0aGVpciBtYW51ZmFjdHVyZXIncyBuYW1lLlxuICAgIGlmIChtYW51ZmFjdHVyZXIgJiYgIXByb2R1Y3QpIHtcbiAgICAgIHByb2R1Y3QgPSBnZXRQcm9kdWN0KFttYW51ZmFjdHVyZXJdKTtcbiAgICB9XG4gICAgLy8gQ2xlYW4gdXAgR29vZ2xlIFRWLlxuICAgIGlmICgoZGF0YSA9IC9cXGJHb29nbGUgVFZcXGIvLmV4ZWMocHJvZHVjdCkpKSB7XG4gICAgICBwcm9kdWN0ID0gZGF0YVswXTtcbiAgICB9XG4gICAgLy8gRGV0ZWN0IHNpbXVsYXRvcnMuXG4gICAgaWYgKC9cXGJTaW11bGF0b3JcXGIvaS50ZXN0KHVhKSkge1xuICAgICAgcHJvZHVjdCA9IChwcm9kdWN0ID8gcHJvZHVjdCArICcgJyA6ICcnKSArICdTaW11bGF0b3InO1xuICAgIH1cbiAgICAvLyBEZXRlY3QgT3BlcmEgTWluaSA4KyBydW5uaW5nIGluIFR1cmJvL1VuY29tcHJlc3NlZCBtb2RlIG9uIGlPUy5cbiAgICBpZiAobmFtZSA9PSAnT3BlcmEgTWluaScgJiYgL1xcYk9QaU9TXFxiLy50ZXN0KHVhKSkge1xuICAgICAgZGVzY3JpcHRpb24ucHVzaCgncnVubmluZyBpbiBUdXJiby9VbmNvbXByZXNzZWQgbW9kZScpO1xuICAgIH1cbiAgICAvLyBEZXRlY3QgSUUgTW9iaWxlIDExLlxuICAgIGlmIChuYW1lID09ICdJRScgJiYgL1xcYmxpa2UgaVBob25lIE9TXFxiLy50ZXN0KHVhKSkge1xuICAgICAgZGF0YSA9IHBhcnNlKHVhLnJlcGxhY2UoL2xpa2UgaVBob25lIE9TLywgJycpKTtcbiAgICAgIG1hbnVmYWN0dXJlciA9IGRhdGEubWFudWZhY3R1cmVyO1xuICAgICAgcHJvZHVjdCA9IGRhdGEucHJvZHVjdDtcbiAgICB9XG4gICAgLy8gRGV0ZWN0IGlPUy5cbiAgICBlbHNlIGlmICgvXmlQLy50ZXN0KHByb2R1Y3QpKSB7XG4gICAgICBuYW1lIHx8IChuYW1lID0gJ1NhZmFyaScpO1xuICAgICAgb3MgPSAnaU9TJyArICgoZGF0YSA9IC8gT1MgKFtcXGRfXSspL2kuZXhlYyh1YSkpXG4gICAgICAgID8gJyAnICsgZGF0YVsxXS5yZXBsYWNlKC9fL2csICcuJylcbiAgICAgICAgOiAnJyk7XG4gICAgfVxuICAgIC8vIERldGVjdCBLdWJ1bnR1LlxuICAgIGVsc2UgaWYgKG5hbWUgPT0gJ0tvbnF1ZXJvcicgJiYgIS9idW50dS9pLnRlc3Qob3MpKSB7XG4gICAgICBvcyA9ICdLdWJ1bnR1JztcbiAgICB9XG4gICAgLy8gRGV0ZWN0IEFuZHJvaWQgYnJvd3NlcnMuXG4gICAgZWxzZSBpZiAoKG1hbnVmYWN0dXJlciAmJiBtYW51ZmFjdHVyZXIgIT0gJ0dvb2dsZScgJiZcbiAgICAgICAgKCgvQ2hyb21lLy50ZXN0KG5hbWUpICYmICEvXFxiTW9iaWxlIFNhZmFyaVxcYi9pLnRlc3QodWEpKSB8fCAvXFxiVml0YVxcYi8udGVzdChwcm9kdWN0KSkpIHx8XG4gICAgICAgICgvXFxiQW5kcm9pZFxcYi8udGVzdChvcykgJiYgL15DaHJvbWUvLnRlc3QobmFtZSkgJiYgL1xcYlZlcnNpb25cXC8vaS50ZXN0KHVhKSkpIHtcbiAgICAgIG5hbWUgPSAnQW5kcm9pZCBCcm93c2VyJztcbiAgICAgIG9zID0gL1xcYkFuZHJvaWRcXGIvLnRlc3Qob3MpID8gb3MgOiAnQW5kcm9pZCc7XG4gICAgfVxuICAgIC8vIERldGVjdCBTaWxrIGRlc2t0b3AvYWNjZWxlcmF0ZWQgbW9kZXMuXG4gICAgZWxzZSBpZiAobmFtZSA9PSAnU2lsaycpIHtcbiAgICAgIGlmICghL1xcYk1vYmkvaS50ZXN0KHVhKSkge1xuICAgICAgICBvcyA9ICdBbmRyb2lkJztcbiAgICAgICAgZGVzY3JpcHRpb24udW5zaGlmdCgnZGVza3RvcCBtb2RlJyk7XG4gICAgICB9XG4gICAgICBpZiAoL0FjY2VsZXJhdGVkICo9ICp0cnVlL2kudGVzdCh1YSkpIHtcbiAgICAgICAgZGVzY3JpcHRpb24udW5zaGlmdCgnYWNjZWxlcmF0ZWQnKTtcbiAgICAgIH1cbiAgICB9XG4gICAgLy8gRGV0ZWN0IFBhbGVNb29uIGlkZW50aWZ5aW5nIGFzIEZpcmVmb3guXG4gICAgZWxzZSBpZiAobmFtZSA9PSAnUGFsZU1vb24nICYmIChkYXRhID0gL1xcYkZpcmVmb3hcXC8oW1xcZC5dKylcXGIvLmV4ZWModWEpKSkge1xuICAgICAgZGVzY3JpcHRpb24ucHVzaCgnaWRlbnRpZnlpbmcgYXMgRmlyZWZveCAnICsgZGF0YVsxXSk7XG4gICAgfVxuICAgIC8vIERldGVjdCBGaXJlZm94IE9TIGFuZCBwcm9kdWN0cyBydW5uaW5nIEZpcmVmb3guXG4gICAgZWxzZSBpZiAobmFtZSA9PSAnRmlyZWZveCcgJiYgKGRhdGEgPSAvXFxiKE1vYmlsZXxUYWJsZXR8VFYpXFxiL2kuZXhlYyh1YSkpKSB7XG4gICAgICBvcyB8fCAob3MgPSAnRmlyZWZveCBPUycpO1xuICAgICAgcHJvZHVjdCB8fCAocHJvZHVjdCA9IGRhdGFbMV0pO1xuICAgIH1cbiAgICAvLyBEZXRlY3QgZmFsc2UgcG9zaXRpdmVzIGZvciBGaXJlZm94L1NhZmFyaS5cbiAgICBlbHNlIGlmICghbmFtZSB8fCAoZGF0YSA9ICEvXFxiTWluZWZpZWxkXFxiL2kudGVzdCh1YSkgJiYgL1xcYig/OkZpcmVmb3h8U2FmYXJpKVxcYi8uZXhlYyhuYW1lKSkpIHtcbiAgICAgIC8vIEVzY2FwZSB0aGUgYC9gIGZvciBGaXJlZm94IDEuXG4gICAgICBpZiAobmFtZSAmJiAhcHJvZHVjdCAmJiAvW1xcLyxdfF5bXihdKz9cXCkvLnRlc3QodWEuc2xpY2UodWEuaW5kZXhPZihkYXRhICsgJy8nKSArIDgpKSkge1xuICAgICAgICAvLyBDbGVhciBuYW1lIG9mIGZhbHNlIHBvc2l0aXZlcy5cbiAgICAgICAgbmFtZSA9IG51bGw7XG4gICAgICB9XG4gICAgICAvLyBSZWFzc2lnbiBhIGdlbmVyaWMgbmFtZS5cbiAgICAgIGlmICgoZGF0YSA9IHByb2R1Y3QgfHwgbWFudWZhY3R1cmVyIHx8IG9zKSAmJlxuICAgICAgICAgIChwcm9kdWN0IHx8IG1hbnVmYWN0dXJlciB8fCAvXFxiKD86QW5kcm9pZHxTeW1iaWFuIE9TfFRhYmxldCBPU3x3ZWJPUylcXGIvLnRlc3Qob3MpKSkge1xuICAgICAgICBuYW1lID0gL1thLXpdKyg/OiBIYXQpPy9pLmV4ZWMoL1xcYkFuZHJvaWRcXGIvLnRlc3Qob3MpID8gb3MgOiBkYXRhKSArICcgQnJvd3Nlcic7XG4gICAgICB9XG4gICAgfVxuICAgIC8vIEFkZCBDaHJvbWUgdmVyc2lvbiB0byBkZXNjcmlwdGlvbiBmb3IgRWxlY3Ryb24uXG4gICAgZWxzZSBpZiAobmFtZSA9PSAnRWxlY3Ryb24nICYmIChkYXRhID0gKC9cXGJDaHJvbWVcXC8oW1xcZC5dKylcXGIvLmV4ZWModWEpIHx8IDApWzFdKSkge1xuICAgICAgZGVzY3JpcHRpb24ucHVzaCgnQ2hyb21pdW0gJyArIGRhdGEpO1xuICAgIH1cbiAgICAvLyBEZXRlY3Qgbm9uLU9wZXJhIChQcmVzdG8tYmFzZWQpIHZlcnNpb25zIChvcmRlciBpcyBpbXBvcnRhbnQpLlxuICAgIGlmICghdmVyc2lvbikge1xuICAgICAgdmVyc2lvbiA9IGdldFZlcnNpb24oW1xuICAgICAgICAnKD86Q2xvdWQ5fENyaU9TfENyTW98RWRnZXxGeGlPU3xJRU1vYmlsZXxJcm9ufE9wZXJhID9NaW5pfE9QaU9TfE9QUnxSYXZlbnxTYW1zdW5nQnJvd3NlcnxTaWxrKD8hL1tcXFxcZC5dKyQpKScsXG4gICAgICAgICdWZXJzaW9uJyxcbiAgICAgICAgcXVhbGlmeShuYW1lKSxcbiAgICAgICAgJyg/OkZpcmVmb3h8TWluZWZpZWxkfE5ldEZyb250KSdcbiAgICAgIF0pO1xuICAgIH1cbiAgICAvLyBEZXRlY3Qgc3R1YmJvcm4gbGF5b3V0IGVuZ2luZXMuXG4gICAgaWYgKChkYXRhID1cbiAgICAgICAgICBsYXlvdXQgPT0gJ2lDYWInICYmIHBhcnNlRmxvYXQodmVyc2lvbikgPiAzICYmICdXZWJLaXQnIHx8XG4gICAgICAgICAgL1xcYk9wZXJhXFxiLy50ZXN0KG5hbWUpICYmICgvXFxiT1BSXFxiLy50ZXN0KHVhKSA/ICdCbGluaycgOiAnUHJlc3RvJykgfHxcbiAgICAgICAgICAvXFxiKD86TWlkb3JpfE5vb2t8U2FmYXJpKVxcYi9pLnRlc3QodWEpICYmICEvXig/OlRyaWRlbnR8RWRnZUhUTUwpJC8udGVzdChsYXlvdXQpICYmICdXZWJLaXQnIHx8XG4gICAgICAgICAgIWxheW91dCAmJiAvXFxiTVNJRVxcYi9pLnRlc3QodWEpICYmIChvcyA9PSAnTWFjIE9TJyA/ICdUYXNtYW4nIDogJ1RyaWRlbnQnKSB8fFxuICAgICAgICAgIGxheW91dCA9PSAnV2ViS2l0JyAmJiAvXFxiUGxheVN0YXRpb25cXGIoPyEgVml0YVxcYikvaS50ZXN0KG5hbWUpICYmICdOZXRGcm9udCdcbiAgICAgICAgKSkge1xuICAgICAgbGF5b3V0ID0gW2RhdGFdO1xuICAgIH1cbiAgICAvLyBEZXRlY3QgV2luZG93cyBQaG9uZSA3IGRlc2t0b3AgbW9kZS5cbiAgICBpZiAobmFtZSA9PSAnSUUnICYmIChkYXRhID0gKC87ICooPzpYQkxXUHxadW5lV1ApKFxcZCspL2kuZXhlYyh1YSkgfHwgMClbMV0pKSB7XG4gICAgICBuYW1lICs9ICcgTW9iaWxlJztcbiAgICAgIG9zID0gJ1dpbmRvd3MgUGhvbmUgJyArICgvXFwrJC8udGVzdChkYXRhKSA/IGRhdGEgOiBkYXRhICsgJy54Jyk7XG4gICAgICBkZXNjcmlwdGlvbi51bnNoaWZ0KCdkZXNrdG9wIG1vZGUnKTtcbiAgICB9XG4gICAgLy8gRGV0ZWN0IFdpbmRvd3MgUGhvbmUgOC54IGRlc2t0b3AgbW9kZS5cbiAgICBlbHNlIGlmICgvXFxiV1BEZXNrdG9wXFxiL2kudGVzdCh1YSkpIHtcbiAgICAgIG5hbWUgPSAnSUUgTW9iaWxlJztcbiAgICAgIG9zID0gJ1dpbmRvd3MgUGhvbmUgOC54JztcbiAgICAgIGRlc2NyaXB0aW9uLnVuc2hpZnQoJ2Rlc2t0b3AgbW9kZScpO1xuICAgICAgdmVyc2lvbiB8fCAodmVyc2lvbiA9ICgvXFxicnY6KFtcXGQuXSspLy5leGVjKHVhKSB8fCAwKVsxXSk7XG4gICAgfVxuICAgIC8vIERldGVjdCBJRSAxMSBpZGVudGlmeWluZyBhcyBvdGhlciBicm93c2Vycy5cbiAgICBlbHNlIGlmIChuYW1lICE9ICdJRScgJiYgbGF5b3V0ID09ICdUcmlkZW50JyAmJiAoZGF0YSA9IC9cXGJydjooW1xcZC5dKykvLmV4ZWModWEpKSkge1xuICAgICAgaWYgKG5hbWUpIHtcbiAgICAgICAgZGVzY3JpcHRpb24ucHVzaCgnaWRlbnRpZnlpbmcgYXMgJyArIG5hbWUgKyAodmVyc2lvbiA/ICcgJyArIHZlcnNpb24gOiAnJykpO1xuICAgICAgfVxuICAgICAgbmFtZSA9ICdJRSc7XG4gICAgICB2ZXJzaW9uID0gZGF0YVsxXTtcbiAgICB9XG4gICAgLy8gTGV2ZXJhZ2UgZW52aXJvbm1lbnQgZmVhdHVyZXMuXG4gICAgaWYgKHVzZUZlYXR1cmVzKSB7XG4gICAgICAvLyBEZXRlY3Qgc2VydmVyLXNpZGUgZW52aXJvbm1lbnRzLlxuICAgICAgLy8gUmhpbm8gaGFzIGEgZ2xvYmFsIGZ1bmN0aW9uIHdoaWxlIG90aGVycyBoYXZlIGEgZ2xvYmFsIG9iamVjdC5cbiAgICAgIGlmIChpc0hvc3RUeXBlKGNvbnRleHQsICdnbG9iYWwnKSkge1xuICAgICAgICBpZiAoamF2YSkge1xuICAgICAgICAgIGRhdGEgPSBqYXZhLmxhbmcuU3lzdGVtO1xuICAgICAgICAgIGFyY2ggPSBkYXRhLmdldFByb3BlcnR5KCdvcy5hcmNoJyk7XG4gICAgICAgICAgb3MgPSBvcyB8fCBkYXRhLmdldFByb3BlcnR5KCdvcy5uYW1lJykgKyAnICcgKyBkYXRhLmdldFByb3BlcnR5KCdvcy52ZXJzaW9uJyk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHJoaW5vKSB7XG4gICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIHZlcnNpb24gPSBjb250ZXh0LnJlcXVpcmUoJ3JpbmdvL2VuZ2luZScpLnZlcnNpb24uam9pbignLicpO1xuICAgICAgICAgICAgbmFtZSA9ICdSaW5nb0pTJztcbiAgICAgICAgICB9IGNhdGNoKGUpIHtcbiAgICAgICAgICAgIGlmICgoZGF0YSA9IGNvbnRleHQuc3lzdGVtKSAmJiBkYXRhLmdsb2JhbC5zeXN0ZW0gPT0gY29udGV4dC5zeXN0ZW0pIHtcbiAgICAgICAgICAgICAgbmFtZSA9ICdOYXJ3aGFsJztcbiAgICAgICAgICAgICAgb3MgfHwgKG9zID0gZGF0YVswXS5vcyB8fCBudWxsKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKCFuYW1lKSB7XG4gICAgICAgICAgICBuYW1lID0gJ1JoaW5vJztcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAoXG4gICAgICAgICAgdHlwZW9mIGNvbnRleHQucHJvY2VzcyA9PSAnb2JqZWN0JyAmJiAhY29udGV4dC5wcm9jZXNzLmJyb3dzZXIgJiZcbiAgICAgICAgICAoZGF0YSA9IGNvbnRleHQucHJvY2VzcylcbiAgICAgICAgKSB7XG4gICAgICAgICAgaWYgKHR5cGVvZiBkYXRhLnZlcnNpb25zID09ICdvYmplY3QnKSB7XG4gICAgICAgICAgICBpZiAodHlwZW9mIGRhdGEudmVyc2lvbnMuZWxlY3Ryb24gPT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgICAgZGVzY3JpcHRpb24ucHVzaCgnTm9kZSAnICsgZGF0YS52ZXJzaW9ucy5ub2RlKTtcbiAgICAgICAgICAgICAgbmFtZSA9ICdFbGVjdHJvbic7XG4gICAgICAgICAgICAgIHZlcnNpb24gPSBkYXRhLnZlcnNpb25zLmVsZWN0cm9uO1xuICAgICAgICAgICAgfSBlbHNlIGlmICh0eXBlb2YgZGF0YS52ZXJzaW9ucy5udyA9PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgICBkZXNjcmlwdGlvbi5wdXNoKCdDaHJvbWl1bSAnICsgdmVyc2lvbiwgJ05vZGUgJyArIGRhdGEudmVyc2lvbnMubm9kZSk7XG4gICAgICAgICAgICAgIG5hbWUgPSAnTlcuanMnO1xuICAgICAgICAgICAgICB2ZXJzaW9uID0gZGF0YS52ZXJzaW9ucy5udztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKCFuYW1lKSB7XG4gICAgICAgICAgICBuYW1lID0gJ05vZGUuanMnO1xuICAgICAgICAgICAgYXJjaCA9IGRhdGEuYXJjaDtcbiAgICAgICAgICAgIG9zID0gZGF0YS5wbGF0Zm9ybTtcbiAgICAgICAgICAgIHZlcnNpb24gPSAvW1xcZC5dKy8uZXhlYyhkYXRhLnZlcnNpb24pO1xuICAgICAgICAgICAgdmVyc2lvbiA9IHZlcnNpb24gPyB2ZXJzaW9uWzBdIDogbnVsbDtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIC8vIERldGVjdCBBZG9iZSBBSVIuXG4gICAgICBlbHNlIGlmIChnZXRDbGFzc09mKChkYXRhID0gY29udGV4dC5ydW50aW1lKSkgPT0gYWlyUnVudGltZUNsYXNzKSB7XG4gICAgICAgIG5hbWUgPSAnQWRvYmUgQUlSJztcbiAgICAgICAgb3MgPSBkYXRhLmZsYXNoLnN5c3RlbS5DYXBhYmlsaXRpZXMub3M7XG4gICAgICB9XG4gICAgICAvLyBEZXRlY3QgUGhhbnRvbUpTLlxuICAgICAgZWxzZSBpZiAoZ2V0Q2xhc3NPZigoZGF0YSA9IGNvbnRleHQucGhhbnRvbSkpID09IHBoYW50b21DbGFzcykge1xuICAgICAgICBuYW1lID0gJ1BoYW50b21KUyc7XG4gICAgICAgIHZlcnNpb24gPSAoZGF0YSA9IGRhdGEudmVyc2lvbiB8fCBudWxsKSAmJiAoZGF0YS5tYWpvciArICcuJyArIGRhdGEubWlub3IgKyAnLicgKyBkYXRhLnBhdGNoKTtcbiAgICAgIH1cbiAgICAgIC8vIERldGVjdCBJRSBjb21wYXRpYmlsaXR5IG1vZGVzLlxuICAgICAgZWxzZSBpZiAodHlwZW9mIGRvYy5kb2N1bWVudE1vZGUgPT0gJ251bWJlcicgJiYgKGRhdGEgPSAvXFxiVHJpZGVudFxcLyhcXGQrKS9pLmV4ZWModWEpKSkge1xuICAgICAgICAvLyBXZSdyZSBpbiBjb21wYXRpYmlsaXR5IG1vZGUgd2hlbiB0aGUgVHJpZGVudCB2ZXJzaW9uICsgNCBkb2Vzbid0XG4gICAgICAgIC8vIGVxdWFsIHRoZSBkb2N1bWVudCBtb2RlLlxuICAgICAgICB2ZXJzaW9uID0gW3ZlcnNpb24sIGRvYy5kb2N1bWVudE1vZGVdO1xuICAgICAgICBpZiAoKGRhdGEgPSArZGF0YVsxXSArIDQpICE9IHZlcnNpb25bMV0pIHtcbiAgICAgICAgICBkZXNjcmlwdGlvbi5wdXNoKCdJRSAnICsgdmVyc2lvblsxXSArICcgbW9kZScpO1xuICAgICAgICAgIGxheW91dCAmJiAobGF5b3V0WzFdID0gJycpO1xuICAgICAgICAgIHZlcnNpb25bMV0gPSBkYXRhO1xuICAgICAgICB9XG4gICAgICAgIHZlcnNpb24gPSBuYW1lID09ICdJRScgPyBTdHJpbmcodmVyc2lvblsxXS50b0ZpeGVkKDEpKSA6IHZlcnNpb25bMF07XG4gICAgICB9XG4gICAgICAvLyBEZXRlY3QgSUUgMTEgbWFza2luZyBhcyBvdGhlciBicm93c2Vycy5cbiAgICAgIGVsc2UgaWYgKHR5cGVvZiBkb2MuZG9jdW1lbnRNb2RlID09ICdudW1iZXInICYmIC9eKD86Q2hyb21lfEZpcmVmb3gpXFxiLy50ZXN0KG5hbWUpKSB7XG4gICAgICAgIGRlc2NyaXB0aW9uLnB1c2goJ21hc2tpbmcgYXMgJyArIG5hbWUgKyAnICcgKyB2ZXJzaW9uKTtcbiAgICAgICAgbmFtZSA9ICdJRSc7XG4gICAgICAgIHZlcnNpb24gPSAnMTEuMCc7XG4gICAgICAgIGxheW91dCA9IFsnVHJpZGVudCddO1xuICAgICAgICBvcyA9ICdXaW5kb3dzJztcbiAgICAgIH1cbiAgICAgIG9zID0gb3MgJiYgZm9ybWF0KG9zKTtcbiAgICB9XG4gICAgLy8gRGV0ZWN0IHByZXJlbGVhc2UgcGhhc2VzLlxuICAgIGlmICh2ZXJzaW9uICYmIChkYXRhID1cbiAgICAgICAgICAvKD86W2FiXXxkcHxwcmV8W2FiXVxcZCtwcmUpKD86XFxkK1xcKz8pPyQvaS5leGVjKHZlcnNpb24pIHx8XG4gICAgICAgICAgLyg/OmFscGhhfGJldGEpKD86ID9cXGQpPy9pLmV4ZWModWEgKyAnOycgKyAodXNlRmVhdHVyZXMgJiYgbmF2LmFwcE1pbm9yVmVyc2lvbikpIHx8XG4gICAgICAgICAgL1xcYk1pbmVmaWVsZFxcYi9pLnRlc3QodWEpICYmICdhJ1xuICAgICAgICApKSB7XG4gICAgICBwcmVyZWxlYXNlID0gL2IvaS50ZXN0KGRhdGEpID8gJ2JldGEnIDogJ2FscGhhJztcbiAgICAgIHZlcnNpb24gPSB2ZXJzaW9uLnJlcGxhY2UoUmVnRXhwKGRhdGEgKyAnXFxcXCs/JCcpLCAnJykgK1xuICAgICAgICAocHJlcmVsZWFzZSA9PSAnYmV0YScgPyBiZXRhIDogYWxwaGEpICsgKC9cXGQrXFwrPy8uZXhlYyhkYXRhKSB8fCAnJyk7XG4gICAgfVxuICAgIC8vIERldGVjdCBGaXJlZm94IE1vYmlsZS5cbiAgICBpZiAobmFtZSA9PSAnRmVubmVjJyB8fCBuYW1lID09ICdGaXJlZm94JyAmJiAvXFxiKD86QW5kcm9pZHxGaXJlZm94IE9TKVxcYi8udGVzdChvcykpIHtcbiAgICAgIG5hbWUgPSAnRmlyZWZveCBNb2JpbGUnO1xuICAgIH1cbiAgICAvLyBPYnNjdXJlIE1heHRob24ncyB1bnJlbGlhYmxlIHZlcnNpb24uXG4gICAgZWxzZSBpZiAobmFtZSA9PSAnTWF4dGhvbicgJiYgdmVyc2lvbikge1xuICAgICAgdmVyc2lvbiA9IHZlcnNpb24ucmVwbGFjZSgvXFwuW1xcZC5dKy8sICcueCcpO1xuICAgIH1cbiAgICAvLyBEZXRlY3QgWGJveCAzNjAgYW5kIFhib3ggT25lLlxuICAgIGVsc2UgaWYgKC9cXGJYYm94XFxiL2kudGVzdChwcm9kdWN0KSkge1xuICAgICAgaWYgKHByb2R1Y3QgPT0gJ1hib3ggMzYwJykge1xuICAgICAgICBvcyA9IG51bGw7XG4gICAgICB9XG4gICAgICBpZiAocHJvZHVjdCA9PSAnWGJveCAzNjAnICYmIC9cXGJJRU1vYmlsZVxcYi8udGVzdCh1YSkpIHtcbiAgICAgICAgZGVzY3JpcHRpb24udW5zaGlmdCgnbW9iaWxlIG1vZGUnKTtcbiAgICAgIH1cbiAgICB9XG4gICAgLy8gQWRkIG1vYmlsZSBwb3N0Zml4LlxuICAgIGVsc2UgaWYgKCgvXig/OkNocm9tZXxJRXxPcGVyYSkkLy50ZXN0KG5hbWUpIHx8IG5hbWUgJiYgIXByb2R1Y3QgJiYgIS9Ccm93c2VyfE1vYmkvLnRlc3QobmFtZSkpICYmXG4gICAgICAgIChvcyA9PSAnV2luZG93cyBDRScgfHwgL01vYmkvaS50ZXN0KHVhKSkpIHtcbiAgICAgIG5hbWUgKz0gJyBNb2JpbGUnO1xuICAgIH1cbiAgICAvLyBEZXRlY3QgSUUgcGxhdGZvcm0gcHJldmlldy5cbiAgICBlbHNlIGlmIChuYW1lID09ICdJRScgJiYgdXNlRmVhdHVyZXMpIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIGlmIChjb250ZXh0LmV4dGVybmFsID09PSBudWxsKSB7XG4gICAgICAgICAgZGVzY3JpcHRpb24udW5zaGlmdCgncGxhdGZvcm0gcHJldmlldycpO1xuICAgICAgICB9XG4gICAgICB9IGNhdGNoKGUpIHtcbiAgICAgICAgZGVzY3JpcHRpb24udW5zaGlmdCgnZW1iZWRkZWQnKTtcbiAgICAgIH1cbiAgICB9XG4gICAgLy8gRGV0ZWN0IEJsYWNrQmVycnkgT1MgdmVyc2lvbi5cbiAgICAvLyBodHRwOi8vZG9jcy5ibGFja2JlcnJ5LmNvbS9lbi9kZXZlbG9wZXJzL2RlbGl2ZXJhYmxlcy8xODE2OS9IVFRQX2hlYWRlcnNfc2VudF9ieV9CQl9Ccm93c2VyXzEyMzQ5MTFfMTEuanNwXG4gICAgZWxzZSBpZiAoKC9cXGJCbGFja0JlcnJ5XFxiLy50ZXN0KHByb2R1Y3QpIHx8IC9cXGJCQjEwXFxiLy50ZXN0KHVhKSkgJiYgKGRhdGEgPVxuICAgICAgICAgIChSZWdFeHAocHJvZHVjdC5yZXBsYWNlKC8gKy9nLCAnIConKSArICcvKFsuXFxcXGRdKyknLCAnaScpLmV4ZWModWEpIHx8IDApWzFdIHx8XG4gICAgICAgICAgdmVyc2lvblxuICAgICAgICApKSB7XG4gICAgICBkYXRhID0gW2RhdGEsIC9CQjEwLy50ZXN0KHVhKV07XG4gICAgICBvcyA9IChkYXRhWzFdID8gKHByb2R1Y3QgPSBudWxsLCBtYW51ZmFjdHVyZXIgPSAnQmxhY2tCZXJyeScpIDogJ0RldmljZSBTb2Z0d2FyZScpICsgJyAnICsgZGF0YVswXTtcbiAgICAgIHZlcnNpb24gPSBudWxsO1xuICAgIH1cbiAgICAvLyBEZXRlY3QgT3BlcmEgaWRlbnRpZnlpbmcvbWFza2luZyBpdHNlbGYgYXMgYW5vdGhlciBicm93c2VyLlxuICAgIC8vIGh0dHA6Ly93d3cub3BlcmEuY29tL3N1cHBvcnQva2Ivdmlldy84NDMvXG4gICAgZWxzZSBpZiAodGhpcyAhPSBmb3JPd24gJiYgcHJvZHVjdCAhPSAnV2lpJyAmJiAoXG4gICAgICAgICAgKHVzZUZlYXR1cmVzICYmIG9wZXJhKSB8fFxuICAgICAgICAgICgvT3BlcmEvLnRlc3QobmFtZSkgJiYgL1xcYig/Ok1TSUV8RmlyZWZveClcXGIvaS50ZXN0KHVhKSkgfHxcbiAgICAgICAgICAobmFtZSA9PSAnRmlyZWZveCcgJiYgL1xcYk9TIFggKD86XFxkK1xcLil7Mix9Ly50ZXN0KG9zKSkgfHxcbiAgICAgICAgICAobmFtZSA9PSAnSUUnICYmIChcbiAgICAgICAgICAgIChvcyAmJiAhL15XaW4vLnRlc3Qob3MpICYmIHZlcnNpb24gPiA1LjUpIHx8XG4gICAgICAgICAgICAvXFxiV2luZG93cyBYUFxcYi8udGVzdChvcykgJiYgdmVyc2lvbiA+IDggfHxcbiAgICAgICAgICAgIHZlcnNpb24gPT0gOCAmJiAhL1xcYlRyaWRlbnRcXGIvLnRlc3QodWEpXG4gICAgICAgICAgKSlcbiAgICAgICAgKSAmJiAhcmVPcGVyYS50ZXN0KChkYXRhID0gcGFyc2UuY2FsbChmb3JPd24sIHVhLnJlcGxhY2UocmVPcGVyYSwgJycpICsgJzsnKSkpICYmIGRhdGEubmFtZSkge1xuICAgICAgLy8gV2hlbiBcImlkZW50aWZ5aW5nXCIsIHRoZSBVQSBjb250YWlucyBib3RoIE9wZXJhIGFuZCB0aGUgb3RoZXIgYnJvd3NlcidzIG5hbWUuXG4gICAgICBkYXRhID0gJ2luZyBhcyAnICsgZGF0YS5uYW1lICsgKChkYXRhID0gZGF0YS52ZXJzaW9uKSA/ICcgJyArIGRhdGEgOiAnJyk7XG4gICAgICBpZiAocmVPcGVyYS50ZXN0KG5hbWUpKSB7XG4gICAgICAgIGlmICgvXFxiSUVcXGIvLnRlc3QoZGF0YSkgJiYgb3MgPT0gJ01hYyBPUycpIHtcbiAgICAgICAgICBvcyA9IG51bGw7XG4gICAgICAgIH1cbiAgICAgICAgZGF0YSA9ICdpZGVudGlmeScgKyBkYXRhO1xuICAgICAgfVxuICAgICAgLy8gV2hlbiBcIm1hc2tpbmdcIiwgdGhlIFVBIGNvbnRhaW5zIG9ubHkgdGhlIG90aGVyIGJyb3dzZXIncyBuYW1lLlxuICAgICAgZWxzZSB7XG4gICAgICAgIGRhdGEgPSAnbWFzaycgKyBkYXRhO1xuICAgICAgICBpZiAob3BlcmFDbGFzcykge1xuICAgICAgICAgIG5hbWUgPSBmb3JtYXQob3BlcmFDbGFzcy5yZXBsYWNlKC8oW2Etel0pKFtBLVpdKS9nLCAnJDEgJDInKSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgbmFtZSA9ICdPcGVyYSc7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKC9cXGJJRVxcYi8udGVzdChkYXRhKSkge1xuICAgICAgICAgIG9zID0gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIXVzZUZlYXR1cmVzKSB7XG4gICAgICAgICAgdmVyc2lvbiA9IG51bGw7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGxheW91dCA9IFsnUHJlc3RvJ107XG4gICAgICBkZXNjcmlwdGlvbi5wdXNoKGRhdGEpO1xuICAgIH1cbiAgICAvLyBEZXRlY3QgV2ViS2l0IE5pZ2h0bHkgYW5kIGFwcHJveGltYXRlIENocm9tZS9TYWZhcmkgdmVyc2lvbnMuXG4gICAgaWYgKChkYXRhID0gKC9cXGJBcHBsZVdlYktpdFxcLyhbXFxkLl0rXFwrPykvaS5leGVjKHVhKSB8fCAwKVsxXSkpIHtcbiAgICAgIC8vIENvcnJlY3QgYnVpbGQgbnVtYmVyIGZvciBudW1lcmljIGNvbXBhcmlzb24uXG4gICAgICAvLyAoZS5nLiBcIjUzMi41XCIgYmVjb21lcyBcIjUzMi4wNVwiKVxuICAgICAgZGF0YSA9IFtwYXJzZUZsb2F0KGRhdGEucmVwbGFjZSgvXFwuKFxcZCkkLywgJy4wJDEnKSksIGRhdGFdO1xuICAgICAgLy8gTmlnaHRseSBidWlsZHMgYXJlIHBvc3RmaXhlZCB3aXRoIGEgXCIrXCIuXG4gICAgICBpZiAobmFtZSA9PSAnU2FmYXJpJyAmJiBkYXRhWzFdLnNsaWNlKC0xKSA9PSAnKycpIHtcbiAgICAgICAgbmFtZSA9ICdXZWJLaXQgTmlnaHRseSc7XG4gICAgICAgIHByZXJlbGVhc2UgPSAnYWxwaGEnO1xuICAgICAgICB2ZXJzaW9uID0gZGF0YVsxXS5zbGljZSgwLCAtMSk7XG4gICAgICB9XG4gICAgICAvLyBDbGVhciBpbmNvcnJlY3QgYnJvd3NlciB2ZXJzaW9ucy5cbiAgICAgIGVsc2UgaWYgKHZlcnNpb24gPT0gZGF0YVsxXSB8fFxuICAgICAgICAgIHZlcnNpb24gPT0gKGRhdGFbMl0gPSAoL1xcYlNhZmFyaVxcLyhbXFxkLl0rXFwrPykvaS5leGVjKHVhKSB8fCAwKVsxXSkpIHtcbiAgICAgICAgdmVyc2lvbiA9IG51bGw7XG4gICAgICB9XG4gICAgICAvLyBVc2UgdGhlIGZ1bGwgQ2hyb21lIHZlcnNpb24gd2hlbiBhdmFpbGFibGUuXG4gICAgICBkYXRhWzFdID0gKC9cXGJDaHJvbWVcXC8oW1xcZC5dKykvaS5leGVjKHVhKSB8fCAwKVsxXTtcbiAgICAgIC8vIERldGVjdCBCbGluayBsYXlvdXQgZW5naW5lLlxuICAgICAgaWYgKGRhdGFbMF0gPT0gNTM3LjM2ICYmIGRhdGFbMl0gPT0gNTM3LjM2ICYmIHBhcnNlRmxvYXQoZGF0YVsxXSkgPj0gMjggJiYgbGF5b3V0ID09ICdXZWJLaXQnKSB7XG4gICAgICAgIGxheW91dCA9IFsnQmxpbmsnXTtcbiAgICAgIH1cbiAgICAgIC8vIERldGVjdCBKYXZhU2NyaXB0Q29yZS5cbiAgICAgIC8vIGh0dHA6Ly9zdGFja292ZXJmbG93LmNvbS9xdWVzdGlvbnMvNjc2ODQ3NC9ob3ctY2FuLWktZGV0ZWN0LXdoaWNoLWphdmFzY3JpcHQtZW5naW5lLXY4LW9yLWpzYy1pcy11c2VkLWF0LXJ1bnRpbWUtaW4tYW5kcm9pXG4gICAgICBpZiAoIXVzZUZlYXR1cmVzIHx8ICghbGlrZUNocm9tZSAmJiAhZGF0YVsxXSkpIHtcbiAgICAgICAgbGF5b3V0ICYmIChsYXlvdXRbMV0gPSAnbGlrZSBTYWZhcmknKTtcbiAgICAgICAgZGF0YSA9IChkYXRhID0gZGF0YVswXSwgZGF0YSA8IDQwMCA/IDEgOiBkYXRhIDwgNTAwID8gMiA6IGRhdGEgPCA1MjYgPyAzIDogZGF0YSA8IDUzMyA/IDQgOiBkYXRhIDwgNTM0ID8gJzQrJyA6IGRhdGEgPCA1MzUgPyA1IDogZGF0YSA8IDUzNyA/IDYgOiBkYXRhIDwgNTM4ID8gNyA6IGRhdGEgPCA2MDEgPyA4IDogJzgnKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGxheW91dCAmJiAobGF5b3V0WzFdID0gJ2xpa2UgQ2hyb21lJyk7XG4gICAgICAgIGRhdGEgPSBkYXRhWzFdIHx8IChkYXRhID0gZGF0YVswXSwgZGF0YSA8IDUzMCA/IDEgOiBkYXRhIDwgNTMyID8gMiA6IGRhdGEgPCA1MzIuMDUgPyAzIDogZGF0YSA8IDUzMyA/IDQgOiBkYXRhIDwgNTM0LjAzID8gNSA6IGRhdGEgPCA1MzQuMDcgPyA2IDogZGF0YSA8IDUzNC4xMCA/IDcgOiBkYXRhIDwgNTM0LjEzID8gOCA6IGRhdGEgPCA1MzQuMTYgPyA5IDogZGF0YSA8IDUzNC4yNCA/IDEwIDogZGF0YSA8IDUzNC4zMCA/IDExIDogZGF0YSA8IDUzNS4wMSA/IDEyIDogZGF0YSA8IDUzNS4wMiA/ICcxMysnIDogZGF0YSA8IDUzNS4wNyA/IDE1IDogZGF0YSA8IDUzNS4xMSA/IDE2IDogZGF0YSA8IDUzNS4xOSA/IDE3IDogZGF0YSA8IDUzNi4wNSA/IDE4IDogZGF0YSA8IDUzNi4xMCA/IDE5IDogZGF0YSA8IDUzNy4wMSA/IDIwIDogZGF0YSA8IDUzNy4xMSA/ICcyMSsnIDogZGF0YSA8IDUzNy4xMyA/IDIzIDogZGF0YSA8IDUzNy4xOCA/IDI0IDogZGF0YSA8IDUzNy4yNCA/IDI1IDogZGF0YSA8IDUzNy4zNiA/IDI2IDogbGF5b3V0ICE9ICdCbGluaycgPyAnMjcnIDogJzI4Jyk7XG4gICAgICB9XG4gICAgICAvLyBBZGQgdGhlIHBvc3RmaXggb2YgXCIueFwiIG9yIFwiK1wiIGZvciBhcHByb3hpbWF0ZSB2ZXJzaW9ucy5cbiAgICAgIGxheW91dCAmJiAobGF5b3V0WzFdICs9ICcgJyArIChkYXRhICs9IHR5cGVvZiBkYXRhID09ICdudW1iZXInID8gJy54JyA6IC9bLitdLy50ZXN0KGRhdGEpID8gJycgOiAnKycpKTtcbiAgICAgIC8vIE9ic2N1cmUgdmVyc2lvbiBmb3Igc29tZSBTYWZhcmkgMS0yIHJlbGVhc2VzLlxuICAgICAgaWYgKG5hbWUgPT0gJ1NhZmFyaScgJiYgKCF2ZXJzaW9uIHx8IHBhcnNlSW50KHZlcnNpb24pID4gNDUpKSB7XG4gICAgICAgIHZlcnNpb24gPSBkYXRhO1xuICAgICAgfVxuICAgIH1cbiAgICAvLyBEZXRlY3QgT3BlcmEgZGVza3RvcCBtb2Rlcy5cbiAgICBpZiAobmFtZSA9PSAnT3BlcmEnICYmICAoZGF0YSA9IC9cXGJ6Ym92fHp2YXYkLy5leGVjKG9zKSkpIHtcbiAgICAgIG5hbWUgKz0gJyAnO1xuICAgICAgZGVzY3JpcHRpb24udW5zaGlmdCgnZGVza3RvcCBtb2RlJyk7XG4gICAgICBpZiAoZGF0YSA9PSAnenZhdicpIHtcbiAgICAgICAgbmFtZSArPSAnTWluaSc7XG4gICAgICAgIHZlcnNpb24gPSBudWxsO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbmFtZSArPSAnTW9iaWxlJztcbiAgICAgIH1cbiAgICAgIG9zID0gb3MucmVwbGFjZShSZWdFeHAoJyAqJyArIGRhdGEgKyAnJCcpLCAnJyk7XG4gICAgfVxuICAgIC8vIERldGVjdCBDaHJvbWUgZGVza3RvcCBtb2RlLlxuICAgIGVsc2UgaWYgKG5hbWUgPT0gJ1NhZmFyaScgJiYgL1xcYkNocm9tZVxcYi8uZXhlYyhsYXlvdXQgJiYgbGF5b3V0WzFdKSkge1xuICAgICAgZGVzY3JpcHRpb24udW5zaGlmdCgnZGVza3RvcCBtb2RlJyk7XG4gICAgICBuYW1lID0gJ0Nocm9tZSBNb2JpbGUnO1xuICAgICAgdmVyc2lvbiA9IG51bGw7XG5cbiAgICAgIGlmICgvXFxiT1MgWFxcYi8udGVzdChvcykpIHtcbiAgICAgICAgbWFudWZhY3R1cmVyID0gJ0FwcGxlJztcbiAgICAgICAgb3MgPSAnaU9TIDQuMysnO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgb3MgPSBudWxsO1xuICAgICAgfVxuICAgIH1cbiAgICAvLyBTdHJpcCBpbmNvcnJlY3QgT1MgdmVyc2lvbnMuXG4gICAgaWYgKHZlcnNpb24gJiYgdmVyc2lvbi5pbmRleE9mKChkYXRhID0gL1tcXGQuXSskLy5leGVjKG9zKSkpID09IDAgJiZcbiAgICAgICAgdWEuaW5kZXhPZignLycgKyBkYXRhICsgJy0nKSA+IC0xKSB7XG4gICAgICBvcyA9IHRyaW0ob3MucmVwbGFjZShkYXRhLCAnJykpO1xuICAgIH1cbiAgICAvLyBBZGQgbGF5b3V0IGVuZ2luZS5cbiAgICBpZiAobGF5b3V0ICYmICEvXFxiKD86QXZhbnR8Tm9vaylcXGIvLnRlc3QobmFtZSkgJiYgKFxuICAgICAgICAvQnJvd3NlcnxMdW5hc2NhcGV8TWF4dGhvbi8udGVzdChuYW1lKSB8fFxuICAgICAgICBuYW1lICE9ICdTYWZhcmknICYmIC9eaU9TLy50ZXN0KG9zKSAmJiAvXFxiU2FmYXJpXFxiLy50ZXN0KGxheW91dFsxXSkgfHxcbiAgICAgICAgL14oPzpBZG9iZXxBcm9yYXxCcmVhY2h8TWlkb3JpfE9wZXJhfFBoYW50b218UmVrb25xfFJvY2t8U2Ftc3VuZyBJbnRlcm5ldHxTbGVpcG5pcnxXZWIpLy50ZXN0KG5hbWUpICYmIGxheW91dFsxXSkpIHtcbiAgICAgIC8vIERvbid0IGFkZCBsYXlvdXQgZGV0YWlscyB0byBkZXNjcmlwdGlvbiBpZiB0aGV5IGFyZSBmYWxzZXkuXG4gICAgICAoZGF0YSA9IGxheW91dFtsYXlvdXQubGVuZ3RoIC0gMV0pICYmIGRlc2NyaXB0aW9uLnB1c2goZGF0YSk7XG4gICAgfVxuICAgIC8vIENvbWJpbmUgY29udGV4dHVhbCBpbmZvcm1hdGlvbi5cbiAgICBpZiAoZGVzY3JpcHRpb24ubGVuZ3RoKSB7XG4gICAgICBkZXNjcmlwdGlvbiA9IFsnKCcgKyBkZXNjcmlwdGlvbi5qb2luKCc7ICcpICsgJyknXTtcbiAgICB9XG4gICAgLy8gQXBwZW5kIG1hbnVmYWN0dXJlciB0byBkZXNjcmlwdGlvbi5cbiAgICBpZiAobWFudWZhY3R1cmVyICYmIHByb2R1Y3QgJiYgcHJvZHVjdC5pbmRleE9mKG1hbnVmYWN0dXJlcikgPCAwKSB7XG4gICAgICBkZXNjcmlwdGlvbi5wdXNoKCdvbiAnICsgbWFudWZhY3R1cmVyKTtcbiAgICB9XG4gICAgLy8gQXBwZW5kIHByb2R1Y3QgdG8gZGVzY3JpcHRpb24uXG4gICAgaWYgKHByb2R1Y3QpIHtcbiAgICAgIGRlc2NyaXB0aW9uLnB1c2goKC9eb24gLy50ZXN0KGRlc2NyaXB0aW9uW2Rlc2NyaXB0aW9uLmxlbmd0aCAtIDFdKSA/ICcnIDogJ29uICcpICsgcHJvZHVjdCk7XG4gICAgfVxuICAgIC8vIFBhcnNlIHRoZSBPUyBpbnRvIGFuIG9iamVjdC5cbiAgICBpZiAob3MpIHtcbiAgICAgIGRhdGEgPSAvIChbXFxkLitdKykkLy5leGVjKG9zKTtcbiAgICAgIGlzU3BlY2lhbENhc2VkT1MgPSBkYXRhICYmIG9zLmNoYXJBdChvcy5sZW5ndGggLSBkYXRhWzBdLmxlbmd0aCAtIDEpID09ICcvJztcbiAgICAgIG9zID0ge1xuICAgICAgICAnYXJjaGl0ZWN0dXJlJzogMzIsXG4gICAgICAgICdmYW1pbHknOiAoZGF0YSAmJiAhaXNTcGVjaWFsQ2FzZWRPUykgPyBvcy5yZXBsYWNlKGRhdGFbMF0sICcnKSA6IG9zLFxuICAgICAgICAndmVyc2lvbic6IGRhdGEgPyBkYXRhWzFdIDogbnVsbCxcbiAgICAgICAgJ3RvU3RyaW5nJzogZnVuY3Rpb24oKSB7XG4gICAgICAgICAgdmFyIHZlcnNpb24gPSB0aGlzLnZlcnNpb247XG4gICAgICAgICAgcmV0dXJuIHRoaXMuZmFtaWx5ICsgKCh2ZXJzaW9uICYmICFpc1NwZWNpYWxDYXNlZE9TKSA/ICcgJyArIHZlcnNpb24gOiAnJykgKyAodGhpcy5hcmNoaXRlY3R1cmUgPT0gNjQgPyAnIDY0LWJpdCcgOiAnJyk7XG4gICAgICAgIH1cbiAgICAgIH07XG4gICAgfVxuICAgIC8vIEFkZCBicm93c2VyL09TIGFyY2hpdGVjdHVyZS5cbiAgICBpZiAoKGRhdGEgPSAvXFxiKD86QU1EfElBfFdpbnxXT1d8eDg2X3x4KTY0XFxiL2kuZXhlYyhhcmNoKSkgJiYgIS9cXGJpNjg2XFxiL2kudGVzdChhcmNoKSkge1xuICAgICAgaWYgKG9zKSB7XG4gICAgICAgIG9zLmFyY2hpdGVjdHVyZSA9IDY0O1xuICAgICAgICBvcy5mYW1pbHkgPSBvcy5mYW1pbHkucmVwbGFjZShSZWdFeHAoJyAqJyArIGRhdGEpLCAnJyk7XG4gICAgICB9XG4gICAgICBpZiAoXG4gICAgICAgICAgbmFtZSAmJiAoL1xcYldPVzY0XFxiL2kudGVzdCh1YSkgfHxcbiAgICAgICAgICAodXNlRmVhdHVyZXMgJiYgL1xcdyg/Ojg2fDMyKSQvLnRlc3QobmF2LmNwdUNsYXNzIHx8IG5hdi5wbGF0Zm9ybSkgJiYgIS9cXGJXaW42NDsgeDY0XFxiL2kudGVzdCh1YSkpKVxuICAgICAgKSB7XG4gICAgICAgIGRlc2NyaXB0aW9uLnVuc2hpZnQoJzMyLWJpdCcpO1xuICAgICAgfVxuICAgIH1cbiAgICAvLyBDaHJvbWUgMzkgYW5kIGFib3ZlIG9uIE9TIFggaXMgYWx3YXlzIDY0LWJpdC5cbiAgICBlbHNlIGlmIChcbiAgICAgICAgb3MgJiYgL15PUyBYLy50ZXN0KG9zLmZhbWlseSkgJiZcbiAgICAgICAgbmFtZSA9PSAnQ2hyb21lJyAmJiBwYXJzZUZsb2F0KHZlcnNpb24pID49IDM5XG4gICAgKSB7XG4gICAgICBvcy5hcmNoaXRlY3R1cmUgPSA2NDtcbiAgICB9XG5cbiAgICB1YSB8fCAodWEgPSBudWxsKTtcblxuICAgIC8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cblxuICAgIC8qKlxuICAgICAqIFRoZSBwbGF0Zm9ybSBvYmplY3QuXG4gICAgICpcbiAgICAgKiBAbmFtZSBwbGF0Zm9ybVxuICAgICAqIEB0eXBlIE9iamVjdFxuICAgICAqL1xuICAgIHZhciBwbGF0Zm9ybSA9IHt9O1xuXG4gICAgLyoqXG4gICAgICogVGhlIHBsYXRmb3JtIGRlc2NyaXB0aW9uLlxuICAgICAqXG4gICAgICogQG1lbWJlck9mIHBsYXRmb3JtXG4gICAgICogQHR5cGUgc3RyaW5nfG51bGxcbiAgICAgKi9cbiAgICBwbGF0Zm9ybS5kZXNjcmlwdGlvbiA9IHVhO1xuXG4gICAgLyoqXG4gICAgICogVGhlIG5hbWUgb2YgdGhlIGJyb3dzZXIncyBsYXlvdXQgZW5naW5lLlxuICAgICAqXG4gICAgICogVGhlIGxpc3Qgb2YgY29tbW9uIGxheW91dCBlbmdpbmVzIGluY2x1ZGU6XG4gICAgICogXCJCbGlua1wiLCBcIkVkZ2VIVE1MXCIsIFwiR2Vja29cIiwgXCJUcmlkZW50XCIgYW5kIFwiV2ViS2l0XCJcbiAgICAgKlxuICAgICAqIEBtZW1iZXJPZiBwbGF0Zm9ybVxuICAgICAqIEB0eXBlIHN0cmluZ3xudWxsXG4gICAgICovXG4gICAgcGxhdGZvcm0ubGF5b3V0ID0gbGF5b3V0ICYmIGxheW91dFswXTtcblxuICAgIC8qKlxuICAgICAqIFRoZSBuYW1lIG9mIHRoZSBwcm9kdWN0J3MgbWFudWZhY3R1cmVyLlxuICAgICAqXG4gICAgICogVGhlIGxpc3Qgb2YgbWFudWZhY3R1cmVycyBpbmNsdWRlOlxuICAgICAqIFwiQXBwbGVcIiwgXCJBcmNob3NcIiwgXCJBbWF6b25cIiwgXCJBc3VzXCIsIFwiQmFybmVzICYgTm9ibGVcIiwgXCJCbGFja0JlcnJ5XCIsXG4gICAgICogXCJHb29nbGVcIiwgXCJIUFwiLCBcIkhUQ1wiLCBcIkxHXCIsIFwiTWljcm9zb2Z0XCIsIFwiTW90b3JvbGFcIiwgXCJOaW50ZW5kb1wiLFxuICAgICAqIFwiTm9raWFcIiwgXCJTYW1zdW5nXCIgYW5kIFwiU29ueVwiXG4gICAgICpcbiAgICAgKiBAbWVtYmVyT2YgcGxhdGZvcm1cbiAgICAgKiBAdHlwZSBzdHJpbmd8bnVsbFxuICAgICAqL1xuICAgIHBsYXRmb3JtLm1hbnVmYWN0dXJlciA9IG1hbnVmYWN0dXJlcjtcblxuICAgIC8qKlxuICAgICAqIFRoZSBuYW1lIG9mIHRoZSBicm93c2VyL2Vudmlyb25tZW50LlxuICAgICAqXG4gICAgICogVGhlIGxpc3Qgb2YgY29tbW9uIGJyb3dzZXIgbmFtZXMgaW5jbHVkZTpcbiAgICAgKiBcIkNocm9tZVwiLCBcIkVsZWN0cm9uXCIsIFwiRmlyZWZveFwiLCBcIkZpcmVmb3ggZm9yIGlPU1wiLCBcIklFXCIsXG4gICAgICogXCJNaWNyb3NvZnQgRWRnZVwiLCBcIlBoYW50b21KU1wiLCBcIlNhZmFyaVwiLCBcIlNlYU1vbmtleVwiLCBcIlNpbGtcIixcbiAgICAgKiBcIk9wZXJhIE1pbmlcIiBhbmQgXCJPcGVyYVwiXG4gICAgICpcbiAgICAgKiBNb2JpbGUgdmVyc2lvbnMgb2Ygc29tZSBicm93c2VycyBoYXZlIFwiTW9iaWxlXCIgYXBwZW5kZWQgdG8gdGhlaXIgbmFtZTpcbiAgICAgKiBlZy4gXCJDaHJvbWUgTW9iaWxlXCIsIFwiRmlyZWZveCBNb2JpbGVcIiwgXCJJRSBNb2JpbGVcIiBhbmQgXCJPcGVyYSBNb2JpbGVcIlxuICAgICAqXG4gICAgICogQG1lbWJlck9mIHBsYXRmb3JtXG4gICAgICogQHR5cGUgc3RyaW5nfG51bGxcbiAgICAgKi9cbiAgICBwbGF0Zm9ybS5uYW1lID0gbmFtZTtcblxuICAgIC8qKlxuICAgICAqIFRoZSBhbHBoYS9iZXRhIHJlbGVhc2UgaW5kaWNhdG9yLlxuICAgICAqXG4gICAgICogQG1lbWJlck9mIHBsYXRmb3JtXG4gICAgICogQHR5cGUgc3RyaW5nfG51bGxcbiAgICAgKi9cbiAgICBwbGF0Zm9ybS5wcmVyZWxlYXNlID0gcHJlcmVsZWFzZTtcblxuICAgIC8qKlxuICAgICAqIFRoZSBuYW1lIG9mIHRoZSBwcm9kdWN0IGhvc3RpbmcgdGhlIGJyb3dzZXIuXG4gICAgICpcbiAgICAgKiBUaGUgbGlzdCBvZiBjb21tb24gcHJvZHVjdHMgaW5jbHVkZTpcbiAgICAgKlxuICAgICAqIFwiQmxhY2tCZXJyeVwiLCBcIkdhbGF4eSBTNFwiLCBcIkx1bWlhXCIsIFwiaVBhZFwiLCBcImlQb2RcIiwgXCJpUGhvbmVcIiwgXCJLaW5kbGVcIixcbiAgICAgKiBcIktpbmRsZSBGaXJlXCIsIFwiTmV4dXNcIiwgXCJOb29rXCIsIFwiUGxheUJvb2tcIiwgXCJUb3VjaFBhZFwiIGFuZCBcIlRyYW5zZm9ybWVyXCJcbiAgICAgKlxuICAgICAqIEBtZW1iZXJPZiBwbGF0Zm9ybVxuICAgICAqIEB0eXBlIHN0cmluZ3xudWxsXG4gICAgICovXG4gICAgcGxhdGZvcm0ucHJvZHVjdCA9IHByb2R1Y3Q7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYnJvd3NlcidzIHVzZXIgYWdlbnQgc3RyaW5nLlxuICAgICAqXG4gICAgICogQG1lbWJlck9mIHBsYXRmb3JtXG4gICAgICogQHR5cGUgc3RyaW5nfG51bGxcbiAgICAgKi9cbiAgICBwbGF0Zm9ybS51YSA9IHVhO1xuXG4gICAgLyoqXG4gICAgICogVGhlIGJyb3dzZXIvZW52aXJvbm1lbnQgdmVyc2lvbi5cbiAgICAgKlxuICAgICAqIEBtZW1iZXJPZiBwbGF0Zm9ybVxuICAgICAqIEB0eXBlIHN0cmluZ3xudWxsXG4gICAgICovXG4gICAgcGxhdGZvcm0udmVyc2lvbiA9IG5hbWUgJiYgdmVyc2lvbjtcblxuICAgIC8qKlxuICAgICAqIFRoZSBuYW1lIG9mIHRoZSBvcGVyYXRpbmcgc3lzdGVtLlxuICAgICAqXG4gICAgICogQG1lbWJlck9mIHBsYXRmb3JtXG4gICAgICogQHR5cGUgT2JqZWN0XG4gICAgICovXG4gICAgcGxhdGZvcm0ub3MgPSBvcyB8fCB7XG5cbiAgICAgIC8qKlxuICAgICAgICogVGhlIENQVSBhcmNoaXRlY3R1cmUgdGhlIE9TIGlzIGJ1aWx0IGZvci5cbiAgICAgICAqXG4gICAgICAgKiBAbWVtYmVyT2YgcGxhdGZvcm0ub3NcbiAgICAgICAqIEB0eXBlIG51bWJlcnxudWxsXG4gICAgICAgKi9cbiAgICAgICdhcmNoaXRlY3R1cmUnOiBudWxsLFxuXG4gICAgICAvKipcbiAgICAgICAqIFRoZSBmYW1pbHkgb2YgdGhlIE9TLlxuICAgICAgICpcbiAgICAgICAqIENvbW1vbiB2YWx1ZXMgaW5jbHVkZTpcbiAgICAgICAqIFwiV2luZG93c1wiLCBcIldpbmRvd3MgU2VydmVyIDIwMDggUjIgLyA3XCIsIFwiV2luZG93cyBTZXJ2ZXIgMjAwOCAvIFZpc3RhXCIsXG4gICAgICAgKiBcIldpbmRvd3MgWFBcIiwgXCJPUyBYXCIsIFwiVWJ1bnR1XCIsIFwiRGViaWFuXCIsIFwiRmVkb3JhXCIsIFwiUmVkIEhhdFwiLCBcIlN1U0VcIixcbiAgICAgICAqIFwiQW5kcm9pZFwiLCBcImlPU1wiIGFuZCBcIldpbmRvd3MgUGhvbmVcIlxuICAgICAgICpcbiAgICAgICAqIEBtZW1iZXJPZiBwbGF0Zm9ybS5vc1xuICAgICAgICogQHR5cGUgc3RyaW5nfG51bGxcbiAgICAgICAqL1xuICAgICAgJ2ZhbWlseSc6IG51bGwsXG5cbiAgICAgIC8qKlxuICAgICAgICogVGhlIHZlcnNpb24gb2YgdGhlIE9TLlxuICAgICAgICpcbiAgICAgICAqIEBtZW1iZXJPZiBwbGF0Zm9ybS5vc1xuICAgICAgICogQHR5cGUgc3RyaW5nfG51bGxcbiAgICAgICAqL1xuICAgICAgJ3ZlcnNpb24nOiBudWxsLFxuXG4gICAgICAvKipcbiAgICAgICAqIFJldHVybnMgdGhlIE9TIHN0cmluZy5cbiAgICAgICAqXG4gICAgICAgKiBAbWVtYmVyT2YgcGxhdGZvcm0ub3NcbiAgICAgICAqIEByZXR1cm5zIHtzdHJpbmd9IFRoZSBPUyBzdHJpbmcuXG4gICAgICAgKi9cbiAgICAgICd0b1N0cmluZyc6IGZ1bmN0aW9uKCkgeyByZXR1cm4gJ251bGwnOyB9XG4gICAgfTtcblxuICAgIHBsYXRmb3JtLnBhcnNlID0gcGFyc2U7XG4gICAgcGxhdGZvcm0udG9TdHJpbmcgPSB0b1N0cmluZ1BsYXRmb3JtO1xuXG4gICAgaWYgKHBsYXRmb3JtLnZlcnNpb24pIHtcbiAgICAgIGRlc2NyaXB0aW9uLnVuc2hpZnQodmVyc2lvbik7XG4gICAgfVxuICAgIGlmIChwbGF0Zm9ybS5uYW1lKSB7XG4gICAgICBkZXNjcmlwdGlvbi51bnNoaWZ0KG5hbWUpO1xuICAgIH1cbiAgICBpZiAob3MgJiYgbmFtZSAmJiAhKG9zID09IFN0cmluZyhvcykuc3BsaXQoJyAnKVswXSAmJiAob3MgPT0gbmFtZS5zcGxpdCgnICcpWzBdIHx8IHByb2R1Y3QpKSkge1xuICAgICAgZGVzY3JpcHRpb24ucHVzaChwcm9kdWN0ID8gJygnICsgb3MgKyAnKScgOiAnb24gJyArIG9zKTtcbiAgICB9XG4gICAgaWYgKGRlc2NyaXB0aW9uLmxlbmd0aCkge1xuICAgICAgcGxhdGZvcm0uZGVzY3JpcHRpb24gPSBkZXNjcmlwdGlvbi5qb2luKCcgJyk7XG4gICAgfVxuICAgIHJldHVybiBwbGF0Zm9ybTtcbiAgfVxuXG4gIC8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuXG4gIC8vIEV4cG9ydCBwbGF0Zm9ybS5cbiAgdmFyIHBsYXRmb3JtID0gcGFyc2UoKTtcblxuICAvLyBTb21lIEFNRCBidWlsZCBvcHRpbWl6ZXJzLCBsaWtlIHIuanMsIGNoZWNrIGZvciBjb25kaXRpb24gcGF0dGVybnMgbGlrZSB0aGUgZm9sbG93aW5nOlxuICBpZiAodHlwZW9mIGRlZmluZSA9PSAnZnVuY3Rpb24nICYmIHR5cGVvZiBkZWZpbmUuYW1kID09ICdvYmplY3QnICYmIGRlZmluZS5hbWQpIHtcbiAgICAvLyBFeHBvc2UgcGxhdGZvcm0gb24gdGhlIGdsb2JhbCBvYmplY3QgdG8gcHJldmVudCBlcnJvcnMgd2hlbiBwbGF0Zm9ybSBpc1xuICAgIC8vIGxvYWRlZCBieSBhIHNjcmlwdCB0YWcgaW4gdGhlIHByZXNlbmNlIG9mIGFuIEFNRCBsb2FkZXIuXG4gICAgLy8gU2VlIGh0dHA6Ly9yZXF1aXJlanMub3JnL2RvY3MvZXJyb3JzLmh0bWwjbWlzbWF0Y2ggZm9yIG1vcmUgZGV0YWlscy5cbiAgICByb290LnBsYXRmb3JtID0gcGxhdGZvcm07XG5cbiAgICAvLyBEZWZpbmUgYXMgYW4gYW5vbnltb3VzIG1vZHVsZSBzbyBwbGF0Zm9ybSBjYW4gYmUgYWxpYXNlZCB0aHJvdWdoIHBhdGggbWFwcGluZy5cbiAgICBkZWZpbmUoZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4gcGxhdGZvcm07XG4gICAgfSk7XG4gIH1cbiAgLy8gQ2hlY2sgZm9yIGBleHBvcnRzYCBhZnRlciBgZGVmaW5lYCBpbiBjYXNlIGEgYnVpbGQgb3B0aW1pemVyIGFkZHMgYW4gYGV4cG9ydHNgIG9iamVjdC5cbiAgZWxzZSBpZiAoZnJlZUV4cG9ydHMgJiYgZnJlZU1vZHVsZSkge1xuICAgIC8vIEV4cG9ydCBmb3IgQ29tbW9uSlMgc3VwcG9ydC5cbiAgICBmb3JPd24ocGxhdGZvcm0sIGZ1bmN0aW9uKHZhbHVlLCBrZXkpIHtcbiAgICAgIGZyZWVFeHBvcnRzW2tleV0gPSB2YWx1ZTtcbiAgICB9KTtcbiAgfVxuICBlbHNlIHtcbiAgICAvLyBFeHBvcnQgdG8gdGhlIGdsb2JhbCBvYmplY3QuXG4gICAgcm9vdC5wbGF0Zm9ybSA9IHBsYXRmb3JtO1xuICB9XG59LmNhbGwodGhpcykpO1xuIiwidmFyIHYxID0gcmVxdWlyZSgnLi92MScpO1xudmFyIHY0ID0gcmVxdWlyZSgnLi92NCcpO1xuXG52YXIgdXVpZCA9IHY0O1xudXVpZC52MSA9IHYxO1xudXVpZC52NCA9IHY0O1xuXG5tb2R1bGUuZXhwb3J0cyA9IHV1aWQ7XG4iLCIvKipcbiAqIENvbnZlcnQgYXJyYXkgb2YgMTYgYnl0ZSB2YWx1ZXMgdG8gVVVJRCBzdHJpbmcgZm9ybWF0IG9mIHRoZSBmb3JtOlxuICogWFhYWFhYWFgtWFhYWC1YWFhYLVhYWFgtWFhYWFhYWFhYWFhYXG4gKi9cbnZhciBieXRlVG9IZXggPSBbXTtcbmZvciAodmFyIGkgPSAwOyBpIDwgMjU2OyArK2kpIHtcbiAgYnl0ZVRvSGV4W2ldID0gKGkgKyAweDEwMCkudG9TdHJpbmcoMTYpLnN1YnN0cigxKTtcbn1cblxuZnVuY3Rpb24gYnl0ZXNUb1V1aWQoYnVmLCBvZmZzZXQpIHtcbiAgdmFyIGkgPSBvZmZzZXQgfHwgMDtcbiAgdmFyIGJ0aCA9IGJ5dGVUb0hleDtcbiAgLy8gam9pbiB1c2VkIHRvIGZpeCBtZW1vcnkgaXNzdWUgY2F1c2VkIGJ5IGNvbmNhdGVuYXRpb246IGh0dHBzOi8vYnVncy5jaHJvbWl1bS5vcmcvcC92OC9pc3N1ZXMvZGV0YWlsP2lkPTMxNzUjYzRcbiAgcmV0dXJuIChbYnRoW2J1ZltpKytdXSwgYnRoW2J1ZltpKytdXSwgXG5cdGJ0aFtidWZbaSsrXV0sIGJ0aFtidWZbaSsrXV0sICctJyxcblx0YnRoW2J1ZltpKytdXSwgYnRoW2J1ZltpKytdXSwgJy0nLFxuXHRidGhbYnVmW2krK11dLCBidGhbYnVmW2krK11dLCAnLScsXG5cdGJ0aFtidWZbaSsrXV0sIGJ0aFtidWZbaSsrXV0sICctJyxcblx0YnRoW2J1ZltpKytdXSwgYnRoW2J1ZltpKytdXSxcblx0YnRoW2J1ZltpKytdXSwgYnRoW2J1ZltpKytdXSxcblx0YnRoW2J1ZltpKytdXSwgYnRoW2J1ZltpKytdXV0pLmpvaW4oJycpO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGJ5dGVzVG9VdWlkO1xuIiwiLy8gVW5pcXVlIElEIGNyZWF0aW9uIHJlcXVpcmVzIGEgaGlnaCBxdWFsaXR5IHJhbmRvbSAjIGdlbmVyYXRvci4gIEluIHRoZVxuLy8gYnJvd3NlciB0aGlzIGlzIGEgbGl0dGxlIGNvbXBsaWNhdGVkIGR1ZSB0byB1bmtub3duIHF1YWxpdHkgb2YgTWF0aC5yYW5kb20oKVxuLy8gYW5kIGluY29uc2lzdGVudCBzdXBwb3J0IGZvciB0aGUgYGNyeXB0b2AgQVBJLiAgV2UgZG8gdGhlIGJlc3Qgd2UgY2FuIHZpYVxuLy8gZmVhdHVyZS1kZXRlY3Rpb25cblxuLy8gZ2V0UmFuZG9tVmFsdWVzIG5lZWRzIHRvIGJlIGludm9rZWQgaW4gYSBjb250ZXh0IHdoZXJlIFwidGhpc1wiIGlzIGEgQ3J5cHRvXG4vLyBpbXBsZW1lbnRhdGlvbi4gQWxzbywgZmluZCB0aGUgY29tcGxldGUgaW1wbGVtZW50YXRpb24gb2YgY3J5cHRvIG9uIElFMTEuXG52YXIgZ2V0UmFuZG9tVmFsdWVzID0gKHR5cGVvZihjcnlwdG8pICE9ICd1bmRlZmluZWQnICYmIGNyeXB0by5nZXRSYW5kb21WYWx1ZXMgJiYgY3J5cHRvLmdldFJhbmRvbVZhbHVlcy5iaW5kKGNyeXB0bykpIHx8XG4gICAgICAgICAgICAgICAgICAgICAgKHR5cGVvZihtc0NyeXB0bykgIT0gJ3VuZGVmaW5lZCcgJiYgdHlwZW9mIHdpbmRvdy5tc0NyeXB0by5nZXRSYW5kb21WYWx1ZXMgPT0gJ2Z1bmN0aW9uJyAmJiBtc0NyeXB0by5nZXRSYW5kb21WYWx1ZXMuYmluZChtc0NyeXB0bykpO1xuXG5pZiAoZ2V0UmFuZG9tVmFsdWVzKSB7XG4gIC8vIFdIQVRXRyBjcnlwdG8gUk5HIC0gaHR0cDovL3dpa2kud2hhdHdnLm9yZy93aWtpL0NyeXB0b1xuICB2YXIgcm5kczggPSBuZXcgVWludDhBcnJheSgxNik7IC8vIGVzbGludC1kaXNhYmxlLWxpbmUgbm8tdW5kZWZcblxuICBtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHdoYXR3Z1JORygpIHtcbiAgICBnZXRSYW5kb21WYWx1ZXMocm5kczgpO1xuICAgIHJldHVybiBybmRzODtcbiAgfTtcbn0gZWxzZSB7XG4gIC8vIE1hdGgucmFuZG9tKCktYmFzZWQgKFJORylcbiAgLy9cbiAgLy8gSWYgYWxsIGVsc2UgZmFpbHMsIHVzZSBNYXRoLnJhbmRvbSgpLiAgSXQncyBmYXN0LCBidXQgaXMgb2YgdW5zcGVjaWZpZWRcbiAgLy8gcXVhbGl0eS5cbiAgdmFyIHJuZHMgPSBuZXcgQXJyYXkoMTYpO1xuXG4gIG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gbWF0aFJORygpIHtcbiAgICBmb3IgKHZhciBpID0gMCwgcjsgaSA8IDE2OyBpKyspIHtcbiAgICAgIGlmICgoaSAmIDB4MDMpID09PSAwKSByID0gTWF0aC5yYW5kb20oKSAqIDB4MTAwMDAwMDAwO1xuICAgICAgcm5kc1tpXSA9IHIgPj4+ICgoaSAmIDB4MDMpIDw8IDMpICYgMHhmZjtcbiAgICB9XG5cbiAgICByZXR1cm4gcm5kcztcbiAgfTtcbn1cbiIsInZhciBybmcgPSByZXF1aXJlKCcuL2xpYi9ybmcnKTtcbnZhciBieXRlc1RvVXVpZCA9IHJlcXVpcmUoJy4vbGliL2J5dGVzVG9VdWlkJyk7XG5cbi8vICoqYHYxKClgIC0gR2VuZXJhdGUgdGltZS1iYXNlZCBVVUlEKipcbi8vXG4vLyBJbnNwaXJlZCBieSBodHRwczovL2dpdGh1Yi5jb20vTGlvc0svVVVJRC5qc1xuLy8gYW5kIGh0dHA6Ly9kb2NzLnB5dGhvbi5vcmcvbGlicmFyeS91dWlkLmh0bWxcblxudmFyIF9ub2RlSWQ7XG52YXIgX2Nsb2Nrc2VxO1xuXG4vLyBQcmV2aW91cyB1dWlkIGNyZWF0aW9uIHRpbWVcbnZhciBfbGFzdE1TZWNzID0gMDtcbnZhciBfbGFzdE5TZWNzID0gMDtcblxuLy8gU2VlIGh0dHBzOi8vZ2l0aHViLmNvbS9icm9vZmEvbm9kZS11dWlkIGZvciBBUEkgZGV0YWlsc1xuZnVuY3Rpb24gdjEob3B0aW9ucywgYnVmLCBvZmZzZXQpIHtcbiAgdmFyIGkgPSBidWYgJiYgb2Zmc2V0IHx8IDA7XG4gIHZhciBiID0gYnVmIHx8IFtdO1xuXG4gIG9wdGlvbnMgPSBvcHRpb25zIHx8IHt9O1xuICB2YXIgbm9kZSA9IG9wdGlvbnMubm9kZSB8fCBfbm9kZUlkO1xuICB2YXIgY2xvY2tzZXEgPSBvcHRpb25zLmNsb2Nrc2VxICE9PSB1bmRlZmluZWQgPyBvcHRpb25zLmNsb2Nrc2VxIDogX2Nsb2Nrc2VxO1xuXG4gIC8vIG5vZGUgYW5kIGNsb2Nrc2VxIG5lZWQgdG8gYmUgaW5pdGlhbGl6ZWQgdG8gcmFuZG9tIHZhbHVlcyBpZiB0aGV5J3JlIG5vdFxuICAvLyBzcGVjaWZpZWQuICBXZSBkbyB0aGlzIGxhemlseSB0byBtaW5pbWl6ZSBpc3N1ZXMgcmVsYXRlZCB0byBpbnN1ZmZpY2llbnRcbiAgLy8gc3lzdGVtIGVudHJvcHkuICBTZWUgIzE4OVxuICBpZiAobm9kZSA9PSBudWxsIHx8IGNsb2Nrc2VxID09IG51bGwpIHtcbiAgICB2YXIgc2VlZEJ5dGVzID0gcm5nKCk7XG4gICAgaWYgKG5vZGUgPT0gbnVsbCkge1xuICAgICAgLy8gUGVyIDQuNSwgY3JlYXRlIGFuZCA0OC1iaXQgbm9kZSBpZCwgKDQ3IHJhbmRvbSBiaXRzICsgbXVsdGljYXN0IGJpdCA9IDEpXG4gICAgICBub2RlID0gX25vZGVJZCA9IFtcbiAgICAgICAgc2VlZEJ5dGVzWzBdIHwgMHgwMSxcbiAgICAgICAgc2VlZEJ5dGVzWzFdLCBzZWVkQnl0ZXNbMl0sIHNlZWRCeXRlc1szXSwgc2VlZEJ5dGVzWzRdLCBzZWVkQnl0ZXNbNV1cbiAgICAgIF07XG4gICAgfVxuICAgIGlmIChjbG9ja3NlcSA9PSBudWxsKSB7XG4gICAgICAvLyBQZXIgNC4yLjIsIHJhbmRvbWl6ZSAoMTQgYml0KSBjbG9ja3NlcVxuICAgICAgY2xvY2tzZXEgPSBfY2xvY2tzZXEgPSAoc2VlZEJ5dGVzWzZdIDw8IDggfCBzZWVkQnl0ZXNbN10pICYgMHgzZmZmO1xuICAgIH1cbiAgfVxuXG4gIC8vIFVVSUQgdGltZXN0YW1wcyBhcmUgMTAwIG5hbm8tc2Vjb25kIHVuaXRzIHNpbmNlIHRoZSBHcmVnb3JpYW4gZXBvY2gsXG4gIC8vICgxNTgyLTEwLTE1IDAwOjAwKS4gIEpTTnVtYmVycyBhcmVuJ3QgcHJlY2lzZSBlbm91Z2ggZm9yIHRoaXMsIHNvXG4gIC8vIHRpbWUgaXMgaGFuZGxlZCBpbnRlcm5hbGx5IGFzICdtc2VjcycgKGludGVnZXIgbWlsbGlzZWNvbmRzKSBhbmQgJ25zZWNzJ1xuICAvLyAoMTAwLW5hbm9zZWNvbmRzIG9mZnNldCBmcm9tIG1zZWNzKSBzaW5jZSB1bml4IGVwb2NoLCAxOTcwLTAxLTAxIDAwOjAwLlxuICB2YXIgbXNlY3MgPSBvcHRpb25zLm1zZWNzICE9PSB1bmRlZmluZWQgPyBvcHRpb25zLm1zZWNzIDogbmV3IERhdGUoKS5nZXRUaW1lKCk7XG5cbiAgLy8gUGVyIDQuMi4xLjIsIHVzZSBjb3VudCBvZiB1dWlkJ3MgZ2VuZXJhdGVkIGR1cmluZyB0aGUgY3VycmVudCBjbG9ja1xuICAvLyBjeWNsZSB0byBzaW11bGF0ZSBoaWdoZXIgcmVzb2x1dGlvbiBjbG9ja1xuICB2YXIgbnNlY3MgPSBvcHRpb25zLm5zZWNzICE9PSB1bmRlZmluZWQgPyBvcHRpb25zLm5zZWNzIDogX2xhc3ROU2VjcyArIDE7XG5cbiAgLy8gVGltZSBzaW5jZSBsYXN0IHV1aWQgY3JlYXRpb24gKGluIG1zZWNzKVxuICB2YXIgZHQgPSAobXNlY3MgLSBfbGFzdE1TZWNzKSArIChuc2VjcyAtIF9sYXN0TlNlY3MpLzEwMDAwO1xuXG4gIC8vIFBlciA0LjIuMS4yLCBCdW1wIGNsb2Nrc2VxIG9uIGNsb2NrIHJlZ3Jlc3Npb25cbiAgaWYgKGR0IDwgMCAmJiBvcHRpb25zLmNsb2Nrc2VxID09PSB1bmRlZmluZWQpIHtcbiAgICBjbG9ja3NlcSA9IGNsb2Nrc2VxICsgMSAmIDB4M2ZmZjtcbiAgfVxuXG4gIC8vIFJlc2V0IG5zZWNzIGlmIGNsb2NrIHJlZ3Jlc3NlcyAobmV3IGNsb2Nrc2VxKSBvciB3ZSd2ZSBtb3ZlZCBvbnRvIGEgbmV3XG4gIC8vIHRpbWUgaW50ZXJ2YWxcbiAgaWYgKChkdCA8IDAgfHwgbXNlY3MgPiBfbGFzdE1TZWNzKSAmJiBvcHRpb25zLm5zZWNzID09PSB1bmRlZmluZWQpIHtcbiAgICBuc2VjcyA9IDA7XG4gIH1cblxuICAvLyBQZXIgNC4yLjEuMiBUaHJvdyBlcnJvciBpZiB0b28gbWFueSB1dWlkcyBhcmUgcmVxdWVzdGVkXG4gIGlmIChuc2VjcyA+PSAxMDAwMCkge1xuICAgIHRocm93IG5ldyBFcnJvcigndXVpZC52MSgpOiBDYW5cXCd0IGNyZWF0ZSBtb3JlIHRoYW4gMTBNIHV1aWRzL3NlYycpO1xuICB9XG5cbiAgX2xhc3RNU2VjcyA9IG1zZWNzO1xuICBfbGFzdE5TZWNzID0gbnNlY3M7XG4gIF9jbG9ja3NlcSA9IGNsb2Nrc2VxO1xuXG4gIC8vIFBlciA0LjEuNCAtIENvbnZlcnQgZnJvbSB1bml4IGVwb2NoIHRvIEdyZWdvcmlhbiBlcG9jaFxuICBtc2VjcyArPSAxMjIxOTI5MjgwMDAwMDtcblxuICAvLyBgdGltZV9sb3dgXG4gIHZhciB0bCA9ICgobXNlY3MgJiAweGZmZmZmZmYpICogMTAwMDAgKyBuc2VjcykgJSAweDEwMDAwMDAwMDtcbiAgYltpKytdID0gdGwgPj4+IDI0ICYgMHhmZjtcbiAgYltpKytdID0gdGwgPj4+IDE2ICYgMHhmZjtcbiAgYltpKytdID0gdGwgPj4+IDggJiAweGZmO1xuICBiW2krK10gPSB0bCAmIDB4ZmY7XG5cbiAgLy8gYHRpbWVfbWlkYFxuICB2YXIgdG1oID0gKG1zZWNzIC8gMHgxMDAwMDAwMDAgKiAxMDAwMCkgJiAweGZmZmZmZmY7XG4gIGJbaSsrXSA9IHRtaCA+Pj4gOCAmIDB4ZmY7XG4gIGJbaSsrXSA9IHRtaCAmIDB4ZmY7XG5cbiAgLy8gYHRpbWVfaGlnaF9hbmRfdmVyc2lvbmBcbiAgYltpKytdID0gdG1oID4+PiAyNCAmIDB4ZiB8IDB4MTA7IC8vIGluY2x1ZGUgdmVyc2lvblxuICBiW2krK10gPSB0bWggPj4+IDE2ICYgMHhmZjtcblxuICAvLyBgY2xvY2tfc2VxX2hpX2FuZF9yZXNlcnZlZGAgKFBlciA0LjIuMiAtIGluY2x1ZGUgdmFyaWFudClcbiAgYltpKytdID0gY2xvY2tzZXEgPj4+IDggfCAweDgwO1xuXG4gIC8vIGBjbG9ja19zZXFfbG93YFxuICBiW2krK10gPSBjbG9ja3NlcSAmIDB4ZmY7XG5cbiAgLy8gYG5vZGVgXG4gIGZvciAodmFyIG4gPSAwOyBuIDwgNjsgKytuKSB7XG4gICAgYltpICsgbl0gPSBub2RlW25dO1xuICB9XG5cbiAgcmV0dXJuIGJ1ZiA/IGJ1ZiA6IGJ5dGVzVG9VdWlkKGIpO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHYxO1xuIiwidmFyIHJuZyA9IHJlcXVpcmUoJy4vbGliL3JuZycpO1xudmFyIGJ5dGVzVG9VdWlkID0gcmVxdWlyZSgnLi9saWIvYnl0ZXNUb1V1aWQnKTtcblxuZnVuY3Rpb24gdjQob3B0aW9ucywgYnVmLCBvZmZzZXQpIHtcbiAgdmFyIGkgPSBidWYgJiYgb2Zmc2V0IHx8IDA7XG5cbiAgaWYgKHR5cGVvZihvcHRpb25zKSA9PSAnc3RyaW5nJykge1xuICAgIGJ1ZiA9IG9wdGlvbnMgPT09ICdiaW5hcnknID8gbmV3IEFycmF5KDE2KSA6IG51bGw7XG4gICAgb3B0aW9ucyA9IG51bGw7XG4gIH1cbiAgb3B0aW9ucyA9IG9wdGlvbnMgfHwge307XG5cbiAgdmFyIHJuZHMgPSBvcHRpb25zLnJhbmRvbSB8fCAob3B0aW9ucy5ybmcgfHwgcm5nKSgpO1xuXG4gIC8vIFBlciA0LjQsIHNldCBiaXRzIGZvciB2ZXJzaW9uIGFuZCBgY2xvY2tfc2VxX2hpX2FuZF9yZXNlcnZlZGBcbiAgcm5kc1s2XSA9IChybmRzWzZdICYgMHgwZikgfCAweDQwO1xuICBybmRzWzhdID0gKHJuZHNbOF0gJiAweDNmKSB8IDB4ODA7XG5cbiAgLy8gQ29weSBieXRlcyB0byBidWZmZXIsIGlmIHByb3ZpZGVkXG4gIGlmIChidWYpIHtcbiAgICBmb3IgKHZhciBpaSA9IDA7IGlpIDwgMTY7ICsraWkpIHtcbiAgICAgIGJ1ZltpICsgaWldID0gcm5kc1tpaV07XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGJ1ZiB8fCBieXRlc1RvVXVpZChybmRzKTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSB2NDtcbiIsIi8qXHJcbldpbGRFbWl0dGVyLmpzIGlzIGEgc2xpbSBsaXR0bGUgZXZlbnQgZW1pdHRlciBieSBAaGVucmlram9yZXRlZyBsYXJnZWx5IGJhc2VkXHJcbm9uIEB2aXNpb25tZWRpYSdzIEVtaXR0ZXIgZnJvbSBVSSBLaXQuXHJcblxyXG5XaHk/IEkgd2FudGVkIGl0IHN0YW5kYWxvbmUuXHJcblxyXG5JIGFsc28gd2FudGVkIHN1cHBvcnQgZm9yIHdpbGRjYXJkIGVtaXR0ZXJzIGxpa2UgdGhpczpcclxuXHJcbmVtaXR0ZXIub24oJyonLCBmdW5jdGlvbiAoZXZlbnROYW1lLCBvdGhlciwgZXZlbnQsIHBheWxvYWRzKSB7XHJcblxyXG59KTtcclxuXHJcbmVtaXR0ZXIub24oJ3NvbWVuYW1lc3BhY2UqJywgZnVuY3Rpb24gKGV2ZW50TmFtZSwgcGF5bG9hZHMpIHtcclxuXHJcbn0pO1xyXG5cclxuUGxlYXNlIG5vdGUgdGhhdCBjYWxsYmFja3MgdHJpZ2dlcmVkIGJ5IHdpbGRjYXJkIHJlZ2lzdGVyZWQgZXZlbnRzIGFsc28gZ2V0XHJcbnRoZSBldmVudCBuYW1lIGFzIHRoZSBmaXJzdCBhcmd1bWVudC5cclxuKi9cclxuXHJcbm1vZHVsZS5leHBvcnRzID0gV2lsZEVtaXR0ZXI7XHJcblxyXG5mdW5jdGlvbiBXaWxkRW1pdHRlcigpIHsgfVxyXG5cclxuV2lsZEVtaXR0ZXIubWl4aW4gPSBmdW5jdGlvbiAoY29uc3RydWN0b3IpIHtcclxuICAgIHZhciBwcm90b3R5cGUgPSBjb25zdHJ1Y3Rvci5wcm90b3R5cGUgfHwgY29uc3RydWN0b3I7XHJcblxyXG4gICAgcHJvdG90eXBlLmlzV2lsZEVtaXR0ZXI9IHRydWU7XHJcblxyXG4gICAgLy8gTGlzdGVuIG9uIHRoZSBnaXZlbiBgZXZlbnRgIHdpdGggYGZuYC4gU3RvcmUgYSBncm91cCBuYW1lIGlmIHByZXNlbnQuXHJcbiAgICBwcm90b3R5cGUub24gPSBmdW5jdGlvbiAoZXZlbnQsIGdyb3VwTmFtZSwgZm4pIHtcclxuICAgICAgICB0aGlzLmNhbGxiYWNrcyA9IHRoaXMuY2FsbGJhY2tzIHx8IHt9O1xyXG4gICAgICAgIHZhciBoYXNHcm91cCA9IChhcmd1bWVudHMubGVuZ3RoID09PSAzKSxcclxuICAgICAgICAgICAgZ3JvdXAgPSBoYXNHcm91cCA/IGFyZ3VtZW50c1sxXSA6IHVuZGVmaW5lZCxcclxuICAgICAgICAgICAgZnVuYyA9IGhhc0dyb3VwID8gYXJndW1lbnRzWzJdIDogYXJndW1lbnRzWzFdO1xyXG4gICAgICAgIGZ1bmMuX2dyb3VwTmFtZSA9IGdyb3VwO1xyXG4gICAgICAgICh0aGlzLmNhbGxiYWNrc1tldmVudF0gPSB0aGlzLmNhbGxiYWNrc1tldmVudF0gfHwgW10pLnB1c2goZnVuYyk7XHJcbiAgICAgICAgcmV0dXJuIHRoaXM7XHJcbiAgICB9O1xyXG5cclxuICAgIC8vIEFkZHMgYW4gYGV2ZW50YCBsaXN0ZW5lciB0aGF0IHdpbGwgYmUgaW52b2tlZCBhIHNpbmdsZVxyXG4gICAgLy8gdGltZSB0aGVuIGF1dG9tYXRpY2FsbHkgcmVtb3ZlZC5cclxuICAgIHByb3RvdHlwZS5vbmNlID0gZnVuY3Rpb24gKGV2ZW50LCBncm91cE5hbWUsIGZuKSB7XHJcbiAgICAgICAgdmFyIHNlbGYgPSB0aGlzLFxyXG4gICAgICAgICAgICBoYXNHcm91cCA9IChhcmd1bWVudHMubGVuZ3RoID09PSAzKSxcclxuICAgICAgICAgICAgZ3JvdXAgPSBoYXNHcm91cCA/IGFyZ3VtZW50c1sxXSA6IHVuZGVmaW5lZCxcclxuICAgICAgICAgICAgZnVuYyA9IGhhc0dyb3VwID8gYXJndW1lbnRzWzJdIDogYXJndW1lbnRzWzFdO1xyXG4gICAgICAgIGZ1bmN0aW9uIG9uKCkge1xyXG4gICAgICAgICAgICBzZWxmLm9mZihldmVudCwgb24pO1xyXG4gICAgICAgICAgICBmdW5jLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHRoaXMub24oZXZlbnQsIGdyb3VwLCBvbik7XHJcbiAgICAgICAgcmV0dXJuIHRoaXM7XHJcbiAgICB9O1xyXG5cclxuICAgIC8vIFVuYmluZHMgYW4gZW50aXJlIGdyb3VwXHJcbiAgICBwcm90b3R5cGUucmVsZWFzZUdyb3VwID0gZnVuY3Rpb24gKGdyb3VwTmFtZSkge1xyXG4gICAgICAgIHRoaXMuY2FsbGJhY2tzID0gdGhpcy5jYWxsYmFja3MgfHwge307XHJcbiAgICAgICAgdmFyIGl0ZW0sIGksIGxlbiwgaGFuZGxlcnM7XHJcbiAgICAgICAgZm9yIChpdGVtIGluIHRoaXMuY2FsbGJhY2tzKSB7XHJcbiAgICAgICAgICAgIGhhbmRsZXJzID0gdGhpcy5jYWxsYmFja3NbaXRlbV07XHJcbiAgICAgICAgICAgIGZvciAoaSA9IDAsIGxlbiA9IGhhbmRsZXJzLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XHJcbiAgICAgICAgICAgICAgICBpZiAoaGFuZGxlcnNbaV0uX2dyb3VwTmFtZSA9PT0gZ3JvdXBOYW1lKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgLy9jb25zb2xlLmxvZygncmVtb3ZpbmcnKTtcclxuICAgICAgICAgICAgICAgICAgICAvLyByZW1vdmUgaXQgYW5kIHNob3J0ZW4gdGhlIGFycmF5IHdlJ3JlIGxvb3BpbmcgdGhyb3VnaFxyXG4gICAgICAgICAgICAgICAgICAgIGhhbmRsZXJzLnNwbGljZShpLCAxKTtcclxuICAgICAgICAgICAgICAgICAgICBpLS07XHJcbiAgICAgICAgICAgICAgICAgICAgbGVuLS07XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgICAgcmV0dXJuIHRoaXM7XHJcbiAgICB9O1xyXG5cclxuICAgIC8vIFJlbW92ZSB0aGUgZ2l2ZW4gY2FsbGJhY2sgZm9yIGBldmVudGAgb3IgYWxsXHJcbiAgICAvLyByZWdpc3RlcmVkIGNhbGxiYWNrcy5cclxuICAgIHByb3RvdHlwZS5vZmYgPSBmdW5jdGlvbiAoZXZlbnQsIGZuKSB7XHJcbiAgICAgICAgdGhpcy5jYWxsYmFja3MgPSB0aGlzLmNhbGxiYWNrcyB8fCB7fTtcclxuICAgICAgICB2YXIgY2FsbGJhY2tzID0gdGhpcy5jYWxsYmFja3NbZXZlbnRdLFxyXG4gICAgICAgICAgICBpO1xyXG5cclxuICAgICAgICBpZiAoIWNhbGxiYWNrcykgcmV0dXJuIHRoaXM7XHJcblxyXG4gICAgICAgIC8vIHJlbW92ZSBhbGwgaGFuZGxlcnNcclxuICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMSkge1xyXG4gICAgICAgICAgICBkZWxldGUgdGhpcy5jYWxsYmFja3NbZXZlbnRdO1xyXG4gICAgICAgICAgICByZXR1cm4gdGhpcztcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC8vIHJlbW92ZSBzcGVjaWZpYyBoYW5kbGVyXHJcbiAgICAgICAgaSA9IGNhbGxiYWNrcy5pbmRleE9mKGZuKTtcclxuICAgICAgICBjYWxsYmFja3Muc3BsaWNlKGksIDEpO1xyXG4gICAgICAgIGlmIChjYWxsYmFja3MubGVuZ3RoID09PSAwKSB7XHJcbiAgICAgICAgICAgIGRlbGV0ZSB0aGlzLmNhbGxiYWNrc1tldmVudF07XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJldHVybiB0aGlzO1xyXG4gICAgfTtcclxuXHJcbiAgICAvLy8gRW1pdCBgZXZlbnRgIHdpdGggdGhlIGdpdmVuIGFyZ3MuXHJcbiAgICAvLyBhbHNvIGNhbGxzIGFueSBgKmAgaGFuZGxlcnNcclxuICAgIHByb3RvdHlwZS5lbWl0ID0gZnVuY3Rpb24gKGV2ZW50KSB7XHJcbiAgICAgICAgdGhpcy5jYWxsYmFja3MgPSB0aGlzLmNhbGxiYWNrcyB8fCB7fTtcclxuICAgICAgICB2YXIgYXJncyA9IFtdLnNsaWNlLmNhbGwoYXJndW1lbnRzLCAxKSxcclxuICAgICAgICAgICAgY2FsbGJhY2tzID0gdGhpcy5jYWxsYmFja3NbZXZlbnRdLFxyXG4gICAgICAgICAgICBzcGVjaWFsQ2FsbGJhY2tzID0gdGhpcy5nZXRXaWxkY2FyZENhbGxiYWNrcyhldmVudCksXHJcbiAgICAgICAgICAgIGksXHJcbiAgICAgICAgICAgIGxlbixcclxuICAgICAgICAgICAgaXRlbSxcclxuICAgICAgICAgICAgbGlzdGVuZXJzO1xyXG5cclxuICAgICAgICBpZiAoY2FsbGJhY2tzKSB7XHJcbiAgICAgICAgICAgIGxpc3RlbmVycyA9IGNhbGxiYWNrcy5zbGljZSgpO1xyXG4gICAgICAgICAgICBmb3IgKGkgPSAwLCBsZW4gPSBsaXN0ZW5lcnMubGVuZ3RoOyBpIDwgbGVuOyArK2kpIHtcclxuICAgICAgICAgICAgICAgIGlmICghbGlzdGVuZXJzW2ldKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICBsaXN0ZW5lcnNbaV0uYXBwbHkodGhpcywgYXJncyk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGlmIChzcGVjaWFsQ2FsbGJhY2tzKSB7XHJcbiAgICAgICAgICAgIGxlbiA9IHNwZWNpYWxDYWxsYmFja3MubGVuZ3RoO1xyXG4gICAgICAgICAgICBsaXN0ZW5lcnMgPSBzcGVjaWFsQ2FsbGJhY2tzLnNsaWNlKCk7XHJcbiAgICAgICAgICAgIGZvciAoaSA9IDAsIGxlbiA9IGxpc3RlbmVycy5sZW5ndGg7IGkgPCBsZW47ICsraSkge1xyXG4gICAgICAgICAgICAgICAgaWYgKCFsaXN0ZW5lcnNbaV0pIHtcclxuICAgICAgICAgICAgICAgICAgICBicmVhaztcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIGxpc3RlbmVyc1tpXS5hcHBseSh0aGlzLCBbZXZlbnRdLmNvbmNhdChhcmdzKSk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHJldHVybiB0aGlzO1xyXG4gICAgfTtcclxuXHJcbiAgICAvLyBIZWxwZXIgZm9yIGZvciBmaW5kaW5nIHNwZWNpYWwgd2lsZGNhcmQgZXZlbnQgaGFuZGxlcnMgdGhhdCBtYXRjaCB0aGUgZXZlbnRcclxuICAgIHByb3RvdHlwZS5nZXRXaWxkY2FyZENhbGxiYWNrcyA9IGZ1bmN0aW9uIChldmVudE5hbWUpIHtcclxuICAgICAgICB0aGlzLmNhbGxiYWNrcyA9IHRoaXMuY2FsbGJhY2tzIHx8IHt9O1xyXG4gICAgICAgIHZhciBpdGVtLFxyXG4gICAgICAgICAgICBzcGxpdCxcclxuICAgICAgICAgICAgcmVzdWx0ID0gW107XHJcblxyXG4gICAgICAgIGZvciAoaXRlbSBpbiB0aGlzLmNhbGxiYWNrcykge1xyXG4gICAgICAgICAgICBzcGxpdCA9IGl0ZW0uc3BsaXQoJyonKTtcclxuICAgICAgICAgICAgaWYgKGl0ZW0gPT09ICcqJyB8fCAoc3BsaXQubGVuZ3RoID09PSAyICYmIGV2ZW50TmFtZS5zbGljZSgwLCBzcGxpdFswXS5sZW5ndGgpID09PSBzcGxpdFswXSkpIHtcclxuICAgICAgICAgICAgICAgIHJlc3VsdCA9IHJlc3VsdC5jb25jYXQodGhpcy5jYWxsYmFja3NbaXRlbV0pO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJldHVybiByZXN1bHQ7XHJcbiAgICB9O1xyXG5cclxufTtcclxuXHJcbldpbGRFbWl0dGVyLm1peGluKFdpbGRFbWl0dGVyKTtcclxuIiwiLyohXG4gKiBFdmVudEVtaXR0ZXIgdjUuMi41IC0gZ2l0LmlvL2VlXG4gKiBVbmxpY2Vuc2UgLSBodHRwOi8vdW5saWNlbnNlLm9yZy9cbiAqIE9saXZlciBDYWxkd2VsbCAtIGh0dHA6Ly9vbGkubWUudWsvXG4gKiBAcHJlc2VydmVcbiAqL1xuXG47KGZ1bmN0aW9uIChleHBvcnRzKSB7XG4gICAgJ3VzZSBzdHJpY3QnO1xuXG4gICAgLyoqXG4gICAgICogQ2xhc3MgZm9yIG1hbmFnaW5nIGV2ZW50cy5cbiAgICAgKiBDYW4gYmUgZXh0ZW5kZWQgdG8gcHJvdmlkZSBldmVudCBmdW5jdGlvbmFsaXR5IGluIG90aGVyIGNsYXNzZXMuXG4gICAgICpcbiAgICAgKiBAY2xhc3MgRXZlbnRFbWl0dGVyIE1hbmFnZXMgZXZlbnQgcmVnaXN0ZXJpbmcgYW5kIGVtaXR0aW5nLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIEV2ZW50RW1pdHRlcigpIHt9XG5cbiAgICAvLyBTaG9ydGN1dHMgdG8gaW1wcm92ZSBzcGVlZCBhbmQgc2l6ZVxuICAgIHZhciBwcm90byA9IEV2ZW50RW1pdHRlci5wcm90b3R5cGU7XG4gICAgdmFyIG9yaWdpbmFsR2xvYmFsVmFsdWUgPSBleHBvcnRzLkV2ZW50RW1pdHRlcjtcblxuICAgIC8qKlxuICAgICAqIEZpbmRzIHRoZSBpbmRleCBvZiB0aGUgbGlzdGVuZXIgZm9yIHRoZSBldmVudCBpbiBpdHMgc3RvcmFnZSBhcnJheS5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb25bXX0gbGlzdGVuZXJzIEFycmF5IG9mIGxpc3RlbmVycyB0byBzZWFyY2ggdGhyb3VnaC5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBsaXN0ZW5lciBNZXRob2QgdG8gbG9vayBmb3IuXG4gICAgICogQHJldHVybiB7TnVtYmVyfSBJbmRleCBvZiB0aGUgc3BlY2lmaWVkIGxpc3RlbmVyLCAtMSBpZiBub3QgZm91bmRcbiAgICAgKiBAYXBpIHByaXZhdGVcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBpbmRleE9mTGlzdGVuZXIobGlzdGVuZXJzLCBsaXN0ZW5lcikge1xuICAgICAgICB2YXIgaSA9IGxpc3RlbmVycy5sZW5ndGg7XG4gICAgICAgIHdoaWxlIChpLS0pIHtcbiAgICAgICAgICAgIGlmIChsaXN0ZW5lcnNbaV0ubGlzdGVuZXIgPT09IGxpc3RlbmVyKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gLTE7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQWxpYXMgYSBtZXRob2Qgd2hpbGUga2VlcGluZyB0aGUgY29udGV4dCBjb3JyZWN0LCB0byBhbGxvdyBmb3Igb3ZlcndyaXRpbmcgb2YgdGFyZ2V0IG1ldGhvZC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfSBuYW1lIFRoZSBuYW1lIG9mIHRoZSB0YXJnZXQgbWV0aG9kLlxuICAgICAqIEByZXR1cm4ge0Z1bmN0aW9ufSBUaGUgYWxpYXNlZCBtZXRob2RcbiAgICAgKiBAYXBpIHByaXZhdGVcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBhbGlhcyhuYW1lKSB7XG4gICAgICAgIHJldHVybiBmdW5jdGlvbiBhbGlhc0Nsb3N1cmUoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpc1tuYW1lXS5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgICAgICB9O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgdGhlIGxpc3RlbmVyIGFycmF5IGZvciB0aGUgc3BlY2lmaWVkIGV2ZW50LlxuICAgICAqIFdpbGwgaW5pdGlhbGlzZSB0aGUgZXZlbnQgb2JqZWN0IGFuZCBsaXN0ZW5lciBhcnJheXMgaWYgcmVxdWlyZWQuXG4gICAgICogV2lsbCByZXR1cm4gYW4gb2JqZWN0IGlmIHlvdSB1c2UgYSByZWdleCBzZWFyY2guIFRoZSBvYmplY3QgY29udGFpbnMga2V5cyBmb3IgZWFjaCBtYXRjaGVkIGV2ZW50LiBTbyAvYmFbcnpdLyBtaWdodCByZXR1cm4gYW4gb2JqZWN0IGNvbnRhaW5pbmcgYmFyIGFuZCBiYXouIEJ1dCBvbmx5IGlmIHlvdSBoYXZlIGVpdGhlciBkZWZpbmVkIHRoZW0gd2l0aCBkZWZpbmVFdmVudCBvciBhZGRlZCBzb21lIGxpc3RlbmVycyB0byB0aGVtLlxuICAgICAqIEVhY2ggcHJvcGVydHkgaW4gdGhlIG9iamVjdCByZXNwb25zZSBpcyBhbiBhcnJheSBvZiBsaXN0ZW5lciBmdW5jdGlvbnMuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1N0cmluZ3xSZWdFeHB9IGV2dCBOYW1lIG9mIHRoZSBldmVudCB0byByZXR1cm4gdGhlIGxpc3RlbmVycyBmcm9tLlxuICAgICAqIEByZXR1cm4ge0Z1bmN0aW9uW118T2JqZWN0fSBBbGwgbGlzdGVuZXIgZnVuY3Rpb25zIGZvciB0aGUgZXZlbnQuXG4gICAgICovXG4gICAgcHJvdG8uZ2V0TGlzdGVuZXJzID0gZnVuY3Rpb24gZ2V0TGlzdGVuZXJzKGV2dCkge1xuICAgICAgICB2YXIgZXZlbnRzID0gdGhpcy5fZ2V0RXZlbnRzKCk7XG4gICAgICAgIHZhciByZXNwb25zZTtcbiAgICAgICAgdmFyIGtleTtcblxuICAgICAgICAvLyBSZXR1cm4gYSBjb25jYXRlbmF0ZWQgYXJyYXkgb2YgYWxsIG1hdGNoaW5nIGV2ZW50cyBpZlxuICAgICAgICAvLyB0aGUgc2VsZWN0b3IgaXMgYSByZWd1bGFyIGV4cHJlc3Npb24uXG4gICAgICAgIGlmIChldnQgaW5zdGFuY2VvZiBSZWdFeHApIHtcbiAgICAgICAgICAgIHJlc3BvbnNlID0ge307XG4gICAgICAgICAgICBmb3IgKGtleSBpbiBldmVudHMpIHtcbiAgICAgICAgICAgICAgICBpZiAoZXZlbnRzLmhhc093blByb3BlcnR5KGtleSkgJiYgZXZ0LnRlc3Qoa2V5KSkge1xuICAgICAgICAgICAgICAgICAgICByZXNwb25zZVtrZXldID0gZXZlbnRzW2tleV07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgcmVzcG9uc2UgPSBldmVudHNbZXZ0XSB8fCAoZXZlbnRzW2V2dF0gPSBbXSk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gcmVzcG9uc2U7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIFRha2VzIGEgbGlzdCBvZiBsaXN0ZW5lciBvYmplY3RzIGFuZCBmbGF0dGVucyBpdCBpbnRvIGEgbGlzdCBvZiBsaXN0ZW5lciBmdW5jdGlvbnMuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge09iamVjdFtdfSBsaXN0ZW5lcnMgUmF3IGxpc3RlbmVyIG9iamVjdHMuXG4gICAgICogQHJldHVybiB7RnVuY3Rpb25bXX0gSnVzdCB0aGUgbGlzdGVuZXIgZnVuY3Rpb25zLlxuICAgICAqL1xuICAgIHByb3RvLmZsYXR0ZW5MaXN0ZW5lcnMgPSBmdW5jdGlvbiBmbGF0dGVuTGlzdGVuZXJzKGxpc3RlbmVycykge1xuICAgICAgICB2YXIgZmxhdExpc3RlbmVycyA9IFtdO1xuICAgICAgICB2YXIgaTtcblxuICAgICAgICBmb3IgKGkgPSAwOyBpIDwgbGlzdGVuZXJzLmxlbmd0aDsgaSArPSAxKSB7XG4gICAgICAgICAgICBmbGF0TGlzdGVuZXJzLnB1c2gobGlzdGVuZXJzW2ldLmxpc3RlbmVyKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBmbGF0TGlzdGVuZXJzO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBGZXRjaGVzIHRoZSByZXF1ZXN0ZWQgbGlzdGVuZXJzIHZpYSBnZXRMaXN0ZW5lcnMgYnV0IHdpbGwgYWx3YXlzIHJldHVybiB0aGUgcmVzdWx0cyBpbnNpZGUgYW4gb2JqZWN0LiBUaGlzIGlzIG1haW5seSBmb3IgaW50ZXJuYWwgdXNlIGJ1dCBvdGhlcnMgbWF5IGZpbmQgaXQgdXNlZnVsLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtTdHJpbmd8UmVnRXhwfSBldnQgTmFtZSBvZiB0aGUgZXZlbnQgdG8gcmV0dXJuIHRoZSBsaXN0ZW5lcnMgZnJvbS5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEFsbCBsaXN0ZW5lciBmdW5jdGlvbnMgZm9yIGFuIGV2ZW50IGluIGFuIG9iamVjdC5cbiAgICAgKi9cbiAgICBwcm90by5nZXRMaXN0ZW5lcnNBc09iamVjdCA9IGZ1bmN0aW9uIGdldExpc3RlbmVyc0FzT2JqZWN0KGV2dCkge1xuICAgICAgICB2YXIgbGlzdGVuZXJzID0gdGhpcy5nZXRMaXN0ZW5lcnMoZXZ0KTtcbiAgICAgICAgdmFyIHJlc3BvbnNlO1xuXG4gICAgICAgIGlmIChsaXN0ZW5lcnMgaW5zdGFuY2VvZiBBcnJheSkge1xuICAgICAgICAgICAgcmVzcG9uc2UgPSB7fTtcbiAgICAgICAgICAgIHJlc3BvbnNlW2V2dF0gPSBsaXN0ZW5lcnM7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gcmVzcG9uc2UgfHwgbGlzdGVuZXJzO1xuICAgIH07XG5cbiAgICBmdW5jdGlvbiBpc1ZhbGlkTGlzdGVuZXIgKGxpc3RlbmVyKSB7XG4gICAgICAgIGlmICh0eXBlb2YgbGlzdGVuZXIgPT09ICdmdW5jdGlvbicgfHwgbGlzdGVuZXIgaW5zdGFuY2VvZiBSZWdFeHApIHtcbiAgICAgICAgICAgIHJldHVybiB0cnVlXG4gICAgICAgIH0gZWxzZSBpZiAobGlzdGVuZXIgJiYgdHlwZW9mIGxpc3RlbmVyID09PSAnb2JqZWN0Jykge1xuICAgICAgICAgICAgcmV0dXJuIGlzVmFsaWRMaXN0ZW5lcihsaXN0ZW5lci5saXN0ZW5lcilcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQWRkcyBhIGxpc3RlbmVyIGZ1bmN0aW9uIHRvIHRoZSBzcGVjaWZpZWQgZXZlbnQuXG4gICAgICogVGhlIGxpc3RlbmVyIHdpbGwgbm90IGJlIGFkZGVkIGlmIGl0IGlzIGEgZHVwbGljYXRlLlxuICAgICAqIElmIHRoZSBsaXN0ZW5lciByZXR1cm5zIHRydWUgdGhlbiBpdCB3aWxsIGJlIHJlbW92ZWQgYWZ0ZXIgaXQgaXMgY2FsbGVkLlxuICAgICAqIElmIHlvdSBwYXNzIGEgcmVndWxhciBleHByZXNzaW9uIGFzIHRoZSBldmVudCBuYW1lIHRoZW4gdGhlIGxpc3RlbmVyIHdpbGwgYmUgYWRkZWQgdG8gYWxsIGV2ZW50cyB0aGF0IG1hdGNoIGl0LlxuICAgICAqXG4gICAgICogQHBhcmFtIHtTdHJpbmd8UmVnRXhwfSBldnQgTmFtZSBvZiB0aGUgZXZlbnQgdG8gYXR0YWNoIHRoZSBsaXN0ZW5lciB0by5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBsaXN0ZW5lciBNZXRob2QgdG8gYmUgY2FsbGVkIHdoZW4gdGhlIGV2ZW50IGlzIGVtaXR0ZWQuIElmIHRoZSBmdW5jdGlvbiByZXR1cm5zIHRydWUgdGhlbiBpdCB3aWxsIGJlIHJlbW92ZWQgYWZ0ZXIgY2FsbGluZy5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEN1cnJlbnQgaW5zdGFuY2Ugb2YgRXZlbnRFbWl0dGVyIGZvciBjaGFpbmluZy5cbiAgICAgKi9cbiAgICBwcm90by5hZGRMaXN0ZW5lciA9IGZ1bmN0aW9uIGFkZExpc3RlbmVyKGV2dCwgbGlzdGVuZXIpIHtcbiAgICAgICAgaWYgKCFpc1ZhbGlkTGlzdGVuZXIobGlzdGVuZXIpKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdsaXN0ZW5lciBtdXN0IGJlIGEgZnVuY3Rpb24nKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBsaXN0ZW5lcnMgPSB0aGlzLmdldExpc3RlbmVyc0FzT2JqZWN0KGV2dCk7XG4gICAgICAgIHZhciBsaXN0ZW5lcklzV3JhcHBlZCA9IHR5cGVvZiBsaXN0ZW5lciA9PT0gJ29iamVjdCc7XG4gICAgICAgIHZhciBrZXk7XG5cbiAgICAgICAgZm9yIChrZXkgaW4gbGlzdGVuZXJzKSB7XG4gICAgICAgICAgICBpZiAobGlzdGVuZXJzLmhhc093blByb3BlcnR5KGtleSkgJiYgaW5kZXhPZkxpc3RlbmVyKGxpc3RlbmVyc1trZXldLCBsaXN0ZW5lcikgPT09IC0xKSB7XG4gICAgICAgICAgICAgICAgbGlzdGVuZXJzW2tleV0ucHVzaChsaXN0ZW5lcklzV3JhcHBlZCA/IGxpc3RlbmVyIDoge1xuICAgICAgICAgICAgICAgICAgICBsaXN0ZW5lcjogbGlzdGVuZXIsXG4gICAgICAgICAgICAgICAgICAgIG9uY2U6IGZhbHNlXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogQWxpYXMgb2YgYWRkTGlzdGVuZXJcbiAgICAgKi9cbiAgICBwcm90by5vbiA9IGFsaWFzKCdhZGRMaXN0ZW5lcicpO1xuXG4gICAgLyoqXG4gICAgICogU2VtaS1hbGlhcyBvZiBhZGRMaXN0ZW5lci4gSXQgd2lsbCBhZGQgYSBsaXN0ZW5lciB0aGF0IHdpbGwgYmVcbiAgICAgKiBhdXRvbWF0aWNhbGx5IHJlbW92ZWQgYWZ0ZXIgaXRzIGZpcnN0IGV4ZWN1dGlvbi5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfFJlZ0V4cH0gZXZ0IE5hbWUgb2YgdGhlIGV2ZW50IHRvIGF0dGFjaCB0aGUgbGlzdGVuZXIgdG8uXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gbGlzdGVuZXIgTWV0aG9kIHRvIGJlIGNhbGxlZCB3aGVuIHRoZSBldmVudCBpcyBlbWl0dGVkLiBJZiB0aGUgZnVuY3Rpb24gcmV0dXJucyB0cnVlIHRoZW4gaXQgd2lsbCBiZSByZW1vdmVkIGFmdGVyIGNhbGxpbmcuXG4gICAgICogQHJldHVybiB7T2JqZWN0fSBDdXJyZW50IGluc3RhbmNlIG9mIEV2ZW50RW1pdHRlciBmb3IgY2hhaW5pbmcuXG4gICAgICovXG4gICAgcHJvdG8uYWRkT25jZUxpc3RlbmVyID0gZnVuY3Rpb24gYWRkT25jZUxpc3RlbmVyKGV2dCwgbGlzdGVuZXIpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuYWRkTGlzdGVuZXIoZXZ0LCB7XG4gICAgICAgICAgICBsaXN0ZW5lcjogbGlzdGVuZXIsXG4gICAgICAgICAgICBvbmNlOiB0cnVlXG4gICAgICAgIH0pO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBBbGlhcyBvZiBhZGRPbmNlTGlzdGVuZXIuXG4gICAgICovXG4gICAgcHJvdG8ub25jZSA9IGFsaWFzKCdhZGRPbmNlTGlzdGVuZXInKTtcblxuICAgIC8qKlxuICAgICAqIERlZmluZXMgYW4gZXZlbnQgbmFtZS4gVGhpcyBpcyByZXF1aXJlZCBpZiB5b3Ugd2FudCB0byB1c2UgYSByZWdleCB0byBhZGQgYSBsaXN0ZW5lciB0byBtdWx0aXBsZSBldmVudHMgYXQgb25jZS4gSWYgeW91IGRvbid0IGRvIHRoaXMgdGhlbiBob3cgZG8geW91IGV4cGVjdCBpdCB0byBrbm93IHdoYXQgZXZlbnQgdG8gYWRkIHRvPyBTaG91bGQgaXQganVzdCBhZGQgdG8gZXZlcnkgcG9zc2libGUgbWF0Y2ggZm9yIGEgcmVnZXg/IE5vLiBUaGF0IGlzIHNjYXJ5IGFuZCBiYWQuXG4gICAgICogWW91IG5lZWQgdG8gdGVsbCBpdCB3aGF0IGV2ZW50IG5hbWVzIHNob3VsZCBiZSBtYXRjaGVkIGJ5IGEgcmVnZXguXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1N0cmluZ30gZXZ0IE5hbWUgb2YgdGhlIGV2ZW50IHRvIGNyZWF0ZS5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEN1cnJlbnQgaW5zdGFuY2Ugb2YgRXZlbnRFbWl0dGVyIGZvciBjaGFpbmluZy5cbiAgICAgKi9cbiAgICBwcm90by5kZWZpbmVFdmVudCA9IGZ1bmN0aW9uIGRlZmluZUV2ZW50KGV2dCkge1xuICAgICAgICB0aGlzLmdldExpc3RlbmVycyhldnQpO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogVXNlcyBkZWZpbmVFdmVudCB0byBkZWZpbmUgbXVsdGlwbGUgZXZlbnRzLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtTdHJpbmdbXX0gZXZ0cyBBbiBhcnJheSBvZiBldmVudCBuYW1lcyB0byBkZWZpbmUuXG4gICAgICogQHJldHVybiB7T2JqZWN0fSBDdXJyZW50IGluc3RhbmNlIG9mIEV2ZW50RW1pdHRlciBmb3IgY2hhaW5pbmcuXG4gICAgICovXG4gICAgcHJvdG8uZGVmaW5lRXZlbnRzID0gZnVuY3Rpb24gZGVmaW5lRXZlbnRzKGV2dHMpIHtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBldnRzLmxlbmd0aDsgaSArPSAxKSB7XG4gICAgICAgICAgICB0aGlzLmRlZmluZUV2ZW50KGV2dHNbaV0pO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBSZW1vdmVzIGEgbGlzdGVuZXIgZnVuY3Rpb24gZnJvbSB0aGUgc3BlY2lmaWVkIGV2ZW50LlxuICAgICAqIFdoZW4gcGFzc2VkIGEgcmVndWxhciBleHByZXNzaW9uIGFzIHRoZSBldmVudCBuYW1lLCBpdCB3aWxsIHJlbW92ZSB0aGUgbGlzdGVuZXIgZnJvbSBhbGwgZXZlbnRzIHRoYXQgbWF0Y2ggaXQuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1N0cmluZ3xSZWdFeHB9IGV2dCBOYW1lIG9mIHRoZSBldmVudCB0byByZW1vdmUgdGhlIGxpc3RlbmVyIGZyb20uXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gbGlzdGVuZXIgTWV0aG9kIHRvIHJlbW92ZSBmcm9tIHRoZSBldmVudC5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEN1cnJlbnQgaW5zdGFuY2Ugb2YgRXZlbnRFbWl0dGVyIGZvciBjaGFpbmluZy5cbiAgICAgKi9cbiAgICBwcm90by5yZW1vdmVMaXN0ZW5lciA9IGZ1bmN0aW9uIHJlbW92ZUxpc3RlbmVyKGV2dCwgbGlzdGVuZXIpIHtcbiAgICAgICAgdmFyIGxpc3RlbmVycyA9IHRoaXMuZ2V0TGlzdGVuZXJzQXNPYmplY3QoZXZ0KTtcbiAgICAgICAgdmFyIGluZGV4O1xuICAgICAgICB2YXIga2V5O1xuXG4gICAgICAgIGZvciAoa2V5IGluIGxpc3RlbmVycykge1xuICAgICAgICAgICAgaWYgKGxpc3RlbmVycy5oYXNPd25Qcm9wZXJ0eShrZXkpKSB7XG4gICAgICAgICAgICAgICAgaW5kZXggPSBpbmRleE9mTGlzdGVuZXIobGlzdGVuZXJzW2tleV0sIGxpc3RlbmVyKTtcblxuICAgICAgICAgICAgICAgIGlmIChpbmRleCAhPT0gLTEpIHtcbiAgICAgICAgICAgICAgICAgICAgbGlzdGVuZXJzW2tleV0uc3BsaWNlKGluZGV4LCAxKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogQWxpYXMgb2YgcmVtb3ZlTGlzdGVuZXJcbiAgICAgKi9cbiAgICBwcm90by5vZmYgPSBhbGlhcygncmVtb3ZlTGlzdGVuZXInKTtcblxuICAgIC8qKlxuICAgICAqIEFkZHMgbGlzdGVuZXJzIGluIGJ1bGsgdXNpbmcgdGhlIG1hbmlwdWxhdGVMaXN0ZW5lcnMgbWV0aG9kLlxuICAgICAqIElmIHlvdSBwYXNzIGFuIG9iamVjdCBhcyB0aGUgZmlyc3QgYXJndW1lbnQgeW91IGNhbiBhZGQgdG8gbXVsdGlwbGUgZXZlbnRzIGF0IG9uY2UuIFRoZSBvYmplY3Qgc2hvdWxkIGNvbnRhaW4ga2V5IHZhbHVlIHBhaXJzIG9mIGV2ZW50cyBhbmQgbGlzdGVuZXJzIG9yIGxpc3RlbmVyIGFycmF5cy4gWW91IGNhbiBhbHNvIHBhc3MgaXQgYW4gZXZlbnQgbmFtZSBhbmQgYW4gYXJyYXkgb2YgbGlzdGVuZXJzIHRvIGJlIGFkZGVkLlxuICAgICAqIFlvdSBjYW4gYWxzbyBwYXNzIGl0IGEgcmVndWxhciBleHByZXNzaW9uIHRvIGFkZCB0aGUgYXJyYXkgb2YgbGlzdGVuZXJzIHRvIGFsbCBldmVudHMgdGhhdCBtYXRjaCBpdC5cbiAgICAgKiBZZWFoLCB0aGlzIGZ1bmN0aW9uIGRvZXMgcXVpdGUgYSBiaXQuIFRoYXQncyBwcm9iYWJseSBhIGJhZCB0aGluZy5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfE9iamVjdHxSZWdFeHB9IGV2dCBBbiBldmVudCBuYW1lIGlmIHlvdSB3aWxsIHBhc3MgYW4gYXJyYXkgb2YgbGlzdGVuZXJzIG5leHQuIEFuIG9iamVjdCBpZiB5b3Ugd2lzaCB0byBhZGQgdG8gbXVsdGlwbGUgZXZlbnRzIGF0IG9uY2UuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbltdfSBbbGlzdGVuZXJzXSBBbiBvcHRpb25hbCBhcnJheSBvZiBsaXN0ZW5lciBmdW5jdGlvbnMgdG8gYWRkLlxuICAgICAqIEByZXR1cm4ge09iamVjdH0gQ3VycmVudCBpbnN0YW5jZSBvZiBFdmVudEVtaXR0ZXIgZm9yIGNoYWluaW5nLlxuICAgICAqL1xuICAgIHByb3RvLmFkZExpc3RlbmVycyA9IGZ1bmN0aW9uIGFkZExpc3RlbmVycyhldnQsIGxpc3RlbmVycykge1xuICAgICAgICAvLyBQYXNzIHRocm91Z2ggdG8gbWFuaXB1bGF0ZUxpc3RlbmVyc1xuICAgICAgICByZXR1cm4gdGhpcy5tYW5pcHVsYXRlTGlzdGVuZXJzKGZhbHNlLCBldnQsIGxpc3RlbmVycyk7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIFJlbW92ZXMgbGlzdGVuZXJzIGluIGJ1bGsgdXNpbmcgdGhlIG1hbmlwdWxhdGVMaXN0ZW5lcnMgbWV0aG9kLlxuICAgICAqIElmIHlvdSBwYXNzIGFuIG9iamVjdCBhcyB0aGUgZmlyc3QgYXJndW1lbnQgeW91IGNhbiByZW1vdmUgZnJvbSBtdWx0aXBsZSBldmVudHMgYXQgb25jZS4gVGhlIG9iamVjdCBzaG91bGQgY29udGFpbiBrZXkgdmFsdWUgcGFpcnMgb2YgZXZlbnRzIGFuZCBsaXN0ZW5lcnMgb3IgbGlzdGVuZXIgYXJyYXlzLlxuICAgICAqIFlvdSBjYW4gYWxzbyBwYXNzIGl0IGFuIGV2ZW50IG5hbWUgYW5kIGFuIGFycmF5IG9mIGxpc3RlbmVycyB0byBiZSByZW1vdmVkLlxuICAgICAqIFlvdSBjYW4gYWxzbyBwYXNzIGl0IGEgcmVndWxhciBleHByZXNzaW9uIHRvIHJlbW92ZSB0aGUgbGlzdGVuZXJzIGZyb20gYWxsIGV2ZW50cyB0aGF0IG1hdGNoIGl0LlxuICAgICAqXG4gICAgICogQHBhcmFtIHtTdHJpbmd8T2JqZWN0fFJlZ0V4cH0gZXZ0IEFuIGV2ZW50IG5hbWUgaWYgeW91IHdpbGwgcGFzcyBhbiBhcnJheSBvZiBsaXN0ZW5lcnMgbmV4dC4gQW4gb2JqZWN0IGlmIHlvdSB3aXNoIHRvIHJlbW92ZSBmcm9tIG11bHRpcGxlIGV2ZW50cyBhdCBvbmNlLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb25bXX0gW2xpc3RlbmVyc10gQW4gb3B0aW9uYWwgYXJyYXkgb2YgbGlzdGVuZXIgZnVuY3Rpb25zIHRvIHJlbW92ZS5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEN1cnJlbnQgaW5zdGFuY2Ugb2YgRXZlbnRFbWl0dGVyIGZvciBjaGFpbmluZy5cbiAgICAgKi9cbiAgICBwcm90by5yZW1vdmVMaXN0ZW5lcnMgPSBmdW5jdGlvbiByZW1vdmVMaXN0ZW5lcnMoZXZ0LCBsaXN0ZW5lcnMpIHtcbiAgICAgICAgLy8gUGFzcyB0aHJvdWdoIHRvIG1hbmlwdWxhdGVMaXN0ZW5lcnNcbiAgICAgICAgcmV0dXJuIHRoaXMubWFuaXB1bGF0ZUxpc3RlbmVycyh0cnVlLCBldnQsIGxpc3RlbmVycyk7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEVkaXRzIGxpc3RlbmVycyBpbiBidWxrLiBUaGUgYWRkTGlzdGVuZXJzIGFuZCByZW1vdmVMaXN0ZW5lcnMgbWV0aG9kcyBib3RoIHVzZSB0aGlzIHRvIGRvIHRoZWlyIGpvYi4gWW91IHNob3VsZCByZWFsbHkgdXNlIHRob3NlIGluc3RlYWQsIHRoaXMgaXMgYSBsaXR0bGUgbG93ZXIgbGV2ZWwuXG4gICAgICogVGhlIGZpcnN0IGFyZ3VtZW50IHdpbGwgZGV0ZXJtaW5lIGlmIHRoZSBsaXN0ZW5lcnMgYXJlIHJlbW92ZWQgKHRydWUpIG9yIGFkZGVkIChmYWxzZSkuXG4gICAgICogSWYgeW91IHBhc3MgYW4gb2JqZWN0IGFzIHRoZSBzZWNvbmQgYXJndW1lbnQgeW91IGNhbiBhZGQvcmVtb3ZlIGZyb20gbXVsdGlwbGUgZXZlbnRzIGF0IG9uY2UuIFRoZSBvYmplY3Qgc2hvdWxkIGNvbnRhaW4ga2V5IHZhbHVlIHBhaXJzIG9mIGV2ZW50cyBhbmQgbGlzdGVuZXJzIG9yIGxpc3RlbmVyIGFycmF5cy5cbiAgICAgKiBZb3UgY2FuIGFsc28gcGFzcyBpdCBhbiBldmVudCBuYW1lIGFuZCBhbiBhcnJheSBvZiBsaXN0ZW5lcnMgdG8gYmUgYWRkZWQvcmVtb3ZlZC5cbiAgICAgKiBZb3UgY2FuIGFsc28gcGFzcyBpdCBhIHJlZ3VsYXIgZXhwcmVzc2lvbiB0byBtYW5pcHVsYXRlIHRoZSBsaXN0ZW5lcnMgb2YgYWxsIGV2ZW50cyB0aGF0IG1hdGNoIGl0LlxuICAgICAqXG4gICAgICogQHBhcmFtIHtCb29sZWFufSByZW1vdmUgVHJ1ZSBpZiB5b3Ugd2FudCB0byByZW1vdmUgbGlzdGVuZXJzLCBmYWxzZSBpZiB5b3Ugd2FudCB0byBhZGQuXG4gICAgICogQHBhcmFtIHtTdHJpbmd8T2JqZWN0fFJlZ0V4cH0gZXZ0IEFuIGV2ZW50IG5hbWUgaWYgeW91IHdpbGwgcGFzcyBhbiBhcnJheSBvZiBsaXN0ZW5lcnMgbmV4dC4gQW4gb2JqZWN0IGlmIHlvdSB3aXNoIHRvIGFkZC9yZW1vdmUgZnJvbSBtdWx0aXBsZSBldmVudHMgYXQgb25jZS5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9uW119IFtsaXN0ZW5lcnNdIEFuIG9wdGlvbmFsIGFycmF5IG9mIGxpc3RlbmVyIGZ1bmN0aW9ucyB0byBhZGQvcmVtb3ZlLlxuICAgICAqIEByZXR1cm4ge09iamVjdH0gQ3VycmVudCBpbnN0YW5jZSBvZiBFdmVudEVtaXR0ZXIgZm9yIGNoYWluaW5nLlxuICAgICAqL1xuICAgIHByb3RvLm1hbmlwdWxhdGVMaXN0ZW5lcnMgPSBmdW5jdGlvbiBtYW5pcHVsYXRlTGlzdGVuZXJzKHJlbW92ZSwgZXZ0LCBsaXN0ZW5lcnMpIHtcbiAgICAgICAgdmFyIGk7XG4gICAgICAgIHZhciB2YWx1ZTtcbiAgICAgICAgdmFyIHNpbmdsZSA9IHJlbW92ZSA/IHRoaXMucmVtb3ZlTGlzdGVuZXIgOiB0aGlzLmFkZExpc3RlbmVyO1xuICAgICAgICB2YXIgbXVsdGlwbGUgPSByZW1vdmUgPyB0aGlzLnJlbW92ZUxpc3RlbmVycyA6IHRoaXMuYWRkTGlzdGVuZXJzO1xuXG4gICAgICAgIC8vIElmIGV2dCBpcyBhbiBvYmplY3QgdGhlbiBwYXNzIGVhY2ggb2YgaXRzIHByb3BlcnRpZXMgdG8gdGhpcyBtZXRob2RcbiAgICAgICAgaWYgKHR5cGVvZiBldnQgPT09ICdvYmplY3QnICYmICEoZXZ0IGluc3RhbmNlb2YgUmVnRXhwKSkge1xuICAgICAgICAgICAgZm9yIChpIGluIGV2dCkge1xuICAgICAgICAgICAgICAgIGlmIChldnQuaGFzT3duUHJvcGVydHkoaSkgJiYgKHZhbHVlID0gZXZ0W2ldKSkge1xuICAgICAgICAgICAgICAgICAgICAvLyBQYXNzIHRoZSBzaW5nbGUgbGlzdGVuZXIgc3RyYWlnaHQgdGhyb3VnaCB0byB0aGUgc2luZ3VsYXIgbWV0aG9kXG4gICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgdmFsdWUgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNpbmdsZS5jYWxsKHRoaXMsIGksIHZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIE90aGVyd2lzZSBwYXNzIGJhY2sgdG8gdGhlIG11bHRpcGxlIGZ1bmN0aW9uXG4gICAgICAgICAgICAgICAgICAgICAgICBtdWx0aXBsZS5jYWxsKHRoaXMsIGksIHZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIC8vIFNvIGV2dCBtdXN0IGJlIGEgc3RyaW5nXG4gICAgICAgICAgICAvLyBBbmQgbGlzdGVuZXJzIG11c3QgYmUgYW4gYXJyYXkgb2YgbGlzdGVuZXJzXG4gICAgICAgICAgICAvLyBMb29wIG92ZXIgaXQgYW5kIHBhc3MgZWFjaCBvbmUgdG8gdGhlIG11bHRpcGxlIG1ldGhvZFxuICAgICAgICAgICAgaSA9IGxpc3RlbmVycy5sZW5ndGg7XG4gICAgICAgICAgICB3aGlsZSAoaS0tKSB7XG4gICAgICAgICAgICAgICAgc2luZ2xlLmNhbGwodGhpcywgZXZ0LCBsaXN0ZW5lcnNbaV0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIFJlbW92ZXMgYWxsIGxpc3RlbmVycyBmcm9tIGEgc3BlY2lmaWVkIGV2ZW50LlxuICAgICAqIElmIHlvdSBkbyBub3Qgc3BlY2lmeSBhbiBldmVudCB0aGVuIGFsbCBsaXN0ZW5lcnMgd2lsbCBiZSByZW1vdmVkLlxuICAgICAqIFRoYXQgbWVhbnMgZXZlcnkgZXZlbnQgd2lsbCBiZSBlbXB0aWVkLlxuICAgICAqIFlvdSBjYW4gYWxzbyBwYXNzIGEgcmVnZXggdG8gcmVtb3ZlIGFsbCBldmVudHMgdGhhdCBtYXRjaCBpdC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfFJlZ0V4cH0gW2V2dF0gT3B0aW9uYWwgbmFtZSBvZiB0aGUgZXZlbnQgdG8gcmVtb3ZlIGFsbCBsaXN0ZW5lcnMgZm9yLiBXaWxsIHJlbW92ZSBmcm9tIGV2ZXJ5IGV2ZW50IGlmIG5vdCBwYXNzZWQuXG4gICAgICogQHJldHVybiB7T2JqZWN0fSBDdXJyZW50IGluc3RhbmNlIG9mIEV2ZW50RW1pdHRlciBmb3IgY2hhaW5pbmcuXG4gICAgICovXG4gICAgcHJvdG8ucmVtb3ZlRXZlbnQgPSBmdW5jdGlvbiByZW1vdmVFdmVudChldnQpIHtcbiAgICAgICAgdmFyIHR5cGUgPSB0eXBlb2YgZXZ0O1xuICAgICAgICB2YXIgZXZlbnRzID0gdGhpcy5fZ2V0RXZlbnRzKCk7XG4gICAgICAgIHZhciBrZXk7XG5cbiAgICAgICAgLy8gUmVtb3ZlIGRpZmZlcmVudCB0aGluZ3MgZGVwZW5kaW5nIG9uIHRoZSBzdGF0ZSBvZiBldnRcbiAgICAgICAgaWYgKHR5cGUgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAvLyBSZW1vdmUgYWxsIGxpc3RlbmVycyBmb3IgdGhlIHNwZWNpZmllZCBldmVudFxuICAgICAgICAgICAgZGVsZXRlIGV2ZW50c1tldnRdO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKGV2dCBpbnN0YW5jZW9mIFJlZ0V4cCkge1xuICAgICAgICAgICAgLy8gUmVtb3ZlIGFsbCBldmVudHMgbWF0Y2hpbmcgdGhlIHJlZ2V4LlxuICAgICAgICAgICAgZm9yIChrZXkgaW4gZXZlbnRzKSB7XG4gICAgICAgICAgICAgICAgaWYgKGV2ZW50cy5oYXNPd25Qcm9wZXJ0eShrZXkpICYmIGV2dC50ZXN0KGtleSkpIHtcbiAgICAgICAgICAgICAgICAgICAgZGVsZXRlIGV2ZW50c1trZXldO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIC8vIFJlbW92ZSBhbGwgbGlzdGVuZXJzIGluIGFsbCBldmVudHNcbiAgICAgICAgICAgIGRlbGV0ZSB0aGlzLl9ldmVudHM7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogQWxpYXMgb2YgcmVtb3ZlRXZlbnQuXG4gICAgICpcbiAgICAgKiBBZGRlZCB0byBtaXJyb3IgdGhlIG5vZGUgQVBJLlxuICAgICAqL1xuICAgIHByb3RvLnJlbW92ZUFsbExpc3RlbmVycyA9IGFsaWFzKCdyZW1vdmVFdmVudCcpO1xuXG4gICAgLyoqXG4gICAgICogRW1pdHMgYW4gZXZlbnQgb2YgeW91ciBjaG9pY2UuXG4gICAgICogV2hlbiBlbWl0dGVkLCBldmVyeSBsaXN0ZW5lciBhdHRhY2hlZCB0byB0aGF0IGV2ZW50IHdpbGwgYmUgZXhlY3V0ZWQuXG4gICAgICogSWYgeW91IHBhc3MgdGhlIG9wdGlvbmFsIGFyZ3VtZW50IGFycmF5IHRoZW4gdGhvc2UgYXJndW1lbnRzIHdpbGwgYmUgcGFzc2VkIHRvIGV2ZXJ5IGxpc3RlbmVyIHVwb24gZXhlY3V0aW9uLlxuICAgICAqIEJlY2F1c2UgaXQgdXNlcyBgYXBwbHlgLCB5b3VyIGFycmF5IG9mIGFyZ3VtZW50cyB3aWxsIGJlIHBhc3NlZCBhcyBpZiB5b3Ugd3JvdGUgdGhlbSBvdXQgc2VwYXJhdGVseS5cbiAgICAgKiBTbyB0aGV5IHdpbGwgbm90IGFycml2ZSB3aXRoaW4gdGhlIGFycmF5IG9uIHRoZSBvdGhlciBzaWRlLCB0aGV5IHdpbGwgYmUgc2VwYXJhdGUuXG4gICAgICogWW91IGNhbiBhbHNvIHBhc3MgYSByZWd1bGFyIGV4cHJlc3Npb24gdG8gZW1pdCB0byBhbGwgZXZlbnRzIHRoYXQgbWF0Y2ggaXQuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1N0cmluZ3xSZWdFeHB9IGV2dCBOYW1lIG9mIHRoZSBldmVudCB0byBlbWl0IGFuZCBleGVjdXRlIGxpc3RlbmVycyBmb3IuXG4gICAgICogQHBhcmFtIHtBcnJheX0gW2FyZ3NdIE9wdGlvbmFsIGFycmF5IG9mIGFyZ3VtZW50cyB0byBiZSBwYXNzZWQgdG8gZWFjaCBsaXN0ZW5lci5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEN1cnJlbnQgaW5zdGFuY2Ugb2YgRXZlbnRFbWl0dGVyIGZvciBjaGFpbmluZy5cbiAgICAgKi9cbiAgICBwcm90by5lbWl0RXZlbnQgPSBmdW5jdGlvbiBlbWl0RXZlbnQoZXZ0LCBhcmdzKSB7XG4gICAgICAgIHZhciBsaXN0ZW5lcnNNYXAgPSB0aGlzLmdldExpc3RlbmVyc0FzT2JqZWN0KGV2dCk7XG4gICAgICAgIHZhciBsaXN0ZW5lcnM7XG4gICAgICAgIHZhciBsaXN0ZW5lcjtcbiAgICAgICAgdmFyIGk7XG4gICAgICAgIHZhciBrZXk7XG4gICAgICAgIHZhciByZXNwb25zZTtcblxuICAgICAgICBmb3IgKGtleSBpbiBsaXN0ZW5lcnNNYXApIHtcbiAgICAgICAgICAgIGlmIChsaXN0ZW5lcnNNYXAuaGFzT3duUHJvcGVydHkoa2V5KSkge1xuICAgICAgICAgICAgICAgIGxpc3RlbmVycyA9IGxpc3RlbmVyc01hcFtrZXldLnNsaWNlKDApO1xuXG4gICAgICAgICAgICAgICAgZm9yIChpID0gMDsgaSA8IGxpc3RlbmVycy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAvLyBJZiB0aGUgbGlzdGVuZXIgcmV0dXJucyB0cnVlIHRoZW4gaXQgc2hhbGwgYmUgcmVtb3ZlZCBmcm9tIHRoZSBldmVudFxuICAgICAgICAgICAgICAgICAgICAvLyBUaGUgZnVuY3Rpb24gaXMgZXhlY3V0ZWQgZWl0aGVyIHdpdGggYSBiYXNpYyBjYWxsIG9yIGFuIGFwcGx5IGlmIHRoZXJlIGlzIGFuIGFyZ3MgYXJyYXlcbiAgICAgICAgICAgICAgICAgICAgbGlzdGVuZXIgPSBsaXN0ZW5lcnNbaV07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGxpc3RlbmVyLm9uY2UgPT09IHRydWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucmVtb3ZlTGlzdGVuZXIoZXZ0LCBsaXN0ZW5lci5saXN0ZW5lcik7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICByZXNwb25zZSA9IGxpc3RlbmVyLmxpc3RlbmVyLmFwcGx5KHRoaXMsIGFyZ3MgfHwgW10pO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChyZXNwb25zZSA9PT0gdGhpcy5fZ2V0T25jZVJldHVyblZhbHVlKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucmVtb3ZlTGlzdGVuZXIoZXZ0LCBsaXN0ZW5lci5saXN0ZW5lcik7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogQWxpYXMgb2YgZW1pdEV2ZW50XG4gICAgICovXG4gICAgcHJvdG8udHJpZ2dlciA9IGFsaWFzKCdlbWl0RXZlbnQnKTtcblxuICAgIC8qKlxuICAgICAqIFN1YnRseSBkaWZmZXJlbnQgZnJvbSBlbWl0RXZlbnQgaW4gdGhhdCBpdCB3aWxsIHBhc3MgaXRzIGFyZ3VtZW50cyBvbiB0byB0aGUgbGlzdGVuZXJzLCBhcyBvcHBvc2VkIHRvIHRha2luZyBhIHNpbmdsZSBhcnJheSBvZiBhcmd1bWVudHMgdG8gcGFzcyBvbi5cbiAgICAgKiBBcyB3aXRoIGVtaXRFdmVudCwgeW91IGNhbiBwYXNzIGEgcmVnZXggaW4gcGxhY2Ugb2YgdGhlIGV2ZW50IG5hbWUgdG8gZW1pdCB0byBhbGwgZXZlbnRzIHRoYXQgbWF0Y2ggaXQuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1N0cmluZ3xSZWdFeHB9IGV2dCBOYW1lIG9mIHRoZSBldmVudCB0byBlbWl0IGFuZCBleGVjdXRlIGxpc3RlbmVycyBmb3IuXG4gICAgICogQHBhcmFtIHsuLi4qfSBPcHRpb25hbCBhZGRpdGlvbmFsIGFyZ3VtZW50cyB0byBiZSBwYXNzZWQgdG8gZWFjaCBsaXN0ZW5lci5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEN1cnJlbnQgaW5zdGFuY2Ugb2YgRXZlbnRFbWl0dGVyIGZvciBjaGFpbmluZy5cbiAgICAgKi9cbiAgICBwcm90by5lbWl0ID0gZnVuY3Rpb24gZW1pdChldnQpIHtcbiAgICAgICAgdmFyIGFyZ3MgPSBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMsIDEpO1xuICAgICAgICByZXR1cm4gdGhpcy5lbWl0RXZlbnQoZXZ0LCBhcmdzKTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogU2V0cyB0aGUgY3VycmVudCB2YWx1ZSB0byBjaGVjayBhZ2FpbnN0IHdoZW4gZXhlY3V0aW5nIGxpc3RlbmVycy4gSWYgYVxuICAgICAqIGxpc3RlbmVycyByZXR1cm4gdmFsdWUgbWF0Y2hlcyB0aGUgb25lIHNldCBoZXJlIHRoZW4gaXQgd2lsbCBiZSByZW1vdmVkXG4gICAgICogYWZ0ZXIgZXhlY3V0aW9uLiBUaGlzIHZhbHVlIGRlZmF1bHRzIHRvIHRydWUuXG4gICAgICpcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSBuZXcgdmFsdWUgdG8gY2hlY2sgZm9yIHdoZW4gZXhlY3V0aW5nIGxpc3RlbmVycy5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEN1cnJlbnQgaW5zdGFuY2Ugb2YgRXZlbnRFbWl0dGVyIGZvciBjaGFpbmluZy5cbiAgICAgKi9cbiAgICBwcm90by5zZXRPbmNlUmV0dXJuVmFsdWUgPSBmdW5jdGlvbiBzZXRPbmNlUmV0dXJuVmFsdWUodmFsdWUpIHtcbiAgICAgICAgdGhpcy5fb25jZVJldHVyblZhbHVlID0gdmFsdWU7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBGZXRjaGVzIHRoZSBjdXJyZW50IHZhbHVlIHRvIGNoZWNrIGFnYWluc3Qgd2hlbiBleGVjdXRpbmcgbGlzdGVuZXJzLiBJZlxuICAgICAqIHRoZSBsaXN0ZW5lcnMgcmV0dXJuIHZhbHVlIG1hdGNoZXMgdGhpcyBvbmUgdGhlbiBpdCBzaG91bGQgYmUgcmVtb3ZlZFxuICAgICAqIGF1dG9tYXRpY2FsbHkuIEl0IHdpbGwgcmV0dXJuIHRydWUgYnkgZGVmYXVsdC5cbiAgICAgKlxuICAgICAqIEByZXR1cm4geyp8Qm9vbGVhbn0gVGhlIGN1cnJlbnQgdmFsdWUgdG8gY2hlY2sgZm9yIG9yIHRoZSBkZWZhdWx0LCB0cnVlLlxuICAgICAqIEBhcGkgcHJpdmF0ZVxuICAgICAqL1xuICAgIHByb3RvLl9nZXRPbmNlUmV0dXJuVmFsdWUgPSBmdW5jdGlvbiBfZ2V0T25jZVJldHVyblZhbHVlKCkge1xuICAgICAgICBpZiAodGhpcy5oYXNPd25Qcm9wZXJ0eSgnX29uY2VSZXR1cm5WYWx1ZScpKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5fb25jZVJldHVyblZhbHVlO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogRmV0Y2hlcyB0aGUgZXZlbnRzIG9iamVjdCBhbmQgY3JlYXRlcyBvbmUgaWYgcmVxdWlyZWQuXG4gICAgICpcbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IFRoZSBldmVudHMgc3RvcmFnZSBvYmplY3QuXG4gICAgICogQGFwaSBwcml2YXRlXG4gICAgICovXG4gICAgcHJvdG8uX2dldEV2ZW50cyA9IGZ1bmN0aW9uIF9nZXRFdmVudHMoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9ldmVudHMgfHwgKHRoaXMuX2V2ZW50cyA9IHt9KTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogUmV2ZXJ0cyB0aGUgZ2xvYmFsIHtAbGluayBFdmVudEVtaXR0ZXJ9IHRvIGl0cyBwcmV2aW91cyB2YWx1ZSBhbmQgcmV0dXJucyBhIHJlZmVyZW5jZSB0byB0aGlzIHZlcnNpb24uXG4gICAgICpcbiAgICAgKiBAcmV0dXJuIHtGdW5jdGlvbn0gTm9uIGNvbmZsaWN0aW5nIEV2ZW50RW1pdHRlciBjbGFzcy5cbiAgICAgKi9cbiAgICBFdmVudEVtaXR0ZXIubm9Db25mbGljdCA9IGZ1bmN0aW9uIG5vQ29uZmxpY3QoKSB7XG4gICAgICAgIGV4cG9ydHMuRXZlbnRFbWl0dGVyID0gb3JpZ2luYWxHbG9iYWxWYWx1ZTtcbiAgICAgICAgcmV0dXJuIEV2ZW50RW1pdHRlcjtcbiAgICB9O1xuXG4gICAgLy8gRXhwb3NlIHRoZSBjbGFzcyBlaXRoZXIgdmlhIEFNRCwgQ29tbW9uSlMgb3IgdGhlIGdsb2JhbCBvYmplY3RcbiAgICBpZiAodHlwZW9mIGRlZmluZSA9PT0gJ2Z1bmN0aW9uJyAmJiBkZWZpbmUuYW1kKSB7XG4gICAgICAgIGRlZmluZShmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gRXZlbnRFbWl0dGVyO1xuICAgICAgICB9KTtcbiAgICB9XG4gICAgZWxzZSBpZiAodHlwZW9mIG1vZHVsZSA9PT0gJ29iamVjdCcgJiYgbW9kdWxlLmV4cG9ydHMpe1xuICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IEV2ZW50RW1pdHRlcjtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIGV4cG9ydHMuRXZlbnRFbWl0dGVyID0gRXZlbnRFbWl0dGVyO1xuICAgIH1cbn0odHlwZW9mIHdpbmRvdyAhPT0gJ3VuZGVmaW5lZCcgPyB3aW5kb3cgOiB0aGlzIHx8IHt9KSk7XG4iLCJpbXBvcnQgeyBPcGVuVmlkdSB9IGZyb20gJy4vT3BlblZpZHUvT3BlblZpZHUnO1xuXG5pZiAod2luZG93KSB7XG4gICAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lOm5vLXN0cmluZy1saXRlcmFsXG4gICAgd2luZG93WydPcGVuVmlkdSddID0gT3BlblZpZHU7XG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBTZXNzaW9uIH0gZnJvbSAnLi9TZXNzaW9uJztcbmltcG9ydCB7IFN0cmVhbSB9IGZyb20gJy4vU3RyZWFtJztcbmltcG9ydCB7IENvbm5lY3Rpb25PcHRpb25zIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9JbnRlcmZhY2VzL1ByaXZhdGUvQ29ubmVjdGlvbk9wdGlvbnMnO1xuaW1wb3J0IHsgSW5ib3VuZFN0cmVhbU9wdGlvbnMgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHJpdmF0ZS9JbmJvdW5kU3RyZWFtT3B0aW9ucyc7XG5pbXBvcnQgeyBTdHJlYW1PcHRpb25zU2VydmVyIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9JbnRlcmZhY2VzL1ByaXZhdGUvU3RyZWFtT3B0aW9uc1NlcnZlcic7XG5cblxuLyoqXG4gKiBSZXByZXNlbnRzIGVhY2ggb25lIG9mIHRoZSB1c2VyJ3MgY29ubmVjdGlvbiB0byB0aGUgc2Vzc2lvbiAodGhlIGxvY2FsIG9uZSBhbmQgb3RoZXIgdXNlcidzIGNvbm5lY3Rpb25zKS5cbiAqIFRoZXJlZm9yZSBlYWNoIFtbU2Vzc2lvbl1dIGFuZCBbW1N0cmVhbV1dIG9iamVjdCBoYXMgYW4gYXR0cmlidXRlIG9mIHR5cGUgQ29ubmVjdGlvblxuICovXG5leHBvcnQgY2xhc3MgQ29ubmVjdGlvbiB7XG5cbiAgICAvKipcbiAgICAgKiBVbmlxdWUgaWRlbnRpZmllciBvZiB0aGUgY29ubmVjdGlvblxuICAgICAqL1xuICAgIGNvbm5lY3Rpb25JZDogc3RyaW5nO1xuXG4gICAgLyoqXG4gICAgICogVGltZSB3aGVuIHRoaXMgY29ubmVjdGlvbiB3YXMgY3JlYXRlZCAoVVRDIG1pbGxpc2Vjb25kcylcbiAgICAgKi9cbiAgICBjcmVhdGlvblRpbWU6IG51bWJlcjtcblxuICAgIC8qKlxuICAgICAqIERhdGEgYXNzb2NpYXRlZCB0byB0aGlzIGNvbm5lY3Rpb24gKGFuZCB0aGVyZWZvcmUgdG8gY2VydGFpbiB1c2VyKS4gVGhpcyBpcyBhbiBpbXBvcnRhbnQgZmllbGQ6XG4gICAgICogaXQgYWxsb3dzIHlvdSB0byBicm9hZGNhc3QgYWxsIHRoZSBpbmZvcm1hdGlvbiB5b3Ugd2FudCBmb3IgZWFjaCB1c2VyIChhIHVzZXJuYW1lLCBmb3IgZXhhbXBsZSlcbiAgICAgKi9cbiAgICBkYXRhOiBzdHJpbmc7XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgc3RyZWFtOiBTdHJlYW07XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgb3B0aW9uczogQ29ubmVjdGlvbk9wdGlvbnMgfCB1bmRlZmluZWQ7XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgZGlzcG9zZWQgPSBmYWxzZTtcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3Rvcihwcml2YXRlIHNlc3Npb246IFNlc3Npb24sIG9wdHM/OiBDb25uZWN0aW9uT3B0aW9ucykge1xuXG4gICAgICAgIGxldCBtc2cgPSBcIidDb25uZWN0aW9uJyBjcmVhdGVkIFwiO1xuICAgICAgICBpZiAoISFvcHRzKSB7XG4gICAgICAgICAgICBtc2cgKz0gXCIocmVtb3RlKSB3aXRoICdjb25uZWN0aW9uSWQnIFtcIiArIG9wdHMuaWQgKyAnXSc7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBtc2cgKz0gJyhsb2NhbCknO1xuICAgICAgICB9XG4gICAgICAgIGNvbnNvbGUuaW5mbyhtc2cpO1xuXG4gICAgICAgIHRoaXMub3B0aW9ucyA9IG9wdHM7XG5cbiAgICAgICAgaWYgKCEhb3B0cykge1xuICAgICAgICAgICAgLy8gQ29ubmVjdGlvbiBpcyByZW1vdGVcbiAgICAgICAgICAgIHRoaXMuY29ubmVjdGlvbklkID0gb3B0cy5pZDtcbiAgICAgICAgICAgIGlmIChvcHRzLm1ldGFkYXRhKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5kYXRhID0gb3B0cy5tZXRhZGF0YTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChvcHRzLnN0cmVhbXMpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmluaXRSZW1vdGVTdHJlYW1zKG9wdHMuc3RyZWFtcyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLmNyZWF0aW9uVGltZSA9IG5ldyBEYXRlKCkuZ2V0VGltZSgpO1xuICAgIH1cblxuXG4gICAgLyogSGlkZGVuIG1ldGhvZHMgKi9cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBzZW5kSWNlQ2FuZGlkYXRlKGNhbmRpZGF0ZTogUlRDSWNlQ2FuZGlkYXRlKTogdm9pZCB7XG5cbiAgICAgICAgY29uc29sZS5kZWJ1ZygoISF0aGlzLnN0cmVhbS5vdXRib3VuZFN0cmVhbU9wdHMgPyAnTG9jYWwnIDogJ1JlbW90ZScpLCAnY2FuZGlkYXRlIGZvcicsXG4gICAgICAgICAgICB0aGlzLmNvbm5lY3Rpb25JZCwgSlNPTi5zdHJpbmdpZnkoY2FuZGlkYXRlKSk7XG5cbiAgICAgICAgdGhpcy5zZXNzaW9uLm9wZW52aWR1LnNlbmRSZXF1ZXN0KCdvbkljZUNhbmRpZGF0ZScsIHtcbiAgICAgICAgICAgIGVuZHBvaW50TmFtZTogdGhpcy5jb25uZWN0aW9uSWQsXG4gICAgICAgICAgICBjYW5kaWRhdGU6IGNhbmRpZGF0ZS5jYW5kaWRhdGUsXG4gICAgICAgICAgICBzZHBNaWQ6IGNhbmRpZGF0ZS5zZHBNaWQsXG4gICAgICAgICAgICBzZHBNTGluZUluZGV4OiBjYW5kaWRhdGUuc2RwTUxpbmVJbmRleFxuICAgICAgICB9LCAoZXJyb3IsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICBpZiAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKCdFcnJvciBzZW5kaW5nIElDRSBjYW5kaWRhdGU6ICdcbiAgICAgICAgICAgICAgICAgICAgKyBKU09OLnN0cmluZ2lmeShlcnJvcikpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgaW5pdFJlbW90ZVN0cmVhbXMob3B0aW9uczogU3RyZWFtT3B0aW9uc1NlcnZlcltdKTogdm9pZCB7XG5cbiAgICAgICAgLy8gVGhpcyBpcyByZWFkeSBmb3Igc3VwcG9ydGluZyBtdWx0aXBsZSBzdHJlYW1zIHBlciBDb25uZWN0aW9uIG9iamVjdC4gUmlnaHQgbm93IHRoZSBsb29wIHdpbGwgYWx3YXlzIHJ1biBqdXN0IG9uY2VcbiAgICAgICAgLy8gdGhpcy5zdHJlYW0gc2hvdWxkIGFsc28gYmUgcmVwbGFjZWQgYnkgYSBjb2xsZWN0aW9uIG9mIHN0cmVhbXMgdG8gc3VwcG9ydCBtdWx0aXBsZSBzdHJlYW1zIHBlciBDb25uZWN0aW9uXG4gICAgICAgIG9wdGlvbnMuZm9yRWFjaChvcHRzID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHN0cmVhbU9wdGlvbnM6IEluYm91bmRTdHJlYW1PcHRpb25zID0ge1xuICAgICAgICAgICAgICAgIGlkOiBvcHRzLmlkLFxuICAgICAgICAgICAgICAgIGNvbm5lY3Rpb246IHRoaXMsXG4gICAgICAgICAgICAgICAgaGFzQXVkaW86IG9wdHMuaGFzQXVkaW8sXG4gICAgICAgICAgICAgICAgaGFzVmlkZW86IG9wdHMuaGFzVmlkZW8sXG4gICAgICAgICAgICAgICAgYXVkaW9BY3RpdmU6IG9wdHMuYXVkaW9BY3RpdmUsXG4gICAgICAgICAgICAgICAgdmlkZW9BY3RpdmU6IG9wdHMudmlkZW9BY3RpdmUsXG4gICAgICAgICAgICAgICAgdHlwZU9mVmlkZW86IG9wdHMudHlwZU9mVmlkZW8sXG4gICAgICAgICAgICAgICAgZnJhbWVSYXRlOiBvcHRzLmZyYW1lUmF0ZSxcbiAgICAgICAgICAgICAgICB2aWRlb0RpbWVuc2lvbnM6ICEhb3B0cy52aWRlb0RpbWVuc2lvbnMgPyBKU09OLnBhcnNlKG9wdHMudmlkZW9EaW1lbnNpb25zKSA6IHVuZGVmaW5lZFxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGNvbnN0IHN0cmVhbSA9IG5ldyBTdHJlYW0odGhpcy5zZXNzaW9uLCBzdHJlYW1PcHRpb25zKTtcblxuICAgICAgICAgICAgdGhpcy5hZGRTdHJlYW0oc3RyZWFtKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgY29uc29sZS5pbmZvKFwiUmVtb3RlICdDb25uZWN0aW9uJyB3aXRoICdjb25uZWN0aW9uSWQnIFtcIiArIHRoaXMuY29ubmVjdGlvbklkICsgJ10gaXMgbm93IGNvbmZpZ3VyZWQgZm9yIHJlY2VpdmluZyBTdHJlYW1zIHdpdGggb3B0aW9uczogJywgdGhpcy5zdHJlYW0uaW5ib3VuZFN0cmVhbU9wdHMpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBhZGRTdHJlYW0oc3RyZWFtOiBTdHJlYW0pOiB2b2lkIHtcbiAgICAgICAgc3RyZWFtLmNvbm5lY3Rpb24gPSB0aGlzO1xuICAgICAgICB0aGlzLnN0cmVhbSA9IHN0cmVhbTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgcmVtb3ZlU3RyZWFtKHN0cmVhbUlkOiBzdHJpbmcpOiB2b2lkIHtcbiAgICAgICAgZGVsZXRlIHRoaXMuc3RyZWFtO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBkaXNwb3NlKCk6IHZvaWQge1xuICAgICAgICBpZiAoISF0aGlzLnN0cmVhbSkge1xuICAgICAgICAgICAgZGVsZXRlIHRoaXMuc3RyZWFtO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuZGlzcG9zZWQgPSB0cnVlO1xuICAgIH1cblxufSIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTctMjAxOCBPcGVuVmlkdSAoaHR0cHM6Ly9vcGVudmlkdS5pby8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuaW1wb3J0IHsgU3RyZWFtIH0gZnJvbSAnLi9TdHJlYW0nO1xuaW1wb3J0IHsgTG9jYWxSZWNvcmRlclN0YXRlIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FbnVtcy9Mb2NhbFJlY29yZGVyU3RhdGUnO1xuXG4vKipcbiAqIEBoaWRkZW5cbiAqL1xuZGVjbGFyZSB2YXIgTWVkaWFSZWNvcmRlcjogYW55O1xuXG5cbi8qKlxuICogRWFzeSByZWNvcmRpbmcgb2YgW1tTdHJlYW1dXSBvYmplY3RzIHN0cmFpZ2h0YXdheSBmcm9tIHRoZSBicm93c2VyLlxuICpcbiAqID4gV0FSTklORzogUGVyZm9ybWluZyBicm93c2VyIGxvY2FsIHJlY29yZGluZyBvZiAqKnJlbW90ZSBzdHJlYW1zKiogbWF5IGNhdXNlIHNvbWUgdHJvdWJsZXMuIEEgbG9uZyB3YWl0aW5nIHRpbWUgbWF5IGJlIHJlcXVpcmVkIGFmdGVyIGNhbGxpbmcgX0xvY2FsUmVjb3JkZXIuc3RvcCgpXyBpbiB0aGlzIGNhc2VcbiAqL1xuZXhwb3J0IGNsYXNzIExvY2FsUmVjb3JkZXIge1xuXG4gICAgc3RhdGU6IExvY2FsUmVjb3JkZXJTdGF0ZTtcblxuICAgIHByaXZhdGUgY29ubmVjdGlvbklkOiBzdHJpbmc7XG4gICAgcHJpdmF0ZSBtZWRpYVJlY29yZGVyOiBhbnk7XG4gICAgcHJpdmF0ZSBjaHVua3M6IGFueVtdID0gW107XG4gICAgcHJpdmF0ZSBibG9iOiBCbG9iO1xuICAgIHByaXZhdGUgY291bnQgPSAwO1xuICAgIHByaXZhdGUgaWQ6IHN0cmluZztcbiAgICBwcml2YXRlIHZpZGVvUHJldmlld1NyYzogc3RyaW5nO1xuICAgIHByaXZhdGUgaHRtbFBhcmVudEVsZW1lbnRJZDogc3RyaW5nO1xuICAgIHByaXZhdGUgdmlkZW9QcmV2aWV3OiBIVE1MVmlkZW9FbGVtZW50O1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHByaXZhdGUgc3RyZWFtOiBTdHJlYW0pIHtcbiAgICAgICAgdGhpcy5jb25uZWN0aW9uSWQgPSAoISF0aGlzLnN0cmVhbS5jb25uZWN0aW9uKSA/IHRoaXMuc3RyZWFtLmNvbm5lY3Rpb24uY29ubmVjdGlvbklkIDogJ2RlZmF1bHQtY29ubmVjdGlvbic7XG4gICAgICAgIHRoaXMuaWQgPSB0aGlzLnN0cmVhbS5zdHJlYW1JZCArICdfJyArIHRoaXMuY29ubmVjdGlvbklkICsgJ19sb2NhbHJlY29yZCc7XG4gICAgICAgIHRoaXMuc3RhdGUgPSBMb2NhbFJlY29yZGVyU3RhdGUuUkVBRFk7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBTdGFydHMgdGhlIHJlY29yZGluZyBvZiB0aGUgU3RyZWFtLiBbW3N0YXRlXV0gcHJvcGVydHkgbXVzdCBiZSBgUkVBRFlgLiBBZnRlciBtZXRob2Qgc3VjY2VlZHMgaXMgc2V0IHRvIGBSRUNPUkRJTkdgXG4gICAgICogQHJldHVybnMgQSBQcm9taXNlICh0byB3aGljaCB5b3UgY2FuIG9wdGlvbmFsbHkgc3Vic2NyaWJlIHRvKSB0aGF0IGlzIHJlc29sdmVkIGlmIHRoZSByZWNvcmRpbmcgc3VjY2Vzc2Z1bGx5IHN0YXJ0ZWQgYW5kIHJlamVjdGVkIHdpdGggYW4gRXJyb3Igb2JqZWN0IGlmIG5vdFxuICAgICAqL1xuICAgIHJlY29yZCgpOiBQcm9taXNlPGFueT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuXG4gICAgICAgICAgICB0cnkge1xuXG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBNZWRpYVJlY29yZGVyID09PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKCdNZWRpYVJlY29yZGVyIG5vdCBzdXBwb3J0ZWQgb24geW91ciBicm93c2VyLiBTZWUgY29tcGF0aWJpbGl0eSBpbiBodHRwczovL2Nhbml1c2UuY29tLyNzZWFyY2g9TWVkaWFSZWNvcmRlcicpO1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyAoRXJyb3IoJ01lZGlhUmVjb3JkZXIgbm90IHN1cHBvcnRlZCBvbiB5b3VyIGJyb3dzZXIuIFNlZSBjb21wYXRpYmlsaXR5IGluIGh0dHBzOi8vY2FuaXVzZS5jb20vI3NlYXJjaD1NZWRpYVJlY29yZGVyJykpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAodGhpcy5zdGF0ZSAhPT0gTG9jYWxSZWNvcmRlclN0YXRlLlJFQURZKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IChFcnJvcignXFwnTG9jYWxSZWNvcmQucmVjb3JkKClcXCcgbmVlZHMgXFwnTG9jYWxSZWNvcmQuc3RhdGVcXCcgdG8gYmUgXFwnUkVBRFlcXCcgKGN1cnJlbnQgdmFsdWU6IFxcJycgKyB0aGlzLnN0YXRlICsgJ1xcJykuIENhbGwgXFwnTG9jYWxSZWNvcmRlci5jbGVhbigpXFwnIG9yIGluaXQgYSBuZXcgTG9jYWxSZWNvcmRlciBiZWZvcmUnKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKFwiU3RhcnRpbmcgbG9jYWwgcmVjb3JkaW5nIG9mIHN0cmVhbSAnXCIgKyB0aGlzLnN0cmVhbS5zdHJlYW1JZCArIFwiJyBvZiBjb25uZWN0aW9uICdcIiArIHRoaXMuY29ubmVjdGlvbklkICsgXCInXCIpO1xuXG5cbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIE1lZGlhUmVjb3JkZXIuaXNUeXBlU3VwcG9ydGVkID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICAgICAgICAgIGxldCBvcHRpb25zO1xuICAgICAgICAgICAgICAgICAgICBpZiAoTWVkaWFSZWNvcmRlci5pc1R5cGVTdXBwb3J0ZWQoJ3ZpZGVvL3dlYm07Y29kZWNzPXZwOScpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBvcHRpb25zID0geyBtaW1lVHlwZTogJ3ZpZGVvL3dlYm07Y29kZWNzPXZwOScgfTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChNZWRpYVJlY29yZGVyLmlzVHlwZVN1cHBvcnRlZCgndmlkZW8vd2VibTtjb2RlY3M9aDI2NCcpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBvcHRpb25zID0geyBtaW1lVHlwZTogJ3ZpZGVvL3dlYm07Y29kZWNzPWgyNjQnIH07XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoTWVkaWFSZWNvcmRlci5pc1R5cGVTdXBwb3J0ZWQoJ3ZpZGVvL3dlYm07Y29kZWNzPXZwOCcpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBvcHRpb25zID0geyBtaW1lVHlwZTogJ3ZpZGVvL3dlYm07Y29kZWNzPXZwOCcgfTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmxvZygnVXNpbmcgbWltZVR5cGUgJyArIG9wdGlvbnMubWltZVR5cGUpO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLm1lZGlhUmVjb3JkZXIgPSBuZXcgTWVkaWFSZWNvcmRlcih0aGlzLnN0cmVhbS5nZXRNZWRpYVN0cmVhbSgpLCBvcHRpb25zKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLndhcm4oJ2lzVHlwZVN1cHBvcnRlZCBpcyBub3Qgc3VwcG9ydGVkLCB1c2luZyBkZWZhdWx0IGNvZGVjcyBmb3IgYnJvd3NlcicpO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLm1lZGlhUmVjb3JkZXIgPSBuZXcgTWVkaWFSZWNvcmRlcih0aGlzLnN0cmVhbS5nZXRNZWRpYVN0cmVhbSgpKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB0aGlzLm1lZGlhUmVjb3JkZXIuc3RhcnQoMTApO1xuXG4gICAgICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAgICAgICByZWplY3QoZXJyKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5tZWRpYVJlY29yZGVyLm9uZGF0YWF2YWlsYWJsZSA9IChlKSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5jaHVua3MucHVzaChlLmRhdGEpO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgdGhpcy5tZWRpYVJlY29yZGVyLm9uZXJyb3IgPSAoZSkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ01lZGlhUmVjb3JkZXIgZXJyb3I6ICcsIGUpO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgdGhpcy5tZWRpYVJlY29yZGVyLm9uc3RhcnQgPSAoKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5sb2coJ01lZGlhUmVjb3JkZXIgc3RhcnRlZCAoc3RhdGU9JyArIHRoaXMubWVkaWFSZWNvcmRlci5zdGF0ZSArICcpJyk7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICB0aGlzLm1lZGlhUmVjb3JkZXIub25zdG9wID0gKCkgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMub25TdG9wRGVmYXVsdCgpO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgdGhpcy5tZWRpYVJlY29yZGVyLm9ucGF1c2UgPSAoKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5sb2coJ01lZGlhUmVjb3JkZXIgcGF1c2VkIChzdGF0ZT0nICsgdGhpcy5tZWRpYVJlY29yZGVyLnN0YXRlICsgJyknKTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIHRoaXMubWVkaWFSZWNvcmRlci5vbnJlc3VtZSA9ICgpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmxvZygnTWVkaWFSZWNvcmRlciByZXN1bWVkIChzdGF0ZT0nICsgdGhpcy5tZWRpYVJlY29yZGVyLnN0YXRlICsgJyknKTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIHRoaXMubWVkaWFSZWNvcmRlci5vbndhcm5pbmcgPSAoZSkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKCdNZWRpYVJlY29yZGVyIHdhcm5pbmc6ICcgKyBlKTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIHRoaXMuc3RhdGUgPSBMb2NhbFJlY29yZGVyU3RhdGUuUkVDT1JESU5HO1xuICAgICAgICAgICAgcmVzb2x2ZSgpO1xuXG4gICAgICAgIH0pO1xuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogRW5kcyB0aGUgcmVjb3JkaW5nIG9mIHRoZSBTdHJlYW0uIFtbc3RhdGVdXSBwcm9wZXJ0eSBtdXN0IGJlIGBSRUNPUkRJTkdgIG9yIGBQQVVTRURgLiBBZnRlciBtZXRob2Qgc3VjY2VlZHMgaXMgc2V0IHRvIGBGSU5JU0hFRGBcbiAgICAgKiBAcmV0dXJucyBBIFByb21pc2UgKHRvIHdoaWNoIHlvdSBjYW4gb3B0aW9uYWxseSBzdWJzY3JpYmUgdG8pIHRoYXQgaXMgcmVzb2x2ZWQgaWYgdGhlIHJlY29yZGluZyBzdWNjZXNzZnVsbHkgc3RvcHBlZCBhbmQgcmVqZWN0ZWQgd2l0aCBhbiBFcnJvciBvYmplY3QgaWYgbm90XG4gICAgICovXG4gICAgc3RvcCgpOiBQcm9taXNlPGFueT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5zdGF0ZSA9PT0gTG9jYWxSZWNvcmRlclN0YXRlLlJFQURZIHx8IHRoaXMuc3RhdGUgPT09IExvY2FsUmVjb3JkZXJTdGF0ZS5GSU5JU0hFRCkge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyAoRXJyb3IoJ1xcJ0xvY2FsUmVjb3JkLnN0b3AoKVxcJyBuZWVkcyBcXCdMb2NhbFJlY29yZC5zdGF0ZVxcJyB0byBiZSBcXCdSRUNPUkRJTkdcXCcgb3IgXFwnUEFVU0VEXFwnIChjdXJyZW50IHZhbHVlOiBcXCcnICsgdGhpcy5zdGF0ZSArICdcXCcpLiBDYWxsIFxcJ0xvY2FsUmVjb3JkZXIuc3RhcnQoKVxcJyBiZWZvcmUnKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRoaXMubWVkaWFSZWNvcmRlci5vbnN0b3AgPSAoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMub25TdG9wRGVmYXVsdCgpO1xuICAgICAgICAgICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB0aGlzLm1lZGlhUmVjb3JkZXIuc3RvcCgpO1xuICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICAgIHJlamVjdChlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBQYXVzZXMgdGhlIHJlY29yZGluZyBvZiB0aGUgU3RyZWFtLiBbW3N0YXRlXV0gcHJvcGVydHkgbXVzdCBiZSBgUkVDT1JESU5HYC4gQWZ0ZXIgbWV0aG9kIHN1Y2NlZWRzIGlzIHNldCB0byBgUEFVU0VEYFxuICAgICAqIEByZXR1cm5zIEEgUHJvbWlzZSAodG8gd2hpY2ggeW91IGNhbiBvcHRpb25hbGx5IHN1YnNjcmliZSB0bykgdGhhdCBpcyByZXNvbHZlZCBpZiB0aGUgcmVjb3JkaW5nIHdhcyBzdWNjZXNzZnVsbHkgcGF1c2VkIGFuZCByZWplY3RlZCB3aXRoIGFuIEVycm9yIG9iamVjdCBpZiBub3RcbiAgICAgKi9cbiAgICBwYXVzZSgpOiBQcm9taXNlPGFueT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5zdGF0ZSAhPT0gTG9jYWxSZWNvcmRlclN0YXRlLlJFQ09SRElORykge1xuICAgICAgICAgICAgICAgICAgICByZWplY3QoRXJyb3IoJ1xcJ0xvY2FsUmVjb3JkLnBhdXNlKClcXCcgbmVlZHMgXFwnTG9jYWxSZWNvcmQuc3RhdGVcXCcgdG8gYmUgXFwnUkVDT1JESU5HXFwnIChjdXJyZW50IHZhbHVlOiBcXCcnICsgdGhpcy5zdGF0ZSArICdcXCcpLiBDYWxsIFxcJ0xvY2FsUmVjb3JkZXIuc3RhcnQoKVxcJyBvciBcXCdMb2NhbFJlY29yZGVyLnJlc3VtZSgpXFwnIGJlZm9yZScpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhpcy5tZWRpYVJlY29yZGVyLnBhdXNlKCk7XG4gICAgICAgICAgICAgICAgdGhpcy5zdGF0ZSA9IExvY2FsUmVjb3JkZXJTdGF0ZS5QQVVTRUQ7XG4gICAgICAgICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlc3VtZXMgdGhlIHJlY29yZGluZyBvZiB0aGUgU3RyZWFtLiBbW3N0YXRlXV0gcHJvcGVydHkgbXVzdCBiZSBgUEFVU0VEYC4gQWZ0ZXIgbWV0aG9kIHN1Y2NlZWRzIGlzIHNldCB0byBgUkVDT1JESU5HYFxuICAgICAqIEByZXR1cm5zIEEgUHJvbWlzZSAodG8gd2hpY2ggeW91IGNhbiBvcHRpb25hbGx5IHN1YnNjcmliZSB0bykgdGhhdCBpcyByZXNvbHZlZCBpZiB0aGUgcmVjb3JkaW5nIHdhcyBzdWNjZXNzZnVsbHkgcmVzdW1lZCBhbmQgcmVqZWN0ZWQgd2l0aCBhbiBFcnJvciBvYmplY3QgaWYgbm90XG4gICAgICovXG4gICAgcmVzdW1lKCk6IFByb21pc2U8YW55PiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLnN0YXRlICE9PSBMb2NhbFJlY29yZGVyU3RhdGUuUEFVU0VEKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IChFcnJvcignXFwnTG9jYWxSZWNvcmQucmVzdW1lKClcXCcgbmVlZHMgXFwnTG9jYWxSZWNvcmQuc3RhdGVcXCcgdG8gYmUgXFwnUEFVU0VEXFwnIChjdXJyZW50IHZhbHVlOiBcXCcnICsgdGhpcy5zdGF0ZSArICdcXCcpLiBDYWxsIFxcJ0xvY2FsUmVjb3JkZXIucGF1c2UoKVxcJyBiZWZvcmUnKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRoaXMubWVkaWFSZWNvcmRlci5yZXN1bWUoKTtcbiAgICAgICAgICAgICAgICB0aGlzLnN0YXRlID0gTG9jYWxSZWNvcmRlclN0YXRlLlJFQ09SRElORztcbiAgICAgICAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBQcmV2aWV3cyB0aGUgcmVjb3JkaW5nLCBhcHBlbmRpbmcgYSBuZXcgSFRNTFZpZGVvRWxlbWVudCB0byBlbGVtZW50IHdpdGggaWQgYHBhcmVudElkYC4gW1tzdGF0ZV1dIHByb3BlcnR5IG11c3QgYmUgYEZJTklTSEVEYFxuICAgICAqL1xuICAgIHByZXZpZXcocGFyZW50RWxlbWVudCk6IEhUTUxWaWRlb0VsZW1lbnQge1xuXG4gICAgICAgIGlmICh0aGlzLnN0YXRlICE9PSBMb2NhbFJlY29yZGVyU3RhdGUuRklOSVNIRUQpIHtcbiAgICAgICAgICAgIHRocm93IChFcnJvcignXFwnTG9jYWxSZWNvcmQucHJldmlldygpXFwnIG5lZWRzIFxcJ0xvY2FsUmVjb3JkLnN0YXRlXFwnIHRvIGJlIFxcJ0ZJTklTSEVEXFwnIChjdXJyZW50IHZhbHVlOiBcXCcnICsgdGhpcy5zdGF0ZSArICdcXCcpLiBDYWxsIFxcJ0xvY2FsUmVjb3JkZXIuc3RvcCgpXFwnIGJlZm9yZScpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMudmlkZW9QcmV2aWV3ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgndmlkZW8nKTtcblxuICAgICAgICB0aGlzLnZpZGVvUHJldmlldy5pZCA9IHRoaXMuaWQ7XG4gICAgICAgIHRoaXMudmlkZW9QcmV2aWV3LmF1dG9wbGF5ID0gdHJ1ZTtcblxuICAgICAgICBpZiAodHlwZW9mIHBhcmVudEVsZW1lbnQgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICB0aGlzLmh0bWxQYXJlbnRFbGVtZW50SWQgPSBwYXJlbnRFbGVtZW50O1xuXG4gICAgICAgICAgICBjb25zdCBwYXJlbnRFbGVtZW50RG9tID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQocGFyZW50RWxlbWVudCk7XG4gICAgICAgICAgICBpZiAocGFyZW50RWxlbWVudERvbSkge1xuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9QcmV2aWV3ID0gcGFyZW50RWxlbWVudERvbS5hcHBlbmRDaGlsZCh0aGlzLnZpZGVvUHJldmlldyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLmh0bWxQYXJlbnRFbGVtZW50SWQgPSBwYXJlbnRFbGVtZW50LmlkO1xuICAgICAgICAgICAgdGhpcy52aWRlb1ByZXZpZXcgPSBwYXJlbnRFbGVtZW50LmFwcGVuZENoaWxkKHRoaXMudmlkZW9QcmV2aWV3KTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMudmlkZW9QcmV2aWV3LnNyYyA9IHRoaXMudmlkZW9QcmV2aWV3U3JjO1xuXG4gICAgICAgIHJldHVybiB0aGlzLnZpZGVvUHJldmlldztcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIEdyYWNlZnVsbHkgc3RvcHMgYW5kIGNsZWFucyB0aGUgY3VycmVudCByZWNvcmRpbmcgKFdBUk5JTkc6IGl0IGlzIGNvbXBsZXRlbHkgZGlzbWlzc2VkKS4gU2V0cyBbW3N0YXRlXV0gdG8gYFJFQURZYCBzbyB0aGUgcmVjb3JkaW5nIGNhbiBzdGFydCBhZ2FpblxuICAgICAqL1xuICAgIGNsZWFuKCk6IHZvaWQge1xuICAgICAgICBjb25zdCBmID0gKCkgPT4ge1xuICAgICAgICAgICAgZGVsZXRlIHRoaXMuYmxvYjtcbiAgICAgICAgICAgIHRoaXMuY2h1bmtzID0gW107XG4gICAgICAgICAgICB0aGlzLmNvdW50ID0gMDtcbiAgICAgICAgICAgIGRlbGV0ZSB0aGlzLm1lZGlhUmVjb3JkZXI7XG4gICAgICAgICAgICB0aGlzLnN0YXRlID0gTG9jYWxSZWNvcmRlclN0YXRlLlJFQURZO1xuICAgICAgICB9O1xuICAgICAgICBpZiAodGhpcy5zdGF0ZSA9PT0gTG9jYWxSZWNvcmRlclN0YXRlLlJFQ09SRElORyB8fCB0aGlzLnN0YXRlID09PSBMb2NhbFJlY29yZGVyU3RhdGUuUEFVU0VEKSB7XG4gICAgICAgICAgICB0aGlzLnN0b3AoKS50aGVuKCgpID0+IGYoKSkuY2F0Y2goKCkgPT4gZigpKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGYoKTtcbiAgICAgICAgfVxuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogRG93bmxvYWRzIHRoZSByZWNvcmRlZCB2aWRlbyB0aHJvdWdoIHRoZSBicm93c2VyLiBbW3N0YXRlXV0gcHJvcGVydHkgbXVzdCBiZSBgRklOSVNIRURgXG4gICAgICovXG4gICAgZG93bmxvYWQoKTogdm9pZCB7XG4gICAgICAgIGlmICh0aGlzLnN0YXRlICE9PSBMb2NhbFJlY29yZGVyU3RhdGUuRklOSVNIRUQpIHtcbiAgICAgICAgICAgIHRocm93IChFcnJvcignXFwnTG9jYWxSZWNvcmQuZG93bmxvYWQoKVxcJyBuZWVkcyBcXCdMb2NhbFJlY29yZC5zdGF0ZVxcJyB0byBiZSBcXCdGSU5JU0hFRFxcJyAoY3VycmVudCB2YWx1ZTogXFwnJyArIHRoaXMuc3RhdGUgKyAnXFwnKS4gQ2FsbCBcXCdMb2NhbFJlY29yZGVyLnN0b3AoKVxcJyBiZWZvcmUnKSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjb25zdCBhOiBIVE1MQW5jaG9yRWxlbWVudCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2EnKTtcbiAgICAgICAgICAgIGEuc3R5bGUuZGlzcGxheSA9ICdub25lJztcbiAgICAgICAgICAgIGRvY3VtZW50LmJvZHkuYXBwZW5kQ2hpbGQoYSk7XG5cbiAgICAgICAgICAgIGNvbnN0IHVybCA9IHdpbmRvdy5VUkwuY3JlYXRlT2JqZWN0VVJMKHRoaXMuYmxvYik7XG4gICAgICAgICAgICBhLmhyZWYgPSB1cmw7XG4gICAgICAgICAgICBhLmRvd25sb2FkID0gdGhpcy5pZCArICcud2VibSc7XG4gICAgICAgICAgICBhLmNsaWNrKCk7XG4gICAgICAgICAgICB3aW5kb3cuVVJMLnJldm9rZU9iamVjdFVSTCh1cmwpO1xuXG4gICAgICAgICAgICBkb2N1bWVudC5ib2R5LnJlbW92ZUNoaWxkKGEpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0cyB0aGUgcmF3IEJsb2IgZmlsZS4gTWV0aG9kcyBwcmV2aWV3LCBkb3dubG9hZCwgdXBsb2FkQXNCaW5hcnkgYW5kIHVwbG9hZEFzTXVsdGlwYXJ0ZmlsZSB1c2UgdGhpcyBzYW1lIGZpbGUgdG8gcGVyZm9ybSB0aGVpciBzcGVjaWZpYyBhY3Rpb25zLiBbW3N0YXRlXV0gcHJvcGVydHkgbXVzdCBiZSBgRklOSVNIRURgXG4gICAgICovXG4gICAgZ2V0QmxvYigpOiBCbG9iIHtcbiAgICAgICAgaWYgKHRoaXMuc3RhdGUgIT09IExvY2FsUmVjb3JkZXJTdGF0ZS5GSU5JU0hFRCkge1xuICAgICAgICAgICAgdGhyb3cgKEVycm9yKCdDYWxsIFxcJ0xvY2FsUmVjb3JkLnN0b3AoKVxcJyBiZWZvcmUgZ2V0dGluZyBCbG9iIGZpbGUnKSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5ibG9iO1xuICAgICAgICB9XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBVcGxvYWRzIHRoZSByZWNvcmRlZCB2aWRlbyBhcyBhIGJpbmFyeSBmaWxlIHBlcmZvcm1pbmcgYW4gSFRUUC9QT1NUIG9wZXJhdGlvbiB0byBVUkwgYGVuZHBvaW50YC4gW1tzdGF0ZV1dIHByb3BlcnR5IG11c3QgYmUgYEZJTklTSEVEYC4gT3B0aW9uYWwgSFRUUCBoZWFkZXJzIGNhbiBiZSBwYXNzZWQgYXMgc2Vjb25kIHBhcmFtZXRlci4gRm9yIGV4YW1wbGU6XG4gICAgICogYGBgXG4gICAgICogdmFyIGhlYWRlcnMgPSB7XG4gICAgICogIFwiQ29va2llXCI6IFwiJFZlcnNpb249MTsgU2tpbj1uZXc7XCIsXG4gICAgICogIFwiQXV0aG9yaXphdGlvblwiOlwiQmFzaWMgUVd4aFpHcGJqcHVJSE5sY3RaUT09XCJcbiAgICAgKiB9XG4gICAgICogYGBgXG4gICAgICogQHJldHVybnMgQSBQcm9taXNlICh0byB3aGljaCB5b3UgY2FuIG9wdGlvbmFsbHkgc3Vic2NyaWJlIHRvKSB0aGF0IGlzIHJlc29sdmVkIHdpdGggdGhlIGBodHRwLnJlc3BvbnNlVGV4dGAgZnJvbSBzZXJ2ZXIgaWYgdGhlIG9wZXJhdGlvbiB3YXMgc3VjY2Vzc2Z1bCBhbmQgcmVqZWN0ZWQgd2l0aCB0aGUgZmFpbGVkIGBodHRwLnN0YXR1c2AgaWYgbm90XG4gICAgICovXG4gICAgdXBsb2FkQXNCaW5hcnkoZW5kcG9pbnQ6IHN0cmluZywgaGVhZGVycz86IGFueSk6IFByb21pc2U8YW55PiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICBpZiAodGhpcy5zdGF0ZSAhPT0gTG9jYWxSZWNvcmRlclN0YXRlLkZJTklTSEVEKSB7XG4gICAgICAgICAgICAgICAgcmVqZWN0KEVycm9yKCdcXCdMb2NhbFJlY29yZC51cGxvYWRBc0JpbmFyeSgpXFwnIG5lZWRzIFxcJ0xvY2FsUmVjb3JkLnN0YXRlXFwnIHRvIGJlIFxcJ0ZJTklTSEVEXFwnIChjdXJyZW50IHZhbHVlOiBcXCcnICsgdGhpcy5zdGF0ZSArICdcXCcpLiBDYWxsIFxcJ0xvY2FsUmVjb3JkZXIuc3RvcCgpXFwnIGJlZm9yZScpKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY29uc3QgaHR0cCA9IG5ldyBYTUxIdHRwUmVxdWVzdCgpO1xuICAgICAgICAgICAgICAgIGh0dHAub3BlbignUE9TVCcsIGVuZHBvaW50LCB0cnVlKTtcblxuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgaGVhZGVycyA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgICAgICAgICAgICAgZm9yIChjb25zdCBrZXkgb2YgT2JqZWN0LmtleXMoaGVhZGVycykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGh0dHAuc2V0UmVxdWVzdEhlYWRlcihrZXksIGhlYWRlcnNba2V5XSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBodHRwLm9ucmVhZHlzdGF0ZWNoYW5nZSA9ICgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGh0dHAucmVhZHlTdGF0ZSA9PT0gNCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGh0dHAuc3RhdHVzLnRvU3RyaW5nKCkuY2hhckF0KDApID09PSAnMicpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBTdWNjZXNzIHJlc3BvbnNlIGZyb20gc2VydmVyIChIVFRQIHN0YXR1cyBzdGFuZGFyZDogMlhYIGlzIHN1Y2Nlc3MpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZShodHRwLnJlc3BvbnNlVGV4dCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChodHRwLnN0YXR1cyk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIGh0dHAuc2VuZCh0aGlzLmJsb2IpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFVwbG9hZHMgdGhlIHJlY29yZGVkIHZpZGVvIGFzIGEgbXVsdGlwYXJ0IGZpbGUgcGVyZm9ybWluZyBhbiBIVFRQL1BPU1Qgb3BlcmF0aW9uIHRvIFVSTCBgZW5kcG9pbnRgLiBbW3N0YXRlXV0gcHJvcGVydHkgbXVzdCBiZSBgRklOSVNIRURgLiBPcHRpb25hbCBIVFRQIGhlYWRlcnMgY2FuIGJlIHBhc3NlZCBhcyBzZWNvbmQgcGFyYW1ldGVyLiBGb3IgZXhhbXBsZTpcbiAgICAgKiBgYGBcbiAgICAgKiB2YXIgaGVhZGVycyA9IHtcbiAgICAgKiAgXCJDb29raWVcIjogXCIkVmVyc2lvbj0xOyBTa2luPW5ldztcIixcbiAgICAgKiAgXCJBdXRob3JpemF0aW9uXCI6XCJCYXNpYyBRV3hoWkdwYmpwdUlITmxjdFpRPT1cIlxuICAgICAqIH1cbiAgICAgKiBgYGBcbiAgICAgKiBAcmV0dXJucyBBIFByb21pc2UgKHRvIHdoaWNoIHlvdSBjYW4gb3B0aW9uYWxseSBzdWJzY3JpYmUgdG8pIHRoYXQgaXMgcmVzb2x2ZWQgd2l0aCB0aGUgYGh0dHAucmVzcG9uc2VUZXh0YCBmcm9tIHNlcnZlciBpZiB0aGUgb3BlcmF0aW9uIHdhcyBzdWNjZXNzZnVsIGFuZCByZWplY3RlZCB3aXRoIHRoZSBmYWlsZWQgYGh0dHAuc3RhdHVzYCBpZiBub3Q6XG4gICAgICovXG4gICAgdXBsb2FkQXNNdWx0aXBhcnRmaWxlKGVuZHBvaW50OiBzdHJpbmcsIGhlYWRlcnM/OiBhbnkpOiBQcm9taXNlPGFueT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgaWYgKHRoaXMuc3RhdGUgIT09IExvY2FsUmVjb3JkZXJTdGF0ZS5GSU5JU0hFRCkge1xuICAgICAgICAgICAgICAgIHJlamVjdChFcnJvcignXFwnTG9jYWxSZWNvcmQudXBsb2FkQXNNdWx0aXBhcnRmaWxlKClcXCcgbmVlZHMgXFwnTG9jYWxSZWNvcmQuc3RhdGVcXCcgdG8gYmUgXFwnRklOSVNIRURcXCcgKGN1cnJlbnQgdmFsdWU6IFxcJycgKyB0aGlzLnN0YXRlICsgJ1xcJykuIENhbGwgXFwnTG9jYWxSZWNvcmRlci5zdG9wKClcXCcgYmVmb3JlJykpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBjb25zdCBodHRwID0gbmV3IFhNTEh0dHBSZXF1ZXN0KCk7XG4gICAgICAgICAgICAgICAgaHR0cC5vcGVuKCdQT1NUJywgZW5kcG9pbnQsIHRydWUpO1xuXG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBoZWFkZXJzID09PSAnb2JqZWN0Jykge1xuICAgICAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IGtleSBvZiBPYmplY3Qua2V5cyhoZWFkZXJzKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaHR0cC5zZXRSZXF1ZXN0SGVhZGVyKGtleSwgaGVhZGVyc1trZXldKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGNvbnN0IHNlbmRhYmxlID0gbmV3IEZvcm1EYXRhKCk7XG4gICAgICAgICAgICAgICAgc2VuZGFibGUuYXBwZW5kKCdmaWxlJywgdGhpcy5ibG9iLCB0aGlzLmlkICsgJy53ZWJtJyk7XG5cbiAgICAgICAgICAgICAgICBodHRwLm9ucmVhZHlzdGF0ZWNoYW5nZSA9ICgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGh0dHAucmVhZHlTdGF0ZSA9PT0gNCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGh0dHAuc3RhdHVzLnRvU3RyaW5nKCkuY2hhckF0KDApID09PSAnMicpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBTdWNjZXNzIHJlc3BvbnNlIGZyb20gc2VydmVyIChIVFRQIHN0YXR1cyBzdGFuZGFyZDogMlhYIGlzIHN1Y2Nlc3MpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZShodHRwLnJlc3BvbnNlVGV4dCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChodHRwLnN0YXR1cyk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICAgICAgaHR0cC5zZW5kKHNlbmRhYmxlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG5cbiAgICAvKiBQcml2YXRlIG1ldGhvZHMgKi9cblxuICAgIHByaXZhdGUgb25TdG9wRGVmYXVsdCgpOiB2b2lkIHtcbiAgICAgICAgY29uc29sZS5sb2coJ01lZGlhUmVjb3JkZXIgc3RvcHBlZCAgKHN0YXRlPScgKyB0aGlzLm1lZGlhUmVjb3JkZXIuc3RhdGUgKyAnKScpO1xuXG4gICAgICAgIHRoaXMuYmxvYiA9IG5ldyBCbG9iKHRoaXMuY2h1bmtzLCB7IHR5cGU6ICd2aWRlby93ZWJtJyB9KTtcbiAgICAgICAgdGhpcy5jaHVua3MgPSBbXTtcblxuICAgICAgICB0aGlzLnZpZGVvUHJldmlld1NyYyA9IHdpbmRvdy5VUkwuY3JlYXRlT2JqZWN0VVJMKHRoaXMuYmxvYik7XG5cbiAgICAgICAgdGhpcy5zdGF0ZSA9IExvY2FsUmVjb3JkZXJTdGF0ZS5GSU5JU0hFRDtcbiAgICB9XG5cbn1cbiIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTctMjAxOCBPcGVuVmlkdSAoaHR0cHM6Ly9vcGVudmlkdS5pby8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuaW1wb3J0IHsgTG9jYWxSZWNvcmRlciB9IGZyb20gJy4vTG9jYWxSZWNvcmRlcic7XG5pbXBvcnQgeyBQdWJsaXNoZXIgfSBmcm9tICcuL1B1Ymxpc2hlcic7XG5pbXBvcnQgeyBTZXNzaW9uIH0gZnJvbSAnLi9TZXNzaW9uJztcbmltcG9ydCB7IFN0cmVhbSB9IGZyb20gJy4vU3RyZWFtJztcbmltcG9ydCB7IFN0cmVhbVByb3BlcnR5Q2hhbmdlZEV2ZW50IH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvU3RyZWFtUHJvcGVydHlDaGFuZ2VkRXZlbnQnO1xuaW1wb3J0IHsgRGV2aWNlIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9JbnRlcmZhY2VzL1B1YmxpYy9EZXZpY2UnO1xuaW1wb3J0IHsgT3BlblZpZHVBZHZhbmNlZENvbmZpZ3VyYXRpb24gfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHVibGljL09wZW5WaWR1QWR2YW5jZWRDb25maWd1cmF0aW9uJztcbmltcG9ydCB7IFB1Ymxpc2hlclByb3BlcnRpZXMgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHVibGljL1B1Ymxpc2hlclByb3BlcnRpZXMnO1xuaW1wb3J0IHsgT3BlblZpZHVFcnJvciwgT3BlblZpZHVFcnJvck5hbWUgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0VudW1zL09wZW5WaWR1RXJyb3InO1xuaW1wb3J0IHsgVmlkZW9JbnNlcnRNb2RlIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FbnVtcy9WaWRlb0luc2VydE1vZGUnO1xuXG5pbXBvcnQgKiBhcyBzY3JlZW5TaGFyaW5nQXV0byBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL1NjcmVlblNoYXJpbmcvU2NyZWVuLUNhcHR1cmluZy1BdXRvJztcbmltcG9ydCAqIGFzIHNjcmVlblNoYXJpbmcgZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9TY3JlZW5TaGFyaW5nL1NjcmVlbi1DYXB0dXJpbmcnO1xuXG5pbXBvcnQgUnBjQnVpbGRlciA9IHJlcXVpcmUoJy4uL09wZW5WaWR1SW50ZXJuYWwvS3VyZW50b1V0aWxzL2t1cmVudG8tanNvbnJwYycpO1xuaW1wb3J0IHBsYXRmb3JtID0gcmVxdWlyZSgncGxhdGZvcm0nKTtcblxuXG4vKipcbiAqIEVudHJ5cG9pbnQgb2YgT3BlblZpZHUgQnJvd3NlciBsaWJyYXJ5LlxuICogVXNlIGl0IHRvIGluaXRpYWxpemUgb2JqZWN0cyBvZiB0eXBlIFtbU2Vzc2lvbl1dLCBbW1B1Ymxpc2hlcl1dIGFuZCBbW0xvY2FsUmVjb3JkZXJdXVxuICovXG5leHBvcnQgY2xhc3MgT3BlblZpZHUge1xuXG4gIHByaXZhdGUganNvblJwY0NsaWVudDogYW55O1xuXG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICBzZXNzaW9uOiBTZXNzaW9uO1xuICAvKipcbiAgICogQGhpZGRlblxuICAgKi9cbiAgcHVibGlzaGVyczogUHVibGlzaGVyW10gPSBbXTtcbiAgLyoqXG4gICAqIEBoaWRkZW5cbiAgICovXG4gIHdzVXJpOiBzdHJpbmc7XG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICBzZWNyZXQgPSAnJztcbiAgLyoqXG4gICAqIEBoaWRkZW5cbiAgICovXG4gIHJlY29yZGVyID0gZmFsc2U7XG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICBpY2VTZXJ2ZXJzOiBSVENJY2VTZXJ2ZXJbXTtcbiAgLyoqXG4gICAqIEBoaWRkZW5cbiAgICovXG4gIHJvbGU6IHN0cmluZztcbiAgLyoqXG4gICAqIEBoaWRkZW5cbiAgICovXG4gIGFkdmFuY2VkQ29uZmlndXJhdGlvbjogT3BlblZpZHVBZHZhbmNlZENvbmZpZ3VyYXRpb24gPSB7fTtcblxuICBjb25zdHJ1Y3RvcigpIHtcbiAgICBjb25zb2xlLmluZm8oXCInT3BlblZpZHUnIGluaXRpYWxpemVkXCIpO1xuXG4gICAgaWYgKHBsYXRmb3JtLm5hbWUhIS50b0xvd2VyQ2FzZSgpLmluZGV4T2YoJ21vYmlsZScpICE9PSAtMSkge1xuICAgICAgLy8gTGlzdGVuIHRvIG9yaWVudGF0aW9uY2hhbmdlIG9ubHkgb24gbW9iaWxlIGJyb3dzZXJzXG4gICAgICAoPGFueT53aW5kb3cpLm9ub3JpZW50YXRpb25jaGFuZ2UgPSAoKSA9PiB7XG4gICAgICAgIHRoaXMucHVibGlzaGVycy5mb3JFYWNoKHB1Ymxpc2hlciA9PiB7XG4gICAgICAgICAgaWYgKCEhcHVibGlzaGVyLnN0cmVhbSAmJiAhIXB1Ymxpc2hlci5zdHJlYW0uaGFzVmlkZW8gJiYgISFwdWJsaXNoZXIuc3RyZWFtLnN0cmVhbU1hbmFnZXIudmlkZW9zWzBdKSB7XG5cbiAgICAgICAgICAgIGxldCBhdHRlbXB0cyA9IDA7XG5cbiAgICAgICAgICAgIGNvbnN0IG9sZFdpZHRoID0gcHVibGlzaGVyLnN0cmVhbS52aWRlb0RpbWVuc2lvbnMud2lkdGg7XG4gICAgICAgICAgICBjb25zdCBvbGRIZWlnaHQgPSBwdWJsaXNoZXIuc3RyZWFtLnZpZGVvRGltZW5zaW9ucy5oZWlnaHQ7XG4gICAgICAgICAgICAvLyBOZXcgcmVzb2x1dGlvbiBnb3QgZnJvbSBkaWZmZXJlbnQgcGxhY2VzIGZvciBDaHJvbWUgYW5kIEZpcmVmb3guIENocm9tZSBuZWVkcyBhIHZpZGVvV2lkdGggYW5kIHZpZGVvSGVpZ2h0IG9mIGEgdmlkZW9FbGVtZW50LlxuICAgICAgICAgICAgLy8gRmlyZWZveCBuZWVkcyBnZXRTZXR0aW5ncyBmcm9tIHRoZSB2aWRlb1RyYWNrXG4gICAgICAgICAgICBsZXQgZmlyZWZveFNldHRpbmdzID0gcHVibGlzaGVyLnN0cmVhbS5nZXRNZWRpYVN0cmVhbSgpLmdldFZpZGVvVHJhY2tzKClbMF0uZ2V0U2V0dGluZ3MoKTtcbiAgICAgICAgICAgIGxldCBuZXdXaWR0aCA9IChwbGF0Zm9ybS5uYW1lISEudG9Mb3dlckNhc2UoKS5pbmRleE9mKCdmaXJlZm94JykgIT09IC0xKSA/IGZpcmVmb3hTZXR0aW5ncy53aWR0aCA6IHB1Ymxpc2hlci52aWRlb1JlZmVyZW5jZS52aWRlb1dpZHRoO1xuICAgICAgICAgICAgbGV0IG5ld0hlaWdodCA9IChwbGF0Zm9ybS5uYW1lISEudG9Mb3dlckNhc2UoKS5pbmRleE9mKCdmaXJlZm94JykgIT09IC0xKSA/IGZpcmVmb3hTZXR0aW5ncy5oZWlnaHQgOiBwdWJsaXNoZXIudmlkZW9SZWZlcmVuY2UudmlkZW9IZWlnaHQ7XG5cbiAgICAgICAgICAgIGNvbnN0IHJlcGVhdFVudGlsQ2hhbmdlID0gc2V0SW50ZXJ2YWwoKCkgPT4ge1xuICAgICAgICAgICAgICBmaXJlZm94U2V0dGluZ3MgPSBwdWJsaXNoZXIuc3RyZWFtLmdldE1lZGlhU3RyZWFtKCkuZ2V0VmlkZW9UcmFja3MoKVswXS5nZXRTZXR0aW5ncygpO1xuICAgICAgICAgICAgICBuZXdXaWR0aCA9IChwbGF0Zm9ybS5uYW1lISEudG9Mb3dlckNhc2UoKS5pbmRleE9mKCdmaXJlZm94JykgIT09IC0xKSA/IGZpcmVmb3hTZXR0aW5ncy53aWR0aCA6IHB1Ymxpc2hlci52aWRlb1JlZmVyZW5jZS52aWRlb1dpZHRoO1xuICAgICAgICAgICAgICBuZXdIZWlnaHQgPSAocGxhdGZvcm0ubmFtZSEhLnRvTG93ZXJDYXNlKCkuaW5kZXhPZignZmlyZWZveCcpICE9PSAtMSkgPyBmaXJlZm94U2V0dGluZ3MuaGVpZ2h0IDogcHVibGlzaGVyLnZpZGVvUmVmZXJlbmNlLnZpZGVvSGVpZ2h0O1xuICAgICAgICAgICAgICBzZW5kU3RyZWFtUHJvcGVydHlDaGFuZ2VkRXZlbnQob2xkV2lkdGgsIG9sZEhlaWdodCwgbmV3V2lkdGgsIG5ld0hlaWdodCk7XG4gICAgICAgICAgICB9LCAxMDApO1xuXG4gICAgICAgICAgICBjb25zdCBzZW5kU3RyZWFtUHJvcGVydHlDaGFuZ2VkRXZlbnQgPSAob2xkV2lkdGgsIG9sZEhlaWdodCwgbmV3V2lkdGgsIG5ld0hlaWdodCkgPT4ge1xuICAgICAgICAgICAgICBhdHRlbXB0cysrO1xuICAgICAgICAgICAgICBpZiAoYXR0ZW1wdHMgPiA0KSB7XG4gICAgICAgICAgICAgICAgY2xlYXJUaW1lb3V0KHJlcGVhdFVudGlsQ2hhbmdlKTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICBpZiAobmV3V2lkdGggIT09IG9sZFdpZHRoIHx8IG5ld0hlaWdodCAhPT0gb2xkSGVpZ2h0KSB7XG4gICAgICAgICAgICAgICAgcHVibGlzaGVyLnN0cmVhbS52aWRlb0RpbWVuc2lvbnMgPSB7XG4gICAgICAgICAgICAgICAgICB3aWR0aDogbmV3V2lkdGggfHwgMCxcbiAgICAgICAgICAgICAgICAgIGhlaWdodDogbmV3SGVpZ2h0IHx8IDBcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIHRoaXMuc2VuZFJlcXVlc3QoXG4gICAgICAgICAgICAgICAgICAnc3RyZWFtUHJvcGVydHlDaGFuZ2VkJyxcbiAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgc3RyZWFtSWQ6IHB1Ymxpc2hlci5zdHJlYW0uc3RyZWFtSWQsXG4gICAgICAgICAgICAgICAgICAgIHByb3BlcnR5OiAndmlkZW9EaW1lbnNpb25zJyxcbiAgICAgICAgICAgICAgICAgICAgbmV3VmFsdWU6IEpTT04uc3RyaW5naWZ5KHB1Ymxpc2hlci5zdHJlYW0udmlkZW9EaW1lbnNpb25zKSxcbiAgICAgICAgICAgICAgICAgICAgcmVhc29uOiAnZGV2aWNlUm90YXRlZCdcbiAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAoZXJyb3IsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoXCJFcnJvciBzZW5kaW5nICdzdHJlYW1Qcm9wZXJ0eUNoYW5nZWQnIGV2ZW50XCIsIGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICB0aGlzLnNlc3Npb24uZW1pdEV2ZW50KCdzdHJlYW1Qcm9wZXJ0eUNoYW5nZWQnLCBbbmV3IFN0cmVhbVByb3BlcnR5Q2hhbmdlZEV2ZW50KHRoaXMuc2Vzc2lvbiwgcHVibGlzaGVyLnN0cmVhbSwgJ3ZpZGVvRGltZW5zaW9ucycsIHB1Ymxpc2hlci5zdHJlYW0udmlkZW9EaW1lbnNpb25zLCB7IHdpZHRoOiBvbGRXaWR0aCwgaGVpZ2h0OiBvbGRIZWlnaHQgfSwgJ2RldmljZVJvdGF0ZWQnKV0pO1xuICAgICAgICAgICAgICAgICAgICAgIHB1Ymxpc2hlci5lbWl0RXZlbnQoJ3N0cmVhbVByb3BlcnR5Q2hhbmdlZCcsIFtuZXcgU3RyZWFtUHJvcGVydHlDaGFuZ2VkRXZlbnQocHVibGlzaGVyLCBwdWJsaXNoZXIuc3RyZWFtLCAndmlkZW9EaW1lbnNpb25zJywgcHVibGlzaGVyLnN0cmVhbS52aWRlb0RpbWVuc2lvbnMsIHsgd2lkdGg6IG9sZFdpZHRoLCBoZWlnaHQ6IG9sZEhlaWdodCB9LCAnZGV2aWNlUm90YXRlZCcpXSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIGNsZWFyVGltZW91dChyZXBlYXRVbnRpbENoYW5nZSk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH07XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgIH07XG4gICAgfVxuICB9XG5cblxuICAvKipcbiAgICogUmV0dXJucyBuZXcgc2Vzc2lvblxuICAgKi9cbiAgaW5pdFNlc3Npb24oKTogU2Vzc2lvbiB7XG4gICAgdGhpcy5zZXNzaW9uID0gbmV3IFNlc3Npb24odGhpcyk7XG4gICAgcmV0dXJuIHRoaXMuc2Vzc2lvbjtcbiAgfVxuXG5cbiAgaW5pdFB1Ymxpc2hlcih0YXJnZXRFbGVtZW50OiBzdHJpbmcgfCBIVE1MRWxlbWVudCk6IFB1Ymxpc2hlcjtcbiAgaW5pdFB1Ymxpc2hlcih0YXJnZXRFbGVtZW50OiBzdHJpbmcgfCBIVE1MRWxlbWVudCwgcHJvcGVydGllczogUHVibGlzaGVyUHJvcGVydGllcyk6IFB1Ymxpc2hlcjtcbiAgaW5pdFB1Ymxpc2hlcih0YXJnZXRFbGVtZW50OiBzdHJpbmcgfCBIVE1MRWxlbWVudCwgY29tcGxldGlvbkhhbmRsZXI6IChlcnJvcjogRXJyb3IgfCB1bmRlZmluZWQpID0+IHZvaWQpOiBQdWJsaXNoZXI7XG4gIGluaXRQdWJsaXNoZXIodGFyZ2V0RWxlbWVudDogc3RyaW5nIHwgSFRNTEVsZW1lbnQsIHByb3BlcnRpZXM6IFB1Ymxpc2hlclByb3BlcnRpZXMsIGNvbXBsZXRpb25IYW5kbGVyOiAoZXJyb3I6IEVycm9yIHwgdW5kZWZpbmVkKSA9PiB2b2lkKTogUHVibGlzaGVyO1xuXG4gIC8qKlxuICAgKiBSZXR1cm5zIGEgbmV3IHB1Ymxpc2hlclxuICAgKlxuICAgKiAjIyMjIEV2ZW50cyBkaXNwYXRjaGVkXG4gICAqXG4gICAqIFRoZSBbW1B1Ymxpc2hlcl1dIG9iamVjdCB3aWxsIGRpc3BhdGNoIGFuIGBhY2Nlc3NEaWFsb2dPcGVuZWRgIGV2ZW50LCBvbmx5IGlmIHRoZSBwb3AtdXAgc2hvd24gYnkgdGhlIGJyb3dzZXIgdG8gcmVxdWVzdCBwZXJtaXNzaW9ucyBmb3IgdGhlIGNhbWVyYSBpcyBvcGVuZWQuIFlvdSBjYW4gdXNlIHRoaXMgZXZlbnQgdG8gYWxlcnQgdGhlIHVzZXIgYWJvdXQgZ3JhbnRpbmcgcGVybWlzc2lvbnNcbiAgICogZm9yIHlvdXIgd2Vic2l0ZS4gQW4gYGFjY2Vzc0RpYWxvZ0Nsb3NlZGAgZXZlbnQgd2lsbCBhbHNvIGJlIGRpc3BhdGNoZWQgYWZ0ZXIgdXNlciBjbGlja3Mgb24gXCJBbGxvd1wiIG9yIFwiQmxvY2tcIiBpbiB0aGUgcG9wLXVwLlxuICAgKlxuICAgKiBUaGUgW1tQdWJsaXNoZXJdXSBvYmplY3Qgd2lsbCBkaXNwYXRjaCBhbiBgYWNjZXNzQWxsb3dlZGAgb3IgYGFjY2Vzc0RlbmllZGAgZXZlbnQgb25jZSBpdCBoYXMgYmVlbiBncmFudGVkIGFjY2VzcyB0byB0aGUgcmVxdWVzdGVkIGlucHV0IGRldmljZXMgb3Igbm90LlxuICAgKlxuICAgKiBUaGUgW1tQdWJsaXNoZXJdXSBvYmplY3Qgd2lsbCBkaXNwYXRjaCBhIGB2aWRlb0VsZW1lbnRDcmVhdGVkYCBldmVudCBvbmNlIGEgSFRNTCB2aWRlbyBlbGVtZW50IGhhcyBiZWVuIGFkZGVkIHRvIERPTSAob25seSBpZiB5b3VcbiAgICogW2xldCBPcGVuVmlkdSB0YWtlIGNhcmUgb2YgdGhlIHZpZGVvIHBsYXllcnNdKC9kb2NzL2hvdy1kby1pL21hbmFnZS12aWRlb3MvI2xldC1vcGVudmlkdS10YWtlLWNhcmUtb2YtdGhlLXZpZGVvLXBsYXllcnMpKS4gU2VlIFtbVmlkZW9FbGVtZW50RXZlbnRdXSB0byBsZWFybiBtb3JlLlxuICAgKlxuICAgKiBUaGUgW1tQdWJsaXNoZXJdXSBvYmplY3Qgd2lsbCBkaXNwYXRjaCBhIGBzdHJlYW1QbGF5aW5nYCBldmVudCBvbmNlIHRoZSBsb2NhbCBzdHJlYW1zIHN0YXJ0cyBwbGF5aW5nLiBTZWUgW1tTdHJlYW1NYW5hZ2VyRXZlbnRdXSB0byBsZWFybiBtb3JlLlxuICAgKlxuICAgKiBAcGFyYW0gdGFyZ2V0RWxlbWVudCAgSFRNTCBET00gZWxlbWVudCAob3IgaXRzIGBpZGAgYXR0cmlidXRlKSBpbiB3aGljaCB0aGUgdmlkZW8gZWxlbWVudCBvZiB0aGUgUHVibGlzaGVyIHdpbGwgYmUgaW5zZXJ0ZWQgKHNlZSBbW1B1Ymxpc2hlclByb3BlcnRpZXMuaW5zZXJ0TW9kZV1dKS4gSWYgKm51bGwqIG9yICp1bmRlZmluZWQqIG5vIGRlZmF1bHQgdmlkZW8gd2lsbCBiZSBjcmVhdGVkIGZvciB0aGlzIFB1Ymxpc2hlci5cbiAgICogWW91IGNhbiBhbHdheXMgY2FsbCBtZXRob2QgW1tQdWJsaXNoZXIuYWRkVmlkZW9FbGVtZW50XV0gb3IgW1tQdWJsaXNoZXIuY3JlYXRlVmlkZW9FbGVtZW50XV0gdG8gbWFuYWdlIHRoZSB2aWRlbyBlbGVtZW50cyBvbiB5b3VyIG93biAoc2VlIFtNYW5hZ2UgdmlkZW8gcGxheWVyc10oL2RvY3MvaG93LWRvLWkvbWFuYWdlLXZpZGVvcykgc2VjdGlvbilcbiAgICogQHBhcmFtIGNvbXBsZXRpb25IYW5kbGVyIGBlcnJvcmAgcGFyYW1ldGVyIGlzIG51bGwgaWYgYGluaXRQdWJsaXNoZXJgIHN1Y2NlZWRzLCBhbmQgaXMgZGVmaW5lZCBpZiBpdCBmYWlscy5cbiAgICogICAgICAgICAgICAgICAgICAgICAgICAgIGBjb21wbGV0aW9uSGFuZGxlcmAgZnVuY3Rpb24gaXMgY2FsbGVkIGJlZm9yZSB0aGUgUHVibGlzaGVyIGRpc3BhdGNoZXMgYW4gYGFjY2Vzc0FsbG93ZWRgIG9yIGFuIGBhY2Nlc3NEZW5pZWRgIGV2ZW50XG4gICAqL1xuICBpbml0UHVibGlzaGVyKHRhcmdldEVsZW1lbnQ6IHN0cmluZyB8IEhUTUxFbGVtZW50LCBwYXJhbTI/LCBwYXJhbTM/KTogUHVibGlzaGVyIHtcblxuICAgIGxldCBwcm9wZXJ0aWVzOiBQdWJsaXNoZXJQcm9wZXJ0aWVzO1xuXG4gICAgaWYgKCEhcGFyYW0yICYmICh0eXBlb2YgcGFyYW0yICE9PSAnZnVuY3Rpb24nKSkge1xuXG4gICAgICAvLyBNYXRjaGVzICdpbml0UHVibGlzaGVyKHRhcmdldEVsZW1lbnQsIHByb3BlcnRpZXMpJyBvciAnaW5pdFB1Ymxpc2hlcih0YXJnZXRFbGVtZW50LCBwcm9wZXJ0aWVzLCBjb21wbGV0aW9uSGFuZGxlciknXG5cbiAgICAgIHByb3BlcnRpZXMgPSAoPFB1Ymxpc2hlclByb3BlcnRpZXM+cGFyYW0yKTtcblxuICAgICAgcHJvcGVydGllcyA9IHtcbiAgICAgICAgYXVkaW9Tb3VyY2U6ICh0eXBlb2YgcHJvcGVydGllcy5hdWRpb1NvdXJjZSAhPT0gJ3VuZGVmaW5lZCcpID8gcHJvcGVydGllcy5hdWRpb1NvdXJjZSA6IHVuZGVmaW5lZCxcbiAgICAgICAgZnJhbWVSYXRlOiB0aGlzLmlzTWVkaWFTdHJlYW1UcmFjayhwcm9wZXJ0aWVzLnZpZGVvU291cmNlKSA/IHVuZGVmaW5lZCA6ICgodHlwZW9mIHByb3BlcnRpZXMuZnJhbWVSYXRlICE9PSAndW5kZWZpbmVkJykgPyBwcm9wZXJ0aWVzLmZyYW1lUmF0ZSA6IHVuZGVmaW5lZCksXG4gICAgICAgIGluc2VydE1vZGU6ICh0eXBlb2YgcHJvcGVydGllcy5pbnNlcnRNb2RlICE9PSAndW5kZWZpbmVkJykgPyAoKHR5cGVvZiBwcm9wZXJ0aWVzLmluc2VydE1vZGUgPT09ICdzdHJpbmcnKSA/IFZpZGVvSW5zZXJ0TW9kZVtwcm9wZXJ0aWVzLmluc2VydE1vZGVdIDogcHJvcGVydGllcy5pbnNlcnRNb2RlKSA6IFZpZGVvSW5zZXJ0TW9kZS5BUFBFTkQsXG4gICAgICAgIG1pcnJvcjogKHR5cGVvZiBwcm9wZXJ0aWVzLm1pcnJvciAhPT0gJ3VuZGVmaW5lZCcpID8gcHJvcGVydGllcy5taXJyb3IgOiB0cnVlLFxuICAgICAgICBwdWJsaXNoQXVkaW86ICh0eXBlb2YgcHJvcGVydGllcy5wdWJsaXNoQXVkaW8gIT09ICd1bmRlZmluZWQnKSA/IHByb3BlcnRpZXMucHVibGlzaEF1ZGlvIDogdHJ1ZSxcbiAgICAgICAgcHVibGlzaFZpZGVvOiAodHlwZW9mIHByb3BlcnRpZXMucHVibGlzaFZpZGVvICE9PSAndW5kZWZpbmVkJykgPyBwcm9wZXJ0aWVzLnB1Ymxpc2hWaWRlbyA6IHRydWUsXG4gICAgICAgIHJlc29sdXRpb246IHRoaXMuaXNNZWRpYVN0cmVhbVRyYWNrKHByb3BlcnRpZXMudmlkZW9Tb3VyY2UpID8gdW5kZWZpbmVkIDogKCh0eXBlb2YgcHJvcGVydGllcy5yZXNvbHV0aW9uICE9PSAndW5kZWZpbmVkJykgPyBwcm9wZXJ0aWVzLnJlc29sdXRpb24gOiAnNjQweDQ4MCcpLFxuICAgICAgICB2aWRlb1NvdXJjZTogKHR5cGVvZiBwcm9wZXJ0aWVzLnZpZGVvU291cmNlICE9PSAndW5kZWZpbmVkJykgPyBwcm9wZXJ0aWVzLnZpZGVvU291cmNlIDogdW5kZWZpbmVkXG4gICAgICB9O1xuICAgIH0gZWxzZSB7XG5cbiAgICAgIC8vIE1hdGNoZXMgJ2luaXRQdWJsaXNoZXIodGFyZ2V0RWxlbWVudCknIG9yICdpbml0UHVibGlzaGVyKHRhcmdldEVsZW1lbnQsIGNvbXBsZXRpb25IYW5kbGVyKSdcblxuICAgICAgcHJvcGVydGllcyA9IHtcbiAgICAgICAgaW5zZXJ0TW9kZTogVmlkZW9JbnNlcnRNb2RlLkFQUEVORCxcbiAgICAgICAgbWlycm9yOiB0cnVlLFxuICAgICAgICBwdWJsaXNoQXVkaW86IHRydWUsXG4gICAgICAgIHB1Ymxpc2hWaWRlbzogdHJ1ZSxcbiAgICAgICAgcmVzb2x1dGlvbjogJzY0MHg0ODAnXG4gICAgICB9O1xuICAgIH1cblxuICAgIGNvbnN0IHB1Ymxpc2hlcjogUHVibGlzaGVyID0gbmV3IFB1Ymxpc2hlcih0YXJnZXRFbGVtZW50LCBwcm9wZXJ0aWVzLCB0aGlzKTtcblxuICAgIGxldCBjb21wbGV0aW9uSGFuZGxlcjogKGVycm9yOiBFcnJvciB8IHVuZGVmaW5lZCkgPT4gdm9pZDtcbiAgICBpZiAoISFwYXJhbTIgJiYgKHR5cGVvZiBwYXJhbTIgPT09ICdmdW5jdGlvbicpKSB7XG4gICAgICBjb21wbGV0aW9uSGFuZGxlciA9IHBhcmFtMjtcbiAgICB9IGVsc2UgaWYgKCEhcGFyYW0zKSB7XG4gICAgICBjb21wbGV0aW9uSGFuZGxlciA9IHBhcmFtMztcbiAgICB9XG5cbiAgICBwdWJsaXNoZXIuaW5pdGlhbGl6ZSgpXG4gICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgIGlmIChjb21wbGV0aW9uSGFuZGxlciAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgY29tcGxldGlvbkhhbmRsZXIodW5kZWZpbmVkKTtcbiAgICAgICAgfVxuICAgICAgICBwdWJsaXNoZXIuZW1pdEV2ZW50KCdhY2Nlc3NBbGxvd2VkJywgW10pO1xuICAgICAgfSkuY2F0Y2goKGVycm9yKSA9PiB7XG4gICAgICAgIGlmIChjb21wbGV0aW9uSGFuZGxlciAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgY29tcGxldGlvbkhhbmRsZXIoZXJyb3IpO1xuICAgICAgICB9XG4gICAgICAgIHB1Ymxpc2hlci5lbWl0RXZlbnQoJ2FjY2Vzc0RlbmllZCcsIFtdKTtcbiAgICAgIH0pO1xuXG4gICAgdGhpcy5wdWJsaXNoZXJzLnB1c2gocHVibGlzaGVyKTtcbiAgICByZXR1cm4gcHVibGlzaGVyO1xuICB9XG5cblxuICAvKipcbiAgICogUHJvbWlzaWZpZWQgdmVyc2lvbiBvZiBbW09wZW5WaWR1LmluaXRQdWJsaXNoZXJdXVxuICAgKlxuICAgKiA+IFdBUk5JTkc6IGV2ZW50cyBgYWNjZXNzRGlhbG9nT3BlbmVkYCBhbmQgYGFjY2Vzc0RpYWxvZ0Nsb3NlZGAgd2lsbCBub3QgYmUgZGlzcGF0Y2hlZCBpZiB1c2luZyB0aGlzIG1ldGhvZCBpbnN0ZWFkIG9mIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dXG4gICAqL1xuICBpbml0UHVibGlzaGVyQXN5bmModGFyZ2V0RWxlbWVudDogc3RyaW5nIHwgSFRNTEVsZW1lbnQpOiBQcm9taXNlPFB1Ymxpc2hlcj47XG4gIGluaXRQdWJsaXNoZXJBc3luYyh0YXJnZXRFbGVtZW50OiBzdHJpbmcgfCBIVE1MRWxlbWVudCwgcHJvcGVydGllczogUHVibGlzaGVyUHJvcGVydGllcyk6IFByb21pc2U8UHVibGlzaGVyPjtcblxuICBpbml0UHVibGlzaGVyQXN5bmModGFyZ2V0RWxlbWVudDogc3RyaW5nIHwgSFRNTEVsZW1lbnQsIHByb3BlcnRpZXM/OiBQdWJsaXNoZXJQcm9wZXJ0aWVzKTogUHJvbWlzZTxQdWJsaXNoZXI+IHtcbiAgICByZXR1cm4gbmV3IFByb21pc2U8UHVibGlzaGVyPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG5cbiAgICAgIGxldCBwdWJsaXNoZXI6IFB1Ymxpc2hlcjtcblxuICAgICAgY29uc3QgY2FsbGJhY2sgPSAoZXJyb3I6IEVycm9yKSA9PiB7XG4gICAgICAgIGlmICghIWVycm9yKSB7XG4gICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICByZXNvbHZlKHB1Ymxpc2hlcik7XG4gICAgICAgIH1cbiAgICAgIH07XG5cbiAgICAgIGlmICghIXByb3BlcnRpZXMpIHtcbiAgICAgICAgcHVibGlzaGVyID0gdGhpcy5pbml0UHVibGlzaGVyKHRhcmdldEVsZW1lbnQsIHByb3BlcnRpZXMsIGNhbGxiYWNrKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHB1Ymxpc2hlciA9IHRoaXMuaW5pdFB1Ymxpc2hlcih0YXJnZXRFbGVtZW50LCBjYWxsYmFjayk7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIGEgbmV3IGxvY2FsIHJlY29yZGVyIGZvciByZWNvcmRpbmcgc3RyZWFtcyBzdHJhaWdodCBhd2F5IGZyb20gdGhlIGJyb3dzZXJcbiAgICogQHBhcmFtIHN0cmVhbSAgU3RyZWFtIHRvIHJlY29yZFxuICAgKi9cbiAgaW5pdExvY2FsUmVjb3JkZXIoc3RyZWFtOiBTdHJlYW0pOiBMb2NhbFJlY29yZGVyIHtcbiAgICByZXR1cm4gbmV3IExvY2FsUmVjb3JkZXIoc3RyZWFtKTtcbiAgfVxuXG5cbiAgLyoqXG4gICAqIENoZWNrcyBpZiB0aGUgYnJvd3NlciBzdXBwb3J0cyBPcGVuVmlkdVxuICAgKiBAcmV0dXJucyAxIGlmIHRoZSBicm93c2VyIHN1cHBvcnRzIE9wZW5WaWR1LCAwIG90aGVyd2lzZVxuICAgKi9cbiAgY2hlY2tTeXN0ZW1SZXF1aXJlbWVudHMoKTogbnVtYmVyIHtcbiAgICBjb25zdCBicm93c2VyID0gcGxhdGZvcm0ubmFtZTtcbiAgICBjb25zdCB2ZXJzaW9uID0gcGxhdGZvcm0udmVyc2lvbjtcblxuICAgIGlmICgoYnJvd3NlciAhPT0gJ0Nocm9tZScpICYmIChicm93c2VyICE9PSAnQ2hyb21lIE1vYmlsZScpICYmXG4gICAgICAoYnJvd3NlciAhPT0gJ0ZpcmVmb3gnKSAmJiAoYnJvd3NlciAhPT0gJ0ZpcmVmb3ggTW9iaWxlJykgJiYgKGJyb3dzZXIgIT09ICdGaXJlZm94IGZvciBpT1MnKSAmJlxuICAgICAgKGJyb3dzZXIgIT09ICdPcGVyYScpICYmIChicm93c2VyICE9PSAnT3BlcmEgTW9iaWxlJykgJiZcbiAgICAgIChicm93c2VyICE9PSAnU2FmYXJpJykpIHtcbiAgICAgIHJldHVybiAwO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gMTtcbiAgICB9XG4gIH1cblxuXG4gIC8qKlxuICAgKiBDb2xsZWN0cyBpbmZvcm1hdGlvbiBhYm91dCB0aGUgbWVkaWEgaW5wdXQgZGV2aWNlcyBhdmFpbGFibGUgb24gdGhlIHN5c3RlbS4gWW91IGNhbiBwYXNzIHByb3BlcnR5IGBkZXZpY2VJZGAgb2YgYSBbW0RldmljZV1dIG9iamVjdCBhcyB2YWx1ZSBvZiBgYXVkaW9Tb3VyY2VgIG9yIGB2aWRlb1NvdXJjZWAgcHJvcGVydGllcyBpbiBbW2luaXRQdWJsaXNoZXJdXSBtZXRob2RcbiAgICovXG4gIGdldERldmljZXMoKTogUHJvbWlzZTxEZXZpY2VbXT4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZTxEZXZpY2VbXT4oKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgbmF2aWdhdG9yLm1lZGlhRGV2aWNlcy5lbnVtZXJhdGVEZXZpY2VzKCkudGhlbigoZGV2aWNlSW5mb3MpID0+IHtcbiAgICAgICAgY29uc3QgZGV2aWNlczogRGV2aWNlW10gPSBbXTtcbiAgICAgICAgZGV2aWNlSW5mb3MuZm9yRWFjaChkZXZpY2VJbmZvID0+IHtcbiAgICAgICAgICBpZiAoZGV2aWNlSW5mby5raW5kID09PSAnYXVkaW9pbnB1dCcgfHwgZGV2aWNlSW5mby5raW5kID09PSAndmlkZW9pbnB1dCcpIHtcbiAgICAgICAgICAgIGRldmljZXMucHVzaCh7XG4gICAgICAgICAgICAgIGtpbmQ6IGRldmljZUluZm8ua2luZCxcbiAgICAgICAgICAgICAgZGV2aWNlSWQ6IGRldmljZUluZm8uZGV2aWNlSWQsXG4gICAgICAgICAgICAgIGxhYmVsOiBkZXZpY2VJbmZvLmxhYmVsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICByZXNvbHZlKGRldmljZXMpO1xuICAgICAgfSkuY2F0Y2goKGVycm9yKSA9PiB7XG4gICAgICAgIGNvbnNvbGUuZXJyb3IoJ0Vycm9yIGdldHRpbmcgZGV2aWNlcycsIGVycm9yKTtcbiAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9XG5cblxuICAvKipcbiAgICogR2V0IGEgTWVkaWFTdHJlYW0gb2JqZWN0IHRoYXQgeW91IGNhbiBjdXN0b21pemUgYmVmb3JlIGNhbGxpbmcgW1tpbml0UHVibGlzaGVyXV0gKHBhc3MgX01lZGlhU3RyZWFtVHJhY2tfIHByb3BlcnR5IG9mIHRoZSBfTWVkaWFTdHJlYW1fIHZhbHVlIHJlc29sdmVkIGJ5IHRoZSBQcm9taXNlIGFzIGBhdWRpb1NvdXJjZWAgb3IgYHZpZGVvU291cmNlYCBwcm9wZXJ0aWVzIGluIFtbaW5pdFB1Ymxpc2hlcl1dKVxuICAgKlxuICAgKiBQYXJhbWV0ZXIgYG9wdGlvbnNgIGlzIHRoZSBzYW1lIGFzIGluIFtbaW5pdFB1Ymxpc2hlcl1dIHNlY29uZCBwYXJhbWV0ZXIgKG9mIHR5cGUgW1tQdWJsaXNoZXJQcm9wZXJ0aWVzXV0pLCBidXQgb25seSB0aGUgZm9sbG93aW5nIHByb3BlcnRpZXMgd2lsbCBiZSBhcHBsaWVkOiBgYXVkaW9Tb3VyY2VgLCBgdmlkZW9Tb3VyY2VgLCBgZnJhbWVSYXRlYCwgYHJlc29sdXRpb25gXG4gICAqXG4gICAqIFRvIGN1c3RvbWl6ZSB0aGUgUHVibGlzaGVyJ3MgdmlkZW8sIHRoZSBBUEkgZm9yIEhUTUxDYW52YXNFbGVtZW50IGlzIHZlcnkgdXNlZnVsLiBGb3IgZXhhbXBsZSwgdG8gZ2V0IGEgYmxhY2stYW5kLXdoaXRlIHZpZGVvIGF0IDEwIGZwcyBhbmQgSEQgcmVzb2x1dGlvbiB3aXRoIG5vIHNvdW5kOlxuICAgKiBgYGBcbiAgICogdmFyIE9WID0gbmV3IE9wZW5WaWR1KCk7XG4gICAqIHZhciBGUkFNRV9SQVRFID0gMTA7XG4gICAqXG4gICAqIE9WLmdldFVzZXJNZWRpYSh7XG4gICAqICAgIGF1ZGlvU291cmNlOiBmYWxzZTtcbiAgICogICAgdmlkZW9Tb3VyY2U6IHVuZGVmaW5lZCxcbiAgICogICAgcmVzb2x1dGlvbjogJzEyODB4NzIwJyxcbiAgICogICAgZnJhbWVSYXRlOiBGUkFNRV9SQVRFXG4gICAqIH0pXG4gICAqIC50aGVuKG1lZGlhU3RyZWFtID0+IHtcbiAgICpcbiAgICogICAgdmFyIHZpZGVvVHJhY2sgPSBtZWRpYVN0cmVhbS5nZXRWaWRlb1RyYWNrcygpWzBdO1xuICAgKiAgICB2YXIgdmlkZW8gPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCd2aWRlbycpO1xuICAgKiAgICB2aWRlby5zcmNPYmplY3QgPSBuZXcgTWVkaWFTdHJlYW0oW3ZpZGVvVHJhY2tdKTtcbiAgICpcbiAgICogICAgdmFyIGNhbnZhcyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2NhbnZhcycpO1xuICAgKiAgICB2YXIgY3R4ID0gY2FudmFzLmdldENvbnRleHQoJzJkJyk7XG4gICAqICAgIGN0eC5maWx0ZXIgPSAnZ3JheXNjYWxlKDEwMCUpJztcbiAgICpcbiAgICogICAgdmlkZW8uYWRkRXZlbnRMaXN0ZW5lcigncGxheScsICgpID0+IHtcbiAgICogICAgICB2YXIgbG9vcCA9ICgpID0+IHtcbiAgICogICAgICAgIGlmICghdmlkZW8ucGF1c2VkICYmICF2aWRlby5lbmRlZCkge1xuICAgKiAgICAgICAgICBjdHguZHJhd0ltYWdlKHZpZGVvLCAwLCAwLCAzMDAsIDE3MCk7XG4gICAqICAgICAgICAgIHNldFRpbWVvdXQobG9vcCwgMTAwMC8gRlJBTUVfUkFURSk7IC8vIERyYXdpbmcgYXQgMTAgZnBzXG4gICAqICAgICAgICB9XG4gICAqICAgICAgfTtcbiAgICogICAgICBsb29wKCk7XG4gICAqICAgIH0pO1xuICAgKiAgICB2aWRlby5wbGF5KCk7XG4gICAqXG4gICAqICAgIHZhciBncmF5VmlkZW9UcmFjayA9IGNhbnZhcy5jYXB0dXJlU3RyZWFtKEZSQU1FX1JBVEUpLmdldFZpZGVvVHJhY2tzKClbMF07XG4gICAqICAgIHZhciBwdWJsaXNoZXIgPSB0aGlzLk9WLmluaXRQdWJsaXNoZXIoXG4gICAqICAgICAgbXlIdG1sVGFyZ2V0LFxuICAgKiAgICAgIHtcbiAgICogICAgICAgIGF1ZGlvU291cmNlOiBmYWxzZSxcbiAgICogICAgICAgIHZpZGVvU291cmNlOiBncmF5VmlkZW9UcmFja1xuICAgKiAgICAgIH0pO1xuICAgKiB9KTtcbiAgICogYGBgXG4gICAqL1xuICBnZXRVc2VyTWVkaWEob3B0aW9uczogUHVibGlzaGVyUHJvcGVydGllcyk6IFByb21pc2U8TWVkaWFTdHJlYW0+IHtcbiAgICByZXR1cm4gbmV3IFByb21pc2U8TWVkaWFTdHJlYW0+KChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIHRoaXMuZ2VuZXJhdGVNZWRpYUNvbnN0cmFpbnRzKG9wdGlvbnMpXG4gICAgICAgIC50aGVuKGNvbnN0cmFpbnRzID0+IHtcbiAgICAgICAgICBuYXZpZ2F0b3IubWVkaWFEZXZpY2VzLmdldFVzZXJNZWRpYShjb25zdHJhaW50cylcbiAgICAgICAgICAgIC50aGVuKG1lZGlhU3RyZWFtID0+IHtcbiAgICAgICAgICAgICAgcmVzb2x2ZShtZWRpYVN0cmVhbSk7XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICAgICAgbGV0IGVycm9yTmFtZTogT3BlblZpZHVFcnJvck5hbWU7XG4gICAgICAgICAgICAgIGNvbnN0IGVycm9yTWVzc2FnZSA9IGVycm9yLnRvU3RyaW5nKCk7XG4gICAgICAgICAgICAgIGlmICghKG9wdGlvbnMudmlkZW9Tb3VyY2UgPT09ICdzY3JlZW4nKSkge1xuICAgICAgICAgICAgICAgIGVycm9yTmFtZSA9IE9wZW5WaWR1RXJyb3JOYW1lLkRFVklDRV9BQ0NFU1NfREVOSUVEO1xuICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGVycm9yTmFtZSA9IE9wZW5WaWR1RXJyb3JOYW1lLlNDUkVFTl9DQVBUVVJFX0RFTklFRDtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICByZWplY3QobmV3IE9wZW5WaWR1RXJyb3IoZXJyb3JOYW1lLCBlcnJvck1lc3NhZ2UpKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KVxuICAgICAgICAuY2F0Y2goKGVycm9yOiBPcGVuVmlkdUVycm9yKSA9PiB7XG4gICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgfSk7XG4gICAgfSk7XG4gIH1cblxuXG4gIC8qIHRzbGludDpkaXNhYmxlOm5vLWVtcHR5ICovXG4gIC8qKlxuICAgKiBEaXNhYmxlIGFsbCBsb2dnaW5nIGV4Y2VwdCBlcnJvciBsZXZlbFxuICAgKi9cbiAgZW5hYmxlUHJvZE1vZGUoKTogdm9pZCB7XG4gICAgY29uc29sZS5sb2cgPSAoKSA9PiB7IH07XG4gICAgY29uc29sZS5kZWJ1ZyA9ICgpID0+IHsgfTtcbiAgICBjb25zb2xlLmluZm8gPSAoKSA9PiB7IH07XG4gICAgY29uc29sZS53YXJuID0gKCkgPT4geyB9O1xuICB9XG4gIC8qIHRzbGludDplbmFibGU6bm8tZW1wdHkgKi9cblxuXG4gIC8qKlxuICAgKiBTZXQgT3BlblZpZHUgYWR2YW5jZWQgY29uZmlndXJhdGlvbiBvcHRpb25zLiBDdXJyZW50bHkgYGNvbmZpZ3VyYXRpb25gIGlzIGFuIG9iamVjdCB3aXRoIHRoZSBmb2xsb3dpbmcgb3B0aW9uYWwgcHJvcGVydGllcyAoc2VlIFtbT3BlblZpZHVBZHZhbmNlZENvbmZpZ3VyYXRpb25dXSBmb3IgbW9yZSBkZXRhaWxzKTpcbiAgICogLSBgaWNlU2VydmVyc2A6IHNldCBjdXN0b20gU1RVTi9UVVJOIHNlcnZlcnMgdG8gYmUgdXNlZCBieSBPcGVuVmlkdSBCcm93c2VyXG4gICAqIC0gYHNjcmVlblNoYXJlQ2hyb21lRXh0ZW5zaW9uYDogdXJsIHRvIGEgY3VzdG9tIHNjcmVlbiBzaGFyZSBleHRlbnNpb24gZm9yIENocm9tZSB0byBiZSB1c2VkIGluc3RlYWQgb2YgdGhlIGRlZmF1bHQgb25lLCBiYXNlZCBvbiBvdXJzIFtodHRwczovL2dpdGh1Yi5jb20vT3BlblZpZHUvb3BlbnZpZHUtc2NyZWVuLXNoYXJpbmctY2hyb21lLWV4dGVuc2lvbl0oaHR0cHM6Ly9naXRodWIuY29tL09wZW5WaWR1L29wZW52aWR1LXNjcmVlbi1zaGFyaW5nLWNocm9tZS1leHRlbnNpb24pXG4gICAqIC0gYHB1Ymxpc2hlclNwZWFraW5nRXZlbnRzT3B0aW9uc2A6IGN1c3RvbSBjb25maWd1cmF0aW9uIGZvciB0aGUgW1tQdWJsaXNoZXJTcGVha2luZ0V2ZW50XV0gZmVhdHVyZVxuICAgKi9cbiAgc2V0QWR2YW5jZWRDb25maWd1cmF0aW9uKGNvbmZpZ3VyYXRpb246IE9wZW5WaWR1QWR2YW5jZWRDb25maWd1cmF0aW9uKTogdm9pZCB7XG4gICAgdGhpcy5hZHZhbmNlZENvbmZpZ3VyYXRpb24gPSBjb25maWd1cmF0aW9uO1xuICB9XG5cblxuICAvKiBIaWRkZW4gbWV0aG9kcyAqL1xuXG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICBnZW5lcmF0ZU1lZGlhQ29uc3RyYWludHMocHVibGlzaGVyUHJvcGVydGllczogUHVibGlzaGVyUHJvcGVydGllcyk6IFByb21pc2U8TWVkaWFTdHJlYW1Db25zdHJhaW50cz4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZTxNZWRpYVN0cmVhbUNvbnN0cmFpbnRzPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICBsZXQgYXVkaW8sIHZpZGVvO1xuXG4gICAgICBpZiAocHVibGlzaGVyUHJvcGVydGllcy5hdWRpb1NvdXJjZSA9PT0gbnVsbCB8fCBwdWJsaXNoZXJQcm9wZXJ0aWVzLmF1ZGlvU291cmNlID09PSBmYWxzZSkge1xuICAgICAgICBhdWRpbyA9IGZhbHNlO1xuICAgICAgfSBlbHNlIGlmIChwdWJsaXNoZXJQcm9wZXJ0aWVzLmF1ZGlvU291cmNlID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgYXVkaW8gPSB0cnVlO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgYXVkaW8gPSBwdWJsaXNoZXJQcm9wZXJ0aWVzLmF1ZGlvU291cmNlO1xuICAgICAgfVxuXG4gICAgICBpZiAocHVibGlzaGVyUHJvcGVydGllcy52aWRlb1NvdXJjZSA9PT0gbnVsbCB8fCBwdWJsaXNoZXJQcm9wZXJ0aWVzLnZpZGVvU291cmNlID09PSBmYWxzZSkge1xuICAgICAgICB2aWRlbyA9IGZhbHNlO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdmlkZW8gPSB7XG4gICAgICAgICAgaGVpZ2h0OiB7XG4gICAgICAgICAgICBpZGVhbDogNDgwXG4gICAgICAgICAgfSxcbiAgICAgICAgICB3aWR0aDoge1xuICAgICAgICAgICAgaWRlYWw6IDY0MFxuICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgbWVkaWFDb25zdHJhaW50czogTWVkaWFTdHJlYW1Db25zdHJhaW50cyA9IHtcbiAgICAgICAgYXVkaW8sXG4gICAgICAgIHZpZGVvXG4gICAgICB9O1xuXG4gICAgICBpZiAodHlwZW9mIG1lZGlhQ29uc3RyYWludHMuYXVkaW8gPT09ICdzdHJpbmcnKSB7XG4gICAgICAgIG1lZGlhQ29uc3RyYWludHMuYXVkaW8gPSB7IGRldmljZUlkOiB7IGV4YWN0OiBtZWRpYUNvbnN0cmFpbnRzLmF1ZGlvIH0gfTtcbiAgICAgIH1cblxuICAgICAgaWYgKG1lZGlhQ29uc3RyYWludHMudmlkZW8pIHtcblxuICAgICAgICBpZiAoISFwdWJsaXNoZXJQcm9wZXJ0aWVzLnJlc29sdXRpb24pIHtcbiAgICAgICAgICBjb25zdCB3aWR0aEFuZEhlaWdodCA9IHB1Ymxpc2hlclByb3BlcnRpZXMucmVzb2x1dGlvbi50b0xvd2VyQ2FzZSgpLnNwbGl0KCd4Jyk7XG4gICAgICAgICAgY29uc3Qgd2lkdGggPSBOdW1iZXIod2lkdGhBbmRIZWlnaHRbMF0pO1xuICAgICAgICAgIGNvbnN0IGhlaWdodCA9IE51bWJlcih3aWR0aEFuZEhlaWdodFsxXSk7XG4gICAgICAgICAgKG1lZGlhQ29uc3RyYWludHMudmlkZW8gYXMgYW55KS53aWR0aC5pZGVhbCA9IHdpZHRoO1xuICAgICAgICAgIChtZWRpYUNvbnN0cmFpbnRzLnZpZGVvIGFzIGFueSkuaGVpZ2h0LmlkZWFsID0gaGVpZ2h0O1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCEhcHVibGlzaGVyUHJvcGVydGllcy5mcmFtZVJhdGUpIHtcbiAgICAgICAgICAobWVkaWFDb25zdHJhaW50cy52aWRlbyBhcyBhbnkpLmZyYW1lUmF0ZSA9IHsgaWRlYWw6IHB1Ymxpc2hlclByb3BlcnRpZXMuZnJhbWVSYXRlIH07XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoISFwdWJsaXNoZXJQcm9wZXJ0aWVzLnZpZGVvU291cmNlICYmIHR5cGVvZiBwdWJsaXNoZXJQcm9wZXJ0aWVzLnZpZGVvU291cmNlID09PSAnc3RyaW5nJykge1xuXG4gICAgICAgICAgaWYgKHB1Ymxpc2hlclByb3BlcnRpZXMudmlkZW9Tb3VyY2UgPT09ICdzY3JlZW4nKSB7XG5cbiAgICAgICAgICAgIGlmIChwbGF0Zm9ybS5uYW1lICE9PSAnQ2hyb21lJyAmJiBwbGF0Zm9ybS5uYW1lIS5pbmRleE9mKCdGaXJlZm94JykgPT09IC0xKSB7XG4gICAgICAgICAgICAgIGNvbnN0IGVycm9yID0gbmV3IE9wZW5WaWR1RXJyb3IoT3BlblZpZHVFcnJvck5hbWUuU0NSRUVOX1NIQVJJTkdfTk9UX1NVUFBPUlRFRCwgJ1lvdSBjYW4gb25seSBzY3JlZW4gc2hhcmUgaW4gZGVza3RvcCBDaHJvbWUgYW5kIEZpcmVmb3guIERldGVjdGVkIGJyb3dzZXI6ICcgKyBwbGF0Zm9ybS5uYW1lKTtcbiAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihlcnJvcik7XG4gICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICB9IGVsc2Uge1xuXG4gICAgICAgICAgICAgIGlmICghIXRoaXMuYWR2YW5jZWRDb25maWd1cmF0aW9uLnNjcmVlblNoYXJlQ2hyb21lRXh0ZW5zaW9uICYmICEocGxhdGZvcm0ubmFtZSEuaW5kZXhPZignRmlyZWZveCcpICE9PSAtMSkpIHtcblxuICAgICAgICAgICAgICAgIC8vIEN1c3RvbSBzY3JlZW4gc2hhcmluZyBleHRlbnNpb24gZm9yIENocm9tZVxuXG4gICAgICAgICAgICAgICAgc2NyZWVuU2hhcmluZy5nZXRTY3JlZW5Db25zdHJhaW50cygoZXJyb3IsIHNjcmVlbkNvbnN0cmFpbnRzKSA9PiB7XG4gICAgICAgICAgICAgICAgICBpZiAoISFlcnJvciB8fCAhIXNjcmVlbkNvbnN0cmFpbnRzLm1hbmRhdG9yeSAmJiBzY3JlZW5Db25zdHJhaW50cy5tYW5kYXRvcnkuY2hyb21lTWVkaWFTb3VyY2UgPT09ICdzY3JlZW4nKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnJvciA9PT0gJ3Blcm1pc3Npb24tZGVuaWVkJyB8fCBlcnJvciA9PT0gJ1Blcm1pc3Npb25EZW5pZWRFcnJvcicpIHtcbiAgICAgICAgICAgICAgICAgICAgICBjb25zdCBlcnJvciA9IG5ldyBPcGVuVmlkdUVycm9yKE9wZW5WaWR1RXJyb3JOYW1lLlNDUkVFTl9DQVBUVVJFX0RFTklFRCwgJ1lvdSBtdXN0IGFsbG93IGFjY2VzcyB0byBvbmUgd2luZG93IG9mIHlvdXIgZGVza3RvcCcpO1xuICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgY29uc3QgZXh0ZW5zaW9uSWQgPSB0aGlzLmFkdmFuY2VkQ29uZmlndXJhdGlvbi5zY3JlZW5TaGFyZUNocm9tZUV4dGVuc2lvbiEuc3BsaXQoJy8nKS5wb3AoKSEhLnRyaW0oKTtcbiAgICAgICAgICAgICAgICAgICAgICBzY3JlZW5TaGFyaW5nLmdldENocm9tZUV4dGVuc2lvblN0YXR1cyhleHRlbnNpb25JZCwgKHN0YXR1cykgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHN0YXR1cyA9PT0gJ2luc3RhbGxlZC1kaXNhYmxlZCcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZXJyb3IgPSBuZXcgT3BlblZpZHVFcnJvcihPcGVuVmlkdUVycm9yTmFtZS5TQ1JFRU5fRVhURU5TSU9OX0RJU0FCTEVELCAnWW91IG11c3QgZW5hYmxlIHRoZSBzY3JlZW4gZXh0ZW5zaW9uJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHN0YXR1cyA9PT0gJ25vdC1pbnN0YWxsZWQnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGVycm9yID0gbmV3IE9wZW5WaWR1RXJyb3IoT3BlblZpZHVFcnJvck5hbWUuU0NSRUVOX0VYVEVOU0lPTl9OT1RfSU5TVEFMTEVELCAoPHN0cmluZz50aGlzLmFkdmFuY2VkQ29uZmlndXJhdGlvbi5zY3JlZW5TaGFyZUNocm9tZUV4dGVuc2lvbikpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgbWVkaWFDb25zdHJhaW50cy52aWRlbyA9IHNjcmVlbkNvbnN0cmFpbnRzO1xuICAgICAgICAgICAgICAgICAgICByZXNvbHZlKG1lZGlhQ29uc3RyYWludHMpO1xuICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICB9IGVsc2Uge1xuXG4gICAgICAgICAgICAgICAgLy8gRGVmYXVsdCBzY3JlZW4gc2hhcmluZyBleHRlbnNpb24gZm9yIENocm9tZVxuXG4gICAgICAgICAgICAgICAgc2NyZWVuU2hhcmluZ0F1dG8uZ2V0U2NyZWVuSWQoKGVycm9yLCBzb3VyY2VJZCwgc2NyZWVuQ29uc3RyYWludHMpID0+IHtcbiAgICAgICAgICAgICAgICAgIGlmICghIWVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnJvciA9PT0gJ25vdC1pbnN0YWxsZWQnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgY29uc3QgZXh0ZW5zaW9uVXJsID0gISF0aGlzLmFkdmFuY2VkQ29uZmlndXJhdGlvbi5zY3JlZW5TaGFyZUNocm9tZUV4dGVuc2lvbiA/IHRoaXMuYWR2YW5jZWRDb25maWd1cmF0aW9uLnNjcmVlblNoYXJlQ2hyb21lRXh0ZW5zaW9uIDpcbiAgICAgICAgICAgICAgICAgICAgICAgICdodHRwczovL2Nocm9tZS5nb29nbGUuY29tL3dlYnN0b3JlL2RldGFpbC9vcGVudmlkdS1zY3JlZW5zaGFyaW5nL2xmY2dmZXBhZm5vYmRsb2VjY2huZmFjbGliZW5qb2xkJztcbiAgICAgICAgICAgICAgICAgICAgICBjb25zdCBlcnJvciA9IG5ldyBPcGVuVmlkdUVycm9yKE9wZW5WaWR1RXJyb3JOYW1lLlNDUkVFTl9FWFRFTlNJT05fTk9UX0lOU1RBTExFRCwgZXh0ZW5zaW9uVXJsKTtcbiAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGVycm9yID09PSAnaW5zdGFsbGVkLWRpc2FibGVkJykge1xuICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGVycm9yID0gbmV3IE9wZW5WaWR1RXJyb3IoT3BlblZpZHVFcnJvck5hbWUuU0NSRUVOX0VYVEVOU0lPTl9ESVNBQkxFRCwgJ1lvdSBtdXN0IGVuYWJsZSB0aGUgc2NyZWVuIGV4dGVuc2lvbicpO1xuICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoZXJyb3IgPT09ICdwZXJtaXNzaW9uLWRlbmllZCcpIHtcbiAgICAgICAgICAgICAgICAgICAgICBjb25zdCBlcnJvciA9IG5ldyBPcGVuVmlkdUVycm9yKE9wZW5WaWR1RXJyb3JOYW1lLlNDUkVFTl9DQVBUVVJFX0RFTklFRCwgJ1lvdSBtdXN0IGFsbG93IGFjY2VzcyB0byBvbmUgd2luZG93IG9mIHlvdXIgZGVza3RvcCcpO1xuICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIG1lZGlhQ29uc3RyYWludHMudmlkZW8gPSBzY3JlZW5Db25zdHJhaW50cy52aWRlbztcbiAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZShtZWRpYUNvbnN0cmFpbnRzKTtcbiAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgIHB1Ymxpc2hlclByb3BlcnRpZXMudmlkZW9Tb3VyY2UgPSAnc2NyZWVuJztcblxuICAgICAgICAgICAgfVxuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6bm8tc3RyaW5nLWxpdGVyYWxcbiAgICAgICAgICAgIG1lZGlhQ29uc3RyYWludHMudmlkZW9bJ2RldmljZUlkJ10gPSB7IGV4YWN0OiBwdWJsaXNoZXJQcm9wZXJ0aWVzLnZpZGVvU291cmNlIH07XG4gICAgICAgICAgICByZXNvbHZlKG1lZGlhQ29uc3RyYWludHMpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICByZXNvbHZlKG1lZGlhQ29uc3RyYWludHMpO1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXNvbHZlKG1lZGlhQ29uc3RyYWludHMpO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIEBoaWRkZW5cbiAgICovXG4gIHN0YXJ0V3Mob25Db25uZWN0U3VjY2VzOiAoZXJyb3I6IEVycm9yKSA9PiB2b2lkKTogdm9pZCB7XG4gICAgY29uc3QgY29uZmlnID0ge1xuICAgICAgaGVhcnRiZWF0OiA1MDAwLFxuICAgICAgc2VuZENsb3NlTWVzc2FnZTogZmFsc2UsXG4gICAgICB3czoge1xuICAgICAgICB1cmk6IHRoaXMud3NVcmksXG4gICAgICAgIHVzZVNvY2tKUzogZmFsc2UsXG4gICAgICAgIG9uY29ubmVjdGVkOiBvbkNvbm5lY3RTdWNjZXMsXG4gICAgICAgIG9uZGlzY29ubmVjdDogdGhpcy5kaXNjb25uZWN0Q2FsbGJhY2suYmluZCh0aGlzKSxcbiAgICAgICAgb25yZWNvbm5lY3Rpbmc6IHRoaXMucmVjb25uZWN0aW5nQ2FsbGJhY2suYmluZCh0aGlzKSxcbiAgICAgICAgb25yZWNvbm5lY3RlZDogdGhpcy5yZWNvbm5lY3RlZENhbGxiYWNrLmJpbmQodGhpcylcbiAgICAgIH0sXG4gICAgICBycGM6IHtcbiAgICAgICAgcmVxdWVzdFRpbWVvdXQ6IDEwMDAwLFxuICAgICAgICBwYXJ0aWNpcGFudEpvaW5lZDogdGhpcy5zZXNzaW9uLm9uUGFydGljaXBhbnRKb2luZWQuYmluZCh0aGlzLnNlc3Npb24pLFxuICAgICAgICBwYXJ0aWNpcGFudFB1Ymxpc2hlZDogdGhpcy5zZXNzaW9uLm9uUGFydGljaXBhbnRQdWJsaXNoZWQuYmluZCh0aGlzLnNlc3Npb24pLFxuICAgICAgICBwYXJ0aWNpcGFudFVucHVibGlzaGVkOiB0aGlzLnNlc3Npb24ub25QYXJ0aWNpcGFudFVucHVibGlzaGVkLmJpbmQodGhpcy5zZXNzaW9uKSxcbiAgICAgICAgcGFydGljaXBhbnRMZWZ0OiB0aGlzLnNlc3Npb24ub25QYXJ0aWNpcGFudExlZnQuYmluZCh0aGlzLnNlc3Npb24pLFxuICAgICAgICBwYXJ0aWNpcGFudEV2aWN0ZWQ6IHRoaXMuc2Vzc2lvbi5vblBhcnRpY2lwYW50RXZpY3RlZC5iaW5kKHRoaXMuc2Vzc2lvbiksXG4gICAgICAgIHJlY29yZGluZ1N0YXJ0ZWQ6IHRoaXMuc2Vzc2lvbi5vblJlY29yZGluZ1N0YXJ0ZWQuYmluZCh0aGlzLnNlc3Npb24pLFxuICAgICAgICByZWNvcmRpbmdTdG9wcGVkOiB0aGlzLnNlc3Npb24ub25SZWNvcmRpbmdTdG9wcGVkLmJpbmQodGhpcy5zZXNzaW9uKSxcbiAgICAgICAgc2VuZE1lc3NhZ2U6IHRoaXMuc2Vzc2lvbi5vbk5ld01lc3NhZ2UuYmluZCh0aGlzLnNlc3Npb24pLFxuICAgICAgICBzdHJlYW1Qcm9wZXJ0eUNoYW5nZWQ6IHRoaXMuc2Vzc2lvbi5vblN0cmVhbVByb3BlcnR5Q2hhbmdlZC5iaW5kKHRoaXMuc2Vzc2lvbiksXG4gICAgICAgIGljZUNhbmRpZGF0ZTogdGhpcy5zZXNzaW9uLnJlY3ZJY2VDYW5kaWRhdGUuYmluZCh0aGlzLnNlc3Npb24pLFxuICAgICAgICBtZWRpYUVycm9yOiB0aGlzLnNlc3Npb24ub25NZWRpYUVycm9yLmJpbmQodGhpcy5zZXNzaW9uKVxuICAgICAgfVxuICAgIH07XG4gICAgdGhpcy5qc29uUnBjQ2xpZW50ID0gbmV3IFJwY0J1aWxkZXIuY2xpZW50cy5Kc29uUnBjQ2xpZW50KGNvbmZpZyk7XG4gIH1cblxuICAvKipcbiAgICogQGhpZGRlblxuICAgKi9cbiAgY2xvc2VXcygpOiB2b2lkIHtcbiAgICB0aGlzLmpzb25ScGNDbGllbnQuY2xvc2UoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICBzZW5kUmVxdWVzdChtZXRob2Q6IHN0cmluZywgcGFyYW1zOiBhbnksIGNhbGxiYWNrPyk6IHZvaWQge1xuICAgIGlmIChwYXJhbXMgJiYgcGFyYW1zIGluc3RhbmNlb2YgRnVuY3Rpb24pIHtcbiAgICAgIGNhbGxiYWNrID0gcGFyYW1zO1xuICAgICAgcGFyYW1zID0ge307XG4gICAgfVxuICAgIGNvbnNvbGUuZGVidWcoJ1NlbmRpbmcgcmVxdWVzdDoge21ldGhvZDpcIicgKyBtZXRob2QgKyAnXCIsIHBhcmFtczogJyArIEpTT04uc3RyaW5naWZ5KHBhcmFtcykgKyAnfScpO1xuICAgIHRoaXMuanNvblJwY0NsaWVudC5zZW5kKG1ldGhvZCwgcGFyYW1zLCBjYWxsYmFjayk7XG4gIH1cblxuICAvKipcbiAgICogQGhpZGRlblxuICAgKi9cbiAgaXNNZWRpYVN0cmVhbVRyYWNrKG1lZGlhU291cmNlOiBhbnkpOiBib29sZWFuIHtcbiAgICBjb25zdCBpcyA9ICghIW1lZGlhU291cmNlICYmXG4gICAgICBtZWRpYVNvdXJjZS5lbmFibGVkICE9PSB1bmRlZmluZWQgJiYgdHlwZW9mIG1lZGlhU291cmNlLmVuYWJsZWQgPT09ICdib29sZWFuJyAmJlxuICAgICAgbWVkaWFTb3VyY2UuaWQgIT09IHVuZGVmaW5lZCAmJiB0eXBlb2YgbWVkaWFTb3VyY2UuaWQgPT09ICdzdHJpbmcnICYmXG4gICAgICBtZWRpYVNvdXJjZS5raW5kICE9PSB1bmRlZmluZWQgJiYgdHlwZW9mIG1lZGlhU291cmNlLmtpbmQgPT09ICdzdHJpbmcnICYmXG4gICAgICBtZWRpYVNvdXJjZS5sYWJlbCAhPT0gdW5kZWZpbmVkICYmIHR5cGVvZiBtZWRpYVNvdXJjZS5sYWJlbCA9PT0gJ3N0cmluZycgJiZcbiAgICAgIG1lZGlhU291cmNlLm11dGVkICE9PSB1bmRlZmluZWQgJiYgdHlwZW9mIG1lZGlhU291cmNlLm11dGVkID09PSAnYm9vbGVhbicgJiZcbiAgICAgIG1lZGlhU291cmNlLnJlYWR5U3RhdGUgIT09IHVuZGVmaW5lZCAmJiB0eXBlb2YgbWVkaWFTb3VyY2UucmVhZHlTdGF0ZSA9PT0gJ3N0cmluZycpO1xuICAgIHJldHVybiBpcztcbiAgfVxuXG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICBnZXRXc1VyaSgpOiBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLndzVXJpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBoaWRkZW5cbiAgICovXG4gIGdldFNlY3JldCgpOiBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLnNlY3JldDtcbiAgfVxuXG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICBnZXRSZWNvcmRlcigpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5yZWNvcmRlcjtcbiAgfVxuXG5cbiAgLyogUHJpdmF0ZSBtZXRob2RzICovXG5cbiAgcHJpdmF0ZSBkaXNjb25uZWN0Q2FsbGJhY2soKTogdm9pZCB7XG4gICAgY29uc29sZS53YXJuKCdXZWJzb2NrZXQgY29ubmVjdGlvbiBsb3N0Jyk7XG4gICAgaWYgKHRoaXMuaXNSb29tQXZhaWxhYmxlKCkpIHtcbiAgICAgIHRoaXMuc2Vzc2lvbi5vbkxvc3RDb25uZWN0aW9uKCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGFsZXJ0KCdDb25uZWN0aW9uIGVycm9yLiBQbGVhc2UgcmVsb2FkIHBhZ2UuJyk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSByZWNvbm5lY3RpbmdDYWxsYmFjaygpOiB2b2lkIHtcbiAgICBjb25zb2xlLndhcm4oJ1dlYnNvY2tldCBjb25uZWN0aW9uIGxvc3QgKHJlY29ubmVjdGluZyknKTtcbiAgICBpZiAodGhpcy5pc1Jvb21BdmFpbGFibGUoKSkge1xuICAgICAgdGhpcy5zZXNzaW9uLm9uTG9zdENvbm5lY3Rpb24oKTtcbiAgICB9IGVsc2Uge1xuICAgICAgYWxlcnQoJ0Nvbm5lY3Rpb24gZXJyb3IuIFBsZWFzZSByZWxvYWQgcGFnZS4nKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIHJlY29ubmVjdGVkQ2FsbGJhY2soKTogdm9pZCB7XG4gICAgY29uc29sZS53YXJuKCdXZWJzb2NrZXQgcmVjb25uZWN0ZWQnKTtcbiAgICBpZiAodGhpcy5pc1Jvb21BdmFpbGFibGUoKSkge1xuICAgICAgdGhpcy5zZXNzaW9uLm9uUmVjb3ZlcmVkQ29ubmVjdGlvbigpO1xuICAgIH0gZWxzZSB7XG4gICAgICBhbGVydCgnQ29ubmVjdGlvbiBlcnJvci4gUGxlYXNlIHJlbG9hZCBwYWdlLicpO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgaXNSb29tQXZhaWxhYmxlKCk6IGJvb2xlYW4ge1xuICAgIGlmICh0aGlzLnNlc3Npb24gIT09IHVuZGVmaW5lZCAmJiB0aGlzLnNlc3Npb24gaW5zdGFuY2VvZiBTZXNzaW9uKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9IGVsc2Uge1xuICAgICAgY29uc29sZS53YXJuKCdTZXNzaW9uIGluc3RhbmNlIG5vdCBmb3VuZCcpO1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfVxuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBPcGVuVmlkdSB9IGZyb20gJy4vT3BlblZpZHUnO1xuaW1wb3J0IHsgU2Vzc2lvbiB9IGZyb20gJy4vU2Vzc2lvbic7XG5pbXBvcnQgeyBTdHJlYW0gfSBmcm9tICcuL1N0cmVhbSc7XG5pbXBvcnQgeyBTdHJlYW1NYW5hZ2VyIH0gZnJvbSAnLi9TdHJlYW1NYW5hZ2VyJztcbmltcG9ydCB7IEV2ZW50RGlzcGF0Y2hlciB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvSW50ZXJmYWNlcy9QdWJsaWMvRXZlbnREaXNwYXRjaGVyJztcbmltcG9ydCB7IFB1Ymxpc2hlclByb3BlcnRpZXMgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHVibGljL1B1Ymxpc2hlclByb3BlcnRpZXMnO1xuaW1wb3J0IHsgRXZlbnQgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0V2ZW50cy9FdmVudCc7XG5pbXBvcnQgeyBTdHJlYW1FdmVudCB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1N0cmVhbUV2ZW50JztcbmltcG9ydCB7IFN0cmVhbVByb3BlcnR5Q2hhbmdlZEV2ZW50IH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvU3RyZWFtUHJvcGVydHlDaGFuZ2VkRXZlbnQnO1xuaW1wb3J0IHsgVmlkZW9FbGVtZW50RXZlbnQgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0V2ZW50cy9WaWRlb0VsZW1lbnRFdmVudCc7XG5pbXBvcnQgeyBPcGVuVmlkdUVycm9yLCBPcGVuVmlkdUVycm9yTmFtZSB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRW51bXMvT3BlblZpZHVFcnJvcic7XG5pbXBvcnQgeyBWaWRlb0luc2VydE1vZGUgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0VudW1zL1ZpZGVvSW5zZXJ0TW9kZSc7XG5cbmltcG9ydCBwbGF0Zm9ybSA9IHJlcXVpcmUoJ3BsYXRmb3JtJyk7XG5cblxuLyoqXG4gKiBQYWNrcyBsb2NhbCBtZWRpYSBzdHJlYW1zLiBQYXJ0aWNpcGFudHMgY2FuIHB1Ymxpc2ggaXQgdG8gYSBzZXNzaW9uLiBJbml0aWFsaXplZCB3aXRoIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dIG1ldGhvZFxuICovXG5leHBvcnQgY2xhc3MgUHVibGlzaGVyIGV4dGVuZHMgU3RyZWFtTWFuYWdlciB7XG5cbiAgICAvKipcbiAgICAgKiBXaGV0aGVyIHRoZSBQdWJsaXNoZXIgaGFzIGJlZW4gZ3JhbnRlZCBhY2Nlc3MgdG8gdGhlIHJlcXVlc3RlZCBpbnB1dCBkZXZpY2VzIG9yIG5vdFxuICAgICAqL1xuICAgIGFjY2Vzc0FsbG93ZWQgPSBmYWxzZTtcblxuICAgIC8qKlxuICAgICAqIFdoZXRoZXIgeW91IGhhdmUgY2FsbGVkIFtbUHVibGlzaGVyLnN1YnNjcmliZVRvUmVtb3RlXV0gd2l0aCB2YWx1ZSBgdHJ1ZWAgb3IgYGZhbHNlYCAoKmZhbHNlKiBieSBkZWZhdWx0KVxuICAgICAqL1xuICAgIGlzU3Vic2NyaWJlZFRvUmVtb3RlID0gZmFsc2U7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgW1tTZXNzaW9uXV0gdG8gd2hpY2ggdGhlIFB1Ymxpc2hlciBiZWxvbmdzXG4gICAgICovXG4gICAgc2Vzc2lvbjogU2Vzc2lvbjsgLy8gSW5pdGlhbGl6ZWQgYnkgU2Vzc2lvbi5wdWJsaXNoKFB1Ymxpc2hlcilcblxuICAgIHByaXZhdGUgYWNjZXNzRGVuaWVkID0gZmFsc2U7XG4gICAgcHJpdmF0ZSBwcm9wZXJ0aWVzOiBQdWJsaXNoZXJQcm9wZXJ0aWVzO1xuICAgIHByaXZhdGUgcGVybWlzc2lvbkRpYWxvZ1RpbWVvdXQ6IE5vZGVKUy5UaW1lcjtcblxuICAgIC8qKlxuICAgICAqIGhpZGRlblxuICAgICAqL1xuICAgIG9wZW52aWR1OiBPcGVuVmlkdTtcbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgdmlkZW9SZWZlcmVuY2U6IEhUTUxWaWRlb0VsZW1lbnQ7XG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHNjcmVlblNoYXJlUmVzaXplSW50ZXJ2YWw6IE5vZGVKUy5UaW1lcjtcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3Rvcih0YXJnRWw6IHN0cmluZyB8IEhUTUxFbGVtZW50LCBwcm9wZXJ0aWVzOiBQdWJsaXNoZXJQcm9wZXJ0aWVzLCBvcGVudmlkdTogT3BlblZpZHUpIHtcbiAgICAgICAgc3VwZXIobmV3IFN0cmVhbSgoISFvcGVudmlkdS5zZXNzaW9uKSA/IG9wZW52aWR1LnNlc3Npb24gOiBuZXcgU2Vzc2lvbihvcGVudmlkdSksIHsgcHVibGlzaGVyUHJvcGVydGllczogcHJvcGVydGllcywgbWVkaWFDb25zdHJhaW50czoge30gfSksIHRhcmdFbCk7XG4gICAgICAgIHRoaXMucHJvcGVydGllcyA9IHByb3BlcnRpZXM7XG4gICAgICAgIHRoaXMub3BlbnZpZHUgPSBvcGVudmlkdTtcblxuICAgICAgICB0aGlzLnN0cmVhbS5lZS5vbignbG9jYWwtc3RyZWFtLWRlc3Ryb3llZCcsIChyZWFzb246IHN0cmluZykgPT4ge1xuICAgICAgICAgICAgdGhpcy5zdHJlYW0uaXNMb2NhbFN0cmVhbVB1Ymxpc2hlZCA9IGZhbHNlO1xuICAgICAgICAgICAgY29uc3Qgc3RyZWFtRXZlbnQgPSBuZXcgU3RyZWFtRXZlbnQodHJ1ZSwgdGhpcywgJ3N0cmVhbURlc3Ryb3llZCcsIHRoaXMuc3RyZWFtLCByZWFzb24pO1xuICAgICAgICAgICAgdGhpcy5lbWl0RXZlbnQoJ3N0cmVhbURlc3Ryb3llZCcsIFtzdHJlYW1FdmVudF0pO1xuICAgICAgICAgICAgc3RyZWFtRXZlbnQuY2FsbERlZmF1bHRCZWhhdmlvcigpO1xuICAgICAgICB9KTtcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFB1Ymxpc2ggb3IgdW5wdWJsaXNoIHRoZSBhdWRpbyBzdHJlYW0gKGlmIGF2YWlsYWJsZSkuIENhbGxpbmcgdGhpcyBtZXRob2QgdHdpY2UgaW4gYSByb3cgcGFzc2luZyBzYW1lIHZhbHVlIHdpbGwgaGF2ZSBubyBlZmZlY3RcbiAgICAgKlxuICAgICAqICMjIyMgRXZlbnRzIGRpc3BhdGNoZWRcbiAgICAgKlxuICAgICAqIFRoZSBbW1Nlc3Npb25dXSBvYmplY3Qgb2YgdGhlIGxvY2FsIHBhcnRpY2lwYW50IHdpbGwgZGlzcGF0Y2ggYSBgc3RyZWFtUHJvcGVydHlDaGFuZ2VkYCBldmVudCB3aXRoIGBjaGFuZ2VkUHJvcGVydHlgIHNldCB0byBgXCJhdWRpb0FjdGl2ZVwiYCBhbmQgYHJlYXNvbmAgc2V0IHRvIGBcInB1Ymxpc2hBdWRpb1wiYFxuICAgICAqIFRoZSBbW1B1Ymxpc2hlcl1dIG9iamVjdCBvZiB0aGUgbG9jYWwgcGFydGljaXBhbnQgd2lsbCBhbHNvIGRpc3BhdGNoIHRoZSBleGFjdCBzYW1lIGV2ZW50XG4gICAgICpcbiAgICAgKiBUaGUgW1tTZXNzaW9uXV0gb2JqZWN0IG9mIGV2ZXJ5IG90aGVyIHBhcnRpY2lwYW50IGNvbm5lY3RlZCB0byB0aGUgc2Vzc2lvbiB3aWxsIGRpc3BhdGNoIGEgYHN0cmVhbVByb3BlcnR5Q2hhbmdlZGAgZXZlbnQgd2l0aCBgY2hhbmdlZFByb3BlcnR5YCBzZXQgdG8gYFwiYXVkaW9BY3RpdmVcImAgYW5kIGByZWFzb25gIHNldCB0byBgXCJwdWJsaXNoQXVkaW9cImBcbiAgICAgKiBUaGUgcmVzcGVjdGl2ZSBbW1N1YnNjcmliZXJdXSBvYmplY3Qgb2YgZXZlcnkgb3RoZXIgcGFydGljaXBhbnQgcmVjZWl2aW5nIHRoaXMgUHVibGlzaGVyJ3Mgc3RyZWFtIHdpbGwgYWxzbyBkaXNwYXRjaCB0aGUgZXhhY3Qgc2FtZSBldmVudFxuICAgICAqXG4gICAgICogU2VlIFtbU3RyZWFtUHJvcGVydHlDaGFuZ2VkRXZlbnRdXSB0byBsZWFybiBtb3JlLlxuICAgICAqXG4gICAgICogQHBhcmFtIHZhbHVlIGB0cnVlYCB0byBwdWJsaXNoIHRoZSBhdWRpbyBzdHJlYW0sIGBmYWxzZWAgdG8gdW5wdWJsaXNoIGl0XG4gICAgICovXG4gICAgcHVibGlzaEF1ZGlvKHZhbHVlOiBib29sZWFuKTogdm9pZCB7XG4gICAgICAgIGlmICh0aGlzLnN0cmVhbS5hdWRpb0FjdGl2ZSAhPT0gdmFsdWUpIHtcbiAgICAgICAgICAgIHRoaXMuc3RyZWFtLmdldE1lZGlhU3RyZWFtKCkuZ2V0QXVkaW9UcmFja3MoKS5mb3JFYWNoKCh0cmFjaykgPT4ge1xuICAgICAgICAgICAgICAgIHRyYWNrLmVuYWJsZWQgPSB2YWx1ZTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgdGhpcy5zZXNzaW9uLm9wZW52aWR1LnNlbmRSZXF1ZXN0KFxuICAgICAgICAgICAgICAgICdzdHJlYW1Qcm9wZXJ0eUNoYW5nZWQnLFxuICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgc3RyZWFtSWQ6IHRoaXMuc3RyZWFtLnN0cmVhbUlkLFxuICAgICAgICAgICAgICAgICAgICBwcm9wZXJ0eTogJ2F1ZGlvQWN0aXZlJyxcbiAgICAgICAgICAgICAgICAgICAgbmV3VmFsdWU6IHZhbHVlLFxuICAgICAgICAgICAgICAgICAgICByZWFzb246ICdwdWJsaXNoQXVkaW8nXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAoZXJyb3IsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihcIkVycm9yIHNlbmRpbmcgJ3N0cmVhbVByb3BlcnR5Q2hhbmdlZCcgZXZlbnRcIiwgZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXNzaW9uLmVtaXRFdmVudCgnc3RyZWFtUHJvcGVydHlDaGFuZ2VkJywgW25ldyBTdHJlYW1Qcm9wZXJ0eUNoYW5nZWRFdmVudCh0aGlzLnNlc3Npb24sIHRoaXMuc3RyZWFtLCAnYXVkaW9BY3RpdmUnLCB2YWx1ZSwgIXZhbHVlLCAncHVibGlzaEF1ZGlvJyldKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZW1pdEV2ZW50KCdzdHJlYW1Qcm9wZXJ0eUNoYW5nZWQnLCBbbmV3IFN0cmVhbVByb3BlcnR5Q2hhbmdlZEV2ZW50KHRoaXMsIHRoaXMuc3RyZWFtLCAnYXVkaW9BY3RpdmUnLCB2YWx1ZSwgIXZhbHVlLCAncHVibGlzaEF1ZGlvJyldKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgdGhpcy5zdHJlYW0uYXVkaW9BY3RpdmUgPSB2YWx1ZTtcbiAgICAgICAgICAgIGNvbnNvbGUuaW5mbyhcIidQdWJsaXNoZXInIGhhcyBcIiArICh2YWx1ZSA/ICdwdWJsaXNoZWQnIDogJ3VucHVibGlzaGVkJykgKyAnIGl0cyBhdWRpbyBzdHJlYW0nKTtcbiAgICAgICAgfVxuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogUHVibGlzaCBvciB1bnB1Ymxpc2ggdGhlIHZpZGVvIHN0cmVhbSAoaWYgYXZhaWxhYmxlKS4gQ2FsbGluZyB0aGlzIG1ldGhvZCB0d2ljZSBpbiBhIHJvdyBwYXNzaW5nIHNhbWUgdmFsdWUgd2lsbCBoYXZlIG5vIGVmZmVjdFxuICAgICAqXG4gICAgICogIyMjIyBFdmVudHMgZGlzcGF0Y2hlZFxuICAgICAqXG4gICAgICogVGhlIFtbU2Vzc2lvbl1dIG9iamVjdCBvZiB0aGUgbG9jYWwgcGFydGljaXBhbnQgd2lsbCBkaXNwYXRjaCBhIGBzdHJlYW1Qcm9wZXJ0eUNoYW5nZWRgIGV2ZW50IHdpdGggYGNoYW5nZWRQcm9wZXJ0eWAgc2V0IHRvIGBcInZpZGVvQWN0aXZlXCJgIGFuZCBgcmVhc29uYCBzZXQgdG8gYFwicHVibGlzaFZpZGVvXCJgXG4gICAgICogVGhlIFtbUHVibGlzaGVyXV0gb2JqZWN0IG9mIHRoZSBsb2NhbCBwYXJ0aWNpcGFudCB3aWxsIGFsc28gZGlzcGF0Y2ggdGhlIGV4YWN0IHNhbWUgZXZlbnRcbiAgICAgKlxuICAgICAqIFRoZSBbW1Nlc3Npb25dXSBvYmplY3Qgb2YgZXZlcnkgb3RoZXIgcGFydGljaXBhbnQgY29ubmVjdGVkIHRvIHRoZSBzZXNzaW9uIHdpbGwgZGlzcGF0Y2ggYSBgc3RyZWFtUHJvcGVydHlDaGFuZ2VkYCBldmVudCB3aXRoIGBjaGFuZ2VkUHJvcGVydHlgIHNldCB0byBgXCJ2aWRlb0FjdGl2ZVwiYCBhbmQgYHJlYXNvbmAgc2V0IHRvIGBcInB1Ymxpc2hWaWRlb1wiYFxuICAgICAqIFRoZSByZXNwZWN0aXZlIFtbU3Vic2NyaWJlcl1dIG9iamVjdCBvZiBldmVyeSBvdGhlciBwYXJ0aWNpcGFudCByZWNlaXZpbmcgdGhpcyBQdWJsaXNoZXIncyBzdHJlYW0gd2lsbCBhbHNvIGRpc3BhdGNoIHRoZSBleGFjdCBzYW1lIGV2ZW50XG4gICAgICpcbiAgICAgKiBTZWUgW1tTdHJlYW1Qcm9wZXJ0eUNoYW5nZWRFdmVudF1dIHRvIGxlYXJuIG1vcmUuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gdmFsdWUgYHRydWVgIHRvIHB1Ymxpc2ggdGhlIHZpZGVvIHN0cmVhbSwgYGZhbHNlYCB0byB1bnB1Ymxpc2ggaXRcbiAgICAgKi9cbiAgICBwdWJsaXNoVmlkZW8odmFsdWU6IGJvb2xlYW4pOiB2b2lkIHtcbiAgICAgICAgaWYgKHRoaXMuc3RyZWFtLnZpZGVvQWN0aXZlICE9PSB2YWx1ZSkge1xuICAgICAgICAgICAgdGhpcy5zdHJlYW0uZ2V0TWVkaWFTdHJlYW0oKS5nZXRWaWRlb1RyYWNrcygpLmZvckVhY2goKHRyYWNrKSA9PiB7XG4gICAgICAgICAgICAgICAgdHJhY2suZW5hYmxlZCA9IHZhbHVlO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB0aGlzLnNlc3Npb24ub3BlbnZpZHUuc2VuZFJlcXVlc3QoXG4gICAgICAgICAgICAgICAgJ3N0cmVhbVByb3BlcnR5Q2hhbmdlZCcsXG4gICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICBzdHJlYW1JZDogdGhpcy5zdHJlYW0uc3RyZWFtSWQsXG4gICAgICAgICAgICAgICAgICAgIHByb3BlcnR5OiAndmlkZW9BY3RpdmUnLFxuICAgICAgICAgICAgICAgICAgICBuZXdWYWx1ZTogdmFsdWUsXG4gICAgICAgICAgICAgICAgICAgIHJlYXNvbjogJ3B1Ymxpc2hWaWRlbydcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIChlcnJvciwgcmVzcG9uc2UpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKFwiRXJyb3Igc2VuZGluZyAnc3RyZWFtUHJvcGVydHlDaGFuZ2VkJyBldmVudFwiLCBlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnNlc3Npb24uZW1pdEV2ZW50KCdzdHJlYW1Qcm9wZXJ0eUNoYW5nZWQnLCBbbmV3IFN0cmVhbVByb3BlcnR5Q2hhbmdlZEV2ZW50KHRoaXMuc2Vzc2lvbiwgdGhpcy5zdHJlYW0sICd2aWRlb0FjdGl2ZScsIHZhbHVlLCAhdmFsdWUsICdwdWJsaXNoVmlkZW8nKV0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5lbWl0RXZlbnQoJ3N0cmVhbVByb3BlcnR5Q2hhbmdlZCcsIFtuZXcgU3RyZWFtUHJvcGVydHlDaGFuZ2VkRXZlbnQodGhpcywgdGhpcy5zdHJlYW0sICd2aWRlb0FjdGl2ZScsIHZhbHVlLCAhdmFsdWUsICdwdWJsaXNoVmlkZW8nKV0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB0aGlzLnN0cmVhbS52aWRlb0FjdGl2ZSA9IHZhbHVlO1xuICAgICAgICAgICAgY29uc29sZS5pbmZvKFwiJ1B1Ymxpc2hlcicgaGFzIFwiICsgKHZhbHVlID8gJ3B1Ymxpc2hlZCcgOiAndW5wdWJsaXNoZWQnKSArICcgaXRzIHZpZGVvIHN0cmVhbScpO1xuICAgICAgICB9XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBDYWxsIHRoaXMgbWV0aG9kIGJlZm9yZSBbW1Nlc3Npb24ucHVibGlzaF1dIGlmIHlvdSBwcmVmZXIgdG8gc3Vic2NyaWJlIHRvIHlvdXIgUHVibGlzaGVyJ3MgcmVtb3RlIHN0cmVhbSBpbnN0ZWFkIG9mIHVzaW5nIHRoZSBsb2NhbCBzdHJlYW0sIGFzIGFueSBvdGhlciB1c2VyIHdvdWxkIGRvLlxuICAgICAqL1xuICAgIHN1YnNjcmliZVRvUmVtb3RlKHZhbHVlPzogYm9vbGVhbik6IHZvaWQge1xuICAgICAgICB2YWx1ZSA9ICh2YWx1ZSAhPT0gdW5kZWZpbmVkKSA/IHZhbHVlIDogdHJ1ZTtcbiAgICAgICAgdGhpcy5pc1N1YnNjcmliZWRUb1JlbW90ZSA9IHZhbHVlO1xuICAgICAgICB0aGlzLnN0cmVhbS5zdWJzY3JpYmVUb015UmVtb3RlKHZhbHVlKTtcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFNlZSBbW0V2ZW50RGlzcGF0Y2hlci5vbl1dXG4gICAgICovXG4gICAgb24odHlwZTogc3RyaW5nLCBoYW5kbGVyOiAoZXZlbnQ6IEV2ZW50KSA9PiB2b2lkKTogRXZlbnREaXNwYXRjaGVyIHtcbiAgICAgICAgc3VwZXIub24odHlwZSwgaGFuZGxlcik7XG4gICAgICAgIGlmICh0eXBlID09PSAnc3RyZWFtQ3JlYXRlZCcpIHtcbiAgICAgICAgICAgIGlmICghIXRoaXMuc3RyZWFtICYmIHRoaXMuc3RyZWFtLmlzTG9jYWxTdHJlYW1QdWJsaXNoZWQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVtaXRFdmVudCgnc3RyZWFtQ3JlYXRlZCcsIFtuZXcgU3RyZWFtRXZlbnQoZmFsc2UsIHRoaXMsICdzdHJlYW1DcmVhdGVkJywgdGhpcy5zdHJlYW0sICcnKV0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbS5lZS5vbignc3RyZWFtLWNyZWF0ZWQtYnktcHVibGlzaGVyJywgKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmVtaXRFdmVudCgnc3RyZWFtQ3JlYXRlZCcsIFtuZXcgU3RyZWFtRXZlbnQoZmFsc2UsIHRoaXMsICdzdHJlYW1DcmVhdGVkJywgdGhpcy5zdHJlYW0sICcnKV0pO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmICh0eXBlID09PSAncmVtb3RlVmlkZW9QbGF5aW5nJykge1xuICAgICAgICAgICAgaWYgKHRoaXMuc3RyZWFtLmRpc3BsYXlNeVJlbW90ZSgpICYmIHRoaXMudmlkZW9zWzBdICYmIHRoaXMudmlkZW9zWzBdLnZpZGVvICYmXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8uY3VycmVudFRpbWUgPiAwICYmXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8ucGF1c2VkID09PSBmYWxzZSAmJlxuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9zWzBdLnZpZGVvLmVuZGVkID09PSBmYWxzZSAmJlxuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9zWzBdLnZpZGVvLnJlYWR5U3RhdGUgPT09IDQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVtaXRFdmVudCgncmVtb3RlVmlkZW9QbGF5aW5nJywgW25ldyBWaWRlb0VsZW1lbnRFdmVudCh0aGlzLnZpZGVvc1swXS52aWRlbywgdGhpcywgJ3JlbW90ZVZpZGVvUGxheWluZycpXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHR5cGUgPT09ICdhY2Nlc3NBbGxvd2VkJykge1xuICAgICAgICAgICAgaWYgKHRoaXMuYWNjZXNzQWxsb3dlZCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZW1pdEV2ZW50KCdhY2Nlc3NBbGxvd2VkJywgW10pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmICh0eXBlID09PSAnYWNjZXNzRGVuaWVkJykge1xuICAgICAgICAgICAgaWYgKHRoaXMuYWNjZXNzRGVuaWVkKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5lbWl0RXZlbnQoJ2FjY2Vzc0RlbmllZCcsIFtdKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFNlZSBbW0V2ZW50RGlzcGF0Y2hlci5vbmNlXV1cbiAgICAgKi9cbiAgICBvbmNlKHR5cGU6IHN0cmluZywgaGFuZGxlcjogKGV2ZW50OiBFdmVudCkgPT4gdm9pZCk6IFB1Ymxpc2hlciB7XG4gICAgICAgIHN1cGVyLm9uY2UodHlwZSwgaGFuZGxlcik7XG4gICAgICAgIGlmICh0eXBlID09PSAnc3RyZWFtQ3JlYXRlZCcpIHtcbiAgICAgICAgICAgIGlmICghIXRoaXMuc3RyZWFtICYmIHRoaXMuc3RyZWFtLmlzTG9jYWxTdHJlYW1QdWJsaXNoZWQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVtaXRFdmVudCgnc3RyZWFtQ3JlYXRlZCcsIFtuZXcgU3RyZWFtRXZlbnQoZmFsc2UsIHRoaXMsICdzdHJlYW1DcmVhdGVkJywgdGhpcy5zdHJlYW0sICcnKV0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbS5lZS5vbmNlKCdzdHJlYW0tY3JlYXRlZC1ieS1wdWJsaXNoZXInLCAoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZW1pdEV2ZW50KCdzdHJlYW1DcmVhdGVkJywgW25ldyBTdHJlYW1FdmVudChmYWxzZSwgdGhpcywgJ3N0cmVhbUNyZWF0ZWQnLCB0aGlzLnN0cmVhbSwgJycpXSk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHR5cGUgPT09ICdyZW1vdGVWaWRlb1BsYXlpbmcnKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5zdHJlYW0uZGlzcGxheU15UmVtb3RlKCkgJiYgdGhpcy52aWRlb3NbMF0gJiYgdGhpcy52aWRlb3NbMF0udmlkZW8gJiZcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvc1swXS52aWRlby5jdXJyZW50VGltZSA+IDAgJiZcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvc1swXS52aWRlby5wYXVzZWQgPT09IGZhbHNlICYmXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8uZW5kZWQgPT09IGZhbHNlICYmXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8ucmVhZHlTdGF0ZSA9PT0gNCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZW1pdEV2ZW50KCdyZW1vdGVWaWRlb1BsYXlpbmcnLCBbbmV3IFZpZGVvRWxlbWVudEV2ZW50KHRoaXMudmlkZW9zWzBdLnZpZGVvLCB0aGlzLCAncmVtb3RlVmlkZW9QbGF5aW5nJyldKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAodHlwZSA9PT0gJ2FjY2Vzc0FsbG93ZWQnKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5hY2Nlc3NBbGxvd2VkKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5lbWl0RXZlbnQoJ2FjY2Vzc0FsbG93ZWQnLCBbXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHR5cGUgPT09ICdhY2Nlc3NEZW5pZWQnKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5hY2Nlc3NEZW5pZWQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVtaXRFdmVudCgnYWNjZXNzRGVuaWVkJywgW10pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuXG4gICAgLyogSGlkZGVuIG1ldGhvZHMgKi9cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBpbml0aWFsaXplKCk6IFByb21pc2U8YW55PiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG5cbiAgICAgICAgICAgIGNvbnN0IGVycm9yQ2FsbGJhY2sgPSAob3BlblZpZHVFcnJvcjogT3BlblZpZHVFcnJvcikgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuYWNjZXNzRGVuaWVkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB0aGlzLmFjY2Vzc0FsbG93ZWQgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICByZWplY3Qob3BlblZpZHVFcnJvcik7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICBjb25zdCBzdWNjZXNzQ2FsbGJhY2sgPSAobWVkaWFTdHJlYW06IE1lZGlhU3RyZWFtKSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5hY2Nlc3NBbGxvd2VkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB0aGlzLmFjY2Vzc0RlbmllZCA9IGZhbHNlO1xuXG4gICAgICAgICAgICAgICAgaWYgKHRoaXMub3BlbnZpZHUuaXNNZWRpYVN0cmVhbVRyYWNrKHRoaXMucHJvcGVydGllcy5hdWRpb1NvdXJjZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgbWVkaWFTdHJlYW0ucmVtb3ZlVHJhY2sobWVkaWFTdHJlYW0uZ2V0QXVkaW9UcmFja3MoKVswXSk7XG4gICAgICAgICAgICAgICAgICAgIG1lZGlhU3RyZWFtLmFkZFRyYWNrKCg8TWVkaWFTdHJlYW1UcmFjaz50aGlzLnByb3BlcnRpZXMuYXVkaW9Tb3VyY2UpKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAodGhpcy5vcGVudmlkdS5pc01lZGlhU3RyZWFtVHJhY2sodGhpcy5wcm9wZXJ0aWVzLnZpZGVvU291cmNlKSkge1xuICAgICAgICAgICAgICAgICAgICBtZWRpYVN0cmVhbS5yZW1vdmVUcmFjayhtZWRpYVN0cmVhbS5nZXRWaWRlb1RyYWNrcygpWzBdKTtcbiAgICAgICAgICAgICAgICAgICAgbWVkaWFTdHJlYW0uYWRkVHJhY2soKDxNZWRpYVN0cmVhbVRyYWNrPnRoaXMucHJvcGVydGllcy52aWRlb1NvdXJjZSkpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIEFwcGx5IFB1Ymxpc2hlclByb3BlcnRpZXMucHVibGlzaEF1ZGlvIGFuZCBQdWJsaXNoZXJQcm9wZXJ0aWVzLnB1Ymxpc2hWaWRlb1xuICAgICAgICAgICAgICAgIGlmICghIW1lZGlhU3RyZWFtLmdldEF1ZGlvVHJhY2tzKClbMF0pIHtcbiAgICAgICAgICAgICAgICAgICAgbWVkaWFTdHJlYW0uZ2V0QXVkaW9UcmFja3MoKVswXS5lbmFibGVkID0gISF0aGlzLnN0cmVhbS5vdXRib3VuZFN0cmVhbU9wdHMucHVibGlzaGVyUHJvcGVydGllcy5wdWJsaXNoQXVkaW87XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmICghIW1lZGlhU3RyZWFtLmdldFZpZGVvVHJhY2tzKClbMF0pIHtcbiAgICAgICAgICAgICAgICAgICAgbWVkaWFTdHJlYW0uZ2V0VmlkZW9UcmFja3MoKVswXS5lbmFibGVkID0gISF0aGlzLnN0cmVhbS5vdXRib3VuZFN0cmVhbU9wdHMucHVibGlzaGVyUHJvcGVydGllcy5wdWJsaXNoVmlkZW87XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb1JlZmVyZW5jZSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3ZpZGVvJyk7XG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb1JlZmVyZW5jZS5zcmNPYmplY3QgPSBtZWRpYVN0cmVhbTtcblxuICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtLnNldE1lZGlhU3RyZWFtKG1lZGlhU3RyZWFtKTtcbiAgICAgICAgICAgICAgICBpZiAoIXRoaXMuc3RyZWFtLmRpc3BsYXlNeVJlbW90ZSgpKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIFdoZW4gd2UgYXJlIHN1YnNjcmliZWQgdG8gb3VyIHJlbW90ZSB3ZSBkb24ndCBzdGlsbCBzZXQgdGhlIE1lZGlhU3RyZWFtIG9iamVjdCBpbiB0aGUgdmlkZW8gZWxlbWVudHMgdG9cbiAgICAgICAgICAgICAgICAgICAgLy8gYXZvaWQgZWFybHkgJ3N0cmVhbVBsYXlpbmcnIGV2ZW50XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtLnVwZGF0ZU1lZGlhU3RyZWFtSW5WaWRlb3MoKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoISF0aGlzLmZpcnN0VmlkZW9FbGVtZW50KSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuY3JlYXRlVmlkZW9FbGVtZW50KHRoaXMuZmlyc3RWaWRlb0VsZW1lbnQudGFyZ2V0RWxlbWVudCwgPFZpZGVvSW5zZXJ0TW9kZT50aGlzLnByb3BlcnRpZXMuaW5zZXJ0TW9kZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGRlbGV0ZSB0aGlzLmZpcnN0VmlkZW9FbGVtZW50O1xuXG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuc3RyZWFtLmlzU2VuZFZpZGVvKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCF0aGlzLnN0cmVhbS5pc1NlbmRTY3JlZW4oKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gV2l0aCBubyBzY3JlZW4gc2hhcmUsIHZpZGVvIGRpbWVuc2lvbiBjYW4gYmUgc2V0IGRpcmVjdGx5IGZyb20gTWVkaWFTdHJlYW0gKGdldFNldHRpbmdzKVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gT3JpZW50YXRpb24gbXVzdCBiZSBjaGVja2VkIGZvciBtb2JpbGUgZGV2aWNlcyAod2lkdGggYW5kIGhlaWdodCBhcmUgcmV2ZXJzZWQpXG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB7IHdpZHRoLCBoZWlnaHQgfSA9IG1lZGlhU3RyZWFtLmdldFZpZGVvVHJhY2tzKClbMF0uZ2V0U2V0dGluZ3MoKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHBsYXRmb3JtLm5hbWUhIS50b0xvd2VyQ2FzZSgpLmluZGV4T2YoJ21vYmlsZScpICE9PSAtMSAmJiAod2luZG93LmlubmVySGVpZ2h0ID4gd2luZG93LmlubmVyV2lkdGgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gTW9iaWxlIHBvcnRyYWl0IG1vZGVcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbS52aWRlb0RpbWVuc2lvbnMgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdpZHRoOiBoZWlnaHQgfHwgMCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaGVpZ2h0OiB3aWR0aCB8fCAwXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdHJlYW0udmlkZW9EaW1lbnNpb25zID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3aWR0aDogd2lkdGggfHwgMCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaGVpZ2h0OiBoZWlnaHQgfHwgMFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbS5pc0xvY2FsU3RyZWFtUmVhZHlUb1B1Ymxpc2ggPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdHJlYW0uZWUuZW1pdEV2ZW50KCdzdHJlYW0tcmVhZHktdG8tcHVibGlzaCcsIFtdKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIFdpdGggc2NyZWVuIHNoYXJlLCB2aWRlbyBkaW1lbnNpb24gbXVzdCBiZSBnb3QgZnJvbSBhIHZpZGVvIGVsZW1lbnQgKG9ubG9hZGVkbWV0YWRhdGEgZXZlbnQpXG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnZpZGVvUmVmZXJlbmNlLm9ubG9hZGVkbWV0YWRhdGEgPSAoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdHJlYW0udmlkZW9EaW1lbnNpb25zID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3aWR0aDogdGhpcy52aWRlb1JlZmVyZW5jZS52aWRlb1dpZHRoLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBoZWlnaHQ6IHRoaXMudmlkZW9SZWZlcmVuY2UudmlkZW9IZWlnaHRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc2NyZWVuU2hhcmVSZXNpemVJbnRlcnZhbCA9IHNldEludGVydmFsKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZmlyZWZveFNldHRpbmdzID0gbWVkaWFTdHJlYW0uZ2V0VmlkZW9UcmFja3MoKVswXS5nZXRTZXR0aW5ncygpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBuZXdXaWR0aCA9IChwbGF0Zm9ybS5uYW1lID09PSAnQ2hyb21lJykgPyB0aGlzLnZpZGVvUmVmZXJlbmNlLnZpZGVvV2lkdGggOiBmaXJlZm94U2V0dGluZ3Mud2lkdGg7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG5ld0hlaWdodCA9IChwbGF0Zm9ybS5uYW1lID09PSAnQ2hyb21lJykgPyB0aGlzLnZpZGVvUmVmZXJlbmNlLnZpZGVvSGVpZ2h0IDogZmlyZWZveFNldHRpbmdzLmhlaWdodDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuc3RyZWFtLmlzTG9jYWxTdHJlYW1QdWJsaXNoZWQgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChuZXdXaWR0aCAhPT0gdGhpcy5zdHJlYW0udmlkZW9EaW1lbnNpb25zLndpZHRoIHx8XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3SGVpZ2h0ICE9PSB0aGlzLnN0cmVhbS52aWRlb0RpbWVuc2lvbnMuaGVpZ2h0KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3Qgb2xkVmFsdWUgPSB7IHdpZHRoOiB0aGlzLnN0cmVhbS52aWRlb0RpbWVuc2lvbnMud2lkdGgsIGhlaWdodDogdGhpcy5zdHJlYW0udmlkZW9EaW1lbnNpb25zLmhlaWdodCB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdHJlYW0udmlkZW9EaW1lbnNpb25zID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdpZHRoOiBuZXdXaWR0aCB8fCAwLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhlaWdodDogbmV3SGVpZ2h0IHx8IDBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnNlc3Npb24ub3BlbnZpZHUuc2VuZFJlcXVlc3QoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ3N0cmVhbVByb3BlcnR5Q2hhbmdlZCcsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJlYW1JZDogdGhpcy5zdHJlYW0uc3RyZWFtSWQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByb3BlcnR5OiAndmlkZW9EaW1lbnNpb25zJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3VmFsdWU6IEpTT04uc3RyaW5naWZ5KHRoaXMuc3RyZWFtLnZpZGVvRGltZW5zaW9ucyksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlYXNvbjogJ3NjcmVlblJlc2l6ZWQnXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoZXJyb3IsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihcIkVycm9yIHNlbmRpbmcgJ3N0cmVhbVByb3BlcnR5Q2hhbmdlZCcgZXZlbnRcIiwgZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXNzaW9uLmVtaXRFdmVudCgnc3RyZWFtUHJvcGVydHlDaGFuZ2VkJywgW25ldyBTdHJlYW1Qcm9wZXJ0eUNoYW5nZWRFdmVudCh0aGlzLnNlc3Npb24sIHRoaXMuc3RyZWFtLCAndmlkZW9EaW1lbnNpb25zJywgdGhpcy5zdHJlYW0udmlkZW9EaW1lbnNpb25zLCBvbGRWYWx1ZSwgJ3NjcmVlblJlc2l6ZWQnKV0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5lbWl0RXZlbnQoJ3N0cmVhbVByb3BlcnR5Q2hhbmdlZCcsIFtuZXcgU3RyZWFtUHJvcGVydHlDaGFuZ2VkRXZlbnQodGhpcywgdGhpcy5zdHJlYW0sICd2aWRlb0RpbWVuc2lvbnMnLCB0aGlzLnN0cmVhbS52aWRlb0RpbWVuc2lvbnMsIG9sZFZhbHVlLCAnc2NyZWVuUmVzaXplZCcpXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0sIDUwMCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdHJlYW0uaXNMb2NhbFN0cmVhbVJlYWR5VG9QdWJsaXNoID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbS5lZS5lbWl0RXZlbnQoJ3N0cmVhbS1yZWFkeS10by1wdWJsaXNoJywgW10pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtLmlzTG9jYWxTdHJlYW1SZWFkeVRvUHVibGlzaCA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtLmVlLmVtaXRFdmVudCgnc3RyZWFtLXJlYWR5LXRvLXB1Ymxpc2gnLCBbXSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIHRoaXMub3BlbnZpZHUuZ2VuZXJhdGVNZWRpYUNvbnN0cmFpbnRzKHRoaXMucHJvcGVydGllcylcbiAgICAgICAgICAgICAgICAudGhlbihjb25zdHJhaW50cyA9PiB7XG5cbiAgICAgICAgICAgICAgICAgICAgY29uc3Qgb3V0Ym91bmRTdHJlYW1PcHRpb25zID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgbWVkaWFDb25zdHJhaW50czogY29uc3RyYWludHMsXG4gICAgICAgICAgICAgICAgICAgICAgICBwdWJsaXNoZXJQcm9wZXJ0aWVzOiB0aGlzLnByb3BlcnRpZXNcbiAgICAgICAgICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbS5zZXRPdXRib3VuZFN0cmVhbU9wdGlvbnMob3V0Ym91bmRTdHJlYW1PcHRpb25zKTtcblxuICAgICAgICAgICAgICAgICAgICBjb25zdCBjb25zdHJhaW50c0F1eDogTWVkaWFTdHJlYW1Db25zdHJhaW50cyA9IHt9O1xuICAgICAgICAgICAgICAgICAgICBjb25zdCB0aW1lRm9yRGlhbG9nRXZlbnQgPSAxMjUwO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLnN0cmVhbS5pc1NlbmRWaWRlbygpIHx8IHRoaXMuc3RyZWFtLmlzU2VuZEF1ZGlvKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGRlZmluZWRBdWRpb0NvbnN0cmFpbnQgPSAoKGNvbnN0cmFpbnRzLmF1ZGlvID09PSB1bmRlZmluZWQpID8gdHJ1ZSA6IGNvbnN0cmFpbnRzLmF1ZGlvKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0cmFpbnRzQXV4LmF1ZGlvID0gdGhpcy5zdHJlYW0uaXNTZW5kU2NyZWVuKCkgPyBmYWxzZSA6IGRlZmluZWRBdWRpb0NvbnN0cmFpbnQ7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdHJhaW50c0F1eC52aWRlbyA9IGNvbnN0cmFpbnRzLnZpZGVvO1xuICAgICAgICAgICAgICAgICAgICAgICAgbGV0IHN0YXJ0VGltZSA9IERhdGUubm93KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnNldFBlcm1pc3Npb25EaWFsb2dUaW1lcih0aW1lRm9yRGlhbG9nRXZlbnQpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBuYXZpZ2F0b3IubWVkaWFEZXZpY2VzLmdldFVzZXJNZWRpYShjb25zdHJhaW50c0F1eClcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAudGhlbihtZWRpYVN0cmVhbSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY2xlYXJQZXJtaXNzaW9uRGlhbG9nVGltZXIoc3RhcnRUaW1lLCB0aW1lRm9yRGlhbG9nRXZlbnQpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLnN0cmVhbS5pc1NlbmRTY3JlZW4oKSAmJiB0aGlzLnN0cmVhbS5pc1NlbmRBdWRpbygpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBXaGVuIGdldHRpbmcgZGVza3RvcCBhcyB1c2VyIG1lZGlhIGF1ZGlvIGNvbnN0cmFpbnQgbXVzdCBiZSBmYWxzZS4gTm93IHdlIGNhbiBhc2sgZm9yIGl0IGlmIHJlcXVpcmVkXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdHJhaW50c0F1eC5hdWRpbyA9IGRlZmluZWRBdWRpb0NvbnN0cmFpbnQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdHJhaW50c0F1eC52aWRlbyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhcnRUaW1lID0gRGF0ZS5ub3coKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc2V0UGVybWlzc2lvbkRpYWxvZ1RpbWVyKHRpbWVGb3JEaWFsb2dFdmVudCk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hdmlnYXRvci5tZWRpYURldmljZXMuZ2V0VXNlck1lZGlhKGNvbnN0cmFpbnRzQXV4KVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC50aGVuKGF1ZGlvT25seVN0cmVhbSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY2xlYXJQZXJtaXNzaW9uRGlhbG9nVGltZXIoc3RhcnRUaW1lLCB0aW1lRm9yRGlhbG9nRXZlbnQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZWRpYVN0cmVhbS5hZGRUcmFjayhhdWRpb09ubHlTdHJlYW0uZ2V0QXVkaW9UcmFja3MoKVswXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN1Y2Nlc3NDYWxsYmFjayhtZWRpYVN0cmVhbSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNsZWFyUGVybWlzc2lvbkRpYWxvZ1RpbWVyKHN0YXJ0VGltZSwgdGltZUZvckRpYWxvZ0V2ZW50KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGVycm9yTmFtZSwgZXJyb3JNZXNzYWdlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzd2l0Y2ggKGVycm9yLm5hbWUudG9Mb3dlckNhc2UoKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAnbm90Zm91bmRlcnJvcic6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JOYW1lID0gT3BlblZpZHVFcnJvck5hbWUuSU5QVVRfQVVESU9fREVWSUNFX05PVF9GT1VORDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck1lc3NhZ2UgPSBlcnJvci50b1N0cmluZygpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yQ2FsbGJhY2sobmV3IE9wZW5WaWR1RXJyb3IoZXJyb3JOYW1lLCBlcnJvck1lc3NhZ2UpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJ25vdGFsbG93ZWRlcnJvcic6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JOYW1lID0gT3BlblZpZHVFcnJvck5hbWUuREVWSUNFX0FDQ0VTU19ERU5JRUQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JNZXNzYWdlID0gZXJyb3IudG9TdHJpbmcoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvckNhbGxiYWNrKG5ldyBPcGVuVmlkdUVycm9yKGVycm9yTmFtZSwgZXJyb3JNZXNzYWdlKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlICdvdmVyY29uc3RyYWluZWRlcnJvcic6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yLmNvbnN0cmFpbnQudG9Mb3dlckNhc2UoKSA9PT0gJ2RldmljZWlkJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck5hbWUgPSBPcGVuVmlkdUVycm9yTmFtZS5JTlBVVF9BVURJT19ERVZJQ0VfTk9UX0ZPVU5EO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck1lc3NhZ2UgPSBcIkF1ZGlvIGlucHV0IGRldmljZSB3aXRoIGRldmljZUlkICdcIiArICg8Q29uc3RyYWluRE9NU3RyaW5nUGFyYW1ldGVycz4oPE1lZGlhVHJhY2tDb25zdHJhaW50cz5jb25zdHJhaW50cy52aWRlbykuZGV2aWNlSWQhISkuZXhhY3QgKyBcIicgbm90IGZvdW5kXCI7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JOYW1lID0gT3BlblZpZHVFcnJvck5hbWUuUFVCTElTSEVSX1BST1BFUlRJRVNfRVJST1I7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yTWVzc2FnZSA9IFwiQXVkaW8gaW5wdXQgZGV2aWNlIGRvZXNuJ3Qgc3VwcG9ydCB0aGUgdmFsdWUgcGFzc2VkIGZvciBjb25zdHJhaW50ICdcIiArIGVycm9yLmNvbnN0cmFpbnQgKyBcIidcIjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JDYWxsYmFjayhuZXcgT3BlblZpZHVFcnJvcihlcnJvck5hbWUsIGVycm9yTWVzc2FnZSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdWNjZXNzQ2FsbGJhY2sobWVkaWFTdHJlYW0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNsZWFyUGVybWlzc2lvbkRpYWxvZ1RpbWVyKHN0YXJ0VGltZSwgdGltZUZvckRpYWxvZ0V2ZW50KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGVycm9yTmFtZSwgZXJyb3JNZXNzYWdlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzd2l0Y2ggKGVycm9yLm5hbWUudG9Mb3dlckNhc2UoKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAnbm90Zm91bmRlcnJvcic6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmF2aWdhdG9yLm1lZGlhRGV2aWNlcy5nZXRVc2VyTWVkaWEoe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhdWRpbzogZmFsc2UsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZpZGVvOiBjb25zdHJhaW50cy52aWRlb1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC50aGVuKG1lZGlhU3RyZWFtID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1lZGlhU3RyZWFtLmdldFZpZGVvVHJhY2tzKCkuZm9yRWFjaCgodHJhY2spID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cmFjay5zdG9wKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yTmFtZSA9IE9wZW5WaWR1RXJyb3JOYW1lLklOUFVUX0FVRElPX0RFVklDRV9OT1RfRk9VTkQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck1lc3NhZ2UgPSBlcnJvci50b1N0cmluZygpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JDYWxsYmFjayhuZXcgT3BlblZpZHVFcnJvcihlcnJvck5hbWUsIGVycm9yTWVzc2FnZSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KS5jYXRjaChlID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yTmFtZSA9IE9wZW5WaWR1RXJyb3JOYW1lLklOUFVUX1ZJREVPX0RFVklDRV9OT1RfRk9VTkQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck1lc3NhZ2UgPSBlcnJvci50b1N0cmluZygpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JDYWxsYmFjayhuZXcgT3BlblZpZHVFcnJvcihlcnJvck5hbWUsIGVycm9yTWVzc2FnZSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJ25vdGFsbG93ZWRlcnJvcic6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JOYW1lID0gdGhpcy5zdHJlYW0uaXNTZW5kU2NyZWVuKCkgPyBPcGVuVmlkdUVycm9yTmFtZS5TQ1JFRU5fQ0FQVFVSRV9ERU5JRUQgOiBPcGVuVmlkdUVycm9yTmFtZS5ERVZJQ0VfQUNDRVNTX0RFTklFRDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck1lc3NhZ2UgPSBlcnJvci50b1N0cmluZygpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yQ2FsbGJhY2sobmV3IE9wZW5WaWR1RXJyb3IoZXJyb3JOYW1lLCBlcnJvck1lc3NhZ2UpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJ292ZXJjb25zdHJhaW5lZGVycm9yJzpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYXZpZ2F0b3IubWVkaWFEZXZpY2VzLmdldFVzZXJNZWRpYSh7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGF1ZGlvOiBmYWxzZSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmlkZW86IGNvbnN0cmFpbnRzLnZpZGVvXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLnRoZW4obWVkaWFTdHJlYW0gPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWVkaWFTdHJlYW0uZ2V0VmlkZW9UcmFja3MoKS5mb3JFYWNoKCh0cmFjaykgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRyYWNrLnN0b3AoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yLmNvbnN0cmFpbnQudG9Mb3dlckNhc2UoKSA9PT0gJ2RldmljZWlkJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yTmFtZSA9IE9wZW5WaWR1RXJyb3JOYW1lLklOUFVUX0FVRElPX0RFVklDRV9OT1RfRk9VTkQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JNZXNzYWdlID0gXCJBdWRpbyBpbnB1dCBkZXZpY2Ugd2l0aCBkZXZpY2VJZCAnXCIgKyAoPENvbnN0cmFpbkRPTVN0cmluZ1BhcmFtZXRlcnM+KDxNZWRpYVRyYWNrQ29uc3RyYWludHM+Y29uc3RyYWludHMuYXVkaW8pLmRldmljZUlkISEpLmV4YWN0ICsgXCInIG5vdCBmb3VuZFwiO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck5hbWUgPSBPcGVuVmlkdUVycm9yTmFtZS5QVUJMSVNIRVJfUFJPUEVSVElFU19FUlJPUjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck1lc3NhZ2UgPSBcIkF1ZGlvIGlucHV0IGRldmljZSBkb2Vzbid0IHN1cHBvcnQgdGhlIHZhbHVlIHBhc3NlZCBmb3IgY29uc3RyYWludCAnXCIgKyBlcnJvci5jb25zdHJhaW50ICsgXCInXCI7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvckNhbGxiYWNrKG5ldyBPcGVuVmlkdUVycm9yKGVycm9yTmFtZSwgZXJyb3JNZXNzYWdlKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pLmNhdGNoKGUgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yLmNvbnN0cmFpbnQudG9Mb3dlckNhc2UoKSA9PT0gJ2RldmljZWlkJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yTmFtZSA9IE9wZW5WaWR1RXJyb3JOYW1lLklOUFVUX1ZJREVPX0RFVklDRV9OT1RfRk9VTkQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JNZXNzYWdlID0gXCJWaWRlbyBpbnB1dCBkZXZpY2Ugd2l0aCBkZXZpY2VJZCAnXCIgKyAoPENvbnN0cmFpbkRPTVN0cmluZ1BhcmFtZXRlcnM+KDxNZWRpYVRyYWNrQ29uc3RyYWludHM+Y29uc3RyYWludHMudmlkZW8pLmRldmljZUlkISEpLmV4YWN0ICsgXCInIG5vdCBmb3VuZFwiO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck5hbWUgPSBPcGVuVmlkdUVycm9yTmFtZS5QVUJMSVNIRVJfUFJPUEVSVElFU19FUlJPUjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck1lc3NhZ2UgPSBcIlZpZGVvIGlucHV0IGRldmljZSBkb2Vzbid0IHN1cHBvcnQgdGhlIHZhbHVlIHBhc3NlZCBmb3IgY29uc3RyYWludCAnXCIgKyBlcnJvci5jb25zdHJhaW50ICsgXCInXCI7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvckNhbGxiYWNrKG5ldyBPcGVuVmlkdUVycm9yKGVycm9yTmFtZSwgZXJyb3JNZXNzYWdlKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZWplY3QobmV3IE9wZW5WaWR1RXJyb3IoT3BlblZpZHVFcnJvck5hbWUuTk9fSU5QVVRfU09VUkNFX1NFVCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBcIlByb3BlcnRpZXMgJ2F1ZGlvU291cmNlJyBhbmQgJ3ZpZGVvU291cmNlJyBjYW5ub3QgYmUgc2V0IHRvIGZhbHNlIG9yIG51bGwgYXQgdGhlIHNhbWUgdGltZSB3aGVuIGNhbGxpbmcgJ09wZW5WaWR1LmluaXRQdWJsaXNoZXInXCIpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgLmNhdGNoKChlcnJvcjogT3BlblZpZHVFcnJvcikgPT4ge1xuICAgICAgICAgICAgICAgICAgICBlcnJvckNhbGxiYWNrKGVycm9yKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHVwZGF0ZVNlc3Npb24oc2Vzc2lvbjogU2Vzc2lvbik6IHZvaWQge1xuICAgICAgICB0aGlzLnNlc3Npb24gPSBzZXNzaW9uO1xuICAgICAgICB0aGlzLnN0cmVhbS5zZXNzaW9uID0gc2Vzc2lvbjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgcmVlc3RhYmxpc2hTdHJlYW1QbGF5aW5nRXZlbnQoKSB7XG4gICAgICAgIGlmICh0aGlzLmVlLmdldExpc3RlbmVycygnc3RyZWFtUGxheWluZycpLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgIHRoaXMuYWRkUGxheUV2ZW50VG9GaXJzdFZpZGVvKCk7XG4gICAgICAgIH1cbiAgICB9XG5cblxuICAgIC8qIFByaXZhdGUgbWV0aG9kcyAqL1xuXG4gICAgcHJpdmF0ZSBzZXRQZXJtaXNzaW9uRGlhbG9nVGltZXIod2FpdFRpbWU6IG51bWJlcik6IHZvaWQge1xuICAgICAgICB0aGlzLnBlcm1pc3Npb25EaWFsb2dUaW1lb3V0ID0gc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgICAgICB0aGlzLmVtaXRFdmVudCgnYWNjZXNzRGlhbG9nT3BlbmVkJywgW10pO1xuICAgICAgICB9LCB3YWl0VGltZSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBjbGVhclBlcm1pc3Npb25EaWFsb2dUaW1lcihzdGFydFRpbWU6IG51bWJlciwgd2FpdFRpbWU6IG51bWJlcik6IHZvaWQge1xuICAgICAgICBjbGVhclRpbWVvdXQodGhpcy5wZXJtaXNzaW9uRGlhbG9nVGltZW91dCk7XG4gICAgICAgIGlmICgoRGF0ZS5ub3coKSAtIHN0YXJ0VGltZSkgPiB3YWl0VGltZSkge1xuICAgICAgICAgICAgLy8gUGVybWlzc2lvbiBkaWFsb2cgd2FzIHNob3duIGFuZCBub3cgaXMgY2xvc2VkXG4gICAgICAgICAgICB0aGlzLmVtaXRFdmVudCgnYWNjZXNzRGlhbG9nQ2xvc2VkJywgW10pO1xuICAgICAgICB9XG4gICAgfVxuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBDb25uZWN0aW9uIH0gZnJvbSAnLi9Db25uZWN0aW9uJztcbmltcG9ydCB7IE9wZW5WaWR1IH0gZnJvbSAnLi9PcGVuVmlkdSc7XG5pbXBvcnQgeyBQdWJsaXNoZXIgfSBmcm9tICcuL1B1Ymxpc2hlcic7XG5pbXBvcnQgeyBTdHJlYW0gfSBmcm9tICcuL1N0cmVhbSc7XG5pbXBvcnQgeyBTdHJlYW1NYW5hZ2VyIH0gZnJvbSAnLi9TdHJlYW1NYW5hZ2VyJztcbmltcG9ydCB7IFN1YnNjcmliZXIgfSBmcm9tICcuL1N1YnNjcmliZXInO1xuaW1wb3J0IHsgQ2FwYWJpbGl0aWVzIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9JbnRlcmZhY2VzL1B1YmxpYy9DYXBhYmlsaXRpZXMnO1xuaW1wb3J0IHsgRXZlbnREaXNwYXRjaGVyIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9JbnRlcmZhY2VzL1B1YmxpYy9FdmVudERpc3BhdGNoZXInO1xuaW1wb3J0IHsgU2lnbmFsT3B0aW9ucyB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvSW50ZXJmYWNlcy9QdWJsaWMvU2lnbmFsT3B0aW9ucyc7XG5pbXBvcnQgeyBTdWJzY3JpYmVyUHJvcGVydGllcyB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvSW50ZXJmYWNlcy9QdWJsaWMvU3Vic2NyaWJlclByb3BlcnRpZXMnO1xuaW1wb3J0IHsgQ29ubmVjdGlvbk9wdGlvbnMgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHJpdmF0ZS9Db25uZWN0aW9uT3B0aW9ucyc7XG5pbXBvcnQgeyBPYmpNYXAgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHJpdmF0ZS9PYmpNYXAnO1xuaW1wb3J0IHsgU2Vzc2lvbk9wdGlvbnMgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHJpdmF0ZS9TZXNzaW9uT3B0aW9ucyc7XG5pbXBvcnQgeyBDb25uZWN0aW9uRXZlbnQgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0V2ZW50cy9Db25uZWN0aW9uRXZlbnQnO1xuaW1wb3J0IHsgUHVibGlzaGVyU3BlYWtpbmdFdmVudCB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1B1Ymxpc2hlclNwZWFraW5nRXZlbnQnO1xuaW1wb3J0IHsgUmVjb3JkaW5nRXZlbnQgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0V2ZW50cy9SZWNvcmRpbmdFdmVudCc7XG5pbXBvcnQgeyBTZXNzaW9uRGlzY29ubmVjdGVkRXZlbnQgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0V2ZW50cy9TZXNzaW9uRGlzY29ubmVjdGVkRXZlbnQnO1xuaW1wb3J0IHsgU2lnbmFsRXZlbnQgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0V2ZW50cy9TaWduYWxFdmVudCc7XG5pbXBvcnQgeyBTdHJlYW1FdmVudCB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1N0cmVhbUV2ZW50JztcbmltcG9ydCB7IFN0cmVhbVByb3BlcnR5Q2hhbmdlZEV2ZW50IH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvU3RyZWFtUHJvcGVydHlDaGFuZ2VkRXZlbnQnO1xuaW1wb3J0IHsgT3BlblZpZHVFcnJvciwgT3BlblZpZHVFcnJvck5hbWUgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0VudW1zL09wZW5WaWR1RXJyb3InO1xuaW1wb3J0IHsgVmlkZW9JbnNlcnRNb2RlIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FbnVtcy9WaWRlb0luc2VydE1vZGUnO1xuXG5pbXBvcnQgcGxhdGZvcm0gPSByZXF1aXJlKCdwbGF0Zm9ybScpO1xuaW1wb3J0IEV2ZW50RW1pdHRlciA9IHJlcXVpcmUoJ3dvbGZ5ODctZXZlbnRlbWl0dGVyJyk7XG5cblxuLyoqXG4gKiBSZXByZXNlbnRzIGEgdmlkZW8gY2FsbC4gSXQgY2FuIGFsc28gYmUgc2VlbiBhcyBhIHZpZGVvY29uZmVyZW5jZSByb29tIHdoZXJlIG11bHRpcGxlIHVzZXJzIGNhbiBjb25uZWN0LlxuICogUGFydGljaXBhbnRzIHdobyBwdWJsaXNoIHRoZWlyIHZpZGVvcyB0byBhIHNlc3Npb24gY2FuIGJlIHNlZW4gYnkgdGhlIHJlc3Qgb2YgdXNlcnMgY29ubmVjdGVkIHRvIHRoYXQgc3BlY2lmaWMgc2Vzc2lvbi5cbiAqIEluaXRpYWxpemVkIHdpdGggW1tPcGVuVmlkdS5pbml0U2Vzc2lvbl1dIG1ldGhvZFxuICovXG5leHBvcnQgY2xhc3MgU2Vzc2lvbiBpbXBsZW1lbnRzIEV2ZW50RGlzcGF0Y2hlciB7XG5cbiAgICAvKipcbiAgICAgKiBMb2NhbCBjb25uZWN0aW9uIHRvIHRoZSBTZXNzaW9uLiBUaGlzIG9iamVjdCBpcyBkZWZpbmVkIG9ubHkgYWZ0ZXIgW1tTZXNzaW9uLmNvbm5lY3RdXSBoYXMgYmVlbiBzdWNjZXNzZnVsbHkgZXhlY3V0ZWQsIGFuZCBjYW4gYmUgcmV0cmlldmVkIHN1YnNjcmliaW5nIHRvIGBjb25uZWN0aW9uQ3JlYXRlZGAgZXZlbnRcbiAgICAgKi9cbiAgICBjb25uZWN0aW9uOiBDb25uZWN0aW9uO1xuXG4gICAgLyoqXG4gICAgICogVW5pcXVlIGlkZW50aWZpZXIgb2YgdGhlIFNlc3Npb25cbiAgICAgKi9cbiAgICBzZXNzaW9uSWQ6IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIENvbGxlY3Rpb24gb2YgYWxsIFN0cmVhbU1hbmFnZXJzIG9mIHRoaXMgU2Vzc2lvbiAoW1tQdWJsaXNoZXJdXSBhbmQgW1tTdWJzY3JpYmVyXV0pXG4gICAgICovXG4gICAgc3RyZWFtTWFuYWdlcnM6IFN0cmVhbU1hbmFnZXJbXSA9IFtdO1xuXG4gICAgLyoqXG4gICAgICogT2JqZWN0IGRlZmluaW5nIHRoZSBtZXRob2RzIHRoYXQgdGhlIGNsaWVudCBpcyBhYmxlIHRvIGNhbGwuIFRoZXNlIGFyZSBkZWZpbmVkIGJ5IHRoZSByb2xlIG9mIHRoZSB0b2tlbiB1c2VkIHRvIGNvbm5lY3QgdG8gdGhlIFNlc3Npb24uXG4gICAgICogVGhpcyBvYmplY3QgaXMgb25seSBkZWZpbmVkIGFmdGVyIFtbU2Vzc2lvbi5jb25uZWN0XV0gaGFzIGJlZW4gc3VjY2Vzc2Z1bGx5IHJlc29sdmVkXG4gICAgICovXG4gICAgY2FwYWJpbGl0aWVzOiBDYXBhYmlsaXRpZXM7XG5cbiAgICAvLyBUaGlzIG1hcCBpcyBvbmx5IHVzZWQgdG8gYXZvaWQgcmFjZSBjb25kaXRpb24gYmV0d2VlbiAnam9pblJvb20nIHJlc3BvbnNlIGFuZCAnb25QYXJ0aWNpcGFudFB1Ymxpc2hlZCcgbm90aWZpY2F0aW9uXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHJlbW90ZVN0cmVhbXNDcmVhdGVkOiBPYmpNYXA8Ym9vbGVhbj4gPSB7fTtcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICByZW1vdGVDb25uZWN0aW9uczogT2JqTWFwPENvbm5lY3Rpb24+ID0ge307XG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIG9wZW52aWR1OiBPcGVuVmlkdTtcbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgb3B0aW9uczogU2Vzc2lvbk9wdGlvbnM7XG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHNwZWFraW5nRXZlbnRzRW5hYmxlZCA9IGZhbHNlO1xuXG4gICAgcHJpdmF0ZSBlZSA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3RvcihvcGVudmlkdTogT3BlblZpZHUpIHtcbiAgICAgICAgdGhpcy5vcGVudmlkdSA9IG9wZW52aWR1O1xuICAgIH1cblxuICAgIGNvbm5lY3QodG9rZW46IHN0cmluZyk6IFByb21pc2U8YW55PjtcbiAgICBjb25uZWN0KHRva2VuOiBzdHJpbmcsIG1ldGFkYXRhOiBhbnkpOiBQcm9taXNlPGFueT47XG5cbiAgICAvKipcbiAgICAgKiBDb25uZWN0cyB0byB0aGUgc2Vzc2lvbiB1c2luZyBgdG9rZW5gLiBQYXJhbWV0ZXIgYG1ldGFkYXRhYCBhbGxvd3MgeW91IHRvIHBhc3MgZXh0cmEgZGF0YSB0byBzaGFyZSB3aXRoIG90aGVyIHVzZXJzIHdoZW5cbiAgICAgKiB0aGV5IHJlY2VpdmUgYHN0cmVhbUNyZWF0ZWRgIGV2ZW50LiBUaGUgc3RydWN0dXJlIG9mIGBtZXRhZGF0YWAgc3RyaW5nIGlzIHVwIHRvIHlvdSAobWF5YmUgc29tZSBzdGFuZGFyaXplZCBmb3JtYXRcbiAgICAgKiBhcyBKU09OIG9yIFhNTCBpcyBhIGdvb2QgaWRlYSksIHRoZSBvbmx5IHJlc3RyaWN0aW9uIGlzIGEgbWF4aW11bSBsZW5ndGggb2YgMTAwMDAgY2hhcnMuXG4gICAgICpcbiAgICAgKiBUaGlzIG1ldGFkYXRhIGlzIG5vdCBjb25zaWRlcmVkIHNlY3VyZSwgYXMgaXQgaXMgZ2VuZXJhdGVkIGluIHRoZSBjbGllbnQgc2lkZS4gVG8gcGFzcyBzZWN1cml6ZWQgZGF0YSwgYWRkIGl0IGFzIGEgcGFyYW1ldGVyIGluIHRoZVxuICAgICAqIHRva2VuIGdlbmVyYXRpb24gb3BlcmF0aW9uICh0aHJvdWdoIHRoZSBBUEkgUkVTVCwgb3BlbnZpZHUtamF2YS1jbGllbnQgb3Igb3BlbnZpZHUtbm9kZS1jbGllbnQpLlxuICAgICAqXG4gICAgICogT25seSBhZnRlciB0aGUgcmV0dXJuZWQgUHJvbWlzZSBpcyBzdWNjZXNzZnVsbHkgcmVzb2x2ZWQgW1tTZXNzaW9uLmNvbm5lY3Rpb25dXSBvYmplY3Qgd2lsbCBiZSBhdmFpbGFibGUgYW5kIHByb3Blcmx5IGRlZmluZWQuXG4gICAgICpcbiAgICAgKiAjIyMjIEV2ZW50cyBkaXNwYXRjaGVkXG4gICAgICpcbiAgICAgKiBUaGUgW1tTZXNzaW9uXV0gb2JqZWN0IG9mIHRoZSBsb2NhbCBwYXJ0aWNpcGFudCB3aWxsIGZpcnN0IGRpc3BhdGNoIG9uZSBvciBtb3JlIGBjb25uZWN0aW9uQ3JlYXRlZGAgZXZlbnRzIHVwb24gc3VjY2Vzc2Z1bCB0ZXJtaW5hdGlvbiBvZiB0aGlzIG1ldGhvZDpcbiAgICAgKiAtIEZpcnN0IG9uZSBmb3IgeW91ciBvd24gbG9jYWwgQ29ubmVjdGlvbiBvYmplY3QsIHNvIHlvdSBjYW4gcmV0cmlldmUgW1tTZXNzaW9uLmNvbm5lY3Rpb25dXSBwcm9wZXJ0eS5cbiAgICAgKiAtIFRoZW4gb25lIGZvciBlYWNoIHJlbW90ZSBDb25uZWN0aW9uIHByZXZpb3VzbHkgY29ubmVjdGVkIHRvIHRoZSBTZXNzaW9uLCBpZiBhbnkuIEFueSBvdGhlciByZW1vdGUgdXNlciBjb25uZWN0aW5nIHRvIHRoZSBTZXNzaW9uIGFmdGVyIHlvdSBoYXZlXG4gICAgICogc3VjY2Vzc2Z1bGx5IGNvbm5lY3RlZCB3aWxsIGFsc28gZGlzcGF0Y2ggYSBgY29ubmVjdGlvbkNyZWF0ZWRgIGV2ZW50IHdoZW4gdGhleSBkbyBzby5cbiAgICAgKlxuICAgICAqIFRoZSBbW1Nlc3Npb25dXSBvYmplY3Qgb2YgdGhlIGxvY2FsIHBhcnRpY2lwYW50IHdpbGwgYWxzbyBkaXNwYXRjaCBhIGBzdHJlYW1DcmVhdGVkYCBldmVudCBmb3IgZWFjaCByZW1vdGUgYWN0aXZlIFtbUHVibGlzaGVyXV0gdGhhdCB3YXMgYWxyZWFkeSBzdHJlYW1pbmdcbiAgICAgKiB3aGVuIGNvbm5lY3RpbmcsIGp1c3QgYWZ0ZXIgZGlzcGF0Y2hpbmcgYWxsIHJlbW90ZSBgY29ubmVjdGlvbkNyZWF0ZWRgIGV2ZW50cy5cbiAgICAgKlxuICAgICAqIFRoZSBbW1Nlc3Npb25dXSBvYmplY3Qgb2YgZXZlcnkgb3RoZXIgcGFydGljaXBhbnQgY29ubmVjdGVkIHRvIHRoZSBzZXNzaW9uIHdpbGwgZGlzcGF0Y2ggYSBgY29ubmVjdGlvbkNyZWF0ZWRgIGV2ZW50LlxuICAgICAqXG4gICAgICogU2VlIFtbQ29ubmVjdGlvbkV2ZW50XV0gYW5kIFtbU3RyZWFtRXZlbnRdXSB0byBsZWFybiBtb3JlLlxuICAgICAqXG4gICAgICogQHJldHVybnMgQSBQcm9taXNlIHRvIHdoaWNoIHlvdSBtdXN0IHN1YnNjcmliZSB0aGF0IGlzIHJlc29sdmVkIGlmIHRoZSB0aGUgY29ubmVjdGlvbiB0byB0aGUgU2Vzc2lvbiB3YXMgc3VjY2Vzc2Z1bCBhbmQgcmVqZWN0ZWQgd2l0aCBhbiBFcnJvciBvYmplY3QgaWYgbm90XG4gICAgICpcbiAgICAgKi9cbiAgICBjb25uZWN0KHRva2VuOiBzdHJpbmcsIG1ldGFkYXRhPzogYW55KTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcblxuICAgICAgICAgICAgdGhpcy5wcm9jZXNzVG9rZW4odG9rZW4pO1xuXG4gICAgICAgICAgICBpZiAodGhpcy5vcGVudmlkdS5jaGVja1N5c3RlbVJlcXVpcmVtZW50cygpKSB7XG4gICAgICAgICAgICAgICAgLy8gRWFybHkgY29uZmlndXJhdGlvbiB0byBkZWFjdGl2YXRlIGF1dG9tYXRpYyBzdWJzY3JpcHRpb24gdG8gc3RyZWFtc1xuICAgICAgICAgICAgICAgIHRoaXMub3B0aW9ucyA9IHtcbiAgICAgICAgICAgICAgICAgICAgc2Vzc2lvbklkOiB0aGlzLnNlc3Npb25JZCxcbiAgICAgICAgICAgICAgICAgICAgcGFydGljaXBhbnRJZDogdG9rZW4sXG4gICAgICAgICAgICAgICAgICAgIG1ldGFkYXRhOiAhIW1ldGFkYXRhID8gdGhpcy5zdHJpbmdDbGllbnRNZXRhZGF0YShtZXRhZGF0YSkgOiAnJ1xuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgdGhpcy5jb25uZWN0QXV4KHRva2VuKS50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgICAgICAgIH0pLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmVqZWN0KG5ldyBPcGVuVmlkdUVycm9yKE9wZW5WaWR1RXJyb3JOYW1lLkJST1dTRVJfTk9UX1NVUFBPUlRFRCwgJ0Jyb3dzZXIgJyArIHBsYXRmb3JtLm5hbWUgKyAnICcgKyBwbGF0Zm9ybS52ZXJzaW9uICsgJyBpcyBub3Qgc3VwcG9ydGVkIGluIE9wZW5WaWR1JykpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBMZWF2ZXMgdGhlIHNlc3Npb24sIGRlc3Ryb3lpbmcgYWxsIHN0cmVhbXMgYW5kIGRlbGV0aW5nIHRoZSB1c2VyIGFzIGEgcGFydGljaXBhbnQuXG4gICAgICpcbiAgICAgKiAjIyMjIEV2ZW50cyBkaXNwYXRjaGVkXG4gICAgICpcbiAgICAgKiBUaGUgW1tTZXNzaW9uXV0gb2JqZWN0IG9mIHRoZSBsb2NhbCBwYXJ0aWNpcGFudCB3aWxsIGRpc3BhdGNoIGEgYHNlc3Npb25EaXNjb25uZWN0ZWRgIGV2ZW50LlxuICAgICAqIFRoaXMgZXZlbnQgd2lsbCBhdXRvbWF0aWNhbGx5IHVuc3Vic2NyaWJlIHRoZSBsZWF2aW5nIHBhcnRpY2lwYW50IGZyb20gZXZlcnkgU3Vic2NyaWJlciBvYmplY3Qgb2YgdGhlIHNlc3Npb24gKHRoaXMgaW5jbHVkZXMgY2xvc2luZyB0aGUgV2ViUlRDUGVlciBjb25uZWN0aW9uIGFuZCBkaXNwb3NpbmcgYWxsIE1lZGlhU3RyZWFtVHJhY2tzKVxuICAgICAqIGFuZCBhbHNvIGRlbGV0ZXMgYW55IEhUTUwgdmlkZW8gZWxlbWVudCBhc3NvY2lhdGVkIHRvIGVhY2ggU3Vic2NyaWJlciAob25seSB0aG9zZSBbY3JlYXRlZCBieSBPcGVuVmlkdSBCcm93c2VyXSgvZG9jcy9ob3ctZG8taS9tYW5hZ2UtdmlkZW9zLyNsZXQtb3BlbnZpZHUtdGFrZS1jYXJlLW9mLXRoZS12aWRlby1wbGF5ZXJzKSkuXG4gICAgICogRm9yIGV2ZXJ5IHZpZGVvIHJlbW92ZWQsIGVhY2ggU3Vic2NyaWJlciBvYmplY3Qgd2lsbCBkaXNwYXRjaCBhIGB2aWRlb0VsZW1lbnREZXN0cm95ZWRgIGV2ZW50LlxuICAgICAqIENhbGwgYGV2ZW50LnByZXZlbnREZWZhdWx0KClgIHVwb24gZXZlbnQgYHNlc3Npb25EaXNjb25uZWN0ZWRgIHRvIGF2b2lkIHRoaXMgYmVoYXZpb3IgYW5kIHRha2UgY2FyZSBvZiBkaXNwb3NpbmcgYW5kIGNsZWFuaW5nIGFsbCB0aGUgU3Vic2NyaWJlciBvYmplY3RzIHlvdXJzZWxmLlxuICAgICAqIFNlZSBbW1Nlc3Npb25EaXNjb25uZWN0ZWRFdmVudF1dIGFuZCBbW1ZpZGVvRWxlbWVudEV2ZW50XV0gdG8gbGVhcm4gbW9yZSB0byBsZWFybiBtb3JlLlxuICAgICAqXG4gICAgICogVGhlIFtbUHVibGlzaGVyXV0gb2JqZWN0IG9mIHRoZSBsb2NhbCBwYXJ0aWNpcGFudCB3aWxsIGRpc3BhdGNoIGEgYHN0cmVhbURlc3Ryb3llZGAgZXZlbnQgaWYgdGhlcmUgaXMgYSBbW1B1Ymxpc2hlcl1dIG9iamVjdCBwdWJsaXNoaW5nIHRvIHRoZSBzZXNzaW9uLlxuICAgICAqIFRoaXMgZXZlbnQgd2lsbCBhdXRvbWF0aWNhbGx5IHN0b3AgYWxsIG1lZGlhIHRyYWNrcyBhbmQgZGVsZXRlIGFueSBIVE1MIHZpZGVvIGVsZW1lbnQgYXNzb2NpYXRlZCB0byBpdCAob25seSB0aG9zZSBbY3JlYXRlZCBieSBPcGVuVmlkdSBCcm93c2VyXSgvZG9jcy9ob3ctZG8taS9tYW5hZ2UtdmlkZW9zLyNsZXQtb3BlbnZpZHUtdGFrZS1jYXJlLW9mLXRoZS12aWRlby1wbGF5ZXJzKSkuXG4gICAgICogRm9yIGV2ZXJ5IHZpZGVvIHJlbW92ZWQsIHRoZSBQdWJsaXNoZXIgb2JqZWN0IHdpbGwgZGlzcGF0Y2ggYSBgdmlkZW9FbGVtZW50RGVzdHJveWVkYCBldmVudC5cbiAgICAgKiBDYWxsIGBldmVudC5wcmV2ZW50RGVmYXVsdCgpYCB1cG9uIGV2ZW50IGBzdHJlYW1EZXN0cm95ZWRgIGlmIHlvdSB3YW50IHRvIGNsZWFuIHRoZSBQdWJsaXNoZXIgb2JqZWN0IG9uIHlvdXIgb3duIG9yIHJlLXB1Ymxpc2ggaXQgaW4gYSBkaWZmZXJlbnQgU2Vzc2lvbiAodG8gZG8gc28gaXQgaXMgYSBtYW5kYXRvcnkgcmVxdWlyZW1lbnQgdG8gY2FsbCBgU2Vzc2lvbi51bnB1Ymxpc2goKWBcbiAgICAgKiBvci9hbmQgYFNlc3Npb24uZGlzY29ubmVjdCgpYCBpbiB0aGUgcHJldmlvdXMgc2Vzc2lvbikuIFNlZSBbW1N0cmVhbUV2ZW50XV0gYW5kIFtbVmlkZW9FbGVtZW50RXZlbnRdXSB0byBsZWFybiBtb3JlLlxuICAgICAqXG4gICAgICogVGhlIFtbU2Vzc2lvbl1dIG9iamVjdCBvZiBldmVyeSBvdGhlciBwYXJ0aWNpcGFudCBjb25uZWN0ZWQgdG8gdGhlIHNlc3Npb24gd2lsbCBkaXNwYXRjaCBhIGBzdHJlYW1EZXN0cm95ZWRgIGV2ZW50IGlmIHRoZSBkaXNjb25uZWN0ZWQgcGFydGljaXBhbnQgd2FzIHB1Ymxpc2hpbmcuXG4gICAgICogVGhpcyBldmVudCB3aWxsIGF1dG9tYXRpY2FsbHkgdW5zdWJzY3JpYmUgdGhlIFN1YnNjcmliZXIgb2JqZWN0IGZyb20gdGhlIHNlc3Npb24gKHRoaXMgaW5jbHVkZXMgY2xvc2luZyB0aGUgV2ViUlRDUGVlciBjb25uZWN0aW9uIGFuZCBkaXNwb3NpbmcgYWxsIE1lZGlhU3RyZWFtVHJhY2tzKVxuICAgICAqIGFuZCBhbHNvIGRlbGV0ZXMgYW55IEhUTUwgdmlkZW8gZWxlbWVudCBhc3NvY2lhdGVkIHRvIHRoYXQgU3Vic2NyaWJlciAob25seSB0aG9zZSBbY3JlYXRlZCBieSBPcGVuVmlkdSBCcm93c2VyXSgvZG9jcy9ob3ctZG8taS9tYW5hZ2UtdmlkZW9zLyNsZXQtb3BlbnZpZHUtdGFrZS1jYXJlLW9mLXRoZS12aWRlby1wbGF5ZXJzKSkuXG4gICAgICogRm9yIGV2ZXJ5IHZpZGVvIHJlbW92ZWQsIHRoZSBTdWJzY3JpYmVyIG9iamVjdCB3aWxsIGRpc3BhdGNoIGEgYHZpZGVvRWxlbWVudERlc3Ryb3llZGAgZXZlbnQuXG4gICAgICogQ2FsbCBgZXZlbnQucHJldmVudERlZmF1bHQoKWAgdXBvbiBldmVudCBgc3RyZWFtRGVzdHJveWVkYCB0byBhdm9pZCB0aGlzIGRlZmF1bHQgYmVoYXZpb3IgYW5kIHRha2UgY2FyZSBvZiBkaXNwb3NpbmcgYW5kIGNsZWFuaW5nIHRoZSBTdWJzY3JpYmVyIG9iamVjdCB5b3Vyc2VsZi5cbiAgICAgKiBTZWUgW1tTdHJlYW1FdmVudF1dIGFuZCBbW1ZpZGVvRWxlbWVudEV2ZW50XV0gdG8gbGVhcm4gbW9yZS5cbiAgICAgKlxuICAgICAqIFRoZSBbW1Nlc3Npb25dXSBvYmplY3Qgb2YgZXZlcnkgb3RoZXIgcGFydGljaXBhbnQgY29ubmVjdGVkIHRvIHRoZSBzZXNzaW9uIHdpbGwgZGlzcGF0Y2ggYSBgY29ubmVjdGlvbkRlc3Ryb3llZGAgZXZlbnQgaW4gYW55IGNhc2UuIFNlZSBbW0Nvbm5lY3Rpb25FdmVudF1dIHRvIGxlYXJuIG1vcmUuXG4gICAgICovXG4gICAgZGlzY29ubmVjdCgpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5sZWF2ZShmYWxzZSwgJ2Rpc2Nvbm5lY3QnKTtcbiAgICB9XG5cbiAgICBzdWJzY3JpYmUoc3RyZWFtOiBTdHJlYW0sIHRhcmdldEVsZW1lbnQ6IHN0cmluZyB8IEhUTUxFbGVtZW50KTogU3Vic2NyaWJlcjtcbiAgICBzdWJzY3JpYmUoc3RyZWFtOiBTdHJlYW0sIHRhcmdldEVsZW1lbnQ6IHN0cmluZyB8IEhUTUxFbGVtZW50LCBwcm9wZXJ0aWVzOiBTdWJzY3JpYmVyUHJvcGVydGllcyk6IFN1YnNjcmliZXI7XG4gICAgc3Vic2NyaWJlKHN0cmVhbTogU3RyZWFtLCB0YXJnZXRFbGVtZW50OiBzdHJpbmcgfCBIVE1MRWxlbWVudCwgY29tcGxldGlvbkhhbmRsZXI6IChlcnJvcjogRXJyb3IgfCB1bmRlZmluZWQpID0+IHZvaWQpOiBTdWJzY3JpYmVyO1xuICAgIHN1YnNjcmliZShzdHJlYW06IFN0cmVhbSwgdGFyZ2V0RWxlbWVudDogc3RyaW5nIHwgSFRNTEVsZW1lbnQsIHByb3BlcnRpZXM6IFN1YnNjcmliZXJQcm9wZXJ0aWVzLCBjb21wbGV0aW9uSGFuZGxlcjogKGVycm9yOiBFcnJvciB8IHVuZGVmaW5lZCkgPT4gdm9pZCk6IFN1YnNjcmliZXI7XG5cbiAgICAvKipcbiAgICAgKiBTdWJzY3JpYmVzIHRvIGEgYHN0cmVhbWAsIGFkZGluZyBhIG5ldyBIVE1MIHZpZGVvIGVsZW1lbnQgdG8gRE9NIHdpdGggYHN1YnNjcmliZXJQcm9wZXJ0aWVzYCBzZXR0aW5ncy4gVGhpcyBtZXRob2QgaXMgdXN1YWxseSBjYWxsZWQgaW4gdGhlIGNhbGxiYWNrIG9mIGBzdHJlYW1DcmVhdGVkYCBldmVudC5cbiAgICAgKlxuICAgICAqICMjIyMgRXZlbnRzIGRpc3BhdGNoZWRcbiAgICAgKlxuICAgICAqIFRoZSBbW1N1YnNjcmliZXJdXSBvYmplY3Qgd2lsbCBkaXNwYXRjaCBhIGB2aWRlb0VsZW1lbnRDcmVhdGVkYCBldmVudCBvbmNlIHRoZSBIVE1MIHZpZGVvIGVsZW1lbnQgaGFzIGJlZW4gYWRkZWQgdG8gRE9NIChvbmx5IGlmIHlvdVxuICAgICAqIFtsZXQgT3BlblZpZHUgdGFrZSBjYXJlIG9mIHRoZSB2aWRlbyBwbGF5ZXJzXSgvZG9jcy9ob3ctZG8taS9tYW5hZ2UtdmlkZW9zLyNsZXQtb3BlbnZpZHUtdGFrZS1jYXJlLW9mLXRoZS12aWRlby1wbGF5ZXJzKSkuIFNlZSBbW1ZpZGVvRWxlbWVudEV2ZW50XV0gdG8gbGVhcm4gbW9yZS5cbiAgICAgKlxuICAgICAqIFRoZSBbW1N1YnNjcmliZXJdXSBvYmplY3Qgd2lsbCBkaXNwYXRjaCBhIGBzdHJlYW1QbGF5aW5nYCBldmVudCBvbmNlIHRoZSByZW1vdGUgc3RyZWFtIHN0YXJ0cyBwbGF5aW5nLiBTZWUgW1tTdHJlYW1NYW5hZ2VyRXZlbnRdXSB0byBsZWFybiBtb3JlLlxuICAgICAqXG4gICAgICogQHBhcmFtIHN0cmVhbSBTdHJlYW0gb2JqZWN0IHRvIHN1YnNjcmliZSB0b1xuICAgICAqIEBwYXJhbSB0YXJnZXRFbGVtZW50IEhUTUwgRE9NIGVsZW1lbnQgKG9yIGl0cyBgaWRgIGF0dHJpYnV0ZSkgaW4gd2hpY2ggdGhlIHZpZGVvIGVsZW1lbnQgb2YgdGhlIFN1YnNjcmliZXIgd2lsbCBiZSBpbnNlcnRlZCAoc2VlIFtbU3Vic2NyaWJlclByb3BlcnRpZXMuaW5zZXJ0TW9kZV1dKS4gSWYgKm51bGwqIG9yICp1bmRlZmluZWQqIG5vIGRlZmF1bHQgdmlkZW8gd2lsbCBiZSBjcmVhdGVkIGZvciB0aGlzIFN1YnNjcmliZXIuXG4gICAgICogWW91IGNhbiBhbHdheXMgY2FsbCBtZXRob2QgW1tTdWJzY3JpYmVyLmFkZFZpZGVvRWxlbWVudF1dIG9yIFtbU3Vic2NyaWJlci5jcmVhdGVWaWRlb0VsZW1lbnRdXSB0byBtYW5hZ2UgdGhlIHZpZGVvIGVsZW1lbnRzIG9uIHlvdXIgb3duIChzZWUgW01hbmFnZSB2aWRlbyBwbGF5ZXJzXSgvZG9jcy9ob3ctZG8taS9tYW5hZ2UtdmlkZW9zKSBzZWN0aW9uKVxuICAgICAqIEBwYXJhbSBjb21wbGV0aW9uSGFuZGxlciBgZXJyb3JgIHBhcmFtZXRlciBpcyBudWxsIGlmIGBzdWJzY3JpYmVgIHN1Y2NlZWRzLCBhbmQgaXMgZGVmaW5lZCBpZiBpdCBmYWlscy5cbiAgICAgKi9cbiAgICBzdWJzY3JpYmUoc3RyZWFtOiBTdHJlYW0sIHRhcmdldEVsZW1lbnQ6IHN0cmluZyB8IEhUTUxFbGVtZW50LCBwYXJhbTM/OiAoKGVycm9yOiBFcnJvciB8IHVuZGVmaW5lZCkgPT4gdm9pZCkgfCBTdWJzY3JpYmVyUHJvcGVydGllcywgcGFyYW00PzogKChlcnJvcjogRXJyb3IgfCB1bmRlZmluZWQpID0+IHZvaWQpKTogU3Vic2NyaWJlciB7XG4gICAgICAgIGxldCBwcm9wZXJ0aWVzOiBTdWJzY3JpYmVyUHJvcGVydGllcyA9IHt9O1xuICAgICAgICBpZiAoISFwYXJhbTMgJiYgdHlwZW9mIHBhcmFtMyAhPT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgcHJvcGVydGllcyA9IHtcbiAgICAgICAgICAgICAgICBpbnNlcnRNb2RlOiAodHlwZW9mIHBhcmFtMy5pbnNlcnRNb2RlICE9PSAndW5kZWZpbmVkJykgPyAoKHR5cGVvZiBwYXJhbTMuaW5zZXJ0TW9kZSA9PT0gJ3N0cmluZycpID8gVmlkZW9JbnNlcnRNb2RlW3BhcmFtMy5pbnNlcnRNb2RlXSA6IHByb3BlcnRpZXMuaW5zZXJ0TW9kZSkgOiBWaWRlb0luc2VydE1vZGUuQVBQRU5ELFxuICAgICAgICAgICAgICAgIHN1YnNjcmliZVRvQXVkaW86ICh0eXBlb2YgcGFyYW0zLnN1YnNjcmliZVRvQXVkaW8gIT09ICd1bmRlZmluZWQnKSA/IHBhcmFtMy5zdWJzY3JpYmVUb0F1ZGlvIDogdHJ1ZSxcbiAgICAgICAgICAgICAgICBzdWJzY3JpYmVUb1ZpZGVvOiAodHlwZW9mIHBhcmFtMy5zdWJzY3JpYmVUb1ZpZGVvICE9PSAndW5kZWZpbmVkJykgPyBwYXJhbTMuc3Vic2NyaWJlVG9WaWRlbyA6IHRydWVcbiAgICAgICAgICAgIH07XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBwcm9wZXJ0aWVzID0ge1xuICAgICAgICAgICAgICAgIGluc2VydE1vZGU6IFZpZGVvSW5zZXJ0TW9kZS5BUFBFTkQsXG4gICAgICAgICAgICAgICAgc3Vic2NyaWJlVG9BdWRpbzogdHJ1ZSxcbiAgICAgICAgICAgICAgICBzdWJzY3JpYmVUb1ZpZGVvOiB0cnVlXG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG5cbiAgICAgICAgbGV0IGNvbXBsZXRpb25IYW5kbGVyOiAoZXJyb3I6IEVycm9yIHwgdW5kZWZpbmVkKSA9PiB2b2lkO1xuICAgICAgICBpZiAoISFwYXJhbTMgJiYgKHR5cGVvZiBwYXJhbTMgPT09ICdmdW5jdGlvbicpKSB7XG4gICAgICAgICAgICBjb21wbGV0aW9uSGFuZGxlciA9IHBhcmFtMztcbiAgICAgICAgfSBlbHNlIGlmICghIXBhcmFtNCkge1xuICAgICAgICAgICAgY29tcGxldGlvbkhhbmRsZXIgPSBwYXJhbTQ7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zb2xlLmluZm8oJ1N1YnNjcmliaW5nIHRvICcgKyBzdHJlYW0uY29ubmVjdGlvbi5jb25uZWN0aW9uSWQpO1xuXG4gICAgICAgIHN0cmVhbS5zdWJzY3JpYmUoKVxuICAgICAgICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbygnU3Vic2NyaWJlZCBjb3JyZWN0bHkgdG8gJyArIHN0cmVhbS5jb25uZWN0aW9uLmNvbm5lY3Rpb25JZCk7XG4gICAgICAgICAgICAgICAgaWYgKGNvbXBsZXRpb25IYW5kbGVyICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgY29tcGxldGlvbkhhbmRsZXIodW5kZWZpbmVkKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICAgICAgICBpZiAoY29tcGxldGlvbkhhbmRsZXIgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICBjb21wbGV0aW9uSGFuZGxlcihlcnJvcik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIGNvbnN0IHN1YnNjcmliZXIgPSBuZXcgU3Vic2NyaWJlcihzdHJlYW0sIHRhcmdldEVsZW1lbnQsIHByb3BlcnRpZXMpO1xuICAgICAgICBpZiAoISFzdWJzY3JpYmVyLnRhcmdldEVsZW1lbnQpIHtcbiAgICAgICAgICAgIHN0cmVhbS5zdHJlYW1NYW5hZ2VyLmNyZWF0ZVZpZGVvRWxlbWVudChzdWJzY3JpYmVyLnRhcmdldEVsZW1lbnQsIDxWaWRlb0luc2VydE1vZGU+cHJvcGVydGllcy5pbnNlcnRNb2RlKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gc3Vic2NyaWJlcjtcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFByb21pc2lmaWVkIHZlcnNpb24gb2YgW1tTZXNzaW9uLnN1YnNjcmliZV1dXG4gICAgICovXG4gICAgc3Vic2NyaWJlQXN5bmMoc3RyZWFtOiBTdHJlYW0sIHRhcmdldEVsZW1lbnQ6IHN0cmluZyB8IEhUTUxFbGVtZW50KTogUHJvbWlzZTxTdWJzY3JpYmVyPjtcbiAgICBzdWJzY3JpYmVBc3luYyhzdHJlYW06IFN0cmVhbSwgdGFyZ2V0RWxlbWVudDogc3RyaW5nIHwgSFRNTEVsZW1lbnQsIHByb3BlcnRpZXM6IFN1YnNjcmliZXJQcm9wZXJ0aWVzKTogUHJvbWlzZTxTdWJzY3JpYmVyPjtcblxuICAgIHN1YnNjcmliZUFzeW5jKHN0cmVhbTogU3RyZWFtLCB0YXJnZXRFbGVtZW50OiBzdHJpbmcgfCBIVE1MRWxlbWVudCwgcHJvcGVydGllcz86IFN1YnNjcmliZXJQcm9wZXJ0aWVzKTogUHJvbWlzZTxTdWJzY3JpYmVyPiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZTxTdWJzY3JpYmVyPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG5cbiAgICAgICAgICAgIGxldCBzdWJzY3JpYmVyOiBTdWJzY3JpYmVyO1xuXG4gICAgICAgICAgICBjb25zdCBjYWxsYmFjayA9IChlcnJvcjogRXJyb3IpID0+IHtcbiAgICAgICAgICAgICAgICBpZiAoISFlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc29sdmUoc3Vic2NyaWJlcik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgaWYgKCEhcHJvcGVydGllcykge1xuICAgICAgICAgICAgICAgIHN1YnNjcmliZXIgPSB0aGlzLnN1YnNjcmliZShzdHJlYW0sIHRhcmdldEVsZW1lbnQsIHByb3BlcnRpZXMsIGNhbGxiYWNrKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgc3Vic2NyaWJlciA9IHRoaXMuc3Vic2NyaWJlKHN0cmVhbSwgdGFyZ2V0RWxlbWVudCwgY2FsbGJhY2spO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgIH0pO1xuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogVW5zdWJzY3JpYmVzIGZyb20gYHN1YnNjcmliZXJgLCBhdXRvbWF0aWNhbGx5IHJlbW92aW5nIGl0cyBhc3NvY2lhdGVkIEhUTUwgdmlkZW8gZWxlbWVudHMuXG4gICAgICpcbiAgICAgKiAjIyMjIEV2ZW50cyBkaXNwYXRjaGVkXG4gICAgICpcbiAgICAgKiBUaGUgW1tTdWJzY3JpYmVyXV0gb2JqZWN0IHdpbGwgZGlzcGF0Y2ggYSBgdmlkZW9FbGVtZW50RGVzdHJveWVkYCBldmVudCBmb3IgZWFjaCB2aWRlbyBhc3NvY2lhdGVkIHRvIGl0IHRoYXQgd2FzIHJlbW92ZWQgZnJvbSBET00uXG4gICAgICogT25seSB2aWRlb3MgW2NyZWF0ZWQgYnkgT3BlblZpZHUgQnJvd3Nlcl0oL2RvY3MvaG93LWRvLWkvbWFuYWdlLXZpZGVvcy8jbGV0LW9wZW52aWR1LXRha2UtY2FyZS1vZi10aGUtdmlkZW8tcGxheWVycykpIHdpbGwgYmUgYXV0b21hdGljYWxseSByZW1vdmVkXG4gICAgICpcbiAgICAgKiBTZWUgW1tWaWRlb0VsZW1lbnRFdmVudF1dIHRvIGxlYXJuIG1vcmVcbiAgICAgKi9cbiAgICB1bnN1YnNjcmliZShzdWJzY3JpYmVyOiBTdWJzY3JpYmVyKTogdm9pZCB7XG4gICAgICAgIGNvbnN0IGNvbm5lY3Rpb25JZCA9IHN1YnNjcmliZXIuc3RyZWFtLmNvbm5lY3Rpb24uY29ubmVjdGlvbklkO1xuXG4gICAgICAgIGNvbnNvbGUuaW5mbygnVW5zdWJzY3JpYmluZyBmcm9tICcgKyBjb25uZWN0aW9uSWQpO1xuXG4gICAgICAgIHRoaXMub3BlbnZpZHUuc2VuZFJlcXVlc3QoXG4gICAgICAgICAgICAndW5zdWJzY3JpYmVGcm9tVmlkZW8nLFxuICAgICAgICAgICAgeyBzZW5kZXI6IHN1YnNjcmliZXIuc3RyZWFtLmNvbm5lY3Rpb24uY29ubmVjdGlvbklkIH0sXG4gICAgICAgICAgICAoZXJyb3IsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ0Vycm9yIHVuc3Vic2NyaWJpbmcgZnJvbSAnICsgY29ubmVjdGlvbklkLCBlcnJvcik7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS5pbmZvKCdVbnN1YnNjcmliZWQgY29ycmVjdGx5IGZyb20gJyArIGNvbm5lY3Rpb25JZCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHN1YnNjcmliZXIuc3RyZWFtLmRpc3Bvc2VXZWJSdGNQZWVyKCk7XG4gICAgICAgICAgICAgICAgc3Vic2NyaWJlci5zdHJlYW0uZGlzcG9zZU1lZGlhU3RyZWFtKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICk7XG4gICAgICAgIHN1YnNjcmliZXIuc3RyZWFtLnN0cmVhbU1hbmFnZXIucmVtb3ZlQWxsVmlkZW9zKCk7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBQdWJsaXNoZXMgdG8gdGhlIFNlc3Npb24gdGhlIFB1Ymxpc2hlciBvYmplY3RcbiAgICAgKlxuICAgICAqICMjIyMgRXZlbnRzIGRpc3BhdGNoZWRcbiAgICAgKlxuICAgICAqIFRoZSBsb2NhbCBbW1B1Ymxpc2hlcl1dIG9iamVjdCB3aWxsIGRpc3BhdGNoIGEgYHN0cmVhbUNyZWF0ZWRgIGV2ZW50IHVwb24gc3VjY2Vzc2Z1bCB0ZXJtaW5hdGlvbiBvZiB0aGlzIG1ldGhvZC4gU2VlIFtbU3RyZWFtRXZlbnRdXSB0byBsZWFybiBtb3JlLlxuICAgICAqXG4gICAgICogVGhlIGxvY2FsIFtbUHVibGlzaGVyXV0gb2JqZWN0IHdpbGwgZGlzcGF0Y2ggYSBgc3RyZWFtUGxheWluZ2Agb25jZSB0aGUgbWVkaWEgc3RyZWFtIHN0YXJ0cyBwbGF5aW5nLiBTZWUgW1tTdHJlYW1NYW5hZ2VyRXZlbnRdXSB0byBsZWFybiBtb3JlLlxuICAgICAqXG4gICAgICogVGhlIFtbU2Vzc2lvbl1dIG9iamVjdCBvZiBldmVyeSBvdGhlciBwYXJ0aWNpcGFudCBjb25uZWN0ZWQgdG8gdGhlIHNlc3Npb24gd2lsbCBkaXNwYXRjaCBhIGBzdHJlYW1DcmVhdGVkYCBldmVudCBzbyB0aGV5IGNhbiBzdWJzY3JpYmUgdG8gaXQuIFNlZSBbW1N0cmVhbUV2ZW50XV0gdG8gbGVhcm4gbW9yZS5cbiAgICAgKlxuICAgICAqIEByZXR1cm5zIEEgUHJvbWlzZSAodG8gd2hpY2ggeW91IGNhbiBvcHRpb25hbGx5IHN1YnNjcmliZSB0bykgdGhhdCBpcyByZXNvbHZlZCBvbmx5IGFmdGVyIHRoZSBwdWJsaXNoZXIgd2FzIHN1Y2Nlc3NmdWxseSBwdWJsaXNoZWQgYW5kIHJlamVjdGVkIHdpdGggYW4gRXJyb3Igb2JqZWN0IGlmIG5vdFxuICAgICAqL1xuICAgIHB1Ymxpc2gocHVibGlzaGVyOiBQdWJsaXNoZXIpOiBQcm9taXNlPGFueT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgcHVibGlzaGVyLnNlc3Npb24gPSB0aGlzO1xuICAgICAgICAgICAgcHVibGlzaGVyLnN0cmVhbS5zZXNzaW9uID0gdGhpcztcblxuICAgICAgICAgICAgaWYgKCFwdWJsaXNoZXIuc3RyZWFtLnB1Ymxpc2hlZE9uY2UpIHtcbiAgICAgICAgICAgICAgICAvLyAnU2Vzc2lvbi51bnB1Ymxpc2goUHVibGlzaGVyKScgaGFzIE5PVCBiZWVuIGNhbGxlZFxuICAgICAgICAgICAgICAgIHRoaXMuY29ubmVjdGlvbi5hZGRTdHJlYW0ocHVibGlzaGVyLnN0cmVhbSk7XG4gICAgICAgICAgICAgICAgcHVibGlzaGVyLnN0cmVhbS5wdWJsaXNoKClcbiAgICAgICAgICAgICAgICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIC8vICdTZXNzaW9uLnVucHVibGlzaChQdWJsaXNoZXIpJyBoYXMgYmVlbiBjYWxsZWQuIE11c3QgaW5pdGlhbGl6ZSBhZ2FpbiBQdWJsaXNoZXJcbiAgICAgICAgICAgICAgICBwdWJsaXNoZXIuaW5pdGlhbGl6ZSgpXG4gICAgICAgICAgICAgICAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY29ubmVjdGlvbi5hZGRTdHJlYW0ocHVibGlzaGVyLnN0cmVhbSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBwdWJsaXNoZXIucmVlc3RhYmxpc2hTdHJlYW1QbGF5aW5nRXZlbnQoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHB1Ymxpc2hlci5zdHJlYW0ucHVibGlzaCgpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICB9KS5jYXRjaCgoZXJyb3IpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFVucHVibGlzaGVzIGZyb20gdGhlIFNlc3Npb24gdGhlIFB1Ymxpc2hlciBvYmplY3QuXG4gICAgICpcbiAgICAgKiAjIyMjIEV2ZW50cyBkaXNwYXRjaGVkXG4gICAgICpcbiAgICAgKiBUaGUgW1tQdWJsaXNoZXJdXSBvYmplY3Qgb2YgdGhlIGxvY2FsIHBhcnRpY2lwYW50IHdpbGwgZGlzcGF0Y2ggYSBgc3RyZWFtRGVzdHJveWVkYCBldmVudC5cbiAgICAgKiBUaGlzIGV2ZW50IHdpbGwgYXV0b21hdGljYWxseSBzdG9wIGFsbCBtZWRpYSB0cmFja3MgYW5kIGRlbGV0ZSBhbnkgSFRNTCB2aWRlbyBlbGVtZW50IGFzc29jaWF0ZWQgdG8gdGhpcyBQdWJsaXNoZXJcbiAgICAgKiAob25seSB0aG9zZSB2aWRlb3MgW2NyZWF0ZWQgYnkgT3BlblZpZHUgQnJvd3Nlcl0oL2RvY3MvaG93LWRvLWkvbWFuYWdlLXZpZGVvcy8jbGV0LW9wZW52aWR1LXRha2UtY2FyZS1vZi10aGUtdmlkZW8tcGxheWVycykpLlxuICAgICAqIEZvciBldmVyeSB2aWRlbyByZW1vdmVkLCB0aGUgUHVibGlzaGVyIG9iamVjdCB3aWxsIGRpc3BhdGNoIGEgYHZpZGVvRWxlbWVudERlc3Ryb3llZGAgZXZlbnQuXG4gICAgICogQ2FsbCBgZXZlbnQucHJldmVudERlZmF1bHQoKWAgdXBvbiBldmVudCBgc3RyZWFtRGVzdHJveWVkYCBpZiB5b3Ugd2FudCB0byBjbGVhbiB0aGUgUHVibGlzaGVyIG9iamVjdCBvbiB5b3VyIG93biBvciByZS1wdWJsaXNoIGl0IGluIGEgZGlmZmVyZW50IFNlc3Npb24uXG4gICAgICpcbiAgICAgKiBUaGUgW1tTZXNzaW9uXV0gb2JqZWN0IG9mIGV2ZXJ5IG90aGVyIHBhcnRpY2lwYW50IGNvbm5lY3RlZCB0byB0aGUgc2Vzc2lvbiB3aWxsIGRpc3BhdGNoIGEgYHN0cmVhbURlc3Ryb3llZGAgZXZlbnQuXG4gICAgICogVGhpcyBldmVudCB3aWxsIGF1dG9tYXRpY2FsbHkgdW5zdWJzY3JpYmUgdGhlIFN1YnNjcmliZXIgb2JqZWN0IGZyb20gdGhlIHNlc3Npb24gKHRoaXMgaW5jbHVkZXMgY2xvc2luZyB0aGUgV2ViUlRDUGVlciBjb25uZWN0aW9uIGFuZCBkaXNwb3NpbmcgYWxsIE1lZGlhU3RyZWFtVHJhY2tzKSBhbmRcbiAgICAgKiBkZWxldGUgYW55IEhUTUwgdmlkZW8gZWxlbWVudCBhc3NvY2lhdGVkIHRvIGl0IChvbmx5IHRob3NlIFtjcmVhdGVkIGJ5IE9wZW5WaWR1IEJyb3dzZXJdKC9kb2NzL2hvdy1kby1pL21hbmFnZS12aWRlb3MvI2xldC1vcGVudmlkdS10YWtlLWNhcmUtb2YtdGhlLXZpZGVvLXBsYXllcnMpKS5cbiAgICAgKiBGb3IgZXZlcnkgdmlkZW8gcmVtb3ZlZCwgdGhlIFN1YnNjcmliZXIgb2JqZWN0IHdpbGwgZGlzcGF0Y2ggYSBgdmlkZW9FbGVtZW50RGVzdHJveWVkYCBldmVudC5cbiAgICAgKiBDYWxsIGBldmVudC5wcmV2ZW50RGVmYXVsdCgpYCB1cG9uIGV2ZW50IGBzdHJlYW1EZXN0cm95ZWRgIHRvIGF2b2lkIHRoaXMgZGVmYXVsdCBiZWhhdmlvciBhbmQgdGFrZSBjYXJlIG9mIGRpc3Bvc2luZyBhbmQgY2xlYW5pbmcgdGhlIFN1YnNjcmliZXIgb2JqZWN0IG9uIHlvdXIgb3duLlxuICAgICAqXG4gICAgICogU2VlIFtbU3RyZWFtRXZlbnRdXSBhbmQgW1tWaWRlb0VsZW1lbnRFdmVudF1dIHRvIGxlYXJuIG1vcmUuXG4gICAgICovXG4gICAgdW5wdWJsaXNoKHB1Ymxpc2hlcjogUHVibGlzaGVyKTogdm9pZCB7XG5cbiAgICAgICAgY29uc3Qgc3RyZWFtID0gcHVibGlzaGVyLnN0cmVhbTtcblxuICAgICAgICBpZiAoIXN0cmVhbS5jb25uZWN0aW9uKSB7XG4gICAgICAgICAgICBjb25zb2xlLmVycm9yKCdUaGUgYXNzb2NpYXRlZCBDb25uZWN0aW9uIG9iamVjdCBvZiB0aGlzIFB1Ymxpc2hlciBpcyBudWxsJywgc3RyZWFtKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfSBlbHNlIGlmIChzdHJlYW0uY29ubmVjdGlvbiAhPT0gdGhpcy5jb25uZWN0aW9uKSB7XG4gICAgICAgICAgICBjb25zb2xlLmVycm9yKCdUaGUgYXNzb2NpYXRlZCBDb25uZWN0aW9uIG9iamVjdCBvZiB0aGlzIFB1Ymxpc2hlciBpcyBub3QgeW91ciBsb2NhbCBDb25uZWN0aW9uLicgK1xuICAgICAgICAgICAgICAgIFwiT25seSBtb2RlcmF0b3JzIGNhbiBmb3JjZSB1bnB1Ymxpc2ggb24gcmVtb3RlIFN0cmVhbXMgdmlhICdmb3JjZVVucHVibGlzaCcgbWV0aG9kXCIsIHN0cmVhbSk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH0gZWxzZSB7XG5cbiAgICAgICAgICAgIGNvbnNvbGUuaW5mbygnVW5wdWJsaXNoaW5nIGxvY2FsIG1lZGlhICgnICsgc3RyZWFtLmNvbm5lY3Rpb24uY29ubmVjdGlvbklkICsgJyknKTtcblxuICAgICAgICAgICAgdGhpcy5vcGVudmlkdS5zZW5kUmVxdWVzdCgndW5wdWJsaXNoVmlkZW8nLCAoZXJyb3IsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoZXJyb3IpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbygnTWVkaWEgdW5wdWJsaXNoZWQgY29ycmVjdGx5Jyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIHN0cmVhbS5kaXNwb3NlV2ViUnRjUGVlcigpO1xuICAgICAgICAgICAgZGVsZXRlIHN0cmVhbS5jb25uZWN0aW9uLnN0cmVhbTtcblxuICAgICAgICAgICAgY29uc3Qgc3RyZWFtRXZlbnQgPSBuZXcgU3RyZWFtRXZlbnQodHJ1ZSwgcHVibGlzaGVyLCAnc3RyZWFtRGVzdHJveWVkJywgcHVibGlzaGVyLnN0cmVhbSwgJ3VucHVibGlzaCcpO1xuICAgICAgICAgICAgcHVibGlzaGVyLmVtaXRFdmVudCgnc3RyZWFtRGVzdHJveWVkJywgW3N0cmVhbUV2ZW50XSk7XG4gICAgICAgICAgICBzdHJlYW1FdmVudC5jYWxsRGVmYXVsdEJlaGF2aW9yKCk7XG4gICAgICAgIH1cbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIEZvcmNlcyBzb21lIHVzZXIgdG8gbGVhdmUgdGhlIHNlc3Npb25cbiAgICAgKlxuICAgICAqICMjIyMgRXZlbnRzIGRpc3BhdGNoZWRcbiAgICAgKlxuICAgICAqIFRoZSBiZWhhdmlvciBpcyB0aGUgc2FtZSBhcyB3aGVuIHNvbWUgdXNlciBjYWxscyBbW1Nlc3Npb24uZGlzY29ubmVjdF1dLCBidXQgYHJlYXNvbmAgcHJvcGVydHkgaW4gYWxsIGV2ZW50cyB3aWxsIGJlIGBcImZvcmNlRGlzY29ubmVjdEJ5VXNlclwiYC5cbiAgICAgKlxuICAgICAqIFRoZSBbW1Nlc3Npb25dXSBvYmplY3Qgb2YgZXZlcnkgcGFydGljaXBhbnQgd2lsbCBkaXNwYXRjaCBhIGBzdHJlYW1EZXN0cm95ZWRgIGV2ZW50IGlmIHRoZSBldmljdGVkIHVzZXIgd2FzIHB1Ymxpc2hpbmcgYSBzdHJlYW0sIHdpdGggcHJvcGVydHkgYHJlYXNvbmAgc2V0IHRvIGBcImZvcmNlRGlzY29ubmVjdEJ5VXNlclwiYC5cbiAgICAgKiBUaGUgW1tTZXNzaW9uXV0gb2JqZWN0IG9mIGV2ZXJ5IHBhcnRpY2lwYW50IGV4Y2VwdCB0aGUgZXZpY3RlZCBvbmUgd2lsbCBkaXNwYXRjaCBhIGBjb25uZWN0aW9uRGVzdHJveWVkYCBldmVudCBmb3IgdGhlIGV2aWN0ZWQgdXNlciwgd2l0aCBwcm9wZXJ0eSBgcmVhc29uYCBzZXQgdG8gYFwiZm9yY2VEaXNjb25uZWN0QnlVc2VyXCJgLlxuICAgICAqXG4gICAgICogSWYgYW55LCB0aGUgW1tQdWJsaXNoZXJdXSBvYmplY3Qgb2YgdGhlIGV2aWN0ZWQgcGFydGljaXBhbnQgd2lsbCBhbHNvIGRpc3BhdGNoIGEgYHN0cmVhbURlc3Ryb3llZGAgZXZlbnQgd2l0aCBwcm9wZXJ0eSBgcmVhc29uYCBzZXQgdG8gYFwiZm9yY2VEaXNjb25uZWN0QnlVc2VyXCJgLlxuICAgICAqIFRoZSBbW1Nlc3Npb25dXSBvYmplY3Qgb2YgdGhlIGV2aWN0ZWQgcGFydGljaXBhbnQgd2lsbCBkaXNwYXRjaCBhIGBzZXNzaW9uRGlzY29ubmVjdGVkYCBldmVudCB3aXRoIHByb3BlcnR5IGByZWFzb25gIHNldCB0byBgXCJmb3JjZURpc2Nvbm5lY3RCeVVzZXJcImAuXG4gICAgICpcbiAgICAgKiBTZWUgW1tTdHJlYW1FdmVudF1dLCBbW0Nvbm5lY3Rpb25FdmVudF1dIGFuZCBbW1Nlc3Npb25EaXNjb25uZWN0ZWRFdmVudF1dIHRvIGxlYXJuIG1vcmUuXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyBBIFByb21pc2UgKHRvIHdoaWNoIHlvdSBjYW4gb3B0aW9uYWxseSBzdWJzY3JpYmUgdG8pIHRoYXQgaXMgcmVzb2x2ZWQgb25seSBhZnRlciB0aGUgcGFydGljaXBhbnQgaGFzIGJlZW4gc3VjY2Vzc2Z1bGx5IGV2aWN0ZWQgZnJvbSB0aGUgc2Vzc2lvbiBhbmQgcmVqZWN0ZWQgd2l0aCBhbiBFcnJvciBvYmplY3QgaWYgbm90XG4gICAgICovXG4gICAgZm9yY2VEaXNjb25uZWN0KGNvbm5lY3Rpb246IENvbm5lY3Rpb24pOiBQcm9taXNlPGFueT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgY29uc29sZS5pbmZvKCdGb3JjaW5nIGRpc2Nvbm5lY3QgZm9yIGNvbm5lY3Rpb24gJyArIGNvbm5lY3Rpb24uY29ubmVjdGlvbklkKTtcbiAgICAgICAgICAgIHRoaXMub3BlbnZpZHUuc2VuZFJlcXVlc3QoXG4gICAgICAgICAgICAgICAgJ2ZvcmNlRGlzY29ubmVjdCcsXG4gICAgICAgICAgICAgICAgeyBjb25uZWN0aW9uSWQ6IGNvbm5lY3Rpb24uY29ubmVjdGlvbklkIH0sXG4gICAgICAgICAgICAgICAgKGVycm9yLCByZXNwb25zZSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBpZiAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ0Vycm9yIGZvcmNpbmcgZGlzY29ubmVjdCBmb3IgQ29ubmVjdGlvbiAnICsgY29ubmVjdGlvbi5jb25uZWN0aW9uSWQsIGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChlcnJvci5jb2RlID09PSA0MDEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWplY3QobmV3IE9wZW5WaWR1RXJyb3IoT3BlblZpZHVFcnJvck5hbWUuT1BFTlZJRFVfUEVSTUlTU0lPTl9ERU5JRUQsIFwiWW91IGRvbid0IGhhdmUgcGVybWlzc2lvbnMgdG8gZm9yY2UgYSBkaXNjb25uZWN0aW9uXCIpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbygnRm9yY2luZyBkaXNjb25uZWN0IGNvcnJlY3RseSBmb3IgQ29ubmVjdGlvbiAnICsgY29ubmVjdGlvbi5jb25uZWN0aW9uSWQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBGb3JjZXMgc29tZSB1c2VyIHRvIHVucHVibGlzaCBhIFN0cmVhbVxuICAgICAqXG4gICAgICogIyMjIyBFdmVudHMgZGlzcGF0Y2hlZFxuICAgICAqXG4gICAgICogVGhlIGJlaGF2aW9yIGlzIHRoZSBzYW1lIGFzIHdoZW4gc29tZSB1c2VyIGNhbGxzIFtbU2Vzc2lvbi51bnB1Ymxpc2hdXSwgYnV0IGByZWFzb25gIHByb3BlcnR5IGluIGFsbCBldmVudHMgd2lsbCBiZSBgXCJmb3JjZVVucHVibGlzaEJ5VXNlclwiYFxuICAgICAqXG4gICAgICogVGhlIFtbU2Vzc2lvbl1dIG9iamVjdCBvZiBldmVyeSBwYXJ0aWNpcGFudCB3aWxsIGRpc3BhdGNoIGEgYHN0cmVhbURlc3Ryb3llZGAgZXZlbnQgd2l0aCBwcm9wZXJ0eSBgcmVhc29uYCBzZXQgdG8gYFwiZm9yY2VEaXNjb25uZWN0QnlVc2VyXCJgXG4gICAgICpcbiAgICAgKiBUaGUgW1tQdWJsaXNoZXJdXSBvYmplY3Qgb2YgdGhlIGFmZmVjdGVkIHBhcnRpY2lwYW50IHdpbGwgYWxzbyBkaXNwYXRjaCBhIGBzdHJlYW1EZXN0cm95ZWRgIGV2ZW50IHdpdGggcHJvcGVydHkgYHJlYXNvbmAgc2V0IHRvIGBcImZvcmNlRGlzY29ubmVjdEJ5VXNlclwiYFxuICAgICAqXG4gICAgICogU2VlIFtbU3RyZWFtRXZlbnRdXSB0byBsZWFybiBtb3JlLlxuICAgICAqXG4gICAgICogQHJldHVybnMgQSBQcm9taXNlICh0byB3aGljaCB5b3UgY2FuIG9wdGlvbmFsbHkgc3Vic2NyaWJlIHRvKSB0aGF0IGlzIHJlc29sdmVkIG9ubHkgYWZ0ZXIgdGhlIHJlbW90ZSBTdHJlYW0gaGFzIGJlZW4gc3VjY2Vzc2Z1bGx5IHVucHVibGlzaGVkIGZyb20gdGhlIHNlc3Npb24gYW5kIHJlamVjdGVkIHdpdGggYW4gRXJyb3Igb2JqZWN0IGlmIG5vdFxuICAgICAqL1xuICAgIGZvcmNlVW5wdWJsaXNoKHN0cmVhbTogU3RyZWFtKTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIGNvbnNvbGUuaW5mbygnRm9yY2luZyB1bnB1Ymxpc2ggZm9yIHN0cmVhbSAnICsgc3RyZWFtLnN0cmVhbUlkKTtcbiAgICAgICAgICAgIHRoaXMub3BlbnZpZHUuc2VuZFJlcXVlc3QoXG4gICAgICAgICAgICAgICAgJ2ZvcmNlVW5wdWJsaXNoJyxcbiAgICAgICAgICAgICAgICB7IHN0cmVhbUlkOiBzdHJlYW0uc3RyZWFtSWQgfSxcbiAgICAgICAgICAgICAgICAoZXJyb3IsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcignRXJyb3IgZm9yY2luZyB1bnB1Ymxpc2ggZm9yIFN0cmVhbSAnICsgc3RyZWFtLnN0cmVhbUlkLCBlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZXJyb3IuY29kZSA9PT0gNDAxKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KG5ldyBPcGVuVmlkdUVycm9yKE9wZW5WaWR1RXJyb3JOYW1lLk9QRU5WSURVX1BFUk1JU1NJT05fREVOSUVELCBcIllvdSBkb24ndCBoYXZlIHBlcm1pc3Npb25zIHRvIGZvcmNlIGFuIHVucHVibGlzaGluZ1wiKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oJ0ZvcmNpbmcgdW5wdWJsaXNoIGNvcnJlY3RseSBmb3IgU3RyZWFtICcgKyBzdHJlYW0uc3RyZWFtSWQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBTZW5kcyBvbmUgc2lnbmFsLiBgc2lnbmFsYCBvYmplY3QgaGFzIHRoZSBmb2xsb3dpbmcgb3B0aW9uYWwgcHJvcGVydGllczpcbiAgICAgKiBgYGBqc29uXG4gICAgICoge2RhdGE6c3RyaW5nLCB0bzpDb25uZWN0aW9uW10sIHR5cGU6c3RyaW5nfVxuICAgICAqIGBgYFxuICAgICAqIEFsbCB1c2VycyBzdWJzY3JpYmVkIHRvIHRoYXQgc2lnbmFsIChgc2Vzc2lvbi5vbignc2lnbmFsOnR5cGUnLCAuLi4pYCBvciBgc2Vzc2lvbi5vbignc2lnbmFsJywgLi4uKWAgZm9yIGFsbCBzaWduYWxzKSBhbmQgd2hvc2UgQ29ubmVjdGlvbiBvYmplY3RzIGFyZSBpbiBgdG9gIGFycmF5IHdpbGwgcmVjZWl2ZSBpdC4gVGhlaXIgbG9jYWxcbiAgICAgKiBTZXNzaW9uIG9iamVjdHMgd2lsbCBkaXNwYXRjaCBhIGBzaWduYWxgIG9yIGBzaWduYWw6dHlwZWAgZXZlbnQuIFNlZSBbW1NpZ25hbEV2ZW50XV0gdG8gbGVhcm4gbW9yZS5cbiAgICAgKlxuICAgICAqIEByZXR1cm5zIEEgUHJvbWlzZSAodG8gd2hpY2ggeW91IGNhbiBvcHRpb25hbGx5IHN1YnNjcmliZSB0bykgdGhhdCBpcyByZXNvbHZlZCBpZiB0aGUgbWVzc2FnZSBzdWNjZXNzZnVsbHkgcmVhY2hlZCBvcGVudmlkdS1zZXJ2ZXIgYW5kIHJlamVjdGVkIHdpdGggYW4gRXJyb3Igb2JqZWN0IGlmIG5vdC4gX1RoaXMgZG9lc24ndFxuICAgICAqIG1lYW4gdGhhdCBvcGVudmlkdS1zZXJ2ZXIgY291bGQgcmVzZW5kIHRoZSBtZXNzYWdlIHRvIGFsbCB0aGUgbGlzdGVkIHJlY2VpdmVycy5fXG4gICAgICovXG4gICAgLyogdHNsaW50OmRpc2FibGU6bm8tc3RyaW5nLWxpdGVyYWwgKi9cbiAgICBzaWduYWwoc2lnbmFsOiBTaWduYWxPcHRpb25zKTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcblxuICAgICAgICAgICAgY29uc3Qgc2lnbmFsTWVzc2FnZSA9IHt9O1xuXG4gICAgICAgICAgICBpZiAoc2lnbmFsLnRvICYmIHNpZ25hbC50by5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgY29ubmVjdGlvbklkczogc3RyaW5nW10gPSBbXTtcblxuICAgICAgICAgICAgICAgIHNpZ25hbC50by5mb3JFYWNoKGNvbm5lY3Rpb24gPT4ge1xuICAgICAgICAgICAgICAgICAgICBjb25uZWN0aW9uSWRzLnB1c2goY29ubmVjdGlvbi5jb25uZWN0aW9uSWQpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIHNpZ25hbE1lc3NhZ2VbJ3RvJ10gPSBjb25uZWN0aW9uSWRzO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBzaWduYWxNZXNzYWdlWyd0byddID0gW107XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHNpZ25hbE1lc3NhZ2VbJ2RhdGEnXSA9IHNpZ25hbC5kYXRhID8gc2lnbmFsLmRhdGEgOiAnJztcbiAgICAgICAgICAgIHNpZ25hbE1lc3NhZ2VbJ3R5cGUnXSA9IHNpZ25hbC50eXBlID8gc2lnbmFsLnR5cGUgOiAnJztcblxuICAgICAgICAgICAgdGhpcy5vcGVudmlkdS5zZW5kUmVxdWVzdCgnc2VuZE1lc3NhZ2UnLCB7XG4gICAgICAgICAgICAgICAgbWVzc2FnZTogSlNPTi5zdHJpbmdpZnkoc2lnbmFsTWVzc2FnZSlcbiAgICAgICAgICAgIH0sIChlcnJvciwgcmVzcG9uc2UpID0+IHtcbiAgICAgICAgICAgICAgICBpZiAoISFlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgfVxuICAgIC8qIHRzbGludDplbmFibGU6bm8tc3RyaW5nLWxpdGVyYWwgKi9cblxuXG4gICAgLyoqXG4gICAgICogU2VlIFtbRXZlbnREaXNwYXRjaGVyLm9uXV1cbiAgICAgKi9cbiAgICBvbih0eXBlOiBzdHJpbmcsIGhhbmRsZXI6IChldmVudDogU2Vzc2lvbkRpc2Nvbm5lY3RlZEV2ZW50IHwgU2lnbmFsRXZlbnQgfCBTdHJlYW1FdmVudCB8IENvbm5lY3Rpb25FdmVudCB8IFB1Ymxpc2hlclNwZWFraW5nRXZlbnQgfCBSZWNvcmRpbmdFdmVudCkgPT4gdm9pZCk6IEV2ZW50RGlzcGF0Y2hlciB7XG5cbiAgICAgICAgdGhpcy5lZS5vbih0eXBlLCBldmVudCA9PiB7XG4gICAgICAgICAgICBpZiAoZXZlbnQpIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oXCJFdmVudCAnXCIgKyB0eXBlICsgXCInIHRyaWdnZXJlZCBieSAnU2Vzc2lvbidcIiwgZXZlbnQpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oXCJFdmVudCAnXCIgKyB0eXBlICsgXCInIHRyaWdnZXJlZCBieSAnU2Vzc2lvbidcIik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBoYW5kbGVyKGV2ZW50KTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgaWYgKHR5cGUgPT09ICdwdWJsaXNoZXJTdGFydFNwZWFraW5nJyB8fCB0eXBlID09PSAncHVibGlzaGVyU3RvcFNwZWFraW5nJykge1xuICAgICAgICAgICAgdGhpcy5zcGVha2luZ0V2ZW50c0VuYWJsZWQgPSB0cnVlO1xuICAgICAgICAgICAgLy8gSWYgdGhlcmUgYXJlIGFscmVhZHkgYXZhaWxhYmxlIHJlbW90ZSBzdHJlYW1zLCBlbmFibGUgaGFyayAnc3BlYWtpbmcnIGV2ZW50IGluIGFsbCBvZiB0aGVtXG4gICAgICAgICAgICBmb3IgKGNvbnN0IGNvbm5lY3Rpb25JZCBpbiB0aGlzLnJlbW90ZUNvbm5lY3Rpb25zKSB7XG4gICAgICAgICAgICAgICAgY29uc3Qgc3RyID0gdGhpcy5yZW1vdGVDb25uZWN0aW9uc1tjb25uZWN0aW9uSWRdLnN0cmVhbTtcbiAgICAgICAgICAgICAgICBpZiAoISFzdHIgJiYgIXN0ci5zcGVlY2hFdmVudCAmJiBzdHIuaGFzQXVkaW8pIHtcbiAgICAgICAgICAgICAgICAgICAgc3RyLmVuYWJsZVNwZWFraW5nRXZlbnRzKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBTZWUgW1tFdmVudERpc3BhdGNoZXIub25jZV1dXG4gICAgICovXG4gICAgb25jZSh0eXBlOiBzdHJpbmcsIGhhbmRsZXI6IChldmVudDogU2Vzc2lvbkRpc2Nvbm5lY3RlZEV2ZW50IHwgU2lnbmFsRXZlbnQgfCBTdHJlYW1FdmVudCB8IENvbm5lY3Rpb25FdmVudCB8IFB1Ymxpc2hlclNwZWFraW5nRXZlbnQgfCBSZWNvcmRpbmdFdmVudCkgPT4gdm9pZCk6IFNlc3Npb24ge1xuICAgICAgICB0aGlzLmVlLm9uY2UodHlwZSwgZXZlbnQgPT4ge1xuICAgICAgICAgICAgaWYgKGV2ZW50KSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5pbmZvKFwiRXZlbnQgJ1wiICsgdHlwZSArIFwiJyB0cmlnZ2VyZWQgYnkgJ1Nlc3Npb24nXCIsIGV2ZW50KTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5pbmZvKFwiRXZlbnQgJ1wiICsgdHlwZSArIFwiJyB0cmlnZ2VyZWQgYnkgJ1Nlc3Npb24nXCIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaGFuZGxlcihldmVudCk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGlmICh0eXBlID09PSAncHVibGlzaGVyU3RhcnRTcGVha2luZycgfHwgdHlwZSA9PT0gJ3B1Ymxpc2hlclN0b3BTcGVha2luZycpIHtcbiAgICAgICAgICAgIHRoaXMuc3BlYWtpbmdFdmVudHNFbmFibGVkID0gdHJ1ZTtcblxuICAgICAgICAgICAgLy8gSWYgdGhlcmUgYXJlIGFscmVhZHkgYXZhaWxhYmxlIHJlbW90ZSBzdHJlYW1zLCBlbmFibGUgaGFyayBpbiBhbGwgb2YgdGhlbVxuICAgICAgICAgICAgZm9yIChjb25zdCBjb25uZWN0aW9uSWQgaW4gdGhpcy5yZW1vdGVDb25uZWN0aW9ucykge1xuICAgICAgICAgICAgICAgIGNvbnN0IHN0ciA9IHRoaXMucmVtb3RlQ29ubmVjdGlvbnNbY29ubmVjdGlvbklkXS5zdHJlYW07XG4gICAgICAgICAgICAgICAgaWYgKCEhc3RyICYmICFzdHIuc3BlZWNoRXZlbnQgJiYgc3RyLmhhc0F1ZGlvKSB7XG4gICAgICAgICAgICAgICAgICAgIHN0ci5lbmFibGVPbmNlU3BlYWtpbmdFdmVudHMoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFNlZSBbW0V2ZW50RGlzcGF0Y2hlci5vZmZdXVxuICAgICAqL1xuICAgIG9mZih0eXBlOiBzdHJpbmcsIGhhbmRsZXI/OiAoZXZlbnQ6IFNlc3Npb25EaXNjb25uZWN0ZWRFdmVudCB8IFNpZ25hbEV2ZW50IHwgU3RyZWFtRXZlbnQgfCBDb25uZWN0aW9uRXZlbnQgfCBQdWJsaXNoZXJTcGVha2luZ0V2ZW50IHwgUmVjb3JkaW5nRXZlbnQpID0+IHZvaWQpOiBTZXNzaW9uIHtcblxuICAgICAgICBpZiAoIWhhbmRsZXIpIHtcbiAgICAgICAgICAgIHRoaXMuZWUucmVtb3ZlQWxsTGlzdGVuZXJzKHR5cGUpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5lZS5vZmYodHlwZSwgaGFuZGxlcik7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodHlwZSA9PT0gJ3B1Ymxpc2hlclN0YXJ0U3BlYWtpbmcnIHx8IHR5cGUgPT09ICdwdWJsaXNoZXJTdG9wU3BlYWtpbmcnKSB7XG4gICAgICAgICAgICB0aGlzLnNwZWFraW5nRXZlbnRzRW5hYmxlZCA9IGZhbHNlO1xuXG4gICAgICAgICAgICAvLyBJZiB0aGVyZSBhcmUgYWxyZWFkeSBhdmFpbGFibGUgcmVtb3RlIHN0cmVhbXMsIGRpc2FibGFlIGhhcmsgaW4gYWxsIG9mIHRoZW1cbiAgICAgICAgICAgIGZvciAoY29uc3QgY29ubmVjdGlvbklkIGluIHRoaXMucmVtb3RlQ29ubmVjdGlvbnMpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBzdHIgPSB0aGlzLnJlbW90ZUNvbm5lY3Rpb25zW2Nvbm5lY3Rpb25JZF0uc3RyZWFtO1xuICAgICAgICAgICAgICAgIGlmICghIXN0ciAmJiAhIXN0ci5zcGVlY2hFdmVudCkge1xuICAgICAgICAgICAgICAgICAgICBzdHIuZGlzYWJsZVNwZWFraW5nRXZlbnRzKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuXG4gICAgLyogSGlkZGVuIG1ldGhvZHMgKi9cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvblBhcnRpY2lwYW50Sm9pbmVkKHJlc3BvbnNlOiBDb25uZWN0aW9uT3B0aW9ucyk6IHZvaWQge1xuICAgICAgICAvLyBDb25uZWN0aW9uIHNob3VsZG4ndCBleGlzdFxuICAgICAgICB0aGlzLmdldENvbm5lY3Rpb24ocmVzcG9uc2UuaWQsICcnKVxuXG4gICAgICAgICAgICAudGhlbihjb25uZWN0aW9uID0+IHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLndhcm4oJ0Nvbm5lY3Rpb24gJyArIHJlc3BvbnNlLmlkICsgJyBhbHJlYWR5IGV4aXN0cyBpbiBjb25uZWN0aW9ucyBsaXN0Jyk7XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLmNhdGNoKG9wZW5WaWR1RXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IGNvbm5lY3Rpb24gPSBuZXcgQ29ubmVjdGlvbih0aGlzLCByZXNwb25zZSk7XG4gICAgICAgICAgICAgICAgdGhpcy5yZW1vdGVDb25uZWN0aW9uc1tyZXNwb25zZS5pZF0gPSBjb25uZWN0aW9uO1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdjb25uZWN0aW9uQ3JlYXRlZCcsIFtuZXcgQ29ubmVjdGlvbkV2ZW50KGZhbHNlLCB0aGlzLCAnY29ubmVjdGlvbkNyZWF0ZWQnLCBjb25uZWN0aW9uLCAnJyldKTtcbiAgICAgICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvblBhcnRpY2lwYW50TGVmdChtc2cpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5nZXRSZW1vdGVDb25uZWN0aW9uKG1zZy5jb25uZWN0aW9uSWQsICdSZW1vdGUgY29ubmVjdGlvbiAnICsgbXNnLmNvbm5lY3Rpb25JZCArIFwiIHVua25vd24gd2hlbiAnb25QYXJ0aWNpcGFudExlZnQnLiBcIiArXG4gICAgICAgICAgICAnRXhpc3RpbmcgcmVtb3RlIGNvbm5lY3Rpb25zOiAnICsgSlNPTi5zdHJpbmdpZnkoT2JqZWN0LmtleXModGhpcy5yZW1vdGVDb25uZWN0aW9ucykpKVxuXG4gICAgICAgICAgICAudGhlbihjb25uZWN0aW9uID0+IHtcbiAgICAgICAgICAgICAgICBpZiAoISFjb25uZWN0aW9uLnN0cmVhbSkge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBzdHJlYW0gPSBjb25uZWN0aW9uLnN0cmVhbTtcblxuICAgICAgICAgICAgICAgICAgICBjb25zdCBzdHJlYW1FdmVudCA9IG5ldyBTdHJlYW1FdmVudCh0cnVlLCB0aGlzLCAnc3RyZWFtRGVzdHJveWVkJywgc3RyZWFtLCBtc2cucmVhc29uKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3N0cmVhbURlc3Ryb3llZCcsIFtzdHJlYW1FdmVudF0pO1xuICAgICAgICAgICAgICAgICAgICBzdHJlYW1FdmVudC5jYWxsRGVmYXVsdEJlaGF2aW9yKCk7XG5cbiAgICAgICAgICAgICAgICAgICAgZGVsZXRlIHRoaXMucmVtb3RlU3RyZWFtc0NyZWF0ZWRbc3RyZWFtLnN0cmVhbUlkXTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZGVsZXRlIHRoaXMucmVtb3RlQ29ubmVjdGlvbnNbY29ubmVjdGlvbi5jb25uZWN0aW9uSWRdO1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdjb25uZWN0aW9uRGVzdHJveWVkJywgW25ldyBDb25uZWN0aW9uRXZlbnQoZmFsc2UsIHRoaXMsICdjb25uZWN0aW9uRGVzdHJveWVkJywgY29ubmVjdGlvbiwgbXNnLnJlYXNvbildKTtcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAuY2F0Y2gob3BlblZpZHVFcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihvcGVuVmlkdUVycm9yKTtcbiAgICAgICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvblBhcnRpY2lwYW50UHVibGlzaGVkKHJlc3BvbnNlOiBDb25uZWN0aW9uT3B0aW9ucyk6IHZvaWQge1xuXG4gICAgICAgIGNvbnN0IGFmdGVyQ29ubmVjdGlvbkZvdW5kID0gKGNvbm5lY3Rpb24pID0+IHtcbiAgICAgICAgICAgIHRoaXMucmVtb3RlQ29ubmVjdGlvbnNbY29ubmVjdGlvbi5jb25uZWN0aW9uSWRdID0gY29ubmVjdGlvbjtcblxuICAgICAgICAgICAgaWYgKCF0aGlzLnJlbW90ZVN0cmVhbXNDcmVhdGVkW2Nvbm5lY3Rpb24uc3RyZWFtLnN0cmVhbUlkXSkge1xuICAgICAgICAgICAgICAgIC8vIEF2b2lkIHJhY2UgY29uZGl0aW9uIGJldHdlZW4gc3RyZWFtLnN1YnNjcmliZSgpIGluIFwib25QYXJ0aWNpcGFudFB1Ymxpc2hlZFwiIGFuZCBpbiBcImpvaW5Sb29tXCIgcnBjIGNhbGxiYWNrXG4gICAgICAgICAgICAgICAgLy8gVGhpcyBjb25kaXRpb24gaXMgZmFsc2UgaWYgb3BlbnZpZHUtc2VydmVyIHNlbmRzIFwicGFydGljaXBhbnRQdWJsaXNoZWRcIiBldmVudCB0byBhIHN1YnNjcmliZXIgcGFydGljaXBhbnQgdGhhdCBoYXNcbiAgICAgICAgICAgICAgICAvLyBhbHJlYWR5IHN1YnNjcmliZWQgdG8gY2VydGFpbiBzdHJlYW0gaW4gdGhlIGNhbGxiYWNrIG9mIFwiam9pblJvb21cIiBtZXRob2RcblxuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdzdHJlYW1DcmVhdGVkJywgW25ldyBTdHJlYW1FdmVudChmYWxzZSwgdGhpcywgJ3N0cmVhbUNyZWF0ZWQnLCBjb25uZWN0aW9uLnN0cmVhbSwgJycpXSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMucmVtb3RlU3RyZWFtc0NyZWF0ZWRbY29ubmVjdGlvbi5zdHJlYW0uc3RyZWFtSWRdID0gdHJ1ZTtcbiAgICAgICAgfTtcblxuICAgICAgICAvLyBHZXQgdGhlIGV4aXN0aW5nIENvbm5lY3Rpb24gY3JlYXRlZCBvbiAnb25QYXJ0aWNpcGFudEpvaW5lZCcgZm9yXG4gICAgICAgIC8vIGV4aXN0aW5nIHBhcnRpY2lwYW50cyBvciBjcmVhdGUgYSBuZXcgb25lIGZvciBuZXcgcGFydGljaXBhbnRzXG4gICAgICAgIGxldCBjb25uZWN0aW9uOiBDb25uZWN0aW9uO1xuICAgICAgICB0aGlzLmdldFJlbW90ZUNvbm5lY3Rpb24ocmVzcG9uc2UuaWQsIFwiUmVtb3RlIGNvbm5lY3Rpb24gJ1wiICsgcmVzcG9uc2UuaWQgKyBcIicgdW5rbm93biB3aGVuICdvblBhcnRpY2lwYW50UHVibGlzaGVkJy4gXCIgK1xuICAgICAgICAgICAgJ0V4aXN0aW5nIHJlbW90ZSBjb25uZWN0aW9uczogJyArIEpTT04uc3RyaW5naWZ5KE9iamVjdC5rZXlzKHRoaXMucmVtb3RlQ29ubmVjdGlvbnMpKSlcblxuICAgICAgICAgICAgLnRoZW4oY29uID0+IHtcbiAgICAgICAgICAgICAgICAvLyBVcGRhdGUgZXhpc3RpbmcgQ29ubmVjdGlvblxuICAgICAgICAgICAgICAgIGNvbm5lY3Rpb24gPSBjb247XG4gICAgICAgICAgICAgICAgcmVzcG9uc2UubWV0YWRhdGEgPSBjb24uZGF0YTtcbiAgICAgICAgICAgICAgICBjb25uZWN0aW9uLm9wdGlvbnMgPSByZXNwb25zZTtcbiAgICAgICAgICAgICAgICBjb25uZWN0aW9uLmluaXRSZW1vdGVTdHJlYW1zKHJlc3BvbnNlLnN0cmVhbXMpO1xuICAgICAgICAgICAgICAgIGFmdGVyQ29ubmVjdGlvbkZvdW5kKGNvbm5lY3Rpb24pO1xuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIC5jYXRjaChvcGVuVmlkdUVycm9yID0+IHtcbiAgICAgICAgICAgICAgICAvLyBDcmVhdGUgbmV3IENvbm5lY3Rpb25cbiAgICAgICAgICAgICAgICBjb25uZWN0aW9uID0gbmV3IENvbm5lY3Rpb24odGhpcywgcmVzcG9uc2UpO1xuICAgICAgICAgICAgICAgIGFmdGVyQ29ubmVjdGlvbkZvdW5kKGNvbm5lY3Rpb24pO1xuICAgICAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIG9uUGFydGljaXBhbnRVbnB1Ymxpc2hlZChtc2cpOiB2b2lkIHtcbiAgICAgICAgaWYgKG1zZy5jb25uZWN0aW9uSWQgPT09IHRoaXMuY29ubmVjdGlvbi5jb25uZWN0aW9uSWQpIHtcbiAgICAgICAgICAgIC8vIFlvdXIgc3RyZWFtIGhhcyBiZWVuIGZvcmNlZGx5IHVucHVibGlzaGVkIGZyb20gdGhlIHNlc3Npb25cbiAgICAgICAgICAgIHRoaXMuc3RvcFB1Ymxpc2hlclN0cmVhbShtc2cucmVhc29uKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuZ2V0UmVtb3RlQ29ubmVjdGlvbihtc2cuY29ubmVjdGlvbklkLCBcIlJlbW90ZSBjb25uZWN0aW9uICdcIiArIG1zZy5jb25uZWN0aW9uSWQgKyBcIicgdW5rbm93biB3aGVuICdvblBhcnRpY2lwYW50VW5wdWJsaXNoZWQnLiBcIiArXG4gICAgICAgICAgICAgICAgJ0V4aXN0aW5nIHJlbW90ZSBjb25uZWN0aW9uczogJyArIEpTT04uc3RyaW5naWZ5KE9iamVjdC5rZXlzKHRoaXMucmVtb3RlQ29ubmVjdGlvbnMpKSlcblxuICAgICAgICAgICAgICAgIC50aGVuKGNvbm5lY3Rpb24gPT4ge1xuXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHN0cmVhbUV2ZW50ID0gbmV3IFN0cmVhbUV2ZW50KHRydWUsIHRoaXMsICdzdHJlYW1EZXN0cm95ZWQnLCBjb25uZWN0aW9uLnN0cmVhbSwgbXNnLnJlYXNvbik7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdzdHJlYW1EZXN0cm95ZWQnLCBbc3RyZWFtRXZlbnRdKTtcbiAgICAgICAgICAgICAgICAgICAgc3RyZWFtRXZlbnQuY2FsbERlZmF1bHRCZWhhdmlvcigpO1xuXG4gICAgICAgICAgICAgICAgICAgIC8vIERlbGV0aW5nIHRoZSByZW1vdGUgc3RyZWFtXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHN0cmVhbUlkOiBzdHJpbmcgPSBjb25uZWN0aW9uLnN0cmVhbS5zdHJlYW1JZDtcbiAgICAgICAgICAgICAgICAgICAgZGVsZXRlIHRoaXMucmVtb3RlU3RyZWFtc0NyZWF0ZWRbc3RyZWFtSWRdO1xuICAgICAgICAgICAgICAgICAgICBjb25uZWN0aW9uLnJlbW92ZVN0cmVhbShzdHJlYW1JZCk7XG4gICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAuY2F0Y2gob3BlblZpZHVFcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3Iob3BlblZpZHVFcnJvcik7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgb25QYXJ0aWNpcGFudEV2aWN0ZWQobXNnKTogdm9pZCB7XG4gICAgICAgIGlmIChtc2cuY29ubmVjdGlvbklkID09PSB0aGlzLmNvbm5lY3Rpb24uY29ubmVjdGlvbklkKSB7XG4gICAgICAgICAgICAvLyBZb3UgaGF2ZSBiZWVuIGV2aWN0ZWQgZnJvbSB0aGUgc2Vzc2lvblxuICAgICAgICAgICAgaWYgKCEhdGhpcy5zZXNzaW9uSWQgJiYgIXRoaXMuY29ubmVjdGlvbi5kaXNwb3NlZCkge1xuICAgICAgICAgICAgICAgIHRoaXMubGVhdmUodHJ1ZSwgbXNnLnJlYXNvbik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgb25OZXdNZXNzYWdlKG1zZyk6IHZvaWQge1xuXG4gICAgICAgIGNvbnNvbGUuaW5mbygnTmV3IHNpZ25hbDogJyArIEpTT04uc3RyaW5naWZ5KG1zZykpO1xuXG4gICAgICAgIHRoaXMuZ2V0Q29ubmVjdGlvbihtc2cuZnJvbSwgXCJDb25uZWN0aW9uICdcIiArIG1zZy5mcm9tICsgXCInIHVua25vdyB3aGVuICdvbk5ld01lc3NhZ2UnLiBFeGlzdGluZyByZW1vdGUgY29ubmVjdGlvbnM6IFwiXG4gICAgICAgICAgICArIEpTT04uc3RyaW5naWZ5KE9iamVjdC5rZXlzKHRoaXMucmVtb3RlQ29ubmVjdGlvbnMpKSArICcuIEV4aXN0aW5nIGxvY2FsIGNvbm5lY3Rpb246ICcgKyB0aGlzLmNvbm5lY3Rpb24uY29ubmVjdGlvbklkKVxuXG4gICAgICAgICAgICAudGhlbihjb25uZWN0aW9uID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnc2lnbmFsJywgW25ldyBTaWduYWxFdmVudCh0aGlzLCBtc2cudHlwZSwgbXNnLmRhdGEsIGNvbm5lY3Rpb24pXSk7XG4gICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3NpZ25hbDonICsgbXNnLnR5cGUsIFtuZXcgU2lnbmFsRXZlbnQodGhpcywgbXNnLnR5cGUsIG1zZy5kYXRhLCBjb25uZWN0aW9uKV0pO1xuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIC5jYXRjaChvcGVuVmlkdUVycm9yID0+IHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKG9wZW5WaWR1RXJyb3IpO1xuICAgICAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIG9uU3RyZWFtUHJvcGVydHlDaGFuZ2VkKG1zZyk6IHZvaWQge1xuICAgICAgICB0aGlzLmdldFJlbW90ZUNvbm5lY3Rpb24obXNnLmNvbm5lY3Rpb25JZCwgJ1JlbW90ZSBjb25uZWN0aW9uICcgKyBtc2cuY29ubmVjdGlvbklkICsgXCIgdW5rbm93biB3aGVuICdvblN0cmVhbVByb3BlcnR5Q2hhbmdlZCcuIFwiICtcbiAgICAgICAgICAgICdFeGlzdGluZyByZW1vdGUgY29ubmVjdGlvbnM6ICcgKyBKU09OLnN0cmluZ2lmeShPYmplY3Qua2V5cyh0aGlzLnJlbW90ZUNvbm5lY3Rpb25zKSkpXG5cbiAgICAgICAgICAgIC50aGVuKGNvbm5lY3Rpb24gPT4ge1xuICAgICAgICAgICAgICAgIGlmICghIWNvbm5lY3Rpb24uc3RyZWFtICYmIGNvbm5lY3Rpb24uc3RyZWFtLnN0cmVhbUlkID09PSBtc2cuc3RyZWFtSWQpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3Qgc3RyZWFtID0gY29ubmVjdGlvbi5zdHJlYW07XG4gICAgICAgICAgICAgICAgICAgIGxldCBvbGRWYWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgc3dpdGNoIChtc2cucHJvcGVydHkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJ2F1ZGlvQWN0aXZlJzpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvbGRWYWx1ZSA9IHN0cmVhbS5hdWRpb0FjdGl2ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtc2cubmV3VmFsdWUgPSBtc2cubmV3VmFsdWUgPT09ICd0cnVlJztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJlYW0uYXVkaW9BY3RpdmUgPSBtc2cubmV3VmFsdWU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlICd2aWRlb0FjdGl2ZSc6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgb2xkVmFsdWUgPSBzdHJlYW0udmlkZW9BY3RpdmU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbXNnLm5ld1ZhbHVlID0gbXNnLm5ld1ZhbHVlID09PSAndHJ1ZSc7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyZWFtLnZpZGVvQWN0aXZlID0gbXNnLm5ld1ZhbHVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAndmlkZW9EaW1lbnNpb25zJzpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvbGRWYWx1ZSA9IHN0cmVhbS52aWRlb0RpbWVuc2lvbnM7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbXNnLm5ld1ZhbHVlID0gSlNPTi5wYXJzZShKU09OLnBhcnNlKG1zZy5uZXdWYWx1ZSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cmVhbS52aWRlb0RpbWVuc2lvbnMgPSBtc2cubmV3VmFsdWU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnc3RyZWFtUHJvcGVydHlDaGFuZ2VkJywgW25ldyBTdHJlYW1Qcm9wZXJ0eUNoYW5nZWRFdmVudCh0aGlzLCBzdHJlYW0sIG1zZy5wcm9wZXJ0eSwgbXNnLm5ld1ZhbHVlLCBvbGRWYWx1ZSwgbXNnLnJlYXNvbildKTtcbiAgICAgICAgICAgICAgICAgICAgc3RyZWFtLnN0cmVhbU1hbmFnZXIuZW1pdEV2ZW50KCdzdHJlYW1Qcm9wZXJ0eUNoYW5nZWQnLCBbbmV3IFN0cmVhbVByb3BlcnR5Q2hhbmdlZEV2ZW50KHN0cmVhbS5zdHJlYW1NYW5hZ2VyLCBzdHJlYW0sIG1zZy5wcm9wZXJ0eSwgbXNnLm5ld1ZhbHVlLCBvbGRWYWx1ZSwgbXNnLnJlYXNvbildKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKFwiTm8gc3RyZWFtIHdpdGggc3RyZWFtSWQgJ1wiICsgbXNnLnN0cmVhbUlkICsgXCInIGZvdW5kIGZvciBjb25uZWN0aW9uICdcIiArIG1zZy5jb25uZWN0aW9uSWQgKyBcIicgb24gJ3N0cmVhbVByb3BlcnR5Q2hhbmdlZCcgZXZlbnRcIik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIC5jYXRjaChvcGVuVmlkdUVycm9yID0+IHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKG9wZW5WaWR1RXJyb3IpO1xuICAgICAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHJlY3ZJY2VDYW5kaWRhdGUobXNnKTogdm9pZCB7XG4gICAgICAgIGNvbnN0IGNhbmRpZGF0ZSA9IHtcbiAgICAgICAgICAgIGNhbmRpZGF0ZTogbXNnLmNhbmRpZGF0ZSxcbiAgICAgICAgICAgIHNkcE1pZDogbXNnLnNkcE1pZCxcbiAgICAgICAgICAgIHNkcE1MaW5lSW5kZXg6IG1zZy5zZHBNTGluZUluZGV4LFxuICAgICAgICAgICAgdG9KU09OOiAoKSA9PiB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHsgY2FuZGlkYXRlOiBtc2cuY2FuZGlkYXRlIH07XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuZ2V0Q29ubmVjdGlvbihtc2cuZW5kcG9pbnROYW1lLCAnQ29ubmVjdGlvbiBub3QgZm91bmQgZm9yIGVuZHBvaW50ICcgKyBtc2cuZW5kcG9pbnROYW1lICsgJy4gSWNlIGNhbmRpZGF0ZSB3aWxsIGJlIGlnbm9yZWQ6ICcgKyBjYW5kaWRhdGUpXG4gICAgICAgICAgICAudGhlbihjb25uZWN0aW9uID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCBzdHJlYW0gPSBjb25uZWN0aW9uLnN0cmVhbTtcbiAgICAgICAgICAgICAgICBzdHJlYW0uZ2V0V2ViUnRjUGVlcigpLmFkZEljZUNhbmRpZGF0ZShjYW5kaWRhdGUpLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcignRXJyb3IgYWRkaW5nIGNhbmRpZGF0ZSBmb3IgJyArIHN0cmVhbS5zdHJlYW1JZFxuICAgICAgICAgICAgICAgICAgICAgICAgKyAnIHN0cmVhbSBvZiBlbmRwb2ludCAnICsgbXNnLmVuZHBvaW50TmFtZSArICc6ICcgKyBlcnJvcik7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLmNhdGNoKG9wZW5WaWR1RXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3Iob3BlblZpZHVFcnJvcik7XG4gICAgICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgb25TZXNzaW9uQ2xvc2VkKG1zZyk6IHZvaWQge1xuICAgICAgICBjb25zb2xlLmluZm8oJ1Nlc3Npb24gY2xvc2VkOiAnICsgSlNPTi5zdHJpbmdpZnkobXNnKSk7XG4gICAgICAgIGNvbnN0IHMgPSBtc2cuc2Vzc2lvbklkO1xuICAgICAgICBpZiAocyAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnc2Vzc2lvbi1jbG9zZWQnLCBbe1xuICAgICAgICAgICAgICAgIHNlc3Npb246IHNcbiAgICAgICAgICAgIH1dKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvbnNvbGUud2FybignU2Vzc2lvbiB1bmRlZmluZWQgb24gc2Vzc2lvbiBjbG9zZWQnLCBtc2cpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIG9uTG9zdENvbm5lY3Rpb24oKTogdm9pZCB7XG5cbiAgICAgICAgLyppZiAoIXRoaXMuY29ubmVjdGlvbikge1xuXG4gICAgICAgICAgICBjb25zb2xlLndhcm4oJ05vdCBjb25uZWN0ZWQgdG8gc2Vzc2lvbjogaWYgeW91IGFyZSBub3QgZGVidWdnaW5nLCB0aGlzIGlzIHByb2JhYmx5IGEgY2VydGlmaWNhdGUgZXJyb3InKTtcblxuICAgICAgICAgICAgY29uc3QgdXJsID0gJ2h0dHBzOi8vJyArIHRoaXMub3BlbnZpZHUuZ2V0V3NVcmkoKS5zcGxpdCgnd3NzOi8vJylbMV0uc3BsaXQoJy9vcGVudmlkdScpWzBdO1xuICAgICAgICAgICAgaWYgKHdpbmRvdy5jb25maXJtKCdJZiB5b3UgYXJlIG5vdCBkZWJ1Z2dpbmcsIHRoaXMgaXMgcHJvYmFibHkgYSBjZXJ0aWZpY2F0ZSBlcnJvciBhdCBcXFwiJyArIHVybCArICdcXFwiXFxuXFxuQ2xpY2sgT0sgdG8gbmF2aWdhdGUgYW5kIGFjY2VwdCBpdCcpKSB7XG4gICAgICAgICAgICAgICAgbG9jYXRpb24uYXNzaWduKHVybCArICcvYWNjZXB0LWNlcnRpZmljYXRlJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH0qL1xuXG4gICAgICAgIGNvbnNvbGUud2FybignTG9zdCBjb25uZWN0aW9uIGluIFNlc3Npb24gJyArIHRoaXMuc2Vzc2lvbklkKTtcbiAgICAgICAgaWYgKCEhdGhpcy5zZXNzaW9uSWQgJiYgIXRoaXMuY29ubmVjdGlvbi5kaXNwb3NlZCkge1xuICAgICAgICAgICAgdGhpcy5sZWF2ZSh0cnVlLCAnbmV0d29ya0Rpc2Nvbm5lY3QnKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvblJlY292ZXJlZENvbm5lY3Rpb24oKTogdm9pZCB7XG4gICAgICAgIGNvbnNvbGUud2FybignUmVjb3ZlcmVkIGNvbm5lY3Rpb24gaW4gU2Vzc2lvbiAnICsgdGhpcy5zZXNzaW9uSWQpO1xuICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnY29ubmVjdGlvblJlY292ZXJlZCcsIFtdKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgb25NZWRpYUVycm9yKHBhcmFtcyk6IHZvaWQge1xuXG4gICAgICAgIGNvbnNvbGUuZXJyb3IoJ01lZGlhIGVycm9yOiAnICsgSlNPTi5zdHJpbmdpZnkocGFyYW1zKSk7XG4gICAgICAgIGNvbnN0IGVyciA9IHBhcmFtcy5lcnJvcjtcbiAgICAgICAgaWYgKGVycikge1xuICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ2Vycm9yLW1lZGlhJywgW3tcbiAgICAgICAgICAgICAgICBlcnJvcjogZXJyXG4gICAgICAgICAgICB9XSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjb25zb2xlLndhcm4oJ1JlY2VpdmVkIHVuZGVmaW5lZCBtZWRpYSBlcnJvci4gUGFyYW1zOicsIHBhcmFtcyk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgb25SZWNvcmRpbmdTdGFydGVkKHJlc3BvbnNlKTogdm9pZCB7XG4gICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdyZWNvcmRpbmdTdGFydGVkJywgW25ldyBSZWNvcmRpbmdFdmVudCh0aGlzLCAncmVjb3JkaW5nU3RhcnRlZCcsIHJlc3BvbnNlLmlkLCByZXNwb25zZS5uYW1lKV0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvblJlY29yZGluZ1N0b3BwZWQocmVzcG9uc2UpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3JlY29yZGluZ1N0b3BwZWQnLCBbbmV3IFJlY29yZGluZ0V2ZW50KHRoaXMsICdyZWNvcmRpbmdTdG9wcGVkJywgcmVzcG9uc2UuaWQsIHJlc3BvbnNlLm5hbWUpXSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGVtaXRFdmVudCh0eXBlOiBzdHJpbmcsIGV2ZW50QXJyYXk6IGFueVtdKTogdm9pZCB7XG4gICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KHR5cGUsIGV2ZW50QXJyYXkpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBsZWF2ZShmb3JjZWQ6IGJvb2xlYW4sIHJlYXNvbjogc3RyaW5nKTogdm9pZCB7XG5cbiAgICAgICAgZm9yY2VkID0gISFmb3JjZWQ7XG4gICAgICAgIGNvbnNvbGUuaW5mbygnTGVhdmluZyBTZXNzaW9uIChmb3JjZWQ9JyArIGZvcmNlZCArICcpJyk7XG5cbiAgICAgICAgaWYgKCEhdGhpcy5jb25uZWN0aW9uKSB7XG4gICAgICAgICAgICBpZiAoIXRoaXMuY29ubmVjdGlvbi5kaXNwb3NlZCAmJiAhZm9yY2VkKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5vcGVudmlkdS5zZW5kUmVxdWVzdCgnbGVhdmVSb29tJywgKGVycm9yLCByZXNwb25zZSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBpZiAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHRoaXMub3BlbnZpZHUuY2xvc2VXcygpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLm9wZW52aWR1LmNsb3NlV3MoKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5zdG9wUHVibGlzaGVyU3RyZWFtKHJlYXNvbik7XG5cbiAgICAgICAgICAgIGlmICghdGhpcy5jb25uZWN0aW9uLmRpc3Bvc2VkKSB7XG4gICAgICAgICAgICAgICAgLy8gTWFrZSBTZXNzaW9uIG9iamVjdCBkaXNwYXRjaCAnc2Vzc2lvbkRpc2Nvbm5lY3RlZCcgZXZlbnQgKGlmIGl0IGlzIG5vdCBhbHJlYWR5IGRpc3Bvc2VkKVxuICAgICAgICAgICAgICAgIGNvbnN0IHNlc3Npb25EaXNjb25uZWN0RXZlbnQgPSBuZXcgU2Vzc2lvbkRpc2Nvbm5lY3RlZEV2ZW50KHRoaXMsIHJlYXNvbik7XG4gICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3Nlc3Npb25EaXNjb25uZWN0ZWQnLCBbc2Vzc2lvbkRpc2Nvbm5lY3RFdmVudF0pO1xuICAgICAgICAgICAgICAgIHNlc3Npb25EaXNjb25uZWN0RXZlbnQuY2FsbERlZmF1bHRCZWhhdmlvcigpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY29uc29sZS53YXJuKCdZb3Ugd2VyZSBub3QgY29ubmVjdGVkIHRvIHRoZSBzZXNzaW9uICcgKyB0aGlzLnNlc3Npb25JZCk7XG4gICAgICAgIH1cbiAgICB9XG5cblxuICAgIC8qIFByaXZhdGUgbWV0aG9kcyAqL1xuXG4gICAgcHJpdmF0ZSBjb25uZWN0QXV4KHRva2VuOiBzdHJpbmcpOiBQcm9taXNlPGFueT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5vcGVudmlkdS5zdGFydFdzKChlcnJvcikgPT4ge1xuICAgICAgICAgICAgICAgIGlmICghIWVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcblxuICAgICAgICAgICAgICAgICAgICBjb25zdCBqb2luUGFyYW1zID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgdG9rZW46ICghIXRva2VuKSA/IHRva2VuIDogJycsXG4gICAgICAgICAgICAgICAgICAgICAgICBzZXNzaW9uOiB0aGlzLnNlc3Npb25JZCxcbiAgICAgICAgICAgICAgICAgICAgICAgIG1ldGFkYXRhOiAhIXRoaXMub3B0aW9ucy5tZXRhZGF0YSA/IHRoaXMub3B0aW9ucy5tZXRhZGF0YSA6ICcnLFxuICAgICAgICAgICAgICAgICAgICAgICAgc2VjcmV0OiB0aGlzLm9wZW52aWR1LmdldFNlY3JldCgpLFxuICAgICAgICAgICAgICAgICAgICAgICAgcmVjb3JkZXI6IHRoaXMub3BlbnZpZHUuZ2V0UmVjb3JkZXIoKSxcbiAgICAgICAgICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgICAgICAgICB0aGlzLm9wZW52aWR1LnNlbmRSZXF1ZXN0KCdqb2luUm9vbScsIGpvaW5QYXJhbXMsIChlcnJvciwgcmVzcG9uc2UpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghIWVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBJbml0aWFsaXplIGNhcGFiaWxpdGllcyBvYmplY3Qgd2l0aCB0aGUgcm9sZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY2FwYWJpbGl0aWVzID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdWJzY3JpYmU6IHRydWUsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHB1Ymxpc2g6IHRoaXMub3BlbnZpZHUucm9sZSAhPT0gJ1NVQlNDUklCRVInLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3JjZVVucHVibGlzaDogdGhpcy5vcGVudmlkdS5yb2xlID09PSAnTU9ERVJBVE9SJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yY2VEaXNjb25uZWN0OiB0aGlzLm9wZW52aWR1LnJvbGUgPT09ICdNT0RFUkFUT1InXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEluaXRpYWxpemUgbG9jYWwgQ29ubmVjdGlvbiBvYmplY3Qgd2l0aCB2YWx1ZXMgcmV0dXJuZWQgYnkgb3BlbnZpZHUtc2VydmVyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jb25uZWN0aW9uID0gbmV3IENvbm5lY3Rpb24odGhpcyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jb25uZWN0aW9uLmNvbm5lY3Rpb25JZCA9IHJlc3BvbnNlLmlkO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY29ubmVjdGlvbi5kYXRhID0gcmVzcG9uc2UubWV0YWRhdGE7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBJbml0aWFsaXplIHJlbW90ZSBDb25uZWN0aW9ucyB3aXRoIHZhbHVlIHJldHVybmVkIGJ5IG9wZW52aWR1LXNlcnZlclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGV2ZW50cyA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29ubmVjdGlvbnM6IG5ldyBBcnJheTxDb25uZWN0aW9uPigpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJlYW1zOiBuZXcgQXJyYXk8U3RyZWFtPigpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBleGlzdGluZ1BhcnRpY2lwYW50czogQ29ubmVjdGlvbk9wdGlvbnNbXSA9IHJlc3BvbnNlLnZhbHVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV4aXN0aW5nUGFydGljaXBhbnRzLmZvckVhY2gocGFydGljaXBhbnQgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBjb25uZWN0aW9uID0gbmV3IENvbm5lY3Rpb24odGhpcywgcGFydGljaXBhbnQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnJlbW90ZUNvbm5lY3Rpb25zW2Nvbm5lY3Rpb24uY29ubmVjdGlvbklkXSA9IGNvbm5lY3Rpb247XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV2ZW50cy5jb25uZWN0aW9ucy5wdXNoKGNvbm5lY3Rpb24pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoISFjb25uZWN0aW9uLnN0cmVhbSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5yZW1vdGVTdHJlYW1zQ3JlYXRlZFtjb25uZWN0aW9uLnN0cmVhbS5zdHJlYW1JZF0gPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXZlbnRzLnN0cmVhbXMucHVzaChjb25uZWN0aW9uLnN0cmVhbSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIE93biAnY29ubmVjdGlvbkNyZWF0ZWQnIGV2ZW50XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ2Nvbm5lY3Rpb25DcmVhdGVkJywgW25ldyBDb25uZWN0aW9uRXZlbnQoZmFsc2UsIHRoaXMsICdjb25uZWN0aW9uQ3JlYXRlZCcsIHRoaXMuY29ubmVjdGlvbiwgJycpXSk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBPbmUgJ2Nvbm5lY3Rpb25DcmVhdGVkJyBldmVudCBmb3IgZWFjaCBleGlzdGluZyBjb25uZWN0aW9uIGluIHRoZSBzZXNzaW9uXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZXZlbnRzLmNvbm5lY3Rpb25zLmZvckVhY2goY29ubmVjdGlvbiA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdjb25uZWN0aW9uQ3JlYXRlZCcsIFtuZXcgQ29ubmVjdGlvbkV2ZW50KGZhbHNlLCB0aGlzLCAnY29ubmVjdGlvbkNyZWF0ZWQnLCBjb25uZWN0aW9uLCAnJyldKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIE9uZSAnc3RyZWFtQ3JlYXRlZCcgZXZlbnQgZm9yIGVhY2ggYWN0aXZlIHN0cmVhbSBpbiB0aGUgc2Vzc2lvblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV2ZW50cy5zdHJlYW1zLmZvckVhY2goc3RyZWFtID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3N0cmVhbUNyZWF0ZWQnLCBbbmV3IFN0cmVhbUV2ZW50KGZhbHNlLCB0aGlzLCAnc3RyZWFtQ3JlYXRlZCcsIHN0cmVhbSwgJycpXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBwcml2YXRlIHN0b3BQdWJsaXNoZXJTdHJlYW0ocmVhc29uOiBzdHJpbmcpIHtcbiAgICAgICAgaWYgKCEhdGhpcy5jb25uZWN0aW9uLnN0cmVhbSkge1xuICAgICAgICAgICAgLy8gRGlzcG9zZSBQdWJsaXNoZXIncyAgbG9jYWwgc3RyZWFtXG4gICAgICAgICAgICB0aGlzLmNvbm5lY3Rpb24uc3RyZWFtLmRpc3Bvc2VXZWJSdGNQZWVyKCk7XG4gICAgICAgICAgICBpZiAodGhpcy5jb25uZWN0aW9uLnN0cmVhbS5pc0xvY2FsU3RyZWFtUHVibGlzaGVkKSB7XG4gICAgICAgICAgICAgICAgLy8gTWFrZSBQdWJsaXNoZXIgb2JqZWN0IGRpc3BhdGNoICdzdHJlYW1EZXN0cm95ZWQnIGV2ZW50IGlmIHRoZSBTdHJlYW0gd2FzIHB1Ymxpc2hlZFxuICAgICAgICAgICAgICAgIHRoaXMuY29ubmVjdGlvbi5zdHJlYW0uZWUuZW1pdEV2ZW50KCdsb2NhbC1zdHJlYW0tZGVzdHJveWVkJywgW3JlYXNvbl0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBzdHJpbmdDbGllbnRNZXRhZGF0YShtZXRhZGF0YTogYW55KTogc3RyaW5nIHtcbiAgICAgICAgaWYgKHR5cGVvZiBtZXRhZGF0YSAhPT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgIHJldHVybiBKU09OLnN0cmluZ2lmeShtZXRhZGF0YSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gbWV0YWRhdGE7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIGdldENvbm5lY3Rpb24oY29ubmVjdGlvbklkOiBzdHJpbmcsIGVycm9yTWVzc2FnZTogc3RyaW5nKTogUHJvbWlzZTxDb25uZWN0aW9uPiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZTxDb25uZWN0aW9uPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICBjb25zdCBjb25uZWN0aW9uID0gdGhpcy5yZW1vdGVDb25uZWN0aW9uc1tjb25uZWN0aW9uSWRdO1xuICAgICAgICAgICAgaWYgKCEhY29ubmVjdGlvbikge1xuICAgICAgICAgICAgICAgIC8vIFJlc29sdmUgcmVtb3RlIGNvbm5lY3Rpb25cbiAgICAgICAgICAgICAgICByZXNvbHZlKGNvbm5lY3Rpb24pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5jb25uZWN0aW9uLmNvbm5lY3Rpb25JZCA9PT0gY29ubmVjdGlvbklkKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIFJlc29sdmUgbG9jYWwgY29ubmVjdGlvblxuICAgICAgICAgICAgICAgICAgICByZXNvbHZlKHRoaXMuY29ubmVjdGlvbik7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gQ29ubmVjdGlvbiBub3QgZm91bmQuIFJlamVjdCB3aXRoIE9wZW5WaWR1RXJyb3JcbiAgICAgICAgICAgICAgICAgICAgcmVqZWN0KG5ldyBPcGVuVmlkdUVycm9yKE9wZW5WaWR1RXJyb3JOYW1lLkdFTkVSSUNfRVJST1IsIGVycm9yTWVzc2FnZSkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBnZXRSZW1vdGVDb25uZWN0aW9uKGNvbm5lY3Rpb25JZDogc3RyaW5nLCBlcnJvck1lc3NhZ2U6IHN0cmluZyk6IFByb21pc2U8Q29ubmVjdGlvbj4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2U8Q29ubmVjdGlvbj4oKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgY29uc3QgY29ubmVjdGlvbiA9IHRoaXMucmVtb3RlQ29ubmVjdGlvbnNbY29ubmVjdGlvbklkXTtcbiAgICAgICAgICAgIGlmICghIWNvbm5lY3Rpb24pIHtcbiAgICAgICAgICAgICAgICAvLyBSZXNvbHZlIHJlbW90ZSBjb25uZWN0aW9uXG4gICAgICAgICAgICAgICAgcmVzb2x2ZShjb25uZWN0aW9uKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgLy8gUmVtb3RlIGNvbm5lY3Rpb24gbm90IGZvdW5kLiBSZWplY3Qgd2l0aCBPcGVuVmlkdUVycm9yXG4gICAgICAgICAgICAgICAgcmVqZWN0KG5ldyBPcGVuVmlkdUVycm9yKE9wZW5WaWR1RXJyb3JOYW1lLkdFTkVSSUNfRVJST1IsIGVycm9yTWVzc2FnZSkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBwcml2YXRlIHByb2Nlc3NUb2tlbih0b2tlbjogc3RyaW5nKTogdm9pZCB7XG4gICAgICAgIGNvbnN0IHVybCA9IG5ldyBVUkwodG9rZW4pO1xuICAgICAgICB0aGlzLnNlc3Npb25JZCA9IDxzdHJpbmc+dXJsLnNlYXJjaFBhcmFtcy5nZXQoJ3Nlc3Npb25JZCcpO1xuICAgICAgICBjb25zdCBzZWNyZXQgPSB1cmwuc2VhcmNoUGFyYW1zLmdldCgnc2VjcmV0Jyk7XG4gICAgICAgIGNvbnN0IHJlY29yZGVyID0gdXJsLnNlYXJjaFBhcmFtcy5nZXQoJ3JlY29yZGVyJyk7XG4gICAgICAgIGNvbnN0IHR1cm5Vc2VybmFtZSA9IHVybC5zZWFyY2hQYXJhbXMuZ2V0KCd0dXJuVXNlcm5hbWUnKTtcbiAgICAgICAgY29uc3QgdHVybkNyZWRlbnRpYWwgPSB1cmwuc2VhcmNoUGFyYW1zLmdldCgndHVybkNyZWRlbnRpYWwnKTtcbiAgICAgICAgY29uc3Qgcm9sZSA9IHVybC5zZWFyY2hQYXJhbXMuZ2V0KCdyb2xlJyk7XG5cbiAgICAgICAgaWYgKCEhc2VjcmV0KSB7XG4gICAgICAgICAgICB0aGlzLm9wZW52aWR1LnNlY3JldCA9IHNlY3JldDtcbiAgICAgICAgfVxuICAgICAgICBpZiAoISFyZWNvcmRlcikge1xuICAgICAgICAgICAgdGhpcy5vcGVudmlkdS5yZWNvcmRlciA9IHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCEhdHVyblVzZXJuYW1lICYmICEhdHVybkNyZWRlbnRpYWwpIHtcbiAgICAgICAgICAgIGNvbnN0IHN0dW5VcmwgPSAnc3R1bjonICsgdXJsLmhvc3RuYW1lICsgJzozNDc4JztcbiAgICAgICAgICAgIGNvbnN0IHR1cm5VcmwxID0gJ3R1cm46JyArIHVybC5ob3N0bmFtZSArICc6MzQ3OCc7XG4gICAgICAgICAgICBjb25zdCB0dXJuVXJsMiA9IHR1cm5VcmwxICsgJz90cmFuc3BvcnQ9dGNwJztcbiAgICAgICAgICAgIHRoaXMub3BlbnZpZHUuaWNlU2VydmVycyA9IFtcbiAgICAgICAgICAgICAgICB7IHVybHM6IFtzdHVuVXJsXSB9LFxuICAgICAgICAgICAgICAgIHsgdXJsczogW3R1cm5VcmwxLCB0dXJuVXJsMl0sIHVzZXJuYW1lOiB0dXJuVXNlcm5hbWUsIGNyZWRlbnRpYWw6IHR1cm5DcmVkZW50aWFsIH1cbiAgICAgICAgICAgIF07XG4gICAgICAgICAgICBjb25zb2xlLmxvZygnVFVSTiB0ZW1wIGNyZWRlbnRpYWxzIFsnICsgdHVyblVzZXJuYW1lICsgJzonICsgdHVybkNyZWRlbnRpYWwgKyAnXScpO1xuICAgICAgICB9XG4gICAgICAgIGlmICghIXJvbGUpIHtcbiAgICAgICAgICAgIHRoaXMub3BlbnZpZHUucm9sZSA9IHJvbGU7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLm9wZW52aWR1LndzVXJpID0gJ3dzczovLycgKyB1cmwuaG9zdCArICcvb3BlbnZpZHUnO1xuICAgIH1cblxufSIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTctMjAxOCBPcGVuVmlkdSAoaHR0cHM6Ly9vcGVudmlkdS5pby8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuaW1wb3J0IHsgQ29ubmVjdGlvbiB9IGZyb20gJy4vQ29ubmVjdGlvbic7XG5pbXBvcnQgeyBTZXNzaW9uIH0gZnJvbSAnLi9TZXNzaW9uJztcbmltcG9ydCB7IFN0cmVhbU1hbmFnZXIgfSBmcm9tICcuL1N0cmVhbU1hbmFnZXInO1xuaW1wb3J0IHsgSW5ib3VuZFN0cmVhbU9wdGlvbnMgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHJpdmF0ZS9JbmJvdW5kU3RyZWFtT3B0aW9ucyc7XG5pbXBvcnQgeyBPdXRib3VuZFN0cmVhbU9wdGlvbnMgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHJpdmF0ZS9PdXRib3VuZFN0cmVhbU9wdGlvbnMnO1xuaW1wb3J0IHsgV2ViUnRjUGVlciwgV2ViUnRjUGVlclNlbmRvbmx5LCBXZWJSdGNQZWVyUmVjdm9ubHksIFdlYlJ0Y1BlZXJTZW5kcmVjdiB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvV2ViUnRjUGVlci9XZWJSdGNQZWVyJztcbmltcG9ydCB7IFdlYlJ0Y1N0YXRzIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9XZWJSdGNTdGF0cy9XZWJSdGNTdGF0cyc7XG5pbXBvcnQgeyBQdWJsaXNoZXJTcGVha2luZ0V2ZW50IH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvUHVibGlzaGVyU3BlYWtpbmdFdmVudCc7XG5cbmltcG9ydCBFdmVudEVtaXR0ZXIgPSByZXF1aXJlKCd3b2xmeTg3LWV2ZW50ZW1pdHRlcicpO1xuaW1wb3J0IGhhcmsgPSByZXF1aXJlKCdoYXJrJyk7XG5pbXBvcnQgeyBPcGVuVmlkdUVycm9yLCBPcGVuVmlkdUVycm9yTmFtZSB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRW51bXMvT3BlblZpZHVFcnJvcic7XG5cblxuLyoqXG4gKiBSZXByZXNlbnRzIGVhY2ggb25lIG9mIHRoZSBtZWRpYSBzdHJlYW1zIGF2YWlsYWJsZSBpbiBPcGVuVmlkdSBTZXJ2ZXIgZm9yIGNlcnRhaW4gc2Vzc2lvbi5cbiAqIEVhY2ggW1tQdWJsaXNoZXJdXSBhbmQgW1tTdWJzY3JpYmVyXV0gaGFzIGFuIGF0dHJpYnV0ZSBvZiB0eXBlIFN0cmVhbSwgYXMgdGhleSBnaXZlIGFjY2Vzc1xuICogdG8gb25lIG9mIHRoZW0gKHNlbmRpbmcgYW5kIHJlY2VpdmluZyBpdCwgcmVzcGVjdGl2ZWx5KVxuICovXG5leHBvcnQgY2xhc3MgU3RyZWFtIHtcblxuICAgIC8qKlxuICAgICAqIFRoZSBDb25uZWN0aW9uIG9iamVjdCB0aGF0IGlzIHB1Ymxpc2hpbmcgdGhlIHN0cmVhbVxuICAgICAqL1xuICAgIGNvbm5lY3Rpb246IENvbm5lY3Rpb247XG5cbiAgICAvKipcbiAgICAgKiBGcmFtZSByYXRlIG9mIHRoZSB2aWRlbyBpbiBmcmFtZXMgcGVyIHNlY29uZC4gVGhpcyBwcm9wZXJ0eSBpcyBvbmx5IGRlZmluZWQgaWYgdGhlIFtbUHVibGlzaGVyXV0gb2ZcbiAgICAgKiB0aGUgc3RyZWFtIHdhcyBpbml0aWFsaXplZCBwYXNzaW5nIGEgX2ZyYW1lUmF0ZV8gcHJvcGVydHkgb24gW1tPcGVuVmlkdS5pbml0UHVibGlzaGVyXV0gbWV0aG9kXG4gICAgICovXG4gICAgZnJhbWVSYXRlPzogbnVtYmVyO1xuXG4gICAgLyoqXG4gICAgICogV2hldGhlciB0aGUgc3RyZWFtIGhhcyBhIHZpZGVvIHRyYWNrIG9yIG5vdFxuICAgICAqL1xuICAgIGhhc1ZpZGVvOiBib29sZWFuO1xuXG4gICAgLyoqXG4gICAgICogV2hldGhlciB0aGUgc3RyZWFtIGhhcyBhbiBhdWRpbyB0cmFjayBvciBub3RcbiAgICAgKi9cbiAgICBoYXNBdWRpbzogYm9vbGVhbjtcblxuICAgIC8qKlxuICAgICAqIFdoZXRoZXIgdGhlIHN0cmVhbSBoYXMgdGhlIHZpZGVvIHRyYWNrIG11dGVkIG9yIHVubXV0ZWQuIElmIFtbaGFzVmlkZW9dXSBpcyBmYWxzZSwgdGhpcyBwcm9wZXJ0eSBpcyB1bmRlZmluZWQuXG4gICAgICpcbiAgICAgKiBUaGlzIHByb3BlcnR5IG1heSBjaGFuZ2UgaWYgdGhlIFB1Ymxpc2hlciBwdWJsaXNoaW5nIHRoZSBzdHJlYW0gY2FsbHMgW1tQdWJsaXNoZXIucHVibGlzaFZpZGVvXV0uIFdoZW5ldmVyIHRoaXMgaGFwcGVucyBhIFtbU3RyZWFtUHJvcGVydHlDaGFuZ2VkRXZlbnRdXSB3aWxsIGJlIGRpc3BhdGNoZWRcbiAgICAgKiBieSB0aGUgU2Vzc2lvbiBvYmplY3QgYXMgd2VsbCBhcyBieSB0aGUgYWZmZWN0ZWQgU3Vic2NyaWJlci9QdWJsaXNoZXIgb2JqZWN0XG4gICAgICovXG4gICAgdmlkZW9BY3RpdmU6IGJvb2xlYW47XG5cbiAgICAvKipcbiAgICAgKiBXaGV0aGVyIHRoZSBzdHJlYW0gaGFzIHRoZSBhdWRpbyB0cmFjayBtdXRlZCBvciB1bm11dGVkLiBJZiBbW2hhc0F1ZGlvXV0gaXMgZmFsc2UsIHRoaXMgcHJvcGVydHkgaXMgdW5kZWZpbmVkXG4gICAgICpcbiAgICAgKiBUaGlzIHByb3BlcnR5IG1heSBjaGFuZ2UgaWYgdGhlIFB1Ymxpc2hlciBwdWJsaXNoaW5nIHRoZSBzdHJlYW0gY2FsbHMgW1tQdWJsaXNoZXIucHVibGlzaEF1ZGlvXV0uIFdoZW5ldmVyIHRoaXMgaGFwcGVucyBhIFtbU3RyZWFtUHJvcGVydHlDaGFuZ2VkRXZlbnRdXSB3aWxsIGJlIGRpc3BhdGNoZWRcbiAgICAgKiBieSB0aGUgU2Vzc2lvbiBvYmplY3QgYXMgd2VsbCBhcyBieSB0aGUgYWZmZWN0ZWQgU3Vic2NyaWJlci9QdWJsaXNoZXIgb2JqZWN0XG4gICAgICovXG4gICAgYXVkaW9BY3RpdmU6IGJvb2xlYW47XG5cbiAgICAvKipcbiAgICAgKiBVbmlxdWUgaWRlbnRpZmllciBvZiB0aGUgc3RyZWFtXG4gICAgICovXG4gICAgc3RyZWFtSWQ6IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIGBcIkNBTUVSQVwiYCwgYFwiU0NSRUVOXCJgIG9yIGBcIkNVU1RPTVwiYCAodGhlIGxhdHRlciB3aGVuIFtbUHVibGlzaGVyUHJvcGVydGllcy52aWRlb1NvdXJjZV1dIGlzIGEgTWVkaWFTdHJlYW1UcmFjayB3aGVuIGNhbGxpbmcgW1tPcGVuVmlkdS5pbml0UHVibGlzaGVyXV0pLlxuICAgICAqIElmIFtbaGFzVmlkZW9dXSBpcyBmYWxzZSwgdGhpcyBwcm9wZXJ0eSBpcyB1bmRlZmluZWRcbiAgICAgKi9cbiAgICB0eXBlT2ZWaWRlbz86IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIFN0cmVhbU1hbmFnZXIgb2JqZWN0IChbW1B1Ymxpc2hlcl1dIG9yIFtbU3Vic2NyaWJlcl1dKSBpbiBjaGFyZ2Ugb2YgZGlzcGxheWluZyB0aGlzIHN0cmVhbSBpbiB0aGUgRE9NXG4gICAgICovXG4gICAgc3RyZWFtTWFuYWdlcjogU3RyZWFtTWFuYWdlcjtcblxuICAgIC8qKlxuICAgICAqIFdpZHRoIGFuZCBoZWlnaHQgaW4gcGl4ZWxzIG9mIHRoZSBlbmNvZGVkIHZpZGVvIHN0cmVhbS4gSWYgW1toYXNWaWRlb11dIGlzIGZhbHNlLCB0aGlzIHByb3BlcnR5IGlzIHVuZGVmaW5lZFxuICAgICAqXG4gICAgICogVGhpcyBwcm9wZXJ0eSBtYXkgY2hhbmdlIGlmIHRoZSBQdWJsaXNoZXIgdGhhdCBpcyBwdWJsaXNoaW5nOlxuICAgICAqIC0gSWYgaXQgaXMgYSBtb2JpbGUgZGV2aWNlLCB3aGVuZXZlciB0aGUgdXNlciByb3RhdGVzIHRoZSBkZXZpY2UuXG4gICAgICogLSBJZiBpdCBpcyBzY3JlZW4tc2hhcmluZywgd2hlbmV2ZXIgdGhlIHVzZXIgY2hhbmdlcyB0aGUgc2l6ZSBvZiB0aGUgY2FwdHVyZWQgd2luZG93LlxuICAgICAqXG4gICAgICogV2hlbmV2ZXIgdGhpcyBoYXBwZW5zIGEgW1tTdHJlYW1Qcm9wZXJ0eUNoYW5nZWRFdmVudF1dIHdpbGwgYmUgZGlzcGF0Y2hlZCBieSB0aGUgU2Vzc2lvbiBvYmplY3QgYXMgd2VsbCBhcyBieSB0aGUgYWZmZWN0ZWQgU3Vic2NyaWJlci9QdWJsaXNoZXIgb2JqZWN0XG4gICAgICovXG4gICAgdmlkZW9EaW1lbnNpb25zOiB7IHdpZHRoOiBudW1iZXIsIGhlaWdodDogbnVtYmVyIH07XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgZWUgPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG5cbiAgICBwcml2YXRlIHdlYlJ0Y1BlZXI6IFdlYlJ0Y1BlZXI7XG4gICAgcHJpdmF0ZSBtZWRpYVN0cmVhbTogTWVkaWFTdHJlYW07XG4gICAgcHJpdmF0ZSB3ZWJSdGNTdGF0czogV2ViUnRjU3RhdHM7XG5cbiAgICBwcml2YXRlIGlzU3Vic2NyaWJlVG9SZW1vdGUgPSBmYWxzZTtcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBpc0xvY2FsU3RyZWFtUmVhZHlUb1B1Ymxpc2ggPSBmYWxzZTtcbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgaXNMb2NhbFN0cmVhbVB1Ymxpc2hlZCA9IGZhbHNlO1xuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBwdWJsaXNoZWRPbmNlID0gZmFsc2U7XG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHNlc3Npb246IFNlc3Npb247XG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGluYm91bmRTdHJlYW1PcHRzOiBJbmJvdW5kU3RyZWFtT3B0aW9ucztcbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgb3V0Ym91bmRTdHJlYW1PcHRzOiBPdXRib3VuZFN0cmVhbU9wdGlvbnM7XG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHNwZWVjaEV2ZW50OiBhbnk7XG5cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3RvcihzZXNzaW9uOiBTZXNzaW9uLCBvcHRpb25zOiBJbmJvdW5kU3RyZWFtT3B0aW9ucyB8IE91dGJvdW5kU3RyZWFtT3B0aW9ucyB8IHt9KSB7XG5cbiAgICAgICAgdGhpcy5zZXNzaW9uID0gc2Vzc2lvbjtcblxuICAgICAgICBpZiAob3B0aW9ucy5oYXNPd25Qcm9wZXJ0eSgnaWQnKSkge1xuICAgICAgICAgICAgLy8gSW5ib3VuZFN0cmVhbU9wdGlvbnM6IHN0cmVhbSBiZWxvbmdzIHRvIGEgU3Vic2NyaWJlclxuICAgICAgICAgICAgdGhpcy5pbmJvdW5kU3RyZWFtT3B0cyA9IDxJbmJvdW5kU3RyZWFtT3B0aW9ucz5vcHRpb25zO1xuICAgICAgICAgICAgdGhpcy5zdHJlYW1JZCA9IHRoaXMuaW5ib3VuZFN0cmVhbU9wdHMuaWQ7XG4gICAgICAgICAgICB0aGlzLmhhc0F1ZGlvID0gdGhpcy5pbmJvdW5kU3RyZWFtT3B0cy5oYXNBdWRpbztcbiAgICAgICAgICAgIHRoaXMuaGFzVmlkZW8gPSB0aGlzLmluYm91bmRTdHJlYW1PcHRzLmhhc1ZpZGVvO1xuICAgICAgICAgICAgaWYgKHRoaXMuaGFzQXVkaW8pIHtcbiAgICAgICAgICAgICAgICB0aGlzLmF1ZGlvQWN0aXZlID0gdGhpcy5pbmJvdW5kU3RyZWFtT3B0cy5hdWRpb0FjdGl2ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0aGlzLmhhc1ZpZGVvKSB7XG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb0FjdGl2ZSA9IHRoaXMuaW5ib3VuZFN0cmVhbU9wdHMudmlkZW9BY3RpdmU7XG4gICAgICAgICAgICAgICAgdGhpcy50eXBlT2ZWaWRlbyA9ICghdGhpcy5pbmJvdW5kU3RyZWFtT3B0cy50eXBlT2ZWaWRlbykgPyB1bmRlZmluZWQgOiB0aGlzLmluYm91bmRTdHJlYW1PcHRzLnR5cGVPZlZpZGVvO1xuICAgICAgICAgICAgICAgIHRoaXMuZnJhbWVSYXRlID0gKHRoaXMuaW5ib3VuZFN0cmVhbU9wdHMuZnJhbWVSYXRlID09PSAtMSkgPyB1bmRlZmluZWQgOiB0aGlzLmluYm91bmRTdHJlYW1PcHRzLmZyYW1lUmF0ZTtcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvRGltZW5zaW9ucyA9IHRoaXMuaW5ib3VuZFN0cmVhbU9wdHMudmlkZW9EaW1lbnNpb25zO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gT3V0Ym91bmRTdHJlYW1PcHRpb25zOiBzdHJlYW0gYmVsb25ncyB0byBhIFB1Ymxpc2hlclxuICAgICAgICAgICAgdGhpcy5vdXRib3VuZFN0cmVhbU9wdHMgPSA8T3V0Ym91bmRTdHJlYW1PcHRpb25zPm9wdGlvbnM7XG5cbiAgICAgICAgICAgIHRoaXMuaGFzQXVkaW8gPSB0aGlzLmlzU2VuZEF1ZGlvKCk7XG4gICAgICAgICAgICB0aGlzLmhhc1ZpZGVvID0gdGhpcy5pc1NlbmRWaWRlbygpO1xuXG4gICAgICAgICAgICBpZiAodGhpcy5oYXNBdWRpbykge1xuICAgICAgICAgICAgICAgIHRoaXMuYXVkaW9BY3RpdmUgPSAhIXRoaXMub3V0Ym91bmRTdHJlYW1PcHRzLnB1Ymxpc2hlclByb3BlcnRpZXMucHVibGlzaEF1ZGlvO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRoaXMuaGFzVmlkZW8pIHtcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvQWN0aXZlID0gISF0aGlzLm91dGJvdW5kU3RyZWFtT3B0cy5wdWJsaXNoZXJQcm9wZXJ0aWVzLnB1Ymxpc2hWaWRlbztcbiAgICAgICAgICAgICAgICB0aGlzLmZyYW1lUmF0ZSA9IHRoaXMub3V0Ym91bmRTdHJlYW1PcHRzLnB1Ymxpc2hlclByb3BlcnRpZXMuZnJhbWVSYXRlO1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLm91dGJvdW5kU3RyZWFtT3B0cy5wdWJsaXNoZXJQcm9wZXJ0aWVzLnZpZGVvU291cmNlIGluc3RhbmNlb2YgTWVkaWFTdHJlYW1UcmFjaykge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnR5cGVPZlZpZGVvID0gJ0NVU1RPTSc7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy50eXBlT2ZWaWRlbyA9IHRoaXMuaXNTZW5kU2NyZWVuKCkgPyAnU0NSRUVOJyA6ICdDQU1FUkEnO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuZWUub24oJ21lZGlhc3RyZWFtLXVwZGF0ZWQnLCAoKSA9PiB7XG4gICAgICAgICAgICB0aGlzLnN0cmVhbU1hbmFnZXIudXBkYXRlTWVkaWFTdHJlYW0odGhpcy5tZWRpYVN0cmVhbSk7XG4gICAgICAgICAgICBjb25zb2xlLmRlYnVnKCdWaWRlbyBzcmNPYmplY3QgWycgKyB0aGlzLm1lZGlhU3RyZWFtICsgJ10gdXBkYXRlZCBpbiBzdHJlYW0gWycgKyB0aGlzLnN0cmVhbUlkICsgJ10nKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG5cbiAgICAvKiBIaWRkZW4gbWV0aG9kcyAqL1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGdldE1lZGlhU3RyZWFtKCk6IE1lZGlhU3RyZWFtIHtcbiAgICAgICAgcmV0dXJuIHRoaXMubWVkaWFTdHJlYW07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHNldE1lZGlhU3RyZWFtKG1lZGlhU3RyZWFtOiBNZWRpYVN0cmVhbSk6IHZvaWQge1xuICAgICAgICB0aGlzLm1lZGlhU3RyZWFtID0gbWVkaWFTdHJlYW07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHVwZGF0ZU1lZGlhU3RyZWFtSW5WaWRlb3MoKSB7XG4gICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdtZWRpYXN0cmVhbS11cGRhdGVkJyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGdldFdlYlJ0Y1BlZXIoKTogV2ViUnRjUGVlciB7XG4gICAgICAgIHJldHVybiB0aGlzLndlYlJ0Y1BlZXI7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGdldFJUQ1BlZXJDb25uZWN0aW9uKCk6IFJUQ1BlZXJDb25uZWN0aW9uIHtcbiAgICAgICAgcmV0dXJuIHRoaXMud2ViUnRjUGVlci5wYztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgc3Vic2NyaWJlVG9NeVJlbW90ZSh2YWx1ZTogYm9vbGVhbik6IHZvaWQge1xuICAgICAgICB0aGlzLmlzU3Vic2NyaWJlVG9SZW1vdGUgPSB2YWx1ZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgc2V0T3V0Ym91bmRTdHJlYW1PcHRpb25zKG91dGJvdW5kU3RyZWFtT3B0czogT3V0Ym91bmRTdHJlYW1PcHRpb25zKTogdm9pZCB7XG4gICAgICAgIHRoaXMub3V0Ym91bmRTdHJlYW1PcHRzID0gb3V0Ym91bmRTdHJlYW1PcHRzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBzdWJzY3JpYmUoKTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIHRoaXMuaW5pdFdlYlJ0Y1BlZXJSZWNlaXZlKClcbiAgICAgICAgICAgICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBwdWJsaXNoKCk6IFByb21pc2U8YW55PiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICBpZiAodGhpcy5pc0xvY2FsU3RyZWFtUmVhZHlUb1B1Ymxpc2gpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmluaXRXZWJSdGNQZWVyU2VuZCgpXG4gICAgICAgICAgICAgICAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLm9uY2UoJ3N0cmVhbS1yZWFkeS10by1wdWJsaXNoJywgKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnB1Ymxpc2goKVxuICAgICAgICAgICAgICAgICAgICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgICAgICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGRpc3Bvc2VXZWJSdGNQZWVyKCk6IHZvaWQge1xuICAgICAgICBpZiAodGhpcy53ZWJSdGNQZWVyKSB7XG4gICAgICAgICAgICB0aGlzLndlYlJ0Y1BlZXIuZGlzcG9zZSgpO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLnNwZWVjaEV2ZW50KSB7XG4gICAgICAgICAgICB0aGlzLnNwZWVjaEV2ZW50LnN0b3AoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuc3RvcFdlYlJ0Y1N0YXRzKCk7XG5cbiAgICAgICAgY29uc29sZS5pbmZvKCghIXRoaXMub3V0Ym91bmRTdHJlYW1PcHRzID8gJ091dGJvdW5kICcgOiAnSW5ib3VuZCAnKSArIFwiV2ViUlRDUGVlciBmcm9tICdTdHJlYW0nIHdpdGggaWQgW1wiICsgdGhpcy5zdHJlYW1JZCArICddIGlzIG5vdyBjbG9zZWQnKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgZGlzcG9zZU1lZGlhU3RyZWFtKCk6IHZvaWQge1xuICAgICAgICBpZiAodGhpcy5tZWRpYVN0cmVhbSkge1xuICAgICAgICAgICAgdGhpcy5tZWRpYVN0cmVhbS5nZXRBdWRpb1RyYWNrcygpLmZvckVhY2goKHRyYWNrKSA9PiB7XG4gICAgICAgICAgICAgICAgdHJhY2suc3RvcCgpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB0aGlzLm1lZGlhU3RyZWFtLmdldFZpZGVvVHJhY2tzKCkuZm9yRWFjaCgodHJhY2spID0+IHtcbiAgICAgICAgICAgICAgICB0cmFjay5zdG9wKCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGRlbGV0ZSB0aGlzLm1lZGlhU3RyZWFtO1xuICAgICAgICB9XG4gICAgICAgIGNvbnNvbGUuaW5mbygoISF0aGlzLm91dGJvdW5kU3RyZWFtT3B0cyA/ICdMb2NhbCAnIDogJ1JlbW90ZSAnKSArIFwiTWVkaWFTdHJlYW0gZnJvbSAnU3RyZWFtJyB3aXRoIGlkIFtcIiArIHRoaXMuc3RyZWFtSWQgKyAnXSBpcyBub3cgZGlzcG9zZWQnKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgZGlzcGxheU15UmVtb3RlKCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gdGhpcy5pc1N1YnNjcmliZVRvUmVtb3RlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBpc1NlbmRBdWRpbygpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuICghIXRoaXMub3V0Ym91bmRTdHJlYW1PcHRzICYmXG4gICAgICAgICAgICB0aGlzLm91dGJvdW5kU3RyZWFtT3B0cy5wdWJsaXNoZXJQcm9wZXJ0aWVzLmF1ZGlvU291cmNlICE9PSBudWxsICYmXG4gICAgICAgICAgICB0aGlzLm91dGJvdW5kU3RyZWFtT3B0cy5wdWJsaXNoZXJQcm9wZXJ0aWVzLmF1ZGlvU291cmNlICE9PSBmYWxzZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGlzU2VuZFZpZGVvKCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gKCEhdGhpcy5vdXRib3VuZFN0cmVhbU9wdHMgJiZcbiAgICAgICAgICAgIHRoaXMub3V0Ym91bmRTdHJlYW1PcHRzLnB1Ymxpc2hlclByb3BlcnRpZXMudmlkZW9Tb3VyY2UgIT09IG51bGwgJiZcbiAgICAgICAgICAgIHRoaXMub3V0Ym91bmRTdHJlYW1PcHRzLnB1Ymxpc2hlclByb3BlcnRpZXMudmlkZW9Tb3VyY2UgIT09IGZhbHNlKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgaXNTZW5kU2NyZWVuKCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gKCEhdGhpcy5vdXRib3VuZFN0cmVhbU9wdHMgJiZcbiAgICAgICAgICAgIHRoaXMub3V0Ym91bmRTdHJlYW1PcHRzLnB1Ymxpc2hlclByb3BlcnRpZXMudmlkZW9Tb3VyY2UgPT09ICdzY3JlZW4nKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgc2V0U3BlZWNoRXZlbnRJZk5vdEV4aXN0cygpOiB2b2lkIHtcbiAgICAgICAgaWYgKCF0aGlzLnNwZWVjaEV2ZW50KSB7XG4gICAgICAgICAgICBjb25zdCBoYXJrT3B0aW9ucyA9IHRoaXMuc2Vzc2lvbi5vcGVudmlkdS5hZHZhbmNlZENvbmZpZ3VyYXRpb24ucHVibGlzaGVyU3BlYWtpbmdFdmVudHNPcHRpb25zIHx8IHt9O1xuICAgICAgICAgICAgaGFya09wdGlvbnMuaW50ZXJ2YWwgPSAodHlwZW9mIGhhcmtPcHRpb25zLmludGVydmFsID09PSAnbnVtYmVyJykgPyBoYXJrT3B0aW9ucy5pbnRlcnZhbCA6IDUwO1xuICAgICAgICAgICAgaGFya09wdGlvbnMudGhyZXNob2xkID0gKHR5cGVvZiBoYXJrT3B0aW9ucy50aHJlc2hvbGQgPT09ICdudW1iZXInKSA/IGhhcmtPcHRpb25zLnRocmVzaG9sZCA6IC01MDtcblxuICAgICAgICAgICAgdGhpcy5zcGVlY2hFdmVudCA9IGhhcmsodGhpcy5tZWRpYVN0cmVhbSwgaGFya09wdGlvbnMpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGVuYWJsZVNwZWFraW5nRXZlbnRzKCk6IHZvaWQge1xuICAgICAgICB0aGlzLnNldFNwZWVjaEV2ZW50SWZOb3RFeGlzdHMoKTtcbiAgICAgICAgdGhpcy5zcGVlY2hFdmVudC5vbignc3BlYWtpbmcnLCAoKSA9PiB7XG4gICAgICAgICAgICB0aGlzLnNlc3Npb24uZW1pdEV2ZW50KCdwdWJsaXNoZXJTdGFydFNwZWFraW5nJywgW25ldyBQdWJsaXNoZXJTcGVha2luZ0V2ZW50KHRoaXMuc2Vzc2lvbiwgJ3B1Ymxpc2hlclN0YXJ0U3BlYWtpbmcnLCB0aGlzLmNvbm5lY3Rpb24sIHRoaXMuc3RyZWFtSWQpXSk7XG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLnNwZWVjaEV2ZW50Lm9uKCdzdG9wcGVkX3NwZWFraW5nJywgKCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5zZXNzaW9uLmVtaXRFdmVudCgncHVibGlzaGVyU3RvcFNwZWFraW5nJywgW25ldyBQdWJsaXNoZXJTcGVha2luZ0V2ZW50KHRoaXMuc2Vzc2lvbiwgJ3B1Ymxpc2hlclN0b3BTcGVha2luZycsIHRoaXMuY29ubmVjdGlvbiwgdGhpcy5zdHJlYW1JZCldKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGVuYWJsZU9uY2VTcGVha2luZ0V2ZW50cygpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5zZXRTcGVlY2hFdmVudElmTm90RXhpc3RzKCk7XG4gICAgICAgIHRoaXMuc3BlZWNoRXZlbnQub24oJ3NwZWFraW5nJywgKCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5zZXNzaW9uLmVtaXRFdmVudCgncHVibGlzaGVyU3RhcnRTcGVha2luZycsIFtuZXcgUHVibGlzaGVyU3BlYWtpbmdFdmVudCh0aGlzLnNlc3Npb24sICdwdWJsaXNoZXJTdGFydFNwZWFraW5nJywgdGhpcy5jb25uZWN0aW9uLCB0aGlzLnN0cmVhbUlkKV0pO1xuICAgICAgICAgICAgdGhpcy5kaXNhYmxlU3BlYWtpbmdFdmVudHMoKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMuc3BlZWNoRXZlbnQub24oJ3N0b3BwZWRfc3BlYWtpbmcnLCAoKSA9PiB7XG4gICAgICAgICAgICB0aGlzLnNlc3Npb24uZW1pdEV2ZW50KCdwdWJsaXNoZXJTdG9wU3BlYWtpbmcnLCBbbmV3IFB1Ymxpc2hlclNwZWFraW5nRXZlbnQodGhpcy5zZXNzaW9uLCAncHVibGlzaGVyU3RvcFNwZWFraW5nJywgdGhpcy5jb25uZWN0aW9uLCB0aGlzLnN0cmVhbUlkKV0pO1xuICAgICAgICAgICAgdGhpcy5kaXNhYmxlU3BlYWtpbmdFdmVudHMoKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGRpc2FibGVTcGVha2luZ0V2ZW50cygpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5zcGVlY2hFdmVudC5zdG9wKCk7XG4gICAgICAgIHRoaXMuc3BlZWNoRXZlbnQgPSB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGlzTG9jYWwoKTogYm9vbGVhbiB7XG4gICAgICAgIC8vIGluYm91bmQgb3B0aW9ucyB1bmRlZmluZWQgYW5kIG91dGJvdW5kIG9wdGlvbnMgZGVmaW5lZFxuICAgICAgICByZXR1cm4gKCF0aGlzLmluYm91bmRTdHJlYW1PcHRzICYmICEhdGhpcy5vdXRib3VuZFN0cmVhbU9wdHMpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBnZXRTZWxlY3RlZEljZUNhbmRpZGF0ZSgpOiBQcm9taXNlPGFueT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgdGhpcy53ZWJSdGNTdGF0cy5nZXRTZWxlY3RlZEljZUNhbmRpZGF0ZUluZm8oKVxuICAgICAgICAgICAgICAgIC50aGVuKHJlcG9ydCA9PiByZXNvbHZlKHJlcG9ydCkpXG4gICAgICAgICAgICAgICAgLmNhdGNoKGVycm9yID0+IHJlamVjdChlcnJvcikpO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgZ2V0UmVtb3RlSWNlQ2FuZGlkYXRlTGlzdCgpOiBSVENJY2VDYW5kaWRhdGVbXSB7XG4gICAgICAgIHJldHVybiB0aGlzLndlYlJ0Y1BlZXIucmVtb3RlQ2FuZGlkYXRlc1F1ZXVlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBnZXRMb2NhbEljZUNhbmRpZGF0ZUxpc3QoKTogUlRDSWNlQ2FuZGlkYXRlW10ge1xuICAgICAgICByZXR1cm4gdGhpcy53ZWJSdGNQZWVyLmxvY2FsQ2FuZGlkYXRlc1F1ZXVlO1xuICAgIH1cblxuICAgIC8qIFByaXZhdGUgbWV0aG9kcyAqL1xuXG4gICAgcHJpdmF0ZSBpbml0V2ViUnRjUGVlclNlbmQoKTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcblxuICAgICAgICAgICAgY29uc3QgdXNlck1lZGlhQ29uc3RyYWludHMgPSB7XG4gICAgICAgICAgICAgICAgYXVkaW86IHRoaXMuaXNTZW5kQXVkaW8oKSxcbiAgICAgICAgICAgICAgICB2aWRlbzogdGhpcy5pc1NlbmRWaWRlbygpXG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICBjb25zdCBvcHRpb25zID0ge1xuICAgICAgICAgICAgICAgIG1lZGlhU3RyZWFtOiB0aGlzLm1lZGlhU3RyZWFtLFxuICAgICAgICAgICAgICAgIG1lZGlhQ29uc3RyYWludHM6IHVzZXJNZWRpYUNvbnN0cmFpbnRzLFxuICAgICAgICAgICAgICAgIG9uaWNlY2FuZGlkYXRlOiB0aGlzLmNvbm5lY3Rpb24uc2VuZEljZUNhbmRpZGF0ZS5iaW5kKHRoaXMuY29ubmVjdGlvbiksXG4gICAgICAgICAgICAgICAgaWNlU2VydmVyczogdGhpcy5nZXRJY2VTZXJ2ZXJzQ29uZigpLFxuICAgICAgICAgICAgICAgIHNpbXVsY2FzdDogZmFsc2VcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIGNvbnN0IHN1Y2Nlc3NDYWxsYmFjayA9IChzZHBPZmZlclBhcmFtKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5kZWJ1ZygnU2VuZGluZyBTRFAgb2ZmZXIgdG8gcHVibGlzaCBhcyAnXG4gICAgICAgICAgICAgICAgICAgICsgdGhpcy5zdHJlYW1JZCwgc2RwT2ZmZXJQYXJhbSk7XG5cbiAgICAgICAgICAgICAgICBsZXQgdHlwZU9mVmlkZW8gPSAnJztcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5pc1NlbmRWaWRlbygpKSB7XG4gICAgICAgICAgICAgICAgICAgIHR5cGVPZlZpZGVvID0gdGhpcy5vdXRib3VuZFN0cmVhbU9wdHMucHVibGlzaGVyUHJvcGVydGllcy52aWRlb1NvdXJjZSBpbnN0YW5jZW9mIE1lZGlhU3RyZWFtVHJhY2sgPyAnQ1VTVE9NJyA6ICh0aGlzLmlzU2VuZFNjcmVlbigpID8gJ1NDUkVFTicgOiAnQ0FNRVJBJyk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdGhpcy5zZXNzaW9uLm9wZW52aWR1LnNlbmRSZXF1ZXN0KCdwdWJsaXNoVmlkZW8nLCB7XG4gICAgICAgICAgICAgICAgICAgIHNkcE9mZmVyOiBzZHBPZmZlclBhcmFtLFxuICAgICAgICAgICAgICAgICAgICBkb0xvb3BiYWNrOiB0aGlzLmRpc3BsYXlNeVJlbW90ZSgpIHx8IGZhbHNlLFxuICAgICAgICAgICAgICAgICAgICBoYXNBdWRpbzogdGhpcy5pc1NlbmRBdWRpbygpLFxuICAgICAgICAgICAgICAgICAgICBoYXNWaWRlbzogdGhpcy5pc1NlbmRWaWRlbygpLFxuICAgICAgICAgICAgICAgICAgICBhdWRpb0FjdGl2ZTogdGhpcy5hdWRpb0FjdGl2ZSxcbiAgICAgICAgICAgICAgICAgICAgdmlkZW9BY3RpdmU6IHRoaXMudmlkZW9BY3RpdmUsXG4gICAgICAgICAgICAgICAgICAgIHR5cGVPZlZpZGVvLFxuICAgICAgICAgICAgICAgICAgICBmcmFtZVJhdGU6ICEhdGhpcy5mcmFtZVJhdGUgPyB0aGlzLmZyYW1lUmF0ZSA6IC0xLFxuICAgICAgICAgICAgICAgICAgICB2aWRlb0RpbWVuc2lvbnM6IEpTT04uc3RyaW5naWZ5KHRoaXMudmlkZW9EaW1lbnNpb25zKVxuICAgICAgICAgICAgICAgIH0sIChlcnJvciwgcmVzcG9uc2UpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZXJyb3IuY29kZSA9PT0gNDAxKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KG5ldyBPcGVuVmlkdUVycm9yKE9wZW5WaWR1RXJyb3JOYW1lLk9QRU5WSURVX1BFUk1JU1NJT05fREVOSUVELCBcIllvdSBkb24ndCBoYXZlIHBlcm1pc3Npb25zIHRvIHB1Ymxpc2hcIikpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWplY3QoJ0Vycm9yIG9uIHB1Ymxpc2hWaWRlbzogJyArIEpTT04uc3RyaW5naWZ5KGVycm9yKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLndlYlJ0Y1BlZXIucHJvY2Vzc0Fuc3dlcihyZXNwb25zZS5zZHBBbnN3ZXIpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbUlkID0gcmVzcG9uc2UuaWQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuaXNMb2NhbFN0cmVhbVB1Ymxpc2hlZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucHVibGlzaGVkT25jZSA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLmRpc3BsYXlNeVJlbW90ZSgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnJlbW90ZVBlZXJTdWNjZXNzZnVsbHlFc3RhYmxpc2hlZCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdzdHJlYW0tY3JlYXRlZC1ieS1wdWJsaXNoZXInKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5pbml0V2ViUnRjU3RhdHMoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbyhcIidQdWJsaXNoZXInIHN1Y2Nlc3NmdWxseSBwdWJsaXNoZWQgdG8gc2Vzc2lvblwiKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgaWYgKHRoaXMuZGlzcGxheU15UmVtb3RlKCkpIHtcbiAgICAgICAgICAgICAgICB0aGlzLndlYlJ0Y1BlZXIgPSBuZXcgV2ViUnRjUGVlclNlbmRyZWN2KG9wdGlvbnMpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLndlYlJ0Y1BlZXIgPSBuZXcgV2ViUnRjUGVlclNlbmRvbmx5KG9wdGlvbnMpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy53ZWJSdGNQZWVyLmdlbmVyYXRlT2ZmZXIoKS50aGVuKG9mZmVyID0+IHtcbiAgICAgICAgICAgICAgICBzdWNjZXNzQ2FsbGJhY2sob2ZmZXIpO1xuICAgICAgICAgICAgfSkuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgIHJlamVjdChuZXcgRXJyb3IoJyhwdWJsaXNoKSBTRFAgb2ZmZXIgZXJyb3I6ICcgKyBKU09OLnN0cmluZ2lmeShlcnJvcikpKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGluaXRXZWJSdGNQZWVyUmVjZWl2ZSgpOiBQcm9taXNlPGFueT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuXG4gICAgICAgICAgICBjb25zdCBvZmZlckNvbnN0cmFpbnRzID0ge1xuICAgICAgICAgICAgICAgIGF1ZGlvOiB0aGlzLmluYm91bmRTdHJlYW1PcHRzLmhhc0F1ZGlvLFxuICAgICAgICAgICAgICAgIHZpZGVvOiB0aGlzLmluYm91bmRTdHJlYW1PcHRzLmhhc1ZpZGVvXG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgY29uc29sZS5kZWJ1ZyhcIidTZXNzaW9uLnN1YnNjcmliZShTdHJlYW0pJyBjYWxsZWQuIENvbnN0cmFpbnRzIG9mIGdlbmVyYXRlIFNEUCBvZmZlclwiLFxuICAgICAgICAgICAgICAgIG9mZmVyQ29uc3RyYWludHMpO1xuICAgICAgICAgICAgY29uc3Qgb3B0aW9ucyA9IHtcbiAgICAgICAgICAgICAgICBvbmljZWNhbmRpZGF0ZTogdGhpcy5jb25uZWN0aW9uLnNlbmRJY2VDYW5kaWRhdGUuYmluZCh0aGlzLmNvbm5lY3Rpb24pLFxuICAgICAgICAgICAgICAgIG1lZGlhQ29uc3RyYWludHM6IG9mZmVyQ29uc3RyYWludHMsXG4gICAgICAgICAgICAgICAgaWNlU2VydmVyczogdGhpcy5nZXRJY2VTZXJ2ZXJzQ29uZigpLFxuICAgICAgICAgICAgICAgIHNpbXVsY2FzdDogZmFsc2VcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIGNvbnN0IHN1Y2Nlc3NDYWxsYmFjayA9IChzZHBPZmZlclBhcmFtKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5kZWJ1ZygnU2VuZGluZyBTRFAgb2ZmZXIgdG8gc3Vic2NyaWJlIHRvICdcbiAgICAgICAgICAgICAgICAgICAgKyB0aGlzLnN0cmVhbUlkLCBzZHBPZmZlclBhcmFtKTtcbiAgICAgICAgICAgICAgICB0aGlzLnNlc3Npb24ub3BlbnZpZHUuc2VuZFJlcXVlc3QoJ3JlY2VpdmVWaWRlb0Zyb20nLCB7XG4gICAgICAgICAgICAgICAgICAgIHNlbmRlcjogdGhpcy5zdHJlYW1JZCxcbiAgICAgICAgICAgICAgICAgICAgc2RwT2ZmZXI6IHNkcE9mZmVyUGFyYW1cbiAgICAgICAgICAgICAgICB9LCAoZXJyb3IsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KG5ldyBFcnJvcignRXJyb3Igb24gcmVjdlZpZGVvRnJvbTogJyArIEpTT04uc3RyaW5naWZ5KGVycm9yKSkpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy53ZWJSdGNQZWVyLnByb2Nlc3NBbnN3ZXIocmVzcG9uc2Uuc2RwQW5zd2VyKS50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnJlbW90ZVBlZXJTdWNjZXNzZnVsbHlFc3RhYmxpc2hlZCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuaW5pdFdlYlJ0Y1N0YXRzKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSkuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgdGhpcy53ZWJSdGNQZWVyID0gbmV3IFdlYlJ0Y1BlZXJSZWN2b25seShvcHRpb25zKTtcbiAgICAgICAgICAgIHRoaXMud2ViUnRjUGVlci5nZW5lcmF0ZU9mZmVyKClcbiAgICAgICAgICAgICAgICAudGhlbihvZmZlciA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHN1Y2Nlc3NDYWxsYmFjayhvZmZlcik7XG4gICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgICAgICByZWplY3QobmV3IEVycm9yKCcoc3Vic2NyaWJlKSBTRFAgb2ZmZXIgZXJyb3I6ICcgKyBKU09OLnN0cmluZ2lmeShlcnJvcikpKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSByZW1vdGVQZWVyU3VjY2Vzc2Z1bGx5RXN0YWJsaXNoZWQoKTogdm9pZCB7XG4gICAgICAgIHRoaXMubWVkaWFTdHJlYW0gPSB0aGlzLndlYlJ0Y1BlZXIucGMuZ2V0UmVtb3RlU3RyZWFtcygpWzBdO1xuICAgICAgICBjb25zb2xlLmRlYnVnKCdQZWVyIHJlbW90ZSBzdHJlYW0nLCB0aGlzLm1lZGlhU3RyZWFtKTtcblxuICAgICAgICBpZiAoISF0aGlzLm1lZGlhU3RyZWFtKSB7XG4gICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnbWVkaWFzdHJlYW0tdXBkYXRlZCcpO1xuICAgICAgICAgICAgaWYgKCF0aGlzLmRpc3BsYXlNeVJlbW90ZSgpICYmICEhdGhpcy5tZWRpYVN0cmVhbS5nZXRBdWRpb1RyYWNrcygpWzBdICYmIHRoaXMuc2Vzc2lvbi5zcGVha2luZ0V2ZW50c0VuYWJsZWQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVuYWJsZVNwZWFraW5nRXZlbnRzKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIGluaXRXZWJSdGNTdGF0cygpOiB2b2lkIHtcbiAgICAgICAgdGhpcy53ZWJSdGNTdGF0cyA9IG5ldyBXZWJSdGNTdGF0cyh0aGlzKTtcbiAgICAgICAgdGhpcy53ZWJSdGNTdGF0cy5pbml0V2ViUnRjU3RhdHMoKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIHN0b3BXZWJSdGNTdGF0cygpOiB2b2lkIHtcbiAgICAgICAgaWYgKCEhdGhpcy53ZWJSdGNTdGF0cyAmJiB0aGlzLndlYlJ0Y1N0YXRzLmlzRW5hYmxlZCgpKSB7XG4gICAgICAgICAgICB0aGlzLndlYlJ0Y1N0YXRzLnN0b3BXZWJSdGNTdGF0cygpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBnZXRJY2VTZXJ2ZXJzQ29uZigpOiBSVENJY2VTZXJ2ZXJbXSB8IHVuZGVmaW5lZCB7XG4gICAgICAgIGxldCByZXR1cm5WYWx1ZTtcbiAgICAgICAgaWYgKCEhdGhpcy5zZXNzaW9uLm9wZW52aWR1LmFkdmFuY2VkQ29uZmlndXJhdGlvbi5pY2VTZXJ2ZXJzKSB7XG4gICAgICAgICAgICByZXR1cm5WYWx1ZSA9IHRoaXMuc2Vzc2lvbi5vcGVudmlkdS5hZHZhbmNlZENvbmZpZ3VyYXRpb24uaWNlU2VydmVycyA9PT0gJ2ZyZWVpY2UnID9cbiAgICAgICAgICAgICAgICB1bmRlZmluZWQgOlxuICAgICAgICAgICAgICAgIHRoaXMuc2Vzc2lvbi5vcGVudmlkdS5hZHZhbmNlZENvbmZpZ3VyYXRpb24uaWNlU2VydmVycztcbiAgICAgICAgfSBlbHNlIGlmICh0aGlzLnNlc3Npb24ub3BlbnZpZHUuaWNlU2VydmVycykge1xuICAgICAgICAgICAgcmV0dXJuVmFsdWUgPSB0aGlzLnNlc3Npb24ub3BlbnZpZHUuaWNlU2VydmVycztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVyblZhbHVlID0gdW5kZWZpbmVkO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZXR1cm5WYWx1ZTtcbiAgICB9XG5cbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IFN0cmVhbSB9IGZyb20gJy4vU3RyZWFtJztcbmltcG9ydCB7IEV2ZW50RGlzcGF0Y2hlciB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvSW50ZXJmYWNlcy9QdWJsaWMvRXZlbnREaXNwYXRjaGVyJztcbmltcG9ydCB7IFN0cmVhbU1hbmFnZXJWaWRlbyB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvSW50ZXJmYWNlcy9QdWJsaWMvU3RyZWFtTWFuYWdlclZpZGVvJztcbmltcG9ydCB7IEV2ZW50IH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvRXZlbnQnO1xuaW1wb3J0IHsgU3RyZWFtTWFuYWdlckV2ZW50IH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvU3RyZWFtTWFuYWdlckV2ZW50JztcbmltcG9ydCB7IFZpZGVvRWxlbWVudEV2ZW50IH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvVmlkZW9FbGVtZW50RXZlbnQnO1xuaW1wb3J0IHsgVmlkZW9JbnNlcnRNb2RlIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FbnVtcy9WaWRlb0luc2VydE1vZGUnO1xuXG5pbXBvcnQgRXZlbnRFbWl0dGVyID0gcmVxdWlyZSgnd29sZnk4Ny1ldmVudGVtaXR0ZXInKTtcblxuXG4vKipcbiAqIEludGVyZmFjZSBpbiBjaGFyZ2Ugb2YgZGlzcGxheWluZyB0aGUgbWVkaWEgc3RyZWFtcyBpbiB0aGUgSFRNTCBET00uIFRoaXMgd3JhcHMgYW55IFtbUHVibGlzaGVyXV0gYW5kIFtbU3Vic2NyaWJlcl1dIG9iamVjdC5cbiAqIFlvdSBjYW4gaW5zZXJ0IGFzIG1hbnkgdmlkZW8gcGxheWVycyBmbyB0aGUgc2FtZSBTdHJlYW0gYXMgeW91IHdhbnQgYnkgY2FsbGluZyBbW1N0cmVhbU1hbmFnZXIuYWRkVmlkZW9FbGVtZW50XV0gb3JcbiAqIFtbU3RyZWFtTWFuYWdlci5jcmVhdGVWaWRlb0VsZW1lbnRdXS5cbiAqXG4gKiBUaGUgdXNlIG9mIFN0cmVhbU1hbmFnZXIgd3JhcHBlciBpcyBwYXJ0aWN1bGFybHkgdXNlZnVsIHdoZW4geW91IGRvbid0IG5lZWQgdG8gZGlmZmVyZW50aWF0ZSBiZXR3ZWVuIFB1Ymxpc2hlciBvciBTdWJzY3JpYmVyIHN0cmVhbXMgb3IganVzdFxuICogd2FudCB0byBkaXJlY3RseSBtYW5hZ2UgeW91ciBvd24gdmlkZW8gZWxlbWVudHMgKGV2ZW4gbW9yZSB0aGFuIG9uZSB2aWRlbyBlbGVtZW50IHBlciBTdHJlYW0pLiBUaGlzIHNjZW5hcmlvIGlzIHByZXR0eSBjb21tb24gaW5cbiAqIGRlY2xhcmF0aXZlLCBNVkMgZnJvbnRlbmQgZnJhbWV3b3JrcyBzdWNoIGFzIEFuZ3VsYXIsIFJlYWN0IG9yIFZ1ZS5qc1xuICovXG5leHBvcnQgY2xhc3MgU3RyZWFtTWFuYWdlciBpbXBsZW1lbnRzIEV2ZW50RGlzcGF0Y2hlciB7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgU3RyZWFtIHJlcHJlc2VudGVkIGluIHRoZSBET00gYnkgdGhlIFB1Ymxpc2hlci9TdWJzY3JpYmVyXG4gICAgICovXG4gICAgc3RyZWFtOiBTdHJlYW07XG5cbiAgICAvKipcbiAgICAgKiBBbGwgdGhlIHZpZGVvcyBkaXNwbGF5aW5nIHRoZSBTdHJlYW0gb2YgdGhpcyBQdWJsaXNoZXIvU3Vic2NyaWJlclxuICAgICAqL1xuICAgIHZpZGVvczogU3RyZWFtTWFuYWdlclZpZGVvW10gPSBbXTtcblxuICAgIC8qKlxuICAgICAqIFdoZXRoZXIgdGhlIFN0cmVhbSByZXByZXNlbnRlZCBpbiB0aGUgRE9NIGlzIGxvY2FsIG9yIHJlbW90ZVxuICAgICAqIC0gYGZhbHNlYCBmb3IgW1tQdWJsaXNoZXJdXVxuICAgICAqIC0gYHRydWVgIGZvciBbW1N1YnNjcmliZXJdXVxuICAgICAqL1xuICAgIHJlbW90ZTogYm9vbGVhbjtcblxuICAgIC8qKlxuICAgICAqIFRoZSBET00gSFRNTEVsZW1lbnQgYXNzaWduZWQgYXMgdGFyZ2V0IGVsZW1lbnQgd2hlbiBjcmVhdGluZyB0aGUgdmlkZW8gZm9yIHRoZSBQdWJsaXNoZXIvU3Vic2NyaWJlci4gVGhpcyBwcm9wZXJ0eSBpcyBvbmx5IGRlZmluZWQgaWY6XG4gICAgICogLSBbW1B1Ymxpc2hlcl1dIGhhcyBiZWVuIGluaXRpYWxpemVkIGJ5IGNhbGxpbmcgbWV0aG9kIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dIHdpdGggYSB2YWxpZCBgdGFyZ2V0RWxlbWVudGAgcGFyYW1ldGVyXG4gICAgICogLSBbW1N1YnNjcmliZXJdXSBoYXMgYmVlbiBpbml0aWFsaXplZCBieSBjYWxsaW5nIG1ldGhvZCBbW1Nlc3Npb24uc3Vic2NyaWJlXV0gd2l0aCBhIHZhbGlkIGB0YXJnZXRFbGVtZW50YCBwYXJhbWV0ZXJcbiAgICAgKi9cbiAgICB0YXJnZXRFbGVtZW50OiBIVE1MRWxlbWVudDtcblxuICAgIC8qKlxuICAgICAqIGBpZGAgYXR0cmlidXRlIG9mIHRoZSBET00gdmlkZW8gZWxlbWVudCBkaXNwbGF5aW5nIHRoZSBQdWJsaXNoZXIvU3Vic2NyaWJlcidzIHN0cmVhbS4gVGhpcyBwcm9wZXJ0eSBpcyBvbmx5IGRlZmluZWQgaWY6XG4gICAgICogLSBbW1B1Ymxpc2hlcl1dIGhhcyBiZWVuIGluaXRpYWxpemVkIGJ5IGNhbGxpbmcgbWV0aG9kIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dIHdpdGggYSB2YWxpZCBgdGFyZ2V0RWxlbWVudGAgcGFyYW1ldGVyXG4gICAgICogLSBbW1N1YnNjcmliZXJdXSBoYXMgYmVlbiBpbml0aWFsaXplZCBieSBjYWxsaW5nIG1ldGhvZCBbW1Nlc3Npb24uc3Vic2NyaWJlXV0gd2l0aCBhIHZhbGlkIGB0YXJnZXRFbGVtZW50YCBwYXJhbWV0ZXJcbiAgICAgKi9cbiAgICBpZDogc3RyaW5nO1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGZpcnN0VmlkZW9FbGVtZW50OiBTdHJlYW1NYW5hZ2VyVmlkZW87XG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGxhenlMYXVuY2hWaWRlb0VsZW1lbnRDcmVhdGVkRXZlbnQgPSBmYWxzZTtcbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgZWxlbWVudDogSFRNTEVsZW1lbnQ7XG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHByb3RlY3RlZCBlZSA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgcHJvdGVjdGVkIGNhblBsYXlMaXN0ZW5lcjogRXZlbnRMaXN0ZW5lck9yRXZlbnRMaXN0ZW5lck9iamVjdDtcblxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHN0cmVhbTogU3RyZWFtLCB0YXJnZXRFbGVtZW50PzogSFRNTEVsZW1lbnQgfCBzdHJpbmcpIHtcbiAgICAgICAgdGhpcy5zdHJlYW0gPSBzdHJlYW07XG4gICAgICAgIHRoaXMuc3RyZWFtLnN0cmVhbU1hbmFnZXIgPSB0aGlzO1xuICAgICAgICB0aGlzLnJlbW90ZSA9ICF0aGlzLnN0cmVhbS5pc0xvY2FsKCk7XG5cbiAgICAgICAgaWYgKCEhdGFyZ2V0RWxlbWVudCkge1xuICAgICAgICAgICAgbGV0IHRhcmdFbDtcbiAgICAgICAgICAgIGlmICh0eXBlb2YgdGFyZ2V0RWxlbWVudCA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgICAgICB0YXJnRWwgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCh0YXJnZXRFbGVtZW50KTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAodGFyZ2V0RWxlbWVudCBpbnN0YW5jZW9mIEhUTUxFbGVtZW50KSB7XG4gICAgICAgICAgICAgICAgdGFyZ0VsID0gdGFyZ2V0RWxlbWVudDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKCEhdGFyZ0VsKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5maXJzdFZpZGVvRWxlbWVudCA9IHtcbiAgICAgICAgICAgICAgICAgICAgdGFyZ2V0RWxlbWVudDogdGFyZ0VsLFxuICAgICAgICAgICAgICAgICAgICB2aWRlbzogZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgndmlkZW8nKSxcbiAgICAgICAgICAgICAgICAgICAgaWQ6ICcnXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB0aGlzLnRhcmdldEVsZW1lbnQgPSB0YXJnRWw7XG4gICAgICAgICAgICAgICAgdGhpcy5lbGVtZW50ID0gdGFyZ0VsO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHRoaXMuY2FuUGxheUxpc3RlbmVyID0gKCkgPT4ge1xuICAgICAgICAgICAgaWYgKHRoaXMuc3RyZWFtLmlzTG9jYWwoKSkge1xuICAgICAgICAgICAgICAgIGlmICghdGhpcy5zdHJlYW0uZGlzcGxheU15UmVtb3RlKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS5pbmZvKFwiWW91ciBsb2NhbCAnU3RyZWFtJyB3aXRoIGlkIFtcIiArIHRoaXMuc3RyZWFtLnN0cmVhbUlkICsgJ10gdmlkZW8gaXMgbm93IHBsYXlpbmcnKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3ZpZGVvUGxheWluZycsIFtuZXcgVmlkZW9FbGVtZW50RXZlbnQodGhpcy52aWRlb3NbMF0udmlkZW8sIHRoaXMsICd2aWRlb1BsYXlpbmcnKV0pO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbyhcIllvdXIgb3duIHJlbW90ZSAnU3RyZWFtJyB3aXRoIGlkIFtcIiArIHRoaXMuc3RyZWFtLnN0cmVhbUlkICsgJ10gdmlkZW8gaXMgbm93IHBsYXlpbmcnKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3JlbW90ZVZpZGVvUGxheWluZycsIFtuZXcgVmlkZW9FbGVtZW50RXZlbnQodGhpcy52aWRlb3NbMF0udmlkZW8sIHRoaXMsICdyZW1vdGVWaWRlb1BsYXlpbmcnKV0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5pbmZvKFwiUmVtb3RlICdTdHJlYW0nIHdpdGggaWQgW1wiICsgdGhpcy5zdHJlYW0uc3RyZWFtSWQgKyAnXSB2aWRlbyBpcyBub3cgcGxheWluZycpO1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCd2aWRlb1BsYXlpbmcnLCBbbmV3IFZpZGVvRWxlbWVudEV2ZW50KHRoaXMudmlkZW9zWzBdLnZpZGVvLCB0aGlzLCAndmlkZW9QbGF5aW5nJyldKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdzdHJlYW1QbGF5aW5nJywgW25ldyBTdHJlYW1NYW5hZ2VyRXZlbnQodGhpcyldKTtcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZWUgW1tFdmVudERpc3BhdGNoZXIub25dXVxuICAgICAqL1xuICAgIG9uKHR5cGU6IHN0cmluZywgaGFuZGxlcjogKGV2ZW50OiBFdmVudCkgPT4gdm9pZCk6IEV2ZW50RGlzcGF0Y2hlciB7XG4gICAgICAgIHRoaXMuZWUub24odHlwZSwgZXZlbnQgPT4ge1xuICAgICAgICAgICAgaWYgKGV2ZW50KSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5pbmZvKFwiRXZlbnQgJ1wiICsgdHlwZSArIFwiJyB0cmlnZ2VyZWQgYnkgJ1wiICsgKHRoaXMucmVtb3RlID8gJ1N1YnNjcmliZXInIDogJ1B1Ymxpc2hlcicpICsgXCInXCIsIGV2ZW50KTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5pbmZvKFwiRXZlbnQgJ1wiICsgdHlwZSArIFwiJyB0cmlnZ2VyZWQgYnkgJ1wiICsgKHRoaXMucmVtb3RlID8gJ1N1YnNjcmliZXInIDogJ1B1Ymxpc2hlcicpICsgXCInXCIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaGFuZGxlcihldmVudCk7XG4gICAgICAgIH0pO1xuICAgICAgICBpZiAodHlwZSA9PT0gJ3ZpZGVvRWxlbWVudENyZWF0ZWQnKSB7XG4gICAgICAgICAgICBpZiAoISF0aGlzLnN0cmVhbSAmJiB0aGlzLmxhenlMYXVuY2hWaWRlb0VsZW1lbnRDcmVhdGVkRXZlbnQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgndmlkZW9FbGVtZW50Q3JlYXRlZCcsIFtuZXcgVmlkZW9FbGVtZW50RXZlbnQodGhpcy52aWRlb3NbMF0udmlkZW8sIHRoaXMsICd2aWRlb0VsZW1lbnRDcmVhdGVkJyldKTtcbiAgICAgICAgICAgICAgICB0aGlzLmxhenlMYXVuY2hWaWRlb0VsZW1lbnRDcmVhdGVkRXZlbnQgPSBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAodHlwZSA9PT0gJ3N0cmVhbVBsYXlpbmcnIHx8IHR5cGUgPT09ICd2aWRlb1BsYXlpbmcnKSB7XG4gICAgICAgICAgICBpZiAodGhpcy52aWRlb3NbMF0gJiYgdGhpcy52aWRlb3NbMF0udmlkZW8gJiZcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvc1swXS52aWRlby5jdXJyZW50VGltZSA+IDAgJiZcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvc1swXS52aWRlby5wYXVzZWQgPT09IGZhbHNlICYmXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8uZW5kZWQgPT09IGZhbHNlICYmXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8ucmVhZHlTdGF0ZSA9PT0gNCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdzdHJlYW1QbGF5aW5nJywgW25ldyBTdHJlYW1NYW5hZ2VyRXZlbnQodGhpcyldKTtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgndmlkZW9QbGF5aW5nJywgW25ldyBWaWRlb0VsZW1lbnRFdmVudCh0aGlzLnZpZGVvc1swXS52aWRlbywgdGhpcywgJ3ZpZGVvUGxheWluZycpXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2VlIFtbRXZlbnREaXNwYXRjaGVyLm9uY2VdXVxuICAgICAqL1xuICAgIG9uY2UodHlwZTogc3RyaW5nLCBoYW5kbGVyOiAoZXZlbnQ6IEV2ZW50KSA9PiB2b2lkKTogU3RyZWFtTWFuYWdlciB7XG4gICAgICAgIHRoaXMuZWUub25jZSh0eXBlLCBldmVudCA9PiB7XG4gICAgICAgICAgICBpZiAoZXZlbnQpIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oXCJFdmVudCAnXCIgKyB0eXBlICsgXCInIHRyaWdnZXJlZCBvbmNlXCIsIGV2ZW50KTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5pbmZvKFwiRXZlbnQgJ1wiICsgdHlwZSArIFwiJyB0cmlnZ2VyZWQgb25jZVwiKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGhhbmRsZXIoZXZlbnQpO1xuICAgICAgICB9KTtcbiAgICAgICAgaWYgKHR5cGUgPT09ICd2aWRlb0VsZW1lbnRDcmVhdGVkJykge1xuICAgICAgICAgICAgaWYgKCEhdGhpcy5zdHJlYW0gJiYgdGhpcy5sYXp5TGF1bmNoVmlkZW9FbGVtZW50Q3JlYXRlZEV2ZW50KSB7XG4gICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3ZpZGVvRWxlbWVudENyZWF0ZWQnLCBbbmV3IFZpZGVvRWxlbWVudEV2ZW50KHRoaXMudmlkZW9zWzBdLnZpZGVvLCB0aGlzLCAndmlkZW9FbGVtZW50Q3JlYXRlZCcpXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHR5cGUgPT09ICdzdHJlYW1QbGF5aW5nJyB8fCB0eXBlID09PSAndmlkZW9QbGF5aW5nJykge1xuICAgICAgICAgICAgaWYgKHRoaXMudmlkZW9zWzBdICYmIHRoaXMudmlkZW9zWzBdLnZpZGVvICYmXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8uY3VycmVudFRpbWUgPiAwICYmXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8ucGF1c2VkID09PSBmYWxzZSAmJlxuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9zWzBdLnZpZGVvLmVuZGVkID09PSBmYWxzZSAmJlxuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9zWzBdLnZpZGVvLnJlYWR5U3RhdGUgPT09IDQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnc3RyZWFtUGxheWluZycsIFtuZXcgU3RyZWFtTWFuYWdlckV2ZW50KHRoaXMpXSk7XG4gICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3ZpZGVvUGxheWluZycsIFtuZXcgVmlkZW9FbGVtZW50RXZlbnQodGhpcy52aWRlb3NbMF0udmlkZW8sIHRoaXMsICd2aWRlb1BsYXlpbmcnKV0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNlZSBbW0V2ZW50RGlzcGF0Y2hlci5vZmZdXVxuICAgICAqL1xuICAgIG9mZih0eXBlOiBzdHJpbmcsIGhhbmRsZXI/OiAoZXZlbnQ6IEV2ZW50KSA9PiB2b2lkKTogU3RyZWFtTWFuYWdlciB7XG4gICAgICAgIGlmICghaGFuZGxlcikge1xuICAgICAgICAgICAgdGhpcy5lZS5yZW1vdmVBbGxMaXN0ZW5lcnModHlwZSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLmVlLm9mZih0eXBlLCBoYW5kbGVyKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBNYWtlcyBgdmlkZW9gIGVsZW1lbnQgcGFyYW1ldGVyIGRpc3BsYXkgdGhpcyBbW3N0cmVhbV1dLiBUaGlzIGlzIHVzZWZ1bCB3aGVuIHlvdSBhcmVcbiAgICAgKiBbbWFuYWdpbmcgdGhlIHZpZGVvIGVsZW1lbnRzIG9uIHlvdXIgb3duXSgvZG9jcy9ob3ctZG8taS9tYW5hZ2UtdmlkZW9zLyN5b3UtdGFrZS1jYXJlLW9mLXRoZS12aWRlby1wbGF5ZXJzKVxuICAgICAqXG4gICAgICogQ2FsbGluZyB0aGlzIG1ldGhvZCB3aXRoIGEgdmlkZW8gYWxyZWFkeSBhZGRlZCB0byBvdGhlciBQdWJsaXNoZXIvU3Vic2NyaWJlciB3aWxsIGNhdXNlIHRoZSB2aWRlbyBlbGVtZW50IHRvIGJlXG4gICAgICogZGlzYXNzb2NpYXRlZCBmcm9tIHRoYXQgcHJldmlvdXMgUHVibGlzaGVyL1N1YnNjcmliZXIgYW5kIHRvIGJlIGFzc29jaWF0ZWQgdG8gdGhpcyBvbmUuXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyAxIGlmIHRoZSB2aWRlbyB3YXNuJ3QgYXNzb2NpYXRlZCB0byBhbnkgb3RoZXIgUHVibGlzaGVyL1N1YnNjcmliZXIgYW5kIGhhcyBiZWVuIHN1Y2Nlc3NmdWxseSBhZGRlZCB0byB0aGlzIG9uZS5cbiAgICAgKiAwIGlmIHRoZSB2aWRlbyB3YXMgYWxyZWFkeSBhZGRlZCB0byB0aGlzIFB1Ymxpc2hlci9TdWJzY3JpYmVyLiAtMSBpZiB0aGUgdmlkZW8gd2FzIHByZXZpb3VzbHkgYXNzb2NpYXRlZCB0byBhbnkgb3RoZXJcbiAgICAgKiBQdWJsaXNoZXIvU3Vic2NyaWJlciBhbmQgaGFzIGJlZW4gc3VjY2Vzc2Z1bGx5IGRpc2Fzc29jaWF0ZWQgZnJvbSB0aGF0IG9uZSBhbmQgcHJvcGVybHkgYWRkZWQgdG8gdGhpcyBvbmUuXG4gICAgICovXG4gICAgYWRkVmlkZW9FbGVtZW50KHZpZGVvOiBIVE1MVmlkZW9FbGVtZW50KTogbnVtYmVyIHtcblxuICAgICAgICB0aGlzLmluaXRpYWxpemVWaWRlb1Byb3BlcnRpZXModmlkZW8pO1xuXG4gICAgICAgIC8vIElmIHRoZSB2aWRlbyBlbGVtZW50IGlzIGFscmVhZHkgcGFydCBvZiB0aGlzIFN0cmVhbU1hbmFnZXIgZG8gbm90aGluZ1xuICAgICAgICBmb3IgKGNvbnN0IHYgb2YgdGhpcy52aWRlb3MpIHtcbiAgICAgICAgICAgIGlmICh2LnZpZGVvID09PSB2aWRlbykge1xuICAgICAgICAgICAgICAgIHJldHVybiAwO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgbGV0IHJldHVybk51bWJlciA9IDE7XG5cbiAgICAgICAgZm9yIChjb25zdCBzdHJlYW1NYW5hZ2VyIG9mIHRoaXMuc3RyZWFtLnNlc3Npb24uc3RyZWFtTWFuYWdlcnMpIHtcbiAgICAgICAgICAgIGlmIChzdHJlYW1NYW5hZ2VyLmRpc2Fzc29jaWF0ZVZpZGVvKHZpZGVvKSkge1xuICAgICAgICAgICAgICAgIHJldHVybk51bWJlciA9IC0xO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5zdHJlYW0uc2Vzc2lvbi5zdHJlYW1NYW5hZ2Vycy5mb3JFYWNoKHN0cmVhbU1hbmFnZXIgPT4ge1xuICAgICAgICAgICAgc3RyZWFtTWFuYWdlci5kaXNhc3NvY2lhdGVWaWRlbyh2aWRlbyk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHRoaXMucHVzaE5ld1N0cmVhbU1hbmFnZXJWaWRlbyh7XG4gICAgICAgICAgICB2aWRlbyxcbiAgICAgICAgICAgIGlkOiB2aWRlby5pZFxuICAgICAgICB9KTtcblxuICAgICAgICBjb25zb2xlLmluZm8oJ05ldyB2aWRlbyBlbGVtZW50IGFzc29jaWF0ZWQgdG8gJywgdGhpcyk7XG5cbiAgICAgICAgcmV0dXJuIHJldHVybk51bWJlcjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgbmV3IHZpZGVvIGVsZW1lbnQgZGlzcGxheWluZyB0aGlzIFtbc3RyZWFtXV0uIFRoaXMgYWxsb3dzIHlvdSB0byBoYXZlIG11bHRpcGxlIHZpZGVvIGVsZW1lbnRzIGRpc3BsYXlpbmcgdGhlIHNhbWUgbWVkaWEgc3RyZWFtLlxuICAgICAqXG4gICAgICogIyMjIyBFdmVudHMgZGlzcGF0Y2hlZFxuICAgICAqXG4gICAgICogVGhlIFB1Ymxpc2hlci9TdWJzY3JpYmVyIG9iamVjdCB3aWxsIGRpc3BhdGNoIGEgYHZpZGVvRWxlbWVudENyZWF0ZWRgIGV2ZW50IG9uY2UgdGhlIEhUTUwgdmlkZW8gZWxlbWVudCBoYXMgYmVlbiBhZGRlZCB0byBET00uIFNlZSBbW1ZpZGVvRWxlbWVudEV2ZW50XV1cbiAgICAgKlxuICAgICAqIEBwYXJhbSB0YXJnZXRFbGVtZW50IEhUTUwgRE9NIGVsZW1lbnQgKG9yIGl0cyBgaWRgIGF0dHJpYnV0ZSkgaW4gd2hpY2ggdGhlIHZpZGVvIGVsZW1lbnQgb2YgdGhlIFB1Ymxpc2hlci9TdWJzY3JpYmVyIHdpbGwgYmUgaW5zZXJ0ZWRcbiAgICAgKiBAcGFyYW0gaW5zZXJ0TW9kZSBIb3cgdGhlIHZpZGVvIGVsZW1lbnQgd2lsbCBiZSBpbnNlcnRlZCBhY2NvcmRpbmdseSB0byBgdGFyZ2V0RWxlbWV0YFxuICAgICAqL1xuICAgIGNyZWF0ZVZpZGVvRWxlbWVudCh0YXJnZXRFbGVtZW50Pzogc3RyaW5nIHwgSFRNTEVsZW1lbnQsIGluc2VydE1vZGU/OiBWaWRlb0luc2VydE1vZGUpOiBIVE1MVmlkZW9FbGVtZW50IHtcbiAgICAgICAgbGV0IHRhcmdFbDtcbiAgICAgICAgaWYgKHR5cGVvZiB0YXJnZXRFbGVtZW50ID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgdGFyZ0VsID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQodGFyZ0VsKTtcbiAgICAgICAgICAgIGlmICghdGFyZ0VsKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiVGhlIHByb3ZpZGVkICd0YXJnZXRFbGVtZW50JyBjb3VsZG4ndCBiZSByZXNvbHZlZCB0byBhbnkgSFRNTCBlbGVtZW50OiBcIiArIHRhcmdldEVsZW1lbnQpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2UgaWYgKHRhcmdldEVsZW1lbnQgaW5zdGFuY2VvZiBIVE1MRWxlbWVudCkge1xuICAgICAgICAgICAgdGFyZ0VsID0gdGFyZ2V0RWxlbWVudDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIlRoZSBwcm92aWRlZCAndGFyZ2V0RWxlbWVudCcgY291bGRuJ3QgYmUgcmVzb2x2ZWQgdG8gYW55IEhUTUwgZWxlbWVudDogXCIgKyB0YXJnZXRFbGVtZW50KTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHZpZGVvID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgndmlkZW8nKTtcbiAgICAgICAgdGhpcy5pbml0aWFsaXplVmlkZW9Qcm9wZXJ0aWVzKHZpZGVvKTtcblxuICAgICAgICBsZXQgaW5zTW9kZSA9ICEhaW5zZXJ0TW9kZSA/IGluc2VydE1vZGUgOiBWaWRlb0luc2VydE1vZGUuQVBQRU5EO1xuICAgICAgICBzd2l0Y2ggKGluc01vZGUpIHtcbiAgICAgICAgICAgIGNhc2UgVmlkZW9JbnNlcnRNb2RlLkFGVEVSOlxuICAgICAgICAgICAgICAgIHRhcmdFbC5wYXJlbnROb2RlISEuaW5zZXJ0QmVmb3JlKHZpZGVvLCB0YXJnRWwubmV4dFNpYmxpbmcpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBWaWRlb0luc2VydE1vZGUuQVBQRU5EOlxuICAgICAgICAgICAgICAgIHRhcmdFbC5hcHBlbmRDaGlsZCh2aWRlbyk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIFZpZGVvSW5zZXJ0TW9kZS5CRUZPUkU6XG4gICAgICAgICAgICAgICAgdGFyZ0VsLnBhcmVudE5vZGUhIS5pbnNlcnRCZWZvcmUodmlkZW8sIHRhcmdFbCk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIFZpZGVvSW5zZXJ0TW9kZS5QUkVQRU5EOlxuICAgICAgICAgICAgICAgIHRhcmdFbC5pbnNlcnRCZWZvcmUodmlkZW8sIHRhcmdFbC5jaGlsZE5vZGVzWzBdKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgVmlkZW9JbnNlcnRNb2RlLlJFUExBQ0U6XG4gICAgICAgICAgICAgICAgdGFyZ0VsLnBhcmVudE5vZGUhIS5yZXBsYWNlQ2hpbGQodmlkZW8sIHRhcmdFbCk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgIGluc01vZGUgPSBWaWRlb0luc2VydE1vZGUuQVBQRU5EO1xuICAgICAgICAgICAgICAgIHRhcmdFbC5hcHBlbmRDaGlsZCh2aWRlbyk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCB2OiBTdHJlYW1NYW5hZ2VyVmlkZW8gPSB7XG4gICAgICAgICAgICB0YXJnZXRFbGVtZW50OiB0YXJnRWwsXG4gICAgICAgICAgICB2aWRlbyxcbiAgICAgICAgICAgIGluc2VydE1vZGU6IGluc01vZGUsXG4gICAgICAgICAgICBpZDogdmlkZW8uaWRcbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5wdXNoTmV3U3RyZWFtTWFuYWdlclZpZGVvKHYpO1xuXG4gICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCd2aWRlb0VsZW1lbnRDcmVhdGVkJywgW25ldyBWaWRlb0VsZW1lbnRFdmVudCh2LnZpZGVvLCB0aGlzLCAndmlkZW9FbGVtZW50Q3JlYXRlZCcpXSk7XG5cbiAgICAgICAgdGhpcy5sYXp5TGF1bmNoVmlkZW9FbGVtZW50Q3JlYXRlZEV2ZW50ID0gISF0aGlzLmZpcnN0VmlkZW9FbGVtZW50O1xuXG4gICAgICAgIHJldHVybiB2aWRlbztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgaW5pdGlhbGl6ZVZpZGVvUHJvcGVydGllcyh2aWRlbzogSFRNTFZpZGVvRWxlbWVudCk6IHZvaWQge1xuICAgICAgICBpZiAoISh0aGlzLnN0cmVhbS5pc0xvY2FsKCkgJiYgdGhpcy5zdHJlYW0uZGlzcGxheU15UmVtb3RlKCkpKSB7XG4gICAgICAgICAgICAvLyBBdm9pZCBzZXR0aW5nIHRoZSBNZWRpYVN0cmVhbSBpbnRvIHRoZSBzcmNPYmplY3QgaWYgcmVtb3RlIHN1YnNjcmlwdGlvbiBiZWZvcmUgcHVibGlzaGluZ1xuICAgICAgICAgICAgdmlkZW8uc3JjT2JqZWN0ID0gdGhpcy5zdHJlYW0uZ2V0TWVkaWFTdHJlYW0oKTtcbiAgICAgICAgfVxuICAgICAgICB2aWRlby5hdXRvcGxheSA9IHRydWU7XG4gICAgICAgIHZpZGVvLmNvbnRyb2xzID0gZmFsc2U7XG4gICAgICAgIGlmICghdmlkZW8uaWQpIHtcbiAgICAgICAgICAgIHZpZGVvLmlkID0gKHRoaXMucmVtb3RlID8gJ3JlbW90ZS0nIDogJ2xvY2FsLScpICsgJ3ZpZGVvLScgKyB0aGlzLnN0cmVhbS5zdHJlYW1JZDtcbiAgICAgICAgICAgIC8vIERFUFJFQ0FURUQgcHJvcGVydHk6IGFzc2lnbiBvbmNlIHRoZSBwcm9wZXJ0eSBpZCBpZiB0aGUgdXNlciBwcm92aWRlZCBhIHZhbGlkIHRhcmdldEVsZW1lbnRcbiAgICAgICAgICAgIGlmICghdGhpcy5pZCAmJiAhIXRoaXMudGFyZ2V0RWxlbWVudCkge1xuICAgICAgICAgICAgICAgIHRoaXMuaWQgPSB2aWRlby5pZDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAoIXRoaXMucmVtb3RlICYmICF0aGlzLnN0cmVhbS5kaXNwbGF5TXlSZW1vdGUoKSkge1xuICAgICAgICAgICAgdmlkZW8ubXV0ZWQgPSB0cnVlO1xuICAgICAgICAgICAgaWYgKHRoaXMuc3RyZWFtLm91dGJvdW5kU3RyZWFtT3B0cy5wdWJsaXNoZXJQcm9wZXJ0aWVzLm1pcnJvcikge1xuICAgICAgICAgICAgICAgIHRoaXMubWlycm9yVmlkZW8odmlkZW8pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHJlbW92ZUFsbFZpZGVvcygpOiB2b2lkIHtcbiAgICAgICAgZm9yIChsZXQgaSA9IHRoaXMuc3RyZWFtLnNlc3Npb24uc3RyZWFtTWFuYWdlcnMubGVuZ3RoIC0gMTsgaSA+PSAwOyAtLWkpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLnN0cmVhbS5zZXNzaW9uLnN0cmVhbU1hbmFnZXJzW2ldID09PSB0aGlzKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5zdHJlYW0uc2Vzc2lvbi5zdHJlYW1NYW5hZ2Vycy5zcGxpY2UoaSwgMSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLnZpZGVvcy5zbGljZSgpLnJldmVyc2UoKS5mb3JFYWNoKChzdHJlYW1NYW5hZ2VyVmlkZW8sIGluZGV4LCB2aWRlb3MpID0+IHtcbiAgICAgICAgICAgIC8vIFJlbW92ZSBvbmNhbnBsYXkgZXZlbnQgbGlzdGVuZXIgKG9ubHkgT3BlblZpZHUgYnJvd3NlciBvbmUsIG5vdCB0aGUgdXNlciBvbmVzKVxuICAgICAgICAgICAgc3RyZWFtTWFuYWdlclZpZGVvLnZpZGVvLnJlbW92ZUV2ZW50TGlzdGVuZXIoJ2NhbnBsYXknLCB0aGlzLmNhblBsYXlMaXN0ZW5lcik7XG4gICAgICAgICAgICBpZiAoISFzdHJlYW1NYW5hZ2VyVmlkZW8udGFyZ2V0RWxlbWVudCkge1xuICAgICAgICAgICAgICAgIC8vIE9ubHkgcmVtb3ZlIHZpZGVvcyBjcmVhdGVkIGJ5IE9wZW5WaWR1IEJyb3dzZXIgKHRob3NlIGdlbmVyYXRlZCBieSBwYXNzaW5nIGEgdmFsaWQgdGFyZ2V0RWxlbWVudCBpbiBPcGVuVmlkdS5pbml0UHVibGlzaGVyIGFuZCBTZXNzaW9uLnN1YnNjcmliZVxuICAgICAgICAgICAgICAgIC8vIG9yIHRob3NlIGNyZWF0ZWQgYnkgU3RyZWFtTWFuYWdlci5jcmVhdGVWaWRlb0VsZW1lbnQpLiBUaGVzZSBhcmUgYWxzbyB0aGUgdmlkZW9zIHRoYXQgdHJpZ2dlcmVkIGEgdmlkZW9FbGVtZW50Q3JlYXRlZCBldmVudFxuICAgICAgICAgICAgICAgIHN0cmVhbU1hbmFnZXJWaWRlby52aWRlby5wYXJlbnROb2RlIS5yZW1vdmVDaGlsZChzdHJlYW1NYW5hZ2VyVmlkZW8udmlkZW8pO1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCd2aWRlb0VsZW1lbnREZXN0cm95ZWQnLCBbbmV3IFZpZGVvRWxlbWVudEV2ZW50KHN0cmVhbU1hbmFnZXJWaWRlby52aWRlbywgdGhpcywgJ3ZpZGVvRWxlbWVudERlc3Ryb3llZCcpXSk7XG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3Muc3BsaWNlKHZpZGVvcy5sZW5ndGggLSAxIC0gaW5kZXgsIDEpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAvLyBSZW1vdmUgc3JjT2JqZWN0IGluIGFsbCB2aWRlb3MgbWFuYWdlZCBieSB0aGUgdXNlclxuICAgICAgICAgICAgICAgIHN0cmVhbU1hbmFnZXJWaWRlby52aWRlby5zcmNPYmplY3QgPSBudWxsO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgZGlzYXNzb2NpYXRlVmlkZW8odmlkZW86IEhUTUxWaWRlb0VsZW1lbnQpOiBib29sZWFuIHtcbiAgICAgICAgbGV0IGRpc2Fzc29jaWF0ZWQgPSBmYWxzZTtcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLnZpZGVvcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgaWYgKHRoaXMudmlkZW9zW2ldLnZpZGVvID09PSB2aWRlbykge1xuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9zLnNwbGljZShpLCAxKTtcbiAgICAgICAgICAgICAgICBkaXNhc3NvY2lhdGVkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oJ1ZpZGVvIGVsZW1lbnQgZGlzYXNzb2NpYXRlZCBmcm9tICcsIHRoaXMpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBkaXNhc3NvY2lhdGVkO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBhZGRQbGF5RXZlbnRUb0ZpcnN0VmlkZW8oKSB7XG4gICAgICAgIGlmICgoISF0aGlzLnZpZGVvc1swXSkgJiYgKCEhdGhpcy52aWRlb3NbMF0udmlkZW8pICYmICh0aGlzLnZpZGVvc1swXS52aWRlby5vbmNhbnBsYXkgPT09IG51bGwpKSB7XG4gICAgICAgICAgICB0aGlzLnZpZGVvc1swXS52aWRlby5hZGRFdmVudExpc3RlbmVyKCdjYW5wbGF5JywgdGhpcy5jYW5QbGF5TGlzdGVuZXIpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHVwZGF0ZU1lZGlhU3RyZWFtKG1lZGlhU3RyZWFtOiBNZWRpYVN0cmVhbSkge1xuICAgICAgICB0aGlzLnZpZGVvcy5mb3JFYWNoKHN0cmVhbU1hbmFnZXJWaWRlbyA9PiB7XG4gICAgICAgICAgICBzdHJlYW1NYW5hZ2VyVmlkZW8udmlkZW8uc3JjT2JqZWN0ID0gbWVkaWFTdHJlYW07XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBlbWl0RXZlbnQodHlwZTogc3RyaW5nLCBldmVudEFycmF5OiBhbnlbXSk6IHZvaWQge1xuICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCh0eXBlLCBldmVudEFycmF5KTtcbiAgICB9XG5cbiAgICBwcml2YXRlIHB1c2hOZXdTdHJlYW1NYW5hZ2VyVmlkZW8oc3RyZWFtTWFuYWdlclZpZGVvOiBTdHJlYW1NYW5hZ2VyVmlkZW8pIHtcbiAgICAgICAgdGhpcy52aWRlb3MucHVzaChzdHJlYW1NYW5hZ2VyVmlkZW8pO1xuICAgICAgICB0aGlzLmFkZFBsYXlFdmVudFRvRmlyc3RWaWRlbygpO1xuICAgICAgICBpZiAodGhpcy5zdHJlYW0uc2Vzc2lvbi5zdHJlYW1NYW5hZ2Vycy5pbmRleE9mKHRoaXMpID09PSAtMSkge1xuICAgICAgICAgICAgdGhpcy5zdHJlYW0uc2Vzc2lvbi5zdHJlYW1NYW5hZ2Vycy5wdXNoKHRoaXMpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBtaXJyb3JWaWRlbyh2aWRlbyk6IHZvaWQge1xuICAgICAgICB2aWRlby5zdHlsZS50cmFuc2Zvcm0gPSAncm90YXRlWSgxODBkZWcpJztcbiAgICAgICAgdmlkZW8uc3R5bGUud2Via2l0VHJhbnNmb3JtID0gJ3JvdGF0ZVkoMTgwZGVnKSc7XG4gICAgfVxuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBTdHJlYW0gfSBmcm9tICcuL1N0cmVhbSc7XG5pbXBvcnQgeyBTdHJlYW1NYW5hZ2VyIH0gZnJvbSAnLi9TdHJlYW1NYW5hZ2VyJztcbmltcG9ydCB7IFN1YnNjcmliZXJQcm9wZXJ0aWVzIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9JbnRlcmZhY2VzL1B1YmxpYy9TdWJzY3JpYmVyUHJvcGVydGllcyc7XG5cblxuLyoqXG4gKiBQYWNrcyByZW1vdGUgbWVkaWEgc3RyZWFtcy4gUGFydGljaXBhbnRzIGF1dG9tYXRpY2FsbHkgcmVjZWl2ZSB0aGVtIHdoZW4gb3RoZXJzIHB1Ymxpc2ggdGhlaXIgc3RyZWFtcy4gSW5pdGlhbGl6ZWQgd2l0aCBbW1Nlc3Npb24uc3Vic2NyaWJlXV0gbWV0aG9kXG4gKi9cbmV4cG9ydCBjbGFzcyBTdWJzY3JpYmVyIGV4dGVuZHMgU3RyZWFtTWFuYWdlciB7XG5cbiAgICBwcml2YXRlIHByb3BlcnRpZXM6IFN1YnNjcmliZXJQcm9wZXJ0aWVzO1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHN0cmVhbTogU3RyZWFtLCB0YXJnRWw6IHN0cmluZyB8IEhUTUxFbGVtZW50LCBwcm9wZXJ0aWVzOiBTdWJzY3JpYmVyUHJvcGVydGllcykge1xuICAgICAgICBzdXBlcihzdHJlYW0sIHRhcmdFbCk7XG4gICAgICAgIHRoaXMuZWxlbWVudCA9IHRoaXMudGFyZ2V0RWxlbWVudDtcbiAgICAgICAgdGhpcy5zdHJlYW0gPSBzdHJlYW07XG4gICAgICAgIHRoaXMucHJvcGVydGllcyA9IHByb3BlcnRpZXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU3Vic2NyaWJlIG9yIHVuc3Vic2NyaWJlIGZyb20gdGhlIGF1ZGlvIHN0cmVhbSAoaWYgYXZhaWxhYmxlKS4gQ2FsbGluZyB0aGlzIG1ldGhvZCB0d2ljZSBpbiBhIHJvdyBwYXNzaW5nIHNhbWUgdmFsdWUgd2lsbCBoYXZlIG5vIGVmZmVjdFxuICAgICAqIEBwYXJhbSB2YWx1ZSBgdHJ1ZWAgdG8gc3Vic2NyaWJlIHRvIHRoZSBhdWRpbyBzdHJlYW0sIGBmYWxzZWAgdG8gdW5zdWJzY3JpYmUgZnJvbSBpdFxuICAgICAqL1xuICAgIHN1YnNjcmliZVRvQXVkaW8odmFsdWU6IGJvb2xlYW4pOiBTdWJzY3JpYmVyIHtcbiAgICAgICAgdGhpcy5zdHJlYW0uZ2V0TWVkaWFTdHJlYW0oKS5nZXRBdWRpb1RyYWNrcygpLmZvckVhY2goKHRyYWNrKSA9PiB7XG4gICAgICAgICAgICB0cmFjay5lbmFibGVkID0gdmFsdWU7XG4gICAgICAgIH0pO1xuICAgICAgICBjb25zb2xlLmluZm8oXCInU3Vic2NyaWJlcicgaGFzIFwiICsgKHZhbHVlID8gJ3N1YnNjcmliZWQgdG8nIDogJ3Vuc3Vic2NyaWJlZCBmcm9tJykgKyAnIGl0cyBhdWRpbyBzdHJlYW0nKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU3Vic2NyaWJlIG9yIHVuc3Vic2NyaWJlIGZyb20gdGhlIHZpZGVvIHN0cmVhbSAoaWYgYXZhaWxhYmxlKS4gQ2FsbGluZyB0aGlzIG1ldGhvZCB0d2ljZSBpbiBhIHJvdyBwYXNzaW5nIHNhbWUgdmFsdWUgd2lsbCBoYXZlIG5vIGVmZmVjdFxuICAgICAqIEBwYXJhbSB2YWx1ZSBgdHJ1ZWAgdG8gc3Vic2NyaWJlIHRvIHRoZSB2aWRlbyBzdHJlYW0sIGBmYWxzZWAgdG8gdW5zdWJzY3JpYmUgZnJvbSBpdFxuICAgICAqL1xuICAgIHN1YnNjcmliZVRvVmlkZW8odmFsdWU6IGJvb2xlYW4pOiBTdWJzY3JpYmVyIHtcbiAgICAgICAgdGhpcy5zdHJlYW0uZ2V0TWVkaWFTdHJlYW0oKS5nZXRWaWRlb1RyYWNrcygpLmZvckVhY2goKHRyYWNrKSA9PiB7XG4gICAgICAgICAgICB0cmFjay5lbmFibGVkID0gdmFsdWU7XG4gICAgICAgIH0pO1xuICAgICAgICBjb25zb2xlLmluZm8oXCInU3Vic2NyaWJlcicgaGFzIFwiICsgKHZhbHVlID8gJ3N1YnNjcmliZWQgdG8nIDogJ3Vuc3Vic2NyaWJlZCBmcm9tJykgKyAnIGl0cyB2aWRlbyBzdHJlYW0nKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5leHBvcnQgZW51bSBMb2NhbFJlY29yZGVyU3RhdGUge1xuICAgIFJFQURZID0gJ1JFQURZJyxcbiAgICBSRUNPUkRJTkcgPSAnUkVDT1JESU5HJyxcbiAgICBQQVVTRUQgPSAnUEFVU0VEJyxcbiAgICBGSU5JU0hFRCA9ICdGSU5JU0hFRCdcbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbi8qKlxuICogRGVmaW5lcyBwcm9wZXJ0eSBbW09wZW5WaWR1RXJyb3IubmFtZV1dXG4gKi9cbmV4cG9ydCBlbnVtIE9wZW5WaWR1RXJyb3JOYW1lIHtcblxuICAgIC8qKlxuICAgICAqIEJyb3dzZXIgaXMgbm90IHN1cHBvcnRlZCBieSBPcGVuVmlkdS5cbiAgICAgKiBSZXR1cm5lZCB1cG9uIHVuc3VjY2Vzc2Z1bCBbW1Nlc3Npb24uY29ubmVjdF1dXG4gICAgICovXG4gICAgQlJPV1NFUl9OT1RfU1VQUE9SVEVEID0gJ0JST1dTRVJfTk9UX1NVUFBPUlRFRCcsXG5cbiAgICAvKipcbiAgICAgKiBUaGUgdXNlciBoYXNuJ3QgZ3JhbnRlZCBwZXJtaXNzaW9ucyB0byB0aGUgcmVxdWlyZWQgaW5wdXQgZGV2aWNlIHdoZW4gdGhlIGJyb3dzZXIgYXNrZWQgZm9yIHRoZW0uXG4gICAgICogUmV0dXJuZWQgdXBvbiB1bnN1Y2Nlc3NmdWwgW1tPcGVuVmlkdS5pbml0UHVibGlzaGVyXV0gb3IgW1tPcGVuVmlkdS5nZXRVc2VyTWVkaWFdXVxuICAgICAqL1xuICAgIERFVklDRV9BQ0NFU1NfREVOSUVEID0gJ0RFVklDRV9BQ0NFU1NfREVOSUVEJyxcblxuICAgIC8qKlxuICAgICAqIFRoZSB1c2VyIGhhc24ndCBncmFudGVkIHBlcm1pc3Npb25zIHRvIGNhcHR1cmUgc29tZSBkZXNrdG9wIHNjcmVlbiB3aGVuIHRoZSBicm93c2VyIGFza2VkIGZvciB0aGVtLlxuICAgICAqIFJldHVybmVkIHVwb24gdW5zdWNjZXNzZnVsIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dIG9yIFtbT3BlblZpZHUuZ2V0VXNlck1lZGlhXV1cbiAgICAgKi9cbiAgICBTQ1JFRU5fQ0FQVFVSRV9ERU5JRUQgPSAnU0NSRUVOX0NBUFRVUkVfREVOSUVEJyxcblxuICAgIC8qKlxuICAgICAqIEJyb3dzZXIgZG9lcyBub3Qgc3VwcG9ydCBzY3JlZW4gc2hhcmluZy5cbiAgICAgKiBSZXR1cm5lZCB1cG9uIHVuc3VjY2Vzc2Z1bCBbW09wZW5WaWR1LmluaXRQdWJsaXNoZXJdXVxuICAgICAqL1xuICAgIFNDUkVFTl9TSEFSSU5HX05PVF9TVVBQT1JURUQgPSAnU0NSRUVOX1NIQVJJTkdfTk9UX1NVUFBPUlRFRCcsXG5cbiAgICAvKipcbiAgICAgKiBPbmx5IGZvciBDaHJvbWUsIHRoZXJlJ3Mgbm8gc2NyZWVuIHNoYXJpbmcgZXh0ZW5zaW9uIGluc3RhbGxlZFxuICAgICAqIFJldHVybmVkIHVwb24gdW5zdWNjZXNzZnVsIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dXG4gICAgICovXG4gICAgU0NSRUVOX0VYVEVOU0lPTl9OT1RfSU5TVEFMTEVEID0gJ1NDUkVFTl9FWFRFTlNJT05fTk9UX0lOU1RBTExFRCcsXG5cbiAgICAvKipcbiAgICAgKiBPbmx5IGZvciBDaHJvbWUsIHRoZSBzY3JlZW4gc2hhcmluZyBleHRlbnNpb24gaXMgaW5zdGFsbGVkIGJ1dCBpcyBkaXNhYmxlZFxuICAgICAqIFJldHVybmVkIHVwb24gdW5zdWNjZXNzZnVsIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dXG4gICAgICovXG4gICAgU0NSRUVOX0VYVEVOU0lPTl9ESVNBQkxFRCA9ICdTQ1JFRU5fRVhURU5TSU9OX0RJU0FCTEVEJyxcblxuICAgIC8qKlxuICAgICAqIE5vIHZpZGVvIGlucHV0IGRldmljZSBmb3VuZCB3aXRoIHRoZSBwcm92aWRlZCBkZXZpY2VJZCAocHJvcGVydHkgW1tQdWJsaXNoZXJQcm9wZXJ0aWVzLnZpZGVvU291cmNlXV0pXG4gICAgICogUmV0dXJuZWQgdXBvbiB1bnN1Y2Nlc3NmdWwgW1tPcGVuVmlkdS5pbml0UHVibGlzaGVyXV1cbiAgICAgKi9cbiAgICBJTlBVVF9WSURFT19ERVZJQ0VfTk9UX0ZPVU5EID0gJ0lOUFVUX1ZJREVPX0RFVklDRV9OT1RfRk9VTkQnLFxuXG4gICAgLyoqXG4gICAgICogTm8gYXVkaW8gaW5wdXQgZGV2aWNlIGZvdW5kIHdpdGggdGhlIHByb3ZpZGVkIGRldmljZUlkIChwcm9wZXJ0eSBbW1B1Ymxpc2hlclByb3BlcnRpZXMuYXVkaW9Tb3VyY2VdXSlcbiAgICAgKiBSZXR1cm5lZCB1cG9uIHVuc3VjY2Vzc2Z1bCBbW09wZW5WaWR1LmluaXRQdWJsaXNoZXJdXVxuICAgICAqL1xuICAgIElOUFVUX0FVRElPX0RFVklDRV9OT1RfRk9VTkQgPSAnSU5QVVRfQVVESU9fREVWSUNFX05PVF9GT1VORCcsXG5cbiAgICAvKipcbiAgICAgKiBNZXRob2QgW1tPcGVuVmlkdS5pbml0UHVibGlzaGVyXV0gaGFzIGJlZW4gY2FsbGVkIHdpdGggcHJvcGVydGllcyBgdmlkZW9Tb3VyY2VgIGFuZCBgYXVkaW9Tb3VyY2VgIG9mXG4gICAgICogW1tQdWJsaXNoZXJQcm9wZXJ0aWVzXV0gcGFyYW1ldGVyIGJvdGggc2V0IHRvICpmYWxzZSogb3IgKm51bGwqXG4gICAgICovXG4gICAgTk9fSU5QVVRfU09VUkNFX1NFVCA9ICdOT19JTlBVVF9TT1VSQ0VfU0VUJyxcblxuICAgIC8qKlxuICAgICAqIFNvbWUgbWVkaWEgcHJvcGVydHkgb2YgW1tQdWJsaXNoZXJQcm9wZXJ0aWVzXV0gc3VjaCBhcyBgZnJhbWVSYXRlYCBvciBgcmVzb2x1dGlvbmAgaXMgbm90IHN1cHBvcnRlZFxuICAgICAqIGJ5IHRoZSBpbnB1dCBkZXZpY2VzICh3aGVuZXZlciBpdCBpcyBwb3NzaWJsZSB0aGV5IGFyZSBhdXRvbWF0aWNhbGx5IGFkanVzdGVkIHRvIHRoZSBtb3N0IHNpbWlsYXIgdmFsdWUpLlxuICAgICAqIFJldHVybmVkIHVwb24gdW5zdWNjZXNzZnVsIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dXG4gICAgICovXG4gICAgUFVCTElTSEVSX1BST1BFUlRJRVNfRVJST1IgPSAnUFVCTElTSEVSX1BST1BFUlRJRVNfRVJST1InLFxuXG4gICAgLyoqXG4gICAgICogVGhlIGNsaWVudCB0cmllZCB0byBjYWxsIGEgbWV0aG9kIHdpdGhvdXQgdGhlIHJlcXVpcmVkIHBlcm1pc3Npb25zLiBUaGlzIGNhbiBvY2N1ciBmb3IgbWV0aG9kcyBbW1Nlc3Npb24ucHVibGlzaF1dLFxuICAgICAqIFtbU2Vzc2lvbi5mb3JjZVVucHVibGlzaF1dIGFuZCBbW1Nlc3Npb24uZm9yY2VEaXNjb25uZWN0XV1cbiAgICAgKi9cbiAgICBPUEVOVklEVV9QRVJNSVNTSU9OX0RFTklFRCA9ICdPUEVOVklEVV9QRVJNSVNTSU9OX0RFTklFRCcsXG5cbiAgICAvKipcbiAgICAgKiBfTm90IGluIHVzZSB5ZXRfXG4gICAgICovXG4gICAgT1BFTlZJRFVfTk9UX0NPTk5FQ1RFRCA9ICdPUEVOVklEVV9OT1RfQ09OTkVDVEVEJyxcblxuICAgIC8qKlxuICAgICAqIF9Ob3QgaW4gdXNlIHlldF9cbiAgICAgKi9cbiAgICBHRU5FUklDX0VSUk9SID0gJ0dFTkVSSUNfRVJST1InXG59XG5cbi8qKlxuICogU2ltcGxlIG9iamVjdCB0byBpZGVudGlmeSBydW50aW1lIGVycm9ycyBvbiB0aGUgY2xpZW50IHNpZGVcbiAqL1xuZXhwb3J0IGNsYXNzIE9wZW5WaWR1RXJyb3Ige1xuXG4gICAgbmFtZTogT3BlblZpZHVFcnJvck5hbWU7XG4gICAgbWVzc2FnZTogc3RyaW5nO1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKG5hbWU6IE9wZW5WaWR1RXJyb3JOYW1lLCBtZXNzYWdlOiBzdHJpbmcpIHtcbiAgICAgICAgdGhpcy5uYW1lID0gbmFtZTtcbiAgICAgICAgdGhpcy5tZXNzYWdlID0gbWVzc2FnZTtcbiAgICB9XG5cbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbi8qKlxuICogSG93IHRoZSB2aWRlbyB3aWxsIGJlIGluc2VydGVkIGluIHRoZSBET00gZm9yIFB1Ymxpc2hlcnMgYW5kIFN1YnNjcmliZXJzLiBTZWUgW1tQdWJsaXNoZXJQcm9wZXJ0aWVzLmluc2VydE1vZGVdXSBhbmQgW1tTdWJzY3JpYmVyUHJvcGVydGllcy5pbnNlcnRNb2RlXV1cbiAqL1xuZXhwb3J0IGVudW0gVmlkZW9JbnNlcnRNb2RlIHtcblxuICAgIC8qKlxuICAgICAqIFZpZGVvIGluc2VydGVkIGFmdGVyIHRoZSB0YXJnZXQgZWxlbWVudCAoYXMgbmV4dCBzaWJsaW5nKVxuICAgICAqL1xuICAgIEFGVEVSID0gJ0FGVEVSJyxcbiAgICAvKipcbiAgICAgKiBWaWRlbyBpbnNlcnRlZCBhcyBsYXN0IGNoaWxkIG9mIHRoZSB0YXJnZXQgZWxlbWVudFxuICAgICAqL1xuICAgIEFQUEVORCA9ICdBUFBFTkQnLFxuICAgIC8qKlxuICAgICAqIFZpZGVvIGluc2VydGVkIGJlZm9yZSB0aGUgdGFyZ2V0IGVsZW1lbnQgKGFzIHByZXZpb3VzIHNpYmxpbmcpXG4gICAgICovXG4gICAgQkVGT1JFID0gJ0JFRk9SRScsXG4gICAgLyoqXG4gICAgICogVmlkZW8gaW5zZXJ0ZWQgYXMgZmlyc3QgY2hpbGQgb2YgdGhlIHRhcmdldCBlbGVtZW50XG4gICAgICovXG4gICAgUFJFUEVORCA9ICdQUkVQRU5EJyxcbiAgICAvKipcbiAgICAgKiBWaWRlbyByZXBsYWNlcyB0YXJnZXQgZWxlbWVudFxuICAgICAqL1xuICAgIFJFUExBQ0UgPSAnUkVQTEFDRSdcblxufSIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTctMjAxOCBPcGVuVmlkdSAoaHR0cHM6Ly9vcGVudmlkdS5pby8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuaW1wb3J0IHsgRXZlbnQgfSBmcm9tICcuL0V2ZW50JztcbmltcG9ydCB7IENvbm5lY3Rpb24gfSBmcm9tICcuLi8uLi9PcGVuVmlkdS9Db25uZWN0aW9uJztcbmltcG9ydCB7IFNlc3Npb24gfSBmcm9tICcuLi8uLi9PcGVuVmlkdS9TZXNzaW9uJztcblxuXG4vKipcbiAqIERlZmluZXMgdGhlIGZvbGxvd2luZyBldmVudHM6XG4gKiAtIGBjb25uZWN0aW9uQ3JlYXRlZGA6IGRpc3BhdGNoZWQgYnkgW1tTZXNzaW9uXV1cbiAqIC0gYGNvbm5lY3Rpb25EZXN0cm95ZWRgOiBkaXNwYXRjaGVkIGJ5IFtbU2Vzc2lvbl1dXG4gKi9cbmV4cG9ydCBjbGFzcyBDb25uZWN0aW9uRXZlbnQgZXh0ZW5kcyBFdmVudCB7XG5cbiAgICAvKipcbiAgICAgKiBDb25uZWN0aW9uIG9iamVjdCB0aGF0IHdhcyBjcmVhdGVkIG9yIGRlc3Ryb3llZFxuICAgICAqL1xuICAgIGNvbm5lY3Rpb246IENvbm5lY3Rpb247XG5cbiAgICAvKipcbiAgICAgKiBGb3IgJ2Nvbm5lY3Rpb25EZXN0cm95ZWQnIGV2ZW50OlxuICAgICAqIC0gXCJkaXNjb25uZWN0XCI6IHRoZSByZW1vdGUgdXNlciBoYXMgY2FsbGVkIGBTZXNzaW9uLmRpc2Nvbm5lY3QoKWBcbiAgICAgKiAtIFwiZm9yY2VEaXNjb25uZWN0QnlVc2VyXCI6IHRoZSByZW1vdGUgdXNlciBoYXMgYmVlbiBldmljdGVkIGZyb20gdGhlIFNlc3Npb24gYnkgb3RoZXIgdXNlciBjYWxsaW5nIGBTZXNzaW9uLmZvcmNlRGlzY29ubmVjdCgpYFxuICAgICAqIC0gXCJmb3JjZURpc2Nvbm5lY3RCeVNlcnZlclwiOiB0aGUgcmVtb3RlIHVzZXIgaGFzIGJlZW4gZXZpY3RlZCBmcm9tIHRoZSBTZXNzaW9uIGJ5IHRoZSBhcHBsaWNhdGlvblxuICAgICAqIC0gXCJzZXNzaW9uQ2xvc2VkQnlTZXJ2ZXJcIjogdGhlIFNlc3Npb24gaGFzIGJlZW4gY2xvc2VkIGJ5IHRoZSBhcHBsaWNhdGlvblxuICAgICAqIC0gXCJuZXR3b3JrRGlzY29ubmVjdFwiOiB0aGUgcmVtb3RlIHVzZXIgbmV0d29yayBjb25uZWN0aW9uIGhhcyBkcm9wcGVkXG4gICAgICpcbiAgICAgKiBGb3IgJ2Nvbm5lY3Rpb25DcmVhdGVkJyBlbXB0eSBzdHJpbmdcbiAgICAgKi9cbiAgICByZWFzb246IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3RvcihjYW5jZWxhYmxlOiBib29sZWFuLCB0YXJnZXQ6IFNlc3Npb24sIHR5cGU6IHN0cmluZywgY29ubmVjdGlvbjogQ29ubmVjdGlvbiwgcmVhc29uOiBzdHJpbmcpIHtcbiAgICAgICAgc3VwZXIoY2FuY2VsYWJsZSwgdGFyZ2V0LCB0eXBlKTtcbiAgICAgICAgdGhpcy5jb25uZWN0aW9uID0gY29ubmVjdGlvbjtcbiAgICAgICAgdGhpcy5yZWFzb24gPSByZWFzb247XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZTpuby1lbXB0eVxuICAgIGNhbGxEZWZhdWx0QmVoYXZpb3IoKSB7IH1cblxufSIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTctMjAxOCBPcGVuVmlkdSAoaHR0cHM6Ly9vcGVudmlkdS5pby8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuaW1wb3J0IHsgU3RyZWFtTWFuYWdlciB9IGZyb20gJy4uLy4uL09wZW5WaWR1L1N0cmVhbU1hbmFnZXInO1xuaW1wb3J0IHsgU2Vzc2lvbiB9IGZyb20gJy4uLy4uL09wZW5WaWR1L1Nlc3Npb24nO1xuXG5leHBvcnQgYWJzdHJhY3QgY2xhc3MgRXZlbnQge1xuXG4gICAgLyoqXG4gICAgICogV2hldGhlciB0aGUgZXZlbnQgaGFzIGEgZGVmYXVsdCBiZWhhdmlvciB0aGF0IG1heSBiZSBwcmV2ZW50ZWQgYnkgY2FsbGluZyBbW0V2ZW50LnByZXZlbnREZWZhdWx0XV1cbiAgICAgKi9cbiAgICBjYW5jZWxhYmxlOiBib29sZWFuO1xuXG4gICAgLyoqXG4gICAgICogVGhlIG9iamVjdCB0aGF0IGRpc3BhdGNoZWQgdGhlIGV2ZW50XG4gICAgICovXG4gICAgdGFyZ2V0OiBTZXNzaW9uIHwgU3RyZWFtTWFuYWdlcjtcblxuICAgIC8qKlxuICAgICAqIFRoZSB0eXBlIG9mIGV2ZW50LiBUaGlzIGlzIHRoZSBzYW1lIHN0cmluZyB5b3UgcGFzcyBhcyBmaXJzdCBwYXJhbWV0ZXIgd2hlbiBjYWxsaW5nIG1ldGhvZCBgb24oKWAgb2YgYW55IG9iamVjdCBpbXBsZW1lbnRpbmcgW1tFdmVudERpc3BhdGNoZXJdXSBpbnRlcmZhY2VcbiAgICAgKi9cbiAgICB0eXBlOiBzdHJpbmc7XG5cbiAgICBwcml2YXRlIGhhc0JlZW5QcmV2ZW50ZWQgPSBmYWxzZTtcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3RvcihjYW5jZWxhYmxlOiBib29sZWFuLCB0YXJnZXQ6IFNlc3Npb24gfCBTdHJlYW1NYW5hZ2VyLCB0eXBlOiBzdHJpbmcpIHtcbiAgICAgICAgdGhpcy5jYW5jZWxhYmxlID0gY2FuY2VsYWJsZTtcbiAgICAgICAgdGhpcy50YXJnZXQgPSB0YXJnZXQ7XG4gICAgICAgIHRoaXMudHlwZSA9IHR5cGU7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogV2hldGhlciB0aGUgZGVmYXVsdCBiZWFoaXZvdXIgb2YgdGhlIGV2ZW50IGhhcyBiZWVuIHByZXZlbnRlZCBvciBub3QuIENhbGwgW1tFdmVudC5wcmV2ZW50RGVmYXVsdF1dIHRvIHByZXZlbnQgaXRcbiAgICAgKi9cbiAgICBpc0RlZmF1bHRQcmV2ZW50ZWQoKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiB0aGlzLmhhc0JlZW5QcmV2ZW50ZWQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUHJldmVudHMgdGhlIGRlZmF1bHQgYmVoYXZpb3Igb2YgdGhlIGV2ZW50LiBUaGUgZm9sbG93aW5nIGV2ZW50cyBoYXZlIGEgZGVmYXVsdCBiZWhhdmlvcjpcbiAgICAgKlxuICAgICAqIC0gYHNlc3Npb25EaXNjb25uZWN0ZWRgOiBkaXNwYXRjaGVkIGJ5IFtbU2Vzc2lvbl1dIG9iamVjdCwgYXV0b21hdGljYWxseSB1bnN1YnNjcmliZXMgdGhlIGxlYXZpbmcgcGFydGljaXBhbnQgZnJvbSBldmVyeSBTdWJzY3JpYmVyIG9iamVjdCBvZiB0aGUgc2Vzc2lvbiAodGhpcyBpbmNsdWRlcyBjbG9zaW5nIHRoZSBXZWJSVENQZWVyIGNvbm5lY3Rpb24gYW5kIGRpc3Bvc2luZyBhbGwgTWVkaWFTdHJlYW1UcmFja3MpXG4gICAgICogYW5kIGFsc28gZGVsZXRlcyBhbnkgSFRNTCB2aWRlbyBlbGVtZW50IGFzc29jaWF0ZWQgdG8gZWFjaCBTdWJzY3JpYmVyIChvbmx5IHRob3NlIGNyZWF0ZWQgYnkgT3BlblZpZHUgQnJvd3NlciwgZWl0aGVyIGJ5IHBhc3NpbmcgYSB2YWxpZCBwYXJhbWV0ZXIgYXMgYHRhcmdldEVsZW1lbnRgIGluIG1ldGhvZCBbW1Nlc3Npb24uc3Vic2NyaWJlXV0gb3JcbiAgICAgKiBieSBjYWxsaW5nIFtbU3Vic2NyaWJlci5jcmVhdGVWaWRlb0VsZW1lbnRdXSkuIEZvciBldmVyeSB2aWRlbyByZW1vdmVkLCBlYWNoIFN1YnNjcmliZXIgb2JqZWN0IHdpbGwgYWxzbyBkaXNwYXRjaCBhIGB2aWRlb0VsZW1lbnREZXN0cm95ZWRgIGV2ZW50LlxuICAgICAqXG4gICAgICogLSBgc3RyZWFtRGVzdHJveWVkYDpcbiAgICAgKiAgIC0gSWYgZGlzcGF0Y2hlZCBieSBhIFtbUHVibGlzaGVyXV0gKCp5b3UqIGhhdmUgdW5wdWJsaXNoZWQpOiBhdXRvbWF0aWNhbGx5IHN0b3BzIGFsbCBtZWRpYSB0cmFja3MgYW5kIGRlbGV0ZXMgYW55IEhUTUwgdmlkZW8gZWxlbWVudCBhc3NvY2lhdGVkIHRvIGl0IChvbmx5IHRob3NlIGNyZWF0ZWQgYnkgT3BlblZpZHUgQnJvd3NlciwgZWl0aGVyIGJ5IHBhc3NpbmcgYSB2YWxpZCBwYXJhbWV0ZXIgYXMgYHRhcmdldEVsZW1lbnRgXG4gICAgICogaW4gbWV0aG9kIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dIG9yIGJ5IGNhbGxpbmcgW1tQdWJsaXNoZXIuY3JlYXRlVmlkZW9FbGVtZW50XV0pLiBGb3IgZXZlcnkgdmlkZW8gcmVtb3ZlZCwgdGhlIFB1Ymxpc2hlciBvYmplY3Qgd2lsbCBhbHNvIGRpc3BhdGNoIGEgYHZpZGVvRWxlbWVudERlc3Ryb3llZGAgZXZlbnQuXG4gICAgICogICAtIElmIGRpc3BhdGNoZWQgYnkgW1tTZXNzaW9uXV0gKCpvdGhlciB1c2VyKiBoYXMgdW5wdWJsaXNoZWQpOiBhdXRvbWF0aWNhbGx5IHVuc3Vic2NyaWJlcyB0aGUgcHJvcGVyIFN1YnNjcmliZXIgb2JqZWN0IGZyb20gdGhlIHNlc3Npb24gKHRoaXMgaW5jbHVkZXMgY2xvc2luZyB0aGUgV2ViUlRDUGVlciBjb25uZWN0aW9uIGFuZCBkaXNwb3NpbmcgYWxsIE1lZGlhU3RyZWFtVHJhY2tzKVxuICAgICAqIGFuZCBhbHNvIGRlbGV0ZXMgYW55IEhUTUwgdmlkZW8gZWxlbWVudCBhc3NvY2lhdGVkIHRvIHRoYXQgU3Vic2NyaWJlciAob25seSB0aG9zZSBjcmVhdGVkIGJ5IE9wZW5WaWR1IEJyb3dzZXIsIGVpdGhlciBieSBwYXNzaW5nIGEgdmFsaWQgcGFyYW1ldGVyIGFzIGB0YXJnZXRFbGVtZW50YCBpbiBtZXRob2QgW1tTZXNzaW9uLnN1YnNjcmliZV1dIG9yXG4gICAgICogYnkgY2FsbGluZyBbW1N1YnNjcmliZXIuY3JlYXRlVmlkZW9FbGVtZW50XV0pLiBGb3IgZXZlcnkgdmlkZW8gcmVtb3ZlZCwgdGhlIFN1YnNjcmliZXIgb2JqZWN0IHdpbGwgYWxzbyBkaXNwYXRjaCBhIGB2aWRlb0VsZW1lbnREZXN0cm95ZWRgIGV2ZW50LlxuICAgICAqL1xuICAgIHByZXZlbnREZWZhdWx0KCkge1xuICAgICAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6bm8tZW1wdHlcbiAgICAgICAgdGhpcy5jYWxsRGVmYXVsdEJlaGF2aW9yID0gKCkgPT4geyB9O1xuICAgICAgICB0aGlzLmhhc0JlZW5QcmV2ZW50ZWQgPSB0cnVlO1xuICAgIH1cblxuICAgIHByb3RlY3RlZCBhYnN0cmFjdCBjYWxsRGVmYXVsdEJlaGF2aW9yKCk7XG5cbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IEV2ZW50IH0gZnJvbSAnLi9FdmVudCc7XG5pbXBvcnQgeyBDb25uZWN0aW9uIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvQ29ubmVjdGlvbic7XG5pbXBvcnQgeyBTZXNzaW9uIH0gZnJvbSAnLi4vLi4nO1xuXG5cbi8qKlxuICogRGVmaW5lcyB0aGUgZm9sbG93aW5nIGV2ZW50czpcbiAqIC0gYHB1Ymxpc2hlclN0YXJ0U3BlYWtpbmdgOiBkaXNwYXRjaGVkIGJ5IFtbU2Vzc2lvbl1dXG4gKiAtIGBwdWJsaXNoZXJTdG9wU3BlYWtpbmdgOiBkaXNwYXRjaGVkIGJ5IFtbU2Vzc2lvbl1dXG4gKlxuICogTW9yZSBpbmZvcm1hdGlvbjpcbiAqIC0gVGhpcyBldmVudHMgd2lsbCBvbmx5IGJlIHRyaWdnZXJlZCBmb3IgKipyZW1vdGUgc3RyZWFtcyB0aGF0IGhhdmUgYXVkaW8gdHJhY2tzKipcbiAqIC0gQm90aCBldmVudHMgc2hhcmUgdGhlIHNhbWUgbGlmZWN5Y2xlLiBUaGF0IG1lYW5zIHRoYXQgeW91IGNhbiBzdWJzY3JpYmUgdG8gb25seSBvbmUgb2YgdGhlbSBpZiB5b3Ugd2FudCwgYnV0IGlmIHlvdSBjYWxsIGBTZXNzaW9uLm9mZigncHVibGlzaGVyU3RvcFNwZWFraW5nJylgLFxuICoga2VlcCBpbiBtaW5kIHRoYXQgdGhpcyB3aWxsIGFsc28gaW50ZXJuYWxseSByZW1vdmUgYW55ICdwdWJsaXNoZXJTdGFydFNwZWFraW5nJyBldmVudFxuICogLSBZb3UgY2FuIGZ1cnRoZXIgY29uZmlndXJlIGhvdyB0aGUgZXZlbnRzIGFyZSBkaXNwYXRjaGVkIGJ5IHNldHRpbmcgcHJvcGVydHkgYHB1Ymxpc2hlclNwZWFraW5nRXZlbnRzT3B0aW9uc2AgaW4gdGhlIGNhbGwgb2YgW1tPcGVuVmlkdS5zZXRBZHZhbmNlZENvbmZpZ3VyYXRpb25dXVxuICovXG5leHBvcnQgY2xhc3MgUHVibGlzaGVyU3BlYWtpbmdFdmVudCBleHRlbmRzIEV2ZW50IHtcblxuICAgIC8qKlxuICAgICAqIFRoZSBjbGllbnQgdGhhdCBzdGFydGVkIG9yIHN0b3BwZWQgc3BlYWtpbmdcbiAgICAgKi9cbiAgICBjb25uZWN0aW9uOiBDb25uZWN0aW9uO1xuXG4gICAgLyoqXG4gICAgICogVGhlIHN0cmVhbUlkIG9mIHRoZSBTdHJlYW0gYWZmZWN0ZWQgYnkgdGhlIHNwZWFraW5nIGV2ZW50XG4gICAgICovXG4gICAgc3RyZWFtSWQ6IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3Rvcih0YXJnZXQ6IFNlc3Npb24sIHR5cGU6IHN0cmluZywgY29ubmVjdGlvbjogQ29ubmVjdGlvbiwgc3RyZWFtSWQ6IHN0cmluZykge1xuICAgICAgICBzdXBlcihmYWxzZSwgdGFyZ2V0LCB0eXBlKTtcbiAgICAgICAgdGhpcy50eXBlID0gdHlwZTtcbiAgICAgICAgdGhpcy5jb25uZWN0aW9uID0gY29ubmVjdGlvbjtcbiAgICAgICAgdGhpcy5zdHJlYW1JZCA9IHN0cmVhbUlkO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6bm8tZW1wdHlcbiAgICBjYWxsRGVmYXVsdEJlaGF2aW9yKCkgeyB9XG5cbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IEV2ZW50IH0gZnJvbSAnLi9FdmVudCc7XG5pbXBvcnQgeyBTZXNzaW9uIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvU2Vzc2lvbic7XG5cblxuLyoqXG4gKiBEZWZpbmVzIHRoZSBmb2xsb3dpbmcgZXZlbnRzOlxuICogLSBgcmVjb3JkaW5nU3RhcnRlZGA6IGRpc3BhdGNoZWQgYnkgW1tTZXNzaW9uXV1cbiAqIC0gYHJlY29yZGluZ1N0b3BwZWRgOiBkaXNwYXRjaGVkIGJ5IFtbU2Vzc2lvbl1dXG4gKi9cbmV4cG9ydCBjbGFzcyBSZWNvcmRpbmdFdmVudCBleHRlbmRzIEV2ZW50IHtcblxuICAgIC8qKlxuICAgICAqIFRoZSByZWNvcmRpbmcgSUQgZ2VuZXJhdGVkIGluIG9wZW52aWR1LXNlcnZlclxuICAgICAqL1xuICAgIGlkOiBzdHJpbmc7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgcmVjb3JkaW5nIG5hbWUgeW91IHN1cHBsaWVkIHRvIG9wZW52aWR1LXNlcnZlci4gRm9yIGV4YW1wbGUsIHRvIG5hbWUgeW91ciByZWNvcmRpbmcgZmlsZSBNWV9SRUNPUkRJTkc6XG4gICAgICogLSBXaXRoICoqQVBJIFJFU1QqKjogUE9TVCB0byBgL2FwaS9yZWNvcmRpbmdzL3N0YXJ0YCBwYXNzaW5nIEpTT04gYm9keSBge1wic2Vzc2lvblwiOlwic2Vzc2lvbklkXCIsXCJuYW1lXCI6XCJNWV9SRUNPUkRJTkdcIn1gXG4gICAgICogLSBXaXRoICoqb3BlbnZpZHUtamF2YS1jbGllbnQqKjogYE9wZW5WaWR1LnN0YXJ0UmVjb3JkaW5nKHNlc3Npb25JZCwgXCJNWV9SRUNPUkRJTkdcIilgIG9yIGBPcGVuVmlkdS5zdGFydFJlY29yZGluZyhzZXNzaW9uSWQsIG5ldyBSZWNvcmRpbmdQcm9wZXJ0aWVzLkJ1aWxkZXIoKS5uYW1lKFwiTVlfUkVDT1JESU5HXCIpLmJ1aWxkKCkpYFxuICAgICAqIC0gV2l0aCAqKm9wZW52aWR1LW5vZGUtY2xpZW50Kio6IGBPcGVuVmlkdS5zdGFydFJlY29yZGluZyhzZXNzaW9uSWQsIFwiTVlfUkVDT1JESU5HXCIpYCBvciBgT3BlblZpZHUuc3RhcnRSZWNvcmRpbmcoc2Vzc2lvbklkLCB7bmFtZTogXCJNWV9SRUNPUkRJTkdcIn0pYFxuICAgICAqXG4gICAgICogSWYgbm8gbmFtZSBpcyBzdXBwbGllZCwgdGhpcyBwcm9wZXJ0eSB3aWxsIGJlIHVuZGVmaW5lZCBhbmQgdGhlIHJlY29yZGVkIGZpbGUgd2lsbCBiZSBuYW1lZCBhZnRlciBwcm9wZXJ0eSBbW2lkXV1cbiAgICAgKi9cbiAgICBuYW1lPzogc3RyaW5nO1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHRhcmdldDogU2Vzc2lvbiwgdHlwZTogc3RyaW5nLCBpZDogc3RyaW5nLCBuYW1lOiBzdHJpbmcpIHtcbiAgICAgICAgc3VwZXIoZmFsc2UsIHRhcmdldCwgdHlwZSk7XG4gICAgICAgIHRoaXMuaWQgPSBpZDtcbiAgICAgICAgaWYgKG5hbWUgIT09IGlkKSB7XG4gICAgICAgICAgICB0aGlzLm5hbWUgPSBuYW1lO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZTpuby1lbXB0eVxuICAgIGNhbGxEZWZhdWx0QmVoYXZpb3IoKSB7IH1cblxufSIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTctMjAxOCBPcGVuVmlkdSAoaHR0cHM6Ly9vcGVudmlkdS5pby8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuaW1wb3J0IHsgRXZlbnQgfSBmcm9tICcuL0V2ZW50JztcbmltcG9ydCB7IFNlc3Npb24gfSBmcm9tICcuLi8uLi9PcGVuVmlkdS9TZXNzaW9uJztcblxuXG4vKipcbiAqIERlZmluZXMgZXZlbnQgYHNlc3Npb25EaXNjb25uZWN0ZWRgIGRpc3BhdGNoZWQgYnkgW1tTZXNzaW9uXV1cbiAqL1xuZXhwb3J0IGNsYXNzIFNlc3Npb25EaXNjb25uZWN0ZWRFdmVudCBleHRlbmRzIEV2ZW50IHtcblxuICAgIC8qKlxuICAgICAqIC0gXCJkaXNjb25uZWN0XCI6IHlvdSBoYXZlIGNhbGxlZCBgU2Vzc2lvbi5kaXNjb25uZWN0KClgXG4gICAgICogLSBcImZvcmNlRGlzY29ubmVjdEJ5VXNlclwiOiB5b3UgaGF2ZSBiZWVuIGV2aWN0ZWQgZnJvbSB0aGUgU2Vzc2lvbiBieSBvdGhlciB1c2VyIGNhbGxpbmcgYFNlc3Npb24uZm9yY2VEaXNjb25uZWN0KClgXG4gICAgICogLSBcImZvcmNlRGlzY29ubmVjdEJ5U2VydmVyXCI6IHlvdSBoYXZlIGJlZW4gZXZpY3RlZCBmcm9tIHRoZSBTZXNzaW9uIGJ5IHRoZSBhcHBsaWNhdGlvblxuICAgICAqIC0gXCJzZXNzaW9uQ2xvc2VkQnlTZXJ2ZXJcIjogdGhlIFNlc3Npb24gaGFzIGJlZW4gY2xvc2VkIGJ5IHRoZSBhcHBsaWNhdGlvblxuICAgICAqIC0gXCJuZXR3b3JrRGlzY29ubmVjdFwiOiB5b3VyIG5ldHdvcmsgY29ubmVjdGlvbiBoYXMgZHJvcHBlZFxuICAgICAqL1xuICAgIHJlYXNvbjogc3RyaW5nO1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHRhcmdldDogU2Vzc2lvbiwgcmVhc29uOiBzdHJpbmcpIHtcbiAgICAgICAgc3VwZXIodHJ1ZSwgdGFyZ2V0LCAnc2Vzc2lvbkRpc2Nvbm5lY3RlZCcpO1xuICAgICAgICB0aGlzLnJlYXNvbiA9IHJlYXNvbjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgY2FsbERlZmF1bHRCZWhhdmlvcigpIHtcblxuICAgICAgICBjb25zb2xlLmluZm8oXCJDYWxsaW5nIGRlZmF1bHQgYmVoYXZpb3IgdXBvbiAnXCIgKyB0aGlzLnR5cGUgKyBcIicgZXZlbnQgZGlzcGF0Y2hlZCBieSAnU2Vzc2lvbidcIik7XG5cbiAgICAgICAgY29uc3Qgc2Vzc2lvbiA9IDxTZXNzaW9uPnRoaXMudGFyZ2V0O1xuXG4gICAgICAgIC8vIERpc3Bvc2UgYW5kIGRlbGV0ZSBhbGwgcmVtb3RlIENvbm5lY3Rpb25zXG4gICAgICAgIGZvciAoY29uc3QgY29ubmVjdGlvbklkIGluIHNlc3Npb24ucmVtb3RlQ29ubmVjdGlvbnMpIHtcbiAgICAgICAgICAgIGlmICghIXNlc3Npb24ucmVtb3RlQ29ubmVjdGlvbnNbY29ubmVjdGlvbklkXS5zdHJlYW0pIHtcbiAgICAgICAgICAgICAgICBzZXNzaW9uLnJlbW90ZUNvbm5lY3Rpb25zW2Nvbm5lY3Rpb25JZF0uc3RyZWFtLmRpc3Bvc2VXZWJSdGNQZWVyKCk7XG4gICAgICAgICAgICAgICAgc2Vzc2lvbi5yZW1vdGVDb25uZWN0aW9uc1tjb25uZWN0aW9uSWRdLnN0cmVhbS5kaXNwb3NlTWVkaWFTdHJlYW0oKTtcbiAgICAgICAgICAgICAgICBpZiAoc2Vzc2lvbi5yZW1vdGVDb25uZWN0aW9uc1tjb25uZWN0aW9uSWRdLnN0cmVhbS5zdHJlYW1NYW5hZ2VyKSB7XG4gICAgICAgICAgICAgICAgICAgIHNlc3Npb24ucmVtb3RlQ29ubmVjdGlvbnNbY29ubmVjdGlvbklkXS5zdHJlYW0uc3RyZWFtTWFuYWdlci5yZW1vdmVBbGxWaWRlb3MoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZGVsZXRlIHNlc3Npb24ucmVtb3RlU3RyZWFtc0NyZWF0ZWRbc2Vzc2lvbi5yZW1vdGVDb25uZWN0aW9uc1tjb25uZWN0aW9uSWRdLnN0cmVhbS5zdHJlYW1JZF07XG4gICAgICAgICAgICAgICAgc2Vzc2lvbi5yZW1vdGVDb25uZWN0aW9uc1tjb25uZWN0aW9uSWRdLmRpc3Bvc2UoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGRlbGV0ZSBzZXNzaW9uLnJlbW90ZUNvbm5lY3Rpb25zW2Nvbm5lY3Rpb25JZF07XG4gICAgICAgIH1cbiAgICB9XG5cbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IEV2ZW50IH0gZnJvbSAnLi9FdmVudCc7XG5pbXBvcnQgeyBDb25uZWN0aW9uIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvQ29ubmVjdGlvbic7XG5pbXBvcnQgeyBTZXNzaW9uIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvU2Vzc2lvbic7XG5cblxuLyoqXG4gKiBEZWZpbmVzIHRoZSBmb2xsb3dpbmcgZXZlbnRzOlxuICogLSBgc2lnbmFsYDogZGlzcGF0Y2hlZCBieSBbW1Nlc3Npb25dXVxuICogLSBgc2lnbmFsOlRZUEVgOiBkaXNwYXRjaGVkIGJ5IFtbU2Vzc2lvbl1dXG4gKi9cbmV4cG9ydCBjbGFzcyBTaWduYWxFdmVudCBleHRlbmRzIEV2ZW50IHtcblxuICAgIC8qKlxuICAgICAqIFRoZSB0eXBlIG9mIHNpZ25hbCAoY2FuIGJlIGVtcHR5KS5cbiAgICAgKlxuICAgICAqIFRoZSBjbGllbnQgbXVzdCBiZSBzdWJzY3JpYmVkIHRvIGBTZXNzaW9uLm9uKCdzaWduYWw6dHlwZScsIGZ1bmN0aW9uKHNpZ25hbEV2ZW50KSB7Li4ufSlgIHRvIHJlY2VpdmUgdGhpcyBvYmplY3QgaW4gdGhlIGNhbGxiYWNrLlxuICAgICAqXG4gICAgICogU3Vic2NyaWJpbmcgdG8gYFNlc3Npb24ub24oJ3NpZ25hbCcsIGZ1bmN0aW9uKHNpZ25hbEV2ZW50KSB7Li4ufSlgIHdpbGwgdHJpZ2dlciBhbGwgdHlwZXMgb2Ygc2lnbmFscy5cbiAgICAgKi9cbiAgICB0eXBlOiBzdHJpbmc7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgbWVzc2FnZSBvZiB0aGUgc2lnbmFsIChjYW4gYmUgZW10cHkpXG4gICAgICovXG4gICAgZGF0YTogc3RyaW5nO1xuXG4gICAgLyoqXG4gICAgICogVGhlIGNsaWVudCB0aGF0IHNlbnQgdGhlIHNpZ25hbFxuICAgICAqL1xuICAgIGZyb206IENvbm5lY3Rpb247XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgY29uc3RydWN0b3IodGFyZ2V0OiBTZXNzaW9uLCB0eXBlOiBzdHJpbmcsIGRhdGE6IHN0cmluZywgZnJvbTogQ29ubmVjdGlvbikge1xuICAgICAgICBzdXBlcihmYWxzZSwgdGFyZ2V0LCB0eXBlKTtcbiAgICAgICAgdGhpcy50eXBlID0gdHlwZTtcbiAgICAgICAgdGhpcy5kYXRhID0gZGF0YTtcbiAgICAgICAgdGhpcy5mcm9tID0gZnJvbTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lOm5vLWVtcHR5XG4gICAgY2FsbERlZmF1bHRCZWhhdmlvcigpIHsgfVxuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBFdmVudCB9IGZyb20gJy4vRXZlbnQnO1xuaW1wb3J0IHsgUHVibGlzaGVyIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvUHVibGlzaGVyJztcbmltcG9ydCB7IFNlc3Npb24gfSBmcm9tICcuLi8uLi9PcGVuVmlkdS9TZXNzaW9uJztcbmltcG9ydCB7IFN0cmVhbSB9IGZyb20gJy4uLy4uL09wZW5WaWR1L1N0cmVhbSc7XG5cblxuLyoqXG4gKiBEZWZpbmVzIHRoZSBmb2xsb3dpbmcgZXZlbnRzOlxuICogLSBgc3RyZWFtQ3JlYXRlZGA6IGRpc3BhdGNoZWQgYnkgW1tTZXNzaW9uXV0gYW5kIFtbUHVibGlzaGVyXV1cbiAqIC0gYHN0cmVhbURlc3Ryb3llZGA6IGRpc3BhdGNoZWQgYnkgW1tTZXNzaW9uXV0gYW5kIFtbUHVibGlzaGVyXV1cbiAqL1xuZXhwb3J0IGNsYXNzIFN0cmVhbUV2ZW50IGV4dGVuZHMgRXZlbnQge1xuXG4gICAgLyoqXG4gICAgICogU3RyZWFtIG9iamVjdCB0aGF0IHdhcyBjcmVhdGVkIG9yIGRlc3Ryb3llZFxuICAgICAqL1xuICAgIHN0cmVhbTogU3RyZWFtO1xuXG4gICAgLyoqXG4gICAgICogRm9yICdzdHJlYW1EZXN0cm95ZWQnIGV2ZW50OlxuICAgICAqIC0gXCJ1bnB1Ymxpc2hcIjogbWV0aG9kIGBTZXNzaW9uLnVucHVibGlzaCgpYCBoYXMgYmVlbiBjYWxsZWRcbiAgICAgKiAtIFwiZGlzY29ubmVjdFwiOiBtZXRob2QgYFNlc3Npb24uZGlzY29ubmVjdCgpYCBoYXMgYmVlbiBjYWxsZWRcbiAgICAgKiAtIFwiZm9yY2VVbnB1Ymxpc2hCeVVzZXJcIjogc29tZSB1c2VyIGhhcyBjYWxsZWQgYFNlc3Npb24uZm9yY2VVbnB1Ymxpc2goKWAgb3ZlciB0aGUgU3RyZWFtXG4gICAgICogLSBcImZvcmNlRGlzY29ubmVjdEJ5VXNlclwiOiBzb21lIHVzZXIgaGFzIGNhbGxlZCBgU2Vzc2lvbi5mb3JjZURpc2Nvbm5lY3QoKWAgb3ZlciB0aGUgU3RyZWFtXG4gICAgICogLSBcImZvcmNlVW5wdWJsaXNoQnlTZXJ2ZXJcIjogdGhlIHVzZXIncyBzdHJlYW0gaGFzIGJlZW4gdW5wdWJsaXNoZWQgZnJvbSB0aGUgU2Vzc2lvbiBieSB0aGUgYXBwbGljYXRpb25cbiAgICAgKiAtIFwiZm9yY2VEaXNjb25uZWN0QnlTZXJ2ZXJcIjogdGhlIHVzZXIgaGFzIGJlZW4gZXZpY3RlZCBmcm9tIHRoZSBTZXNzaW9uIGJ5IHRoZSBhcHBsaWNhdGlvblxuICAgICAqIC0gXCJzZXNzaW9uQ2xvc2VkQnlTZXJ2ZXJcIjogdGhlIFNlc3Npb24gaGFzIGJlZW4gY2xvc2VkIGJ5IHRoZSBhcHBsaWNhdGlvblxuICAgICAqIC0gXCJuZXR3b3JrRGlzY29ubmVjdFwiOiB0aGUgdXNlcidzIG5ldHdvcmsgY29ubmVjdGlvbiBoYXMgZHJvcHBlZFxuICAgICAqXG4gICAgICogRm9yICdzdHJlYW1DcmVhdGVkJyBlbXB0eSBzdHJpbmdcbiAgICAgKi9cbiAgICByZWFzb246IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3RvcihjYW5jZWxhYmxlOiBib29sZWFuLCB0YXJnZXQ6IFNlc3Npb24gfCBQdWJsaXNoZXIsIHR5cGU6IHN0cmluZywgc3RyZWFtOiBTdHJlYW0sIHJlYXNvbjogc3RyaW5nKSB7XG4gICAgICAgIHN1cGVyKGNhbmNlbGFibGUsIHRhcmdldCwgdHlwZSk7XG4gICAgICAgIHRoaXMuc3RyZWFtID0gc3RyZWFtO1xuICAgICAgICB0aGlzLnJlYXNvbiA9IHJlYXNvbjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgY2FsbERlZmF1bHRCZWhhdmlvcigpIHtcbiAgICAgICAgaWYgKHRoaXMudHlwZSA9PT0gJ3N0cmVhbURlc3Ryb3llZCcpIHtcblxuICAgICAgICAgICAgaWYgKHRoaXMudGFyZ2V0IGluc3RhbmNlb2YgU2Vzc2lvbikge1xuICAgICAgICAgICAgICAgIC8vIFJlbW90ZSBTdHJlYW1cbiAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oXCJDYWxsaW5nIGRlZmF1bHQgYmVoYXZpb3IgdXBvbiAnXCIgKyB0aGlzLnR5cGUgKyBcIicgZXZlbnQgZGlzcGF0Y2hlZCBieSAnU2Vzc2lvbidcIik7XG4gICAgICAgICAgICAgICAgdGhpcy5zdHJlYW0uZGlzcG9zZVdlYlJ0Y1BlZXIoKTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAodGhpcy50YXJnZXQgaW5zdGFuY2VvZiBQdWJsaXNoZXIpIHtcbiAgICAgICAgICAgICAgICAvLyBMb2NhbCBTdHJlYW1cbiAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oXCJDYWxsaW5nIGRlZmF1bHQgYmVoYXZpb3IgdXBvbiAnXCIgKyB0aGlzLnR5cGUgKyBcIicgZXZlbnQgZGlzcGF0Y2hlZCBieSAnUHVibGlzaGVyJ1wiKTtcbiAgICAgICAgICAgICAgICBjbGVhckludGVydmFsKCg8UHVibGlzaGVyPnRoaXMudGFyZ2V0KS5zY3JlZW5TaGFyZVJlc2l6ZUludGVydmFsKTtcbiAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbS5pc0xvY2FsU3RyZWFtUmVhZHlUb1B1Ymxpc2ggPSBmYWxzZTtcblxuICAgICAgICAgICAgICAgIC8vIERlbGV0ZSBQdWJsaXNoZXIgb2JqZWN0IGZyb20gT3BlblZpZHUgcHVibGlzaGVycyBhcnJheVxuICAgICAgICAgICAgICAgIGNvbnN0IG9wZW52aWR1UHVibGlzaGVycyA9ICg8UHVibGlzaGVyPnRoaXMudGFyZ2V0KS5vcGVudmlkdS5wdWJsaXNoZXJzO1xuICAgICAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgb3BlbnZpZHVQdWJsaXNoZXJzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChvcGVudmlkdVB1Ymxpc2hlcnNbaV0gPT09ICg8UHVibGlzaGVyPnRoaXMudGFyZ2V0KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgb3BlbnZpZHVQdWJsaXNoZXJzLnNwbGljZShpLCAxKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBEaXNwb3NlIHRoZSBNZWRpYVN0cmVhbSBsb2NhbCBvYmplY3RcbiAgICAgICAgICAgIHRoaXMuc3RyZWFtLmRpc3Bvc2VNZWRpYVN0cmVhbSgpO1xuXG4gICAgICAgICAgICAvLyBSZW1vdmUgZnJvbSBET00gYWxsIHZpZGVvIGVsZW1lbnRzIGFzc29jaWF0ZWQgdG8gdGhpcyBTdHJlYW0sIGlmIHRoZXJlJ3MgYSBTdHJlYW1NYW5hZ2VyIGRlZmluZWRcbiAgICAgICAgICAgIC8vIChtZXRob2QgU2Vzc2lvbi5zdWJzY3JpYmUgbXVzdCBoYXZlIGJlZW4gY2FsbGVkKVxuICAgICAgICAgICAgaWYgKHRoaXMuc3RyZWFtLnN0cmVhbU1hbmFnZXIpIHRoaXMuc3RyZWFtLnN0cmVhbU1hbmFnZXIucmVtb3ZlQWxsVmlkZW9zKCk7XG5cbiAgICAgICAgICAgIC8vIERlbGV0ZSBzdHJlYW0gZnJvbSBTZXNzaW9uLnJlbW90ZVN0cmVhbXNDcmVhdGVkIG1hcFxuICAgICAgICAgICAgZGVsZXRlIHRoaXMuc3RyZWFtLnNlc3Npb24ucmVtb3RlU3RyZWFtc0NyZWF0ZWRbdGhpcy5zdHJlYW0uc3RyZWFtSWRdO1xuXG4gICAgICAgICAgICAvLyBEZWxldGUgU3RyZWFtT3B0aW9uc1NlcnZlciBmcm9tIHJlbW90ZSBDb25uZWN0aW9uXG4gICAgICAgICAgICBjb25zdCByZW1vdGVDb25uZWN0aW9uID0gdGhpcy5zdHJlYW0uc2Vzc2lvbi5yZW1vdGVDb25uZWN0aW9uc1t0aGlzLnN0cmVhbS5jb25uZWN0aW9uLmNvbm5lY3Rpb25JZF07XG4gICAgICAgICAgICBpZiAoISFyZW1vdGVDb25uZWN0aW9uICYmICEhcmVtb3RlQ29ubmVjdGlvbi5vcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgY29uc3Qgc3RyZWFtT3B0aW9uc1NlcnZlciA9IHJlbW90ZUNvbm5lY3Rpb24ub3B0aW9ucy5zdHJlYW1zO1xuICAgICAgICAgICAgICAgIGZvciAobGV0IGkgPSBzdHJlYW1PcHRpb25zU2VydmVyLmxlbmd0aCAtIDE7IGkgPj0gMDsgLS1pKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChzdHJlYW1PcHRpb25zU2VydmVyW2ldLmlkID09PSB0aGlzLnN0cmVhbS5zdHJlYW1JZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgc3RyZWFtT3B0aW9uc1NlcnZlci5zcGxpY2UoaSwgMSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgfVxuICAgIH1cblxufSIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTctMjAxOCBPcGVuVmlkdSAoaHR0cHM6Ly9vcGVudmlkdS5pby8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuaW1wb3J0IHsgRXZlbnQgfSBmcm9tICcuL0V2ZW50JztcbmltcG9ydCB7IFN0cmVhbU1hbmFnZXIgfSBmcm9tICcuLi8uLi9PcGVuVmlkdS9TdHJlYW1NYW5hZ2VyJztcblxuLyoqXG4gKiBEZWZpbmVzIHRoZSBmb2xsb3dpbmcgZXZlbnRzOlxuICogLSBgc3RyZWFtUGxheWluZ2A6IGRpc3BhdGNoZWQgYnkgW1tTdHJlYW1NYW5hZ2VyXV0gKFtbUHVibGlzaGVyXV0gYW5kIFtbU3Vic2NyaWJlcl1dKVxuICovXG5leHBvcnQgY2xhc3MgU3RyZWFtTWFuYWdlckV2ZW50IGV4dGVuZHMgRXZlbnQge1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHRhcmdldDogU3RyZWFtTWFuYWdlcikge1xuICAgICAgICBzdXBlcihmYWxzZSwgdGFyZ2V0LCAnc3RyZWFtUGxheWluZycpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6bm8tZW1wdHlcbiAgICBjYWxsRGVmYXVsdEJlaGF2aW9yKCkgeyB9XG5cbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IEV2ZW50IH0gZnJvbSAnLi9FdmVudCc7XG5pbXBvcnQgeyBTZXNzaW9uIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvU2Vzc2lvbic7XG5pbXBvcnQgeyBTdHJlYW0gfSBmcm9tICcuLi8uLi9PcGVuVmlkdS9TdHJlYW0nO1xuaW1wb3J0IHsgU3RyZWFtTWFuYWdlciB9IGZyb20gJy4uLy4uL09wZW5WaWR1L1N0cmVhbU1hbmFnZXInO1xuXG4vKipcbiAqIERlZmluZXMgZXZlbnQgYHN0cmVhbVByb3BlcnR5Q2hhbmdlZGAgZGlzcGF0Y2hlZCBieSBbW1Nlc3Npb25dXSBhcyB3ZWxsIGFzIGJ5IFtbU3RyZWFtTWFuYWdlcl1dIChbW1B1Ymxpc2hlcl1dIGFuZCBbW1N1YnNjcmliZXJdXSkuXG4gKiBUaGlzIGV2ZW50IGlzIGZpcmVkIHdoZW4gYW55IHJlbW90ZSBzdHJlYW0gKG93bmVkIGJ5IGEgU3Vic2NyaWJlcikgb3IgbG9jYWwgc3RyZWFtIChvd25lZCBieSBhIFB1Ymxpc2hlcikgdW5kZXJnb2VzXG4gKiBhbnkgY2hhbmdlIGluIGFueSBvZiBpdHMgbXV0YWJsZSBwcm9wZXJ0aWVzIChzZWUgW1tjaGFuZ2VkUHJvcGVydHldXSkuXG4gKi9cbmV4cG9ydCBjbGFzcyBTdHJlYW1Qcm9wZXJ0eUNoYW5nZWRFdmVudCBleHRlbmRzIEV2ZW50IHtcblxuICAgIC8qKlxuICAgICAqIFRoZSBTdHJlYW0gd2hvc2UgcHJvcGVydHkgaGFzIGNoYW5nZWQuIFlvdSBjYW4gYWx3YXlzIGlkZW50aWZ5IHRoZSB1c2VyIHB1Ymxpc2hpbmcgdGhlIGNoYW5nZWQgc3RyZWFtIGJ5IGNvbnN1bHRpbmcgcHJvcGVydHkgW1tTdHJlYW0uY29ubmVjdGlvbl1dXG4gICAgICovXG4gICAgc3RyZWFtOiBTdHJlYW07XG5cbiAgICAvKipcbiAgICAgKiBUaGUgcHJvcGVydHkgb2YgdGhlIHN0cmVhbSB0aGF0IGNoYW5nZWQuIFRoaXMgdmFsdWUgaXMgZWl0aGVyIGBcInZpZGVvQWN0aXZlXCJgLCBgXCJhdWRpb0FjdGl2ZVwiYCBvciBgXCJ2aWRlb0RpbWVuc2lvbnNcImBcbiAgICAgKi9cbiAgICBjaGFuZ2VkUHJvcGVydHk6IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIENhdXNlIG9mIHRoZSBjaGFuZ2Ugb24gdGhlIHN0cmVhbSdzIHByb3BlcnR5OlxuICAgICAqIC0gRm9yIGB2aWRlb0FjdGl2ZWA6IGBcInB1Ymxpc2hWaWRlb1wiYFxuICAgICAqIC0gRm9yIGBhdWRpb0FjdGl2ZWA6IGBcInB1Ymxpc2hBdWRpb1wiYFxuICAgICAqIC0gRm9yIGB2aWRlb0RpbWVuc2lvbnNgOiBgXCJkZXZpY2VSb3RhdGVkXCJgIG9yIGBcInNjcmVlblJlc2l6ZWRcImBcbiAgICAgKi9cbiAgICByZWFzb246IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIE5ldyB2YWx1ZSBvZiB0aGUgcHJvcGVydHkgKGFmdGVyIGNoYW5nZSwgY3VycmVudCB2YWx1ZSlcbiAgICAgKi9cbiAgICBuZXdWYWx1ZTogT2JqZWN0O1xuXG4gICAgLyoqXG4gICAgICogUHJldmlvdXMgdmFsdWUgb2YgdGhlIHByb3BlcnR5IChiZWZvcmUgY2hhbmdlKVxuICAgICAqL1xuICAgIG9sZFZhbHVlOiBPYmplY3Q7XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgY29uc3RydWN0b3IodGFyZ2V0OiBTZXNzaW9uIHwgU3RyZWFtTWFuYWdlciwgc3RyZWFtOiBTdHJlYW0sIGNoYW5nZWRQcm9wZXJ0eTogc3RyaW5nLCBuZXdWYWx1ZTogT2JqZWN0LCBvbGRWYWx1ZTogT2JqZWN0LCByZWFzb246IHN0cmluZykge1xuICAgICAgICBzdXBlcihmYWxzZSwgdGFyZ2V0LCAnc3RyZWFtUHJvcGVydHlDaGFuZ2VkJyk7XG4gICAgICAgIHRoaXMuc3RyZWFtID0gc3RyZWFtO1xuICAgICAgICB0aGlzLmNoYW5nZWRQcm9wZXJ0eSA9IGNoYW5nZWRQcm9wZXJ0eTtcbiAgICAgICAgdGhpcy5uZXdWYWx1ZSA9IG5ld1ZhbHVlO1xuICAgICAgICB0aGlzLm9sZFZhbHVlID0gb2xkVmFsdWU7XG4gICAgICAgIHRoaXMucmVhc29uID0gcmVhc29uO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6bm8tZW1wdHlcbiAgICBjYWxsRGVmYXVsdEJlaGF2aW9yKCkgeyB9XG5cbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IEV2ZW50IH0gZnJvbSAnLi9FdmVudCc7XG5pbXBvcnQgeyBTdHJlYW1NYW5hZ2VyIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvU3RyZWFtTWFuYWdlcic7XG5cblxuLyoqXG4gKiBEZWZpbmVzIHRoZSBmb2xsb3dpbmcgZXZlbnRzOlxuICogLSBgdmlkZW9FbGVtZW50Q3JlYXRlZGA6IGRpc3BhdGNoZWQgYnkgW1tQdWJsaXNoZXJdXSBhbmQgW1tTdWJzY3JpYmVyXV0gd2hlbmV2ZXIgYSBuZXcgSFRNTCB2aWRlbyBlbGVtZW50IGhhcyBiZWVuIGluc2VydGVkIGludG8gRE9NIGJ5IE9wZW5WaWR1IEJyb3dzZXIgbGlicmFyeS4gU2VlXG4gKiBbTWFuYWdlIHZpZGVvIHBsYXllcnNdKC9kb2NzL2hvdy1kby1pL21hbmFnZS12aWRlb3MpIHNlY3Rpb24uXG4gKiAtIGB2aWRlb0VsZW1lbnREZXN0cm95ZWRgOiBkaXNwYXRjaGVkIGJ5IFtbUHVibGlzaGVyXV0gYW5kIFtbU3Vic2NyaWJlcl1dIHdoZW5ldmVyIGFuIEhUTUwgdmlkZW8gZWxlbWVudCBoYXMgYmVlbiByZW1vdmVkIGZyb20gRE9NIGJ5IE9wZW5WaWR1IEJyb3dzZXIgbGlicmFyeS5cbiAqL1xuZXhwb3J0IGNsYXNzIFZpZGVvRWxlbWVudEV2ZW50IGV4dGVuZHMgRXZlbnQge1xuXG4gICAgLyoqXG4gICAgICogVmlkZW8gZWxlbWVudCB0aGF0IHdhcyBjcmVhdGVkIG9yIGRlc3Ryb3llZFxuICAgICAqL1xuICAgIGVsZW1lbnQ6IEhUTUxWaWRlb0VsZW1lbnQ7XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgY29uc3RydWN0b3IoZWxlbWVudDogSFRNTFZpZGVvRWxlbWVudCwgdGFyZ2V0OiBTdHJlYW1NYW5hZ2VyLCB0eXBlOiBzdHJpbmcpIHtcbiAgICAgICAgc3VwZXIoZmFsc2UsIHRhcmdldCwgdHlwZSk7XG4gICAgICAgIHRoaXMuZWxlbWVudCA9IGVsZW1lbnQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZTpuby1lbXB0eVxuICAgIGNhbGxEZWZhdWx0QmVoYXZpb3IoKSB7IH1cblxufSIsImZ1bmN0aW9uIE1hcHBlcigpXG57XG4gIHZhciBzb3VyY2VzID0ge307XG5cblxuICB0aGlzLmZvckVhY2ggPSBmdW5jdGlvbihjYWxsYmFjaylcbiAge1xuICAgIGZvcih2YXIga2V5IGluIHNvdXJjZXMpXG4gICAge1xuICAgICAgdmFyIHNvdXJjZSA9IHNvdXJjZXNba2V5XTtcblxuICAgICAgZm9yKHZhciBrZXkyIGluIHNvdXJjZSlcbiAgICAgICAgY2FsbGJhY2soc291cmNlW2tleTJdKTtcbiAgICB9O1xuICB9O1xuXG4gIHRoaXMuZ2V0ID0gZnVuY3Rpb24oaWQsIHNvdXJjZSlcbiAge1xuICAgIHZhciBpZHMgPSBzb3VyY2VzW3NvdXJjZV07XG4gICAgaWYoaWRzID09IHVuZGVmaW5lZClcbiAgICAgIHJldHVybiB1bmRlZmluZWQ7XG5cbiAgICByZXR1cm4gaWRzW2lkXTtcbiAgfTtcblxuICB0aGlzLnJlbW92ZSA9IGZ1bmN0aW9uKGlkLCBzb3VyY2UpXG4gIHtcbiAgICB2YXIgaWRzID0gc291cmNlc1tzb3VyY2VdO1xuICAgIGlmKGlkcyA9PSB1bmRlZmluZWQpXG4gICAgICByZXR1cm47XG5cbiAgICBkZWxldGUgaWRzW2lkXTtcblxuICAgIC8vIENoZWNrIGl0J3MgZW1wdHlcbiAgICBmb3IodmFyIGkgaW4gaWRzKXtyZXR1cm4gZmFsc2V9XG5cbiAgICBkZWxldGUgc291cmNlc1tzb3VyY2VdO1xuICB9O1xuXG4gIHRoaXMuc2V0ID0gZnVuY3Rpb24odmFsdWUsIGlkLCBzb3VyY2UpXG4gIHtcbiAgICBpZih2YWx1ZSA9PSB1bmRlZmluZWQpXG4gICAgICByZXR1cm4gdGhpcy5yZW1vdmUoaWQsIHNvdXJjZSk7XG5cbiAgICB2YXIgaWRzID0gc291cmNlc1tzb3VyY2VdO1xuICAgIGlmKGlkcyA9PSB1bmRlZmluZWQpXG4gICAgICBzb3VyY2VzW3NvdXJjZV0gPSBpZHMgPSB7fTtcblxuICAgIGlkc1tpZF0gPSB2YWx1ZTtcbiAgfTtcbn07XG5cblxuTWFwcGVyLnByb3RvdHlwZS5wb3AgPSBmdW5jdGlvbihpZCwgc291cmNlKVxue1xuICB2YXIgdmFsdWUgPSB0aGlzLmdldChpZCwgc291cmNlKTtcbiAgaWYodmFsdWUgPT0gdW5kZWZpbmVkKVxuICAgIHJldHVybiB1bmRlZmluZWQ7XG5cbiAgdGhpcy5yZW1vdmUoaWQsIHNvdXJjZSk7XG5cbiAgcmV0dXJuIHZhbHVlO1xufTtcblxuXG5tb2R1bGUuZXhwb3J0cyA9IE1hcHBlcjtcbiIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTQgS3VyZW50byAoaHR0cDovL2t1cmVudG8ub3JnLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG52YXIgSnNvblJwY0NsaWVudCAgPSByZXF1aXJlKCcuL2pzb25ycGNjbGllbnQnKTtcblxuXG5leHBvcnRzLkpzb25ScGNDbGllbnQgID0gSnNvblJwY0NsaWVudDsiLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE0IEt1cmVudG8gKGh0dHA6Ly9rdXJlbnRvLm9yZy8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxudmFyIFJwY0J1aWxkZXIgPSByZXF1aXJlKCcuLi8nKTtcbnZhciBXZWJTb2NrZXRXaXRoUmVjb25uZWN0aW9uID0gcmVxdWlyZSgnLi90cmFuc3BvcnRzL3dlYlNvY2tldFdpdGhSZWNvbm5lY3Rpb24nKTtcblxuRGF0ZS5ub3cgPSBEYXRlLm5vdyB8fCBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gK25ldyBEYXRlO1xufTtcblxudmFyIFBJTkdfSU5URVJWQUwgPSA1MDAwO1xuXG52YXIgUkVDT05ORUNUSU5HID0gJ1JFQ09OTkVDVElORyc7XG52YXIgQ09OTkVDVEVEID0gJ0NPTk5FQ1RFRCc7XG52YXIgRElTQ09OTkVDVEVEID0gJ0RJU0NPTk5FQ1RFRCc7XG5cbnZhciBMb2dnZXIgPSBjb25zb2xlO1xuXG4vKipcbiAqXG4gKiBoZWFydGJlYXQ6IGludGVydmFsIGluIG1zIGZvciBlYWNoIGhlYXJ0YmVhdCBtZXNzYWdlLFxuICogc2VuZENsb3NlTWVzc2FnZSA6IHRydWUgLyBmYWxzZSwgYmVmb3JlIGNsb3NpbmcgdGhlIGNvbm5lY3Rpb24sIGl0IHNlbmRzIGEgY2xvc2VTZXNzaW9uIG1lc3NhZ2VcbiAqIDxwcmU+XG4gKiB3cyA6IHtcbiAqIFx0dXJpIDogVVJJIHRvIGNvbm50ZWN0IHRvLFxuICogIHVzZVNvY2tKUyA6IHRydWUgKHVzZSBTb2NrSlMpIC8gZmFsc2UgKHVzZSBXZWJTb2NrZXQpIGJ5IGRlZmF1bHQsXG4gKiBcdG9uY29ubmVjdGVkIDogY2FsbGJhY2sgbWV0aG9kIHRvIGludm9rZSB3aGVuIGNvbm5lY3Rpb24gaXMgc3VjY2Vzc2Z1bCxcbiAqIFx0b25kaXNjb25uZWN0IDogY2FsbGJhY2sgbWV0aG9kIHRvIGludm9rZSB3aGVuIHRoZSBjb25uZWN0aW9uIGlzIGxvc3QsXG4gKiBcdG9ucmVjb25uZWN0aW5nIDogY2FsbGJhY2sgbWV0aG9kIHRvIGludm9rZSB3aGVuIHRoZSBjbGllbnQgaXMgcmVjb25uZWN0aW5nLFxuICogXHRvbnJlY29ubmVjdGVkIDogY2FsbGJhY2sgbWV0aG9kIHRvIGludm9rZSB3aGVuIHRoZSBjbGllbnQgc3VjY2Vzc2Z1bGx5IHJlY29ubmVjdHMsXG4gKiBcdG9uZXJyb3IgOiBjYWxsYmFjayBtZXRob2QgdG8gaW52b2tlIHdoZW4gdGhlcmUgaXMgYW4gZXJyb3JcbiAqIH0sXG4gKiBycGMgOiB7XG4gKiBcdHJlcXVlc3RUaW1lb3V0IDogdGltZW91dCBmb3IgYSByZXF1ZXN0LFxuICogXHRzZXNzaW9uU3RhdHVzQ2hhbmdlZDogY2FsbGJhY2sgbWV0aG9kIGZvciBjaGFuZ2VzIGluIHNlc3Npb24gc3RhdHVzLFxuICogXHRtZWRpYVJlbmVnb3RpYXRpb246IG1lZGlhUmVuZWdvdGlhdGlvblxuICogfVxuICogPC9wcmU+XG4gKi9cbmZ1bmN0aW9uIEpzb25ScGNDbGllbnQoY29uZmlndXJhdGlvbikge1xuXG4gICAgdmFyIHNlbGYgPSB0aGlzO1xuXG4gICAgdmFyIHdzQ29uZmlnID0gY29uZmlndXJhdGlvbi53cztcblxuICAgIHZhciBub3RSZWNvbm5lY3RJZk51bUxlc3NUaGFuID0gLTE7XG5cbiAgICB2YXIgcGluZ05leHROdW0gPSAwO1xuICAgIHZhciBlbmFibGVkUGluZ3MgPSB0cnVlO1xuICAgIHZhciBwaW5nUG9uZ1N0YXJ0ZWQgPSBmYWxzZTtcbiAgICB2YXIgcGluZ0ludGVydmFsO1xuXG4gICAgdmFyIHN0YXR1cyA9IERJU0NPTk5FQ1RFRDtcblxuICAgIHZhciBvbnJlY29ubmVjdGluZyA9IHdzQ29uZmlnLm9ucmVjb25uZWN0aW5nO1xuICAgIHZhciBvbnJlY29ubmVjdGVkID0gd3NDb25maWcub25yZWNvbm5lY3RlZDtcbiAgICB2YXIgb25jb25uZWN0ZWQgPSB3c0NvbmZpZy5vbmNvbm5lY3RlZDtcbiAgICB2YXIgb25lcnJvciA9IHdzQ29uZmlnLm9uZXJyb3I7XG5cbiAgICBjb25maWd1cmF0aW9uLnJwYy5wdWxsID0gZnVuY3Rpb24ocGFyYW1zLCByZXF1ZXN0KSB7XG4gICAgICAgIHJlcXVlc3QucmVwbHkobnVsbCwgXCJwdXNoXCIpO1xuICAgIH1cblxuICAgIHdzQ29uZmlnLm9ucmVjb25uZWN0aW5nID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIExvZ2dlci5kZWJ1ZyhcIi0tLS0tLS0tLSBPTlJFQ09OTkVDVElORyAtLS0tLS0tLS0tLVwiKTtcbiAgICAgICAgaWYgKHN0YXR1cyA9PT0gUkVDT05ORUNUSU5HKSB7XG4gICAgICAgICAgICBMb2dnZXIuZXJyb3IoXCJXZWJzb2NrZXQgYWxyZWFkeSBpbiBSRUNPTk5FQ1RJTkcgc3RhdGUgd2hlbiByZWNlaXZpbmcgYSBuZXcgT05SRUNPTk5FQ1RJTkcgbWVzc2FnZS4gSWdub3JpbmcgaXRcIik7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBzdGF0dXMgPSBSRUNPTk5FQ1RJTkc7XG4gICAgICAgIGlmIChvbnJlY29ubmVjdGluZykge1xuICAgICAgICAgICAgb25yZWNvbm5lY3RpbmcoKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHdzQ29uZmlnLm9ucmVjb25uZWN0ZWQgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgTG9nZ2VyLmRlYnVnKFwiLS0tLS0tLS0tIE9OUkVDT05ORUNURUQgLS0tLS0tLS0tLS1cIik7XG4gICAgICAgIGlmIChzdGF0dXMgPT09IENPTk5FQ1RFRCkge1xuICAgICAgICAgICAgTG9nZ2VyLmVycm9yKFwiV2Vic29ja2V0IGFscmVhZHkgaW4gQ09OTkVDVEVEIHN0YXRlIHdoZW4gcmVjZWl2aW5nIGEgbmV3IE9OUkVDT05ORUNURUQgbWVzc2FnZS4gSWdub3JpbmcgaXRcIik7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgc3RhdHVzID0gQ09OTkVDVEVEO1xuXG4gICAgICAgIGVuYWJsZWRQaW5ncyA9IHRydWU7XG4gICAgICAgIHVwZGF0ZU5vdFJlY29ubmVjdElmTGVzc1RoYW4oKTtcbiAgICAgICAgdXNlUGluZygpO1xuXG4gICAgICAgIGlmIChvbnJlY29ubmVjdGVkKSB7XG4gICAgICAgICAgICBvbnJlY29ubmVjdGVkKCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB3c0NvbmZpZy5vbmNvbm5lY3RlZCA9IGZ1bmN0aW9uKCkge1xuICAgICAgICBMb2dnZXIuZGVidWcoXCItLS0tLS0tLS0gT05DT05ORUNURUQgLS0tLS0tLS0tLS1cIik7XG4gICAgICAgIGlmIChzdGF0dXMgPT09IENPTk5FQ1RFRCkge1xuICAgICAgICAgICAgTG9nZ2VyLmVycm9yKFwiV2Vic29ja2V0IGFscmVhZHkgaW4gQ09OTkVDVEVEIHN0YXRlIHdoZW4gcmVjZWl2aW5nIGEgbmV3IE9OQ09OTkVDVEVEIG1lc3NhZ2UuIElnbm9yaW5nIGl0XCIpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHN0YXR1cyA9IENPTk5FQ1RFRDtcblxuICAgICAgICBlbmFibGVkUGluZ3MgPSB0cnVlO1xuICAgICAgICB1c2VQaW5nKCk7XG5cbiAgICAgICAgaWYgKG9uY29ubmVjdGVkKSB7XG4gICAgICAgICAgICBvbmNvbm5lY3RlZCgpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgd3NDb25maWcub25lcnJvciA9IGZ1bmN0aW9uKGVycm9yKSB7XG4gICAgICAgIExvZ2dlci5kZWJ1ZyhcIi0tLS0tLS0tLSBPTkVSUk9SIC0tLS0tLS0tLS0tXCIpO1xuXG4gICAgICAgIHN0YXR1cyA9IERJU0NPTk5FQ1RFRDtcblxuICAgICAgICBpZiAob25lcnJvcikge1xuICAgICAgICAgICAgb25lcnJvcihlcnJvcik7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB2YXIgd3MgPSBuZXcgV2ViU29ja2V0V2l0aFJlY29ubmVjdGlvbih3c0NvbmZpZyk7XG5cbiAgICBMb2dnZXIuZGVidWcoJ0Nvbm5lY3Rpbmcgd2Vic29ja2V0IHRvIFVSSTogJyArIHdzQ29uZmlnLnVyaSk7XG5cbiAgICB2YXIgcnBjQnVpbGRlck9wdGlvbnMgPSB7XG4gICAgICAgIHJlcXVlc3RfdGltZW91dDogY29uZmlndXJhdGlvbi5ycGMucmVxdWVzdFRpbWVvdXQsXG4gICAgICAgIHBpbmdfcmVxdWVzdF90aW1lb3V0OiBjb25maWd1cmF0aW9uLnJwYy5oZWFydGJlYXRSZXF1ZXN0VGltZW91dFxuICAgIH07XG5cbiAgICB2YXIgcnBjID0gbmV3IFJwY0J1aWxkZXIoUnBjQnVpbGRlci5wYWNrZXJzLkpzb25SUEMsIHJwY0J1aWxkZXJPcHRpb25zLCB3cyxcbiAgICAgICAgZnVuY3Rpb24ocmVxdWVzdCkge1xuXG4gICAgICAgICAgICBMb2dnZXIuZGVidWcoJ1JlY2VpdmVkIHJlcXVlc3Q6ICcgKyBKU09OLnN0cmluZ2lmeShyZXF1ZXN0KSk7XG5cbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgdmFyIGZ1bmMgPSBjb25maWd1cmF0aW9uLnJwY1tyZXF1ZXN0Lm1ldGhvZF07XG5cbiAgICAgICAgICAgICAgICBpZiAoZnVuYyA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgIExvZ2dlci5lcnJvcihcIk1ldGhvZCBcIiArIHJlcXVlc3QubWV0aG9kICsgXCIgbm90IHJlZ2lzdGVyZWQgaW4gY2xpZW50XCIpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGZ1bmMocmVxdWVzdC5wYXJhbXMsIHJlcXVlc3QpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgICAgIExvZ2dlci5lcnJvcignRXhjZXB0aW9uIHByb2Nlc3NpbmcgcmVxdWVzdDogJyArIEpTT04uc3RyaW5naWZ5KHJlcXVlc3QpKTtcbiAgICAgICAgICAgICAgICBMb2dnZXIuZXJyb3IoZXJyKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG5cbiAgICB0aGlzLnNlbmQgPSBmdW5jdGlvbihtZXRob2QsIHBhcmFtcywgY2FsbGJhY2spIHtcbiAgICAgICAgaWYgKG1ldGhvZCAhPT0gJ3BpbmcnKSB7XG4gICAgICAgICAgICBMb2dnZXIuZGVidWcoJ1JlcXVlc3Q6IG1ldGhvZDonICsgbWV0aG9kICsgXCIgcGFyYW1zOlwiICsgSlNPTi5zdHJpbmdpZnkocGFyYW1zKSk7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgcmVxdWVzdFRpbWUgPSBEYXRlLm5vdygpO1xuXG4gICAgICAgIHJwYy5lbmNvZGUobWV0aG9kLCBwYXJhbXMsIGZ1bmN0aW9uKGVycm9yLCByZXN1bHQpIHtcbiAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgIExvZ2dlci5lcnJvcihcIkVSUk9SOlwiICsgZXJyb3IubWVzc2FnZSArIFwiIGluIFJlcXVlc3Q6IG1ldGhvZDpcIiArXG4gICAgICAgICAgICAgICAgICAgICAgICBtZXRob2QgKyBcIiBwYXJhbXM6XCIgKyBKU09OLnN0cmluZ2lmeShwYXJhbXMpICsgXCIgcmVxdWVzdDpcIiArXG4gICAgICAgICAgICAgICAgICAgICAgICBlcnJvci5yZXF1ZXN0KTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yLmRhdGEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIExvZ2dlci5lcnJvcihcIkVSUk9SIERBVEE6XCIgKyBKU09OLnN0cmluZ2lmeShlcnJvci5kYXRhKSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGNhdGNoIChlKSB7fVxuICAgICAgICAgICAgICAgIGVycm9yLnJlcXVlc3RUaW1lID0gcmVxdWVzdFRpbWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoY2FsbGJhY2spIHtcbiAgICAgICAgICAgICAgICBpZiAocmVzdWx0ICE9IHVuZGVmaW5lZCAmJiByZXN1bHQudmFsdWUgIT09ICdwb25nJykge1xuICAgICAgICAgICAgICAgICAgICBMb2dnZXIuZGVidWcoJ1Jlc3BvbnNlOiAnICsgSlNPTi5zdHJpbmdpZnkocmVzdWx0KSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNhbGxiYWNrKGVycm9yLCByZXN1bHQpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiB1cGRhdGVOb3RSZWNvbm5lY3RJZkxlc3NUaGFuKCkge1xuICAgICAgICBMb2dnZXIuZGVidWcoXCJub3RSZWNvbm5lY3RJZk51bUxlc3NUaGFuID0gXCIgKyBwaW5nTmV4dE51bSArICcgKG9sZD0nICtcbiAgICAgICAgICAgIG5vdFJlY29ubmVjdElmTnVtTGVzc1RoYW4gKyAnKScpO1xuICAgICAgICBub3RSZWNvbm5lY3RJZk51bUxlc3NUaGFuID0gcGluZ05leHROdW07XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gc2VuZFBpbmcoKSB7XG4gICAgICAgIGlmIChlbmFibGVkUGluZ3MpIHtcbiAgICAgICAgICAgIHZhciBwYXJhbXMgPSBudWxsO1xuICAgICAgICAgICAgaWYgKHBpbmdOZXh0TnVtID09IDAgfHwgcGluZ05leHROdW0gPT0gbm90UmVjb25uZWN0SWZOdW1MZXNzVGhhbikge1xuICAgICAgICAgICAgICAgIHBhcmFtcyA9IHtcbiAgICAgICAgICAgICAgICAgICAgaW50ZXJ2YWw6IGNvbmZpZ3VyYXRpb24uaGVhcnRiZWF0IHx8IFBJTkdfSU5URVJWQUxcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcGluZ05leHROdW0rKztcblxuICAgICAgICAgICAgc2VsZi5zZW5kKCdwaW5nJywgcGFyYW1zLCAoZnVuY3Rpb24ocGluZ051bSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmdW5jdGlvbihlcnJvciwgcmVzdWx0KSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFwiRXJyb3IgaW4gcGluZyByZXF1ZXN0ICNcIiArIHBpbmdOdW0gKyBcIiAoXCIgK1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yLm1lc3NhZ2UgKyBcIilcIik7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocGluZ051bSA+IG5vdFJlY29ubmVjdElmTnVtTGVzc1RoYW4pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbmFibGVkUGluZ3MgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB1cGRhdGVOb3RSZWNvbm5lY3RJZkxlc3NUaGFuKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFwiU2VydmVyIGRpZCBub3QgcmVzcG9uZCB0byBwaW5nIG1lc3NhZ2UgI1wiICtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGluZ051bSArIFwiLiBSZWNvbm5lY3RpbmcuLi4gXCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdzLnJlY29ubmVjdFdzKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KShwaW5nTmV4dE51bSkpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFwiVHJ5aW5nIHRvIHNlbmQgcGluZywgYnV0IHBpbmcgaXMgbm90IGVuYWJsZWRcIik7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKlxuICAgICogSWYgY29uZmlndXJhdGlvbi5oZWFyYmVhdCBoYXMgYW55IHZhbHVlLCB0aGUgcGluZy1wb25nIHdpbGwgd29yayB3aXRoIHRoZSBpbnRlcnZhbFxuICAgICogb2YgY29uZmlndXJhdGlvbi5oZWFyYmVhdFxuICAgICovXG4gICAgZnVuY3Rpb24gdXNlUGluZygpIHtcbiAgICAgICAgaWYgKCFwaW5nUG9uZ1N0YXJ0ZWQpIHtcbiAgICAgICAgICAgIExvZ2dlci5kZWJ1ZyhcIlN0YXJ0aW5nIHBpbmcgKGlmIGNvbmZpZ3VyZWQpXCIpXG4gICAgICAgICAgICBwaW5nUG9uZ1N0YXJ0ZWQgPSB0cnVlO1xuXG4gICAgICAgICAgICBpZiAoY29uZmlndXJhdGlvbi5oZWFydGJlYXQgIT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgcGluZ0ludGVydmFsID0gc2V0SW50ZXJ2YWwoc2VuZFBpbmcsIGNvbmZpZ3VyYXRpb24uaGVhcnRiZWF0KTtcbiAgICAgICAgICAgICAgICBzZW5kUGluZygpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgdGhpcy5jbG9zZSA9IGZ1bmN0aW9uKCkge1xuICAgICAgICBMb2dnZXIuZGVidWcoXCJDbG9zaW5nIGpzb25ScGNDbGllbnQgZXhwbGljaXRseSBieSBjbGllbnRcIik7XG5cbiAgICAgICAgaWYgKHBpbmdJbnRlcnZhbCAhPSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIExvZ2dlci5kZWJ1ZyhcIkNsZWFyaW5nIHBpbmcgaW50ZXJ2YWxcIik7XG4gICAgICAgICAgICBjbGVhckludGVydmFsKHBpbmdJbnRlcnZhbCk7XG4gICAgICAgIH1cbiAgICAgICAgcGluZ1BvbmdTdGFydGVkID0gZmFsc2U7XG4gICAgICAgIGVuYWJsZWRQaW5ncyA9IGZhbHNlO1xuXG4gICAgICAgIGlmIChjb25maWd1cmF0aW9uLnNlbmRDbG9zZU1lc3NhZ2UpIHtcbiAgICAgICAgICAgIExvZ2dlci5kZWJ1ZyhcIlNlbmRpbmcgY2xvc2UgbWVzc2FnZVwiKVxuICAgICAgICAgICAgdGhpcy5zZW5kKCdjbG9zZVNlc3Npb24nLCBudWxsLCBmdW5jdGlvbihlcnJvciwgcmVzdWx0KSB7XG4gICAgICAgICAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgIExvZ2dlci5lcnJvcihcIkVycm9yIHNlbmRpbmcgY2xvc2UgbWVzc2FnZTogXCIgKyBKU09OLnN0cmluZ2lmeShlcnJvcikpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB3cy5jbG9zZSgpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0gZWxzZSB7XG5cdFx0XHR3cy5jbG9zZSgpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gVGhpcyBtZXRob2QgaXMgb25seSBmb3IgdGVzdGluZ1xuICAgIHRoaXMuZm9yY2VDbG9zZSA9IGZ1bmN0aW9uKG1pbGxpcykge1xuICAgICAgICB3cy5mb3JjZUNsb3NlKG1pbGxpcyk7XG4gICAgfVxuXG4gICAgdGhpcy5yZWNvbm5lY3QgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgd3MucmVjb25uZWN0V3MoKTtcbiAgICB9XG59XG5cblxubW9kdWxlLmV4cG9ydHMgPSBKc29uUnBjQ2xpZW50O1xuIiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNCBLdXJlbnRvIChodHRwOi8va3VyZW50by5vcmcvKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbnZhciBXZWJTb2NrZXRXaXRoUmVjb25uZWN0aW9uICA9IHJlcXVpcmUoJy4vd2ViU29ja2V0V2l0aFJlY29ubmVjdGlvbicpO1xuXG5cbmV4cG9ydHMuV2ViU29ja2V0V2l0aFJlY29ubmVjdGlvbiAgPSBXZWJTb2NrZXRXaXRoUmVjb25uZWN0aW9uOyIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTMtMjAxNSBLdXJlbnRvIChodHRwOi8va3VyZW50by5vcmcvKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuXCJ1c2Ugc3RyaWN0XCI7XG5cbnZhciBCcm93c2VyV2ViU29ja2V0ID0gZ2xvYmFsLldlYlNvY2tldCB8fCBnbG9iYWwuTW96V2ViU29ja2V0O1xuXG52YXIgTG9nZ2VyID0gY29uc29sZTtcblxuLyoqXG4gKiBHZXQgZWl0aGVyIHRoZSBgV2ViU29ja2V0YCBvciBgTW96V2ViU29ja2V0YCBnbG9iYWxzXG4gKiBpbiB0aGUgYnJvd3NlciBvciB0cnkgdG8gcmVzb2x2ZSBXZWJTb2NrZXQtY29tcGF0aWJsZVxuICogaW50ZXJmYWNlIGV4cG9zZWQgYnkgYHdzYCBmb3IgTm9kZS1saWtlIGVudmlyb25tZW50LlxuICovXG5cbi8qdmFyIFdlYlNvY2tldCA9IEJyb3dzZXJXZWJTb2NrZXQ7XG5pZiAoIVdlYlNvY2tldCAmJiB0eXBlb2Ygd2luZG93ID09PSAndW5kZWZpbmVkJykge1xuICAgIHRyeSB7XG4gICAgICAgIFdlYlNvY2tldCA9IHJlcXVpcmUoJ3dzJyk7XG4gICAgfSBjYXRjaCAoZSkgeyB9XG59Ki9cblxuLy92YXIgU29ja0pTID0gcmVxdWlyZSgnc29ja2pzLWNsaWVudCcpO1xuXG52YXIgTUFYX1JFVFJJRVMgPSAyMDAwOyAvLyBGb3JldmVyLi4uXG52YXIgUkVUUllfVElNRV9NUyA9IDMwMDA7IC8vIEZJWE1FOiBJbXBsZW1lbnQgZXhwb25lbnRpYWwgd2FpdCB0aW1lcy4uLlxuXG52YXIgQ09OTkVDVElORyA9IDA7XG52YXIgT1BFTiA9IDE7XG52YXIgQ0xPU0lORyA9IDI7XG52YXIgQ0xPU0VEID0gMztcblxuLypcbmNvbmZpZyA9IHtcblx0XHR1cmkgOiB3c1VyaSxcblx0XHR1c2VTb2NrSlMgOiB0cnVlICh1c2UgU29ja0pTKSAvIGZhbHNlICh1c2UgV2ViU29ja2V0KSBieSBkZWZhdWx0LFxuXHRcdG9uY29ubmVjdGVkIDogY2FsbGJhY2sgbWV0aG9kIHRvIGludm9rZSB3aGVuIGNvbm5lY3Rpb24gaXMgc3VjY2Vzc2Z1bCxcblx0XHRvbmRpc2Nvbm5lY3QgOiBjYWxsYmFjayBtZXRob2QgdG8gaW52b2tlIHdoZW4gdGhlIGNvbm5lY3Rpb24gaXMgbG9zdCxcblx0XHRvbnJlY29ubmVjdGluZyA6IGNhbGxiYWNrIG1ldGhvZCB0byBpbnZva2Ugd2hlbiB0aGUgY2xpZW50IGlzIHJlY29ubmVjdGluZyxcblx0XHRvbnJlY29ubmVjdGVkIDogY2FsbGJhY2sgbWV0aG9kIHRvIGludm9rZSB3aGVuIHRoZSBjbGllbnQgc3VjY2Vzc2Z1bGx5IHJlY29ubmVjdHMsXG5cdH07XG4qL1xuZnVuY3Rpb24gV2ViU29ja2V0V2l0aFJlY29ubmVjdGlvbihjb25maWcpIHtcblxuICAgIHZhciBjbG9zaW5nID0gZmFsc2U7XG4gICAgdmFyIHJlZ2lzdGVyTWVzc2FnZUhhbmRsZXI7XG4gICAgdmFyIHdzVXJpID0gY29uZmlnLnVyaTtcbiAgICB2YXIgdXNlU29ja0pTID0gY29uZmlnLnVzZVNvY2tKUztcbiAgICB2YXIgcmVjb25uZWN0aW5nID0gZmFsc2U7XG5cbiAgICB2YXIgZm9yY2luZ0Rpc2Nvbm5lY3Rpb24gPSBmYWxzZTtcblxuICAgIHZhciB3cztcblxuICAgIGlmICh1c2VTb2NrSlMpIHtcbiAgICAgICAgd3MgPSBuZXcgU29ja0pTKHdzVXJpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICB3cyA9IG5ldyBXZWJTb2NrZXQod3NVcmkpO1xuICAgIH1cblxuICAgIHdzLm9ub3BlbiA9IGZ1bmN0aW9uKCkge1xuICAgICAgICBsb2dDb25uZWN0ZWQod3MsIHdzVXJpKTtcbiAgICAgICAgaWYgKGNvbmZpZy5vbmNvbm5lY3RlZCkge1xuICAgICAgICAgICAgY29uZmlnLm9uY29ubmVjdGVkKCk7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgd3Mub25lcnJvciA9IGZ1bmN0aW9uKGVycm9yKSB7XG4gICAgICAgIExvZ2dlci5lcnJvcihcIkNvdWxkIG5vdCBjb25uZWN0IHRvIFwiICsgd3NVcmkgKyBcIiAoaW52b2tpbmcgb25lcnJvciBpZiBkZWZpbmVkKVwiLCBlcnJvcik7XG4gICAgICAgIGlmIChjb25maWcub25lcnJvcikge1xuICAgICAgICAgICAgY29uZmlnLm9uZXJyb3IoZXJyb3IpO1xuICAgICAgICB9XG4gICAgfTtcblxuICAgIGZ1bmN0aW9uIGxvZ0Nvbm5lY3RlZCh3cywgd3NVcmkpIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIExvZ2dlci5kZWJ1ZyhcIldlYlNvY2tldCBjb25uZWN0ZWQgdG8gXCIgKyB3c1VyaSk7XG4gICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgIExvZ2dlci5lcnJvcihlKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHZhciByZWNvbm5lY3Rpb25PbkNsb3NlID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIGlmICh3cy5yZWFkeVN0YXRlID09PSBDTE9TRUQpIHtcbiAgICAgICAgICAgIGlmIChjbG9zaW5nKSB7XG4gICAgICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFwiQ29ubmVjdGlvbiBjbG9zZWQgYnkgdXNlclwiKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFwiQ29ubmVjdGlvbiBjbG9zZWQgdW5leHBlY3RlY2x5LiBSZWNvbm5lY3RpbmcuLi5cIik7XG4gICAgICAgICAgICAgICAgcmVjb25uZWN0VG9TYW1lVXJpKE1BWF9SRVRSSUVTLCAxKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIExvZ2dlci5kZWJ1ZyhcIkNsb3NlIGNhbGxiYWNrIGZyb20gcHJldmlvdXMgd2Vic29ja2V0LiBJZ25vcmluZyBpdFwiKTtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICB3cy5vbmNsb3NlID0gcmVjb25uZWN0aW9uT25DbG9zZTtcblxuICAgIGZ1bmN0aW9uIHJlY29ubmVjdFRvU2FtZVVyaShtYXhSZXRyaWVzLCBudW1SZXRyaWVzKSB7XG4gICAgICAgIExvZ2dlci5kZWJ1ZyhcInJlY29ubmVjdFRvU2FtZVVyaSAoYXR0ZW1wdCAjXCIgKyBudW1SZXRyaWVzICsgXCIsIG1heD1cIiArIG1heFJldHJpZXMgKyBcIilcIik7XG5cbiAgICAgICAgaWYgKG51bVJldHJpZXMgPT09IDEpIHtcbiAgICAgICAgICAgIGlmIChyZWNvbm5lY3RpbmcpIHtcbiAgICAgICAgICAgICAgICBMb2dnZXIud2FybihcIlRyeWluZyB0byByZWNvbm5lY3RUb05ld1VyaSB3aGVuIHJlY29ubmVjdGluZy4uLiBJZ25vcmluZyB0aGlzIHJlY29ubmVjdGlvbi5cIilcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJlY29ubmVjdGluZyA9IHRydWU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChjb25maWcub25yZWNvbm5lY3RpbmcpIHtcbiAgICAgICAgICAgICAgICBjb25maWcub25yZWNvbm5lY3RpbmcoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChmb3JjaW5nRGlzY29ubmVjdGlvbikge1xuICAgICAgICAgICAgcmVjb25uZWN0VG9OZXdVcmkobWF4UmV0cmllcywgbnVtUmV0cmllcywgd3NVcmkpO1xuXG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBpZiAoY29uZmlnLm5ld1dzVXJpT25SZWNvbm5lY3Rpb24pIHtcbiAgICAgICAgICAgICAgICBjb25maWcubmV3V3NVcmlPblJlY29ubmVjdGlvbihmdW5jdGlvbihlcnJvciwgbmV3V3NVcmkpIHtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIExvZ2dlci5kZWJ1ZyhlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlY29ubmVjdFRvU2FtZVVyaShtYXhSZXRyaWVzLCBudW1SZXRyaWVzICsgMSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9LCBSRVRSWV9USU1FX01TKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlY29ubmVjdFRvTmV3VXJpKG1heFJldHJpZXMsIG51bVJldHJpZXMsIG5ld1dzVXJpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJlY29ubmVjdFRvTmV3VXJpKG1heFJldHJpZXMsIG51bVJldHJpZXMsIHdzVXJpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIFRPRE8gVGVzdCByZXRyaWVzLiBIb3cgdG8gZm9yY2Ugbm90IGNvbm5lY3Rpb24/XG4gICAgZnVuY3Rpb24gcmVjb25uZWN0VG9OZXdVcmkobWF4UmV0cmllcywgbnVtUmV0cmllcywgcmVjb25uZWN0V3NVcmkpIHtcbiAgICAgICAgTG9nZ2VyLmRlYnVnKFwiUmVjb25uZWN0aW9uIGF0dGVtcHQgI1wiICsgbnVtUmV0cmllcyk7XG5cbiAgICAgICAgd3MuY2xvc2UoKTtcblxuICAgICAgICB3c1VyaSA9IHJlY29ubmVjdFdzVXJpIHx8IHdzVXJpO1xuXG4gICAgICAgIHZhciBuZXdXcztcbiAgICAgICAgaWYgKHVzZVNvY2tKUykge1xuICAgICAgICAgICAgbmV3V3MgPSBuZXcgU29ja0pTKHdzVXJpKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIG5ld1dzID0gbmV3IFdlYlNvY2tldCh3c1VyaSk7XG4gICAgICAgIH1cblxuICAgICAgICBuZXdXcy5vbm9wZW4gPSBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIExvZ2dlci5kZWJ1ZyhcIlJlY29ubmVjdGVkIGFmdGVyIFwiICsgbnVtUmV0cmllcyArIFwiIGF0dGVtcHRzLi4uXCIpO1xuICAgICAgICAgICAgbG9nQ29ubmVjdGVkKG5ld1dzLCB3c1VyaSk7XG4gICAgICAgICAgICByZWNvbm5lY3RpbmcgPSBmYWxzZTtcbiAgICAgICAgICAgIHJlZ2lzdGVyTWVzc2FnZUhhbmRsZXIoKTtcbiAgICAgICAgICAgIGlmIChjb25maWcub25yZWNvbm5lY3RlZCgpKSB7XG4gICAgICAgICAgICAgICAgY29uZmlnLm9ucmVjb25uZWN0ZWQoKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgbmV3V3Mub25jbG9zZSA9IHJlY29ubmVjdGlvbk9uQ2xvc2U7XG4gICAgICAgIH07XG5cbiAgICAgICAgdmFyIG9uRXJyb3JPckNsb3NlID0gZnVuY3Rpb24oZXJyb3IpIHtcbiAgICAgICAgICAgIExvZ2dlci53YXJuKFwiUmVjb25uZWN0aW9uIGVycm9yOiBcIiwgZXJyb3IpO1xuXG4gICAgICAgICAgICBpZiAobnVtUmV0cmllcyA9PT0gbWF4UmV0cmllcykge1xuICAgICAgICAgICAgICAgIGlmIChjb25maWcub25kaXNjb25uZWN0KSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbmZpZy5vbmRpc2Nvbm5lY3QoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlY29ubmVjdFRvU2FtZVVyaShtYXhSZXRyaWVzLCBudW1SZXRyaWVzICsgMSk7XG4gICAgICAgICAgICAgICAgfSwgUkVUUllfVElNRV9NUyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG5cbiAgICAgICAgbmV3V3Mub25lcnJvciA9IG9uRXJyb3JPckNsb3NlO1xuXG4gICAgICAgIHdzID0gbmV3V3M7XG4gICAgfVxuXG4gICAgdGhpcy5jbG9zZSA9IGZ1bmN0aW9uKCkge1xuICAgICAgICBjbG9zaW5nID0gdHJ1ZTtcbiAgICAgICAgd3MuY2xvc2UoKTtcbiAgICB9O1xuXG5cbiAgICAvLyBUaGlzIG1ldGhvZCBpcyBvbmx5IGZvciB0ZXN0aW5nXG4gICAgdGhpcy5mb3JjZUNsb3NlID0gZnVuY3Rpb24obWlsbGlzKSB7XG4gICAgICAgIExvZ2dlci5kZWJ1ZyhcIlRlc3Rpbmc6IEZvcmNlIFdlYlNvY2tldCBjbG9zZVwiKTtcblxuICAgICAgICBpZiAobWlsbGlzKSB7XG4gICAgICAgICAgICBMb2dnZXIuZGVidWcoXCJUZXN0aW5nOiBDaGFuZ2Ugd3NVcmkgZm9yIFwiICsgbWlsbGlzICsgXCIgbWlsbGlzIHRvIHNpbXVsYXRlIG5ldCBmYWlsdXJlXCIpO1xuICAgICAgICAgICAgdmFyIGdvb2RXc1VyaSA9IHdzVXJpO1xuICAgICAgICAgICAgd3NVcmkgPSBcIndzczovLzIxLjIzNC4xMi4zNC40OjQ0My9cIjtcblxuICAgICAgICAgICAgZm9yY2luZ0Rpc2Nvbm5lY3Rpb24gPSB0cnVlO1xuXG4gICAgICAgICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgIExvZ2dlci5kZWJ1ZyhcIlRlc3Rpbmc6IFJlY292ZXIgZ29vZCB3c1VyaSBcIiArIGdvb2RXc1VyaSk7XG4gICAgICAgICAgICAgICAgd3NVcmkgPSBnb29kV3NVcmk7XG5cbiAgICAgICAgICAgICAgICBmb3JjaW5nRGlzY29ubmVjdGlvbiA9IGZhbHNlO1xuXG4gICAgICAgICAgICB9LCBtaWxsaXMpO1xuICAgICAgICB9XG5cbiAgICAgICAgd3MuY2xvc2UoKTtcbiAgICB9O1xuXG4gICAgdGhpcy5yZWNvbm5lY3RXcyA9IGZ1bmN0aW9uKCkge1xuICAgICAgICBMb2dnZXIuZGVidWcoXCJyZWNvbm5lY3RXc1wiKTtcbiAgICAgICAgcmVjb25uZWN0VG9TYW1lVXJpKE1BWF9SRVRSSUVTLCAxLCB3c1VyaSk7XG4gICAgfTtcblxuICAgIHRoaXMuc2VuZCA9IGZ1bmN0aW9uKG1lc3NhZ2UpIHtcbiAgICAgICAgd3Muc2VuZChtZXNzYWdlKTtcbiAgICB9O1xuXG4gICAgdGhpcy5hZGRFdmVudExpc3RlbmVyID0gZnVuY3Rpb24odHlwZSwgY2FsbGJhY2spIHtcbiAgICAgICAgcmVnaXN0ZXJNZXNzYWdlSGFuZGxlciA9IGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgd3MuYWRkRXZlbnRMaXN0ZW5lcih0eXBlLCBjYWxsYmFjayk7XG4gICAgICAgIH07XG5cbiAgICAgICAgcmVnaXN0ZXJNZXNzYWdlSGFuZGxlcigpO1xuICAgIH07XG59XG5cbm1vZHVsZS5leHBvcnRzID0gV2ViU29ja2V0V2l0aFJlY29ubmVjdGlvbjtcbiIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTQgS3VyZW50byAoaHR0cDovL2t1cmVudG8ub3JnLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5cbnZhciBkZWZpbmVQcm9wZXJ0eV9JRTggPSBmYWxzZVxuaWYoT2JqZWN0LmRlZmluZVByb3BlcnR5KVxue1xuICB0cnlcbiAge1xuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh7fSwgXCJ4XCIsIHt9KTtcbiAgfVxuICBjYXRjaChlKVxuICB7XG4gICAgZGVmaW5lUHJvcGVydHlfSUU4ID0gdHJ1ZVxuICB9XG59XG5cbi8vIGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0phdmFTY3JpcHQvUmVmZXJlbmNlL0dsb2JhbF9PYmplY3RzL0Z1bmN0aW9uL2JpbmRcbmlmICghRnVuY3Rpb24ucHJvdG90eXBlLmJpbmQpIHtcbiAgRnVuY3Rpb24ucHJvdG90eXBlLmJpbmQgPSBmdW5jdGlvbihvVGhpcykge1xuICAgIGlmICh0eXBlb2YgdGhpcyAhPT0gJ2Z1bmN0aW9uJykge1xuICAgICAgLy8gY2xvc2VzdCB0aGluZyBwb3NzaWJsZSB0byB0aGUgRUNNQVNjcmlwdCA1XG4gICAgICAvLyBpbnRlcm5hbCBJc0NhbGxhYmxlIGZ1bmN0aW9uXG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdGdW5jdGlvbi5wcm90b3R5cGUuYmluZCAtIHdoYXQgaXMgdHJ5aW5nIHRvIGJlIGJvdW5kIGlzIG5vdCBjYWxsYWJsZScpO1xuICAgIH1cblxuICAgIHZhciBhQXJncyAgID0gQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzLCAxKSxcbiAgICAgICAgZlRvQmluZCA9IHRoaXMsXG4gICAgICAgIGZOT1AgICAgPSBmdW5jdGlvbigpIHt9LFxuICAgICAgICBmQm91bmQgID0gZnVuY3Rpb24oKSB7XG4gICAgICAgICAgcmV0dXJuIGZUb0JpbmQuYXBwbHkodGhpcyBpbnN0YW5jZW9mIGZOT1AgJiYgb1RoaXNcbiAgICAgICAgICAgICAgICAgPyB0aGlzXG4gICAgICAgICAgICAgICAgIDogb1RoaXMsXG4gICAgICAgICAgICAgICAgIGFBcmdzLmNvbmNhdChBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMpKSk7XG4gICAgICAgIH07XG5cbiAgICBmTk9QLnByb3RvdHlwZSA9IHRoaXMucHJvdG90eXBlO1xuICAgIGZCb3VuZC5wcm90b3R5cGUgPSBuZXcgZk5PUCgpO1xuXG4gICAgcmV0dXJuIGZCb3VuZDtcbiAgfTtcbn1cblxuXG52YXIgRXZlbnRFbWl0dGVyID0gcmVxdWlyZSgnZXZlbnRzJykuRXZlbnRFbWl0dGVyO1xuXG52YXIgaW5oZXJpdHMgPSByZXF1aXJlKCdpbmhlcml0cycpO1xuXG52YXIgcGFja2VycyA9IHJlcXVpcmUoJy4vcGFja2VycycpO1xudmFyIE1hcHBlciA9IHJlcXVpcmUoJy4vTWFwcGVyJyk7XG5cblxudmFyIEJBU0VfVElNRU9VVCA9IDUwMDA7XG5cblxuZnVuY3Rpb24gdW5pZnlSZXNwb25zZU1ldGhvZHMocmVzcG9uc2VNZXRob2RzKVxue1xuICBpZighcmVzcG9uc2VNZXRob2RzKSByZXR1cm4ge307XG5cbiAgZm9yKHZhciBrZXkgaW4gcmVzcG9uc2VNZXRob2RzKVxuICB7XG4gICAgdmFyIHZhbHVlID0gcmVzcG9uc2VNZXRob2RzW2tleV07XG5cbiAgICBpZih0eXBlb2YgdmFsdWUgPT0gJ3N0cmluZycpXG4gICAgICByZXNwb25zZU1ldGhvZHNba2V5XSA9XG4gICAgICB7XG4gICAgICAgIHJlc3BvbnNlOiB2YWx1ZVxuICAgICAgfVxuICB9O1xuXG4gIHJldHVybiByZXNwb25zZU1ldGhvZHM7XG59O1xuXG5mdW5jdGlvbiB1bmlmeVRyYW5zcG9ydCh0cmFuc3BvcnQpXG57XG4gIGlmKCF0cmFuc3BvcnQpIHJldHVybjtcblxuICAvLyBUcmFuc3BvcnQgYXMgYSBmdW5jdGlvblxuICBpZih0cmFuc3BvcnQgaW5zdGFuY2VvZiBGdW5jdGlvbilcbiAgICByZXR1cm4ge3NlbmQ6IHRyYW5zcG9ydH07XG5cbiAgLy8gV2ViU29ja2V0ICYgRGF0YUNoYW5uZWxcbiAgaWYodHJhbnNwb3J0LnNlbmQgaW5zdGFuY2VvZiBGdW5jdGlvbilcbiAgICByZXR1cm4gdHJhbnNwb3J0O1xuXG4gIC8vIE1lc3NhZ2UgQVBJIChJbnRlci13aW5kb3cgJiBXZWJXb3JrZXIpXG4gIGlmKHRyYW5zcG9ydC5wb3N0TWVzc2FnZSBpbnN0YW5jZW9mIEZ1bmN0aW9uKVxuICB7XG4gICAgdHJhbnNwb3J0LnNlbmQgPSB0cmFuc3BvcnQucG9zdE1lc3NhZ2U7XG4gICAgcmV0dXJuIHRyYW5zcG9ydDtcbiAgfVxuXG4gIC8vIFN0cmVhbSBBUElcbiAgaWYodHJhbnNwb3J0LndyaXRlIGluc3RhbmNlb2YgRnVuY3Rpb24pXG4gIHtcbiAgICB0cmFuc3BvcnQuc2VuZCA9IHRyYW5zcG9ydC53cml0ZTtcbiAgICByZXR1cm4gdHJhbnNwb3J0O1xuICB9XG5cbiAgLy8gVHJhbnNwb3J0cyB0aGF0IG9ubHkgY2FuIHJlY2VpdmUgbWVzc2FnZXMsIGJ1dCBub3Qgc2VuZFxuICBpZih0cmFuc3BvcnQub25tZXNzYWdlICE9PSB1bmRlZmluZWQpIHJldHVybjtcbiAgaWYodHJhbnNwb3J0LnBhdXNlIGluc3RhbmNlb2YgRnVuY3Rpb24pIHJldHVybjtcblxuICB0aHJvdyBuZXcgU3ludGF4RXJyb3IoXCJUcmFuc3BvcnQgaXMgbm90IGEgZnVuY3Rpb24gbm9yIGEgdmFsaWQgb2JqZWN0XCIpO1xufTtcblxuXG4vKipcbiAqIFJlcHJlc2VudGF0aW9uIG9mIGEgUlBDIG5vdGlmaWNhdGlvblxuICpcbiAqIEBjbGFzc1xuICpcbiAqIEBjb25zdHJ1Y3RvclxuICpcbiAqIEBwYXJhbSB7U3RyaW5nfSBtZXRob2QgLW1ldGhvZCBvZiB0aGUgbm90aWZpY2F0aW9uXG4gKiBAcGFyYW0gcGFyYW1zIC0gcGFyYW1ldGVycyBvZiB0aGUgbm90aWZpY2F0aW9uXG4gKi9cbmZ1bmN0aW9uIFJwY05vdGlmaWNhdGlvbihtZXRob2QsIHBhcmFtcylcbntcbiAgaWYoZGVmaW5lUHJvcGVydHlfSUU4KVxuICB7XG4gICAgdGhpcy5tZXRob2QgPSBtZXRob2RcbiAgICB0aGlzLnBhcmFtcyA9IHBhcmFtc1xuICB9XG4gIGVsc2VcbiAge1xuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0aGlzLCAnbWV0aG9kJywge3ZhbHVlOiBtZXRob2QsIGVudW1lcmFibGU6IHRydWV9KTtcbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkodGhpcywgJ3BhcmFtcycsIHt2YWx1ZTogcGFyYW1zLCBlbnVtZXJhYmxlOiB0cnVlfSk7XG4gIH1cbn07XG5cblxuLyoqXG4gKiBAY2xhc3NcbiAqXG4gKiBAY29uc3RydWN0b3JcbiAqXG4gKiBAcGFyYW0ge29iamVjdH0gcGFja2VyXG4gKlxuICogQHBhcmFtIHtvYmplY3R9IFtvcHRpb25zXVxuICpcbiAqIEBwYXJhbSB7b2JqZWN0fSBbdHJhbnNwb3J0XVxuICpcbiAqIEBwYXJhbSB7RnVuY3Rpb259IFtvblJlcXVlc3RdXG4gKi9cbmZ1bmN0aW9uIFJwY0J1aWxkZXIocGFja2VyLCBvcHRpb25zLCB0cmFuc3BvcnQsIG9uUmVxdWVzdClcbntcbiAgdmFyIHNlbGYgPSB0aGlzO1xuXG4gIGlmKCFwYWNrZXIpXG4gICAgdGhyb3cgbmV3IFN5bnRheEVycm9yKCdQYWNrZXIgaXMgbm90IGRlZmluZWQnKTtcblxuICBpZighcGFja2VyLnBhY2sgfHwgIXBhY2tlci51bnBhY2spXG4gICAgdGhyb3cgbmV3IFN5bnRheEVycm9yKCdQYWNrZXIgaXMgaW52YWxpZCcpO1xuXG4gIHZhciByZXNwb25zZU1ldGhvZHMgPSB1bmlmeVJlc3BvbnNlTWV0aG9kcyhwYWNrZXIucmVzcG9uc2VNZXRob2RzKTtcblxuXG4gIGlmKG9wdGlvbnMgaW5zdGFuY2VvZiBGdW5jdGlvbilcbiAge1xuICAgIGlmKHRyYW5zcG9ydCAhPSB1bmRlZmluZWQpXG4gICAgICB0aHJvdyBuZXcgU3ludGF4RXJyb3IoXCJUaGVyZSBjYW4ndCBiZSBwYXJhbWV0ZXJzIGFmdGVyIG9uUmVxdWVzdFwiKTtcblxuICAgIG9uUmVxdWVzdCA9IG9wdGlvbnM7XG4gICAgdHJhbnNwb3J0ID0gdW5kZWZpbmVkO1xuICAgIG9wdGlvbnMgICA9IHVuZGVmaW5lZDtcbiAgfTtcblxuICBpZihvcHRpb25zICYmIG9wdGlvbnMuc2VuZCBpbnN0YW5jZW9mIEZ1bmN0aW9uKVxuICB7XG4gICAgaWYodHJhbnNwb3J0ICYmICEodHJhbnNwb3J0IGluc3RhbmNlb2YgRnVuY3Rpb24pKVxuICAgICAgdGhyb3cgbmV3IFN5bnRheEVycm9yKFwiT25seSBhIGZ1bmN0aW9uIGNhbiBiZSBhZnRlciB0cmFuc3BvcnRcIik7XG5cbiAgICBvblJlcXVlc3QgPSB0cmFuc3BvcnQ7XG4gICAgdHJhbnNwb3J0ID0gb3B0aW9ucztcbiAgICBvcHRpb25zICAgPSB1bmRlZmluZWQ7XG4gIH07XG5cbiAgaWYodHJhbnNwb3J0IGluc3RhbmNlb2YgRnVuY3Rpb24pXG4gIHtcbiAgICBpZihvblJlcXVlc3QgIT0gdW5kZWZpbmVkKVxuICAgICAgdGhyb3cgbmV3IFN5bnRheEVycm9yKFwiVGhlcmUgY2FuJ3QgYmUgcGFyYW1ldGVycyBhZnRlciBvblJlcXVlc3RcIik7XG5cbiAgICBvblJlcXVlc3QgPSB0cmFuc3BvcnQ7XG4gICAgdHJhbnNwb3J0ID0gdW5kZWZpbmVkO1xuICB9O1xuXG4gIGlmKHRyYW5zcG9ydCAmJiB0cmFuc3BvcnQuc2VuZCBpbnN0YW5jZW9mIEZ1bmN0aW9uKVxuICAgIGlmKG9uUmVxdWVzdCAmJiAhKG9uUmVxdWVzdCBpbnN0YW5jZW9mIEZ1bmN0aW9uKSlcbiAgICAgIHRocm93IG5ldyBTeW50YXhFcnJvcihcIk9ubHkgYSBmdW5jdGlvbiBjYW4gYmUgYWZ0ZXIgdHJhbnNwb3J0XCIpO1xuXG4gIG9wdGlvbnMgPSBvcHRpb25zIHx8IHt9O1xuXG5cbiAgRXZlbnRFbWl0dGVyLmNhbGwodGhpcyk7XG5cbiAgaWYob25SZXF1ZXN0KVxuICAgIHRoaXMub24oJ3JlcXVlc3QnLCBvblJlcXVlc3QpO1xuXG5cbiAgaWYoZGVmaW5lUHJvcGVydHlfSUU4KVxuICAgIHRoaXMucGVlcklEID0gb3B0aW9ucy5wZWVySURcbiAgZWxzZVxuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0aGlzLCAncGVlcklEJywge3ZhbHVlOiBvcHRpb25zLnBlZXJJRH0pO1xuXG4gIHZhciBtYXhfcmV0cmllcyA9IG9wdGlvbnMubWF4X3JldHJpZXMgfHwgMDtcblxuXG4gIGZ1bmN0aW9uIHRyYW5zcG9ydE1lc3NhZ2UoZXZlbnQpXG4gIHtcbiAgICBzZWxmLmRlY29kZShldmVudC5kYXRhIHx8IGV2ZW50KTtcbiAgfTtcblxuICB0aGlzLmdldFRyYW5zcG9ydCA9IGZ1bmN0aW9uKClcbiAge1xuICAgIHJldHVybiB0cmFuc3BvcnQ7XG4gIH1cbiAgdGhpcy5zZXRUcmFuc3BvcnQgPSBmdW5jdGlvbih2YWx1ZSlcbiAge1xuICAgIC8vIFJlbW92ZSBsaXN0ZW5lciBmcm9tIG9sZCB0cmFuc3BvcnRcbiAgICBpZih0cmFuc3BvcnQpXG4gICAge1xuICAgICAgLy8gVzNDIHRyYW5zcG9ydHNcbiAgICAgIGlmKHRyYW5zcG9ydC5yZW1vdmVFdmVudExpc3RlbmVyKVxuICAgICAgICB0cmFuc3BvcnQucmVtb3ZlRXZlbnRMaXN0ZW5lcignbWVzc2FnZScsIHRyYW5zcG9ydE1lc3NhZ2UpO1xuXG4gICAgICAvLyBOb2RlLmpzIFN0cmVhbXMgQVBJXG4gICAgICBlbHNlIGlmKHRyYW5zcG9ydC5yZW1vdmVMaXN0ZW5lcilcbiAgICAgICAgdHJhbnNwb3J0LnJlbW92ZUxpc3RlbmVyKCdkYXRhJywgdHJhbnNwb3J0TWVzc2FnZSk7XG4gICAgfTtcblxuICAgIC8vIFNldCBsaXN0ZW5lciBvbiBuZXcgdHJhbnNwb3J0XG4gICAgaWYodmFsdWUpXG4gICAge1xuICAgICAgLy8gVzNDIHRyYW5zcG9ydHNcbiAgICAgIGlmKHZhbHVlLmFkZEV2ZW50TGlzdGVuZXIpXG4gICAgICAgIHZhbHVlLmFkZEV2ZW50TGlzdGVuZXIoJ21lc3NhZ2UnLCB0cmFuc3BvcnRNZXNzYWdlKTtcblxuICAgICAgLy8gTm9kZS5qcyBTdHJlYW1zIEFQSVxuICAgICAgZWxzZSBpZih2YWx1ZS5hZGRMaXN0ZW5lcilcbiAgICAgICAgdmFsdWUuYWRkTGlzdGVuZXIoJ2RhdGEnLCB0cmFuc3BvcnRNZXNzYWdlKTtcbiAgICB9O1xuXG4gICAgdHJhbnNwb3J0ID0gdW5pZnlUcmFuc3BvcnQodmFsdWUpO1xuICB9XG5cbiAgaWYoIWRlZmluZVByb3BlcnR5X0lFOClcbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkodGhpcywgJ3RyYW5zcG9ydCcsXG4gICAge1xuICAgICAgZ2V0OiB0aGlzLmdldFRyYW5zcG9ydC5iaW5kKHRoaXMpLFxuICAgICAgc2V0OiB0aGlzLnNldFRyYW5zcG9ydC5iaW5kKHRoaXMpXG4gICAgfSlcblxuICB0aGlzLnNldFRyYW5zcG9ydCh0cmFuc3BvcnQpO1xuXG5cbiAgdmFyIHJlcXVlc3RfdGltZW91dCAgICAgID0gb3B0aW9ucy5yZXF1ZXN0X3RpbWVvdXQgICAgICB8fCBCQVNFX1RJTUVPVVQ7XG4gIHZhciBwaW5nX3JlcXVlc3RfdGltZW91dCA9IG9wdGlvbnMucGluZ19yZXF1ZXN0X3RpbWVvdXQgfHwgcmVxdWVzdF90aW1lb3V0O1xuICB2YXIgcmVzcG9uc2VfdGltZW91dCAgICAgPSBvcHRpb25zLnJlc3BvbnNlX3RpbWVvdXQgICAgIHx8IEJBU0VfVElNRU9VVDtcbiAgdmFyIGR1cGxpY2F0ZXNfdGltZW91dCAgID0gb3B0aW9ucy5kdXBsaWNhdGVzX3RpbWVvdXQgICB8fCBCQVNFX1RJTUVPVVQ7XG5cblxuICB2YXIgcmVxdWVzdElEID0gMDtcblxuICB2YXIgcmVxdWVzdHMgID0gbmV3IE1hcHBlcigpO1xuICB2YXIgcmVzcG9uc2VzID0gbmV3IE1hcHBlcigpO1xuICB2YXIgcHJvY2Vzc2VkUmVzcG9uc2VzID0gbmV3IE1hcHBlcigpO1xuXG4gIHZhciBtZXNzYWdlMktleSA9IHt9O1xuXG5cbiAgLyoqXG4gICAqIFN0b3JlIHRoZSByZXNwb25zZSB0byBwcmV2ZW50IHRvIHByb2Nlc3MgZHVwbGljYXRlIHJlcXVlc3QgbGF0ZXJcbiAgICovXG4gIGZ1bmN0aW9uIHN0b3JlUmVzcG9uc2UobWVzc2FnZSwgaWQsIGRlc3QpXG4gIHtcbiAgICB2YXIgcmVzcG9uc2UgPVxuICAgIHtcbiAgICAgIG1lc3NhZ2U6IG1lc3NhZ2UsXG4gICAgICAvKiogVGltZW91dCB0byBhdXRvLWNsZWFuIG9sZCByZXNwb25zZXMgKi9cbiAgICAgIHRpbWVvdXQ6IHNldFRpbWVvdXQoZnVuY3Rpb24oKVxuICAgICAge1xuICAgICAgICByZXNwb25zZXMucmVtb3ZlKGlkLCBkZXN0KTtcbiAgICAgIH0sXG4gICAgICByZXNwb25zZV90aW1lb3V0KVxuICAgIH07XG5cbiAgICByZXNwb25zZXMuc2V0KHJlc3BvbnNlLCBpZCwgZGVzdCk7XG4gIH07XG5cbiAgLyoqXG4gICAqIFN0b3JlIHRoZSByZXNwb25zZSB0byBpZ25vcmUgZHVwbGljYXRlZCBtZXNzYWdlcyBsYXRlclxuICAgKi9cbiAgZnVuY3Rpb24gc3RvcmVQcm9jZXNzZWRSZXNwb25zZShhY2ssIGZyb20pXG4gIHtcbiAgICB2YXIgdGltZW91dCA9IHNldFRpbWVvdXQoZnVuY3Rpb24oKVxuICAgIHtcbiAgICAgIHByb2Nlc3NlZFJlc3BvbnNlcy5yZW1vdmUoYWNrLCBmcm9tKTtcbiAgICB9LFxuICAgIGR1cGxpY2F0ZXNfdGltZW91dCk7XG5cbiAgICBwcm9jZXNzZWRSZXNwb25zZXMuc2V0KHRpbWVvdXQsIGFjaywgZnJvbSk7XG4gIH07XG5cblxuICAvKipcbiAgICogUmVwcmVzZW50YXRpb24gb2YgYSBSUEMgcmVxdWVzdFxuICAgKlxuICAgKiBAY2xhc3NcbiAgICogQGV4dGVuZHMgUnBjTm90aWZpY2F0aW9uXG4gICAqXG4gICAqIEBjb25zdHJ1Y3RvclxuICAgKlxuICAgKiBAcGFyYW0ge1N0cmluZ30gbWV0aG9kIC1tZXRob2Qgb2YgdGhlIG5vdGlmaWNhdGlvblxuICAgKiBAcGFyYW0gcGFyYW1zIC0gcGFyYW1ldGVycyBvZiB0aGUgbm90aWZpY2F0aW9uXG4gICAqIEBwYXJhbSB7SW50ZWdlcn0gaWQgLSBpZGVudGlmaWVyIG9mIHRoZSByZXF1ZXN0XG4gICAqIEBwYXJhbSBbZnJvbV0gLSBzb3VyY2Ugb2YgdGhlIG5vdGlmaWNhdGlvblxuICAgKi9cbiAgZnVuY3Rpb24gUnBjUmVxdWVzdChtZXRob2QsIHBhcmFtcywgaWQsIGZyb20sIHRyYW5zcG9ydClcbiAge1xuICAgIFJwY05vdGlmaWNhdGlvbi5jYWxsKHRoaXMsIG1ldGhvZCwgcGFyYW1zKTtcblxuICAgIHRoaXMuZ2V0VHJhbnNwb3J0ID0gZnVuY3Rpb24oKVxuICAgIHtcbiAgICAgIHJldHVybiB0cmFuc3BvcnQ7XG4gICAgfVxuICAgIHRoaXMuc2V0VHJhbnNwb3J0ID0gZnVuY3Rpb24odmFsdWUpXG4gICAge1xuICAgICAgdHJhbnNwb3J0ID0gdW5pZnlUcmFuc3BvcnQodmFsdWUpO1xuICAgIH1cblxuICAgIGlmKCFkZWZpbmVQcm9wZXJ0eV9JRTgpXG4gICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkodGhpcywgJ3RyYW5zcG9ydCcsXG4gICAgICB7XG4gICAgICAgIGdldDogdGhpcy5nZXRUcmFuc3BvcnQuYmluZCh0aGlzKSxcbiAgICAgICAgc2V0OiB0aGlzLnNldFRyYW5zcG9ydC5iaW5kKHRoaXMpXG4gICAgICB9KVxuXG4gICAgdmFyIHJlc3BvbnNlID0gcmVzcG9uc2VzLmdldChpZCwgZnJvbSk7XG5cbiAgICAvKipcbiAgICAgKiBAY29uc3RhbnQge0Jvb2xlYW59IGR1cGxpY2F0ZWRcbiAgICAgKi9cbiAgICBpZighKHRyYW5zcG9ydCB8fCBzZWxmLmdldFRyYW5zcG9ydCgpKSlcbiAgICB7XG4gICAgICBpZihkZWZpbmVQcm9wZXJ0eV9JRTgpXG4gICAgICAgIHRoaXMuZHVwbGljYXRlZCA9IEJvb2xlYW4ocmVzcG9uc2UpXG4gICAgICBlbHNlXG4gICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0aGlzLCAnZHVwbGljYXRlZCcsXG4gICAgICAgIHtcbiAgICAgICAgICB2YWx1ZTogQm9vbGVhbihyZXNwb25zZSlcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgdmFyIHJlc3BvbnNlTWV0aG9kID0gcmVzcG9uc2VNZXRob2RzW21ldGhvZF07XG5cbiAgICB0aGlzLnBhY2sgPSBwYWNrZXIucGFjay5iaW5kKHBhY2tlciwgdGhpcywgaWQpXG5cbiAgICAvKipcbiAgICAgKiBHZW5lcmF0ZSBhIHJlc3BvbnNlIHRvIHRoaXMgcmVxdWVzdFxuICAgICAqXG4gICAgICogQHBhcmFtIHtFcnJvcn0gW2Vycm9yXVxuICAgICAqIEBwYXJhbSB7Kn0gW3Jlc3VsdF1cbiAgICAgKlxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9XG4gICAgICovXG4gICAgdGhpcy5yZXBseSA9IGZ1bmN0aW9uKGVycm9yLCByZXN1bHQsIHRyYW5zcG9ydClcbiAgICB7XG4gICAgICAvLyBGaXggb3B0aW9uYWwgcGFyYW1ldGVyc1xuICAgICAgaWYoZXJyb3IgaW5zdGFuY2VvZiBGdW5jdGlvbiB8fCBlcnJvciAmJiBlcnJvci5zZW5kIGluc3RhbmNlb2YgRnVuY3Rpb24pXG4gICAgICB7XG4gICAgICAgIGlmKHJlc3VsdCAhPSB1bmRlZmluZWQpXG4gICAgICAgICAgdGhyb3cgbmV3IFN5bnRheEVycm9yKFwiVGhlcmUgY2FuJ3QgYmUgcGFyYW1ldGVycyBhZnRlciBjYWxsYmFja1wiKTtcblxuICAgICAgICB0cmFuc3BvcnQgPSBlcnJvcjtcbiAgICAgICAgcmVzdWx0ID0gbnVsbDtcbiAgICAgICAgZXJyb3IgPSB1bmRlZmluZWQ7XG4gICAgICB9XG5cbiAgICAgIGVsc2UgaWYocmVzdWx0IGluc3RhbmNlb2YgRnVuY3Rpb25cbiAgICAgIHx8IHJlc3VsdCAmJiByZXN1bHQuc2VuZCBpbnN0YW5jZW9mIEZ1bmN0aW9uKVxuICAgICAge1xuICAgICAgICBpZih0cmFuc3BvcnQgIT0gdW5kZWZpbmVkKVxuICAgICAgICAgIHRocm93IG5ldyBTeW50YXhFcnJvcihcIlRoZXJlIGNhbid0IGJlIHBhcmFtZXRlcnMgYWZ0ZXIgY2FsbGJhY2tcIik7XG5cbiAgICAgICAgdHJhbnNwb3J0ID0gcmVzdWx0O1xuICAgICAgICByZXN1bHQgPSBudWxsO1xuICAgICAgfTtcblxuICAgICAgdHJhbnNwb3J0ID0gdW5pZnlUcmFuc3BvcnQodHJhbnNwb3J0KTtcblxuICAgICAgLy8gRHVwbGljYXRlZCByZXF1ZXN0LCByZW1vdmUgb2xkIHJlc3BvbnNlIHRpbWVvdXRcbiAgICAgIGlmKHJlc3BvbnNlKVxuICAgICAgICBjbGVhclRpbWVvdXQocmVzcG9uc2UudGltZW91dCk7XG5cbiAgICAgIGlmKGZyb20gIT0gdW5kZWZpbmVkKVxuICAgICAge1xuICAgICAgICBpZihlcnJvcilcbiAgICAgICAgICBlcnJvci5kZXN0ID0gZnJvbTtcblxuICAgICAgICBpZihyZXN1bHQpXG4gICAgICAgICAgcmVzdWx0LmRlc3QgPSBmcm9tO1xuICAgICAgfTtcblxuICAgICAgdmFyIG1lc3NhZ2U7XG5cbiAgICAgIC8vIE5ldyByZXF1ZXN0IG9yIG92ZXJyaWRlbiBvbmUsIGNyZWF0ZSBuZXcgcmVzcG9uc2Ugd2l0aCBwcm92aWRlZCBkYXRhXG4gICAgICBpZihlcnJvciB8fCByZXN1bHQgIT0gdW5kZWZpbmVkKVxuICAgICAge1xuICAgICAgICBpZihzZWxmLnBlZXJJRCAhPSB1bmRlZmluZWQpXG4gICAgICAgIHtcbiAgICAgICAgICBpZihlcnJvcilcbiAgICAgICAgICAgIGVycm9yLmZyb20gPSBzZWxmLnBlZXJJRDtcbiAgICAgICAgICBlbHNlXG4gICAgICAgICAgICByZXN1bHQuZnJvbSA9IHNlbGYucGVlcklEO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gUHJvdG9jb2wgaW5kaWNhdGVzIHRoYXQgcmVzcG9uc2VzIGhhcyBvd24gcmVxdWVzdCBtZXRob2RzXG4gICAgICAgIGlmKHJlc3BvbnNlTWV0aG9kKVxuICAgICAgICB7XG4gICAgICAgICAgaWYocmVzcG9uc2VNZXRob2QuZXJyb3IgPT0gdW5kZWZpbmVkICYmIGVycm9yKVxuICAgICAgICAgICAgbWVzc2FnZSA9XG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIGVycm9yOiBlcnJvclxuICAgICAgICAgICAgfTtcblxuICAgICAgICAgIGVsc2VcbiAgICAgICAgICB7XG4gICAgICAgICAgICB2YXIgbWV0aG9kID0gZXJyb3JcbiAgICAgICAgICAgICAgICAgICAgICAgPyByZXNwb25zZU1ldGhvZC5lcnJvclxuICAgICAgICAgICAgICAgICAgICAgICA6IHJlc3BvbnNlTWV0aG9kLnJlc3BvbnNlO1xuXG4gICAgICAgICAgICBtZXNzYWdlID1cbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgbWV0aG9kOiBtZXRob2QsXG4gICAgICAgICAgICAgIHBhcmFtczogZXJyb3IgfHwgcmVzdWx0XG4gICAgICAgICAgICB9O1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlXG4gICAgICAgICAgbWVzc2FnZSA9XG4gICAgICAgICAge1xuICAgICAgICAgICAgZXJyb3I6ICBlcnJvcixcbiAgICAgICAgICAgIHJlc3VsdDogcmVzdWx0XG4gICAgICAgICAgfTtcblxuICAgICAgICBtZXNzYWdlID0gcGFja2VyLnBhY2sobWVzc2FnZSwgaWQpO1xuICAgICAgfVxuXG4gICAgICAvLyBEdXBsaWNhdGUgJiBub3Qtb3ZlcnJpZGVuIHJlcXVlc3QsIHJlLXNlbmQgb2xkIHJlc3BvbnNlXG4gICAgICBlbHNlIGlmKHJlc3BvbnNlKVxuICAgICAgICBtZXNzYWdlID0gcmVzcG9uc2UubWVzc2FnZTtcblxuICAgICAgLy8gTmV3IGVtcHR5IHJlcGx5LCByZXNwb25zZSBudWxsIHZhbHVlXG4gICAgICBlbHNlXG4gICAgICAgIG1lc3NhZ2UgPSBwYWNrZXIucGFjayh7cmVzdWx0OiBudWxsfSwgaWQpO1xuXG4gICAgICAvLyBTdG9yZSB0aGUgcmVzcG9uc2UgdG8gcHJldmVudCB0byBwcm9jZXNzIGEgZHVwbGljYXRlZCByZXF1ZXN0IGxhdGVyXG4gICAgICBzdG9yZVJlc3BvbnNlKG1lc3NhZ2UsIGlkLCBmcm9tKTtcblxuICAgICAgLy8gUmV0dXJuIHRoZSBzdG9yZWQgcmVzcG9uc2Ugc28gaXQgY2FuIGJlIGRpcmVjdGx5IHNlbmQgYmFja1xuICAgICAgdHJhbnNwb3J0ID0gdHJhbnNwb3J0IHx8IHRoaXMuZ2V0VHJhbnNwb3J0KCkgfHwgc2VsZi5nZXRUcmFuc3BvcnQoKTtcblxuICAgICAgaWYodHJhbnNwb3J0KVxuICAgICAgICByZXR1cm4gdHJhbnNwb3J0LnNlbmQobWVzc2FnZSk7XG5cbiAgICAgIHJldHVybiBtZXNzYWdlO1xuICAgIH1cbiAgfTtcbiAgaW5oZXJpdHMoUnBjUmVxdWVzdCwgUnBjTm90aWZpY2F0aW9uKTtcblxuXG4gIGZ1bmN0aW9uIGNhbmNlbChtZXNzYWdlKVxuICB7XG4gICAgdmFyIGtleSA9IG1lc3NhZ2UyS2V5W21lc3NhZ2VdO1xuICAgIGlmKCFrZXkpIHJldHVybjtcblxuICAgIGRlbGV0ZSBtZXNzYWdlMktleVttZXNzYWdlXTtcblxuICAgIHZhciByZXF1ZXN0ID0gcmVxdWVzdHMucG9wKGtleS5pZCwga2V5LmRlc3QpO1xuICAgIGlmKCFyZXF1ZXN0KSByZXR1cm47XG5cbiAgICBjbGVhclRpbWVvdXQocmVxdWVzdC50aW1lb3V0KTtcblxuICAgIC8vIFN0YXJ0IGR1cGxpY2F0ZWQgcmVzcG9uc2VzIHRpbWVvdXRcbiAgICBzdG9yZVByb2Nlc3NlZFJlc3BvbnNlKGtleS5pZCwga2V5LmRlc3QpO1xuICB9O1xuXG4gIC8qKlxuICAgKiBBbGxvdyB0byBjYW5jZWwgYSByZXF1ZXN0IGFuZCBkb24ndCB3YWl0IGZvciBhIHJlc3BvbnNlXG4gICAqXG4gICAqIElmIGBtZXNzYWdlYCBpcyBub3QgZ2l2ZW4sIGNhbmNlbCBhbGwgdGhlIHJlcXVlc3RcbiAgICovXG4gIHRoaXMuY2FuY2VsID0gZnVuY3Rpb24obWVzc2FnZSlcbiAge1xuICAgIGlmKG1lc3NhZ2UpIHJldHVybiBjYW5jZWwobWVzc2FnZSk7XG5cbiAgICBmb3IodmFyIG1lc3NhZ2UgaW4gbWVzc2FnZTJLZXkpXG4gICAgICBjYW5jZWwobWVzc2FnZSk7XG4gIH07XG5cblxuICB0aGlzLmNsb3NlID0gZnVuY3Rpb24oKVxuICB7XG4gICAgLy8gUHJldmVudCB0byByZWNlaXZlIG5ldyBtZXNzYWdlc1xuICAgIHZhciB0cmFuc3BvcnQgPSB0aGlzLmdldFRyYW5zcG9ydCgpO1xuICAgIGlmKHRyYW5zcG9ydCAmJiB0cmFuc3BvcnQuY2xvc2UpXG4gICAgICAgdHJhbnNwb3J0LmNsb3NlKCk7XG5cbiAgICAvLyBSZXF1ZXN0ICYgcHJvY2Vzc2VkIHJlc3BvbnNlc1xuICAgIHRoaXMuY2FuY2VsKCk7XG5cbiAgICBwcm9jZXNzZWRSZXNwb25zZXMuZm9yRWFjaChjbGVhclRpbWVvdXQpO1xuXG4gICAgLy8gUmVzcG9uc2VzXG4gICAgcmVzcG9uc2VzLmZvckVhY2goZnVuY3Rpb24ocmVzcG9uc2UpXG4gICAge1xuICAgICAgY2xlYXJUaW1lb3V0KHJlc3BvbnNlLnRpbWVvdXQpO1xuICAgIH0pO1xuICB9O1xuXG5cbiAgLyoqXG4gICAqIEdlbmVyYXRlcyBhbmQgZW5jb2RlIGEgSnNvblJQQyAyLjAgbWVzc2FnZVxuICAgKlxuICAgKiBAcGFyYW0ge1N0cmluZ30gbWV0aG9kIC1tZXRob2Qgb2YgdGhlIG5vdGlmaWNhdGlvblxuICAgKiBAcGFyYW0gcGFyYW1zIC0gcGFyYW1ldGVycyBvZiB0aGUgbm90aWZpY2F0aW9uXG4gICAqIEBwYXJhbSBbZGVzdF0gLSBkZXN0aW5hdGlvbiBvZiB0aGUgbm90aWZpY2F0aW9uXG4gICAqIEBwYXJhbSB7b2JqZWN0fSBbdHJhbnNwb3J0XSAtIHRyYW5zcG9ydCB3aGVyZSB0byBzZW5kIHRoZSBtZXNzYWdlXG4gICAqIEBwYXJhbSBbY2FsbGJhY2tdIC0gZnVuY3Rpb24gY2FsbGVkIHdoZW4gYSByZXNwb25zZSB0byB0aGlzIHJlcXVlc3QgaXNcbiAgICogICByZWNlaXZlZC4gSWYgbm90IGRlZmluZWQsIGEgbm90aWZpY2F0aW9uIHdpbGwgYmUgc2VuZCBpbnN0ZWFkXG4gICAqXG4gICAqIEByZXR1cm5zIHtzdHJpbmd9IEEgcmF3IEpzb25SUEMgMi4wIHJlcXVlc3Qgb3Igbm90aWZpY2F0aW9uIHN0cmluZ1xuICAgKi9cbiAgdGhpcy5lbmNvZGUgPSBmdW5jdGlvbihtZXRob2QsIHBhcmFtcywgZGVzdCwgdHJhbnNwb3J0LCBjYWxsYmFjaylcbiAge1xuICAgIC8vIEZpeCBvcHRpb25hbCBwYXJhbWV0ZXJzXG4gICAgaWYocGFyYW1zIGluc3RhbmNlb2YgRnVuY3Rpb24pXG4gICAge1xuICAgICAgaWYoZGVzdCAhPSB1bmRlZmluZWQpXG4gICAgICAgIHRocm93IG5ldyBTeW50YXhFcnJvcihcIlRoZXJlIGNhbid0IGJlIHBhcmFtZXRlcnMgYWZ0ZXIgY2FsbGJhY2tcIik7XG5cbiAgICAgIGNhbGxiYWNrICA9IHBhcmFtcztcbiAgICAgIHRyYW5zcG9ydCA9IHVuZGVmaW5lZDtcbiAgICAgIGRlc3QgICAgICA9IHVuZGVmaW5lZDtcbiAgICAgIHBhcmFtcyAgICA9IHVuZGVmaW5lZDtcbiAgICB9XG5cbiAgICBlbHNlIGlmKGRlc3QgaW5zdGFuY2VvZiBGdW5jdGlvbilcbiAgICB7XG4gICAgICBpZih0cmFuc3BvcnQgIT0gdW5kZWZpbmVkKVxuICAgICAgICB0aHJvdyBuZXcgU3ludGF4RXJyb3IoXCJUaGVyZSBjYW4ndCBiZSBwYXJhbWV0ZXJzIGFmdGVyIGNhbGxiYWNrXCIpO1xuXG4gICAgICBjYWxsYmFjayAgPSBkZXN0O1xuICAgICAgdHJhbnNwb3J0ID0gdW5kZWZpbmVkO1xuICAgICAgZGVzdCAgICAgID0gdW5kZWZpbmVkO1xuICAgIH1cblxuICAgIGVsc2UgaWYodHJhbnNwb3J0IGluc3RhbmNlb2YgRnVuY3Rpb24pXG4gICAge1xuICAgICAgaWYoY2FsbGJhY2sgIT0gdW5kZWZpbmVkKVxuICAgICAgICB0aHJvdyBuZXcgU3ludGF4RXJyb3IoXCJUaGVyZSBjYW4ndCBiZSBwYXJhbWV0ZXJzIGFmdGVyIGNhbGxiYWNrXCIpO1xuXG4gICAgICBjYWxsYmFjayAgPSB0cmFuc3BvcnQ7XG4gICAgICB0cmFuc3BvcnQgPSB1bmRlZmluZWQ7XG4gICAgfTtcblxuICAgIGlmKHNlbGYucGVlcklEICE9IHVuZGVmaW5lZClcbiAgICB7XG4gICAgICBwYXJhbXMgPSBwYXJhbXMgfHwge307XG5cbiAgICAgIHBhcmFtcy5mcm9tID0gc2VsZi5wZWVySUQ7XG4gICAgfTtcblxuICAgIGlmKGRlc3QgIT0gdW5kZWZpbmVkKVxuICAgIHtcbiAgICAgIHBhcmFtcyA9IHBhcmFtcyB8fCB7fTtcblxuICAgICAgcGFyYW1zLmRlc3QgPSBkZXN0O1xuICAgIH07XG5cbiAgICAvLyBFbmNvZGUgbWVzc2FnZVxuICAgIHZhciBtZXNzYWdlID1cbiAgICB7XG4gICAgICBtZXRob2Q6IG1ldGhvZCxcbiAgICAgIHBhcmFtczogcGFyYW1zXG4gICAgfTtcblxuICAgIGlmKGNhbGxiYWNrKVxuICAgIHtcbiAgICAgIHZhciBpZCA9IHJlcXVlc3RJRCsrO1xuICAgICAgdmFyIHJldHJpZWQgPSAwO1xuXG4gICAgICBtZXNzYWdlID0gcGFja2VyLnBhY2sobWVzc2FnZSwgaWQpO1xuXG4gICAgICBmdW5jdGlvbiBkaXNwYXRjaENhbGxiYWNrKGVycm9yLCByZXN1bHQpXG4gICAgICB7XG4gICAgICAgIHNlbGYuY2FuY2VsKG1lc3NhZ2UpO1xuXG4gICAgICAgIGNhbGxiYWNrKGVycm9yLCByZXN1bHQpO1xuICAgICAgfTtcblxuICAgICAgdmFyIHJlcXVlc3QgPVxuICAgICAge1xuICAgICAgICBtZXNzYWdlOiAgICAgICAgIG1lc3NhZ2UsXG4gICAgICAgIGNhbGxiYWNrOiAgICAgICAgZGlzcGF0Y2hDYWxsYmFjayxcbiAgICAgICAgcmVzcG9uc2VNZXRob2RzOiByZXNwb25zZU1ldGhvZHNbbWV0aG9kXSB8fCB7fVxuICAgICAgfTtcblxuICAgICAgdmFyIGVuY29kZV90cmFuc3BvcnQgPSB1bmlmeVRyYW5zcG9ydCh0cmFuc3BvcnQpO1xuXG4gICAgICBmdW5jdGlvbiBzZW5kUmVxdWVzdCh0cmFuc3BvcnQpXG4gICAgICB7XG4gICAgICAgIHZhciBydCA9IChtZXRob2QgPT09ICdwaW5nJyA/IHBpbmdfcmVxdWVzdF90aW1lb3V0IDogcmVxdWVzdF90aW1lb3V0KTtcbiAgICAgICAgcmVxdWVzdC50aW1lb3V0ID0gc2V0VGltZW91dCh0aW1lb3V0LCBydCpNYXRoLnBvdygyLCByZXRyaWVkKyspKTtcbiAgICAgICAgbWVzc2FnZTJLZXlbbWVzc2FnZV0gPSB7aWQ6IGlkLCBkZXN0OiBkZXN0fTtcbiAgICAgICAgcmVxdWVzdHMuc2V0KHJlcXVlc3QsIGlkLCBkZXN0KTtcblxuICAgICAgICB0cmFuc3BvcnQgPSB0cmFuc3BvcnQgfHwgZW5jb2RlX3RyYW5zcG9ydCB8fCBzZWxmLmdldFRyYW5zcG9ydCgpO1xuICAgICAgICBpZih0cmFuc3BvcnQpXG4gICAgICAgICAgcmV0dXJuIHRyYW5zcG9ydC5zZW5kKG1lc3NhZ2UpO1xuXG4gICAgICAgIHJldHVybiBtZXNzYWdlO1xuICAgICAgfTtcblxuICAgICAgZnVuY3Rpb24gcmV0cnkodHJhbnNwb3J0KVxuICAgICAge1xuICAgICAgICB0cmFuc3BvcnQgPSB1bmlmeVRyYW5zcG9ydCh0cmFuc3BvcnQpO1xuXG4gICAgICAgIGNvbnNvbGUud2FybihyZXRyaWVkKycgcmV0cnkgZm9yIHJlcXVlc3QgbWVzc2FnZTonLG1lc3NhZ2UpO1xuXG4gICAgICAgIHZhciB0aW1lb3V0ID0gcHJvY2Vzc2VkUmVzcG9uc2VzLnBvcChpZCwgZGVzdCk7XG4gICAgICAgIGNsZWFyVGltZW91dCh0aW1lb3V0KTtcblxuICAgICAgICByZXR1cm4gc2VuZFJlcXVlc3QodHJhbnNwb3J0KTtcbiAgICAgIH07XG5cbiAgICAgIGZ1bmN0aW9uIHRpbWVvdXQoKVxuICAgICAge1xuICAgICAgICBpZihyZXRyaWVkIDwgbWF4X3JldHJpZXMpXG4gICAgICAgICAgcmV0dXJuIHJldHJ5KHRyYW5zcG9ydCk7XG5cbiAgICAgICAgdmFyIGVycm9yID0gbmV3IEVycm9yKCdSZXF1ZXN0IGhhcyB0aW1lZCBvdXQnKTtcbiAgICAgICAgICAgIGVycm9yLnJlcXVlc3QgPSBtZXNzYWdlO1xuXG4gICAgICAgIGVycm9yLnJldHJ5ID0gcmV0cnk7XG5cbiAgICAgICAgZGlzcGF0Y2hDYWxsYmFjayhlcnJvcilcbiAgICAgIH07XG5cbiAgICAgIHJldHVybiBzZW5kUmVxdWVzdCh0cmFuc3BvcnQpO1xuICAgIH07XG5cbiAgICAvLyBSZXR1cm4gdGhlIHBhY2tlZCBtZXNzYWdlXG4gICAgbWVzc2FnZSA9IHBhY2tlci5wYWNrKG1lc3NhZ2UpO1xuXG4gICAgdHJhbnNwb3J0ID0gdHJhbnNwb3J0IHx8IHRoaXMuZ2V0VHJhbnNwb3J0KCk7XG4gICAgaWYodHJhbnNwb3J0KVxuICAgICAgcmV0dXJuIHRyYW5zcG9ydC5zZW5kKG1lc3NhZ2UpO1xuXG4gICAgcmV0dXJuIG1lc3NhZ2U7XG4gIH07XG5cbiAgLyoqXG4gICAqIERlY29kZSBhbmQgcHJvY2VzcyBhIEpzb25SUEMgMi4wIG1lc3NhZ2VcbiAgICpcbiAgICogQHBhcmFtIHtzdHJpbmd9IG1lc3NhZ2UgLSBzdHJpbmcgd2l0aCB0aGUgY29udGVudCBvZiB0aGUgbWVzc2FnZVxuICAgKlxuICAgKiBAcmV0dXJucyB7UnBjTm90aWZpY2F0aW9ufFJwY1JlcXVlc3R8dW5kZWZpbmVkfSAtIHRoZSByZXByZXNlbnRhdGlvbiBvZiB0aGVcbiAgICogICBub3RpZmljYXRpb24gb3IgdGhlIHJlcXVlc3QuIElmIGEgcmVzcG9uc2Ugd2FzIHByb2Nlc3NlZCwgaXQgd2lsbCByZXR1cm5cbiAgICogICBgdW5kZWZpbmVkYCB0byBub3RpZnkgdGhhdCBpdCB3YXMgcHJvY2Vzc2VkXG4gICAqXG4gICAqIEB0aHJvd3Mge1R5cGVFcnJvcn0gLSBNZXNzYWdlIGlzIG5vdCBkZWZpbmVkXG4gICAqL1xuICB0aGlzLmRlY29kZSA9IGZ1bmN0aW9uKG1lc3NhZ2UsIHRyYW5zcG9ydClcbiAge1xuICAgIGlmKCFtZXNzYWdlKVxuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIk1lc3NhZ2UgaXMgbm90IGRlZmluZWRcIik7XG5cbiAgICB0cnlcbiAgICB7XG4gICAgICBtZXNzYWdlID0gcGFja2VyLnVucGFjayhtZXNzYWdlKTtcbiAgICB9XG4gICAgY2F0Y2goZSlcbiAgICB7XG4gICAgICAvLyBJZ25vcmUgaW52YWxpZCBtZXNzYWdlc1xuICAgICAgcmV0dXJuIGNvbnNvbGUuZGVidWcoZSwgbWVzc2FnZSk7XG4gICAgfTtcblxuICAgIHZhciBpZCAgICAgPSBtZXNzYWdlLmlkO1xuICAgIHZhciBhY2sgICAgPSBtZXNzYWdlLmFjaztcbiAgICB2YXIgbWV0aG9kID0gbWVzc2FnZS5tZXRob2Q7XG4gICAgdmFyIHBhcmFtcyA9IG1lc3NhZ2UucGFyYW1zIHx8IHt9O1xuXG4gICAgdmFyIGZyb20gPSBwYXJhbXMuZnJvbTtcbiAgICB2YXIgZGVzdCA9IHBhcmFtcy5kZXN0O1xuXG4gICAgLy8gSWdub3JlIG1lc3NhZ2VzIHNlbmQgYnkgdXNcbiAgICBpZihzZWxmLnBlZXJJRCAhPSB1bmRlZmluZWQgJiYgZnJvbSA9PSBzZWxmLnBlZXJJRCkgcmV0dXJuO1xuXG4gICAgLy8gTm90aWZpY2F0aW9uXG4gICAgaWYoaWQgPT0gdW5kZWZpbmVkICYmIGFjayA9PSB1bmRlZmluZWQpXG4gICAge1xuICAgICAgdmFyIG5vdGlmaWNhdGlvbiA9IG5ldyBScGNOb3RpZmljYXRpb24obWV0aG9kLCBwYXJhbXMpO1xuXG4gICAgICBpZihzZWxmLmVtaXQoJ3JlcXVlc3QnLCBub3RpZmljYXRpb24pKSByZXR1cm47XG4gICAgICByZXR1cm4gbm90aWZpY2F0aW9uO1xuICAgIH07XG5cblxuICAgIGZ1bmN0aW9uIHByb2Nlc3NSZXF1ZXN0KClcbiAgICB7XG4gICAgICAvLyBJZiB3ZSBoYXZlIGEgdHJhbnNwb3J0IGFuZCBpdCdzIGEgZHVwbGljYXRlZCByZXF1ZXN0LCByZXBseSBpbm1lZGlhdGx5XG4gICAgICB0cmFuc3BvcnQgPSB1bmlmeVRyYW5zcG9ydCh0cmFuc3BvcnQpIHx8IHNlbGYuZ2V0VHJhbnNwb3J0KCk7XG4gICAgICBpZih0cmFuc3BvcnQpXG4gICAgICB7XG4gICAgICAgIHZhciByZXNwb25zZSA9IHJlc3BvbnNlcy5nZXQoaWQsIGZyb20pO1xuICAgICAgICBpZihyZXNwb25zZSlcbiAgICAgICAgICByZXR1cm4gdHJhbnNwb3J0LnNlbmQocmVzcG9uc2UubWVzc2FnZSk7XG4gICAgICB9O1xuXG4gICAgICB2YXIgaWRBY2sgPSAoaWQgIT0gdW5kZWZpbmVkKSA/IGlkIDogYWNrO1xuICAgICAgdmFyIHJlcXVlc3QgPSBuZXcgUnBjUmVxdWVzdChtZXRob2QsIHBhcmFtcywgaWRBY2ssIGZyb20sIHRyYW5zcG9ydCk7XG5cbiAgICAgIGlmKHNlbGYuZW1pdCgncmVxdWVzdCcsIHJlcXVlc3QpKSByZXR1cm47XG4gICAgICByZXR1cm4gcmVxdWVzdDtcbiAgICB9O1xuXG4gICAgZnVuY3Rpb24gcHJvY2Vzc1Jlc3BvbnNlKHJlcXVlc3QsIGVycm9yLCByZXN1bHQpXG4gICAge1xuICAgICAgcmVxdWVzdC5jYWxsYmFjayhlcnJvciwgcmVzdWx0KTtcbiAgICB9O1xuXG4gICAgZnVuY3Rpb24gZHVwbGljYXRlZFJlc3BvbnNlKHRpbWVvdXQpXG4gICAge1xuICAgICAgY29uc29sZS53YXJuKFwiUmVzcG9uc2UgYWxyZWFkeSBwcm9jZXNzZWRcIiwgbWVzc2FnZSk7XG5cbiAgICAgIC8vIFVwZGF0ZSBkdXBsaWNhdGVkIHJlc3BvbnNlcyB0aW1lb3V0XG4gICAgICBjbGVhclRpbWVvdXQodGltZW91dCk7XG4gICAgICBzdG9yZVByb2Nlc3NlZFJlc3BvbnNlKGFjaywgZnJvbSk7XG4gICAgfTtcblxuXG4gICAgLy8gUmVxdWVzdCwgb3IgcmVzcG9uc2Ugd2l0aCBvd24gbWV0aG9kXG4gICAgaWYobWV0aG9kKVxuICAgIHtcbiAgICAgIC8vIENoZWNrIGlmIGl0J3MgYSByZXNwb25zZSB3aXRoIG93biBtZXRob2RcbiAgICAgIGlmKGRlc3QgPT0gdW5kZWZpbmVkIHx8IGRlc3QgPT0gc2VsZi5wZWVySUQpXG4gICAgICB7XG4gICAgICAgIHZhciByZXF1ZXN0ID0gcmVxdWVzdHMuZ2V0KGFjaywgZnJvbSk7XG4gICAgICAgIGlmKHJlcXVlc3QpXG4gICAgICAgIHtcbiAgICAgICAgICB2YXIgcmVzcG9uc2VNZXRob2RzID0gcmVxdWVzdC5yZXNwb25zZU1ldGhvZHM7XG5cbiAgICAgICAgICBpZihtZXRob2QgPT0gcmVzcG9uc2VNZXRob2RzLmVycm9yKVxuICAgICAgICAgICAgcmV0dXJuIHByb2Nlc3NSZXNwb25zZShyZXF1ZXN0LCBwYXJhbXMpO1xuXG4gICAgICAgICAgaWYobWV0aG9kID09IHJlc3BvbnNlTWV0aG9kcy5yZXNwb25zZSlcbiAgICAgICAgICAgIHJldHVybiBwcm9jZXNzUmVzcG9uc2UocmVxdWVzdCwgbnVsbCwgcGFyYW1zKTtcblxuICAgICAgICAgIHJldHVybiBwcm9jZXNzUmVxdWVzdCgpO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIHByb2Nlc3NlZCA9IHByb2Nlc3NlZFJlc3BvbnNlcy5nZXQoYWNrLCBmcm9tKTtcbiAgICAgICAgaWYocHJvY2Vzc2VkKVxuICAgICAgICAgIHJldHVybiBkdXBsaWNhdGVkUmVzcG9uc2UocHJvY2Vzc2VkKTtcbiAgICAgIH1cblxuICAgICAgLy8gUmVxdWVzdFxuICAgICAgcmV0dXJuIHByb2Nlc3NSZXF1ZXN0KCk7XG4gICAgfTtcblxuICAgIHZhciBlcnJvciAgPSBtZXNzYWdlLmVycm9yO1xuICAgIHZhciByZXN1bHQgPSBtZXNzYWdlLnJlc3VsdDtcblxuICAgIC8vIElnbm9yZSByZXNwb25zZXMgbm90IHNlbmQgdG8gdXNcbiAgICBpZihlcnJvciAgJiYgZXJyb3IuZGVzdCAgJiYgZXJyb3IuZGVzdCAgIT0gc2VsZi5wZWVySUQpIHJldHVybjtcbiAgICBpZihyZXN1bHQgJiYgcmVzdWx0LmRlc3QgJiYgcmVzdWx0LmRlc3QgIT0gc2VsZi5wZWVySUQpIHJldHVybjtcblxuICAgIC8vIFJlc3BvbnNlXG4gICAgdmFyIHJlcXVlc3QgPSByZXF1ZXN0cy5nZXQoYWNrLCBmcm9tKTtcbiAgICBpZighcmVxdWVzdClcbiAgICB7XG4gICAgICB2YXIgcHJvY2Vzc2VkID0gcHJvY2Vzc2VkUmVzcG9uc2VzLmdldChhY2ssIGZyb20pO1xuICAgICAgaWYocHJvY2Vzc2VkKVxuICAgICAgICByZXR1cm4gZHVwbGljYXRlZFJlc3BvbnNlKHByb2Nlc3NlZCk7XG5cbiAgICAgIHJldHVybiBjb25zb2xlLndhcm4oXCJObyBjYWxsYmFjayB3YXMgZGVmaW5lZCBmb3IgdGhpcyBtZXNzYWdlXCIsIG1lc3NhZ2UpO1xuICAgIH07XG5cbiAgICAvLyBQcm9jZXNzIHJlc3BvbnNlXG4gICAgcHJvY2Vzc1Jlc3BvbnNlKHJlcXVlc3QsIGVycm9yLCByZXN1bHQpO1xuICB9O1xufTtcbmluaGVyaXRzKFJwY0J1aWxkZXIsIEV2ZW50RW1pdHRlcik7XG5cblxuUnBjQnVpbGRlci5ScGNOb3RpZmljYXRpb24gPSBScGNOb3RpZmljYXRpb247XG5cblxubW9kdWxlLmV4cG9ydHMgPSBScGNCdWlsZGVyO1xuXG52YXIgY2xpZW50cyA9IHJlcXVpcmUoJy4vY2xpZW50cycpO1xudmFyIHRyYW5zcG9ydHMgPSByZXF1aXJlKCcuL2NsaWVudHMvdHJhbnNwb3J0cycpO1xuXG5ScGNCdWlsZGVyLmNsaWVudHMgPSBjbGllbnRzO1xuUnBjQnVpbGRlci5jbGllbnRzLnRyYW5zcG9ydHMgPSB0cmFuc3BvcnRzO1xuUnBjQnVpbGRlci5wYWNrZXJzID0gcGFja2VycztcbiIsIi8qKlxuICogSnNvblJQQyAyLjAgcGFja2VyXG4gKi9cblxuLyoqXG4gKiBQYWNrIGEgSnNvblJQQyAyLjAgbWVzc2FnZVxuICpcbiAqIEBwYXJhbSB7T2JqZWN0fSBtZXNzYWdlIC0gb2JqZWN0IHRvIGJlIHBhY2thZ2VkLiBJdCByZXF1aXJlcyB0byBoYXZlIGFsbCB0aGVcbiAqICAgZmllbGRzIG5lZWRlZCBieSB0aGUgSnNvblJQQyAyLjAgbWVzc2FnZSB0aGF0IGl0J3MgZ29pbmcgdG8gYmUgZ2VuZXJhdGVkXG4gKlxuICogQHJldHVybiB7U3RyaW5nfSAtIHRoZSBzdHJpbmdpZmllZCBKc29uUlBDIDIuMCBtZXNzYWdlXG4gKi9cbmZ1bmN0aW9uIHBhY2sobWVzc2FnZSwgaWQpXG57XG4gIHZhciByZXN1bHQgPVxuICB7XG4gICAganNvbnJwYzogXCIyLjBcIlxuICB9O1xuXG4gIC8vIFJlcXVlc3RcbiAgaWYobWVzc2FnZS5tZXRob2QpXG4gIHtcbiAgICByZXN1bHQubWV0aG9kID0gbWVzc2FnZS5tZXRob2Q7XG5cbiAgICBpZihtZXNzYWdlLnBhcmFtcylcbiAgICAgIHJlc3VsdC5wYXJhbXMgPSBtZXNzYWdlLnBhcmFtcztcblxuICAgIC8vIFJlcXVlc3QgaXMgYSBub3RpZmljYXRpb25cbiAgICBpZihpZCAhPSB1bmRlZmluZWQpXG4gICAgICByZXN1bHQuaWQgPSBpZDtcbiAgfVxuXG4gIC8vIFJlc3BvbnNlXG4gIGVsc2UgaWYoaWQgIT0gdW5kZWZpbmVkKVxuICB7XG4gICAgaWYobWVzc2FnZS5lcnJvcilcbiAgICB7XG4gICAgICBpZihtZXNzYWdlLnJlc3VsdCAhPT0gdW5kZWZpbmVkKVxuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQm90aCByZXN1bHQgYW5kIGVycm9yIGFyZSBkZWZpbmVkXCIpO1xuXG4gICAgICByZXN1bHQuZXJyb3IgPSBtZXNzYWdlLmVycm9yO1xuICAgIH1cbiAgICBlbHNlIGlmKG1lc3NhZ2UucmVzdWx0ICE9PSB1bmRlZmluZWQpXG4gICAgICByZXN1bHQucmVzdWx0ID0gbWVzc2FnZS5yZXN1bHQ7XG4gICAgZWxzZVxuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIk5vIHJlc3VsdCBvciBlcnJvciBpcyBkZWZpbmVkXCIpO1xuXG4gICAgcmVzdWx0LmlkID0gaWQ7XG4gIH07XG5cbiAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KHJlc3VsdCk7XG59O1xuXG4vKipcbiAqIFVucGFjayBhIEpzb25SUEMgMi4wIG1lc3NhZ2VcbiAqXG4gKiBAcGFyYW0ge1N0cmluZ30gbWVzc2FnZSAtIHN0cmluZyB3aXRoIHRoZSBjb250ZW50IG9mIHRoZSBKc29uUlBDIDIuMCBtZXNzYWdlXG4gKlxuICogQHRocm93cyB7VHlwZUVycm9yfSAtIEludmFsaWQgSnNvblJQQyB2ZXJzaW9uXG4gKlxuICogQHJldHVybiB7T2JqZWN0fSAtIG9iamVjdCBmaWxsZWQgd2l0aCB0aGUgSnNvblJQQyAyLjAgbWVzc2FnZSBjb250ZW50XG4gKi9cbmZ1bmN0aW9uIHVucGFjayhtZXNzYWdlKVxue1xuICB2YXIgcmVzdWx0ID0gbWVzc2FnZTtcblxuICBpZih0eXBlb2YgbWVzc2FnZSA9PT0gJ3N0cmluZycgfHwgbWVzc2FnZSBpbnN0YW5jZW9mIFN0cmluZykge1xuICAgIHJlc3VsdCA9IEpTT04ucGFyc2UobWVzc2FnZSk7XG4gIH1cblxuICAvLyBDaGVjayBpZiBpdCdzIGEgdmFsaWQgbWVzc2FnZVxuXG4gIHZhciB2ZXJzaW9uID0gcmVzdWx0Lmpzb25ycGM7XG4gIGlmKHZlcnNpb24gIT09ICcyLjAnKVxuICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJJbnZhbGlkIEpzb25SUEMgdmVyc2lvbiAnXCIgKyB2ZXJzaW9uICsgXCInOiBcIiArIG1lc3NhZ2UpO1xuXG4gIC8vIFJlc3BvbnNlXG4gIGlmKHJlc3VsdC5tZXRob2QgPT0gdW5kZWZpbmVkKVxuICB7XG4gICAgaWYocmVzdWx0LmlkID09IHVuZGVmaW5lZClcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJJbnZhbGlkIG1lc3NhZ2U6IFwiK21lc3NhZ2UpO1xuXG4gICAgdmFyIHJlc3VsdF9kZWZpbmVkID0gcmVzdWx0LnJlc3VsdCAhPT0gdW5kZWZpbmVkO1xuICAgIHZhciBlcnJvcl9kZWZpbmVkICA9IHJlc3VsdC5lcnJvciAgIT09IHVuZGVmaW5lZDtcblxuICAgIC8vIENoZWNrIG9ubHkgcmVzdWx0IG9yIGVycm9yIGlzIGRlZmluZWQsIG5vdCBib3RoIG9yIG5vbmVcbiAgICBpZihyZXN1bHRfZGVmaW5lZCAmJiBlcnJvcl9kZWZpbmVkKVxuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkJvdGggcmVzdWx0IGFuZCBlcnJvciBhcmUgZGVmaW5lZDogXCIrbWVzc2FnZSk7XG5cbiAgICBpZighcmVzdWx0X2RlZmluZWQgJiYgIWVycm9yX2RlZmluZWQpXG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiTm8gcmVzdWx0IG9yIGVycm9yIGlzIGRlZmluZWQ6IFwiK21lc3NhZ2UpO1xuXG4gICAgcmVzdWx0LmFjayA9IHJlc3VsdC5pZDtcbiAgICBkZWxldGUgcmVzdWx0LmlkO1xuICB9XG5cbiAgLy8gUmV0dXJuIHVucGFja2VkIG1lc3NhZ2VcbiAgcmV0dXJuIHJlc3VsdDtcbn07XG5cblxuZXhwb3J0cy5wYWNrICAgPSBwYWNrO1xuZXhwb3J0cy51bnBhY2sgPSB1bnBhY2s7XG4iLCJmdW5jdGlvbiBwYWNrKG1lc3NhZ2UpXG57XG4gIHRocm93IG5ldyBUeXBlRXJyb3IoXCJOb3QgeWV0IGltcGxlbWVudGVkXCIpO1xufTtcblxuZnVuY3Rpb24gdW5wYWNrKG1lc3NhZ2UpXG57XG4gIHRocm93IG5ldyBUeXBlRXJyb3IoXCJOb3QgeWV0IGltcGxlbWVudGVkXCIpO1xufTtcblxuXG5leHBvcnRzLnBhY2sgICA9IHBhY2s7XG5leHBvcnRzLnVucGFjayA9IHVucGFjaztcbiIsInZhciBKc29uUlBDID0gcmVxdWlyZSgnLi9Kc29uUlBDJyk7XG52YXIgWG1sUlBDICA9IHJlcXVpcmUoJy4vWG1sUlBDJyk7XG5cblxuZXhwb3J0cy5Kc29uUlBDID0gSnNvblJQQztcbmV4cG9ydHMuWG1sUlBDICA9IFhtbFJQQztcbiIsIi8vIExhc3QgdGltZSB1cGRhdGVkIG9uIEp1bmUgMDgsIDIwMThcblxuLy8gTGF0ZXN0IGZpbGUgY2FuIGJlIGZvdW5kIGhlcmU6IGh0dHBzOi8vY2RuLndlYnJ0Yy1leHBlcmltZW50LmNvbS9nZXRTY3JlZW5JZC5qc1xuXG4vLyBNdWF6IEtoYW4gICAgICAgICAtIHd3dy5NdWF6S2hhbi5jb21cbi8vIE1JVCBMaWNlbnNlICAgICAgIC0gd3d3LldlYlJUQy1FeHBlcmltZW50LmNvbS9saWNlbmNlXG4vLyBEb2N1bWVudGF0aW9uICAgICAtIGh0dHBzOi8vZ2l0aHViLmNvbS9tdWF6LWtoYW4vZ2V0U2NyZWVuSWQuXG5cbi8vIF9fX19fX19fX19fX19fXG4vLyBnZXRTY3JlZW5JZC5qc1xuXG4vKlxuZ2V0U2NyZWVuSWQoZnVuY3Rpb24gKGVycm9yLCBzb3VyY2VJZCwgc2NyZWVuX2NvbnN0cmFpbnRzKSB7XG4gICAgLy8gZXJyb3IgICAgPT0gbnVsbCB8fCAncGVybWlzc2lvbi1kZW5pZWQnIHx8ICdub3QtaW5zdGFsbGVkJyB8fCAnaW5zdGFsbGVkLWRpc2FibGVkJyB8fCAnbm90LWNocm9tZSdcbiAgICAvLyBzb3VyY2VJZCA9PSBudWxsIHx8ICdzdHJpbmcnIHx8ICdmaXJlZm94J1xuICAgIFxuICAgIGlmKG1pY3Jvc29mdEVkZ2UpIHtcbiAgICAgICAgbmF2aWdhdG9yLmdldERpc3BsYXlNZWRpYShzY3JlZW5fY29uc3RyYWludHMpLnRoZW4ob25TdWNjZXNzLCBvbkZhaWx1cmUpO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgbmF2aWdhdG9yLm1lZGlhRGV2aWNlcy5nZXRVc2VyTWVkaWEoc2NyZWVuX2NvbnN0cmFpbnRzKS50aGVuKG9uU3VjY2VzcyljYXRjaChvbkZhaWx1cmUpO1xuICAgIH1cbn0sICdwYXNzIHNlY29uZCBwYXJhbWV0ZXIgb25seSBpZiB5b3Ugd2FudCBzeXN0ZW0gYXVkaW8nKTtcbiovXG5cbndpbmRvdy5nZXRTY3JlZW5JZCA9IGZ1bmN0aW9uIChjYWxsYmFjaywgY3VzdG9tX3BhcmFtZXRlcikge1xuICAgIGlmIChuYXZpZ2F0b3IudXNlckFnZW50LmluZGV4T2YoJ0VkZ2UnKSAhPT0gLTEgJiYgKCEhbmF2aWdhdG9yLm1zU2F2ZU9yT3BlbkJsb2IgfHwgISFuYXZpZ2F0b3IubXNTYXZlQmxvYikpIHtcbiAgICAgICAgLy8gbWljcm9zb2Z0IGVkZ2UgPT4gbmF2aWdhdG9yLmdldERpc3BsYXlNZWRpYShzY3JlZW5fY29uc3RyYWludHMpLnRoZW4ob25TdWNjZXNzLCBvbkZhaWx1cmUpO1xuICAgICAgICBjYWxsYmFjayh7XG4gICAgICAgICAgICB2aWRlbzogdHJ1ZVxuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8vIGZvciBGaXJlZm94OlxuICAgIC8vIHNvdXJjZUlkID09ICdmaXJlZm94J1xuICAgIC8vIHNjcmVlbl9jb25zdHJhaW50cyA9IHsuLi59XG4gICAgaWYgKCEhbmF2aWdhdG9yLm1vekdldFVzZXJNZWRpYSkge1xuICAgICAgICBjYWxsYmFjayhudWxsLCAnZmlyZWZveCcsIHtcbiAgICAgICAgICAgIHZpZGVvOiB7XG4gICAgICAgICAgICAgICAgbW96TWVkaWFTb3VyY2U6ICd3aW5kb3cnLFxuICAgICAgICAgICAgICAgIG1lZGlhU291cmNlOiAnd2luZG93J1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdtZXNzYWdlJywgb25JRnJhbWVDYWxsYmFjayk7XG5cbiAgICBmdW5jdGlvbiBvbklGcmFtZUNhbGxiYWNrKGV2ZW50KSB7XG4gICAgICAgIGlmICghZXZlbnQuZGF0YSkgcmV0dXJuO1xuXG4gICAgICAgIGlmIChldmVudC5kYXRhLmNocm9tZU1lZGlhU291cmNlSWQpIHtcbiAgICAgICAgICAgIGlmIChldmVudC5kYXRhLmNocm9tZU1lZGlhU291cmNlSWQgPT09ICdQZXJtaXNzaW9uRGVuaWVkRXJyb3InKSB7XG4gICAgICAgICAgICAgICAgY2FsbGJhY2soJ3Blcm1pc3Npb24tZGVuaWVkJyk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGNhbGxiYWNrKG51bGwsIGV2ZW50LmRhdGEuY2hyb21lTWVkaWFTb3VyY2VJZCwgZ2V0U2NyZWVuQ29uc3RyYWludHMobnVsbCwgZXZlbnQuZGF0YS5jaHJvbWVNZWRpYVNvdXJjZUlkLCBldmVudC5kYXRhLmNhblJlcXVlc3RBdWRpb1RyYWNrKSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIHRoaXMgZXZlbnQgbGlzdGVuZXIgaXMgbm8gbW9yZSBuZWVkZWRcbiAgICAgICAgICAgIHdpbmRvdy5yZW1vdmVFdmVudExpc3RlbmVyKCdtZXNzYWdlJywgb25JRnJhbWVDYWxsYmFjayk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoZXZlbnQuZGF0YS5jaHJvbWVFeHRlbnNpb25TdGF0dXMpIHtcbiAgICAgICAgICAgIGNhbGxiYWNrKGV2ZW50LmRhdGEuY2hyb21lRXh0ZW5zaW9uU3RhdHVzLCBudWxsLCBnZXRTY3JlZW5Db25zdHJhaW50cyhldmVudC5kYXRhLmNocm9tZUV4dGVuc2lvblN0YXR1cykpO1xuXG4gICAgICAgICAgICAvLyB0aGlzIGV2ZW50IGxpc3RlbmVyIGlzIG5vIG1vcmUgbmVlZGVkXG4gICAgICAgICAgICB3aW5kb3cucmVtb3ZlRXZlbnRMaXN0ZW5lcignbWVzc2FnZScsIG9uSUZyYW1lQ2FsbGJhY2spO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgaWYgKCFjdXN0b21fcGFyYW1ldGVyKSB7XG4gICAgICAgIHNldFRpbWVvdXQocG9zdEdldFNvdXJjZUlkTWVzc2FnZSwgMTAwKTtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcG9zdEdldFNvdXJjZUlkTWVzc2FnZShjdXN0b21fcGFyYW1ldGVyKTtcbiAgICAgICAgfSwgMTAwKTtcbiAgICB9XG59O1xuXG5mdW5jdGlvbiBnZXRTY3JlZW5Db25zdHJhaW50cyhlcnJvciwgc291cmNlSWQsIGNhblJlcXVlc3RBdWRpb1RyYWNrKSB7XG4gICAgdmFyIHNjcmVlbl9jb25zdHJhaW50cyA9IHtcbiAgICAgICAgYXVkaW86IGZhbHNlLFxuICAgICAgICB2aWRlbzoge1xuICAgICAgICAgICAgbWFuZGF0b3J5OiB7XG4gICAgICAgICAgICAgICAgY2hyb21lTWVkaWFTb3VyY2U6IGVycm9yID8gJ3NjcmVlbicgOiAnZGVza3RvcCcsXG4gICAgICAgICAgICAgICAgbWF4V2lkdGg6IHdpbmRvdy5zY3JlZW4ud2lkdGggPiAxOTIwID8gd2luZG93LnNjcmVlbi53aWR0aCA6IDE5MjAsXG4gICAgICAgICAgICAgICAgbWF4SGVpZ2h0OiB3aW5kb3cuc2NyZWVuLmhlaWdodCA+IDEwODAgPyB3aW5kb3cuc2NyZWVuLmhlaWdodCA6IDEwODBcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBvcHRpb25hbDogW11cbiAgICAgICAgfVxuICAgIH07XG5cbiAgICBpZiAoISFjYW5SZXF1ZXN0QXVkaW9UcmFjaykge1xuICAgICAgICBzY3JlZW5fY29uc3RyYWludHMuYXVkaW8gPSB7XG4gICAgICAgICAgICBtYW5kYXRvcnk6IHtcbiAgICAgICAgICAgICAgICBjaHJvbWVNZWRpYVNvdXJjZTogZXJyb3IgPyAnc2NyZWVuJyA6ICdkZXNrdG9wJyxcbiAgICAgICAgICAgICAgICAvLyBlY2hvQ2FuY2VsbGF0aW9uOiB0cnVlXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgb3B0aW9uYWw6IFtdXG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgaWYgKHNvdXJjZUlkKSB7XG4gICAgICAgIHNjcmVlbl9jb25zdHJhaW50cy52aWRlby5tYW5kYXRvcnkuY2hyb21lTWVkaWFTb3VyY2VJZCA9IHNvdXJjZUlkO1xuXG4gICAgICAgIGlmIChzY3JlZW5fY29uc3RyYWludHMuYXVkaW8gJiYgc2NyZWVuX2NvbnN0cmFpbnRzLmF1ZGlvLm1hbmRhdG9yeSkge1xuICAgICAgICAgICAgc2NyZWVuX2NvbnN0cmFpbnRzLmF1ZGlvLm1hbmRhdG9yeS5jaHJvbWVNZWRpYVNvdXJjZUlkID0gc291cmNlSWQ7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gc2NyZWVuX2NvbnN0cmFpbnRzO1xufVxuXG5mdW5jdGlvbiBwb3N0R2V0U291cmNlSWRNZXNzYWdlKGN1c3RvbV9wYXJhbWV0ZXIpIHtcbiAgICBpZiAoIWlmcmFtZSkge1xuICAgICAgICBsb2FkSUZyYW1lKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHBvc3RHZXRTb3VyY2VJZE1lc3NhZ2UoY3VzdG9tX3BhcmFtZXRlcik7XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYgKCFpZnJhbWUuaXNMb2FkZWQpIHtcbiAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBwb3N0R2V0U291cmNlSWRNZXNzYWdlKGN1c3RvbV9wYXJhbWV0ZXIpO1xuICAgICAgICB9LCAxMDApO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYgKCFjdXN0b21fcGFyYW1ldGVyKSB7XG4gICAgICAgIGlmcmFtZS5jb250ZW50V2luZG93LnBvc3RNZXNzYWdlKHtcbiAgICAgICAgICAgIGNhcHR1cmVTb3VyY2VJZDogdHJ1ZVxuICAgICAgICB9LCAnKicpO1xuICAgIH1cbiAgICBlbHNlIGlmICghIWN1c3RvbV9wYXJhbWV0ZXIuZm9yRWFjaCkge1xuICAgICAgICBpZnJhbWUuY29udGVudFdpbmRvdy5wb3N0TWVzc2FnZSh7XG4gICAgICAgICAgICBjYXB0dXJlQ3VzdG9tU291cmNlSWQ6IGN1c3RvbV9wYXJhbWV0ZXJcbiAgICAgICAgfSwgJyonKTtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIGlmcmFtZS5jb250ZW50V2luZG93LnBvc3RNZXNzYWdlKHtcbiAgICAgICAgICAgIGNhcHR1cmVTb3VyY2VJZFdpdGhBdWRpbzogdHJ1ZVxuICAgICAgICB9LCAnKicpO1xuICAgIH1cbn1cblxudmFyIGlmcmFtZTtcblxuLy8gdGhpcyBmdW5jdGlvbiBpcyB1c2VkIGluIFJUQ011bHRpQ29ubmVjdGlvbiB2M1xud2luZG93LmdldFNjcmVlbkNvbnN0cmFpbnRzID0gZnVuY3Rpb24gKGNhbGxiYWNrKSB7XG4gICAgbG9hZElGcmFtZShmdW5jdGlvbiAoKSB7XG4gICAgICAgIGdldFNjcmVlbklkKGZ1bmN0aW9uIChlcnJvciwgc291cmNlSWQsIHNjcmVlbl9jb25zdHJhaW50cykge1xuICAgICAgICAgICAgaWYgKCFzY3JlZW5fY29uc3RyYWludHMpIHtcbiAgICAgICAgICAgICAgICBzY3JlZW5fY29uc3RyYWludHMgPSB7XG4gICAgICAgICAgICAgICAgICAgIHZpZGVvOiB0cnVlXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgY2FsbGJhY2soZXJyb3IsIHNjcmVlbl9jb25zdHJhaW50cy52aWRlbyk7XG4gICAgICAgIH0pO1xuICAgIH0pO1xufTtcblxuZnVuY3Rpb24gbG9hZElGcmFtZShsb2FkQ2FsbGJhY2spIHtcbiAgICBpZiAoaWZyYW1lKSB7XG4gICAgICAgIGxvYWRDYWxsYmFjaygpO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWZyYW1lID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnaWZyYW1lJyk7XG4gICAgaWZyYW1lLm9ubG9hZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWZyYW1lLmlzTG9hZGVkID0gdHJ1ZTtcbiAgICAgICAgbG9hZENhbGxiYWNrKCk7XG4gICAgfTtcbiAgICBpZnJhbWUuc3JjID0gJ2h0dHBzOi8vb3BlbnZpZHUuZ2l0aHViLmlvL29wZW52aWR1LXNjcmVlbi1zaGFyaW5nLWNocm9tZS1leHRlbnNpb24vJztcbiAgICBpZnJhbWUuc3R5bGUuZGlzcGxheSA9ICdub25lJztcbiAgICAoZG9jdW1lbnQuYm9keSB8fCBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQpLmFwcGVuZENoaWxkKGlmcmFtZSk7XG59XG5cbndpbmRvdy5nZXRDaHJvbWVFeHRlbnNpb25TdGF0dXMgPSBmdW5jdGlvbiAoY2FsbGJhY2spIHtcbiAgICAvLyBmb3IgRmlyZWZveDpcbiAgICBpZiAoISFuYXZpZ2F0b3IubW96R2V0VXNlck1lZGlhKSB7XG4gICAgICAgIGNhbGxiYWNrKCdpbnN0YWxsZWQtZW5hYmxlZCcpO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ21lc3NhZ2UnLCBvbklGcmFtZUNhbGxiYWNrKTtcblxuICAgIGZ1bmN0aW9uIG9uSUZyYW1lQ2FsbGJhY2soZXZlbnQpIHtcbiAgICAgICAgaWYgKCFldmVudC5kYXRhKSByZXR1cm47XG5cbiAgICAgICAgaWYgKGV2ZW50LmRhdGEuY2hyb21lRXh0ZW5zaW9uU3RhdHVzKSB7XG4gICAgICAgICAgICBjYWxsYmFjayhldmVudC5kYXRhLmNocm9tZUV4dGVuc2lvblN0YXR1cyk7XG5cbiAgICAgICAgICAgIC8vIHRoaXMgZXZlbnQgbGlzdGVuZXIgaXMgbm8gbW9yZSBuZWVkZWRcbiAgICAgICAgICAgIHdpbmRvdy5yZW1vdmVFdmVudExpc3RlbmVyKCdtZXNzYWdlJywgb25JRnJhbWVDYWxsYmFjayk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBzZXRUaW1lb3V0KHBvc3RHZXRDaHJvbWVFeHRlbnNpb25TdGF0dXNNZXNzYWdlLCAxMDApO1xufTtcblxuZnVuY3Rpb24gcG9zdEdldENocm9tZUV4dGVuc2lvblN0YXR1c01lc3NhZ2UoKSB7XG4gICAgaWYgKCFpZnJhbWUpIHtcbiAgICAgICAgbG9hZElGcmFtZShwb3N0R2V0Q2hyb21lRXh0ZW5zaW9uU3RhdHVzTWVzc2FnZSk7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAoIWlmcmFtZS5pc0xvYWRlZCkge1xuICAgICAgICBzZXRUaW1lb3V0KHBvc3RHZXRDaHJvbWVFeHRlbnNpb25TdGF0dXNNZXNzYWdlLCAxMDApO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWZyYW1lLmNvbnRlbnRXaW5kb3cucG9zdE1lc3NhZ2Uoe1xuICAgICAgICBnZXRDaHJvbWVFeHRlbnNpb25TdGF0dXM6IHRydWVcbiAgICB9LCAnKicpO1xufVxuXG5leHBvcnRzLmdldFNjcmVlbklkID0gZ2V0U2NyZWVuSWQ7IiwiLy8gZ2xvYmFsIHZhcmlhYmxlc1xudmFyIGNocm9tZU1lZGlhU291cmNlID0gJ3NjcmVlbic7XG52YXIgc291cmNlSWQ7XG52YXIgc2NyZWVuQ2FsbGJhY2s7XG52YXIgaXNGaXJlZm94ID0gdHlwZW9mIHdpbmRvdy5JbnN0YWxsVHJpZ2dlciAhPT0gJ3VuZGVmaW5lZCc7XG52YXIgaXNPcGVyYSA9ICEhd2luZG93Lm9wZXJhIHx8IG5hdmlnYXRvci51c2VyQWdlbnQuaW5kZXhPZignIE9QUi8nKSA+PSAwO1xudmFyIGlzQ2hyb21lID0gISF3aW5kb3cuY2hyb21lICYmICFpc09wZXJhO1xuXG53aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcignbWVzc2FnZScsIGZ1bmN0aW9uIChldmVudCkge1xuICAgIGlmIChldmVudC5vcmlnaW4gIT0gd2luZG93LmxvY2F0aW9uLm9yaWdpbikge1xuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIG9uTWVzc2FnZUNhbGxiYWNrKGV2ZW50LmRhdGEpO1xufSk7XG5cbi8vIGFuZCB0aGUgZnVuY3Rpb24gdGhhdCBoYW5kbGVzIHJlY2VpdmVkIG1lc3NhZ2VzXG5mdW5jdGlvbiBvbk1lc3NhZ2VDYWxsYmFjayhkYXRhKSB7XG4gICAgLy8gXCJjYW5jZWxcIiBidXR0b24gaXMgY2xpY2tlZFxuICAgIGlmIChkYXRhID09ICdQZXJtaXNzaW9uRGVuaWVkRXJyb3InKSB7XG4gICAgICAgIGlmIChzY3JlZW5DYWxsYmFjaylcbiAgICAgICAgICAgIHJldHVybiBzY3JlZW5DYWxsYmFjaygnUGVybWlzc2lvbkRlbmllZEVycm9yJyk7XG4gICAgICAgIGVsc2VcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignUGVybWlzc2lvbkRlbmllZEVycm9yJyk7XG4gICAgfVxuICAgIC8vIGV4dGVuc2lvbiBub3RpZmllZCBoaXMgcHJlc2VuY2VcbiAgICBpZiAoZGF0YSA9PSAncnRjbXVsdGljb25uZWN0aW9uLWV4dGVuc2lvbi1sb2FkZWQnKSB7XG4gICAgICAgIGNocm9tZU1lZGlhU291cmNlID0gJ2Rlc2t0b3AnO1xuICAgIH1cbiAgICAvLyBleHRlbnNpb24gc2hhcmVkIHRlbXAgc291cmNlSWRcbiAgICBpZiAoZGF0YS5zb3VyY2VJZCAmJiBzY3JlZW5DYWxsYmFjaykge1xuICAgICAgICBzY3JlZW5DYWxsYmFjayhzb3VyY2VJZCA9IGRhdGEuc291cmNlSWQsIGRhdGEuY2FuUmVxdWVzdEF1ZGlvVHJhY2sgPT09IHRydWUpO1xuICAgIH1cbn1cblxuLy8gdGhpcyBtZXRob2QgY2FuIGJlIHVzZWQgdG8gY2hlY2sgaWYgY2hyb21lIGV4dGVuc2lvbiBpcyBpbnN0YWxsZWQgJiBlbmFibGVkLlxuZnVuY3Rpb24gaXNDaHJvbWVFeHRlbnNpb25BdmFpbGFibGUoY2FsbGJhY2spIHtcbiAgICBpZiAoIWNhbGxiYWNrKSByZXR1cm47XG4gICAgaWYgKGNocm9tZU1lZGlhU291cmNlID09ICdkZXNrdG9wJykgcmV0dXJuIGNhbGxiYWNrKHRydWUpO1xuXG4gICAgLy8gYXNrIGV4dGVuc2lvbiBpZiBpdCBpcyBhdmFpbGFibGVcbiAgICB3aW5kb3cucG9zdE1lc3NhZ2UoJ2FyZS15b3UtdGhlcmUnLCAnKicpO1xuICAgIHNldFRpbWVvdXQoZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAoY2hyb21lTWVkaWFTb3VyY2UgPT0gJ3NjcmVlbicpIHtcbiAgICAgICAgICAgIGNhbGxiYWNrKGZhbHNlKTtcbiAgICAgICAgfSBlbHNlIGNhbGxiYWNrKHRydWUpO1xuICAgIH0sIDIwMDApO1xufVxuXG4vLyB0aGlzIGZ1bmN0aW9uIGNhbiBiZSB1c2VkIHRvIGdldCBcInNvdXJjZS1pZFwiIGZyb20gdGhlIGV4dGVuc2lvblxuZnVuY3Rpb24gZ2V0U291cmNlSWQoY2FsbGJhY2spIHtcbiAgICBpZiAoIWNhbGxiYWNrKVxuICAgICAgICB0aHJvdyAnXCJjYWxsYmFja1wiIHBhcmFtZXRlciBpcyBtYW5kYXRvcnkuJztcbiAgICBpZiAoc291cmNlSWQpXG4gICAgICAgIHJldHVybiBjYWxsYmFjayhzb3VyY2VJZCk7XG4gICAgc2NyZWVuQ2FsbGJhY2sgPSBjYWxsYmFjaztcbiAgICB3aW5kb3cucG9zdE1lc3NhZ2UoJ2dldC1zb3VyY2VJZCcsICcqJyk7XG59XG5cbi8vIHRoaXMgZnVuY3Rpb24gY2FuIGJlIHVzZWQgdG8gZ2V0IFwic291cmNlLWlkXCIgZnJvbSB0aGUgZXh0ZW5zaW9uXG5mdW5jdGlvbiBnZXRDdXN0b21Tb3VyY2VJZChhcnIsIGNhbGxiYWNrKSB7XG4gICAgaWYgKCFhcnIgfHwgIWFyci5mb3JFYWNoKSB0aHJvdyAnXCJhcnJcIiBwYXJhbWV0ZXIgaXMgbWFuZGF0b3J5IGFuZCBpdCBtdXN0IGJlIGFuIGFycmF5Lic7XG4gICAgaWYgKCFjYWxsYmFjaykgdGhyb3cgJ1wiY2FsbGJhY2tcIiBwYXJhbWV0ZXIgaXMgbWFuZGF0b3J5Lic7XG5cbiAgICBpZiAoc291cmNlSWQpIHJldHVybiBjYWxsYmFjayhzb3VyY2VJZCk7XG5cbiAgICBzY3JlZW5DYWxsYmFjayA9IGNhbGxiYWNrO1xuICAgIHdpbmRvdy5wb3N0TWVzc2FnZSh7XG4gICAgICAgICdnZXQtY3VzdG9tLXNvdXJjZUlkJzogYXJyXG4gICAgfSwgJyonKTtcbn1cblxuLy8gdGhpcyBmdW5jdGlvbiBjYW4gYmUgdXNlZCB0byBnZXQgXCJzb3VyY2UtaWRcIiBmcm9tIHRoZSBleHRlbnNpb25cbmZ1bmN0aW9uIGdldFNvdXJjZUlkV2l0aEF1ZGlvKGNhbGxiYWNrKSB7XG4gICAgaWYgKCFjYWxsYmFjaykgdGhyb3cgJ1wiY2FsbGJhY2tcIiBwYXJhbWV0ZXIgaXMgbWFuZGF0b3J5Lic7XG4gICAgaWYgKHNvdXJjZUlkKSByZXR1cm4gY2FsbGJhY2soc291cmNlSWQpO1xuXG4gICAgc2NyZWVuQ2FsbGJhY2sgPSBjYWxsYmFjaztcbiAgICB3aW5kb3cucG9zdE1lc3NhZ2UoJ2F1ZGlvLXBsdXMtdGFiJywgJyonKTtcbn1cblxuZnVuY3Rpb24gZ2V0Q2hyb21lRXh0ZW5zaW9uU3RhdHVzKGV4dGVuc2lvbmlkLCBjYWxsYmFjaykge1xuICAgIGlmIChpc0ZpcmVmb3gpXG4gICAgICAgIHJldHVybiBjYWxsYmFjaygnbm90LWNocm9tZScpO1xuICAgIGlmIChhcmd1bWVudHMubGVuZ3RoICE9IDIpIHtcbiAgICAgICAgY2FsbGJhY2sgPSBleHRlbnNpb25pZDtcbiAgICAgICAgZXh0ZW5zaW9uaWQgPSAnbGZjZ2ZlcGFmbm9iZGxvZWNjaG5mYWNsaWJlbmpvbGQnOyAvLyBkZWZhdWx0IGV4dGVuc2lvbi1pZFxuICAgIH1cbiAgICB2YXIgaW1hZ2UgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdpbWcnKTtcbiAgICBpbWFnZS5zcmMgPSAnY2hyb21lLWV4dGVuc2lvbjovLycgKyBleHRlbnNpb25pZCArICcvaWNvbi5wbmcnO1xuICAgIGltYWdlLm9ubG9hZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgY2hyb21lTWVkaWFTb3VyY2UgPSAnc2NyZWVuJztcbiAgICAgICAgd2luZG93LnBvc3RNZXNzYWdlKCdhcmUteW91LXRoZXJlJywgJyonKTtcbiAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBpZiAoY2hyb21lTWVkaWFTb3VyY2UgPT0gJ3NjcmVlbicpIHtcbiAgICAgICAgICAgICAgICBjYWxsYmFjaygnaW5zdGFsbGVkLWRpc2FibGVkJyk7XG4gICAgICAgICAgICB9IGVsc2VcbiAgICAgICAgICAgICAgICBjYWxsYmFjaygnaW5zdGFsbGVkLWVuYWJsZWQnKTtcbiAgICAgICAgfSwgMjAwMCk7XG4gICAgfTtcbiAgICBpbWFnZS5vbmVycm9yID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBjYWxsYmFjaygnbm90LWluc3RhbGxlZCcpO1xuICAgIH07XG59XG5cbmZ1bmN0aW9uIGdldFNjcmVlbkNvbnN0cmFpbnRzV2l0aEF1ZGlvKGNhbGxiYWNrKSB7XG4gICAgZ2V0U2NyZWVuQ29uc3RyYWludHMoY2FsbGJhY2ssIHRydWUpO1xufVxuXG4vLyB0aGlzIGZ1bmN0aW9uIGV4cGxhaW5zIGhvdyB0byB1c2UgYWJvdmUgbWV0aG9kcy9vYmplY3RzXG5mdW5jdGlvbiBnZXRTY3JlZW5Db25zdHJhaW50cyhjYWxsYmFjaywgY2FwdHVyZVNvdXJjZUlkV2l0aEF1ZGlvKSB7XG4gICAgc291cmNlSWQgPSAnJztcbiAgICB2YXIgZmlyZWZveFNjcmVlbkNvbnN0cmFpbnRzID0ge1xuICAgICAgICBtb3pNZWRpYVNvdXJjZTogJ3dpbmRvdycsXG4gICAgICAgIG1lZGlhU291cmNlOiAnd2luZG93J1xuICAgIH07XG4gICAgaWYgKGlzRmlyZWZveClcbiAgICAgICAgcmV0dXJuIGNhbGxiYWNrKG51bGwsIGZpcmVmb3hTY3JlZW5Db25zdHJhaW50cyk7XG4gICAgLy8gdGhpcyBzdGF0ZW1lbnQgZGVmaW5lcyBnZXRVc2VyTWVkaWEgY29uc3RyYWludHNcbiAgICAvLyB0aGF0IHdpbGwgYmUgdXNlZCB0byBjYXB0dXJlIGNvbnRlbnQgb2Ygc2NyZWVuXG4gICAgdmFyIHNjcmVlbl9jb25zdHJhaW50cyA9IHtcbiAgICAgICAgbWFuZGF0b3J5OiB7XG4gICAgICAgICAgICBjaHJvbWVNZWRpYVNvdXJjZTogY2hyb21lTWVkaWFTb3VyY2UsXG4gICAgICAgICAgICBtYXhXaWR0aDogc2NyZWVuLndpZHRoID4gMTkyMCA/IHNjcmVlbi53aWR0aCA6IDE5MjAsXG4gICAgICAgICAgICBtYXhIZWlnaHQ6IHNjcmVlbi5oZWlnaHQgPiAxMDgwID8gc2NyZWVuLmhlaWdodCA6IDEwODBcbiAgICAgICAgfSxcbiAgICAgICAgb3B0aW9uYWw6IFtdXG4gICAgfTtcbiAgICAvLyB0aGlzIHN0YXRlbWVudCB2ZXJpZmllcyBjaHJvbWUgZXh0ZW5zaW9uIGF2YWlsYWJpbGl0eVxuICAgIC8vIGlmIGluc3RhbGxlZCBhbmQgYXZhaWxhYmxlIHRoZW4gaXQgd2lsbCBpbnZva2UgZXh0ZW5zaW9uIEFQSVxuICAgIC8vIG90aGVyd2lzZSBpdCB3aWxsIGZhbGxiYWNrIHRvIGNvbW1hbmQtbGluZSBiYXNlZCBzY3JlZW4gY2FwdHVyaW5nIEFQSVxuICAgIGlmIChjaHJvbWVNZWRpYVNvdXJjZSA9PSAnZGVza3RvcCcgJiYgIXNvdXJjZUlkKSB7XG4gICAgICAgIGlmIChjYXB0dXJlU291cmNlSWRXaXRoQXVkaW8pIHtcbiAgICAgICAgICAgIGdldFNvdXJjZUlkV2l0aEF1ZGlvKGZ1bmN0aW9uIChzb3VyY2VJZCwgY2FuUmVxdWVzdEF1ZGlvVHJhY2spIHtcbiAgICAgICAgICAgICAgICBzY3JlZW5fY29uc3RyYWludHMubWFuZGF0b3J5LmNocm9tZU1lZGlhU291cmNlSWQgPSBzb3VyY2VJZDtcblxuICAgICAgICAgICAgICAgIGlmIChjYW5SZXF1ZXN0QXVkaW9UcmFjaykge1xuICAgICAgICAgICAgICAgICAgICBzY3JlZW5fY29uc3RyYWludHMuY2FuUmVxdWVzdEF1ZGlvVHJhY2sgPSB0cnVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjYWxsYmFjayhzb3VyY2VJZCA9PSAnUGVybWlzc2lvbkRlbmllZEVycm9yJyA/IHNvdXJjZUlkIDogbnVsbCwgc2NyZWVuX2NvbnN0cmFpbnRzKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgZ2V0U291cmNlSWQoZnVuY3Rpb24gKHNvdXJjZUlkKSB7XG4gICAgICAgICAgICAgICAgc2NyZWVuX2NvbnN0cmFpbnRzLm1hbmRhdG9yeS5jaHJvbWVNZWRpYVNvdXJjZUlkID0gc291cmNlSWQ7XG4gICAgICAgICAgICAgICAgY2FsbGJhY2soc291cmNlSWQgPT0gJ1Blcm1pc3Npb25EZW5pZWRFcnJvcicgPyBzb3VyY2VJZCA6IG51bGwsIHNjcmVlbl9jb25zdHJhaW50cyk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gdGhpcyBzdGF0ZW1lbnQgc2V0cyBnZXRzICdzb3VyY2VJZFwiIGFuZCBzZXRzIFwiY2hyb21lTWVkaWFTb3VyY2VJZFwiIFxuICAgIGlmIChjaHJvbWVNZWRpYVNvdXJjZSA9PSAnZGVza3RvcCcpIHtcbiAgICAgICAgc2NyZWVuX2NvbnN0cmFpbnRzLm1hbmRhdG9yeS5jaHJvbWVNZWRpYVNvdXJjZUlkID0gc291cmNlSWQ7XG4gICAgfVxuXG4gICAgLy8gbm93IGludm9raW5nIG5hdGl2ZSBnZXRVc2VyTWVkaWEgQVBJXG4gICAgY2FsbGJhY2sobnVsbCwgc2NyZWVuX2NvbnN0cmFpbnRzKTtcbn1cblxuZXhwb3J0cy5nZXRTY3JlZW5Db25zdHJhaW50cyA9IGdldFNjcmVlbkNvbnN0cmFpbnRzO1xuZXhwb3J0cy5nZXRTY3JlZW5Db25zdHJhaW50c1dpdGhBdWRpbyA9IGdldFNjcmVlbkNvbnN0cmFpbnRzV2l0aEF1ZGlvO1xuZXhwb3J0cy5pc0Nocm9tZUV4dGVuc2lvbkF2YWlsYWJsZSA9IGlzQ2hyb21lRXh0ZW5zaW9uQXZhaWxhYmxlO1xuZXhwb3J0cy5nZXRDaHJvbWVFeHRlbnNpb25TdGF0dXMgPSBnZXRDaHJvbWVFeHRlbnNpb25TdGF0dXM7XG5leHBvcnRzLmdldFNvdXJjZUlkID0gZ2V0U291cmNlSWQ7IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgZnJlZWljZSA9IHJlcXVpcmUoJ2ZyZWVpY2UnKTtcbmltcG9ydCB1dWlkID0gcmVxdWlyZSgndXVpZCcpO1xuaW1wb3J0IHBsYXRmb3JtID0gcmVxdWlyZSgncGxhdGZvcm0nKTtcblxuXG5leHBvcnQgaW50ZXJmYWNlIFdlYlJ0Y1BlZXJDb25maWd1cmF0aW9uIHtcbiAgICBtZWRpYUNvbnN0cmFpbnRzOiB7XG4gICAgICAgIGF1ZGlvOiBib29sZWFuLFxuICAgICAgICB2aWRlbzogYm9vbGVhblxuICAgIH07XG4gICAgc2ltdWxjYXN0OiBib29sZWFuO1xuICAgIG9uaWNlY2FuZGlkYXRlOiAoZXZlbnQpID0+IHZvaWQ7XG4gICAgaWNlU2VydmVyczogUlRDSWNlU2VydmVyW10gfCB1bmRlZmluZWQ7XG4gICAgbWVkaWFTdHJlYW0/OiBNZWRpYVN0cmVhbTtcbiAgICBtb2RlPzogc3RyaW5nOyAvLyBzZW5kb25seSwgcmVjb25seSwgc2VuZHJlY3ZcbiAgICBpZD86IHN0cmluZztcbn1cblxuZXhwb3J0IGNsYXNzIFdlYlJ0Y1BlZXIge1xuXG4gICAgcGM6IFJUQ1BlZXJDb25uZWN0aW9uO1xuICAgIGlkOiBzdHJpbmc7XG4gICAgcmVtb3RlQ2FuZGlkYXRlc1F1ZXVlOiBSVENJY2VDYW5kaWRhdGVbXSA9IFtdO1xuICAgIGxvY2FsQ2FuZGlkYXRlc1F1ZXVlOiBSVENJY2VDYW5kaWRhdGVbXSA9IFtdO1xuXG4gICAgaWNlQ2FuZGlkYXRlTGlzdDogUlRDSWNlQ2FuZGlkYXRlW10gPSBbXTtcblxuICAgIHByaXZhdGUgY2FuZGlkYXRlZ2F0aGVyaW5nZG9uZSA9IGZhbHNlO1xuXG4gICAgY29uc3RydWN0b3IocHJpdmF0ZSBjb25maWd1cmF0aW9uOiBXZWJSdGNQZWVyQ29uZmlndXJhdGlvbikge1xuICAgICAgICB0aGlzLmNvbmZpZ3VyYXRpb24uaWNlU2VydmVycyA9ICghIXRoaXMuY29uZmlndXJhdGlvbi5pY2VTZXJ2ZXJzICYmIHRoaXMuY29uZmlndXJhdGlvbi5pY2VTZXJ2ZXJzLmxlbmd0aCA+IDApID8gdGhpcy5jb25maWd1cmF0aW9uLmljZVNlcnZlcnMgOiBmcmVlaWNlKCk7XG5cbiAgICAgICAgdGhpcy5wYyA9IG5ldyBSVENQZWVyQ29ubmVjdGlvbih7IGljZVNlcnZlcnM6IHRoaXMuY29uZmlndXJhdGlvbi5pY2VTZXJ2ZXJzIH0pO1xuICAgICAgICB0aGlzLmlkID0gISFjb25maWd1cmF0aW9uLmlkID8gY29uZmlndXJhdGlvbi5pZCA6IHV1aWQudjQoKTtcblxuICAgICAgICB0aGlzLnBjLm9uaWNlY2FuZGlkYXRlID0gZXZlbnQgPT4ge1xuICAgICAgICAgICAgY29uc3QgY2FuZGlkYXRlOiBSVENJY2VDYW5kaWRhdGUgPSBldmVudC5jYW5kaWRhdGU7XG4gICAgICAgICAgICBpZiAoY2FuZGlkYXRlKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5sb2NhbENhbmRpZGF0ZXNRdWV1ZS5wdXNoKDxSVENJY2VDYW5kaWRhdGU+eyBjYW5kaWRhdGU6IGNhbmRpZGF0ZS5jYW5kaWRhdGUgfSk7XG4gICAgICAgICAgICAgICAgdGhpcy5jYW5kaWRhdGVnYXRoZXJpbmdkb25lID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgdGhpcy5jb25maWd1cmF0aW9uLm9uaWNlY2FuZGlkYXRlKGV2ZW50LmNhbmRpZGF0ZSk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKCF0aGlzLmNhbmRpZGF0ZWdhdGhlcmluZ2RvbmUpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmNhbmRpZGF0ZWdhdGhlcmluZ2RvbmUgPSB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuXG4gICAgICAgIHRoaXMucGMub25zaWduYWxpbmdzdGF0ZWNoYW5nZSA9ICgpID0+IHtcbiAgICAgICAgICAgIGlmICh0aGlzLnBjLnNpZ25hbGluZ1N0YXRlID09PSAnc3RhYmxlJykge1xuICAgICAgICAgICAgICAgIHdoaWxlICh0aGlzLmljZUNhbmRpZGF0ZUxpc3QubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnBjLmFkZEljZUNhbmRpZGF0ZSg8UlRDSWNlQ2FuZGlkYXRlPnRoaXMuaWNlQ2FuZGlkYXRlTGlzdC5zaGlmdCgpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG5cbiAgICAgICAgdGhpcy5zdGFydCgpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoaXMgZnVuY3Rpb24gY3JlYXRlcyB0aGUgUlRDUGVlckNvbm5lY3Rpb24gb2JqZWN0IHRha2luZyBpbnRvIGFjY291bnQgdGhlXG4gICAgICogcHJvcGVydGllcyByZWNlaXZlZCBpbiB0aGUgY29uc3RydWN0b3IuIEl0IHN0YXJ0cyB0aGUgU0RQIG5lZ290aWF0aW9uXG4gICAgICogcHJvY2VzczogZ2VuZXJhdGVzIHRoZSBTRFAgb2ZmZXIgYW5kIGludm9rZXMgdGhlIG9uc2Rwb2ZmZXIgY2FsbGJhY2suIFRoaXNcbiAgICAgKiBjYWxsYmFjayBpcyBleHBlY3RlZCB0byBzZW5kIHRoZSBTRFAgb2ZmZXIsIGluIG9yZGVyIHRvIG9idGFpbiBhbiBTRFBcbiAgICAgKiBhbnN3ZXIgZnJvbSBhbm90aGVyIHBlZXIuXG4gICAgICovXG4gICAgc3RhcnQoKTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIGlmICh0aGlzLnBjLnNpZ25hbGluZ1N0YXRlID09PSAnY2xvc2VkJykge1xuICAgICAgICAgICAgICAgIHJlamVjdCgnVGhlIHBlZXIgY29ubmVjdGlvbiBvYmplY3QgaXMgaW4gXCJjbG9zZWRcIiBzdGF0ZS4gVGhpcyBpcyBtb3N0IGxpa2VseSBkdWUgdG8gYW4gaW52b2NhdGlvbiBvZiB0aGUgZGlzcG9zZSBtZXRob2QgYmVmb3JlIGFjY2VwdGluZyBpbiB0aGUgZGlhbG9ndWUnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICghIXRoaXMuY29uZmlndXJhdGlvbi5tZWRpYVN0cmVhbSkge1xuICAgICAgICAgICAgICAgIHRoaXMucGMuYWRkU3RyZWFtKHRoaXMuY29uZmlndXJhdGlvbi5tZWRpYVN0cmVhbSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIFtIYWNrXSBodHRwczovL2NvZGUuZ29vZ2xlLmNvbS9wL2Nocm9taXVtL2lzc3Vlcy9kZXRhaWw/aWQ9NDQzNTU4XG4gICAgICAgICAgICBpZiAodGhpcy5jb25maWd1cmF0aW9uLm1vZGUgPT09ICdzZW5kb25seScgJiZcbiAgICAgICAgICAgICAgICAocGxhdGZvcm0ubmFtZSA9PT0gJ0Nocm9tZScgJiYgcGxhdGZvcm0udmVyc2lvbiEudG9TdHJpbmcoKS5zdWJzdHJpbmcoMCwgMikgPT09ICczOScpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5jb25maWd1cmF0aW9uLm1vZGUgPSAnc2VuZHJlY3YnO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoaXMgbWV0aG9kIGZyZWVzIHRoZSByZXNvdXJjZXMgdXNlZCBieSBXZWJSdGNQZWVyXG4gICAgICovXG4gICAgZGlzcG9zZSgpIHtcbiAgICAgICAgY29uc29sZS5kZWJ1ZygnRGlzcG9zaW5nIFdlYlJ0Y1BlZXInKTtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGlmICh0aGlzLnBjKSB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMucGMuc2lnbmFsaW5nU3RhdGUgPT09ICdjbG9zZWQnKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhpcy5yZW1vdGVDYW5kaWRhdGVzUXVldWUgPSBbXTtcbiAgICAgICAgICAgICAgICB0aGlzLmxvY2FsQ2FuZGlkYXRlc1F1ZXVlID0gW107XG5cbiAgICAgICAgICAgICAgICB0aGlzLnBjLmdldExvY2FsU3RyZWFtcygpLmZvckVhY2goc3RyID0+IHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5zdHJlYW1TdG9wKHN0cik7XG4gICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICAvLyBGSVhNRSBUaGlzIGlzIG5vdCB5ZXQgaW1wbGVtZW50ZWQgaW4gZmlyZWZveFxuICAgICAgICAgICAgICAgIC8vIGlmKHZpZGVvU3RyZWFtKSBwYy5yZW1vdmVTdHJlYW0odmlkZW9TdHJlYW0pO1xuICAgICAgICAgICAgICAgIC8vIGlmKGF1ZGlvU3RyZWFtKSBwYy5yZW1vdmVTdHJlYW0oYXVkaW9TdHJlYW0pO1xuXG4gICAgICAgICAgICAgICAgdGhpcy5wYy5jbG9zZSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAgIGNvbnNvbGUud2FybignRXhjZXB0aW9uIGRpc3Bvc2luZyB3ZWJydGMgcGVlciAnICsgZXJyKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIDEpIEZ1bmN0aW9uIHRoYXQgY3JlYXRlcyBhbiBvZmZlciwgc2V0cyBpdCBhcyBsb2NhbCBkZXNjcmlwdGlvbiBhbmQgcmV0dXJucyB0aGUgb2ZmZXIgcGFyYW1cbiAgICAgKiB0byBzZW5kIHRvIE9wZW5WaWR1IFNlcnZlciAod2lsbCBiZSB0aGUgcmVtb3RlIGRlc2NyaXB0aW9uIG9mIG90aGVyIHBlZXIpXG4gICAgICovXG4gICAgZ2VuZXJhdGVPZmZlcigpOiBQcm9taXNlPHN0cmluZz4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgbGV0IG9mZmVyQXVkaW8sIG9mZmVyVmlkZW8gPSB0cnVlO1xuXG4gICAgICAgICAgICAvLyBDb25zdHJhaW50cyBtdXN0IGhhdmUgYm90aCBibG9ja3NcbiAgICAgICAgICAgIGlmICghIXRoaXMuY29uZmlndXJhdGlvbi5tZWRpYUNvbnN0cmFpbnRzKSB7XG4gICAgICAgICAgICAgICAgb2ZmZXJBdWRpbyA9ICh0eXBlb2YgdGhpcy5jb25maWd1cmF0aW9uLm1lZGlhQ29uc3RyYWludHMuYXVkaW8gPT09ICdib29sZWFuJykgP1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbmZpZ3VyYXRpb24ubWVkaWFDb25zdHJhaW50cy5hdWRpbyA6IHRydWU7XG4gICAgICAgICAgICAgICAgb2ZmZXJWaWRlbyA9ICh0eXBlb2YgdGhpcy5jb25maWd1cmF0aW9uLm1lZGlhQ29uc3RyYWludHMudmlkZW8gPT09ICdib29sZWFuJykgP1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbmZpZ3VyYXRpb24ubWVkaWFDb25zdHJhaW50cy52aWRlbyA6IHRydWU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGNvbnN0IGNvbnN0cmFpbnRzOiBSVENPZmZlck9wdGlvbnMgPSB7XG4gICAgICAgICAgICAgICAgb2ZmZXJUb1JlY2VpdmVBdWRpbzogKyAodGhpcy5jb25maWd1cmF0aW9uLm1vZGUgIT09ICdzZW5kb25seScgJiYgb2ZmZXJBdWRpbyksXG4gICAgICAgICAgICAgICAgb2ZmZXJUb1JlY2VpdmVWaWRlbzogKyAodGhpcy5jb25maWd1cmF0aW9uLm1vZGUgIT09ICdzZW5kb25seScgJiYgb2ZmZXJWaWRlbylcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIGNvbnNvbGUuZGVidWcoJ1JUQ1BlZXJDb25uZWN0aW9uIGNvbnN0cmFpbnRzOiAnICsgSlNPTi5zdHJpbmdpZnkoY29uc3RyYWludHMpKTtcblxuICAgICAgICAgICAgdGhpcy5wYy5jcmVhdGVPZmZlcihjb25zdHJhaW50cykudGhlbihvZmZlciA9PiB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5kZWJ1ZygnQ3JlYXRlZCBTRFAgb2ZmZXInKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5wYy5zZXRMb2NhbERlc2NyaXB0aW9uKG9mZmVyKTtcbiAgICAgICAgICAgIH0pLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IGxvY2FsRGVzY3JpcHRpb24gPSB0aGlzLnBjLmxvY2FsRGVzY3JpcHRpb247XG4gICAgICAgICAgICAgICAgaWYgKCEhbG9jYWxEZXNjcmlwdGlvbikge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmRlYnVnKCdMb2NhbCBkZXNjcmlwdGlvbiBzZXQnLCBsb2NhbERlc2NyaXB0aW9uLnNkcCk7XG4gICAgICAgICAgICAgICAgICAgIHJlc29sdmUoPHN0cmluZz5sb2NhbERlc2NyaXB0aW9uLnNkcCk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcmVqZWN0KCdMb2NhbCBkZXNjcmlwdGlvbiBpcyBub3QgZGVmaW5lZCcpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pLmNhdGNoKGVycm9yID0+IHJlamVjdChlcnJvcikpO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiAyKSBGdW5jdGlvbiB0byBpbnZva2Ugd2hlbiBhIFNEUCBvZmZlciBpcyByZWNlaXZlZC4gU2V0cyBpdCBhcyByZW1vdGUgZGVzY3JpcHRpb24sXG4gICAgICogZ2VuZXJhdGVzIGFuZCBhbnN3ZXIgYW5kIHJldHVybnMgaXQgdG8gc2VuZCBpdCB0byBPcGVuVmlkdSBTZXJ2ZXJcbiAgICAgKi9cbiAgICBwcm9jZXNzT2ZmZXIoc2RwT2ZmZXI6IHN0cmluZyk6IFByb21pc2U8Q29uc3RyYWluRE9NU3RyaW5nPiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICBjb25zdCBvZmZlcjogUlRDU2Vzc2lvbkRlc2NyaXB0aW9uSW5pdCA9IHtcbiAgICAgICAgICAgICAgICB0eXBlOiAnb2ZmZXInLFxuICAgICAgICAgICAgICAgIHNkcDogc2RwT2ZmZXJcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIGNvbnNvbGUuZGVidWcoJ1NEUCBvZmZlciByZWNlaXZlZCwgc2V0dGluZyByZW1vdGUgZGVzY3JpcHRpb24nKTtcblxuICAgICAgICAgICAgaWYgKHRoaXMucGMuc2lnbmFsaW5nU3RhdGUgPT09ICdjbG9zZWQnKSB7XG4gICAgICAgICAgICAgICAgcmVqZWN0KCdQZWVyQ29ubmVjdGlvbiBpcyBjbG9zZWQnKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5wYy5zZXRSZW1vdGVEZXNjcmlwdGlvbihvZmZlcilcbiAgICAgICAgICAgICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLnBjLmNyZWF0ZUFuc3dlcigpO1xuICAgICAgICAgICAgICAgIH0pLnRoZW4oYW5zd2VyID0+IHtcbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS5kZWJ1ZygnQ3JlYXRlZCBTRFAgYW5zd2VyJyk7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLnBjLnNldExvY2FsRGVzY3JpcHRpb24oYW5zd2VyKTtcbiAgICAgICAgICAgICAgICB9KS50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgbG9jYWxEZXNjcmlwdGlvbiA9IHRoaXMucGMubG9jYWxEZXNjcmlwdGlvbjtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCEhbG9jYWxEZXNjcmlwdGlvbikge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5kZWJ1ZygnTG9jYWwgZGVzY3JpcHRpb24gc2V0JywgbG9jYWxEZXNjcmlwdGlvbi5zZHApO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSg8c3RyaW5nPmxvY2FsRGVzY3JpcHRpb24uc2RwKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdCgnTG9jYWwgZGVzY3JpcHRpb24gaXMgbm90IGRlZmluZWQnKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pLmNhdGNoKGVycm9yID0+IHJlamVjdChlcnJvcikpO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiAzKSBGdW5jdGlvbiBpbnZva2VkIHdoZW4gYSBTRFAgYW5zd2VyIGlzIHJlY2VpdmVkLiBGaW5hbCBzdGVwIGluIFNEUCBuZWdvdGlhdGlvbiwgdGhlIHBlZXJcbiAgICAgKiBqdXN0IG5lZWRzIHRvIHNldCB0aGUgYW5zd2VyIGFzIGl0cyByZW1vdGUgZGVzY3JpcHRpb25cbiAgICAgKi9cbiAgICBwcm9jZXNzQW5zd2VyKHNkcEFuc3dlcjogc3RyaW5nKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcblxuICAgICAgICAgICAgY29uc3QgYW5zd2VyOiBSVENTZXNzaW9uRGVzY3JpcHRpb25Jbml0ID0ge1xuICAgICAgICAgICAgICAgIHR5cGU6ICdhbnN3ZXInLFxuICAgICAgICAgICAgICAgIHNkcDogc2RwQW5zd2VyXG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICBjb25zb2xlLmRlYnVnKCdTRFAgYW5zd2VyIHJlY2VpdmVkLCBzZXR0aW5nIHJlbW90ZSBkZXNjcmlwdGlvbicpO1xuXG4gICAgICAgICAgICBpZiAodGhpcy5wYy5zaWduYWxpbmdTdGF0ZSA9PT0gJ2Nsb3NlZCcpIHtcbiAgICAgICAgICAgICAgICByZWplY3QoJ1JUQ1BlZXJDb25uZWN0aW9uIGlzIGNsb3NlZCcpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLnBjLnNldFJlbW90ZURlc2NyaXB0aW9uKGFuc3dlcikudGhlbigoKSA9PiByZXNvbHZlKCkpLmNhdGNoKGVycm9yID0+IHJlamVjdChlcnJvcikpO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDYWxsYmFjayBmdW5jdGlvbiBpbnZva2VkIHdoZW4gYW4gSUNFIGNhbmRpZGF0ZSBpcyByZWNlaXZlZFxuICAgICAqL1xuICAgIGFkZEljZUNhbmRpZGF0ZShpY2VDYW5kaWRhdGU6IFJUQ0ljZUNhbmRpZGF0ZSk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgY29uc29sZS5kZWJ1ZygnUmVtb3RlIElDRSBjYW5kaWRhdGUgcmVjZWl2ZWQnLCBpY2VDYW5kaWRhdGUpO1xuICAgICAgICAgICAgdGhpcy5yZW1vdGVDYW5kaWRhdGVzUXVldWUucHVzaChpY2VDYW5kaWRhdGUpO1xuICAgICAgICAgICAgc3dpdGNoICh0aGlzLnBjLnNpZ25hbGluZ1N0YXRlKSB7XG4gICAgICAgICAgICAgICAgY2FzZSAnY2xvc2VkJzpcbiAgICAgICAgICAgICAgICAgICAgcmVqZWN0KG5ldyBFcnJvcignUGVlckNvbm5lY3Rpb24gb2JqZWN0IGlzIGNsb3NlZCcpKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAnc3RhYmxlJzpcbiAgICAgICAgICAgICAgICAgICAgaWYgKCEhdGhpcy5wYy5yZW1vdGVEZXNjcmlwdGlvbikge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5wYy5hZGRJY2VDYW5kaWRhdGUoaWNlQ2FuZGlkYXRlKS50aGVuKCgpID0+IHJlc29sdmUoKSkuY2F0Y2goZXJyb3IgPT4gcmVqZWN0KGVycm9yKSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5pY2VDYW5kaWRhdGVMaXN0LnB1c2goaWNlQ2FuZGlkYXRlKTtcbiAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBwcml2YXRlIHN0cmVhbVN0b3Aoc3RyZWFtOiBNZWRpYVN0cmVhbSk6IHZvaWQge1xuICAgICAgICBzdHJlYW0uZ2V0VHJhY2tzKCkuZm9yRWFjaCh0cmFjayA9PiB7XG4gICAgICAgICAgICB0cmFjay5zdG9wKCk7XG4gICAgICAgICAgICBzdHJlYW0ucmVtb3ZlVHJhY2sodHJhY2spO1xuICAgICAgICB9KTtcbiAgICB9XG59XG5cblxuZXhwb3J0IGNsYXNzIFdlYlJ0Y1BlZXJSZWN2b25seSBleHRlbmRzIFdlYlJ0Y1BlZXIge1xuICAgIGNvbnN0cnVjdG9yKGNvbmZpZ3VyYXRpb246IFdlYlJ0Y1BlZXJDb25maWd1cmF0aW9uKSB7XG4gICAgICAgIGNvbmZpZ3VyYXRpb24ubW9kZSA9ICdyZWN2b25seSc7XG4gICAgICAgIHN1cGVyKGNvbmZpZ3VyYXRpb24pO1xuICAgIH1cbn1cblxuZXhwb3J0IGNsYXNzIFdlYlJ0Y1BlZXJTZW5kb25seSBleHRlbmRzIFdlYlJ0Y1BlZXIge1xuICAgIGNvbnN0cnVjdG9yKGNvbmZpZ3VyYXRpb246IFdlYlJ0Y1BlZXJDb25maWd1cmF0aW9uKSB7XG4gICAgICAgIGNvbmZpZ3VyYXRpb24ubW9kZSA9ICdzZW5kb25seSc7XG4gICAgICAgIHN1cGVyKGNvbmZpZ3VyYXRpb24pO1xuICAgIH1cbn1cblxuZXhwb3J0IGNsYXNzIFdlYlJ0Y1BlZXJTZW5kcmVjdiBleHRlbmRzIFdlYlJ0Y1BlZXIge1xuICAgIGNvbnN0cnVjdG9yKGNvbmZpZ3VyYXRpb246IFdlYlJ0Y1BlZXJDb25maWd1cmF0aW9uKSB7XG4gICAgICAgIGNvbmZpZ3VyYXRpb24ubW9kZSA9ICdzZW5kcmVjdic7XG4gICAgICAgIHN1cGVyKGNvbmZpZ3VyYXRpb24pO1xuICAgIH1cbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbi8vIHRzbGludDpkaXNhYmxlOm5vLXN0cmluZy1saXRlcmFsXG5cbmltcG9ydCB7IFN0cmVhbSB9IGZyb20gJy4uLy4uL09wZW5WaWR1L1N0cmVhbSc7XG5pbXBvcnQgcGxhdGZvcm0gPSByZXF1aXJlKCdwbGF0Zm9ybScpO1xuXG5leHBvcnQgY2xhc3MgV2ViUnRjU3RhdHMge1xuXG4gICAgcHJpdmF0ZSB3ZWJSdGNTdGF0c0VuYWJsZWQgPSBmYWxzZTtcbiAgICBwcml2YXRlIHdlYlJ0Y1N0YXRzSW50ZXJ2YWxJZDogTm9kZUpTLlRpbWVyO1xuICAgIHByaXZhdGUgc3RhdHNJbnRlcnZhbCA9IDE7XG4gICAgcHJpdmF0ZSBzdGF0czogYW55ID0ge1xuICAgICAgICBpbmJvdW5kOiB7XG4gICAgICAgICAgICBhdWRpbzoge1xuICAgICAgICAgICAgICAgIGJ5dGVzUmVjZWl2ZWQ6IDAsXG4gICAgICAgICAgICAgICAgcGFja2V0c1JlY2VpdmVkOiAwLFxuICAgICAgICAgICAgICAgIHBhY2tldHNMb3N0OiAwXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgdmlkZW86IHtcbiAgICAgICAgICAgICAgICBieXRlc1JlY2VpdmVkOiAwLFxuICAgICAgICAgICAgICAgIHBhY2tldHNSZWNlaXZlZDogMCxcbiAgICAgICAgICAgICAgICBwYWNrZXRzTG9zdDogMCxcbiAgICAgICAgICAgICAgICBmcmFtZXNEZWNvZGVkOiAwLFxuICAgICAgICAgICAgICAgIG5hY2tDb3VudDogMFxuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBvdXRib3VuZDoge1xuICAgICAgICAgICAgYXVkaW86IHtcbiAgICAgICAgICAgICAgICBieXRlc1NlbnQ6IDAsXG4gICAgICAgICAgICAgICAgcGFja2V0c1NlbnQ6IDAsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgdmlkZW86IHtcbiAgICAgICAgICAgICAgICBieXRlc1NlbnQ6IDAsXG4gICAgICAgICAgICAgICAgcGFja2V0c1NlbnQ6IDAsXG4gICAgICAgICAgICAgICAgZnJhbWVzRW5jb2RlZDogMCxcbiAgICAgICAgICAgICAgICBuYWNrQ291bnQ6IDBcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH07XG5cbiAgICBjb25zdHJ1Y3Rvcihwcml2YXRlIHN0cmVhbTogU3RyZWFtKSB7IH1cblxuICAgIHB1YmxpYyBpc0VuYWJsZWQoKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiB0aGlzLndlYlJ0Y1N0YXRzRW5hYmxlZDtcbiAgICB9XG5cbiAgICBwdWJsaWMgaW5pdFdlYlJ0Y1N0YXRzKCk6IHZvaWQge1xuXG4gICAgICAgIGNvbnN0IGVsYXN0ZXN0SW5zdHJ1bWVudGF0aW9uID0gbG9jYWxTdG9yYWdlLmdldEl0ZW0oJ2VsYXN0ZXN0LWluc3RydW1lbnRhdGlvbicpO1xuXG4gICAgICAgIGlmIChlbGFzdGVzdEluc3RydW1lbnRhdGlvbikge1xuICAgICAgICAgICAgLy8gRWxhc1Rlc3QgaW5zdHJ1bWVudGF0aW9uIG9iamVjdCBmb3VuZCBpbiBsb2NhbCBzdG9yYWdlXG5cbiAgICAgICAgICAgIGNvbnNvbGUud2FybignV2ViUnRjIHN0YXRzIGVuYWJsZWQgZm9yIHN0cmVhbSAnICsgdGhpcy5zdHJlYW0uc3RyZWFtSWQgKyAnIG9mIGNvbm5lY3Rpb24gJyArIHRoaXMuc3RyZWFtLmNvbm5lY3Rpb24uY29ubmVjdGlvbklkKTtcblxuICAgICAgICAgICAgdGhpcy53ZWJSdGNTdGF0c0VuYWJsZWQgPSB0cnVlO1xuXG4gICAgICAgICAgICBjb25zdCBpbnN0cnVtZW50YXRpb24gPSBKU09OLnBhcnNlKGVsYXN0ZXN0SW5zdHJ1bWVudGF0aW9uKTtcbiAgICAgICAgICAgIHRoaXMuc3RhdHNJbnRlcnZhbCA9IGluc3RydW1lbnRhdGlvbi53ZWJydGMuaW50ZXJ2YWw7ICAvLyBJbnRlcnZhbCBpbiBzZWNvbmRzXG5cbiAgICAgICAgICAgIGNvbnNvbGUud2FybignbG9jYWxTdG9yYWdlIGl0ZW06ICcgKyBKU09OLnN0cmluZ2lmeShpbnN0cnVtZW50YXRpb24pKTtcblxuICAgICAgICAgICAgdGhpcy53ZWJSdGNTdGF0c0ludGVydmFsSWQgPSBzZXRJbnRlcnZhbCgoKSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5zZW5kU3RhdHNUb0h0dHBFbmRwb2ludChpbnN0cnVtZW50YXRpb24pO1xuICAgICAgICAgICAgfSwgdGhpcy5zdGF0c0ludGVydmFsICogMTAwMCk7XG5cbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnNvbGUuZGVidWcoJ1dlYlJ0YyBzdGF0cyBub3QgZW5hYmxlZCcpO1xuICAgIH1cblxuICAgIHB1YmxpYyBzdG9wV2ViUnRjU3RhdHMoKSB7XG4gICAgICAgIGlmICh0aGlzLndlYlJ0Y1N0YXRzRW5hYmxlZCkge1xuICAgICAgICAgICAgY2xlYXJJbnRlcnZhbCh0aGlzLndlYlJ0Y1N0YXRzSW50ZXJ2YWxJZCk7XG4gICAgICAgICAgICBjb25zb2xlLndhcm4oJ1dlYlJ0YyBzdGF0cyBzdG9wcGVkIGZvciBkaXNwb3NlZCBzdHJlYW0gJyArIHRoaXMuc3RyZWFtLnN0cmVhbUlkICsgJyBvZiBjb25uZWN0aW9uICcgKyB0aGlzLnN0cmVhbS5jb25uZWN0aW9uLmNvbm5lY3Rpb25JZCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwdWJsaWMgZ2V0U2VsZWN0ZWRJY2VDYW5kaWRhdGVJbmZvKCk6IFByb21pc2U8YW55PiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICB0aGlzLmdldFN0YXRzQWdub3N0aWModGhpcy5zdHJlYW0uZ2V0UlRDUGVlckNvbm5lY3Rpb24oKSxcbiAgICAgICAgICAgICAgICAoc3RhdHMpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKChwbGF0Zm9ybS5uYW1lIS5pbmRleE9mKCdDaHJvbWUnKSAhPT0gLTEpIHx8IChwbGF0Zm9ybS5uYW1lIS5pbmRleE9mKCdPcGVyYScpICE9PSAtMSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBsb2NhbENhbmRpZGF0ZUlkLCByZW1vdGVDYW5kaWRhdGVJZCwgZ29vZ0NhbmRpZGF0ZVBhaXI7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBsb2NhbENhbmRpZGF0ZXMgPSB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHJlbW90ZUNhbmRpZGF0ZXMgPSB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAoY29uc3Qga2V5IGluIHN0YXRzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3Qgc3RhdCA9IHN0YXRzW2tleV07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHN0YXQudHlwZSA9PT0gJ2xvY2FsY2FuZGlkYXRlJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsb2NhbENhbmRpZGF0ZXNbc3RhdC5pZF0gPSBzdGF0O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoc3RhdC50eXBlID09PSAncmVtb3RlY2FuZGlkYXRlJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZW1vdGVDYW5kaWRhdGVzW3N0YXQuaWRdID0gc3RhdDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHN0YXQudHlwZSA9PT0gJ2dvb2dDYW5kaWRhdGVQYWlyJyAmJiAoc3RhdC5nb29nQWN0aXZlQ29ubmVjdGlvbiA9PT0gJ3RydWUnKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnb29nQ2FuZGlkYXRlUGFpciA9IHN0YXQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxvY2FsQ2FuZGlkYXRlSWQgPSBzdGF0LmxvY2FsQ2FuZGlkYXRlSWQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlbW90ZUNhbmRpZGF0ZUlkID0gc3RhdC5yZW1vdGVDYW5kaWRhdGVJZDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBsZXQgZmluYWxMb2NhbENhbmRpZGF0ZSA9IGxvY2FsQ2FuZGlkYXRlc1tsb2NhbENhbmRpZGF0ZUlkXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghIWZpbmFsTG9jYWxDYW5kaWRhdGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBjYW5kTGlzdCA9IHRoaXMuc3RyZWFtLmdldExvY2FsSWNlQ2FuZGlkYXRlTGlzdCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGNhbmQgPSBjYW5kTGlzdC5maWx0ZXIoKGM6IFJUQ0ljZUNhbmRpZGF0ZSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gKCEhYy5jYW5kaWRhdGUgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuY2FuZGlkYXRlLmluZGV4T2YoZmluYWxMb2NhbENhbmRpZGF0ZS5pcEFkZHJlc3MpID49IDAgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuY2FuZGlkYXRlLmluZGV4T2YoZmluYWxMb2NhbENhbmRpZGF0ZS5wb3J0TnVtYmVyKSA+PSAwICYmXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjLmNhbmRpZGF0ZS5pbmRleE9mKGZpbmFsTG9jYWxDYW5kaWRhdGUucHJpb3JpdHkpID49IDApO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbmFsTG9jYWxDYW5kaWRhdGUucmF3ID0gISFjYW5kWzBdID8gY2FuZFswXS5jYW5kaWRhdGUgOiAnRVJST1I6IENhbm5vdCBmaW5kIGxvY2FsIGNhbmRpZGF0ZSBpbiBsaXN0IG9mIHNlbnQgSUNFIGNhbmRpZGF0ZXMnO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaW5hbExvY2FsQ2FuZGlkYXRlID0gJ0VSUk9SOiBObyBhY3RpdmUgbG9jYWwgSUNFIGNhbmRpZGF0ZS4gUHJvYmFibHkgSUNFLVRDUCBpcyBiZWluZyB1c2VkJztcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGZpbmFsUmVtb3RlQ2FuZGlkYXRlID0gcmVtb3RlQ2FuZGlkYXRlc1tyZW1vdGVDYW5kaWRhdGVJZF07XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoISFmaW5hbFJlbW90ZUNhbmRpZGF0ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGNhbmRMaXN0ID0gdGhpcy5zdHJlYW0uZ2V0UmVtb3RlSWNlQ2FuZGlkYXRlTGlzdCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGNhbmQgPSBjYW5kTGlzdC5maWx0ZXIoKGM6IFJUQ0ljZUNhbmRpZGF0ZSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gKCEhYy5jYW5kaWRhdGUgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuY2FuZGlkYXRlLmluZGV4T2YoZmluYWxSZW1vdGVDYW5kaWRhdGUuaXBBZGRyZXNzKSA+PSAwICYmXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjLmNhbmRpZGF0ZS5pbmRleE9mKGZpbmFsUmVtb3RlQ2FuZGlkYXRlLnBvcnROdW1iZXIpID49IDAgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuY2FuZGlkYXRlLmluZGV4T2YoZmluYWxSZW1vdGVDYW5kaWRhdGUucHJpb3JpdHkpID49IDApO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbmFsUmVtb3RlQ2FuZGlkYXRlLnJhdyA9ICEhY2FuZFswXSA/IGNhbmRbMF0uY2FuZGlkYXRlIDogJ0VSUk9SOiBDYW5ub3QgZmluZCByZW1vdGUgY2FuZGlkYXRlIGluIGxpc3Qgb2YgcmVjZWl2ZWQgSUNFIGNhbmRpZGF0ZXMnO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaW5hbFJlbW90ZUNhbmRpZGF0ZSA9ICdFUlJPUjogTm8gYWN0aXZlIHJlbW90ZSBJQ0UgY2FuZGlkYXRlLiBQcm9iYWJseSBJQ0UtVENQIGlzIGJlaW5nIHVzZWQnO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICByZXNvbHZlKHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBnb29nQ2FuZGlkYXRlUGFpcixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsb2NhbENhbmRpZGF0ZTogZmluYWxMb2NhbENhbmRpZGF0ZSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZW1vdGVDYW5kaWRhdGU6IGZpbmFsUmVtb3RlQ2FuZGlkYXRlXG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdCgnU2VsZWN0ZWQgSUNFIGNhbmRpZGF0ZSBpbmZvIG9ubHkgYXZhaWxhYmxlIGZvciBDaHJvbWUnKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgKGVycm9yKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIHByaXZhdGUgc2VuZFN0YXRzVG9IdHRwRW5kcG9pbnQoaW5zdHJ1bWVudGF0aW9uKTogdm9pZCB7XG5cbiAgICAgICAgY29uc3Qgc2VuZFBvc3QgPSAoanNvbikgPT4ge1xuICAgICAgICAgICAgY29uc3QgaHR0cDogWE1MSHR0cFJlcXVlc3QgPSBuZXcgWE1MSHR0cFJlcXVlc3QoKTtcbiAgICAgICAgICAgIGNvbnN0IHVybDogc3RyaW5nID0gaW5zdHJ1bWVudGF0aW9uLndlYnJ0Yy5odHRwRW5kcG9pbnQ7XG4gICAgICAgICAgICBodHRwLm9wZW4oJ1BPU1QnLCB1cmwsIHRydWUpO1xuXG4gICAgICAgICAgICBodHRwLnNldFJlcXVlc3RIZWFkZXIoJ0NvbnRlbnQtdHlwZScsICdhcHBsaWNhdGlvbi9qc29uJyk7XG5cbiAgICAgICAgICAgIGh0dHAub25yZWFkeXN0YXRlY2hhbmdlID0gKCkgPT4geyAvLyBDYWxsIGEgZnVuY3Rpb24gd2hlbiB0aGUgc3RhdGUgY2hhbmdlcy5cbiAgICAgICAgICAgICAgICBpZiAoaHR0cC5yZWFkeVN0YXRlID09PSA0ICYmIGh0dHAuc3RhdHVzID09PSAyMDApIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS5sb2coJ1dlYlJ0YyBzdGF0cyBzdWNjZXNzZnVsbHkgc2VudCB0byAnICsgdXJsICsgJyBmb3Igc3RyZWFtICcgKyB0aGlzLnN0cmVhbS5zdHJlYW1JZCArICcgb2YgY29ubmVjdGlvbiAnICsgdGhpcy5zdHJlYW0uY29ubmVjdGlvbi5jb25uZWN0aW9uSWQpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBodHRwLnNlbmQoanNvbik7XG4gICAgICAgIH07XG5cbiAgICAgICAgY29uc3QgZiA9IChzdGF0cykgPT4ge1xuXG4gICAgICAgICAgICBpZiAocGxhdGZvcm0ubmFtZSEuaW5kZXhPZignRmlyZWZveCcpICE9PSAtMSkge1xuICAgICAgICAgICAgICAgIHN0YXRzLmZvckVhY2goKHN0YXQpID0+IHtcblxuICAgICAgICAgICAgICAgICAgICBsZXQganNvbiA9IHt9O1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICgoc3RhdC50eXBlID09PSAnaW5ib3VuZC1ydHAnKSAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEF2b2lkIGZpcmVmb3ggZW1wdHkgb3V0Ym91bmQtcnRwIHN0YXRpc3RpY3NcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGF0Lm5hY2tDb3VudCAhPT0gbnVsbCAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0YXQuaXNSZW1vdGUgPT09IGZhbHNlICYmXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhdC5pZC5zdGFydHNXaXRoKCdpbmJvdW5kJykgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGF0LnJlbW90ZUlkLnN0YXJ0c1dpdGgoJ2luYm91bmQnKVxuICAgICAgICAgICAgICAgICAgICAgICAgKSkge1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBtZXRyaWNJZCA9ICd3ZWJydGNfaW5ib3VuZF8nICsgc3RhdC5tZWRpYVR5cGUgKyAnXycgKyBzdGF0LnNzcmM7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBqaXQgPSBzdGF0LmppdHRlciAqIDEwMDA7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG1ldHJpY3MgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnl0ZXNSZWNlaXZlZDogKHN0YXQuYnl0ZXNSZWNlaXZlZCAtIHRoaXMuc3RhdHMuaW5ib3VuZFtzdGF0Lm1lZGlhVHlwZV0uYnl0ZXNSZWNlaXZlZCkgLyB0aGlzLnN0YXRzSW50ZXJ2YWwsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaml0dGVyOiBqaXQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFja2V0c1JlY2VpdmVkOiAoc3RhdC5wYWNrZXRzUmVjZWl2ZWQgLSB0aGlzLnN0YXRzLmluYm91bmRbc3RhdC5tZWRpYVR5cGVdLnBhY2tldHNSZWNlaXZlZCkgLyB0aGlzLnN0YXRzSW50ZXJ2YWwsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFja2V0c0xvc3Q6IChzdGF0LnBhY2tldHNMb3N0IC0gdGhpcy5zdGF0cy5pbmJvdW5kW3N0YXQubWVkaWFUeXBlXS5wYWNrZXRzTG9zdCkgLyB0aGlzLnN0YXRzSW50ZXJ2YWxcbiAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB1bml0cyA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBieXRlc1JlY2VpdmVkOiAnYnl0ZXMnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGppdHRlcjogJ21zJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYWNrZXRzUmVjZWl2ZWQ6ICdwYWNrZXRzJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYWNrZXRzTG9zdDogJ3BhY2tldHMnXG4gICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHN0YXQubWVkaWFUeXBlID09PSAndmlkZW8nKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbWV0cmljc1snZnJhbWVzRGVjb2RlZCddID0gKHN0YXQuZnJhbWVzRGVjb2RlZCAtIHRoaXMuc3RhdHMuaW5ib3VuZC52aWRlby5mcmFtZXNEZWNvZGVkKSAvIHRoaXMuc3RhdHNJbnRlcnZhbDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXRyaWNzWyduYWNrQ291bnQnXSA9IChzdGF0Lm5hY2tDb3VudCAtIHRoaXMuc3RhdHMuaW5ib3VuZC52aWRlby5uYWNrQ291bnQpIC8gdGhpcy5zdGF0c0ludGVydmFsO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVuaXRzWydmcmFtZXNEZWNvZGVkJ10gPSAnZnJhbWVzJztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB1bml0c1snbmFja0NvdW50J10gPSAncGFja2V0cyc7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXRzLmluYm91bmQudmlkZW8uZnJhbWVzRGVjb2RlZCA9IHN0YXQuZnJhbWVzRGVjb2RlZDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXRzLmluYm91bmQudmlkZW8ubmFja0NvdW50ID0gc3RhdC5uYWNrQ291bnQ7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdHMuaW5ib3VuZFtzdGF0Lm1lZGlhVHlwZV0uYnl0ZXNSZWNlaXZlZCA9IHN0YXQuYnl0ZXNSZWNlaXZlZDtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdHMuaW5ib3VuZFtzdGF0Lm1lZGlhVHlwZV0ucGFja2V0c1JlY2VpdmVkID0gc3RhdC5wYWNrZXRzUmVjZWl2ZWQ7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXRzLmluYm91bmRbc3RhdC5tZWRpYVR5cGVdLnBhY2tldHNMb3N0ID0gc3RhdC5wYWNrZXRzTG9zdDtcblxuICAgICAgICAgICAgICAgICAgICAgICAganNvbiA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAnQHRpbWVzdGFtcCc6IG5ldyBEYXRlKHN0YXQudGltZXN0YW1wKS50b0lTT1N0cmluZygpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICdleGVjJzogaW5zdHJ1bWVudGF0aW9uLmV4ZWMsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJ2NvbXBvbmVudCc6IGluc3RydW1lbnRhdGlvbi5jb21wb25lbnQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJ3N0cmVhbSc6ICd3ZWJSdGMnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICd0eXBlJzogbWV0cmljSWQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJ3N0cmVhbV90eXBlJzogJ2NvbXBvc2VkX21ldHJpY3MnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICd1bml0cyc6IHVuaXRzXG4gICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAganNvblttZXRyaWNJZF0gPSBtZXRyaWNzO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBzZW5kUG9zdChKU09OLnN0cmluZ2lmeShqc29uKSk7XG5cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICgoc3RhdC50eXBlID09PSAnb3V0Ym91bmQtcnRwJykgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgIChcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBBdm9pZCBmaXJlZm94IGVtcHR5IGluYm91bmQtcnRwIHN0YXRpc3RpY3NcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGF0LmlzUmVtb3RlID09PSBmYWxzZSAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0YXQuaWQudG9Mb3dlckNhc2UoKS5pbmNsdWRlcygnb3V0Ym91bmQnKVxuICAgICAgICAgICAgICAgICAgICAgICAgKSkge1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBtZXRyaWNJZCA9ICd3ZWJydGNfb3V0Ym91bmRfJyArIHN0YXQubWVkaWFUeXBlICsgJ18nICsgc3RhdC5zc3JjO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBtZXRyaWNzID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ5dGVzU2VudDogKHN0YXQuYnl0ZXNTZW50IC0gdGhpcy5zdGF0cy5vdXRib3VuZFtzdGF0Lm1lZGlhVHlwZV0uYnl0ZXNTZW50KSAvIHRoaXMuc3RhdHNJbnRlcnZhbCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYWNrZXRzU2VudDogKHN0YXQucGFja2V0c1NlbnQgLSB0aGlzLnN0YXRzLm91dGJvdW5kW3N0YXQubWVkaWFUeXBlXS5wYWNrZXRzU2VudCkgLyB0aGlzLnN0YXRzSW50ZXJ2YWxcbiAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB1bml0cyA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBieXRlc1NlbnQ6ICdieXRlcycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFja2V0c1NlbnQ6ICdwYWNrZXRzJ1xuICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzdGF0Lm1lZGlhVHlwZSA9PT0gJ3ZpZGVvJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1ldHJpY3NbJ2ZyYW1lc0VuY29kZWQnXSA9IChzdGF0LmZyYW1lc0VuY29kZWQgLSB0aGlzLnN0YXRzLm91dGJvdW5kLnZpZGVvLmZyYW1lc0VuY29kZWQpIC8gdGhpcy5zdGF0c0ludGVydmFsO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVuaXRzWydmcmFtZXNFbmNvZGVkJ10gPSAnZnJhbWVzJztcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdHMub3V0Ym91bmQudmlkZW8uZnJhbWVzRW5jb2RlZCA9IHN0YXQuZnJhbWVzRW5jb2RlZDtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0cy5vdXRib3VuZFtzdGF0Lm1lZGlhVHlwZV0uYnl0ZXNTZW50ID0gc3RhdC5ieXRlc1NlbnQ7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXRzLm91dGJvdW5kW3N0YXQubWVkaWFUeXBlXS5wYWNrZXRzU2VudCA9IHN0YXQucGFja2V0c1NlbnQ7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGpzb24gPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJ0B0aW1lc3RhbXAnOiBuZXcgRGF0ZShzdGF0LnRpbWVzdGFtcCkudG9JU09TdHJpbmcoKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAnZXhlYyc6IGluc3RydW1lbnRhdGlvbi5leGVjLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICdjb21wb25lbnQnOiBpbnN0cnVtZW50YXRpb24uY29tcG9uZW50LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICdzdHJlYW0nOiAnd2ViUnRjJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAndHlwZSc6IG1ldHJpY0lkLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICdzdHJlYW1fdHlwZSc6ICdjb21wb3NlZF9tZXRyaWNzJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAndW5pdHMnOiB1bml0c1xuICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGpzb25bbWV0cmljSWRdID0gbWV0cmljcztcblxuICAgICAgICAgICAgICAgICAgICAgICAgc2VuZFBvc3QoSlNPTi5zdHJpbmdpZnkoanNvbikpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKChwbGF0Zm9ybS5uYW1lIS5pbmRleE9mKCdDaHJvbWUnKSAhPT0gLTEpIHx8IChwbGF0Zm9ybS5uYW1lIS5pbmRleE9mKCdPcGVyYScpICE9PSAtMSkpIHtcbiAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IGtleSBvZiBPYmplY3Qua2V5cyhzdGF0cykpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3Qgc3RhdCA9IHN0YXRzW2tleV07XG4gICAgICAgICAgICAgICAgICAgIGlmIChzdGF0LnR5cGUgPT09ICdzc3JjJykge1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBsZXQganNvbiA9IHt9O1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoJ2J5dGVzUmVjZWl2ZWQnIGluIHN0YXQgJiYgKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIChzdGF0Lm1lZGlhVHlwZSA9PT0gJ2F1ZGlvJyAmJiAnYXVkaW9PdXRwdXRMZXZlbCcgaW4gc3RhdCkgfHxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAoc3RhdC5tZWRpYVR5cGUgPT09ICd2aWRlbycgJiYgJ3FwU3VtJyBpbiBzdGF0KVxuICAgICAgICAgICAgICAgICAgICAgICAgKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGluYm91bmQtcnRwXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgbWV0cmljSWQgPSAnd2VicnRjX2luYm91bmRfJyArIHN0YXQubWVkaWFUeXBlICsgJ18nICsgc3RhdC5zc3JjO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgbWV0cmljcyA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnl0ZXNSZWNlaXZlZDogKHN0YXQuYnl0ZXNSZWNlaXZlZCAtIHRoaXMuc3RhdHMuaW5ib3VuZFtzdGF0Lm1lZGlhVHlwZV0uYnl0ZXNSZWNlaXZlZCkgLyB0aGlzLnN0YXRzSW50ZXJ2YWwsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGppdHRlcjogc3RhdC5nb29nSml0dGVyQnVmZmVyTXMsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhY2tldHNSZWNlaXZlZDogKHN0YXQucGFja2V0c1JlY2VpdmVkIC0gdGhpcy5zdGF0cy5pbmJvdW5kW3N0YXQubWVkaWFUeXBlXS5wYWNrZXRzUmVjZWl2ZWQpIC8gdGhpcy5zdGF0c0ludGVydmFsLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYWNrZXRzTG9zdDogKHN0YXQucGFja2V0c0xvc3QgLSB0aGlzLnN0YXRzLmluYm91bmRbc3RhdC5tZWRpYVR5cGVdLnBhY2tldHNMb3N0KSAvIHRoaXMuc3RhdHNJbnRlcnZhbFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgdW5pdHMgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ5dGVzUmVjZWl2ZWQ6ICdieXRlcycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGppdHRlcjogJ21zJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFja2V0c1JlY2VpdmVkOiAncGFja2V0cycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhY2tldHNMb3N0OiAncGFja2V0cydcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzdGF0Lm1lZGlhVHlwZSA9PT0gJ3ZpZGVvJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXRyaWNzWydmcmFtZXNEZWNvZGVkJ10gPSAoc3RhdC5mcmFtZXNEZWNvZGVkIC0gdGhpcy5zdGF0cy5pbmJvdW5kLnZpZGVvLmZyYW1lc0RlY29kZWQpIC8gdGhpcy5zdGF0c0ludGVydmFsO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXRyaWNzWyduYWNrQ291bnQnXSA9IChzdGF0Lmdvb2dOYWNrc1NlbnQgLSB0aGlzLnN0YXRzLmluYm91bmQudmlkZW8ubmFja0NvdW50KSAvIHRoaXMuc3RhdHNJbnRlcnZhbDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdW5pdHNbJ2ZyYW1lc0RlY29kZWQnXSA9ICdmcmFtZXMnO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1bml0c1snbmFja0NvdW50J10gPSAncGFja2V0cyc7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0cy5pbmJvdW5kLnZpZGVvLmZyYW1lc0RlY29kZWQgPSBzdGF0LmZyYW1lc0RlY29kZWQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdHMuaW5ib3VuZC52aWRlby5uYWNrQ291bnQgPSBzdGF0Lmdvb2dOYWNrc1NlbnQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0cy5pbmJvdW5kW3N0YXQubWVkaWFUeXBlXS5ieXRlc1JlY2VpdmVkID0gc3RhdC5ieXRlc1JlY2VpdmVkO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdHMuaW5ib3VuZFtzdGF0Lm1lZGlhVHlwZV0ucGFja2V0c1JlY2VpdmVkID0gc3RhdC5wYWNrZXRzUmVjZWl2ZWQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0cy5pbmJvdW5kW3N0YXQubWVkaWFUeXBlXS5wYWNrZXRzTG9zdCA9IHN0YXQucGFja2V0c0xvc3Q7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBqc29uID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnQHRpbWVzdGFtcCc6IG5ldyBEYXRlKHN0YXQudGltZXN0YW1wKS50b0lTT1N0cmluZygpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnZXhlYyc6IGluc3RydW1lbnRhdGlvbi5leGVjLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnY29tcG9uZW50JzogaW5zdHJ1bWVudGF0aW9uLmNvbXBvbmVudCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ3N0cmVhbSc6ICd3ZWJSdGMnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAndHlwZSc6IG1ldHJpY0lkLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnc3RyZWFtX3R5cGUnOiAnY29tcG9zZWRfbWV0cmljcycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICd1bml0cyc6IHVuaXRzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBqc29uW21ldHJpY0lkXSA9IG1ldHJpY3M7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZW5kUG9zdChKU09OLnN0cmluZ2lmeShqc29uKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKCdieXRlc1NlbnQnIGluIHN0YXQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBvdXRib3VuZC1ydHBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBtZXRyaWNJZCA9ICd3ZWJydGNfb3V0Ym91bmRfJyArIHN0YXQubWVkaWFUeXBlICsgJ18nICsgc3RhdC5zc3JjO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgbWV0cmljcyA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnl0ZXNTZW50OiAoc3RhdC5ieXRlc1NlbnQgLSB0aGlzLnN0YXRzLm91dGJvdW5kW3N0YXQubWVkaWFUeXBlXS5ieXRlc1NlbnQpIC8gdGhpcy5zdGF0c0ludGVydmFsLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYWNrZXRzU2VudDogKHN0YXQucGFja2V0c1NlbnQgLSB0aGlzLnN0YXRzLm91dGJvdW5kW3N0YXQubWVkaWFUeXBlXS5wYWNrZXRzU2VudCkgLyB0aGlzLnN0YXRzSW50ZXJ2YWxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHVuaXRzID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBieXRlc1NlbnQ6ICdieXRlcycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhY2tldHNTZW50OiAncGFja2V0cydcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzdGF0Lm1lZGlhVHlwZSA9PT0gJ3ZpZGVvJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXRyaWNzWydmcmFtZXNFbmNvZGVkJ10gPSAoc3RhdC5mcmFtZXNFbmNvZGVkIC0gdGhpcy5zdGF0cy5vdXRib3VuZC52aWRlby5mcmFtZXNFbmNvZGVkKSAvIHRoaXMuc3RhdHNJbnRlcnZhbDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdW5pdHNbJ2ZyYW1lc0VuY29kZWQnXSA9ICdmcmFtZXMnO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdHMub3V0Ym91bmQudmlkZW8uZnJhbWVzRW5jb2RlZCA9IHN0YXQuZnJhbWVzRW5jb2RlZDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXRzLm91dGJvdW5kW3N0YXQubWVkaWFUeXBlXS5ieXRlc1NlbnQgPSBzdGF0LmJ5dGVzU2VudDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXRzLm91dGJvdW5kW3N0YXQubWVkaWFUeXBlXS5wYWNrZXRzU2VudCA9IHN0YXQucGFja2V0c1NlbnQ7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBqc29uID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnQHRpbWVzdGFtcCc6IG5ldyBEYXRlKHN0YXQudGltZXN0YW1wKS50b0lTT1N0cmluZygpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnZXhlYyc6IGluc3RydW1lbnRhdGlvbi5leGVjLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnY29tcG9uZW50JzogaW5zdHJ1bWVudGF0aW9uLmNvbXBvbmVudCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ3N0cmVhbSc6ICd3ZWJSdGMnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAndHlwZSc6IG1ldHJpY0lkLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnc3RyZWFtX3R5cGUnOiAnY29tcG9zZWRfbWV0cmljcycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICd1bml0cyc6IHVuaXRzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBqc29uW21ldHJpY0lkXSA9IG1ldHJpY3M7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZW5kUG9zdChKU09OLnN0cmluZ2lmeShqc29uKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG5cbiAgICAgICAgdGhpcy5nZXRTdGF0c0Fnbm9zdGljKHRoaXMuc3RyZWFtLmdldFJUQ1BlZXJDb25uZWN0aW9uKCksIGYsIChlcnJvcikgPT4geyBjb25zb2xlLmxvZyhlcnJvcik7IH0pO1xuICAgIH1cblxuICAgIHByaXZhdGUgc3RhbmRhcmRpemVSZXBvcnQocmVzcG9uc2UpIHtcbiAgICAgICAgY29uc29sZS5sb2cocmVzcG9uc2UpO1xuICAgICAgICBjb25zdCBzdGFuZGFyZFJlcG9ydCA9IHt9O1xuXG4gICAgICAgIGlmIChwbGF0Zm9ybS5uYW1lIS5pbmRleE9mKCdGaXJlZm94JykgIT09IC0xKSB7XG4gICAgICAgICAgICBPYmplY3Qua2V5cyhyZXNwb25zZSkuZm9yRWFjaChrZXkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKHJlc3BvbnNlW2tleV0pO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICByZXR1cm4gcmVzcG9uc2U7XG4gICAgICAgIH1cblxuICAgICAgICByZXNwb25zZS5yZXN1bHQoKS5mb3JFYWNoKHJlcG9ydCA9PiB7XG4gICAgICAgICAgICBjb25zdCBzdGFuZGFyZFN0YXRzID0ge1xuICAgICAgICAgICAgICAgIGlkOiByZXBvcnQuaWQsXG4gICAgICAgICAgICAgICAgdGltZXN0YW1wOiByZXBvcnQudGltZXN0YW1wLFxuICAgICAgICAgICAgICAgIHR5cGU6IHJlcG9ydC50eXBlXG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgcmVwb3J0Lm5hbWVzKCkuZm9yRWFjaCgobmFtZSkgPT4ge1xuICAgICAgICAgICAgICAgIHN0YW5kYXJkU3RhdHNbbmFtZV0gPSByZXBvcnQuc3RhdChuYW1lKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgc3RhbmRhcmRSZXBvcnRbc3RhbmRhcmRTdGF0cy5pZF0gPSBzdGFuZGFyZFN0YXRzO1xuICAgICAgICB9KTtcblxuICAgICAgICByZXR1cm4gc3RhbmRhcmRSZXBvcnQ7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBnZXRTdGF0c0Fnbm9zdGljKHBjLCBzdWNjZXNzQ2IsIGZhaWx1cmVDYikge1xuICAgICAgICBpZiAocGxhdGZvcm0ubmFtZSEuaW5kZXhPZignRmlyZWZveCcpICE9PSAtMSkge1xuICAgICAgICAgICAgLy8gZ2V0U3RhdHMgdGFrZXMgYXJncyBpbiBkaWZmZXJlbnQgb3JkZXIgaW4gQ2hyb21lIGFuZCBGaXJlZm94XG4gICAgICAgICAgICByZXR1cm4gcGMuZ2V0U3RhdHMobnVsbCkudGhlbihyZXNwb25zZSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3QgcmVwb3J0ID0gdGhpcy5zdGFuZGFyZGl6ZVJlcG9ydChyZXNwb25zZSk7XG4gICAgICAgICAgICAgICAgc3VjY2Vzc0NiKHJlcG9ydCk7XG4gICAgICAgICAgICB9KS5jYXRjaChmYWlsdXJlQ2IpO1xuICAgICAgICB9IGVsc2UgaWYgKChwbGF0Zm9ybS5uYW1lIS5pbmRleE9mKCdDaHJvbWUnKSAhPT0gLTEpIHx8IChwbGF0Zm9ybS5uYW1lIS5pbmRleE9mKCdPcGVyYScpICE9PSAtMSkpIHtcbiAgICAgICAgICAgIC8vIEluIENocm9tZSwgdGhlIGZpcnN0IHR3byBhcmd1bWVudHMgYXJlIHJldmVyc2VkXG4gICAgICAgICAgICByZXR1cm4gcGMuZ2V0U3RhdHMoKHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3QgcmVwb3J0ID0gdGhpcy5zdGFuZGFyZGl6ZVJlcG9ydChyZXNwb25zZSk7XG4gICAgICAgICAgICAgICAgc3VjY2Vzc0NiKHJlcG9ydCk7XG4gICAgICAgICAgICB9LCBudWxsLCBmYWlsdXJlQ2IpO1xuICAgICAgICB9XG4gICAgfVxuXG59Il19
diff --git a/openvidu-insecure-js/web/openvidu-browser-2.4.0.js b/openvidu-insecure-js/web/openvidu-browser-2.4.0.js
new file mode 100644
index 000000000..61298c941
--- /dev/null
+++ b/openvidu-insecure-js/web/openvidu-browser-2.4.0.js
@@ -0,0 +1,7696 @@
+(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 1)
+ er = arguments[1];
+ if (er instanceof Error) {
+ throw er; // Unhandled 'error' event
+ } else {
+ // At least give some kind of context to the user
+ var err = new Error('Unhandled "error" event. (' + er + ')');
+ err.context = er;
+ throw err;
+ }
+ return false;
+ }
+
+ handler = events[type];
+
+ if (!handler)
+ return false;
+
+ var isFn = typeof handler === 'function';
+ len = arguments.length;
+ switch (len) {
+ // fast cases
+ case 1:
+ emitNone(handler, isFn, this);
+ break;
+ case 2:
+ emitOne(handler, isFn, this, arguments[1]);
+ break;
+ case 3:
+ emitTwo(handler, isFn, this, arguments[1], arguments[2]);
+ break;
+ case 4:
+ emitThree(handler, isFn, this, arguments[1], arguments[2], arguments[3]);
+ break;
+ // slower
+ default:
+ args = new Array(len - 1);
+ for (i = 1; i < len; i++)
+ args[i - 1] = arguments[i];
+ emitMany(handler, isFn, this, args);
+ }
+
+ return true;
+};
+
+function _addListener(target, type, listener, prepend) {
+ var m;
+ var events;
+ var existing;
+
+ if (typeof listener !== 'function')
+ throw new TypeError('"listener" argument must be a function');
+
+ events = target._events;
+ if (!events) {
+ events = target._events = objectCreate(null);
+ target._eventsCount = 0;
+ } else {
+ // To avoid recursion in the case that type === "newListener"! Before
+ // adding it to the listeners, first emit "newListener".
+ if (events.newListener) {
+ target.emit('newListener', type,
+ listener.listener ? listener.listener : listener);
+
+ // Re-assign `events` because a newListener handler could have caused the
+ // this._events to be assigned to a new object
+ events = target._events;
+ }
+ existing = events[type];
+ }
+
+ if (!existing) {
+ // Optimize the case of one listener. Don't need the extra array object.
+ existing = events[type] = listener;
+ ++target._eventsCount;
+ } else {
+ if (typeof existing === 'function') {
+ // Adding the second element, need to change to array.
+ existing = events[type] =
+ prepend ? [listener, existing] : [existing, listener];
+ } else {
+ // If we've already got an array, just append.
+ if (prepend) {
+ existing.unshift(listener);
+ } else {
+ existing.push(listener);
+ }
+ }
+
+ // Check for listener leak
+ if (!existing.warned) {
+ m = $getMaxListeners(target);
+ if (m && m > 0 && existing.length > m) {
+ existing.warned = true;
+ var w = new Error('Possible EventEmitter memory leak detected. ' +
+ existing.length + ' "' + String(type) + '" listeners ' +
+ 'added. Use emitter.setMaxListeners() to ' +
+ 'increase limit.');
+ w.name = 'MaxListenersExceededWarning';
+ w.emitter = target;
+ w.type = type;
+ w.count = existing.length;
+ if (typeof console === 'object' && console.warn) {
+ console.warn('%s: %s', w.name, w.message);
+ }
+ }
+ }
+ }
+
+ return target;
+}
+
+EventEmitter.prototype.addListener = function addListener(type, listener) {
+ return _addListener(this, type, listener, false);
+};
+
+EventEmitter.prototype.on = EventEmitter.prototype.addListener;
+
+EventEmitter.prototype.prependListener =
+ function prependListener(type, listener) {
+ return _addListener(this, type, listener, true);
+ };
+
+function onceWrapper() {
+ if (!this.fired) {
+ this.target.removeListener(this.type, this.wrapFn);
+ this.fired = true;
+ switch (arguments.length) {
+ case 0:
+ return this.listener.call(this.target);
+ case 1:
+ return this.listener.call(this.target, arguments[0]);
+ case 2:
+ return this.listener.call(this.target, arguments[0], arguments[1]);
+ case 3:
+ return this.listener.call(this.target, arguments[0], arguments[1],
+ arguments[2]);
+ default:
+ var args = new Array(arguments.length);
+ for (var i = 0; i < args.length; ++i)
+ args[i] = arguments[i];
+ this.listener.apply(this.target, args);
+ }
+ }
+}
+
+function _onceWrap(target, type, listener) {
+ var state = { fired: false, wrapFn: undefined, target: target, type: type, listener: listener };
+ var wrapped = bind.call(onceWrapper, state);
+ wrapped.listener = listener;
+ state.wrapFn = wrapped;
+ return wrapped;
+}
+
+EventEmitter.prototype.once = function once(type, listener) {
+ if (typeof listener !== 'function')
+ throw new TypeError('"listener" argument must be a function');
+ this.on(type, _onceWrap(this, type, listener));
+ return this;
+};
+
+EventEmitter.prototype.prependOnceListener =
+ function prependOnceListener(type, listener) {
+ if (typeof listener !== 'function')
+ throw new TypeError('"listener" argument must be a function');
+ this.prependListener(type, _onceWrap(this, type, listener));
+ return this;
+ };
+
+// Emits a 'removeListener' event if and only if the listener was removed.
+EventEmitter.prototype.removeListener =
+ function removeListener(type, listener) {
+ var list, events, position, i, originalListener;
+
+ if (typeof listener !== 'function')
+ throw new TypeError('"listener" argument must be a function');
+
+ events = this._events;
+ if (!events)
+ return this;
+
+ list = events[type];
+ if (!list)
+ return this;
+
+ if (list === listener || list.listener === listener) {
+ if (--this._eventsCount === 0)
+ this._events = objectCreate(null);
+ else {
+ delete events[type];
+ if (events.removeListener)
+ this.emit('removeListener', type, list.listener || listener);
+ }
+ } else if (typeof list !== 'function') {
+ position = -1;
+
+ for (i = list.length - 1; i >= 0; i--) {
+ if (list[i] === listener || list[i].listener === listener) {
+ originalListener = list[i].listener;
+ position = i;
+ break;
+ }
+ }
+
+ if (position < 0)
+ return this;
+
+ if (position === 0)
+ list.shift();
+ else
+ spliceOne(list, position);
+
+ if (list.length === 1)
+ events[type] = list[0];
+
+ if (events.removeListener)
+ this.emit('removeListener', type, originalListener || listener);
+ }
+
+ return this;
+ };
+
+EventEmitter.prototype.removeAllListeners =
+ function removeAllListeners(type) {
+ var listeners, events, i;
+
+ events = this._events;
+ if (!events)
+ return this;
+
+ // not listening for removeListener, no need to emit
+ if (!events.removeListener) {
+ if (arguments.length === 0) {
+ this._events = objectCreate(null);
+ this._eventsCount = 0;
+ } else if (events[type]) {
+ if (--this._eventsCount === 0)
+ this._events = objectCreate(null);
+ else
+ delete events[type];
+ }
+ return this;
+ }
+
+ // emit removeListener for all listeners on all events
+ if (arguments.length === 0) {
+ var keys = objectKeys(events);
+ var key;
+ for (i = 0; i < keys.length; ++i) {
+ key = keys[i];
+ if (key === 'removeListener') continue;
+ this.removeAllListeners(key);
+ }
+ this.removeAllListeners('removeListener');
+ this._events = objectCreate(null);
+ this._eventsCount = 0;
+ return this;
+ }
+
+ listeners = events[type];
+
+ if (typeof listeners === 'function') {
+ this.removeListener(type, listeners);
+ } else if (listeners) {
+ // LIFO order
+ for (i = listeners.length - 1; i >= 0; i--) {
+ this.removeListener(type, listeners[i]);
+ }
+ }
+
+ return this;
+ };
+
+function _listeners(target, type, unwrap) {
+ var events = target._events;
+
+ if (!events)
+ return [];
+
+ var evlistener = events[type];
+ if (!evlistener)
+ return [];
+
+ if (typeof evlistener === 'function')
+ return unwrap ? [evlistener.listener || evlistener] : [evlistener];
+
+ return unwrap ? unwrapListeners(evlistener) : arrayClone(evlistener, evlistener.length);
+}
+
+EventEmitter.prototype.listeners = function listeners(type) {
+ return _listeners(this, type, true);
+};
+
+EventEmitter.prototype.rawListeners = function rawListeners(type) {
+ return _listeners(this, type, false);
+};
+
+EventEmitter.listenerCount = function(emitter, type) {
+ if (typeof emitter.listenerCount === 'function') {
+ return emitter.listenerCount(type);
+ } else {
+ return listenerCount.call(emitter, type);
+ }
+};
+
+EventEmitter.prototype.listenerCount = listenerCount;
+function listenerCount(type) {
+ var events = this._events;
+
+ if (events) {
+ var evlistener = events[type];
+
+ if (typeof evlistener === 'function') {
+ return 1;
+ } else if (evlistener) {
+ return evlistener.length;
+ }
+ }
+
+ return 0;
+}
+
+EventEmitter.prototype.eventNames = function eventNames() {
+ return this._eventsCount > 0 ? Reflect.ownKeys(this._events) : [];
+};
+
+// About 1.5x faster than the two-arg version of Array#splice().
+function spliceOne(list, index) {
+ for (var i = index, k = i + 1, n = list.length; k < n; i += 1, k += 1)
+ list[i] = list[k];
+ list.pop();
+}
+
+function arrayClone(arr, n) {
+ var copy = new Array(n);
+ for (var i = 0; i < n; ++i)
+ copy[i] = arr[i];
+ return copy;
+}
+
+function unwrapListeners(arr) {
+ var ret = new Array(arr.length);
+ for (var i = 0; i < ret.length; ++i) {
+ ret[i] = arr[i].listener || arr[i];
+ }
+ return ret;
+}
+
+function objectCreatePolyfill(proto) {
+ var F = function() {};
+ F.prototype = proto;
+ return new F;
+}
+function objectKeysPolyfill(obj) {
+ var keys = [];
+ for (var k in obj) if (Object.prototype.hasOwnProperty.call(obj, k)) {
+ keys.push(k);
+ }
+ return k;
+}
+function functionBindPolyfill(context) {
+ var fn = this;
+ return function () {
+ return fn.apply(context, arguments);
+ };
+}
+
+},{}],2:[function(require,module,exports){
+/* jshint node: true */
+'use strict';
+
+var normalice = require('normalice');
+
+/**
+ # freeice
+
+ The `freeice` module is a simple way of getting random STUN or TURN server
+ for your WebRTC application. The list of servers (just STUN at this stage)
+ were sourced from this [gist](https://gist.github.com/zziuni/3741933).
+
+ ## Example Use
+
+ The following demonstrates how you can use `freeice` with
+ [rtc-quickconnect](https://github.com/rtc-io/rtc-quickconnect):
+
+ <<< examples/quickconnect.js
+
+ As the `freeice` module generates ice servers in a list compliant with the
+ WebRTC spec you will be able to use it with raw `RTCPeerConnection`
+ constructors and other WebRTC libraries.
+
+ ## Hey, don't use my STUN/TURN server!
+
+ If for some reason your free STUN or TURN server ends up in the
+ list of servers ([stun](https://github.com/DamonOehlman/freeice/blob/master/stun.json) or
+ [turn](https://github.com/DamonOehlman/freeice/blob/master/turn.json))
+ that is used in this module, you can feel
+ free to open an issue on this repository and those servers will be removed
+ within 24 hours (or sooner). This is the quickest and probably the most
+ polite way to have something removed (and provides us some visibility
+ if someone opens a pull request requesting that a server is added).
+
+ ## Please add my server!
+
+ If you have a server that you wish to add to the list, that's awesome! I'm
+ sure I speak on behalf of a whole pile of WebRTC developers who say thanks.
+ To get it into the list, feel free to either open a pull request or if you
+ find that process a bit daunting then just create an issue requesting
+ the addition of the server (make sure you provide all the details, and if
+ you have a Terms of Service then including that in the PR/issue would be
+ awesome).
+
+ ## I know of a free server, can I add it?
+
+ Sure, if you do your homework and make sure it is ok to use (I'm currently
+ in the process of reviewing the terms of those STUN servers included from
+ the original list). If it's ok to go, then please see the previous entry
+ for how to add it.
+
+ ## Current List of Servers
+
+ * current as at the time of last `README.md` file generation
+
+ ### STUN
+
+ <<< stun.json
+
+ ### TURN
+
+ <<< turn.json
+
+**/
+
+var freeice = module.exports = function(opts) {
+ // if a list of servers has been provided, then use it instead of defaults
+ var servers = {
+ stun: (opts || {}).stun || require('./stun.json'),
+ turn: (opts || {}).turn || require('./turn.json')
+ };
+
+ var stunCount = (opts || {}).stunCount || 2;
+ var turnCount = (opts || {}).turnCount || 0;
+ var selected;
+
+ function getServers(type, count) {
+ var out = [];
+ var input = [].concat(servers[type]);
+ var idx;
+
+ while (input.length && out.length < count) {
+ idx = (Math.random() * input.length) | 0;
+ out = out.concat(input.splice(idx, 1));
+ }
+
+ return out.map(function(url) {
+ //If it's a not a string, don't try to "normalice" it otherwise using type:url will screw it up
+ if ((typeof url !== 'string') && (! (url instanceof String))) {
+ return url;
+ } else {
+ return normalice(type + ':' + url);
+ }
+ });
+ }
+
+ // add stun servers
+ selected = [].concat(getServers('stun', stunCount));
+
+ if (turnCount) {
+ selected = selected.concat(getServers('turn', turnCount));
+ }
+
+ return selected;
+};
+
+},{"./stun.json":3,"./turn.json":4,"normalice":7}],3:[function(require,module,exports){
+module.exports=[
+ "stun.l.google.com:19302",
+ "stun1.l.google.com:19302",
+ "stun2.l.google.com:19302",
+ "stun3.l.google.com:19302",
+ "stun4.l.google.com:19302",
+ "stun.ekiga.net",
+ "stun.ideasip.com",
+ "stun.schlund.de",
+ "stun.stunprotocol.org:3478",
+ "stun.voiparound.com",
+ "stun.voipbuster.com",
+ "stun.voipstunt.com",
+ "stun.voxgratia.org",
+ "stun.services.mozilla.com"
+]
+
+},{}],4:[function(require,module,exports){
+module.exports=[]
+
+},{}],5:[function(require,module,exports){
+var WildEmitter = require('wildemitter');
+
+function getMaxVolume (analyser, fftBins) {
+ var maxVolume = -Infinity;
+ analyser.getFloatFrequencyData(fftBins);
+
+ for(var i=4, ii=fftBins.length; i < ii; i++) {
+ if (fftBins[i] > maxVolume && fftBins[i] < 0) {
+ maxVolume = fftBins[i];
+ }
+ };
+
+ return maxVolume;
+}
+
+
+var audioContextType;
+if (typeof window !== 'undefined') {
+ audioContextType = window.AudioContext || window.webkitAudioContext;
+}
+// use a single audio context due to hardware limits
+var audioContext = null;
+module.exports = function(stream, options) {
+ var harker = new WildEmitter();
+
+
+ // make it not break in non-supported browsers
+ if (!audioContextType) return harker;
+
+ //Config
+ var options = options || {},
+ smoothing = (options.smoothing || 0.1),
+ interval = (options.interval || 50),
+ threshold = options.threshold,
+ play = options.play,
+ history = options.history || 10,
+ running = true;
+
+ //Setup Audio Context
+ if (!audioContext) {
+ audioContext = new audioContextType();
+ }
+ var sourceNode, fftBins, analyser;
+
+ analyser = audioContext.createAnalyser();
+ analyser.fftSize = 512;
+ analyser.smoothingTimeConstant = smoothing;
+ fftBins = new Float32Array(analyser.frequencyBinCount);
+
+ if (stream.jquery) stream = stream[0];
+ if (stream instanceof HTMLAudioElement || stream instanceof HTMLVideoElement) {
+ //Audio Tag
+ sourceNode = audioContext.createMediaElementSource(stream);
+ if (typeof play === 'undefined') play = true;
+ threshold = threshold || -50;
+ } else {
+ //WebRTC Stream
+ sourceNode = audioContext.createMediaStreamSource(stream);
+ threshold = threshold || -50;
+ }
+
+ sourceNode.connect(analyser);
+ if (play) analyser.connect(audioContext.destination);
+
+ harker.speaking = false;
+
+ harker.suspend = function() {
+ audioContext.suspend();
+ }
+ harker.resume = function() {
+ audioContext.resume();
+ }
+ Object.defineProperty(harker, 'state', { get: function() {
+ return audioContext.state;
+ }});
+ audioContext.onstatechange = function() {
+ harker.emit('state_change', audioContext.state);
+ }
+
+ harker.setThreshold = function(t) {
+ threshold = t;
+ };
+
+ harker.setInterval = function(i) {
+ interval = i;
+ };
+
+ harker.stop = function() {
+ running = false;
+ harker.emit('volume_change', -100, threshold);
+ if (harker.speaking) {
+ harker.speaking = false;
+ harker.emit('stopped_speaking');
+ }
+ analyser.disconnect();
+ sourceNode.disconnect();
+ };
+ harker.speakingHistory = [];
+ for (var i = 0; i < history; i++) {
+ harker.speakingHistory.push(0);
+ }
+
+ // Poll the analyser node to determine if speaking
+ // and emit events if changed
+ var looper = function() {
+ setTimeout(function() {
+
+ //check if stop has been called
+ if(!running) {
+ return;
+ }
+
+ var currentVolume = getMaxVolume(analyser, fftBins);
+
+ harker.emit('volume_change', currentVolume, threshold);
+
+ var history = 0;
+ if (currentVolume > threshold && !harker.speaking) {
+ // trigger quickly, short history
+ for (var i = harker.speakingHistory.length - 3; i < harker.speakingHistory.length; i++) {
+ history += harker.speakingHistory[i];
+ }
+ if (history >= 2) {
+ harker.speaking = true;
+ harker.emit('speaking');
+ }
+ } else if (currentVolume < threshold && harker.speaking) {
+ for (var i = 0; i < harker.speakingHistory.length; i++) {
+ history += harker.speakingHistory[i];
+ }
+ if (history == 0) {
+ harker.speaking = false;
+ harker.emit('stopped_speaking');
+ }
+ }
+ harker.speakingHistory.shift();
+ harker.speakingHistory.push(0 + (currentVolume > threshold));
+
+ looper();
+ }, interval);
+ };
+ looper();
+
+
+ return harker;
+}
+
+},{"wildemitter":14}],6:[function(require,module,exports){
+if (typeof Object.create === 'function') {
+ // implementation from standard node.js 'util' module
+ module.exports = function inherits(ctor, superCtor) {
+ ctor.super_ = superCtor
+ ctor.prototype = Object.create(superCtor.prototype, {
+ constructor: {
+ value: ctor,
+ enumerable: false,
+ writable: true,
+ configurable: true
+ }
+ });
+ };
+} else {
+ // old school shim for old browsers
+ module.exports = function inherits(ctor, superCtor) {
+ ctor.super_ = superCtor
+ var TempCtor = function () {}
+ TempCtor.prototype = superCtor.prototype
+ ctor.prototype = new TempCtor()
+ ctor.prototype.constructor = ctor
+ }
+}
+
+},{}],7:[function(require,module,exports){
+/**
+ # normalice
+
+ Normalize an ice server configuration object (or plain old string) into a format
+ that is usable in all browsers supporting WebRTC. Primarily this module is designed
+ to help with the transition of the `url` attribute of the configuration object to
+ the `urls` attribute.
+
+ ## Example Usage
+
+ <<< examples/simple.js
+
+**/
+
+var protocols = [
+ 'stun:',
+ 'turn:'
+];
+
+module.exports = function(input) {
+ var url = (input || {}).url || input;
+ var protocol;
+ var parts;
+ var output = {};
+
+ // if we don't have a string url, then allow the input to passthrough
+ if (typeof url != 'string' && (! (url instanceof String))) {
+ return input;
+ }
+
+ // trim the url string, and convert to an array
+ url = url.trim();
+
+ // if the protocol is not known, then passthrough
+ protocol = protocols[protocols.indexOf(url.slice(0, 5))];
+ if (! protocol) {
+ return input;
+ }
+
+ // now let's attack the remaining url parts
+ url = url.slice(5);
+ parts = url.split('@');
+
+ output.username = input.username;
+ output.credential = input.credential;
+ // if we have an authentication part, then set the credentials
+ if (parts.length > 1) {
+ url = parts[1];
+ parts = parts[0].split(':');
+
+ // add the output credential and username
+ output.username = parts[0];
+ output.credential = (input || {}).credential || parts[1] || '';
+ }
+
+ output.url = protocol + url;
+ output.urls = [ output.url ];
+
+ return output;
+};
+
+},{}],8:[function(require,module,exports){
+(function (global){
+/*!
+ * Platform.js
+ * Copyright 2014-2018 Benjamin Tan
+ * Copyright 2011-2013 John-David Dalton
+ * Available under MIT license
+ */
+;(function() {
+ 'use strict';
+
+ /** Used to determine if values are of the language type `Object`. */
+ var objectTypes = {
+ 'function': true,
+ 'object': true
+ };
+
+ /** Used as a reference to the global object. */
+ var root = (objectTypes[typeof window] && window) || this;
+
+ /** Backup possible global object. */
+ var oldRoot = root;
+
+ /** Detect free variable `exports`. */
+ var freeExports = objectTypes[typeof exports] && exports;
+
+ /** Detect free variable `module`. */
+ var freeModule = objectTypes[typeof module] && module && !module.nodeType && module;
+
+ /** Detect free variable `global` from Node.js or Browserified code and use it as `root`. */
+ var freeGlobal = freeExports && freeModule && typeof global == 'object' && global;
+ if (freeGlobal && (freeGlobal.global === freeGlobal || freeGlobal.window === freeGlobal || freeGlobal.self === freeGlobal)) {
+ root = freeGlobal;
+ }
+
+ /**
+ * Used as the maximum length of an array-like object.
+ * See the [ES6 spec](http://people.mozilla.org/~jorendorff/es6-draft.html#sec-tolength)
+ * for more details.
+ */
+ var maxSafeInteger = Math.pow(2, 53) - 1;
+
+ /** Regular expression to detect Opera. */
+ var reOpera = /\bOpera/;
+
+ /** Possible global object. */
+ var thisBinding = this;
+
+ /** Used for native method references. */
+ var objectProto = Object.prototype;
+
+ /** Used to check for own properties of an object. */
+ var hasOwnProperty = objectProto.hasOwnProperty;
+
+ /** Used to resolve the internal `[[Class]]` of values. */
+ var toString = objectProto.toString;
+
+ /*--------------------------------------------------------------------------*/
+
+ /**
+ * Capitalizes a string value.
+ *
+ * @private
+ * @param {string} string The string to capitalize.
+ * @returns {string} The capitalized string.
+ */
+ function capitalize(string) {
+ string = String(string);
+ return string.charAt(0).toUpperCase() + string.slice(1);
+ }
+
+ /**
+ * A utility function to clean up the OS name.
+ *
+ * @private
+ * @param {string} os The OS name to clean up.
+ * @param {string} [pattern] A `RegExp` pattern matching the OS name.
+ * @param {string} [label] A label for the OS.
+ */
+ function cleanupOS(os, pattern, label) {
+ // Platform tokens are defined at:
+ // http://msdn.microsoft.com/en-us/library/ms537503(VS.85).aspx
+ // http://web.archive.org/web/20081122053950/http://msdn.microsoft.com/en-us/library/ms537503(VS.85).aspx
+ var data = {
+ '10.0': '10',
+ '6.4': '10 Technical Preview',
+ '6.3': '8.1',
+ '6.2': '8',
+ '6.1': 'Server 2008 R2 / 7',
+ '6.0': 'Server 2008 / Vista',
+ '5.2': 'Server 2003 / XP 64-bit',
+ '5.1': 'XP',
+ '5.01': '2000 SP1',
+ '5.0': '2000',
+ '4.0': 'NT',
+ '4.90': 'ME'
+ };
+ // Detect Windows version from platform tokens.
+ if (pattern && label && /^Win/i.test(os) && !/^Windows Phone /i.test(os) &&
+ (data = data[/[\d.]+$/.exec(os)])) {
+ os = 'Windows ' + data;
+ }
+ // Correct character case and cleanup string.
+ os = String(os);
+
+ if (pattern && label) {
+ os = os.replace(RegExp(pattern, 'i'), label);
+ }
+
+ os = format(
+ os.replace(/ ce$/i, ' CE')
+ .replace(/\bhpw/i, 'web')
+ .replace(/\bMacintosh\b/, 'Mac OS')
+ .replace(/_PowerPC\b/i, ' OS')
+ .replace(/\b(OS X) [^ \d]+/i, '$1')
+ .replace(/\bMac (OS X)\b/, '$1')
+ .replace(/\/(\d)/, ' $1')
+ .replace(/_/g, '.')
+ .replace(/(?: BePC|[ .]*fc[ \d.]+)$/i, '')
+ .replace(/\bx86\.64\b/gi, 'x86_64')
+ .replace(/\b(Windows Phone) OS\b/, '$1')
+ .replace(/\b(Chrome OS \w+) [\d.]+\b/, '$1')
+ .split(' on ')[0]
+ );
+
+ return os;
+ }
+
+ /**
+ * An iteration utility for arrays and objects.
+ *
+ * @private
+ * @param {Array|Object} object The object to iterate over.
+ * @param {Function} callback The function called per iteration.
+ */
+ function each(object, callback) {
+ var index = -1,
+ length = object ? object.length : 0;
+
+ if (typeof length == 'number' && length > -1 && length <= maxSafeInteger) {
+ while (++index < length) {
+ callback(object[index], index, object);
+ }
+ } else {
+ forOwn(object, callback);
+ }
+ }
+
+ /**
+ * Trim and conditionally capitalize string values.
+ *
+ * @private
+ * @param {string} string The string to format.
+ * @returns {string} The formatted string.
+ */
+ function format(string) {
+ string = trim(string);
+ return /^(?:webOS|i(?:OS|P))/.test(string)
+ ? string
+ : capitalize(string);
+ }
+
+ /**
+ * Iterates over an object's own properties, executing the `callback` for each.
+ *
+ * @private
+ * @param {Object} object The object to iterate over.
+ * @param {Function} callback The function executed per own property.
+ */
+ function forOwn(object, callback) {
+ for (var key in object) {
+ if (hasOwnProperty.call(object, key)) {
+ callback(object[key], key, object);
+ }
+ }
+ }
+
+ /**
+ * Gets the internal `[[Class]]` of a value.
+ *
+ * @private
+ * @param {*} value The value.
+ * @returns {string} The `[[Class]]`.
+ */
+ function getClassOf(value) {
+ return value == null
+ ? capitalize(value)
+ : toString.call(value).slice(8, -1);
+ }
+
+ /**
+ * Host objects can return type values that are different from their actual
+ * data type. The objects we are concerned with usually return non-primitive
+ * types of "object", "function", or "unknown".
+ *
+ * @private
+ * @param {*} object The owner of the property.
+ * @param {string} property The property to check.
+ * @returns {boolean} Returns `true` if the property value is a non-primitive, else `false`.
+ */
+ function isHostType(object, property) {
+ var type = object != null ? typeof object[property] : 'number';
+ return !/^(?:boolean|number|string|undefined)$/.test(type) &&
+ (type == 'object' ? !!object[property] : true);
+ }
+
+ /**
+ * Prepares a string for use in a `RegExp` by making hyphens and spaces optional.
+ *
+ * @private
+ * @param {string} string The string to qualify.
+ * @returns {string} The qualified string.
+ */
+ function qualify(string) {
+ return String(string).replace(/([ -])(?!$)/g, '$1?');
+ }
+
+ /**
+ * A bare-bones `Array#reduce` like utility function.
+ *
+ * @private
+ * @param {Array} array The array to iterate over.
+ * @param {Function} callback The function called per iteration.
+ * @returns {*} The accumulated result.
+ */
+ function reduce(array, callback) {
+ var accumulator = null;
+ each(array, function(value, index) {
+ accumulator = callback(accumulator, value, index, array);
+ });
+ return accumulator;
+ }
+
+ /**
+ * Removes leading and trailing whitespace from a string.
+ *
+ * @private
+ * @param {string} string The string to trim.
+ * @returns {string} The trimmed string.
+ */
+ function trim(string) {
+ return String(string).replace(/^ +| +$/g, '');
+ }
+
+ /*--------------------------------------------------------------------------*/
+
+ /**
+ * Creates a new platform object.
+ *
+ * @memberOf platform
+ * @param {Object|string} [ua=navigator.userAgent] The user agent string or
+ * context object.
+ * @returns {Object} A platform object.
+ */
+ function parse(ua) {
+
+ /** The environment context object. */
+ var context = root;
+
+ /** Used to flag when a custom context is provided. */
+ var isCustomContext = ua && typeof ua == 'object' && getClassOf(ua) != 'String';
+
+ // Juggle arguments.
+ if (isCustomContext) {
+ context = ua;
+ ua = null;
+ }
+
+ /** Browser navigator object. */
+ var nav = context.navigator || {};
+
+ /** Browser user agent string. */
+ var userAgent = nav.userAgent || '';
+
+ ua || (ua = userAgent);
+
+ /** Used to flag when `thisBinding` is the [ModuleScope]. */
+ var isModuleScope = isCustomContext || thisBinding == oldRoot;
+
+ /** Used to detect if browser is like Chrome. */
+ var likeChrome = isCustomContext
+ ? !!nav.likeChrome
+ : /\bChrome\b/.test(ua) && !/internal|\n/i.test(toString.toString());
+
+ /** Internal `[[Class]]` value shortcuts. */
+ var objectClass = 'Object',
+ airRuntimeClass = isCustomContext ? objectClass : 'ScriptBridgingProxyObject',
+ enviroClass = isCustomContext ? objectClass : 'Environment',
+ javaClass = (isCustomContext && context.java) ? 'JavaPackage' : getClassOf(context.java),
+ phantomClass = isCustomContext ? objectClass : 'RuntimeObject';
+
+ /** Detect Java environments. */
+ var java = /\bJava/.test(javaClass) && context.java;
+
+ /** Detect Rhino. */
+ var rhino = java && getClassOf(context.environment) == enviroClass;
+
+ /** A character to represent alpha. */
+ var alpha = java ? 'a' : '\u03b1';
+
+ /** A character to represent beta. */
+ var beta = java ? 'b' : '\u03b2';
+
+ /** Browser document object. */
+ var doc = context.document || {};
+
+ /**
+ * Detect Opera browser (Presto-based).
+ * http://www.howtocreate.co.uk/operaStuff/operaObject.html
+ * http://dev.opera.com/articles/view/opera-mini-web-content-authoring-guidelines/#operamini
+ */
+ var opera = context.operamini || context.opera;
+
+ /** Opera `[[Class]]`. */
+ var operaClass = reOpera.test(operaClass = (isCustomContext && opera) ? opera['[[Class]]'] : getClassOf(opera))
+ ? operaClass
+ : (opera = null);
+
+ /*------------------------------------------------------------------------*/
+
+ /** Temporary variable used over the script's lifetime. */
+ var data;
+
+ /** The CPU architecture. */
+ var arch = ua;
+
+ /** Platform description array. */
+ var description = [];
+
+ /** Platform alpha/beta indicator. */
+ var prerelease = null;
+
+ /** A flag to indicate that environment features should be used to resolve the platform. */
+ var useFeatures = ua == userAgent;
+
+ /** The browser/environment version. */
+ var version = useFeatures && opera && typeof opera.version == 'function' && opera.version();
+
+ /** A flag to indicate if the OS ends with "/ Version" */
+ var isSpecialCasedOS;
+
+ /* Detectable layout engines (order is important). */
+ var layout = getLayout([
+ { 'label': 'EdgeHTML', 'pattern': 'Edge' },
+ 'Trident',
+ { 'label': 'WebKit', 'pattern': 'AppleWebKit' },
+ 'iCab',
+ 'Presto',
+ 'NetFront',
+ 'Tasman',
+ 'KHTML',
+ 'Gecko'
+ ]);
+
+ /* Detectable browser names (order is important). */
+ var name = getName([
+ 'Adobe AIR',
+ 'Arora',
+ 'Avant Browser',
+ 'Breach',
+ 'Camino',
+ 'Electron',
+ 'Epiphany',
+ 'Fennec',
+ 'Flock',
+ 'Galeon',
+ 'GreenBrowser',
+ 'iCab',
+ 'Iceweasel',
+ 'K-Meleon',
+ 'Konqueror',
+ 'Lunascape',
+ 'Maxthon',
+ { 'label': 'Microsoft Edge', 'pattern': 'Edge' },
+ 'Midori',
+ 'Nook Browser',
+ 'PaleMoon',
+ 'PhantomJS',
+ 'Raven',
+ 'Rekonq',
+ 'RockMelt',
+ { 'label': 'Samsung Internet', 'pattern': 'SamsungBrowser' },
+ 'SeaMonkey',
+ { 'label': 'Silk', 'pattern': '(?:Cloud9|Silk-Accelerated)' },
+ 'Sleipnir',
+ 'SlimBrowser',
+ { 'label': 'SRWare Iron', 'pattern': 'Iron' },
+ 'Sunrise',
+ 'Swiftfox',
+ 'Waterfox',
+ 'WebPositive',
+ 'Opera Mini',
+ { 'label': 'Opera Mini', 'pattern': 'OPiOS' },
+ 'Opera',
+ { 'label': 'Opera', 'pattern': 'OPR' },
+ 'Chrome',
+ { 'label': 'Chrome Mobile', 'pattern': '(?:CriOS|CrMo)' },
+ { 'label': 'Firefox', 'pattern': '(?:Firefox|Minefield)' },
+ { 'label': 'Firefox for iOS', 'pattern': 'FxiOS' },
+ { 'label': 'IE', 'pattern': 'IEMobile' },
+ { 'label': 'IE', 'pattern': 'MSIE' },
+ 'Safari'
+ ]);
+
+ /* Detectable products (order is important). */
+ var product = getProduct([
+ { 'label': 'BlackBerry', 'pattern': 'BB10' },
+ 'BlackBerry',
+ { 'label': 'Galaxy S', 'pattern': 'GT-I9000' },
+ { 'label': 'Galaxy S2', 'pattern': 'GT-I9100' },
+ { 'label': 'Galaxy S3', 'pattern': 'GT-I9300' },
+ { 'label': 'Galaxy S4', 'pattern': 'GT-I9500' },
+ { 'label': 'Galaxy S5', 'pattern': 'SM-G900' },
+ { 'label': 'Galaxy S6', 'pattern': 'SM-G920' },
+ { 'label': 'Galaxy S6 Edge', 'pattern': 'SM-G925' },
+ { 'label': 'Galaxy S7', 'pattern': 'SM-G930' },
+ { 'label': 'Galaxy S7 Edge', 'pattern': 'SM-G935' },
+ 'Google TV',
+ 'Lumia',
+ 'iPad',
+ 'iPod',
+ 'iPhone',
+ 'Kindle',
+ { 'label': 'Kindle Fire', 'pattern': '(?:Cloud9|Silk-Accelerated)' },
+ 'Nexus',
+ 'Nook',
+ 'PlayBook',
+ 'PlayStation Vita',
+ 'PlayStation',
+ 'TouchPad',
+ 'Transformer',
+ { 'label': 'Wii U', 'pattern': 'WiiU' },
+ 'Wii',
+ 'Xbox One',
+ { 'label': 'Xbox 360', 'pattern': 'Xbox' },
+ 'Xoom'
+ ]);
+
+ /* Detectable manufacturers. */
+ var manufacturer = getManufacturer({
+ 'Apple': { 'iPad': 1, 'iPhone': 1, 'iPod': 1 },
+ 'Archos': {},
+ 'Amazon': { 'Kindle': 1, 'Kindle Fire': 1 },
+ 'Asus': { 'Transformer': 1 },
+ 'Barnes & Noble': { 'Nook': 1 },
+ 'BlackBerry': { 'PlayBook': 1 },
+ 'Google': { 'Google TV': 1, 'Nexus': 1 },
+ 'HP': { 'TouchPad': 1 },
+ 'HTC': {},
+ 'LG': {},
+ 'Microsoft': { 'Xbox': 1, 'Xbox One': 1 },
+ 'Motorola': { 'Xoom': 1 },
+ 'Nintendo': { 'Wii U': 1, 'Wii': 1 },
+ 'Nokia': { 'Lumia': 1 },
+ 'Samsung': { 'Galaxy S': 1, 'Galaxy S2': 1, 'Galaxy S3': 1, 'Galaxy S4': 1 },
+ 'Sony': { 'PlayStation': 1, 'PlayStation Vita': 1 }
+ });
+
+ /* Detectable operating systems (order is important). */
+ var os = getOS([
+ 'Windows Phone',
+ 'Android',
+ 'CentOS',
+ { 'label': 'Chrome OS', 'pattern': 'CrOS' },
+ 'Debian',
+ 'Fedora',
+ 'FreeBSD',
+ 'Gentoo',
+ 'Haiku',
+ 'Kubuntu',
+ 'Linux Mint',
+ 'OpenBSD',
+ 'Red Hat',
+ 'SuSE',
+ 'Ubuntu',
+ 'Xubuntu',
+ 'Cygwin',
+ 'Symbian OS',
+ 'hpwOS',
+ 'webOS ',
+ 'webOS',
+ 'Tablet OS',
+ 'Tizen',
+ 'Linux',
+ 'Mac OS X',
+ 'Macintosh',
+ 'Mac',
+ 'Windows 98;',
+ 'Windows '
+ ]);
+
+ /*------------------------------------------------------------------------*/
+
+ /**
+ * Picks the layout engine from an array of guesses.
+ *
+ * @private
+ * @param {Array} guesses An array of guesses.
+ * @returns {null|string} The detected layout engine.
+ */
+ function getLayout(guesses) {
+ return reduce(guesses, function(result, guess) {
+ return result || RegExp('\\b' + (
+ guess.pattern || qualify(guess)
+ ) + '\\b', 'i').exec(ua) && (guess.label || guess);
+ });
+ }
+
+ /**
+ * Picks the manufacturer from an array of guesses.
+ *
+ * @private
+ * @param {Array} guesses An object of guesses.
+ * @returns {null|string} The detected manufacturer.
+ */
+ function getManufacturer(guesses) {
+ return reduce(guesses, function(result, value, key) {
+ // Lookup the manufacturer by product or scan the UA for the manufacturer.
+ return result || (
+ value[product] ||
+ value[/^[a-z]+(?: +[a-z]+\b)*/i.exec(product)] ||
+ RegExp('\\b' + qualify(key) + '(?:\\b|\\w*\\d)', 'i').exec(ua)
+ ) && key;
+ });
+ }
+
+ /**
+ * Picks the browser name from an array of guesses.
+ *
+ * @private
+ * @param {Array} guesses An array of guesses.
+ * @returns {null|string} The detected browser name.
+ */
+ function getName(guesses) {
+ return reduce(guesses, function(result, guess) {
+ return result || RegExp('\\b' + (
+ guess.pattern || qualify(guess)
+ ) + '\\b', 'i').exec(ua) && (guess.label || guess);
+ });
+ }
+
+ /**
+ * Picks the OS name from an array of guesses.
+ *
+ * @private
+ * @param {Array} guesses An array of guesses.
+ * @returns {null|string} The detected OS name.
+ */
+ function getOS(guesses) {
+ return reduce(guesses, function(result, guess) {
+ var pattern = guess.pattern || qualify(guess);
+ if (!result && (result =
+ RegExp('\\b' + pattern + '(?:/[\\d.]+|[ \\w.]*)', 'i').exec(ua)
+ )) {
+ result = cleanupOS(result, pattern, guess.label || guess);
+ }
+ return result;
+ });
+ }
+
+ /**
+ * Picks the product name from an array of guesses.
+ *
+ * @private
+ * @param {Array} guesses An array of guesses.
+ * @returns {null|string} The detected product name.
+ */
+ function getProduct(guesses) {
+ return reduce(guesses, function(result, guess) {
+ var pattern = guess.pattern || qualify(guess);
+ if (!result && (result =
+ RegExp('\\b' + pattern + ' *\\d+[.\\w_]*', 'i').exec(ua) ||
+ RegExp('\\b' + pattern + ' *\\w+-[\\w]*', 'i').exec(ua) ||
+ RegExp('\\b' + pattern + '(?:; *(?:[a-z]+[_-])?[a-z]+\\d+|[^ ();-]*)', 'i').exec(ua)
+ )) {
+ // Split by forward slash and append product version if needed.
+ if ((result = String((guess.label && !RegExp(pattern, 'i').test(guess.label)) ? guess.label : result).split('/'))[1] && !/[\d.]+/.test(result[0])) {
+ result[0] += ' ' + result[1];
+ }
+ // Correct character case and cleanup string.
+ guess = guess.label || guess;
+ result = format(result[0]
+ .replace(RegExp(pattern, 'i'), guess)
+ .replace(RegExp('; *(?:' + guess + '[_-])?', 'i'), ' ')
+ .replace(RegExp('(' + guess + ')[-_.]?(\\w)', 'i'), '$1 $2'));
+ }
+ return result;
+ });
+ }
+
+ /**
+ * Resolves the version using an array of UA patterns.
+ *
+ * @private
+ * @param {Array} patterns An array of UA patterns.
+ * @returns {null|string} The detected version.
+ */
+ function getVersion(patterns) {
+ return reduce(patterns, function(result, pattern) {
+ return result || (RegExp(pattern +
+ '(?:-[\\d.]+/|(?: for [\\w-]+)?[ /-])([\\d.]+[^ ();/_-]*)', 'i').exec(ua) || 0)[1] || null;
+ });
+ }
+
+ /**
+ * Returns `platform.description` when the platform object is coerced to a string.
+ *
+ * @name toString
+ * @memberOf platform
+ * @returns {string} Returns `platform.description` if available, else an empty string.
+ */
+ function toStringPlatform() {
+ return this.description || '';
+ }
+
+ /*------------------------------------------------------------------------*/
+
+ // Convert layout to an array so we can add extra details.
+ layout && (layout = [layout]);
+
+ // Detect product names that contain their manufacturer's name.
+ if (manufacturer && !product) {
+ product = getProduct([manufacturer]);
+ }
+ // Clean up Google TV.
+ if ((data = /\bGoogle TV\b/.exec(product))) {
+ product = data[0];
+ }
+ // Detect simulators.
+ if (/\bSimulator\b/i.test(ua)) {
+ product = (product ? product + ' ' : '') + 'Simulator';
+ }
+ // Detect Opera Mini 8+ running in Turbo/Uncompressed mode on iOS.
+ if (name == 'Opera Mini' && /\bOPiOS\b/.test(ua)) {
+ description.push('running in Turbo/Uncompressed mode');
+ }
+ // Detect IE Mobile 11.
+ if (name == 'IE' && /\blike iPhone OS\b/.test(ua)) {
+ data = parse(ua.replace(/like iPhone OS/, ''));
+ manufacturer = data.manufacturer;
+ product = data.product;
+ }
+ // Detect iOS.
+ else if (/^iP/.test(product)) {
+ name || (name = 'Safari');
+ os = 'iOS' + ((data = / OS ([\d_]+)/i.exec(ua))
+ ? ' ' + data[1].replace(/_/g, '.')
+ : '');
+ }
+ // Detect Kubuntu.
+ else if (name == 'Konqueror' && !/buntu/i.test(os)) {
+ os = 'Kubuntu';
+ }
+ // Detect Android browsers.
+ else if ((manufacturer && manufacturer != 'Google' &&
+ ((/Chrome/.test(name) && !/\bMobile Safari\b/i.test(ua)) || /\bVita\b/.test(product))) ||
+ (/\bAndroid\b/.test(os) && /^Chrome/.test(name) && /\bVersion\//i.test(ua))) {
+ name = 'Android Browser';
+ os = /\bAndroid\b/.test(os) ? os : 'Android';
+ }
+ // Detect Silk desktop/accelerated modes.
+ else if (name == 'Silk') {
+ if (!/\bMobi/i.test(ua)) {
+ os = 'Android';
+ description.unshift('desktop mode');
+ }
+ if (/Accelerated *= *true/i.test(ua)) {
+ description.unshift('accelerated');
+ }
+ }
+ // Detect PaleMoon identifying as Firefox.
+ else if (name == 'PaleMoon' && (data = /\bFirefox\/([\d.]+)\b/.exec(ua))) {
+ description.push('identifying as Firefox ' + data[1]);
+ }
+ // Detect Firefox OS and products running Firefox.
+ else if (name == 'Firefox' && (data = /\b(Mobile|Tablet|TV)\b/i.exec(ua))) {
+ os || (os = 'Firefox OS');
+ product || (product = data[1]);
+ }
+ // Detect false positives for Firefox/Safari.
+ else if (!name || (data = !/\bMinefield\b/i.test(ua) && /\b(?:Firefox|Safari)\b/.exec(name))) {
+ // Escape the `/` for Firefox 1.
+ if (name && !product && /[\/,]|^[^(]+?\)/.test(ua.slice(ua.indexOf(data + '/') + 8))) {
+ // Clear name of false positives.
+ name = null;
+ }
+ // Reassign a generic name.
+ if ((data = product || manufacturer || os) &&
+ (product || manufacturer || /\b(?:Android|Symbian OS|Tablet OS|webOS)\b/.test(os))) {
+ name = /[a-z]+(?: Hat)?/i.exec(/\bAndroid\b/.test(os) ? os : data) + ' Browser';
+ }
+ }
+ // Add Chrome version to description for Electron.
+ else if (name == 'Electron' && (data = (/\bChrome\/([\d.]+)\b/.exec(ua) || 0)[1])) {
+ description.push('Chromium ' + data);
+ }
+ // Detect non-Opera (Presto-based) versions (order is important).
+ if (!version) {
+ version = getVersion([
+ '(?:Cloud9|CriOS|CrMo|Edge|FxiOS|IEMobile|Iron|Opera ?Mini|OPiOS|OPR|Raven|SamsungBrowser|Silk(?!/[\\d.]+$))',
+ 'Version',
+ qualify(name),
+ '(?:Firefox|Minefield|NetFront)'
+ ]);
+ }
+ // Detect stubborn layout engines.
+ if ((data =
+ layout == 'iCab' && parseFloat(version) > 3 && 'WebKit' ||
+ /\bOpera\b/.test(name) && (/\bOPR\b/.test(ua) ? 'Blink' : 'Presto') ||
+ /\b(?:Midori|Nook|Safari)\b/i.test(ua) && !/^(?:Trident|EdgeHTML)$/.test(layout) && 'WebKit' ||
+ !layout && /\bMSIE\b/i.test(ua) && (os == 'Mac OS' ? 'Tasman' : 'Trident') ||
+ layout == 'WebKit' && /\bPlayStation\b(?! Vita\b)/i.test(name) && 'NetFront'
+ )) {
+ layout = [data];
+ }
+ // Detect Windows Phone 7 desktop mode.
+ if (name == 'IE' && (data = (/; *(?:XBLWP|ZuneWP)(\d+)/i.exec(ua) || 0)[1])) {
+ name += ' Mobile';
+ os = 'Windows Phone ' + (/\+$/.test(data) ? data : data + '.x');
+ description.unshift('desktop mode');
+ }
+ // Detect Windows Phone 8.x desktop mode.
+ else if (/\bWPDesktop\b/i.test(ua)) {
+ name = 'IE Mobile';
+ os = 'Windows Phone 8.x';
+ description.unshift('desktop mode');
+ version || (version = (/\brv:([\d.]+)/.exec(ua) || 0)[1]);
+ }
+ // Detect IE 11 identifying as other browsers.
+ else if (name != 'IE' && layout == 'Trident' && (data = /\brv:([\d.]+)/.exec(ua))) {
+ if (name) {
+ description.push('identifying as ' + name + (version ? ' ' + version : ''));
+ }
+ name = 'IE';
+ version = data[1];
+ }
+ // Leverage environment features.
+ if (useFeatures) {
+ // Detect server-side environments.
+ // Rhino has a global function while others have a global object.
+ if (isHostType(context, 'global')) {
+ if (java) {
+ data = java.lang.System;
+ arch = data.getProperty('os.arch');
+ os = os || data.getProperty('os.name') + ' ' + data.getProperty('os.version');
+ }
+ if (rhino) {
+ try {
+ version = context.require('ringo/engine').version.join('.');
+ name = 'RingoJS';
+ } catch(e) {
+ if ((data = context.system) && data.global.system == context.system) {
+ name = 'Narwhal';
+ os || (os = data[0].os || null);
+ }
+ }
+ if (!name) {
+ name = 'Rhino';
+ }
+ }
+ else if (
+ typeof context.process == 'object' && !context.process.browser &&
+ (data = context.process)
+ ) {
+ if (typeof data.versions == 'object') {
+ if (typeof data.versions.electron == 'string') {
+ description.push('Node ' + data.versions.node);
+ name = 'Electron';
+ version = data.versions.electron;
+ } else if (typeof data.versions.nw == 'string') {
+ description.push('Chromium ' + version, 'Node ' + data.versions.node);
+ name = 'NW.js';
+ version = data.versions.nw;
+ }
+ }
+ if (!name) {
+ name = 'Node.js';
+ arch = data.arch;
+ os = data.platform;
+ version = /[\d.]+/.exec(data.version);
+ version = version ? version[0] : null;
+ }
+ }
+ }
+ // Detect Adobe AIR.
+ else if (getClassOf((data = context.runtime)) == airRuntimeClass) {
+ name = 'Adobe AIR';
+ os = data.flash.system.Capabilities.os;
+ }
+ // Detect PhantomJS.
+ else if (getClassOf((data = context.phantom)) == phantomClass) {
+ name = 'PhantomJS';
+ version = (data = data.version || null) && (data.major + '.' + data.minor + '.' + data.patch);
+ }
+ // Detect IE compatibility modes.
+ else if (typeof doc.documentMode == 'number' && (data = /\bTrident\/(\d+)/i.exec(ua))) {
+ // We're in compatibility mode when the Trident version + 4 doesn't
+ // equal the document mode.
+ version = [version, doc.documentMode];
+ if ((data = +data[1] + 4) != version[1]) {
+ description.push('IE ' + version[1] + ' mode');
+ layout && (layout[1] = '');
+ version[1] = data;
+ }
+ version = name == 'IE' ? String(version[1].toFixed(1)) : version[0];
+ }
+ // Detect IE 11 masking as other browsers.
+ else if (typeof doc.documentMode == 'number' && /^(?:Chrome|Firefox)\b/.test(name)) {
+ description.push('masking as ' + name + ' ' + version);
+ name = 'IE';
+ version = '11.0';
+ layout = ['Trident'];
+ os = 'Windows';
+ }
+ os = os && format(os);
+ }
+ // Detect prerelease phases.
+ if (version && (data =
+ /(?:[ab]|dp|pre|[ab]\d+pre)(?:\d+\+?)?$/i.exec(version) ||
+ /(?:alpha|beta)(?: ?\d)?/i.exec(ua + ';' + (useFeatures && nav.appMinorVersion)) ||
+ /\bMinefield\b/i.test(ua) && 'a'
+ )) {
+ prerelease = /b/i.test(data) ? 'beta' : 'alpha';
+ version = version.replace(RegExp(data + '\\+?$'), '') +
+ (prerelease == 'beta' ? beta : alpha) + (/\d+\+?/.exec(data) || '');
+ }
+ // Detect Firefox Mobile.
+ if (name == 'Fennec' || name == 'Firefox' && /\b(?:Android|Firefox OS)\b/.test(os)) {
+ name = 'Firefox Mobile';
+ }
+ // Obscure Maxthon's unreliable version.
+ else if (name == 'Maxthon' && version) {
+ version = version.replace(/\.[\d.]+/, '.x');
+ }
+ // Detect Xbox 360 and Xbox One.
+ else if (/\bXbox\b/i.test(product)) {
+ if (product == 'Xbox 360') {
+ os = null;
+ }
+ if (product == 'Xbox 360' && /\bIEMobile\b/.test(ua)) {
+ description.unshift('mobile mode');
+ }
+ }
+ // Add mobile postfix.
+ else if ((/^(?:Chrome|IE|Opera)$/.test(name) || name && !product && !/Browser|Mobi/.test(name)) &&
+ (os == 'Windows CE' || /Mobi/i.test(ua))) {
+ name += ' Mobile';
+ }
+ // Detect IE platform preview.
+ else if (name == 'IE' && useFeatures) {
+ try {
+ if (context.external === null) {
+ description.unshift('platform preview');
+ }
+ } catch(e) {
+ description.unshift('embedded');
+ }
+ }
+ // Detect BlackBerry OS version.
+ // http://docs.blackberry.com/en/developers/deliverables/18169/HTTP_headers_sent_by_BB_Browser_1234911_11.jsp
+ else if ((/\bBlackBerry\b/.test(product) || /\bBB10\b/.test(ua)) && (data =
+ (RegExp(product.replace(/ +/g, ' *') + '/([.\\d]+)', 'i').exec(ua) || 0)[1] ||
+ version
+ )) {
+ data = [data, /BB10/.test(ua)];
+ os = (data[1] ? (product = null, manufacturer = 'BlackBerry') : 'Device Software') + ' ' + data[0];
+ version = null;
+ }
+ // Detect Opera identifying/masking itself as another browser.
+ // http://www.opera.com/support/kb/view/843/
+ else if (this != forOwn && product != 'Wii' && (
+ (useFeatures && opera) ||
+ (/Opera/.test(name) && /\b(?:MSIE|Firefox)\b/i.test(ua)) ||
+ (name == 'Firefox' && /\bOS X (?:\d+\.){2,}/.test(os)) ||
+ (name == 'IE' && (
+ (os && !/^Win/.test(os) && version > 5.5) ||
+ /\bWindows XP\b/.test(os) && version > 8 ||
+ version == 8 && !/\bTrident\b/.test(ua)
+ ))
+ ) && !reOpera.test((data = parse.call(forOwn, ua.replace(reOpera, '') + ';'))) && data.name) {
+ // When "identifying", the UA contains both Opera and the other browser's name.
+ data = 'ing as ' + data.name + ((data = data.version) ? ' ' + data : '');
+ if (reOpera.test(name)) {
+ if (/\bIE\b/.test(data) && os == 'Mac OS') {
+ os = null;
+ }
+ data = 'identify' + data;
+ }
+ // When "masking", the UA contains only the other browser's name.
+ else {
+ data = 'mask' + data;
+ if (operaClass) {
+ name = format(operaClass.replace(/([a-z])([A-Z])/g, '$1 $2'));
+ } else {
+ name = 'Opera';
+ }
+ if (/\bIE\b/.test(data)) {
+ os = null;
+ }
+ if (!useFeatures) {
+ version = null;
+ }
+ }
+ layout = ['Presto'];
+ description.push(data);
+ }
+ // Detect WebKit Nightly and approximate Chrome/Safari versions.
+ if ((data = (/\bAppleWebKit\/([\d.]+\+?)/i.exec(ua) || 0)[1])) {
+ // Correct build number for numeric comparison.
+ // (e.g. "532.5" becomes "532.05")
+ data = [parseFloat(data.replace(/\.(\d)$/, '.0$1')), data];
+ // Nightly builds are postfixed with a "+".
+ if (name == 'Safari' && data[1].slice(-1) == '+') {
+ name = 'WebKit Nightly';
+ prerelease = 'alpha';
+ version = data[1].slice(0, -1);
+ }
+ // Clear incorrect browser versions.
+ else if (version == data[1] ||
+ version == (data[2] = (/\bSafari\/([\d.]+\+?)/i.exec(ua) || 0)[1])) {
+ version = null;
+ }
+ // Use the full Chrome version when available.
+ data[1] = (/\bChrome\/([\d.]+)/i.exec(ua) || 0)[1];
+ // Detect Blink layout engine.
+ if (data[0] == 537.36 && data[2] == 537.36 && parseFloat(data[1]) >= 28 && layout == 'WebKit') {
+ layout = ['Blink'];
+ }
+ // Detect JavaScriptCore.
+ // http://stackoverflow.com/questions/6768474/how-can-i-detect-which-javascript-engine-v8-or-jsc-is-used-at-runtime-in-androi
+ if (!useFeatures || (!likeChrome && !data[1])) {
+ layout && (layout[1] = 'like Safari');
+ data = (data = data[0], data < 400 ? 1 : data < 500 ? 2 : data < 526 ? 3 : data < 533 ? 4 : data < 534 ? '4+' : data < 535 ? 5 : data < 537 ? 6 : data < 538 ? 7 : data < 601 ? 8 : '8');
+ } else {
+ layout && (layout[1] = 'like Chrome');
+ data = data[1] || (data = data[0], data < 530 ? 1 : data < 532 ? 2 : data < 532.05 ? 3 : data < 533 ? 4 : data < 534.03 ? 5 : data < 534.07 ? 6 : data < 534.10 ? 7 : data < 534.13 ? 8 : data < 534.16 ? 9 : data < 534.24 ? 10 : data < 534.30 ? 11 : data < 535.01 ? 12 : data < 535.02 ? '13+' : data < 535.07 ? 15 : data < 535.11 ? 16 : data < 535.19 ? 17 : data < 536.05 ? 18 : data < 536.10 ? 19 : data < 537.01 ? 20 : data < 537.11 ? '21+' : data < 537.13 ? 23 : data < 537.18 ? 24 : data < 537.24 ? 25 : data < 537.36 ? 26 : layout != 'Blink' ? '27' : '28');
+ }
+ // Add the postfix of ".x" or "+" for approximate versions.
+ layout && (layout[1] += ' ' + (data += typeof data == 'number' ? '.x' : /[.+]/.test(data) ? '' : '+'));
+ // Obscure version for some Safari 1-2 releases.
+ if (name == 'Safari' && (!version || parseInt(version) > 45)) {
+ version = data;
+ }
+ }
+ // Detect Opera desktop modes.
+ if (name == 'Opera' && (data = /\bzbov|zvav$/.exec(os))) {
+ name += ' ';
+ description.unshift('desktop mode');
+ if (data == 'zvav') {
+ name += 'Mini';
+ version = null;
+ } else {
+ name += 'Mobile';
+ }
+ os = os.replace(RegExp(' *' + data + '$'), '');
+ }
+ // Detect Chrome desktop mode.
+ else if (name == 'Safari' && /\bChrome\b/.exec(layout && layout[1])) {
+ description.unshift('desktop mode');
+ name = 'Chrome Mobile';
+ version = null;
+
+ if (/\bOS X\b/.test(os)) {
+ manufacturer = 'Apple';
+ os = 'iOS 4.3+';
+ } else {
+ os = null;
+ }
+ }
+ // Strip incorrect OS versions.
+ if (version && version.indexOf((data = /[\d.]+$/.exec(os))) == 0 &&
+ ua.indexOf('/' + data + '-') > -1) {
+ os = trim(os.replace(data, ''));
+ }
+ // Add layout engine.
+ if (layout && !/\b(?:Avant|Nook)\b/.test(name) && (
+ /Browser|Lunascape|Maxthon/.test(name) ||
+ name != 'Safari' && /^iOS/.test(os) && /\bSafari\b/.test(layout[1]) ||
+ /^(?:Adobe|Arora|Breach|Midori|Opera|Phantom|Rekonq|Rock|Samsung Internet|Sleipnir|Web)/.test(name) && layout[1])) {
+ // Don't add layout details to description if they are falsey.
+ (data = layout[layout.length - 1]) && description.push(data);
+ }
+ // Combine contextual information.
+ if (description.length) {
+ description = ['(' + description.join('; ') + ')'];
+ }
+ // Append manufacturer to description.
+ if (manufacturer && product && product.indexOf(manufacturer) < 0) {
+ description.push('on ' + manufacturer);
+ }
+ // Append product to description.
+ if (product) {
+ description.push((/^on /.test(description[description.length - 1]) ? '' : 'on ') + product);
+ }
+ // Parse the OS into an object.
+ if (os) {
+ data = / ([\d.+]+)$/.exec(os);
+ isSpecialCasedOS = data && os.charAt(os.length - data[0].length - 1) == '/';
+ os = {
+ 'architecture': 32,
+ 'family': (data && !isSpecialCasedOS) ? os.replace(data[0], '') : os,
+ 'version': data ? data[1] : null,
+ 'toString': function() {
+ var version = this.version;
+ return this.family + ((version && !isSpecialCasedOS) ? ' ' + version : '') + (this.architecture == 64 ? ' 64-bit' : '');
+ }
+ };
+ }
+ // Add browser/OS architecture.
+ if ((data = /\b(?:AMD|IA|Win|WOW|x86_|x)64\b/i.exec(arch)) && !/\bi686\b/i.test(arch)) {
+ if (os) {
+ os.architecture = 64;
+ os.family = os.family.replace(RegExp(' *' + data), '');
+ }
+ if (
+ name && (/\bWOW64\b/i.test(ua) ||
+ (useFeatures && /\w(?:86|32)$/.test(nav.cpuClass || nav.platform) && !/\bWin64; x64\b/i.test(ua)))
+ ) {
+ description.unshift('32-bit');
+ }
+ }
+ // Chrome 39 and above on OS X is always 64-bit.
+ else if (
+ os && /^OS X/.test(os.family) &&
+ name == 'Chrome' && parseFloat(version) >= 39
+ ) {
+ os.architecture = 64;
+ }
+
+ ua || (ua = null);
+
+ /*------------------------------------------------------------------------*/
+
+ /**
+ * The platform object.
+ *
+ * @name platform
+ * @type Object
+ */
+ var platform = {};
+
+ /**
+ * The platform description.
+ *
+ * @memberOf platform
+ * @type string|null
+ */
+ platform.description = ua;
+
+ /**
+ * The name of the browser's layout engine.
+ *
+ * The list of common layout engines include:
+ * "Blink", "EdgeHTML", "Gecko", "Trident" and "WebKit"
+ *
+ * @memberOf platform
+ * @type string|null
+ */
+ platform.layout = layout && layout[0];
+
+ /**
+ * The name of the product's manufacturer.
+ *
+ * The list of manufacturers include:
+ * "Apple", "Archos", "Amazon", "Asus", "Barnes & Noble", "BlackBerry",
+ * "Google", "HP", "HTC", "LG", "Microsoft", "Motorola", "Nintendo",
+ * "Nokia", "Samsung" and "Sony"
+ *
+ * @memberOf platform
+ * @type string|null
+ */
+ platform.manufacturer = manufacturer;
+
+ /**
+ * The name of the browser/environment.
+ *
+ * The list of common browser names include:
+ * "Chrome", "Electron", "Firefox", "Firefox for iOS", "IE",
+ * "Microsoft Edge", "PhantomJS", "Safari", "SeaMonkey", "Silk",
+ * "Opera Mini" and "Opera"
+ *
+ * Mobile versions of some browsers have "Mobile" appended to their name:
+ * eg. "Chrome Mobile", "Firefox Mobile", "IE Mobile" and "Opera Mobile"
+ *
+ * @memberOf platform
+ * @type string|null
+ */
+ platform.name = name;
+
+ /**
+ * The alpha/beta release indicator.
+ *
+ * @memberOf platform
+ * @type string|null
+ */
+ platform.prerelease = prerelease;
+
+ /**
+ * The name of the product hosting the browser.
+ *
+ * The list of common products include:
+ *
+ * "BlackBerry", "Galaxy S4", "Lumia", "iPad", "iPod", "iPhone", "Kindle",
+ * "Kindle Fire", "Nexus", "Nook", "PlayBook", "TouchPad" and "Transformer"
+ *
+ * @memberOf platform
+ * @type string|null
+ */
+ platform.product = product;
+
+ /**
+ * The browser's user agent string.
+ *
+ * @memberOf platform
+ * @type string|null
+ */
+ platform.ua = ua;
+
+ /**
+ * The browser/environment version.
+ *
+ * @memberOf platform
+ * @type string|null
+ */
+ platform.version = name && version;
+
+ /**
+ * The name of the operating system.
+ *
+ * @memberOf platform
+ * @type Object
+ */
+ platform.os = os || {
+
+ /**
+ * The CPU architecture the OS is built for.
+ *
+ * @memberOf platform.os
+ * @type number|null
+ */
+ 'architecture': null,
+
+ /**
+ * The family of the OS.
+ *
+ * Common values include:
+ * "Windows", "Windows Server 2008 R2 / 7", "Windows Server 2008 / Vista",
+ * "Windows XP", "OS X", "Ubuntu", "Debian", "Fedora", "Red Hat", "SuSE",
+ * "Android", "iOS" and "Windows Phone"
+ *
+ * @memberOf platform.os
+ * @type string|null
+ */
+ 'family': null,
+
+ /**
+ * The version of the OS.
+ *
+ * @memberOf platform.os
+ * @type string|null
+ */
+ 'version': null,
+
+ /**
+ * Returns the OS string.
+ *
+ * @memberOf platform.os
+ * @returns {string} The OS string.
+ */
+ 'toString': function() { return 'null'; }
+ };
+
+ platform.parse = parse;
+ platform.toString = toStringPlatform;
+
+ if (platform.version) {
+ description.unshift(version);
+ }
+ if (platform.name) {
+ description.unshift(name);
+ }
+ if (os && name && !(os == String(os).split(' ')[0] && (os == name.split(' ')[0] || product))) {
+ description.push(product ? '(' + os + ')' : 'on ' + os);
+ }
+ if (description.length) {
+ platform.description = description.join(' ');
+ }
+ return platform;
+ }
+
+ /*--------------------------------------------------------------------------*/
+
+ // Export platform.
+ var platform = parse();
+
+ // Some AMD build optimizers, like r.js, check for condition patterns like the following:
+ if (typeof define == 'function' && typeof define.amd == 'object' && define.amd) {
+ // Expose platform on the global object to prevent errors when platform is
+ // loaded by a script tag in the presence of an AMD loader.
+ // See http://requirejs.org/docs/errors.html#mismatch for more details.
+ root.platform = platform;
+
+ // Define as an anonymous module so platform can be aliased through path mapping.
+ define(function() {
+ return platform;
+ });
+ }
+ // Check for `exports` after `define` in case a build optimizer adds an `exports` object.
+ else if (freeExports && freeModule) {
+ // Export for CommonJS support.
+ forOwn(platform, function(value, key) {
+ freeExports[key] = value;
+ });
+ }
+ else {
+ // Export to the global object.
+ root.platform = platform;
+ }
+}.call(this));
+
+}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
+
+},{}],9:[function(require,module,exports){
+var v1 = require('./v1');
+var v4 = require('./v4');
+
+var uuid = v4;
+uuid.v1 = v1;
+uuid.v4 = v4;
+
+module.exports = uuid;
+
+},{"./v1":12,"./v4":13}],10:[function(require,module,exports){
+/**
+ * Convert array of 16 byte values to UUID string format of the form:
+ * XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
+ */
+var byteToHex = [];
+for (var i = 0; i < 256; ++i) {
+ byteToHex[i] = (i + 0x100).toString(16).substr(1);
+}
+
+function bytesToUuid(buf, offset) {
+ var i = offset || 0;
+ var bth = byteToHex;
+ // join used to fix memory issue caused by concatenation: https://bugs.chromium.org/p/v8/issues/detail?id=3175#c4
+ return ([bth[buf[i++]], bth[buf[i++]],
+ bth[buf[i++]], bth[buf[i++]], '-',
+ bth[buf[i++]], bth[buf[i++]], '-',
+ bth[buf[i++]], bth[buf[i++]], '-',
+ bth[buf[i++]], bth[buf[i++]], '-',
+ bth[buf[i++]], bth[buf[i++]],
+ bth[buf[i++]], bth[buf[i++]],
+ bth[buf[i++]], bth[buf[i++]]]).join('');
+}
+
+module.exports = bytesToUuid;
+
+},{}],11:[function(require,module,exports){
+// Unique ID creation requires a high quality random # generator. In the
+// browser this is a little complicated due to unknown quality of Math.random()
+// and inconsistent support for the `crypto` API. We do the best we can via
+// feature-detection
+
+// getRandomValues needs to be invoked in a context where "this" is a Crypto
+// implementation. Also, find the complete implementation of crypto on IE11.
+var getRandomValues = (typeof(crypto) != 'undefined' && crypto.getRandomValues && crypto.getRandomValues.bind(crypto)) ||
+ (typeof(msCrypto) != 'undefined' && typeof window.msCrypto.getRandomValues == 'function' && msCrypto.getRandomValues.bind(msCrypto));
+
+if (getRandomValues) {
+ // WHATWG crypto RNG - http://wiki.whatwg.org/wiki/Crypto
+ var rnds8 = new Uint8Array(16); // eslint-disable-line no-undef
+
+ module.exports = function whatwgRNG() {
+ getRandomValues(rnds8);
+ return rnds8;
+ };
+} else {
+ // Math.random()-based (RNG)
+ //
+ // If all else fails, use Math.random(). It's fast, but is of unspecified
+ // quality.
+ var rnds = new Array(16);
+
+ module.exports = function mathRNG() {
+ for (var i = 0, r; i < 16; i++) {
+ if ((i & 0x03) === 0) r = Math.random() * 0x100000000;
+ rnds[i] = r >>> ((i & 0x03) << 3) & 0xff;
+ }
+
+ return rnds;
+ };
+}
+
+},{}],12:[function(require,module,exports){
+var rng = require('./lib/rng');
+var bytesToUuid = require('./lib/bytesToUuid');
+
+// **`v1()` - Generate time-based UUID**
+//
+// Inspired by https://github.com/LiosK/UUID.js
+// and http://docs.python.org/library/uuid.html
+
+var _nodeId;
+var _clockseq;
+
+// Previous uuid creation time
+var _lastMSecs = 0;
+var _lastNSecs = 0;
+
+// See https://github.com/broofa/node-uuid for API details
+function v1(options, buf, offset) {
+ var i = buf && offset || 0;
+ var b = buf || [];
+
+ options = options || {};
+ var node = options.node || _nodeId;
+ var clockseq = options.clockseq !== undefined ? options.clockseq : _clockseq;
+
+ // node and clockseq need to be initialized to random values if they're not
+ // specified. We do this lazily to minimize issues related to insufficient
+ // system entropy. See #189
+ if (node == null || clockseq == null) {
+ var seedBytes = rng();
+ if (node == null) {
+ // Per 4.5, create and 48-bit node id, (47 random bits + multicast bit = 1)
+ node = _nodeId = [
+ seedBytes[0] | 0x01,
+ seedBytes[1], seedBytes[2], seedBytes[3], seedBytes[4], seedBytes[5]
+ ];
+ }
+ if (clockseq == null) {
+ // Per 4.2.2, randomize (14 bit) clockseq
+ clockseq = _clockseq = (seedBytes[6] << 8 | seedBytes[7]) & 0x3fff;
+ }
+ }
+
+ // UUID timestamps are 100 nano-second units since the Gregorian epoch,
+ // (1582-10-15 00:00). JSNumbers aren't precise enough for this, so
+ // time is handled internally as 'msecs' (integer milliseconds) and 'nsecs'
+ // (100-nanoseconds offset from msecs) since unix epoch, 1970-01-01 00:00.
+ var msecs = options.msecs !== undefined ? options.msecs : new Date().getTime();
+
+ // Per 4.2.1.2, use count of uuid's generated during the current clock
+ // cycle to simulate higher resolution clock
+ var nsecs = options.nsecs !== undefined ? options.nsecs : _lastNSecs + 1;
+
+ // Time since last uuid creation (in msecs)
+ var dt = (msecs - _lastMSecs) + (nsecs - _lastNSecs)/10000;
+
+ // Per 4.2.1.2, Bump clockseq on clock regression
+ if (dt < 0 && options.clockseq === undefined) {
+ clockseq = clockseq + 1 & 0x3fff;
+ }
+
+ // Reset nsecs if clock regresses (new clockseq) or we've moved onto a new
+ // time interval
+ if ((dt < 0 || msecs > _lastMSecs) && options.nsecs === undefined) {
+ nsecs = 0;
+ }
+
+ // Per 4.2.1.2 Throw error if too many uuids are requested
+ if (nsecs >= 10000) {
+ throw new Error('uuid.v1(): Can\'t create more than 10M uuids/sec');
+ }
+
+ _lastMSecs = msecs;
+ _lastNSecs = nsecs;
+ _clockseq = clockseq;
+
+ // Per 4.1.4 - Convert from unix epoch to Gregorian epoch
+ msecs += 12219292800000;
+
+ // `time_low`
+ var tl = ((msecs & 0xfffffff) * 10000 + nsecs) % 0x100000000;
+ b[i++] = tl >>> 24 & 0xff;
+ b[i++] = tl >>> 16 & 0xff;
+ b[i++] = tl >>> 8 & 0xff;
+ b[i++] = tl & 0xff;
+
+ // `time_mid`
+ var tmh = (msecs / 0x100000000 * 10000) & 0xfffffff;
+ b[i++] = tmh >>> 8 & 0xff;
+ b[i++] = tmh & 0xff;
+
+ // `time_high_and_version`
+ b[i++] = tmh >>> 24 & 0xf | 0x10; // include version
+ b[i++] = tmh >>> 16 & 0xff;
+
+ // `clock_seq_hi_and_reserved` (Per 4.2.2 - include variant)
+ b[i++] = clockseq >>> 8 | 0x80;
+
+ // `clock_seq_low`
+ b[i++] = clockseq & 0xff;
+
+ // `node`
+ for (var n = 0; n < 6; ++n) {
+ b[i + n] = node[n];
+ }
+
+ return buf ? buf : bytesToUuid(b);
+}
+
+module.exports = v1;
+
+},{"./lib/bytesToUuid":10,"./lib/rng":11}],13:[function(require,module,exports){
+var rng = require('./lib/rng');
+var bytesToUuid = require('./lib/bytesToUuid');
+
+function v4(options, buf, offset) {
+ var i = buf && offset || 0;
+
+ if (typeof(options) == 'string') {
+ buf = options === 'binary' ? new Array(16) : null;
+ options = null;
+ }
+ options = options || {};
+
+ var rnds = options.random || (options.rng || rng)();
+
+ // Per 4.4, set bits for version and `clock_seq_hi_and_reserved`
+ rnds[6] = (rnds[6] & 0x0f) | 0x40;
+ rnds[8] = (rnds[8] & 0x3f) | 0x80;
+
+ // Copy bytes to buffer, if provided
+ if (buf) {
+ for (var ii = 0; ii < 16; ++ii) {
+ buf[i + ii] = rnds[ii];
+ }
+ }
+
+ return buf || bytesToUuid(rnds);
+}
+
+module.exports = v4;
+
+},{"./lib/bytesToUuid":10,"./lib/rng":11}],14:[function(require,module,exports){
+/*
+WildEmitter.js is a slim little event emitter by @henrikjoreteg largely based
+on @visionmedia's Emitter from UI Kit.
+
+Why? I wanted it standalone.
+
+I also wanted support for wildcard emitters like this:
+
+emitter.on('*', function (eventName, other, event, payloads) {
+
+});
+
+emitter.on('somenamespace*', function (eventName, payloads) {
+
+});
+
+Please note that callbacks triggered by wildcard registered events also get
+the event name as the first argument.
+*/
+
+module.exports = WildEmitter;
+
+function WildEmitter() { }
+
+WildEmitter.mixin = function (constructor) {
+ var prototype = constructor.prototype || constructor;
+
+ prototype.isWildEmitter= true;
+
+ // Listen on the given `event` with `fn`. Store a group name if present.
+ prototype.on = function (event, groupName, fn) {
+ this.callbacks = this.callbacks || {};
+ var hasGroup = (arguments.length === 3),
+ group = hasGroup ? arguments[1] : undefined,
+ func = hasGroup ? arguments[2] : arguments[1];
+ func._groupName = group;
+ (this.callbacks[event] = this.callbacks[event] || []).push(func);
+ return this;
+ };
+
+ // Adds an `event` listener that will be invoked a single
+ // time then automatically removed.
+ prototype.once = function (event, groupName, fn) {
+ var self = this,
+ hasGroup = (arguments.length === 3),
+ group = hasGroup ? arguments[1] : undefined,
+ func = hasGroup ? arguments[2] : arguments[1];
+ function on() {
+ self.off(event, on);
+ func.apply(this, arguments);
+ }
+ this.on(event, group, on);
+ return this;
+ };
+
+ // Unbinds an entire group
+ prototype.releaseGroup = function (groupName) {
+ this.callbacks = this.callbacks || {};
+ var item, i, len, handlers;
+ for (item in this.callbacks) {
+ handlers = this.callbacks[item];
+ for (i = 0, len = handlers.length; i < len; i++) {
+ if (handlers[i]._groupName === groupName) {
+ //console.log('removing');
+ // remove it and shorten the array we're looping through
+ handlers.splice(i, 1);
+ i--;
+ len--;
+ }
+ }
+ }
+ return this;
+ };
+
+ // Remove the given callback for `event` or all
+ // registered callbacks.
+ prototype.off = function (event, fn) {
+ this.callbacks = this.callbacks || {};
+ var callbacks = this.callbacks[event],
+ i;
+
+ if (!callbacks) return this;
+
+ // remove all handlers
+ if (arguments.length === 1) {
+ delete this.callbacks[event];
+ return this;
+ }
+
+ // remove specific handler
+ i = callbacks.indexOf(fn);
+ callbacks.splice(i, 1);
+ if (callbacks.length === 0) {
+ delete this.callbacks[event];
+ }
+ return this;
+ };
+
+ /// Emit `event` with the given args.
+ // also calls any `*` handlers
+ prototype.emit = function (event) {
+ this.callbacks = this.callbacks || {};
+ var args = [].slice.call(arguments, 1),
+ callbacks = this.callbacks[event],
+ specialCallbacks = this.getWildcardCallbacks(event),
+ i,
+ len,
+ item,
+ listeners;
+
+ if (callbacks) {
+ listeners = callbacks.slice();
+ for (i = 0, len = listeners.length; i < len; ++i) {
+ if (!listeners[i]) {
+ break;
+ }
+ listeners[i].apply(this, args);
+ }
+ }
+
+ if (specialCallbacks) {
+ len = specialCallbacks.length;
+ listeners = specialCallbacks.slice();
+ for (i = 0, len = listeners.length; i < len; ++i) {
+ if (!listeners[i]) {
+ break;
+ }
+ listeners[i].apply(this, [event].concat(args));
+ }
+ }
+
+ return this;
+ };
+
+ // Helper for for finding special wildcard event handlers that match the event
+ prototype.getWildcardCallbacks = function (eventName) {
+ this.callbacks = this.callbacks || {};
+ var item,
+ split,
+ result = [];
+
+ for (item in this.callbacks) {
+ split = item.split('*');
+ if (item === '*' || (split.length === 2 && eventName.slice(0, split[0].length) === split[0])) {
+ result = result.concat(this.callbacks[item]);
+ }
+ }
+ return result;
+ };
+
+};
+
+WildEmitter.mixin(WildEmitter);
+
+},{}],15:[function(require,module,exports){
+/*!
+ * EventEmitter v5.2.5 - git.io/ee
+ * Unlicense - http://unlicense.org/
+ * Oliver Caldwell - http://oli.me.uk/
+ * @preserve
+ */
+
+;(function (exports) {
+ 'use strict';
+
+ /**
+ * Class for managing events.
+ * Can be extended to provide event functionality in other classes.
+ *
+ * @class EventEmitter Manages event registering and emitting.
+ */
+ function EventEmitter() {}
+
+ // Shortcuts to improve speed and size
+ var proto = EventEmitter.prototype;
+ var originalGlobalValue = exports.EventEmitter;
+
+ /**
+ * Finds the index of the listener for the event in its storage array.
+ *
+ * @param {Function[]} listeners Array of listeners to search through.
+ * @param {Function} listener Method to look for.
+ * @return {Number} Index of the specified listener, -1 if not found
+ * @api private
+ */
+ function indexOfListener(listeners, listener) {
+ var i = listeners.length;
+ while (i--) {
+ if (listeners[i].listener === listener) {
+ return i;
+ }
+ }
+
+ return -1;
+ }
+
+ /**
+ * Alias a method while keeping the context correct, to allow for overwriting of target method.
+ *
+ * @param {String} name The name of the target method.
+ * @return {Function} The aliased method
+ * @api private
+ */
+ function alias(name) {
+ return function aliasClosure() {
+ return this[name].apply(this, arguments);
+ };
+ }
+
+ /**
+ * Returns the listener array for the specified event.
+ * Will initialise the event object and listener arrays if required.
+ * Will return an object if you use a regex search. The object contains keys for each matched event. So /ba[rz]/ might return an object containing bar and baz. But only if you have either defined them with defineEvent or added some listeners to them.
+ * Each property in the object response is an array of listener functions.
+ *
+ * @param {String|RegExp} evt Name of the event to return the listeners from.
+ * @return {Function[]|Object} All listener functions for the event.
+ */
+ proto.getListeners = function getListeners(evt) {
+ var events = this._getEvents();
+ var response;
+ var key;
+
+ // Return a concatenated array of all matching events if
+ // the selector is a regular expression.
+ if (evt instanceof RegExp) {
+ response = {};
+ for (key in events) {
+ if (events.hasOwnProperty(key) && evt.test(key)) {
+ response[key] = events[key];
+ }
+ }
+ }
+ else {
+ response = events[evt] || (events[evt] = []);
+ }
+
+ return response;
+ };
+
+ /**
+ * Takes a list of listener objects and flattens it into a list of listener functions.
+ *
+ * @param {Object[]} listeners Raw listener objects.
+ * @return {Function[]} Just the listener functions.
+ */
+ proto.flattenListeners = function flattenListeners(listeners) {
+ var flatListeners = [];
+ var i;
+
+ for (i = 0; i < listeners.length; i += 1) {
+ flatListeners.push(listeners[i].listener);
+ }
+
+ return flatListeners;
+ };
+
+ /**
+ * Fetches the requested listeners via getListeners but will always return the results inside an object. This is mainly for internal use but others may find it useful.
+ *
+ * @param {String|RegExp} evt Name of the event to return the listeners from.
+ * @return {Object} All listener functions for an event in an object.
+ */
+ proto.getListenersAsObject = function getListenersAsObject(evt) {
+ var listeners = this.getListeners(evt);
+ var response;
+
+ if (listeners instanceof Array) {
+ response = {};
+ response[evt] = listeners;
+ }
+
+ return response || listeners;
+ };
+
+ function isValidListener (listener) {
+ if (typeof listener === 'function' || listener instanceof RegExp) {
+ return true
+ } else if (listener && typeof listener === 'object') {
+ return isValidListener(listener.listener)
+ } else {
+ return false
+ }
+ }
+
+ /**
+ * Adds a listener function to the specified event.
+ * The listener will not be added if it is a duplicate.
+ * If the listener returns true then it will be removed after it is called.
+ * If you pass a regular expression as the event name then the listener will be added to all events that match it.
+ *
+ * @param {String|RegExp} evt Name of the event to attach the listener to.
+ * @param {Function} listener Method to be called when the event is emitted. If the function returns true then it will be removed after calling.
+ * @return {Object} Current instance of EventEmitter for chaining.
+ */
+ proto.addListener = function addListener(evt, listener) {
+ if (!isValidListener(listener)) {
+ throw new TypeError('listener must be a function');
+ }
+
+ var listeners = this.getListenersAsObject(evt);
+ var listenerIsWrapped = typeof listener === 'object';
+ var key;
+
+ for (key in listeners) {
+ if (listeners.hasOwnProperty(key) && indexOfListener(listeners[key], listener) === -1) {
+ listeners[key].push(listenerIsWrapped ? listener : {
+ listener: listener,
+ once: false
+ });
+ }
+ }
+
+ return this;
+ };
+
+ /**
+ * Alias of addListener
+ */
+ proto.on = alias('addListener');
+
+ /**
+ * Semi-alias of addListener. It will add a listener that will be
+ * automatically removed after its first execution.
+ *
+ * @param {String|RegExp} evt Name of the event to attach the listener to.
+ * @param {Function} listener Method to be called when the event is emitted. If the function returns true then it will be removed after calling.
+ * @return {Object} Current instance of EventEmitter for chaining.
+ */
+ proto.addOnceListener = function addOnceListener(evt, listener) {
+ return this.addListener(evt, {
+ listener: listener,
+ once: true
+ });
+ };
+
+ /**
+ * Alias of addOnceListener.
+ */
+ proto.once = alias('addOnceListener');
+
+ /**
+ * Defines an event name. This is required if you want to use a regex to add a listener to multiple events at once. If you don't do this then how do you expect it to know what event to add to? Should it just add to every possible match for a regex? No. That is scary and bad.
+ * You need to tell it what event names should be matched by a regex.
+ *
+ * @param {String} evt Name of the event to create.
+ * @return {Object} Current instance of EventEmitter for chaining.
+ */
+ proto.defineEvent = function defineEvent(evt) {
+ this.getListeners(evt);
+ return this;
+ };
+
+ /**
+ * Uses defineEvent to define multiple events.
+ *
+ * @param {String[]} evts An array of event names to define.
+ * @return {Object} Current instance of EventEmitter for chaining.
+ */
+ proto.defineEvents = function defineEvents(evts) {
+ for (var i = 0; i < evts.length; i += 1) {
+ this.defineEvent(evts[i]);
+ }
+ return this;
+ };
+
+ /**
+ * Removes a listener function from the specified event.
+ * When passed a regular expression as the event name, it will remove the listener from all events that match it.
+ *
+ * @param {String|RegExp} evt Name of the event to remove the listener from.
+ * @param {Function} listener Method to remove from the event.
+ * @return {Object} Current instance of EventEmitter for chaining.
+ */
+ proto.removeListener = function removeListener(evt, listener) {
+ var listeners = this.getListenersAsObject(evt);
+ var index;
+ var key;
+
+ for (key in listeners) {
+ if (listeners.hasOwnProperty(key)) {
+ index = indexOfListener(listeners[key], listener);
+
+ if (index !== -1) {
+ listeners[key].splice(index, 1);
+ }
+ }
+ }
+
+ return this;
+ };
+
+ /**
+ * Alias of removeListener
+ */
+ proto.off = alias('removeListener');
+
+ /**
+ * Adds listeners in bulk using the manipulateListeners method.
+ * If you pass an object as the first argument you can add to multiple events at once. The object should contain key value pairs of events and listeners or listener arrays. You can also pass it an event name and an array of listeners to be added.
+ * You can also pass it a regular expression to add the array of listeners to all events that match it.
+ * Yeah, this function does quite a bit. That's probably a bad thing.
+ *
+ * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to add to multiple events at once.
+ * @param {Function[]} [listeners] An optional array of listener functions to add.
+ * @return {Object} Current instance of EventEmitter for chaining.
+ */
+ proto.addListeners = function addListeners(evt, listeners) {
+ // Pass through to manipulateListeners
+ return this.manipulateListeners(false, evt, listeners);
+ };
+
+ /**
+ * Removes listeners in bulk using the manipulateListeners method.
+ * If you pass an object as the first argument you can remove from multiple events at once. The object should contain key value pairs of events and listeners or listener arrays.
+ * You can also pass it an event name and an array of listeners to be removed.
+ * You can also pass it a regular expression to remove the listeners from all events that match it.
+ *
+ * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to remove from multiple events at once.
+ * @param {Function[]} [listeners] An optional array of listener functions to remove.
+ * @return {Object} Current instance of EventEmitter for chaining.
+ */
+ proto.removeListeners = function removeListeners(evt, listeners) {
+ // Pass through to manipulateListeners
+ return this.manipulateListeners(true, evt, listeners);
+ };
+
+ /**
+ * Edits listeners in bulk. The addListeners and removeListeners methods both use this to do their job. You should really use those instead, this is a little lower level.
+ * The first argument will determine if the listeners are removed (true) or added (false).
+ * If you pass an object as the second argument you can add/remove from multiple events at once. The object should contain key value pairs of events and listeners or listener arrays.
+ * You can also pass it an event name and an array of listeners to be added/removed.
+ * You can also pass it a regular expression to manipulate the listeners of all events that match it.
+ *
+ * @param {Boolean} remove True if you want to remove listeners, false if you want to add.
+ * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to add/remove from multiple events at once.
+ * @param {Function[]} [listeners] An optional array of listener functions to add/remove.
+ * @return {Object} Current instance of EventEmitter for chaining.
+ */
+ proto.manipulateListeners = function manipulateListeners(remove, evt, listeners) {
+ var i;
+ var value;
+ var single = remove ? this.removeListener : this.addListener;
+ var multiple = remove ? this.removeListeners : this.addListeners;
+
+ // If evt is an object then pass each of its properties to this method
+ if (typeof evt === 'object' && !(evt instanceof RegExp)) {
+ for (i in evt) {
+ if (evt.hasOwnProperty(i) && (value = evt[i])) {
+ // Pass the single listener straight through to the singular method
+ if (typeof value === 'function') {
+ single.call(this, i, value);
+ }
+ else {
+ // Otherwise pass back to the multiple function
+ multiple.call(this, i, value);
+ }
+ }
+ }
+ }
+ else {
+ // So evt must be a string
+ // And listeners must be an array of listeners
+ // Loop over it and pass each one to the multiple method
+ i = listeners.length;
+ while (i--) {
+ single.call(this, evt, listeners[i]);
+ }
+ }
+
+ return this;
+ };
+
+ /**
+ * Removes all listeners from a specified event.
+ * If you do not specify an event then all listeners will be removed.
+ * That means every event will be emptied.
+ * You can also pass a regex to remove all events that match it.
+ *
+ * @param {String|RegExp} [evt] Optional name of the event to remove all listeners for. Will remove from every event if not passed.
+ * @return {Object} Current instance of EventEmitter for chaining.
+ */
+ proto.removeEvent = function removeEvent(evt) {
+ var type = typeof evt;
+ var events = this._getEvents();
+ var key;
+
+ // Remove different things depending on the state of evt
+ if (type === 'string') {
+ // Remove all listeners for the specified event
+ delete events[evt];
+ }
+ else if (evt instanceof RegExp) {
+ // Remove all events matching the regex.
+ for (key in events) {
+ if (events.hasOwnProperty(key) && evt.test(key)) {
+ delete events[key];
+ }
+ }
+ }
+ else {
+ // Remove all listeners in all events
+ delete this._events;
+ }
+
+ return this;
+ };
+
+ /**
+ * Alias of removeEvent.
+ *
+ * Added to mirror the node API.
+ */
+ proto.removeAllListeners = alias('removeEvent');
+
+ /**
+ * Emits an event of your choice.
+ * When emitted, every listener attached to that event will be executed.
+ * If you pass the optional argument array then those arguments will be passed to every listener upon execution.
+ * Because it uses `apply`, your array of arguments will be passed as if you wrote them out separately.
+ * So they will not arrive within the array on the other side, they will be separate.
+ * You can also pass a regular expression to emit to all events that match it.
+ *
+ * @param {String|RegExp} evt Name of the event to emit and execute listeners for.
+ * @param {Array} [args] Optional array of arguments to be passed to each listener.
+ * @return {Object} Current instance of EventEmitter for chaining.
+ */
+ proto.emitEvent = function emitEvent(evt, args) {
+ var listenersMap = this.getListenersAsObject(evt);
+ var listeners;
+ var listener;
+ var i;
+ var key;
+ var response;
+
+ for (key in listenersMap) {
+ if (listenersMap.hasOwnProperty(key)) {
+ listeners = listenersMap[key].slice(0);
+
+ for (i = 0; i < listeners.length; i++) {
+ // If the listener returns true then it shall be removed from the event
+ // The function is executed either with a basic call or an apply if there is an args array
+ listener = listeners[i];
+
+ if (listener.once === true) {
+ this.removeListener(evt, listener.listener);
+ }
+
+ response = listener.listener.apply(this, args || []);
+
+ if (response === this._getOnceReturnValue()) {
+ this.removeListener(evt, listener.listener);
+ }
+ }
+ }
+ }
+
+ return this;
+ };
+
+ /**
+ * Alias of emitEvent
+ */
+ proto.trigger = alias('emitEvent');
+
+ /**
+ * Subtly different from emitEvent in that it will pass its arguments on to the listeners, as opposed to taking a single array of arguments to pass on.
+ * As with emitEvent, you can pass a regex in place of the event name to emit to all events that match it.
+ *
+ * @param {String|RegExp} evt Name of the event to emit and execute listeners for.
+ * @param {...*} Optional additional arguments to be passed to each listener.
+ * @return {Object} Current instance of EventEmitter for chaining.
+ */
+ proto.emit = function emit(evt) {
+ var args = Array.prototype.slice.call(arguments, 1);
+ return this.emitEvent(evt, args);
+ };
+
+ /**
+ * Sets the current value to check against when executing listeners. If a
+ * listeners return value matches the one set here then it will be removed
+ * after execution. This value defaults to true.
+ *
+ * @param {*} value The new value to check for when executing listeners.
+ * @return {Object} Current instance of EventEmitter for chaining.
+ */
+ proto.setOnceReturnValue = function setOnceReturnValue(value) {
+ this._onceReturnValue = value;
+ return this;
+ };
+
+ /**
+ * Fetches the current value to check against when executing listeners. If
+ * the listeners return value matches this one then it should be removed
+ * automatically. It will return true by default.
+ *
+ * @return {*|Boolean} The current value to check for or the default, true.
+ * @api private
+ */
+ proto._getOnceReturnValue = function _getOnceReturnValue() {
+ if (this.hasOwnProperty('_onceReturnValue')) {
+ return this._onceReturnValue;
+ }
+ else {
+ return true;
+ }
+ };
+
+ /**
+ * Fetches the events object and creates one if required.
+ *
+ * @return {Object} The events storage object.
+ * @api private
+ */
+ proto._getEvents = function _getEvents() {
+ return this._events || (this._events = {});
+ };
+
+ /**
+ * Reverts the global {@link EventEmitter} to its previous value and returns a reference to this version.
+ *
+ * @return {Function} Non conflicting EventEmitter class.
+ */
+ EventEmitter.noConflict = function noConflict() {
+ exports.EventEmitter = originalGlobalValue;
+ return EventEmitter;
+ };
+
+ // Expose the class either via AMD, CommonJS or the global object
+ if (typeof define === 'function' && define.amd) {
+ define(function () {
+ return EventEmitter;
+ });
+ }
+ else if (typeof module === 'object' && module.exports){
+ module.exports = EventEmitter;
+ }
+ else {
+ exports.EventEmitter = EventEmitter;
+ }
+}(typeof window !== 'undefined' ? window : this || {}));
+
+},{}],16:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+var OpenVidu_1 = require("./OpenVidu/OpenVidu");
+if (window) {
+ window['OpenVidu'] = OpenVidu_1.OpenVidu;
+}
+
+},{"./OpenVidu/OpenVidu":19}],17:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+var Stream_1 = require("./Stream");
+var Connection = (function () {
+ function Connection(session, opts) {
+ this.session = session;
+ this.disposed = false;
+ var msg = "'Connection' created ";
+ if (!!opts) {
+ msg += "(remote) with 'connectionId' [" + opts.id + ']';
+ }
+ else {
+ msg += '(local)';
+ }
+ console.info(msg);
+ this.options = opts;
+ if (!!opts) {
+ this.connectionId = opts.id;
+ if (opts.metadata) {
+ this.data = opts.metadata;
+ }
+ if (opts.streams) {
+ this.initRemoteStreams(opts.streams);
+ }
+ }
+ this.creationTime = new Date().getTime();
+ }
+ Connection.prototype.sendIceCandidate = function (candidate) {
+ console.debug((!!this.stream.outboundStreamOpts ? 'Local' : 'Remote'), 'candidate for', this.connectionId, JSON.stringify(candidate));
+ this.session.openvidu.sendRequest('onIceCandidate', {
+ endpointName: this.connectionId,
+ candidate: candidate.candidate,
+ sdpMid: candidate.sdpMid,
+ sdpMLineIndex: candidate.sdpMLineIndex
+ }, function (error, response) {
+ if (error) {
+ console.error('Error sending ICE candidate: '
+ + JSON.stringify(error));
+ }
+ });
+ };
+ Connection.prototype.initRemoteStreams = function (options) {
+ var _this = this;
+ options.forEach(function (opts) {
+ var streamOptions = {
+ id: opts.id,
+ connection: _this,
+ hasAudio: opts.hasAudio,
+ hasVideo: opts.hasVideo,
+ audioActive: opts.audioActive,
+ videoActive: opts.videoActive,
+ typeOfVideo: opts.typeOfVideo,
+ frameRate: opts.frameRate,
+ videoDimensions: !!opts.videoDimensions ? JSON.parse(opts.videoDimensions) : undefined
+ };
+ var stream = new Stream_1.Stream(_this.session, streamOptions);
+ _this.addStream(stream);
+ });
+ console.info("Remote 'Connection' with 'connectionId' [" + this.connectionId + '] is now configured for receiving Streams with options: ', this.stream.inboundStreamOpts);
+ };
+ Connection.prototype.addStream = function (stream) {
+ stream.connection = this;
+ this.stream = stream;
+ };
+ Connection.prototype.removeStream = function (streamId) {
+ delete this.stream;
+ };
+ Connection.prototype.dispose = function () {
+ if (!!this.stream) {
+ delete this.stream;
+ }
+ this.disposed = true;
+ };
+ return Connection;
+}());
+exports.Connection = Connection;
+
+},{"./Stream":22}],18:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+var LocalRecorderState_1 = require("../OpenViduInternal/Enums/LocalRecorderState");
+var LocalRecorder = (function () {
+ function LocalRecorder(stream) {
+ this.stream = stream;
+ this.chunks = [];
+ this.count = 0;
+ this.connectionId = (!!this.stream.connection) ? this.stream.connection.connectionId : 'default-connection';
+ this.id = this.stream.streamId + '_' + this.connectionId + '_localrecord';
+ this.state = LocalRecorderState_1.LocalRecorderState.READY;
+ }
+ LocalRecorder.prototype.record = function () {
+ var _this = this;
+ return new Promise(function (resolve, reject) {
+ try {
+ if (typeof MediaRecorder === 'undefined') {
+ console.error('MediaRecorder not supported on your browser. See compatibility in https://caniuse.com/#search=MediaRecorder');
+ throw (Error('MediaRecorder not supported on your browser. See compatibility in https://caniuse.com/#search=MediaRecorder'));
+ }
+ if (_this.state !== LocalRecorderState_1.LocalRecorderState.READY) {
+ throw (Error('\'LocalRecord.record()\' needs \'LocalRecord.state\' to be \'READY\' (current value: \'' + _this.state + '\'). Call \'LocalRecorder.clean()\' or init a new LocalRecorder before'));
+ }
+ console.log("Starting local recording of stream '" + _this.stream.streamId + "' of connection '" + _this.connectionId + "'");
+ if (typeof MediaRecorder.isTypeSupported === 'function') {
+ var options = void 0;
+ if (MediaRecorder.isTypeSupported('video/webm;codecs=vp9')) {
+ options = { mimeType: 'video/webm;codecs=vp9' };
+ }
+ else if (MediaRecorder.isTypeSupported('video/webm;codecs=h264')) {
+ options = { mimeType: 'video/webm;codecs=h264' };
+ }
+ else if (MediaRecorder.isTypeSupported('video/webm;codecs=vp8')) {
+ options = { mimeType: 'video/webm;codecs=vp8' };
+ }
+ console.log('Using mimeType ' + options.mimeType);
+ _this.mediaRecorder = new MediaRecorder(_this.stream.getMediaStream(), options);
+ }
+ else {
+ console.warn('isTypeSupported is not supported, using default codecs for browser');
+ _this.mediaRecorder = new MediaRecorder(_this.stream.getMediaStream());
+ }
+ _this.mediaRecorder.start(10);
+ }
+ catch (err) {
+ reject(err);
+ }
+ _this.mediaRecorder.ondataavailable = function (e) {
+ _this.chunks.push(e.data);
+ };
+ _this.mediaRecorder.onerror = function (e) {
+ console.error('MediaRecorder error: ', e);
+ };
+ _this.mediaRecorder.onstart = function () {
+ console.log('MediaRecorder started (state=' + _this.mediaRecorder.state + ')');
+ };
+ _this.mediaRecorder.onstop = function () {
+ _this.onStopDefault();
+ };
+ _this.mediaRecorder.onpause = function () {
+ console.log('MediaRecorder paused (state=' + _this.mediaRecorder.state + ')');
+ };
+ _this.mediaRecorder.onresume = function () {
+ console.log('MediaRecorder resumed (state=' + _this.mediaRecorder.state + ')');
+ };
+ _this.mediaRecorder.onwarning = function (e) {
+ console.log('MediaRecorder warning: ' + e);
+ };
+ _this.state = LocalRecorderState_1.LocalRecorderState.RECORDING;
+ resolve();
+ });
+ };
+ LocalRecorder.prototype.stop = function () {
+ var _this = this;
+ return new Promise(function (resolve, reject) {
+ try {
+ if (_this.state === LocalRecorderState_1.LocalRecorderState.READY || _this.state === LocalRecorderState_1.LocalRecorderState.FINISHED) {
+ throw (Error('\'LocalRecord.stop()\' needs \'LocalRecord.state\' to be \'RECORDING\' or \'PAUSED\' (current value: \'' + _this.state + '\'). Call \'LocalRecorder.start()\' before'));
+ }
+ _this.mediaRecorder.onstop = function () {
+ _this.onStopDefault();
+ resolve();
+ };
+ _this.mediaRecorder.stop();
+ }
+ catch (e) {
+ reject(e);
+ }
+ });
+ };
+ LocalRecorder.prototype.pause = function () {
+ var _this = this;
+ return new Promise(function (resolve, reject) {
+ try {
+ if (_this.state !== LocalRecorderState_1.LocalRecorderState.RECORDING) {
+ reject(Error('\'LocalRecord.pause()\' needs \'LocalRecord.state\' to be \'RECORDING\' (current value: \'' + _this.state + '\'). Call \'LocalRecorder.start()\' or \'LocalRecorder.resume()\' before'));
+ }
+ _this.mediaRecorder.pause();
+ _this.state = LocalRecorderState_1.LocalRecorderState.PAUSED;
+ }
+ catch (error) {
+ reject(error);
+ }
+ });
+ };
+ LocalRecorder.prototype.resume = function () {
+ var _this = this;
+ return new Promise(function (resolve, reject) {
+ try {
+ if (_this.state !== LocalRecorderState_1.LocalRecorderState.PAUSED) {
+ throw (Error('\'LocalRecord.resume()\' needs \'LocalRecord.state\' to be \'PAUSED\' (current value: \'' + _this.state + '\'). Call \'LocalRecorder.pause()\' before'));
+ }
+ _this.mediaRecorder.resume();
+ _this.state = LocalRecorderState_1.LocalRecorderState.RECORDING;
+ }
+ catch (error) {
+ reject(error);
+ }
+ });
+ };
+ LocalRecorder.prototype.preview = function (parentElement) {
+ if (this.state !== LocalRecorderState_1.LocalRecorderState.FINISHED) {
+ throw (Error('\'LocalRecord.preview()\' needs \'LocalRecord.state\' to be \'FINISHED\' (current value: \'' + this.state + '\'). Call \'LocalRecorder.stop()\' before'));
+ }
+ this.videoPreview = document.createElement('video');
+ this.videoPreview.id = this.id;
+ this.videoPreview.autoplay = true;
+ if (typeof parentElement === 'string') {
+ this.htmlParentElementId = parentElement;
+ var parentElementDom = document.getElementById(parentElement);
+ if (parentElementDom) {
+ this.videoPreview = parentElementDom.appendChild(this.videoPreview);
+ }
+ }
+ else {
+ this.htmlParentElementId = parentElement.id;
+ this.videoPreview = parentElement.appendChild(this.videoPreview);
+ }
+ this.videoPreview.src = this.videoPreviewSrc;
+ return this.videoPreview;
+ };
+ LocalRecorder.prototype.clean = function () {
+ var _this = this;
+ var f = function () {
+ delete _this.blob;
+ _this.chunks = [];
+ _this.count = 0;
+ delete _this.mediaRecorder;
+ _this.state = LocalRecorderState_1.LocalRecorderState.READY;
+ };
+ if (this.state === LocalRecorderState_1.LocalRecorderState.RECORDING || this.state === LocalRecorderState_1.LocalRecorderState.PAUSED) {
+ this.stop().then(function () { return f(); }).catch(function () { return f(); });
+ }
+ else {
+ f();
+ }
+ };
+ LocalRecorder.prototype.download = function () {
+ if (this.state !== LocalRecorderState_1.LocalRecorderState.FINISHED) {
+ throw (Error('\'LocalRecord.download()\' needs \'LocalRecord.state\' to be \'FINISHED\' (current value: \'' + this.state + '\'). Call \'LocalRecorder.stop()\' before'));
+ }
+ else {
+ var a = document.createElement('a');
+ a.style.display = 'none';
+ document.body.appendChild(a);
+ var url = window.URL.createObjectURL(this.blob);
+ a.href = url;
+ a.download = this.id + '.webm';
+ a.click();
+ window.URL.revokeObjectURL(url);
+ document.body.removeChild(a);
+ }
+ };
+ LocalRecorder.prototype.getBlob = function () {
+ if (this.state !== LocalRecorderState_1.LocalRecorderState.FINISHED) {
+ throw (Error('Call \'LocalRecord.stop()\' before getting Blob file'));
+ }
+ else {
+ return this.blob;
+ }
+ };
+ LocalRecorder.prototype.uploadAsBinary = function (endpoint, headers) {
+ var _this = this;
+ return new Promise(function (resolve, reject) {
+ if (_this.state !== LocalRecorderState_1.LocalRecorderState.FINISHED) {
+ reject(Error('\'LocalRecord.uploadAsBinary()\' needs \'LocalRecord.state\' to be \'FINISHED\' (current value: \'' + _this.state + '\'). Call \'LocalRecorder.stop()\' before'));
+ }
+ else {
+ var http_1 = new XMLHttpRequest();
+ http_1.open('POST', endpoint, true);
+ if (typeof headers === 'object') {
+ for (var _i = 0, _a = Object.keys(headers); _i < _a.length; _i++) {
+ var key = _a[_i];
+ http_1.setRequestHeader(key, headers[key]);
+ }
+ }
+ http_1.onreadystatechange = function () {
+ if (http_1.readyState === 4) {
+ if (http_1.status.toString().charAt(0) === '2') {
+ resolve(http_1.responseText);
+ }
+ else {
+ reject(http_1.status);
+ }
+ }
+ };
+ http_1.send(_this.blob);
+ }
+ });
+ };
+ LocalRecorder.prototype.uploadAsMultipartfile = function (endpoint, headers) {
+ var _this = this;
+ return new Promise(function (resolve, reject) {
+ if (_this.state !== LocalRecorderState_1.LocalRecorderState.FINISHED) {
+ reject(Error('\'LocalRecord.uploadAsMultipartfile()\' needs \'LocalRecord.state\' to be \'FINISHED\' (current value: \'' + _this.state + '\'). Call \'LocalRecorder.stop()\' before'));
+ }
+ else {
+ var http_2 = new XMLHttpRequest();
+ http_2.open('POST', endpoint, true);
+ if (typeof headers === 'object') {
+ for (var _i = 0, _a = Object.keys(headers); _i < _a.length; _i++) {
+ var key = _a[_i];
+ http_2.setRequestHeader(key, headers[key]);
+ }
+ }
+ var sendable = new FormData();
+ sendable.append('file', _this.blob, _this.id + '.webm');
+ http_2.onreadystatechange = function () {
+ if (http_2.readyState === 4) {
+ if (http_2.status.toString().charAt(0) === '2') {
+ resolve(http_2.responseText);
+ }
+ else {
+ reject(http_2.status);
+ }
+ }
+ };
+ http_2.send(sendable);
+ }
+ });
+ };
+ LocalRecorder.prototype.onStopDefault = function () {
+ console.log('MediaRecorder stopped (state=' + this.mediaRecorder.state + ')');
+ this.blob = new Blob(this.chunks, { type: 'video/webm' });
+ this.chunks = [];
+ this.videoPreviewSrc = window.URL.createObjectURL(this.blob);
+ this.state = LocalRecorderState_1.LocalRecorderState.FINISHED;
+ };
+ return LocalRecorder;
+}());
+exports.LocalRecorder = LocalRecorder;
+
+},{"../OpenViduInternal/Enums/LocalRecorderState":25}],19:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+var LocalRecorder_1 = require("./LocalRecorder");
+var Publisher_1 = require("./Publisher");
+var Session_1 = require("./Session");
+var StreamPropertyChangedEvent_1 = require("../OpenViduInternal/Events/StreamPropertyChangedEvent");
+var OpenViduError_1 = require("../OpenViduInternal/Enums/OpenViduError");
+var VideoInsertMode_1 = require("../OpenViduInternal/Enums/VideoInsertMode");
+var screenSharingAuto = require("../OpenViduInternal/ScreenSharing/Screen-Capturing-Auto");
+var screenSharing = require("../OpenViduInternal/ScreenSharing/Screen-Capturing");
+var RpcBuilder = require("../OpenViduInternal/KurentoUtils/kurento-jsonrpc");
+var platform = require("platform");
+var OpenVidu = (function () {
+ function OpenVidu() {
+ var _this = this;
+ this.publishers = [];
+ this.secret = '';
+ this.recorder = false;
+ this.advancedConfiguration = {};
+ console.info("'OpenVidu' initialized");
+ if (platform.name.toLowerCase().indexOf('mobile') !== -1) {
+ window.onorientationchange = function () {
+ _this.publishers.forEach(function (publisher) {
+ if (!!publisher.stream && !!publisher.stream.hasVideo && !!publisher.stream.streamManager.videos[0]) {
+ var attempts_1 = 0;
+ var oldWidth_1 = publisher.stream.videoDimensions.width;
+ var oldHeight_1 = publisher.stream.videoDimensions.height;
+ var firefoxSettings_1 = publisher.stream.getMediaStream().getVideoTracks()[0].getSettings();
+ var newWidth_1 = (platform.name.toLowerCase().indexOf('firefox') !== -1) ? firefoxSettings_1.width : publisher.videoReference.videoWidth;
+ var newHeight_1 = (platform.name.toLowerCase().indexOf('firefox') !== -1) ? firefoxSettings_1.height : publisher.videoReference.videoHeight;
+ var repeatUntilChange_1 = setInterval(function () {
+ firefoxSettings_1 = publisher.stream.getMediaStream().getVideoTracks()[0].getSettings();
+ newWidth_1 = (platform.name.toLowerCase().indexOf('firefox') !== -1) ? firefoxSettings_1.width : publisher.videoReference.videoWidth;
+ newHeight_1 = (platform.name.toLowerCase().indexOf('firefox') !== -1) ? firefoxSettings_1.height : publisher.videoReference.videoHeight;
+ sendStreamPropertyChangedEvent_1(oldWidth_1, oldHeight_1, newWidth_1, newHeight_1);
+ }, 100);
+ var sendStreamPropertyChangedEvent_1 = function (oldWidth, oldHeight, newWidth, newHeight) {
+ attempts_1++;
+ if (attempts_1 > 4) {
+ clearTimeout(repeatUntilChange_1);
+ }
+ if (newWidth !== oldWidth || newHeight !== oldHeight) {
+ publisher.stream.videoDimensions = {
+ width: newWidth || 0,
+ height: newHeight || 0
+ };
+ _this.sendRequest('streamPropertyChanged', {
+ streamId: publisher.stream.streamId,
+ property: 'videoDimensions',
+ newValue: JSON.stringify(publisher.stream.videoDimensions),
+ reason: 'deviceRotated'
+ }, function (error, response) {
+ if (error) {
+ console.error("Error sending 'streamPropertyChanged' event", error);
+ }
+ else {
+ _this.session.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent_1.StreamPropertyChangedEvent(_this.session, publisher.stream, 'videoDimensions', publisher.stream.videoDimensions, { width: oldWidth, height: oldHeight }, 'deviceRotated')]);
+ publisher.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent_1.StreamPropertyChangedEvent(publisher, publisher.stream, 'videoDimensions', publisher.stream.videoDimensions, { width: oldWidth, height: oldHeight }, 'deviceRotated')]);
+ }
+ });
+ clearTimeout(repeatUntilChange_1);
+ }
+ };
+ }
+ });
+ };
+ }
+ }
+ OpenVidu.prototype.initSession = function () {
+ this.session = new Session_1.Session(this);
+ return this.session;
+ };
+ OpenVidu.prototype.initPublisher = function (targetElement, param2, param3) {
+ var properties;
+ if (!!param2 && (typeof param2 !== 'function')) {
+ properties = param2;
+ properties = {
+ audioSource: (typeof properties.audioSource !== 'undefined') ? properties.audioSource : undefined,
+ frameRate: this.isMediaStreamTrack(properties.videoSource) ? undefined : ((typeof properties.frameRate !== 'undefined') ? properties.frameRate : undefined),
+ insertMode: (typeof properties.insertMode !== 'undefined') ? ((typeof properties.insertMode === 'string') ? VideoInsertMode_1.VideoInsertMode[properties.insertMode] : properties.insertMode) : VideoInsertMode_1.VideoInsertMode.APPEND,
+ mirror: (typeof properties.mirror !== 'undefined') ? properties.mirror : true,
+ publishAudio: (typeof properties.publishAudio !== 'undefined') ? properties.publishAudio : true,
+ publishVideo: (typeof properties.publishVideo !== 'undefined') ? properties.publishVideo : true,
+ resolution: this.isMediaStreamTrack(properties.videoSource) ? undefined : ((typeof properties.resolution !== 'undefined') ? properties.resolution : '640x480'),
+ videoSource: (typeof properties.videoSource !== 'undefined') ? properties.videoSource : undefined
+ };
+ }
+ else {
+ properties = {
+ insertMode: VideoInsertMode_1.VideoInsertMode.APPEND,
+ mirror: true,
+ publishAudio: true,
+ publishVideo: true,
+ resolution: '640x480'
+ };
+ }
+ var publisher = new Publisher_1.Publisher(targetElement, properties, this);
+ var completionHandler;
+ if (!!param2 && (typeof param2 === 'function')) {
+ completionHandler = param2;
+ }
+ else if (!!param3) {
+ completionHandler = param3;
+ }
+ publisher.initialize()
+ .then(function () {
+ if (completionHandler !== undefined) {
+ completionHandler(undefined);
+ }
+ publisher.emitEvent('accessAllowed', []);
+ }).catch(function (error) {
+ if (completionHandler !== undefined) {
+ completionHandler(error);
+ }
+ publisher.emitEvent('accessDenied', []);
+ });
+ this.publishers.push(publisher);
+ return publisher;
+ };
+ OpenVidu.prototype.initPublisherAsync = function (targetElement, properties) {
+ var _this = this;
+ return new Promise(function (resolve, reject) {
+ var publisher;
+ var callback = function (error) {
+ if (!!error) {
+ reject(error);
+ }
+ else {
+ resolve(publisher);
+ }
+ };
+ if (!!properties) {
+ publisher = _this.initPublisher(targetElement, properties, callback);
+ }
+ else {
+ publisher = _this.initPublisher(targetElement, callback);
+ }
+ });
+ };
+ OpenVidu.prototype.initLocalRecorder = function (stream) {
+ return new LocalRecorder_1.LocalRecorder(stream);
+ };
+ OpenVidu.prototype.checkSystemRequirements = function () {
+ var browser = platform.name;
+ var version = platform.version;
+ if ((browser !== 'Chrome') && (browser !== 'Chrome Mobile') &&
+ (browser !== 'Firefox') && (browser !== 'Firefox Mobile') && (browser !== 'Firefox for iOS') &&
+ (browser !== 'Opera') && (browser !== 'Opera Mobile') &&
+ (browser !== 'Safari')) {
+ return 0;
+ }
+ else {
+ return 1;
+ }
+ };
+ OpenVidu.prototype.getDevices = function () {
+ return new Promise(function (resolve, reject) {
+ navigator.mediaDevices.enumerateDevices().then(function (deviceInfos) {
+ var devices = [];
+ deviceInfos.forEach(function (deviceInfo) {
+ if (deviceInfo.kind === 'audioinput' || deviceInfo.kind === 'videoinput') {
+ devices.push({
+ kind: deviceInfo.kind,
+ deviceId: deviceInfo.deviceId,
+ label: deviceInfo.label
+ });
+ }
+ });
+ resolve(devices);
+ }).catch(function (error) {
+ console.error('Error getting devices', error);
+ reject(error);
+ });
+ });
+ };
+ OpenVidu.prototype.getUserMedia = function (options) {
+ var _this = this;
+ return new Promise(function (resolve, reject) {
+ _this.generateMediaConstraints(options)
+ .then(function (constraints) {
+ navigator.mediaDevices.getUserMedia(constraints)
+ .then(function (mediaStream) {
+ resolve(mediaStream);
+ })
+ .catch(function (error) {
+ var errorName;
+ var errorMessage = error.toString();
+ if (!(options.videoSource === 'screen')) {
+ errorName = OpenViduError_1.OpenViduErrorName.DEVICE_ACCESS_DENIED;
+ }
+ else {
+ errorName = OpenViduError_1.OpenViduErrorName.SCREEN_CAPTURE_DENIED;
+ }
+ reject(new OpenViduError_1.OpenViduError(errorName, errorMessage));
+ });
+ })
+ .catch(function (error) {
+ reject(error);
+ });
+ });
+ };
+ OpenVidu.prototype.enableProdMode = function () {
+ console.log = function () { };
+ console.debug = function () { };
+ console.info = function () { };
+ console.warn = function () { };
+ };
+ OpenVidu.prototype.setAdvancedConfiguration = function (configuration) {
+ this.advancedConfiguration = configuration;
+ };
+ OpenVidu.prototype.generateMediaConstraints = function (publisherProperties) {
+ var _this = this;
+ return new Promise(function (resolve, reject) {
+ var audio, video;
+ if (publisherProperties.audioSource === null || publisherProperties.audioSource === false) {
+ audio = false;
+ }
+ else if (publisherProperties.audioSource === undefined) {
+ audio = true;
+ }
+ else {
+ audio = publisherProperties.audioSource;
+ }
+ if (publisherProperties.videoSource === null || publisherProperties.videoSource === false) {
+ video = false;
+ }
+ else {
+ video = {
+ height: {
+ ideal: 480
+ },
+ width: {
+ ideal: 640
+ }
+ };
+ }
+ var mediaConstraints = {
+ audio: audio,
+ video: video
+ };
+ if (typeof mediaConstraints.audio === 'string') {
+ mediaConstraints.audio = { deviceId: { exact: mediaConstraints.audio } };
+ }
+ if (mediaConstraints.video) {
+ if (!!publisherProperties.resolution) {
+ var widthAndHeight = publisherProperties.resolution.toLowerCase().split('x');
+ var width = Number(widthAndHeight[0]);
+ var height = Number(widthAndHeight[1]);
+ mediaConstraints.video.width.ideal = width;
+ mediaConstraints.video.height.ideal = height;
+ }
+ if (!!publisherProperties.frameRate) {
+ mediaConstraints.video.frameRate = { ideal: publisherProperties.frameRate };
+ }
+ if (!!publisherProperties.videoSource && typeof publisherProperties.videoSource === 'string') {
+ if (publisherProperties.videoSource === 'screen') {
+ if (platform.name !== 'Chrome' && platform.name.indexOf('Firefox') === -1) {
+ var error = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_SHARING_NOT_SUPPORTED, 'You can only screen share in desktop Chrome and Firefox. Detected browser: ' + platform.name);
+ console.error(error);
+ reject(error);
+ }
+ else {
+ if (!!_this.advancedConfiguration.screenShareChromeExtension && !(platform.name.indexOf('Firefox') !== -1)) {
+ screenSharing.getScreenConstraints(function (error, screenConstraints) {
+ if (!!error || !!screenConstraints.mandatory && screenConstraints.mandatory.chromeMediaSource === 'screen') {
+ if (error === 'permission-denied' || error === 'PermissionDeniedError') {
+ var error_1 = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_CAPTURE_DENIED, 'You must allow access to one window of your desktop');
+ console.error(error_1);
+ reject(error_1);
+ }
+ else {
+ var extensionId = _this.advancedConfiguration.screenShareChromeExtension.split('/').pop().trim();
+ screenSharing.getChromeExtensionStatus(extensionId, function (status) {
+ if (status === 'installed-disabled') {
+ var error_2 = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_EXTENSION_DISABLED, 'You must enable the screen extension');
+ console.error(error_2);
+ reject(error_2);
+ }
+ if (status === 'not-installed') {
+ var error_3 = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_EXTENSION_NOT_INSTALLED, _this.advancedConfiguration.screenShareChromeExtension);
+ console.error(error_3);
+ reject(error_3);
+ }
+ });
+ }
+ }
+ else {
+ mediaConstraints.video = screenConstraints;
+ resolve(mediaConstraints);
+ }
+ });
+ }
+ else {
+ screenSharingAuto.getScreenId(function (error, sourceId, screenConstraints) {
+ if (!!error) {
+ if (error === 'not-installed') {
+ var extensionUrl = !!_this.advancedConfiguration.screenShareChromeExtension ? _this.advancedConfiguration.screenShareChromeExtension :
+ 'https://chrome.google.com/webstore/detail/openvidu-screensharing/lfcgfepafnobdloecchnfaclibenjold';
+ var error_4 = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_EXTENSION_NOT_INSTALLED, extensionUrl);
+ console.error(error_4);
+ reject(error_4);
+ }
+ else if (error === 'installed-disabled') {
+ var error_5 = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_EXTENSION_DISABLED, 'You must enable the screen extension');
+ console.error(error_5);
+ reject(error_5);
+ }
+ else if (error === 'permission-denied') {
+ var error_6 = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_CAPTURE_DENIED, 'You must allow access to one window of your desktop');
+ console.error(error_6);
+ reject(error_6);
+ }
+ }
+ else {
+ mediaConstraints.video = screenConstraints.video;
+ resolve(mediaConstraints);
+ }
+ });
+ }
+ publisherProperties.videoSource = 'screen';
+ }
+ }
+ else {
+ mediaConstraints.video['deviceId'] = { exact: publisherProperties.videoSource };
+ resolve(mediaConstraints);
+ }
+ }
+ else {
+ resolve(mediaConstraints);
+ }
+ }
+ else {
+ resolve(mediaConstraints);
+ }
+ });
+ };
+ OpenVidu.prototype.startWs = function (onConnectSucces) {
+ var config = {
+ heartbeat: 5000,
+ sendCloseMessage: false,
+ ws: {
+ uri: this.wsUri,
+ useSockJS: false,
+ onconnected: onConnectSucces,
+ ondisconnect: this.disconnectCallback.bind(this),
+ onreconnecting: this.reconnectingCallback.bind(this),
+ onreconnected: this.reconnectedCallback.bind(this)
+ },
+ rpc: {
+ requestTimeout: 10000,
+ participantJoined: this.session.onParticipantJoined.bind(this.session),
+ participantPublished: this.session.onParticipantPublished.bind(this.session),
+ participantUnpublished: this.session.onParticipantUnpublished.bind(this.session),
+ participantLeft: this.session.onParticipantLeft.bind(this.session),
+ participantEvicted: this.session.onParticipantEvicted.bind(this.session),
+ recordingStarted: this.session.onRecordingStarted.bind(this.session),
+ recordingStopped: this.session.onRecordingStopped.bind(this.session),
+ sendMessage: this.session.onNewMessage.bind(this.session),
+ streamPropertyChanged: this.session.onStreamPropertyChanged.bind(this.session),
+ iceCandidate: this.session.recvIceCandidate.bind(this.session),
+ mediaError: this.session.onMediaError.bind(this.session)
+ }
+ };
+ this.jsonRpcClient = new RpcBuilder.clients.JsonRpcClient(config);
+ };
+ OpenVidu.prototype.closeWs = function () {
+ this.jsonRpcClient.close();
+ };
+ OpenVidu.prototype.sendRequest = function (method, params, callback) {
+ if (params && params instanceof Function) {
+ callback = params;
+ params = {};
+ }
+ console.debug('Sending request: {method:"' + method + '", params: ' + JSON.stringify(params) + '}');
+ this.jsonRpcClient.send(method, params, callback);
+ };
+ OpenVidu.prototype.isMediaStreamTrack = function (mediaSource) {
+ var is = (!!mediaSource &&
+ mediaSource.enabled !== undefined && typeof mediaSource.enabled === 'boolean' &&
+ mediaSource.id !== undefined && typeof mediaSource.id === 'string' &&
+ mediaSource.kind !== undefined && typeof mediaSource.kind === 'string' &&
+ mediaSource.label !== undefined && typeof mediaSource.label === 'string' &&
+ mediaSource.muted !== undefined && typeof mediaSource.muted === 'boolean' &&
+ mediaSource.readyState !== undefined && typeof mediaSource.readyState === 'string');
+ return is;
+ };
+ OpenVidu.prototype.getWsUri = function () {
+ return this.wsUri;
+ };
+ OpenVidu.prototype.getSecret = function () {
+ return this.secret;
+ };
+ OpenVidu.prototype.getRecorder = function () {
+ return this.recorder;
+ };
+ OpenVidu.prototype.disconnectCallback = function () {
+ console.warn('Websocket connection lost');
+ if (this.isRoomAvailable()) {
+ this.session.onLostConnection();
+ }
+ else {
+ alert('Connection error. Please reload page.');
+ }
+ };
+ OpenVidu.prototype.reconnectingCallback = function () {
+ console.warn('Websocket connection lost (reconnecting)');
+ if (this.isRoomAvailable()) {
+ this.session.onLostConnection();
+ }
+ else {
+ alert('Connection error. Please reload page.');
+ }
+ };
+ OpenVidu.prototype.reconnectedCallback = function () {
+ console.warn('Websocket reconnected');
+ if (this.isRoomAvailable()) {
+ this.session.onRecoveredConnection();
+ }
+ else {
+ alert('Connection error. Please reload page.');
+ }
+ };
+ OpenVidu.prototype.isRoomAvailable = function () {
+ if (this.session !== undefined && this.session instanceof Session_1.Session) {
+ return true;
+ }
+ else {
+ console.warn('Session instance not found');
+ return false;
+ }
+ };
+ return OpenVidu;
+}());
+exports.OpenVidu = OpenVidu;
+
+},{"../OpenViduInternal/Enums/OpenViduError":26,"../OpenViduInternal/Enums/VideoInsertMode":27,"../OpenViduInternal/Events/StreamPropertyChangedEvent":36,"../OpenViduInternal/KurentoUtils/kurento-jsonrpc":43,"../OpenViduInternal/ScreenSharing/Screen-Capturing":48,"../OpenViduInternal/ScreenSharing/Screen-Capturing-Auto":47,"./LocalRecorder":18,"./Publisher":20,"./Session":21,"platform":8}],20:[function(require,module,exports){
+"use strict";
+var __extends = (this && this.__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 __());
+ };
+})();
+Object.defineProperty(exports, "__esModule", { value: true });
+var Session_1 = require("./Session");
+var Stream_1 = require("./Stream");
+var StreamManager_1 = require("./StreamManager");
+var StreamEvent_1 = require("../OpenViduInternal/Events/StreamEvent");
+var StreamPropertyChangedEvent_1 = require("../OpenViduInternal/Events/StreamPropertyChangedEvent");
+var VideoElementEvent_1 = require("../OpenViduInternal/Events/VideoElementEvent");
+var OpenViduError_1 = require("../OpenViduInternal/Enums/OpenViduError");
+var platform = require("platform");
+var Publisher = (function (_super) {
+ __extends(Publisher, _super);
+ function Publisher(targEl, properties, openvidu) {
+ var _this = _super.call(this, new Stream_1.Stream((!!openvidu.session) ? openvidu.session : new Session_1.Session(openvidu), { publisherProperties: properties, mediaConstraints: {} }), targEl) || this;
+ _this.accessAllowed = false;
+ _this.isSubscribedToRemote = false;
+ _this.accessDenied = false;
+ _this.properties = properties;
+ _this.openvidu = openvidu;
+ _this.stream.ee.on('local-stream-destroyed', function (reason) {
+ _this.stream.isLocalStreamPublished = false;
+ var streamEvent = new StreamEvent_1.StreamEvent(true, _this, 'streamDestroyed', _this.stream, reason);
+ _this.emitEvent('streamDestroyed', [streamEvent]);
+ streamEvent.callDefaultBehavior();
+ });
+ return _this;
+ }
+ Publisher.prototype.publishAudio = function (value) {
+ var _this = this;
+ if (this.stream.audioActive !== value) {
+ this.stream.getMediaStream().getAudioTracks().forEach(function (track) {
+ track.enabled = value;
+ });
+ this.session.openvidu.sendRequest('streamPropertyChanged', {
+ streamId: this.stream.streamId,
+ property: 'audioActive',
+ newValue: value,
+ reason: 'publishAudio'
+ }, function (error, response) {
+ if (error) {
+ console.error("Error sending 'streamPropertyChanged' event", error);
+ }
+ else {
+ _this.session.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent_1.StreamPropertyChangedEvent(_this.session, _this.stream, 'audioActive', value, !value, 'publishAudio')]);
+ _this.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent_1.StreamPropertyChangedEvent(_this, _this.stream, 'audioActive', value, !value, 'publishAudio')]);
+ }
+ });
+ this.stream.audioActive = value;
+ console.info("'Publisher' has " + (value ? 'published' : 'unpublished') + ' its audio stream');
+ }
+ };
+ Publisher.prototype.publishVideo = function (value) {
+ var _this = this;
+ if (this.stream.videoActive !== value) {
+ this.stream.getMediaStream().getVideoTracks().forEach(function (track) {
+ track.enabled = value;
+ });
+ this.session.openvidu.sendRequest('streamPropertyChanged', {
+ streamId: this.stream.streamId,
+ property: 'videoActive',
+ newValue: value,
+ reason: 'publishVideo'
+ }, function (error, response) {
+ if (error) {
+ console.error("Error sending 'streamPropertyChanged' event", error);
+ }
+ else {
+ _this.session.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent_1.StreamPropertyChangedEvent(_this.session, _this.stream, 'videoActive', value, !value, 'publishVideo')]);
+ _this.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent_1.StreamPropertyChangedEvent(_this, _this.stream, 'videoActive', value, !value, 'publishVideo')]);
+ }
+ });
+ this.stream.videoActive = value;
+ console.info("'Publisher' has " + (value ? 'published' : 'unpublished') + ' its video stream');
+ }
+ };
+ Publisher.prototype.subscribeToRemote = function (value) {
+ value = (value !== undefined) ? value : true;
+ this.isSubscribedToRemote = value;
+ this.stream.subscribeToMyRemote(value);
+ };
+ Publisher.prototype.on = function (type, handler) {
+ var _this = this;
+ _super.prototype.on.call(this, type, handler);
+ if (type === 'streamCreated') {
+ if (!!this.stream && this.stream.isLocalStreamPublished) {
+ this.emitEvent('streamCreated', [new StreamEvent_1.StreamEvent(false, this, 'streamCreated', this.stream, '')]);
+ }
+ else {
+ this.stream.ee.on('stream-created-by-publisher', function () {
+ _this.emitEvent('streamCreated', [new StreamEvent_1.StreamEvent(false, _this, 'streamCreated', _this.stream, '')]);
+ });
+ }
+ }
+ if (type === 'remoteVideoPlaying') {
+ if (this.stream.displayMyRemote() && this.videos[0] && this.videos[0].video &&
+ this.videos[0].video.currentTime > 0 &&
+ this.videos[0].video.paused === false &&
+ this.videos[0].video.ended === false &&
+ this.videos[0].video.readyState === 4) {
+ this.emitEvent('remoteVideoPlaying', [new VideoElementEvent_1.VideoElementEvent(this.videos[0].video, this, 'remoteVideoPlaying')]);
+ }
+ }
+ if (type === 'accessAllowed') {
+ if (this.accessAllowed) {
+ this.emitEvent('accessAllowed', []);
+ }
+ }
+ if (type === 'accessDenied') {
+ if (this.accessDenied) {
+ this.emitEvent('accessDenied', []);
+ }
+ }
+ return this;
+ };
+ Publisher.prototype.once = function (type, handler) {
+ var _this = this;
+ _super.prototype.once.call(this, type, handler);
+ if (type === 'streamCreated') {
+ if (!!this.stream && this.stream.isLocalStreamPublished) {
+ this.emitEvent('streamCreated', [new StreamEvent_1.StreamEvent(false, this, 'streamCreated', this.stream, '')]);
+ }
+ else {
+ this.stream.ee.once('stream-created-by-publisher', function () {
+ _this.emitEvent('streamCreated', [new StreamEvent_1.StreamEvent(false, _this, 'streamCreated', _this.stream, '')]);
+ });
+ }
+ }
+ if (type === 'remoteVideoPlaying') {
+ if (this.stream.displayMyRemote() && this.videos[0] && this.videos[0].video &&
+ this.videos[0].video.currentTime > 0 &&
+ this.videos[0].video.paused === false &&
+ this.videos[0].video.ended === false &&
+ this.videos[0].video.readyState === 4) {
+ this.emitEvent('remoteVideoPlaying', [new VideoElementEvent_1.VideoElementEvent(this.videos[0].video, this, 'remoteVideoPlaying')]);
+ }
+ }
+ if (type === 'accessAllowed') {
+ if (this.accessAllowed) {
+ this.emitEvent('accessAllowed', []);
+ }
+ }
+ if (type === 'accessDenied') {
+ if (this.accessDenied) {
+ this.emitEvent('accessDenied', []);
+ }
+ }
+ return this;
+ };
+ Publisher.prototype.initialize = function () {
+ var _this = this;
+ return new Promise(function (resolve, reject) {
+ var errorCallback = function (openViduError) {
+ _this.accessDenied = true;
+ _this.accessAllowed = false;
+ reject(openViduError);
+ };
+ var successCallback = function (mediaStream) {
+ _this.accessAllowed = true;
+ _this.accessDenied = false;
+ if (_this.openvidu.isMediaStreamTrack(_this.properties.audioSource)) {
+ mediaStream.removeTrack(mediaStream.getAudioTracks()[0]);
+ mediaStream.addTrack(_this.properties.audioSource);
+ }
+ if (_this.openvidu.isMediaStreamTrack(_this.properties.videoSource)) {
+ mediaStream.removeTrack(mediaStream.getVideoTracks()[0]);
+ mediaStream.addTrack(_this.properties.videoSource);
+ }
+ if (!!mediaStream.getAudioTracks()[0]) {
+ var enabled = (_this.stream.audioActive !== undefined && _this.stream.audioActive !== null) ? _this.stream.audioActive : !!_this.stream.outboundStreamOpts.publisherProperties.publishAudio;
+ mediaStream.getAudioTracks()[0].enabled = enabled;
+ }
+ if (!!mediaStream.getVideoTracks()[0]) {
+ var enabled = (_this.stream.videoActive !== undefined && _this.stream.videoActive !== null) ? _this.stream.videoActive : !!_this.stream.outboundStreamOpts.publisherProperties.publishVideo;
+ mediaStream.getVideoTracks()[0].enabled = enabled;
+ }
+ _this.videoReference = document.createElement('video');
+ _this.videoReference.srcObject = mediaStream;
+ _this.stream.setMediaStream(mediaStream);
+ if (!_this.stream.displayMyRemote()) {
+ _this.stream.updateMediaStreamInVideos();
+ }
+ if (!!_this.firstVideoElement) {
+ _this.createVideoElement(_this.firstVideoElement.targetElement, _this.properties.insertMode);
+ }
+ delete _this.firstVideoElement;
+ if (_this.stream.isSendVideo()) {
+ if (!_this.stream.isSendScreen()) {
+ var _a = mediaStream.getVideoTracks()[0].getSettings(), width = _a.width, height = _a.height;
+ if (platform.name.toLowerCase().indexOf('mobile') !== -1 && (window.innerHeight > window.innerWidth)) {
+ _this.stream.videoDimensions = {
+ width: height || 0,
+ height: width || 0
+ };
+ }
+ else {
+ _this.stream.videoDimensions = {
+ width: width || 0,
+ height: height || 0
+ };
+ }
+ _this.stream.isLocalStreamReadyToPublish = true;
+ _this.stream.ee.emitEvent('stream-ready-to-publish', []);
+ }
+ else {
+ _this.videoReference.onloadedmetadata = function () {
+ _this.stream.videoDimensions = {
+ width: _this.videoReference.videoWidth,
+ height: _this.videoReference.videoHeight
+ };
+ _this.screenShareResizeInterval = setInterval(function () {
+ var firefoxSettings = mediaStream.getVideoTracks()[0].getSettings();
+ var newWidth = (platform.name === 'Chrome') ? _this.videoReference.videoWidth : firefoxSettings.width;
+ var newHeight = (platform.name === 'Chrome') ? _this.videoReference.videoHeight : firefoxSettings.height;
+ if (_this.stream.isLocalStreamPublished &&
+ (newWidth !== _this.stream.videoDimensions.width ||
+ newHeight !== _this.stream.videoDimensions.height)) {
+ var oldValue_1 = { width: _this.stream.videoDimensions.width, height: _this.stream.videoDimensions.height };
+ _this.stream.videoDimensions = {
+ width: newWidth || 0,
+ height: newHeight || 0
+ };
+ _this.session.openvidu.sendRequest('streamPropertyChanged', {
+ streamId: _this.stream.streamId,
+ property: 'videoDimensions',
+ newValue: JSON.stringify(_this.stream.videoDimensions),
+ reason: 'screenResized'
+ }, function (error, response) {
+ if (error) {
+ console.error("Error sending 'streamPropertyChanged' event", error);
+ }
+ else {
+ _this.session.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent_1.StreamPropertyChangedEvent(_this.session, _this.stream, 'videoDimensions', _this.stream.videoDimensions, oldValue_1, 'screenResized')]);
+ _this.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent_1.StreamPropertyChangedEvent(_this, _this.stream, 'videoDimensions', _this.stream.videoDimensions, oldValue_1, 'screenResized')]);
+ }
+ });
+ }
+ }, 500);
+ _this.stream.isLocalStreamReadyToPublish = true;
+ _this.stream.ee.emitEvent('stream-ready-to-publish', []);
+ };
+ }
+ }
+ else {
+ _this.stream.isLocalStreamReadyToPublish = true;
+ _this.stream.ee.emitEvent('stream-ready-to-publish', []);
+ }
+ resolve();
+ };
+ _this.openvidu.generateMediaConstraints(_this.properties)
+ .then(function (constraints) {
+ var outboundStreamOptions = {
+ mediaConstraints: constraints,
+ publisherProperties: _this.properties
+ };
+ _this.stream.setOutboundStreamOptions(outboundStreamOptions);
+ var constraintsAux = {};
+ var timeForDialogEvent = 1250;
+ if (_this.stream.isSendVideo() || _this.stream.isSendAudio()) {
+ var definedAudioConstraint_1 = ((constraints.audio === undefined) ? true : constraints.audio);
+ constraintsAux.audio = _this.stream.isSendScreen() ? false : definedAudioConstraint_1;
+ constraintsAux.video = constraints.video;
+ var startTime_1 = Date.now();
+ _this.setPermissionDialogTimer(timeForDialogEvent);
+ navigator.mediaDevices.getUserMedia(constraintsAux)
+ .then(function (mediaStream) {
+ _this.clearPermissionDialogTimer(startTime_1, timeForDialogEvent);
+ if (_this.stream.isSendScreen() && _this.stream.isSendAudio()) {
+ constraintsAux.audio = definedAudioConstraint_1;
+ constraintsAux.video = false;
+ startTime_1 = Date.now();
+ _this.setPermissionDialogTimer(timeForDialogEvent);
+ navigator.mediaDevices.getUserMedia(constraintsAux)
+ .then(function (audioOnlyStream) {
+ _this.clearPermissionDialogTimer(startTime_1, timeForDialogEvent);
+ mediaStream.addTrack(audioOnlyStream.getAudioTracks()[0]);
+ successCallback(mediaStream);
+ })
+ .catch(function (error) {
+ _this.clearPermissionDialogTimer(startTime_1, timeForDialogEvent);
+ var errorName, errorMessage;
+ switch (error.name.toLowerCase()) {
+ case 'notfounderror':
+ errorName = OpenViduError_1.OpenViduErrorName.INPUT_AUDIO_DEVICE_NOT_FOUND;
+ errorMessage = error.toString();
+ errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage));
+ break;
+ case 'notallowederror':
+ errorName = OpenViduError_1.OpenViduErrorName.DEVICE_ACCESS_DENIED;
+ errorMessage = error.toString();
+ errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage));
+ break;
+ case 'overconstrainederror':
+ if (error.constraint.toLowerCase() === 'deviceid') {
+ errorName = OpenViduError_1.OpenViduErrorName.INPUT_AUDIO_DEVICE_NOT_FOUND;
+ errorMessage = "Audio input device with deviceId '" + constraints.video.deviceId.exact + "' not found";
+ }
+ else {
+ errorName = OpenViduError_1.OpenViduErrorName.PUBLISHER_PROPERTIES_ERROR;
+ errorMessage = "Audio input device doesn't support the value passed for constraint '" + error.constraint + "'";
+ }
+ errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage));
+ break;
+ }
+ });
+ }
+ else {
+ successCallback(mediaStream);
+ }
+ })
+ .catch(function (error) {
+ _this.clearPermissionDialogTimer(startTime_1, timeForDialogEvent);
+ var errorName, errorMessage;
+ switch (error.name.toLowerCase()) {
+ case 'notfounderror':
+ navigator.mediaDevices.getUserMedia({
+ audio: false,
+ video: constraints.video
+ })
+ .then(function (mediaStream) {
+ mediaStream.getVideoTracks().forEach(function (track) {
+ track.stop();
+ });
+ errorName = OpenViduError_1.OpenViduErrorName.INPUT_AUDIO_DEVICE_NOT_FOUND;
+ errorMessage = error.toString();
+ errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage));
+ }).catch(function (e) {
+ errorName = OpenViduError_1.OpenViduErrorName.INPUT_VIDEO_DEVICE_NOT_FOUND;
+ errorMessage = error.toString();
+ errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage));
+ });
+ break;
+ case 'notallowederror':
+ errorName = _this.stream.isSendScreen() ? OpenViduError_1.OpenViduErrorName.SCREEN_CAPTURE_DENIED : OpenViduError_1.OpenViduErrorName.DEVICE_ACCESS_DENIED;
+ errorMessage = error.toString();
+ errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage));
+ break;
+ case 'overconstrainederror':
+ navigator.mediaDevices.getUserMedia({
+ audio: false,
+ video: constraints.video
+ })
+ .then(function (mediaStream) {
+ mediaStream.getVideoTracks().forEach(function (track) {
+ track.stop();
+ });
+ if (error.constraint.toLowerCase() === 'deviceid') {
+ errorName = OpenViduError_1.OpenViduErrorName.INPUT_AUDIO_DEVICE_NOT_FOUND;
+ errorMessage = "Audio input device with deviceId '" + constraints.audio.deviceId.exact + "' not found";
+ }
+ else {
+ errorName = OpenViduError_1.OpenViduErrorName.PUBLISHER_PROPERTIES_ERROR;
+ errorMessage = "Audio input device doesn't support the value passed for constraint '" + error.constraint + "'";
+ }
+ errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage));
+ }).catch(function (e) {
+ if (error.constraint.toLowerCase() === 'deviceid') {
+ errorName = OpenViduError_1.OpenViduErrorName.INPUT_VIDEO_DEVICE_NOT_FOUND;
+ errorMessage = "Video input device with deviceId '" + constraints.video.deviceId.exact + "' not found";
+ }
+ else {
+ errorName = OpenViduError_1.OpenViduErrorName.PUBLISHER_PROPERTIES_ERROR;
+ errorMessage = "Video input device doesn't support the value passed for constraint '" + error.constraint + "'";
+ }
+ errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage));
+ });
+ break;
+ }
+ });
+ }
+ else {
+ reject(new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.NO_INPUT_SOURCE_SET, "Properties 'audioSource' and 'videoSource' cannot be set to false or null at the same time when calling 'OpenVidu.initPublisher'"));
+ }
+ })
+ .catch(function (error) {
+ errorCallback(error);
+ });
+ });
+ };
+ Publisher.prototype.reestablishStreamPlayingEvent = function () {
+ if (this.ee.getListeners('streamPlaying').length > 0) {
+ this.addPlayEventToFirstVideo();
+ }
+ };
+ Publisher.prototype.setPermissionDialogTimer = function (waitTime) {
+ var _this = this;
+ this.permissionDialogTimeout = setTimeout(function () {
+ _this.emitEvent('accessDialogOpened', []);
+ }, waitTime);
+ };
+ Publisher.prototype.clearPermissionDialogTimer = function (startTime, waitTime) {
+ clearTimeout(this.permissionDialogTimeout);
+ if ((Date.now() - startTime) > waitTime) {
+ this.emitEvent('accessDialogClosed', []);
+ }
+ };
+ return Publisher;
+}(StreamManager_1.StreamManager));
+exports.Publisher = Publisher;
+
+},{"../OpenViduInternal/Enums/OpenViduError":26,"../OpenViduInternal/Events/StreamEvent":34,"../OpenViduInternal/Events/StreamPropertyChangedEvent":36,"../OpenViduInternal/Events/VideoElementEvent":37,"./Session":21,"./Stream":22,"./StreamManager":23,"platform":8}],21:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+var Connection_1 = require("./Connection");
+var Subscriber_1 = require("./Subscriber");
+var ConnectionEvent_1 = require("../OpenViduInternal/Events/ConnectionEvent");
+var RecordingEvent_1 = require("../OpenViduInternal/Events/RecordingEvent");
+var SessionDisconnectedEvent_1 = require("../OpenViduInternal/Events/SessionDisconnectedEvent");
+var SignalEvent_1 = require("../OpenViduInternal/Events/SignalEvent");
+var StreamEvent_1 = require("../OpenViduInternal/Events/StreamEvent");
+var StreamPropertyChangedEvent_1 = require("../OpenViduInternal/Events/StreamPropertyChangedEvent");
+var OpenViduError_1 = require("../OpenViduInternal/Enums/OpenViduError");
+var VideoInsertMode_1 = require("../OpenViduInternal/Enums/VideoInsertMode");
+var platform = require("platform");
+var EventEmitter = require("wolfy87-eventemitter");
+var Session = (function () {
+ function Session(openvidu) {
+ this.streamManagers = [];
+ this.remoteStreamsCreated = {};
+ this.remoteConnections = {};
+ this.speakingEventsEnabled = false;
+ this.ee = new EventEmitter();
+ this.openvidu = openvidu;
+ }
+ Session.prototype.connect = function (token, metadata) {
+ var _this = this;
+ return new Promise(function (resolve, reject) {
+ _this.processToken(token);
+ if (_this.openvidu.checkSystemRequirements()) {
+ _this.options = {
+ sessionId: _this.sessionId,
+ participantId: token,
+ metadata: !!metadata ? _this.stringClientMetadata(metadata) : ''
+ };
+ _this.connectAux(token).then(function () {
+ resolve();
+ }).catch(function (error) {
+ reject(error);
+ });
+ }
+ else {
+ reject(new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.BROWSER_NOT_SUPPORTED, 'Browser ' + platform.name + ' ' + platform.version + ' is not supported in OpenVidu'));
+ }
+ });
+ };
+ Session.prototype.disconnect = function () {
+ this.leave(false, 'disconnect');
+ };
+ Session.prototype.subscribe = function (stream, targetElement, param3, param4) {
+ var properties = {};
+ if (!!param3 && typeof param3 !== 'function') {
+ properties = {
+ insertMode: (typeof param3.insertMode !== 'undefined') ? ((typeof param3.insertMode === 'string') ? VideoInsertMode_1.VideoInsertMode[param3.insertMode] : properties.insertMode) : VideoInsertMode_1.VideoInsertMode.APPEND,
+ subscribeToAudio: (typeof param3.subscribeToAudio !== 'undefined') ? param3.subscribeToAudio : true,
+ subscribeToVideo: (typeof param3.subscribeToVideo !== 'undefined') ? param3.subscribeToVideo : true
+ };
+ }
+ else {
+ properties = {
+ insertMode: VideoInsertMode_1.VideoInsertMode.APPEND,
+ subscribeToAudio: true,
+ subscribeToVideo: true
+ };
+ }
+ var completionHandler;
+ if (!!param3 && (typeof param3 === 'function')) {
+ completionHandler = param3;
+ }
+ else if (!!param4) {
+ completionHandler = param4;
+ }
+ console.info('Subscribing to ' + stream.connection.connectionId);
+ stream.subscribe()
+ .then(function () {
+ console.info('Subscribed correctly to ' + stream.connection.connectionId);
+ if (completionHandler !== undefined) {
+ completionHandler(undefined);
+ }
+ })
+ .catch(function (error) {
+ if (completionHandler !== undefined) {
+ completionHandler(error);
+ }
+ });
+ var subscriber = new Subscriber_1.Subscriber(stream, targetElement, properties);
+ if (!!subscriber.targetElement) {
+ stream.streamManager.createVideoElement(subscriber.targetElement, properties.insertMode);
+ }
+ return subscriber;
+ };
+ Session.prototype.subscribeAsync = function (stream, targetElement, properties) {
+ var _this = this;
+ return new Promise(function (resolve, reject) {
+ var subscriber;
+ var callback = function (error) {
+ if (!!error) {
+ reject(error);
+ }
+ else {
+ resolve(subscriber);
+ }
+ };
+ if (!!properties) {
+ subscriber = _this.subscribe(stream, targetElement, properties, callback);
+ }
+ else {
+ subscriber = _this.subscribe(stream, targetElement, callback);
+ }
+ });
+ };
+ Session.prototype.unsubscribe = function (subscriber) {
+ var connectionId = subscriber.stream.connection.connectionId;
+ console.info('Unsubscribing from ' + connectionId);
+ this.openvidu.sendRequest('unsubscribeFromVideo', { sender: subscriber.stream.connection.connectionId }, function (error, response) {
+ if (error) {
+ console.error('Error unsubscribing from ' + connectionId, error);
+ }
+ else {
+ console.info('Unsubscribed correctly from ' + connectionId);
+ }
+ subscriber.stream.disposeWebRtcPeer();
+ subscriber.stream.disposeMediaStream();
+ });
+ subscriber.stream.streamManager.removeAllVideos();
+ };
+ Session.prototype.publish = function (publisher) {
+ var _this = this;
+ return new Promise(function (resolve, reject) {
+ publisher.session = _this;
+ publisher.stream.session = _this;
+ if (!publisher.stream.publishedOnce) {
+ _this.connection.addStream(publisher.stream);
+ publisher.stream.publish()
+ .then(function () {
+ resolve();
+ })
+ .catch(function (error) {
+ reject(error);
+ });
+ }
+ else {
+ publisher.initialize()
+ .then(function () {
+ _this.connection.addStream(publisher.stream);
+ publisher.reestablishStreamPlayingEvent();
+ publisher.stream.publish()
+ .then(function () {
+ resolve();
+ })
+ .catch(function (error) {
+ reject(error);
+ });
+ }).catch(function (error) {
+ reject(error);
+ });
+ }
+ });
+ };
+ Session.prototype.unpublish = function (publisher) {
+ var stream = publisher.stream;
+ if (!stream.connection) {
+ console.error('The associated Connection object of this Publisher is null', stream);
+ return;
+ }
+ else if (stream.connection !== this.connection) {
+ console.error('The associated Connection object of this Publisher is not your local Connection.' +
+ "Only moderators can force unpublish on remote Streams via 'forceUnpublish' method", stream);
+ return;
+ }
+ else {
+ console.info('Unpublishing local media (' + stream.connection.connectionId + ')');
+ this.openvidu.sendRequest('unpublishVideo', function (error, response) {
+ if (error) {
+ console.error(error);
+ }
+ else {
+ console.info('Media unpublished correctly');
+ }
+ });
+ stream.disposeWebRtcPeer();
+ delete stream.connection.stream;
+ var streamEvent = new StreamEvent_1.StreamEvent(true, publisher, 'streamDestroyed', publisher.stream, 'unpublish');
+ publisher.emitEvent('streamDestroyed', [streamEvent]);
+ streamEvent.callDefaultBehavior();
+ }
+ };
+ Session.prototype.forceDisconnect = function (connection) {
+ var _this = this;
+ return new Promise(function (resolve, reject) {
+ console.info('Forcing disconnect for connection ' + connection.connectionId);
+ _this.openvidu.sendRequest('forceDisconnect', { connectionId: connection.connectionId }, function (error, response) {
+ if (error) {
+ console.error('Error forcing disconnect for Connection ' + connection.connectionId, error);
+ if (error.code === 401) {
+ reject(new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.OPENVIDU_PERMISSION_DENIED, "You don't have permissions to force a disconnection"));
+ }
+ else {
+ reject(error);
+ }
+ }
+ else {
+ console.info('Forcing disconnect correctly for Connection ' + connection.connectionId);
+ resolve();
+ }
+ });
+ });
+ };
+ Session.prototype.forceUnpublish = function (stream) {
+ var _this = this;
+ return new Promise(function (resolve, reject) {
+ console.info('Forcing unpublish for stream ' + stream.streamId);
+ _this.openvidu.sendRequest('forceUnpublish', { streamId: stream.streamId }, function (error, response) {
+ if (error) {
+ console.error('Error forcing unpublish for Stream ' + stream.streamId, error);
+ if (error.code === 401) {
+ reject(new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.OPENVIDU_PERMISSION_DENIED, "You don't have permissions to force an unpublishing"));
+ }
+ else {
+ reject(error);
+ }
+ }
+ else {
+ console.info('Forcing unpublish correctly for Stream ' + stream.streamId);
+ resolve();
+ }
+ });
+ });
+ };
+ Session.prototype.signal = function (signal) {
+ var _this = this;
+ return new Promise(function (resolve, reject) {
+ var signalMessage = {};
+ if (signal.to && signal.to.length > 0) {
+ var connectionIds_1 = [];
+ signal.to.forEach(function (connection) {
+ connectionIds_1.push(connection.connectionId);
+ });
+ signalMessage['to'] = connectionIds_1;
+ }
+ else {
+ signalMessage['to'] = [];
+ }
+ signalMessage['data'] = signal.data ? signal.data : '';
+ signalMessage['type'] = signal.type ? signal.type : '';
+ _this.openvidu.sendRequest('sendMessage', {
+ message: JSON.stringify(signalMessage)
+ }, function (error, response) {
+ if (!!error) {
+ reject(error);
+ }
+ else {
+ resolve();
+ }
+ });
+ });
+ };
+ Session.prototype.on = function (type, handler) {
+ this.ee.on(type, function (event) {
+ if (event) {
+ console.info("Event '" + type + "' triggered by 'Session'", event);
+ }
+ else {
+ console.info("Event '" + type + "' triggered by 'Session'");
+ }
+ handler(event);
+ });
+ if (type === 'publisherStartSpeaking' || type === 'publisherStopSpeaking') {
+ this.speakingEventsEnabled = true;
+ for (var connectionId in this.remoteConnections) {
+ var str = this.remoteConnections[connectionId].stream;
+ if (!!str && !str.speechEvent && str.hasAudio) {
+ str.enableSpeakingEvents();
+ }
+ }
+ }
+ return this;
+ };
+ Session.prototype.once = function (type, handler) {
+ this.ee.once(type, function (event) {
+ if (event) {
+ console.info("Event '" + type + "' triggered by 'Session'", event);
+ }
+ else {
+ console.info("Event '" + type + "' triggered by 'Session'");
+ }
+ handler(event);
+ });
+ if (type === 'publisherStartSpeaking' || type === 'publisherStopSpeaking') {
+ this.speakingEventsEnabled = true;
+ for (var connectionId in this.remoteConnections) {
+ var str = this.remoteConnections[connectionId].stream;
+ if (!!str && !str.speechEvent && str.hasAudio) {
+ str.enableOnceSpeakingEvents();
+ }
+ }
+ }
+ return this;
+ };
+ Session.prototype.off = function (type, handler) {
+ if (!handler) {
+ this.ee.removeAllListeners(type);
+ }
+ else {
+ this.ee.off(type, handler);
+ }
+ if (type === 'publisherStartSpeaking' || type === 'publisherStopSpeaking') {
+ this.speakingEventsEnabled = false;
+ for (var connectionId in this.remoteConnections) {
+ var str = this.remoteConnections[connectionId].stream;
+ if (!!str && !!str.speechEvent) {
+ str.disableSpeakingEvents();
+ }
+ }
+ }
+ return this;
+ };
+ Session.prototype.onParticipantJoined = function (response) {
+ var _this = this;
+ this.getConnection(response.id, '')
+ .then(function (connection) {
+ console.warn('Connection ' + response.id + ' already exists in connections list');
+ })
+ .catch(function (openViduError) {
+ var connection = new Connection_1.Connection(_this, response);
+ _this.remoteConnections[response.id] = connection;
+ _this.ee.emitEvent('connectionCreated', [new ConnectionEvent_1.ConnectionEvent(false, _this, 'connectionCreated', connection, '')]);
+ });
+ };
+ Session.prototype.onParticipantLeft = function (msg) {
+ var _this = this;
+ this.getRemoteConnection(msg.connectionId, 'Remote connection ' + msg.connectionId + " unknown when 'onParticipantLeft'. " +
+ 'Existing remote connections: ' + JSON.stringify(Object.keys(this.remoteConnections)))
+ .then(function (connection) {
+ if (!!connection.stream) {
+ var stream = connection.stream;
+ var streamEvent = new StreamEvent_1.StreamEvent(true, _this, 'streamDestroyed', stream, msg.reason);
+ _this.ee.emitEvent('streamDestroyed', [streamEvent]);
+ streamEvent.callDefaultBehavior();
+ delete _this.remoteStreamsCreated[stream.streamId];
+ }
+ delete _this.remoteConnections[connection.connectionId];
+ _this.ee.emitEvent('connectionDestroyed', [new ConnectionEvent_1.ConnectionEvent(false, _this, 'connectionDestroyed', connection, msg.reason)]);
+ })
+ .catch(function (openViduError) {
+ console.error(openViduError);
+ });
+ };
+ Session.prototype.onParticipantPublished = function (response) {
+ var _this = this;
+ var afterConnectionFound = function (connection) {
+ _this.remoteConnections[connection.connectionId] = connection;
+ if (!_this.remoteStreamsCreated[connection.stream.streamId]) {
+ _this.ee.emitEvent('streamCreated', [new StreamEvent_1.StreamEvent(false, _this, 'streamCreated', connection.stream, '')]);
+ }
+ _this.remoteStreamsCreated[connection.stream.streamId] = true;
+ };
+ var connection;
+ this.getRemoteConnection(response.id, "Remote connection '" + response.id + "' unknown when 'onParticipantPublished'. " +
+ 'Existing remote connections: ' + JSON.stringify(Object.keys(this.remoteConnections)))
+ .then(function (con) {
+ connection = con;
+ response.metadata = con.data;
+ connection.options = response;
+ connection.initRemoteStreams(response.streams);
+ afterConnectionFound(connection);
+ })
+ .catch(function (openViduError) {
+ connection = new Connection_1.Connection(_this, response);
+ afterConnectionFound(connection);
+ });
+ };
+ Session.prototype.onParticipantUnpublished = function (msg) {
+ var _this = this;
+ if (msg.connectionId === this.connection.connectionId) {
+ this.stopPublisherStream(msg.reason);
+ }
+ else {
+ this.getRemoteConnection(msg.connectionId, "Remote connection '" + msg.connectionId + "' unknown when 'onParticipantUnpublished'. " +
+ 'Existing remote connections: ' + JSON.stringify(Object.keys(this.remoteConnections)))
+ .then(function (connection) {
+ var streamEvent = new StreamEvent_1.StreamEvent(true, _this, 'streamDestroyed', connection.stream, msg.reason);
+ _this.ee.emitEvent('streamDestroyed', [streamEvent]);
+ streamEvent.callDefaultBehavior();
+ var streamId = connection.stream.streamId;
+ delete _this.remoteStreamsCreated[streamId];
+ connection.removeStream(streamId);
+ })
+ .catch(function (openViduError) {
+ console.error(openViduError);
+ });
+ }
+ };
+ Session.prototype.onParticipantEvicted = function (msg) {
+ if (msg.connectionId === this.connection.connectionId) {
+ if (!!this.sessionId && !this.connection.disposed) {
+ this.leave(true, msg.reason);
+ }
+ }
+ };
+ Session.prototype.onNewMessage = function (msg) {
+ var _this = this;
+ console.info('New signal: ' + JSON.stringify(msg));
+ this.getConnection(msg.from, "Connection '" + msg.from + "' unknow when 'onNewMessage'. Existing remote connections: "
+ + JSON.stringify(Object.keys(this.remoteConnections)) + '. Existing local connection: ' + this.connection.connectionId)
+ .then(function (connection) {
+ _this.ee.emitEvent('signal', [new SignalEvent_1.SignalEvent(_this, msg.type, msg.data, connection)]);
+ _this.ee.emitEvent('signal:' + msg.type, [new SignalEvent_1.SignalEvent(_this, msg.type, msg.data, connection)]);
+ })
+ .catch(function (openViduError) {
+ console.error(openViduError);
+ });
+ };
+ Session.prototype.onStreamPropertyChanged = function (msg) {
+ var _this = this;
+ this.getRemoteConnection(msg.connectionId, 'Remote connection ' + msg.connectionId + " unknown when 'onStreamPropertyChanged'. " +
+ 'Existing remote connections: ' + JSON.stringify(Object.keys(this.remoteConnections)))
+ .then(function (connection) {
+ if (!!connection.stream && connection.stream.streamId === msg.streamId) {
+ var stream = connection.stream;
+ var oldValue = void 0;
+ switch (msg.property) {
+ case 'audioActive':
+ oldValue = stream.audioActive;
+ msg.newValue = msg.newValue === 'true';
+ stream.audioActive = msg.newValue;
+ break;
+ case 'videoActive':
+ oldValue = stream.videoActive;
+ msg.newValue = msg.newValue === 'true';
+ stream.videoActive = msg.newValue;
+ break;
+ case 'videoDimensions':
+ oldValue = stream.videoDimensions;
+ msg.newValue = JSON.parse(JSON.parse(msg.newValue));
+ stream.videoDimensions = msg.newValue;
+ break;
+ }
+ _this.ee.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent_1.StreamPropertyChangedEvent(_this, stream, msg.property, msg.newValue, oldValue, msg.reason)]);
+ stream.streamManager.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent_1.StreamPropertyChangedEvent(stream.streamManager, stream, msg.property, msg.newValue, oldValue, msg.reason)]);
+ }
+ else {
+ console.error("No stream with streamId '" + msg.streamId + "' found for connection '" + msg.connectionId + "' on 'streamPropertyChanged' event");
+ }
+ })
+ .catch(function (openViduError) {
+ console.error(openViduError);
+ });
+ };
+ Session.prototype.recvIceCandidate = function (msg) {
+ var candidate = {
+ candidate: msg.candidate,
+ sdpMid: msg.sdpMid,
+ sdpMLineIndex: msg.sdpMLineIndex,
+ toJSON: function () {
+ return { candidate: msg.candidate };
+ }
+ };
+ this.getConnection(msg.endpointName, 'Connection not found for endpoint ' + msg.endpointName + '. Ice candidate will be ignored: ' + candidate)
+ .then(function (connection) {
+ var stream = connection.stream;
+ stream.getWebRtcPeer().addIceCandidate(candidate).catch(function (error) {
+ console.error('Error adding candidate for ' + stream.streamId
+ + ' stream of endpoint ' + msg.endpointName + ': ' + error);
+ });
+ })
+ .catch(function (openViduError) {
+ console.error(openViduError);
+ });
+ };
+ Session.prototype.onSessionClosed = function (msg) {
+ console.info('Session closed: ' + JSON.stringify(msg));
+ var s = msg.sessionId;
+ if (s !== undefined) {
+ this.ee.emitEvent('session-closed', [{
+ session: s
+ }]);
+ }
+ else {
+ console.warn('Session undefined on session closed', msg);
+ }
+ };
+ Session.prototype.onLostConnection = function () {
+ console.warn('Lost connection in Session ' + this.sessionId);
+ if (!!this.sessionId && !this.connection.disposed) {
+ this.leave(true, 'networkDisconnect');
+ }
+ };
+ Session.prototype.onRecoveredConnection = function () {
+ console.warn('Recovered connection in Session ' + this.sessionId);
+ this.ee.emitEvent('connectionRecovered', []);
+ };
+ Session.prototype.onMediaError = function (params) {
+ console.error('Media error: ' + JSON.stringify(params));
+ var err = params.error;
+ if (err) {
+ this.ee.emitEvent('error-media', [{
+ error: err
+ }]);
+ }
+ else {
+ console.warn('Received undefined media error. Params:', params);
+ }
+ };
+ Session.prototype.onRecordingStarted = function (response) {
+ this.ee.emitEvent('recordingStarted', [new RecordingEvent_1.RecordingEvent(this, 'recordingStarted', response.id, response.name)]);
+ };
+ Session.prototype.onRecordingStopped = function (response) {
+ this.ee.emitEvent('recordingStopped', [new RecordingEvent_1.RecordingEvent(this, 'recordingStopped', response.id, response.name)]);
+ };
+ Session.prototype.emitEvent = function (type, eventArray) {
+ this.ee.emitEvent(type, eventArray);
+ };
+ Session.prototype.leave = function (forced, reason) {
+ var _this = this;
+ forced = !!forced;
+ console.info('Leaving Session (forced=' + forced + ')');
+ if (!!this.connection) {
+ if (!this.connection.disposed && !forced) {
+ this.openvidu.sendRequest('leaveRoom', function (error, response) {
+ if (error) {
+ console.error(error);
+ }
+ _this.openvidu.closeWs();
+ });
+ }
+ else {
+ this.openvidu.closeWs();
+ }
+ this.stopPublisherStream(reason);
+ if (!this.connection.disposed) {
+ var sessionDisconnectEvent = new SessionDisconnectedEvent_1.SessionDisconnectedEvent(this, reason);
+ this.ee.emitEvent('sessionDisconnected', [sessionDisconnectEvent]);
+ sessionDisconnectEvent.callDefaultBehavior();
+ }
+ }
+ else {
+ console.warn('You were not connected to the session ' + this.sessionId);
+ }
+ };
+ Session.prototype.connectAux = function (token) {
+ var _this = this;
+ return new Promise(function (resolve, reject) {
+ _this.openvidu.startWs(function (error) {
+ if (!!error) {
+ reject(error);
+ }
+ else {
+ var joinParams = {
+ token: (!!token) ? token : '',
+ session: _this.sessionId,
+ metadata: !!_this.options.metadata ? _this.options.metadata : '',
+ secret: _this.openvidu.getSecret(),
+ recorder: _this.openvidu.getRecorder(),
+ };
+ _this.openvidu.sendRequest('joinRoom', joinParams, function (error, response) {
+ if (!!error) {
+ reject(error);
+ }
+ else {
+ _this.capabilities = {
+ subscribe: true,
+ publish: _this.openvidu.role !== 'SUBSCRIBER',
+ forceUnpublish: _this.openvidu.role === 'MODERATOR',
+ forceDisconnect: _this.openvidu.role === 'MODERATOR'
+ };
+ _this.connection = new Connection_1.Connection(_this);
+ _this.connection.connectionId = response.id;
+ _this.connection.data = response.metadata;
+ var events_1 = {
+ connections: new Array(),
+ streams: new Array()
+ };
+ var existingParticipants = response.value;
+ existingParticipants.forEach(function (participant) {
+ var connection = new Connection_1.Connection(_this, participant);
+ _this.remoteConnections[connection.connectionId] = connection;
+ events_1.connections.push(connection);
+ if (!!connection.stream) {
+ _this.remoteStreamsCreated[connection.stream.streamId] = true;
+ events_1.streams.push(connection.stream);
+ }
+ });
+ _this.ee.emitEvent('connectionCreated', [new ConnectionEvent_1.ConnectionEvent(false, _this, 'connectionCreated', _this.connection, '')]);
+ events_1.connections.forEach(function (connection) {
+ _this.ee.emitEvent('connectionCreated', [new ConnectionEvent_1.ConnectionEvent(false, _this, 'connectionCreated', connection, '')]);
+ });
+ events_1.streams.forEach(function (stream) {
+ _this.ee.emitEvent('streamCreated', [new StreamEvent_1.StreamEvent(false, _this, 'streamCreated', stream, '')]);
+ });
+ resolve();
+ }
+ });
+ }
+ });
+ });
+ };
+ Session.prototype.stopPublisherStream = function (reason) {
+ if (!!this.connection.stream) {
+ this.connection.stream.disposeWebRtcPeer();
+ if (this.connection.stream.isLocalStreamPublished) {
+ this.connection.stream.ee.emitEvent('local-stream-destroyed', [reason]);
+ }
+ }
+ };
+ Session.prototype.stringClientMetadata = function (metadata) {
+ if (typeof metadata !== 'string') {
+ return JSON.stringify(metadata);
+ }
+ else {
+ return metadata;
+ }
+ };
+ Session.prototype.getConnection = function (connectionId, errorMessage) {
+ var _this = this;
+ return new Promise(function (resolve, reject) {
+ var connection = _this.remoteConnections[connectionId];
+ if (!!connection) {
+ resolve(connection);
+ }
+ else {
+ if (_this.connection.connectionId === connectionId) {
+ resolve(_this.connection);
+ }
+ else {
+ reject(new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.GENERIC_ERROR, errorMessage));
+ }
+ }
+ });
+ };
+ Session.prototype.getRemoteConnection = function (connectionId, errorMessage) {
+ var _this = this;
+ return new Promise(function (resolve, reject) {
+ var connection = _this.remoteConnections[connectionId];
+ if (!!connection) {
+ resolve(connection);
+ }
+ else {
+ reject(new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.GENERIC_ERROR, errorMessage));
+ }
+ });
+ };
+ Session.prototype.processToken = function (token) {
+ var url = new URL(token);
+ this.sessionId = url.searchParams.get('sessionId');
+ var secret = url.searchParams.get('secret');
+ var recorder = url.searchParams.get('recorder');
+ var turnUsername = url.searchParams.get('turnUsername');
+ var turnCredential = url.searchParams.get('turnCredential');
+ var role = url.searchParams.get('role');
+ if (!!secret) {
+ this.openvidu.secret = secret;
+ }
+ if (!!recorder) {
+ this.openvidu.recorder = true;
+ }
+ if (!!turnUsername && !!turnCredential) {
+ var stunUrl = 'stun:' + url.hostname + ':3478';
+ var turnUrl1 = 'turn:' + url.hostname + ':3478';
+ var turnUrl2 = turnUrl1 + '?transport=tcp';
+ this.openvidu.iceServers = [
+ { urls: [stunUrl] },
+ { urls: [turnUrl1, turnUrl2], username: turnUsername, credential: turnCredential }
+ ];
+ console.log('TURN temp credentials [' + turnUsername + ':' + turnCredential + ']');
+ }
+ if (!!role) {
+ this.openvidu.role = role;
+ }
+ this.openvidu.wsUri = 'wss://' + url.host + '/openvidu';
+ };
+ return Session;
+}());
+exports.Session = Session;
+
+},{"../OpenViduInternal/Enums/OpenViduError":26,"../OpenViduInternal/Enums/VideoInsertMode":27,"../OpenViduInternal/Events/ConnectionEvent":28,"../OpenViduInternal/Events/RecordingEvent":31,"../OpenViduInternal/Events/SessionDisconnectedEvent":32,"../OpenViduInternal/Events/SignalEvent":33,"../OpenViduInternal/Events/StreamEvent":34,"../OpenViduInternal/Events/StreamPropertyChangedEvent":36,"./Connection":17,"./Subscriber":24,"platform":8,"wolfy87-eventemitter":15}],22:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+var WebRtcPeer_1 = require("../OpenViduInternal/WebRtcPeer/WebRtcPeer");
+var WebRtcStats_1 = require("../OpenViduInternal/WebRtcStats/WebRtcStats");
+var PublisherSpeakingEvent_1 = require("../OpenViduInternal/Events/PublisherSpeakingEvent");
+var EventEmitter = require("wolfy87-eventemitter");
+var hark = require("hark");
+var OpenViduError_1 = require("../OpenViduInternal/Enums/OpenViduError");
+var Stream = (function () {
+ function Stream(session, options) {
+ var _this = this;
+ this.ee = new EventEmitter();
+ this.isSubscribeToRemote = false;
+ this.isLocalStreamReadyToPublish = false;
+ this.isLocalStreamPublished = false;
+ this.publishedOnce = false;
+ this.session = session;
+ if (options.hasOwnProperty('id')) {
+ this.inboundStreamOpts = options;
+ this.streamId = this.inboundStreamOpts.id;
+ this.hasAudio = this.inboundStreamOpts.hasAudio;
+ this.hasVideo = this.inboundStreamOpts.hasVideo;
+ if (this.hasAudio) {
+ this.audioActive = this.inboundStreamOpts.audioActive;
+ }
+ if (this.hasVideo) {
+ this.videoActive = this.inboundStreamOpts.videoActive;
+ this.typeOfVideo = (!this.inboundStreamOpts.typeOfVideo) ? undefined : this.inboundStreamOpts.typeOfVideo;
+ this.frameRate = (this.inboundStreamOpts.frameRate === -1) ? undefined : this.inboundStreamOpts.frameRate;
+ this.videoDimensions = this.inboundStreamOpts.videoDimensions;
+ }
+ }
+ else {
+ this.outboundStreamOpts = options;
+ this.hasAudio = this.isSendAudio();
+ this.hasVideo = this.isSendVideo();
+ if (this.hasAudio) {
+ this.audioActive = !!this.outboundStreamOpts.publisherProperties.publishAudio;
+ }
+ if (this.hasVideo) {
+ this.videoActive = !!this.outboundStreamOpts.publisherProperties.publishVideo;
+ this.frameRate = this.outboundStreamOpts.publisherProperties.frameRate;
+ if (this.outboundStreamOpts.publisherProperties.videoSource instanceof MediaStreamTrack) {
+ this.typeOfVideo = 'CUSTOM';
+ }
+ else {
+ this.typeOfVideo = this.isSendScreen() ? 'SCREEN' : 'CAMERA';
+ }
+ }
+ }
+ this.ee.on('mediastream-updated', function () {
+ _this.streamManager.updateMediaStream(_this.mediaStream);
+ console.debug('Video srcObject [' + _this.mediaStream + '] updated in stream [' + _this.streamId + ']');
+ });
+ }
+ Stream.prototype.getMediaStream = function () {
+ return this.mediaStream;
+ };
+ Stream.prototype.setMediaStream = function (mediaStream) {
+ this.mediaStream = mediaStream;
+ };
+ Stream.prototype.updateMediaStreamInVideos = function () {
+ this.ee.emitEvent('mediastream-updated');
+ };
+ Stream.prototype.getWebRtcPeer = function () {
+ return this.webRtcPeer;
+ };
+ Stream.prototype.getRTCPeerConnection = function () {
+ return this.webRtcPeer.pc;
+ };
+ Stream.prototype.subscribeToMyRemote = function (value) {
+ this.isSubscribeToRemote = value;
+ };
+ Stream.prototype.setOutboundStreamOptions = function (outboundStreamOpts) {
+ this.outboundStreamOpts = outboundStreamOpts;
+ };
+ Stream.prototype.subscribe = function () {
+ var _this = this;
+ return new Promise(function (resolve, reject) {
+ _this.initWebRtcPeerReceive()
+ .then(function () {
+ resolve();
+ })
+ .catch(function (error) {
+ reject(error);
+ });
+ });
+ };
+ Stream.prototype.publish = function () {
+ var _this = this;
+ return new Promise(function (resolve, reject) {
+ if (_this.isLocalStreamReadyToPublish) {
+ _this.initWebRtcPeerSend()
+ .then(function () {
+ resolve();
+ })
+ .catch(function (error) {
+ reject(error);
+ });
+ }
+ else {
+ _this.ee.once('stream-ready-to-publish', function () {
+ _this.publish()
+ .then(function () {
+ resolve();
+ })
+ .catch(function (error) {
+ reject(error);
+ });
+ });
+ }
+ });
+ };
+ Stream.prototype.disposeWebRtcPeer = function () {
+ if (this.webRtcPeer) {
+ this.webRtcPeer.dispose();
+ }
+ if (this.speechEvent) {
+ this.speechEvent.stop();
+ }
+ this.stopWebRtcStats();
+ console.info((!!this.outboundStreamOpts ? 'Outbound ' : 'Inbound ') + "WebRTCPeer from 'Stream' with id [" + this.streamId + '] is now closed');
+ };
+ Stream.prototype.disposeMediaStream = function () {
+ if (this.mediaStream) {
+ this.mediaStream.getAudioTracks().forEach(function (track) {
+ track.stop();
+ });
+ this.mediaStream.getVideoTracks().forEach(function (track) {
+ track.stop();
+ });
+ delete this.mediaStream;
+ }
+ console.info((!!this.outboundStreamOpts ? 'Local ' : 'Remote ') + "MediaStream from 'Stream' with id [" + this.streamId + '] is now disposed');
+ };
+ Stream.prototype.displayMyRemote = function () {
+ return this.isSubscribeToRemote;
+ };
+ Stream.prototype.isSendAudio = function () {
+ return (!!this.outboundStreamOpts &&
+ this.outboundStreamOpts.publisherProperties.audioSource !== null &&
+ this.outboundStreamOpts.publisherProperties.audioSource !== false);
+ };
+ Stream.prototype.isSendVideo = function () {
+ return (!!this.outboundStreamOpts &&
+ this.outboundStreamOpts.publisherProperties.videoSource !== null &&
+ this.outboundStreamOpts.publisherProperties.videoSource !== false);
+ };
+ Stream.prototype.isSendScreen = function () {
+ return (!!this.outboundStreamOpts &&
+ this.outboundStreamOpts.publisherProperties.videoSource === 'screen');
+ };
+ Stream.prototype.setSpeechEventIfNotExists = function () {
+ if (!this.speechEvent) {
+ var harkOptions = this.session.openvidu.advancedConfiguration.publisherSpeakingEventsOptions || {};
+ harkOptions.interval = (typeof harkOptions.interval === 'number') ? harkOptions.interval : 50;
+ harkOptions.threshold = (typeof harkOptions.threshold === 'number') ? harkOptions.threshold : -50;
+ this.speechEvent = hark(this.mediaStream, harkOptions);
+ }
+ };
+ Stream.prototype.enableSpeakingEvents = function () {
+ var _this = this;
+ this.setSpeechEventIfNotExists();
+ this.speechEvent.on('speaking', function () {
+ _this.session.emitEvent('publisherStartSpeaking', [new PublisherSpeakingEvent_1.PublisherSpeakingEvent(_this.session, 'publisherStartSpeaking', _this.connection, _this.streamId)]);
+ });
+ this.speechEvent.on('stopped_speaking', function () {
+ _this.session.emitEvent('publisherStopSpeaking', [new PublisherSpeakingEvent_1.PublisherSpeakingEvent(_this.session, 'publisherStopSpeaking', _this.connection, _this.streamId)]);
+ });
+ };
+ Stream.prototype.enableOnceSpeakingEvents = function () {
+ var _this = this;
+ this.setSpeechEventIfNotExists();
+ this.speechEvent.on('speaking', function () {
+ _this.session.emitEvent('publisherStartSpeaking', [new PublisherSpeakingEvent_1.PublisherSpeakingEvent(_this.session, 'publisherStartSpeaking', _this.connection, _this.streamId)]);
+ _this.disableSpeakingEvents();
+ });
+ this.speechEvent.on('stopped_speaking', function () {
+ _this.session.emitEvent('publisherStopSpeaking', [new PublisherSpeakingEvent_1.PublisherSpeakingEvent(_this.session, 'publisherStopSpeaking', _this.connection, _this.streamId)]);
+ _this.disableSpeakingEvents();
+ });
+ };
+ Stream.prototype.disableSpeakingEvents = function () {
+ this.speechEvent.stop();
+ this.speechEvent = undefined;
+ };
+ Stream.prototype.isLocal = function () {
+ return (!this.inboundStreamOpts && !!this.outboundStreamOpts);
+ };
+ Stream.prototype.getSelectedIceCandidate = function () {
+ var _this = this;
+ return new Promise(function (resolve, reject) {
+ _this.webRtcStats.getSelectedIceCandidateInfo()
+ .then(function (report) { return resolve(report); })
+ .catch(function (error) { return reject(error); });
+ });
+ };
+ Stream.prototype.getRemoteIceCandidateList = function () {
+ return this.webRtcPeer.remoteCandidatesQueue;
+ };
+ Stream.prototype.getLocalIceCandidateList = function () {
+ return this.webRtcPeer.localCandidatesQueue;
+ };
+ Stream.prototype.initWebRtcPeerSend = function () {
+ var _this = this;
+ return new Promise(function (resolve, reject) {
+ var userMediaConstraints = {
+ audio: _this.isSendAudio(),
+ video: _this.isSendVideo()
+ };
+ var options = {
+ mediaStream: _this.mediaStream,
+ mediaConstraints: userMediaConstraints,
+ onicecandidate: _this.connection.sendIceCandidate.bind(_this.connection),
+ iceServers: _this.getIceServersConf(),
+ simulcast: false
+ };
+ var successCallback = function (sdpOfferParam) {
+ console.debug('Sending SDP offer to publish as '
+ + _this.streamId, sdpOfferParam);
+ var typeOfVideo = '';
+ if (_this.isSendVideo()) {
+ typeOfVideo = _this.outboundStreamOpts.publisherProperties.videoSource instanceof MediaStreamTrack ? 'CUSTOM' : (_this.isSendScreen() ? 'SCREEN' : 'CAMERA');
+ }
+ _this.session.openvidu.sendRequest('publishVideo', {
+ sdpOffer: sdpOfferParam,
+ doLoopback: _this.displayMyRemote() || false,
+ hasAudio: _this.isSendAudio(),
+ hasVideo: _this.isSendVideo(),
+ audioActive: _this.audioActive,
+ videoActive: _this.videoActive,
+ typeOfVideo: typeOfVideo,
+ frameRate: !!_this.frameRate ? _this.frameRate : -1,
+ videoDimensions: JSON.stringify(_this.videoDimensions)
+ }, function (error, response) {
+ if (error) {
+ if (error.code === 401) {
+ reject(new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.OPENVIDU_PERMISSION_DENIED, "You don't have permissions to publish"));
+ }
+ else {
+ reject('Error on publishVideo: ' + JSON.stringify(error));
+ }
+ }
+ else {
+ _this.webRtcPeer.processAnswer(response.sdpAnswer)
+ .then(function () {
+ _this.streamId = response.id;
+ _this.isLocalStreamPublished = true;
+ _this.publishedOnce = true;
+ if (_this.displayMyRemote()) {
+ _this.remotePeerSuccessfullyEstablished();
+ }
+ _this.ee.emitEvent('stream-created-by-publisher');
+ _this.initWebRtcStats();
+ resolve();
+ })
+ .catch(function (error) {
+ reject(error);
+ });
+ console.info("'Publisher' successfully published to session");
+ }
+ });
+ };
+ if (_this.displayMyRemote()) {
+ _this.webRtcPeer = new WebRtcPeer_1.WebRtcPeerSendrecv(options);
+ }
+ else {
+ _this.webRtcPeer = new WebRtcPeer_1.WebRtcPeerSendonly(options);
+ }
+ _this.webRtcPeer.generateOffer().then(function (offer) {
+ successCallback(offer);
+ }).catch(function (error) {
+ reject(new Error('(publish) SDP offer error: ' + JSON.stringify(error)));
+ });
+ });
+ };
+ Stream.prototype.initWebRtcPeerReceive = function () {
+ var _this = this;
+ return new Promise(function (resolve, reject) {
+ var offerConstraints = {
+ audio: _this.inboundStreamOpts.hasAudio,
+ video: _this.inboundStreamOpts.hasVideo
+ };
+ console.debug("'Session.subscribe(Stream)' called. Constraints of generate SDP offer", offerConstraints);
+ var options = {
+ onicecandidate: _this.connection.sendIceCandidate.bind(_this.connection),
+ mediaConstraints: offerConstraints,
+ iceServers: _this.getIceServersConf(),
+ simulcast: false
+ };
+ var successCallback = function (sdpOfferParam) {
+ console.debug('Sending SDP offer to subscribe to '
+ + _this.streamId, sdpOfferParam);
+ _this.session.openvidu.sendRequest('receiveVideoFrom', {
+ sender: _this.streamId,
+ sdpOffer: sdpOfferParam
+ }, function (error, response) {
+ if (error) {
+ reject(new Error('Error on recvVideoFrom: ' + JSON.stringify(error)));
+ }
+ else {
+ _this.webRtcPeer.processAnswer(response.sdpAnswer).then(function () {
+ _this.remotePeerSuccessfullyEstablished();
+ _this.initWebRtcStats();
+ resolve();
+ }).catch(function (error) {
+ reject(error);
+ });
+ }
+ });
+ };
+ _this.webRtcPeer = new WebRtcPeer_1.WebRtcPeerRecvonly(options);
+ _this.webRtcPeer.generateOffer()
+ .then(function (offer) {
+ successCallback(offer);
+ })
+ .catch(function (error) {
+ reject(new Error('(subscribe) SDP offer error: ' + JSON.stringify(error)));
+ });
+ });
+ };
+ Stream.prototype.remotePeerSuccessfullyEstablished = function () {
+ this.mediaStream = this.webRtcPeer.pc.getRemoteStreams()[0];
+ console.debug('Peer remote stream', this.mediaStream);
+ if (!!this.mediaStream) {
+ this.ee.emitEvent('mediastream-updated');
+ if (!this.displayMyRemote() && !!this.mediaStream.getAudioTracks()[0] && this.session.speakingEventsEnabled) {
+ this.enableSpeakingEvents();
+ }
+ }
+ };
+ Stream.prototype.initWebRtcStats = function () {
+ this.webRtcStats = new WebRtcStats_1.WebRtcStats(this);
+ this.webRtcStats.initWebRtcStats();
+ };
+ Stream.prototype.stopWebRtcStats = function () {
+ if (!!this.webRtcStats && this.webRtcStats.isEnabled()) {
+ this.webRtcStats.stopWebRtcStats();
+ }
+ };
+ Stream.prototype.getIceServersConf = function () {
+ var returnValue;
+ if (!!this.session.openvidu.advancedConfiguration.iceServers) {
+ returnValue = this.session.openvidu.advancedConfiguration.iceServers === 'freeice' ?
+ undefined :
+ this.session.openvidu.advancedConfiguration.iceServers;
+ }
+ else if (this.session.openvidu.iceServers) {
+ returnValue = this.session.openvidu.iceServers;
+ }
+ else {
+ returnValue = undefined;
+ }
+ return returnValue;
+ };
+ return Stream;
+}());
+exports.Stream = Stream;
+
+},{"../OpenViduInternal/Enums/OpenViduError":26,"../OpenViduInternal/Events/PublisherSpeakingEvent":30,"../OpenViduInternal/WebRtcPeer/WebRtcPeer":49,"../OpenViduInternal/WebRtcStats/WebRtcStats":50,"hark":5,"wolfy87-eventemitter":15}],23:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+var StreamManagerEvent_1 = require("../OpenViduInternal/Events/StreamManagerEvent");
+var VideoElementEvent_1 = require("../OpenViduInternal/Events/VideoElementEvent");
+var VideoInsertMode_1 = require("../OpenViduInternal/Enums/VideoInsertMode");
+var EventEmitter = require("wolfy87-eventemitter");
+var StreamManager = (function () {
+ function StreamManager(stream, targetElement) {
+ var _this = this;
+ this.videos = [];
+ this.lazyLaunchVideoElementCreatedEvent = false;
+ this.ee = new EventEmitter();
+ this.stream = stream;
+ this.stream.streamManager = this;
+ this.remote = !this.stream.isLocal();
+ if (!!targetElement) {
+ var targEl = void 0;
+ if (typeof targetElement === 'string') {
+ targEl = document.getElementById(targetElement);
+ }
+ else if (targetElement instanceof HTMLElement) {
+ targEl = targetElement;
+ }
+ if (!!targEl) {
+ this.firstVideoElement = {
+ targetElement: targEl,
+ video: document.createElement('video'),
+ id: ''
+ };
+ this.targetElement = targEl;
+ this.element = targEl;
+ }
+ }
+ this.canPlayListener = function () {
+ if (_this.stream.isLocal()) {
+ if (!_this.stream.displayMyRemote()) {
+ console.info("Your local 'Stream' with id [" + _this.stream.streamId + '] video is now playing');
+ _this.ee.emitEvent('videoPlaying', [new VideoElementEvent_1.VideoElementEvent(_this.videos[0].video, _this, 'videoPlaying')]);
+ }
+ else {
+ console.info("Your own remote 'Stream' with id [" + _this.stream.streamId + '] video is now playing');
+ _this.ee.emitEvent('remoteVideoPlaying', [new VideoElementEvent_1.VideoElementEvent(_this.videos[0].video, _this, 'remoteVideoPlaying')]);
+ }
+ }
+ else {
+ console.info("Remote 'Stream' with id [" + _this.stream.streamId + '] video is now playing');
+ _this.ee.emitEvent('videoPlaying', [new VideoElementEvent_1.VideoElementEvent(_this.videos[0].video, _this, 'videoPlaying')]);
+ }
+ _this.ee.emitEvent('streamPlaying', [new StreamManagerEvent_1.StreamManagerEvent(_this)]);
+ };
+ }
+ StreamManager.prototype.on = function (type, handler) {
+ var _this = this;
+ this.ee.on(type, function (event) {
+ if (event) {
+ console.info("Event '" + type + "' triggered by '" + (_this.remote ? 'Subscriber' : 'Publisher') + "'", event);
+ }
+ else {
+ console.info("Event '" + type + "' triggered by '" + (_this.remote ? 'Subscriber' : 'Publisher') + "'");
+ }
+ handler(event);
+ });
+ if (type === 'videoElementCreated') {
+ if (!!this.stream && this.lazyLaunchVideoElementCreatedEvent) {
+ this.ee.emitEvent('videoElementCreated', [new VideoElementEvent_1.VideoElementEvent(this.videos[0].video, this, 'videoElementCreated')]);
+ this.lazyLaunchVideoElementCreatedEvent = false;
+ }
+ }
+ if (type === 'streamPlaying' || type === 'videoPlaying') {
+ if (this.videos[0] && this.videos[0].video &&
+ this.videos[0].video.currentTime > 0 &&
+ this.videos[0].video.paused === false &&
+ this.videos[0].video.ended === false &&
+ this.videos[0].video.readyState === 4) {
+ this.ee.emitEvent('streamPlaying', [new StreamManagerEvent_1.StreamManagerEvent(this)]);
+ this.ee.emitEvent('videoPlaying', [new VideoElementEvent_1.VideoElementEvent(this.videos[0].video, this, 'videoPlaying')]);
+ }
+ }
+ return this;
+ };
+ StreamManager.prototype.once = function (type, handler) {
+ this.ee.once(type, function (event) {
+ if (event) {
+ console.info("Event '" + type + "' triggered once", event);
+ }
+ else {
+ console.info("Event '" + type + "' triggered once");
+ }
+ handler(event);
+ });
+ if (type === 'videoElementCreated') {
+ if (!!this.stream && this.lazyLaunchVideoElementCreatedEvent) {
+ this.ee.emitEvent('videoElementCreated', [new VideoElementEvent_1.VideoElementEvent(this.videos[0].video, this, 'videoElementCreated')]);
+ }
+ }
+ if (type === 'streamPlaying' || type === 'videoPlaying') {
+ if (this.videos[0] && this.videos[0].video &&
+ this.videos[0].video.currentTime > 0 &&
+ this.videos[0].video.paused === false &&
+ this.videos[0].video.ended === false &&
+ this.videos[0].video.readyState === 4) {
+ this.ee.emitEvent('streamPlaying', [new StreamManagerEvent_1.StreamManagerEvent(this)]);
+ this.ee.emitEvent('videoPlaying', [new VideoElementEvent_1.VideoElementEvent(this.videos[0].video, this, 'videoPlaying')]);
+ }
+ }
+ return this;
+ };
+ StreamManager.prototype.off = function (type, handler) {
+ if (!handler) {
+ this.ee.removeAllListeners(type);
+ }
+ else {
+ this.ee.off(type, handler);
+ }
+ return this;
+ };
+ StreamManager.prototype.addVideoElement = function (video) {
+ this.initializeVideoProperties(video);
+ for (var _i = 0, _a = this.videos; _i < _a.length; _i++) {
+ var v = _a[_i];
+ if (v.video === video) {
+ return 0;
+ }
+ }
+ var returnNumber = 1;
+ for (var _b = 0, _c = this.stream.session.streamManagers; _b < _c.length; _b++) {
+ var streamManager = _c[_b];
+ if (streamManager.disassociateVideo(video)) {
+ returnNumber = -1;
+ break;
+ }
+ }
+ this.stream.session.streamManagers.forEach(function (streamManager) {
+ streamManager.disassociateVideo(video);
+ });
+ this.pushNewStreamManagerVideo({
+ video: video,
+ id: video.id
+ });
+ console.info('New video element associated to ', this);
+ return returnNumber;
+ };
+ StreamManager.prototype.createVideoElement = function (targetElement, insertMode) {
+ var targEl;
+ if (typeof targetElement === 'string') {
+ targEl = document.getElementById(targEl);
+ if (!targEl) {
+ throw new Error("The provided 'targetElement' couldn't be resolved to any HTML element: " + targetElement);
+ }
+ }
+ else if (targetElement instanceof HTMLElement) {
+ targEl = targetElement;
+ }
+ else {
+ throw new Error("The provided 'targetElement' couldn't be resolved to any HTML element: " + targetElement);
+ }
+ var video = document.createElement('video');
+ this.initializeVideoProperties(video);
+ var insMode = !!insertMode ? insertMode : VideoInsertMode_1.VideoInsertMode.APPEND;
+ switch (insMode) {
+ case VideoInsertMode_1.VideoInsertMode.AFTER:
+ targEl.parentNode.insertBefore(video, targEl.nextSibling);
+ break;
+ case VideoInsertMode_1.VideoInsertMode.APPEND:
+ targEl.appendChild(video);
+ break;
+ case VideoInsertMode_1.VideoInsertMode.BEFORE:
+ targEl.parentNode.insertBefore(video, targEl);
+ break;
+ case VideoInsertMode_1.VideoInsertMode.PREPEND:
+ targEl.insertBefore(video, targEl.childNodes[0]);
+ break;
+ case VideoInsertMode_1.VideoInsertMode.REPLACE:
+ targEl.parentNode.replaceChild(video, targEl);
+ break;
+ default:
+ insMode = VideoInsertMode_1.VideoInsertMode.APPEND;
+ targEl.appendChild(video);
+ break;
+ }
+ var v = {
+ targetElement: targEl,
+ video: video,
+ insertMode: insMode,
+ id: video.id
+ };
+ this.pushNewStreamManagerVideo(v);
+ this.ee.emitEvent('videoElementCreated', [new VideoElementEvent_1.VideoElementEvent(v.video, this, 'videoElementCreated')]);
+ this.lazyLaunchVideoElementCreatedEvent = !!this.firstVideoElement;
+ return video;
+ };
+ StreamManager.prototype.initializeVideoProperties = function (video) {
+ if (!(this.stream.isLocal() && this.stream.displayMyRemote())) {
+ video.srcObject = this.stream.getMediaStream();
+ }
+ video.autoplay = true;
+ video.controls = false;
+ if (!video.id) {
+ video.id = (this.remote ? 'remote-' : 'local-') + 'video-' + this.stream.streamId;
+ if (!this.id && !!this.targetElement) {
+ this.id = video.id;
+ }
+ }
+ if (!this.remote && !this.stream.displayMyRemote()) {
+ video.muted = true;
+ if (this.stream.outboundStreamOpts.publisherProperties.mirror) {
+ this.mirrorVideo(video);
+ }
+ }
+ };
+ StreamManager.prototype.removeAllVideos = function () {
+ var _this = this;
+ for (var i = this.stream.session.streamManagers.length - 1; i >= 0; --i) {
+ if (this.stream.session.streamManagers[i] === this) {
+ this.stream.session.streamManagers.splice(i, 1);
+ }
+ }
+ this.videos.forEach(function (streamManagerVideo) {
+ streamManagerVideo.video.removeEventListener('canplay', _this.canPlayListener);
+ if (!!streamManagerVideo.targetElement) {
+ streamManagerVideo.video.parentNode.removeChild(streamManagerVideo.video);
+ _this.ee.emitEvent('videoElementDestroyed', [new VideoElementEvent_1.VideoElementEvent(streamManagerVideo.video, _this, 'videoElementDestroyed')]);
+ }
+ streamManagerVideo.video.srcObject = null;
+ _this.videos.filter(function (v) { return !v.targetElement; });
+ });
+ };
+ StreamManager.prototype.disassociateVideo = function (video) {
+ var disassociated = false;
+ for (var i = 0; i < this.videos.length; i++) {
+ if (this.videos[i].video === video) {
+ this.videos.splice(i, 1);
+ disassociated = true;
+ console.info('Video element disassociated from ', this);
+ break;
+ }
+ }
+ return disassociated;
+ };
+ StreamManager.prototype.addPlayEventToFirstVideo = function () {
+ if ((!!this.videos[0]) && (!!this.videos[0].video) && (this.videos[0].video.oncanplay === null)) {
+ this.videos[0].video.addEventListener('canplay', this.canPlayListener);
+ }
+ };
+ StreamManager.prototype.updateMediaStream = function (mediaStream) {
+ this.videos.forEach(function (streamManagerVideo) {
+ streamManagerVideo.video.srcObject = mediaStream;
+ });
+ };
+ StreamManager.prototype.emitEvent = function (type, eventArray) {
+ this.ee.emitEvent(type, eventArray);
+ };
+ StreamManager.prototype.pushNewStreamManagerVideo = function (streamManagerVideo) {
+ this.videos.push(streamManagerVideo);
+ this.addPlayEventToFirstVideo();
+ if (this.stream.session.streamManagers.indexOf(this) === -1) {
+ this.stream.session.streamManagers.push(this);
+ }
+ };
+ StreamManager.prototype.mirrorVideo = function (video) {
+ video.style.transform = 'rotateY(180deg)';
+ video.style.webkitTransform = 'rotateY(180deg)';
+ };
+ return StreamManager;
+}());
+exports.StreamManager = StreamManager;
+
+},{"../OpenViduInternal/Enums/VideoInsertMode":27,"../OpenViduInternal/Events/StreamManagerEvent":35,"../OpenViduInternal/Events/VideoElementEvent":37,"wolfy87-eventemitter":15}],24:[function(require,module,exports){
+"use strict";
+var __extends = (this && this.__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 __());
+ };
+})();
+Object.defineProperty(exports, "__esModule", { value: true });
+var StreamManager_1 = require("./StreamManager");
+var Subscriber = (function (_super) {
+ __extends(Subscriber, _super);
+ function Subscriber(stream, targEl, properties) {
+ var _this = _super.call(this, stream, targEl) || this;
+ _this.element = _this.targetElement;
+ _this.stream = stream;
+ _this.properties = properties;
+ return _this;
+ }
+ Subscriber.prototype.subscribeToAudio = function (value) {
+ this.stream.getMediaStream().getAudioTracks().forEach(function (track) {
+ track.enabled = value;
+ });
+ console.info("'Subscriber' has " + (value ? 'subscribed to' : 'unsubscribed from') + ' its audio stream');
+ return this;
+ };
+ Subscriber.prototype.subscribeToVideo = function (value) {
+ this.stream.getMediaStream().getVideoTracks().forEach(function (track) {
+ track.enabled = value;
+ });
+ console.info("'Subscriber' has " + (value ? 'subscribed to' : 'unsubscribed from') + ' its video stream');
+ return this;
+ };
+ return Subscriber;
+}(StreamManager_1.StreamManager));
+exports.Subscriber = Subscriber;
+
+},{"./StreamManager":23}],25:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+var LocalRecorderState;
+(function (LocalRecorderState) {
+ LocalRecorderState["READY"] = "READY";
+ LocalRecorderState["RECORDING"] = "RECORDING";
+ LocalRecorderState["PAUSED"] = "PAUSED";
+ LocalRecorderState["FINISHED"] = "FINISHED";
+})(LocalRecorderState = exports.LocalRecorderState || (exports.LocalRecorderState = {}));
+
+},{}],26:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+var OpenViduErrorName;
+(function (OpenViduErrorName) {
+ OpenViduErrorName["BROWSER_NOT_SUPPORTED"] = "BROWSER_NOT_SUPPORTED";
+ OpenViduErrorName["DEVICE_ACCESS_DENIED"] = "DEVICE_ACCESS_DENIED";
+ OpenViduErrorName["SCREEN_CAPTURE_DENIED"] = "SCREEN_CAPTURE_DENIED";
+ OpenViduErrorName["SCREEN_SHARING_NOT_SUPPORTED"] = "SCREEN_SHARING_NOT_SUPPORTED";
+ OpenViduErrorName["SCREEN_EXTENSION_NOT_INSTALLED"] = "SCREEN_EXTENSION_NOT_INSTALLED";
+ OpenViduErrorName["SCREEN_EXTENSION_DISABLED"] = "SCREEN_EXTENSION_DISABLED";
+ OpenViduErrorName["INPUT_VIDEO_DEVICE_NOT_FOUND"] = "INPUT_VIDEO_DEVICE_NOT_FOUND";
+ OpenViduErrorName["INPUT_AUDIO_DEVICE_NOT_FOUND"] = "INPUT_AUDIO_DEVICE_NOT_FOUND";
+ OpenViduErrorName["NO_INPUT_SOURCE_SET"] = "NO_INPUT_SOURCE_SET";
+ OpenViduErrorName["PUBLISHER_PROPERTIES_ERROR"] = "PUBLISHER_PROPERTIES_ERROR";
+ OpenViduErrorName["OPENVIDU_PERMISSION_DENIED"] = "OPENVIDU_PERMISSION_DENIED";
+ OpenViduErrorName["OPENVIDU_NOT_CONNECTED"] = "OPENVIDU_NOT_CONNECTED";
+ OpenViduErrorName["GENERIC_ERROR"] = "GENERIC_ERROR";
+})(OpenViduErrorName = exports.OpenViduErrorName || (exports.OpenViduErrorName = {}));
+var OpenViduError = (function () {
+ function OpenViduError(name, message) {
+ this.name = name;
+ this.message = message;
+ }
+ return OpenViduError;
+}());
+exports.OpenViduError = OpenViduError;
+
+},{}],27:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+var VideoInsertMode;
+(function (VideoInsertMode) {
+ VideoInsertMode["AFTER"] = "AFTER";
+ VideoInsertMode["APPEND"] = "APPEND";
+ VideoInsertMode["BEFORE"] = "BEFORE";
+ VideoInsertMode["PREPEND"] = "PREPEND";
+ VideoInsertMode["REPLACE"] = "REPLACE";
+})(VideoInsertMode = exports.VideoInsertMode || (exports.VideoInsertMode = {}));
+
+},{}],28:[function(require,module,exports){
+"use strict";
+var __extends = (this && this.__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 __());
+ };
+})();
+Object.defineProperty(exports, "__esModule", { value: true });
+var Event_1 = require("./Event");
+var ConnectionEvent = (function (_super) {
+ __extends(ConnectionEvent, _super);
+ function ConnectionEvent(cancelable, target, type, connection, reason) {
+ var _this = _super.call(this, cancelable, target, type) || this;
+ _this.connection = connection;
+ _this.reason = reason;
+ return _this;
+ }
+ ConnectionEvent.prototype.callDefaultBehavior = function () { };
+ return ConnectionEvent;
+}(Event_1.Event));
+exports.ConnectionEvent = ConnectionEvent;
+
+},{"./Event":29}],29:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+var Event = (function () {
+ function Event(cancelable, target, type) {
+ this.hasBeenPrevented = false;
+ this.cancelable = cancelable;
+ this.target = target;
+ this.type = type;
+ }
+ Event.prototype.isDefaultPrevented = function () {
+ return this.hasBeenPrevented;
+ };
+ Event.prototype.preventDefault = function () {
+ this.callDefaultBehavior = function () { };
+ this.hasBeenPrevented = true;
+ };
+ return Event;
+}());
+exports.Event = Event;
+
+},{}],30:[function(require,module,exports){
+"use strict";
+var __extends = (this && this.__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 __());
+ };
+})();
+Object.defineProperty(exports, "__esModule", { value: true });
+var Event_1 = require("./Event");
+var PublisherSpeakingEvent = (function (_super) {
+ __extends(PublisherSpeakingEvent, _super);
+ function PublisherSpeakingEvent(target, type, connection, streamId) {
+ var _this = _super.call(this, false, target, type) || this;
+ _this.type = type;
+ _this.connection = connection;
+ _this.streamId = streamId;
+ return _this;
+ }
+ PublisherSpeakingEvent.prototype.callDefaultBehavior = function () { };
+ return PublisherSpeakingEvent;
+}(Event_1.Event));
+exports.PublisherSpeakingEvent = PublisherSpeakingEvent;
+
+},{"./Event":29}],31:[function(require,module,exports){
+"use strict";
+var __extends = (this && this.__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 __());
+ };
+})();
+Object.defineProperty(exports, "__esModule", { value: true });
+var Event_1 = require("./Event");
+var RecordingEvent = (function (_super) {
+ __extends(RecordingEvent, _super);
+ function RecordingEvent(target, type, id, name) {
+ var _this = _super.call(this, false, target, type) || this;
+ _this.id = id;
+ if (name !== id) {
+ _this.name = name;
+ }
+ return _this;
+ }
+ RecordingEvent.prototype.callDefaultBehavior = function () { };
+ return RecordingEvent;
+}(Event_1.Event));
+exports.RecordingEvent = RecordingEvent;
+
+},{"./Event":29}],32:[function(require,module,exports){
+"use strict";
+var __extends = (this && this.__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 __());
+ };
+})();
+Object.defineProperty(exports, "__esModule", { value: true });
+var Event_1 = require("./Event");
+var SessionDisconnectedEvent = (function (_super) {
+ __extends(SessionDisconnectedEvent, _super);
+ function SessionDisconnectedEvent(target, reason) {
+ var _this = _super.call(this, true, target, 'sessionDisconnected') || this;
+ _this.reason = reason;
+ return _this;
+ }
+ SessionDisconnectedEvent.prototype.callDefaultBehavior = function () {
+ console.info("Calling default behavior upon '" + this.type + "' event dispatched by 'Session'");
+ var session = this.target;
+ for (var connectionId in session.remoteConnections) {
+ if (!!session.remoteConnections[connectionId].stream) {
+ session.remoteConnections[connectionId].stream.disposeWebRtcPeer();
+ session.remoteConnections[connectionId].stream.disposeMediaStream();
+ if (session.remoteConnections[connectionId].stream.streamManager) {
+ session.remoteConnections[connectionId].stream.streamManager.removeAllVideos();
+ }
+ delete session.remoteStreamsCreated[session.remoteConnections[connectionId].stream.streamId];
+ session.remoteConnections[connectionId].dispose();
+ }
+ delete session.remoteConnections[connectionId];
+ }
+ };
+ return SessionDisconnectedEvent;
+}(Event_1.Event));
+exports.SessionDisconnectedEvent = SessionDisconnectedEvent;
+
+},{"./Event":29}],33:[function(require,module,exports){
+"use strict";
+var __extends = (this && this.__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 __());
+ };
+})();
+Object.defineProperty(exports, "__esModule", { value: true });
+var Event_1 = require("./Event");
+var SignalEvent = (function (_super) {
+ __extends(SignalEvent, _super);
+ function SignalEvent(target, type, data, from) {
+ var _this = _super.call(this, false, target, type) || this;
+ _this.type = type;
+ _this.data = data;
+ _this.from = from;
+ return _this;
+ }
+ SignalEvent.prototype.callDefaultBehavior = function () { };
+ return SignalEvent;
+}(Event_1.Event));
+exports.SignalEvent = SignalEvent;
+
+},{"./Event":29}],34:[function(require,module,exports){
+"use strict";
+var __extends = (this && this.__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 __());
+ };
+})();
+Object.defineProperty(exports, "__esModule", { value: true });
+var Event_1 = require("./Event");
+var Publisher_1 = require("../../OpenVidu/Publisher");
+var Session_1 = require("../../OpenVidu/Session");
+var StreamEvent = (function (_super) {
+ __extends(StreamEvent, _super);
+ function StreamEvent(cancelable, target, type, stream, reason) {
+ var _this = _super.call(this, cancelable, target, type) || this;
+ _this.stream = stream;
+ _this.reason = reason;
+ return _this;
+ }
+ StreamEvent.prototype.callDefaultBehavior = function () {
+ if (this.type === 'streamDestroyed') {
+ if (this.target instanceof Session_1.Session) {
+ console.info("Calling default behavior upon '" + this.type + "' event dispatched by 'Session'");
+ this.stream.disposeWebRtcPeer();
+ }
+ else if (this.target instanceof Publisher_1.Publisher) {
+ console.info("Calling default behavior upon '" + this.type + "' event dispatched by 'Publisher'");
+ clearInterval(this.target.screenShareResizeInterval);
+ this.stream.isLocalStreamReadyToPublish = false;
+ var openviduPublishers = this.target.openvidu.publishers;
+ for (var i = 0; i < openviduPublishers.length; i++) {
+ if (openviduPublishers[i] === this.target) {
+ openviduPublishers.splice(i, 1);
+ break;
+ }
+ }
+ }
+ this.stream.disposeMediaStream();
+ if (this.stream.streamManager)
+ this.stream.streamManager.removeAllVideos();
+ delete this.stream.session.remoteStreamsCreated[this.stream.streamId];
+ var remoteConnection = this.stream.session.remoteConnections[this.stream.connection.connectionId];
+ if (!!remoteConnection && !!remoteConnection.options) {
+ var streamOptionsServer = remoteConnection.options.streams;
+ for (var i = streamOptionsServer.length - 1; i >= 0; --i) {
+ if (streamOptionsServer[i].id === this.stream.streamId) {
+ streamOptionsServer.splice(i, 1);
+ }
+ }
+ }
+ }
+ };
+ return StreamEvent;
+}(Event_1.Event));
+exports.StreamEvent = StreamEvent;
+
+},{"../../OpenVidu/Publisher":20,"../../OpenVidu/Session":21,"./Event":29}],35:[function(require,module,exports){
+"use strict";
+var __extends = (this && this.__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 __());
+ };
+})();
+Object.defineProperty(exports, "__esModule", { value: true });
+var Event_1 = require("./Event");
+var StreamManagerEvent = (function (_super) {
+ __extends(StreamManagerEvent, _super);
+ function StreamManagerEvent(target) {
+ return _super.call(this, false, target, 'streamPlaying') || this;
+ }
+ StreamManagerEvent.prototype.callDefaultBehavior = function () { };
+ return StreamManagerEvent;
+}(Event_1.Event));
+exports.StreamManagerEvent = StreamManagerEvent;
+
+},{"./Event":29}],36:[function(require,module,exports){
+"use strict";
+var __extends = (this && this.__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 __());
+ };
+})();
+Object.defineProperty(exports, "__esModule", { value: true });
+var Event_1 = require("./Event");
+var StreamPropertyChangedEvent = (function (_super) {
+ __extends(StreamPropertyChangedEvent, _super);
+ function StreamPropertyChangedEvent(target, stream, changedProperty, newValue, oldValue, reason) {
+ var _this = _super.call(this, false, target, 'streamPropertyChanged') || this;
+ _this.stream = stream;
+ _this.changedProperty = changedProperty;
+ _this.newValue = newValue;
+ _this.oldValue = oldValue;
+ _this.reason = reason;
+ return _this;
+ }
+ StreamPropertyChangedEvent.prototype.callDefaultBehavior = function () { };
+ return StreamPropertyChangedEvent;
+}(Event_1.Event));
+exports.StreamPropertyChangedEvent = StreamPropertyChangedEvent;
+
+},{"./Event":29}],37:[function(require,module,exports){
+"use strict";
+var __extends = (this && this.__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 __());
+ };
+})();
+Object.defineProperty(exports, "__esModule", { value: true });
+var Event_1 = require("./Event");
+var VideoElementEvent = (function (_super) {
+ __extends(VideoElementEvent, _super);
+ function VideoElementEvent(element, target, type) {
+ var _this = _super.call(this, false, target, type) || this;
+ _this.element = element;
+ return _this;
+ }
+ VideoElementEvent.prototype.callDefaultBehavior = function () { };
+ return VideoElementEvent;
+}(Event_1.Event));
+exports.VideoElementEvent = VideoElementEvent;
+
+},{"./Event":29}],38:[function(require,module,exports){
+function Mapper() {
+ var sources = {};
+ this.forEach = function (callback) {
+ for (var key in sources) {
+ var source = sources[key];
+ for (var key2 in source)
+ callback(source[key2]);
+ }
+ ;
+ };
+ this.get = function (id, source) {
+ var ids = sources[source];
+ if (ids == undefined)
+ return undefined;
+ return ids[id];
+ };
+ this.remove = function (id, source) {
+ var ids = sources[source];
+ if (ids == undefined)
+ return;
+ delete ids[id];
+ for (var i in ids) {
+ return false;
+ }
+ delete sources[source];
+ };
+ this.set = function (value, id, source) {
+ if (value == undefined)
+ return this.remove(id, source);
+ var ids = sources[source];
+ if (ids == undefined)
+ sources[source] = ids = {};
+ ids[id] = value;
+ };
+}
+;
+Mapper.prototype.pop = function (id, source) {
+ var value = this.get(id, source);
+ if (value == undefined)
+ return undefined;
+ this.remove(id, source);
+ return value;
+};
+module.exports = Mapper;
+
+},{}],39:[function(require,module,exports){
+var JsonRpcClient = require('./jsonrpcclient');
+exports.JsonRpcClient = JsonRpcClient;
+
+},{"./jsonrpcclient":40}],40:[function(require,module,exports){
+var RpcBuilder = require('../');
+var WebSocketWithReconnection = require('./transports/webSocketWithReconnection');
+Date.now = Date.now || function () {
+ return +new Date;
+};
+var PING_INTERVAL = 5000;
+var RECONNECTING = 'RECONNECTING';
+var CONNECTED = 'CONNECTED';
+var DISCONNECTED = 'DISCONNECTED';
+var Logger = console;
+function JsonRpcClient(configuration) {
+ var self = this;
+ var wsConfig = configuration.ws;
+ var notReconnectIfNumLessThan = -1;
+ var pingNextNum = 0;
+ var enabledPings = true;
+ var pingPongStarted = false;
+ var pingInterval;
+ var status = DISCONNECTED;
+ var onreconnecting = wsConfig.onreconnecting;
+ var onreconnected = wsConfig.onreconnected;
+ var onconnected = wsConfig.onconnected;
+ var onerror = wsConfig.onerror;
+ configuration.rpc.pull = function (params, request) {
+ request.reply(null, "push");
+ };
+ wsConfig.onreconnecting = function () {
+ Logger.debug("--------- ONRECONNECTING -----------");
+ if (status === RECONNECTING) {
+ Logger.error("Websocket already in RECONNECTING state when receiving a new ONRECONNECTING message. Ignoring it");
+ return;
+ }
+ status = RECONNECTING;
+ if (onreconnecting) {
+ onreconnecting();
+ }
+ };
+ wsConfig.onreconnected = function () {
+ Logger.debug("--------- ONRECONNECTED -----------");
+ if (status === CONNECTED) {
+ Logger.error("Websocket already in CONNECTED state when receiving a new ONRECONNECTED message. Ignoring it");
+ return;
+ }
+ status = CONNECTED;
+ enabledPings = true;
+ updateNotReconnectIfLessThan();
+ usePing();
+ if (onreconnected) {
+ onreconnected();
+ }
+ };
+ wsConfig.onconnected = function () {
+ Logger.debug("--------- ONCONNECTED -----------");
+ if (status === CONNECTED) {
+ Logger.error("Websocket already in CONNECTED state when receiving a new ONCONNECTED message. Ignoring it");
+ return;
+ }
+ status = CONNECTED;
+ enabledPings = true;
+ usePing();
+ if (onconnected) {
+ onconnected();
+ }
+ };
+ wsConfig.onerror = function (error) {
+ Logger.debug("--------- ONERROR -----------");
+ status = DISCONNECTED;
+ if (onerror) {
+ onerror(error);
+ }
+ };
+ var ws = new WebSocketWithReconnection(wsConfig);
+ Logger.debug('Connecting websocket to URI: ' + wsConfig.uri);
+ var rpcBuilderOptions = {
+ request_timeout: configuration.rpc.requestTimeout,
+ ping_request_timeout: configuration.rpc.heartbeatRequestTimeout
+ };
+ var rpc = new RpcBuilder(RpcBuilder.packers.JsonRPC, rpcBuilderOptions, ws, function (request) {
+ Logger.debug('Received request: ' + JSON.stringify(request));
+ try {
+ var func = configuration.rpc[request.method];
+ if (func === undefined) {
+ Logger.error("Method " + request.method + " not registered in client");
+ }
+ else {
+ func(request.params, request);
+ }
+ }
+ catch (err) {
+ Logger.error('Exception processing request: ' + JSON.stringify(request));
+ Logger.error(err);
+ }
+ });
+ this.send = function (method, params, callback) {
+ if (method !== 'ping') {
+ Logger.debug('Request: method:' + method + " params:" + JSON.stringify(params));
+ }
+ var requestTime = Date.now();
+ rpc.encode(method, params, function (error, result) {
+ if (error) {
+ try {
+ Logger.error("ERROR:" + error.message + " in Request: method:" +
+ method + " params:" + JSON.stringify(params) + " request:" +
+ error.request);
+ if (error.data) {
+ Logger.error("ERROR DATA:" + JSON.stringify(error.data));
+ }
+ }
+ catch (e) { }
+ error.requestTime = requestTime;
+ }
+ if (callback) {
+ if (result != undefined && result.value !== 'pong') {
+ Logger.debug('Response: ' + JSON.stringify(result));
+ }
+ callback(error, result);
+ }
+ });
+ };
+ function updateNotReconnectIfLessThan() {
+ Logger.debug("notReconnectIfNumLessThan = " + pingNextNum + ' (old=' +
+ notReconnectIfNumLessThan + ')');
+ notReconnectIfNumLessThan = pingNextNum;
+ }
+ function sendPing() {
+ if (enabledPings) {
+ var params = null;
+ if (pingNextNum == 0 || pingNextNum == notReconnectIfNumLessThan) {
+ params = {
+ interval: configuration.heartbeat || PING_INTERVAL
+ };
+ }
+ pingNextNum++;
+ self.send('ping', params, (function (pingNum) {
+ return function (error, result) {
+ if (error) {
+ Logger.debug("Error in ping request #" + pingNum + " (" +
+ error.message + ")");
+ if (pingNum > notReconnectIfNumLessThan) {
+ enabledPings = false;
+ updateNotReconnectIfLessThan();
+ Logger.debug("Server did not respond to ping message #" +
+ pingNum + ". Reconnecting... ");
+ ws.reconnectWs();
+ }
+ }
+ };
+ })(pingNextNum));
+ }
+ else {
+ Logger.debug("Trying to send ping, but ping is not enabled");
+ }
+ }
+ function usePing() {
+ if (!pingPongStarted) {
+ Logger.debug("Starting ping (if configured)");
+ pingPongStarted = true;
+ if (configuration.heartbeat != undefined) {
+ pingInterval = setInterval(sendPing, configuration.heartbeat);
+ sendPing();
+ }
+ }
+ }
+ this.close = function () {
+ Logger.debug("Closing jsonRpcClient explicitly by client");
+ if (pingInterval != undefined) {
+ Logger.debug("Clearing ping interval");
+ clearInterval(pingInterval);
+ }
+ pingPongStarted = false;
+ enabledPings = false;
+ if (configuration.sendCloseMessage) {
+ Logger.debug("Sending close message");
+ this.send('closeSession', null, function (error, result) {
+ if (error) {
+ Logger.error("Error sending close message: " + JSON.stringify(error));
+ }
+ ws.close();
+ });
+ }
+ else {
+ ws.close();
+ }
+ };
+ this.forceClose = function (millis) {
+ ws.forceClose(millis);
+ };
+ this.reconnect = function () {
+ ws.reconnectWs();
+ };
+}
+module.exports = JsonRpcClient;
+
+},{"../":43,"./transports/webSocketWithReconnection":42}],41:[function(require,module,exports){
+var WebSocketWithReconnection = require('./webSocketWithReconnection');
+exports.WebSocketWithReconnection = WebSocketWithReconnection;
+
+},{"./webSocketWithReconnection":42}],42:[function(require,module,exports){
+(function (global){
+"use strict";
+var BrowserWebSocket = global.WebSocket || global.MozWebSocket;
+var Logger = console;
+var MAX_RETRIES = 2000;
+var RETRY_TIME_MS = 3000;
+var CONNECTING = 0;
+var OPEN = 1;
+var CLOSING = 2;
+var CLOSED = 3;
+function WebSocketWithReconnection(config) {
+ var closing = false;
+ var registerMessageHandler;
+ var wsUri = config.uri;
+ var useSockJS = config.useSockJS;
+ var reconnecting = false;
+ var forcingDisconnection = false;
+ var ws;
+ if (useSockJS) {
+ ws = new SockJS(wsUri);
+ }
+ else {
+ ws = new WebSocket(wsUri);
+ }
+ ws.onopen = function () {
+ logConnected(ws, wsUri);
+ if (config.onconnected) {
+ config.onconnected();
+ }
+ };
+ ws.onerror = function (error) {
+ Logger.error("Could not connect to " + wsUri + " (invoking onerror if defined)", error);
+ if (config.onerror) {
+ config.onerror(error);
+ }
+ };
+ function logConnected(ws, wsUri) {
+ try {
+ Logger.debug("WebSocket connected to " + wsUri);
+ }
+ catch (e) {
+ Logger.error(e);
+ }
+ }
+ var reconnectionOnClose = function () {
+ if (ws.readyState === CLOSED) {
+ if (closing) {
+ Logger.debug("Connection closed by user");
+ }
+ else {
+ Logger.debug("Connection closed unexpectecly. Reconnecting...");
+ reconnectToSameUri(MAX_RETRIES, 1);
+ }
+ }
+ else {
+ Logger.debug("Close callback from previous websocket. Ignoring it");
+ }
+ };
+ ws.onclose = reconnectionOnClose;
+ function reconnectToSameUri(maxRetries, numRetries) {
+ Logger.debug("reconnectToSameUri (attempt #" + numRetries + ", max=" + maxRetries + ")");
+ if (numRetries === 1) {
+ if (reconnecting) {
+ Logger.warn("Trying to reconnectToNewUri when reconnecting... Ignoring this reconnection.");
+ return;
+ }
+ else {
+ reconnecting = true;
+ }
+ if (config.onreconnecting) {
+ config.onreconnecting();
+ }
+ }
+ if (forcingDisconnection) {
+ reconnectToNewUri(maxRetries, numRetries, wsUri);
+ }
+ else {
+ if (config.newWsUriOnReconnection) {
+ config.newWsUriOnReconnection(function (error, newWsUri) {
+ if (error) {
+ Logger.debug(error);
+ setTimeout(function () {
+ reconnectToSameUri(maxRetries, numRetries + 1);
+ }, RETRY_TIME_MS);
+ }
+ else {
+ reconnectToNewUri(maxRetries, numRetries, newWsUri);
+ }
+ });
+ }
+ else {
+ reconnectToNewUri(maxRetries, numRetries, wsUri);
+ }
+ }
+ }
+ function reconnectToNewUri(maxRetries, numRetries, reconnectWsUri) {
+ Logger.debug("Reconnection attempt #" + numRetries);
+ ws.close();
+ wsUri = reconnectWsUri || wsUri;
+ var newWs;
+ if (useSockJS) {
+ newWs = new SockJS(wsUri);
+ }
+ else {
+ newWs = new WebSocket(wsUri);
+ }
+ newWs.onopen = function () {
+ Logger.debug("Reconnected after " + numRetries + " attempts...");
+ logConnected(newWs, wsUri);
+ reconnecting = false;
+ registerMessageHandler();
+ if (config.onreconnected()) {
+ config.onreconnected();
+ }
+ newWs.onclose = reconnectionOnClose;
+ };
+ var onErrorOrClose = function (error) {
+ Logger.warn("Reconnection error: ", error);
+ if (numRetries === maxRetries) {
+ if (config.ondisconnect) {
+ config.ondisconnect();
+ }
+ }
+ else {
+ setTimeout(function () {
+ reconnectToSameUri(maxRetries, numRetries + 1);
+ }, RETRY_TIME_MS);
+ }
+ };
+ newWs.onerror = onErrorOrClose;
+ ws = newWs;
+ }
+ this.close = function () {
+ closing = true;
+ ws.close();
+ };
+ this.forceClose = function (millis) {
+ Logger.debug("Testing: Force WebSocket close");
+ if (millis) {
+ Logger.debug("Testing: Change wsUri for " + millis + " millis to simulate net failure");
+ var goodWsUri = wsUri;
+ wsUri = "wss://21.234.12.34.4:443/";
+ forcingDisconnection = true;
+ setTimeout(function () {
+ Logger.debug("Testing: Recover good wsUri " + goodWsUri);
+ wsUri = goodWsUri;
+ forcingDisconnection = false;
+ }, millis);
+ }
+ ws.close();
+ };
+ this.reconnectWs = function () {
+ Logger.debug("reconnectWs");
+ reconnectToSameUri(MAX_RETRIES, 1);
+ };
+ this.send = function (message) {
+ ws.send(message);
+ };
+ this.addEventListener = function (type, callback) {
+ registerMessageHandler = function () {
+ ws.addEventListener(type, callback);
+ };
+ registerMessageHandler();
+ };
+}
+module.exports = WebSocketWithReconnection;
+
+}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
+
+},{}],43:[function(require,module,exports){
+var defineProperty_IE8 = false;
+if (Object.defineProperty) {
+ try {
+ Object.defineProperty({}, "x", {});
+ }
+ catch (e) {
+ defineProperty_IE8 = true;
+ }
+}
+if (!Function.prototype.bind) {
+ Function.prototype.bind = function (oThis) {
+ if (typeof this !== 'function') {
+ throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable');
+ }
+ var aArgs = Array.prototype.slice.call(arguments, 1), fToBind = this, fNOP = function () { }, fBound = function () {
+ return fToBind.apply(this instanceof fNOP && oThis
+ ? this
+ : oThis, aArgs.concat(Array.prototype.slice.call(arguments)));
+ };
+ fNOP.prototype = this.prototype;
+ fBound.prototype = new fNOP();
+ return fBound;
+ };
+}
+var EventEmitter = require('events').EventEmitter;
+var inherits = require('inherits');
+var packers = require('./packers');
+var Mapper = require('./Mapper');
+var BASE_TIMEOUT = 5000;
+function unifyResponseMethods(responseMethods) {
+ if (!responseMethods)
+ return {};
+ for (var key in responseMethods) {
+ var value = responseMethods[key];
+ if (typeof value == 'string')
+ responseMethods[key] =
+ {
+ response: value
+ };
+ }
+ ;
+ return responseMethods;
+}
+;
+function unifyTransport(transport) {
+ if (!transport)
+ return;
+ if (transport instanceof Function)
+ return { send: transport };
+ if (transport.send instanceof Function)
+ return transport;
+ if (transport.postMessage instanceof Function) {
+ transport.send = transport.postMessage;
+ return transport;
+ }
+ if (transport.write instanceof Function) {
+ transport.send = transport.write;
+ return transport;
+ }
+ if (transport.onmessage !== undefined)
+ return;
+ if (transport.pause instanceof Function)
+ return;
+ throw new SyntaxError("Transport is not a function nor a valid object");
+}
+;
+function RpcNotification(method, params) {
+ if (defineProperty_IE8) {
+ this.method = method;
+ this.params = params;
+ }
+ else {
+ Object.defineProperty(this, 'method', { value: method, enumerable: true });
+ Object.defineProperty(this, 'params', { value: params, enumerable: true });
+ }
+}
+;
+function RpcBuilder(packer, options, transport, onRequest) {
+ var self = this;
+ if (!packer)
+ throw new SyntaxError('Packer is not defined');
+ if (!packer.pack || !packer.unpack)
+ throw new SyntaxError('Packer is invalid');
+ var responseMethods = unifyResponseMethods(packer.responseMethods);
+ if (options instanceof Function) {
+ if (transport != undefined)
+ throw new SyntaxError("There can't be parameters after onRequest");
+ onRequest = options;
+ transport = undefined;
+ options = undefined;
+ }
+ ;
+ if (options && options.send instanceof Function) {
+ if (transport && !(transport instanceof Function))
+ throw new SyntaxError("Only a function can be after transport");
+ onRequest = transport;
+ transport = options;
+ options = undefined;
+ }
+ ;
+ if (transport instanceof Function) {
+ if (onRequest != undefined)
+ throw new SyntaxError("There can't be parameters after onRequest");
+ onRequest = transport;
+ transport = undefined;
+ }
+ ;
+ if (transport && transport.send instanceof Function)
+ if (onRequest && !(onRequest instanceof Function))
+ throw new SyntaxError("Only a function can be after transport");
+ options = options || {};
+ EventEmitter.call(this);
+ if (onRequest)
+ this.on('request', onRequest);
+ if (defineProperty_IE8)
+ this.peerID = options.peerID;
+ else
+ Object.defineProperty(this, 'peerID', { value: options.peerID });
+ var max_retries = options.max_retries || 0;
+ function transportMessage(event) {
+ self.decode(event.data || event);
+ }
+ ;
+ this.getTransport = function () {
+ return transport;
+ };
+ this.setTransport = function (value) {
+ if (transport) {
+ if (transport.removeEventListener)
+ transport.removeEventListener('message', transportMessage);
+ else if (transport.removeListener)
+ transport.removeListener('data', transportMessage);
+ }
+ ;
+ if (value) {
+ if (value.addEventListener)
+ value.addEventListener('message', transportMessage);
+ else if (value.addListener)
+ value.addListener('data', transportMessage);
+ }
+ ;
+ transport = unifyTransport(value);
+ };
+ if (!defineProperty_IE8)
+ Object.defineProperty(this, 'transport', {
+ get: this.getTransport.bind(this),
+ set: this.setTransport.bind(this)
+ });
+ this.setTransport(transport);
+ var request_timeout = options.request_timeout || BASE_TIMEOUT;
+ var ping_request_timeout = options.ping_request_timeout || request_timeout;
+ var response_timeout = options.response_timeout || BASE_TIMEOUT;
+ var duplicates_timeout = options.duplicates_timeout || BASE_TIMEOUT;
+ var requestID = 0;
+ var requests = new Mapper();
+ var responses = new Mapper();
+ var processedResponses = new Mapper();
+ var message2Key = {};
+ function storeResponse(message, id, dest) {
+ var response = {
+ message: message,
+ timeout: setTimeout(function () {
+ responses.remove(id, dest);
+ }, response_timeout)
+ };
+ responses.set(response, id, dest);
+ }
+ ;
+ function storeProcessedResponse(ack, from) {
+ var timeout = setTimeout(function () {
+ processedResponses.remove(ack, from);
+ }, duplicates_timeout);
+ processedResponses.set(timeout, ack, from);
+ }
+ ;
+ function RpcRequest(method, params, id, from, transport) {
+ RpcNotification.call(this, method, params);
+ this.getTransport = function () {
+ return transport;
+ };
+ this.setTransport = function (value) {
+ transport = unifyTransport(value);
+ };
+ if (!defineProperty_IE8)
+ Object.defineProperty(this, 'transport', {
+ get: this.getTransport.bind(this),
+ set: this.setTransport.bind(this)
+ });
+ var response = responses.get(id, from);
+ if (!(transport || self.getTransport())) {
+ if (defineProperty_IE8)
+ this.duplicated = Boolean(response);
+ else
+ Object.defineProperty(this, 'duplicated', {
+ value: Boolean(response)
+ });
+ }
+ var responseMethod = responseMethods[method];
+ this.pack = packer.pack.bind(packer, this, id);
+ this.reply = function (error, result, transport) {
+ if (error instanceof Function || error && error.send instanceof Function) {
+ if (result != undefined)
+ throw new SyntaxError("There can't be parameters after callback");
+ transport = error;
+ result = null;
+ error = undefined;
+ }
+ else if (result instanceof Function
+ || result && result.send instanceof Function) {
+ if (transport != undefined)
+ throw new SyntaxError("There can't be parameters after callback");
+ transport = result;
+ result = null;
+ }
+ ;
+ transport = unifyTransport(transport);
+ if (response)
+ clearTimeout(response.timeout);
+ if (from != undefined) {
+ if (error)
+ error.dest = from;
+ if (result)
+ result.dest = from;
+ }
+ ;
+ var message;
+ if (error || result != undefined) {
+ if (self.peerID != undefined) {
+ if (error)
+ error.from = self.peerID;
+ else
+ result.from = self.peerID;
+ }
+ if (responseMethod) {
+ if (responseMethod.error == undefined && error)
+ message =
+ {
+ error: error
+ };
+ else {
+ var method = error
+ ? responseMethod.error
+ : responseMethod.response;
+ message =
+ {
+ method: method,
+ params: error || result
+ };
+ }
+ }
+ else
+ message =
+ {
+ error: error,
+ result: result
+ };
+ message = packer.pack(message, id);
+ }
+ else if (response)
+ message = response.message;
+ else
+ message = packer.pack({ result: null }, id);
+ storeResponse(message, id, from);
+ transport = transport || this.getTransport() || self.getTransport();
+ if (transport)
+ return transport.send(message);
+ return message;
+ };
+ }
+ ;
+ inherits(RpcRequest, RpcNotification);
+ function cancel(message) {
+ var key = message2Key[message];
+ if (!key)
+ return;
+ delete message2Key[message];
+ var request = requests.pop(key.id, key.dest);
+ if (!request)
+ return;
+ clearTimeout(request.timeout);
+ storeProcessedResponse(key.id, key.dest);
+ }
+ ;
+ this.cancel = function (message) {
+ if (message)
+ return cancel(message);
+ for (var message in message2Key)
+ cancel(message);
+ };
+ this.close = function () {
+ var transport = this.getTransport();
+ if (transport && transport.close)
+ transport.close();
+ this.cancel();
+ processedResponses.forEach(clearTimeout);
+ responses.forEach(function (response) {
+ clearTimeout(response.timeout);
+ });
+ };
+ this.encode = function (method, params, dest, transport, callback) {
+ if (params instanceof Function) {
+ if (dest != undefined)
+ throw new SyntaxError("There can't be parameters after callback");
+ callback = params;
+ transport = undefined;
+ dest = undefined;
+ params = undefined;
+ }
+ else if (dest instanceof Function) {
+ if (transport != undefined)
+ throw new SyntaxError("There can't be parameters after callback");
+ callback = dest;
+ transport = undefined;
+ dest = undefined;
+ }
+ else if (transport instanceof Function) {
+ if (callback != undefined)
+ throw new SyntaxError("There can't be parameters after callback");
+ callback = transport;
+ transport = undefined;
+ }
+ ;
+ if (self.peerID != undefined) {
+ params = params || {};
+ params.from = self.peerID;
+ }
+ ;
+ if (dest != undefined) {
+ params = params || {};
+ params.dest = dest;
+ }
+ ;
+ var message = {
+ method: method,
+ params: params
+ };
+ if (callback) {
+ var id = requestID++;
+ var retried = 0;
+ message = packer.pack(message, id);
+ function dispatchCallback(error, result) {
+ self.cancel(message);
+ callback(error, result);
+ }
+ ;
+ var request = {
+ message: message,
+ callback: dispatchCallback,
+ responseMethods: responseMethods[method] || {}
+ };
+ var encode_transport = unifyTransport(transport);
+ function sendRequest(transport) {
+ var rt = (method === 'ping' ? ping_request_timeout : request_timeout);
+ request.timeout = setTimeout(timeout, rt * Math.pow(2, retried++));
+ message2Key[message] = { id: id, dest: dest };
+ requests.set(request, id, dest);
+ transport = transport || encode_transport || self.getTransport();
+ if (transport)
+ return transport.send(message);
+ return message;
+ }
+ ;
+ function retry(transport) {
+ transport = unifyTransport(transport);
+ console.warn(retried + ' retry for request message:', message);
+ var timeout = processedResponses.pop(id, dest);
+ clearTimeout(timeout);
+ return sendRequest(transport);
+ }
+ ;
+ function timeout() {
+ if (retried < max_retries)
+ return retry(transport);
+ var error = new Error('Request has timed out');
+ error.request = message;
+ error.retry = retry;
+ dispatchCallback(error);
+ }
+ ;
+ return sendRequest(transport);
+ }
+ ;
+ message = packer.pack(message);
+ transport = transport || this.getTransport();
+ if (transport)
+ return transport.send(message);
+ return message;
+ };
+ this.decode = function (message, transport) {
+ if (!message)
+ throw new TypeError("Message is not defined");
+ try {
+ message = packer.unpack(message);
+ }
+ catch (e) {
+ return console.debug(e, message);
+ }
+ ;
+ var id = message.id;
+ var ack = message.ack;
+ var method = message.method;
+ var params = message.params || {};
+ var from = params.from;
+ var dest = params.dest;
+ if (self.peerID != undefined && from == self.peerID)
+ return;
+ if (id == undefined && ack == undefined) {
+ var notification = new RpcNotification(method, params);
+ if (self.emit('request', notification))
+ return;
+ return notification;
+ }
+ ;
+ function processRequest() {
+ transport = unifyTransport(transport) || self.getTransport();
+ if (transport) {
+ var response = responses.get(id, from);
+ if (response)
+ return transport.send(response.message);
+ }
+ ;
+ var idAck = (id != undefined) ? id : ack;
+ var request = new RpcRequest(method, params, idAck, from, transport);
+ if (self.emit('request', request))
+ return;
+ return request;
+ }
+ ;
+ function processResponse(request, error, result) {
+ request.callback(error, result);
+ }
+ ;
+ function duplicatedResponse(timeout) {
+ console.warn("Response already processed", message);
+ clearTimeout(timeout);
+ storeProcessedResponse(ack, from);
+ }
+ ;
+ if (method) {
+ if (dest == undefined || dest == self.peerID) {
+ var request = requests.get(ack, from);
+ if (request) {
+ var responseMethods = request.responseMethods;
+ if (method == responseMethods.error)
+ return processResponse(request, params);
+ if (method == responseMethods.response)
+ return processResponse(request, null, params);
+ return processRequest();
+ }
+ var processed = processedResponses.get(ack, from);
+ if (processed)
+ return duplicatedResponse(processed);
+ }
+ return processRequest();
+ }
+ ;
+ var error = message.error;
+ var result = message.result;
+ if (error && error.dest && error.dest != self.peerID)
+ return;
+ if (result && result.dest && result.dest != self.peerID)
+ return;
+ var request = requests.get(ack, from);
+ if (!request) {
+ var processed = processedResponses.get(ack, from);
+ if (processed)
+ return duplicatedResponse(processed);
+ return console.warn("No callback was defined for this message", message);
+ }
+ ;
+ processResponse(request, error, result);
+ };
+}
+;
+inherits(RpcBuilder, EventEmitter);
+RpcBuilder.RpcNotification = RpcNotification;
+module.exports = RpcBuilder;
+var clients = require('./clients');
+var transports = require('./clients/transports');
+RpcBuilder.clients = clients;
+RpcBuilder.clients.transports = transports;
+RpcBuilder.packers = packers;
+
+},{"./Mapper":38,"./clients":39,"./clients/transports":41,"./packers":46,"events":1,"inherits":6}],44:[function(require,module,exports){
+function pack(message, id) {
+ var result = {
+ jsonrpc: "2.0"
+ };
+ if (message.method) {
+ result.method = message.method;
+ if (message.params)
+ result.params = message.params;
+ if (id != undefined)
+ result.id = id;
+ }
+ else if (id != undefined) {
+ if (message.error) {
+ if (message.result !== undefined)
+ throw new TypeError("Both result and error are defined");
+ result.error = message.error;
+ }
+ else if (message.result !== undefined)
+ result.result = message.result;
+ else
+ throw new TypeError("No result or error is defined");
+ result.id = id;
+ }
+ ;
+ return JSON.stringify(result);
+}
+;
+function unpack(message) {
+ var result = message;
+ if (typeof message === 'string' || message instanceof String) {
+ result = JSON.parse(message);
+ }
+ var version = result.jsonrpc;
+ if (version !== '2.0')
+ throw new TypeError("Invalid JsonRPC version '" + version + "': " + message);
+ if (result.method == undefined) {
+ if (result.id == undefined)
+ throw new TypeError("Invalid message: " + message);
+ var result_defined = result.result !== undefined;
+ var error_defined = result.error !== undefined;
+ if (result_defined && error_defined)
+ throw new TypeError("Both result and error are defined: " + message);
+ if (!result_defined && !error_defined)
+ throw new TypeError("No result or error is defined: " + message);
+ result.ack = result.id;
+ delete result.id;
+ }
+ return result;
+}
+;
+exports.pack = pack;
+exports.unpack = unpack;
+
+},{}],45:[function(require,module,exports){
+function pack(message) {
+ throw new TypeError("Not yet implemented");
+}
+;
+function unpack(message) {
+ throw new TypeError("Not yet implemented");
+}
+;
+exports.pack = pack;
+exports.unpack = unpack;
+
+},{}],46:[function(require,module,exports){
+var JsonRPC = require('./JsonRPC');
+var XmlRPC = require('./XmlRPC');
+exports.JsonRPC = JsonRPC;
+exports.XmlRPC = XmlRPC;
+
+},{"./JsonRPC":44,"./XmlRPC":45}],47:[function(require,module,exports){
+window.getScreenId = function (callback, custom_parameter) {
+ if (navigator.userAgent.indexOf('Edge') !== -1 && (!!navigator.msSaveOrOpenBlob || !!navigator.msSaveBlob)) {
+ callback({
+ video: true
+ });
+ return;
+ }
+ if (!!navigator.mozGetUserMedia) {
+ callback(null, 'firefox', {
+ video: {
+ mozMediaSource: 'window',
+ mediaSource: 'window'
+ }
+ });
+ return;
+ }
+ window.addEventListener('message', onIFrameCallback);
+ function onIFrameCallback(event) {
+ if (!event.data)
+ return;
+ if (event.data.chromeMediaSourceId) {
+ if (event.data.chromeMediaSourceId === 'PermissionDeniedError') {
+ callback('permission-denied');
+ }
+ else {
+ callback(null, event.data.chromeMediaSourceId, getScreenConstraints(null, event.data.chromeMediaSourceId, event.data.canRequestAudioTrack));
+ }
+ window.removeEventListener('message', onIFrameCallback);
+ }
+ if (event.data.chromeExtensionStatus) {
+ callback(event.data.chromeExtensionStatus, null, getScreenConstraints(event.data.chromeExtensionStatus));
+ window.removeEventListener('message', onIFrameCallback);
+ }
+ }
+ if (!custom_parameter) {
+ setTimeout(postGetSourceIdMessage, 100);
+ }
+ else {
+ setTimeout(function () {
+ postGetSourceIdMessage(custom_parameter);
+ }, 100);
+ }
+};
+function getScreenConstraints(error, sourceId, canRequestAudioTrack) {
+ var screen_constraints = {
+ audio: false,
+ video: {
+ mandatory: {
+ chromeMediaSource: error ? 'screen' : 'desktop',
+ maxWidth: window.screen.width > 1920 ? window.screen.width : 1920,
+ maxHeight: window.screen.height > 1080 ? window.screen.height : 1080
+ },
+ optional: []
+ }
+ };
+ if (!!canRequestAudioTrack) {
+ screen_constraints.audio = {
+ mandatory: {
+ chromeMediaSource: error ? 'screen' : 'desktop',
+ },
+ optional: []
+ };
+ }
+ if (sourceId) {
+ screen_constraints.video.mandatory.chromeMediaSourceId = sourceId;
+ if (screen_constraints.audio && screen_constraints.audio.mandatory) {
+ screen_constraints.audio.mandatory.chromeMediaSourceId = sourceId;
+ }
+ }
+ return screen_constraints;
+}
+function postGetSourceIdMessage(custom_parameter) {
+ if (!iframe) {
+ loadIFrame(function () {
+ postGetSourceIdMessage(custom_parameter);
+ });
+ return;
+ }
+ if (!iframe.isLoaded) {
+ setTimeout(function () {
+ postGetSourceIdMessage(custom_parameter);
+ }, 100);
+ return;
+ }
+ if (!custom_parameter) {
+ iframe.contentWindow.postMessage({
+ captureSourceId: true
+ }, '*');
+ }
+ else if (!!custom_parameter.forEach) {
+ iframe.contentWindow.postMessage({
+ captureCustomSourceId: custom_parameter
+ }, '*');
+ }
+ else {
+ iframe.contentWindow.postMessage({
+ captureSourceIdWithAudio: true
+ }, '*');
+ }
+}
+var iframe;
+window.getScreenConstraints = function (callback) {
+ loadIFrame(function () {
+ getScreenId(function (error, sourceId, screen_constraints) {
+ if (!screen_constraints) {
+ screen_constraints = {
+ video: true
+ };
+ }
+ callback(error, screen_constraints.video);
+ });
+ });
+};
+function loadIFrame(loadCallback) {
+ if (iframe) {
+ loadCallback();
+ return;
+ }
+ iframe = document.createElement('iframe');
+ iframe.onload = function () {
+ iframe.isLoaded = true;
+ loadCallback();
+ };
+ iframe.src = 'https://openvidu.github.io/openvidu-screen-sharing-chrome-extension/';
+ iframe.style.display = 'none';
+ (document.body || document.documentElement).appendChild(iframe);
+}
+window.getChromeExtensionStatus = function (callback) {
+ if (!!navigator.mozGetUserMedia) {
+ callback('installed-enabled');
+ return;
+ }
+ window.addEventListener('message', onIFrameCallback);
+ function onIFrameCallback(event) {
+ if (!event.data)
+ return;
+ if (event.data.chromeExtensionStatus) {
+ callback(event.data.chromeExtensionStatus);
+ window.removeEventListener('message', onIFrameCallback);
+ }
+ }
+ setTimeout(postGetChromeExtensionStatusMessage, 100);
+};
+function postGetChromeExtensionStatusMessage() {
+ if (!iframe) {
+ loadIFrame(postGetChromeExtensionStatusMessage);
+ return;
+ }
+ if (!iframe.isLoaded) {
+ setTimeout(postGetChromeExtensionStatusMessage, 100);
+ return;
+ }
+ iframe.contentWindow.postMessage({
+ getChromeExtensionStatus: true
+ }, '*');
+}
+exports.getScreenId = getScreenId;
+
+},{}],48:[function(require,module,exports){
+var chromeMediaSource = 'screen';
+var sourceId;
+var screenCallback;
+var isFirefox = typeof window.InstallTrigger !== 'undefined';
+var isOpera = !!window.opera || navigator.userAgent.indexOf(' OPR/') >= 0;
+var isChrome = !!window.chrome && !isOpera;
+window.addEventListener('message', function (event) {
+ if (event.origin != window.location.origin) {
+ return;
+ }
+ onMessageCallback(event.data);
+});
+function onMessageCallback(data) {
+ if (data == 'PermissionDeniedError') {
+ if (screenCallback)
+ return screenCallback('PermissionDeniedError');
+ else
+ throw new Error('PermissionDeniedError');
+ }
+ if (data == 'rtcmulticonnection-extension-loaded') {
+ chromeMediaSource = 'desktop';
+ }
+ if (data.sourceId && screenCallback) {
+ screenCallback(sourceId = data.sourceId, data.canRequestAudioTrack === true);
+ }
+}
+function isChromeExtensionAvailable(callback) {
+ if (!callback)
+ return;
+ if (chromeMediaSource == 'desktop')
+ return callback(true);
+ window.postMessage('are-you-there', '*');
+ setTimeout(function () {
+ if (chromeMediaSource == 'screen') {
+ callback(false);
+ }
+ else
+ callback(true);
+ }, 2000);
+}
+function getSourceId(callback) {
+ if (!callback)
+ throw '"callback" parameter is mandatory.';
+ if (sourceId)
+ return callback(sourceId);
+ screenCallback = callback;
+ window.postMessage('get-sourceId', '*');
+}
+function getCustomSourceId(arr, callback) {
+ if (!arr || !arr.forEach)
+ throw '"arr" parameter is mandatory and it must be an array.';
+ if (!callback)
+ throw '"callback" parameter is mandatory.';
+ if (sourceId)
+ return callback(sourceId);
+ screenCallback = callback;
+ window.postMessage({
+ 'get-custom-sourceId': arr
+ }, '*');
+}
+function getSourceIdWithAudio(callback) {
+ if (!callback)
+ throw '"callback" parameter is mandatory.';
+ if (sourceId)
+ return callback(sourceId);
+ screenCallback = callback;
+ window.postMessage('audio-plus-tab', '*');
+}
+function getChromeExtensionStatus(extensionid, callback) {
+ if (isFirefox)
+ return callback('not-chrome');
+ if (arguments.length != 2) {
+ callback = extensionid;
+ extensionid = 'lfcgfepafnobdloecchnfaclibenjold';
+ }
+ var image = document.createElement('img');
+ image.src = 'chrome-extension://' + extensionid + '/icon.png';
+ image.onload = function () {
+ chromeMediaSource = 'screen';
+ window.postMessage('are-you-there', '*');
+ setTimeout(function () {
+ if (chromeMediaSource == 'screen') {
+ callback('installed-disabled');
+ }
+ else
+ callback('installed-enabled');
+ }, 2000);
+ };
+ image.onerror = function () {
+ callback('not-installed');
+ };
+}
+function getScreenConstraintsWithAudio(callback) {
+ getScreenConstraints(callback, true);
+}
+function getScreenConstraints(callback, captureSourceIdWithAudio) {
+ sourceId = '';
+ var firefoxScreenConstraints = {
+ mozMediaSource: 'window',
+ mediaSource: 'window'
+ };
+ if (isFirefox)
+ return callback(null, firefoxScreenConstraints);
+ var screen_constraints = {
+ mandatory: {
+ chromeMediaSource: chromeMediaSource,
+ maxWidth: screen.width > 1920 ? screen.width : 1920,
+ maxHeight: screen.height > 1080 ? screen.height : 1080
+ },
+ optional: []
+ };
+ if (chromeMediaSource == 'desktop' && !sourceId) {
+ if (captureSourceIdWithAudio) {
+ getSourceIdWithAudio(function (sourceId, canRequestAudioTrack) {
+ screen_constraints.mandatory.chromeMediaSourceId = sourceId;
+ if (canRequestAudioTrack) {
+ screen_constraints.canRequestAudioTrack = true;
+ }
+ callback(sourceId == 'PermissionDeniedError' ? sourceId : null, screen_constraints);
+ });
+ }
+ else {
+ getSourceId(function (sourceId) {
+ screen_constraints.mandatory.chromeMediaSourceId = sourceId;
+ callback(sourceId == 'PermissionDeniedError' ? sourceId : null, screen_constraints);
+ });
+ }
+ return;
+ }
+ if (chromeMediaSource == 'desktop') {
+ screen_constraints.mandatory.chromeMediaSourceId = sourceId;
+ }
+ callback(null, screen_constraints);
+}
+exports.getScreenConstraints = getScreenConstraints;
+exports.getScreenConstraintsWithAudio = getScreenConstraintsWithAudio;
+exports.isChromeExtensionAvailable = isChromeExtensionAvailable;
+exports.getChromeExtensionStatus = getChromeExtensionStatus;
+exports.getSourceId = getSourceId;
+
+},{}],49:[function(require,module,exports){
+"use strict";
+var __extends = (this && this.__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 __());
+ };
+})();
+Object.defineProperty(exports, "__esModule", { value: true });
+var freeice = require("freeice");
+var uuid = require("uuid");
+var platform = require("platform");
+var WebRtcPeer = (function () {
+ function WebRtcPeer(configuration) {
+ var _this = this;
+ this.configuration = configuration;
+ this.remoteCandidatesQueue = [];
+ this.localCandidatesQueue = [];
+ this.iceCandidateList = [];
+ this.candidategatheringdone = false;
+ this.configuration.iceServers = (!!this.configuration.iceServers && this.configuration.iceServers.length > 0) ? this.configuration.iceServers : freeice();
+ this.pc = new RTCPeerConnection({ iceServers: this.configuration.iceServers });
+ this.id = !!configuration.id ? configuration.id : uuid.v4();
+ this.pc.onicecandidate = function (event) {
+ var candidate = event.candidate;
+ if (candidate) {
+ _this.localCandidatesQueue.push({ candidate: candidate.candidate });
+ _this.candidategatheringdone = false;
+ _this.configuration.onicecandidate(event.candidate);
+ }
+ else if (!_this.candidategatheringdone) {
+ _this.candidategatheringdone = true;
+ }
+ };
+ this.pc.onsignalingstatechange = function () {
+ if (_this.pc.signalingState === 'stable') {
+ while (_this.iceCandidateList.length > 0) {
+ _this.pc.addIceCandidate(_this.iceCandidateList.shift());
+ }
+ }
+ };
+ this.start();
+ }
+ WebRtcPeer.prototype.start = function () {
+ var _this = this;
+ return new Promise(function (resolve, reject) {
+ if (_this.pc.signalingState === 'closed') {
+ reject('The peer connection object is in "closed" state. This is most likely due to an invocation of the dispose method before accepting in the dialogue');
+ }
+ if (!!_this.configuration.mediaStream) {
+ _this.pc.addStream(_this.configuration.mediaStream);
+ }
+ if (_this.configuration.mode === 'sendonly' &&
+ (platform.name === 'Chrome' && platform.version.toString().substring(0, 2) === '39')) {
+ _this.configuration.mode = 'sendrecv';
+ }
+ resolve();
+ });
+ };
+ WebRtcPeer.prototype.dispose = function () {
+ var _this = this;
+ console.debug('Disposing WebRtcPeer');
+ try {
+ if (this.pc) {
+ if (this.pc.signalingState === 'closed') {
+ return;
+ }
+ this.remoteCandidatesQueue = [];
+ this.localCandidatesQueue = [];
+ this.pc.getLocalStreams().forEach(function (str) {
+ _this.streamStop(str);
+ });
+ this.pc.close();
+ }
+ }
+ catch (err) {
+ console.warn('Exception disposing webrtc peer ' + err);
+ }
+ };
+ WebRtcPeer.prototype.generateOffer = function () {
+ var _this = this;
+ return new Promise(function (resolve, reject) {
+ var offerAudio, offerVideo = true;
+ if (!!_this.configuration.mediaConstraints) {
+ offerAudio = (typeof _this.configuration.mediaConstraints.audio === 'boolean') ?
+ _this.configuration.mediaConstraints.audio : true;
+ offerVideo = (typeof _this.configuration.mediaConstraints.video === 'boolean') ?
+ _this.configuration.mediaConstraints.video : true;
+ }
+ var constraints = {
+ offerToReceiveAudio: +(_this.configuration.mode !== 'sendonly' && offerAudio),
+ offerToReceiveVideo: +(_this.configuration.mode !== 'sendonly' && offerVideo)
+ };
+ console.debug('RTCPeerConnection constraints: ' + JSON.stringify(constraints));
+ _this.pc.createOffer(constraints).then(function (offer) {
+ console.debug('Created SDP offer');
+ return _this.pc.setLocalDescription(offer);
+ }).then(function () {
+ var localDescription = _this.pc.localDescription;
+ if (!!localDescription) {
+ console.debug('Local description set', localDescription.sdp);
+ resolve(localDescription.sdp);
+ }
+ else {
+ reject('Local description is not defined');
+ }
+ }).catch(function (error) { return reject(error); });
+ });
+ };
+ WebRtcPeer.prototype.processOffer = function (sdpOffer) {
+ var _this = this;
+ return new Promise(function (resolve, reject) {
+ var offer = {
+ type: 'offer',
+ sdp: sdpOffer
+ };
+ console.debug('SDP offer received, setting remote description');
+ if (_this.pc.signalingState === 'closed') {
+ reject('PeerConnection is closed');
+ }
+ _this.pc.setRemoteDescription(offer)
+ .then(function () {
+ return _this.pc.createAnswer();
+ }).then(function (answer) {
+ console.debug('Created SDP answer');
+ return _this.pc.setLocalDescription(answer);
+ }).then(function () {
+ var localDescription = _this.pc.localDescription;
+ if (!!localDescription) {
+ console.debug('Local description set', localDescription.sdp);
+ resolve(localDescription.sdp);
+ }
+ else {
+ reject('Local description is not defined');
+ }
+ }).catch(function (error) { return reject(error); });
+ });
+ };
+ WebRtcPeer.prototype.processAnswer = function (sdpAnswer) {
+ var _this = this;
+ return new Promise(function (resolve, reject) {
+ var answer = {
+ type: 'answer',
+ sdp: sdpAnswer
+ };
+ console.debug('SDP answer received, setting remote description');
+ if (_this.pc.signalingState === 'closed') {
+ reject('RTCPeerConnection is closed');
+ }
+ _this.pc.setRemoteDescription(answer).then(function () { return resolve(); }).catch(function (error) { return reject(error); });
+ });
+ };
+ WebRtcPeer.prototype.addIceCandidate = function (iceCandidate) {
+ var _this = this;
+ return new Promise(function (resolve, reject) {
+ console.debug('Remote ICE candidate received', iceCandidate);
+ _this.remoteCandidatesQueue.push(iceCandidate);
+ switch (_this.pc.signalingState) {
+ case 'closed':
+ reject(new Error('PeerConnection object is closed'));
+ break;
+ case 'stable':
+ if (!!_this.pc.remoteDescription) {
+ _this.pc.addIceCandidate(iceCandidate).then(function () { return resolve(); }).catch(function (error) { return reject(error); });
+ }
+ break;
+ default:
+ _this.iceCandidateList.push(iceCandidate);
+ resolve();
+ }
+ });
+ };
+ WebRtcPeer.prototype.streamStop = function (stream) {
+ stream.getTracks().forEach(function (track) {
+ track.stop();
+ stream.removeTrack(track);
+ });
+ };
+ return WebRtcPeer;
+}());
+exports.WebRtcPeer = WebRtcPeer;
+var WebRtcPeerRecvonly = (function (_super) {
+ __extends(WebRtcPeerRecvonly, _super);
+ function WebRtcPeerRecvonly(configuration) {
+ var _this = this;
+ configuration.mode = 'recvonly';
+ _this = _super.call(this, configuration) || this;
+ return _this;
+ }
+ return WebRtcPeerRecvonly;
+}(WebRtcPeer));
+exports.WebRtcPeerRecvonly = WebRtcPeerRecvonly;
+var WebRtcPeerSendonly = (function (_super) {
+ __extends(WebRtcPeerSendonly, _super);
+ function WebRtcPeerSendonly(configuration) {
+ var _this = this;
+ configuration.mode = 'sendonly';
+ _this = _super.call(this, configuration) || this;
+ return _this;
+ }
+ return WebRtcPeerSendonly;
+}(WebRtcPeer));
+exports.WebRtcPeerSendonly = WebRtcPeerSendonly;
+var WebRtcPeerSendrecv = (function (_super) {
+ __extends(WebRtcPeerSendrecv, _super);
+ function WebRtcPeerSendrecv(configuration) {
+ var _this = this;
+ configuration.mode = 'sendrecv';
+ _this = _super.call(this, configuration) || this;
+ return _this;
+ }
+ return WebRtcPeerSendrecv;
+}(WebRtcPeer));
+exports.WebRtcPeerSendrecv = WebRtcPeerSendrecv;
+
+},{"freeice":2,"platform":8,"uuid":9}],50:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+var platform = require("platform");
+var WebRtcStats = (function () {
+ function WebRtcStats(stream) {
+ this.stream = stream;
+ this.webRtcStatsEnabled = false;
+ this.statsInterval = 1;
+ this.stats = {
+ inbound: {
+ audio: {
+ bytesReceived: 0,
+ packetsReceived: 0,
+ packetsLost: 0
+ },
+ video: {
+ bytesReceived: 0,
+ packetsReceived: 0,
+ packetsLost: 0,
+ framesDecoded: 0,
+ nackCount: 0
+ }
+ },
+ outbound: {
+ audio: {
+ bytesSent: 0,
+ packetsSent: 0,
+ },
+ video: {
+ bytesSent: 0,
+ packetsSent: 0,
+ framesEncoded: 0,
+ nackCount: 0
+ }
+ }
+ };
+ }
+ WebRtcStats.prototype.isEnabled = function () {
+ return this.webRtcStatsEnabled;
+ };
+ WebRtcStats.prototype.initWebRtcStats = function () {
+ var _this = this;
+ var elastestInstrumentation = localStorage.getItem('elastest-instrumentation');
+ if (elastestInstrumentation) {
+ console.warn('WebRtc stats enabled for stream ' + this.stream.streamId + ' of connection ' + this.stream.connection.connectionId);
+ this.webRtcStatsEnabled = true;
+ var instrumentation_1 = JSON.parse(elastestInstrumentation);
+ this.statsInterval = instrumentation_1.webrtc.interval;
+ console.warn('localStorage item: ' + JSON.stringify(instrumentation_1));
+ this.webRtcStatsIntervalId = setInterval(function () {
+ _this.sendStatsToHttpEndpoint(instrumentation_1);
+ }, this.statsInterval * 1000);
+ return;
+ }
+ console.debug('WebRtc stats not enabled');
+ };
+ WebRtcStats.prototype.stopWebRtcStats = function () {
+ if (this.webRtcStatsEnabled) {
+ clearInterval(this.webRtcStatsIntervalId);
+ console.warn('WebRtc stats stopped for disposed stream ' + this.stream.streamId + ' of connection ' + this.stream.connection.connectionId);
+ }
+ };
+ WebRtcStats.prototype.getSelectedIceCandidateInfo = function () {
+ var _this = this;
+ return new Promise(function (resolve, reject) {
+ _this.getStatsAgnostic(_this.stream.getRTCPeerConnection(), function (stats) {
+ if ((platform.name.indexOf('Chrome') !== -1) || (platform.name.indexOf('Opera') !== -1)) {
+ var localCandidateId = void 0, remoteCandidateId = void 0, googCandidatePair = void 0;
+ var localCandidates = {};
+ var remoteCandidates = {};
+ for (var key in stats) {
+ var stat = stats[key];
+ if (stat.type === 'localcandidate') {
+ localCandidates[stat.id] = stat;
+ }
+ else if (stat.type === 'remotecandidate') {
+ remoteCandidates[stat.id] = stat;
+ }
+ else if (stat.type === 'googCandidatePair' && (stat.googActiveConnection === 'true')) {
+ googCandidatePair = stat;
+ localCandidateId = stat.localCandidateId;
+ remoteCandidateId = stat.remoteCandidateId;
+ }
+ }
+ var finalLocalCandidate_1 = localCandidates[localCandidateId];
+ if (!!finalLocalCandidate_1) {
+ var candList = _this.stream.getLocalIceCandidateList();
+ var cand = candList.filter(function (c) {
+ return (!!c.candidate &&
+ c.candidate.indexOf(finalLocalCandidate_1.ipAddress) >= 0 &&
+ c.candidate.indexOf(finalLocalCandidate_1.portNumber) >= 0 &&
+ c.candidate.indexOf(finalLocalCandidate_1.priority) >= 0);
+ });
+ finalLocalCandidate_1.raw = !!cand[0] ? cand[0].candidate : 'ERROR: Cannot find local candidate in list of sent ICE candidates';
+ }
+ else {
+ finalLocalCandidate_1 = 'ERROR: No active local ICE candidate. Probably ICE-TCP is being used';
+ }
+ var finalRemoteCandidate_1 = remoteCandidates[remoteCandidateId];
+ if (!!finalRemoteCandidate_1) {
+ var candList = _this.stream.getRemoteIceCandidateList();
+ var cand = candList.filter(function (c) {
+ return (!!c.candidate &&
+ c.candidate.indexOf(finalRemoteCandidate_1.ipAddress) >= 0 &&
+ c.candidate.indexOf(finalRemoteCandidate_1.portNumber) >= 0 &&
+ c.candidate.indexOf(finalRemoteCandidate_1.priority) >= 0);
+ });
+ finalRemoteCandidate_1.raw = !!cand[0] ? cand[0].candidate : 'ERROR: Cannot find remote candidate in list of received ICE candidates';
+ }
+ else {
+ finalRemoteCandidate_1 = 'ERROR: No active remote ICE candidate. Probably ICE-TCP is being used';
+ }
+ resolve({
+ googCandidatePair: googCandidatePair,
+ localCandidate: finalLocalCandidate_1,
+ remoteCandidate: finalRemoteCandidate_1
+ });
+ }
+ else {
+ reject('Selected ICE candidate info only available for Chrome');
+ }
+ }, function (error) {
+ reject(error);
+ });
+ });
+ };
+ WebRtcStats.prototype.sendStatsToHttpEndpoint = function (instrumentation) {
+ var _this = this;
+ var sendPost = function (json) {
+ var http = new XMLHttpRequest();
+ var url = instrumentation.webrtc.httpEndpoint;
+ http.open('POST', url, true);
+ http.setRequestHeader('Content-type', 'application/json');
+ http.onreadystatechange = function () {
+ if (http.readyState === 4 && http.status === 200) {
+ console.log('WebRtc stats successfully sent to ' + url + ' for stream ' + _this.stream.streamId + ' of connection ' + _this.stream.connection.connectionId);
+ }
+ };
+ http.send(json);
+ };
+ var f = function (stats) {
+ if (platform.name.indexOf('Firefox') !== -1) {
+ stats.forEach(function (stat) {
+ var json = {};
+ if ((stat.type === 'inbound-rtp') &&
+ (stat.nackCount !== null &&
+ stat.isRemote === false &&
+ stat.id.startsWith('inbound') &&
+ stat.remoteId.startsWith('inbound'))) {
+ var metricId = 'webrtc_inbound_' + stat.mediaType + '_' + stat.ssrc;
+ var jit = stat.jitter * 1000;
+ var metrics = {
+ bytesReceived: (stat.bytesReceived - _this.stats.inbound[stat.mediaType].bytesReceived) / _this.statsInterval,
+ jitter: jit,
+ packetsReceived: (stat.packetsReceived - _this.stats.inbound[stat.mediaType].packetsReceived) / _this.statsInterval,
+ packetsLost: (stat.packetsLost - _this.stats.inbound[stat.mediaType].packetsLost) / _this.statsInterval
+ };
+ var units = {
+ bytesReceived: 'bytes',
+ jitter: 'ms',
+ packetsReceived: 'packets',
+ packetsLost: 'packets'
+ };
+ if (stat.mediaType === 'video') {
+ metrics['framesDecoded'] = (stat.framesDecoded - _this.stats.inbound.video.framesDecoded) / _this.statsInterval;
+ metrics['nackCount'] = (stat.nackCount - _this.stats.inbound.video.nackCount) / _this.statsInterval;
+ units['framesDecoded'] = 'frames';
+ units['nackCount'] = 'packets';
+ _this.stats.inbound.video.framesDecoded = stat.framesDecoded;
+ _this.stats.inbound.video.nackCount = stat.nackCount;
+ }
+ _this.stats.inbound[stat.mediaType].bytesReceived = stat.bytesReceived;
+ _this.stats.inbound[stat.mediaType].packetsReceived = stat.packetsReceived;
+ _this.stats.inbound[stat.mediaType].packetsLost = stat.packetsLost;
+ json = {
+ '@timestamp': new Date(stat.timestamp).toISOString(),
+ 'exec': instrumentation.exec,
+ 'component': instrumentation.component,
+ 'stream': 'webRtc',
+ 'type': metricId,
+ 'stream_type': 'composed_metrics',
+ 'units': units
+ };
+ json[metricId] = metrics;
+ sendPost(JSON.stringify(json));
+ }
+ else if ((stat.type === 'outbound-rtp') &&
+ (stat.isRemote === false &&
+ stat.id.toLowerCase().includes('outbound'))) {
+ var metricId = 'webrtc_outbound_' + stat.mediaType + '_' + stat.ssrc;
+ var metrics = {
+ bytesSent: (stat.bytesSent - _this.stats.outbound[stat.mediaType].bytesSent) / _this.statsInterval,
+ packetsSent: (stat.packetsSent - _this.stats.outbound[stat.mediaType].packetsSent) / _this.statsInterval
+ };
+ var units = {
+ bytesSent: 'bytes',
+ packetsSent: 'packets'
+ };
+ if (stat.mediaType === 'video') {
+ metrics['framesEncoded'] = (stat.framesEncoded - _this.stats.outbound.video.framesEncoded) / _this.statsInterval;
+ units['framesEncoded'] = 'frames';
+ _this.stats.outbound.video.framesEncoded = stat.framesEncoded;
+ }
+ _this.stats.outbound[stat.mediaType].bytesSent = stat.bytesSent;
+ _this.stats.outbound[stat.mediaType].packetsSent = stat.packetsSent;
+ json = {
+ '@timestamp': new Date(stat.timestamp).toISOString(),
+ 'exec': instrumentation.exec,
+ 'component': instrumentation.component,
+ 'stream': 'webRtc',
+ 'type': metricId,
+ 'stream_type': 'composed_metrics',
+ 'units': units
+ };
+ json[metricId] = metrics;
+ sendPost(JSON.stringify(json));
+ }
+ });
+ }
+ else if ((platform.name.indexOf('Chrome') !== -1) || (platform.name.indexOf('Opera') !== -1)) {
+ for (var _i = 0, _a = Object.keys(stats); _i < _a.length; _i++) {
+ var key = _a[_i];
+ var stat = stats[key];
+ if (stat.type === 'ssrc') {
+ var json = {};
+ if ('bytesReceived' in stat && ((stat.mediaType === 'audio' && 'audioOutputLevel' in stat) ||
+ (stat.mediaType === 'video' && 'qpSum' in stat))) {
+ var metricId = 'webrtc_inbound_' + stat.mediaType + '_' + stat.ssrc;
+ var metrics = {
+ bytesReceived: (stat.bytesReceived - _this.stats.inbound[stat.mediaType].bytesReceived) / _this.statsInterval,
+ jitter: stat.googJitterBufferMs,
+ packetsReceived: (stat.packetsReceived - _this.stats.inbound[stat.mediaType].packetsReceived) / _this.statsInterval,
+ packetsLost: (stat.packetsLost - _this.stats.inbound[stat.mediaType].packetsLost) / _this.statsInterval
+ };
+ var units = {
+ bytesReceived: 'bytes',
+ jitter: 'ms',
+ packetsReceived: 'packets',
+ packetsLost: 'packets'
+ };
+ if (stat.mediaType === 'video') {
+ metrics['framesDecoded'] = (stat.framesDecoded - _this.stats.inbound.video.framesDecoded) / _this.statsInterval;
+ metrics['nackCount'] = (stat.googNacksSent - _this.stats.inbound.video.nackCount) / _this.statsInterval;
+ units['framesDecoded'] = 'frames';
+ units['nackCount'] = 'packets';
+ _this.stats.inbound.video.framesDecoded = stat.framesDecoded;
+ _this.stats.inbound.video.nackCount = stat.googNacksSent;
+ }
+ _this.stats.inbound[stat.mediaType].bytesReceived = stat.bytesReceived;
+ _this.stats.inbound[stat.mediaType].packetsReceived = stat.packetsReceived;
+ _this.stats.inbound[stat.mediaType].packetsLost = stat.packetsLost;
+ json = {
+ '@timestamp': new Date(stat.timestamp).toISOString(),
+ 'exec': instrumentation.exec,
+ 'component': instrumentation.component,
+ 'stream': 'webRtc',
+ 'type': metricId,
+ 'stream_type': 'composed_metrics',
+ 'units': units
+ };
+ json[metricId] = metrics;
+ sendPost(JSON.stringify(json));
+ }
+ else if ('bytesSent' in stat) {
+ var metricId = 'webrtc_outbound_' + stat.mediaType + '_' + stat.ssrc;
+ var metrics = {
+ bytesSent: (stat.bytesSent - _this.stats.outbound[stat.mediaType].bytesSent) / _this.statsInterval,
+ packetsSent: (stat.packetsSent - _this.stats.outbound[stat.mediaType].packetsSent) / _this.statsInterval
+ };
+ var units = {
+ bytesSent: 'bytes',
+ packetsSent: 'packets'
+ };
+ if (stat.mediaType === 'video') {
+ metrics['framesEncoded'] = (stat.framesEncoded - _this.stats.outbound.video.framesEncoded) / _this.statsInterval;
+ units['framesEncoded'] = 'frames';
+ _this.stats.outbound.video.framesEncoded = stat.framesEncoded;
+ }
+ _this.stats.outbound[stat.mediaType].bytesSent = stat.bytesSent;
+ _this.stats.outbound[stat.mediaType].packetsSent = stat.packetsSent;
+ json = {
+ '@timestamp': new Date(stat.timestamp).toISOString(),
+ 'exec': instrumentation.exec,
+ 'component': instrumentation.component,
+ 'stream': 'webRtc',
+ 'type': metricId,
+ 'stream_type': 'composed_metrics',
+ 'units': units
+ };
+ json[metricId] = metrics;
+ sendPost(JSON.stringify(json));
+ }
+ }
+ }
+ }
+ };
+ this.getStatsAgnostic(this.stream.getRTCPeerConnection(), f, function (error) { console.log(error); });
+ };
+ WebRtcStats.prototype.standardizeReport = function (response) {
+ console.log(response);
+ var standardReport = {};
+ if (platform.name.indexOf('Firefox') !== -1) {
+ Object.keys(response).forEach(function (key) {
+ console.log(response[key]);
+ });
+ return response;
+ }
+ response.result().forEach(function (report) {
+ var standardStats = {
+ id: report.id,
+ timestamp: report.timestamp,
+ type: report.type
+ };
+ report.names().forEach(function (name) {
+ standardStats[name] = report.stat(name);
+ });
+ standardReport[standardStats.id] = standardStats;
+ });
+ return standardReport;
+ };
+ WebRtcStats.prototype.getStatsAgnostic = function (pc, successCb, failureCb) {
+ var _this = this;
+ if (platform.name.indexOf('Firefox') !== -1) {
+ return pc.getStats(null).then(function (response) {
+ var report = _this.standardizeReport(response);
+ successCb(report);
+ }).catch(failureCb);
+ }
+ else if ((platform.name.indexOf('Chrome') !== -1) || (platform.name.indexOf('Opera') !== -1)) {
+ return pc.getStats(function (response) {
+ var report = _this.standardizeReport(response);
+ successCb(report);
+ }, null, failureCb);
+ }
+ };
+ return WebRtcStats;
+}());
+exports.WebRtcStats = WebRtcStats;
+
+},{"platform":8}]},{},[16])
+//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL25vZGVfbW9kdWxlcy9icm93c2VyLXBhY2svX3ByZWx1ZGUuanMiLCIuLi9ub2RlX21vZHVsZXMvZXZlbnRzL2V2ZW50cy5qcyIsIi4uL25vZGVfbW9kdWxlcy9mcmVlaWNlL2luZGV4LmpzIiwiLi4vbm9kZV9tb2R1bGVzL2ZyZWVpY2Uvc3R1bi5qc29uIiwiLi4vbm9kZV9tb2R1bGVzL2ZyZWVpY2UvdHVybi5qc29uIiwiLi4vbm9kZV9tb2R1bGVzL2hhcmsvaGFyay5qcyIsIi4uL25vZGVfbW9kdWxlcy9pbmhlcml0cy9pbmhlcml0c19icm93c2VyLmpzIiwiLi4vbm9kZV9tb2R1bGVzL25vcm1hbGljZS9pbmRleC5qcyIsIi4uL25vZGVfbW9kdWxlcy9wbGF0Zm9ybS9wbGF0Zm9ybS5qcyIsIi4uL25vZGVfbW9kdWxlcy91dWlkL2luZGV4LmpzIiwiLi4vbm9kZV9tb2R1bGVzL3V1aWQvbGliL2J5dGVzVG9VdWlkLmpzIiwiLi4vbm9kZV9tb2R1bGVzL3V1aWQvbGliL3JuZy1icm93c2VyLmpzIiwiLi4vbm9kZV9tb2R1bGVzL3V1aWQvdjEuanMiLCIuLi9ub2RlX21vZHVsZXMvdXVpZC92NC5qcyIsIi4uL25vZGVfbW9kdWxlcy93aWxkZW1pdHRlci93aWxkZW1pdHRlci5qcyIsIi4uL25vZGVfbW9kdWxlcy93b2xmeTg3LWV2ZW50ZW1pdHRlci9FdmVudEVtaXR0ZXIuanMiLCJNYWluLnRzIiwiT3BlblZpZHUvQ29ubmVjdGlvbi50cyIsIk9wZW5WaWR1L0xvY2FsUmVjb3JkZXIudHMiLCJPcGVuVmlkdS9PcGVuVmlkdS50cyIsIk9wZW5WaWR1L1B1Ymxpc2hlci50cyIsIk9wZW5WaWR1L1Nlc3Npb24udHMiLCJPcGVuVmlkdS9TdHJlYW0udHMiLCJPcGVuVmlkdS9TdHJlYW1NYW5hZ2VyLnRzIiwiT3BlblZpZHUvU3Vic2NyaWJlci50cyIsIk9wZW5WaWR1SW50ZXJuYWwvRW51bXMvTG9jYWxSZWNvcmRlclN0YXRlLnRzIiwiT3BlblZpZHVJbnRlcm5hbC9FbnVtcy9PcGVuVmlkdUVycm9yLnRzIiwiT3BlblZpZHVJbnRlcm5hbC9FbnVtcy9WaWRlb0luc2VydE1vZGUudHMiLCJPcGVuVmlkdUludGVybmFsL0V2ZW50cy9Db25uZWN0aW9uRXZlbnQudHMiLCJPcGVuVmlkdUludGVybmFsL0V2ZW50cy9FdmVudC50cyIsIk9wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1B1Ymxpc2hlclNwZWFraW5nRXZlbnQudHMiLCJPcGVuVmlkdUludGVybmFsL0V2ZW50cy9SZWNvcmRpbmdFdmVudC50cyIsIk9wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1Nlc3Npb25EaXNjb25uZWN0ZWRFdmVudC50cyIsIk9wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1NpZ25hbEV2ZW50LnRzIiwiT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvU3RyZWFtRXZlbnQudHMiLCJPcGVuVmlkdUludGVybmFsL0V2ZW50cy9TdHJlYW1NYW5hZ2VyRXZlbnQudHMiLCJPcGVuVmlkdUludGVybmFsL0V2ZW50cy9TdHJlYW1Qcm9wZXJ0eUNoYW5nZWRFdmVudC50cyIsIk9wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1ZpZGVvRWxlbWVudEV2ZW50LnRzIiwiT3BlblZpZHVJbnRlcm5hbC9LdXJlbnRvVXRpbHMva3VyZW50by1qc29ucnBjL01hcHBlci5qcyIsIk9wZW5WaWR1SW50ZXJuYWwvS3VyZW50b1V0aWxzL2t1cmVudG8tanNvbnJwYy9jbGllbnRzL2luZGV4LmpzIiwiT3BlblZpZHVJbnRlcm5hbC9LdXJlbnRvVXRpbHMva3VyZW50by1qc29ucnBjL2NsaWVudHMvanNvbnJwY2NsaWVudC5qcyIsIk9wZW5WaWR1SW50ZXJuYWwvS3VyZW50b1V0aWxzL2t1cmVudG8tanNvbnJwYy9jbGllbnRzL3RyYW5zcG9ydHMvaW5kZXguanMiLCJPcGVuVmlkdUludGVybmFsL0t1cmVudG9VdGlscy9rdXJlbnRvLWpzb25ycGMvY2xpZW50cy90cmFuc3BvcnRzL3dlYlNvY2tldFdpdGhSZWNvbm5lY3Rpb24uanMiLCJPcGVuVmlkdUludGVybmFsL0t1cmVudG9VdGlscy9rdXJlbnRvLWpzb25ycGMvaW5kZXguanMiLCJPcGVuVmlkdUludGVybmFsL0t1cmVudG9VdGlscy9rdXJlbnRvLWpzb25ycGMvcGFja2Vycy9Kc29uUlBDLmpzIiwiT3BlblZpZHVJbnRlcm5hbC9LdXJlbnRvVXRpbHMva3VyZW50by1qc29ucnBjL3BhY2tlcnMvWG1sUlBDLmpzIiwiT3BlblZpZHVJbnRlcm5hbC9LdXJlbnRvVXRpbHMva3VyZW50by1qc29ucnBjL3BhY2tlcnMvaW5kZXguanMiLCJPcGVuVmlkdUludGVybmFsL1NjcmVlblNoYXJpbmcvU2NyZWVuLUNhcHR1cmluZy1BdXRvLmpzIiwiT3BlblZpZHVJbnRlcm5hbC9TY3JlZW5TaGFyaW5nL1NjcmVlbi1DYXB0dXJpbmcuanMiLCJPcGVuVmlkdUludGVybmFsL1dlYlJ0Y1BlZXIvV2ViUnRjUGVlci50cyIsIk9wZW5WaWR1SW50ZXJuYWwvV2ViUnRjU3RhdHMvV2ViUnRjU3RhdHMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7QUNBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzNnQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDekdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDaEJBO0FBQ0E7O0FDREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2xKQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdkJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUM1REE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7O0FDanNDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDUkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDeEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbENBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDN0dBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM3QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDekpBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7O0FDdGVBLGdEQUErQztBQUUvQyxJQUFJLE1BQU0s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bigpe2Z1bmN0aW9uIHIoZSxuLHQpe2Z1bmN0aW9uIG8oaSxmKXtpZighbltpXSl7aWYoIWVbaV0pe3ZhciBjPVwiZnVuY3Rpb25cIj09dHlwZW9mIHJlcXVpcmUmJnJlcXVpcmU7aWYoIWYmJmMpcmV0dXJuIGMoaSwhMCk7aWYodSlyZXR1cm4gdShpLCEwKTt2YXIgYT1uZXcgRXJyb3IoXCJDYW5ub3QgZmluZCBtb2R1bGUgJ1wiK2krXCInXCIpO3Rocm93IGEuY29kZT1cIk1PRFVMRV9OT1RfRk9VTkRcIixhfXZhciBwPW5baV09e2V4cG9ydHM6e319O2VbaV1bMF0uY2FsbChwLmV4cG9ydHMsZnVuY3Rpb24ocil7dmFyIG49ZVtpXVsxXVtyXTtyZXR1cm4gbyhufHxyKX0scCxwLmV4cG9ydHMscixlLG4sdCl9cmV0dXJuIG5baV0uZXhwb3J0c31mb3IodmFyIHU9XCJmdW5jdGlvblwiPT10eXBlb2YgcmVxdWlyZSYmcmVxdWlyZSxpPTA7aTx0Lmxlbmd0aDtpKyspbyh0W2ldKTtyZXR1cm4gb31yZXR1cm4gcn0pKCkiLCIvLyBDb3B5cmlnaHQgSm95ZW50LCBJbmMuIGFuZCBvdGhlciBOb2RlIGNvbnRyaWJ1dG9ycy5cbi8vXG4vLyBQZXJtaXNzaW9uIGlzIGhlcmVieSBncmFudGVkLCBmcmVlIG9mIGNoYXJnZSwgdG8gYW55IHBlcnNvbiBvYnRhaW5pbmcgYVxuLy8gY29weSBvZiB0aGlzIHNvZnR3YXJlIGFuZCBhc3NvY2lhdGVkIGRvY3VtZW50YXRpb24gZmlsZXMgKHRoZVxuLy8gXCJTb2Z0d2FyZVwiKSwgdG8gZGVhbCBpbiB0aGUgU29mdHdhcmUgd2l0aG91dCByZXN0cmljdGlvbiwgaW5jbHVkaW5nXG4vLyB3aXRob3V0IGxpbWl0YXRpb24gdGhlIHJpZ2h0cyB0byB1c2UsIGNvcHksIG1vZGlmeSwgbWVyZ2UsIHB1Ymxpc2gsXG4vLyBkaXN0cmlidXRlLCBzdWJsaWNlbnNlLCBhbmQvb3Igc2VsbCBjb3BpZXMgb2YgdGhlIFNvZnR3YXJlLCBhbmQgdG8gcGVybWl0XG4vLyBwZXJzb25zIHRvIHdob20gdGhlIFNvZnR3YXJlIGlzIGZ1cm5pc2hlZCB0byBkbyBzbywgc3ViamVjdCB0byB0aGVcbi8vIGZvbGxvd2luZyBjb25kaXRpb25zOlxuLy9cbi8vIFRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlIGFuZCB0aGlzIHBlcm1pc3Npb24gbm90aWNlIHNoYWxsIGJlIGluY2x1ZGVkXG4vLyBpbiBhbGwgY29waWVzIG9yIHN1YnN0YW50aWFsIHBvcnRpb25zIG9mIHRoZSBTb2Z0d2FyZS5cbi8vXG4vLyBUSEUgU09GVFdBUkUgSVMgUFJPVklERUQgXCJBUyBJU1wiLCBXSVRIT1VUIFdBUlJBTlRZIE9GIEFOWSBLSU5ELCBFWFBSRVNTXG4vLyBPUiBJTVBMSUVELCBJTkNMVURJTkcgQlVUIE5PVCBMSU1JVEVEIFRPIFRIRSBXQVJSQU5USUVTIE9GXG4vLyBNRVJDSEFOVEFCSUxJVFksIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFORCBOT05JTkZSSU5HRU1FTlQuIElOXG4vLyBOTyBFVkVOVCBTSEFMTCBUSEUgQVVUSE9SUyBPUiBDT1BZUklHSFQgSE9MREVSUyBCRSBMSUFCTEUgRk9SIEFOWSBDTEFJTSxcbi8vIERBTUFHRVMgT1IgT1RIRVIgTElBQklMSVRZLCBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgVE9SVCBPUlxuLy8gT1RIRVJXSVNFLCBBUklTSU5HIEZST00sIE9VVCBPRiBPUiBJTiBDT05ORUNUSU9OIFdJVEggVEhFIFNPRlRXQVJFIE9SIFRIRVxuLy8gVVNFIE9SIE9USEVSIERFQUxJTkdTIElOIFRIRSBTT0ZUV0FSRS5cblxudmFyIG9iamVjdENyZWF0ZSA9IE9iamVjdC5jcmVhdGUgfHwgb2JqZWN0Q3JlYXRlUG9seWZpbGxcbnZhciBvYmplY3RLZXlzID0gT2JqZWN0LmtleXMgfHwgb2JqZWN0S2V5c1BvbHlmaWxsXG52YXIgYmluZCA9IEZ1bmN0aW9uLnByb3RvdHlwZS5iaW5kIHx8IGZ1bmN0aW9uQmluZFBvbHlmaWxsXG5cbmZ1bmN0aW9uIEV2ZW50RW1pdHRlcigpIHtcbiAgaWYgKCF0aGlzLl9ldmVudHMgfHwgIU9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbCh0aGlzLCAnX2V2ZW50cycpKSB7XG4gICAgdGhpcy5fZXZlbnRzID0gb2JqZWN0Q3JlYXRlKG51bGwpO1xuICAgIHRoaXMuX2V2ZW50c0NvdW50ID0gMDtcbiAgfVxuXG4gIHRoaXMuX21heExpc3RlbmVycyA9IHRoaXMuX21heExpc3RlbmVycyB8fCB1bmRlZmluZWQ7XG59XG5tb2R1bGUuZXhwb3J0cyA9IEV2ZW50RW1pdHRlcjtcblxuLy8gQmFja3dhcmRzLWNvbXBhdCB3aXRoIG5vZGUgMC4xMC54XG5FdmVudEVtaXR0ZXIuRXZlbnRFbWl0dGVyID0gRXZlbnRFbWl0dGVyO1xuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLl9ldmVudHMgPSB1bmRlZmluZWQ7XG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLl9tYXhMaXN0ZW5lcnMgPSB1bmRlZmluZWQ7XG5cbi8vIEJ5IGRlZmF1bHQgRXZlbnRFbWl0dGVycyB3aWxsIHByaW50IGEgd2FybmluZyBpZiBtb3JlIHRoYW4gMTAgbGlzdGVuZXJzIGFyZVxuLy8gYWRkZWQgdG8gaXQuIFRoaXMgaXMgYSB1c2VmdWwgZGVmYXVsdCB3aGljaCBoZWxwcyBmaW5kaW5nIG1lbW9yeSBsZWFrcy5cbnZhciBkZWZhdWx0TWF4TGlzdGVuZXJzID0gMTA7XG5cbnZhciBoYXNEZWZpbmVQcm9wZXJ0eTtcbnRyeSB7XG4gIHZhciBvID0ge307XG4gIGlmIChPYmplY3QuZGVmaW5lUHJvcGVydHkpIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShvLCAneCcsIHsgdmFsdWU6IDAgfSk7XG4gIGhhc0RlZmluZVByb3BlcnR5ID0gby54ID09PSAwO1xufSBjYXRjaCAoZXJyKSB7IGhhc0RlZmluZVByb3BlcnR5ID0gZmFsc2UgfVxuaWYgKGhhc0RlZmluZVByb3BlcnR5KSB7XG4gIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShFdmVudEVtaXR0ZXIsICdkZWZhdWx0TWF4TGlzdGVuZXJzJywge1xuICAgIGVudW1lcmFibGU6IHRydWUsXG4gICAgZ2V0OiBmdW5jdGlvbigpIHtcbiAgICAgIHJldHVybiBkZWZhdWx0TWF4TGlzdGVuZXJzO1xuICAgIH0sXG4gICAgc2V0OiBmdW5jdGlvbihhcmcpIHtcbiAgICAgIC8vIGNoZWNrIHdoZXRoZXIgdGhlIGlucHV0IGlzIGEgcG9zaXRpdmUgbnVtYmVyICh3aG9zZSB2YWx1ZSBpcyB6ZXJvIG9yXG4gICAgICAvLyBncmVhdGVyIGFuZCBub3QgYSBOYU4pLlxuICAgICAgaWYgKHR5cGVvZiBhcmcgIT09ICdudW1iZXInIHx8IGFyZyA8IDAgfHwgYXJnICE9PSBhcmcpXG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ1wiZGVmYXVsdE1heExpc3RlbmVyc1wiIG11c3QgYmUgYSBwb3NpdGl2ZSBudW1iZXInKTtcbiAgICAgIGRlZmF1bHRNYXhMaXN0ZW5lcnMgPSBhcmc7XG4gICAgfVxuICB9KTtcbn0gZWxzZSB7XG4gIEV2ZW50RW1pdHRlci5kZWZhdWx0TWF4TGlzdGVuZXJzID0gZGVmYXVsdE1heExpc3RlbmVycztcbn1cblxuLy8gT2J2aW91c2x5IG5vdCBhbGwgRW1pdHRlcnMgc2hvdWxkIGJlIGxpbWl0ZWQgdG8gMTAuIFRoaXMgZnVuY3Rpb24gYWxsb3dzXG4vLyB0aGF0IHRvIGJlIGluY3JlYXNlZC4gU2V0IHRvIHplcm8gZm9yIHVubGltaXRlZC5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUuc2V0TWF4TGlzdGVuZXJzID0gZnVuY3Rpb24gc2V0TWF4TGlzdGVuZXJzKG4pIHtcbiAgaWYgKHR5cGVvZiBuICE9PSAnbnVtYmVyJyB8fCBuIDwgMCB8fCBpc05hTihuKSlcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdcIm5cIiBhcmd1bWVudCBtdXN0IGJlIGEgcG9zaXRpdmUgbnVtYmVyJyk7XG4gIHRoaXMuX21heExpc3RlbmVycyA9IG47XG4gIHJldHVybiB0aGlzO1xufTtcblxuZnVuY3Rpb24gJGdldE1heExpc3RlbmVycyh0aGF0KSB7XG4gIGlmICh0aGF0Ll9tYXhMaXN0ZW5lcnMgPT09IHVuZGVmaW5lZClcbiAgICByZXR1cm4gRXZlbnRFbWl0dGVyLmRlZmF1bHRNYXhMaXN0ZW5lcnM7XG4gIHJldHVybiB0aGF0Ll9tYXhMaXN0ZW5lcnM7XG59XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUuZ2V0TWF4TGlzdGVuZXJzID0gZnVuY3Rpb24gZ2V0TWF4TGlzdGVuZXJzKCkge1xuICByZXR1cm4gJGdldE1heExpc3RlbmVycyh0aGlzKTtcbn07XG5cbi8vIFRoZXNlIHN0YW5kYWxvbmUgZW1pdCogZnVuY3Rpb25zIGFyZSB1c2VkIHRvIG9wdGltaXplIGNhbGxpbmcgb2YgZXZlbnRcbi8vIGhhbmRsZXJzIGZvciBmYXN0IGNhc2VzIGJlY2F1c2UgZW1pdCgpIGl0c2VsZiBvZnRlbiBoYXMgYSB2YXJpYWJsZSBudW1iZXIgb2Zcbi8vIGFyZ3VtZW50cyBhbmQgY2FuIGJlIGRlb3B0aW1pemVkIGJlY2F1c2Ugb2YgdGhhdC4gVGhlc2UgZnVuY3Rpb25zIGFsd2F5cyBoYXZlXG4vLyB0aGUgc2FtZSBudW1iZXIgb2YgYXJndW1lbnRzIGFuZCB0aHVzIGRvIG5vdCBnZXQgZGVvcHRpbWl6ZWQsIHNvIHRoZSBjb2RlXG4vLyBpbnNpZGUgdGhlbSBjYW4gZXhlY3V0ZSBmYXN0ZXIuXG5mdW5jdGlvbiBlbWl0Tm9uZShoYW5kbGVyLCBpc0ZuLCBzZWxmKSB7XG4gIGlmIChpc0ZuKVxuICAgIGhhbmRsZXIuY2FsbChzZWxmKTtcbiAgZWxzZSB7XG4gICAgdmFyIGxlbiA9IGhhbmRsZXIubGVuZ3RoO1xuICAgIHZhciBsaXN0ZW5lcnMgPSBhcnJheUNsb25lKGhhbmRsZXIsIGxlbik7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW47ICsraSlcbiAgICAgIGxpc3RlbmVyc1tpXS5jYWxsKHNlbGYpO1xuICB9XG59XG5mdW5jdGlvbiBlbWl0T25lKGhhbmRsZXIsIGlzRm4sIHNlbGYsIGFyZzEpIHtcbiAgaWYgKGlzRm4pXG4gICAgaGFuZGxlci5jYWxsKHNlbGYsIGFyZzEpO1xuICBlbHNlIHtcbiAgICB2YXIgbGVuID0gaGFuZGxlci5sZW5ndGg7XG4gICAgdmFyIGxpc3RlbmVycyA9IGFycmF5Q2xvbmUoaGFuZGxlciwgbGVuKTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgKytpKVxuICAgICAgbGlzdGVuZXJzW2ldLmNhbGwoc2VsZiwgYXJnMSk7XG4gIH1cbn1cbmZ1bmN0aW9uIGVtaXRUd28oaGFuZGxlciwgaXNGbiwgc2VsZiwgYXJnMSwgYXJnMikge1xuICBpZiAoaXNGbilcbiAgICBoYW5kbGVyLmNhbGwoc2VsZiwgYXJnMSwgYXJnMik7XG4gIGVsc2Uge1xuICAgIHZhciBsZW4gPSBoYW5kbGVyLmxlbmd0aDtcbiAgICB2YXIgbGlzdGVuZXJzID0gYXJyYXlDbG9uZShoYW5kbGVyLCBsZW4pO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuOyArK2kpXG4gICAgICBsaXN0ZW5lcnNbaV0uY2FsbChzZWxmLCBhcmcxLCBhcmcyKTtcbiAgfVxufVxuZnVuY3Rpb24gZW1pdFRocmVlKGhhbmRsZXIsIGlzRm4sIHNlbGYsIGFyZzEsIGFyZzIsIGFyZzMpIHtcbiAgaWYgKGlzRm4pXG4gICAgaGFuZGxlci5jYWxsKHNlbGYsIGFyZzEsIGFyZzIsIGFyZzMpO1xuICBlbHNlIHtcbiAgICB2YXIgbGVuID0gaGFuZGxlci5sZW5ndGg7XG4gICAgdmFyIGxpc3RlbmVycyA9IGFycmF5Q2xvbmUoaGFuZGxlciwgbGVuKTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgKytpKVxuICAgICAgbGlzdGVuZXJzW2ldLmNhbGwoc2VsZiwgYXJnMSwgYXJnMiwgYXJnMyk7XG4gIH1cbn1cblxuZnVuY3Rpb24gZW1pdE1hbnkoaGFuZGxlciwgaXNGbiwgc2VsZiwgYXJncykge1xuICBpZiAoaXNGbilcbiAgICBoYW5kbGVyLmFwcGx5KHNlbGYsIGFyZ3MpO1xuICBlbHNlIHtcbiAgICB2YXIgbGVuID0gaGFuZGxlci5sZW5ndGg7XG4gICAgdmFyIGxpc3RlbmVycyA9IGFycmF5Q2xvbmUoaGFuZGxlciwgbGVuKTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgKytpKVxuICAgICAgbGlzdGVuZXJzW2ldLmFwcGx5KHNlbGYsIGFyZ3MpO1xuICB9XG59XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUuZW1pdCA9IGZ1bmN0aW9uIGVtaXQodHlwZSkge1xuICB2YXIgZXIsIGhhbmRsZXIsIGxlbiwgYXJncywgaSwgZXZlbnRzO1xuICB2YXIgZG9FcnJvciA9ICh0eXBlID09PSAnZXJyb3InKTtcblxuICBldmVudHMgPSB0aGlzLl9ldmVudHM7XG4gIGlmIChldmVudHMpXG4gICAgZG9FcnJvciA9IChkb0Vycm9yICYmIGV2ZW50cy5lcnJvciA9PSBudWxsKTtcbiAgZWxzZSBpZiAoIWRvRXJyb3IpXG4gICAgcmV0dXJuIGZhbHNlO1xuXG4gIC8vIElmIHRoZXJlIGlzIG5vICdlcnJvcicgZXZlbnQgbGlzdGVuZXIgdGhlbiB0aHJvdy5cbiAgaWYgKGRvRXJyb3IpIHtcbiAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA+IDEpXG4gICAgICBlciA9IGFyZ3VtZW50c1sxXTtcbiAgICBpZiAoZXIgaW5zdGFuY2VvZiBFcnJvcikge1xuICAgICAgdGhyb3cgZXI7IC8vIFVuaGFuZGxlZCAnZXJyb3InIGV2ZW50XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIEF0IGxlYXN0IGdpdmUgc29tZSBraW5kIG9mIGNvbnRleHQgdG8gdGhlIHVzZXJcbiAgICAgIHZhciBlcnIgPSBuZXcgRXJyb3IoJ1VuaGFuZGxlZCBcImVycm9yXCIgZXZlbnQuICgnICsgZXIgKyAnKScpO1xuICAgICAgZXJyLmNvbnRleHQgPSBlcjtcbiAgICAgIHRocm93IGVycjtcbiAgICB9XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgaGFuZGxlciA9IGV2ZW50c1t0eXBlXTtcblxuICBpZiAoIWhhbmRsZXIpXG4gICAgcmV0dXJuIGZhbHNlO1xuXG4gIHZhciBpc0ZuID0gdHlwZW9mIGhhbmRsZXIgPT09ICdmdW5jdGlvbic7XG4gIGxlbiA9IGFyZ3VtZW50cy5sZW5ndGg7XG4gIHN3aXRjaCAobGVuKSB7XG4gICAgICAvLyBmYXN0IGNhc2VzXG4gICAgY2FzZSAxOlxuICAgICAgZW1pdE5vbmUoaGFuZGxlciwgaXNGbiwgdGhpcyk7XG4gICAgICBicmVhaztcbiAgICBjYXNlIDI6XG4gICAgICBlbWl0T25lKGhhbmRsZXIsIGlzRm4sIHRoaXMsIGFyZ3VtZW50c1sxXSk7XG4gICAgICBicmVhaztcbiAgICBjYXNlIDM6XG4gICAgICBlbWl0VHdvKGhhbmRsZXIsIGlzRm4sIHRoaXMsIGFyZ3VtZW50c1sxXSwgYXJndW1lbnRzWzJdKTtcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgNDpcbiAgICAgIGVtaXRUaHJlZShoYW5kbGVyLCBpc0ZuLCB0aGlzLCBhcmd1bWVudHNbMV0sIGFyZ3VtZW50c1syXSwgYXJndW1lbnRzWzNdKTtcbiAgICAgIGJyZWFrO1xuICAgICAgLy8gc2xvd2VyXG4gICAgZGVmYXVsdDpcbiAgICAgIGFyZ3MgPSBuZXcgQXJyYXkobGVuIC0gMSk7XG4gICAgICBmb3IgKGkgPSAxOyBpIDwgbGVuOyBpKyspXG4gICAgICAgIGFyZ3NbaSAtIDFdID0gYXJndW1lbnRzW2ldO1xuICAgICAgZW1pdE1hbnkoaGFuZGxlciwgaXNGbiwgdGhpcywgYXJncyk7XG4gIH1cblxuICByZXR1cm4gdHJ1ZTtcbn07XG5cbmZ1bmN0aW9uIF9hZGRMaXN0ZW5lcih0YXJnZXQsIHR5cGUsIGxpc3RlbmVyLCBwcmVwZW5kKSB7XG4gIHZhciBtO1xuICB2YXIgZXZlbnRzO1xuICB2YXIgZXhpc3Rpbmc7XG5cbiAgaWYgKHR5cGVvZiBsaXN0ZW5lciAhPT0gJ2Z1bmN0aW9uJylcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdcImxpc3RlbmVyXCIgYXJndW1lbnQgbXVzdCBiZSBhIGZ1bmN0aW9uJyk7XG5cbiAgZXZlbnRzID0gdGFyZ2V0Ll9ldmVudHM7XG4gIGlmICghZXZlbnRzKSB7XG4gICAgZXZlbnRzID0gdGFyZ2V0Ll9ldmVudHMgPSBvYmplY3RDcmVhdGUobnVsbCk7XG4gICAgdGFyZ2V0Ll9ldmVudHNDb3VudCA9IDA7XG4gIH0gZWxzZSB7XG4gICAgLy8gVG8gYXZvaWQgcmVjdXJzaW9uIGluIHRoZSBjYXNlIHRoYXQgdHlwZSA9PT0gXCJuZXdMaXN0ZW5lclwiISBCZWZvcmVcbiAgICAvLyBhZGRpbmcgaXQgdG8gdGhlIGxpc3RlbmVycywgZmlyc3QgZW1pdCBcIm5ld0xpc3RlbmVyXCIuXG4gICAgaWYgKGV2ZW50cy5uZXdMaXN0ZW5lcikge1xuICAgICAgdGFyZ2V0LmVtaXQoJ25ld0xpc3RlbmVyJywgdHlwZSxcbiAgICAgICAgICBsaXN0ZW5lci5saXN0ZW5lciA/IGxpc3RlbmVyLmxpc3RlbmVyIDogbGlzdGVuZXIpO1xuXG4gICAgICAvLyBSZS1hc3NpZ24gYGV2ZW50c2AgYmVjYXVzZSBhIG5ld0xpc3RlbmVyIGhhbmRsZXIgY291bGQgaGF2ZSBjYXVzZWQgdGhlXG4gICAgICAvLyB0aGlzLl9ldmVudHMgdG8gYmUgYXNzaWduZWQgdG8gYSBuZXcgb2JqZWN0XG4gICAgICBldmVudHMgPSB0YXJnZXQuX2V2ZW50cztcbiAgICB9XG4gICAgZXhpc3RpbmcgPSBldmVudHNbdHlwZV07XG4gIH1cblxuICBpZiAoIWV4aXN0aW5nKSB7XG4gICAgLy8gT3B0aW1pemUgdGhlIGNhc2Ugb2Ygb25lIGxpc3RlbmVyLiBEb24ndCBuZWVkIHRoZSBleHRyYSBhcnJheSBvYmplY3QuXG4gICAgZXhpc3RpbmcgPSBldmVudHNbdHlwZV0gPSBsaXN0ZW5lcjtcbiAgICArK3RhcmdldC5fZXZlbnRzQ291bnQ7XG4gIH0gZWxzZSB7XG4gICAgaWYgKHR5cGVvZiBleGlzdGluZyA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgLy8gQWRkaW5nIHRoZSBzZWNvbmQgZWxlbWVudCwgbmVlZCB0byBjaGFuZ2UgdG8gYXJyYXkuXG4gICAgICBleGlzdGluZyA9IGV2ZW50c1t0eXBlXSA9XG4gICAgICAgICAgcHJlcGVuZCA/IFtsaXN0ZW5lciwgZXhpc3RpbmddIDogW2V4aXN0aW5nLCBsaXN0ZW5lcl07XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIElmIHdlJ3ZlIGFscmVhZHkgZ290IGFuIGFycmF5LCBqdXN0IGFwcGVuZC5cbiAgICAgIGlmIChwcmVwZW5kKSB7XG4gICAgICAgIGV4aXN0aW5nLnVuc2hpZnQobGlzdGVuZXIpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgZXhpc3RpbmcucHVzaChsaXN0ZW5lcik7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gQ2hlY2sgZm9yIGxpc3RlbmVyIGxlYWtcbiAgICBpZiAoIWV4aXN0aW5nLndhcm5lZCkge1xuICAgICAgbSA9ICRnZXRNYXhMaXN0ZW5lcnModGFyZ2V0KTtcbiAgICAgIGlmIChtICYmIG0gPiAwICYmIGV4aXN0aW5nLmxlbmd0aCA+IG0pIHtcbiAgICAgICAgZXhpc3Rpbmcud2FybmVkID0gdHJ1ZTtcbiAgICAgICAgdmFyIHcgPSBuZXcgRXJyb3IoJ1Bvc3NpYmxlIEV2ZW50RW1pdHRlciBtZW1vcnkgbGVhayBkZXRlY3RlZC4gJyArXG4gICAgICAgICAgICBleGlzdGluZy5sZW5ndGggKyAnIFwiJyArIFN0cmluZyh0eXBlKSArICdcIiBsaXN0ZW5lcnMgJyArXG4gICAgICAgICAgICAnYWRkZWQuIFVzZSBlbWl0dGVyLnNldE1heExpc3RlbmVycygpIHRvICcgK1xuICAgICAgICAgICAgJ2luY3JlYXNlIGxpbWl0LicpO1xuICAgICAgICB3Lm5hbWUgPSAnTWF4TGlzdGVuZXJzRXhjZWVkZWRXYXJuaW5nJztcbiAgICAgICAgdy5lbWl0dGVyID0gdGFyZ2V0O1xuICAgICAgICB3LnR5cGUgPSB0eXBlO1xuICAgICAgICB3LmNvdW50ID0gZXhpc3RpbmcubGVuZ3RoO1xuICAgICAgICBpZiAodHlwZW9mIGNvbnNvbGUgPT09ICdvYmplY3QnICYmIGNvbnNvbGUud2Fybikge1xuICAgICAgICAgIGNvbnNvbGUud2FybignJXM6ICVzJywgdy5uYW1lLCB3Lm1lc3NhZ2UpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHRhcmdldDtcbn1cblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5hZGRMaXN0ZW5lciA9IGZ1bmN0aW9uIGFkZExpc3RlbmVyKHR5cGUsIGxpc3RlbmVyKSB7XG4gIHJldHVybiBfYWRkTGlzdGVuZXIodGhpcywgdHlwZSwgbGlzdGVuZXIsIGZhbHNlKTtcbn07XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUub24gPSBFdmVudEVtaXR0ZXIucHJvdG90eXBlLmFkZExpc3RlbmVyO1xuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLnByZXBlbmRMaXN0ZW5lciA9XG4gICAgZnVuY3Rpb24gcHJlcGVuZExpc3RlbmVyKHR5cGUsIGxpc3RlbmVyKSB7XG4gICAgICByZXR1cm4gX2FkZExpc3RlbmVyKHRoaXMsIHR5cGUsIGxpc3RlbmVyLCB0cnVlKTtcbiAgICB9O1xuXG5mdW5jdGlvbiBvbmNlV3JhcHBlcigpIHtcbiAgaWYgKCF0aGlzLmZpcmVkKSB7XG4gICAgdGhpcy50YXJnZXQucmVtb3ZlTGlzdGVuZXIodGhpcy50eXBlLCB0aGlzLndyYXBGbik7XG4gICAgdGhpcy5maXJlZCA9IHRydWU7XG4gICAgc3dpdGNoIChhcmd1bWVudHMubGVuZ3RoKSB7XG4gICAgICBjYXNlIDA6XG4gICAgICAgIHJldHVybiB0aGlzLmxpc3RlbmVyLmNhbGwodGhpcy50YXJnZXQpO1xuICAgICAgY2FzZSAxOlxuICAgICAgICByZXR1cm4gdGhpcy5saXN0ZW5lci5jYWxsKHRoaXMudGFyZ2V0LCBhcmd1bWVudHNbMF0pO1xuICAgICAgY2FzZSAyOlxuICAgICAgICByZXR1cm4gdGhpcy5saXN0ZW5lci5jYWxsKHRoaXMudGFyZ2V0LCBhcmd1bWVudHNbMF0sIGFyZ3VtZW50c1sxXSk7XG4gICAgICBjYXNlIDM6XG4gICAgICAgIHJldHVybiB0aGlzLmxpc3RlbmVyLmNhbGwodGhpcy50YXJnZXQsIGFyZ3VtZW50c1swXSwgYXJndW1lbnRzWzFdLFxuICAgICAgICAgICAgYXJndW1lbnRzWzJdKTtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHZhciBhcmdzID0gbmV3IEFycmF5KGFyZ3VtZW50cy5sZW5ndGgpO1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGFyZ3MubGVuZ3RoOyArK2kpXG4gICAgICAgICAgYXJnc1tpXSA9IGFyZ3VtZW50c1tpXTtcbiAgICAgICAgdGhpcy5saXN0ZW5lci5hcHBseSh0aGlzLnRhcmdldCwgYXJncyk7XG4gICAgfVxuICB9XG59XG5cbmZ1bmN0aW9uIF9vbmNlV3JhcCh0YXJnZXQsIHR5cGUsIGxpc3RlbmVyKSB7XG4gIHZhciBzdGF0ZSA9IHsgZmlyZWQ6IGZhbHNlLCB3cmFwRm46IHVuZGVmaW5lZCwgdGFyZ2V0OiB0YXJnZXQsIHR5cGU6IHR5cGUsIGxpc3RlbmVyOiBsaXN0ZW5lciB9O1xuICB2YXIgd3JhcHBlZCA9IGJpbmQuY2FsbChvbmNlV3JhcHBlciwgc3RhdGUpO1xuICB3cmFwcGVkLmxpc3RlbmVyID0gbGlzdGVuZXI7XG4gIHN0YXRlLndyYXBGbiA9IHdyYXBwZWQ7XG4gIHJldHVybiB3cmFwcGVkO1xufVxuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLm9uY2UgPSBmdW5jdGlvbiBvbmNlKHR5cGUsIGxpc3RlbmVyKSB7XG4gIGlmICh0eXBlb2YgbGlzdGVuZXIgIT09ICdmdW5jdGlvbicpXG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcignXCJsaXN0ZW5lclwiIGFyZ3VtZW50IG11c3QgYmUgYSBmdW5jdGlvbicpO1xuICB0aGlzLm9uKHR5cGUsIF9vbmNlV3JhcCh0aGlzLCB0eXBlLCBsaXN0ZW5lcikpO1xuICByZXR1cm4gdGhpcztcbn07XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUucHJlcGVuZE9uY2VMaXN0ZW5lciA9XG4gICAgZnVuY3Rpb24gcHJlcGVuZE9uY2VMaXN0ZW5lcih0eXBlLCBsaXN0ZW5lcikge1xuICAgICAgaWYgKHR5cGVvZiBsaXN0ZW5lciAhPT0gJ2Z1bmN0aW9uJylcbiAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignXCJsaXN0ZW5lclwiIGFyZ3VtZW50IG11c3QgYmUgYSBmdW5jdGlvbicpO1xuICAgICAgdGhpcy5wcmVwZW5kTGlzdGVuZXIodHlwZSwgX29uY2VXcmFwKHRoaXMsIHR5cGUsIGxpc3RlbmVyKSk7XG4gICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuXG4vLyBFbWl0cyBhICdyZW1vdmVMaXN0ZW5lcicgZXZlbnQgaWYgYW5kIG9ubHkgaWYgdGhlIGxpc3RlbmVyIHdhcyByZW1vdmVkLlxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5yZW1vdmVMaXN0ZW5lciA9XG4gICAgZnVuY3Rpb24gcmVtb3ZlTGlzdGVuZXIodHlwZSwgbGlzdGVuZXIpIHtcbiAgICAgIHZhciBsaXN0LCBldmVudHMsIHBvc2l0aW9uLCBpLCBvcmlnaW5hbExpc3RlbmVyO1xuXG4gICAgICBpZiAodHlwZW9mIGxpc3RlbmVyICE9PSAnZnVuY3Rpb24nKVxuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdcImxpc3RlbmVyXCIgYXJndW1lbnQgbXVzdCBiZSBhIGZ1bmN0aW9uJyk7XG5cbiAgICAgIGV2ZW50cyA9IHRoaXMuX2V2ZW50cztcbiAgICAgIGlmICghZXZlbnRzKVxuICAgICAgICByZXR1cm4gdGhpcztcblxuICAgICAgbGlzdCA9IGV2ZW50c1t0eXBlXTtcbiAgICAgIGlmICghbGlzdClcbiAgICAgICAgcmV0dXJuIHRoaXM7XG5cbiAgICAgIGlmIChsaXN0ID09PSBsaXN0ZW5lciB8fCBsaXN0Lmxpc3RlbmVyID09PSBsaXN0ZW5lcikge1xuICAgICAgICBpZiAoLS10aGlzLl9ldmVudHNDb3VudCA9PT0gMClcbiAgICAgICAgICB0aGlzLl9ldmVudHMgPSBvYmplY3RDcmVhdGUobnVsbCk7XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgIGRlbGV0ZSBldmVudHNbdHlwZV07XG4gICAgICAgICAgaWYgKGV2ZW50cy5yZW1vdmVMaXN0ZW5lcilcbiAgICAgICAgICAgIHRoaXMuZW1pdCgncmVtb3ZlTGlzdGVuZXInLCB0eXBlLCBsaXN0Lmxpc3RlbmVyIHx8IGxpc3RlbmVyKTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIGlmICh0eXBlb2YgbGlzdCAhPT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICBwb3NpdGlvbiA9IC0xO1xuXG4gICAgICAgIGZvciAoaSA9IGxpc3QubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgICAgICBpZiAobGlzdFtpXSA9PT0gbGlzdGVuZXIgfHwgbGlzdFtpXS5saXN0ZW5lciA9PT0gbGlzdGVuZXIpIHtcbiAgICAgICAgICAgIG9yaWdpbmFsTGlzdGVuZXIgPSBsaXN0W2ldLmxpc3RlbmVyO1xuICAgICAgICAgICAgcG9zaXRpb24gPSBpO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHBvc2l0aW9uIDwgMClcbiAgICAgICAgICByZXR1cm4gdGhpcztcblxuICAgICAgICBpZiAocG9zaXRpb24gPT09IDApXG4gICAgICAgICAgbGlzdC5zaGlmdCgpO1xuICAgICAgICBlbHNlXG4gICAgICAgICAgc3BsaWNlT25lKGxpc3QsIHBvc2l0aW9uKTtcblxuICAgICAgICBpZiAobGlzdC5sZW5ndGggPT09IDEpXG4gICAgICAgICAgZXZlbnRzW3R5cGVdID0gbGlzdFswXTtcblxuICAgICAgICBpZiAoZXZlbnRzLnJlbW92ZUxpc3RlbmVyKVxuICAgICAgICAgIHRoaXMuZW1pdCgncmVtb3ZlTGlzdGVuZXInLCB0eXBlLCBvcmlnaW5hbExpc3RlbmVyIHx8IGxpc3RlbmVyKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5yZW1vdmVBbGxMaXN0ZW5lcnMgPVxuICAgIGZ1bmN0aW9uIHJlbW92ZUFsbExpc3RlbmVycyh0eXBlKSB7XG4gICAgICB2YXIgbGlzdGVuZXJzLCBldmVudHMsIGk7XG5cbiAgICAgIGV2ZW50cyA9IHRoaXMuX2V2ZW50cztcbiAgICAgIGlmICghZXZlbnRzKVxuICAgICAgICByZXR1cm4gdGhpcztcblxuICAgICAgLy8gbm90IGxpc3RlbmluZyBmb3IgcmVtb3ZlTGlzdGVuZXIsIG5vIG5lZWQgdG8gZW1pdFxuICAgICAgaWYgKCFldmVudHMucmVtb3ZlTGlzdGVuZXIpIHtcbiAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICB0aGlzLl9ldmVudHMgPSBvYmplY3RDcmVhdGUobnVsbCk7XG4gICAgICAgICAgdGhpcy5fZXZlbnRzQ291bnQgPSAwO1xuICAgICAgICB9IGVsc2UgaWYgKGV2ZW50c1t0eXBlXSkge1xuICAgICAgICAgIGlmICgtLXRoaXMuX2V2ZW50c0NvdW50ID09PSAwKVxuICAgICAgICAgICAgdGhpcy5fZXZlbnRzID0gb2JqZWN0Q3JlYXRlKG51bGwpO1xuICAgICAgICAgIGVsc2VcbiAgICAgICAgICAgIGRlbGV0ZSBldmVudHNbdHlwZV07XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICB9XG5cbiAgICAgIC8vIGVtaXQgcmVtb3ZlTGlzdGVuZXIgZm9yIGFsbCBsaXN0ZW5lcnMgb24gYWxsIGV2ZW50c1xuICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgdmFyIGtleXMgPSBvYmplY3RLZXlzKGV2ZW50cyk7XG4gICAgICAgIHZhciBrZXk7XG4gICAgICAgIGZvciAoaSA9IDA7IGkgPCBrZXlzLmxlbmd0aDsgKytpKSB7XG4gICAgICAgICAga2V5ID0ga2V5c1tpXTtcbiAgICAgICAgICBpZiAoa2V5ID09PSAncmVtb3ZlTGlzdGVuZXInKSBjb250aW51ZTtcbiAgICAgICAgICB0aGlzLnJlbW92ZUFsbExpc3RlbmVycyhrZXkpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMucmVtb3ZlQWxsTGlzdGVuZXJzKCdyZW1vdmVMaXN0ZW5lcicpO1xuICAgICAgICB0aGlzLl9ldmVudHMgPSBvYmplY3RDcmVhdGUobnVsbCk7XG4gICAgICAgIHRoaXMuX2V2ZW50c0NvdW50ID0gMDtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICB9XG5cbiAgICAgIGxpc3RlbmVycyA9IGV2ZW50c1t0eXBlXTtcblxuICAgICAgaWYgKHR5cGVvZiBsaXN0ZW5lcnMgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgdGhpcy5yZW1vdmVMaXN0ZW5lcih0eXBlLCBsaXN0ZW5lcnMpO1xuICAgICAgfSBlbHNlIGlmIChsaXN0ZW5lcnMpIHtcbiAgICAgICAgLy8gTElGTyBvcmRlclxuICAgICAgICBmb3IgKGkgPSBsaXN0ZW5lcnMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgICAgICB0aGlzLnJlbW92ZUxpc3RlbmVyKHR5cGUsIGxpc3RlbmVyc1tpXSk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcblxuZnVuY3Rpb24gX2xpc3RlbmVycyh0YXJnZXQsIHR5cGUsIHVud3JhcCkge1xuICB2YXIgZXZlbnRzID0gdGFyZ2V0Ll9ldmVudHM7XG5cbiAgaWYgKCFldmVudHMpXG4gICAgcmV0dXJuIFtdO1xuXG4gIHZhciBldmxpc3RlbmVyID0gZXZlbnRzW3R5cGVdO1xuICBpZiAoIWV2bGlzdGVuZXIpXG4gICAgcmV0dXJuIFtdO1xuXG4gIGlmICh0eXBlb2YgZXZsaXN0ZW5lciA9PT0gJ2Z1bmN0aW9uJylcbiAgICByZXR1cm4gdW53cmFwID8gW2V2bGlzdGVuZXIubGlzdGVuZXIgfHwgZXZsaXN0ZW5lcl0gOiBbZXZsaXN0ZW5lcl07XG5cbiAgcmV0dXJuIHVud3JhcCA/IHVud3JhcExpc3RlbmVycyhldmxpc3RlbmVyKSA6IGFycmF5Q2xvbmUoZXZsaXN0ZW5lciwgZXZsaXN0ZW5lci5sZW5ndGgpO1xufVxuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLmxpc3RlbmVycyA9IGZ1bmN0aW9uIGxpc3RlbmVycyh0eXBlKSB7XG4gIHJldHVybiBfbGlzdGVuZXJzKHRoaXMsIHR5cGUsIHRydWUpO1xufTtcblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5yYXdMaXN0ZW5lcnMgPSBmdW5jdGlvbiByYXdMaXN0ZW5lcnModHlwZSkge1xuICByZXR1cm4gX2xpc3RlbmVycyh0aGlzLCB0eXBlLCBmYWxzZSk7XG59O1xuXG5FdmVudEVtaXR0ZXIubGlzdGVuZXJDb3VudCA9IGZ1bmN0aW9uKGVtaXR0ZXIsIHR5cGUpIHtcbiAgaWYgKHR5cGVvZiBlbWl0dGVyLmxpc3RlbmVyQ291bnQgPT09ICdmdW5jdGlvbicpIHtcbiAgICByZXR1cm4gZW1pdHRlci5saXN0ZW5lckNvdW50KHR5cGUpO1xuICB9IGVsc2Uge1xuICAgIHJldHVybiBsaXN0ZW5lckNvdW50LmNhbGwoZW1pdHRlciwgdHlwZSk7XG4gIH1cbn07XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUubGlzdGVuZXJDb3VudCA9IGxpc3RlbmVyQ291bnQ7XG5mdW5jdGlvbiBsaXN0ZW5lckNvdW50KHR5cGUpIHtcbiAgdmFyIGV2ZW50cyA9IHRoaXMuX2V2ZW50cztcblxuICBpZiAoZXZlbnRzKSB7XG4gICAgdmFyIGV2bGlzdGVuZXIgPSBldmVudHNbdHlwZV07XG5cbiAgICBpZiAodHlwZW9mIGV2bGlzdGVuZXIgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgIHJldHVybiAxO1xuICAgIH0gZWxzZSBpZiAoZXZsaXN0ZW5lcikge1xuICAgICAgcmV0dXJuIGV2bGlzdGVuZXIubGVuZ3RoO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiAwO1xufVxuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLmV2ZW50TmFtZXMgPSBmdW5jdGlvbiBldmVudE5hbWVzKCkge1xuICByZXR1cm4gdGhpcy5fZXZlbnRzQ291bnQgPiAwID8gUmVmbGVjdC5vd25LZXlzKHRoaXMuX2V2ZW50cykgOiBbXTtcbn07XG5cbi8vIEFib3V0IDEuNXggZmFzdGVyIHRoYW4gdGhlIHR3by1hcmcgdmVyc2lvbiBvZiBBcnJheSNzcGxpY2UoKS5cbmZ1bmN0aW9uIHNwbGljZU9uZShsaXN0LCBpbmRleCkge1xuICBmb3IgKHZhciBpID0gaW5kZXgsIGsgPSBpICsgMSwgbiA9IGxpc3QubGVuZ3RoOyBrIDwgbjsgaSArPSAxLCBrICs9IDEpXG4gICAgbGlzdFtpXSA9IGxpc3Rba107XG4gIGxpc3QucG9wKCk7XG59XG5cbmZ1bmN0aW9uIGFycmF5Q2xvbmUoYXJyLCBuKSB7XG4gIHZhciBjb3B5ID0gbmV3IEFycmF5KG4pO1xuICBmb3IgKHZhciBpID0gMDsgaSA8IG47ICsraSlcbiAgICBjb3B5W2ldID0gYXJyW2ldO1xuICByZXR1cm4gY29weTtcbn1cblxuZnVuY3Rpb24gdW53cmFwTGlzdGVuZXJzKGFycikge1xuICB2YXIgcmV0ID0gbmV3IEFycmF5KGFyci5sZW5ndGgpO1xuICBmb3IgKHZhciBpID0gMDsgaSA8IHJldC5sZW5ndGg7ICsraSkge1xuICAgIHJldFtpXSA9IGFycltpXS5saXN0ZW5lciB8fCBhcnJbaV07XG4gIH1cbiAgcmV0dXJuIHJldDtcbn1cblxuZnVuY3Rpb24gb2JqZWN0Q3JlYXRlUG9seWZpbGwocHJvdG8pIHtcbiAgdmFyIEYgPSBmdW5jdGlvbigpIHt9O1xuICBGLnByb3RvdHlwZSA9IHByb3RvO1xuICByZXR1cm4gbmV3IEY7XG59XG5mdW5jdGlvbiBvYmplY3RLZXlzUG9seWZpbGwob2JqKSB7XG4gIHZhciBrZXlzID0gW107XG4gIGZvciAodmFyIGsgaW4gb2JqKSBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKG9iaiwgaykpIHtcbiAgICBrZXlzLnB1c2goayk7XG4gIH1cbiAgcmV0dXJuIGs7XG59XG5mdW5jdGlvbiBmdW5jdGlvbkJpbmRQb2x5ZmlsbChjb250ZXh0KSB7XG4gIHZhciBmbiA9IHRoaXM7XG4gIHJldHVybiBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIGZuLmFwcGx5KGNvbnRleHQsIGFyZ3VtZW50cyk7XG4gIH07XG59XG4iLCIvKiBqc2hpbnQgbm9kZTogdHJ1ZSAqL1xuJ3VzZSBzdHJpY3QnO1xuXG52YXIgbm9ybWFsaWNlID0gcmVxdWlyZSgnbm9ybWFsaWNlJyk7XG5cbi8qKlxuICAjIGZyZWVpY2VcblxuICBUaGUgYGZyZWVpY2VgIG1vZHVsZSBpcyBhIHNpbXBsZSB3YXkgb2YgZ2V0dGluZyByYW5kb20gU1RVTiBvciBUVVJOIHNlcnZlclxuICBmb3IgeW91ciBXZWJSVEMgYXBwbGljYXRpb24uICBUaGUgbGlzdCBvZiBzZXJ2ZXJzIChqdXN0IFNUVU4gYXQgdGhpcyBzdGFnZSlcbiAgd2VyZSBzb3VyY2VkIGZyb20gdGhpcyBbZ2lzdF0oaHR0cHM6Ly9naXN0LmdpdGh1Yi5jb20venppdW5pLzM3NDE5MzMpLlxuXG4gICMjIEV4YW1wbGUgVXNlXG5cbiAgVGhlIGZvbGxvd2luZyBkZW1vbnN0cmF0ZXMgaG93IHlvdSBjYW4gdXNlIGBmcmVlaWNlYCB3aXRoXG4gIFtydGMtcXVpY2tjb25uZWN0XShodHRwczovL2dpdGh1Yi5jb20vcnRjLWlvL3J0Yy1xdWlja2Nvbm5lY3QpOlxuXG4gIDw8PCBleGFtcGxlcy9xdWlja2Nvbm5lY3QuanNcblxuICBBcyB0aGUgYGZyZWVpY2VgIG1vZHVsZSBnZW5lcmF0ZXMgaWNlIHNlcnZlcnMgaW4gYSBsaXN0IGNvbXBsaWFudCB3aXRoIHRoZVxuICBXZWJSVEMgc3BlYyB5b3Ugd2lsbCBiZSBhYmxlIHRvIHVzZSBpdCB3aXRoIHJhdyBgUlRDUGVlckNvbm5lY3Rpb25gXG4gIGNvbnN0cnVjdG9ycyBhbmQgb3RoZXIgV2ViUlRDIGxpYnJhcmllcy5cblxuICAjIyBIZXksIGRvbid0IHVzZSBteSBTVFVOL1RVUk4gc2VydmVyIVxuXG4gIElmIGZvciBzb21lIHJlYXNvbiB5b3VyIGZyZWUgU1RVTiBvciBUVVJOIHNlcnZlciBlbmRzIHVwIGluIHRoZVxuICBsaXN0IG9mIHNlcnZlcnMgKFtzdHVuXShodHRwczovL2dpdGh1Yi5jb20vRGFtb25PZWhsbWFuL2ZyZWVpY2UvYmxvYi9tYXN0ZXIvc3R1bi5qc29uKSBvclxuICBbdHVybl0oaHR0cHM6Ly9naXRodWIuY29tL0RhbW9uT2VobG1hbi9mcmVlaWNlL2Jsb2IvbWFzdGVyL3R1cm4uanNvbikpXG4gIHRoYXQgaXMgdXNlZCBpbiB0aGlzIG1vZHVsZSwgeW91IGNhbiBmZWVsXG4gIGZyZWUgdG8gb3BlbiBhbiBpc3N1ZSBvbiB0aGlzIHJlcG9zaXRvcnkgYW5kIHRob3NlIHNlcnZlcnMgd2lsbCBiZSByZW1vdmVkXG4gIHdpdGhpbiAyNCBob3VycyAob3Igc29vbmVyKS4gIFRoaXMgaXMgdGhlIHF1aWNrZXN0IGFuZCBwcm9iYWJseSB0aGUgbW9zdFxuICBwb2xpdGUgd2F5IHRvIGhhdmUgc29tZXRoaW5nIHJlbW92ZWQgKGFuZCBwcm92aWRlcyB1cyBzb21lIHZpc2liaWxpdHlcbiAgaWYgc29tZW9uZSBvcGVucyBhIHB1bGwgcmVxdWVzdCByZXF1ZXN0aW5nIHRoYXQgYSBzZXJ2ZXIgaXMgYWRkZWQpLlxuXG4gICMjIFBsZWFzZSBhZGQgbXkgc2VydmVyIVxuXG4gIElmIHlvdSBoYXZlIGEgc2VydmVyIHRoYXQgeW91IHdpc2ggdG8gYWRkIHRvIHRoZSBsaXN0LCB0aGF0J3MgYXdlc29tZSEgSSdtXG4gIHN1cmUgSSBzcGVhayBvbiBiZWhhbGYgb2YgYSB3aG9sZSBwaWxlIG9mIFdlYlJUQyBkZXZlbG9wZXJzIHdobyBzYXkgdGhhbmtzLlxuICBUbyBnZXQgaXQgaW50byB0aGUgbGlzdCwgZmVlbCBmcmVlIHRvIGVpdGhlciBvcGVuIGEgcHVsbCByZXF1ZXN0IG9yIGlmIHlvdVxuICBmaW5kIHRoYXQgcHJvY2VzcyBhIGJpdCBkYXVudGluZyB0aGVuIGp1c3QgY3JlYXRlIGFuIGlzc3VlIHJlcXVlc3RpbmdcbiAgdGhlIGFkZGl0aW9uIG9mIHRoZSBzZXJ2ZXIgKG1ha2Ugc3VyZSB5b3UgcHJvdmlkZSBhbGwgdGhlIGRldGFpbHMsIGFuZCBpZlxuICB5b3UgaGF2ZSBhIFRlcm1zIG9mIFNlcnZpY2UgdGhlbiBpbmNsdWRpbmcgdGhhdCBpbiB0aGUgUFIvaXNzdWUgd291bGQgYmVcbiAgYXdlc29tZSkuXG5cbiAgIyMgSSBrbm93IG9mIGEgZnJlZSBzZXJ2ZXIsIGNhbiBJIGFkZCBpdD9cblxuICBTdXJlLCBpZiB5b3UgZG8geW91ciBob21ld29yayBhbmQgbWFrZSBzdXJlIGl0IGlzIG9rIHRvIHVzZSAoSSdtIGN1cnJlbnRseVxuICBpbiB0aGUgcHJvY2VzcyBvZiByZXZpZXdpbmcgdGhlIHRlcm1zIG9mIHRob3NlIFNUVU4gc2VydmVycyBpbmNsdWRlZCBmcm9tXG4gIHRoZSBvcmlnaW5hbCBsaXN0KS4gIElmIGl0J3Mgb2sgdG8gZ28sIHRoZW4gcGxlYXNlIHNlZSB0aGUgcHJldmlvdXMgZW50cnlcbiAgZm9yIGhvdyB0byBhZGQgaXQuXG5cbiAgIyMgQ3VycmVudCBMaXN0IG9mIFNlcnZlcnNcblxuICAqIGN1cnJlbnQgYXMgYXQgdGhlIHRpbWUgb2YgbGFzdCBgUkVBRE1FLm1kYCBmaWxlIGdlbmVyYXRpb25cblxuICAjIyMgU1RVTlxuXG4gIDw8PCBzdHVuLmpzb25cblxuICAjIyMgVFVSTlxuXG4gIDw8PCB0dXJuLmpzb25cblxuKiovXG5cbnZhciBmcmVlaWNlID0gbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihvcHRzKSB7XG4gIC8vIGlmIGEgbGlzdCBvZiBzZXJ2ZXJzIGhhcyBiZWVuIHByb3ZpZGVkLCB0aGVuIHVzZSBpdCBpbnN0ZWFkIG9mIGRlZmF1bHRzXG4gIHZhciBzZXJ2ZXJzID0ge1xuICAgIHN0dW46IChvcHRzIHx8IHt9KS5zdHVuIHx8IHJlcXVpcmUoJy4vc3R1bi5qc29uJyksXG4gICAgdHVybjogKG9wdHMgfHwge30pLnR1cm4gfHwgcmVxdWlyZSgnLi90dXJuLmpzb24nKVxuICB9O1xuXG4gIHZhciBzdHVuQ291bnQgPSAob3B0cyB8fCB7fSkuc3R1bkNvdW50IHx8IDI7XG4gIHZhciB0dXJuQ291bnQgPSAob3B0cyB8fCB7fSkudHVybkNvdW50IHx8IDA7XG4gIHZhciBzZWxlY3RlZDtcblxuICBmdW5jdGlvbiBnZXRTZXJ2ZXJzKHR5cGUsIGNvdW50KSB7XG4gICAgdmFyIG91dCA9IFtdO1xuICAgIHZhciBpbnB1dCA9IFtdLmNvbmNhdChzZXJ2ZXJzW3R5cGVdKTtcbiAgICB2YXIgaWR4O1xuXG4gICAgd2hpbGUgKGlucHV0Lmxlbmd0aCAmJiBvdXQubGVuZ3RoIDwgY291bnQpIHtcbiAgICAgIGlkeCA9IChNYXRoLnJhbmRvbSgpICogaW5wdXQubGVuZ3RoKSB8IDA7XG4gICAgICBvdXQgPSBvdXQuY29uY2F0KGlucHV0LnNwbGljZShpZHgsIDEpKTtcbiAgICB9XG5cbiAgICByZXR1cm4gb3V0Lm1hcChmdW5jdGlvbih1cmwpIHtcbiAgICAgICAgLy9JZiBpdCdzIGEgbm90IGEgc3RyaW5nLCBkb24ndCB0cnkgdG8gXCJub3JtYWxpY2VcIiBpdCBvdGhlcndpc2UgdXNpbmcgdHlwZTp1cmwgd2lsbCBzY3JldyBpdCB1cFxuICAgICAgICBpZiAoKHR5cGVvZiB1cmwgIT09ICdzdHJpbmcnKSAmJiAoISAodXJsIGluc3RhbmNlb2YgU3RyaW5nKSkpIHtcbiAgICAgICAgICAgIHJldHVybiB1cmw7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gbm9ybWFsaWNlKHR5cGUgKyAnOicgKyB1cmwpO1xuICAgICAgICB9XG4gICAgfSk7XG4gIH1cblxuICAvLyBhZGQgc3R1biBzZXJ2ZXJzXG4gIHNlbGVjdGVkID0gW10uY29uY2F0KGdldFNlcnZlcnMoJ3N0dW4nLCBzdHVuQ291bnQpKTtcblxuICBpZiAodHVybkNvdW50KSB7XG4gICAgc2VsZWN0ZWQgPSBzZWxlY3RlZC5jb25jYXQoZ2V0U2VydmVycygndHVybicsIHR1cm5Db3VudCkpO1xuICB9XG5cbiAgcmV0dXJuIHNlbGVjdGVkO1xufTtcbiIsIm1vZHVsZS5leHBvcnRzPVtcbiAgXCJzdHVuLmwuZ29vZ2xlLmNvbToxOTMwMlwiLFxuICBcInN0dW4xLmwuZ29vZ2xlLmNvbToxOTMwMlwiLFxuICBcInN0dW4yLmwuZ29vZ2xlLmNvbToxOTMwMlwiLFxuICBcInN0dW4zLmwuZ29vZ2xlLmNvbToxOTMwMlwiLFxuICBcInN0dW40LmwuZ29vZ2xlLmNvbToxOTMwMlwiLFxuICBcInN0dW4uZWtpZ2EubmV0XCIsXG4gIFwic3R1bi5pZGVhc2lwLmNvbVwiLFxuICBcInN0dW4uc2NobHVuZC5kZVwiLFxuICBcInN0dW4uc3R1bnByb3RvY29sLm9yZzozNDc4XCIsXG4gIFwic3R1bi52b2lwYXJvdW5kLmNvbVwiLFxuICBcInN0dW4udm9pcGJ1c3Rlci5jb21cIixcbiAgXCJzdHVuLnZvaXBzdHVudC5jb21cIixcbiAgXCJzdHVuLnZveGdyYXRpYS5vcmdcIixcbiAgXCJzdHVuLnNlcnZpY2VzLm1vemlsbGEuY29tXCJcbl1cbiIsIm1vZHVsZS5leHBvcnRzPVtdXG4iLCJ2YXIgV2lsZEVtaXR0ZXIgPSByZXF1aXJlKCd3aWxkZW1pdHRlcicpO1xuXG5mdW5jdGlvbiBnZXRNYXhWb2x1bWUgKGFuYWx5c2VyLCBmZnRCaW5zKSB7XG4gIHZhciBtYXhWb2x1bWUgPSAtSW5maW5pdHk7XG4gIGFuYWx5c2VyLmdldEZsb2F0RnJlcXVlbmN5RGF0YShmZnRCaW5zKTtcblxuICBmb3IodmFyIGk9NCwgaWk9ZmZ0Qmlucy5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7XG4gICAgaWYgKGZmdEJpbnNbaV0gPiBtYXhWb2x1bWUgJiYgZmZ0Qmluc1tpXSA8IDApIHtcbiAgICAgIG1heFZvbHVtZSA9IGZmdEJpbnNbaV07XG4gICAgfVxuICB9O1xuXG4gIHJldHVybiBtYXhWb2x1bWU7XG59XG5cblxudmFyIGF1ZGlvQ29udGV4dFR5cGU7XG5pZiAodHlwZW9mIHdpbmRvdyAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgYXVkaW9Db250ZXh0VHlwZSA9IHdpbmRvdy5BdWRpb0NvbnRleHQgfHwgd2luZG93LndlYmtpdEF1ZGlvQ29udGV4dDtcbn1cbi8vIHVzZSBhIHNpbmdsZSBhdWRpbyBjb250ZXh0IGR1ZSB0byBoYXJkd2FyZSBsaW1pdHNcbnZhciBhdWRpb0NvbnRleHQgPSBudWxsO1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihzdHJlYW0sIG9wdGlvbnMpIHtcbiAgdmFyIGhhcmtlciA9IG5ldyBXaWxkRW1pdHRlcigpO1xuXG5cbiAgLy8gbWFrZSBpdCBub3QgYnJlYWsgaW4gbm9uLXN1cHBvcnRlZCBicm93c2Vyc1xuICBpZiAoIWF1ZGlvQ29udGV4dFR5cGUpIHJldHVybiBoYXJrZXI7XG5cbiAgLy9Db25maWdcbiAgdmFyIG9wdGlvbnMgPSBvcHRpb25zIHx8IHt9LFxuICAgICAgc21vb3RoaW5nID0gKG9wdGlvbnMuc21vb3RoaW5nIHx8IDAuMSksXG4gICAgICBpbnRlcnZhbCA9IChvcHRpb25zLmludGVydmFsIHx8IDUwKSxcbiAgICAgIHRocmVzaG9sZCA9IG9wdGlvbnMudGhyZXNob2xkLFxuICAgICAgcGxheSA9IG9wdGlvbnMucGxheSxcbiAgICAgIGhpc3RvcnkgPSBvcHRpb25zLmhpc3RvcnkgfHwgMTAsXG4gICAgICBydW5uaW5nID0gdHJ1ZTtcblxuICAvL1NldHVwIEF1ZGlvIENvbnRleHRcbiAgaWYgKCFhdWRpb0NvbnRleHQpIHtcbiAgICBhdWRpb0NvbnRleHQgPSBuZXcgYXVkaW9Db250ZXh0VHlwZSgpO1xuICB9XG4gIHZhciBzb3VyY2VOb2RlLCBmZnRCaW5zLCBhbmFseXNlcjtcblxuICBhbmFseXNlciA9IGF1ZGlvQ29udGV4dC5jcmVhdGVBbmFseXNlcigpO1xuICBhbmFseXNlci5mZnRTaXplID0gNTEyO1xuICBhbmFseXNlci5zbW9vdGhpbmdUaW1lQ29uc3RhbnQgPSBzbW9vdGhpbmc7XG4gIGZmdEJpbnMgPSBuZXcgRmxvYXQzMkFycmF5KGFuYWx5c2VyLmZyZXF1ZW5jeUJpbkNvdW50KTtcblxuICBpZiAoc3RyZWFtLmpxdWVyeSkgc3RyZWFtID0gc3RyZWFtWzBdO1xuICBpZiAoc3RyZWFtIGluc3RhbmNlb2YgSFRNTEF1ZGlvRWxlbWVudCB8fCBzdHJlYW0gaW5zdGFuY2VvZiBIVE1MVmlkZW9FbGVtZW50KSB7XG4gICAgLy9BdWRpbyBUYWdcbiAgICBzb3VyY2VOb2RlID0gYXVkaW9Db250ZXh0LmNyZWF0ZU1lZGlhRWxlbWVudFNvdXJjZShzdHJlYW0pO1xuICAgIGlmICh0eXBlb2YgcGxheSA9PT0gJ3VuZGVmaW5lZCcpIHBsYXkgPSB0cnVlO1xuICAgIHRocmVzaG9sZCA9IHRocmVzaG9sZCB8fCAtNTA7XG4gIH0gZWxzZSB7XG4gICAgLy9XZWJSVEMgU3RyZWFtXG4gICAgc291cmNlTm9kZSA9IGF1ZGlvQ29udGV4dC5jcmVhdGVNZWRpYVN0cmVhbVNvdXJjZShzdHJlYW0pO1xuICAgIHRocmVzaG9sZCA9IHRocmVzaG9sZCB8fCAtNTA7XG4gIH1cblxuICBzb3VyY2VOb2RlLmNvbm5lY3QoYW5hbHlzZXIpO1xuICBpZiAocGxheSkgYW5hbHlzZXIuY29ubmVjdChhdWRpb0NvbnRleHQuZGVzdGluYXRpb24pO1xuXG4gIGhhcmtlci5zcGVha2luZyA9IGZhbHNlO1xuXG4gIGhhcmtlci5zdXNwZW5kID0gZnVuY3Rpb24oKSB7XG4gICAgYXVkaW9Db250ZXh0LnN1c3BlbmQoKTtcbiAgfVxuICBoYXJrZXIucmVzdW1lID0gZnVuY3Rpb24oKSB7XG4gICAgYXVkaW9Db250ZXh0LnJlc3VtZSgpO1xuICB9XG4gIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShoYXJrZXIsICdzdGF0ZScsIHsgZ2V0OiBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gYXVkaW9Db250ZXh0LnN0YXRlO1xuICB9fSk7XG4gIGF1ZGlvQ29udGV4dC5vbnN0YXRlY2hhbmdlID0gZnVuY3Rpb24oKSB7XG4gICAgaGFya2VyLmVtaXQoJ3N0YXRlX2NoYW5nZScsIGF1ZGlvQ29udGV4dC5zdGF0ZSk7XG4gIH1cblxuICBoYXJrZXIuc2V0VGhyZXNob2xkID0gZnVuY3Rpb24odCkge1xuICAgIHRocmVzaG9sZCA9IHQ7XG4gIH07XG5cbiAgaGFya2VyLnNldEludGVydmFsID0gZnVuY3Rpb24oaSkge1xuICAgIGludGVydmFsID0gaTtcbiAgfTtcblxuICBoYXJrZXIuc3RvcCA9IGZ1bmN0aW9uKCkge1xuICAgIHJ1bm5pbmcgPSBmYWxzZTtcbiAgICBoYXJrZXIuZW1pdCgndm9sdW1lX2NoYW5nZScsIC0xMDAsIHRocmVzaG9sZCk7XG4gICAgaWYgKGhhcmtlci5zcGVha2luZykge1xuICAgICAgaGFya2VyLnNwZWFraW5nID0gZmFsc2U7XG4gICAgICBoYXJrZXIuZW1pdCgnc3RvcHBlZF9zcGVha2luZycpO1xuICAgIH1cbiAgICBhbmFseXNlci5kaXNjb25uZWN0KCk7XG4gICAgc291cmNlTm9kZS5kaXNjb25uZWN0KCk7XG4gIH07XG4gIGhhcmtlci5zcGVha2luZ0hpc3RvcnkgPSBbXTtcbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBoaXN0b3J5OyBpKyspIHtcbiAgICAgIGhhcmtlci5zcGVha2luZ0hpc3RvcnkucHVzaCgwKTtcbiAgfVxuXG4gIC8vIFBvbGwgdGhlIGFuYWx5c2VyIG5vZGUgdG8gZGV0ZXJtaW5lIGlmIHNwZWFraW5nXG4gIC8vIGFuZCBlbWl0IGV2ZW50cyBpZiBjaGFuZ2VkXG4gIHZhciBsb29wZXIgPSBmdW5jdGlvbigpIHtcbiAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uKCkge1xuXG4gICAgICAvL2NoZWNrIGlmIHN0b3AgaGFzIGJlZW4gY2FsbGVkXG4gICAgICBpZighcnVubmluZykge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIHZhciBjdXJyZW50Vm9sdW1lID0gZ2V0TWF4Vm9sdW1lKGFuYWx5c2VyLCBmZnRCaW5zKTtcblxuICAgICAgaGFya2VyLmVtaXQoJ3ZvbHVtZV9jaGFuZ2UnLCBjdXJyZW50Vm9sdW1lLCB0aHJlc2hvbGQpO1xuXG4gICAgICB2YXIgaGlzdG9yeSA9IDA7XG4gICAgICBpZiAoY3VycmVudFZvbHVtZSA+IHRocmVzaG9sZCAmJiAhaGFya2VyLnNwZWFraW5nKSB7XG4gICAgICAgIC8vIHRyaWdnZXIgcXVpY2tseSwgc2hvcnQgaGlzdG9yeVxuICAgICAgICBmb3IgKHZhciBpID0gaGFya2VyLnNwZWFraW5nSGlzdG9yeS5sZW5ndGggLSAzOyBpIDwgaGFya2VyLnNwZWFraW5nSGlzdG9yeS5sZW5ndGg7IGkrKykge1xuICAgICAgICAgIGhpc3RvcnkgKz0gaGFya2VyLnNwZWFraW5nSGlzdG9yeVtpXTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoaGlzdG9yeSA+PSAyKSB7XG4gICAgICAgICAgaGFya2VyLnNwZWFraW5nID0gdHJ1ZTtcbiAgICAgICAgICBoYXJrZXIuZW1pdCgnc3BlYWtpbmcnKTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIGlmIChjdXJyZW50Vm9sdW1lIDwgdGhyZXNob2xkICYmIGhhcmtlci5zcGVha2luZykge1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGhhcmtlci5zcGVha2luZ0hpc3RvcnkubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICBoaXN0b3J5ICs9IGhhcmtlci5zcGVha2luZ0hpc3RvcnlbaV07XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGhpc3RvcnkgPT0gMCkge1xuICAgICAgICAgIGhhcmtlci5zcGVha2luZyA9IGZhbHNlO1xuICAgICAgICAgIGhhcmtlci5lbWl0KCdzdG9wcGVkX3NwZWFraW5nJyk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGhhcmtlci5zcGVha2luZ0hpc3Rvcnkuc2hpZnQoKTtcbiAgICAgIGhhcmtlci5zcGVha2luZ0hpc3RvcnkucHVzaCgwICsgKGN1cnJlbnRWb2x1bWUgPiB0aHJlc2hvbGQpKTtcblxuICAgICAgbG9vcGVyKCk7XG4gICAgfSwgaW50ZXJ2YWwpO1xuICB9O1xuICBsb29wZXIoKTtcblxuXG4gIHJldHVybiBoYXJrZXI7XG59XG4iLCJpZiAodHlwZW9mIE9iamVjdC5jcmVhdGUgPT09ICdmdW5jdGlvbicpIHtcbiAgLy8gaW1wbGVtZW50YXRpb24gZnJvbSBzdGFuZGFyZCBub2RlLmpzICd1dGlsJyBtb2R1bGVcbiAgbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBpbmhlcml0cyhjdG9yLCBzdXBlckN0b3IpIHtcbiAgICBjdG9yLnN1cGVyXyA9IHN1cGVyQ3RvclxuICAgIGN0b3IucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShzdXBlckN0b3IucHJvdG90eXBlLCB7XG4gICAgICBjb25zdHJ1Y3Rvcjoge1xuICAgICAgICB2YWx1ZTogY3RvcixcbiAgICAgICAgZW51bWVyYWJsZTogZmFsc2UsXG4gICAgICAgIHdyaXRhYmxlOiB0cnVlLFxuICAgICAgICBjb25maWd1cmFibGU6IHRydWVcbiAgICAgIH1cbiAgICB9KTtcbiAgfTtcbn0gZWxzZSB7XG4gIC8vIG9sZCBzY2hvb2wgc2hpbSBmb3Igb2xkIGJyb3dzZXJzXG4gIG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gaW5oZXJpdHMoY3Rvciwgc3VwZXJDdG9yKSB7XG4gICAgY3Rvci5zdXBlcl8gPSBzdXBlckN0b3JcbiAgICB2YXIgVGVtcEN0b3IgPSBmdW5jdGlvbiAoKSB7fVxuICAgIFRlbXBDdG9yLnByb3RvdHlwZSA9IHN1cGVyQ3Rvci5wcm90b3R5cGVcbiAgICBjdG9yLnByb3RvdHlwZSA9IG5ldyBUZW1wQ3RvcigpXG4gICAgY3Rvci5wcm90b3R5cGUuY29uc3RydWN0b3IgPSBjdG9yXG4gIH1cbn1cbiIsIi8qKlxuICAjIG5vcm1hbGljZVxuXG4gIE5vcm1hbGl6ZSBhbiBpY2Ugc2VydmVyIGNvbmZpZ3VyYXRpb24gb2JqZWN0IChvciBwbGFpbiBvbGQgc3RyaW5nKSBpbnRvIGEgZm9ybWF0XG4gIHRoYXQgaXMgdXNhYmxlIGluIGFsbCBicm93c2VycyBzdXBwb3J0aW5nIFdlYlJUQy4gIFByaW1hcmlseSB0aGlzIG1vZHVsZSBpcyBkZXNpZ25lZFxuICB0byBoZWxwIHdpdGggdGhlIHRyYW5zaXRpb24gb2YgdGhlIGB1cmxgIGF0dHJpYnV0ZSBvZiB0aGUgY29uZmlndXJhdGlvbiBvYmplY3QgdG9cbiAgdGhlIGB1cmxzYCBhdHRyaWJ1dGUuXG5cbiAgIyMgRXhhbXBsZSBVc2FnZVxuXG4gIDw8PCBleGFtcGxlcy9zaW1wbGUuanNcblxuKiovXG5cbnZhciBwcm90b2NvbHMgPSBbXG4gICdzdHVuOicsXG4gICd0dXJuOidcbl07XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24oaW5wdXQpIHtcbiAgdmFyIHVybCA9IChpbnB1dCB8fCB7fSkudXJsIHx8IGlucHV0O1xuICB2YXIgcHJvdG9jb2w7XG4gIHZhciBwYXJ0cztcbiAgdmFyIG91dHB1dCA9IHt9O1xuXG4gIC8vIGlmIHdlIGRvbid0IGhhdmUgYSBzdHJpbmcgdXJsLCB0aGVuIGFsbG93IHRoZSBpbnB1dCB0byBwYXNzdGhyb3VnaFxuICBpZiAodHlwZW9mIHVybCAhPSAnc3RyaW5nJyAmJiAoISAodXJsIGluc3RhbmNlb2YgU3RyaW5nKSkpIHtcbiAgICByZXR1cm4gaW5wdXQ7XG4gIH1cblxuICAvLyB0cmltIHRoZSB1cmwgc3RyaW5nLCBhbmQgY29udmVydCB0byBhbiBhcnJheVxuICB1cmwgPSB1cmwudHJpbSgpO1xuXG4gIC8vIGlmIHRoZSBwcm90b2NvbCBpcyBub3Qga25vd24sIHRoZW4gcGFzc3Rocm91Z2hcbiAgcHJvdG9jb2wgPSBwcm90b2NvbHNbcHJvdG9jb2xzLmluZGV4T2YodXJsLnNsaWNlKDAsIDUpKV07XG4gIGlmICghIHByb3RvY29sKSB7XG4gICAgcmV0dXJuIGlucHV0O1xuICB9XG5cbiAgLy8gbm93IGxldCdzIGF0dGFjayB0aGUgcmVtYWluaW5nIHVybCBwYXJ0c1xuICB1cmwgPSB1cmwuc2xpY2UoNSk7XG4gIHBhcnRzID0gdXJsLnNwbGl0KCdAJyk7XG5cbiAgb3V0cHV0LnVzZXJuYW1lID0gaW5wdXQudXNlcm5hbWU7XG4gIG91dHB1dC5jcmVkZW50aWFsID0gaW5wdXQuY3JlZGVudGlhbDtcbiAgLy8gaWYgd2UgaGF2ZSBhbiBhdXRoZW50aWNhdGlvbiBwYXJ0LCB0aGVuIHNldCB0aGUgY3JlZGVudGlhbHNcbiAgaWYgKHBhcnRzLmxlbmd0aCA+IDEpIHtcbiAgICB1cmwgPSBwYXJ0c1sxXTtcbiAgICBwYXJ0cyA9IHBhcnRzWzBdLnNwbGl0KCc6Jyk7XG5cbiAgICAvLyBhZGQgdGhlIG91dHB1dCBjcmVkZW50aWFsIGFuZCB1c2VybmFtZVxuICAgIG91dHB1dC51c2VybmFtZSA9IHBhcnRzWzBdO1xuICAgIG91dHB1dC5jcmVkZW50aWFsID0gKGlucHV0IHx8IHt9KS5jcmVkZW50aWFsIHx8IHBhcnRzWzFdIHx8ICcnO1xuICB9XG5cbiAgb3V0cHV0LnVybCA9IHByb3RvY29sICsgdXJsO1xuICBvdXRwdXQudXJscyA9IFsgb3V0cHV0LnVybCBdO1xuXG4gIHJldHVybiBvdXRwdXQ7XG59O1xuIiwiLyohXG4gKiBQbGF0Zm9ybS5qcyA8aHR0cHM6Ly9tdGhzLmJlL3BsYXRmb3JtPlxuICogQ29weXJpZ2h0IDIwMTQtMjAxOCBCZW5qYW1pbiBUYW4gPGh0dHBzOi8vYm5qbW50NG4ubm93LnNoLz5cbiAqIENvcHlyaWdodCAyMDExLTIwMTMgSm9obi1EYXZpZCBEYWx0b24gPGh0dHA6Ly9hbGx5b3VjYW5sZWV0LmNvbS8+XG4gKiBBdmFpbGFibGUgdW5kZXIgTUlUIGxpY2Vuc2UgPGh0dHBzOi8vbXRocy5iZS9taXQ+XG4gKi9cbjsoZnVuY3Rpb24oKSB7XG4gICd1c2Ugc3RyaWN0JztcblxuICAvKiogVXNlZCB0byBkZXRlcm1pbmUgaWYgdmFsdWVzIGFyZSBvZiB0aGUgbGFuZ3VhZ2UgdHlwZSBgT2JqZWN0YC4gKi9cbiAgdmFyIG9iamVjdFR5cGVzID0ge1xuICAgICdmdW5jdGlvbic6IHRydWUsXG4gICAgJ29iamVjdCc6IHRydWVcbiAgfTtcblxuICAvKiogVXNlZCBhcyBhIHJlZmVyZW5jZSB0byB0aGUgZ2xvYmFsIG9iamVjdC4gKi9cbiAgdmFyIHJvb3QgPSAob2JqZWN0VHlwZXNbdHlwZW9mIHdpbmRvd10gJiYgd2luZG93KSB8fCB0aGlzO1xuXG4gIC8qKiBCYWNrdXAgcG9zc2libGUgZ2xvYmFsIG9iamVjdC4gKi9cbiAgdmFyIG9sZFJvb3QgPSByb290O1xuXG4gIC8qKiBEZXRlY3QgZnJlZSB2YXJpYWJsZSBgZXhwb3J0c2AuICovXG4gIHZhciBmcmVlRXhwb3J0cyA9IG9iamVjdFR5cGVzW3R5cGVvZiBleHBvcnRzXSAmJiBleHBvcnRzO1xuXG4gIC8qKiBEZXRlY3QgZnJlZSB2YXJpYWJsZSBgbW9kdWxlYC4gKi9cbiAgdmFyIGZyZWVNb2R1bGUgPSBvYmplY3RUeXBlc1t0eXBlb2YgbW9kdWxlXSAmJiBtb2R1bGUgJiYgIW1vZHVsZS5ub2RlVHlwZSAmJiBtb2R1bGU7XG5cbiAgLyoqIERldGVjdCBmcmVlIHZhcmlhYmxlIGBnbG9iYWxgIGZyb20gTm9kZS5qcyBvciBCcm93c2VyaWZpZWQgY29kZSBhbmQgdXNlIGl0IGFzIGByb290YC4gKi9cbiAgdmFyIGZyZWVHbG9iYWwgPSBmcmVlRXhwb3J0cyAmJiBmcmVlTW9kdWxlICYmIHR5cGVvZiBnbG9iYWwgPT0gJ29iamVjdCcgJiYgZ2xvYmFsO1xuICBpZiAoZnJlZUdsb2JhbCAmJiAoZnJlZUdsb2JhbC5nbG9iYWwgPT09IGZyZWVHbG9iYWwgfHwgZnJlZUdsb2JhbC53aW5kb3cgPT09IGZyZWVHbG9iYWwgfHwgZnJlZUdsb2JhbC5zZWxmID09PSBmcmVlR2xvYmFsKSkge1xuICAgIHJvb3QgPSBmcmVlR2xvYmFsO1xuICB9XG5cbiAgLyoqXG4gICAqIFVzZWQgYXMgdGhlIG1heGltdW0gbGVuZ3RoIG9mIGFuIGFycmF5LWxpa2Ugb2JqZWN0LlxuICAgKiBTZWUgdGhlIFtFUzYgc3BlY10oaHR0cDovL3Blb3BsZS5tb3ppbGxhLm9yZy9+am9yZW5kb3JmZi9lczYtZHJhZnQuaHRtbCNzZWMtdG9sZW5ndGgpXG4gICAqIGZvciBtb3JlIGRldGFpbHMuXG4gICAqL1xuICB2YXIgbWF4U2FmZUludGVnZXIgPSBNYXRoLnBvdygyLCA1MykgLSAxO1xuXG4gIC8qKiBSZWd1bGFyIGV4cHJlc3Npb24gdG8gZGV0ZWN0IE9wZXJhLiAqL1xuICB2YXIgcmVPcGVyYSA9IC9cXGJPcGVyYS87XG5cbiAgLyoqIFBvc3NpYmxlIGdsb2JhbCBvYmplY3QuICovXG4gIHZhciB0aGlzQmluZGluZyA9IHRoaXM7XG5cbiAgLyoqIFVzZWQgZm9yIG5hdGl2ZSBtZXRob2QgcmVmZXJlbmNlcy4gKi9cbiAgdmFyIG9iamVjdFByb3RvID0gT2JqZWN0LnByb3RvdHlwZTtcblxuICAvKiogVXNlZCB0byBjaGVjayBmb3Igb3duIHByb3BlcnRpZXMgb2YgYW4gb2JqZWN0LiAqL1xuICB2YXIgaGFzT3duUHJvcGVydHkgPSBvYmplY3RQcm90by5oYXNPd25Qcm9wZXJ0eTtcblxuICAvKiogVXNlZCB0byByZXNvbHZlIHRoZSBpbnRlcm5hbCBgW1tDbGFzc11dYCBvZiB2YWx1ZXMuICovXG4gIHZhciB0b1N0cmluZyA9IG9iamVjdFByb3RvLnRvU3RyaW5nO1xuXG4gIC8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuXG4gIC8qKlxuICAgKiBDYXBpdGFsaXplcyBhIHN0cmluZyB2YWx1ZS5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtzdHJpbmd9IHN0cmluZyBUaGUgc3RyaW5nIHRvIGNhcGl0YWxpemUuXG4gICAqIEByZXR1cm5zIHtzdHJpbmd9IFRoZSBjYXBpdGFsaXplZCBzdHJpbmcuXG4gICAqL1xuICBmdW5jdGlvbiBjYXBpdGFsaXplKHN0cmluZykge1xuICAgIHN0cmluZyA9IFN0cmluZyhzdHJpbmcpO1xuICAgIHJldHVybiBzdHJpbmcuY2hhckF0KDApLnRvVXBwZXJDYXNlKCkgKyBzdHJpbmcuc2xpY2UoMSk7XG4gIH1cblxuICAvKipcbiAgICogQSB1dGlsaXR5IGZ1bmN0aW9uIHRvIGNsZWFuIHVwIHRoZSBPUyBuYW1lLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gb3MgVGhlIE9TIG5hbWUgdG8gY2xlYW4gdXAuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbcGF0dGVybl0gQSBgUmVnRXhwYCBwYXR0ZXJuIG1hdGNoaW5nIHRoZSBPUyBuYW1lLlxuICAgKiBAcGFyYW0ge3N0cmluZ30gW2xhYmVsXSBBIGxhYmVsIGZvciB0aGUgT1MuXG4gICAqL1xuICBmdW5jdGlvbiBjbGVhbnVwT1Mob3MsIHBhdHRlcm4sIGxhYmVsKSB7XG4gICAgLy8gUGxhdGZvcm0gdG9rZW5zIGFyZSBkZWZpbmVkIGF0OlxuICAgIC8vIGh0dHA6Ly9tc2RuLm1pY3Jvc29mdC5jb20vZW4tdXMvbGlicmFyeS9tczUzNzUwMyhWUy44NSkuYXNweFxuICAgIC8vIGh0dHA6Ly93ZWIuYXJjaGl2ZS5vcmcvd2ViLzIwMDgxMTIyMDUzOTUwL2h0dHA6Ly9tc2RuLm1pY3Jvc29mdC5jb20vZW4tdXMvbGlicmFyeS9tczUzNzUwMyhWUy44NSkuYXNweFxuICAgIHZhciBkYXRhID0ge1xuICAgICAgJzEwLjAnOiAnMTAnLFxuICAgICAgJzYuNCc6ICAnMTAgVGVjaG5pY2FsIFByZXZpZXcnLFxuICAgICAgJzYuMyc6ICAnOC4xJyxcbiAgICAgICc2LjInOiAgJzgnLFxuICAgICAgJzYuMSc6ICAnU2VydmVyIDIwMDggUjIgLyA3JyxcbiAgICAgICc2LjAnOiAgJ1NlcnZlciAyMDA4IC8gVmlzdGEnLFxuICAgICAgJzUuMic6ICAnU2VydmVyIDIwMDMgLyBYUCA2NC1iaXQnLFxuICAgICAgJzUuMSc6ICAnWFAnLFxuICAgICAgJzUuMDEnOiAnMjAwMCBTUDEnLFxuICAgICAgJzUuMCc6ICAnMjAwMCcsXG4gICAgICAnNC4wJzogICdOVCcsXG4gICAgICAnNC45MCc6ICdNRSdcbiAgICB9O1xuICAgIC8vIERldGVjdCBXaW5kb3dzIHZlcnNpb24gZnJvbSBwbGF0Zm9ybSB0b2tlbnMuXG4gICAgaWYgKHBhdHRlcm4gJiYgbGFiZWwgJiYgL15XaW4vaS50ZXN0KG9zKSAmJiAhL15XaW5kb3dzIFBob25lIC9pLnRlc3Qob3MpICYmXG4gICAgICAgIChkYXRhID0gZGF0YVsvW1xcZC5dKyQvLmV4ZWMob3MpXSkpIHtcbiAgICAgIG9zID0gJ1dpbmRvd3MgJyArIGRhdGE7XG4gICAgfVxuICAgIC8vIENvcnJlY3QgY2hhcmFjdGVyIGNhc2UgYW5kIGNsZWFudXAgc3RyaW5nLlxuICAgIG9zID0gU3RyaW5nKG9zKTtcblxuICAgIGlmIChwYXR0ZXJuICYmIGxhYmVsKSB7XG4gICAgICBvcyA9IG9zLnJlcGxhY2UoUmVnRXhwKHBhdHRlcm4sICdpJyksIGxhYmVsKTtcbiAgICB9XG5cbiAgICBvcyA9IGZvcm1hdChcbiAgICAgIG9zLnJlcGxhY2UoLyBjZSQvaSwgJyBDRScpXG4gICAgICAgIC5yZXBsYWNlKC9cXGJocHcvaSwgJ3dlYicpXG4gICAgICAgIC5yZXBsYWNlKC9cXGJNYWNpbnRvc2hcXGIvLCAnTWFjIE9TJylcbiAgICAgICAgLnJlcGxhY2UoL19Qb3dlclBDXFxiL2ksICcgT1MnKVxuICAgICAgICAucmVwbGFjZSgvXFxiKE9TIFgpIFteIFxcZF0rL2ksICckMScpXG4gICAgICAgIC5yZXBsYWNlKC9cXGJNYWMgKE9TIFgpXFxiLywgJyQxJylcbiAgICAgICAgLnJlcGxhY2UoL1xcLyhcXGQpLywgJyAkMScpXG4gICAgICAgIC5yZXBsYWNlKC9fL2csICcuJylcbiAgICAgICAgLnJlcGxhY2UoLyg/OiBCZVBDfFsgLl0qZmNbIFxcZC5dKykkL2ksICcnKVxuICAgICAgICAucmVwbGFjZSgvXFxieDg2XFwuNjRcXGIvZ2ksICd4ODZfNjQnKVxuICAgICAgICAucmVwbGFjZSgvXFxiKFdpbmRvd3MgUGhvbmUpIE9TXFxiLywgJyQxJylcbiAgICAgICAgLnJlcGxhY2UoL1xcYihDaHJvbWUgT1MgXFx3KykgW1xcZC5dK1xcYi8sICckMScpXG4gICAgICAgIC5zcGxpdCgnIG9uICcpWzBdXG4gICAgKTtcblxuICAgIHJldHVybiBvcztcbiAgfVxuXG4gIC8qKlxuICAgKiBBbiBpdGVyYXRpb24gdXRpbGl0eSBmb3IgYXJyYXlzIGFuZCBvYmplY3RzLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge0FycmF5fE9iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gaXRlcmF0ZSBvdmVyLlxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBjYWxsYmFjayBUaGUgZnVuY3Rpb24gY2FsbGVkIHBlciBpdGVyYXRpb24uXG4gICAqL1xuICBmdW5jdGlvbiBlYWNoKG9iamVjdCwgY2FsbGJhY2spIHtcbiAgICB2YXIgaW5kZXggPSAtMSxcbiAgICAgICAgbGVuZ3RoID0gb2JqZWN0ID8gb2JqZWN0Lmxlbmd0aCA6IDA7XG5cbiAgICBpZiAodHlwZW9mIGxlbmd0aCA9PSAnbnVtYmVyJyAmJiBsZW5ndGggPiAtMSAmJiBsZW5ndGggPD0gbWF4U2FmZUludGVnZXIpIHtcbiAgICAgIHdoaWxlICgrK2luZGV4IDwgbGVuZ3RoKSB7XG4gICAgICAgIGNhbGxiYWNrKG9iamVjdFtpbmRleF0sIGluZGV4LCBvYmplY3QpO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBmb3JPd24ob2JqZWN0LCBjYWxsYmFjayk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFRyaW0gYW5kIGNvbmRpdGlvbmFsbHkgY2FwaXRhbGl6ZSBzdHJpbmcgdmFsdWVzLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gc3RyaW5nIFRoZSBzdHJpbmcgdG8gZm9ybWF0LlxuICAgKiBAcmV0dXJucyB7c3RyaW5nfSBUaGUgZm9ybWF0dGVkIHN0cmluZy5cbiAgICovXG4gIGZ1bmN0aW9uIGZvcm1hdChzdHJpbmcpIHtcbiAgICBzdHJpbmcgPSB0cmltKHN0cmluZyk7XG4gICAgcmV0dXJuIC9eKD86d2ViT1N8aSg/Ok9TfFApKS8udGVzdChzdHJpbmcpXG4gICAgICA/IHN0cmluZ1xuICAgICAgOiBjYXBpdGFsaXplKHN0cmluZyk7XG4gIH1cblxuICAvKipcbiAgICogSXRlcmF0ZXMgb3ZlciBhbiBvYmplY3QncyBvd24gcHJvcGVydGllcywgZXhlY3V0aW5nIHRoZSBgY2FsbGJhY2tgIGZvciBlYWNoLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gaXRlcmF0ZSBvdmVyLlxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBjYWxsYmFjayBUaGUgZnVuY3Rpb24gZXhlY3V0ZWQgcGVyIG93biBwcm9wZXJ0eS5cbiAgICovXG4gIGZ1bmN0aW9uIGZvck93bihvYmplY3QsIGNhbGxiYWNrKSB7XG4gICAgZm9yICh2YXIga2V5IGluIG9iamVjdCkge1xuICAgICAgaWYgKGhhc093blByb3BlcnR5LmNhbGwob2JqZWN0LCBrZXkpKSB7XG4gICAgICAgIGNhbGxiYWNrKG9iamVjdFtrZXldLCBrZXksIG9iamVjdCk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEdldHMgdGhlIGludGVybmFsIGBbW0NsYXNzXV1gIG9mIGEgdmFsdWUuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlLlxuICAgKiBAcmV0dXJucyB7c3RyaW5nfSBUaGUgYFtbQ2xhc3NdXWAuXG4gICAqL1xuICBmdW5jdGlvbiBnZXRDbGFzc09mKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlID09IG51bGxcbiAgICAgID8gY2FwaXRhbGl6ZSh2YWx1ZSlcbiAgICAgIDogdG9TdHJpbmcuY2FsbCh2YWx1ZSkuc2xpY2UoOCwgLTEpO1xuICB9XG5cbiAgLyoqXG4gICAqIEhvc3Qgb2JqZWN0cyBjYW4gcmV0dXJuIHR5cGUgdmFsdWVzIHRoYXQgYXJlIGRpZmZlcmVudCBmcm9tIHRoZWlyIGFjdHVhbFxuICAgKiBkYXRhIHR5cGUuIFRoZSBvYmplY3RzIHdlIGFyZSBjb25jZXJuZWQgd2l0aCB1c3VhbGx5IHJldHVybiBub24tcHJpbWl0aXZlXG4gICAqIHR5cGVzIG9mIFwib2JqZWN0XCIsIFwiZnVuY3Rpb25cIiwgb3IgXCJ1bmtub3duXCIuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7Kn0gb2JqZWN0IFRoZSBvd25lciBvZiB0aGUgcHJvcGVydHkuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBwcm9wZXJ0eSBUaGUgcHJvcGVydHkgdG8gY2hlY2suXG4gICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiB0aGUgcHJvcGVydHkgdmFsdWUgaXMgYSBub24tcHJpbWl0aXZlLCBlbHNlIGBmYWxzZWAuXG4gICAqL1xuICBmdW5jdGlvbiBpc0hvc3RUeXBlKG9iamVjdCwgcHJvcGVydHkpIHtcbiAgICB2YXIgdHlwZSA9IG9iamVjdCAhPSBudWxsID8gdHlwZW9mIG9iamVjdFtwcm9wZXJ0eV0gOiAnbnVtYmVyJztcbiAgICByZXR1cm4gIS9eKD86Ym9vbGVhbnxudW1iZXJ8c3RyaW5nfHVuZGVmaW5lZCkkLy50ZXN0KHR5cGUpICYmXG4gICAgICAodHlwZSA9PSAnb2JqZWN0JyA/ICEhb2JqZWN0W3Byb3BlcnR5XSA6IHRydWUpO1xuICB9XG5cbiAgLyoqXG4gICAqIFByZXBhcmVzIGEgc3RyaW5nIGZvciB1c2UgaW4gYSBgUmVnRXhwYCBieSBtYWtpbmcgaHlwaGVucyBhbmQgc3BhY2VzIG9wdGlvbmFsLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gc3RyaW5nIFRoZSBzdHJpbmcgdG8gcXVhbGlmeS5cbiAgICogQHJldHVybnMge3N0cmluZ30gVGhlIHF1YWxpZmllZCBzdHJpbmcuXG4gICAqL1xuICBmdW5jdGlvbiBxdWFsaWZ5KHN0cmluZykge1xuICAgIHJldHVybiBTdHJpbmcoc3RyaW5nKS5yZXBsYWNlKC8oWyAtXSkoPyEkKS9nLCAnJDE/Jyk7XG4gIH1cblxuICAvKipcbiAgICogQSBiYXJlLWJvbmVzIGBBcnJheSNyZWR1Y2VgIGxpa2UgdXRpbGl0eSBmdW5jdGlvbi5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIGl0ZXJhdGUgb3Zlci5cbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gY2FsbGJhY2sgVGhlIGZ1bmN0aW9uIGNhbGxlZCBwZXIgaXRlcmF0aW9uLlxuICAgKiBAcmV0dXJucyB7Kn0gVGhlIGFjY3VtdWxhdGVkIHJlc3VsdC5cbiAgICovXG4gIGZ1bmN0aW9uIHJlZHVjZShhcnJheSwgY2FsbGJhY2spIHtcbiAgICB2YXIgYWNjdW11bGF0b3IgPSBudWxsO1xuICAgIGVhY2goYXJyYXksIGZ1bmN0aW9uKHZhbHVlLCBpbmRleCkge1xuICAgICAgYWNjdW11bGF0b3IgPSBjYWxsYmFjayhhY2N1bXVsYXRvciwgdmFsdWUsIGluZGV4LCBhcnJheSk7XG4gICAgfSk7XG4gICAgcmV0dXJuIGFjY3VtdWxhdG9yO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlbW92ZXMgbGVhZGluZyBhbmQgdHJhaWxpbmcgd2hpdGVzcGFjZSBmcm9tIGEgc3RyaW5nLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gc3RyaW5nIFRoZSBzdHJpbmcgdG8gdHJpbS5cbiAgICogQHJldHVybnMge3N0cmluZ30gVGhlIHRyaW1tZWQgc3RyaW5nLlxuICAgKi9cbiAgZnVuY3Rpb24gdHJpbShzdHJpbmcpIHtcbiAgICByZXR1cm4gU3RyaW5nKHN0cmluZykucmVwbGFjZSgvXiArfCArJC9nLCAnJyk7XG4gIH1cblxuICAvKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cblxuICAvKipcbiAgICogQ3JlYXRlcyBhIG5ldyBwbGF0Zm9ybSBvYmplY3QuXG4gICAqXG4gICAqIEBtZW1iZXJPZiBwbGF0Zm9ybVxuICAgKiBAcGFyYW0ge09iamVjdHxzdHJpbmd9IFt1YT1uYXZpZ2F0b3IudXNlckFnZW50XSBUaGUgdXNlciBhZ2VudCBzdHJpbmcgb3JcbiAgICogIGNvbnRleHQgb2JqZWN0LlxuICAgKiBAcmV0dXJucyB7T2JqZWN0fSBBIHBsYXRmb3JtIG9iamVjdC5cbiAgICovXG4gIGZ1bmN0aW9uIHBhcnNlKHVhKSB7XG5cbiAgICAvKiogVGhlIGVudmlyb25tZW50IGNvbnRleHQgb2JqZWN0LiAqL1xuICAgIHZhciBjb250ZXh0ID0gcm9vdDtcblxuICAgIC8qKiBVc2VkIHRvIGZsYWcgd2hlbiBhIGN1c3RvbSBjb250ZXh0IGlzIHByb3ZpZGVkLiAqL1xuICAgIHZhciBpc0N1c3RvbUNvbnRleHQgPSB1YSAmJiB0eXBlb2YgdWEgPT0gJ29iamVjdCcgJiYgZ2V0Q2xhc3NPZih1YSkgIT0gJ1N0cmluZyc7XG5cbiAgICAvLyBKdWdnbGUgYXJndW1lbnRzLlxuICAgIGlmIChpc0N1c3RvbUNvbnRleHQpIHtcbiAgICAgIGNvbnRleHQgPSB1YTtcbiAgICAgIHVhID0gbnVsbDtcbiAgICB9XG5cbiAgICAvKiogQnJvd3NlciBuYXZpZ2F0b3Igb2JqZWN0LiAqL1xuICAgIHZhciBuYXYgPSBjb250ZXh0Lm5hdmlnYXRvciB8fCB7fTtcblxuICAgIC8qKiBCcm93c2VyIHVzZXIgYWdlbnQgc3RyaW5nLiAqL1xuICAgIHZhciB1c2VyQWdlbnQgPSBuYXYudXNlckFnZW50IHx8ICcnO1xuXG4gICAgdWEgfHwgKHVhID0gdXNlckFnZW50KTtcblxuICAgIC8qKiBVc2VkIHRvIGZsYWcgd2hlbiBgdGhpc0JpbmRpbmdgIGlzIHRoZSBbTW9kdWxlU2NvcGVdLiAqL1xuICAgIHZhciBpc01vZHVsZVNjb3BlID0gaXNDdXN0b21Db250ZXh0IHx8IHRoaXNCaW5kaW5nID09IG9sZFJvb3Q7XG5cbiAgICAvKiogVXNlZCB0byBkZXRlY3QgaWYgYnJvd3NlciBpcyBsaWtlIENocm9tZS4gKi9cbiAgICB2YXIgbGlrZUNocm9tZSA9IGlzQ3VzdG9tQ29udGV4dFxuICAgICAgPyAhIW5hdi5saWtlQ2hyb21lXG4gICAgICA6IC9cXGJDaHJvbWVcXGIvLnRlc3QodWEpICYmICEvaW50ZXJuYWx8XFxuL2kudGVzdCh0b1N0cmluZy50b1N0cmluZygpKTtcblxuICAgIC8qKiBJbnRlcm5hbCBgW1tDbGFzc11dYCB2YWx1ZSBzaG9ydGN1dHMuICovXG4gICAgdmFyIG9iamVjdENsYXNzID0gJ09iamVjdCcsXG4gICAgICAgIGFpclJ1bnRpbWVDbGFzcyA9IGlzQ3VzdG9tQ29udGV4dCA/IG9iamVjdENsYXNzIDogJ1NjcmlwdEJyaWRnaW5nUHJveHlPYmplY3QnLFxuICAgICAgICBlbnZpcm9DbGFzcyA9IGlzQ3VzdG9tQ29udGV4dCA/IG9iamVjdENsYXNzIDogJ0Vudmlyb25tZW50JyxcbiAgICAgICAgamF2YUNsYXNzID0gKGlzQ3VzdG9tQ29udGV4dCAmJiBjb250ZXh0LmphdmEpID8gJ0phdmFQYWNrYWdlJyA6IGdldENsYXNzT2YoY29udGV4dC5qYXZhKSxcbiAgICAgICAgcGhhbnRvbUNsYXNzID0gaXNDdXN0b21Db250ZXh0ID8gb2JqZWN0Q2xhc3MgOiAnUnVudGltZU9iamVjdCc7XG5cbiAgICAvKiogRGV0ZWN0IEphdmEgZW52aXJvbm1lbnRzLiAqL1xuICAgIHZhciBqYXZhID0gL1xcYkphdmEvLnRlc3QoamF2YUNsYXNzKSAmJiBjb250ZXh0LmphdmE7XG5cbiAgICAvKiogRGV0ZWN0IFJoaW5vLiAqL1xuICAgIHZhciByaGlubyA9IGphdmEgJiYgZ2V0Q2xhc3NPZihjb250ZXh0LmVudmlyb25tZW50KSA9PSBlbnZpcm9DbGFzcztcblxuICAgIC8qKiBBIGNoYXJhY3RlciB0byByZXByZXNlbnQgYWxwaGEuICovXG4gICAgdmFyIGFscGhhID0gamF2YSA/ICdhJyA6ICdcXHUwM2IxJztcblxuICAgIC8qKiBBIGNoYXJhY3RlciB0byByZXByZXNlbnQgYmV0YS4gKi9cbiAgICB2YXIgYmV0YSA9IGphdmEgPyAnYicgOiAnXFx1MDNiMic7XG5cbiAgICAvKiogQnJvd3NlciBkb2N1bWVudCBvYmplY3QuICovXG4gICAgdmFyIGRvYyA9IGNvbnRleHQuZG9jdW1lbnQgfHwge307XG5cbiAgICAvKipcbiAgICAgKiBEZXRlY3QgT3BlcmEgYnJvd3NlciAoUHJlc3RvLWJhc2VkKS5cbiAgICAgKiBodHRwOi8vd3d3Lmhvd3RvY3JlYXRlLmNvLnVrL29wZXJhU3R1ZmYvb3BlcmFPYmplY3QuaHRtbFxuICAgICAqIGh0dHA6Ly9kZXYub3BlcmEuY29tL2FydGljbGVzL3ZpZXcvb3BlcmEtbWluaS13ZWItY29udGVudC1hdXRob3JpbmctZ3VpZGVsaW5lcy8jb3BlcmFtaW5pXG4gICAgICovXG4gICAgdmFyIG9wZXJhID0gY29udGV4dC5vcGVyYW1pbmkgfHwgY29udGV4dC5vcGVyYTtcblxuICAgIC8qKiBPcGVyYSBgW1tDbGFzc11dYC4gKi9cbiAgICB2YXIgb3BlcmFDbGFzcyA9IHJlT3BlcmEudGVzdChvcGVyYUNsYXNzID0gKGlzQ3VzdG9tQ29udGV4dCAmJiBvcGVyYSkgPyBvcGVyYVsnW1tDbGFzc11dJ10gOiBnZXRDbGFzc09mKG9wZXJhKSlcbiAgICAgID8gb3BlcmFDbGFzc1xuICAgICAgOiAob3BlcmEgPSBudWxsKTtcblxuICAgIC8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cblxuICAgIC8qKiBUZW1wb3JhcnkgdmFyaWFibGUgdXNlZCBvdmVyIHRoZSBzY3JpcHQncyBsaWZldGltZS4gKi9cbiAgICB2YXIgZGF0YTtcblxuICAgIC8qKiBUaGUgQ1BVIGFyY2hpdGVjdHVyZS4gKi9cbiAgICB2YXIgYXJjaCA9IHVhO1xuXG4gICAgLyoqIFBsYXRmb3JtIGRlc2NyaXB0aW9uIGFycmF5LiAqL1xuICAgIHZhciBkZXNjcmlwdGlvbiA9IFtdO1xuXG4gICAgLyoqIFBsYXRmb3JtIGFscGhhL2JldGEgaW5kaWNhdG9yLiAqL1xuICAgIHZhciBwcmVyZWxlYXNlID0gbnVsbDtcblxuICAgIC8qKiBBIGZsYWcgdG8gaW5kaWNhdGUgdGhhdCBlbnZpcm9ubWVudCBmZWF0dXJlcyBzaG91bGQgYmUgdXNlZCB0byByZXNvbHZlIHRoZSBwbGF0Zm9ybS4gKi9cbiAgICB2YXIgdXNlRmVhdHVyZXMgPSB1YSA9PSB1c2VyQWdlbnQ7XG5cbiAgICAvKiogVGhlIGJyb3dzZXIvZW52aXJvbm1lbnQgdmVyc2lvbi4gKi9cbiAgICB2YXIgdmVyc2lvbiA9IHVzZUZlYXR1cmVzICYmIG9wZXJhICYmIHR5cGVvZiBvcGVyYS52ZXJzaW9uID09ICdmdW5jdGlvbicgJiYgb3BlcmEudmVyc2lvbigpO1xuXG4gICAgLyoqIEEgZmxhZyB0byBpbmRpY2F0ZSBpZiB0aGUgT1MgZW5kcyB3aXRoIFwiLyBWZXJzaW9uXCIgKi9cbiAgICB2YXIgaXNTcGVjaWFsQ2FzZWRPUztcblxuICAgIC8qIERldGVjdGFibGUgbGF5b3V0IGVuZ2luZXMgKG9yZGVyIGlzIGltcG9ydGFudCkuICovXG4gICAgdmFyIGxheW91dCA9IGdldExheW91dChbXG4gICAgICB7ICdsYWJlbCc6ICdFZGdlSFRNTCcsICdwYXR0ZXJuJzogJ0VkZ2UnIH0sXG4gICAgICAnVHJpZGVudCcsXG4gICAgICB7ICdsYWJlbCc6ICdXZWJLaXQnLCAncGF0dGVybic6ICdBcHBsZVdlYktpdCcgfSxcbiAgICAgICdpQ2FiJyxcbiAgICAgICdQcmVzdG8nLFxuICAgICAgJ05ldEZyb250JyxcbiAgICAgICdUYXNtYW4nLFxuICAgICAgJ0tIVE1MJyxcbiAgICAgICdHZWNrbydcbiAgICBdKTtcblxuICAgIC8qIERldGVjdGFibGUgYnJvd3NlciBuYW1lcyAob3JkZXIgaXMgaW1wb3J0YW50KS4gKi9cbiAgICB2YXIgbmFtZSA9IGdldE5hbWUoW1xuICAgICAgJ0Fkb2JlIEFJUicsXG4gICAgICAnQXJvcmEnLFxuICAgICAgJ0F2YW50IEJyb3dzZXInLFxuICAgICAgJ0JyZWFjaCcsXG4gICAgICAnQ2FtaW5vJyxcbiAgICAgICdFbGVjdHJvbicsXG4gICAgICAnRXBpcGhhbnknLFxuICAgICAgJ0Zlbm5lYycsXG4gICAgICAnRmxvY2snLFxuICAgICAgJ0dhbGVvbicsXG4gICAgICAnR3JlZW5Ccm93c2VyJyxcbiAgICAgICdpQ2FiJyxcbiAgICAgICdJY2V3ZWFzZWwnLFxuICAgICAgJ0stTWVsZW9uJyxcbiAgICAgICdLb25xdWVyb3InLFxuICAgICAgJ0x1bmFzY2FwZScsXG4gICAgICAnTWF4dGhvbicsXG4gICAgICB7ICdsYWJlbCc6ICdNaWNyb3NvZnQgRWRnZScsICdwYXR0ZXJuJzogJ0VkZ2UnIH0sXG4gICAgICAnTWlkb3JpJyxcbiAgICAgICdOb29rIEJyb3dzZXInLFxuICAgICAgJ1BhbGVNb29uJyxcbiAgICAgICdQaGFudG9tSlMnLFxuICAgICAgJ1JhdmVuJyxcbiAgICAgICdSZWtvbnEnLFxuICAgICAgJ1JvY2tNZWx0JyxcbiAgICAgIHsgJ2xhYmVsJzogJ1NhbXN1bmcgSW50ZXJuZXQnLCAncGF0dGVybic6ICdTYW1zdW5nQnJvd3NlcicgfSxcbiAgICAgICdTZWFNb25rZXknLFxuICAgICAgeyAnbGFiZWwnOiAnU2lsaycsICdwYXR0ZXJuJzogJyg/OkNsb3VkOXxTaWxrLUFjY2VsZXJhdGVkKScgfSxcbiAgICAgICdTbGVpcG5pcicsXG4gICAgICAnU2xpbUJyb3dzZXInLFxuICAgICAgeyAnbGFiZWwnOiAnU1JXYXJlIElyb24nLCAncGF0dGVybic6ICdJcm9uJyB9LFxuICAgICAgJ1N1bnJpc2UnLFxuICAgICAgJ1N3aWZ0Zm94JyxcbiAgICAgICdXYXRlcmZveCcsXG4gICAgICAnV2ViUG9zaXRpdmUnLFxuICAgICAgJ09wZXJhIE1pbmknLFxuICAgICAgeyAnbGFiZWwnOiAnT3BlcmEgTWluaScsICdwYXR0ZXJuJzogJ09QaU9TJyB9LFxuICAgICAgJ09wZXJhJyxcbiAgICAgIHsgJ2xhYmVsJzogJ09wZXJhJywgJ3BhdHRlcm4nOiAnT1BSJyB9LFxuICAgICAgJ0Nocm9tZScsXG4gICAgICB7ICdsYWJlbCc6ICdDaHJvbWUgTW9iaWxlJywgJ3BhdHRlcm4nOiAnKD86Q3JpT1N8Q3JNbyknIH0sXG4gICAgICB7ICdsYWJlbCc6ICdGaXJlZm94JywgJ3BhdHRlcm4nOiAnKD86RmlyZWZveHxNaW5lZmllbGQpJyB9LFxuICAgICAgeyAnbGFiZWwnOiAnRmlyZWZveCBmb3IgaU9TJywgJ3BhdHRlcm4nOiAnRnhpT1MnIH0sXG4gICAgICB7ICdsYWJlbCc6ICdJRScsICdwYXR0ZXJuJzogJ0lFTW9iaWxlJyB9LFxuICAgICAgeyAnbGFiZWwnOiAnSUUnLCAncGF0dGVybic6ICdNU0lFJyB9LFxuICAgICAgJ1NhZmFyaSdcbiAgICBdKTtcblxuICAgIC8qIERldGVjdGFibGUgcHJvZHVjdHMgKG9yZGVyIGlzIGltcG9ydGFudCkuICovXG4gICAgdmFyIHByb2R1Y3QgPSBnZXRQcm9kdWN0KFtcbiAgICAgIHsgJ2xhYmVsJzogJ0JsYWNrQmVycnknLCAncGF0dGVybic6ICdCQjEwJyB9LFxuICAgICAgJ0JsYWNrQmVycnknLFxuICAgICAgeyAnbGFiZWwnOiAnR2FsYXh5IFMnLCAncGF0dGVybic6ICdHVC1JOTAwMCcgfSxcbiAgICAgIHsgJ2xhYmVsJzogJ0dhbGF4eSBTMicsICdwYXR0ZXJuJzogJ0dULUk5MTAwJyB9LFxuICAgICAgeyAnbGFiZWwnOiAnR2FsYXh5IFMzJywgJ3BhdHRlcm4nOiAnR1QtSTkzMDAnIH0sXG4gICAgICB7ICdsYWJlbCc6ICdHYWxheHkgUzQnLCAncGF0dGVybic6ICdHVC1JOTUwMCcgfSxcbiAgICAgIHsgJ2xhYmVsJzogJ0dhbGF4eSBTNScsICdwYXR0ZXJuJzogJ1NNLUc5MDAnIH0sXG4gICAgICB7ICdsYWJlbCc6ICdHYWxheHkgUzYnLCAncGF0dGVybic6ICdTTS1HOTIwJyB9LFxuICAgICAgeyAnbGFiZWwnOiAnR2FsYXh5IFM2IEVkZ2UnLCAncGF0dGVybic6ICdTTS1HOTI1JyB9LFxuICAgICAgeyAnbGFiZWwnOiAnR2FsYXh5IFM3JywgJ3BhdHRlcm4nOiAnU00tRzkzMCcgfSxcbiAgICAgIHsgJ2xhYmVsJzogJ0dhbGF4eSBTNyBFZGdlJywgJ3BhdHRlcm4nOiAnU00tRzkzNScgfSxcbiAgICAgICdHb29nbGUgVFYnLFxuICAgICAgJ0x1bWlhJyxcbiAgICAgICdpUGFkJyxcbiAgICAgICdpUG9kJyxcbiAgICAgICdpUGhvbmUnLFxuICAgICAgJ0tpbmRsZScsXG4gICAgICB7ICdsYWJlbCc6ICdLaW5kbGUgRmlyZScsICdwYXR0ZXJuJzogJyg/OkNsb3VkOXxTaWxrLUFjY2VsZXJhdGVkKScgfSxcbiAgICAgICdOZXh1cycsXG4gICAgICAnTm9vaycsXG4gICAgICAnUGxheUJvb2snLFxuICAgICAgJ1BsYXlTdGF0aW9uIFZpdGEnLFxuICAgICAgJ1BsYXlTdGF0aW9uJyxcbiAgICAgICdUb3VjaFBhZCcsXG4gICAgICAnVHJhbnNmb3JtZXInLFxuICAgICAgeyAnbGFiZWwnOiAnV2lpIFUnLCAncGF0dGVybic6ICdXaWlVJyB9LFxuICAgICAgJ1dpaScsXG4gICAgICAnWGJveCBPbmUnLFxuICAgICAgeyAnbGFiZWwnOiAnWGJveCAzNjAnLCAncGF0dGVybic6ICdYYm94JyB9LFxuICAgICAgJ1hvb20nXG4gICAgXSk7XG5cbiAgICAvKiBEZXRlY3RhYmxlIG1hbnVmYWN0dXJlcnMuICovXG4gICAgdmFyIG1hbnVmYWN0dXJlciA9IGdldE1hbnVmYWN0dXJlcih7XG4gICAgICAnQXBwbGUnOiB7ICdpUGFkJzogMSwgJ2lQaG9uZSc6IDEsICdpUG9kJzogMSB9LFxuICAgICAgJ0FyY2hvcyc6IHt9LFxuICAgICAgJ0FtYXpvbic6IHsgJ0tpbmRsZSc6IDEsICdLaW5kbGUgRmlyZSc6IDEgfSxcbiAgICAgICdBc3VzJzogeyAnVHJhbnNmb3JtZXInOiAxIH0sXG4gICAgICAnQmFybmVzICYgTm9ibGUnOiB7ICdOb29rJzogMSB9LFxuICAgICAgJ0JsYWNrQmVycnknOiB7ICdQbGF5Qm9vayc6IDEgfSxcbiAgICAgICdHb29nbGUnOiB7ICdHb29nbGUgVFYnOiAxLCAnTmV4dXMnOiAxIH0sXG4gICAgICAnSFAnOiB7ICdUb3VjaFBhZCc6IDEgfSxcbiAgICAgICdIVEMnOiB7fSxcbiAgICAgICdMRyc6IHt9LFxuICAgICAgJ01pY3Jvc29mdCc6IHsgJ1hib3gnOiAxLCAnWGJveCBPbmUnOiAxIH0sXG4gICAgICAnTW90b3JvbGEnOiB7ICdYb29tJzogMSB9LFxuICAgICAgJ05pbnRlbmRvJzogeyAnV2lpIFUnOiAxLCAgJ1dpaSc6IDEgfSxcbiAgICAgICdOb2tpYSc6IHsgJ0x1bWlhJzogMSB9LFxuICAgICAgJ1NhbXN1bmcnOiB7ICdHYWxheHkgUyc6IDEsICdHYWxheHkgUzInOiAxLCAnR2FsYXh5IFMzJzogMSwgJ0dhbGF4eSBTNCc6IDEgfSxcbiAgICAgICdTb255JzogeyAnUGxheVN0YXRpb24nOiAxLCAnUGxheVN0YXRpb24gVml0YSc6IDEgfVxuICAgIH0pO1xuXG4gICAgLyogRGV0ZWN0YWJsZSBvcGVyYXRpbmcgc3lzdGVtcyAob3JkZXIgaXMgaW1wb3J0YW50KS4gKi9cbiAgICB2YXIgb3MgPSBnZXRPUyhbXG4gICAgICAnV2luZG93cyBQaG9uZScsXG4gICAgICAnQW5kcm9pZCcsXG4gICAgICAnQ2VudE9TJyxcbiAgICAgIHsgJ2xhYmVsJzogJ0Nocm9tZSBPUycsICdwYXR0ZXJuJzogJ0NyT1MnIH0sXG4gICAgICAnRGViaWFuJyxcbiAgICAgICdGZWRvcmEnLFxuICAgICAgJ0ZyZWVCU0QnLFxuICAgICAgJ0dlbnRvbycsXG4gICAgICAnSGFpa3UnLFxuICAgICAgJ0t1YnVudHUnLFxuICAgICAgJ0xpbnV4IE1pbnQnLFxuICAgICAgJ09wZW5CU0QnLFxuICAgICAgJ1JlZCBIYXQnLFxuICAgICAgJ1N1U0UnLFxuICAgICAgJ1VidW50dScsXG4gICAgICAnWHVidW50dScsXG4gICAgICAnQ3lnd2luJyxcbiAgICAgICdTeW1iaWFuIE9TJyxcbiAgICAgICdocHdPUycsXG4gICAgICAnd2ViT1MgJyxcbiAgICAgICd3ZWJPUycsXG4gICAgICAnVGFibGV0IE9TJyxcbiAgICAgICdUaXplbicsXG4gICAgICAnTGludXgnLFxuICAgICAgJ01hYyBPUyBYJyxcbiAgICAgICdNYWNpbnRvc2gnLFxuICAgICAgJ01hYycsXG4gICAgICAnV2luZG93cyA5ODsnLFxuICAgICAgJ1dpbmRvd3MgJ1xuICAgIF0pO1xuXG4gICAgLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuXG4gICAgLyoqXG4gICAgICogUGlja3MgdGhlIGxheW91dCBlbmdpbmUgZnJvbSBhbiBhcnJheSBvZiBndWVzc2VzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBndWVzc2VzIEFuIGFycmF5IG9mIGd1ZXNzZXMuXG4gICAgICogQHJldHVybnMge251bGx8c3RyaW5nfSBUaGUgZGV0ZWN0ZWQgbGF5b3V0IGVuZ2luZS5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBnZXRMYXlvdXQoZ3Vlc3Nlcykge1xuICAgICAgcmV0dXJuIHJlZHVjZShndWVzc2VzLCBmdW5jdGlvbihyZXN1bHQsIGd1ZXNzKSB7XG4gICAgICAgIHJldHVybiByZXN1bHQgfHwgUmVnRXhwKCdcXFxcYicgKyAoXG4gICAgICAgICAgZ3Vlc3MucGF0dGVybiB8fCBxdWFsaWZ5KGd1ZXNzKVxuICAgICAgICApICsgJ1xcXFxiJywgJ2knKS5leGVjKHVhKSAmJiAoZ3Vlc3MubGFiZWwgfHwgZ3Vlc3MpO1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUGlja3MgdGhlIG1hbnVmYWN0dXJlciBmcm9tIGFuIGFycmF5IG9mIGd1ZXNzZXMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGd1ZXNzZXMgQW4gb2JqZWN0IG9mIGd1ZXNzZXMuXG4gICAgICogQHJldHVybnMge251bGx8c3RyaW5nfSBUaGUgZGV0ZWN0ZWQgbWFudWZhY3R1cmVyLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGdldE1hbnVmYWN0dXJlcihndWVzc2VzKSB7XG4gICAgICByZXR1cm4gcmVkdWNlKGd1ZXNzZXMsIGZ1bmN0aW9uKHJlc3VsdCwgdmFsdWUsIGtleSkge1xuICAgICAgICAvLyBMb29rdXAgdGhlIG1hbnVmYWN0dXJlciBieSBwcm9kdWN0IG9yIHNjYW4gdGhlIFVBIGZvciB0aGUgbWFudWZhY3R1cmVyLlxuICAgICAgICByZXR1cm4gcmVzdWx0IHx8IChcbiAgICAgICAgICB2YWx1ZVtwcm9kdWN0XSB8fFxuICAgICAgICAgIHZhbHVlWy9eW2Etel0rKD86ICtbYS16XStcXGIpKi9pLmV4ZWMocHJvZHVjdCldIHx8XG4gICAgICAgICAgUmVnRXhwKCdcXFxcYicgKyBxdWFsaWZ5KGtleSkgKyAnKD86XFxcXGJ8XFxcXHcqXFxcXGQpJywgJ2knKS5leGVjKHVhKVxuICAgICAgICApICYmIGtleTtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFBpY2tzIHRoZSBicm93c2VyIG5hbWUgZnJvbSBhbiBhcnJheSBvZiBndWVzc2VzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBndWVzc2VzIEFuIGFycmF5IG9mIGd1ZXNzZXMuXG4gICAgICogQHJldHVybnMge251bGx8c3RyaW5nfSBUaGUgZGV0ZWN0ZWQgYnJvd3NlciBuYW1lLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGdldE5hbWUoZ3Vlc3Nlcykge1xuICAgICAgcmV0dXJuIHJlZHVjZShndWVzc2VzLCBmdW5jdGlvbihyZXN1bHQsIGd1ZXNzKSB7XG4gICAgICAgIHJldHVybiByZXN1bHQgfHwgUmVnRXhwKCdcXFxcYicgKyAoXG4gICAgICAgICAgZ3Vlc3MucGF0dGVybiB8fCBxdWFsaWZ5KGd1ZXNzKVxuICAgICAgICApICsgJ1xcXFxiJywgJ2knKS5leGVjKHVhKSAmJiAoZ3Vlc3MubGFiZWwgfHwgZ3Vlc3MpO1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUGlja3MgdGhlIE9TIG5hbWUgZnJvbSBhbiBhcnJheSBvZiBndWVzc2VzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBndWVzc2VzIEFuIGFycmF5IG9mIGd1ZXNzZXMuXG4gICAgICogQHJldHVybnMge251bGx8c3RyaW5nfSBUaGUgZGV0ZWN0ZWQgT1MgbmFtZS5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBnZXRPUyhndWVzc2VzKSB7XG4gICAgICByZXR1cm4gcmVkdWNlKGd1ZXNzZXMsIGZ1bmN0aW9uKHJlc3VsdCwgZ3Vlc3MpIHtcbiAgICAgICAgdmFyIHBhdHRlcm4gPSBndWVzcy5wYXR0ZXJuIHx8IHF1YWxpZnkoZ3Vlc3MpO1xuICAgICAgICBpZiAoIXJlc3VsdCAmJiAocmVzdWx0ID1cbiAgICAgICAgICAgICAgUmVnRXhwKCdcXFxcYicgKyBwYXR0ZXJuICsgJyg/Oi9bXFxcXGQuXSt8WyBcXFxcdy5dKiknLCAnaScpLmV4ZWModWEpXG4gICAgICAgICAgICApKSB7XG4gICAgICAgICAgcmVzdWx0ID0gY2xlYW51cE9TKHJlc3VsdCwgcGF0dGVybiwgZ3Vlc3MubGFiZWwgfHwgZ3Vlc3MpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBQaWNrcyB0aGUgcHJvZHVjdCBuYW1lIGZyb20gYW4gYXJyYXkgb2YgZ3Vlc3Nlcy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtBcnJheX0gZ3Vlc3NlcyBBbiBhcnJheSBvZiBndWVzc2VzLlxuICAgICAqIEByZXR1cm5zIHtudWxsfHN0cmluZ30gVGhlIGRldGVjdGVkIHByb2R1Y3QgbmFtZS5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBnZXRQcm9kdWN0KGd1ZXNzZXMpIHtcbiAgICAgIHJldHVybiByZWR1Y2UoZ3Vlc3NlcywgZnVuY3Rpb24ocmVzdWx0LCBndWVzcykge1xuICAgICAgICB2YXIgcGF0dGVybiA9IGd1ZXNzLnBhdHRlcm4gfHwgcXVhbGlmeShndWVzcyk7XG4gICAgICAgIGlmICghcmVzdWx0ICYmIChyZXN1bHQgPVxuICAgICAgICAgICAgICBSZWdFeHAoJ1xcXFxiJyArIHBhdHRlcm4gKyAnICpcXFxcZCtbLlxcXFx3X10qJywgJ2knKS5leGVjKHVhKSB8fFxuICAgICAgICAgICAgICBSZWdFeHAoJ1xcXFxiJyArIHBhdHRlcm4gKyAnICpcXFxcdystW1xcXFx3XSonLCAnaScpLmV4ZWModWEpIHx8XG4gICAgICAgICAgICAgIFJlZ0V4cCgnXFxcXGInICsgcGF0dGVybiArICcoPzo7ICooPzpbYS16XStbXy1dKT9bYS16XStcXFxcZCt8W14gKCk7LV0qKScsICdpJykuZXhlYyh1YSlcbiAgICAgICAgICAgICkpIHtcbiAgICAgICAgICAvLyBTcGxpdCBieSBmb3J3YXJkIHNsYXNoIGFuZCBhcHBlbmQgcHJvZHVjdCB2ZXJzaW9uIGlmIG5lZWRlZC5cbiAgICAgICAgICBpZiAoKHJlc3VsdCA9IFN0cmluZygoZ3Vlc3MubGFiZWwgJiYgIVJlZ0V4cChwYXR0ZXJuLCAnaScpLnRlc3QoZ3Vlc3MubGFiZWwpKSA/IGd1ZXNzLmxhYmVsIDogcmVzdWx0KS5zcGxpdCgnLycpKVsxXSAmJiAhL1tcXGQuXSsvLnRlc3QocmVzdWx0WzBdKSkge1xuICAgICAgICAgICAgcmVzdWx0WzBdICs9ICcgJyArIHJlc3VsdFsxXTtcbiAgICAgICAgICB9XG4gICAgICAgICAgLy8gQ29ycmVjdCBjaGFyYWN0ZXIgY2FzZSBhbmQgY2xlYW51cCBzdHJpbmcuXG4gICAgICAgICAgZ3Vlc3MgPSBndWVzcy5sYWJlbCB8fCBndWVzcztcbiAgICAgICAgICByZXN1bHQgPSBmb3JtYXQocmVzdWx0WzBdXG4gICAgICAgICAgICAucmVwbGFjZShSZWdFeHAocGF0dGVybiwgJ2knKSwgZ3Vlc3MpXG4gICAgICAgICAgICAucmVwbGFjZShSZWdFeHAoJzsgKig/OicgKyBndWVzcyArICdbXy1dKT8nLCAnaScpLCAnICcpXG4gICAgICAgICAgICAucmVwbGFjZShSZWdFeHAoJygnICsgZ3Vlc3MgKyAnKVstXy5dPyhcXFxcdyknLCAnaScpLCAnJDEgJDInKSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlc29sdmVzIHRoZSB2ZXJzaW9uIHVzaW5nIGFuIGFycmF5IG9mIFVBIHBhdHRlcm5zLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBwYXR0ZXJucyBBbiBhcnJheSBvZiBVQSBwYXR0ZXJucy5cbiAgICAgKiBAcmV0dXJucyB7bnVsbHxzdHJpbmd9IFRoZSBkZXRlY3RlZCB2ZXJzaW9uLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGdldFZlcnNpb24ocGF0dGVybnMpIHtcbiAgICAgIHJldHVybiByZWR1Y2UocGF0dGVybnMsIGZ1bmN0aW9uKHJlc3VsdCwgcGF0dGVybikge1xuICAgICAgICByZXR1cm4gcmVzdWx0IHx8IChSZWdFeHAocGF0dGVybiArXG4gICAgICAgICAgJyg/Oi1bXFxcXGQuXSsvfCg/OiBmb3IgW1xcXFx3LV0rKT9bIC8tXSkoW1xcXFxkLl0rW14gKCk7L18tXSopJywgJ2knKS5leGVjKHVhKSB8fCAwKVsxXSB8fCBudWxsO1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyBgcGxhdGZvcm0uZGVzY3JpcHRpb25gIHdoZW4gdGhlIHBsYXRmb3JtIG9iamVjdCBpcyBjb2VyY2VkIHRvIGEgc3RyaW5nLlxuICAgICAqXG4gICAgICogQG5hbWUgdG9TdHJpbmdcbiAgICAgKiBAbWVtYmVyT2YgcGxhdGZvcm1cbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfSBSZXR1cm5zIGBwbGF0Zm9ybS5kZXNjcmlwdGlvbmAgaWYgYXZhaWxhYmxlLCBlbHNlIGFuIGVtcHR5IHN0cmluZy5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiB0b1N0cmluZ1BsYXRmb3JtKCkge1xuICAgICAgcmV0dXJuIHRoaXMuZGVzY3JpcHRpb24gfHwgJyc7XG4gICAgfVxuXG4gICAgLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuXG4gICAgLy8gQ29udmVydCBsYXlvdXQgdG8gYW4gYXJyYXkgc28gd2UgY2FuIGFkZCBleHRyYSBkZXRhaWxzLlxuICAgIGxheW91dCAmJiAobGF5b3V0ID0gW2xheW91dF0pO1xuXG4gICAgLy8gRGV0ZWN0IHByb2R1Y3QgbmFtZXMgdGhhdCBjb250YWluIHRoZWlyIG1hbnVmYWN0dXJlcidzIG5hbWUuXG4gICAgaWYgKG1hbnVmYWN0dXJlciAmJiAhcHJvZHVjdCkge1xuICAgICAgcHJvZHVjdCA9IGdldFByb2R1Y3QoW21hbnVmYWN0dXJlcl0pO1xuICAgIH1cbiAgICAvLyBDbGVhbiB1cCBHb29nbGUgVFYuXG4gICAgaWYgKChkYXRhID0gL1xcYkdvb2dsZSBUVlxcYi8uZXhlYyhwcm9kdWN0KSkpIHtcbiAgICAgIHByb2R1Y3QgPSBkYXRhWzBdO1xuICAgIH1cbiAgICAvLyBEZXRlY3Qgc2ltdWxhdG9ycy5cbiAgICBpZiAoL1xcYlNpbXVsYXRvclxcYi9pLnRlc3QodWEpKSB7XG4gICAgICBwcm9kdWN0ID0gKHByb2R1Y3QgPyBwcm9kdWN0ICsgJyAnIDogJycpICsgJ1NpbXVsYXRvcic7XG4gICAgfVxuICAgIC8vIERldGVjdCBPcGVyYSBNaW5pIDgrIHJ1bm5pbmcgaW4gVHVyYm8vVW5jb21wcmVzc2VkIG1vZGUgb24gaU9TLlxuICAgIGlmIChuYW1lID09ICdPcGVyYSBNaW5pJyAmJiAvXFxiT1BpT1NcXGIvLnRlc3QodWEpKSB7XG4gICAgICBkZXNjcmlwdGlvbi5wdXNoKCdydW5uaW5nIGluIFR1cmJvL1VuY29tcHJlc3NlZCBtb2RlJyk7XG4gICAgfVxuICAgIC8vIERldGVjdCBJRSBNb2JpbGUgMTEuXG4gICAgaWYgKG5hbWUgPT0gJ0lFJyAmJiAvXFxibGlrZSBpUGhvbmUgT1NcXGIvLnRlc3QodWEpKSB7XG4gICAgICBkYXRhID0gcGFyc2UodWEucmVwbGFjZSgvbGlrZSBpUGhvbmUgT1MvLCAnJykpO1xuICAgICAgbWFudWZhY3R1cmVyID0gZGF0YS5tYW51ZmFjdHVyZXI7XG4gICAgICBwcm9kdWN0ID0gZGF0YS5wcm9kdWN0O1xuICAgIH1cbiAgICAvLyBEZXRlY3QgaU9TLlxuICAgIGVsc2UgaWYgKC9eaVAvLnRlc3QocHJvZHVjdCkpIHtcbiAgICAgIG5hbWUgfHwgKG5hbWUgPSAnU2FmYXJpJyk7XG4gICAgICBvcyA9ICdpT1MnICsgKChkYXRhID0gLyBPUyAoW1xcZF9dKykvaS5leGVjKHVhKSlcbiAgICAgICAgPyAnICcgKyBkYXRhWzFdLnJlcGxhY2UoL18vZywgJy4nKVxuICAgICAgICA6ICcnKTtcbiAgICB9XG4gICAgLy8gRGV0ZWN0IEt1YnVudHUuXG4gICAgZWxzZSBpZiAobmFtZSA9PSAnS29ucXVlcm9yJyAmJiAhL2J1bnR1L2kudGVzdChvcykpIHtcbiAgICAgIG9zID0gJ0t1YnVudHUnO1xuICAgIH1cbiAgICAvLyBEZXRlY3QgQW5kcm9pZCBicm93c2Vycy5cbiAgICBlbHNlIGlmICgobWFudWZhY3R1cmVyICYmIG1hbnVmYWN0dXJlciAhPSAnR29vZ2xlJyAmJlxuICAgICAgICAoKC9DaHJvbWUvLnRlc3QobmFtZSkgJiYgIS9cXGJNb2JpbGUgU2FmYXJpXFxiL2kudGVzdCh1YSkpIHx8IC9cXGJWaXRhXFxiLy50ZXN0KHByb2R1Y3QpKSkgfHxcbiAgICAgICAgKC9cXGJBbmRyb2lkXFxiLy50ZXN0KG9zKSAmJiAvXkNocm9tZS8udGVzdChuYW1lKSAmJiAvXFxiVmVyc2lvblxcLy9pLnRlc3QodWEpKSkge1xuICAgICAgbmFtZSA9ICdBbmRyb2lkIEJyb3dzZXInO1xuICAgICAgb3MgPSAvXFxiQW5kcm9pZFxcYi8udGVzdChvcykgPyBvcyA6ICdBbmRyb2lkJztcbiAgICB9XG4gICAgLy8gRGV0ZWN0IFNpbGsgZGVza3RvcC9hY2NlbGVyYXRlZCBtb2Rlcy5cbiAgICBlbHNlIGlmIChuYW1lID09ICdTaWxrJykge1xuICAgICAgaWYgKCEvXFxiTW9iaS9pLnRlc3QodWEpKSB7XG4gICAgICAgIG9zID0gJ0FuZHJvaWQnO1xuICAgICAgICBkZXNjcmlwdGlvbi51bnNoaWZ0KCdkZXNrdG9wIG1vZGUnKTtcbiAgICAgIH1cbiAgICAgIGlmICgvQWNjZWxlcmF0ZWQgKj0gKnRydWUvaS50ZXN0KHVhKSkge1xuICAgICAgICBkZXNjcmlwdGlvbi51bnNoaWZ0KCdhY2NlbGVyYXRlZCcpO1xuICAgICAgfVxuICAgIH1cbiAgICAvLyBEZXRlY3QgUGFsZU1vb24gaWRlbnRpZnlpbmcgYXMgRmlyZWZveC5cbiAgICBlbHNlIGlmIChuYW1lID09ICdQYWxlTW9vbicgJiYgKGRhdGEgPSAvXFxiRmlyZWZveFxcLyhbXFxkLl0rKVxcYi8uZXhlYyh1YSkpKSB7XG4gICAgICBkZXNjcmlwdGlvbi5wdXNoKCdpZGVudGlmeWluZyBhcyBGaXJlZm94ICcgKyBkYXRhWzFdKTtcbiAgICB9XG4gICAgLy8gRGV0ZWN0IEZpcmVmb3ggT1MgYW5kIHByb2R1Y3RzIHJ1bm5pbmcgRmlyZWZveC5cbiAgICBlbHNlIGlmIChuYW1lID09ICdGaXJlZm94JyAmJiAoZGF0YSA9IC9cXGIoTW9iaWxlfFRhYmxldHxUVilcXGIvaS5leGVjKHVhKSkpIHtcbiAgICAgIG9zIHx8IChvcyA9ICdGaXJlZm94IE9TJyk7XG4gICAgICBwcm9kdWN0IHx8IChwcm9kdWN0ID0gZGF0YVsxXSk7XG4gICAgfVxuICAgIC8vIERldGVjdCBmYWxzZSBwb3NpdGl2ZXMgZm9yIEZpcmVmb3gvU2FmYXJpLlxuICAgIGVsc2UgaWYgKCFuYW1lIHx8IChkYXRhID0gIS9cXGJNaW5lZmllbGRcXGIvaS50ZXN0KHVhKSAmJiAvXFxiKD86RmlyZWZveHxTYWZhcmkpXFxiLy5leGVjKG5hbWUpKSkge1xuICAgICAgLy8gRXNjYXBlIHRoZSBgL2AgZm9yIEZpcmVmb3ggMS5cbiAgICAgIGlmIChuYW1lICYmICFwcm9kdWN0ICYmIC9bXFwvLF18XlteKF0rP1xcKS8udGVzdCh1YS5zbGljZSh1YS5pbmRleE9mKGRhdGEgKyAnLycpICsgOCkpKSB7XG4gICAgICAgIC8vIENsZWFyIG5hbWUgb2YgZmFsc2UgcG9zaXRpdmVzLlxuICAgICAgICBuYW1lID0gbnVsbDtcbiAgICAgIH1cbiAgICAgIC8vIFJlYXNzaWduIGEgZ2VuZXJpYyBuYW1lLlxuICAgICAgaWYgKChkYXRhID0gcHJvZHVjdCB8fCBtYW51ZmFjdHVyZXIgfHwgb3MpICYmXG4gICAgICAgICAgKHByb2R1Y3QgfHwgbWFudWZhY3R1cmVyIHx8IC9cXGIoPzpBbmRyb2lkfFN5bWJpYW4gT1N8VGFibGV0IE9TfHdlYk9TKVxcYi8udGVzdChvcykpKSB7XG4gICAgICAgIG5hbWUgPSAvW2Etel0rKD86IEhhdCk/L2kuZXhlYygvXFxiQW5kcm9pZFxcYi8udGVzdChvcykgPyBvcyA6IGRhdGEpICsgJyBCcm93c2VyJztcbiAgICAgIH1cbiAgICB9XG4gICAgLy8gQWRkIENocm9tZSB2ZXJzaW9uIHRvIGRlc2NyaXB0aW9uIGZvciBFbGVjdHJvbi5cbiAgICBlbHNlIGlmIChuYW1lID09ICdFbGVjdHJvbicgJiYgKGRhdGEgPSAoL1xcYkNocm9tZVxcLyhbXFxkLl0rKVxcYi8uZXhlYyh1YSkgfHwgMClbMV0pKSB7XG4gICAgICBkZXNjcmlwdGlvbi5wdXNoKCdDaHJvbWl1bSAnICsgZGF0YSk7XG4gICAgfVxuICAgIC8vIERldGVjdCBub24tT3BlcmEgKFByZXN0by1iYXNlZCkgdmVyc2lvbnMgKG9yZGVyIGlzIGltcG9ydGFudCkuXG4gICAgaWYgKCF2ZXJzaW9uKSB7XG4gICAgICB2ZXJzaW9uID0gZ2V0VmVyc2lvbihbXG4gICAgICAgICcoPzpDbG91ZDl8Q3JpT1N8Q3JNb3xFZGdlfEZ4aU9TfElFTW9iaWxlfElyb258T3BlcmEgP01pbml8T1BpT1N8T1BSfFJhdmVufFNhbXN1bmdCcm93c2VyfFNpbGsoPyEvW1xcXFxkLl0rJCkpJyxcbiAgICAgICAgJ1ZlcnNpb24nLFxuICAgICAgICBxdWFsaWZ5KG5hbWUpLFxuICAgICAgICAnKD86RmlyZWZveHxNaW5lZmllbGR8TmV0RnJvbnQpJ1xuICAgICAgXSk7XG4gICAgfVxuICAgIC8vIERldGVjdCBzdHViYm9ybiBsYXlvdXQgZW5naW5lcy5cbiAgICBpZiAoKGRhdGEgPVxuICAgICAgICAgIGxheW91dCA9PSAnaUNhYicgJiYgcGFyc2VGbG9hdCh2ZXJzaW9uKSA+IDMgJiYgJ1dlYktpdCcgfHxcbiAgICAgICAgICAvXFxiT3BlcmFcXGIvLnRlc3QobmFtZSkgJiYgKC9cXGJPUFJcXGIvLnRlc3QodWEpID8gJ0JsaW5rJyA6ICdQcmVzdG8nKSB8fFxuICAgICAgICAgIC9cXGIoPzpNaWRvcml8Tm9va3xTYWZhcmkpXFxiL2kudGVzdCh1YSkgJiYgIS9eKD86VHJpZGVudHxFZGdlSFRNTCkkLy50ZXN0KGxheW91dCkgJiYgJ1dlYktpdCcgfHxcbiAgICAgICAgICAhbGF5b3V0ICYmIC9cXGJNU0lFXFxiL2kudGVzdCh1YSkgJiYgKG9zID09ICdNYWMgT1MnID8gJ1Rhc21hbicgOiAnVHJpZGVudCcpIHx8XG4gICAgICAgICAgbGF5b3V0ID09ICdXZWJLaXQnICYmIC9cXGJQbGF5U3RhdGlvblxcYig/ISBWaXRhXFxiKS9pLnRlc3QobmFtZSkgJiYgJ05ldEZyb250J1xuICAgICAgICApKSB7XG4gICAgICBsYXlvdXQgPSBbZGF0YV07XG4gICAgfVxuICAgIC8vIERldGVjdCBXaW5kb3dzIFBob25lIDcgZGVza3RvcCBtb2RlLlxuICAgIGlmIChuYW1lID09ICdJRScgJiYgKGRhdGEgPSAoLzsgKig/OlhCTFdQfFp1bmVXUCkoXFxkKykvaS5leGVjKHVhKSB8fCAwKVsxXSkpIHtcbiAgICAgIG5hbWUgKz0gJyBNb2JpbGUnO1xuICAgICAgb3MgPSAnV2luZG93cyBQaG9uZSAnICsgKC9cXCskLy50ZXN0KGRhdGEpID8gZGF0YSA6IGRhdGEgKyAnLngnKTtcbiAgICAgIGRlc2NyaXB0aW9uLnVuc2hpZnQoJ2Rlc2t0b3AgbW9kZScpO1xuICAgIH1cbiAgICAvLyBEZXRlY3QgV2luZG93cyBQaG9uZSA4LnggZGVza3RvcCBtb2RlLlxuICAgIGVsc2UgaWYgKC9cXGJXUERlc2t0b3BcXGIvaS50ZXN0KHVhKSkge1xuICAgICAgbmFtZSA9ICdJRSBNb2JpbGUnO1xuICAgICAgb3MgPSAnV2luZG93cyBQaG9uZSA4LngnO1xuICAgICAgZGVzY3JpcHRpb24udW5zaGlmdCgnZGVza3RvcCBtb2RlJyk7XG4gICAgICB2ZXJzaW9uIHx8ICh2ZXJzaW9uID0gKC9cXGJydjooW1xcZC5dKykvLmV4ZWModWEpIHx8IDApWzFdKTtcbiAgICB9XG4gICAgLy8gRGV0ZWN0IElFIDExIGlkZW50aWZ5aW5nIGFzIG90aGVyIGJyb3dzZXJzLlxuICAgIGVsc2UgaWYgKG5hbWUgIT0gJ0lFJyAmJiBsYXlvdXQgPT0gJ1RyaWRlbnQnICYmIChkYXRhID0gL1xcYnJ2OihbXFxkLl0rKS8uZXhlYyh1YSkpKSB7XG4gICAgICBpZiAobmFtZSkge1xuICAgICAgICBkZXNjcmlwdGlvbi5wdXNoKCdpZGVudGlmeWluZyBhcyAnICsgbmFtZSArICh2ZXJzaW9uID8gJyAnICsgdmVyc2lvbiA6ICcnKSk7XG4gICAgICB9XG4gICAgICBuYW1lID0gJ0lFJztcbiAgICAgIHZlcnNpb24gPSBkYXRhWzFdO1xuICAgIH1cbiAgICAvLyBMZXZlcmFnZSBlbnZpcm9ubWVudCBmZWF0dXJlcy5cbiAgICBpZiAodXNlRmVhdHVyZXMpIHtcbiAgICAgIC8vIERldGVjdCBzZXJ2ZXItc2lkZSBlbnZpcm9ubWVudHMuXG4gICAgICAvLyBSaGlubyBoYXMgYSBnbG9iYWwgZnVuY3Rpb24gd2hpbGUgb3RoZXJzIGhhdmUgYSBnbG9iYWwgb2JqZWN0LlxuICAgICAgaWYgKGlzSG9zdFR5cGUoY29udGV4dCwgJ2dsb2JhbCcpKSB7XG4gICAgICAgIGlmIChqYXZhKSB7XG4gICAgICAgICAgZGF0YSA9IGphdmEubGFuZy5TeXN0ZW07XG4gICAgICAgICAgYXJjaCA9IGRhdGEuZ2V0UHJvcGVydHkoJ29zLmFyY2gnKTtcbiAgICAgICAgICBvcyA9IG9zIHx8IGRhdGEuZ2V0UHJvcGVydHkoJ29zLm5hbWUnKSArICcgJyArIGRhdGEuZ2V0UHJvcGVydHkoJ29zLnZlcnNpb24nKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAocmhpbm8pIHtcbiAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgdmVyc2lvbiA9IGNvbnRleHQucmVxdWlyZSgncmluZ28vZW5naW5lJykudmVyc2lvbi5qb2luKCcuJyk7XG4gICAgICAgICAgICBuYW1lID0gJ1JpbmdvSlMnO1xuICAgICAgICAgIH0gY2F0Y2goZSkge1xuICAgICAgICAgICAgaWYgKChkYXRhID0gY29udGV4dC5zeXN0ZW0pICYmIGRhdGEuZ2xvYmFsLnN5c3RlbSA9PSBjb250ZXh0LnN5c3RlbSkge1xuICAgICAgICAgICAgICBuYW1lID0gJ05hcndoYWwnO1xuICAgICAgICAgICAgICBvcyB8fCAob3MgPSBkYXRhWzBdLm9zIHx8IG51bGwpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoIW5hbWUpIHtcbiAgICAgICAgICAgIG5hbWUgPSAnUmhpbm8nO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmIChcbiAgICAgICAgICB0eXBlb2YgY29udGV4dC5wcm9jZXNzID09ICdvYmplY3QnICYmICFjb250ZXh0LnByb2Nlc3MuYnJvd3NlciAmJlxuICAgICAgICAgIChkYXRhID0gY29udGV4dC5wcm9jZXNzKVxuICAgICAgICApIHtcbiAgICAgICAgICBpZiAodHlwZW9mIGRhdGEudmVyc2lvbnMgPT0gJ29iamVjdCcpIHtcbiAgICAgICAgICAgIGlmICh0eXBlb2YgZGF0YS52ZXJzaW9ucy5lbGVjdHJvbiA9PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgICBkZXNjcmlwdGlvbi5wdXNoKCdOb2RlICcgKyBkYXRhLnZlcnNpb25zLm5vZGUpO1xuICAgICAgICAgICAgICBuYW1lID0gJ0VsZWN0cm9uJztcbiAgICAgICAgICAgICAgdmVyc2lvbiA9IGRhdGEudmVyc2lvbnMuZWxlY3Ryb247XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHR5cGVvZiBkYXRhLnZlcnNpb25zLm53ID09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAgIGRlc2NyaXB0aW9uLnB1c2goJ0Nocm9taXVtICcgKyB2ZXJzaW9uLCAnTm9kZSAnICsgZGF0YS52ZXJzaW9ucy5ub2RlKTtcbiAgICAgICAgICAgICAgbmFtZSA9ICdOVy5qcyc7XG4gICAgICAgICAgICAgIHZlcnNpb24gPSBkYXRhLnZlcnNpb25zLm53O1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoIW5hbWUpIHtcbiAgICAgICAgICAgIG5hbWUgPSAnTm9kZS5qcyc7XG4gICAgICAgICAgICBhcmNoID0gZGF0YS5hcmNoO1xuICAgICAgICAgICAgb3MgPSBkYXRhLnBsYXRmb3JtO1xuICAgICAgICAgICAgdmVyc2lvbiA9IC9bXFxkLl0rLy5leGVjKGRhdGEudmVyc2lvbik7XG4gICAgICAgICAgICB2ZXJzaW9uID0gdmVyc2lvbiA/IHZlcnNpb25bMF0gOiBudWxsO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgLy8gRGV0ZWN0IEFkb2JlIEFJUi5cbiAgICAgIGVsc2UgaWYgKGdldENsYXNzT2YoKGRhdGEgPSBjb250ZXh0LnJ1bnRpbWUpKSA9PSBhaXJSdW50aW1lQ2xhc3MpIHtcbiAgICAgICAgbmFtZSA9ICdBZG9iZSBBSVInO1xuICAgICAgICBvcyA9IGRhdGEuZmxhc2guc3lzdGVtLkNhcGFiaWxpdGllcy5vcztcbiAgICAgIH1cbiAgICAgIC8vIERldGVjdCBQaGFudG9tSlMuXG4gICAgICBlbHNlIGlmIChnZXRDbGFzc09mKChkYXRhID0gY29udGV4dC5waGFudG9tKSkgPT0gcGhhbnRvbUNsYXNzKSB7XG4gICAgICAgIG5hbWUgPSAnUGhhbnRvbUpTJztcbiAgICAgICAgdmVyc2lvbiA9IChkYXRhID0gZGF0YS52ZXJzaW9uIHx8IG51bGwpICYmIChkYXRhLm1ham9yICsgJy4nICsgZGF0YS5taW5vciArICcuJyArIGRhdGEucGF0Y2gpO1xuICAgICAgfVxuICAgICAgLy8gRGV0ZWN0IElFIGNvbXBhdGliaWxpdHkgbW9kZXMuXG4gICAgICBlbHNlIGlmICh0eXBlb2YgZG9jLmRvY3VtZW50TW9kZSA9PSAnbnVtYmVyJyAmJiAoZGF0YSA9IC9cXGJUcmlkZW50XFwvKFxcZCspL2kuZXhlYyh1YSkpKSB7XG4gICAgICAgIC8vIFdlJ3JlIGluIGNvbXBhdGliaWxpdHkgbW9kZSB3aGVuIHRoZSBUcmlkZW50IHZlcnNpb24gKyA0IGRvZXNuJ3RcbiAgICAgICAgLy8gZXF1YWwgdGhlIGRvY3VtZW50IG1vZGUuXG4gICAgICAgIHZlcnNpb24gPSBbdmVyc2lvbiwgZG9jLmRvY3VtZW50TW9kZV07XG4gICAgICAgIGlmICgoZGF0YSA9ICtkYXRhWzFdICsgNCkgIT0gdmVyc2lvblsxXSkge1xuICAgICAgICAgIGRlc2NyaXB0aW9uLnB1c2goJ0lFICcgKyB2ZXJzaW9uWzFdICsgJyBtb2RlJyk7XG4gICAgICAgICAgbGF5b3V0ICYmIChsYXlvdXRbMV0gPSAnJyk7XG4gICAgICAgICAgdmVyc2lvblsxXSA9IGRhdGE7XG4gICAgICAgIH1cbiAgICAgICAgdmVyc2lvbiA9IG5hbWUgPT0gJ0lFJyA/IFN0cmluZyh2ZXJzaW9uWzFdLnRvRml4ZWQoMSkpIDogdmVyc2lvblswXTtcbiAgICAgIH1cbiAgICAgIC8vIERldGVjdCBJRSAxMSBtYXNraW5nIGFzIG90aGVyIGJyb3dzZXJzLlxuICAgICAgZWxzZSBpZiAodHlwZW9mIGRvYy5kb2N1bWVudE1vZGUgPT0gJ251bWJlcicgJiYgL14oPzpDaHJvbWV8RmlyZWZveClcXGIvLnRlc3QobmFtZSkpIHtcbiAgICAgICAgZGVzY3JpcHRpb24ucHVzaCgnbWFza2luZyBhcyAnICsgbmFtZSArICcgJyArIHZlcnNpb24pO1xuICAgICAgICBuYW1lID0gJ0lFJztcbiAgICAgICAgdmVyc2lvbiA9ICcxMS4wJztcbiAgICAgICAgbGF5b3V0ID0gWydUcmlkZW50J107XG4gICAgICAgIG9zID0gJ1dpbmRvd3MnO1xuICAgICAgfVxuICAgICAgb3MgPSBvcyAmJiBmb3JtYXQob3MpO1xuICAgIH1cbiAgICAvLyBEZXRlY3QgcHJlcmVsZWFzZSBwaGFzZXMuXG4gICAgaWYgKHZlcnNpb24gJiYgKGRhdGEgPVxuICAgICAgICAgIC8oPzpbYWJdfGRwfHByZXxbYWJdXFxkK3ByZSkoPzpcXGQrXFwrPyk/JC9pLmV4ZWModmVyc2lvbikgfHxcbiAgICAgICAgICAvKD86YWxwaGF8YmV0YSkoPzogP1xcZCk/L2kuZXhlYyh1YSArICc7JyArICh1c2VGZWF0dXJlcyAmJiBuYXYuYXBwTWlub3JWZXJzaW9uKSkgfHxcbiAgICAgICAgICAvXFxiTWluZWZpZWxkXFxiL2kudGVzdCh1YSkgJiYgJ2EnXG4gICAgICAgICkpIHtcbiAgICAgIHByZXJlbGVhc2UgPSAvYi9pLnRlc3QoZGF0YSkgPyAnYmV0YScgOiAnYWxwaGEnO1xuICAgICAgdmVyc2lvbiA9IHZlcnNpb24ucmVwbGFjZShSZWdFeHAoZGF0YSArICdcXFxcKz8kJyksICcnKSArXG4gICAgICAgIChwcmVyZWxlYXNlID09ICdiZXRhJyA/IGJldGEgOiBhbHBoYSkgKyAoL1xcZCtcXCs/Ly5leGVjKGRhdGEpIHx8ICcnKTtcbiAgICB9XG4gICAgLy8gRGV0ZWN0IEZpcmVmb3ggTW9iaWxlLlxuICAgIGlmIChuYW1lID09ICdGZW5uZWMnIHx8IG5hbWUgPT0gJ0ZpcmVmb3gnICYmIC9cXGIoPzpBbmRyb2lkfEZpcmVmb3ggT1MpXFxiLy50ZXN0KG9zKSkge1xuICAgICAgbmFtZSA9ICdGaXJlZm94IE1vYmlsZSc7XG4gICAgfVxuICAgIC8vIE9ic2N1cmUgTWF4dGhvbidzIHVucmVsaWFibGUgdmVyc2lvbi5cbiAgICBlbHNlIGlmIChuYW1lID09ICdNYXh0aG9uJyAmJiB2ZXJzaW9uKSB7XG4gICAgICB2ZXJzaW9uID0gdmVyc2lvbi5yZXBsYWNlKC9cXC5bXFxkLl0rLywgJy54Jyk7XG4gICAgfVxuICAgIC8vIERldGVjdCBYYm94IDM2MCBhbmQgWGJveCBPbmUuXG4gICAgZWxzZSBpZiAoL1xcYlhib3hcXGIvaS50ZXN0KHByb2R1Y3QpKSB7XG4gICAgICBpZiAocHJvZHVjdCA9PSAnWGJveCAzNjAnKSB7XG4gICAgICAgIG9zID0gbnVsbDtcbiAgICAgIH1cbiAgICAgIGlmIChwcm9kdWN0ID09ICdYYm94IDM2MCcgJiYgL1xcYklFTW9iaWxlXFxiLy50ZXN0KHVhKSkge1xuICAgICAgICBkZXNjcmlwdGlvbi51bnNoaWZ0KCdtb2JpbGUgbW9kZScpO1xuICAgICAgfVxuICAgIH1cbiAgICAvLyBBZGQgbW9iaWxlIHBvc3RmaXguXG4gICAgZWxzZSBpZiAoKC9eKD86Q2hyb21lfElFfE9wZXJhKSQvLnRlc3QobmFtZSkgfHwgbmFtZSAmJiAhcHJvZHVjdCAmJiAhL0Jyb3dzZXJ8TW9iaS8udGVzdChuYW1lKSkgJiZcbiAgICAgICAgKG9zID09ICdXaW5kb3dzIENFJyB8fCAvTW9iaS9pLnRlc3QodWEpKSkge1xuICAgICAgbmFtZSArPSAnIE1vYmlsZSc7XG4gICAgfVxuICAgIC8vIERldGVjdCBJRSBwbGF0Zm9ybSBwcmV2aWV3LlxuICAgIGVsc2UgaWYgKG5hbWUgPT0gJ0lFJyAmJiB1c2VGZWF0dXJlcykge1xuICAgICAgdHJ5IHtcbiAgICAgICAgaWYgKGNvbnRleHQuZXh0ZXJuYWwgPT09IG51bGwpIHtcbiAgICAgICAgICBkZXNjcmlwdGlvbi51bnNoaWZ0KCdwbGF0Zm9ybSBwcmV2aWV3Jyk7XG4gICAgICAgIH1cbiAgICAgIH0gY2F0Y2goZSkge1xuICAgICAgICBkZXNjcmlwdGlvbi51bnNoaWZ0KCdlbWJlZGRlZCcpO1xuICAgICAgfVxuICAgIH1cbiAgICAvLyBEZXRlY3QgQmxhY2tCZXJyeSBPUyB2ZXJzaW9uLlxuICAgIC8vIGh0dHA6Ly9kb2NzLmJsYWNrYmVycnkuY29tL2VuL2RldmVsb3BlcnMvZGVsaXZlcmFibGVzLzE4MTY5L0hUVFBfaGVhZGVyc19zZW50X2J5X0JCX0Jyb3dzZXJfMTIzNDkxMV8xMS5qc3BcbiAgICBlbHNlIGlmICgoL1xcYkJsYWNrQmVycnlcXGIvLnRlc3QocHJvZHVjdCkgfHwgL1xcYkJCMTBcXGIvLnRlc3QodWEpKSAmJiAoZGF0YSA9XG4gICAgICAgICAgKFJlZ0V4cChwcm9kdWN0LnJlcGxhY2UoLyArL2csICcgKicpICsgJy8oWy5cXFxcZF0rKScsICdpJykuZXhlYyh1YSkgfHwgMClbMV0gfHxcbiAgICAgICAgICB2ZXJzaW9uXG4gICAgICAgICkpIHtcbiAgICAgIGRhdGEgPSBbZGF0YSwgL0JCMTAvLnRlc3QodWEpXTtcbiAgICAgIG9zID0gKGRhdGFbMV0gPyAocHJvZHVjdCA9IG51bGwsIG1hbnVmYWN0dXJlciA9ICdCbGFja0JlcnJ5JykgOiAnRGV2aWNlIFNvZnR3YXJlJykgKyAnICcgKyBkYXRhWzBdO1xuICAgICAgdmVyc2lvbiA9IG51bGw7XG4gICAgfVxuICAgIC8vIERldGVjdCBPcGVyYSBpZGVudGlmeWluZy9tYXNraW5nIGl0c2VsZiBhcyBhbm90aGVyIGJyb3dzZXIuXG4gICAgLy8gaHR0cDovL3d3dy5vcGVyYS5jb20vc3VwcG9ydC9rYi92aWV3Lzg0My9cbiAgICBlbHNlIGlmICh0aGlzICE9IGZvck93biAmJiBwcm9kdWN0ICE9ICdXaWknICYmIChcbiAgICAgICAgICAodXNlRmVhdHVyZXMgJiYgb3BlcmEpIHx8XG4gICAgICAgICAgKC9PcGVyYS8udGVzdChuYW1lKSAmJiAvXFxiKD86TVNJRXxGaXJlZm94KVxcYi9pLnRlc3QodWEpKSB8fFxuICAgICAgICAgIChuYW1lID09ICdGaXJlZm94JyAmJiAvXFxiT1MgWCAoPzpcXGQrXFwuKXsyLH0vLnRlc3Qob3MpKSB8fFxuICAgICAgICAgIChuYW1lID09ICdJRScgJiYgKFxuICAgICAgICAgICAgKG9zICYmICEvXldpbi8udGVzdChvcykgJiYgdmVyc2lvbiA+IDUuNSkgfHxcbiAgICAgICAgICAgIC9cXGJXaW5kb3dzIFhQXFxiLy50ZXN0KG9zKSAmJiB2ZXJzaW9uID4gOCB8fFxuICAgICAgICAgICAgdmVyc2lvbiA9PSA4ICYmICEvXFxiVHJpZGVudFxcYi8udGVzdCh1YSlcbiAgICAgICAgICApKVxuICAgICAgICApICYmICFyZU9wZXJhLnRlc3QoKGRhdGEgPSBwYXJzZS5jYWxsKGZvck93biwgdWEucmVwbGFjZShyZU9wZXJhLCAnJykgKyAnOycpKSkgJiYgZGF0YS5uYW1lKSB7XG4gICAgICAvLyBXaGVuIFwiaWRlbnRpZnlpbmdcIiwgdGhlIFVBIGNvbnRhaW5zIGJvdGggT3BlcmEgYW5kIHRoZSBvdGhlciBicm93c2VyJ3MgbmFtZS5cbiAgICAgIGRhdGEgPSAnaW5nIGFzICcgKyBkYXRhLm5hbWUgKyAoKGRhdGEgPSBkYXRhLnZlcnNpb24pID8gJyAnICsgZGF0YSA6ICcnKTtcbiAgICAgIGlmIChyZU9wZXJhLnRlc3QobmFtZSkpIHtcbiAgICAgICAgaWYgKC9cXGJJRVxcYi8udGVzdChkYXRhKSAmJiBvcyA9PSAnTWFjIE9TJykge1xuICAgICAgICAgIG9zID0gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICBkYXRhID0gJ2lkZW50aWZ5JyArIGRhdGE7XG4gICAgICB9XG4gICAgICAvLyBXaGVuIFwibWFza2luZ1wiLCB0aGUgVUEgY29udGFpbnMgb25seSB0aGUgb3RoZXIgYnJvd3NlcidzIG5hbWUuXG4gICAgICBlbHNlIHtcbiAgICAgICAgZGF0YSA9ICdtYXNrJyArIGRhdGE7XG4gICAgICAgIGlmIChvcGVyYUNsYXNzKSB7XG4gICAgICAgICAgbmFtZSA9IGZvcm1hdChvcGVyYUNsYXNzLnJlcGxhY2UoLyhbYS16XSkoW0EtWl0pL2csICckMSAkMicpKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBuYW1lID0gJ09wZXJhJztcbiAgICAgICAgfVxuICAgICAgICBpZiAoL1xcYklFXFxiLy50ZXN0KGRhdGEpKSB7XG4gICAgICAgICAgb3MgPSBudWxsO1xuICAgICAgICB9XG4gICAgICAgIGlmICghdXNlRmVhdHVyZXMpIHtcbiAgICAgICAgICB2ZXJzaW9uID0gbnVsbDtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgbGF5b3V0ID0gWydQcmVzdG8nXTtcbiAgICAgIGRlc2NyaXB0aW9uLnB1c2goZGF0YSk7XG4gICAgfVxuICAgIC8vIERldGVjdCBXZWJLaXQgTmlnaHRseSBhbmQgYXBwcm94aW1hdGUgQ2hyb21lL1NhZmFyaSB2ZXJzaW9ucy5cbiAgICBpZiAoKGRhdGEgPSAoL1xcYkFwcGxlV2ViS2l0XFwvKFtcXGQuXStcXCs/KS9pLmV4ZWModWEpIHx8IDApWzFdKSkge1xuICAgICAgLy8gQ29ycmVjdCBidWlsZCBudW1iZXIgZm9yIG51bWVyaWMgY29tcGFyaXNvbi5cbiAgICAgIC8vIChlLmcuIFwiNTMyLjVcIiBiZWNvbWVzIFwiNTMyLjA1XCIpXG4gICAgICBkYXRhID0gW3BhcnNlRmxvYXQoZGF0YS5yZXBsYWNlKC9cXC4oXFxkKSQvLCAnLjAkMScpKSwgZGF0YV07XG4gICAgICAvLyBOaWdodGx5IGJ1aWxkcyBhcmUgcG9zdGZpeGVkIHdpdGggYSBcIitcIi5cbiAgICAgIGlmIChuYW1lID09ICdTYWZhcmknICYmIGRhdGFbMV0uc2xpY2UoLTEpID09ICcrJykge1xuICAgICAgICBuYW1lID0gJ1dlYktpdCBOaWdodGx5JztcbiAgICAgICAgcHJlcmVsZWFzZSA9ICdhbHBoYSc7XG4gICAgICAgIHZlcnNpb24gPSBkYXRhWzFdLnNsaWNlKDAsIC0xKTtcbiAgICAgIH1cbiAgICAgIC8vIENsZWFyIGluY29ycmVjdCBicm93c2VyIHZlcnNpb25zLlxuICAgICAgZWxzZSBpZiAodmVyc2lvbiA9PSBkYXRhWzFdIHx8XG4gICAgICAgICAgdmVyc2lvbiA9PSAoZGF0YVsyXSA9ICgvXFxiU2FmYXJpXFwvKFtcXGQuXStcXCs/KS9pLmV4ZWModWEpIHx8IDApWzFdKSkge1xuICAgICAgICB2ZXJzaW9uID0gbnVsbDtcbiAgICAgIH1cbiAgICAgIC8vIFVzZSB0aGUgZnVsbCBDaHJvbWUgdmVyc2lvbiB3aGVuIGF2YWlsYWJsZS5cbiAgICAgIGRhdGFbMV0gPSAoL1xcYkNocm9tZVxcLyhbXFxkLl0rKS9pLmV4ZWModWEpIHx8IDApWzFdO1xuICAgICAgLy8gRGV0ZWN0IEJsaW5rIGxheW91dCBlbmdpbmUuXG4gICAgICBpZiAoZGF0YVswXSA9PSA1MzcuMzYgJiYgZGF0YVsyXSA9PSA1MzcuMzYgJiYgcGFyc2VGbG9hdChkYXRhWzFdKSA+PSAyOCAmJiBsYXlvdXQgPT0gJ1dlYktpdCcpIHtcbiAgICAgICAgbGF5b3V0ID0gWydCbGluayddO1xuICAgICAgfVxuICAgICAgLy8gRGV0ZWN0IEphdmFTY3JpcHRDb3JlLlxuICAgICAgLy8gaHR0cDovL3N0YWNrb3ZlcmZsb3cuY29tL3F1ZXN0aW9ucy82NzY4NDc0L2hvdy1jYW4taS1kZXRlY3Qtd2hpY2gtamF2YXNjcmlwdC1lbmdpbmUtdjgtb3ItanNjLWlzLXVzZWQtYXQtcnVudGltZS1pbi1hbmRyb2lcbiAgICAgIGlmICghdXNlRmVhdHVyZXMgfHwgKCFsaWtlQ2hyb21lICYmICFkYXRhWzFdKSkge1xuICAgICAgICBsYXlvdXQgJiYgKGxheW91dFsxXSA9ICdsaWtlIFNhZmFyaScpO1xuICAgICAgICBkYXRhID0gKGRhdGEgPSBkYXRhWzBdLCBkYXRhIDwgNDAwID8gMSA6IGRhdGEgPCA1MDAgPyAyIDogZGF0YSA8IDUyNiA/IDMgOiBkYXRhIDwgNTMzID8gNCA6IGRhdGEgPCA1MzQgPyAnNCsnIDogZGF0YSA8IDUzNSA/IDUgOiBkYXRhIDwgNTM3ID8gNiA6IGRhdGEgPCA1MzggPyA3IDogZGF0YSA8IDYwMSA/IDggOiAnOCcpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbGF5b3V0ICYmIChsYXlvdXRbMV0gPSAnbGlrZSBDaHJvbWUnKTtcbiAgICAgICAgZGF0YSA9IGRhdGFbMV0gfHwgKGRhdGEgPSBkYXRhWzBdLCBkYXRhIDwgNTMwID8gMSA6IGRhdGEgPCA1MzIgPyAyIDogZGF0YSA8IDUzMi4wNSA/IDMgOiBkYXRhIDwgNTMzID8gNCA6IGRhdGEgPCA1MzQuMDMgPyA1IDogZGF0YSA8IDUzNC4wNyA/IDYgOiBkYXRhIDwgNTM0LjEwID8gNyA6IGRhdGEgPCA1MzQuMTMgPyA4IDogZGF0YSA8IDUzNC4xNiA/IDkgOiBkYXRhIDwgNTM0LjI0ID8gMTAgOiBkYXRhIDwgNTM0LjMwID8gMTEgOiBkYXRhIDwgNTM1LjAxID8gMTIgOiBkYXRhIDwgNTM1LjAyID8gJzEzKycgOiBkYXRhIDwgNTM1LjA3ID8gMTUgOiBkYXRhIDwgNTM1LjExID8gMTYgOiBkYXRhIDwgNTM1LjE5ID8gMTcgOiBkYXRhIDwgNTM2LjA1ID8gMTggOiBkYXRhIDwgNTM2LjEwID8gMTkgOiBkYXRhIDwgNTM3LjAxID8gMjAgOiBkYXRhIDwgNTM3LjExID8gJzIxKycgOiBkYXRhIDwgNTM3LjEzID8gMjMgOiBkYXRhIDwgNTM3LjE4ID8gMjQgOiBkYXRhIDwgNTM3LjI0ID8gMjUgOiBkYXRhIDwgNTM3LjM2ID8gMjYgOiBsYXlvdXQgIT0gJ0JsaW5rJyA/ICcyNycgOiAnMjgnKTtcbiAgICAgIH1cbiAgICAgIC8vIEFkZCB0aGUgcG9zdGZpeCBvZiBcIi54XCIgb3IgXCIrXCIgZm9yIGFwcHJveGltYXRlIHZlcnNpb25zLlxuICAgICAgbGF5b3V0ICYmIChsYXlvdXRbMV0gKz0gJyAnICsgKGRhdGEgKz0gdHlwZW9mIGRhdGEgPT0gJ251bWJlcicgPyAnLngnIDogL1suK10vLnRlc3QoZGF0YSkgPyAnJyA6ICcrJykpO1xuICAgICAgLy8gT2JzY3VyZSB2ZXJzaW9uIGZvciBzb21lIFNhZmFyaSAxLTIgcmVsZWFzZXMuXG4gICAgICBpZiAobmFtZSA9PSAnU2FmYXJpJyAmJiAoIXZlcnNpb24gfHwgcGFyc2VJbnQodmVyc2lvbikgPiA0NSkpIHtcbiAgICAgICAgdmVyc2lvbiA9IGRhdGE7XG4gICAgICB9XG4gICAgfVxuICAgIC8vIERldGVjdCBPcGVyYSBkZXNrdG9wIG1vZGVzLlxuICAgIGlmIChuYW1lID09ICdPcGVyYScgJiYgIChkYXRhID0gL1xcYnpib3Z8enZhdiQvLmV4ZWMob3MpKSkge1xuICAgICAgbmFtZSArPSAnICc7XG4gICAgICBkZXNjcmlwdGlvbi51bnNoaWZ0KCdkZXNrdG9wIG1vZGUnKTtcbiAgICAgIGlmIChkYXRhID09ICd6dmF2Jykge1xuICAgICAgICBuYW1lICs9ICdNaW5pJztcbiAgICAgICAgdmVyc2lvbiA9IG51bGw7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBuYW1lICs9ICdNb2JpbGUnO1xuICAgICAgfVxuICAgICAgb3MgPSBvcy5yZXBsYWNlKFJlZ0V4cCgnIConICsgZGF0YSArICckJyksICcnKTtcbiAgICB9XG4gICAgLy8gRGV0ZWN0IENocm9tZSBkZXNrdG9wIG1vZGUuXG4gICAgZWxzZSBpZiAobmFtZSA9PSAnU2FmYXJpJyAmJiAvXFxiQ2hyb21lXFxiLy5leGVjKGxheW91dCAmJiBsYXlvdXRbMV0pKSB7XG4gICAgICBkZXNjcmlwdGlvbi51bnNoaWZ0KCdkZXNrdG9wIG1vZGUnKTtcbiAgICAgIG5hbWUgPSAnQ2hyb21lIE1vYmlsZSc7XG4gICAgICB2ZXJzaW9uID0gbnVsbDtcblxuICAgICAgaWYgKC9cXGJPUyBYXFxiLy50ZXN0KG9zKSkge1xuICAgICAgICBtYW51ZmFjdHVyZXIgPSAnQXBwbGUnO1xuICAgICAgICBvcyA9ICdpT1MgNC4zKyc7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBvcyA9IG51bGw7XG4gICAgICB9XG4gICAgfVxuICAgIC8vIFN0cmlwIGluY29ycmVjdCBPUyB2ZXJzaW9ucy5cbiAgICBpZiAodmVyc2lvbiAmJiB2ZXJzaW9uLmluZGV4T2YoKGRhdGEgPSAvW1xcZC5dKyQvLmV4ZWMob3MpKSkgPT0gMCAmJlxuICAgICAgICB1YS5pbmRleE9mKCcvJyArIGRhdGEgKyAnLScpID4gLTEpIHtcbiAgICAgIG9zID0gdHJpbShvcy5yZXBsYWNlKGRhdGEsICcnKSk7XG4gICAgfVxuICAgIC8vIEFkZCBsYXlvdXQgZW5naW5lLlxuICAgIGlmIChsYXlvdXQgJiYgIS9cXGIoPzpBdmFudHxOb29rKVxcYi8udGVzdChuYW1lKSAmJiAoXG4gICAgICAgIC9Ccm93c2VyfEx1bmFzY2FwZXxNYXh0aG9uLy50ZXN0KG5hbWUpIHx8XG4gICAgICAgIG5hbWUgIT0gJ1NhZmFyaScgJiYgL15pT1MvLnRlc3Qob3MpICYmIC9cXGJTYWZhcmlcXGIvLnRlc3QobGF5b3V0WzFdKSB8fFxuICAgICAgICAvXig/OkFkb2JlfEFyb3JhfEJyZWFjaHxNaWRvcml8T3BlcmF8UGhhbnRvbXxSZWtvbnF8Um9ja3xTYW1zdW5nIEludGVybmV0fFNsZWlwbmlyfFdlYikvLnRlc3QobmFtZSkgJiYgbGF5b3V0WzFdKSkge1xuICAgICAgLy8gRG9uJ3QgYWRkIGxheW91dCBkZXRhaWxzIHRvIGRlc2NyaXB0aW9uIGlmIHRoZXkgYXJlIGZhbHNleS5cbiAgICAgIChkYXRhID0gbGF5b3V0W2xheW91dC5sZW5ndGggLSAxXSkgJiYgZGVzY3JpcHRpb24ucHVzaChkYXRhKTtcbiAgICB9XG4gICAgLy8gQ29tYmluZSBjb250ZXh0dWFsIGluZm9ybWF0aW9uLlxuICAgIGlmIChkZXNjcmlwdGlvbi5sZW5ndGgpIHtcbiAgICAgIGRlc2NyaXB0aW9uID0gWycoJyArIGRlc2NyaXB0aW9uLmpvaW4oJzsgJykgKyAnKSddO1xuICAgIH1cbiAgICAvLyBBcHBlbmQgbWFudWZhY3R1cmVyIHRvIGRlc2NyaXB0aW9uLlxuICAgIGlmIChtYW51ZmFjdHVyZXIgJiYgcHJvZHVjdCAmJiBwcm9kdWN0LmluZGV4T2YobWFudWZhY3R1cmVyKSA8IDApIHtcbiAgICAgIGRlc2NyaXB0aW9uLnB1c2goJ29uICcgKyBtYW51ZmFjdHVyZXIpO1xuICAgIH1cbiAgICAvLyBBcHBlbmQgcHJvZHVjdCB0byBkZXNjcmlwdGlvbi5cbiAgICBpZiAocHJvZHVjdCkge1xuICAgICAgZGVzY3JpcHRpb24ucHVzaCgoL15vbiAvLnRlc3QoZGVzY3JpcHRpb25bZGVzY3JpcHRpb24ubGVuZ3RoIC0gMV0pID8gJycgOiAnb24gJykgKyBwcm9kdWN0KTtcbiAgICB9XG4gICAgLy8gUGFyc2UgdGhlIE9TIGludG8gYW4gb2JqZWN0LlxuICAgIGlmIChvcykge1xuICAgICAgZGF0YSA9IC8gKFtcXGQuK10rKSQvLmV4ZWMob3MpO1xuICAgICAgaXNTcGVjaWFsQ2FzZWRPUyA9IGRhdGEgJiYgb3MuY2hhckF0KG9zLmxlbmd0aCAtIGRhdGFbMF0ubGVuZ3RoIC0gMSkgPT0gJy8nO1xuICAgICAgb3MgPSB7XG4gICAgICAgICdhcmNoaXRlY3R1cmUnOiAzMixcbiAgICAgICAgJ2ZhbWlseSc6IChkYXRhICYmICFpc1NwZWNpYWxDYXNlZE9TKSA/IG9zLnJlcGxhY2UoZGF0YVswXSwgJycpIDogb3MsXG4gICAgICAgICd2ZXJzaW9uJzogZGF0YSA/IGRhdGFbMV0gOiBudWxsLFxuICAgICAgICAndG9TdHJpbmcnOiBmdW5jdGlvbigpIHtcbiAgICAgICAgICB2YXIgdmVyc2lvbiA9IHRoaXMudmVyc2lvbjtcbiAgICAgICAgICByZXR1cm4gdGhpcy5mYW1pbHkgKyAoKHZlcnNpb24gJiYgIWlzU3BlY2lhbENhc2VkT1MpID8gJyAnICsgdmVyc2lvbiA6ICcnKSArICh0aGlzLmFyY2hpdGVjdHVyZSA9PSA2NCA/ICcgNjQtYml0JyA6ICcnKTtcbiAgICAgICAgfVxuICAgICAgfTtcbiAgICB9XG4gICAgLy8gQWRkIGJyb3dzZXIvT1MgYXJjaGl0ZWN0dXJlLlxuICAgIGlmICgoZGF0YSA9IC9cXGIoPzpBTUR8SUF8V2lufFdPV3x4ODZffHgpNjRcXGIvaS5leGVjKGFyY2gpKSAmJiAhL1xcYmk2ODZcXGIvaS50ZXN0KGFyY2gpKSB7XG4gICAgICBpZiAob3MpIHtcbiAgICAgICAgb3MuYXJjaGl0ZWN0dXJlID0gNjQ7XG4gICAgICAgIG9zLmZhbWlseSA9IG9zLmZhbWlseS5yZXBsYWNlKFJlZ0V4cCgnIConICsgZGF0YSksICcnKTtcbiAgICAgIH1cbiAgICAgIGlmIChcbiAgICAgICAgICBuYW1lICYmICgvXFxiV09XNjRcXGIvaS50ZXN0KHVhKSB8fFxuICAgICAgICAgICh1c2VGZWF0dXJlcyAmJiAvXFx3KD86ODZ8MzIpJC8udGVzdChuYXYuY3B1Q2xhc3MgfHwgbmF2LnBsYXRmb3JtKSAmJiAhL1xcYldpbjY0OyB4NjRcXGIvaS50ZXN0KHVhKSkpXG4gICAgICApIHtcbiAgICAgICAgZGVzY3JpcHRpb24udW5zaGlmdCgnMzItYml0Jyk7XG4gICAgICB9XG4gICAgfVxuICAgIC8vIENocm9tZSAzOSBhbmQgYWJvdmUgb24gT1MgWCBpcyBhbHdheXMgNjQtYml0LlxuICAgIGVsc2UgaWYgKFxuICAgICAgICBvcyAmJiAvXk9TIFgvLnRlc3Qob3MuZmFtaWx5KSAmJlxuICAgICAgICBuYW1lID09ICdDaHJvbWUnICYmIHBhcnNlRmxvYXQodmVyc2lvbikgPj0gMzlcbiAgICApIHtcbiAgICAgIG9zLmFyY2hpdGVjdHVyZSA9IDY0O1xuICAgIH1cblxuICAgIHVhIHx8ICh1YSA9IG51bGwpO1xuXG4gICAgLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuXG4gICAgLyoqXG4gICAgICogVGhlIHBsYXRmb3JtIG9iamVjdC5cbiAgICAgKlxuICAgICAqIEBuYW1lIHBsYXRmb3JtXG4gICAgICogQHR5cGUgT2JqZWN0XG4gICAgICovXG4gICAgdmFyIHBsYXRmb3JtID0ge307XG5cbiAgICAvKipcbiAgICAgKiBUaGUgcGxhdGZvcm0gZGVzY3JpcHRpb24uXG4gICAgICpcbiAgICAgKiBAbWVtYmVyT2YgcGxhdGZvcm1cbiAgICAgKiBAdHlwZSBzdHJpbmd8bnVsbFxuICAgICAqL1xuICAgIHBsYXRmb3JtLmRlc2NyaXB0aW9uID0gdWE7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgbmFtZSBvZiB0aGUgYnJvd3NlcidzIGxheW91dCBlbmdpbmUuXG4gICAgICpcbiAgICAgKiBUaGUgbGlzdCBvZiBjb21tb24gbGF5b3V0IGVuZ2luZXMgaW5jbHVkZTpcbiAgICAgKiBcIkJsaW5rXCIsIFwiRWRnZUhUTUxcIiwgXCJHZWNrb1wiLCBcIlRyaWRlbnRcIiBhbmQgXCJXZWJLaXRcIlxuICAgICAqXG4gICAgICogQG1lbWJlck9mIHBsYXRmb3JtXG4gICAgICogQHR5cGUgc3RyaW5nfG51bGxcbiAgICAgKi9cbiAgICBwbGF0Zm9ybS5sYXlvdXQgPSBsYXlvdXQgJiYgbGF5b3V0WzBdO1xuXG4gICAgLyoqXG4gICAgICogVGhlIG5hbWUgb2YgdGhlIHByb2R1Y3QncyBtYW51ZmFjdHVyZXIuXG4gICAgICpcbiAgICAgKiBUaGUgbGlzdCBvZiBtYW51ZmFjdHVyZXJzIGluY2x1ZGU6XG4gICAgICogXCJBcHBsZVwiLCBcIkFyY2hvc1wiLCBcIkFtYXpvblwiLCBcIkFzdXNcIiwgXCJCYXJuZXMgJiBOb2JsZVwiLCBcIkJsYWNrQmVycnlcIixcbiAgICAgKiBcIkdvb2dsZVwiLCBcIkhQXCIsIFwiSFRDXCIsIFwiTEdcIiwgXCJNaWNyb3NvZnRcIiwgXCJNb3Rvcm9sYVwiLCBcIk5pbnRlbmRvXCIsXG4gICAgICogXCJOb2tpYVwiLCBcIlNhbXN1bmdcIiBhbmQgXCJTb255XCJcbiAgICAgKlxuICAgICAqIEBtZW1iZXJPZiBwbGF0Zm9ybVxuICAgICAqIEB0eXBlIHN0cmluZ3xudWxsXG4gICAgICovXG4gICAgcGxhdGZvcm0ubWFudWZhY3R1cmVyID0gbWFudWZhY3R1cmVyO1xuXG4gICAgLyoqXG4gICAgICogVGhlIG5hbWUgb2YgdGhlIGJyb3dzZXIvZW52aXJvbm1lbnQuXG4gICAgICpcbiAgICAgKiBUaGUgbGlzdCBvZiBjb21tb24gYnJvd3NlciBuYW1lcyBpbmNsdWRlOlxuICAgICAqIFwiQ2hyb21lXCIsIFwiRWxlY3Ryb25cIiwgXCJGaXJlZm94XCIsIFwiRmlyZWZveCBmb3IgaU9TXCIsIFwiSUVcIixcbiAgICAgKiBcIk1pY3Jvc29mdCBFZGdlXCIsIFwiUGhhbnRvbUpTXCIsIFwiU2FmYXJpXCIsIFwiU2VhTW9ua2V5XCIsIFwiU2lsa1wiLFxuICAgICAqIFwiT3BlcmEgTWluaVwiIGFuZCBcIk9wZXJhXCJcbiAgICAgKlxuICAgICAqIE1vYmlsZSB2ZXJzaW9ucyBvZiBzb21lIGJyb3dzZXJzIGhhdmUgXCJNb2JpbGVcIiBhcHBlbmRlZCB0byB0aGVpciBuYW1lOlxuICAgICAqIGVnLiBcIkNocm9tZSBNb2JpbGVcIiwgXCJGaXJlZm94IE1vYmlsZVwiLCBcIklFIE1vYmlsZVwiIGFuZCBcIk9wZXJhIE1vYmlsZVwiXG4gICAgICpcbiAgICAgKiBAbWVtYmVyT2YgcGxhdGZvcm1cbiAgICAgKiBAdHlwZSBzdHJpbmd8bnVsbFxuICAgICAqL1xuICAgIHBsYXRmb3JtLm5hbWUgPSBuYW1lO1xuXG4gICAgLyoqXG4gICAgICogVGhlIGFscGhhL2JldGEgcmVsZWFzZSBpbmRpY2F0b3IuXG4gICAgICpcbiAgICAgKiBAbWVtYmVyT2YgcGxhdGZvcm1cbiAgICAgKiBAdHlwZSBzdHJpbmd8bnVsbFxuICAgICAqL1xuICAgIHBsYXRmb3JtLnByZXJlbGVhc2UgPSBwcmVyZWxlYXNlO1xuXG4gICAgLyoqXG4gICAgICogVGhlIG5hbWUgb2YgdGhlIHByb2R1Y3QgaG9zdGluZyB0aGUgYnJvd3Nlci5cbiAgICAgKlxuICAgICAqIFRoZSBsaXN0IG9mIGNvbW1vbiBwcm9kdWN0cyBpbmNsdWRlOlxuICAgICAqXG4gICAgICogXCJCbGFja0JlcnJ5XCIsIFwiR2FsYXh5IFM0XCIsIFwiTHVtaWFcIiwgXCJpUGFkXCIsIFwiaVBvZFwiLCBcImlQaG9uZVwiLCBcIktpbmRsZVwiLFxuICAgICAqIFwiS2luZGxlIEZpcmVcIiwgXCJOZXh1c1wiLCBcIk5vb2tcIiwgXCJQbGF5Qm9va1wiLCBcIlRvdWNoUGFkXCIgYW5kIFwiVHJhbnNmb3JtZXJcIlxuICAgICAqXG4gICAgICogQG1lbWJlck9mIHBsYXRmb3JtXG4gICAgICogQHR5cGUgc3RyaW5nfG51bGxcbiAgICAgKi9cbiAgICBwbGF0Zm9ybS5wcm9kdWN0ID0gcHJvZHVjdDtcblxuICAgIC8qKlxuICAgICAqIFRoZSBicm93c2VyJ3MgdXNlciBhZ2VudCBzdHJpbmcuXG4gICAgICpcbiAgICAgKiBAbWVtYmVyT2YgcGxhdGZvcm1cbiAgICAgKiBAdHlwZSBzdHJpbmd8bnVsbFxuICAgICAqL1xuICAgIHBsYXRmb3JtLnVhID0gdWE7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYnJvd3Nlci9lbnZpcm9ubWVudCB2ZXJzaW9uLlxuICAgICAqXG4gICAgICogQG1lbWJlck9mIHBsYXRmb3JtXG4gICAgICogQHR5cGUgc3RyaW5nfG51bGxcbiAgICAgKi9cbiAgICBwbGF0Zm9ybS52ZXJzaW9uID0gbmFtZSAmJiB2ZXJzaW9uO1xuXG4gICAgLyoqXG4gICAgICogVGhlIG5hbWUgb2YgdGhlIG9wZXJhdGluZyBzeXN0ZW0uXG4gICAgICpcbiAgICAgKiBAbWVtYmVyT2YgcGxhdGZvcm1cbiAgICAgKiBAdHlwZSBPYmplY3RcbiAgICAgKi9cbiAgICBwbGF0Zm9ybS5vcyA9IG9zIHx8IHtcblxuICAgICAgLyoqXG4gICAgICAgKiBUaGUgQ1BVIGFyY2hpdGVjdHVyZSB0aGUgT1MgaXMgYnVpbHQgZm9yLlxuICAgICAgICpcbiAgICAgICAqIEBtZW1iZXJPZiBwbGF0Zm9ybS5vc1xuICAgICAgICogQHR5cGUgbnVtYmVyfG51bGxcbiAgICAgICAqL1xuICAgICAgJ2FyY2hpdGVjdHVyZSc6IG51bGwsXG5cbiAgICAgIC8qKlxuICAgICAgICogVGhlIGZhbWlseSBvZiB0aGUgT1MuXG4gICAgICAgKlxuICAgICAgICogQ29tbW9uIHZhbHVlcyBpbmNsdWRlOlxuICAgICAgICogXCJXaW5kb3dzXCIsIFwiV2luZG93cyBTZXJ2ZXIgMjAwOCBSMiAvIDdcIiwgXCJXaW5kb3dzIFNlcnZlciAyMDA4IC8gVmlzdGFcIixcbiAgICAgICAqIFwiV2luZG93cyBYUFwiLCBcIk9TIFhcIiwgXCJVYnVudHVcIiwgXCJEZWJpYW5cIiwgXCJGZWRvcmFcIiwgXCJSZWQgSGF0XCIsIFwiU3VTRVwiLFxuICAgICAgICogXCJBbmRyb2lkXCIsIFwiaU9TXCIgYW5kIFwiV2luZG93cyBQaG9uZVwiXG4gICAgICAgKlxuICAgICAgICogQG1lbWJlck9mIHBsYXRmb3JtLm9zXG4gICAgICAgKiBAdHlwZSBzdHJpbmd8bnVsbFxuICAgICAgICovXG4gICAgICAnZmFtaWx5JzogbnVsbCxcblxuICAgICAgLyoqXG4gICAgICAgKiBUaGUgdmVyc2lvbiBvZiB0aGUgT1MuXG4gICAgICAgKlxuICAgICAgICogQG1lbWJlck9mIHBsYXRmb3JtLm9zXG4gICAgICAgKiBAdHlwZSBzdHJpbmd8bnVsbFxuICAgICAgICovXG4gICAgICAndmVyc2lvbic6IG51bGwsXG5cbiAgICAgIC8qKlxuICAgICAgICogUmV0dXJucyB0aGUgT1Mgc3RyaW5nLlxuICAgICAgICpcbiAgICAgICAqIEBtZW1iZXJPZiBwbGF0Zm9ybS5vc1xuICAgICAgICogQHJldHVybnMge3N0cmluZ30gVGhlIE9TIHN0cmluZy5cbiAgICAgICAqL1xuICAgICAgJ3RvU3RyaW5nJzogZnVuY3Rpb24oKSB7IHJldHVybiAnbnVsbCc7IH1cbiAgICB9O1xuXG4gICAgcGxhdGZvcm0ucGFyc2UgPSBwYXJzZTtcbiAgICBwbGF0Zm9ybS50b1N0cmluZyA9IHRvU3RyaW5nUGxhdGZvcm07XG5cbiAgICBpZiAocGxhdGZvcm0udmVyc2lvbikge1xuICAgICAgZGVzY3JpcHRpb24udW5zaGlmdCh2ZXJzaW9uKTtcbiAgICB9XG4gICAgaWYgKHBsYXRmb3JtLm5hbWUpIHtcbiAgICAgIGRlc2NyaXB0aW9uLnVuc2hpZnQobmFtZSk7XG4gICAgfVxuICAgIGlmIChvcyAmJiBuYW1lICYmICEob3MgPT0gU3RyaW5nKG9zKS5zcGxpdCgnICcpWzBdICYmIChvcyA9PSBuYW1lLnNwbGl0KCcgJylbMF0gfHwgcHJvZHVjdCkpKSB7XG4gICAgICBkZXNjcmlwdGlvbi5wdXNoKHByb2R1Y3QgPyAnKCcgKyBvcyArICcpJyA6ICdvbiAnICsgb3MpO1xuICAgIH1cbiAgICBpZiAoZGVzY3JpcHRpb24ubGVuZ3RoKSB7XG4gICAgICBwbGF0Zm9ybS5kZXNjcmlwdGlvbiA9IGRlc2NyaXB0aW9uLmpvaW4oJyAnKTtcbiAgICB9XG4gICAgcmV0dXJuIHBsYXRmb3JtO1xuICB9XG5cbiAgLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG5cbiAgLy8gRXhwb3J0IHBsYXRmb3JtLlxuICB2YXIgcGxhdGZvcm0gPSBwYXJzZSgpO1xuXG4gIC8vIFNvbWUgQU1EIGJ1aWxkIG9wdGltaXplcnMsIGxpa2Ugci5qcywgY2hlY2sgZm9yIGNvbmRpdGlvbiBwYXR0ZXJucyBsaWtlIHRoZSBmb2xsb3dpbmc6XG4gIGlmICh0eXBlb2YgZGVmaW5lID09ICdmdW5jdGlvbicgJiYgdHlwZW9mIGRlZmluZS5hbWQgPT0gJ29iamVjdCcgJiYgZGVmaW5lLmFtZCkge1xuICAgIC8vIEV4cG9zZSBwbGF0Zm9ybSBvbiB0aGUgZ2xvYmFsIG9iamVjdCB0byBwcmV2ZW50IGVycm9ycyB3aGVuIHBsYXRmb3JtIGlzXG4gICAgLy8gbG9hZGVkIGJ5IGEgc2NyaXB0IHRhZyBpbiB0aGUgcHJlc2VuY2Ugb2YgYW4gQU1EIGxvYWRlci5cbiAgICAvLyBTZWUgaHR0cDovL3JlcXVpcmVqcy5vcmcvZG9jcy9lcnJvcnMuaHRtbCNtaXNtYXRjaCBmb3IgbW9yZSBkZXRhaWxzLlxuICAgIHJvb3QucGxhdGZvcm0gPSBwbGF0Zm9ybTtcblxuICAgIC8vIERlZmluZSBhcyBhbiBhbm9ueW1vdXMgbW9kdWxlIHNvIHBsYXRmb3JtIGNhbiBiZSBhbGlhc2VkIHRocm91Z2ggcGF0aCBtYXBwaW5nLlxuICAgIGRlZmluZShmdW5jdGlvbigpIHtcbiAgICAgIHJldHVybiBwbGF0Zm9ybTtcbiAgICB9KTtcbiAgfVxuICAvLyBDaGVjayBmb3IgYGV4cG9ydHNgIGFmdGVyIGBkZWZpbmVgIGluIGNhc2UgYSBidWlsZCBvcHRpbWl6ZXIgYWRkcyBhbiBgZXhwb3J0c2Agb2JqZWN0LlxuICBlbHNlIGlmIChmcmVlRXhwb3J0cyAmJiBmcmVlTW9kdWxlKSB7XG4gICAgLy8gRXhwb3J0IGZvciBDb21tb25KUyBzdXBwb3J0LlxuICAgIGZvck93bihwbGF0Zm9ybSwgZnVuY3Rpb24odmFsdWUsIGtleSkge1xuICAgICAgZnJlZUV4cG9ydHNba2V5XSA9IHZhbHVlO1xuICAgIH0pO1xuICB9XG4gIGVsc2Uge1xuICAgIC8vIEV4cG9ydCB0byB0aGUgZ2xvYmFsIG9iamVjdC5cbiAgICByb290LnBsYXRmb3JtID0gcGxhdGZvcm07XG4gIH1cbn0uY2FsbCh0aGlzKSk7XG4iLCJ2YXIgdjEgPSByZXF1aXJlKCcuL3YxJyk7XG52YXIgdjQgPSByZXF1aXJlKCcuL3Y0Jyk7XG5cbnZhciB1dWlkID0gdjQ7XG51dWlkLnYxID0gdjE7XG51dWlkLnY0ID0gdjQ7XG5cbm1vZHVsZS5leHBvcnRzID0gdXVpZDtcbiIsIi8qKlxuICogQ29udmVydCBhcnJheSBvZiAxNiBieXRlIHZhbHVlcyB0byBVVUlEIHN0cmluZyBmb3JtYXQgb2YgdGhlIGZvcm06XG4gKiBYWFhYWFhYWC1YWFhYLVhYWFgtWFhYWC1YWFhYWFhYWFhYWFhcbiAqL1xudmFyIGJ5dGVUb0hleCA9IFtdO1xuZm9yICh2YXIgaSA9IDA7IGkgPCAyNTY7ICsraSkge1xuICBieXRlVG9IZXhbaV0gPSAoaSArIDB4MTAwKS50b1N0cmluZygxNikuc3Vic3RyKDEpO1xufVxuXG5mdW5jdGlvbiBieXRlc1RvVXVpZChidWYsIG9mZnNldCkge1xuICB2YXIgaSA9IG9mZnNldCB8fCAwO1xuICB2YXIgYnRoID0gYnl0ZVRvSGV4O1xuICAvLyBqb2luIHVzZWQgdG8gZml4IG1lbW9yeSBpc3N1ZSBjYXVzZWQgYnkgY29uY2F0ZW5hdGlvbjogaHR0cHM6Ly9idWdzLmNocm9taXVtLm9yZy9wL3Y4L2lzc3Vlcy9kZXRhaWw/aWQ9MzE3NSNjNFxuICByZXR1cm4gKFtidGhbYnVmW2krK11dLCBidGhbYnVmW2krK11dLCBcblx0YnRoW2J1ZltpKytdXSwgYnRoW2J1ZltpKytdXSwgJy0nLFxuXHRidGhbYnVmW2krK11dLCBidGhbYnVmW2krK11dLCAnLScsXG5cdGJ0aFtidWZbaSsrXV0sIGJ0aFtidWZbaSsrXV0sICctJyxcblx0YnRoW2J1ZltpKytdXSwgYnRoW2J1ZltpKytdXSwgJy0nLFxuXHRidGhbYnVmW2krK11dLCBidGhbYnVmW2krK11dLFxuXHRidGhbYnVmW2krK11dLCBidGhbYnVmW2krK11dLFxuXHRidGhbYnVmW2krK11dLCBidGhbYnVmW2krK11dXSkuam9pbignJyk7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gYnl0ZXNUb1V1aWQ7XG4iLCIvLyBVbmlxdWUgSUQgY3JlYXRpb24gcmVxdWlyZXMgYSBoaWdoIHF1YWxpdHkgcmFuZG9tICMgZ2VuZXJhdG9yLiAgSW4gdGhlXG4vLyBicm93c2VyIHRoaXMgaXMgYSBsaXR0bGUgY29tcGxpY2F0ZWQgZHVlIHRvIHVua25vd24gcXVhbGl0eSBvZiBNYXRoLnJhbmRvbSgpXG4vLyBhbmQgaW5jb25zaXN0ZW50IHN1cHBvcnQgZm9yIHRoZSBgY3J5cHRvYCBBUEkuICBXZSBkbyB0aGUgYmVzdCB3ZSBjYW4gdmlhXG4vLyBmZWF0dXJlLWRldGVjdGlvblxuXG4vLyBnZXRSYW5kb21WYWx1ZXMgbmVlZHMgdG8gYmUgaW52b2tlZCBpbiBhIGNvbnRleHQgd2hlcmUgXCJ0aGlzXCIgaXMgYSBDcnlwdG9cbi8vIGltcGxlbWVudGF0aW9uLiBBbHNvLCBmaW5kIHRoZSBjb21wbGV0ZSBpbXBsZW1lbnRhdGlvbiBvZiBjcnlwdG8gb24gSUUxMS5cbnZhciBnZXRSYW5kb21WYWx1ZXMgPSAodHlwZW9mKGNyeXB0bykgIT0gJ3VuZGVmaW5lZCcgJiYgY3J5cHRvLmdldFJhbmRvbVZhbHVlcyAmJiBjcnlwdG8uZ2V0UmFuZG9tVmFsdWVzLmJpbmQoY3J5cHRvKSkgfHxcbiAgICAgICAgICAgICAgICAgICAgICAodHlwZW9mKG1zQ3J5cHRvKSAhPSAndW5kZWZpbmVkJyAmJiB0eXBlb2Ygd2luZG93Lm1zQ3J5cHRvLmdldFJhbmRvbVZhbHVlcyA9PSAnZnVuY3Rpb24nICYmIG1zQ3J5cHRvLmdldFJhbmRvbVZhbHVlcy5iaW5kKG1zQ3J5cHRvKSk7XG5cbmlmIChnZXRSYW5kb21WYWx1ZXMpIHtcbiAgLy8gV0hBVFdHIGNyeXB0byBSTkcgLSBodHRwOi8vd2lraS53aGF0d2cub3JnL3dpa2kvQ3J5cHRvXG4gIHZhciBybmRzOCA9IG5ldyBVaW50OEFycmF5KDE2KTsgLy8gZXNsaW50LWRpc2FibGUtbGluZSBuby11bmRlZlxuXG4gIG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gd2hhdHdnUk5HKCkge1xuICAgIGdldFJhbmRvbVZhbHVlcyhybmRzOCk7XG4gICAgcmV0dXJuIHJuZHM4O1xuICB9O1xufSBlbHNlIHtcbiAgLy8gTWF0aC5yYW5kb20oKS1iYXNlZCAoUk5HKVxuICAvL1xuICAvLyBJZiBhbGwgZWxzZSBmYWlscywgdXNlIE1hdGgucmFuZG9tKCkuICBJdCdzIGZhc3QsIGJ1dCBpcyBvZiB1bnNwZWNpZmllZFxuICAvLyBxdWFsaXR5LlxuICB2YXIgcm5kcyA9IG5ldyBBcnJheSgxNik7XG5cbiAgbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBtYXRoUk5HKCkge1xuICAgIGZvciAodmFyIGkgPSAwLCByOyBpIDwgMTY7IGkrKykge1xuICAgICAgaWYgKChpICYgMHgwMykgPT09IDApIHIgPSBNYXRoLnJhbmRvbSgpICogMHgxMDAwMDAwMDA7XG4gICAgICBybmRzW2ldID0gciA+Pj4gKChpICYgMHgwMykgPDwgMykgJiAweGZmO1xuICAgIH1cblxuICAgIHJldHVybiBybmRzO1xuICB9O1xufVxuIiwidmFyIHJuZyA9IHJlcXVpcmUoJy4vbGliL3JuZycpO1xudmFyIGJ5dGVzVG9VdWlkID0gcmVxdWlyZSgnLi9saWIvYnl0ZXNUb1V1aWQnKTtcblxuLy8gKipgdjEoKWAgLSBHZW5lcmF0ZSB0aW1lLWJhc2VkIFVVSUQqKlxuLy9cbi8vIEluc3BpcmVkIGJ5IGh0dHBzOi8vZ2l0aHViLmNvbS9MaW9zSy9VVUlELmpzXG4vLyBhbmQgaHR0cDovL2RvY3MucHl0aG9uLm9yZy9saWJyYXJ5L3V1aWQuaHRtbFxuXG52YXIgX25vZGVJZDtcbnZhciBfY2xvY2tzZXE7XG5cbi8vIFByZXZpb3VzIHV1aWQgY3JlYXRpb24gdGltZVxudmFyIF9sYXN0TVNlY3MgPSAwO1xudmFyIF9sYXN0TlNlY3MgPSAwO1xuXG4vLyBTZWUgaHR0cHM6Ly9naXRodWIuY29tL2Jyb29mYS9ub2RlLXV1aWQgZm9yIEFQSSBkZXRhaWxzXG5mdW5jdGlvbiB2MShvcHRpb25zLCBidWYsIG9mZnNldCkge1xuICB2YXIgaSA9IGJ1ZiAmJiBvZmZzZXQgfHwgMDtcbiAgdmFyIGIgPSBidWYgfHwgW107XG5cbiAgb3B0aW9ucyA9IG9wdGlvbnMgfHwge307XG4gIHZhciBub2RlID0gb3B0aW9ucy5ub2RlIHx8IF9ub2RlSWQ7XG4gIHZhciBjbG9ja3NlcSA9IG9wdGlvbnMuY2xvY2tzZXEgIT09IHVuZGVmaW5lZCA/IG9wdGlvbnMuY2xvY2tzZXEgOiBfY2xvY2tzZXE7XG5cbiAgLy8gbm9kZSBhbmQgY2xvY2tzZXEgbmVlZCB0byBiZSBpbml0aWFsaXplZCB0byByYW5kb20gdmFsdWVzIGlmIHRoZXkncmUgbm90XG4gIC8vIHNwZWNpZmllZC4gIFdlIGRvIHRoaXMgbGF6aWx5IHRvIG1pbmltaXplIGlzc3VlcyByZWxhdGVkIHRvIGluc3VmZmljaWVudFxuICAvLyBzeXN0ZW0gZW50cm9weS4gIFNlZSAjMTg5XG4gIGlmIChub2RlID09IG51bGwgfHwgY2xvY2tzZXEgPT0gbnVsbCkge1xuICAgIHZhciBzZWVkQnl0ZXMgPSBybmcoKTtcbiAgICBpZiAobm9kZSA9PSBudWxsKSB7XG4gICAgICAvLyBQZXIgNC41LCBjcmVhdGUgYW5kIDQ4LWJpdCBub2RlIGlkLCAoNDcgcmFuZG9tIGJpdHMgKyBtdWx0aWNhc3QgYml0ID0gMSlcbiAgICAgIG5vZGUgPSBfbm9kZUlkID0gW1xuICAgICAgICBzZWVkQnl0ZXNbMF0gfCAweDAxLFxuICAgICAgICBzZWVkQnl0ZXNbMV0sIHNlZWRCeXRlc1syXSwgc2VlZEJ5dGVzWzNdLCBzZWVkQnl0ZXNbNF0sIHNlZWRCeXRlc1s1XVxuICAgICAgXTtcbiAgICB9XG4gICAgaWYgKGNsb2Nrc2VxID09IG51bGwpIHtcbiAgICAgIC8vIFBlciA0LjIuMiwgcmFuZG9taXplICgxNCBiaXQpIGNsb2Nrc2VxXG4gICAgICBjbG9ja3NlcSA9IF9jbG9ja3NlcSA9IChzZWVkQnl0ZXNbNl0gPDwgOCB8IHNlZWRCeXRlc1s3XSkgJiAweDNmZmY7XG4gICAgfVxuICB9XG5cbiAgLy8gVVVJRCB0aW1lc3RhbXBzIGFyZSAxMDAgbmFuby1zZWNvbmQgdW5pdHMgc2luY2UgdGhlIEdyZWdvcmlhbiBlcG9jaCxcbiAgLy8gKDE1ODItMTAtMTUgMDA6MDApLiAgSlNOdW1iZXJzIGFyZW4ndCBwcmVjaXNlIGVub3VnaCBmb3IgdGhpcywgc29cbiAgLy8gdGltZSBpcyBoYW5kbGVkIGludGVybmFsbHkgYXMgJ21zZWNzJyAoaW50ZWdlciBtaWxsaXNlY29uZHMpIGFuZCAnbnNlY3MnXG4gIC8vICgxMDAtbmFub3NlY29uZHMgb2Zmc2V0IGZyb20gbXNlY3MpIHNpbmNlIHVuaXggZXBvY2gsIDE5NzAtMDEtMDEgMDA6MDAuXG4gIHZhciBtc2VjcyA9IG9wdGlvbnMubXNlY3MgIT09IHVuZGVmaW5lZCA/IG9wdGlvbnMubXNlY3MgOiBuZXcgRGF0ZSgpLmdldFRpbWUoKTtcblxuICAvLyBQZXIgNC4yLjEuMiwgdXNlIGNvdW50IG9mIHV1aWQncyBnZW5lcmF0ZWQgZHVyaW5nIHRoZSBjdXJyZW50IGNsb2NrXG4gIC8vIGN5Y2xlIHRvIHNpbXVsYXRlIGhpZ2hlciByZXNvbHV0aW9uIGNsb2NrXG4gIHZhciBuc2VjcyA9IG9wdGlvbnMubnNlY3MgIT09IHVuZGVmaW5lZCA/IG9wdGlvbnMubnNlY3MgOiBfbGFzdE5TZWNzICsgMTtcblxuICAvLyBUaW1lIHNpbmNlIGxhc3QgdXVpZCBjcmVhdGlvbiAoaW4gbXNlY3MpXG4gIHZhciBkdCA9IChtc2VjcyAtIF9sYXN0TVNlY3MpICsgKG5zZWNzIC0gX2xhc3ROU2VjcykvMTAwMDA7XG5cbiAgLy8gUGVyIDQuMi4xLjIsIEJ1bXAgY2xvY2tzZXEgb24gY2xvY2sgcmVncmVzc2lvblxuICBpZiAoZHQgPCAwICYmIG9wdGlvbnMuY2xvY2tzZXEgPT09IHVuZGVmaW5lZCkge1xuICAgIGNsb2Nrc2VxID0gY2xvY2tzZXEgKyAxICYgMHgzZmZmO1xuICB9XG5cbiAgLy8gUmVzZXQgbnNlY3MgaWYgY2xvY2sgcmVncmVzc2VzIChuZXcgY2xvY2tzZXEpIG9yIHdlJ3ZlIG1vdmVkIG9udG8gYSBuZXdcbiAgLy8gdGltZSBpbnRlcnZhbFxuICBpZiAoKGR0IDwgMCB8fCBtc2VjcyA+IF9sYXN0TVNlY3MpICYmIG9wdGlvbnMubnNlY3MgPT09IHVuZGVmaW5lZCkge1xuICAgIG5zZWNzID0gMDtcbiAgfVxuXG4gIC8vIFBlciA0LjIuMS4yIFRocm93IGVycm9yIGlmIHRvbyBtYW55IHV1aWRzIGFyZSByZXF1ZXN0ZWRcbiAgaWYgKG5zZWNzID49IDEwMDAwKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCd1dWlkLnYxKCk6IENhblxcJ3QgY3JlYXRlIG1vcmUgdGhhbiAxME0gdXVpZHMvc2VjJyk7XG4gIH1cblxuICBfbGFzdE1TZWNzID0gbXNlY3M7XG4gIF9sYXN0TlNlY3MgPSBuc2VjcztcbiAgX2Nsb2Nrc2VxID0gY2xvY2tzZXE7XG5cbiAgLy8gUGVyIDQuMS40IC0gQ29udmVydCBmcm9tIHVuaXggZXBvY2ggdG8gR3JlZ29yaWFuIGVwb2NoXG4gIG1zZWNzICs9IDEyMjE5MjkyODAwMDAwO1xuXG4gIC8vIGB0aW1lX2xvd2BcbiAgdmFyIHRsID0gKChtc2VjcyAmIDB4ZmZmZmZmZikgKiAxMDAwMCArIG5zZWNzKSAlIDB4MTAwMDAwMDAwO1xuICBiW2krK10gPSB0bCA+Pj4gMjQgJiAweGZmO1xuICBiW2krK10gPSB0bCA+Pj4gMTYgJiAweGZmO1xuICBiW2krK10gPSB0bCA+Pj4gOCAmIDB4ZmY7XG4gIGJbaSsrXSA9IHRsICYgMHhmZjtcblxuICAvLyBgdGltZV9taWRgXG4gIHZhciB0bWggPSAobXNlY3MgLyAweDEwMDAwMDAwMCAqIDEwMDAwKSAmIDB4ZmZmZmZmZjtcbiAgYltpKytdID0gdG1oID4+PiA4ICYgMHhmZjtcbiAgYltpKytdID0gdG1oICYgMHhmZjtcblxuICAvLyBgdGltZV9oaWdoX2FuZF92ZXJzaW9uYFxuICBiW2krK10gPSB0bWggPj4+IDI0ICYgMHhmIHwgMHgxMDsgLy8gaW5jbHVkZSB2ZXJzaW9uXG4gIGJbaSsrXSA9IHRtaCA+Pj4gMTYgJiAweGZmO1xuXG4gIC8vIGBjbG9ja19zZXFfaGlfYW5kX3Jlc2VydmVkYCAoUGVyIDQuMi4yIC0gaW5jbHVkZSB2YXJpYW50KVxuICBiW2krK10gPSBjbG9ja3NlcSA+Pj4gOCB8IDB4ODA7XG5cbiAgLy8gYGNsb2NrX3NlcV9sb3dgXG4gIGJbaSsrXSA9IGNsb2Nrc2VxICYgMHhmZjtcblxuICAvLyBgbm9kZWBcbiAgZm9yICh2YXIgbiA9IDA7IG4gPCA2OyArK24pIHtcbiAgICBiW2kgKyBuXSA9IG5vZGVbbl07XG4gIH1cblxuICByZXR1cm4gYnVmID8gYnVmIDogYnl0ZXNUb1V1aWQoYik7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gdjE7XG4iLCJ2YXIgcm5nID0gcmVxdWlyZSgnLi9saWIvcm5nJyk7XG52YXIgYnl0ZXNUb1V1aWQgPSByZXF1aXJlKCcuL2xpYi9ieXRlc1RvVXVpZCcpO1xuXG5mdW5jdGlvbiB2NChvcHRpb25zLCBidWYsIG9mZnNldCkge1xuICB2YXIgaSA9IGJ1ZiAmJiBvZmZzZXQgfHwgMDtcblxuICBpZiAodHlwZW9mKG9wdGlvbnMpID09ICdzdHJpbmcnKSB7XG4gICAgYnVmID0gb3B0aW9ucyA9PT0gJ2JpbmFyeScgPyBuZXcgQXJyYXkoMTYpIDogbnVsbDtcbiAgICBvcHRpb25zID0gbnVsbDtcbiAgfVxuICBvcHRpb25zID0gb3B0aW9ucyB8fCB7fTtcblxuICB2YXIgcm5kcyA9IG9wdGlvbnMucmFuZG9tIHx8IChvcHRpb25zLnJuZyB8fCBybmcpKCk7XG5cbiAgLy8gUGVyIDQuNCwgc2V0IGJpdHMgZm9yIHZlcnNpb24gYW5kIGBjbG9ja19zZXFfaGlfYW5kX3Jlc2VydmVkYFxuICBybmRzWzZdID0gKHJuZHNbNl0gJiAweDBmKSB8IDB4NDA7XG4gIHJuZHNbOF0gPSAocm5kc1s4XSAmIDB4M2YpIHwgMHg4MDtcblxuICAvLyBDb3B5IGJ5dGVzIHRvIGJ1ZmZlciwgaWYgcHJvdmlkZWRcbiAgaWYgKGJ1Zikge1xuICAgIGZvciAodmFyIGlpID0gMDsgaWkgPCAxNjsgKytpaSkge1xuICAgICAgYnVmW2kgKyBpaV0gPSBybmRzW2lpXTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gYnVmIHx8IGJ5dGVzVG9VdWlkKHJuZHMpO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHY0O1xuIiwiLypcclxuV2lsZEVtaXR0ZXIuanMgaXMgYSBzbGltIGxpdHRsZSBldmVudCBlbWl0dGVyIGJ5IEBoZW5yaWtqb3JldGVnIGxhcmdlbHkgYmFzZWRcclxub24gQHZpc2lvbm1lZGlhJ3MgRW1pdHRlciBmcm9tIFVJIEtpdC5cclxuXHJcbldoeT8gSSB3YW50ZWQgaXQgc3RhbmRhbG9uZS5cclxuXHJcbkkgYWxzbyB3YW50ZWQgc3VwcG9ydCBmb3Igd2lsZGNhcmQgZW1pdHRlcnMgbGlrZSB0aGlzOlxyXG5cclxuZW1pdHRlci5vbignKicsIGZ1bmN0aW9uIChldmVudE5hbWUsIG90aGVyLCBldmVudCwgcGF5bG9hZHMpIHtcclxuXHJcbn0pO1xyXG5cclxuZW1pdHRlci5vbignc29tZW5hbWVzcGFjZSonLCBmdW5jdGlvbiAoZXZlbnROYW1lLCBwYXlsb2Fkcykge1xyXG5cclxufSk7XHJcblxyXG5QbGVhc2Ugbm90ZSB0aGF0IGNhbGxiYWNrcyB0cmlnZ2VyZWQgYnkgd2lsZGNhcmQgcmVnaXN0ZXJlZCBldmVudHMgYWxzbyBnZXRcclxudGhlIGV2ZW50IG5hbWUgYXMgdGhlIGZpcnN0IGFyZ3VtZW50LlxyXG4qL1xyXG5cclxubW9kdWxlLmV4cG9ydHMgPSBXaWxkRW1pdHRlcjtcclxuXHJcbmZ1bmN0aW9uIFdpbGRFbWl0dGVyKCkgeyB9XHJcblxyXG5XaWxkRW1pdHRlci5taXhpbiA9IGZ1bmN0aW9uIChjb25zdHJ1Y3Rvcikge1xyXG4gICAgdmFyIHByb3RvdHlwZSA9IGNvbnN0cnVjdG9yLnByb3RvdHlwZSB8fCBjb25zdHJ1Y3RvcjtcclxuXHJcbiAgICBwcm90b3R5cGUuaXNXaWxkRW1pdHRlcj0gdHJ1ZTtcclxuXHJcbiAgICAvLyBMaXN0ZW4gb24gdGhlIGdpdmVuIGBldmVudGAgd2l0aCBgZm5gLiBTdG9yZSBhIGdyb3VwIG5hbWUgaWYgcHJlc2VudC5cclxuICAgIHByb3RvdHlwZS5vbiA9IGZ1bmN0aW9uIChldmVudCwgZ3JvdXBOYW1lLCBmbikge1xyXG4gICAgICAgIHRoaXMuY2FsbGJhY2tzID0gdGhpcy5jYWxsYmFja3MgfHwge307XHJcbiAgICAgICAgdmFyIGhhc0dyb3VwID0gKGFyZ3VtZW50cy5sZW5ndGggPT09IDMpLFxyXG4gICAgICAgICAgICBncm91cCA9IGhhc0dyb3VwID8gYXJndW1lbnRzWzFdIDogdW5kZWZpbmVkLFxyXG4gICAgICAgICAgICBmdW5jID0gaGFzR3JvdXAgPyBhcmd1bWVudHNbMl0gOiBhcmd1bWVudHNbMV07XHJcbiAgICAgICAgZnVuYy5fZ3JvdXBOYW1lID0gZ3JvdXA7XHJcbiAgICAgICAgKHRoaXMuY2FsbGJhY2tzW2V2ZW50XSA9IHRoaXMuY2FsbGJhY2tzW2V2ZW50XSB8fCBbXSkucHVzaChmdW5jKTtcclxuICAgICAgICByZXR1cm4gdGhpcztcclxuICAgIH07XHJcblxyXG4gICAgLy8gQWRkcyBhbiBgZXZlbnRgIGxpc3RlbmVyIHRoYXQgd2lsbCBiZSBpbnZva2VkIGEgc2luZ2xlXHJcbiAgICAvLyB0aW1lIHRoZW4gYXV0b21hdGljYWxseSByZW1vdmVkLlxyXG4gICAgcHJvdG90eXBlLm9uY2UgPSBmdW5jdGlvbiAoZXZlbnQsIGdyb3VwTmFtZSwgZm4pIHtcclxuICAgICAgICB2YXIgc2VsZiA9IHRoaXMsXHJcbiAgICAgICAgICAgIGhhc0dyb3VwID0gKGFyZ3VtZW50cy5sZW5ndGggPT09IDMpLFxyXG4gICAgICAgICAgICBncm91cCA9IGhhc0dyb3VwID8gYXJndW1lbnRzWzFdIDogdW5kZWZpbmVkLFxyXG4gICAgICAgICAgICBmdW5jID0gaGFzR3JvdXAgPyBhcmd1bWVudHNbMl0gOiBhcmd1bWVudHNbMV07XHJcbiAgICAgICAgZnVuY3Rpb24gb24oKSB7XHJcbiAgICAgICAgICAgIHNlbGYub2ZmKGV2ZW50LCBvbik7XHJcbiAgICAgICAgICAgIGZ1bmMuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgdGhpcy5vbihldmVudCwgZ3JvdXAsIG9uKTtcclxuICAgICAgICByZXR1cm4gdGhpcztcclxuICAgIH07XHJcblxyXG4gICAgLy8gVW5iaW5kcyBhbiBlbnRpcmUgZ3JvdXBcclxuICAgIHByb3RvdHlwZS5yZWxlYXNlR3JvdXAgPSBmdW5jdGlvbiAoZ3JvdXBOYW1lKSB7XHJcbiAgICAgICAgdGhpcy5jYWxsYmFja3MgPSB0aGlzLmNhbGxiYWNrcyB8fCB7fTtcclxuICAgICAgICB2YXIgaXRlbSwgaSwgbGVuLCBoYW5kbGVycztcclxuICAgICAgICBmb3IgKGl0ZW0gaW4gdGhpcy5jYWxsYmFja3MpIHtcclxuICAgICAgICAgICAgaGFuZGxlcnMgPSB0aGlzLmNhbGxiYWNrc1tpdGVtXTtcclxuICAgICAgICAgICAgZm9yIChpID0gMCwgbGVuID0gaGFuZGxlcnMubGVuZ3RoOyBpIDwgbGVuOyBpKyspIHtcclxuICAgICAgICAgICAgICAgIGlmIChoYW5kbGVyc1tpXS5fZ3JvdXBOYW1lID09PSBncm91cE5hbWUpIHtcclxuICAgICAgICAgICAgICAgICAgICAvL2NvbnNvbGUubG9nKCdyZW1vdmluZycpO1xyXG4gICAgICAgICAgICAgICAgICAgIC8vIHJlbW92ZSBpdCBhbmQgc2hvcnRlbiB0aGUgYXJyYXkgd2UncmUgbG9vcGluZyB0aHJvdWdoXHJcbiAgICAgICAgICAgICAgICAgICAgaGFuZGxlcnMuc3BsaWNlKGksIDEpO1xyXG4gICAgICAgICAgICAgICAgICAgIGktLTtcclxuICAgICAgICAgICAgICAgICAgICBsZW4tLTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgICAgICByZXR1cm4gdGhpcztcclxuICAgIH07XHJcblxyXG4gICAgLy8gUmVtb3ZlIHRoZSBnaXZlbiBjYWxsYmFjayBmb3IgYGV2ZW50YCBvciBhbGxcclxuICAgIC8vIHJlZ2lzdGVyZWQgY2FsbGJhY2tzLlxyXG4gICAgcHJvdG90eXBlLm9mZiA9IGZ1bmN0aW9uIChldmVudCwgZm4pIHtcclxuICAgICAgICB0aGlzLmNhbGxiYWNrcyA9IHRoaXMuY2FsbGJhY2tzIHx8IHt9O1xyXG4gICAgICAgIHZhciBjYWxsYmFja3MgPSB0aGlzLmNhbGxiYWNrc1tldmVudF0sXHJcbiAgICAgICAgICAgIGk7XHJcblxyXG4gICAgICAgIGlmICghY2FsbGJhY2tzKSByZXR1cm4gdGhpcztcclxuXHJcbiAgICAgICAgLy8gcmVtb3ZlIGFsbCBoYW5kbGVyc1xyXG4gICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAxKSB7XHJcbiAgICAgICAgICAgIGRlbGV0ZSB0aGlzLmNhbGxiYWNrc1tldmVudF07XHJcbiAgICAgICAgICAgIHJldHVybiB0aGlzO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgLy8gcmVtb3ZlIHNwZWNpZmljIGhhbmRsZXJcclxuICAgICAgICBpID0gY2FsbGJhY2tzLmluZGV4T2YoZm4pO1xyXG4gICAgICAgIGNhbGxiYWNrcy5zcGxpY2UoaSwgMSk7XHJcbiAgICAgICAgaWYgKGNhbGxiYWNrcy5sZW5ndGggPT09IDApIHtcclxuICAgICAgICAgICAgZGVsZXRlIHRoaXMuY2FsbGJhY2tzW2V2ZW50XTtcclxuICAgICAgICB9XHJcbiAgICAgICAgcmV0dXJuIHRoaXM7XHJcbiAgICB9O1xyXG5cclxuICAgIC8vLyBFbWl0IGBldmVudGAgd2l0aCB0aGUgZ2l2ZW4gYXJncy5cclxuICAgIC8vIGFsc28gY2FsbHMgYW55IGAqYCBoYW5kbGVyc1xyXG4gICAgcHJvdG90eXBlLmVtaXQgPSBmdW5jdGlvbiAoZXZlbnQpIHtcclxuICAgICAgICB0aGlzLmNhbGxiYWNrcyA9IHRoaXMuY2FsbGJhY2tzIHx8IHt9O1xyXG4gICAgICAgIHZhciBhcmdzID0gW10uc2xpY2UuY2FsbChhcmd1bWVudHMsIDEpLFxyXG4gICAgICAgICAgICBjYWxsYmFja3MgPSB0aGlzLmNhbGxiYWNrc1tldmVudF0sXHJcbiAgICAgICAgICAgIHNwZWNpYWxDYWxsYmFja3MgPSB0aGlzLmdldFdpbGRjYXJkQ2FsbGJhY2tzKGV2ZW50KSxcclxuICAgICAgICAgICAgaSxcclxuICAgICAgICAgICAgbGVuLFxyXG4gICAgICAgICAgICBpdGVtLFxyXG4gICAgICAgICAgICBsaXN0ZW5lcnM7XHJcblxyXG4gICAgICAgIGlmIChjYWxsYmFja3MpIHtcclxuICAgICAgICAgICAgbGlzdGVuZXJzID0gY2FsbGJhY2tzLnNsaWNlKCk7XHJcbiAgICAgICAgICAgIGZvciAoaSA9IDAsIGxlbiA9IGxpc3RlbmVycy5sZW5ndGg7IGkgPCBsZW47ICsraSkge1xyXG4gICAgICAgICAgICAgICAgaWYgKCFsaXN0ZW5lcnNbaV0pIHtcclxuICAgICAgICAgICAgICAgICAgICBicmVhaztcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIGxpc3RlbmVyc1tpXS5hcHBseSh0aGlzLCBhcmdzKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgaWYgKHNwZWNpYWxDYWxsYmFja3MpIHtcclxuICAgICAgICAgICAgbGVuID0gc3BlY2lhbENhbGxiYWNrcy5sZW5ndGg7XHJcbiAgICAgICAgICAgIGxpc3RlbmVycyA9IHNwZWNpYWxDYWxsYmFja3Muc2xpY2UoKTtcclxuICAgICAgICAgICAgZm9yIChpID0gMCwgbGVuID0gbGlzdGVuZXJzLmxlbmd0aDsgaSA8IGxlbjsgKytpKSB7XHJcbiAgICAgICAgICAgICAgICBpZiAoIWxpc3RlbmVyc1tpXSkge1xyXG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgbGlzdGVuZXJzW2ldLmFwcGx5KHRoaXMsIFtldmVudF0uY29uY2F0KGFyZ3MpKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgcmV0dXJuIHRoaXM7XHJcbiAgICB9O1xyXG5cclxuICAgIC8vIEhlbHBlciBmb3IgZm9yIGZpbmRpbmcgc3BlY2lhbCB3aWxkY2FyZCBldmVudCBoYW5kbGVycyB0aGF0IG1hdGNoIHRoZSBldmVudFxyXG4gICAgcHJvdG90eXBlLmdldFdpbGRjYXJkQ2FsbGJhY2tzID0gZnVuY3Rpb24gKGV2ZW50TmFtZSkge1xyXG4gICAgICAgIHRoaXMuY2FsbGJhY2tzID0gdGhpcy5jYWxsYmFja3MgfHwge307XHJcbiAgICAgICAgdmFyIGl0ZW0sXHJcbiAgICAgICAgICAgIHNwbGl0LFxyXG4gICAgICAgICAgICByZXN1bHQgPSBbXTtcclxuXHJcbiAgICAgICAgZm9yIChpdGVtIGluIHRoaXMuY2FsbGJhY2tzKSB7XHJcbiAgICAgICAgICAgIHNwbGl0ID0gaXRlbS5zcGxpdCgnKicpO1xyXG4gICAgICAgICAgICBpZiAoaXRlbSA9PT0gJyonIHx8IChzcGxpdC5sZW5ndGggPT09IDIgJiYgZXZlbnROYW1lLnNsaWNlKDAsIHNwbGl0WzBdLmxlbmd0aCkgPT09IHNwbGl0WzBdKSkge1xyXG4gICAgICAgICAgICAgICAgcmVzdWx0ID0gcmVzdWx0LmNvbmNhdCh0aGlzLmNhbGxiYWNrc1tpdGVtXSk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcclxuICAgIH07XHJcblxyXG59O1xyXG5cclxuV2lsZEVtaXR0ZXIubWl4aW4oV2lsZEVtaXR0ZXIpO1xyXG4iLCIvKiFcbiAqIEV2ZW50RW1pdHRlciB2NS4yLjUgLSBnaXQuaW8vZWVcbiAqIFVubGljZW5zZSAtIGh0dHA6Ly91bmxpY2Vuc2Uub3JnL1xuICogT2xpdmVyIENhbGR3ZWxsIC0gaHR0cDovL29saS5tZS51ay9cbiAqIEBwcmVzZXJ2ZVxuICovXG5cbjsoZnVuY3Rpb24gKGV4cG9ydHMpIHtcbiAgICAndXNlIHN0cmljdCc7XG5cbiAgICAvKipcbiAgICAgKiBDbGFzcyBmb3IgbWFuYWdpbmcgZXZlbnRzLlxuICAgICAqIENhbiBiZSBleHRlbmRlZCB0byBwcm92aWRlIGV2ZW50IGZ1bmN0aW9uYWxpdHkgaW4gb3RoZXIgY2xhc3Nlcy5cbiAgICAgKlxuICAgICAqIEBjbGFzcyBFdmVudEVtaXR0ZXIgTWFuYWdlcyBldmVudCByZWdpc3RlcmluZyBhbmQgZW1pdHRpbmcuXG4gICAgICovXG4gICAgZnVuY3Rpb24gRXZlbnRFbWl0dGVyKCkge31cblxuICAgIC8vIFNob3J0Y3V0cyB0byBpbXByb3ZlIHNwZWVkIGFuZCBzaXplXG4gICAgdmFyIHByb3RvID0gRXZlbnRFbWl0dGVyLnByb3RvdHlwZTtcbiAgICB2YXIgb3JpZ2luYWxHbG9iYWxWYWx1ZSA9IGV4cG9ydHMuRXZlbnRFbWl0dGVyO1xuXG4gICAgLyoqXG4gICAgICogRmluZHMgdGhlIGluZGV4IG9mIHRoZSBsaXN0ZW5lciBmb3IgdGhlIGV2ZW50IGluIGl0cyBzdG9yYWdlIGFycmF5LlxuICAgICAqXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbltdfSBsaXN0ZW5lcnMgQXJyYXkgb2YgbGlzdGVuZXJzIHRvIHNlYXJjaCB0aHJvdWdoLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGxpc3RlbmVyIE1ldGhvZCB0byBsb29rIGZvci5cbiAgICAgKiBAcmV0dXJuIHtOdW1iZXJ9IEluZGV4IG9mIHRoZSBzcGVjaWZpZWQgbGlzdGVuZXIsIC0xIGlmIG5vdCBmb3VuZFxuICAgICAqIEBhcGkgcHJpdmF0ZVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGluZGV4T2ZMaXN0ZW5lcihsaXN0ZW5lcnMsIGxpc3RlbmVyKSB7XG4gICAgICAgIHZhciBpID0gbGlzdGVuZXJzLmxlbmd0aDtcbiAgICAgICAgd2hpbGUgKGktLSkge1xuICAgICAgICAgICAgaWYgKGxpc3RlbmVyc1tpXS5saXN0ZW5lciA9PT0gbGlzdGVuZXIpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiAtMTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBBbGlhcyBhIG1ldGhvZCB3aGlsZSBrZWVwaW5nIHRoZSBjb250ZXh0IGNvcnJlY3QsIHRvIGFsbG93IGZvciBvdmVyd3JpdGluZyBvZiB0YXJnZXQgbWV0aG9kLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtTdHJpbmd9IG5hbWUgVGhlIG5hbWUgb2YgdGhlIHRhcmdldCBtZXRob2QuXG4gICAgICogQHJldHVybiB7RnVuY3Rpb259IFRoZSBhbGlhc2VkIG1ldGhvZFxuICAgICAqIEBhcGkgcHJpdmF0ZVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGFsaWFzKG5hbWUpIHtcbiAgICAgICAgcmV0dXJuIGZ1bmN0aW9uIGFsaWFzQ2xvc3VyZSgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzW25hbWVdLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyB0aGUgbGlzdGVuZXIgYXJyYXkgZm9yIHRoZSBzcGVjaWZpZWQgZXZlbnQuXG4gICAgICogV2lsbCBpbml0aWFsaXNlIHRoZSBldmVudCBvYmplY3QgYW5kIGxpc3RlbmVyIGFycmF5cyBpZiByZXF1aXJlZC5cbiAgICAgKiBXaWxsIHJldHVybiBhbiBvYmplY3QgaWYgeW91IHVzZSBhIHJlZ2V4IHNlYXJjaC4gVGhlIG9iamVjdCBjb250YWlucyBrZXlzIGZvciBlYWNoIG1hdGNoZWQgZXZlbnQuIFNvIC9iYVtyel0vIG1pZ2h0IHJldHVybiBhbiBvYmplY3QgY29udGFpbmluZyBiYXIgYW5kIGJhei4gQnV0IG9ubHkgaWYgeW91IGhhdmUgZWl0aGVyIGRlZmluZWQgdGhlbSB3aXRoIGRlZmluZUV2ZW50IG9yIGFkZGVkIHNvbWUgbGlzdGVuZXJzIHRvIHRoZW0uXG4gICAgICogRWFjaCBwcm9wZXJ0eSBpbiB0aGUgb2JqZWN0IHJlc3BvbnNlIGlzIGFuIGFycmF5IG9mIGxpc3RlbmVyIGZ1bmN0aW9ucy5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfFJlZ0V4cH0gZXZ0IE5hbWUgb2YgdGhlIGV2ZW50IHRvIHJldHVybiB0aGUgbGlzdGVuZXJzIGZyb20uXG4gICAgICogQHJldHVybiB7RnVuY3Rpb25bXXxPYmplY3R9IEFsbCBsaXN0ZW5lciBmdW5jdGlvbnMgZm9yIHRoZSBldmVudC5cbiAgICAgKi9cbiAgICBwcm90by5nZXRMaXN0ZW5lcnMgPSBmdW5jdGlvbiBnZXRMaXN0ZW5lcnMoZXZ0KSB7XG4gICAgICAgIHZhciBldmVudHMgPSB0aGlzLl9nZXRFdmVudHMoKTtcbiAgICAgICAgdmFyIHJlc3BvbnNlO1xuICAgICAgICB2YXIga2V5O1xuXG4gICAgICAgIC8vIFJldHVybiBhIGNvbmNhdGVuYXRlZCBhcnJheSBvZiBhbGwgbWF0Y2hpbmcgZXZlbnRzIGlmXG4gICAgICAgIC8vIHRoZSBzZWxlY3RvciBpcyBhIHJlZ3VsYXIgZXhwcmVzc2lvbi5cbiAgICAgICAgaWYgKGV2dCBpbnN0YW5jZW9mIFJlZ0V4cCkge1xuICAgICAgICAgICAgcmVzcG9uc2UgPSB7fTtcbiAgICAgICAgICAgIGZvciAoa2V5IGluIGV2ZW50cykge1xuICAgICAgICAgICAgICAgIGlmIChldmVudHMuaGFzT3duUHJvcGVydHkoa2V5KSAmJiBldnQudGVzdChrZXkpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc3BvbnNlW2tleV0gPSBldmVudHNba2V5XTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICByZXNwb25zZSA9IGV2ZW50c1tldnRdIHx8IChldmVudHNbZXZ0XSA9IFtdKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiByZXNwb25zZTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogVGFrZXMgYSBsaXN0IG9mIGxpc3RlbmVyIG9iamVjdHMgYW5kIGZsYXR0ZW5zIGl0IGludG8gYSBsaXN0IG9mIGxpc3RlbmVyIGZ1bmN0aW9ucy5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7T2JqZWN0W119IGxpc3RlbmVycyBSYXcgbGlzdGVuZXIgb2JqZWN0cy5cbiAgICAgKiBAcmV0dXJuIHtGdW5jdGlvbltdfSBKdXN0IHRoZSBsaXN0ZW5lciBmdW5jdGlvbnMuXG4gICAgICovXG4gICAgcHJvdG8uZmxhdHRlbkxpc3RlbmVycyA9IGZ1bmN0aW9uIGZsYXR0ZW5MaXN0ZW5lcnMobGlzdGVuZXJzKSB7XG4gICAgICAgIHZhciBmbGF0TGlzdGVuZXJzID0gW107XG4gICAgICAgIHZhciBpO1xuXG4gICAgICAgIGZvciAoaSA9IDA7IGkgPCBsaXN0ZW5lcnMubGVuZ3RoOyBpICs9IDEpIHtcbiAgICAgICAgICAgIGZsYXRMaXN0ZW5lcnMucHVzaChsaXN0ZW5lcnNbaV0ubGlzdGVuZXIpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGZsYXRMaXN0ZW5lcnM7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEZldGNoZXMgdGhlIHJlcXVlc3RlZCBsaXN0ZW5lcnMgdmlhIGdldExpc3RlbmVycyBidXQgd2lsbCBhbHdheXMgcmV0dXJuIHRoZSByZXN1bHRzIGluc2lkZSBhbiBvYmplY3QuIFRoaXMgaXMgbWFpbmx5IGZvciBpbnRlcm5hbCB1c2UgYnV0IG90aGVycyBtYXkgZmluZCBpdCB1c2VmdWwuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1N0cmluZ3xSZWdFeHB9IGV2dCBOYW1lIG9mIHRoZSBldmVudCB0byByZXR1cm4gdGhlIGxpc3RlbmVycyBmcm9tLlxuICAgICAqIEByZXR1cm4ge09iamVjdH0gQWxsIGxpc3RlbmVyIGZ1bmN0aW9ucyBmb3IgYW4gZXZlbnQgaW4gYW4gb2JqZWN0LlxuICAgICAqL1xuICAgIHByb3RvLmdldExpc3RlbmVyc0FzT2JqZWN0ID0gZnVuY3Rpb24gZ2V0TGlzdGVuZXJzQXNPYmplY3QoZXZ0KSB7XG4gICAgICAgIHZhciBsaXN0ZW5lcnMgPSB0aGlzLmdldExpc3RlbmVycyhldnQpO1xuICAgICAgICB2YXIgcmVzcG9uc2U7XG5cbiAgICAgICAgaWYgKGxpc3RlbmVycyBpbnN0YW5jZW9mIEFycmF5KSB7XG4gICAgICAgICAgICByZXNwb25zZSA9IHt9O1xuICAgICAgICAgICAgcmVzcG9uc2VbZXZ0XSA9IGxpc3RlbmVycztcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiByZXNwb25zZSB8fCBsaXN0ZW5lcnM7XG4gICAgfTtcblxuICAgIGZ1bmN0aW9uIGlzVmFsaWRMaXN0ZW5lciAobGlzdGVuZXIpIHtcbiAgICAgICAgaWYgKHR5cGVvZiBsaXN0ZW5lciA9PT0gJ2Z1bmN0aW9uJyB8fCBsaXN0ZW5lciBpbnN0YW5jZW9mIFJlZ0V4cCkge1xuICAgICAgICAgICAgcmV0dXJuIHRydWVcbiAgICAgICAgfSBlbHNlIGlmIChsaXN0ZW5lciAmJiB0eXBlb2YgbGlzdGVuZXIgPT09ICdvYmplY3QnKSB7XG4gICAgICAgICAgICByZXR1cm4gaXNWYWxpZExpc3RlbmVyKGxpc3RlbmVyLmxpc3RlbmVyKVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlXG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBBZGRzIGEgbGlzdGVuZXIgZnVuY3Rpb24gdG8gdGhlIHNwZWNpZmllZCBldmVudC5cbiAgICAgKiBUaGUgbGlzdGVuZXIgd2lsbCBub3QgYmUgYWRkZWQgaWYgaXQgaXMgYSBkdXBsaWNhdGUuXG4gICAgICogSWYgdGhlIGxpc3RlbmVyIHJldHVybnMgdHJ1ZSB0aGVuIGl0IHdpbGwgYmUgcmVtb3ZlZCBhZnRlciBpdCBpcyBjYWxsZWQuXG4gICAgICogSWYgeW91IHBhc3MgYSByZWd1bGFyIGV4cHJlc3Npb24gYXMgdGhlIGV2ZW50IG5hbWUgdGhlbiB0aGUgbGlzdGVuZXIgd2lsbCBiZSBhZGRlZCB0byBhbGwgZXZlbnRzIHRoYXQgbWF0Y2ggaXQuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1N0cmluZ3xSZWdFeHB9IGV2dCBOYW1lIG9mIHRoZSBldmVudCB0byBhdHRhY2ggdGhlIGxpc3RlbmVyIHRvLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGxpc3RlbmVyIE1ldGhvZCB0byBiZSBjYWxsZWQgd2hlbiB0aGUgZXZlbnQgaXMgZW1pdHRlZC4gSWYgdGhlIGZ1bmN0aW9uIHJldHVybnMgdHJ1ZSB0aGVuIGl0IHdpbGwgYmUgcmVtb3ZlZCBhZnRlciBjYWxsaW5nLlxuICAgICAqIEByZXR1cm4ge09iamVjdH0gQ3VycmVudCBpbnN0YW5jZSBvZiBFdmVudEVtaXR0ZXIgZm9yIGNoYWluaW5nLlxuICAgICAqL1xuICAgIHByb3RvLmFkZExpc3RlbmVyID0gZnVuY3Rpb24gYWRkTGlzdGVuZXIoZXZ0LCBsaXN0ZW5lcikge1xuICAgICAgICBpZiAoIWlzVmFsaWRMaXN0ZW5lcihsaXN0ZW5lcikpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2xpc3RlbmVyIG11c3QgYmUgYSBmdW5jdGlvbicpO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIGxpc3RlbmVycyA9IHRoaXMuZ2V0TGlzdGVuZXJzQXNPYmplY3QoZXZ0KTtcbiAgICAgICAgdmFyIGxpc3RlbmVySXNXcmFwcGVkID0gdHlwZW9mIGxpc3RlbmVyID09PSAnb2JqZWN0JztcbiAgICAgICAgdmFyIGtleTtcblxuICAgICAgICBmb3IgKGtleSBpbiBsaXN0ZW5lcnMpIHtcbiAgICAgICAgICAgIGlmIChsaXN0ZW5lcnMuaGFzT3duUHJvcGVydHkoa2V5KSAmJiBpbmRleE9mTGlzdGVuZXIobGlzdGVuZXJzW2tleV0sIGxpc3RlbmVyKSA9PT0gLTEpIHtcbiAgICAgICAgICAgICAgICBsaXN0ZW5lcnNba2V5XS5wdXNoKGxpc3RlbmVySXNXcmFwcGVkID8gbGlzdGVuZXIgOiB7XG4gICAgICAgICAgICAgICAgICAgIGxpc3RlbmVyOiBsaXN0ZW5lcixcbiAgICAgICAgICAgICAgICAgICAgb25jZTogZmFsc2VcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBBbGlhcyBvZiBhZGRMaXN0ZW5lclxuICAgICAqL1xuICAgIHByb3RvLm9uID0gYWxpYXMoJ2FkZExpc3RlbmVyJyk7XG5cbiAgICAvKipcbiAgICAgKiBTZW1pLWFsaWFzIG9mIGFkZExpc3RlbmVyLiBJdCB3aWxsIGFkZCBhIGxpc3RlbmVyIHRoYXQgd2lsbCBiZVxuICAgICAqIGF1dG9tYXRpY2FsbHkgcmVtb3ZlZCBhZnRlciBpdHMgZmlyc3QgZXhlY3V0aW9uLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtTdHJpbmd8UmVnRXhwfSBldnQgTmFtZSBvZiB0aGUgZXZlbnQgdG8gYXR0YWNoIHRoZSBsaXN0ZW5lciB0by5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBsaXN0ZW5lciBNZXRob2QgdG8gYmUgY2FsbGVkIHdoZW4gdGhlIGV2ZW50IGlzIGVtaXR0ZWQuIElmIHRoZSBmdW5jdGlvbiByZXR1cm5zIHRydWUgdGhlbiBpdCB3aWxsIGJlIHJlbW92ZWQgYWZ0ZXIgY2FsbGluZy5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEN1cnJlbnQgaW5zdGFuY2Ugb2YgRXZlbnRFbWl0dGVyIGZvciBjaGFpbmluZy5cbiAgICAgKi9cbiAgICBwcm90by5hZGRPbmNlTGlzdGVuZXIgPSBmdW5jdGlvbiBhZGRPbmNlTGlzdGVuZXIoZXZ0LCBsaXN0ZW5lcikge1xuICAgICAgICByZXR1cm4gdGhpcy5hZGRMaXN0ZW5lcihldnQsIHtcbiAgICAgICAgICAgIGxpc3RlbmVyOiBsaXN0ZW5lcixcbiAgICAgICAgICAgIG9uY2U6IHRydWVcbiAgICAgICAgfSk7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEFsaWFzIG9mIGFkZE9uY2VMaXN0ZW5lci5cbiAgICAgKi9cbiAgICBwcm90by5vbmNlID0gYWxpYXMoJ2FkZE9uY2VMaXN0ZW5lcicpO1xuXG4gICAgLyoqXG4gICAgICogRGVmaW5lcyBhbiBldmVudCBuYW1lLiBUaGlzIGlzIHJlcXVpcmVkIGlmIHlvdSB3YW50IHRvIHVzZSBhIHJlZ2V4IHRvIGFkZCBhIGxpc3RlbmVyIHRvIG11bHRpcGxlIGV2ZW50cyBhdCBvbmNlLiBJZiB5b3UgZG9uJ3QgZG8gdGhpcyB0aGVuIGhvdyBkbyB5b3UgZXhwZWN0IGl0IHRvIGtub3cgd2hhdCBldmVudCB0byBhZGQgdG8/IFNob3VsZCBpdCBqdXN0IGFkZCB0byBldmVyeSBwb3NzaWJsZSBtYXRjaCBmb3IgYSByZWdleD8gTm8uIFRoYXQgaXMgc2NhcnkgYW5kIGJhZC5cbiAgICAgKiBZb3UgbmVlZCB0byB0ZWxsIGl0IHdoYXQgZXZlbnQgbmFtZXMgc2hvdWxkIGJlIG1hdGNoZWQgYnkgYSByZWdleC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfSBldnQgTmFtZSBvZiB0aGUgZXZlbnQgdG8gY3JlYXRlLlxuICAgICAqIEByZXR1cm4ge09iamVjdH0gQ3VycmVudCBpbnN0YW5jZSBvZiBFdmVudEVtaXR0ZXIgZm9yIGNoYWluaW5nLlxuICAgICAqL1xuICAgIHByb3RvLmRlZmluZUV2ZW50ID0gZnVuY3Rpb24gZGVmaW5lRXZlbnQoZXZ0KSB7XG4gICAgICAgIHRoaXMuZ2V0TGlzdGVuZXJzKGV2dCk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBVc2VzIGRlZmluZUV2ZW50IHRvIGRlZmluZSBtdWx0aXBsZSBldmVudHMuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1N0cmluZ1tdfSBldnRzIEFuIGFycmF5IG9mIGV2ZW50IG5hbWVzIHRvIGRlZmluZS5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEN1cnJlbnQgaW5zdGFuY2Ugb2YgRXZlbnRFbWl0dGVyIGZvciBjaGFpbmluZy5cbiAgICAgKi9cbiAgICBwcm90by5kZWZpbmVFdmVudHMgPSBmdW5jdGlvbiBkZWZpbmVFdmVudHMoZXZ0cykge1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGV2dHMubGVuZ3RoOyBpICs9IDEpIHtcbiAgICAgICAgICAgIHRoaXMuZGVmaW5lRXZlbnQoZXZ0c1tpXSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIFJlbW92ZXMgYSBsaXN0ZW5lciBmdW5jdGlvbiBmcm9tIHRoZSBzcGVjaWZpZWQgZXZlbnQuXG4gICAgICogV2hlbiBwYXNzZWQgYSByZWd1bGFyIGV4cHJlc3Npb24gYXMgdGhlIGV2ZW50IG5hbWUsIGl0IHdpbGwgcmVtb3ZlIHRoZSBsaXN0ZW5lciBmcm9tIGFsbCBldmVudHMgdGhhdCBtYXRjaCBpdC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfFJlZ0V4cH0gZXZ0IE5hbWUgb2YgdGhlIGV2ZW50IHRvIHJlbW92ZSB0aGUgbGlzdGVuZXIgZnJvbS5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBsaXN0ZW5lciBNZXRob2QgdG8gcmVtb3ZlIGZyb20gdGhlIGV2ZW50LlxuICAgICAqIEByZXR1cm4ge09iamVjdH0gQ3VycmVudCBpbnN0YW5jZSBvZiBFdmVudEVtaXR0ZXIgZm9yIGNoYWluaW5nLlxuICAgICAqL1xuICAgIHByb3RvLnJlbW92ZUxpc3RlbmVyID0gZnVuY3Rpb24gcmVtb3ZlTGlzdGVuZXIoZXZ0LCBsaXN0ZW5lcikge1xuICAgICAgICB2YXIgbGlzdGVuZXJzID0gdGhpcy5nZXRMaXN0ZW5lcnNBc09iamVjdChldnQpO1xuICAgICAgICB2YXIgaW5kZXg7XG4gICAgICAgIHZhciBrZXk7XG5cbiAgICAgICAgZm9yIChrZXkgaW4gbGlzdGVuZXJzKSB7XG4gICAgICAgICAgICBpZiAobGlzdGVuZXJzLmhhc093blByb3BlcnR5KGtleSkpIHtcbiAgICAgICAgICAgICAgICBpbmRleCA9IGluZGV4T2ZMaXN0ZW5lcihsaXN0ZW5lcnNba2V5XSwgbGlzdGVuZXIpO1xuXG4gICAgICAgICAgICAgICAgaWYgKGluZGV4ICE9PSAtMSkge1xuICAgICAgICAgICAgICAgICAgICBsaXN0ZW5lcnNba2V5XS5zcGxpY2UoaW5kZXgsIDEpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBBbGlhcyBvZiByZW1vdmVMaXN0ZW5lclxuICAgICAqL1xuICAgIHByb3RvLm9mZiA9IGFsaWFzKCdyZW1vdmVMaXN0ZW5lcicpO1xuXG4gICAgLyoqXG4gICAgICogQWRkcyBsaXN0ZW5lcnMgaW4gYnVsayB1c2luZyB0aGUgbWFuaXB1bGF0ZUxpc3RlbmVycyBtZXRob2QuXG4gICAgICogSWYgeW91IHBhc3MgYW4gb2JqZWN0IGFzIHRoZSBmaXJzdCBhcmd1bWVudCB5b3UgY2FuIGFkZCB0byBtdWx0aXBsZSBldmVudHMgYXQgb25jZS4gVGhlIG9iamVjdCBzaG91bGQgY29udGFpbiBrZXkgdmFsdWUgcGFpcnMgb2YgZXZlbnRzIGFuZCBsaXN0ZW5lcnMgb3IgbGlzdGVuZXIgYXJyYXlzLiBZb3UgY2FuIGFsc28gcGFzcyBpdCBhbiBldmVudCBuYW1lIGFuZCBhbiBhcnJheSBvZiBsaXN0ZW5lcnMgdG8gYmUgYWRkZWQuXG4gICAgICogWW91IGNhbiBhbHNvIHBhc3MgaXQgYSByZWd1bGFyIGV4cHJlc3Npb24gdG8gYWRkIHRoZSBhcnJheSBvZiBsaXN0ZW5lcnMgdG8gYWxsIGV2ZW50cyB0aGF0IG1hdGNoIGl0LlxuICAgICAqIFllYWgsIHRoaXMgZnVuY3Rpb24gZG9lcyBxdWl0ZSBhIGJpdC4gVGhhdCdzIHByb2JhYmx5IGEgYmFkIHRoaW5nLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtTdHJpbmd8T2JqZWN0fFJlZ0V4cH0gZXZ0IEFuIGV2ZW50IG5hbWUgaWYgeW91IHdpbGwgcGFzcyBhbiBhcnJheSBvZiBsaXN0ZW5lcnMgbmV4dC4gQW4gb2JqZWN0IGlmIHlvdSB3aXNoIHRvIGFkZCB0byBtdWx0aXBsZSBldmVudHMgYXQgb25jZS5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9uW119IFtsaXN0ZW5lcnNdIEFuIG9wdGlvbmFsIGFycmF5IG9mIGxpc3RlbmVyIGZ1bmN0aW9ucyB0byBhZGQuXG4gICAgICogQHJldHVybiB7T2JqZWN0fSBDdXJyZW50IGluc3RhbmNlIG9mIEV2ZW50RW1pdHRlciBmb3IgY2hhaW5pbmcuXG4gICAgICovXG4gICAgcHJvdG8uYWRkTGlzdGVuZXJzID0gZnVuY3Rpb24gYWRkTGlzdGVuZXJzKGV2dCwgbGlzdGVuZXJzKSB7XG4gICAgICAgIC8vIFBhc3MgdGhyb3VnaCB0byBtYW5pcHVsYXRlTGlzdGVuZXJzXG4gICAgICAgIHJldHVybiB0aGlzLm1hbmlwdWxhdGVMaXN0ZW5lcnMoZmFsc2UsIGV2dCwgbGlzdGVuZXJzKTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlcyBsaXN0ZW5lcnMgaW4gYnVsayB1c2luZyB0aGUgbWFuaXB1bGF0ZUxpc3RlbmVycyBtZXRob2QuXG4gICAgICogSWYgeW91IHBhc3MgYW4gb2JqZWN0IGFzIHRoZSBmaXJzdCBhcmd1bWVudCB5b3UgY2FuIHJlbW92ZSBmcm9tIG11bHRpcGxlIGV2ZW50cyBhdCBvbmNlLiBUaGUgb2JqZWN0IHNob3VsZCBjb250YWluIGtleSB2YWx1ZSBwYWlycyBvZiBldmVudHMgYW5kIGxpc3RlbmVycyBvciBsaXN0ZW5lciBhcnJheXMuXG4gICAgICogWW91IGNhbiBhbHNvIHBhc3MgaXQgYW4gZXZlbnQgbmFtZSBhbmQgYW4gYXJyYXkgb2YgbGlzdGVuZXJzIHRvIGJlIHJlbW92ZWQuXG4gICAgICogWW91IGNhbiBhbHNvIHBhc3MgaXQgYSByZWd1bGFyIGV4cHJlc3Npb24gdG8gcmVtb3ZlIHRoZSBsaXN0ZW5lcnMgZnJvbSBhbGwgZXZlbnRzIHRoYXQgbWF0Y2ggaXQuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1N0cmluZ3xPYmplY3R8UmVnRXhwfSBldnQgQW4gZXZlbnQgbmFtZSBpZiB5b3Ugd2lsbCBwYXNzIGFuIGFycmF5IG9mIGxpc3RlbmVycyBuZXh0LiBBbiBvYmplY3QgaWYgeW91IHdpc2ggdG8gcmVtb3ZlIGZyb20gbXVsdGlwbGUgZXZlbnRzIGF0IG9uY2UuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbltdfSBbbGlzdGVuZXJzXSBBbiBvcHRpb25hbCBhcnJheSBvZiBsaXN0ZW5lciBmdW5jdGlvbnMgdG8gcmVtb3ZlLlxuICAgICAqIEByZXR1cm4ge09iamVjdH0gQ3VycmVudCBpbnN0YW5jZSBvZiBFdmVudEVtaXR0ZXIgZm9yIGNoYWluaW5nLlxuICAgICAqL1xuICAgIHByb3RvLnJlbW92ZUxpc3RlbmVycyA9IGZ1bmN0aW9uIHJlbW92ZUxpc3RlbmVycyhldnQsIGxpc3RlbmVycykge1xuICAgICAgICAvLyBQYXNzIHRocm91Z2ggdG8gbWFuaXB1bGF0ZUxpc3RlbmVyc1xuICAgICAgICByZXR1cm4gdGhpcy5tYW5pcHVsYXRlTGlzdGVuZXJzKHRydWUsIGV2dCwgbGlzdGVuZXJzKTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogRWRpdHMgbGlzdGVuZXJzIGluIGJ1bGsuIFRoZSBhZGRMaXN0ZW5lcnMgYW5kIHJlbW92ZUxpc3RlbmVycyBtZXRob2RzIGJvdGggdXNlIHRoaXMgdG8gZG8gdGhlaXIgam9iLiBZb3Ugc2hvdWxkIHJlYWxseSB1c2UgdGhvc2UgaW5zdGVhZCwgdGhpcyBpcyBhIGxpdHRsZSBsb3dlciBsZXZlbC5cbiAgICAgKiBUaGUgZmlyc3QgYXJndW1lbnQgd2lsbCBkZXRlcm1pbmUgaWYgdGhlIGxpc3RlbmVycyBhcmUgcmVtb3ZlZCAodHJ1ZSkgb3IgYWRkZWQgKGZhbHNlKS5cbiAgICAgKiBJZiB5b3UgcGFzcyBhbiBvYmplY3QgYXMgdGhlIHNlY29uZCBhcmd1bWVudCB5b3UgY2FuIGFkZC9yZW1vdmUgZnJvbSBtdWx0aXBsZSBldmVudHMgYXQgb25jZS4gVGhlIG9iamVjdCBzaG91bGQgY29udGFpbiBrZXkgdmFsdWUgcGFpcnMgb2YgZXZlbnRzIGFuZCBsaXN0ZW5lcnMgb3IgbGlzdGVuZXIgYXJyYXlzLlxuICAgICAqIFlvdSBjYW4gYWxzbyBwYXNzIGl0IGFuIGV2ZW50IG5hbWUgYW5kIGFuIGFycmF5IG9mIGxpc3RlbmVycyB0byBiZSBhZGRlZC9yZW1vdmVkLlxuICAgICAqIFlvdSBjYW4gYWxzbyBwYXNzIGl0IGEgcmVndWxhciBleHByZXNzaW9uIHRvIG1hbmlwdWxhdGUgdGhlIGxpc3RlbmVycyBvZiBhbGwgZXZlbnRzIHRoYXQgbWF0Y2ggaXQuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0Jvb2xlYW59IHJlbW92ZSBUcnVlIGlmIHlvdSB3YW50IHRvIHJlbW92ZSBsaXN0ZW5lcnMsIGZhbHNlIGlmIHlvdSB3YW50IHRvIGFkZC5cbiAgICAgKiBAcGFyYW0ge1N0cmluZ3xPYmplY3R8UmVnRXhwfSBldnQgQW4gZXZlbnQgbmFtZSBpZiB5b3Ugd2lsbCBwYXNzIGFuIGFycmF5IG9mIGxpc3RlbmVycyBuZXh0LiBBbiBvYmplY3QgaWYgeW91IHdpc2ggdG8gYWRkL3JlbW92ZSBmcm9tIG11bHRpcGxlIGV2ZW50cyBhdCBvbmNlLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb25bXX0gW2xpc3RlbmVyc10gQW4gb3B0aW9uYWwgYXJyYXkgb2YgbGlzdGVuZXIgZnVuY3Rpb25zIHRvIGFkZC9yZW1vdmUuXG4gICAgICogQHJldHVybiB7T2JqZWN0fSBDdXJyZW50IGluc3RhbmNlIG9mIEV2ZW50RW1pdHRlciBmb3IgY2hhaW5pbmcuXG4gICAgICovXG4gICAgcHJvdG8ubWFuaXB1bGF0ZUxpc3RlbmVycyA9IGZ1bmN0aW9uIG1hbmlwdWxhdGVMaXN0ZW5lcnMocmVtb3ZlLCBldnQsIGxpc3RlbmVycykge1xuICAgICAgICB2YXIgaTtcbiAgICAgICAgdmFyIHZhbHVlO1xuICAgICAgICB2YXIgc2luZ2xlID0gcmVtb3ZlID8gdGhpcy5yZW1vdmVMaXN0ZW5lciA6IHRoaXMuYWRkTGlzdGVuZXI7XG4gICAgICAgIHZhciBtdWx0aXBsZSA9IHJlbW92ZSA/IHRoaXMucmVtb3ZlTGlzdGVuZXJzIDogdGhpcy5hZGRMaXN0ZW5lcnM7XG5cbiAgICAgICAgLy8gSWYgZXZ0IGlzIGFuIG9iamVjdCB0aGVuIHBhc3MgZWFjaCBvZiBpdHMgcHJvcGVydGllcyB0byB0aGlzIG1ldGhvZFxuICAgICAgICBpZiAodHlwZW9mIGV2dCA9PT0gJ29iamVjdCcgJiYgIShldnQgaW5zdGFuY2VvZiBSZWdFeHApKSB7XG4gICAgICAgICAgICBmb3IgKGkgaW4gZXZ0KSB7XG4gICAgICAgICAgICAgICAgaWYgKGV2dC5oYXNPd25Qcm9wZXJ0eShpKSAmJiAodmFsdWUgPSBldnRbaV0pKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIFBhc3MgdGhlIHNpbmdsZSBsaXN0ZW5lciBzdHJhaWdodCB0aHJvdWdoIHRvIHRoZSBzaW5ndWxhciBtZXRob2RcbiAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgc2luZ2xlLmNhbGwodGhpcywgaSwgdmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gT3RoZXJ3aXNlIHBhc3MgYmFjayB0byB0aGUgbXVsdGlwbGUgZnVuY3Rpb25cbiAgICAgICAgICAgICAgICAgICAgICAgIG11bHRpcGxlLmNhbGwodGhpcywgaSwgdmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgLy8gU28gZXZ0IG11c3QgYmUgYSBzdHJpbmdcbiAgICAgICAgICAgIC8vIEFuZCBsaXN0ZW5lcnMgbXVzdCBiZSBhbiBhcnJheSBvZiBsaXN0ZW5lcnNcbiAgICAgICAgICAgIC8vIExvb3Agb3ZlciBpdCBhbmQgcGFzcyBlYWNoIG9uZSB0byB0aGUgbXVsdGlwbGUgbWV0aG9kXG4gICAgICAgICAgICBpID0gbGlzdGVuZXJzLmxlbmd0aDtcbiAgICAgICAgICAgIHdoaWxlIChpLS0pIHtcbiAgICAgICAgICAgICAgICBzaW5nbGUuY2FsbCh0aGlzLCBldnQsIGxpc3RlbmVyc1tpXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlcyBhbGwgbGlzdGVuZXJzIGZyb20gYSBzcGVjaWZpZWQgZXZlbnQuXG4gICAgICogSWYgeW91IGRvIG5vdCBzcGVjaWZ5IGFuIGV2ZW50IHRoZW4gYWxsIGxpc3RlbmVycyB3aWxsIGJlIHJlbW92ZWQuXG4gICAgICogVGhhdCBtZWFucyBldmVyeSBldmVudCB3aWxsIGJlIGVtcHRpZWQuXG4gICAgICogWW91IGNhbiBhbHNvIHBhc3MgYSByZWdleCB0byByZW1vdmUgYWxsIGV2ZW50cyB0aGF0IG1hdGNoIGl0LlxuICAgICAqXG4gICAgICogQHBhcmFtIHtTdHJpbmd8UmVnRXhwfSBbZXZ0XSBPcHRpb25hbCBuYW1lIG9mIHRoZSBldmVudCB0byByZW1vdmUgYWxsIGxpc3RlbmVycyBmb3IuIFdpbGwgcmVtb3ZlIGZyb20gZXZlcnkgZXZlbnQgaWYgbm90IHBhc3NlZC5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEN1cnJlbnQgaW5zdGFuY2Ugb2YgRXZlbnRFbWl0dGVyIGZvciBjaGFpbmluZy5cbiAgICAgKi9cbiAgICBwcm90by5yZW1vdmVFdmVudCA9IGZ1bmN0aW9uIHJlbW92ZUV2ZW50KGV2dCkge1xuICAgICAgICB2YXIgdHlwZSA9IHR5cGVvZiBldnQ7XG4gICAgICAgIHZhciBldmVudHMgPSB0aGlzLl9nZXRFdmVudHMoKTtcbiAgICAgICAgdmFyIGtleTtcblxuICAgICAgICAvLyBSZW1vdmUgZGlmZmVyZW50IHRoaW5ncyBkZXBlbmRpbmcgb24gdGhlIHN0YXRlIG9mIGV2dFxuICAgICAgICBpZiAodHlwZSA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgIC8vIFJlbW92ZSBhbGwgbGlzdGVuZXJzIGZvciB0aGUgc3BlY2lmaWVkIGV2ZW50XG4gICAgICAgICAgICBkZWxldGUgZXZlbnRzW2V2dF07XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAoZXZ0IGluc3RhbmNlb2YgUmVnRXhwKSB7XG4gICAgICAgICAgICAvLyBSZW1vdmUgYWxsIGV2ZW50cyBtYXRjaGluZyB0aGUgcmVnZXguXG4gICAgICAgICAgICBmb3IgKGtleSBpbiBldmVudHMpIHtcbiAgICAgICAgICAgICAgICBpZiAoZXZlbnRzLmhhc093blByb3BlcnR5KGtleSkgJiYgZXZ0LnRlc3Qoa2V5KSkge1xuICAgICAgICAgICAgICAgICAgICBkZWxldGUgZXZlbnRzW2tleV07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgLy8gUmVtb3ZlIGFsbCBsaXN0ZW5lcnMgaW4gYWxsIGV2ZW50c1xuICAgICAgICAgICAgZGVsZXRlIHRoaXMuX2V2ZW50cztcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBBbGlhcyBvZiByZW1vdmVFdmVudC5cbiAgICAgKlxuICAgICAqIEFkZGVkIHRvIG1pcnJvciB0aGUgbm9kZSBBUEkuXG4gICAgICovXG4gICAgcHJvdG8ucmVtb3ZlQWxsTGlzdGVuZXJzID0gYWxpYXMoJ3JlbW92ZUV2ZW50Jyk7XG5cbiAgICAvKipcbiAgICAgKiBFbWl0cyBhbiBldmVudCBvZiB5b3VyIGNob2ljZS5cbiAgICAgKiBXaGVuIGVtaXR0ZWQsIGV2ZXJ5IGxpc3RlbmVyIGF0dGFjaGVkIHRvIHRoYXQgZXZlbnQgd2lsbCBiZSBleGVjdXRlZC5cbiAgICAgKiBJZiB5b3UgcGFzcyB0aGUgb3B0aW9uYWwgYXJndW1lbnQgYXJyYXkgdGhlbiB0aG9zZSBhcmd1bWVudHMgd2lsbCBiZSBwYXNzZWQgdG8gZXZlcnkgbGlzdGVuZXIgdXBvbiBleGVjdXRpb24uXG4gICAgICogQmVjYXVzZSBpdCB1c2VzIGBhcHBseWAsIHlvdXIgYXJyYXkgb2YgYXJndW1lbnRzIHdpbGwgYmUgcGFzc2VkIGFzIGlmIHlvdSB3cm90ZSB0aGVtIG91dCBzZXBhcmF0ZWx5LlxuICAgICAqIFNvIHRoZXkgd2lsbCBub3QgYXJyaXZlIHdpdGhpbiB0aGUgYXJyYXkgb24gdGhlIG90aGVyIHNpZGUsIHRoZXkgd2lsbCBiZSBzZXBhcmF0ZS5cbiAgICAgKiBZb3UgY2FuIGFsc28gcGFzcyBhIHJlZ3VsYXIgZXhwcmVzc2lvbiB0byBlbWl0IHRvIGFsbCBldmVudHMgdGhhdCBtYXRjaCBpdC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfFJlZ0V4cH0gZXZ0IE5hbWUgb2YgdGhlIGV2ZW50IHRvIGVtaXQgYW5kIGV4ZWN1dGUgbGlzdGVuZXJzIGZvci5cbiAgICAgKiBAcGFyYW0ge0FycmF5fSBbYXJnc10gT3B0aW9uYWwgYXJyYXkgb2YgYXJndW1lbnRzIHRvIGJlIHBhc3NlZCB0byBlYWNoIGxpc3RlbmVyLlxuICAgICAqIEByZXR1cm4ge09iamVjdH0gQ3VycmVudCBpbnN0YW5jZSBvZiBFdmVudEVtaXR0ZXIgZm9yIGNoYWluaW5nLlxuICAgICAqL1xuICAgIHByb3RvLmVtaXRFdmVudCA9IGZ1bmN0aW9uIGVtaXRFdmVudChldnQsIGFyZ3MpIHtcbiAgICAgICAgdmFyIGxpc3RlbmVyc01hcCA9IHRoaXMuZ2V0TGlzdGVuZXJzQXNPYmplY3QoZXZ0KTtcbiAgICAgICAgdmFyIGxpc3RlbmVycztcbiAgICAgICAgdmFyIGxpc3RlbmVyO1xuICAgICAgICB2YXIgaTtcbiAgICAgICAgdmFyIGtleTtcbiAgICAgICAgdmFyIHJlc3BvbnNlO1xuXG4gICAgICAgIGZvciAoa2V5IGluIGxpc3RlbmVyc01hcCkge1xuICAgICAgICAgICAgaWYgKGxpc3RlbmVyc01hcC5oYXNPd25Qcm9wZXJ0eShrZXkpKSB7XG4gICAgICAgICAgICAgICAgbGlzdGVuZXJzID0gbGlzdGVuZXJzTWFwW2tleV0uc2xpY2UoMCk7XG5cbiAgICAgICAgICAgICAgICBmb3IgKGkgPSAwOyBpIDwgbGlzdGVuZXJzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIElmIHRoZSBsaXN0ZW5lciByZXR1cm5zIHRydWUgdGhlbiBpdCBzaGFsbCBiZSByZW1vdmVkIGZyb20gdGhlIGV2ZW50XG4gICAgICAgICAgICAgICAgICAgIC8vIFRoZSBmdW5jdGlvbiBpcyBleGVjdXRlZCBlaXRoZXIgd2l0aCBhIGJhc2ljIGNhbGwgb3IgYW4gYXBwbHkgaWYgdGhlcmUgaXMgYW4gYXJncyBhcnJheVxuICAgICAgICAgICAgICAgICAgICBsaXN0ZW5lciA9IGxpc3RlbmVyc1tpXTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAobGlzdGVuZXIub25jZSA9PT0gdHJ1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5yZW1vdmVMaXN0ZW5lcihldnQsIGxpc3RlbmVyLmxpc3RlbmVyKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHJlc3BvbnNlID0gbGlzdGVuZXIubGlzdGVuZXIuYXBwbHkodGhpcywgYXJncyB8fCBbXSk7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKHJlc3BvbnNlID09PSB0aGlzLl9nZXRPbmNlUmV0dXJuVmFsdWUoKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5yZW1vdmVMaXN0ZW5lcihldnQsIGxpc3RlbmVyLmxpc3RlbmVyKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBBbGlhcyBvZiBlbWl0RXZlbnRcbiAgICAgKi9cbiAgICBwcm90by50cmlnZ2VyID0gYWxpYXMoJ2VtaXRFdmVudCcpO1xuXG4gICAgLyoqXG4gICAgICogU3VidGx5IGRpZmZlcmVudCBmcm9tIGVtaXRFdmVudCBpbiB0aGF0IGl0IHdpbGwgcGFzcyBpdHMgYXJndW1lbnRzIG9uIHRvIHRoZSBsaXN0ZW5lcnMsIGFzIG9wcG9zZWQgdG8gdGFraW5nIGEgc2luZ2xlIGFycmF5IG9mIGFyZ3VtZW50cyB0byBwYXNzIG9uLlxuICAgICAqIEFzIHdpdGggZW1pdEV2ZW50LCB5b3UgY2FuIHBhc3MgYSByZWdleCBpbiBwbGFjZSBvZiB0aGUgZXZlbnQgbmFtZSB0byBlbWl0IHRvIGFsbCBldmVudHMgdGhhdCBtYXRjaCBpdC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfFJlZ0V4cH0gZXZ0IE5hbWUgb2YgdGhlIGV2ZW50IHRvIGVtaXQgYW5kIGV4ZWN1dGUgbGlzdGVuZXJzIGZvci5cbiAgICAgKiBAcGFyYW0gey4uLip9IE9wdGlvbmFsIGFkZGl0aW9uYWwgYXJndW1lbnRzIHRvIGJlIHBhc3NlZCB0byBlYWNoIGxpc3RlbmVyLlxuICAgICAqIEByZXR1cm4ge09iamVjdH0gQ3VycmVudCBpbnN0YW5jZSBvZiBFdmVudEVtaXR0ZXIgZm9yIGNoYWluaW5nLlxuICAgICAqL1xuICAgIHByb3RvLmVtaXQgPSBmdW5jdGlvbiBlbWl0KGV2dCkge1xuICAgICAgICB2YXIgYXJncyA9IEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3VtZW50cywgMSk7XG4gICAgICAgIHJldHVybiB0aGlzLmVtaXRFdmVudChldnQsIGFyZ3MpO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBTZXRzIHRoZSBjdXJyZW50IHZhbHVlIHRvIGNoZWNrIGFnYWluc3Qgd2hlbiBleGVjdXRpbmcgbGlzdGVuZXJzLiBJZiBhXG4gICAgICogbGlzdGVuZXJzIHJldHVybiB2YWx1ZSBtYXRjaGVzIHRoZSBvbmUgc2V0IGhlcmUgdGhlbiBpdCB3aWxsIGJlIHJlbW92ZWRcbiAgICAgKiBhZnRlciBleGVjdXRpb24uIFRoaXMgdmFsdWUgZGVmYXVsdHMgdG8gdHJ1ZS5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIG5ldyB2YWx1ZSB0byBjaGVjayBmb3Igd2hlbiBleGVjdXRpbmcgbGlzdGVuZXJzLlxuICAgICAqIEByZXR1cm4ge09iamVjdH0gQ3VycmVudCBpbnN0YW5jZSBvZiBFdmVudEVtaXR0ZXIgZm9yIGNoYWluaW5nLlxuICAgICAqL1xuICAgIHByb3RvLnNldE9uY2VSZXR1cm5WYWx1ZSA9IGZ1bmN0aW9uIHNldE9uY2VSZXR1cm5WYWx1ZSh2YWx1ZSkge1xuICAgICAgICB0aGlzLl9vbmNlUmV0dXJuVmFsdWUgPSB2YWx1ZTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEZldGNoZXMgdGhlIGN1cnJlbnQgdmFsdWUgdG8gY2hlY2sgYWdhaW5zdCB3aGVuIGV4ZWN1dGluZyBsaXN0ZW5lcnMuIElmXG4gICAgICogdGhlIGxpc3RlbmVycyByZXR1cm4gdmFsdWUgbWF0Y2hlcyB0aGlzIG9uZSB0aGVuIGl0IHNob3VsZCBiZSByZW1vdmVkXG4gICAgICogYXV0b21hdGljYWxseS4gSXQgd2lsbCByZXR1cm4gdHJ1ZSBieSBkZWZhdWx0LlxuICAgICAqXG4gICAgICogQHJldHVybiB7KnxCb29sZWFufSBUaGUgY3VycmVudCB2YWx1ZSB0byBjaGVjayBmb3Igb3IgdGhlIGRlZmF1bHQsIHRydWUuXG4gICAgICogQGFwaSBwcml2YXRlXG4gICAgICovXG4gICAgcHJvdG8uX2dldE9uY2VSZXR1cm5WYWx1ZSA9IGZ1bmN0aW9uIF9nZXRPbmNlUmV0dXJuVmFsdWUoKSB7XG4gICAgICAgIGlmICh0aGlzLmhhc093blByb3BlcnR5KCdfb25jZVJldHVyblZhbHVlJykpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLl9vbmNlUmV0dXJuVmFsdWU7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBGZXRjaGVzIHRoZSBldmVudHMgb2JqZWN0IGFuZCBjcmVhdGVzIG9uZSBpZiByZXF1aXJlZC5cbiAgICAgKlxuICAgICAqIEByZXR1cm4ge09iamVjdH0gVGhlIGV2ZW50cyBzdG9yYWdlIG9iamVjdC5cbiAgICAgKiBAYXBpIHByaXZhdGVcbiAgICAgKi9cbiAgICBwcm90by5fZ2V0RXZlbnRzID0gZnVuY3Rpb24gX2dldEV2ZW50cygpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2V2ZW50cyB8fCAodGhpcy5fZXZlbnRzID0ge30pO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBSZXZlcnRzIHRoZSBnbG9iYWwge0BsaW5rIEV2ZW50RW1pdHRlcn0gdG8gaXRzIHByZXZpb3VzIHZhbHVlIGFuZCByZXR1cm5zIGEgcmVmZXJlbmNlIHRvIHRoaXMgdmVyc2lvbi5cbiAgICAgKlxuICAgICAqIEByZXR1cm4ge0Z1bmN0aW9ufSBOb24gY29uZmxpY3RpbmcgRXZlbnRFbWl0dGVyIGNsYXNzLlxuICAgICAqL1xuICAgIEV2ZW50RW1pdHRlci5ub0NvbmZsaWN0ID0gZnVuY3Rpb24gbm9Db25mbGljdCgpIHtcbiAgICAgICAgZXhwb3J0cy5FdmVudEVtaXR0ZXIgPSBvcmlnaW5hbEdsb2JhbFZhbHVlO1xuICAgICAgICByZXR1cm4gRXZlbnRFbWl0dGVyO1xuICAgIH07XG5cbiAgICAvLyBFeHBvc2UgdGhlIGNsYXNzIGVpdGhlciB2aWEgQU1ELCBDb21tb25KUyBvciB0aGUgZ2xvYmFsIG9iamVjdFxuICAgIGlmICh0eXBlb2YgZGVmaW5lID09PSAnZnVuY3Rpb24nICYmIGRlZmluZS5hbWQpIHtcbiAgICAgICAgZGVmaW5lKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiBFdmVudEVtaXR0ZXI7XG4gICAgICAgIH0pO1xuICAgIH1cbiAgICBlbHNlIGlmICh0eXBlb2YgbW9kdWxlID09PSAnb2JqZWN0JyAmJiBtb2R1bGUuZXhwb3J0cyl7XG4gICAgICAgIG1vZHVsZS5leHBvcnRzID0gRXZlbnRFbWl0dGVyO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgZXhwb3J0cy5FdmVudEVtaXR0ZXIgPSBFdmVudEVtaXR0ZXI7XG4gICAgfVxufSh0eXBlb2Ygd2luZG93ICE9PSAndW5kZWZpbmVkJyA/IHdpbmRvdyA6IHRoaXMgfHwge30pKTtcbiIsImltcG9ydCB7IE9wZW5WaWR1IH0gZnJvbSAnLi9PcGVuVmlkdS9PcGVuVmlkdSc7XG5cbmlmICh3aW5kb3cpIHtcbiAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6bm8tc3RyaW5nLWxpdGVyYWxcbiAgICB3aW5kb3dbJ09wZW5WaWR1J10gPSBPcGVuVmlkdTtcbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IFNlc3Npb24gfSBmcm9tICcuL1Nlc3Npb24nO1xuaW1wb3J0IHsgU3RyZWFtIH0gZnJvbSAnLi9TdHJlYW0nO1xuaW1wb3J0IHsgQ29ubmVjdGlvbk9wdGlvbnMgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHJpdmF0ZS9Db25uZWN0aW9uT3B0aW9ucyc7XG5pbXBvcnQgeyBJbmJvdW5kU3RyZWFtT3B0aW9ucyB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvSW50ZXJmYWNlcy9Qcml2YXRlL0luYm91bmRTdHJlYW1PcHRpb25zJztcbmltcG9ydCB7IFN0cmVhbU9wdGlvbnNTZXJ2ZXIgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHJpdmF0ZS9TdHJlYW1PcHRpb25zU2VydmVyJztcblxuXG4vKipcbiAqIFJlcHJlc2VudHMgZWFjaCBvbmUgb2YgdGhlIHVzZXIncyBjb25uZWN0aW9uIHRvIHRoZSBzZXNzaW9uICh0aGUgbG9jYWwgb25lIGFuZCBvdGhlciB1c2VyJ3MgY29ubmVjdGlvbnMpLlxuICogVGhlcmVmb3JlIGVhY2ggW1tTZXNzaW9uXV0gYW5kIFtbU3RyZWFtXV0gb2JqZWN0IGhhcyBhbiBhdHRyaWJ1dGUgb2YgdHlwZSBDb25uZWN0aW9uXG4gKi9cbmV4cG9ydCBjbGFzcyBDb25uZWN0aW9uIHtcblxuICAgIC8qKlxuICAgICAqIFVuaXF1ZSBpZGVudGlmaWVyIG9mIHRoZSBjb25uZWN0aW9uXG4gICAgICovXG4gICAgY29ubmVjdGlvbklkOiBzdHJpbmc7XG5cbiAgICAvKipcbiAgICAgKiBUaW1lIHdoZW4gdGhpcyBjb25uZWN0aW9uIHdhcyBjcmVhdGVkIChVVEMgbWlsbGlzZWNvbmRzKVxuICAgICAqL1xuICAgIGNyZWF0aW9uVGltZTogbnVtYmVyO1xuXG4gICAgLyoqXG4gICAgICogRGF0YSBhc3NvY2lhdGVkIHRvIHRoaXMgY29ubmVjdGlvbiAoYW5kIHRoZXJlZm9yZSB0byBjZXJ0YWluIHVzZXIpLiBUaGlzIGlzIGFuIGltcG9ydGFudCBmaWVsZDpcbiAgICAgKiBpdCBhbGxvd3MgeW91IHRvIGJyb2FkY2FzdCBhbGwgdGhlIGluZm9ybWF0aW9uIHlvdSB3YW50IGZvciBlYWNoIHVzZXIgKGEgdXNlcm5hbWUsIGZvciBleGFtcGxlKVxuICAgICAqL1xuICAgIGRhdGE6IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBzdHJlYW06IFN0cmVhbTtcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvcHRpb25zOiBDb25uZWN0aW9uT3B0aW9ucyB8IHVuZGVmaW5lZDtcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBkaXNwb3NlZCA9IGZhbHNlO1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHByaXZhdGUgc2Vzc2lvbjogU2Vzc2lvbiwgb3B0cz86IENvbm5lY3Rpb25PcHRpb25zKSB7XG5cbiAgICAgICAgbGV0IG1zZyA9IFwiJ0Nvbm5lY3Rpb24nIGNyZWF0ZWQgXCI7XG4gICAgICAgIGlmICghIW9wdHMpIHtcbiAgICAgICAgICAgIG1zZyArPSBcIihyZW1vdGUpIHdpdGggJ2Nvbm5lY3Rpb25JZCcgW1wiICsgb3B0cy5pZCArICddJztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIG1zZyArPSAnKGxvY2FsKSc7XG4gICAgICAgIH1cbiAgICAgICAgY29uc29sZS5pbmZvKG1zZyk7XG5cbiAgICAgICAgdGhpcy5vcHRpb25zID0gb3B0cztcblxuICAgICAgICBpZiAoISFvcHRzKSB7XG4gICAgICAgICAgICAvLyBDb25uZWN0aW9uIGlzIHJlbW90ZVxuICAgICAgICAgICAgdGhpcy5jb25uZWN0aW9uSWQgPSBvcHRzLmlkO1xuICAgICAgICAgICAgaWYgKG9wdHMubWV0YWRhdGEpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmRhdGEgPSBvcHRzLm1ldGFkYXRhO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG9wdHMuc3RyZWFtcykge1xuICAgICAgICAgICAgICAgIHRoaXMuaW5pdFJlbW90ZVN0cmVhbXMob3B0cy5zdHJlYW1zKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuY3JlYXRpb25UaW1lID0gbmV3IERhdGUoKS5nZXRUaW1lKCk7XG4gICAgfVxuXG5cbiAgICAvKiBIaWRkZW4gbWV0aG9kcyAqL1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHNlbmRJY2VDYW5kaWRhdGUoY2FuZGlkYXRlOiBSVENJY2VDYW5kaWRhdGUpOiB2b2lkIHtcblxuICAgICAgICBjb25zb2xlLmRlYnVnKCghIXRoaXMuc3RyZWFtLm91dGJvdW5kU3RyZWFtT3B0cyA/ICdMb2NhbCcgOiAnUmVtb3RlJyksICdjYW5kaWRhdGUgZm9yJyxcbiAgICAgICAgICAgIHRoaXMuY29ubmVjdGlvbklkLCBKU09OLnN0cmluZ2lmeShjYW5kaWRhdGUpKTtcblxuICAgICAgICB0aGlzLnNlc3Npb24ub3BlbnZpZHUuc2VuZFJlcXVlc3QoJ29uSWNlQ2FuZGlkYXRlJywge1xuICAgICAgICAgICAgZW5kcG9pbnROYW1lOiB0aGlzLmNvbm5lY3Rpb25JZCxcbiAgICAgICAgICAgIGNhbmRpZGF0ZTogY2FuZGlkYXRlLmNhbmRpZGF0ZSxcbiAgICAgICAgICAgIHNkcE1pZDogY2FuZGlkYXRlLnNkcE1pZCxcbiAgICAgICAgICAgIHNkcE1MaW5lSW5kZXg6IGNhbmRpZGF0ZS5zZHBNTGluZUluZGV4XG4gICAgICAgIH0sIChlcnJvciwgcmVzcG9uc2UpID0+IHtcbiAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ0Vycm9yIHNlbmRpbmcgSUNFIGNhbmRpZGF0ZTogJ1xuICAgICAgICAgICAgICAgICAgICArIEpTT04uc3RyaW5naWZ5KGVycm9yKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBpbml0UmVtb3RlU3RyZWFtcyhvcHRpb25zOiBTdHJlYW1PcHRpb25zU2VydmVyW10pOiB2b2lkIHtcblxuICAgICAgICAvLyBUaGlzIGlzIHJlYWR5IGZvciBzdXBwb3J0aW5nIG11bHRpcGxlIHN0cmVhbXMgcGVyIENvbm5lY3Rpb24gb2JqZWN0LiBSaWdodCBub3cgdGhlIGxvb3Agd2lsbCBhbHdheXMgcnVuIGp1c3Qgb25jZVxuICAgICAgICAvLyB0aGlzLnN0cmVhbSBzaG91bGQgYWxzbyBiZSByZXBsYWNlZCBieSBhIGNvbGxlY3Rpb24gb2Ygc3RyZWFtcyB0byBzdXBwb3J0IG11bHRpcGxlIHN0cmVhbXMgcGVyIENvbm5lY3Rpb25cbiAgICAgICAgb3B0aW9ucy5mb3JFYWNoKG9wdHMgPT4ge1xuICAgICAgICAgICAgY29uc3Qgc3RyZWFtT3B0aW9uczogSW5ib3VuZFN0cmVhbU9wdGlvbnMgPSB7XG4gICAgICAgICAgICAgICAgaWQ6IG9wdHMuaWQsXG4gICAgICAgICAgICAgICAgY29ubmVjdGlvbjogdGhpcyxcbiAgICAgICAgICAgICAgICBoYXNBdWRpbzogb3B0cy5oYXNBdWRpbyxcbiAgICAgICAgICAgICAgICBoYXNWaWRlbzogb3B0cy5oYXNWaWRlbyxcbiAgICAgICAgICAgICAgICBhdWRpb0FjdGl2ZTogb3B0cy5hdWRpb0FjdGl2ZSxcbiAgICAgICAgICAgICAgICB2aWRlb0FjdGl2ZTogb3B0cy52aWRlb0FjdGl2ZSxcbiAgICAgICAgICAgICAgICB0eXBlT2ZWaWRlbzogb3B0cy50eXBlT2ZWaWRlbyxcbiAgICAgICAgICAgICAgICBmcmFtZVJhdGU6IG9wdHMuZnJhbWVSYXRlLFxuICAgICAgICAgICAgICAgIHZpZGVvRGltZW5zaW9uczogISFvcHRzLnZpZGVvRGltZW5zaW9ucyA/IEpTT04ucGFyc2Uob3B0cy52aWRlb0RpbWVuc2lvbnMpIDogdW5kZWZpbmVkXG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgY29uc3Qgc3RyZWFtID0gbmV3IFN0cmVhbSh0aGlzLnNlc3Npb24sIHN0cmVhbU9wdGlvbnMpO1xuXG4gICAgICAgICAgICB0aGlzLmFkZFN0cmVhbShzdHJlYW0pO1xuICAgICAgICB9KTtcblxuICAgICAgICBjb25zb2xlLmluZm8oXCJSZW1vdGUgJ0Nvbm5lY3Rpb24nIHdpdGggJ2Nvbm5lY3Rpb25JZCcgW1wiICsgdGhpcy5jb25uZWN0aW9uSWQgKyAnXSBpcyBub3cgY29uZmlndXJlZCBmb3IgcmVjZWl2aW5nIFN0cmVhbXMgd2l0aCBvcHRpb25zOiAnLCB0aGlzLnN0cmVhbS5pbmJvdW5kU3RyZWFtT3B0cyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGFkZFN0cmVhbShzdHJlYW06IFN0cmVhbSk6IHZvaWQge1xuICAgICAgICBzdHJlYW0uY29ubmVjdGlvbiA9IHRoaXM7XG4gICAgICAgIHRoaXMuc3RyZWFtID0gc3RyZWFtO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICByZW1vdmVTdHJlYW0oc3RyZWFtSWQ6IHN0cmluZyk6IHZvaWQge1xuICAgICAgICBkZWxldGUgdGhpcy5zdHJlYW07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGRpc3Bvc2UoKTogdm9pZCB7XG4gICAgICAgIGlmICghIXRoaXMuc3RyZWFtKSB7XG4gICAgICAgICAgICBkZWxldGUgdGhpcy5zdHJlYW07XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5kaXNwb3NlZCA9IHRydWU7XG4gICAgfVxuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBTdHJlYW0gfSBmcm9tICcuL1N0cmVhbSc7XG5pbXBvcnQgeyBMb2NhbFJlY29yZGVyU3RhdGUgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0VudW1zL0xvY2FsUmVjb3JkZXJTdGF0ZSc7XG5cbi8qKlxuICogQGhpZGRlblxuICovXG5kZWNsYXJlIHZhciBNZWRpYVJlY29yZGVyOiBhbnk7XG5cblxuLyoqXG4gKiBFYXN5IHJlY29yZGluZyBvZiBbW1N0cmVhbV1dIG9iamVjdHMgc3RyYWlnaHRhd2F5IGZyb20gdGhlIGJyb3dzZXIuIEluaXRpYWxpemVkIHdpdGggW1tPcGVuVmlkdS5pbml0TG9jYWxSZWNvcmRlcl1dIG1ldGhvZFxuICpcbiAqID4gV0FSTklORzogUGVyZm9ybWluZyBicm93c2VyIGxvY2FsIHJlY29yZGluZyBvZiAqKnJlbW90ZSBzdHJlYW1zKiogbWF5IGNhdXNlIHNvbWUgdHJvdWJsZXMuIEEgbG9uZyB3YWl0aW5nIHRpbWUgbWF5IGJlIHJlcXVpcmVkIGFmdGVyIGNhbGxpbmcgX0xvY2FsUmVjb3JkZXIuc3RvcCgpXyBpbiB0aGlzIGNhc2VcbiAqL1xuZXhwb3J0IGNsYXNzIExvY2FsUmVjb3JkZXIge1xuXG4gICAgc3RhdGU6IExvY2FsUmVjb3JkZXJTdGF0ZTtcblxuICAgIHByaXZhdGUgY29ubmVjdGlvbklkOiBzdHJpbmc7XG4gICAgcHJpdmF0ZSBtZWRpYVJlY29yZGVyOiBhbnk7XG4gICAgcHJpdmF0ZSBjaHVua3M6IGFueVtdID0gW107XG4gICAgcHJpdmF0ZSBibG9iOiBCbG9iO1xuICAgIHByaXZhdGUgY291bnQgPSAwO1xuICAgIHByaXZhdGUgaWQ6IHN0cmluZztcbiAgICBwcml2YXRlIHZpZGVvUHJldmlld1NyYzogc3RyaW5nO1xuICAgIHByaXZhdGUgaHRtbFBhcmVudEVsZW1lbnRJZDogc3RyaW5nO1xuICAgIHByaXZhdGUgdmlkZW9QcmV2aWV3OiBIVE1MVmlkZW9FbGVtZW50O1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHByaXZhdGUgc3RyZWFtOiBTdHJlYW0pIHtcbiAgICAgICAgdGhpcy5jb25uZWN0aW9uSWQgPSAoISF0aGlzLnN0cmVhbS5jb25uZWN0aW9uKSA/IHRoaXMuc3RyZWFtLmNvbm5lY3Rpb24uY29ubmVjdGlvbklkIDogJ2RlZmF1bHQtY29ubmVjdGlvbic7XG4gICAgICAgIHRoaXMuaWQgPSB0aGlzLnN0cmVhbS5zdHJlYW1JZCArICdfJyArIHRoaXMuY29ubmVjdGlvbklkICsgJ19sb2NhbHJlY29yZCc7XG4gICAgICAgIHRoaXMuc3RhdGUgPSBMb2NhbFJlY29yZGVyU3RhdGUuUkVBRFk7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBTdGFydHMgdGhlIHJlY29yZGluZyBvZiB0aGUgU3RyZWFtLiBbW3N0YXRlXV0gcHJvcGVydHkgbXVzdCBiZSBgUkVBRFlgLiBBZnRlciBtZXRob2Qgc3VjY2VlZHMgaXMgc2V0IHRvIGBSRUNPUkRJTkdgXG4gICAgICogQHJldHVybnMgQSBQcm9taXNlICh0byB3aGljaCB5b3UgY2FuIG9wdGlvbmFsbHkgc3Vic2NyaWJlIHRvKSB0aGF0IGlzIHJlc29sdmVkIGlmIHRoZSByZWNvcmRpbmcgc3VjY2Vzc2Z1bGx5IHN0YXJ0ZWQgYW5kIHJlamVjdGVkIHdpdGggYW4gRXJyb3Igb2JqZWN0IGlmIG5vdFxuICAgICAqL1xuICAgIHJlY29yZCgpOiBQcm9taXNlPGFueT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuXG4gICAgICAgICAgICB0cnkge1xuXG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBNZWRpYVJlY29yZGVyID09PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKCdNZWRpYVJlY29yZGVyIG5vdCBzdXBwb3J0ZWQgb24geW91ciBicm93c2VyLiBTZWUgY29tcGF0aWJpbGl0eSBpbiBodHRwczovL2Nhbml1c2UuY29tLyNzZWFyY2g9TWVkaWFSZWNvcmRlcicpO1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyAoRXJyb3IoJ01lZGlhUmVjb3JkZXIgbm90IHN1cHBvcnRlZCBvbiB5b3VyIGJyb3dzZXIuIFNlZSBjb21wYXRpYmlsaXR5IGluIGh0dHBzOi8vY2FuaXVzZS5jb20vI3NlYXJjaD1NZWRpYVJlY29yZGVyJykpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAodGhpcy5zdGF0ZSAhPT0gTG9jYWxSZWNvcmRlclN0YXRlLlJFQURZKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IChFcnJvcignXFwnTG9jYWxSZWNvcmQucmVjb3JkKClcXCcgbmVlZHMgXFwnTG9jYWxSZWNvcmQuc3RhdGVcXCcgdG8gYmUgXFwnUkVBRFlcXCcgKGN1cnJlbnQgdmFsdWU6IFxcJycgKyB0aGlzLnN0YXRlICsgJ1xcJykuIENhbGwgXFwnTG9jYWxSZWNvcmRlci5jbGVhbigpXFwnIG9yIGluaXQgYSBuZXcgTG9jYWxSZWNvcmRlciBiZWZvcmUnKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKFwiU3RhcnRpbmcgbG9jYWwgcmVjb3JkaW5nIG9mIHN0cmVhbSAnXCIgKyB0aGlzLnN0cmVhbS5zdHJlYW1JZCArIFwiJyBvZiBjb25uZWN0aW9uICdcIiArIHRoaXMuY29ubmVjdGlvbklkICsgXCInXCIpO1xuXG5cbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIE1lZGlhUmVjb3JkZXIuaXNUeXBlU3VwcG9ydGVkID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICAgICAgICAgIGxldCBvcHRpb25zO1xuICAgICAgICAgICAgICAgICAgICBpZiAoTWVkaWFSZWNvcmRlci5pc1R5cGVTdXBwb3J0ZWQoJ3ZpZGVvL3dlYm07Y29kZWNzPXZwOScpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBvcHRpb25zID0geyBtaW1lVHlwZTogJ3ZpZGVvL3dlYm07Y29kZWNzPXZwOScgfTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChNZWRpYVJlY29yZGVyLmlzVHlwZVN1cHBvcnRlZCgndmlkZW8vd2VibTtjb2RlY3M9aDI2NCcpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBvcHRpb25zID0geyBtaW1lVHlwZTogJ3ZpZGVvL3dlYm07Y29kZWNzPWgyNjQnIH07XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoTWVkaWFSZWNvcmRlci5pc1R5cGVTdXBwb3J0ZWQoJ3ZpZGVvL3dlYm07Y29kZWNzPXZwOCcpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBvcHRpb25zID0geyBtaW1lVHlwZTogJ3ZpZGVvL3dlYm07Y29kZWNzPXZwOCcgfTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmxvZygnVXNpbmcgbWltZVR5cGUgJyArIG9wdGlvbnMubWltZVR5cGUpO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLm1lZGlhUmVjb3JkZXIgPSBuZXcgTWVkaWFSZWNvcmRlcih0aGlzLnN0cmVhbS5nZXRNZWRpYVN0cmVhbSgpLCBvcHRpb25zKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLndhcm4oJ2lzVHlwZVN1cHBvcnRlZCBpcyBub3Qgc3VwcG9ydGVkLCB1c2luZyBkZWZhdWx0IGNvZGVjcyBmb3IgYnJvd3NlcicpO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLm1lZGlhUmVjb3JkZXIgPSBuZXcgTWVkaWFSZWNvcmRlcih0aGlzLnN0cmVhbS5nZXRNZWRpYVN0cmVhbSgpKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB0aGlzLm1lZGlhUmVjb3JkZXIuc3RhcnQoMTApO1xuXG4gICAgICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAgICAgICByZWplY3QoZXJyKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5tZWRpYVJlY29yZGVyLm9uZGF0YWF2YWlsYWJsZSA9IChlKSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5jaHVua3MucHVzaChlLmRhdGEpO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgdGhpcy5tZWRpYVJlY29yZGVyLm9uZXJyb3IgPSAoZSkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ01lZGlhUmVjb3JkZXIgZXJyb3I6ICcsIGUpO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgdGhpcy5tZWRpYVJlY29yZGVyLm9uc3RhcnQgPSAoKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5sb2coJ01lZGlhUmVjb3JkZXIgc3RhcnRlZCAoc3RhdGU9JyArIHRoaXMubWVkaWFSZWNvcmRlci5zdGF0ZSArICcpJyk7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICB0aGlzLm1lZGlhUmVjb3JkZXIub25zdG9wID0gKCkgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMub25TdG9wRGVmYXVsdCgpO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgdGhpcy5tZWRpYVJlY29yZGVyLm9ucGF1c2UgPSAoKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5sb2coJ01lZGlhUmVjb3JkZXIgcGF1c2VkIChzdGF0ZT0nICsgdGhpcy5tZWRpYVJlY29yZGVyLnN0YXRlICsgJyknKTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIHRoaXMubWVkaWFSZWNvcmRlci5vbnJlc3VtZSA9ICgpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmxvZygnTWVkaWFSZWNvcmRlciByZXN1bWVkIChzdGF0ZT0nICsgdGhpcy5tZWRpYVJlY29yZGVyLnN0YXRlICsgJyknKTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIHRoaXMubWVkaWFSZWNvcmRlci5vbndhcm5pbmcgPSAoZSkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKCdNZWRpYVJlY29yZGVyIHdhcm5pbmc6ICcgKyBlKTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIHRoaXMuc3RhdGUgPSBMb2NhbFJlY29yZGVyU3RhdGUuUkVDT1JESU5HO1xuICAgICAgICAgICAgcmVzb2x2ZSgpO1xuXG4gICAgICAgIH0pO1xuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogRW5kcyB0aGUgcmVjb3JkaW5nIG9mIHRoZSBTdHJlYW0uIFtbc3RhdGVdXSBwcm9wZXJ0eSBtdXN0IGJlIGBSRUNPUkRJTkdgIG9yIGBQQVVTRURgLiBBZnRlciBtZXRob2Qgc3VjY2VlZHMgaXMgc2V0IHRvIGBGSU5JU0hFRGBcbiAgICAgKiBAcmV0dXJucyBBIFByb21pc2UgKHRvIHdoaWNoIHlvdSBjYW4gb3B0aW9uYWxseSBzdWJzY3JpYmUgdG8pIHRoYXQgaXMgcmVzb2x2ZWQgaWYgdGhlIHJlY29yZGluZyBzdWNjZXNzZnVsbHkgc3RvcHBlZCBhbmQgcmVqZWN0ZWQgd2l0aCBhbiBFcnJvciBvYmplY3QgaWYgbm90XG4gICAgICovXG4gICAgc3RvcCgpOiBQcm9taXNlPGFueT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5zdGF0ZSA9PT0gTG9jYWxSZWNvcmRlclN0YXRlLlJFQURZIHx8IHRoaXMuc3RhdGUgPT09IExvY2FsUmVjb3JkZXJTdGF0ZS5GSU5JU0hFRCkge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyAoRXJyb3IoJ1xcJ0xvY2FsUmVjb3JkLnN0b3AoKVxcJyBuZWVkcyBcXCdMb2NhbFJlY29yZC5zdGF0ZVxcJyB0byBiZSBcXCdSRUNPUkRJTkdcXCcgb3IgXFwnUEFVU0VEXFwnIChjdXJyZW50IHZhbHVlOiBcXCcnICsgdGhpcy5zdGF0ZSArICdcXCcpLiBDYWxsIFxcJ0xvY2FsUmVjb3JkZXIuc3RhcnQoKVxcJyBiZWZvcmUnKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRoaXMubWVkaWFSZWNvcmRlci5vbnN0b3AgPSAoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMub25TdG9wRGVmYXVsdCgpO1xuICAgICAgICAgICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB0aGlzLm1lZGlhUmVjb3JkZXIuc3RvcCgpO1xuICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICAgIHJlamVjdChlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBQYXVzZXMgdGhlIHJlY29yZGluZyBvZiB0aGUgU3RyZWFtLiBbW3N0YXRlXV0gcHJvcGVydHkgbXVzdCBiZSBgUkVDT1JESU5HYC4gQWZ0ZXIgbWV0aG9kIHN1Y2NlZWRzIGlzIHNldCB0byBgUEFVU0VEYFxuICAgICAqIEByZXR1cm5zIEEgUHJvbWlzZSAodG8gd2hpY2ggeW91IGNhbiBvcHRpb25hbGx5IHN1YnNjcmliZSB0bykgdGhhdCBpcyByZXNvbHZlZCBpZiB0aGUgcmVjb3JkaW5nIHdhcyBzdWNjZXNzZnVsbHkgcGF1c2VkIGFuZCByZWplY3RlZCB3aXRoIGFuIEVycm9yIG9iamVjdCBpZiBub3RcbiAgICAgKi9cbiAgICBwYXVzZSgpOiBQcm9taXNlPGFueT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5zdGF0ZSAhPT0gTG9jYWxSZWNvcmRlclN0YXRlLlJFQ09SRElORykge1xuICAgICAgICAgICAgICAgICAgICByZWplY3QoRXJyb3IoJ1xcJ0xvY2FsUmVjb3JkLnBhdXNlKClcXCcgbmVlZHMgXFwnTG9jYWxSZWNvcmQuc3RhdGVcXCcgdG8gYmUgXFwnUkVDT1JESU5HXFwnIChjdXJyZW50IHZhbHVlOiBcXCcnICsgdGhpcy5zdGF0ZSArICdcXCcpLiBDYWxsIFxcJ0xvY2FsUmVjb3JkZXIuc3RhcnQoKVxcJyBvciBcXCdMb2NhbFJlY29yZGVyLnJlc3VtZSgpXFwnIGJlZm9yZScpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhpcy5tZWRpYVJlY29yZGVyLnBhdXNlKCk7XG4gICAgICAgICAgICAgICAgdGhpcy5zdGF0ZSA9IExvY2FsUmVjb3JkZXJTdGF0ZS5QQVVTRUQ7XG4gICAgICAgICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlc3VtZXMgdGhlIHJlY29yZGluZyBvZiB0aGUgU3RyZWFtLiBbW3N0YXRlXV0gcHJvcGVydHkgbXVzdCBiZSBgUEFVU0VEYC4gQWZ0ZXIgbWV0aG9kIHN1Y2NlZWRzIGlzIHNldCB0byBgUkVDT1JESU5HYFxuICAgICAqIEByZXR1cm5zIEEgUHJvbWlzZSAodG8gd2hpY2ggeW91IGNhbiBvcHRpb25hbGx5IHN1YnNjcmliZSB0bykgdGhhdCBpcyByZXNvbHZlZCBpZiB0aGUgcmVjb3JkaW5nIHdhcyBzdWNjZXNzZnVsbHkgcmVzdW1lZCBhbmQgcmVqZWN0ZWQgd2l0aCBhbiBFcnJvciBvYmplY3QgaWYgbm90XG4gICAgICovXG4gICAgcmVzdW1lKCk6IFByb21pc2U8YW55PiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLnN0YXRlICE9PSBMb2NhbFJlY29yZGVyU3RhdGUuUEFVU0VEKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IChFcnJvcignXFwnTG9jYWxSZWNvcmQucmVzdW1lKClcXCcgbmVlZHMgXFwnTG9jYWxSZWNvcmQuc3RhdGVcXCcgdG8gYmUgXFwnUEFVU0VEXFwnIChjdXJyZW50IHZhbHVlOiBcXCcnICsgdGhpcy5zdGF0ZSArICdcXCcpLiBDYWxsIFxcJ0xvY2FsUmVjb3JkZXIucGF1c2UoKVxcJyBiZWZvcmUnKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRoaXMubWVkaWFSZWNvcmRlci5yZXN1bWUoKTtcbiAgICAgICAgICAgICAgICB0aGlzLnN0YXRlID0gTG9jYWxSZWNvcmRlclN0YXRlLlJFQ09SRElORztcbiAgICAgICAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBQcmV2aWV3cyB0aGUgcmVjb3JkaW5nLCBhcHBlbmRpbmcgYSBuZXcgSFRNTFZpZGVvRWxlbWVudCB0byBlbGVtZW50IHdpdGggaWQgYHBhcmVudElkYC4gW1tzdGF0ZV1dIHByb3BlcnR5IG11c3QgYmUgYEZJTklTSEVEYFxuICAgICAqL1xuICAgIHByZXZpZXcocGFyZW50RWxlbWVudCk6IEhUTUxWaWRlb0VsZW1lbnQge1xuXG4gICAgICAgIGlmICh0aGlzLnN0YXRlICE9PSBMb2NhbFJlY29yZGVyU3RhdGUuRklOSVNIRUQpIHtcbiAgICAgICAgICAgIHRocm93IChFcnJvcignXFwnTG9jYWxSZWNvcmQucHJldmlldygpXFwnIG5lZWRzIFxcJ0xvY2FsUmVjb3JkLnN0YXRlXFwnIHRvIGJlIFxcJ0ZJTklTSEVEXFwnIChjdXJyZW50IHZhbHVlOiBcXCcnICsgdGhpcy5zdGF0ZSArICdcXCcpLiBDYWxsIFxcJ0xvY2FsUmVjb3JkZXIuc3RvcCgpXFwnIGJlZm9yZScpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMudmlkZW9QcmV2aWV3ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgndmlkZW8nKTtcblxuICAgICAgICB0aGlzLnZpZGVvUHJldmlldy5pZCA9IHRoaXMuaWQ7XG4gICAgICAgIHRoaXMudmlkZW9QcmV2aWV3LmF1dG9wbGF5ID0gdHJ1ZTtcblxuICAgICAgICBpZiAodHlwZW9mIHBhcmVudEVsZW1lbnQgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICB0aGlzLmh0bWxQYXJlbnRFbGVtZW50SWQgPSBwYXJlbnRFbGVtZW50O1xuXG4gICAgICAgICAgICBjb25zdCBwYXJlbnRFbGVtZW50RG9tID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQocGFyZW50RWxlbWVudCk7XG4gICAgICAgICAgICBpZiAocGFyZW50RWxlbWVudERvbSkge1xuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9QcmV2aWV3ID0gcGFyZW50RWxlbWVudERvbS5hcHBlbmRDaGlsZCh0aGlzLnZpZGVvUHJldmlldyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLmh0bWxQYXJlbnRFbGVtZW50SWQgPSBwYXJlbnRFbGVtZW50LmlkO1xuICAgICAgICAgICAgdGhpcy52aWRlb1ByZXZpZXcgPSBwYXJlbnRFbGVtZW50LmFwcGVuZENoaWxkKHRoaXMudmlkZW9QcmV2aWV3KTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMudmlkZW9QcmV2aWV3LnNyYyA9IHRoaXMudmlkZW9QcmV2aWV3U3JjO1xuXG4gICAgICAgIHJldHVybiB0aGlzLnZpZGVvUHJldmlldztcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIEdyYWNlZnVsbHkgc3RvcHMgYW5kIGNsZWFucyB0aGUgY3VycmVudCByZWNvcmRpbmcgKFdBUk5JTkc6IGl0IGlzIGNvbXBsZXRlbHkgZGlzbWlzc2VkKS4gU2V0cyBbW3N0YXRlXV0gdG8gYFJFQURZYCBzbyB0aGUgcmVjb3JkaW5nIGNhbiBzdGFydCBhZ2FpblxuICAgICAqL1xuICAgIGNsZWFuKCk6IHZvaWQge1xuICAgICAgICBjb25zdCBmID0gKCkgPT4ge1xuICAgICAgICAgICAgZGVsZXRlIHRoaXMuYmxvYjtcbiAgICAgICAgICAgIHRoaXMuY2h1bmtzID0gW107XG4gICAgICAgICAgICB0aGlzLmNvdW50ID0gMDtcbiAgICAgICAgICAgIGRlbGV0ZSB0aGlzLm1lZGlhUmVjb3JkZXI7XG4gICAgICAgICAgICB0aGlzLnN0YXRlID0gTG9jYWxSZWNvcmRlclN0YXRlLlJFQURZO1xuICAgICAgICB9O1xuICAgICAgICBpZiAodGhpcy5zdGF0ZSA9PT0gTG9jYWxSZWNvcmRlclN0YXRlLlJFQ09SRElORyB8fCB0aGlzLnN0YXRlID09PSBMb2NhbFJlY29yZGVyU3RhdGUuUEFVU0VEKSB7XG4gICAgICAgICAgICB0aGlzLnN0b3AoKS50aGVuKCgpID0+IGYoKSkuY2F0Y2goKCkgPT4gZigpKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGYoKTtcbiAgICAgICAgfVxuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogRG93bmxvYWRzIHRoZSByZWNvcmRlZCB2aWRlbyB0aHJvdWdoIHRoZSBicm93c2VyLiBbW3N0YXRlXV0gcHJvcGVydHkgbXVzdCBiZSBgRklOSVNIRURgXG4gICAgICovXG4gICAgZG93bmxvYWQoKTogdm9pZCB7XG4gICAgICAgIGlmICh0aGlzLnN0YXRlICE9PSBMb2NhbFJlY29yZGVyU3RhdGUuRklOSVNIRUQpIHtcbiAgICAgICAgICAgIHRocm93IChFcnJvcignXFwnTG9jYWxSZWNvcmQuZG93bmxvYWQoKVxcJyBuZWVkcyBcXCdMb2NhbFJlY29yZC5zdGF0ZVxcJyB0byBiZSBcXCdGSU5JU0hFRFxcJyAoY3VycmVudCB2YWx1ZTogXFwnJyArIHRoaXMuc3RhdGUgKyAnXFwnKS4gQ2FsbCBcXCdMb2NhbFJlY29yZGVyLnN0b3AoKVxcJyBiZWZvcmUnKSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjb25zdCBhOiBIVE1MQW5jaG9yRWxlbWVudCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2EnKTtcbiAgICAgICAgICAgIGEuc3R5bGUuZGlzcGxheSA9ICdub25lJztcbiAgICAgICAgICAgIGRvY3VtZW50LmJvZHkuYXBwZW5kQ2hpbGQoYSk7XG5cbiAgICAgICAgICAgIGNvbnN0IHVybCA9IHdpbmRvdy5VUkwuY3JlYXRlT2JqZWN0VVJMKHRoaXMuYmxvYik7XG4gICAgICAgICAgICBhLmhyZWYgPSB1cmw7XG4gICAgICAgICAgICBhLmRvd25sb2FkID0gdGhpcy5pZCArICcud2VibSc7XG4gICAgICAgICAgICBhLmNsaWNrKCk7XG4gICAgICAgICAgICB3aW5kb3cuVVJMLnJldm9rZU9iamVjdFVSTCh1cmwpO1xuXG4gICAgICAgICAgICBkb2N1bWVudC5ib2R5LnJlbW92ZUNoaWxkKGEpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0cyB0aGUgcmF3IEJsb2IgZmlsZS4gTWV0aG9kcyBwcmV2aWV3LCBkb3dubG9hZCwgdXBsb2FkQXNCaW5hcnkgYW5kIHVwbG9hZEFzTXVsdGlwYXJ0ZmlsZSB1c2UgdGhpcyBzYW1lIGZpbGUgdG8gcGVyZm9ybSB0aGVpciBzcGVjaWZpYyBhY3Rpb25zLiBbW3N0YXRlXV0gcHJvcGVydHkgbXVzdCBiZSBgRklOSVNIRURgXG4gICAgICovXG4gICAgZ2V0QmxvYigpOiBCbG9iIHtcbiAgICAgICAgaWYgKHRoaXMuc3RhdGUgIT09IExvY2FsUmVjb3JkZXJTdGF0ZS5GSU5JU0hFRCkge1xuICAgICAgICAgICAgdGhyb3cgKEVycm9yKCdDYWxsIFxcJ0xvY2FsUmVjb3JkLnN0b3AoKVxcJyBiZWZvcmUgZ2V0dGluZyBCbG9iIGZpbGUnKSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5ibG9iO1xuICAgICAgICB9XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBVcGxvYWRzIHRoZSByZWNvcmRlZCB2aWRlbyBhcyBhIGJpbmFyeSBmaWxlIHBlcmZvcm1pbmcgYW4gSFRUUC9QT1NUIG9wZXJhdGlvbiB0byBVUkwgYGVuZHBvaW50YC4gW1tzdGF0ZV1dIHByb3BlcnR5IG11c3QgYmUgYEZJTklTSEVEYC4gT3B0aW9uYWwgSFRUUCBoZWFkZXJzIGNhbiBiZSBwYXNzZWQgYXMgc2Vjb25kIHBhcmFtZXRlci4gRm9yIGV4YW1wbGU6XG4gICAgICogYGBgXG4gICAgICogdmFyIGhlYWRlcnMgPSB7XG4gICAgICogIFwiQ29va2llXCI6IFwiJFZlcnNpb249MTsgU2tpbj1uZXc7XCIsXG4gICAgICogIFwiQXV0aG9yaXphdGlvblwiOlwiQmFzaWMgUVd4aFpHcGJqcHVJSE5sY3RaUT09XCJcbiAgICAgKiB9XG4gICAgICogYGBgXG4gICAgICogQHJldHVybnMgQSBQcm9taXNlICh0byB3aGljaCB5b3UgY2FuIG9wdGlvbmFsbHkgc3Vic2NyaWJlIHRvKSB0aGF0IGlzIHJlc29sdmVkIHdpdGggdGhlIGBodHRwLnJlc3BvbnNlVGV4dGAgZnJvbSBzZXJ2ZXIgaWYgdGhlIG9wZXJhdGlvbiB3YXMgc3VjY2Vzc2Z1bCBhbmQgcmVqZWN0ZWQgd2l0aCB0aGUgZmFpbGVkIGBodHRwLnN0YXR1c2AgaWYgbm90XG4gICAgICovXG4gICAgdXBsb2FkQXNCaW5hcnkoZW5kcG9pbnQ6IHN0cmluZywgaGVhZGVycz86IGFueSk6IFByb21pc2U8YW55PiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICBpZiAodGhpcy5zdGF0ZSAhPT0gTG9jYWxSZWNvcmRlclN0YXRlLkZJTklTSEVEKSB7XG4gICAgICAgICAgICAgICAgcmVqZWN0KEVycm9yKCdcXCdMb2NhbFJlY29yZC51cGxvYWRBc0JpbmFyeSgpXFwnIG5lZWRzIFxcJ0xvY2FsUmVjb3JkLnN0YXRlXFwnIHRvIGJlIFxcJ0ZJTklTSEVEXFwnIChjdXJyZW50IHZhbHVlOiBcXCcnICsgdGhpcy5zdGF0ZSArICdcXCcpLiBDYWxsIFxcJ0xvY2FsUmVjb3JkZXIuc3RvcCgpXFwnIGJlZm9yZScpKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY29uc3QgaHR0cCA9IG5ldyBYTUxIdHRwUmVxdWVzdCgpO1xuICAgICAgICAgICAgICAgIGh0dHAub3BlbignUE9TVCcsIGVuZHBvaW50LCB0cnVlKTtcblxuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgaGVhZGVycyA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgICAgICAgICAgICAgZm9yIChjb25zdCBrZXkgb2YgT2JqZWN0LmtleXMoaGVhZGVycykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGh0dHAuc2V0UmVxdWVzdEhlYWRlcihrZXksIGhlYWRlcnNba2V5XSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBodHRwLm9ucmVhZHlzdGF0ZWNoYW5nZSA9ICgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGh0dHAucmVhZHlTdGF0ZSA9PT0gNCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGh0dHAuc3RhdHVzLnRvU3RyaW5nKCkuY2hhckF0KDApID09PSAnMicpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBTdWNjZXNzIHJlc3BvbnNlIGZyb20gc2VydmVyIChIVFRQIHN0YXR1cyBzdGFuZGFyZDogMlhYIGlzIHN1Y2Nlc3MpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZShodHRwLnJlc3BvbnNlVGV4dCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChodHRwLnN0YXR1cyk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIGh0dHAuc2VuZCh0aGlzLmJsb2IpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFVwbG9hZHMgdGhlIHJlY29yZGVkIHZpZGVvIGFzIGEgbXVsdGlwYXJ0IGZpbGUgcGVyZm9ybWluZyBhbiBIVFRQL1BPU1Qgb3BlcmF0aW9uIHRvIFVSTCBgZW5kcG9pbnRgLiBbW3N0YXRlXV0gcHJvcGVydHkgbXVzdCBiZSBgRklOSVNIRURgLiBPcHRpb25hbCBIVFRQIGhlYWRlcnMgY2FuIGJlIHBhc3NlZCBhcyBzZWNvbmQgcGFyYW1ldGVyLiBGb3IgZXhhbXBsZTpcbiAgICAgKiBgYGBcbiAgICAgKiB2YXIgaGVhZGVycyA9IHtcbiAgICAgKiAgXCJDb29raWVcIjogXCIkVmVyc2lvbj0xOyBTa2luPW5ldztcIixcbiAgICAgKiAgXCJBdXRob3JpemF0aW9uXCI6XCJCYXNpYyBRV3hoWkdwYmpwdUlITmxjdFpRPT1cIlxuICAgICAqIH1cbiAgICAgKiBgYGBcbiAgICAgKiBAcmV0dXJucyBBIFByb21pc2UgKHRvIHdoaWNoIHlvdSBjYW4gb3B0aW9uYWxseSBzdWJzY3JpYmUgdG8pIHRoYXQgaXMgcmVzb2x2ZWQgd2l0aCB0aGUgYGh0dHAucmVzcG9uc2VUZXh0YCBmcm9tIHNlcnZlciBpZiB0aGUgb3BlcmF0aW9uIHdhcyBzdWNjZXNzZnVsIGFuZCByZWplY3RlZCB3aXRoIHRoZSBmYWlsZWQgYGh0dHAuc3RhdHVzYCBpZiBub3Q6XG4gICAgICovXG4gICAgdXBsb2FkQXNNdWx0aXBhcnRmaWxlKGVuZHBvaW50OiBzdHJpbmcsIGhlYWRlcnM/OiBhbnkpOiBQcm9taXNlPGFueT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgaWYgKHRoaXMuc3RhdGUgIT09IExvY2FsUmVjb3JkZXJTdGF0ZS5GSU5JU0hFRCkge1xuICAgICAgICAgICAgICAgIHJlamVjdChFcnJvcignXFwnTG9jYWxSZWNvcmQudXBsb2FkQXNNdWx0aXBhcnRmaWxlKClcXCcgbmVlZHMgXFwnTG9jYWxSZWNvcmQuc3RhdGVcXCcgdG8gYmUgXFwnRklOSVNIRURcXCcgKGN1cnJlbnQgdmFsdWU6IFxcJycgKyB0aGlzLnN0YXRlICsgJ1xcJykuIENhbGwgXFwnTG9jYWxSZWNvcmRlci5zdG9wKClcXCcgYmVmb3JlJykpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBjb25zdCBodHRwID0gbmV3IFhNTEh0dHBSZXF1ZXN0KCk7XG4gICAgICAgICAgICAgICAgaHR0cC5vcGVuKCdQT1NUJywgZW5kcG9pbnQsIHRydWUpO1xuXG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBoZWFkZXJzID09PSAnb2JqZWN0Jykge1xuICAgICAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IGtleSBvZiBPYmplY3Qua2V5cyhoZWFkZXJzKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaHR0cC5zZXRSZXF1ZXN0SGVhZGVyKGtleSwgaGVhZGVyc1trZXldKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGNvbnN0IHNlbmRhYmxlID0gbmV3IEZvcm1EYXRhKCk7XG4gICAgICAgICAgICAgICAgc2VuZGFibGUuYXBwZW5kKCdmaWxlJywgdGhpcy5ibG9iLCB0aGlzLmlkICsgJy53ZWJtJyk7XG5cbiAgICAgICAgICAgICAgICBodHRwLm9ucmVhZHlzdGF0ZWNoYW5nZSA9ICgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGh0dHAucmVhZHlTdGF0ZSA9PT0gNCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGh0dHAuc3RhdHVzLnRvU3RyaW5nKCkuY2hhckF0KDApID09PSAnMicpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBTdWNjZXNzIHJlc3BvbnNlIGZyb20gc2VydmVyIChIVFRQIHN0YXR1cyBzdGFuZGFyZDogMlhYIGlzIHN1Y2Nlc3MpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZShodHRwLnJlc3BvbnNlVGV4dCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChodHRwLnN0YXR1cyk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICAgICAgaHR0cC5zZW5kKHNlbmRhYmxlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG5cbiAgICAvKiBQcml2YXRlIG1ldGhvZHMgKi9cblxuICAgIHByaXZhdGUgb25TdG9wRGVmYXVsdCgpOiB2b2lkIHtcbiAgICAgICAgY29uc29sZS5sb2coJ01lZGlhUmVjb3JkZXIgc3RvcHBlZCAgKHN0YXRlPScgKyB0aGlzLm1lZGlhUmVjb3JkZXIuc3RhdGUgKyAnKScpO1xuXG4gICAgICAgIHRoaXMuYmxvYiA9IG5ldyBCbG9iKHRoaXMuY2h1bmtzLCB7IHR5cGU6ICd2aWRlby93ZWJtJyB9KTtcbiAgICAgICAgdGhpcy5jaHVua3MgPSBbXTtcblxuICAgICAgICB0aGlzLnZpZGVvUHJldmlld1NyYyA9IHdpbmRvdy5VUkwuY3JlYXRlT2JqZWN0VVJMKHRoaXMuYmxvYik7XG5cbiAgICAgICAgdGhpcy5zdGF0ZSA9IExvY2FsUmVjb3JkZXJTdGF0ZS5GSU5JU0hFRDtcbiAgICB9XG5cbn1cbiIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTctMjAxOCBPcGVuVmlkdSAoaHR0cHM6Ly9vcGVudmlkdS5pby8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuaW1wb3J0IHsgTG9jYWxSZWNvcmRlciB9IGZyb20gJy4vTG9jYWxSZWNvcmRlcic7XG5pbXBvcnQgeyBQdWJsaXNoZXIgfSBmcm9tICcuL1B1Ymxpc2hlcic7XG5pbXBvcnQgeyBTZXNzaW9uIH0gZnJvbSAnLi9TZXNzaW9uJztcbmltcG9ydCB7IFN0cmVhbSB9IGZyb20gJy4vU3RyZWFtJztcbmltcG9ydCB7IFN0cmVhbVByb3BlcnR5Q2hhbmdlZEV2ZW50IH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvU3RyZWFtUHJvcGVydHlDaGFuZ2VkRXZlbnQnO1xuaW1wb3J0IHsgRGV2aWNlIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9JbnRlcmZhY2VzL1B1YmxpYy9EZXZpY2UnO1xuaW1wb3J0IHsgT3BlblZpZHVBZHZhbmNlZENvbmZpZ3VyYXRpb24gfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHVibGljL09wZW5WaWR1QWR2YW5jZWRDb25maWd1cmF0aW9uJztcbmltcG9ydCB7IFB1Ymxpc2hlclByb3BlcnRpZXMgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHVibGljL1B1Ymxpc2hlclByb3BlcnRpZXMnO1xuaW1wb3J0IHsgT3BlblZpZHVFcnJvciwgT3BlblZpZHVFcnJvck5hbWUgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0VudW1zL09wZW5WaWR1RXJyb3InO1xuaW1wb3J0IHsgVmlkZW9JbnNlcnRNb2RlIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FbnVtcy9WaWRlb0luc2VydE1vZGUnO1xuXG5pbXBvcnQgKiBhcyBzY3JlZW5TaGFyaW5nQXV0byBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL1NjcmVlblNoYXJpbmcvU2NyZWVuLUNhcHR1cmluZy1BdXRvJztcbmltcG9ydCAqIGFzIHNjcmVlblNoYXJpbmcgZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9TY3JlZW5TaGFyaW5nL1NjcmVlbi1DYXB0dXJpbmcnO1xuXG5pbXBvcnQgUnBjQnVpbGRlciA9IHJlcXVpcmUoJy4uL09wZW5WaWR1SW50ZXJuYWwvS3VyZW50b1V0aWxzL2t1cmVudG8tanNvbnJwYycpO1xuaW1wb3J0IHBsYXRmb3JtID0gcmVxdWlyZSgncGxhdGZvcm0nKTtcblxuXG4vKipcbiAqIEVudHJ5cG9pbnQgb2YgT3BlblZpZHUgQnJvd3NlciBsaWJyYXJ5LlxuICogVXNlIGl0IHRvIGluaXRpYWxpemUgb2JqZWN0cyBvZiB0eXBlIFtbU2Vzc2lvbl1dLCBbW1B1Ymxpc2hlcl1dIGFuZCBbW0xvY2FsUmVjb3JkZXJdXVxuICovXG5leHBvcnQgY2xhc3MgT3BlblZpZHUge1xuXG4gIHByaXZhdGUganNvblJwY0NsaWVudDogYW55O1xuXG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICBzZXNzaW9uOiBTZXNzaW9uO1xuICAvKipcbiAgICogQGhpZGRlblxuICAgKi9cbiAgcHVibGlzaGVyczogUHVibGlzaGVyW10gPSBbXTtcbiAgLyoqXG4gICAqIEBoaWRkZW5cbiAgICovXG4gIHdzVXJpOiBzdHJpbmc7XG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICBzZWNyZXQgPSAnJztcbiAgLyoqXG4gICAqIEBoaWRkZW5cbiAgICovXG4gIHJlY29yZGVyID0gZmFsc2U7XG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICBpY2VTZXJ2ZXJzOiBSVENJY2VTZXJ2ZXJbXTtcbiAgLyoqXG4gICAqIEBoaWRkZW5cbiAgICovXG4gIHJvbGU6IHN0cmluZztcbiAgLyoqXG4gICAqIEBoaWRkZW5cbiAgICovXG4gIGFkdmFuY2VkQ29uZmlndXJhdGlvbjogT3BlblZpZHVBZHZhbmNlZENvbmZpZ3VyYXRpb24gPSB7fTtcblxuICBjb25zdHJ1Y3RvcigpIHtcbiAgICBjb25zb2xlLmluZm8oXCInT3BlblZpZHUnIGluaXRpYWxpemVkXCIpO1xuXG4gICAgaWYgKHBsYXRmb3JtLm5hbWUhIS50b0xvd2VyQ2FzZSgpLmluZGV4T2YoJ21vYmlsZScpICE9PSAtMSkge1xuICAgICAgLy8gTGlzdGVuIHRvIG9yaWVudGF0aW9uY2hhbmdlIG9ubHkgb24gbW9iaWxlIGJyb3dzZXJzXG4gICAgICAoPGFueT53aW5kb3cpLm9ub3JpZW50YXRpb25jaGFuZ2UgPSAoKSA9PiB7XG4gICAgICAgIHRoaXMucHVibGlzaGVycy5mb3JFYWNoKHB1Ymxpc2hlciA9PiB7XG4gICAgICAgICAgaWYgKCEhcHVibGlzaGVyLnN0cmVhbSAmJiAhIXB1Ymxpc2hlci5zdHJlYW0uaGFzVmlkZW8gJiYgISFwdWJsaXNoZXIuc3RyZWFtLnN0cmVhbU1hbmFnZXIudmlkZW9zWzBdKSB7XG5cbiAgICAgICAgICAgIGxldCBhdHRlbXB0cyA9IDA7XG5cbiAgICAgICAgICAgIGNvbnN0IG9sZFdpZHRoID0gcHVibGlzaGVyLnN0cmVhbS52aWRlb0RpbWVuc2lvbnMud2lkdGg7XG4gICAgICAgICAgICBjb25zdCBvbGRIZWlnaHQgPSBwdWJsaXNoZXIuc3RyZWFtLnZpZGVvRGltZW5zaW9ucy5oZWlnaHQ7XG4gICAgICAgICAgICAvLyBOZXcgcmVzb2x1dGlvbiBnb3QgZnJvbSBkaWZmZXJlbnQgcGxhY2VzIGZvciBDaHJvbWUgYW5kIEZpcmVmb3guIENocm9tZSBuZWVkcyBhIHZpZGVvV2lkdGggYW5kIHZpZGVvSGVpZ2h0IG9mIGEgdmlkZW9FbGVtZW50LlxuICAgICAgICAgICAgLy8gRmlyZWZveCBuZWVkcyBnZXRTZXR0aW5ncyBmcm9tIHRoZSB2aWRlb1RyYWNrXG4gICAgICAgICAgICBsZXQgZmlyZWZveFNldHRpbmdzID0gcHVibGlzaGVyLnN0cmVhbS5nZXRNZWRpYVN0cmVhbSgpLmdldFZpZGVvVHJhY2tzKClbMF0uZ2V0U2V0dGluZ3MoKTtcbiAgICAgICAgICAgIGxldCBuZXdXaWR0aCA9IChwbGF0Zm9ybS5uYW1lISEudG9Mb3dlckNhc2UoKS5pbmRleE9mKCdmaXJlZm94JykgIT09IC0xKSA/IGZpcmVmb3hTZXR0aW5ncy53aWR0aCA6IHB1Ymxpc2hlci52aWRlb1JlZmVyZW5jZS52aWRlb1dpZHRoO1xuICAgICAgICAgICAgbGV0IG5ld0hlaWdodCA9IChwbGF0Zm9ybS5uYW1lISEudG9Mb3dlckNhc2UoKS5pbmRleE9mKCdmaXJlZm94JykgIT09IC0xKSA/IGZpcmVmb3hTZXR0aW5ncy5oZWlnaHQgOiBwdWJsaXNoZXIudmlkZW9SZWZlcmVuY2UudmlkZW9IZWlnaHQ7XG5cbiAgICAgICAgICAgIGNvbnN0IHJlcGVhdFVudGlsQ2hhbmdlID0gc2V0SW50ZXJ2YWwoKCkgPT4ge1xuICAgICAgICAgICAgICBmaXJlZm94U2V0dGluZ3MgPSBwdWJsaXNoZXIuc3RyZWFtLmdldE1lZGlhU3RyZWFtKCkuZ2V0VmlkZW9UcmFja3MoKVswXS5nZXRTZXR0aW5ncygpO1xuICAgICAgICAgICAgICBuZXdXaWR0aCA9IChwbGF0Zm9ybS5uYW1lISEudG9Mb3dlckNhc2UoKS5pbmRleE9mKCdmaXJlZm94JykgIT09IC0xKSA/IGZpcmVmb3hTZXR0aW5ncy53aWR0aCA6IHB1Ymxpc2hlci52aWRlb1JlZmVyZW5jZS52aWRlb1dpZHRoO1xuICAgICAgICAgICAgICBuZXdIZWlnaHQgPSAocGxhdGZvcm0ubmFtZSEhLnRvTG93ZXJDYXNlKCkuaW5kZXhPZignZmlyZWZveCcpICE9PSAtMSkgPyBmaXJlZm94U2V0dGluZ3MuaGVpZ2h0IDogcHVibGlzaGVyLnZpZGVvUmVmZXJlbmNlLnZpZGVvSGVpZ2h0O1xuICAgICAgICAgICAgICBzZW5kU3RyZWFtUHJvcGVydHlDaGFuZ2VkRXZlbnQob2xkV2lkdGgsIG9sZEhlaWdodCwgbmV3V2lkdGgsIG5ld0hlaWdodCk7XG4gICAgICAgICAgICB9LCAxMDApO1xuXG4gICAgICAgICAgICBjb25zdCBzZW5kU3RyZWFtUHJvcGVydHlDaGFuZ2VkRXZlbnQgPSAob2xkV2lkdGgsIG9sZEhlaWdodCwgbmV3V2lkdGgsIG5ld0hlaWdodCkgPT4ge1xuICAgICAgICAgICAgICBhdHRlbXB0cysrO1xuICAgICAgICAgICAgICBpZiAoYXR0ZW1wdHMgPiA0KSB7XG4gICAgICAgICAgICAgICAgY2xlYXJUaW1lb3V0KHJlcGVhdFVudGlsQ2hhbmdlKTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICBpZiAobmV3V2lkdGggIT09IG9sZFdpZHRoIHx8IG5ld0hlaWdodCAhPT0gb2xkSGVpZ2h0KSB7XG4gICAgICAgICAgICAgICAgcHVibGlzaGVyLnN0cmVhbS52aWRlb0RpbWVuc2lvbnMgPSB7XG4gICAgICAgICAgICAgICAgICB3aWR0aDogbmV3V2lkdGggfHwgMCxcbiAgICAgICAgICAgICAgICAgIGhlaWdodDogbmV3SGVpZ2h0IHx8IDBcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIHRoaXMuc2VuZFJlcXVlc3QoXG4gICAgICAgICAgICAgICAgICAnc3RyZWFtUHJvcGVydHlDaGFuZ2VkJyxcbiAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgc3RyZWFtSWQ6IHB1Ymxpc2hlci5zdHJlYW0uc3RyZWFtSWQsXG4gICAgICAgICAgICAgICAgICAgIHByb3BlcnR5OiAndmlkZW9EaW1lbnNpb25zJyxcbiAgICAgICAgICAgICAgICAgICAgbmV3VmFsdWU6IEpTT04uc3RyaW5naWZ5KHB1Ymxpc2hlci5zdHJlYW0udmlkZW9EaW1lbnNpb25zKSxcbiAgICAgICAgICAgICAgICAgICAgcmVhc29uOiAnZGV2aWNlUm90YXRlZCdcbiAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAoZXJyb3IsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoXCJFcnJvciBzZW5kaW5nICdzdHJlYW1Qcm9wZXJ0eUNoYW5nZWQnIGV2ZW50XCIsIGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICB0aGlzLnNlc3Npb24uZW1pdEV2ZW50KCdzdHJlYW1Qcm9wZXJ0eUNoYW5nZWQnLCBbbmV3IFN0cmVhbVByb3BlcnR5Q2hhbmdlZEV2ZW50KHRoaXMuc2Vzc2lvbiwgcHVibGlzaGVyLnN0cmVhbSwgJ3ZpZGVvRGltZW5zaW9ucycsIHB1Ymxpc2hlci5zdHJlYW0udmlkZW9EaW1lbnNpb25zLCB7IHdpZHRoOiBvbGRXaWR0aCwgaGVpZ2h0OiBvbGRIZWlnaHQgfSwgJ2RldmljZVJvdGF0ZWQnKV0pO1xuICAgICAgICAgICAgICAgICAgICAgIHB1Ymxpc2hlci5lbWl0RXZlbnQoJ3N0cmVhbVByb3BlcnR5Q2hhbmdlZCcsIFtuZXcgU3RyZWFtUHJvcGVydHlDaGFuZ2VkRXZlbnQocHVibGlzaGVyLCBwdWJsaXNoZXIuc3RyZWFtLCAndmlkZW9EaW1lbnNpb25zJywgcHVibGlzaGVyLnN0cmVhbS52aWRlb0RpbWVuc2lvbnMsIHsgd2lkdGg6IG9sZFdpZHRoLCBoZWlnaHQ6IG9sZEhlaWdodCB9LCAnZGV2aWNlUm90YXRlZCcpXSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIGNsZWFyVGltZW91dChyZXBlYXRVbnRpbENoYW5nZSk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH07XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgIH07XG4gICAgfVxuICB9XG5cblxuICAvKipcbiAgICogUmV0dXJucyBuZXcgc2Vzc2lvblxuICAgKi9cbiAgaW5pdFNlc3Npb24oKTogU2Vzc2lvbiB7XG4gICAgdGhpcy5zZXNzaW9uID0gbmV3IFNlc3Npb24odGhpcyk7XG4gICAgcmV0dXJuIHRoaXMuc2Vzc2lvbjtcbiAgfVxuXG5cbiAgaW5pdFB1Ymxpc2hlcih0YXJnZXRFbGVtZW50OiBzdHJpbmcgfCBIVE1MRWxlbWVudCk6IFB1Ymxpc2hlcjtcbiAgaW5pdFB1Ymxpc2hlcih0YXJnZXRFbGVtZW50OiBzdHJpbmcgfCBIVE1MRWxlbWVudCwgcHJvcGVydGllczogUHVibGlzaGVyUHJvcGVydGllcyk6IFB1Ymxpc2hlcjtcbiAgaW5pdFB1Ymxpc2hlcih0YXJnZXRFbGVtZW50OiBzdHJpbmcgfCBIVE1MRWxlbWVudCwgY29tcGxldGlvbkhhbmRsZXI6IChlcnJvcjogRXJyb3IgfCB1bmRlZmluZWQpID0+IHZvaWQpOiBQdWJsaXNoZXI7XG4gIGluaXRQdWJsaXNoZXIodGFyZ2V0RWxlbWVudDogc3RyaW5nIHwgSFRNTEVsZW1lbnQsIHByb3BlcnRpZXM6IFB1Ymxpc2hlclByb3BlcnRpZXMsIGNvbXBsZXRpb25IYW5kbGVyOiAoZXJyb3I6IEVycm9yIHwgdW5kZWZpbmVkKSA9PiB2b2lkKTogUHVibGlzaGVyO1xuXG4gIC8qKlxuICAgKiBSZXR1cm5zIGEgbmV3IHB1Ymxpc2hlclxuICAgKlxuICAgKiAjIyMjIEV2ZW50cyBkaXNwYXRjaGVkXG4gICAqXG4gICAqIFRoZSBbW1B1Ymxpc2hlcl1dIG9iamVjdCB3aWxsIGRpc3BhdGNoIGFuIGBhY2Nlc3NEaWFsb2dPcGVuZWRgIGV2ZW50LCBvbmx5IGlmIHRoZSBwb3AtdXAgc2hvd24gYnkgdGhlIGJyb3dzZXIgdG8gcmVxdWVzdCBwZXJtaXNzaW9ucyBmb3IgdGhlIGNhbWVyYSBpcyBvcGVuZWQuIFlvdSBjYW4gdXNlIHRoaXMgZXZlbnQgdG8gYWxlcnQgdGhlIHVzZXIgYWJvdXQgZ3JhbnRpbmcgcGVybWlzc2lvbnNcbiAgICogZm9yIHlvdXIgd2Vic2l0ZS4gQW4gYGFjY2Vzc0RpYWxvZ0Nsb3NlZGAgZXZlbnQgd2lsbCBhbHNvIGJlIGRpc3BhdGNoZWQgYWZ0ZXIgdXNlciBjbGlja3Mgb24gXCJBbGxvd1wiIG9yIFwiQmxvY2tcIiBpbiB0aGUgcG9wLXVwLlxuICAgKlxuICAgKiBUaGUgW1tQdWJsaXNoZXJdXSBvYmplY3Qgd2lsbCBkaXNwYXRjaCBhbiBgYWNjZXNzQWxsb3dlZGAgb3IgYGFjY2Vzc0RlbmllZGAgZXZlbnQgb25jZSBpdCBoYXMgYmVlbiBncmFudGVkIGFjY2VzcyB0byB0aGUgcmVxdWVzdGVkIGlucHV0IGRldmljZXMgb3Igbm90LlxuICAgKlxuICAgKiBUaGUgW1tQdWJsaXNoZXJdXSBvYmplY3Qgd2lsbCBkaXNwYXRjaCBhIGB2aWRlb0VsZW1lbnRDcmVhdGVkYCBldmVudCBvbmNlIGEgSFRNTCB2aWRlbyBlbGVtZW50IGhhcyBiZWVuIGFkZGVkIHRvIERPTSAob25seSBpZiB5b3VcbiAgICogW2xldCBPcGVuVmlkdSB0YWtlIGNhcmUgb2YgdGhlIHZpZGVvIHBsYXllcnNdKC9kb2NzL2hvdy1kby1pL21hbmFnZS12aWRlb3MvI2xldC1vcGVudmlkdS10YWtlLWNhcmUtb2YtdGhlLXZpZGVvLXBsYXllcnMpKS4gU2VlIFtbVmlkZW9FbGVtZW50RXZlbnRdXSB0byBsZWFybiBtb3JlLlxuICAgKlxuICAgKiBUaGUgW1tQdWJsaXNoZXJdXSBvYmplY3Qgd2lsbCBkaXNwYXRjaCBhIGBzdHJlYW1QbGF5aW5nYCBldmVudCBvbmNlIHRoZSBsb2NhbCBzdHJlYW1zIHN0YXJ0cyBwbGF5aW5nLiBTZWUgW1tTdHJlYW1NYW5hZ2VyRXZlbnRdXSB0byBsZWFybiBtb3JlLlxuICAgKlxuICAgKiBAcGFyYW0gdGFyZ2V0RWxlbWVudCAgSFRNTCBET00gZWxlbWVudCAob3IgaXRzIGBpZGAgYXR0cmlidXRlKSBpbiB3aGljaCB0aGUgdmlkZW8gZWxlbWVudCBvZiB0aGUgUHVibGlzaGVyIHdpbGwgYmUgaW5zZXJ0ZWQgKHNlZSBbW1B1Ymxpc2hlclByb3BlcnRpZXMuaW5zZXJ0TW9kZV1dKS4gSWYgKm51bGwqIG9yICp1bmRlZmluZWQqIG5vIGRlZmF1bHQgdmlkZW8gd2lsbCBiZSBjcmVhdGVkIGZvciB0aGlzIFB1Ymxpc2hlci5cbiAgICogWW91IGNhbiBhbHdheXMgY2FsbCBtZXRob2QgW1tQdWJsaXNoZXIuYWRkVmlkZW9FbGVtZW50XV0gb3IgW1tQdWJsaXNoZXIuY3JlYXRlVmlkZW9FbGVtZW50XV0gdG8gbWFuYWdlIHRoZSB2aWRlbyBlbGVtZW50cyBvbiB5b3VyIG93biAoc2VlIFtNYW5hZ2UgdmlkZW8gcGxheWVyc10oL2RvY3MvaG93LWRvLWkvbWFuYWdlLXZpZGVvcykgc2VjdGlvbilcbiAgICogQHBhcmFtIGNvbXBsZXRpb25IYW5kbGVyIGBlcnJvcmAgcGFyYW1ldGVyIGlzIG51bGwgaWYgYGluaXRQdWJsaXNoZXJgIHN1Y2NlZWRzLCBhbmQgaXMgZGVmaW5lZCBpZiBpdCBmYWlscy5cbiAgICogICAgICAgICAgICAgICAgICAgICAgICAgIGBjb21wbGV0aW9uSGFuZGxlcmAgZnVuY3Rpb24gaXMgY2FsbGVkIGJlZm9yZSB0aGUgUHVibGlzaGVyIGRpc3BhdGNoZXMgYW4gYGFjY2Vzc0FsbG93ZWRgIG9yIGFuIGBhY2Nlc3NEZW5pZWRgIGV2ZW50XG4gICAqL1xuICBpbml0UHVibGlzaGVyKHRhcmdldEVsZW1lbnQ6IHN0cmluZyB8IEhUTUxFbGVtZW50LCBwYXJhbTI/LCBwYXJhbTM/KTogUHVibGlzaGVyIHtcblxuICAgIGxldCBwcm9wZXJ0aWVzOiBQdWJsaXNoZXJQcm9wZXJ0aWVzO1xuXG4gICAgaWYgKCEhcGFyYW0yICYmICh0eXBlb2YgcGFyYW0yICE9PSAnZnVuY3Rpb24nKSkge1xuXG4gICAgICAvLyBNYXRjaGVzICdpbml0UHVibGlzaGVyKHRhcmdldEVsZW1lbnQsIHByb3BlcnRpZXMpJyBvciAnaW5pdFB1Ymxpc2hlcih0YXJnZXRFbGVtZW50LCBwcm9wZXJ0aWVzLCBjb21wbGV0aW9uSGFuZGxlciknXG5cbiAgICAgIHByb3BlcnRpZXMgPSAoPFB1Ymxpc2hlclByb3BlcnRpZXM+cGFyYW0yKTtcblxuICAgICAgcHJvcGVydGllcyA9IHtcbiAgICAgICAgYXVkaW9Tb3VyY2U6ICh0eXBlb2YgcHJvcGVydGllcy5hdWRpb1NvdXJjZSAhPT0gJ3VuZGVmaW5lZCcpID8gcHJvcGVydGllcy5hdWRpb1NvdXJjZSA6IHVuZGVmaW5lZCxcbiAgICAgICAgZnJhbWVSYXRlOiB0aGlzLmlzTWVkaWFTdHJlYW1UcmFjayhwcm9wZXJ0aWVzLnZpZGVvU291cmNlKSA/IHVuZGVmaW5lZCA6ICgodHlwZW9mIHByb3BlcnRpZXMuZnJhbWVSYXRlICE9PSAndW5kZWZpbmVkJykgPyBwcm9wZXJ0aWVzLmZyYW1lUmF0ZSA6IHVuZGVmaW5lZCksXG4gICAgICAgIGluc2VydE1vZGU6ICh0eXBlb2YgcHJvcGVydGllcy5pbnNlcnRNb2RlICE9PSAndW5kZWZpbmVkJykgPyAoKHR5cGVvZiBwcm9wZXJ0aWVzLmluc2VydE1vZGUgPT09ICdzdHJpbmcnKSA/IFZpZGVvSW5zZXJ0TW9kZVtwcm9wZXJ0aWVzLmluc2VydE1vZGVdIDogcHJvcGVydGllcy5pbnNlcnRNb2RlKSA6IFZpZGVvSW5zZXJ0TW9kZS5BUFBFTkQsXG4gICAgICAgIG1pcnJvcjogKHR5cGVvZiBwcm9wZXJ0aWVzLm1pcnJvciAhPT0gJ3VuZGVmaW5lZCcpID8gcHJvcGVydGllcy5taXJyb3IgOiB0cnVlLFxuICAgICAgICBwdWJsaXNoQXVkaW86ICh0eXBlb2YgcHJvcGVydGllcy5wdWJsaXNoQXVkaW8gIT09ICd1bmRlZmluZWQnKSA/IHByb3BlcnRpZXMucHVibGlzaEF1ZGlvIDogdHJ1ZSxcbiAgICAgICAgcHVibGlzaFZpZGVvOiAodHlwZW9mIHByb3BlcnRpZXMucHVibGlzaFZpZGVvICE9PSAndW5kZWZpbmVkJykgPyBwcm9wZXJ0aWVzLnB1Ymxpc2hWaWRlbyA6IHRydWUsXG4gICAgICAgIHJlc29sdXRpb246IHRoaXMuaXNNZWRpYVN0cmVhbVRyYWNrKHByb3BlcnRpZXMudmlkZW9Tb3VyY2UpID8gdW5kZWZpbmVkIDogKCh0eXBlb2YgcHJvcGVydGllcy5yZXNvbHV0aW9uICE9PSAndW5kZWZpbmVkJykgPyBwcm9wZXJ0aWVzLnJlc29sdXRpb24gOiAnNjQweDQ4MCcpLFxuICAgICAgICB2aWRlb1NvdXJjZTogKHR5cGVvZiBwcm9wZXJ0aWVzLnZpZGVvU291cmNlICE9PSAndW5kZWZpbmVkJykgPyBwcm9wZXJ0aWVzLnZpZGVvU291cmNlIDogdW5kZWZpbmVkXG4gICAgICB9O1xuICAgIH0gZWxzZSB7XG5cbiAgICAgIC8vIE1hdGNoZXMgJ2luaXRQdWJsaXNoZXIodGFyZ2V0RWxlbWVudCknIG9yICdpbml0UHVibGlzaGVyKHRhcmdldEVsZW1lbnQsIGNvbXBsZXRpb25IYW5kbGVyKSdcblxuICAgICAgcHJvcGVydGllcyA9IHtcbiAgICAgICAgaW5zZXJ0TW9kZTogVmlkZW9JbnNlcnRNb2RlLkFQUEVORCxcbiAgICAgICAgbWlycm9yOiB0cnVlLFxuICAgICAgICBwdWJsaXNoQXVkaW86IHRydWUsXG4gICAgICAgIHB1Ymxpc2hWaWRlbzogdHJ1ZSxcbiAgICAgICAgcmVzb2x1dGlvbjogJzY0MHg0ODAnXG4gICAgICB9O1xuICAgIH1cblxuICAgIGNvbnN0IHB1Ymxpc2hlcjogUHVibGlzaGVyID0gbmV3IFB1Ymxpc2hlcih0YXJnZXRFbGVtZW50LCBwcm9wZXJ0aWVzLCB0aGlzKTtcblxuICAgIGxldCBjb21wbGV0aW9uSGFuZGxlcjogKGVycm9yOiBFcnJvciB8IHVuZGVmaW5lZCkgPT4gdm9pZDtcbiAgICBpZiAoISFwYXJhbTIgJiYgKHR5cGVvZiBwYXJhbTIgPT09ICdmdW5jdGlvbicpKSB7XG4gICAgICBjb21wbGV0aW9uSGFuZGxlciA9IHBhcmFtMjtcbiAgICB9IGVsc2UgaWYgKCEhcGFyYW0zKSB7XG4gICAgICBjb21wbGV0aW9uSGFuZGxlciA9IHBhcmFtMztcbiAgICB9XG5cbiAgICBwdWJsaXNoZXIuaW5pdGlhbGl6ZSgpXG4gICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgIGlmIChjb21wbGV0aW9uSGFuZGxlciAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgY29tcGxldGlvbkhhbmRsZXIodW5kZWZpbmVkKTtcbiAgICAgICAgfVxuICAgICAgICBwdWJsaXNoZXIuZW1pdEV2ZW50KCdhY2Nlc3NBbGxvd2VkJywgW10pO1xuICAgICAgfSkuY2F0Y2goKGVycm9yKSA9PiB7XG4gICAgICAgIGlmIChjb21wbGV0aW9uSGFuZGxlciAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgY29tcGxldGlvbkhhbmRsZXIoZXJyb3IpO1xuICAgICAgICB9XG4gICAgICAgIHB1Ymxpc2hlci5lbWl0RXZlbnQoJ2FjY2Vzc0RlbmllZCcsIFtdKTtcbiAgICAgIH0pO1xuXG4gICAgdGhpcy5wdWJsaXNoZXJzLnB1c2gocHVibGlzaGVyKTtcbiAgICByZXR1cm4gcHVibGlzaGVyO1xuICB9XG5cblxuICAvKipcbiAgICogUHJvbWlzaWZpZWQgdmVyc2lvbiBvZiBbW09wZW5WaWR1LmluaXRQdWJsaXNoZXJdXVxuICAgKlxuICAgKiA+IFdBUk5JTkc6IGV2ZW50cyBgYWNjZXNzRGlhbG9nT3BlbmVkYCBhbmQgYGFjY2Vzc0RpYWxvZ0Nsb3NlZGAgd2lsbCBub3QgYmUgZGlzcGF0Y2hlZCBpZiB1c2luZyB0aGlzIG1ldGhvZCBpbnN0ZWFkIG9mIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dXG4gICAqL1xuICBpbml0UHVibGlzaGVyQXN5bmModGFyZ2V0RWxlbWVudDogc3RyaW5nIHwgSFRNTEVsZW1lbnQpOiBQcm9taXNlPFB1Ymxpc2hlcj47XG4gIGluaXRQdWJsaXNoZXJBc3luYyh0YXJnZXRFbGVtZW50OiBzdHJpbmcgfCBIVE1MRWxlbWVudCwgcHJvcGVydGllczogUHVibGlzaGVyUHJvcGVydGllcyk6IFByb21pc2U8UHVibGlzaGVyPjtcblxuICBpbml0UHVibGlzaGVyQXN5bmModGFyZ2V0RWxlbWVudDogc3RyaW5nIHwgSFRNTEVsZW1lbnQsIHByb3BlcnRpZXM/OiBQdWJsaXNoZXJQcm9wZXJ0aWVzKTogUHJvbWlzZTxQdWJsaXNoZXI+IHtcbiAgICByZXR1cm4gbmV3IFByb21pc2U8UHVibGlzaGVyPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG5cbiAgICAgIGxldCBwdWJsaXNoZXI6IFB1Ymxpc2hlcjtcblxuICAgICAgY29uc3QgY2FsbGJhY2sgPSAoZXJyb3I6IEVycm9yKSA9PiB7XG4gICAgICAgIGlmICghIWVycm9yKSB7XG4gICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICByZXNvbHZlKHB1Ymxpc2hlcik7XG4gICAgICAgIH1cbiAgICAgIH07XG5cbiAgICAgIGlmICghIXByb3BlcnRpZXMpIHtcbiAgICAgICAgcHVibGlzaGVyID0gdGhpcy5pbml0UHVibGlzaGVyKHRhcmdldEVsZW1lbnQsIHByb3BlcnRpZXMsIGNhbGxiYWNrKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHB1Ymxpc2hlciA9IHRoaXMuaW5pdFB1Ymxpc2hlcih0YXJnZXRFbGVtZW50LCBjYWxsYmFjayk7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIGEgbmV3IGxvY2FsIHJlY29yZGVyIGZvciByZWNvcmRpbmcgc3RyZWFtcyBzdHJhaWdodCBhd2F5IGZyb20gdGhlIGJyb3dzZXJcbiAgICogQHBhcmFtIHN0cmVhbSAgU3RyZWFtIHRvIHJlY29yZFxuICAgKi9cbiAgaW5pdExvY2FsUmVjb3JkZXIoc3RyZWFtOiBTdHJlYW0pOiBMb2NhbFJlY29yZGVyIHtcbiAgICByZXR1cm4gbmV3IExvY2FsUmVjb3JkZXIoc3RyZWFtKTtcbiAgfVxuXG5cbiAgLyoqXG4gICAqIENoZWNrcyBpZiB0aGUgYnJvd3NlciBzdXBwb3J0cyBPcGVuVmlkdVxuICAgKiBAcmV0dXJucyAxIGlmIHRoZSBicm93c2VyIHN1cHBvcnRzIE9wZW5WaWR1LCAwIG90aGVyd2lzZVxuICAgKi9cbiAgY2hlY2tTeXN0ZW1SZXF1aXJlbWVudHMoKTogbnVtYmVyIHtcbiAgICBjb25zdCBicm93c2VyID0gcGxhdGZvcm0ubmFtZTtcbiAgICBjb25zdCB2ZXJzaW9uID0gcGxhdGZvcm0udmVyc2lvbjtcblxuICAgIGlmICgoYnJvd3NlciAhPT0gJ0Nocm9tZScpICYmIChicm93c2VyICE9PSAnQ2hyb21lIE1vYmlsZScpICYmXG4gICAgICAoYnJvd3NlciAhPT0gJ0ZpcmVmb3gnKSAmJiAoYnJvd3NlciAhPT0gJ0ZpcmVmb3ggTW9iaWxlJykgJiYgKGJyb3dzZXIgIT09ICdGaXJlZm94IGZvciBpT1MnKSAmJlxuICAgICAgKGJyb3dzZXIgIT09ICdPcGVyYScpICYmIChicm93c2VyICE9PSAnT3BlcmEgTW9iaWxlJykgJiZcbiAgICAgIChicm93c2VyICE9PSAnU2FmYXJpJykpIHtcbiAgICAgIHJldHVybiAwO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gMTtcbiAgICB9XG4gIH1cblxuXG4gIC8qKlxuICAgKiBDb2xsZWN0cyBpbmZvcm1hdGlvbiBhYm91dCB0aGUgbWVkaWEgaW5wdXQgZGV2aWNlcyBhdmFpbGFibGUgb24gdGhlIHN5c3RlbS4gWW91IGNhbiBwYXNzIHByb3BlcnR5IGBkZXZpY2VJZGAgb2YgYSBbW0RldmljZV1dIG9iamVjdCBhcyB2YWx1ZSBvZiBgYXVkaW9Tb3VyY2VgIG9yIGB2aWRlb1NvdXJjZWAgcHJvcGVydGllcyBpbiBbW2luaXRQdWJsaXNoZXJdXSBtZXRob2RcbiAgICovXG4gIGdldERldmljZXMoKTogUHJvbWlzZTxEZXZpY2VbXT4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZTxEZXZpY2VbXT4oKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgbmF2aWdhdG9yLm1lZGlhRGV2aWNlcy5lbnVtZXJhdGVEZXZpY2VzKCkudGhlbigoZGV2aWNlSW5mb3MpID0+IHtcbiAgICAgICAgY29uc3QgZGV2aWNlczogRGV2aWNlW10gPSBbXTtcbiAgICAgICAgZGV2aWNlSW5mb3MuZm9yRWFjaChkZXZpY2VJbmZvID0+IHtcbiAgICAgICAgICBpZiAoZGV2aWNlSW5mby5raW5kID09PSAnYXVkaW9pbnB1dCcgfHwgZGV2aWNlSW5mby5raW5kID09PSAndmlkZW9pbnB1dCcpIHtcbiAgICAgICAgICAgIGRldmljZXMucHVzaCh7XG4gICAgICAgICAgICAgIGtpbmQ6IGRldmljZUluZm8ua2luZCxcbiAgICAgICAgICAgICAgZGV2aWNlSWQ6IGRldmljZUluZm8uZGV2aWNlSWQsXG4gICAgICAgICAgICAgIGxhYmVsOiBkZXZpY2VJbmZvLmxhYmVsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICByZXNvbHZlKGRldmljZXMpO1xuICAgICAgfSkuY2F0Y2goKGVycm9yKSA9PiB7XG4gICAgICAgIGNvbnNvbGUuZXJyb3IoJ0Vycm9yIGdldHRpbmcgZGV2aWNlcycsIGVycm9yKTtcbiAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9XG5cblxuICAvKipcbiAgICogR2V0IGEgTWVkaWFTdHJlYW0gb2JqZWN0IHRoYXQgeW91IGNhbiBjdXN0b21pemUgYmVmb3JlIGNhbGxpbmcgW1tpbml0UHVibGlzaGVyXV0gKHBhc3MgX01lZGlhU3RyZWFtVHJhY2tfIHByb3BlcnR5IG9mIHRoZSBfTWVkaWFTdHJlYW1fIHZhbHVlIHJlc29sdmVkIGJ5IHRoZSBQcm9taXNlIGFzIGBhdWRpb1NvdXJjZWAgb3IgYHZpZGVvU291cmNlYCBwcm9wZXJ0aWVzIGluIFtbaW5pdFB1Ymxpc2hlcl1dKVxuICAgKlxuICAgKiBQYXJhbWV0ZXIgYG9wdGlvbnNgIGlzIHRoZSBzYW1lIGFzIGluIFtbaW5pdFB1Ymxpc2hlcl1dIHNlY29uZCBwYXJhbWV0ZXIgKG9mIHR5cGUgW1tQdWJsaXNoZXJQcm9wZXJ0aWVzXV0pLCBidXQgb25seSB0aGUgZm9sbG93aW5nIHByb3BlcnRpZXMgd2lsbCBiZSBhcHBsaWVkOiBgYXVkaW9Tb3VyY2VgLCBgdmlkZW9Tb3VyY2VgLCBgZnJhbWVSYXRlYCwgYHJlc29sdXRpb25gXG4gICAqXG4gICAqIFRvIGN1c3RvbWl6ZSB0aGUgUHVibGlzaGVyJ3MgdmlkZW8sIHRoZSBBUEkgZm9yIEhUTUxDYW52YXNFbGVtZW50IGlzIHZlcnkgdXNlZnVsLiBGb3IgZXhhbXBsZSwgdG8gZ2V0IGEgYmxhY2stYW5kLXdoaXRlIHZpZGVvIGF0IDEwIGZwcyBhbmQgSEQgcmVzb2x1dGlvbiB3aXRoIG5vIHNvdW5kOlxuICAgKiBgYGBcbiAgICogdmFyIE9WID0gbmV3IE9wZW5WaWR1KCk7XG4gICAqIHZhciBGUkFNRV9SQVRFID0gMTA7XG4gICAqXG4gICAqIE9WLmdldFVzZXJNZWRpYSh7XG4gICAqICAgIGF1ZGlvU291cmNlOiBmYWxzZTtcbiAgICogICAgdmlkZW9Tb3VyY2U6IHVuZGVmaW5lZCxcbiAgICogICAgcmVzb2x1dGlvbjogJzEyODB4NzIwJyxcbiAgICogICAgZnJhbWVSYXRlOiBGUkFNRV9SQVRFXG4gICAqIH0pXG4gICAqIC50aGVuKG1lZGlhU3RyZWFtID0+IHtcbiAgICpcbiAgICogICAgdmFyIHZpZGVvVHJhY2sgPSBtZWRpYVN0cmVhbS5nZXRWaWRlb1RyYWNrcygpWzBdO1xuICAgKiAgICB2YXIgdmlkZW8gPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCd2aWRlbycpO1xuICAgKiAgICB2aWRlby5zcmNPYmplY3QgPSBuZXcgTWVkaWFTdHJlYW0oW3ZpZGVvVHJhY2tdKTtcbiAgICpcbiAgICogICAgdmFyIGNhbnZhcyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2NhbnZhcycpO1xuICAgKiAgICB2YXIgY3R4ID0gY2FudmFzLmdldENvbnRleHQoJzJkJyk7XG4gICAqICAgIGN0eC5maWx0ZXIgPSAnZ3JheXNjYWxlKDEwMCUpJztcbiAgICpcbiAgICogICAgdmlkZW8uYWRkRXZlbnRMaXN0ZW5lcigncGxheScsICgpID0+IHtcbiAgICogICAgICB2YXIgbG9vcCA9ICgpID0+IHtcbiAgICogICAgICAgIGlmICghdmlkZW8ucGF1c2VkICYmICF2aWRlby5lbmRlZCkge1xuICAgKiAgICAgICAgICBjdHguZHJhd0ltYWdlKHZpZGVvLCAwLCAwLCAzMDAsIDE3MCk7XG4gICAqICAgICAgICAgIHNldFRpbWVvdXQobG9vcCwgMTAwMC8gRlJBTUVfUkFURSk7IC8vIERyYXdpbmcgYXQgMTAgZnBzXG4gICAqICAgICAgICB9XG4gICAqICAgICAgfTtcbiAgICogICAgICBsb29wKCk7XG4gICAqICAgIH0pO1xuICAgKiAgICB2aWRlby5wbGF5KCk7XG4gICAqXG4gICAqICAgIHZhciBncmF5VmlkZW9UcmFjayA9IGNhbnZhcy5jYXB0dXJlU3RyZWFtKEZSQU1FX1JBVEUpLmdldFZpZGVvVHJhY2tzKClbMF07XG4gICAqICAgIHZhciBwdWJsaXNoZXIgPSB0aGlzLk9WLmluaXRQdWJsaXNoZXIoXG4gICAqICAgICAgbXlIdG1sVGFyZ2V0LFxuICAgKiAgICAgIHtcbiAgICogICAgICAgIGF1ZGlvU291cmNlOiBmYWxzZSxcbiAgICogICAgICAgIHZpZGVvU291cmNlOiBncmF5VmlkZW9UcmFja1xuICAgKiAgICAgIH0pO1xuICAgKiB9KTtcbiAgICogYGBgXG4gICAqL1xuICBnZXRVc2VyTWVkaWEob3B0aW9uczogUHVibGlzaGVyUHJvcGVydGllcyk6IFByb21pc2U8TWVkaWFTdHJlYW0+IHtcbiAgICByZXR1cm4gbmV3IFByb21pc2U8TWVkaWFTdHJlYW0+KChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIHRoaXMuZ2VuZXJhdGVNZWRpYUNvbnN0cmFpbnRzKG9wdGlvbnMpXG4gICAgICAgIC50aGVuKGNvbnN0cmFpbnRzID0+IHtcbiAgICAgICAgICBuYXZpZ2F0b3IubWVkaWFEZXZpY2VzLmdldFVzZXJNZWRpYShjb25zdHJhaW50cylcbiAgICAgICAgICAgIC50aGVuKG1lZGlhU3RyZWFtID0+IHtcbiAgICAgICAgICAgICAgcmVzb2x2ZShtZWRpYVN0cmVhbSk7XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICAgICAgbGV0IGVycm9yTmFtZTogT3BlblZpZHVFcnJvck5hbWU7XG4gICAgICAgICAgICAgIGNvbnN0IGVycm9yTWVzc2FnZSA9IGVycm9yLnRvU3RyaW5nKCk7XG4gICAgICAgICAgICAgIGlmICghKG9wdGlvbnMudmlkZW9Tb3VyY2UgPT09ICdzY3JlZW4nKSkge1xuICAgICAgICAgICAgICAgIGVycm9yTmFtZSA9IE9wZW5WaWR1RXJyb3JOYW1lLkRFVklDRV9BQ0NFU1NfREVOSUVEO1xuICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGVycm9yTmFtZSA9IE9wZW5WaWR1RXJyb3JOYW1lLlNDUkVFTl9DQVBUVVJFX0RFTklFRDtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICByZWplY3QobmV3IE9wZW5WaWR1RXJyb3IoZXJyb3JOYW1lLCBlcnJvck1lc3NhZ2UpKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KVxuICAgICAgICAuY2F0Y2goKGVycm9yOiBPcGVuVmlkdUVycm9yKSA9PiB7XG4gICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgfSk7XG4gICAgfSk7XG4gIH1cblxuXG4gIC8qIHRzbGludDpkaXNhYmxlOm5vLWVtcHR5ICovXG4gIC8qKlxuICAgKiBEaXNhYmxlIGFsbCBsb2dnaW5nIGV4Y2VwdCBlcnJvciBsZXZlbFxuICAgKi9cbiAgZW5hYmxlUHJvZE1vZGUoKTogdm9pZCB7XG4gICAgY29uc29sZS5sb2cgPSAoKSA9PiB7IH07XG4gICAgY29uc29sZS5kZWJ1ZyA9ICgpID0+IHsgfTtcbiAgICBjb25zb2xlLmluZm8gPSAoKSA9PiB7IH07XG4gICAgY29uc29sZS53YXJuID0gKCkgPT4geyB9O1xuICB9XG4gIC8qIHRzbGludDplbmFibGU6bm8tZW1wdHkgKi9cblxuXG4gIC8qKlxuICAgKiBTZXQgT3BlblZpZHUgYWR2YW5jZWQgY29uZmlndXJhdGlvbiBvcHRpb25zLiBDdXJyZW50bHkgYGNvbmZpZ3VyYXRpb25gIGlzIGFuIG9iamVjdCB3aXRoIHRoZSBmb2xsb3dpbmcgb3B0aW9uYWwgcHJvcGVydGllcyAoc2VlIFtbT3BlblZpZHVBZHZhbmNlZENvbmZpZ3VyYXRpb25dXSBmb3IgbW9yZSBkZXRhaWxzKTpcbiAgICogLSBgaWNlU2VydmVyc2A6IHNldCBjdXN0b20gU1RVTi9UVVJOIHNlcnZlcnMgdG8gYmUgdXNlZCBieSBPcGVuVmlkdSBCcm93c2VyXG4gICAqIC0gYHNjcmVlblNoYXJlQ2hyb21lRXh0ZW5zaW9uYDogdXJsIHRvIGEgY3VzdG9tIHNjcmVlbiBzaGFyZSBleHRlbnNpb24gZm9yIENocm9tZSB0byBiZSB1c2VkIGluc3RlYWQgb2YgdGhlIGRlZmF1bHQgb25lLCBiYXNlZCBvbiBvdXJzIFtodHRwczovL2dpdGh1Yi5jb20vT3BlblZpZHUvb3BlbnZpZHUtc2NyZWVuLXNoYXJpbmctY2hyb21lLWV4dGVuc2lvbl0oaHR0cHM6Ly9naXRodWIuY29tL09wZW5WaWR1L29wZW52aWR1LXNjcmVlbi1zaGFyaW5nLWNocm9tZS1leHRlbnNpb24pXG4gICAqIC0gYHB1Ymxpc2hlclNwZWFraW5nRXZlbnRzT3B0aW9uc2A6IGN1c3RvbSBjb25maWd1cmF0aW9uIGZvciB0aGUgW1tQdWJsaXNoZXJTcGVha2luZ0V2ZW50XV0gZmVhdHVyZVxuICAgKi9cbiAgc2V0QWR2YW5jZWRDb25maWd1cmF0aW9uKGNvbmZpZ3VyYXRpb246IE9wZW5WaWR1QWR2YW5jZWRDb25maWd1cmF0aW9uKTogdm9pZCB7XG4gICAgdGhpcy5hZHZhbmNlZENvbmZpZ3VyYXRpb24gPSBjb25maWd1cmF0aW9uO1xuICB9XG5cblxuICAvKiBIaWRkZW4gbWV0aG9kcyAqL1xuXG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICBnZW5lcmF0ZU1lZGlhQ29uc3RyYWludHMocHVibGlzaGVyUHJvcGVydGllczogUHVibGlzaGVyUHJvcGVydGllcyk6IFByb21pc2U8TWVkaWFTdHJlYW1Db25zdHJhaW50cz4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZTxNZWRpYVN0cmVhbUNvbnN0cmFpbnRzPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICBsZXQgYXVkaW8sIHZpZGVvO1xuXG4gICAgICBpZiAocHVibGlzaGVyUHJvcGVydGllcy5hdWRpb1NvdXJjZSA9PT0gbnVsbCB8fCBwdWJsaXNoZXJQcm9wZXJ0aWVzLmF1ZGlvU291cmNlID09PSBmYWxzZSkge1xuICAgICAgICBhdWRpbyA9IGZhbHNlO1xuICAgICAgfSBlbHNlIGlmIChwdWJsaXNoZXJQcm9wZXJ0aWVzLmF1ZGlvU291cmNlID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgYXVkaW8gPSB0cnVlO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgYXVkaW8gPSBwdWJsaXNoZXJQcm9wZXJ0aWVzLmF1ZGlvU291cmNlO1xuICAgICAgfVxuXG4gICAgICBpZiAocHVibGlzaGVyUHJvcGVydGllcy52aWRlb1NvdXJjZSA9PT0gbnVsbCB8fCBwdWJsaXNoZXJQcm9wZXJ0aWVzLnZpZGVvU291cmNlID09PSBmYWxzZSkge1xuICAgICAgICB2aWRlbyA9IGZhbHNlO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdmlkZW8gPSB7XG4gICAgICAgICAgaGVpZ2h0OiB7XG4gICAgICAgICAgICBpZGVhbDogNDgwXG4gICAgICAgICAgfSxcbiAgICAgICAgICB3aWR0aDoge1xuICAgICAgICAgICAgaWRlYWw6IDY0MFxuICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgbWVkaWFDb25zdHJhaW50czogTWVkaWFTdHJlYW1Db25zdHJhaW50cyA9IHtcbiAgICAgICAgYXVkaW8sXG4gICAgICAgIHZpZGVvXG4gICAgICB9O1xuXG4gICAgICBpZiAodHlwZW9mIG1lZGlhQ29uc3RyYWludHMuYXVkaW8gPT09ICdzdHJpbmcnKSB7XG4gICAgICAgIG1lZGlhQ29uc3RyYWludHMuYXVkaW8gPSB7IGRldmljZUlkOiB7IGV4YWN0OiBtZWRpYUNvbnN0cmFpbnRzLmF1ZGlvIH0gfTtcbiAgICAgIH1cblxuICAgICAgaWYgKG1lZGlhQ29uc3RyYWludHMudmlkZW8pIHtcblxuICAgICAgICBpZiAoISFwdWJsaXNoZXJQcm9wZXJ0aWVzLnJlc29sdXRpb24pIHtcbiAgICAgICAgICBjb25zdCB3aWR0aEFuZEhlaWdodCA9IHB1Ymxpc2hlclByb3BlcnRpZXMucmVzb2x1dGlvbi50b0xvd2VyQ2FzZSgpLnNwbGl0KCd4Jyk7XG4gICAgICAgICAgY29uc3Qgd2lkdGggPSBOdW1iZXIod2lkdGhBbmRIZWlnaHRbMF0pO1xuICAgICAgICAgIGNvbnN0IGhlaWdodCA9IE51bWJlcih3aWR0aEFuZEhlaWdodFsxXSk7XG4gICAgICAgICAgKG1lZGlhQ29uc3RyYWludHMudmlkZW8gYXMgYW55KS53aWR0aC5pZGVhbCA9IHdpZHRoO1xuICAgICAgICAgIChtZWRpYUNvbnN0cmFpbnRzLnZpZGVvIGFzIGFueSkuaGVpZ2h0LmlkZWFsID0gaGVpZ2h0O1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCEhcHVibGlzaGVyUHJvcGVydGllcy5mcmFtZVJhdGUpIHtcbiAgICAgICAgICAobWVkaWFDb25zdHJhaW50cy52aWRlbyBhcyBhbnkpLmZyYW1lUmF0ZSA9IHsgaWRlYWw6IHB1Ymxpc2hlclByb3BlcnRpZXMuZnJhbWVSYXRlIH07XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoISFwdWJsaXNoZXJQcm9wZXJ0aWVzLnZpZGVvU291cmNlICYmIHR5cGVvZiBwdWJsaXNoZXJQcm9wZXJ0aWVzLnZpZGVvU291cmNlID09PSAnc3RyaW5nJykge1xuXG4gICAgICAgICAgaWYgKHB1Ymxpc2hlclByb3BlcnRpZXMudmlkZW9Tb3VyY2UgPT09ICdzY3JlZW4nKSB7XG5cbiAgICAgICAgICAgIGlmIChwbGF0Zm9ybS5uYW1lICE9PSAnQ2hyb21lJyAmJiBwbGF0Zm9ybS5uYW1lIS5pbmRleE9mKCdGaXJlZm94JykgPT09IC0xKSB7XG4gICAgICAgICAgICAgIGNvbnN0IGVycm9yID0gbmV3IE9wZW5WaWR1RXJyb3IoT3BlblZpZHVFcnJvck5hbWUuU0NSRUVOX1NIQVJJTkdfTk9UX1NVUFBPUlRFRCwgJ1lvdSBjYW4gb25seSBzY3JlZW4gc2hhcmUgaW4gZGVza3RvcCBDaHJvbWUgYW5kIEZpcmVmb3guIERldGVjdGVkIGJyb3dzZXI6ICcgKyBwbGF0Zm9ybS5uYW1lKTtcbiAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihlcnJvcik7XG4gICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICB9IGVsc2Uge1xuXG4gICAgICAgICAgICAgIGlmICghIXRoaXMuYWR2YW5jZWRDb25maWd1cmF0aW9uLnNjcmVlblNoYXJlQ2hyb21lRXh0ZW5zaW9uICYmICEocGxhdGZvcm0ubmFtZSEuaW5kZXhPZignRmlyZWZveCcpICE9PSAtMSkpIHtcblxuICAgICAgICAgICAgICAgIC8vIEN1c3RvbSBzY3JlZW4gc2hhcmluZyBleHRlbnNpb24gZm9yIENocm9tZVxuXG4gICAgICAgICAgICAgICAgc2NyZWVuU2hhcmluZy5nZXRTY3JlZW5Db25zdHJhaW50cygoZXJyb3IsIHNjcmVlbkNvbnN0cmFpbnRzKSA9PiB7XG4gICAgICAgICAgICAgICAgICBpZiAoISFlcnJvciB8fCAhIXNjcmVlbkNvbnN0cmFpbnRzLm1hbmRhdG9yeSAmJiBzY3JlZW5Db25zdHJhaW50cy5tYW5kYXRvcnkuY2hyb21lTWVkaWFTb3VyY2UgPT09ICdzY3JlZW4nKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnJvciA9PT0gJ3Blcm1pc3Npb24tZGVuaWVkJyB8fCBlcnJvciA9PT0gJ1Blcm1pc3Npb25EZW5pZWRFcnJvcicpIHtcbiAgICAgICAgICAgICAgICAgICAgICBjb25zdCBlcnJvciA9IG5ldyBPcGVuVmlkdUVycm9yKE9wZW5WaWR1RXJyb3JOYW1lLlNDUkVFTl9DQVBUVVJFX0RFTklFRCwgJ1lvdSBtdXN0IGFsbG93IGFjY2VzcyB0byBvbmUgd2luZG93IG9mIHlvdXIgZGVza3RvcCcpO1xuICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgY29uc3QgZXh0ZW5zaW9uSWQgPSB0aGlzLmFkdmFuY2VkQ29uZmlndXJhdGlvbi5zY3JlZW5TaGFyZUNocm9tZUV4dGVuc2lvbiEuc3BsaXQoJy8nKS5wb3AoKSEhLnRyaW0oKTtcbiAgICAgICAgICAgICAgICAgICAgICBzY3JlZW5TaGFyaW5nLmdldENocm9tZUV4dGVuc2lvblN0YXR1cyhleHRlbnNpb25JZCwgKHN0YXR1cykgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHN0YXR1cyA9PT0gJ2luc3RhbGxlZC1kaXNhYmxlZCcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZXJyb3IgPSBuZXcgT3BlblZpZHVFcnJvcihPcGVuVmlkdUVycm9yTmFtZS5TQ1JFRU5fRVhURU5TSU9OX0RJU0FCTEVELCAnWW91IG11c3QgZW5hYmxlIHRoZSBzY3JlZW4gZXh0ZW5zaW9uJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHN0YXR1cyA9PT0gJ25vdC1pbnN0YWxsZWQnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGVycm9yID0gbmV3IE9wZW5WaWR1RXJyb3IoT3BlblZpZHVFcnJvck5hbWUuU0NSRUVOX0VYVEVOU0lPTl9OT1RfSU5TVEFMTEVELCAoPHN0cmluZz50aGlzLmFkdmFuY2VkQ29uZmlndXJhdGlvbi5zY3JlZW5TaGFyZUNocm9tZUV4dGVuc2lvbikpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgbWVkaWFDb25zdHJhaW50cy52aWRlbyA9IHNjcmVlbkNvbnN0cmFpbnRzO1xuICAgICAgICAgICAgICAgICAgICByZXNvbHZlKG1lZGlhQ29uc3RyYWludHMpO1xuICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICB9IGVsc2Uge1xuXG4gICAgICAgICAgICAgICAgLy8gRGVmYXVsdCBzY3JlZW4gc2hhcmluZyBleHRlbnNpb24gZm9yIENocm9tZVxuXG4gICAgICAgICAgICAgICAgc2NyZWVuU2hhcmluZ0F1dG8uZ2V0U2NyZWVuSWQoKGVycm9yLCBzb3VyY2VJZCwgc2NyZWVuQ29uc3RyYWludHMpID0+IHtcbiAgICAgICAgICAgICAgICAgIGlmICghIWVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnJvciA9PT0gJ25vdC1pbnN0YWxsZWQnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgY29uc3QgZXh0ZW5zaW9uVXJsID0gISF0aGlzLmFkdmFuY2VkQ29uZmlndXJhdGlvbi5zY3JlZW5TaGFyZUNocm9tZUV4dGVuc2lvbiA/IHRoaXMuYWR2YW5jZWRDb25maWd1cmF0aW9uLnNjcmVlblNoYXJlQ2hyb21lRXh0ZW5zaW9uIDpcbiAgICAgICAgICAgICAgICAgICAgICAgICdodHRwczovL2Nocm9tZS5nb29nbGUuY29tL3dlYnN0b3JlL2RldGFpbC9vcGVudmlkdS1zY3JlZW5zaGFyaW5nL2xmY2dmZXBhZm5vYmRsb2VjY2huZmFjbGliZW5qb2xkJztcbiAgICAgICAgICAgICAgICAgICAgICBjb25zdCBlcnJvciA9IG5ldyBPcGVuVmlkdUVycm9yKE9wZW5WaWR1RXJyb3JOYW1lLlNDUkVFTl9FWFRFTlNJT05fTk9UX0lOU1RBTExFRCwgZXh0ZW5zaW9uVXJsKTtcbiAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGVycm9yID09PSAnaW5zdGFsbGVkLWRpc2FibGVkJykge1xuICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGVycm9yID0gbmV3IE9wZW5WaWR1RXJyb3IoT3BlblZpZHVFcnJvck5hbWUuU0NSRUVOX0VYVEVOU0lPTl9ESVNBQkxFRCwgJ1lvdSBtdXN0IGVuYWJsZSB0aGUgc2NyZWVuIGV4dGVuc2lvbicpO1xuICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoZXJyb3IgPT09ICdwZXJtaXNzaW9uLWRlbmllZCcpIHtcbiAgICAgICAgICAgICAgICAgICAgICBjb25zdCBlcnJvciA9IG5ldyBPcGVuVmlkdUVycm9yKE9wZW5WaWR1RXJyb3JOYW1lLlNDUkVFTl9DQVBUVVJFX0RFTklFRCwgJ1lvdSBtdXN0IGFsbG93IGFjY2VzcyB0byBvbmUgd2luZG93IG9mIHlvdXIgZGVza3RvcCcpO1xuICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIG1lZGlhQ29uc3RyYWludHMudmlkZW8gPSBzY3JlZW5Db25zdHJhaW50cy52aWRlbztcbiAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZShtZWRpYUNvbnN0cmFpbnRzKTtcbiAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgIHB1Ymxpc2hlclByb3BlcnRpZXMudmlkZW9Tb3VyY2UgPSAnc2NyZWVuJztcblxuICAgICAgICAgICAgfVxuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6bm8tc3RyaW5nLWxpdGVyYWxcbiAgICAgICAgICAgIG1lZGlhQ29uc3RyYWludHMudmlkZW9bJ2RldmljZUlkJ10gPSB7IGV4YWN0OiBwdWJsaXNoZXJQcm9wZXJ0aWVzLnZpZGVvU291cmNlIH07XG4gICAgICAgICAgICByZXNvbHZlKG1lZGlhQ29uc3RyYWludHMpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICByZXNvbHZlKG1lZGlhQ29uc3RyYWludHMpO1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXNvbHZlKG1lZGlhQ29uc3RyYWludHMpO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIEBoaWRkZW5cbiAgICovXG4gIHN0YXJ0V3Mob25Db25uZWN0U3VjY2VzOiAoZXJyb3I6IEVycm9yKSA9PiB2b2lkKTogdm9pZCB7XG4gICAgY29uc3QgY29uZmlnID0ge1xuICAgICAgaGVhcnRiZWF0OiA1MDAwLFxuICAgICAgc2VuZENsb3NlTWVzc2FnZTogZmFsc2UsXG4gICAgICB3czoge1xuICAgICAgICB1cmk6IHRoaXMud3NVcmksXG4gICAgICAgIHVzZVNvY2tKUzogZmFsc2UsXG4gICAgICAgIG9uY29ubmVjdGVkOiBvbkNvbm5lY3RTdWNjZXMsXG4gICAgICAgIG9uZGlzY29ubmVjdDogdGhpcy5kaXNjb25uZWN0Q2FsbGJhY2suYmluZCh0aGlzKSxcbiAgICAgICAgb25yZWNvbm5lY3Rpbmc6IHRoaXMucmVjb25uZWN0aW5nQ2FsbGJhY2suYmluZCh0aGlzKSxcbiAgICAgICAgb25yZWNvbm5lY3RlZDogdGhpcy5yZWNvbm5lY3RlZENhbGxiYWNrLmJpbmQodGhpcylcbiAgICAgIH0sXG4gICAgICBycGM6IHtcbiAgICAgICAgcmVxdWVzdFRpbWVvdXQ6IDEwMDAwLFxuICAgICAgICBwYXJ0aWNpcGFudEpvaW5lZDogdGhpcy5zZXNzaW9uLm9uUGFydGljaXBhbnRKb2luZWQuYmluZCh0aGlzLnNlc3Npb24pLFxuICAgICAgICBwYXJ0aWNpcGFudFB1Ymxpc2hlZDogdGhpcy5zZXNzaW9uLm9uUGFydGljaXBhbnRQdWJsaXNoZWQuYmluZCh0aGlzLnNlc3Npb24pLFxuICAgICAgICBwYXJ0aWNpcGFudFVucHVibGlzaGVkOiB0aGlzLnNlc3Npb24ub25QYXJ0aWNpcGFudFVucHVibGlzaGVkLmJpbmQodGhpcy5zZXNzaW9uKSxcbiAgICAgICAgcGFydGljaXBhbnRMZWZ0OiB0aGlzLnNlc3Npb24ub25QYXJ0aWNpcGFudExlZnQuYmluZCh0aGlzLnNlc3Npb24pLFxuICAgICAgICBwYXJ0aWNpcGFudEV2aWN0ZWQ6IHRoaXMuc2Vzc2lvbi5vblBhcnRpY2lwYW50RXZpY3RlZC5iaW5kKHRoaXMuc2Vzc2lvbiksXG4gICAgICAgIHJlY29yZGluZ1N0YXJ0ZWQ6IHRoaXMuc2Vzc2lvbi5vblJlY29yZGluZ1N0YXJ0ZWQuYmluZCh0aGlzLnNlc3Npb24pLFxuICAgICAgICByZWNvcmRpbmdTdG9wcGVkOiB0aGlzLnNlc3Npb24ub25SZWNvcmRpbmdTdG9wcGVkLmJpbmQodGhpcy5zZXNzaW9uKSxcbiAgICAgICAgc2VuZE1lc3NhZ2U6IHRoaXMuc2Vzc2lvbi5vbk5ld01lc3NhZ2UuYmluZCh0aGlzLnNlc3Npb24pLFxuICAgICAgICBzdHJlYW1Qcm9wZXJ0eUNoYW5nZWQ6IHRoaXMuc2Vzc2lvbi5vblN0cmVhbVByb3BlcnR5Q2hhbmdlZC5iaW5kKHRoaXMuc2Vzc2lvbiksXG4gICAgICAgIGljZUNhbmRpZGF0ZTogdGhpcy5zZXNzaW9uLnJlY3ZJY2VDYW5kaWRhdGUuYmluZCh0aGlzLnNlc3Npb24pLFxuICAgICAgICBtZWRpYUVycm9yOiB0aGlzLnNlc3Npb24ub25NZWRpYUVycm9yLmJpbmQodGhpcy5zZXNzaW9uKVxuICAgICAgfVxuICAgIH07XG4gICAgdGhpcy5qc29uUnBjQ2xpZW50ID0gbmV3IFJwY0J1aWxkZXIuY2xpZW50cy5Kc29uUnBjQ2xpZW50KGNvbmZpZyk7XG4gIH1cblxuICAvKipcbiAgICogQGhpZGRlblxuICAgKi9cbiAgY2xvc2VXcygpOiB2b2lkIHtcbiAgICB0aGlzLmpzb25ScGNDbGllbnQuY2xvc2UoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICBzZW5kUmVxdWVzdChtZXRob2Q6IHN0cmluZywgcGFyYW1zOiBhbnksIGNhbGxiYWNrPyk6IHZvaWQge1xuICAgIGlmIChwYXJhbXMgJiYgcGFyYW1zIGluc3RhbmNlb2YgRnVuY3Rpb24pIHtcbiAgICAgIGNhbGxiYWNrID0gcGFyYW1zO1xuICAgICAgcGFyYW1zID0ge307XG4gICAgfVxuICAgIGNvbnNvbGUuZGVidWcoJ1NlbmRpbmcgcmVxdWVzdDoge21ldGhvZDpcIicgKyBtZXRob2QgKyAnXCIsIHBhcmFtczogJyArIEpTT04uc3RyaW5naWZ5KHBhcmFtcykgKyAnfScpO1xuICAgIHRoaXMuanNvblJwY0NsaWVudC5zZW5kKG1ldGhvZCwgcGFyYW1zLCBjYWxsYmFjayk7XG4gIH1cblxuICAvKipcbiAgICogQGhpZGRlblxuICAgKi9cbiAgaXNNZWRpYVN0cmVhbVRyYWNrKG1lZGlhU291cmNlOiBhbnkpOiBib29sZWFuIHtcbiAgICBjb25zdCBpcyA9ICghIW1lZGlhU291cmNlICYmXG4gICAgICBtZWRpYVNvdXJjZS5lbmFibGVkICE9PSB1bmRlZmluZWQgJiYgdHlwZW9mIG1lZGlhU291cmNlLmVuYWJsZWQgPT09ICdib29sZWFuJyAmJlxuICAgICAgbWVkaWFTb3VyY2UuaWQgIT09IHVuZGVmaW5lZCAmJiB0eXBlb2YgbWVkaWFTb3VyY2UuaWQgPT09ICdzdHJpbmcnICYmXG4gICAgICBtZWRpYVNvdXJjZS5raW5kICE9PSB1bmRlZmluZWQgJiYgdHlwZW9mIG1lZGlhU291cmNlLmtpbmQgPT09ICdzdHJpbmcnICYmXG4gICAgICBtZWRpYVNvdXJjZS5sYWJlbCAhPT0gdW5kZWZpbmVkICYmIHR5cGVvZiBtZWRpYVNvdXJjZS5sYWJlbCA9PT0gJ3N0cmluZycgJiZcbiAgICAgIG1lZGlhU291cmNlLm11dGVkICE9PSB1bmRlZmluZWQgJiYgdHlwZW9mIG1lZGlhU291cmNlLm11dGVkID09PSAnYm9vbGVhbicgJiZcbiAgICAgIG1lZGlhU291cmNlLnJlYWR5U3RhdGUgIT09IHVuZGVmaW5lZCAmJiB0eXBlb2YgbWVkaWFTb3VyY2UucmVhZHlTdGF0ZSA9PT0gJ3N0cmluZycpO1xuICAgIHJldHVybiBpcztcbiAgfVxuXG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICBnZXRXc1VyaSgpOiBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLndzVXJpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBoaWRkZW5cbiAgICovXG4gIGdldFNlY3JldCgpOiBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLnNlY3JldDtcbiAgfVxuXG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICBnZXRSZWNvcmRlcigpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5yZWNvcmRlcjtcbiAgfVxuXG5cbiAgLyogUHJpdmF0ZSBtZXRob2RzICovXG5cbiAgcHJpdmF0ZSBkaXNjb25uZWN0Q2FsbGJhY2soKTogdm9pZCB7XG4gICAgY29uc29sZS53YXJuKCdXZWJzb2NrZXQgY29ubmVjdGlvbiBsb3N0Jyk7XG4gICAgaWYgKHRoaXMuaXNSb29tQXZhaWxhYmxlKCkpIHtcbiAgICAgIHRoaXMuc2Vzc2lvbi5vbkxvc3RDb25uZWN0aW9uKCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGFsZXJ0KCdDb25uZWN0aW9uIGVycm9yLiBQbGVhc2UgcmVsb2FkIHBhZ2UuJyk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSByZWNvbm5lY3RpbmdDYWxsYmFjaygpOiB2b2lkIHtcbiAgICBjb25zb2xlLndhcm4oJ1dlYnNvY2tldCBjb25uZWN0aW9uIGxvc3QgKHJlY29ubmVjdGluZyknKTtcbiAgICBpZiAodGhpcy5pc1Jvb21BdmFpbGFibGUoKSkge1xuICAgICAgdGhpcy5zZXNzaW9uLm9uTG9zdENvbm5lY3Rpb24oKTtcbiAgICB9IGVsc2Uge1xuICAgICAgYWxlcnQoJ0Nvbm5lY3Rpb24gZXJyb3IuIFBsZWFzZSByZWxvYWQgcGFnZS4nKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIHJlY29ubmVjdGVkQ2FsbGJhY2soKTogdm9pZCB7XG4gICAgY29uc29sZS53YXJuKCdXZWJzb2NrZXQgcmVjb25uZWN0ZWQnKTtcbiAgICBpZiAodGhpcy5pc1Jvb21BdmFpbGFibGUoKSkge1xuICAgICAgdGhpcy5zZXNzaW9uLm9uUmVjb3ZlcmVkQ29ubmVjdGlvbigpO1xuICAgIH0gZWxzZSB7XG4gICAgICBhbGVydCgnQ29ubmVjdGlvbiBlcnJvci4gUGxlYXNlIHJlbG9hZCBwYWdlLicpO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgaXNSb29tQXZhaWxhYmxlKCk6IGJvb2xlYW4ge1xuICAgIGlmICh0aGlzLnNlc3Npb24gIT09IHVuZGVmaW5lZCAmJiB0aGlzLnNlc3Npb24gaW5zdGFuY2VvZiBTZXNzaW9uKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9IGVsc2Uge1xuICAgICAgY29uc29sZS53YXJuKCdTZXNzaW9uIGluc3RhbmNlIG5vdCBmb3VuZCcpO1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfVxuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBPcGVuVmlkdSB9IGZyb20gJy4vT3BlblZpZHUnO1xuaW1wb3J0IHsgU2Vzc2lvbiB9IGZyb20gJy4vU2Vzc2lvbic7XG5pbXBvcnQgeyBTdHJlYW0gfSBmcm9tICcuL1N0cmVhbSc7XG5pbXBvcnQgeyBTdHJlYW1NYW5hZ2VyIH0gZnJvbSAnLi9TdHJlYW1NYW5hZ2VyJztcbmltcG9ydCB7IEV2ZW50RGlzcGF0Y2hlciB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvSW50ZXJmYWNlcy9QdWJsaWMvRXZlbnREaXNwYXRjaGVyJztcbmltcG9ydCB7IFB1Ymxpc2hlclByb3BlcnRpZXMgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHVibGljL1B1Ymxpc2hlclByb3BlcnRpZXMnO1xuaW1wb3J0IHsgRXZlbnQgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0V2ZW50cy9FdmVudCc7XG5pbXBvcnQgeyBTdHJlYW1FdmVudCB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1N0cmVhbUV2ZW50JztcbmltcG9ydCB7IFN0cmVhbVByb3BlcnR5Q2hhbmdlZEV2ZW50IH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvU3RyZWFtUHJvcGVydHlDaGFuZ2VkRXZlbnQnO1xuaW1wb3J0IHsgVmlkZW9FbGVtZW50RXZlbnQgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0V2ZW50cy9WaWRlb0VsZW1lbnRFdmVudCc7XG5pbXBvcnQgeyBPcGVuVmlkdUVycm9yLCBPcGVuVmlkdUVycm9yTmFtZSB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRW51bXMvT3BlblZpZHVFcnJvcic7XG5pbXBvcnQgeyBWaWRlb0luc2VydE1vZGUgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0VudW1zL1ZpZGVvSW5zZXJ0TW9kZSc7XG5cbmltcG9ydCBwbGF0Zm9ybSA9IHJlcXVpcmUoJ3BsYXRmb3JtJyk7XG5cblxuLyoqXG4gKiBQYWNrcyBsb2NhbCBtZWRpYSBzdHJlYW1zLiBQYXJ0aWNpcGFudHMgY2FuIHB1Ymxpc2ggaXQgdG8gYSBzZXNzaW9uLiBJbml0aWFsaXplZCB3aXRoIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dIG1ldGhvZFxuICovXG5leHBvcnQgY2xhc3MgUHVibGlzaGVyIGV4dGVuZHMgU3RyZWFtTWFuYWdlciB7XG5cbiAgICAvKipcbiAgICAgKiBXaGV0aGVyIHRoZSBQdWJsaXNoZXIgaGFzIGJlZW4gZ3JhbnRlZCBhY2Nlc3MgdG8gdGhlIHJlcXVlc3RlZCBpbnB1dCBkZXZpY2VzIG9yIG5vdFxuICAgICAqL1xuICAgIGFjY2Vzc0FsbG93ZWQgPSBmYWxzZTtcblxuICAgIC8qKlxuICAgICAqIFdoZXRoZXIgeW91IGhhdmUgY2FsbGVkIFtbUHVibGlzaGVyLnN1YnNjcmliZVRvUmVtb3RlXV0gd2l0aCB2YWx1ZSBgdHJ1ZWAgb3IgYGZhbHNlYCAoKmZhbHNlKiBieSBkZWZhdWx0KVxuICAgICAqL1xuICAgIGlzU3Vic2NyaWJlZFRvUmVtb3RlID0gZmFsc2U7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgW1tTZXNzaW9uXV0gdG8gd2hpY2ggdGhlIFB1Ymxpc2hlciBiZWxvbmdzXG4gICAgICovXG4gICAgc2Vzc2lvbjogU2Vzc2lvbjsgLy8gSW5pdGlhbGl6ZWQgYnkgU2Vzc2lvbi5wdWJsaXNoKFB1Ymxpc2hlcilcblxuICAgIHByaXZhdGUgYWNjZXNzRGVuaWVkID0gZmFsc2U7XG4gICAgcHJpdmF0ZSBwcm9wZXJ0aWVzOiBQdWJsaXNoZXJQcm9wZXJ0aWVzO1xuICAgIHByaXZhdGUgcGVybWlzc2lvbkRpYWxvZ1RpbWVvdXQ6IE5vZGVKUy5UaW1lcjtcblxuICAgIC8qKlxuICAgICAqIGhpZGRlblxuICAgICAqL1xuICAgIG9wZW52aWR1OiBPcGVuVmlkdTtcbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgdmlkZW9SZWZlcmVuY2U6IEhUTUxWaWRlb0VsZW1lbnQ7XG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHNjcmVlblNoYXJlUmVzaXplSW50ZXJ2YWw6IE5vZGVKUy5UaW1lcjtcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3Rvcih0YXJnRWw6IHN0cmluZyB8IEhUTUxFbGVtZW50LCBwcm9wZXJ0aWVzOiBQdWJsaXNoZXJQcm9wZXJ0aWVzLCBvcGVudmlkdTogT3BlblZpZHUpIHtcbiAgICAgICAgc3VwZXIobmV3IFN0cmVhbSgoISFvcGVudmlkdS5zZXNzaW9uKSA/IG9wZW52aWR1LnNlc3Npb24gOiBuZXcgU2Vzc2lvbihvcGVudmlkdSksIHsgcHVibGlzaGVyUHJvcGVydGllczogcHJvcGVydGllcywgbWVkaWFDb25zdHJhaW50czoge30gfSksIHRhcmdFbCk7XG4gICAgICAgIHRoaXMucHJvcGVydGllcyA9IHByb3BlcnRpZXM7XG4gICAgICAgIHRoaXMub3BlbnZpZHUgPSBvcGVudmlkdTtcblxuICAgICAgICB0aGlzLnN0cmVhbS5lZS5vbignbG9jYWwtc3RyZWFtLWRlc3Ryb3llZCcsIChyZWFzb246IHN0cmluZykgPT4ge1xuICAgICAgICAgICAgdGhpcy5zdHJlYW0uaXNMb2NhbFN0cmVhbVB1Ymxpc2hlZCA9IGZhbHNlO1xuICAgICAgICAgICAgY29uc3Qgc3RyZWFtRXZlbnQgPSBuZXcgU3RyZWFtRXZlbnQodHJ1ZSwgdGhpcywgJ3N0cmVhbURlc3Ryb3llZCcsIHRoaXMuc3RyZWFtLCByZWFzb24pO1xuICAgICAgICAgICAgdGhpcy5lbWl0RXZlbnQoJ3N0cmVhbURlc3Ryb3llZCcsIFtzdHJlYW1FdmVudF0pO1xuICAgICAgICAgICAgc3RyZWFtRXZlbnQuY2FsbERlZmF1bHRCZWhhdmlvcigpO1xuICAgICAgICB9KTtcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFB1Ymxpc2ggb3IgdW5wdWJsaXNoIHRoZSBhdWRpbyBzdHJlYW0gKGlmIGF2YWlsYWJsZSkuIENhbGxpbmcgdGhpcyBtZXRob2QgdHdpY2UgaW4gYSByb3cgcGFzc2luZyBzYW1lIHZhbHVlIHdpbGwgaGF2ZSBubyBlZmZlY3RcbiAgICAgKlxuICAgICAqICMjIyMgRXZlbnRzIGRpc3BhdGNoZWRcbiAgICAgKlxuICAgICAqIFRoZSBbW1Nlc3Npb25dXSBvYmplY3Qgb2YgdGhlIGxvY2FsIHBhcnRpY2lwYW50IHdpbGwgZGlzcGF0Y2ggYSBgc3RyZWFtUHJvcGVydHlDaGFuZ2VkYCBldmVudCB3aXRoIGBjaGFuZ2VkUHJvcGVydHlgIHNldCB0byBgXCJhdWRpb0FjdGl2ZVwiYCBhbmQgYHJlYXNvbmAgc2V0IHRvIGBcInB1Ymxpc2hBdWRpb1wiYFxuICAgICAqIFRoZSBbW1B1Ymxpc2hlcl1dIG9iamVjdCBvZiB0aGUgbG9jYWwgcGFydGljaXBhbnQgd2lsbCBhbHNvIGRpc3BhdGNoIHRoZSBleGFjdCBzYW1lIGV2ZW50XG4gICAgICpcbiAgICAgKiBUaGUgW1tTZXNzaW9uXV0gb2JqZWN0IG9mIGV2ZXJ5IG90aGVyIHBhcnRpY2lwYW50IGNvbm5lY3RlZCB0byB0aGUgc2Vzc2lvbiB3aWxsIGRpc3BhdGNoIGEgYHN0cmVhbVByb3BlcnR5Q2hhbmdlZGAgZXZlbnQgd2l0aCBgY2hhbmdlZFByb3BlcnR5YCBzZXQgdG8gYFwiYXVkaW9BY3RpdmVcImAgYW5kIGByZWFzb25gIHNldCB0byBgXCJwdWJsaXNoQXVkaW9cImBcbiAgICAgKiBUaGUgcmVzcGVjdGl2ZSBbW1N1YnNjcmliZXJdXSBvYmplY3Qgb2YgZXZlcnkgb3RoZXIgcGFydGljaXBhbnQgcmVjZWl2aW5nIHRoaXMgUHVibGlzaGVyJ3Mgc3RyZWFtIHdpbGwgYWxzbyBkaXNwYXRjaCB0aGUgZXhhY3Qgc2FtZSBldmVudFxuICAgICAqXG4gICAgICogU2VlIFtbU3RyZWFtUHJvcGVydHlDaGFuZ2VkRXZlbnRdXSB0byBsZWFybiBtb3JlLlxuICAgICAqXG4gICAgICogQHBhcmFtIHZhbHVlIGB0cnVlYCB0byBwdWJsaXNoIHRoZSBhdWRpbyBzdHJlYW0sIGBmYWxzZWAgdG8gdW5wdWJsaXNoIGl0XG4gICAgICovXG4gICAgcHVibGlzaEF1ZGlvKHZhbHVlOiBib29sZWFuKTogdm9pZCB7XG4gICAgICAgIGlmICh0aGlzLnN0cmVhbS5hdWRpb0FjdGl2ZSAhPT0gdmFsdWUpIHtcbiAgICAgICAgICAgIHRoaXMuc3RyZWFtLmdldE1lZGlhU3RyZWFtKCkuZ2V0QXVkaW9UcmFja3MoKS5mb3JFYWNoKCh0cmFjaykgPT4ge1xuICAgICAgICAgICAgICAgIHRyYWNrLmVuYWJsZWQgPSB2YWx1ZTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgdGhpcy5zZXNzaW9uLm9wZW52aWR1LnNlbmRSZXF1ZXN0KFxuICAgICAgICAgICAgICAgICdzdHJlYW1Qcm9wZXJ0eUNoYW5nZWQnLFxuICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgc3RyZWFtSWQ6IHRoaXMuc3RyZWFtLnN0cmVhbUlkLFxuICAgICAgICAgICAgICAgICAgICBwcm9wZXJ0eTogJ2F1ZGlvQWN0aXZlJyxcbiAgICAgICAgICAgICAgICAgICAgbmV3VmFsdWU6IHZhbHVlLFxuICAgICAgICAgICAgICAgICAgICByZWFzb246ICdwdWJsaXNoQXVkaW8nXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAoZXJyb3IsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihcIkVycm9yIHNlbmRpbmcgJ3N0cmVhbVByb3BlcnR5Q2hhbmdlZCcgZXZlbnRcIiwgZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXNzaW9uLmVtaXRFdmVudCgnc3RyZWFtUHJvcGVydHlDaGFuZ2VkJywgW25ldyBTdHJlYW1Qcm9wZXJ0eUNoYW5nZWRFdmVudCh0aGlzLnNlc3Npb24sIHRoaXMuc3RyZWFtLCAnYXVkaW9BY3RpdmUnLCB2YWx1ZSwgIXZhbHVlLCAncHVibGlzaEF1ZGlvJyldKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZW1pdEV2ZW50KCdzdHJlYW1Qcm9wZXJ0eUNoYW5nZWQnLCBbbmV3IFN0cmVhbVByb3BlcnR5Q2hhbmdlZEV2ZW50KHRoaXMsIHRoaXMuc3RyZWFtLCAnYXVkaW9BY3RpdmUnLCB2YWx1ZSwgIXZhbHVlLCAncHVibGlzaEF1ZGlvJyldKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgdGhpcy5zdHJlYW0uYXVkaW9BY3RpdmUgPSB2YWx1ZTtcbiAgICAgICAgICAgIGNvbnNvbGUuaW5mbyhcIidQdWJsaXNoZXInIGhhcyBcIiArICh2YWx1ZSA/ICdwdWJsaXNoZWQnIDogJ3VucHVibGlzaGVkJykgKyAnIGl0cyBhdWRpbyBzdHJlYW0nKTtcbiAgICAgICAgfVxuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogUHVibGlzaCBvciB1bnB1Ymxpc2ggdGhlIHZpZGVvIHN0cmVhbSAoaWYgYXZhaWxhYmxlKS4gQ2FsbGluZyB0aGlzIG1ldGhvZCB0d2ljZSBpbiBhIHJvdyBwYXNzaW5nIHNhbWUgdmFsdWUgd2lsbCBoYXZlIG5vIGVmZmVjdFxuICAgICAqXG4gICAgICogIyMjIyBFdmVudHMgZGlzcGF0Y2hlZFxuICAgICAqXG4gICAgICogVGhlIFtbU2Vzc2lvbl1dIG9iamVjdCBvZiB0aGUgbG9jYWwgcGFydGljaXBhbnQgd2lsbCBkaXNwYXRjaCBhIGBzdHJlYW1Qcm9wZXJ0eUNoYW5nZWRgIGV2ZW50IHdpdGggYGNoYW5nZWRQcm9wZXJ0eWAgc2V0IHRvIGBcInZpZGVvQWN0aXZlXCJgIGFuZCBgcmVhc29uYCBzZXQgdG8gYFwicHVibGlzaFZpZGVvXCJgXG4gICAgICogVGhlIFtbUHVibGlzaGVyXV0gb2JqZWN0IG9mIHRoZSBsb2NhbCBwYXJ0aWNpcGFudCB3aWxsIGFsc28gZGlzcGF0Y2ggdGhlIGV4YWN0IHNhbWUgZXZlbnRcbiAgICAgKlxuICAgICAqIFRoZSBbW1Nlc3Npb25dXSBvYmplY3Qgb2YgZXZlcnkgb3RoZXIgcGFydGljaXBhbnQgY29ubmVjdGVkIHRvIHRoZSBzZXNzaW9uIHdpbGwgZGlzcGF0Y2ggYSBgc3RyZWFtUHJvcGVydHlDaGFuZ2VkYCBldmVudCB3aXRoIGBjaGFuZ2VkUHJvcGVydHlgIHNldCB0byBgXCJ2aWRlb0FjdGl2ZVwiYCBhbmQgYHJlYXNvbmAgc2V0IHRvIGBcInB1Ymxpc2hWaWRlb1wiYFxuICAgICAqIFRoZSByZXNwZWN0aXZlIFtbU3Vic2NyaWJlcl1dIG9iamVjdCBvZiBldmVyeSBvdGhlciBwYXJ0aWNpcGFudCByZWNlaXZpbmcgdGhpcyBQdWJsaXNoZXIncyBzdHJlYW0gd2lsbCBhbHNvIGRpc3BhdGNoIHRoZSBleGFjdCBzYW1lIGV2ZW50XG4gICAgICpcbiAgICAgKiBTZWUgW1tTdHJlYW1Qcm9wZXJ0eUNoYW5nZWRFdmVudF1dIHRvIGxlYXJuIG1vcmUuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gdmFsdWUgYHRydWVgIHRvIHB1Ymxpc2ggdGhlIHZpZGVvIHN0cmVhbSwgYGZhbHNlYCB0byB1bnB1Ymxpc2ggaXRcbiAgICAgKi9cbiAgICBwdWJsaXNoVmlkZW8odmFsdWU6IGJvb2xlYW4pOiB2b2lkIHtcbiAgICAgICAgaWYgKHRoaXMuc3RyZWFtLnZpZGVvQWN0aXZlICE9PSB2YWx1ZSkge1xuICAgICAgICAgICAgdGhpcy5zdHJlYW0uZ2V0TWVkaWFTdHJlYW0oKS5nZXRWaWRlb1RyYWNrcygpLmZvckVhY2goKHRyYWNrKSA9PiB7XG4gICAgICAgICAgICAgICAgdHJhY2suZW5hYmxlZCA9IHZhbHVlO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB0aGlzLnNlc3Npb24ub3BlbnZpZHUuc2VuZFJlcXVlc3QoXG4gICAgICAgICAgICAgICAgJ3N0cmVhbVByb3BlcnR5Q2hhbmdlZCcsXG4gICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICBzdHJlYW1JZDogdGhpcy5zdHJlYW0uc3RyZWFtSWQsXG4gICAgICAgICAgICAgICAgICAgIHByb3BlcnR5OiAndmlkZW9BY3RpdmUnLFxuICAgICAgICAgICAgICAgICAgICBuZXdWYWx1ZTogdmFsdWUsXG4gICAgICAgICAgICAgICAgICAgIHJlYXNvbjogJ3B1Ymxpc2hWaWRlbydcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIChlcnJvciwgcmVzcG9uc2UpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKFwiRXJyb3Igc2VuZGluZyAnc3RyZWFtUHJvcGVydHlDaGFuZ2VkJyBldmVudFwiLCBlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnNlc3Npb24uZW1pdEV2ZW50KCdzdHJlYW1Qcm9wZXJ0eUNoYW5nZWQnLCBbbmV3IFN0cmVhbVByb3BlcnR5Q2hhbmdlZEV2ZW50KHRoaXMuc2Vzc2lvbiwgdGhpcy5zdHJlYW0sICd2aWRlb0FjdGl2ZScsIHZhbHVlLCAhdmFsdWUsICdwdWJsaXNoVmlkZW8nKV0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5lbWl0RXZlbnQoJ3N0cmVhbVByb3BlcnR5Q2hhbmdlZCcsIFtuZXcgU3RyZWFtUHJvcGVydHlDaGFuZ2VkRXZlbnQodGhpcywgdGhpcy5zdHJlYW0sICd2aWRlb0FjdGl2ZScsIHZhbHVlLCAhdmFsdWUsICdwdWJsaXNoVmlkZW8nKV0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB0aGlzLnN0cmVhbS52aWRlb0FjdGl2ZSA9IHZhbHVlO1xuICAgICAgICAgICAgY29uc29sZS5pbmZvKFwiJ1B1Ymxpc2hlcicgaGFzIFwiICsgKHZhbHVlID8gJ3B1Ymxpc2hlZCcgOiAndW5wdWJsaXNoZWQnKSArICcgaXRzIHZpZGVvIHN0cmVhbScpO1xuICAgICAgICB9XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBDYWxsIHRoaXMgbWV0aG9kIGJlZm9yZSBbW1Nlc3Npb24ucHVibGlzaF1dIGlmIHlvdSBwcmVmZXIgdG8gc3Vic2NyaWJlIHRvIHlvdXIgUHVibGlzaGVyJ3MgcmVtb3RlIHN0cmVhbSBpbnN0ZWFkIG9mIHVzaW5nIHRoZSBsb2NhbCBzdHJlYW0sIGFzIGFueSBvdGhlciB1c2VyIHdvdWxkIGRvLlxuICAgICAqL1xuICAgIHN1YnNjcmliZVRvUmVtb3RlKHZhbHVlPzogYm9vbGVhbik6IHZvaWQge1xuICAgICAgICB2YWx1ZSA9ICh2YWx1ZSAhPT0gdW5kZWZpbmVkKSA/IHZhbHVlIDogdHJ1ZTtcbiAgICAgICAgdGhpcy5pc1N1YnNjcmliZWRUb1JlbW90ZSA9IHZhbHVlO1xuICAgICAgICB0aGlzLnN0cmVhbS5zdWJzY3JpYmVUb015UmVtb3RlKHZhbHVlKTtcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFNlZSBbW0V2ZW50RGlzcGF0Y2hlci5vbl1dXG4gICAgICovXG4gICAgb24odHlwZTogc3RyaW5nLCBoYW5kbGVyOiAoZXZlbnQ6IEV2ZW50KSA9PiB2b2lkKTogRXZlbnREaXNwYXRjaGVyIHtcbiAgICAgICAgc3VwZXIub24odHlwZSwgaGFuZGxlcik7XG4gICAgICAgIGlmICh0eXBlID09PSAnc3RyZWFtQ3JlYXRlZCcpIHtcbiAgICAgICAgICAgIGlmICghIXRoaXMuc3RyZWFtICYmIHRoaXMuc3RyZWFtLmlzTG9jYWxTdHJlYW1QdWJsaXNoZWQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVtaXRFdmVudCgnc3RyZWFtQ3JlYXRlZCcsIFtuZXcgU3RyZWFtRXZlbnQoZmFsc2UsIHRoaXMsICdzdHJlYW1DcmVhdGVkJywgdGhpcy5zdHJlYW0sICcnKV0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbS5lZS5vbignc3RyZWFtLWNyZWF0ZWQtYnktcHVibGlzaGVyJywgKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmVtaXRFdmVudCgnc3RyZWFtQ3JlYXRlZCcsIFtuZXcgU3RyZWFtRXZlbnQoZmFsc2UsIHRoaXMsICdzdHJlYW1DcmVhdGVkJywgdGhpcy5zdHJlYW0sICcnKV0pO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmICh0eXBlID09PSAncmVtb3RlVmlkZW9QbGF5aW5nJykge1xuICAgICAgICAgICAgaWYgKHRoaXMuc3RyZWFtLmRpc3BsYXlNeVJlbW90ZSgpICYmIHRoaXMudmlkZW9zWzBdICYmIHRoaXMudmlkZW9zWzBdLnZpZGVvICYmXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8uY3VycmVudFRpbWUgPiAwICYmXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8ucGF1c2VkID09PSBmYWxzZSAmJlxuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9zWzBdLnZpZGVvLmVuZGVkID09PSBmYWxzZSAmJlxuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9zWzBdLnZpZGVvLnJlYWR5U3RhdGUgPT09IDQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVtaXRFdmVudCgncmVtb3RlVmlkZW9QbGF5aW5nJywgW25ldyBWaWRlb0VsZW1lbnRFdmVudCh0aGlzLnZpZGVvc1swXS52aWRlbywgdGhpcywgJ3JlbW90ZVZpZGVvUGxheWluZycpXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHR5cGUgPT09ICdhY2Nlc3NBbGxvd2VkJykge1xuICAgICAgICAgICAgaWYgKHRoaXMuYWNjZXNzQWxsb3dlZCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZW1pdEV2ZW50KCdhY2Nlc3NBbGxvd2VkJywgW10pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmICh0eXBlID09PSAnYWNjZXNzRGVuaWVkJykge1xuICAgICAgICAgICAgaWYgKHRoaXMuYWNjZXNzRGVuaWVkKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5lbWl0RXZlbnQoJ2FjY2Vzc0RlbmllZCcsIFtdKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFNlZSBbW0V2ZW50RGlzcGF0Y2hlci5vbmNlXV1cbiAgICAgKi9cbiAgICBvbmNlKHR5cGU6IHN0cmluZywgaGFuZGxlcjogKGV2ZW50OiBFdmVudCkgPT4gdm9pZCk6IFB1Ymxpc2hlciB7XG4gICAgICAgIHN1cGVyLm9uY2UodHlwZSwgaGFuZGxlcik7XG4gICAgICAgIGlmICh0eXBlID09PSAnc3RyZWFtQ3JlYXRlZCcpIHtcbiAgICAgICAgICAgIGlmICghIXRoaXMuc3RyZWFtICYmIHRoaXMuc3RyZWFtLmlzTG9jYWxTdHJlYW1QdWJsaXNoZWQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVtaXRFdmVudCgnc3RyZWFtQ3JlYXRlZCcsIFtuZXcgU3RyZWFtRXZlbnQoZmFsc2UsIHRoaXMsICdzdHJlYW1DcmVhdGVkJywgdGhpcy5zdHJlYW0sICcnKV0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbS5lZS5vbmNlKCdzdHJlYW0tY3JlYXRlZC1ieS1wdWJsaXNoZXInLCAoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZW1pdEV2ZW50KCdzdHJlYW1DcmVhdGVkJywgW25ldyBTdHJlYW1FdmVudChmYWxzZSwgdGhpcywgJ3N0cmVhbUNyZWF0ZWQnLCB0aGlzLnN0cmVhbSwgJycpXSk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHR5cGUgPT09ICdyZW1vdGVWaWRlb1BsYXlpbmcnKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5zdHJlYW0uZGlzcGxheU15UmVtb3RlKCkgJiYgdGhpcy52aWRlb3NbMF0gJiYgdGhpcy52aWRlb3NbMF0udmlkZW8gJiZcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvc1swXS52aWRlby5jdXJyZW50VGltZSA+IDAgJiZcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvc1swXS52aWRlby5wYXVzZWQgPT09IGZhbHNlICYmXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8uZW5kZWQgPT09IGZhbHNlICYmXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8ucmVhZHlTdGF0ZSA9PT0gNCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZW1pdEV2ZW50KCdyZW1vdGVWaWRlb1BsYXlpbmcnLCBbbmV3IFZpZGVvRWxlbWVudEV2ZW50KHRoaXMudmlkZW9zWzBdLnZpZGVvLCB0aGlzLCAncmVtb3RlVmlkZW9QbGF5aW5nJyldKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAodHlwZSA9PT0gJ2FjY2Vzc0FsbG93ZWQnKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5hY2Nlc3NBbGxvd2VkKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5lbWl0RXZlbnQoJ2FjY2Vzc0FsbG93ZWQnLCBbXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHR5cGUgPT09ICdhY2Nlc3NEZW5pZWQnKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5hY2Nlc3NEZW5pZWQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVtaXRFdmVudCgnYWNjZXNzRGVuaWVkJywgW10pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuXG4gICAgLyogSGlkZGVuIG1ldGhvZHMgKi9cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBpbml0aWFsaXplKCk6IFByb21pc2U8YW55PiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG5cbiAgICAgICAgICAgIGNvbnN0IGVycm9yQ2FsbGJhY2sgPSAob3BlblZpZHVFcnJvcjogT3BlblZpZHVFcnJvcikgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuYWNjZXNzRGVuaWVkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB0aGlzLmFjY2Vzc0FsbG93ZWQgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICByZWplY3Qob3BlblZpZHVFcnJvcik7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICBjb25zdCBzdWNjZXNzQ2FsbGJhY2sgPSAobWVkaWFTdHJlYW06IE1lZGlhU3RyZWFtKSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5hY2Nlc3NBbGxvd2VkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB0aGlzLmFjY2Vzc0RlbmllZCA9IGZhbHNlO1xuXG4gICAgICAgICAgICAgICAgaWYgKHRoaXMub3BlbnZpZHUuaXNNZWRpYVN0cmVhbVRyYWNrKHRoaXMucHJvcGVydGllcy5hdWRpb1NvdXJjZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgbWVkaWFTdHJlYW0ucmVtb3ZlVHJhY2sobWVkaWFTdHJlYW0uZ2V0QXVkaW9UcmFja3MoKVswXSk7XG4gICAgICAgICAgICAgICAgICAgIG1lZGlhU3RyZWFtLmFkZFRyYWNrKCg8TWVkaWFTdHJlYW1UcmFjaz50aGlzLnByb3BlcnRpZXMuYXVkaW9Tb3VyY2UpKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAodGhpcy5vcGVudmlkdS5pc01lZGlhU3RyZWFtVHJhY2sodGhpcy5wcm9wZXJ0aWVzLnZpZGVvU291cmNlKSkge1xuICAgICAgICAgICAgICAgICAgICBtZWRpYVN0cmVhbS5yZW1vdmVUcmFjayhtZWRpYVN0cmVhbS5nZXRWaWRlb1RyYWNrcygpWzBdKTtcbiAgICAgICAgICAgICAgICAgICAgbWVkaWFTdHJlYW0uYWRkVHJhY2soKDxNZWRpYVN0cmVhbVRyYWNrPnRoaXMucHJvcGVydGllcy52aWRlb1NvdXJjZSkpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIEFwcGx5IFB1Ymxpc2hlclByb3BlcnRpZXMucHVibGlzaEF1ZGlvIGFuZCBQdWJsaXNoZXJQcm9wZXJ0aWVzLnB1Ymxpc2hWaWRlb1xuICAgICAgICAgICAgICAgIGlmICghIW1lZGlhU3RyZWFtLmdldEF1ZGlvVHJhY2tzKClbMF0pIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgZW5hYmxlZCA9ICh0aGlzLnN0cmVhbS5hdWRpb0FjdGl2ZSAhPT0gdW5kZWZpbmVkICYmIHRoaXMuc3RyZWFtLmF1ZGlvQWN0aXZlICE9PSBudWxsKSA/IHRoaXMuc3RyZWFtLmF1ZGlvQWN0aXZlIDogISF0aGlzLnN0cmVhbS5vdXRib3VuZFN0cmVhbU9wdHMucHVibGlzaGVyUHJvcGVydGllcy5wdWJsaXNoQXVkaW87XG4gICAgICAgICAgICAgICAgICAgIG1lZGlhU3RyZWFtLmdldEF1ZGlvVHJhY2tzKClbMF0uZW5hYmxlZCA9IGVuYWJsZWQ7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmICghIW1lZGlhU3RyZWFtLmdldFZpZGVvVHJhY2tzKClbMF0pIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgZW5hYmxlZCA9ICh0aGlzLnN0cmVhbS52aWRlb0FjdGl2ZSAhPT0gdW5kZWZpbmVkICYmIHRoaXMuc3RyZWFtLnZpZGVvQWN0aXZlICE9PSBudWxsKSA/IHRoaXMuc3RyZWFtLnZpZGVvQWN0aXZlIDogISF0aGlzLnN0cmVhbS5vdXRib3VuZFN0cmVhbU9wdHMucHVibGlzaGVyUHJvcGVydGllcy5wdWJsaXNoVmlkZW87XG4gICAgICAgICAgICAgICAgICAgIG1lZGlhU3RyZWFtLmdldFZpZGVvVHJhY2tzKClbMF0uZW5hYmxlZCA9IGVuYWJsZWQ7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb1JlZmVyZW5jZSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3ZpZGVvJyk7XG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb1JlZmVyZW5jZS5zcmNPYmplY3QgPSBtZWRpYVN0cmVhbTtcblxuICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtLnNldE1lZGlhU3RyZWFtKG1lZGlhU3RyZWFtKTtcbiAgICAgICAgICAgICAgICBpZiAoIXRoaXMuc3RyZWFtLmRpc3BsYXlNeVJlbW90ZSgpKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIFdoZW4gd2UgYXJlIHN1YnNjcmliZWQgdG8gb3VyIHJlbW90ZSB3ZSBkb24ndCBzdGlsbCBzZXQgdGhlIE1lZGlhU3RyZWFtIG9iamVjdCBpbiB0aGUgdmlkZW8gZWxlbWVudHMgdG9cbiAgICAgICAgICAgICAgICAgICAgLy8gYXZvaWQgZWFybHkgJ3N0cmVhbVBsYXlpbmcnIGV2ZW50XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtLnVwZGF0ZU1lZGlhU3RyZWFtSW5WaWRlb3MoKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoISF0aGlzLmZpcnN0VmlkZW9FbGVtZW50KSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuY3JlYXRlVmlkZW9FbGVtZW50KHRoaXMuZmlyc3RWaWRlb0VsZW1lbnQudGFyZ2V0RWxlbWVudCwgPFZpZGVvSW5zZXJ0TW9kZT50aGlzLnByb3BlcnRpZXMuaW5zZXJ0TW9kZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGRlbGV0ZSB0aGlzLmZpcnN0VmlkZW9FbGVtZW50O1xuXG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuc3RyZWFtLmlzU2VuZFZpZGVvKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCF0aGlzLnN0cmVhbS5pc1NlbmRTY3JlZW4oKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gV2l0aCBubyBzY3JlZW4gc2hhcmUsIHZpZGVvIGRpbWVuc2lvbiBjYW4gYmUgc2V0IGRpcmVjdGx5IGZyb20gTWVkaWFTdHJlYW0gKGdldFNldHRpbmdzKVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gT3JpZW50YXRpb24gbXVzdCBiZSBjaGVja2VkIGZvciBtb2JpbGUgZGV2aWNlcyAod2lkdGggYW5kIGhlaWdodCBhcmUgcmV2ZXJzZWQpXG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB7IHdpZHRoLCBoZWlnaHQgfSA9IG1lZGlhU3RyZWFtLmdldFZpZGVvVHJhY2tzKClbMF0uZ2V0U2V0dGluZ3MoKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHBsYXRmb3JtLm5hbWUhIS50b0xvd2VyQ2FzZSgpLmluZGV4T2YoJ21vYmlsZScpICE9PSAtMSAmJiAod2luZG93LmlubmVySGVpZ2h0ID4gd2luZG93LmlubmVyV2lkdGgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gTW9iaWxlIHBvcnRyYWl0IG1vZGVcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbS52aWRlb0RpbWVuc2lvbnMgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdpZHRoOiBoZWlnaHQgfHwgMCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaGVpZ2h0OiB3aWR0aCB8fCAwXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdHJlYW0udmlkZW9EaW1lbnNpb25zID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3aWR0aDogd2lkdGggfHwgMCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaGVpZ2h0OiBoZWlnaHQgfHwgMFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbS5pc0xvY2FsU3RyZWFtUmVhZHlUb1B1Ymxpc2ggPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdHJlYW0uZWUuZW1pdEV2ZW50KCdzdHJlYW0tcmVhZHktdG8tcHVibGlzaCcsIFtdKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIFdpdGggc2NyZWVuIHNoYXJlLCB2aWRlbyBkaW1lbnNpb24gbXVzdCBiZSBnb3QgZnJvbSBhIHZpZGVvIGVsZW1lbnQgKG9ubG9hZGVkbWV0YWRhdGEgZXZlbnQpXG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnZpZGVvUmVmZXJlbmNlLm9ubG9hZGVkbWV0YWRhdGEgPSAoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdHJlYW0udmlkZW9EaW1lbnNpb25zID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3aWR0aDogdGhpcy52aWRlb1JlZmVyZW5jZS52aWRlb1dpZHRoLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBoZWlnaHQ6IHRoaXMudmlkZW9SZWZlcmVuY2UudmlkZW9IZWlnaHRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc2NyZWVuU2hhcmVSZXNpemVJbnRlcnZhbCA9IHNldEludGVydmFsKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZmlyZWZveFNldHRpbmdzID0gbWVkaWFTdHJlYW0uZ2V0VmlkZW9UcmFja3MoKVswXS5nZXRTZXR0aW5ncygpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBuZXdXaWR0aCA9IChwbGF0Zm9ybS5uYW1lID09PSAnQ2hyb21lJykgPyB0aGlzLnZpZGVvUmVmZXJlbmNlLnZpZGVvV2lkdGggOiBmaXJlZm94U2V0dGluZ3Mud2lkdGg7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG5ld0hlaWdodCA9IChwbGF0Zm9ybS5uYW1lID09PSAnQ2hyb21lJykgPyB0aGlzLnZpZGVvUmVmZXJlbmNlLnZpZGVvSGVpZ2h0IDogZmlyZWZveFNldHRpbmdzLmhlaWdodDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuc3RyZWFtLmlzTG9jYWxTdHJlYW1QdWJsaXNoZWQgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChuZXdXaWR0aCAhPT0gdGhpcy5zdHJlYW0udmlkZW9EaW1lbnNpb25zLndpZHRoIHx8XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3SGVpZ2h0ICE9PSB0aGlzLnN0cmVhbS52aWRlb0RpbWVuc2lvbnMuaGVpZ2h0KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3Qgb2xkVmFsdWUgPSB7IHdpZHRoOiB0aGlzLnN0cmVhbS52aWRlb0RpbWVuc2lvbnMud2lkdGgsIGhlaWdodDogdGhpcy5zdHJlYW0udmlkZW9EaW1lbnNpb25zLmhlaWdodCB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdHJlYW0udmlkZW9EaW1lbnNpb25zID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdpZHRoOiBuZXdXaWR0aCB8fCAwLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhlaWdodDogbmV3SGVpZ2h0IHx8IDBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnNlc3Npb24ub3BlbnZpZHUuc2VuZFJlcXVlc3QoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ3N0cmVhbVByb3BlcnR5Q2hhbmdlZCcsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJlYW1JZDogdGhpcy5zdHJlYW0uc3RyZWFtSWQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByb3BlcnR5OiAndmlkZW9EaW1lbnNpb25zJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3VmFsdWU6IEpTT04uc3RyaW5naWZ5KHRoaXMuc3RyZWFtLnZpZGVvRGltZW5zaW9ucyksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlYXNvbjogJ3NjcmVlblJlc2l6ZWQnXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoZXJyb3IsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihcIkVycm9yIHNlbmRpbmcgJ3N0cmVhbVByb3BlcnR5Q2hhbmdlZCcgZXZlbnRcIiwgZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXNzaW9uLmVtaXRFdmVudCgnc3RyZWFtUHJvcGVydHlDaGFuZ2VkJywgW25ldyBTdHJlYW1Qcm9wZXJ0eUNoYW5nZWRFdmVudCh0aGlzLnNlc3Npb24sIHRoaXMuc3RyZWFtLCAndmlkZW9EaW1lbnNpb25zJywgdGhpcy5zdHJlYW0udmlkZW9EaW1lbnNpb25zLCBvbGRWYWx1ZSwgJ3NjcmVlblJlc2l6ZWQnKV0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5lbWl0RXZlbnQoJ3N0cmVhbVByb3BlcnR5Q2hhbmdlZCcsIFtuZXcgU3RyZWFtUHJvcGVydHlDaGFuZ2VkRXZlbnQodGhpcywgdGhpcy5zdHJlYW0sICd2aWRlb0RpbWVuc2lvbnMnLCB0aGlzLnN0cmVhbS52aWRlb0RpbWVuc2lvbnMsIG9sZFZhbHVlLCAnc2NyZWVuUmVzaXplZCcpXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0sIDUwMCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdHJlYW0uaXNMb2NhbFN0cmVhbVJlYWR5VG9QdWJsaXNoID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbS5lZS5lbWl0RXZlbnQoJ3N0cmVhbS1yZWFkeS10by1wdWJsaXNoJywgW10pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtLmlzTG9jYWxTdHJlYW1SZWFkeVRvUHVibGlzaCA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtLmVlLmVtaXRFdmVudCgnc3RyZWFtLXJlYWR5LXRvLXB1Ymxpc2gnLCBbXSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIHRoaXMub3BlbnZpZHUuZ2VuZXJhdGVNZWRpYUNvbnN0cmFpbnRzKHRoaXMucHJvcGVydGllcylcbiAgICAgICAgICAgICAgICAudGhlbihjb25zdHJhaW50cyA9PiB7XG5cbiAgICAgICAgICAgICAgICAgICAgY29uc3Qgb3V0Ym91bmRTdHJlYW1PcHRpb25zID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgbWVkaWFDb25zdHJhaW50czogY29uc3RyYWludHMsXG4gICAgICAgICAgICAgICAgICAgICAgICBwdWJsaXNoZXJQcm9wZXJ0aWVzOiB0aGlzLnByb3BlcnRpZXNcbiAgICAgICAgICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbS5zZXRPdXRib3VuZFN0cmVhbU9wdGlvbnMob3V0Ym91bmRTdHJlYW1PcHRpb25zKTtcblxuICAgICAgICAgICAgICAgICAgICBjb25zdCBjb25zdHJhaW50c0F1eDogTWVkaWFTdHJlYW1Db25zdHJhaW50cyA9IHt9O1xuICAgICAgICAgICAgICAgICAgICBjb25zdCB0aW1lRm9yRGlhbG9nRXZlbnQgPSAxMjUwO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLnN0cmVhbS5pc1NlbmRWaWRlbygpIHx8IHRoaXMuc3RyZWFtLmlzU2VuZEF1ZGlvKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGRlZmluZWRBdWRpb0NvbnN0cmFpbnQgPSAoKGNvbnN0cmFpbnRzLmF1ZGlvID09PSB1bmRlZmluZWQpID8gdHJ1ZSA6IGNvbnN0cmFpbnRzLmF1ZGlvKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0cmFpbnRzQXV4LmF1ZGlvID0gdGhpcy5zdHJlYW0uaXNTZW5kU2NyZWVuKCkgPyBmYWxzZSA6IGRlZmluZWRBdWRpb0NvbnN0cmFpbnQ7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdHJhaW50c0F1eC52aWRlbyA9IGNvbnN0cmFpbnRzLnZpZGVvO1xuICAgICAgICAgICAgICAgICAgICAgICAgbGV0IHN0YXJ0VGltZSA9IERhdGUubm93KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnNldFBlcm1pc3Npb25EaWFsb2dUaW1lcih0aW1lRm9yRGlhbG9nRXZlbnQpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBuYXZpZ2F0b3IubWVkaWFEZXZpY2VzLmdldFVzZXJNZWRpYShjb25zdHJhaW50c0F1eClcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAudGhlbihtZWRpYVN0cmVhbSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY2xlYXJQZXJtaXNzaW9uRGlhbG9nVGltZXIoc3RhcnRUaW1lLCB0aW1lRm9yRGlhbG9nRXZlbnQpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLnN0cmVhbS5pc1NlbmRTY3JlZW4oKSAmJiB0aGlzLnN0cmVhbS5pc1NlbmRBdWRpbygpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBXaGVuIGdldHRpbmcgZGVza3RvcCBhcyB1c2VyIG1lZGlhIGF1ZGlvIGNvbnN0cmFpbnQgbXVzdCBiZSBmYWxzZS4gTm93IHdlIGNhbiBhc2sgZm9yIGl0IGlmIHJlcXVpcmVkXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdHJhaW50c0F1eC5hdWRpbyA9IGRlZmluZWRBdWRpb0NvbnN0cmFpbnQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdHJhaW50c0F1eC52aWRlbyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhcnRUaW1lID0gRGF0ZS5ub3coKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc2V0UGVybWlzc2lvbkRpYWxvZ1RpbWVyKHRpbWVGb3JEaWFsb2dFdmVudCk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hdmlnYXRvci5tZWRpYURldmljZXMuZ2V0VXNlck1lZGlhKGNvbnN0cmFpbnRzQXV4KVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC50aGVuKGF1ZGlvT25seVN0cmVhbSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY2xlYXJQZXJtaXNzaW9uRGlhbG9nVGltZXIoc3RhcnRUaW1lLCB0aW1lRm9yRGlhbG9nRXZlbnQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZWRpYVN0cmVhbS5hZGRUcmFjayhhdWRpb09ubHlTdHJlYW0uZ2V0QXVkaW9UcmFja3MoKVswXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN1Y2Nlc3NDYWxsYmFjayhtZWRpYVN0cmVhbSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNsZWFyUGVybWlzc2lvbkRpYWxvZ1RpbWVyKHN0YXJ0VGltZSwgdGltZUZvckRpYWxvZ0V2ZW50KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGVycm9yTmFtZSwgZXJyb3JNZXNzYWdlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzd2l0Y2ggKGVycm9yLm5hbWUudG9Mb3dlckNhc2UoKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAnbm90Zm91bmRlcnJvcic6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JOYW1lID0gT3BlblZpZHVFcnJvck5hbWUuSU5QVVRfQVVESU9fREVWSUNFX05PVF9GT1VORDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck1lc3NhZ2UgPSBlcnJvci50b1N0cmluZygpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yQ2FsbGJhY2sobmV3IE9wZW5WaWR1RXJyb3IoZXJyb3JOYW1lLCBlcnJvck1lc3NhZ2UpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJ25vdGFsbG93ZWRlcnJvcic6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JOYW1lID0gT3BlblZpZHVFcnJvck5hbWUuREVWSUNFX0FDQ0VTU19ERU5JRUQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JNZXNzYWdlID0gZXJyb3IudG9TdHJpbmcoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvckNhbGxiYWNrKG5ldyBPcGVuVmlkdUVycm9yKGVycm9yTmFtZSwgZXJyb3JNZXNzYWdlKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlICdvdmVyY29uc3RyYWluZWRlcnJvcic6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yLmNvbnN0cmFpbnQudG9Mb3dlckNhc2UoKSA9PT0gJ2RldmljZWlkJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck5hbWUgPSBPcGVuVmlkdUVycm9yTmFtZS5JTlBVVF9BVURJT19ERVZJQ0VfTk9UX0ZPVU5EO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck1lc3NhZ2UgPSBcIkF1ZGlvIGlucHV0IGRldmljZSB3aXRoIGRldmljZUlkICdcIiArICg8Q29uc3RyYWluRE9NU3RyaW5nUGFyYW1ldGVycz4oPE1lZGlhVHJhY2tDb25zdHJhaW50cz5jb25zdHJhaW50cy52aWRlbykuZGV2aWNlSWQhISkuZXhhY3QgKyBcIicgbm90IGZvdW5kXCI7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JOYW1lID0gT3BlblZpZHVFcnJvck5hbWUuUFVCTElTSEVSX1BST1BFUlRJRVNfRVJST1I7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yTWVzc2FnZSA9IFwiQXVkaW8gaW5wdXQgZGV2aWNlIGRvZXNuJ3Qgc3VwcG9ydCB0aGUgdmFsdWUgcGFzc2VkIGZvciBjb25zdHJhaW50ICdcIiArIGVycm9yLmNvbnN0cmFpbnQgKyBcIidcIjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JDYWxsYmFjayhuZXcgT3BlblZpZHVFcnJvcihlcnJvck5hbWUsIGVycm9yTWVzc2FnZSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdWNjZXNzQ2FsbGJhY2sobWVkaWFTdHJlYW0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNsZWFyUGVybWlzc2lvbkRpYWxvZ1RpbWVyKHN0YXJ0VGltZSwgdGltZUZvckRpYWxvZ0V2ZW50KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGVycm9yTmFtZSwgZXJyb3JNZXNzYWdlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzd2l0Y2ggKGVycm9yLm5hbWUudG9Mb3dlckNhc2UoKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAnbm90Zm91bmRlcnJvcic6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmF2aWdhdG9yLm1lZGlhRGV2aWNlcy5nZXRVc2VyTWVkaWEoe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhdWRpbzogZmFsc2UsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZpZGVvOiBjb25zdHJhaW50cy52aWRlb1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC50aGVuKG1lZGlhU3RyZWFtID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1lZGlhU3RyZWFtLmdldFZpZGVvVHJhY2tzKCkuZm9yRWFjaCgodHJhY2spID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cmFjay5zdG9wKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yTmFtZSA9IE9wZW5WaWR1RXJyb3JOYW1lLklOUFVUX0FVRElPX0RFVklDRV9OT1RfRk9VTkQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck1lc3NhZ2UgPSBlcnJvci50b1N0cmluZygpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JDYWxsYmFjayhuZXcgT3BlblZpZHVFcnJvcihlcnJvck5hbWUsIGVycm9yTWVzc2FnZSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KS5jYXRjaChlID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yTmFtZSA9IE9wZW5WaWR1RXJyb3JOYW1lLklOUFVUX1ZJREVPX0RFVklDRV9OT1RfRk9VTkQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck1lc3NhZ2UgPSBlcnJvci50b1N0cmluZygpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JDYWxsYmFjayhuZXcgT3BlblZpZHVFcnJvcihlcnJvck5hbWUsIGVycm9yTWVzc2FnZSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJ25vdGFsbG93ZWRlcnJvcic6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JOYW1lID0gdGhpcy5zdHJlYW0uaXNTZW5kU2NyZWVuKCkgPyBPcGVuVmlkdUVycm9yTmFtZS5TQ1JFRU5fQ0FQVFVSRV9ERU5JRUQgOiBPcGVuVmlkdUVycm9yTmFtZS5ERVZJQ0VfQUNDRVNTX0RFTklFRDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck1lc3NhZ2UgPSBlcnJvci50b1N0cmluZygpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yQ2FsbGJhY2sobmV3IE9wZW5WaWR1RXJyb3IoZXJyb3JOYW1lLCBlcnJvck1lc3NhZ2UpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJ292ZXJjb25zdHJhaW5lZGVycm9yJzpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYXZpZ2F0b3IubWVkaWFEZXZpY2VzLmdldFVzZXJNZWRpYSh7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGF1ZGlvOiBmYWxzZSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmlkZW86IGNvbnN0cmFpbnRzLnZpZGVvXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLnRoZW4obWVkaWFTdHJlYW0gPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWVkaWFTdHJlYW0uZ2V0VmlkZW9UcmFja3MoKS5mb3JFYWNoKCh0cmFjaykgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRyYWNrLnN0b3AoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yLmNvbnN0cmFpbnQudG9Mb3dlckNhc2UoKSA9PT0gJ2RldmljZWlkJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yTmFtZSA9IE9wZW5WaWR1RXJyb3JOYW1lLklOUFVUX0FVRElPX0RFVklDRV9OT1RfRk9VTkQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JNZXNzYWdlID0gXCJBdWRpbyBpbnB1dCBkZXZpY2Ugd2l0aCBkZXZpY2VJZCAnXCIgKyAoPENvbnN0cmFpbkRPTVN0cmluZ1BhcmFtZXRlcnM+KDxNZWRpYVRyYWNrQ29uc3RyYWludHM+Y29uc3RyYWludHMuYXVkaW8pLmRldmljZUlkISEpLmV4YWN0ICsgXCInIG5vdCBmb3VuZFwiO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck5hbWUgPSBPcGVuVmlkdUVycm9yTmFtZS5QVUJMSVNIRVJfUFJPUEVSVElFU19FUlJPUjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck1lc3NhZ2UgPSBcIkF1ZGlvIGlucHV0IGRldmljZSBkb2Vzbid0IHN1cHBvcnQgdGhlIHZhbHVlIHBhc3NlZCBmb3IgY29uc3RyYWludCAnXCIgKyBlcnJvci5jb25zdHJhaW50ICsgXCInXCI7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvckNhbGxiYWNrKG5ldyBPcGVuVmlkdUVycm9yKGVycm9yTmFtZSwgZXJyb3JNZXNzYWdlKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pLmNhdGNoKGUgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yLmNvbnN0cmFpbnQudG9Mb3dlckNhc2UoKSA9PT0gJ2RldmljZWlkJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yTmFtZSA9IE9wZW5WaWR1RXJyb3JOYW1lLklOUFVUX1ZJREVPX0RFVklDRV9OT1RfRk9VTkQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JNZXNzYWdlID0gXCJWaWRlbyBpbnB1dCBkZXZpY2Ugd2l0aCBkZXZpY2VJZCAnXCIgKyAoPENvbnN0cmFpbkRPTVN0cmluZ1BhcmFtZXRlcnM+KDxNZWRpYVRyYWNrQ29uc3RyYWludHM+Y29uc3RyYWludHMudmlkZW8pLmRldmljZUlkISEpLmV4YWN0ICsgXCInIG5vdCBmb3VuZFwiO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck5hbWUgPSBPcGVuVmlkdUVycm9yTmFtZS5QVUJMSVNIRVJfUFJPUEVSVElFU19FUlJPUjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck1lc3NhZ2UgPSBcIlZpZGVvIGlucHV0IGRldmljZSBkb2Vzbid0IHN1cHBvcnQgdGhlIHZhbHVlIHBhc3NlZCBmb3IgY29uc3RyYWludCAnXCIgKyBlcnJvci5jb25zdHJhaW50ICsgXCInXCI7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvckNhbGxiYWNrKG5ldyBPcGVuVmlkdUVycm9yKGVycm9yTmFtZSwgZXJyb3JNZXNzYWdlKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZWplY3QobmV3IE9wZW5WaWR1RXJyb3IoT3BlblZpZHVFcnJvck5hbWUuTk9fSU5QVVRfU09VUkNFX1NFVCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBcIlByb3BlcnRpZXMgJ2F1ZGlvU291cmNlJyBhbmQgJ3ZpZGVvU291cmNlJyBjYW5ub3QgYmUgc2V0IHRvIGZhbHNlIG9yIG51bGwgYXQgdGhlIHNhbWUgdGltZSB3aGVuIGNhbGxpbmcgJ09wZW5WaWR1LmluaXRQdWJsaXNoZXInXCIpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgLmNhdGNoKChlcnJvcjogT3BlblZpZHVFcnJvcikgPT4ge1xuICAgICAgICAgICAgICAgICAgICBlcnJvckNhbGxiYWNrKGVycm9yKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHJlZXN0YWJsaXNoU3RyZWFtUGxheWluZ0V2ZW50KCkge1xuICAgICAgICBpZiAodGhpcy5lZS5nZXRMaXN0ZW5lcnMoJ3N0cmVhbVBsYXlpbmcnKS5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICB0aGlzLmFkZFBsYXlFdmVudFRvRmlyc3RWaWRlbygpO1xuICAgICAgICB9XG4gICAgfVxuXG5cbiAgICAvKiBQcml2YXRlIG1ldGhvZHMgKi9cblxuICAgIHByaXZhdGUgc2V0UGVybWlzc2lvbkRpYWxvZ1RpbWVyKHdhaXRUaW1lOiBudW1iZXIpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5wZXJtaXNzaW9uRGlhbG9nVGltZW91dCA9IHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5lbWl0RXZlbnQoJ2FjY2Vzc0RpYWxvZ09wZW5lZCcsIFtdKTtcbiAgICAgICAgfSwgd2FpdFRpbWUpO1xuICAgIH1cblxuICAgIHByaXZhdGUgY2xlYXJQZXJtaXNzaW9uRGlhbG9nVGltZXIoc3RhcnRUaW1lOiBudW1iZXIsIHdhaXRUaW1lOiBudW1iZXIpOiB2b2lkIHtcbiAgICAgICAgY2xlYXJUaW1lb3V0KHRoaXMucGVybWlzc2lvbkRpYWxvZ1RpbWVvdXQpO1xuICAgICAgICBpZiAoKERhdGUubm93KCkgLSBzdGFydFRpbWUpID4gd2FpdFRpbWUpIHtcbiAgICAgICAgICAgIC8vIFBlcm1pc3Npb24gZGlhbG9nIHdhcyBzaG93biBhbmQgbm93IGlzIGNsb3NlZFxuICAgICAgICAgICAgdGhpcy5lbWl0RXZlbnQoJ2FjY2Vzc0RpYWxvZ0Nsb3NlZCcsIFtdKTtcbiAgICAgICAgfVxuICAgIH1cblxufSIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTctMjAxOCBPcGVuVmlkdSAoaHR0cHM6Ly9vcGVudmlkdS5pby8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuaW1wb3J0IHsgQ29ubmVjdGlvbiB9IGZyb20gJy4vQ29ubmVjdGlvbic7XG5pbXBvcnQgeyBPcGVuVmlkdSB9IGZyb20gJy4vT3BlblZpZHUnO1xuaW1wb3J0IHsgUHVibGlzaGVyIH0gZnJvbSAnLi9QdWJsaXNoZXInO1xuaW1wb3J0IHsgU3RyZWFtIH0gZnJvbSAnLi9TdHJlYW0nO1xuaW1wb3J0IHsgU3RyZWFtTWFuYWdlciB9IGZyb20gJy4vU3RyZWFtTWFuYWdlcic7XG5pbXBvcnQgeyBTdWJzY3JpYmVyIH0gZnJvbSAnLi9TdWJzY3JpYmVyJztcbmltcG9ydCB7IENhcGFiaWxpdGllcyB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvSW50ZXJmYWNlcy9QdWJsaWMvQ2FwYWJpbGl0aWVzJztcbmltcG9ydCB7IEV2ZW50RGlzcGF0Y2hlciB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvSW50ZXJmYWNlcy9QdWJsaWMvRXZlbnREaXNwYXRjaGVyJztcbmltcG9ydCB7IFNpZ25hbE9wdGlvbnMgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHVibGljL1NpZ25hbE9wdGlvbnMnO1xuaW1wb3J0IHsgU3Vic2NyaWJlclByb3BlcnRpZXMgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHVibGljL1N1YnNjcmliZXJQcm9wZXJ0aWVzJztcbmltcG9ydCB7IENvbm5lY3Rpb25PcHRpb25zIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9JbnRlcmZhY2VzL1ByaXZhdGUvQ29ubmVjdGlvbk9wdGlvbnMnO1xuaW1wb3J0IHsgT2JqTWFwIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9JbnRlcmZhY2VzL1ByaXZhdGUvT2JqTWFwJztcbmltcG9ydCB7IFNlc3Npb25PcHRpb25zIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9JbnRlcmZhY2VzL1ByaXZhdGUvU2Vzc2lvbk9wdGlvbnMnO1xuaW1wb3J0IHsgQ29ubmVjdGlvbkV2ZW50IH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvQ29ubmVjdGlvbkV2ZW50JztcbmltcG9ydCB7IFB1Ymxpc2hlclNwZWFraW5nRXZlbnQgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0V2ZW50cy9QdWJsaXNoZXJTcGVha2luZ0V2ZW50JztcbmltcG9ydCB7IFJlY29yZGluZ0V2ZW50IH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvUmVjb3JkaW5nRXZlbnQnO1xuaW1wb3J0IHsgU2Vzc2lvbkRpc2Nvbm5lY3RlZEV2ZW50IH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvU2Vzc2lvbkRpc2Nvbm5lY3RlZEV2ZW50JztcbmltcG9ydCB7IFNpZ25hbEV2ZW50IH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvU2lnbmFsRXZlbnQnO1xuaW1wb3J0IHsgU3RyZWFtRXZlbnQgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0V2ZW50cy9TdHJlYW1FdmVudCc7XG5pbXBvcnQgeyBTdHJlYW1Qcm9wZXJ0eUNoYW5nZWRFdmVudCB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1N0cmVhbVByb3BlcnR5Q2hhbmdlZEV2ZW50JztcbmltcG9ydCB7IE9wZW5WaWR1RXJyb3IsIE9wZW5WaWR1RXJyb3JOYW1lIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FbnVtcy9PcGVuVmlkdUVycm9yJztcbmltcG9ydCB7IFZpZGVvSW5zZXJ0TW9kZSB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRW51bXMvVmlkZW9JbnNlcnRNb2RlJztcblxuaW1wb3J0IHBsYXRmb3JtID0gcmVxdWlyZSgncGxhdGZvcm0nKTtcbmltcG9ydCBFdmVudEVtaXR0ZXIgPSByZXF1aXJlKCd3b2xmeTg3LWV2ZW50ZW1pdHRlcicpO1xuXG5cbi8qKlxuICogUmVwcmVzZW50cyBhIHZpZGVvIGNhbGwuIEl0IGNhbiBhbHNvIGJlIHNlZW4gYXMgYSB2aWRlb2NvbmZlcmVuY2Ugcm9vbSB3aGVyZSBtdWx0aXBsZSB1c2VycyBjYW4gY29ubmVjdC5cbiAqIFBhcnRpY2lwYW50cyB3aG8gcHVibGlzaCB0aGVpciB2aWRlb3MgdG8gYSBzZXNzaW9uIGNhbiBiZSBzZWVuIGJ5IHRoZSByZXN0IG9mIHVzZXJzIGNvbm5lY3RlZCB0byB0aGF0IHNwZWNpZmljIHNlc3Npb24uXG4gKiBJbml0aWFsaXplZCB3aXRoIFtbT3BlblZpZHUuaW5pdFNlc3Npb25dXSBtZXRob2RcbiAqL1xuZXhwb3J0IGNsYXNzIFNlc3Npb24gaW1wbGVtZW50cyBFdmVudERpc3BhdGNoZXIge1xuXG4gICAgLyoqXG4gICAgICogTG9jYWwgY29ubmVjdGlvbiB0byB0aGUgU2Vzc2lvbi4gVGhpcyBvYmplY3QgaXMgZGVmaW5lZCBvbmx5IGFmdGVyIFtbU2Vzc2lvbi5jb25uZWN0XV0gaGFzIGJlZW4gc3VjY2Vzc2Z1bGx5IGV4ZWN1dGVkLCBhbmQgY2FuIGJlIHJldHJpZXZlZCBzdWJzY3JpYmluZyB0byBgY29ubmVjdGlvbkNyZWF0ZWRgIGV2ZW50XG4gICAgICovXG4gICAgY29ubmVjdGlvbjogQ29ubmVjdGlvbjtcblxuICAgIC8qKlxuICAgICAqIFVuaXF1ZSBpZGVudGlmaWVyIG9mIHRoZSBTZXNzaW9uXG4gICAgICovXG4gICAgc2Vzc2lvbklkOiBzdHJpbmc7XG5cbiAgICAvKipcbiAgICAgKiBDb2xsZWN0aW9uIG9mIGFsbCBTdHJlYW1NYW5hZ2VycyBvZiB0aGlzIFNlc3Npb24gKFtbUHVibGlzaGVyXV0gYW5kIFtbU3Vic2NyaWJlcl1dKVxuICAgICAqL1xuICAgIHN0cmVhbU1hbmFnZXJzOiBTdHJlYW1NYW5hZ2VyW10gPSBbXTtcblxuICAgIC8qKlxuICAgICAqIE9iamVjdCBkZWZpbmluZyB0aGUgbWV0aG9kcyB0aGF0IHRoZSBjbGllbnQgaXMgYWJsZSB0byBjYWxsLiBUaGVzZSBhcmUgZGVmaW5lZCBieSB0aGUgcm9sZSBvZiB0aGUgdG9rZW4gdXNlZCB0byBjb25uZWN0IHRvIHRoZSBTZXNzaW9uLlxuICAgICAqIFRoaXMgb2JqZWN0IGlzIG9ubHkgZGVmaW5lZCBhZnRlciBbW1Nlc3Npb24uY29ubmVjdF1dIGhhcyBiZWVuIHN1Y2Nlc3NmdWxseSByZXNvbHZlZFxuICAgICAqL1xuICAgIGNhcGFiaWxpdGllczogQ2FwYWJpbGl0aWVzO1xuXG4gICAgLy8gVGhpcyBtYXAgaXMgb25seSB1c2VkIHRvIGF2b2lkIHJhY2UgY29uZGl0aW9uIGJldHdlZW4gJ2pvaW5Sb29tJyByZXNwb25zZSBhbmQgJ29uUGFydGljaXBhbnRQdWJsaXNoZWQnIG5vdGlmaWNhdGlvblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICByZW1vdGVTdHJlYW1zQ3JlYXRlZDogT2JqTWFwPGJvb2xlYW4+ID0ge307XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgcmVtb3RlQ29ubmVjdGlvbnM6IE9iak1hcDxDb25uZWN0aW9uPiA9IHt9O1xuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvcGVudmlkdTogT3BlblZpZHU7XG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIG9wdGlvbnM6IFNlc3Npb25PcHRpb25zO1xuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBzcGVha2luZ0V2ZW50c0VuYWJsZWQgPSBmYWxzZTtcblxuICAgIHByaXZhdGUgZWUgPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgY29uc3RydWN0b3Iob3BlbnZpZHU6IE9wZW5WaWR1KSB7XG4gICAgICAgIHRoaXMub3BlbnZpZHUgPSBvcGVudmlkdTtcbiAgICB9XG5cbiAgICBjb25uZWN0KHRva2VuOiBzdHJpbmcpOiBQcm9taXNlPGFueT47XG4gICAgY29ubmVjdCh0b2tlbjogc3RyaW5nLCBtZXRhZGF0YTogYW55KTogUHJvbWlzZTxhbnk+O1xuXG4gICAgLyoqXG4gICAgICogQ29ubmVjdHMgdG8gdGhlIHNlc3Npb24gdXNpbmcgYHRva2VuYC4gUGFyYW1ldGVyIGBtZXRhZGF0YWAgYWxsb3dzIHlvdSB0byBwYXNzIGV4dHJhIGRhdGEgdG8gc2hhcmUgd2l0aCBvdGhlciB1c2VycyB3aGVuXG4gICAgICogdGhleSByZWNlaXZlIGBzdHJlYW1DcmVhdGVkYCBldmVudC4gVGhlIHN0cnVjdHVyZSBvZiBgbWV0YWRhdGFgIHN0cmluZyBpcyB1cCB0byB5b3UgKG1heWJlIHNvbWUgc3RhbmRhcml6ZWQgZm9ybWF0XG4gICAgICogYXMgSlNPTiBvciBYTUwgaXMgYSBnb29kIGlkZWEpLCB0aGUgb25seSByZXN0cmljdGlvbiBpcyBhIG1heGltdW0gbGVuZ3RoIG9mIDEwMDAwIGNoYXJzLlxuICAgICAqXG4gICAgICogVGhpcyBtZXRhZGF0YSBpcyBub3QgY29uc2lkZXJlZCBzZWN1cmUsIGFzIGl0IGlzIGdlbmVyYXRlZCBpbiB0aGUgY2xpZW50IHNpZGUuIFRvIHBhc3Mgc2VjdXJpemVkIGRhdGEsIGFkZCBpdCBhcyBhIHBhcmFtZXRlciBpbiB0aGVcbiAgICAgKiB0b2tlbiBnZW5lcmF0aW9uIG9wZXJhdGlvbiAodGhyb3VnaCB0aGUgQVBJIFJFU1QsIG9wZW52aWR1LWphdmEtY2xpZW50IG9yIG9wZW52aWR1LW5vZGUtY2xpZW50KS5cbiAgICAgKlxuICAgICAqIE9ubHkgYWZ0ZXIgdGhlIHJldHVybmVkIFByb21pc2UgaXMgc3VjY2Vzc2Z1bGx5IHJlc29sdmVkIFtbU2Vzc2lvbi5jb25uZWN0aW9uXV0gb2JqZWN0IHdpbGwgYmUgYXZhaWxhYmxlIGFuZCBwcm9wZXJseSBkZWZpbmVkLlxuICAgICAqXG4gICAgICogIyMjIyBFdmVudHMgZGlzcGF0Y2hlZFxuICAgICAqXG4gICAgICogVGhlIFtbU2Vzc2lvbl1dIG9iamVjdCBvZiB0aGUgbG9jYWwgcGFydGljaXBhbnQgd2lsbCBmaXJzdCBkaXNwYXRjaCBvbmUgb3IgbW9yZSBgY29ubmVjdGlvbkNyZWF0ZWRgIGV2ZW50cyB1cG9uIHN1Y2Nlc3NmdWwgdGVybWluYXRpb24gb2YgdGhpcyBtZXRob2Q6XG4gICAgICogLSBGaXJzdCBvbmUgZm9yIHlvdXIgb3duIGxvY2FsIENvbm5lY3Rpb24gb2JqZWN0LCBzbyB5b3UgY2FuIHJldHJpZXZlIFtbU2Vzc2lvbi5jb25uZWN0aW9uXV0gcHJvcGVydHkuXG4gICAgICogLSBUaGVuIG9uZSBmb3IgZWFjaCByZW1vdGUgQ29ubmVjdGlvbiBwcmV2aW91c2x5IGNvbm5lY3RlZCB0byB0aGUgU2Vzc2lvbiwgaWYgYW55LiBBbnkgb3RoZXIgcmVtb3RlIHVzZXIgY29ubmVjdGluZyB0byB0aGUgU2Vzc2lvbiBhZnRlciB5b3UgaGF2ZVxuICAgICAqIHN1Y2Nlc3NmdWxseSBjb25uZWN0ZWQgd2lsbCBhbHNvIGRpc3BhdGNoIGEgYGNvbm5lY3Rpb25DcmVhdGVkYCBldmVudCB3aGVuIHRoZXkgZG8gc28uXG4gICAgICpcbiAgICAgKiBUaGUgW1tTZXNzaW9uXV0gb2JqZWN0IG9mIHRoZSBsb2NhbCBwYXJ0aWNpcGFudCB3aWxsIGFsc28gZGlzcGF0Y2ggYSBgc3RyZWFtQ3JlYXRlZGAgZXZlbnQgZm9yIGVhY2ggcmVtb3RlIGFjdGl2ZSBbW1B1Ymxpc2hlcl1dIHRoYXQgd2FzIGFscmVhZHkgc3RyZWFtaW5nXG4gICAgICogd2hlbiBjb25uZWN0aW5nLCBqdXN0IGFmdGVyIGRpc3BhdGNoaW5nIGFsbCByZW1vdGUgYGNvbm5lY3Rpb25DcmVhdGVkYCBldmVudHMuXG4gICAgICpcbiAgICAgKiBUaGUgW1tTZXNzaW9uXV0gb2JqZWN0IG9mIGV2ZXJ5IG90aGVyIHBhcnRpY2lwYW50IGNvbm5lY3RlZCB0byB0aGUgc2Vzc2lvbiB3aWxsIGRpc3BhdGNoIGEgYGNvbm5lY3Rpb25DcmVhdGVkYCBldmVudC5cbiAgICAgKlxuICAgICAqIFNlZSBbW0Nvbm5lY3Rpb25FdmVudF1dIGFuZCBbW1N0cmVhbUV2ZW50XV0gdG8gbGVhcm4gbW9yZS5cbiAgICAgKlxuICAgICAqIEByZXR1cm5zIEEgUHJvbWlzZSB0byB3aGljaCB5b3UgbXVzdCBzdWJzY3JpYmUgdGhhdCBpcyByZXNvbHZlZCBpZiB0aGUgdGhlIGNvbm5lY3Rpb24gdG8gdGhlIFNlc3Npb24gd2FzIHN1Y2Nlc3NmdWwgYW5kIHJlamVjdGVkIHdpdGggYW4gRXJyb3Igb2JqZWN0IGlmIG5vdFxuICAgICAqXG4gICAgICovXG4gICAgY29ubmVjdCh0b2tlbjogc3RyaW5nLCBtZXRhZGF0YT86IGFueSk6IFByb21pc2U8YW55PiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG5cbiAgICAgICAgICAgIHRoaXMucHJvY2Vzc1Rva2VuKHRva2VuKTtcblxuICAgICAgICAgICAgaWYgKHRoaXMub3BlbnZpZHUuY2hlY2tTeXN0ZW1SZXF1aXJlbWVudHMoKSkge1xuICAgICAgICAgICAgICAgIC8vIEVhcmx5IGNvbmZpZ3VyYXRpb24gdG8gZGVhY3RpdmF0ZSBhdXRvbWF0aWMgc3Vic2NyaXB0aW9uIHRvIHN0cmVhbXNcbiAgICAgICAgICAgICAgICB0aGlzLm9wdGlvbnMgPSB7XG4gICAgICAgICAgICAgICAgICAgIHNlc3Npb25JZDogdGhpcy5zZXNzaW9uSWQsXG4gICAgICAgICAgICAgICAgICAgIHBhcnRpY2lwYW50SWQ6IHRva2VuLFxuICAgICAgICAgICAgICAgICAgICBtZXRhZGF0YTogISFtZXRhZGF0YSA/IHRoaXMuc3RyaW5nQ2xpZW50TWV0YWRhdGEobWV0YWRhdGEpIDogJydcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIHRoaXMuY29ubmVjdEF1eCh0b2tlbikudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICB9KS5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJlamVjdChuZXcgT3BlblZpZHVFcnJvcihPcGVuVmlkdUVycm9yTmFtZS5CUk9XU0VSX05PVF9TVVBQT1JURUQsICdCcm93c2VyICcgKyBwbGF0Zm9ybS5uYW1lICsgJyAnICsgcGxhdGZvcm0udmVyc2lvbiArICcgaXMgbm90IHN1cHBvcnRlZCBpbiBPcGVuVmlkdScpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogTGVhdmVzIHRoZSBzZXNzaW9uLCBkZXN0cm95aW5nIGFsbCBzdHJlYW1zIGFuZCBkZWxldGluZyB0aGUgdXNlciBhcyBhIHBhcnRpY2lwYW50LlxuICAgICAqXG4gICAgICogIyMjIyBFdmVudHMgZGlzcGF0Y2hlZFxuICAgICAqXG4gICAgICogVGhlIFtbU2Vzc2lvbl1dIG9iamVjdCBvZiB0aGUgbG9jYWwgcGFydGljaXBhbnQgd2lsbCBkaXNwYXRjaCBhIGBzZXNzaW9uRGlzY29ubmVjdGVkYCBldmVudC5cbiAgICAgKiBUaGlzIGV2ZW50IHdpbGwgYXV0b21hdGljYWxseSB1bnN1YnNjcmliZSB0aGUgbGVhdmluZyBwYXJ0aWNpcGFudCBmcm9tIGV2ZXJ5IFN1YnNjcmliZXIgb2JqZWN0IG9mIHRoZSBzZXNzaW9uICh0aGlzIGluY2x1ZGVzIGNsb3NpbmcgdGhlIFdlYlJUQ1BlZXIgY29ubmVjdGlvbiBhbmQgZGlzcG9zaW5nIGFsbCBNZWRpYVN0cmVhbVRyYWNrcylcbiAgICAgKiBhbmQgYWxzbyBkZWxldGVzIGFueSBIVE1MIHZpZGVvIGVsZW1lbnQgYXNzb2NpYXRlZCB0byBlYWNoIFN1YnNjcmliZXIgKG9ubHkgdGhvc2UgW2NyZWF0ZWQgYnkgT3BlblZpZHUgQnJvd3Nlcl0oL2RvY3MvaG93LWRvLWkvbWFuYWdlLXZpZGVvcy8jbGV0LW9wZW52aWR1LXRha2UtY2FyZS1vZi10aGUtdmlkZW8tcGxheWVycykpLlxuICAgICAqIEZvciBldmVyeSB2aWRlbyByZW1vdmVkLCBlYWNoIFN1YnNjcmliZXIgb2JqZWN0IHdpbGwgZGlzcGF0Y2ggYSBgdmlkZW9FbGVtZW50RGVzdHJveWVkYCBldmVudC5cbiAgICAgKiBDYWxsIGBldmVudC5wcmV2ZW50RGVmYXVsdCgpYCB1cG9uIGV2ZW50IGBzZXNzaW9uRGlzY29ubmVjdGVkYCB0byBhdm9pZCB0aGlzIGJlaGF2aW9yIGFuZCB0YWtlIGNhcmUgb2YgZGlzcG9zaW5nIGFuZCBjbGVhbmluZyBhbGwgdGhlIFN1YnNjcmliZXIgb2JqZWN0cyB5b3Vyc2VsZi5cbiAgICAgKiBTZWUgW1tTZXNzaW9uRGlzY29ubmVjdGVkRXZlbnRdXSBhbmQgW1tWaWRlb0VsZW1lbnRFdmVudF1dIHRvIGxlYXJuIG1vcmUgdG8gbGVhcm4gbW9yZS5cbiAgICAgKlxuICAgICAqIFRoZSBbW1B1Ymxpc2hlcl1dIG9iamVjdCBvZiB0aGUgbG9jYWwgcGFydGljaXBhbnQgd2lsbCBkaXNwYXRjaCBhIGBzdHJlYW1EZXN0cm95ZWRgIGV2ZW50IGlmIHRoZXJlIGlzIGEgW1tQdWJsaXNoZXJdXSBvYmplY3QgcHVibGlzaGluZyB0byB0aGUgc2Vzc2lvbi5cbiAgICAgKiBUaGlzIGV2ZW50IHdpbGwgYXV0b21hdGljYWxseSBzdG9wIGFsbCBtZWRpYSB0cmFja3MgYW5kIGRlbGV0ZSBhbnkgSFRNTCB2aWRlbyBlbGVtZW50IGFzc29jaWF0ZWQgdG8gaXQgKG9ubHkgdGhvc2UgW2NyZWF0ZWQgYnkgT3BlblZpZHUgQnJvd3Nlcl0oL2RvY3MvaG93LWRvLWkvbWFuYWdlLXZpZGVvcy8jbGV0LW9wZW52aWR1LXRha2UtY2FyZS1vZi10aGUtdmlkZW8tcGxheWVycykpLlxuICAgICAqIEZvciBldmVyeSB2aWRlbyByZW1vdmVkLCB0aGUgUHVibGlzaGVyIG9iamVjdCB3aWxsIGRpc3BhdGNoIGEgYHZpZGVvRWxlbWVudERlc3Ryb3llZGAgZXZlbnQuXG4gICAgICogQ2FsbCBgZXZlbnQucHJldmVudERlZmF1bHQoKWAgdXBvbiBldmVudCBgc3RyZWFtRGVzdHJveWVkYCBpZiB5b3Ugd2FudCB0byBjbGVhbiB0aGUgUHVibGlzaGVyIG9iamVjdCBvbiB5b3VyIG93biBvciByZS1wdWJsaXNoIGl0IGluIGEgZGlmZmVyZW50IFNlc3Npb24gKHRvIGRvIHNvIGl0IGlzIGEgbWFuZGF0b3J5IHJlcXVpcmVtZW50IHRvIGNhbGwgYFNlc3Npb24udW5wdWJsaXNoKClgXG4gICAgICogb3IvYW5kIGBTZXNzaW9uLmRpc2Nvbm5lY3QoKWAgaW4gdGhlIHByZXZpb3VzIHNlc3Npb24pLiBTZWUgW1tTdHJlYW1FdmVudF1dIGFuZCBbW1ZpZGVvRWxlbWVudEV2ZW50XV0gdG8gbGVhcm4gbW9yZS5cbiAgICAgKlxuICAgICAqIFRoZSBbW1Nlc3Npb25dXSBvYmplY3Qgb2YgZXZlcnkgb3RoZXIgcGFydGljaXBhbnQgY29ubmVjdGVkIHRvIHRoZSBzZXNzaW9uIHdpbGwgZGlzcGF0Y2ggYSBgc3RyZWFtRGVzdHJveWVkYCBldmVudCBpZiB0aGUgZGlzY29ubmVjdGVkIHBhcnRpY2lwYW50IHdhcyBwdWJsaXNoaW5nLlxuICAgICAqIFRoaXMgZXZlbnQgd2lsbCBhdXRvbWF0aWNhbGx5IHVuc3Vic2NyaWJlIHRoZSBTdWJzY3JpYmVyIG9iamVjdCBmcm9tIHRoZSBzZXNzaW9uICh0aGlzIGluY2x1ZGVzIGNsb3NpbmcgdGhlIFdlYlJUQ1BlZXIgY29ubmVjdGlvbiBhbmQgZGlzcG9zaW5nIGFsbCBNZWRpYVN0cmVhbVRyYWNrcylcbiAgICAgKiBhbmQgYWxzbyBkZWxldGVzIGFueSBIVE1MIHZpZGVvIGVsZW1lbnQgYXNzb2NpYXRlZCB0byB0aGF0IFN1YnNjcmliZXIgKG9ubHkgdGhvc2UgW2NyZWF0ZWQgYnkgT3BlblZpZHUgQnJvd3Nlcl0oL2RvY3MvaG93LWRvLWkvbWFuYWdlLXZpZGVvcy8jbGV0LW9wZW52aWR1LXRha2UtY2FyZS1vZi10aGUtdmlkZW8tcGxheWVycykpLlxuICAgICAqIEZvciBldmVyeSB2aWRlbyByZW1vdmVkLCB0aGUgU3Vic2NyaWJlciBvYmplY3Qgd2lsbCBkaXNwYXRjaCBhIGB2aWRlb0VsZW1lbnREZXN0cm95ZWRgIGV2ZW50LlxuICAgICAqIENhbGwgYGV2ZW50LnByZXZlbnREZWZhdWx0KClgIHVwb24gZXZlbnQgYHN0cmVhbURlc3Ryb3llZGAgdG8gYXZvaWQgdGhpcyBkZWZhdWx0IGJlaGF2aW9yIGFuZCB0YWtlIGNhcmUgb2YgZGlzcG9zaW5nIGFuZCBjbGVhbmluZyB0aGUgU3Vic2NyaWJlciBvYmplY3QgeW91cnNlbGYuXG4gICAgICogU2VlIFtbU3RyZWFtRXZlbnRdXSBhbmQgW1tWaWRlb0VsZW1lbnRFdmVudF1dIHRvIGxlYXJuIG1vcmUuXG4gICAgICpcbiAgICAgKiBUaGUgW1tTZXNzaW9uXV0gb2JqZWN0IG9mIGV2ZXJ5IG90aGVyIHBhcnRpY2lwYW50IGNvbm5lY3RlZCB0byB0aGUgc2Vzc2lvbiB3aWxsIGRpc3BhdGNoIGEgYGNvbm5lY3Rpb25EZXN0cm95ZWRgIGV2ZW50IGluIGFueSBjYXNlLiBTZWUgW1tDb25uZWN0aW9uRXZlbnRdXSB0byBsZWFybiBtb3JlLlxuICAgICAqL1xuICAgIGRpc2Nvbm5lY3QoKTogdm9pZCB7XG4gICAgICAgIHRoaXMubGVhdmUoZmFsc2UsICdkaXNjb25uZWN0Jyk7XG4gICAgfVxuXG4gICAgc3Vic2NyaWJlKHN0cmVhbTogU3RyZWFtLCB0YXJnZXRFbGVtZW50OiBzdHJpbmcgfCBIVE1MRWxlbWVudCk6IFN1YnNjcmliZXI7XG4gICAgc3Vic2NyaWJlKHN0cmVhbTogU3RyZWFtLCB0YXJnZXRFbGVtZW50OiBzdHJpbmcgfCBIVE1MRWxlbWVudCwgcHJvcGVydGllczogU3Vic2NyaWJlclByb3BlcnRpZXMpOiBTdWJzY3JpYmVyO1xuICAgIHN1YnNjcmliZShzdHJlYW06IFN0cmVhbSwgdGFyZ2V0RWxlbWVudDogc3RyaW5nIHwgSFRNTEVsZW1lbnQsIGNvbXBsZXRpb25IYW5kbGVyOiAoZXJyb3I6IEVycm9yIHwgdW5kZWZpbmVkKSA9PiB2b2lkKTogU3Vic2NyaWJlcjtcbiAgICBzdWJzY3JpYmUoc3RyZWFtOiBTdHJlYW0sIHRhcmdldEVsZW1lbnQ6IHN0cmluZyB8IEhUTUxFbGVtZW50LCBwcm9wZXJ0aWVzOiBTdWJzY3JpYmVyUHJvcGVydGllcywgY29tcGxldGlvbkhhbmRsZXI6IChlcnJvcjogRXJyb3IgfCB1bmRlZmluZWQpID0+IHZvaWQpOiBTdWJzY3JpYmVyO1xuXG4gICAgLyoqXG4gICAgICogU3Vic2NyaWJlcyB0byBhIGBzdHJlYW1gLCBhZGRpbmcgYSBuZXcgSFRNTCB2aWRlbyBlbGVtZW50IHRvIERPTSB3aXRoIGBzdWJzY3JpYmVyUHJvcGVydGllc2Agc2V0dGluZ3MuIFRoaXMgbWV0aG9kIGlzIHVzdWFsbHkgY2FsbGVkIGluIHRoZSBjYWxsYmFjayBvZiBgc3RyZWFtQ3JlYXRlZGAgZXZlbnQuXG4gICAgICpcbiAgICAgKiAjIyMjIEV2ZW50cyBkaXNwYXRjaGVkXG4gICAgICpcbiAgICAgKiBUaGUgW1tTdWJzY3JpYmVyXV0gb2JqZWN0IHdpbGwgZGlzcGF0Y2ggYSBgdmlkZW9FbGVtZW50Q3JlYXRlZGAgZXZlbnQgb25jZSB0aGUgSFRNTCB2aWRlbyBlbGVtZW50IGhhcyBiZWVuIGFkZGVkIHRvIERPTSAob25seSBpZiB5b3VcbiAgICAgKiBbbGV0IE9wZW5WaWR1IHRha2UgY2FyZSBvZiB0aGUgdmlkZW8gcGxheWVyc10oL2RvY3MvaG93LWRvLWkvbWFuYWdlLXZpZGVvcy8jbGV0LW9wZW52aWR1LXRha2UtY2FyZS1vZi10aGUtdmlkZW8tcGxheWVycykpLiBTZWUgW1tWaWRlb0VsZW1lbnRFdmVudF1dIHRvIGxlYXJuIG1vcmUuXG4gICAgICpcbiAgICAgKiBUaGUgW1tTdWJzY3JpYmVyXV0gb2JqZWN0IHdpbGwgZGlzcGF0Y2ggYSBgc3RyZWFtUGxheWluZ2AgZXZlbnQgb25jZSB0aGUgcmVtb3RlIHN0cmVhbSBzdGFydHMgcGxheWluZy4gU2VlIFtbU3RyZWFtTWFuYWdlckV2ZW50XV0gdG8gbGVhcm4gbW9yZS5cbiAgICAgKlxuICAgICAqIEBwYXJhbSBzdHJlYW0gU3RyZWFtIG9iamVjdCB0byBzdWJzY3JpYmUgdG9cbiAgICAgKiBAcGFyYW0gdGFyZ2V0RWxlbWVudCBIVE1MIERPTSBlbGVtZW50IChvciBpdHMgYGlkYCBhdHRyaWJ1dGUpIGluIHdoaWNoIHRoZSB2aWRlbyBlbGVtZW50IG9mIHRoZSBTdWJzY3JpYmVyIHdpbGwgYmUgaW5zZXJ0ZWQgKHNlZSBbW1N1YnNjcmliZXJQcm9wZXJ0aWVzLmluc2VydE1vZGVdXSkuIElmICpudWxsKiBvciAqdW5kZWZpbmVkKiBubyBkZWZhdWx0IHZpZGVvIHdpbGwgYmUgY3JlYXRlZCBmb3IgdGhpcyBTdWJzY3JpYmVyLlxuICAgICAqIFlvdSBjYW4gYWx3YXlzIGNhbGwgbWV0aG9kIFtbU3Vic2NyaWJlci5hZGRWaWRlb0VsZW1lbnRdXSBvciBbW1N1YnNjcmliZXIuY3JlYXRlVmlkZW9FbGVtZW50XV0gdG8gbWFuYWdlIHRoZSB2aWRlbyBlbGVtZW50cyBvbiB5b3VyIG93biAoc2VlIFtNYW5hZ2UgdmlkZW8gcGxheWVyc10oL2RvY3MvaG93LWRvLWkvbWFuYWdlLXZpZGVvcykgc2VjdGlvbilcbiAgICAgKiBAcGFyYW0gY29tcGxldGlvbkhhbmRsZXIgYGVycm9yYCBwYXJhbWV0ZXIgaXMgbnVsbCBpZiBgc3Vic2NyaWJlYCBzdWNjZWVkcywgYW5kIGlzIGRlZmluZWQgaWYgaXQgZmFpbHMuXG4gICAgICovXG4gICAgc3Vic2NyaWJlKHN0cmVhbTogU3RyZWFtLCB0YXJnZXRFbGVtZW50OiBzdHJpbmcgfCBIVE1MRWxlbWVudCwgcGFyYW0zPzogKChlcnJvcjogRXJyb3IgfCB1bmRlZmluZWQpID0+IHZvaWQpIHwgU3Vic2NyaWJlclByb3BlcnRpZXMsIHBhcmFtND86ICgoZXJyb3I6IEVycm9yIHwgdW5kZWZpbmVkKSA9PiB2b2lkKSk6IFN1YnNjcmliZXIge1xuICAgICAgICBsZXQgcHJvcGVydGllczogU3Vic2NyaWJlclByb3BlcnRpZXMgPSB7fTtcbiAgICAgICAgaWYgKCEhcGFyYW0zICYmIHR5cGVvZiBwYXJhbTMgIT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgIHByb3BlcnRpZXMgPSB7XG4gICAgICAgICAgICAgICAgaW5zZXJ0TW9kZTogKHR5cGVvZiBwYXJhbTMuaW5zZXJ0TW9kZSAhPT0gJ3VuZGVmaW5lZCcpID8gKCh0eXBlb2YgcGFyYW0zLmluc2VydE1vZGUgPT09ICdzdHJpbmcnKSA/IFZpZGVvSW5zZXJ0TW9kZVtwYXJhbTMuaW5zZXJ0TW9kZV0gOiBwcm9wZXJ0aWVzLmluc2VydE1vZGUpIDogVmlkZW9JbnNlcnRNb2RlLkFQUEVORCxcbiAgICAgICAgICAgICAgICBzdWJzY3JpYmVUb0F1ZGlvOiAodHlwZW9mIHBhcmFtMy5zdWJzY3JpYmVUb0F1ZGlvICE9PSAndW5kZWZpbmVkJykgPyBwYXJhbTMuc3Vic2NyaWJlVG9BdWRpbyA6IHRydWUsXG4gICAgICAgICAgICAgICAgc3Vic2NyaWJlVG9WaWRlbzogKHR5cGVvZiBwYXJhbTMuc3Vic2NyaWJlVG9WaWRlbyAhPT0gJ3VuZGVmaW5lZCcpID8gcGFyYW0zLnN1YnNjcmliZVRvVmlkZW8gOiB0cnVlXG4gICAgICAgICAgICB9O1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcHJvcGVydGllcyA9IHtcbiAgICAgICAgICAgICAgICBpbnNlcnRNb2RlOiBWaWRlb0luc2VydE1vZGUuQVBQRU5ELFxuICAgICAgICAgICAgICAgIHN1YnNjcmliZVRvQXVkaW86IHRydWUsXG4gICAgICAgICAgICAgICAgc3Vic2NyaWJlVG9WaWRlbzogdHJ1ZVxuICAgICAgICAgICAgfTtcbiAgICAgICAgfVxuXG4gICAgICAgIGxldCBjb21wbGV0aW9uSGFuZGxlcjogKGVycm9yOiBFcnJvciB8IHVuZGVmaW5lZCkgPT4gdm9pZDtcbiAgICAgICAgaWYgKCEhcGFyYW0zICYmICh0eXBlb2YgcGFyYW0zID09PSAnZnVuY3Rpb24nKSkge1xuICAgICAgICAgICAgY29tcGxldGlvbkhhbmRsZXIgPSBwYXJhbTM7XG4gICAgICAgIH0gZWxzZSBpZiAoISFwYXJhbTQpIHtcbiAgICAgICAgICAgIGNvbXBsZXRpb25IYW5kbGVyID0gcGFyYW00O1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc29sZS5pbmZvKCdTdWJzY3JpYmluZyB0byAnICsgc3RyZWFtLmNvbm5lY3Rpb24uY29ubmVjdGlvbklkKTtcblxuICAgICAgICBzdHJlYW0uc3Vic2NyaWJlKClcbiAgICAgICAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oJ1N1YnNjcmliZWQgY29ycmVjdGx5IHRvICcgKyBzdHJlYW0uY29ubmVjdGlvbi5jb25uZWN0aW9uSWQpO1xuICAgICAgICAgICAgICAgIGlmIChjb21wbGV0aW9uSGFuZGxlciAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbXBsZXRpb25IYW5kbGVyKHVuZGVmaW5lZCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKGNvbXBsZXRpb25IYW5kbGVyICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgY29tcGxldGlvbkhhbmRsZXIoZXJyb3IpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICBjb25zdCBzdWJzY3JpYmVyID0gbmV3IFN1YnNjcmliZXIoc3RyZWFtLCB0YXJnZXRFbGVtZW50LCBwcm9wZXJ0aWVzKTtcbiAgICAgICAgaWYgKCEhc3Vic2NyaWJlci50YXJnZXRFbGVtZW50KSB7XG4gICAgICAgICAgICBzdHJlYW0uc3RyZWFtTWFuYWdlci5jcmVhdGVWaWRlb0VsZW1lbnQoc3Vic2NyaWJlci50YXJnZXRFbGVtZW50LCA8VmlkZW9JbnNlcnRNb2RlPnByb3BlcnRpZXMuaW5zZXJ0TW9kZSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHN1YnNjcmliZXI7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBQcm9taXNpZmllZCB2ZXJzaW9uIG9mIFtbU2Vzc2lvbi5zdWJzY3JpYmVdXVxuICAgICAqL1xuICAgIHN1YnNjcmliZUFzeW5jKHN0cmVhbTogU3RyZWFtLCB0YXJnZXRFbGVtZW50OiBzdHJpbmcgfCBIVE1MRWxlbWVudCk6IFByb21pc2U8U3Vic2NyaWJlcj47XG4gICAgc3Vic2NyaWJlQXN5bmMoc3RyZWFtOiBTdHJlYW0sIHRhcmdldEVsZW1lbnQ6IHN0cmluZyB8IEhUTUxFbGVtZW50LCBwcm9wZXJ0aWVzOiBTdWJzY3JpYmVyUHJvcGVydGllcyk6IFByb21pc2U8U3Vic2NyaWJlcj47XG5cbiAgICBzdWJzY3JpYmVBc3luYyhzdHJlYW06IFN0cmVhbSwgdGFyZ2V0RWxlbWVudDogc3RyaW5nIHwgSFRNTEVsZW1lbnQsIHByb3BlcnRpZXM/OiBTdWJzY3JpYmVyUHJvcGVydGllcyk6IFByb21pc2U8U3Vic2NyaWJlcj4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2U8U3Vic2NyaWJlcj4oKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuXG4gICAgICAgICAgICBsZXQgc3Vic2NyaWJlcjogU3Vic2NyaWJlcjtcblxuICAgICAgICAgICAgY29uc3QgY2FsbGJhY2sgPSAoZXJyb3I6IEVycm9yKSA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKCEhZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICByZXNvbHZlKHN1YnNjcmliZXIpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIGlmICghIXByb3BlcnRpZXMpIHtcbiAgICAgICAgICAgICAgICBzdWJzY3JpYmVyID0gdGhpcy5zdWJzY3JpYmUoc3RyZWFtLCB0YXJnZXRFbGVtZW50LCBwcm9wZXJ0aWVzLCBjYWxsYmFjayk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHN1YnNjcmliZXIgPSB0aGlzLnN1YnNjcmliZShzdHJlYW0sIHRhcmdldEVsZW1lbnQsIGNhbGxiYWNrKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICB9KTtcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFVuc3Vic2NyaWJlcyBmcm9tIGBzdWJzY3JpYmVyYCwgYXV0b21hdGljYWxseSByZW1vdmluZyBpdHMgYXNzb2NpYXRlZCBIVE1MIHZpZGVvIGVsZW1lbnRzLlxuICAgICAqXG4gICAgICogIyMjIyBFdmVudHMgZGlzcGF0Y2hlZFxuICAgICAqXG4gICAgICogVGhlIFtbU3Vic2NyaWJlcl1dIG9iamVjdCB3aWxsIGRpc3BhdGNoIGEgYHZpZGVvRWxlbWVudERlc3Ryb3llZGAgZXZlbnQgZm9yIGVhY2ggdmlkZW8gYXNzb2NpYXRlZCB0byBpdCB0aGF0IHdhcyByZW1vdmVkIGZyb20gRE9NLlxuICAgICAqIE9ubHkgdmlkZW9zIFtjcmVhdGVkIGJ5IE9wZW5WaWR1IEJyb3dzZXJdKC9kb2NzL2hvdy1kby1pL21hbmFnZS12aWRlb3MvI2xldC1vcGVudmlkdS10YWtlLWNhcmUtb2YtdGhlLXZpZGVvLXBsYXllcnMpKSB3aWxsIGJlIGF1dG9tYXRpY2FsbHkgcmVtb3ZlZFxuICAgICAqXG4gICAgICogU2VlIFtbVmlkZW9FbGVtZW50RXZlbnRdXSB0byBsZWFybiBtb3JlXG4gICAgICovXG4gICAgdW5zdWJzY3JpYmUoc3Vic2NyaWJlcjogU3Vic2NyaWJlcik6IHZvaWQge1xuICAgICAgICBjb25zdCBjb25uZWN0aW9uSWQgPSBzdWJzY3JpYmVyLnN0cmVhbS5jb25uZWN0aW9uLmNvbm5lY3Rpb25JZDtcblxuICAgICAgICBjb25zb2xlLmluZm8oJ1Vuc3Vic2NyaWJpbmcgZnJvbSAnICsgY29ubmVjdGlvbklkKTtcblxuICAgICAgICB0aGlzLm9wZW52aWR1LnNlbmRSZXF1ZXN0KFxuICAgICAgICAgICAgJ3Vuc3Vic2NyaWJlRnJvbVZpZGVvJyxcbiAgICAgICAgICAgIHsgc2VuZGVyOiBzdWJzY3JpYmVyLnN0cmVhbS5jb25uZWN0aW9uLmNvbm5lY3Rpb25JZCB9LFxuICAgICAgICAgICAgKGVycm9yLCByZXNwb25zZSkgPT4ge1xuICAgICAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKCdFcnJvciB1bnN1YnNjcmliaW5nIGZyb20gJyArIGNvbm5lY3Rpb25JZCwgZXJyb3IpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbygnVW5zdWJzY3JpYmVkIGNvcnJlY3RseSBmcm9tICcgKyBjb25uZWN0aW9uSWQpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBzdWJzY3JpYmVyLnN0cmVhbS5kaXNwb3NlV2ViUnRjUGVlcigpO1xuICAgICAgICAgICAgICAgIHN1YnNjcmliZXIuc3RyZWFtLmRpc3Bvc2VNZWRpYVN0cmVhbSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICApO1xuICAgICAgICBzdWJzY3JpYmVyLnN0cmVhbS5zdHJlYW1NYW5hZ2VyLnJlbW92ZUFsbFZpZGVvcygpO1xuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogUHVibGlzaGVzIHRvIHRoZSBTZXNzaW9uIHRoZSBQdWJsaXNoZXIgb2JqZWN0XG4gICAgICpcbiAgICAgKiAjIyMjIEV2ZW50cyBkaXNwYXRjaGVkXG4gICAgICpcbiAgICAgKiBUaGUgbG9jYWwgW1tQdWJsaXNoZXJdXSBvYmplY3Qgd2lsbCBkaXNwYXRjaCBhIGBzdHJlYW1DcmVhdGVkYCBldmVudCB1cG9uIHN1Y2Nlc3NmdWwgdGVybWluYXRpb24gb2YgdGhpcyBtZXRob2QuIFNlZSBbW1N0cmVhbUV2ZW50XV0gdG8gbGVhcm4gbW9yZS5cbiAgICAgKlxuICAgICAqIFRoZSBsb2NhbCBbW1B1Ymxpc2hlcl1dIG9iamVjdCB3aWxsIGRpc3BhdGNoIGEgYHN0cmVhbVBsYXlpbmdgIG9uY2UgdGhlIG1lZGlhIHN0cmVhbSBzdGFydHMgcGxheWluZy4gU2VlIFtbU3RyZWFtTWFuYWdlckV2ZW50XV0gdG8gbGVhcm4gbW9yZS5cbiAgICAgKlxuICAgICAqIFRoZSBbW1Nlc3Npb25dXSBvYmplY3Qgb2YgZXZlcnkgb3RoZXIgcGFydGljaXBhbnQgY29ubmVjdGVkIHRvIHRoZSBzZXNzaW9uIHdpbGwgZGlzcGF0Y2ggYSBgc3RyZWFtQ3JlYXRlZGAgZXZlbnQgc28gdGhleSBjYW4gc3Vic2NyaWJlIHRvIGl0LiBTZWUgW1tTdHJlYW1FdmVudF1dIHRvIGxlYXJuIG1vcmUuXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyBBIFByb21pc2UgKHRvIHdoaWNoIHlvdSBjYW4gb3B0aW9uYWxseSBzdWJzY3JpYmUgdG8pIHRoYXQgaXMgcmVzb2x2ZWQgb25seSBhZnRlciB0aGUgcHVibGlzaGVyIHdhcyBzdWNjZXNzZnVsbHkgcHVibGlzaGVkIGFuZCByZWplY3RlZCB3aXRoIGFuIEVycm9yIG9iamVjdCBpZiBub3RcbiAgICAgKi9cbiAgICBwdWJsaXNoKHB1Ymxpc2hlcjogUHVibGlzaGVyKTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIHB1Ymxpc2hlci5zZXNzaW9uID0gdGhpcztcbiAgICAgICAgICAgIHB1Ymxpc2hlci5zdHJlYW0uc2Vzc2lvbiA9IHRoaXM7XG5cbiAgICAgICAgICAgIGlmICghcHVibGlzaGVyLnN0cmVhbS5wdWJsaXNoZWRPbmNlKSB7XG4gICAgICAgICAgICAgICAgLy8gJ1Nlc3Npb24udW5wdWJsaXNoKFB1Ymxpc2hlciknIGhhcyBOT1QgYmVlbiBjYWxsZWRcbiAgICAgICAgICAgICAgICB0aGlzLmNvbm5lY3Rpb24uYWRkU3RyZWFtKHB1Ymxpc2hlci5zdHJlYW0pO1xuICAgICAgICAgICAgICAgIHB1Ymxpc2hlci5zdHJlYW0ucHVibGlzaCgpXG4gICAgICAgICAgICAgICAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAvLyAnU2Vzc2lvbi51bnB1Ymxpc2goUHVibGlzaGVyKScgaGFzIGJlZW4gY2FsbGVkLiBNdXN0IGluaXRpYWxpemUgYWdhaW4gUHVibGlzaGVyXG4gICAgICAgICAgICAgICAgcHVibGlzaGVyLmluaXRpYWxpemUoKVxuICAgICAgICAgICAgICAgICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbm5lY3Rpb24uYWRkU3RyZWFtKHB1Ymxpc2hlci5zdHJlYW0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgcHVibGlzaGVyLnJlZXN0YWJsaXNoU3RyZWFtUGxheWluZ0V2ZW50KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBwdWJsaXNoZXIuc3RyZWFtLnB1Ymxpc2goKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgfSkuY2F0Y2goKGVycm9yKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBVbnB1Ymxpc2hlcyBmcm9tIHRoZSBTZXNzaW9uIHRoZSBQdWJsaXNoZXIgb2JqZWN0LlxuICAgICAqXG4gICAgICogIyMjIyBFdmVudHMgZGlzcGF0Y2hlZFxuICAgICAqXG4gICAgICogVGhlIFtbUHVibGlzaGVyXV0gb2JqZWN0IG9mIHRoZSBsb2NhbCBwYXJ0aWNpcGFudCB3aWxsIGRpc3BhdGNoIGEgYHN0cmVhbURlc3Ryb3llZGAgZXZlbnQuXG4gICAgICogVGhpcyBldmVudCB3aWxsIGF1dG9tYXRpY2FsbHkgc3RvcCBhbGwgbWVkaWEgdHJhY2tzIGFuZCBkZWxldGUgYW55IEhUTUwgdmlkZW8gZWxlbWVudCBhc3NvY2lhdGVkIHRvIHRoaXMgUHVibGlzaGVyXG4gICAgICogKG9ubHkgdGhvc2UgdmlkZW9zIFtjcmVhdGVkIGJ5IE9wZW5WaWR1IEJyb3dzZXJdKC9kb2NzL2hvdy1kby1pL21hbmFnZS12aWRlb3MvI2xldC1vcGVudmlkdS10YWtlLWNhcmUtb2YtdGhlLXZpZGVvLXBsYXllcnMpKS5cbiAgICAgKiBGb3IgZXZlcnkgdmlkZW8gcmVtb3ZlZCwgdGhlIFB1Ymxpc2hlciBvYmplY3Qgd2lsbCBkaXNwYXRjaCBhIGB2aWRlb0VsZW1lbnREZXN0cm95ZWRgIGV2ZW50LlxuICAgICAqIENhbGwgYGV2ZW50LnByZXZlbnREZWZhdWx0KClgIHVwb24gZXZlbnQgYHN0cmVhbURlc3Ryb3llZGAgaWYgeW91IHdhbnQgdG8gY2xlYW4gdGhlIFB1Ymxpc2hlciBvYmplY3Qgb24geW91ciBvd24gb3IgcmUtcHVibGlzaCBpdCBpbiBhIGRpZmZlcmVudCBTZXNzaW9uLlxuICAgICAqXG4gICAgICogVGhlIFtbU2Vzc2lvbl1dIG9iamVjdCBvZiBldmVyeSBvdGhlciBwYXJ0aWNpcGFudCBjb25uZWN0ZWQgdG8gdGhlIHNlc3Npb24gd2lsbCBkaXNwYXRjaCBhIGBzdHJlYW1EZXN0cm95ZWRgIGV2ZW50LlxuICAgICAqIFRoaXMgZXZlbnQgd2lsbCBhdXRvbWF0aWNhbGx5IHVuc3Vic2NyaWJlIHRoZSBTdWJzY3JpYmVyIG9iamVjdCBmcm9tIHRoZSBzZXNzaW9uICh0aGlzIGluY2x1ZGVzIGNsb3NpbmcgdGhlIFdlYlJUQ1BlZXIgY29ubmVjdGlvbiBhbmQgZGlzcG9zaW5nIGFsbCBNZWRpYVN0cmVhbVRyYWNrcykgYW5kXG4gICAgICogZGVsZXRlIGFueSBIVE1MIHZpZGVvIGVsZW1lbnQgYXNzb2NpYXRlZCB0byBpdCAob25seSB0aG9zZSBbY3JlYXRlZCBieSBPcGVuVmlkdSBCcm93c2VyXSgvZG9jcy9ob3ctZG8taS9tYW5hZ2UtdmlkZW9zLyNsZXQtb3BlbnZpZHUtdGFrZS1jYXJlLW9mLXRoZS12aWRlby1wbGF5ZXJzKSkuXG4gICAgICogRm9yIGV2ZXJ5IHZpZGVvIHJlbW92ZWQsIHRoZSBTdWJzY3JpYmVyIG9iamVjdCB3aWxsIGRpc3BhdGNoIGEgYHZpZGVvRWxlbWVudERlc3Ryb3llZGAgZXZlbnQuXG4gICAgICogQ2FsbCBgZXZlbnQucHJldmVudERlZmF1bHQoKWAgdXBvbiBldmVudCBgc3RyZWFtRGVzdHJveWVkYCB0byBhdm9pZCB0aGlzIGRlZmF1bHQgYmVoYXZpb3IgYW5kIHRha2UgY2FyZSBvZiBkaXNwb3NpbmcgYW5kIGNsZWFuaW5nIHRoZSBTdWJzY3JpYmVyIG9iamVjdCBvbiB5b3VyIG93bi5cbiAgICAgKlxuICAgICAqIFNlZSBbW1N0cmVhbUV2ZW50XV0gYW5kIFtbVmlkZW9FbGVtZW50RXZlbnRdXSB0byBsZWFybiBtb3JlLlxuICAgICAqL1xuICAgIHVucHVibGlzaChwdWJsaXNoZXI6IFB1Ymxpc2hlcik6IHZvaWQge1xuXG4gICAgICAgIGNvbnN0IHN0cmVhbSA9IHB1Ymxpc2hlci5zdHJlYW07XG5cbiAgICAgICAgaWYgKCFzdHJlYW0uY29ubmVjdGlvbikge1xuICAgICAgICAgICAgY29uc29sZS5lcnJvcignVGhlIGFzc29jaWF0ZWQgQ29ubmVjdGlvbiBvYmplY3Qgb2YgdGhpcyBQdWJsaXNoZXIgaXMgbnVsbCcsIHN0cmVhbSk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH0gZWxzZSBpZiAoc3RyZWFtLmNvbm5lY3Rpb24gIT09IHRoaXMuY29ubmVjdGlvbikge1xuICAgICAgICAgICAgY29uc29sZS5lcnJvcignVGhlIGFzc29jaWF0ZWQgQ29ubmVjdGlvbiBvYmplY3Qgb2YgdGhpcyBQdWJsaXNoZXIgaXMgbm90IHlvdXIgbG9jYWwgQ29ubmVjdGlvbi4nICtcbiAgICAgICAgICAgICAgICBcIk9ubHkgbW9kZXJhdG9ycyBjYW4gZm9yY2UgdW5wdWJsaXNoIG9uIHJlbW90ZSBTdHJlYW1zIHZpYSAnZm9yY2VVbnB1Ymxpc2gnIG1ldGhvZFwiLCBzdHJlYW0pO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9IGVsc2Uge1xuXG4gICAgICAgICAgICBjb25zb2xlLmluZm8oJ1VucHVibGlzaGluZyBsb2NhbCBtZWRpYSAoJyArIHN0cmVhbS5jb25uZWN0aW9uLmNvbm5lY3Rpb25JZCArICcpJyk7XG5cbiAgICAgICAgICAgIHRoaXMub3BlbnZpZHUuc2VuZFJlcXVlc3QoJ3VucHVibGlzaFZpZGVvJywgKGVycm9yLCByZXNwb25zZSkgPT4ge1xuICAgICAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKGVycm9yKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oJ01lZGlhIHVucHVibGlzaGVkIGNvcnJlY3RseScpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICBzdHJlYW0uZGlzcG9zZVdlYlJ0Y1BlZXIoKTtcbiAgICAgICAgICAgIGRlbGV0ZSBzdHJlYW0uY29ubmVjdGlvbi5zdHJlYW07XG5cbiAgICAgICAgICAgIGNvbnN0IHN0cmVhbUV2ZW50ID0gbmV3IFN0cmVhbUV2ZW50KHRydWUsIHB1Ymxpc2hlciwgJ3N0cmVhbURlc3Ryb3llZCcsIHB1Ymxpc2hlci5zdHJlYW0sICd1bnB1Ymxpc2gnKTtcbiAgICAgICAgICAgIHB1Ymxpc2hlci5lbWl0RXZlbnQoJ3N0cmVhbURlc3Ryb3llZCcsIFtzdHJlYW1FdmVudF0pO1xuICAgICAgICAgICAgc3RyZWFtRXZlbnQuY2FsbERlZmF1bHRCZWhhdmlvcigpO1xuICAgICAgICB9XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBGb3JjZXMgc29tZSB1c2VyIHRvIGxlYXZlIHRoZSBzZXNzaW9uXG4gICAgICpcbiAgICAgKiAjIyMjIEV2ZW50cyBkaXNwYXRjaGVkXG4gICAgICpcbiAgICAgKiBUaGUgYmVoYXZpb3IgaXMgdGhlIHNhbWUgYXMgd2hlbiBzb21lIHVzZXIgY2FsbHMgW1tTZXNzaW9uLmRpc2Nvbm5lY3RdXSwgYnV0IGByZWFzb25gIHByb3BlcnR5IGluIGFsbCBldmVudHMgd2lsbCBiZSBgXCJmb3JjZURpc2Nvbm5lY3RCeVVzZXJcImAuXG4gICAgICpcbiAgICAgKiBUaGUgW1tTZXNzaW9uXV0gb2JqZWN0IG9mIGV2ZXJ5IHBhcnRpY2lwYW50IHdpbGwgZGlzcGF0Y2ggYSBgc3RyZWFtRGVzdHJveWVkYCBldmVudCBpZiB0aGUgZXZpY3RlZCB1c2VyIHdhcyBwdWJsaXNoaW5nIGEgc3RyZWFtLCB3aXRoIHByb3BlcnR5IGByZWFzb25gIHNldCB0byBgXCJmb3JjZURpc2Nvbm5lY3RCeVVzZXJcImAuXG4gICAgICogVGhlIFtbU2Vzc2lvbl1dIG9iamVjdCBvZiBldmVyeSBwYXJ0aWNpcGFudCBleGNlcHQgdGhlIGV2aWN0ZWQgb25lIHdpbGwgZGlzcGF0Y2ggYSBgY29ubmVjdGlvbkRlc3Ryb3llZGAgZXZlbnQgZm9yIHRoZSBldmljdGVkIHVzZXIsIHdpdGggcHJvcGVydHkgYHJlYXNvbmAgc2V0IHRvIGBcImZvcmNlRGlzY29ubmVjdEJ5VXNlclwiYC5cbiAgICAgKlxuICAgICAqIElmIGFueSwgdGhlIFtbUHVibGlzaGVyXV0gb2JqZWN0IG9mIHRoZSBldmljdGVkIHBhcnRpY2lwYW50IHdpbGwgYWxzbyBkaXNwYXRjaCBhIGBzdHJlYW1EZXN0cm95ZWRgIGV2ZW50IHdpdGggcHJvcGVydHkgYHJlYXNvbmAgc2V0IHRvIGBcImZvcmNlRGlzY29ubmVjdEJ5VXNlclwiYC5cbiAgICAgKiBUaGUgW1tTZXNzaW9uXV0gb2JqZWN0IG9mIHRoZSBldmljdGVkIHBhcnRpY2lwYW50IHdpbGwgZGlzcGF0Y2ggYSBgc2Vzc2lvbkRpc2Nvbm5lY3RlZGAgZXZlbnQgd2l0aCBwcm9wZXJ0eSBgcmVhc29uYCBzZXQgdG8gYFwiZm9yY2VEaXNjb25uZWN0QnlVc2VyXCJgLlxuICAgICAqXG4gICAgICogU2VlIFtbU3RyZWFtRXZlbnRdXSwgW1tDb25uZWN0aW9uRXZlbnRdXSBhbmQgW1tTZXNzaW9uRGlzY29ubmVjdGVkRXZlbnRdXSB0byBsZWFybiBtb3JlLlxuICAgICAqXG4gICAgICogQHJldHVybnMgQSBQcm9taXNlICh0byB3aGljaCB5b3UgY2FuIG9wdGlvbmFsbHkgc3Vic2NyaWJlIHRvKSB0aGF0IGlzIHJlc29sdmVkIG9ubHkgYWZ0ZXIgdGhlIHBhcnRpY2lwYW50IGhhcyBiZWVuIHN1Y2Nlc3NmdWxseSBldmljdGVkIGZyb20gdGhlIHNlc3Npb24gYW5kIHJlamVjdGVkIHdpdGggYW4gRXJyb3Igb2JqZWN0IGlmIG5vdFxuICAgICAqL1xuICAgIGZvcmNlRGlzY29ubmVjdChjb25uZWN0aW9uOiBDb25uZWN0aW9uKTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIGNvbnNvbGUuaW5mbygnRm9yY2luZyBkaXNjb25uZWN0IGZvciBjb25uZWN0aW9uICcgKyBjb25uZWN0aW9uLmNvbm5lY3Rpb25JZCk7XG4gICAgICAgICAgICB0aGlzLm9wZW52aWR1LnNlbmRSZXF1ZXN0KFxuICAgICAgICAgICAgICAgICdmb3JjZURpc2Nvbm5lY3QnLFxuICAgICAgICAgICAgICAgIHsgY29ubmVjdGlvbklkOiBjb25uZWN0aW9uLmNvbm5lY3Rpb25JZCB9LFxuICAgICAgICAgICAgICAgIChlcnJvciwgcmVzcG9uc2UpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKCdFcnJvciBmb3JjaW5nIGRpc2Nvbm5lY3QgZm9yIENvbm5lY3Rpb24gJyArIGNvbm5lY3Rpb24uY29ubmVjdGlvbklkLCBlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZXJyb3IuY29kZSA9PT0gNDAxKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KG5ldyBPcGVuVmlkdUVycm9yKE9wZW5WaWR1RXJyb3JOYW1lLk9QRU5WSURVX1BFUk1JU1NJT05fREVOSUVELCBcIllvdSBkb24ndCBoYXZlIHBlcm1pc3Npb25zIHRvIGZvcmNlIGEgZGlzY29ubmVjdGlvblwiKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oJ0ZvcmNpbmcgZGlzY29ubmVjdCBjb3JyZWN0bHkgZm9yIENvbm5lY3Rpb24gJyArIGNvbm5lY3Rpb24uY29ubmVjdGlvbklkKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogRm9yY2VzIHNvbWUgdXNlciB0byB1bnB1Ymxpc2ggYSBTdHJlYW1cbiAgICAgKlxuICAgICAqICMjIyMgRXZlbnRzIGRpc3BhdGNoZWRcbiAgICAgKlxuICAgICAqIFRoZSBiZWhhdmlvciBpcyB0aGUgc2FtZSBhcyB3aGVuIHNvbWUgdXNlciBjYWxscyBbW1Nlc3Npb24udW5wdWJsaXNoXV0sIGJ1dCBgcmVhc29uYCBwcm9wZXJ0eSBpbiBhbGwgZXZlbnRzIHdpbGwgYmUgYFwiZm9yY2VVbnB1Ymxpc2hCeVVzZXJcImBcbiAgICAgKlxuICAgICAqIFRoZSBbW1Nlc3Npb25dXSBvYmplY3Qgb2YgZXZlcnkgcGFydGljaXBhbnQgd2lsbCBkaXNwYXRjaCBhIGBzdHJlYW1EZXN0cm95ZWRgIGV2ZW50IHdpdGggcHJvcGVydHkgYHJlYXNvbmAgc2V0IHRvIGBcImZvcmNlRGlzY29ubmVjdEJ5VXNlclwiYFxuICAgICAqXG4gICAgICogVGhlIFtbUHVibGlzaGVyXV0gb2JqZWN0IG9mIHRoZSBhZmZlY3RlZCBwYXJ0aWNpcGFudCB3aWxsIGFsc28gZGlzcGF0Y2ggYSBgc3RyZWFtRGVzdHJveWVkYCBldmVudCB3aXRoIHByb3BlcnR5IGByZWFzb25gIHNldCB0byBgXCJmb3JjZURpc2Nvbm5lY3RCeVVzZXJcImBcbiAgICAgKlxuICAgICAqIFNlZSBbW1N0cmVhbUV2ZW50XV0gdG8gbGVhcm4gbW9yZS5cbiAgICAgKlxuICAgICAqIEByZXR1cm5zIEEgUHJvbWlzZSAodG8gd2hpY2ggeW91IGNhbiBvcHRpb25hbGx5IHN1YnNjcmliZSB0bykgdGhhdCBpcyByZXNvbHZlZCBvbmx5IGFmdGVyIHRoZSByZW1vdGUgU3RyZWFtIGhhcyBiZWVuIHN1Y2Nlc3NmdWxseSB1bnB1Ymxpc2hlZCBmcm9tIHRoZSBzZXNzaW9uIGFuZCByZWplY3RlZCB3aXRoIGFuIEVycm9yIG9iamVjdCBpZiBub3RcbiAgICAgKi9cbiAgICBmb3JjZVVucHVibGlzaChzdHJlYW06IFN0cmVhbSk6IFByb21pc2U8YW55PiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICBjb25zb2xlLmluZm8oJ0ZvcmNpbmcgdW5wdWJsaXNoIGZvciBzdHJlYW0gJyArIHN0cmVhbS5zdHJlYW1JZCk7XG4gICAgICAgICAgICB0aGlzLm9wZW52aWR1LnNlbmRSZXF1ZXN0KFxuICAgICAgICAgICAgICAgICdmb3JjZVVucHVibGlzaCcsXG4gICAgICAgICAgICAgICAgeyBzdHJlYW1JZDogc3RyZWFtLnN0cmVhbUlkIH0sXG4gICAgICAgICAgICAgICAgKGVycm9yLCByZXNwb25zZSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBpZiAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ0Vycm9yIGZvcmNpbmcgdW5wdWJsaXNoIGZvciBTdHJlYW0gJyArIHN0cmVhbS5zdHJlYW1JZCwgZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yLmNvZGUgPT09IDQwMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChuZXcgT3BlblZpZHVFcnJvcihPcGVuVmlkdUVycm9yTmFtZS5PUEVOVklEVV9QRVJNSVNTSU9OX0RFTklFRCwgXCJZb3UgZG9uJ3QgaGF2ZSBwZXJtaXNzaW9ucyB0byBmb3JjZSBhbiB1bnB1Ymxpc2hpbmdcIikpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5pbmZvKCdGb3JjaW5nIHVucHVibGlzaCBjb3JyZWN0bHkgZm9yIFN0cmVhbSAnICsgc3RyZWFtLnN0cmVhbUlkKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogU2VuZHMgb25lIHNpZ25hbC4gYHNpZ25hbGAgb2JqZWN0IGhhcyB0aGUgZm9sbG93aW5nIG9wdGlvbmFsIHByb3BlcnRpZXM6XG4gICAgICogYGBganNvblxuICAgICAqIHtkYXRhOnN0cmluZywgdG86Q29ubmVjdGlvbltdLCB0eXBlOnN0cmluZ31cbiAgICAgKiBgYGBcbiAgICAgKiBBbGwgdXNlcnMgc3Vic2NyaWJlZCB0byB0aGF0IHNpZ25hbCAoYHNlc3Npb24ub24oJ3NpZ25hbDp0eXBlJywgLi4uKWAgb3IgYHNlc3Npb24ub24oJ3NpZ25hbCcsIC4uLilgIGZvciBhbGwgc2lnbmFscykgYW5kIHdob3NlIENvbm5lY3Rpb24gb2JqZWN0cyBhcmUgaW4gYHRvYCBhcnJheSB3aWxsIHJlY2VpdmUgaXQuIFRoZWlyIGxvY2FsXG4gICAgICogU2Vzc2lvbiBvYmplY3RzIHdpbGwgZGlzcGF0Y2ggYSBgc2lnbmFsYCBvciBgc2lnbmFsOnR5cGVgIGV2ZW50LiBTZWUgW1tTaWduYWxFdmVudF1dIHRvIGxlYXJuIG1vcmUuXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyBBIFByb21pc2UgKHRvIHdoaWNoIHlvdSBjYW4gb3B0aW9uYWxseSBzdWJzY3JpYmUgdG8pIHRoYXQgaXMgcmVzb2x2ZWQgaWYgdGhlIG1lc3NhZ2Ugc3VjY2Vzc2Z1bGx5IHJlYWNoZWQgb3BlbnZpZHUtc2VydmVyIGFuZCByZWplY3RlZCB3aXRoIGFuIEVycm9yIG9iamVjdCBpZiBub3QuIF9UaGlzIGRvZXNuJ3RcbiAgICAgKiBtZWFuIHRoYXQgb3BlbnZpZHUtc2VydmVyIGNvdWxkIHJlc2VuZCB0aGUgbWVzc2FnZSB0byBhbGwgdGhlIGxpc3RlZCByZWNlaXZlcnMuX1xuICAgICAqL1xuICAgIC8qIHRzbGludDpkaXNhYmxlOm5vLXN0cmluZy1saXRlcmFsICovXG4gICAgc2lnbmFsKHNpZ25hbDogU2lnbmFsT3B0aW9ucyk6IFByb21pc2U8YW55PiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG5cbiAgICAgICAgICAgIGNvbnN0IHNpZ25hbE1lc3NhZ2UgPSB7fTtcblxuICAgICAgICAgICAgaWYgKHNpZ25hbC50byAmJiBzaWduYWwudG8ubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgICAgIGNvbnN0IGNvbm5lY3Rpb25JZHM6IHN0cmluZ1tdID0gW107XG5cbiAgICAgICAgICAgICAgICBzaWduYWwudG8uZm9yRWFjaChjb25uZWN0aW9uID0+IHtcbiAgICAgICAgICAgICAgICAgICAgY29ubmVjdGlvbklkcy5wdXNoKGNvbm5lY3Rpb24uY29ubmVjdGlvbklkKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICBzaWduYWxNZXNzYWdlWyd0byddID0gY29ubmVjdGlvbklkcztcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgc2lnbmFsTWVzc2FnZVsndG8nXSA9IFtdO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBzaWduYWxNZXNzYWdlWydkYXRhJ10gPSBzaWduYWwuZGF0YSA/IHNpZ25hbC5kYXRhIDogJyc7XG4gICAgICAgICAgICBzaWduYWxNZXNzYWdlWyd0eXBlJ10gPSBzaWduYWwudHlwZSA/IHNpZ25hbC50eXBlIDogJyc7XG5cbiAgICAgICAgICAgIHRoaXMub3BlbnZpZHUuc2VuZFJlcXVlc3QoJ3NlbmRNZXNzYWdlJywge1xuICAgICAgICAgICAgICAgIG1lc3NhZ2U6IEpTT04uc3RyaW5naWZ5KHNpZ25hbE1lc3NhZ2UpXG4gICAgICAgICAgICB9LCAoZXJyb3IsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKCEhZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgIH1cbiAgICAvKiB0c2xpbnQ6ZW5hYmxlOm5vLXN0cmluZy1saXRlcmFsICovXG5cblxuICAgIC8qKlxuICAgICAqIFNlZSBbW0V2ZW50RGlzcGF0Y2hlci5vbl1dXG4gICAgICovXG4gICAgb24odHlwZTogc3RyaW5nLCBoYW5kbGVyOiAoZXZlbnQ6IFNlc3Npb25EaXNjb25uZWN0ZWRFdmVudCB8IFNpZ25hbEV2ZW50IHwgU3RyZWFtRXZlbnQgfCBDb25uZWN0aW9uRXZlbnQgfCBQdWJsaXNoZXJTcGVha2luZ0V2ZW50IHwgUmVjb3JkaW5nRXZlbnQpID0+IHZvaWQpOiBFdmVudERpc3BhdGNoZXIge1xuXG4gICAgICAgIHRoaXMuZWUub24odHlwZSwgZXZlbnQgPT4ge1xuICAgICAgICAgICAgaWYgKGV2ZW50KSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5pbmZvKFwiRXZlbnQgJ1wiICsgdHlwZSArIFwiJyB0cmlnZ2VyZWQgYnkgJ1Nlc3Npb24nXCIsIGV2ZW50KTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5pbmZvKFwiRXZlbnQgJ1wiICsgdHlwZSArIFwiJyB0cmlnZ2VyZWQgYnkgJ1Nlc3Npb24nXCIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaGFuZGxlcihldmVudCk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGlmICh0eXBlID09PSAncHVibGlzaGVyU3RhcnRTcGVha2luZycgfHwgdHlwZSA9PT0gJ3B1Ymxpc2hlclN0b3BTcGVha2luZycpIHtcbiAgICAgICAgICAgIHRoaXMuc3BlYWtpbmdFdmVudHNFbmFibGVkID0gdHJ1ZTtcbiAgICAgICAgICAgIC8vIElmIHRoZXJlIGFyZSBhbHJlYWR5IGF2YWlsYWJsZSByZW1vdGUgc3RyZWFtcywgZW5hYmxlIGhhcmsgJ3NwZWFraW5nJyBldmVudCBpbiBhbGwgb2YgdGhlbVxuICAgICAgICAgICAgZm9yIChjb25zdCBjb25uZWN0aW9uSWQgaW4gdGhpcy5yZW1vdGVDb25uZWN0aW9ucykge1xuICAgICAgICAgICAgICAgIGNvbnN0IHN0ciA9IHRoaXMucmVtb3RlQ29ubmVjdGlvbnNbY29ubmVjdGlvbklkXS5zdHJlYW07XG4gICAgICAgICAgICAgICAgaWYgKCEhc3RyICYmICFzdHIuc3BlZWNoRXZlbnQgJiYgc3RyLmhhc0F1ZGlvKSB7XG4gICAgICAgICAgICAgICAgICAgIHN0ci5lbmFibGVTcGVha2luZ0V2ZW50cygpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogU2VlIFtbRXZlbnREaXNwYXRjaGVyLm9uY2VdXVxuICAgICAqL1xuICAgIG9uY2UodHlwZTogc3RyaW5nLCBoYW5kbGVyOiAoZXZlbnQ6IFNlc3Npb25EaXNjb25uZWN0ZWRFdmVudCB8IFNpZ25hbEV2ZW50IHwgU3RyZWFtRXZlbnQgfCBDb25uZWN0aW9uRXZlbnQgfCBQdWJsaXNoZXJTcGVha2luZ0V2ZW50IHwgUmVjb3JkaW5nRXZlbnQpID0+IHZvaWQpOiBTZXNzaW9uIHtcblxuICAgICAgICB0aGlzLmVlLm9uY2UodHlwZSwgZXZlbnQgPT4ge1xuICAgICAgICAgICAgaWYgKGV2ZW50KSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5pbmZvKFwiRXZlbnQgJ1wiICsgdHlwZSArIFwiJyB0cmlnZ2VyZWQgYnkgJ1Nlc3Npb24nXCIsIGV2ZW50KTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5pbmZvKFwiRXZlbnQgJ1wiICsgdHlwZSArIFwiJyB0cmlnZ2VyZWQgYnkgJ1Nlc3Npb24nXCIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaGFuZGxlcihldmVudCk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGlmICh0eXBlID09PSAncHVibGlzaGVyU3RhcnRTcGVha2luZycgfHwgdHlwZSA9PT0gJ3B1Ymxpc2hlclN0b3BTcGVha2luZycpIHtcbiAgICAgICAgICAgIHRoaXMuc3BlYWtpbmdFdmVudHNFbmFibGVkID0gdHJ1ZTtcbiAgICAgICAgICAgIC8vIElmIHRoZXJlIGFyZSBhbHJlYWR5IGF2YWlsYWJsZSByZW1vdGUgc3RyZWFtcywgZW5hYmxlIGhhcmsgaW4gYWxsIG9mIHRoZW1cbiAgICAgICAgICAgIGZvciAoY29uc3QgY29ubmVjdGlvbklkIGluIHRoaXMucmVtb3RlQ29ubmVjdGlvbnMpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBzdHIgPSB0aGlzLnJlbW90ZUNvbm5lY3Rpb25zW2Nvbm5lY3Rpb25JZF0uc3RyZWFtO1xuICAgICAgICAgICAgICAgIGlmICghIXN0ciAmJiAhc3RyLnNwZWVjaEV2ZW50ICYmIHN0ci5oYXNBdWRpbykge1xuICAgICAgICAgICAgICAgICAgICBzdHIuZW5hYmxlT25jZVNwZWFraW5nRXZlbnRzKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBTZWUgW1tFdmVudERpc3BhdGNoZXIub2ZmXV1cbiAgICAgKi9cbiAgICBvZmYodHlwZTogc3RyaW5nLCBoYW5kbGVyPzogKGV2ZW50OiBTZXNzaW9uRGlzY29ubmVjdGVkRXZlbnQgfCBTaWduYWxFdmVudCB8IFN0cmVhbUV2ZW50IHwgQ29ubmVjdGlvbkV2ZW50IHwgUHVibGlzaGVyU3BlYWtpbmdFdmVudCB8IFJlY29yZGluZ0V2ZW50KSA9PiB2b2lkKTogU2Vzc2lvbiB7XG5cbiAgICAgICAgaWYgKCFoYW5kbGVyKSB7XG4gICAgICAgICAgICB0aGlzLmVlLnJlbW92ZUFsbExpc3RlbmVycyh0eXBlKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuZWUub2ZmKHR5cGUsIGhhbmRsZXIpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHR5cGUgPT09ICdwdWJsaXNoZXJTdGFydFNwZWFraW5nJyB8fCB0eXBlID09PSAncHVibGlzaGVyU3RvcFNwZWFraW5nJykge1xuICAgICAgICAgICAgdGhpcy5zcGVha2luZ0V2ZW50c0VuYWJsZWQgPSBmYWxzZTtcblxuICAgICAgICAgICAgLy8gSWYgdGhlcmUgYXJlIGFscmVhZHkgYXZhaWxhYmxlIHJlbW90ZSBzdHJlYW1zLCBkaXNhYmxhZSBoYXJrIGluIGFsbCBvZiB0aGVtXG4gICAgICAgICAgICBmb3IgKGNvbnN0IGNvbm5lY3Rpb25JZCBpbiB0aGlzLnJlbW90ZUNvbm5lY3Rpb25zKSB7XG4gICAgICAgICAgICAgICAgY29uc3Qgc3RyID0gdGhpcy5yZW1vdGVDb25uZWN0aW9uc1tjb25uZWN0aW9uSWRdLnN0cmVhbTtcbiAgICAgICAgICAgICAgICBpZiAoISFzdHIgJiYgISFzdHIuc3BlZWNoRXZlbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgc3RyLmRpc2FibGVTcGVha2luZ0V2ZW50cygpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cblxuICAgIC8qIEhpZGRlbiBtZXRob2RzICovXG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgb25QYXJ0aWNpcGFudEpvaW5lZChyZXNwb25zZTogQ29ubmVjdGlvbk9wdGlvbnMpOiB2b2lkIHtcbiAgICAgICAgLy8gQ29ubmVjdGlvbiBzaG91bGRuJ3QgZXhpc3RcbiAgICAgICAgdGhpcy5nZXRDb25uZWN0aW9uKHJlc3BvbnNlLmlkLCAnJylcblxuICAgICAgICAgICAgLnRoZW4oY29ubmVjdGlvbiA9PiB7XG4gICAgICAgICAgICAgICAgY29uc29sZS53YXJuKCdDb25uZWN0aW9uICcgKyByZXNwb25zZS5pZCArICcgYWxyZWFkeSBleGlzdHMgaW4gY29ubmVjdGlvbnMgbGlzdCcpO1xuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIC5jYXRjaChvcGVuVmlkdUVycm9yID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCBjb25uZWN0aW9uID0gbmV3IENvbm5lY3Rpb24odGhpcywgcmVzcG9uc2UpO1xuICAgICAgICAgICAgICAgIHRoaXMucmVtb3RlQ29ubmVjdGlvbnNbcmVzcG9uc2UuaWRdID0gY29ubmVjdGlvbjtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnY29ubmVjdGlvbkNyZWF0ZWQnLCBbbmV3IENvbm5lY3Rpb25FdmVudChmYWxzZSwgdGhpcywgJ2Nvbm5lY3Rpb25DcmVhdGVkJywgY29ubmVjdGlvbiwgJycpXSk7XG4gICAgICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgb25QYXJ0aWNpcGFudExlZnQobXNnKTogdm9pZCB7XG4gICAgICAgIHRoaXMuZ2V0UmVtb3RlQ29ubmVjdGlvbihtc2cuY29ubmVjdGlvbklkLCAnUmVtb3RlIGNvbm5lY3Rpb24gJyArIG1zZy5jb25uZWN0aW9uSWQgKyBcIiB1bmtub3duIHdoZW4gJ29uUGFydGljaXBhbnRMZWZ0Jy4gXCIgK1xuICAgICAgICAgICAgJ0V4aXN0aW5nIHJlbW90ZSBjb25uZWN0aW9uczogJyArIEpTT04uc3RyaW5naWZ5KE9iamVjdC5rZXlzKHRoaXMucmVtb3RlQ29ubmVjdGlvbnMpKSlcblxuICAgICAgICAgICAgLnRoZW4oY29ubmVjdGlvbiA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKCEhY29ubmVjdGlvbi5zdHJlYW0pIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3Qgc3RyZWFtID0gY29ubmVjdGlvbi5zdHJlYW07XG5cbiAgICAgICAgICAgICAgICAgICAgY29uc3Qgc3RyZWFtRXZlbnQgPSBuZXcgU3RyZWFtRXZlbnQodHJ1ZSwgdGhpcywgJ3N0cmVhbURlc3Ryb3llZCcsIHN0cmVhbSwgbXNnLnJlYXNvbik7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdzdHJlYW1EZXN0cm95ZWQnLCBbc3RyZWFtRXZlbnRdKTtcbiAgICAgICAgICAgICAgICAgICAgc3RyZWFtRXZlbnQuY2FsbERlZmF1bHRCZWhhdmlvcigpO1xuXG4gICAgICAgICAgICAgICAgICAgIGRlbGV0ZSB0aGlzLnJlbW90ZVN0cmVhbXNDcmVhdGVkW3N0cmVhbS5zdHJlYW1JZF07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGRlbGV0ZSB0aGlzLnJlbW90ZUNvbm5lY3Rpb25zW2Nvbm5lY3Rpb24uY29ubmVjdGlvbklkXTtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnY29ubmVjdGlvbkRlc3Ryb3llZCcsIFtuZXcgQ29ubmVjdGlvbkV2ZW50KGZhbHNlLCB0aGlzLCAnY29ubmVjdGlvbkRlc3Ryb3llZCcsIGNvbm5lY3Rpb24sIG1zZy5yZWFzb24pXSk7XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLmNhdGNoKG9wZW5WaWR1RXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3Iob3BlblZpZHVFcnJvcik7XG4gICAgICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgb25QYXJ0aWNpcGFudFB1Ymxpc2hlZChyZXNwb25zZTogQ29ubmVjdGlvbk9wdGlvbnMpOiB2b2lkIHtcblxuICAgICAgICBjb25zdCBhZnRlckNvbm5lY3Rpb25Gb3VuZCA9IChjb25uZWN0aW9uKSA9PiB7XG4gICAgICAgICAgICB0aGlzLnJlbW90ZUNvbm5lY3Rpb25zW2Nvbm5lY3Rpb24uY29ubmVjdGlvbklkXSA9IGNvbm5lY3Rpb247XG5cbiAgICAgICAgICAgIGlmICghdGhpcy5yZW1vdGVTdHJlYW1zQ3JlYXRlZFtjb25uZWN0aW9uLnN0cmVhbS5zdHJlYW1JZF0pIHtcbiAgICAgICAgICAgICAgICAvLyBBdm9pZCByYWNlIGNvbmRpdGlvbiBiZXR3ZWVuIHN0cmVhbS5zdWJzY3JpYmUoKSBpbiBcIm9uUGFydGljaXBhbnRQdWJsaXNoZWRcIiBhbmQgaW4gXCJqb2luUm9vbVwiIHJwYyBjYWxsYmFja1xuICAgICAgICAgICAgICAgIC8vIFRoaXMgY29uZGl0aW9uIGlzIGZhbHNlIGlmIG9wZW52aWR1LXNlcnZlciBzZW5kcyBcInBhcnRpY2lwYW50UHVibGlzaGVkXCIgZXZlbnQgdG8gYSBzdWJzY3JpYmVyIHBhcnRpY2lwYW50IHRoYXQgaGFzXG4gICAgICAgICAgICAgICAgLy8gYWxyZWFkeSBzdWJzY3JpYmVkIHRvIGNlcnRhaW4gc3RyZWFtIGluIHRoZSBjYWxsYmFjayBvZiBcImpvaW5Sb29tXCIgbWV0aG9kXG5cbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnc3RyZWFtQ3JlYXRlZCcsIFtuZXcgU3RyZWFtRXZlbnQoZmFsc2UsIHRoaXMsICdzdHJlYW1DcmVhdGVkJywgY29ubmVjdGlvbi5zdHJlYW0sICcnKV0pO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLnJlbW90ZVN0cmVhbXNDcmVhdGVkW2Nvbm5lY3Rpb24uc3RyZWFtLnN0cmVhbUlkXSA9IHRydWU7XG4gICAgICAgIH07XG5cbiAgICAgICAgLy8gR2V0IHRoZSBleGlzdGluZyBDb25uZWN0aW9uIGNyZWF0ZWQgb24gJ29uUGFydGljaXBhbnRKb2luZWQnIGZvclxuICAgICAgICAvLyBleGlzdGluZyBwYXJ0aWNpcGFudHMgb3IgY3JlYXRlIGEgbmV3IG9uZSBmb3IgbmV3IHBhcnRpY2lwYW50c1xuICAgICAgICBsZXQgY29ubmVjdGlvbjogQ29ubmVjdGlvbjtcbiAgICAgICAgdGhpcy5nZXRSZW1vdGVDb25uZWN0aW9uKHJlc3BvbnNlLmlkLCBcIlJlbW90ZSBjb25uZWN0aW9uICdcIiArIHJlc3BvbnNlLmlkICsgXCInIHVua25vd24gd2hlbiAnb25QYXJ0aWNpcGFudFB1Ymxpc2hlZCcuIFwiICtcbiAgICAgICAgICAgICdFeGlzdGluZyByZW1vdGUgY29ubmVjdGlvbnM6ICcgKyBKU09OLnN0cmluZ2lmeShPYmplY3Qua2V5cyh0aGlzLnJlbW90ZUNvbm5lY3Rpb25zKSkpXG5cbiAgICAgICAgICAgIC50aGVuKGNvbiA9PiB7XG4gICAgICAgICAgICAgICAgLy8gVXBkYXRlIGV4aXN0aW5nIENvbm5lY3Rpb25cbiAgICAgICAgICAgICAgICBjb25uZWN0aW9uID0gY29uO1xuICAgICAgICAgICAgICAgIHJlc3BvbnNlLm1ldGFkYXRhID0gY29uLmRhdGE7XG4gICAgICAgICAgICAgICAgY29ubmVjdGlvbi5vcHRpb25zID0gcmVzcG9uc2U7XG4gICAgICAgICAgICAgICAgY29ubmVjdGlvbi5pbml0UmVtb3RlU3RyZWFtcyhyZXNwb25zZS5zdHJlYW1zKTtcbiAgICAgICAgICAgICAgICBhZnRlckNvbm5lY3Rpb25Gb3VuZChjb25uZWN0aW9uKTtcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAuY2F0Y2gob3BlblZpZHVFcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgLy8gQ3JlYXRlIG5ldyBDb25uZWN0aW9uXG4gICAgICAgICAgICAgICAgY29ubmVjdGlvbiA9IG5ldyBDb25uZWN0aW9uKHRoaXMsIHJlc3BvbnNlKTtcbiAgICAgICAgICAgICAgICBhZnRlckNvbm5lY3Rpb25Gb3VuZChjb25uZWN0aW9uKTtcbiAgICAgICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvblBhcnRpY2lwYW50VW5wdWJsaXNoZWQobXNnKTogdm9pZCB7XG4gICAgICAgIGlmIChtc2cuY29ubmVjdGlvbklkID09PSB0aGlzLmNvbm5lY3Rpb24uY29ubmVjdGlvbklkKSB7XG4gICAgICAgICAgICAvLyBZb3VyIHN0cmVhbSBoYXMgYmVlbiBmb3JjZWRseSB1bnB1Ymxpc2hlZCBmcm9tIHRoZSBzZXNzaW9uXG4gICAgICAgICAgICB0aGlzLnN0b3BQdWJsaXNoZXJTdHJlYW0obXNnLnJlYXNvbik7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLmdldFJlbW90ZUNvbm5lY3Rpb24obXNnLmNvbm5lY3Rpb25JZCwgXCJSZW1vdGUgY29ubmVjdGlvbiAnXCIgKyBtc2cuY29ubmVjdGlvbklkICsgXCInIHVua25vd24gd2hlbiAnb25QYXJ0aWNpcGFudFVucHVibGlzaGVkJy4gXCIgK1xuICAgICAgICAgICAgICAgICdFeGlzdGluZyByZW1vdGUgY29ubmVjdGlvbnM6ICcgKyBKU09OLnN0cmluZ2lmeShPYmplY3Qua2V5cyh0aGlzLnJlbW90ZUNvbm5lY3Rpb25zKSkpXG5cbiAgICAgICAgICAgICAgICAudGhlbihjb25uZWN0aW9uID0+IHtcblxuICAgICAgICAgICAgICAgICAgICBjb25zdCBzdHJlYW1FdmVudCA9IG5ldyBTdHJlYW1FdmVudCh0cnVlLCB0aGlzLCAnc3RyZWFtRGVzdHJveWVkJywgY29ubmVjdGlvbi5zdHJlYW0sIG1zZy5yZWFzb24pO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnc3RyZWFtRGVzdHJveWVkJywgW3N0cmVhbUV2ZW50XSk7XG4gICAgICAgICAgICAgICAgICAgIHN0cmVhbUV2ZW50LmNhbGxEZWZhdWx0QmVoYXZpb3IoKTtcblxuICAgICAgICAgICAgICAgICAgICAvLyBEZWxldGluZyB0aGUgcmVtb3RlIHN0cmVhbVxuICAgICAgICAgICAgICAgICAgICBjb25zdCBzdHJlYW1JZDogc3RyaW5nID0gY29ubmVjdGlvbi5zdHJlYW0uc3RyZWFtSWQ7XG4gICAgICAgICAgICAgICAgICAgIGRlbGV0ZSB0aGlzLnJlbW90ZVN0cmVhbXNDcmVhdGVkW3N0cmVhbUlkXTtcbiAgICAgICAgICAgICAgICAgICAgY29ubmVjdGlvbi5yZW1vdmVTdHJlYW0oc3RyZWFtSWQpO1xuICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgLmNhdGNoKG9wZW5WaWR1RXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKG9wZW5WaWR1RXJyb3IpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIG9uUGFydGljaXBhbnRFdmljdGVkKG1zZyk6IHZvaWQge1xuICAgICAgICBpZiAobXNnLmNvbm5lY3Rpb25JZCA9PT0gdGhpcy5jb25uZWN0aW9uLmNvbm5lY3Rpb25JZCkge1xuICAgICAgICAgICAgLy8gWW91IGhhdmUgYmVlbiBldmljdGVkIGZyb20gdGhlIHNlc3Npb25cbiAgICAgICAgICAgIGlmICghIXRoaXMuc2Vzc2lvbklkICYmICF0aGlzLmNvbm5lY3Rpb24uZGlzcG9zZWQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmxlYXZlKHRydWUsIG1zZy5yZWFzb24pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIG9uTmV3TWVzc2FnZShtc2cpOiB2b2lkIHtcblxuICAgICAgICBjb25zb2xlLmluZm8oJ05ldyBzaWduYWw6ICcgKyBKU09OLnN0cmluZ2lmeShtc2cpKTtcblxuICAgICAgICB0aGlzLmdldENvbm5lY3Rpb24obXNnLmZyb20sIFwiQ29ubmVjdGlvbiAnXCIgKyBtc2cuZnJvbSArIFwiJyB1bmtub3cgd2hlbiAnb25OZXdNZXNzYWdlJy4gRXhpc3RpbmcgcmVtb3RlIGNvbm5lY3Rpb25zOiBcIlxuICAgICAgICAgICAgKyBKU09OLnN0cmluZ2lmeShPYmplY3Qua2V5cyh0aGlzLnJlbW90ZUNvbm5lY3Rpb25zKSkgKyAnLiBFeGlzdGluZyBsb2NhbCBjb25uZWN0aW9uOiAnICsgdGhpcy5jb25uZWN0aW9uLmNvbm5lY3Rpb25JZClcblxuICAgICAgICAgICAgLnRoZW4oY29ubmVjdGlvbiA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3NpZ25hbCcsIFtuZXcgU2lnbmFsRXZlbnQodGhpcywgbXNnLnR5cGUsIG1zZy5kYXRhLCBjb25uZWN0aW9uKV0pO1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdzaWduYWw6JyArIG1zZy50eXBlLCBbbmV3IFNpZ25hbEV2ZW50KHRoaXMsIG1zZy50eXBlLCBtc2cuZGF0YSwgY29ubmVjdGlvbildKTtcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAuY2F0Y2gob3BlblZpZHVFcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihvcGVuVmlkdUVycm9yKTtcbiAgICAgICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvblN0cmVhbVByb3BlcnR5Q2hhbmdlZChtc2cpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5nZXRSZW1vdGVDb25uZWN0aW9uKG1zZy5jb25uZWN0aW9uSWQsICdSZW1vdGUgY29ubmVjdGlvbiAnICsgbXNnLmNvbm5lY3Rpb25JZCArIFwiIHVua25vd24gd2hlbiAnb25TdHJlYW1Qcm9wZXJ0eUNoYW5nZWQnLiBcIiArXG4gICAgICAgICAgICAnRXhpc3RpbmcgcmVtb3RlIGNvbm5lY3Rpb25zOiAnICsgSlNPTi5zdHJpbmdpZnkoT2JqZWN0LmtleXModGhpcy5yZW1vdGVDb25uZWN0aW9ucykpKVxuXG4gICAgICAgICAgICAudGhlbihjb25uZWN0aW9uID0+IHtcbiAgICAgICAgICAgICAgICBpZiAoISFjb25uZWN0aW9uLnN0cmVhbSAmJiBjb25uZWN0aW9uLnN0cmVhbS5zdHJlYW1JZCA9PT0gbXNnLnN0cmVhbUlkKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHN0cmVhbSA9IGNvbm5lY3Rpb24uc3RyZWFtO1xuICAgICAgICAgICAgICAgICAgICBsZXQgb2xkVmFsdWU7XG4gICAgICAgICAgICAgICAgICAgIHN3aXRjaCAobXNnLnByb3BlcnR5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlICdhdWRpb0FjdGl2ZSc6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgb2xkVmFsdWUgPSBzdHJlYW0uYXVkaW9BY3RpdmU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbXNnLm5ld1ZhbHVlID0gbXNnLm5ld1ZhbHVlID09PSAndHJ1ZSc7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyZWFtLmF1ZGlvQWN0aXZlID0gbXNnLm5ld1ZhbHVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAndmlkZW9BY3RpdmUnOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9sZFZhbHVlID0gc3RyZWFtLnZpZGVvQWN0aXZlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1zZy5uZXdWYWx1ZSA9IG1zZy5uZXdWYWx1ZSA9PT0gJ3RydWUnO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cmVhbS52aWRlb0FjdGl2ZSA9IG1zZy5uZXdWYWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJ3ZpZGVvRGltZW5zaW9ucyc6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgb2xkVmFsdWUgPSBzdHJlYW0udmlkZW9EaW1lbnNpb25zO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1zZy5uZXdWYWx1ZSA9IEpTT04ucGFyc2UoSlNPTi5wYXJzZShtc2cubmV3VmFsdWUpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJlYW0udmlkZW9EaW1lbnNpb25zID0gbXNnLm5ld1ZhbHVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3N0cmVhbVByb3BlcnR5Q2hhbmdlZCcsIFtuZXcgU3RyZWFtUHJvcGVydHlDaGFuZ2VkRXZlbnQodGhpcywgc3RyZWFtLCBtc2cucHJvcGVydHksIG1zZy5uZXdWYWx1ZSwgb2xkVmFsdWUsIG1zZy5yZWFzb24pXSk7XG4gICAgICAgICAgICAgICAgICAgIHN0cmVhbS5zdHJlYW1NYW5hZ2VyLmVtaXRFdmVudCgnc3RyZWFtUHJvcGVydHlDaGFuZ2VkJywgW25ldyBTdHJlYW1Qcm9wZXJ0eUNoYW5nZWRFdmVudChzdHJlYW0uc3RyZWFtTWFuYWdlciwgc3RyZWFtLCBtc2cucHJvcGVydHksIG1zZy5uZXdWYWx1ZSwgb2xkVmFsdWUsIG1zZy5yZWFzb24pXSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihcIk5vIHN0cmVhbSB3aXRoIHN0cmVhbUlkICdcIiArIG1zZy5zdHJlYW1JZCArIFwiJyBmb3VuZCBmb3IgY29ubmVjdGlvbiAnXCIgKyBtc2cuY29ubmVjdGlvbklkICsgXCInIG9uICdzdHJlYW1Qcm9wZXJ0eUNoYW5nZWQnIGV2ZW50XCIpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAuY2F0Y2gob3BlblZpZHVFcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihvcGVuVmlkdUVycm9yKTtcbiAgICAgICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICByZWN2SWNlQ2FuZGlkYXRlKG1zZyk6IHZvaWQge1xuICAgICAgICBjb25zdCBjYW5kaWRhdGUgPSB7XG4gICAgICAgICAgICBjYW5kaWRhdGU6IG1zZy5jYW5kaWRhdGUsXG4gICAgICAgICAgICBzZHBNaWQ6IG1zZy5zZHBNaWQsXG4gICAgICAgICAgICBzZHBNTGluZUluZGV4OiBtc2cuc2RwTUxpbmVJbmRleCxcbiAgICAgICAgICAgIHRvSlNPTjogKCkgPT4ge1xuICAgICAgICAgICAgICAgIHJldHVybiB7IGNhbmRpZGF0ZTogbXNnLmNhbmRpZGF0ZSB9O1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICB0aGlzLmdldENvbm5lY3Rpb24obXNnLmVuZHBvaW50TmFtZSwgJ0Nvbm5lY3Rpb24gbm90IGZvdW5kIGZvciBlbmRwb2ludCAnICsgbXNnLmVuZHBvaW50TmFtZSArICcuIEljZSBjYW5kaWRhdGUgd2lsbCBiZSBpZ25vcmVkOiAnICsgY2FuZGlkYXRlKVxuICAgICAgICAgICAgLnRoZW4oY29ubmVjdGlvbiA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3Qgc3RyZWFtID0gY29ubmVjdGlvbi5zdHJlYW07XG4gICAgICAgICAgICAgICAgc3RyZWFtLmdldFdlYlJ0Y1BlZXIoKS5hZGRJY2VDYW5kaWRhdGUoY2FuZGlkYXRlKS5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ0Vycm9yIGFkZGluZyBjYW5kaWRhdGUgZm9yICcgKyBzdHJlYW0uc3RyZWFtSWRcbiAgICAgICAgICAgICAgICAgICAgICAgICsgJyBzdHJlYW0gb2YgZW5kcG9pbnQgJyArIG1zZy5lbmRwb2ludE5hbWUgKyAnOiAnICsgZXJyb3IpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIC5jYXRjaChvcGVuVmlkdUVycm9yID0+IHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKG9wZW5WaWR1RXJyb3IpO1xuICAgICAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIG9uU2Vzc2lvbkNsb3NlZChtc2cpOiB2b2lkIHtcbiAgICAgICAgY29uc29sZS5pbmZvKCdTZXNzaW9uIGNsb3NlZDogJyArIEpTT04uc3RyaW5naWZ5KG1zZykpO1xuICAgICAgICBjb25zdCBzID0gbXNnLnNlc3Npb25JZDtcbiAgICAgICAgaWYgKHMgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3Nlc3Npb24tY2xvc2VkJywgW3tcbiAgICAgICAgICAgICAgICBzZXNzaW9uOiBzXG4gICAgICAgICAgICB9XSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjb25zb2xlLndhcm4oJ1Nlc3Npb24gdW5kZWZpbmVkIG9uIHNlc3Npb24gY2xvc2VkJywgbXNnKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvbkxvc3RDb25uZWN0aW9uKCk6IHZvaWQge1xuXG4gICAgICAgIC8qaWYgKCF0aGlzLmNvbm5lY3Rpb24pIHtcblxuICAgICAgICAgICAgY29uc29sZS53YXJuKCdOb3QgY29ubmVjdGVkIHRvIHNlc3Npb246IGlmIHlvdSBhcmUgbm90IGRlYnVnZ2luZywgdGhpcyBpcyBwcm9iYWJseSBhIGNlcnRpZmljYXRlIGVycm9yJyk7XG5cbiAgICAgICAgICAgIGNvbnN0IHVybCA9ICdodHRwczovLycgKyB0aGlzLm9wZW52aWR1LmdldFdzVXJpKCkuc3BsaXQoJ3dzczovLycpWzFdLnNwbGl0KCcvb3BlbnZpZHUnKVswXTtcbiAgICAgICAgICAgIGlmICh3aW5kb3cuY29uZmlybSgnSWYgeW91IGFyZSBub3QgZGVidWdnaW5nLCB0aGlzIGlzIHByb2JhYmx5IGEgY2VydGlmaWNhdGUgZXJyb3IgYXQgXFxcIicgKyB1cmwgKyAnXFxcIlxcblxcbkNsaWNrIE9LIHRvIG5hdmlnYXRlIGFuZCBhY2NlcHQgaXQnKSkge1xuICAgICAgICAgICAgICAgIGxvY2F0aW9uLmFzc2lnbih1cmwgKyAnL2FjY2VwdC1jZXJ0aWZpY2F0ZScpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9Ki9cblxuICAgICAgICBjb25zb2xlLndhcm4oJ0xvc3QgY29ubmVjdGlvbiBpbiBTZXNzaW9uICcgKyB0aGlzLnNlc3Npb25JZCk7XG4gICAgICAgIGlmICghIXRoaXMuc2Vzc2lvbklkICYmICF0aGlzLmNvbm5lY3Rpb24uZGlzcG9zZWQpIHtcbiAgICAgICAgICAgIHRoaXMubGVhdmUodHJ1ZSwgJ25ldHdvcmtEaXNjb25uZWN0Jyk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgb25SZWNvdmVyZWRDb25uZWN0aW9uKCk6IHZvaWQge1xuICAgICAgICBjb25zb2xlLndhcm4oJ1JlY292ZXJlZCBjb25uZWN0aW9uIGluIFNlc3Npb24gJyArIHRoaXMuc2Vzc2lvbklkKTtcbiAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ2Nvbm5lY3Rpb25SZWNvdmVyZWQnLCBbXSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIG9uTWVkaWFFcnJvcihwYXJhbXMpOiB2b2lkIHtcblxuICAgICAgICBjb25zb2xlLmVycm9yKCdNZWRpYSBlcnJvcjogJyArIEpTT04uc3RyaW5naWZ5KHBhcmFtcykpO1xuICAgICAgICBjb25zdCBlcnIgPSBwYXJhbXMuZXJyb3I7XG4gICAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdlcnJvci1tZWRpYScsIFt7XG4gICAgICAgICAgICAgICAgZXJyb3I6IGVyclxuICAgICAgICAgICAgfV0pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY29uc29sZS53YXJuKCdSZWNlaXZlZCB1bmRlZmluZWQgbWVkaWEgZXJyb3IuIFBhcmFtczonLCBwYXJhbXMpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIG9uUmVjb3JkaW5nU3RhcnRlZChyZXNwb25zZSk6IHZvaWQge1xuICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgncmVjb3JkaW5nU3RhcnRlZCcsIFtuZXcgUmVjb3JkaW5nRXZlbnQodGhpcywgJ3JlY29yZGluZ1N0YXJ0ZWQnLCByZXNwb25zZS5pZCwgcmVzcG9uc2UubmFtZSldKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgb25SZWNvcmRpbmdTdG9wcGVkKHJlc3BvbnNlKTogdm9pZCB7XG4gICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdyZWNvcmRpbmdTdG9wcGVkJywgW25ldyBSZWNvcmRpbmdFdmVudCh0aGlzLCAncmVjb3JkaW5nU3RvcHBlZCcsIHJlc3BvbnNlLmlkLCByZXNwb25zZS5uYW1lKV0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBlbWl0RXZlbnQodHlwZTogc3RyaW5nLCBldmVudEFycmF5OiBhbnlbXSk6IHZvaWQge1xuICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCh0eXBlLCBldmVudEFycmF5KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgbGVhdmUoZm9yY2VkOiBib29sZWFuLCByZWFzb246IHN0cmluZyk6IHZvaWQge1xuXG4gICAgICAgIGZvcmNlZCA9ICEhZm9yY2VkO1xuICAgICAgICBjb25zb2xlLmluZm8oJ0xlYXZpbmcgU2Vzc2lvbiAoZm9yY2VkPScgKyBmb3JjZWQgKyAnKScpO1xuXG4gICAgICAgIGlmICghIXRoaXMuY29ubmVjdGlvbikge1xuICAgICAgICAgICAgaWYgKCF0aGlzLmNvbm5lY3Rpb24uZGlzcG9zZWQgJiYgIWZvcmNlZCkge1xuICAgICAgICAgICAgICAgIHRoaXMub3BlbnZpZHUuc2VuZFJlcXVlc3QoJ2xlYXZlUm9vbScsIChlcnJvciwgcmVzcG9uc2UpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB0aGlzLm9wZW52aWR1LmNsb3NlV3MoKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy5vcGVudmlkdS5jbG9zZVdzKCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMuc3RvcFB1Ymxpc2hlclN0cmVhbShyZWFzb24pO1xuXG4gICAgICAgICAgICBpZiAoIXRoaXMuY29ubmVjdGlvbi5kaXNwb3NlZCkge1xuICAgICAgICAgICAgICAgIC8vIE1ha2UgU2Vzc2lvbiBvYmplY3QgZGlzcGF0Y2ggJ3Nlc3Npb25EaXNjb25uZWN0ZWQnIGV2ZW50IChpZiBpdCBpcyBub3QgYWxyZWFkeSBkaXNwb3NlZClcbiAgICAgICAgICAgICAgICBjb25zdCBzZXNzaW9uRGlzY29ubmVjdEV2ZW50ID0gbmV3IFNlc3Npb25EaXNjb25uZWN0ZWRFdmVudCh0aGlzLCByZWFzb24pO1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdzZXNzaW9uRGlzY29ubmVjdGVkJywgW3Nlc3Npb25EaXNjb25uZWN0RXZlbnRdKTtcbiAgICAgICAgICAgICAgICBzZXNzaW9uRGlzY29ubmVjdEV2ZW50LmNhbGxEZWZhdWx0QmVoYXZpb3IoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvbnNvbGUud2FybignWW91IHdlcmUgbm90IGNvbm5lY3RlZCB0byB0aGUgc2Vzc2lvbiAnICsgdGhpcy5zZXNzaW9uSWQpO1xuICAgICAgICB9XG4gICAgfVxuXG5cbiAgICAvKiBQcml2YXRlIG1ldGhvZHMgKi9cblxuICAgIHByaXZhdGUgY29ubmVjdEF1eCh0b2tlbjogc3RyaW5nKTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIHRoaXMub3BlbnZpZHUuc3RhcnRXcygoZXJyb3IpID0+IHtcbiAgICAgICAgICAgICAgICBpZiAoISFlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG5cbiAgICAgICAgICAgICAgICAgICAgY29uc3Qgam9pblBhcmFtcyA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRva2VuOiAoISF0b2tlbikgPyB0b2tlbiA6ICcnLFxuICAgICAgICAgICAgICAgICAgICAgICAgc2Vzc2lvbjogdGhpcy5zZXNzaW9uSWQsXG4gICAgICAgICAgICAgICAgICAgICAgICBtZXRhZGF0YTogISF0aGlzLm9wdGlvbnMubWV0YWRhdGEgPyB0aGlzLm9wdGlvbnMubWV0YWRhdGEgOiAnJyxcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlY3JldDogdGhpcy5vcGVudmlkdS5nZXRTZWNyZXQoKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlY29yZGVyOiB0aGlzLm9wZW52aWR1LmdldFJlY29yZGVyKCksXG4gICAgICAgICAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgICAgICAgICAgdGhpcy5vcGVudmlkdS5zZW5kUmVxdWVzdCgnam9pblJvb20nLCBqb2luUGFyYW1zLCAoZXJyb3IsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoISFlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gSW5pdGlhbGl6ZSBjYXBhYmlsaXRpZXMgb2JqZWN0IHdpdGggdGhlIHJvbGVcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNhcGFiaWxpdGllcyA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3Vic2NyaWJlOiB0cnVlLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwdWJsaXNoOiB0aGlzLm9wZW52aWR1LnJvbGUgIT09ICdTVUJTQ1JJQkVSJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yY2VVbnB1Ymxpc2g6IHRoaXMub3BlbnZpZHUucm9sZSA9PT0gJ01PREVSQVRPUicsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvcmNlRGlzY29ubmVjdDogdGhpcy5vcGVudmlkdS5yb2xlID09PSAnTU9ERVJBVE9SJ1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBJbml0aWFsaXplIGxvY2FsIENvbm5lY3Rpb24gb2JqZWN0IHdpdGggdmFsdWVzIHJldHVybmVkIGJ5IG9wZW52aWR1LXNlcnZlclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY29ubmVjdGlvbiA9IG5ldyBDb25uZWN0aW9uKHRoaXMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY29ubmVjdGlvbi5jb25uZWN0aW9uSWQgPSByZXNwb25zZS5pZDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbm5lY3Rpb24uZGF0YSA9IHJlc3BvbnNlLm1ldGFkYXRhO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gSW5pdGlhbGl6ZSByZW1vdGUgQ29ubmVjdGlvbnMgd2l0aCB2YWx1ZSByZXR1cm5lZCBieSBvcGVudmlkdS1zZXJ2ZXJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBldmVudHMgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbm5lY3Rpb25zOiBuZXcgQXJyYXk8Q29ubmVjdGlvbj4oKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyZWFtczogbmV3IEFycmF5PFN0cmVhbT4oKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZXhpc3RpbmdQYXJ0aWNpcGFudHM6IENvbm5lY3Rpb25PcHRpb25zW10gPSByZXNwb25zZS52YWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBleGlzdGluZ1BhcnRpY2lwYW50cy5mb3JFYWNoKHBhcnRpY2lwYW50ID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgY29ubmVjdGlvbiA9IG5ldyBDb25uZWN0aW9uKHRoaXMsIHBhcnRpY2lwYW50KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5yZW1vdGVDb25uZWN0aW9uc1tjb25uZWN0aW9uLmNvbm5lY3Rpb25JZF0gPSBjb25uZWN0aW9uO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBldmVudHMuY29ubmVjdGlvbnMucHVzaChjb25uZWN0aW9uKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCEhY29ubmVjdGlvbi5zdHJlYW0pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucmVtb3RlU3RyZWFtc0NyZWF0ZWRbY29ubmVjdGlvbi5zdHJlYW0uc3RyZWFtSWRdID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV2ZW50cy5zdHJlYW1zLnB1c2goY29ubmVjdGlvbi5zdHJlYW0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBPd24gJ2Nvbm5lY3Rpb25DcmVhdGVkJyBldmVudFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdjb25uZWN0aW9uQ3JlYXRlZCcsIFtuZXcgQ29ubmVjdGlvbkV2ZW50KGZhbHNlLCB0aGlzLCAnY29ubmVjdGlvbkNyZWF0ZWQnLCB0aGlzLmNvbm5lY3Rpb24sICcnKV0pO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gT25lICdjb25uZWN0aW9uQ3JlYXRlZCcgZXZlbnQgZm9yIGVhY2ggZXhpc3RpbmcgY29ubmVjdGlvbiBpbiB0aGUgc2Vzc2lvblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV2ZW50cy5jb25uZWN0aW9ucy5mb3JFYWNoKGNvbm5lY3Rpb24gPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnY29ubmVjdGlvbkNyZWF0ZWQnLCBbbmV3IENvbm5lY3Rpb25FdmVudChmYWxzZSwgdGhpcywgJ2Nvbm5lY3Rpb25DcmVhdGVkJywgY29ubmVjdGlvbiwgJycpXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBPbmUgJ3N0cmVhbUNyZWF0ZWQnIGV2ZW50IGZvciBlYWNoIGFjdGl2ZSBzdHJlYW0gaW4gdGhlIHNlc3Npb25cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBldmVudHMuc3RyZWFtcy5mb3JFYWNoKHN0cmVhbSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdzdHJlYW1DcmVhdGVkJywgW25ldyBTdHJlYW1FdmVudChmYWxzZSwgdGhpcywgJ3N0cmVhbUNyZWF0ZWQnLCBzdHJlYW0sICcnKV0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBzdG9wUHVibGlzaGVyU3RyZWFtKHJlYXNvbjogc3RyaW5nKSB7XG4gICAgICAgIGlmICghIXRoaXMuY29ubmVjdGlvbi5zdHJlYW0pIHtcbiAgICAgICAgICAgIC8vIERpc3Bvc2UgUHVibGlzaGVyJ3MgIGxvY2FsIHN0cmVhbVxuICAgICAgICAgICAgdGhpcy5jb25uZWN0aW9uLnN0cmVhbS5kaXNwb3NlV2ViUnRjUGVlcigpO1xuICAgICAgICAgICAgaWYgKHRoaXMuY29ubmVjdGlvbi5zdHJlYW0uaXNMb2NhbFN0cmVhbVB1Ymxpc2hlZCkge1xuICAgICAgICAgICAgICAgIC8vIE1ha2UgUHVibGlzaGVyIG9iamVjdCBkaXNwYXRjaCAnc3RyZWFtRGVzdHJveWVkJyBldmVudCBpZiB0aGUgU3RyZWFtIHdhcyBwdWJsaXNoZWRcbiAgICAgICAgICAgICAgICB0aGlzLmNvbm5lY3Rpb24uc3RyZWFtLmVlLmVtaXRFdmVudCgnbG9jYWwtc3RyZWFtLWRlc3Ryb3llZCcsIFtyZWFzb25dKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgc3RyaW5nQ2xpZW50TWV0YWRhdGEobWV0YWRhdGE6IGFueSk6IHN0cmluZyB7XG4gICAgICAgIGlmICh0eXBlb2YgbWV0YWRhdGEgIT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkobWV0YWRhdGEpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIG1ldGFkYXRhO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBnZXRDb25uZWN0aW9uKGNvbm5lY3Rpb25JZDogc3RyaW5nLCBlcnJvck1lc3NhZ2U6IHN0cmluZyk6IFByb21pc2U8Q29ubmVjdGlvbj4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2U8Q29ubmVjdGlvbj4oKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgY29uc3QgY29ubmVjdGlvbiA9IHRoaXMucmVtb3RlQ29ubmVjdGlvbnNbY29ubmVjdGlvbklkXTtcbiAgICAgICAgICAgIGlmICghIWNvbm5lY3Rpb24pIHtcbiAgICAgICAgICAgICAgICAvLyBSZXNvbHZlIHJlbW90ZSBjb25uZWN0aW9uXG4gICAgICAgICAgICAgICAgcmVzb2x2ZShjb25uZWN0aW9uKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuY29ubmVjdGlvbi5jb25uZWN0aW9uSWQgPT09IGNvbm5lY3Rpb25JZCkge1xuICAgICAgICAgICAgICAgICAgICAvLyBSZXNvbHZlIGxvY2FsIGNvbm5lY3Rpb25cbiAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSh0aGlzLmNvbm5lY3Rpb24pO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIENvbm5lY3Rpb24gbm90IGZvdW5kLiBSZWplY3Qgd2l0aCBPcGVuVmlkdUVycm9yXG4gICAgICAgICAgICAgICAgICAgIHJlamVjdChuZXcgT3BlblZpZHVFcnJvcihPcGVuVmlkdUVycm9yTmFtZS5HRU5FUklDX0VSUk9SLCBlcnJvck1lc3NhZ2UpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIHByaXZhdGUgZ2V0UmVtb3RlQ29ubmVjdGlvbihjb25uZWN0aW9uSWQ6IHN0cmluZywgZXJyb3JNZXNzYWdlOiBzdHJpbmcpOiBQcm9taXNlPENvbm5lY3Rpb24+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlPENvbm5lY3Rpb24+KChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGNvbm5lY3Rpb24gPSB0aGlzLnJlbW90ZUNvbm5lY3Rpb25zW2Nvbm5lY3Rpb25JZF07XG4gICAgICAgICAgICBpZiAoISFjb25uZWN0aW9uKSB7XG4gICAgICAgICAgICAgICAgLy8gUmVzb2x2ZSByZW1vdGUgY29ubmVjdGlvblxuICAgICAgICAgICAgICAgIHJlc29sdmUoY29ubmVjdGlvbik7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIC8vIFJlbW90ZSBjb25uZWN0aW9uIG5vdCBmb3VuZC4gUmVqZWN0IHdpdGggT3BlblZpZHVFcnJvclxuICAgICAgICAgICAgICAgIHJlamVjdChuZXcgT3BlblZpZHVFcnJvcihPcGVuVmlkdUVycm9yTmFtZS5HRU5FUklDX0VSUk9SLCBlcnJvck1lc3NhZ2UpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBwcm9jZXNzVG9rZW4odG9rZW46IHN0cmluZyk6IHZvaWQge1xuICAgICAgICBjb25zdCB1cmwgPSBuZXcgVVJMKHRva2VuKTtcbiAgICAgICAgdGhpcy5zZXNzaW9uSWQgPSA8c3RyaW5nPnVybC5zZWFyY2hQYXJhbXMuZ2V0KCdzZXNzaW9uSWQnKTtcbiAgICAgICAgY29uc3Qgc2VjcmV0ID0gdXJsLnNlYXJjaFBhcmFtcy5nZXQoJ3NlY3JldCcpO1xuICAgICAgICBjb25zdCByZWNvcmRlciA9IHVybC5zZWFyY2hQYXJhbXMuZ2V0KCdyZWNvcmRlcicpO1xuICAgICAgICBjb25zdCB0dXJuVXNlcm5hbWUgPSB1cmwuc2VhcmNoUGFyYW1zLmdldCgndHVyblVzZXJuYW1lJyk7XG4gICAgICAgIGNvbnN0IHR1cm5DcmVkZW50aWFsID0gdXJsLnNlYXJjaFBhcmFtcy5nZXQoJ3R1cm5DcmVkZW50aWFsJyk7XG4gICAgICAgIGNvbnN0IHJvbGUgPSB1cmwuc2VhcmNoUGFyYW1zLmdldCgncm9sZScpO1xuXG4gICAgICAgIGlmICghIXNlY3JldCkge1xuICAgICAgICAgICAgdGhpcy5vcGVudmlkdS5zZWNyZXQgPSBzZWNyZXQ7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCEhcmVjb3JkZXIpIHtcbiAgICAgICAgICAgIHRoaXMub3BlbnZpZHUucmVjb3JkZXIgPSB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIGlmICghIXR1cm5Vc2VybmFtZSAmJiAhIXR1cm5DcmVkZW50aWFsKSB7XG4gICAgICAgICAgICBjb25zdCBzdHVuVXJsID0gJ3N0dW46JyArIHVybC5ob3N0bmFtZSArICc6MzQ3OCc7XG4gICAgICAgICAgICBjb25zdCB0dXJuVXJsMSA9ICd0dXJuOicgKyB1cmwuaG9zdG5hbWUgKyAnOjM0NzgnO1xuICAgICAgICAgICAgY29uc3QgdHVyblVybDIgPSB0dXJuVXJsMSArICc/dHJhbnNwb3J0PXRjcCc7XG4gICAgICAgICAgICB0aGlzLm9wZW52aWR1LmljZVNlcnZlcnMgPSBbXG4gICAgICAgICAgICAgICAgeyB1cmxzOiBbc3R1blVybF0gfSxcbiAgICAgICAgICAgICAgICB7IHVybHM6IFt0dXJuVXJsMSwgdHVyblVybDJdLCB1c2VybmFtZTogdHVyblVzZXJuYW1lLCBjcmVkZW50aWFsOiB0dXJuQ3JlZGVudGlhbCB9XG4gICAgICAgICAgICBdO1xuICAgICAgICAgICAgY29uc29sZS5sb2coJ1RVUk4gdGVtcCBjcmVkZW50aWFscyBbJyArIHR1cm5Vc2VybmFtZSArICc6JyArIHR1cm5DcmVkZW50aWFsICsgJ10nKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoISFyb2xlKSB7XG4gICAgICAgICAgICB0aGlzLm9wZW52aWR1LnJvbGUgPSByb2xlO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5vcGVudmlkdS53c1VyaSA9ICd3c3M6Ly8nICsgdXJsLmhvc3QgKyAnL29wZW52aWR1JztcbiAgICB9XG5cbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IENvbm5lY3Rpb24gfSBmcm9tICcuL0Nvbm5lY3Rpb24nO1xuaW1wb3J0IHsgU2Vzc2lvbiB9IGZyb20gJy4vU2Vzc2lvbic7XG5pbXBvcnQgeyBTdHJlYW1NYW5hZ2VyIH0gZnJvbSAnLi9TdHJlYW1NYW5hZ2VyJztcbmltcG9ydCB7IEluYm91bmRTdHJlYW1PcHRpb25zIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9JbnRlcmZhY2VzL1ByaXZhdGUvSW5ib3VuZFN0cmVhbU9wdGlvbnMnO1xuaW1wb3J0IHsgT3V0Ym91bmRTdHJlYW1PcHRpb25zIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9JbnRlcmZhY2VzL1ByaXZhdGUvT3V0Ym91bmRTdHJlYW1PcHRpb25zJztcbmltcG9ydCB7IFdlYlJ0Y1BlZXIsIFdlYlJ0Y1BlZXJTZW5kb25seSwgV2ViUnRjUGVlclJlY3Zvbmx5LCBXZWJSdGNQZWVyU2VuZHJlY3YgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL1dlYlJ0Y1BlZXIvV2ViUnRjUGVlcic7XG5pbXBvcnQgeyBXZWJSdGNTdGF0cyB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvV2ViUnRjU3RhdHMvV2ViUnRjU3RhdHMnO1xuaW1wb3J0IHsgUHVibGlzaGVyU3BlYWtpbmdFdmVudCB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1B1Ymxpc2hlclNwZWFraW5nRXZlbnQnO1xuXG5pbXBvcnQgRXZlbnRFbWl0dGVyID0gcmVxdWlyZSgnd29sZnk4Ny1ldmVudGVtaXR0ZXInKTtcbmltcG9ydCBoYXJrID0gcmVxdWlyZSgnaGFyaycpO1xuaW1wb3J0IHsgT3BlblZpZHVFcnJvciwgT3BlblZpZHVFcnJvck5hbWUgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0VudW1zL09wZW5WaWR1RXJyb3InO1xuXG5cbi8qKlxuICogUmVwcmVzZW50cyBlYWNoIG9uZSBvZiB0aGUgbWVkaWEgc3RyZWFtcyBhdmFpbGFibGUgaW4gT3BlblZpZHUgU2VydmVyIGZvciBjZXJ0YWluIHNlc3Npb24uXG4gKiBFYWNoIFtbUHVibGlzaGVyXV0gYW5kIFtbU3Vic2NyaWJlcl1dIGhhcyBhbiBhdHRyaWJ1dGUgb2YgdHlwZSBTdHJlYW0sIGFzIHRoZXkgZ2l2ZSBhY2Nlc3NcbiAqIHRvIG9uZSBvZiB0aGVtIChzZW5kaW5nIGFuZCByZWNlaXZpbmcgaXQsIHJlc3BlY3RpdmVseSlcbiAqL1xuZXhwb3J0IGNsYXNzIFN0cmVhbSB7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgQ29ubmVjdGlvbiBvYmplY3QgdGhhdCBpcyBwdWJsaXNoaW5nIHRoZSBzdHJlYW1cbiAgICAgKi9cbiAgICBjb25uZWN0aW9uOiBDb25uZWN0aW9uO1xuXG4gICAgLyoqXG4gICAgICogRnJhbWUgcmF0ZSBvZiB0aGUgdmlkZW8gaW4gZnJhbWVzIHBlciBzZWNvbmQuIFRoaXMgcHJvcGVydHkgaXMgb25seSBkZWZpbmVkIGlmIHRoZSBbW1B1Ymxpc2hlcl1dIG9mXG4gICAgICogdGhlIHN0cmVhbSB3YXMgaW5pdGlhbGl6ZWQgcGFzc2luZyBhIF9mcmFtZVJhdGVfIHByb3BlcnR5IG9uIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dIG1ldGhvZFxuICAgICAqL1xuICAgIGZyYW1lUmF0ZT86IG51bWJlcjtcblxuICAgIC8qKlxuICAgICAqIFdoZXRoZXIgdGhlIHN0cmVhbSBoYXMgYSB2aWRlbyB0cmFjayBvciBub3RcbiAgICAgKi9cbiAgICBoYXNWaWRlbzogYm9vbGVhbjtcblxuICAgIC8qKlxuICAgICAqIFdoZXRoZXIgdGhlIHN0cmVhbSBoYXMgYW4gYXVkaW8gdHJhY2sgb3Igbm90XG4gICAgICovXG4gICAgaGFzQXVkaW86IGJvb2xlYW47XG5cbiAgICAvKipcbiAgICAgKiBXaGV0aGVyIHRoZSBzdHJlYW0gaGFzIHRoZSB2aWRlbyB0cmFjayBtdXRlZCBvciB1bm11dGVkLiBJZiBbW2hhc1ZpZGVvXV0gaXMgZmFsc2UsIHRoaXMgcHJvcGVydHkgaXMgdW5kZWZpbmVkLlxuICAgICAqXG4gICAgICogVGhpcyBwcm9wZXJ0eSBtYXkgY2hhbmdlIGlmIHRoZSBQdWJsaXNoZXIgcHVibGlzaGluZyB0aGUgc3RyZWFtIGNhbGxzIFtbUHVibGlzaGVyLnB1Ymxpc2hWaWRlb11dLiBXaGVuZXZlciB0aGlzIGhhcHBlbnMgYSBbW1N0cmVhbVByb3BlcnR5Q2hhbmdlZEV2ZW50XV0gd2lsbCBiZSBkaXNwYXRjaGVkXG4gICAgICogYnkgdGhlIFNlc3Npb24gb2JqZWN0IGFzIHdlbGwgYXMgYnkgdGhlIGFmZmVjdGVkIFN1YnNjcmliZXIvUHVibGlzaGVyIG9iamVjdFxuICAgICAqL1xuICAgIHZpZGVvQWN0aXZlOiBib29sZWFuO1xuXG4gICAgLyoqXG4gICAgICogV2hldGhlciB0aGUgc3RyZWFtIGhhcyB0aGUgYXVkaW8gdHJhY2sgbXV0ZWQgb3IgdW5tdXRlZC4gSWYgW1toYXNBdWRpb11dIGlzIGZhbHNlLCB0aGlzIHByb3BlcnR5IGlzIHVuZGVmaW5lZFxuICAgICAqXG4gICAgICogVGhpcyBwcm9wZXJ0eSBtYXkgY2hhbmdlIGlmIHRoZSBQdWJsaXNoZXIgcHVibGlzaGluZyB0aGUgc3RyZWFtIGNhbGxzIFtbUHVibGlzaGVyLnB1Ymxpc2hBdWRpb11dLiBXaGVuZXZlciB0aGlzIGhhcHBlbnMgYSBbW1N0cmVhbVByb3BlcnR5Q2hhbmdlZEV2ZW50XV0gd2lsbCBiZSBkaXNwYXRjaGVkXG4gICAgICogYnkgdGhlIFNlc3Npb24gb2JqZWN0IGFzIHdlbGwgYXMgYnkgdGhlIGFmZmVjdGVkIFN1YnNjcmliZXIvUHVibGlzaGVyIG9iamVjdFxuICAgICAqL1xuICAgIGF1ZGlvQWN0aXZlOiBib29sZWFuO1xuXG4gICAgLyoqXG4gICAgICogVW5pcXVlIGlkZW50aWZpZXIgb2YgdGhlIHN0cmVhbVxuICAgICAqL1xuICAgIHN0cmVhbUlkOiBzdHJpbmc7XG5cbiAgICAvKipcbiAgICAgKiBgXCJDQU1FUkFcImAsIGBcIlNDUkVFTlwiYCBvciBgXCJDVVNUT01cImAgKHRoZSBsYXR0ZXIgd2hlbiBbW1B1Ymxpc2hlclByb3BlcnRpZXMudmlkZW9Tb3VyY2VdXSBpcyBhIE1lZGlhU3RyZWFtVHJhY2sgd2hlbiBjYWxsaW5nIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dKS5cbiAgICAgKiBJZiBbW2hhc1ZpZGVvXV0gaXMgZmFsc2UsIHRoaXMgcHJvcGVydHkgaXMgdW5kZWZpbmVkXG4gICAgICovXG4gICAgdHlwZU9mVmlkZW8/OiBzdHJpbmc7XG5cbiAgICAvKipcbiAgICAgKiBTdHJlYW1NYW5hZ2VyIG9iamVjdCAoW1tQdWJsaXNoZXJdXSBvciBbW1N1YnNjcmliZXJdXSkgaW4gY2hhcmdlIG9mIGRpc3BsYXlpbmcgdGhpcyBzdHJlYW0gaW4gdGhlIERPTVxuICAgICAqL1xuICAgIHN0cmVhbU1hbmFnZXI6IFN0cmVhbU1hbmFnZXI7XG5cbiAgICAvKipcbiAgICAgKiBXaWR0aCBhbmQgaGVpZ2h0IGluIHBpeGVscyBvZiB0aGUgZW5jb2RlZCB2aWRlbyBzdHJlYW0uIElmIFtbaGFzVmlkZW9dXSBpcyBmYWxzZSwgdGhpcyBwcm9wZXJ0eSBpcyB1bmRlZmluZWRcbiAgICAgKlxuICAgICAqIFRoaXMgcHJvcGVydHkgbWF5IGNoYW5nZSBpZiB0aGUgUHVibGlzaGVyIHRoYXQgaXMgcHVibGlzaGluZzpcbiAgICAgKiAtIElmIGl0IGlzIGEgbW9iaWxlIGRldmljZSwgd2hlbmV2ZXIgdGhlIHVzZXIgcm90YXRlcyB0aGUgZGV2aWNlLlxuICAgICAqIC0gSWYgaXQgaXMgc2NyZWVuLXNoYXJpbmcsIHdoZW5ldmVyIHRoZSB1c2VyIGNoYW5nZXMgdGhlIHNpemUgb2YgdGhlIGNhcHR1cmVkIHdpbmRvdy5cbiAgICAgKlxuICAgICAqIFdoZW5ldmVyIHRoaXMgaGFwcGVucyBhIFtbU3RyZWFtUHJvcGVydHlDaGFuZ2VkRXZlbnRdXSB3aWxsIGJlIGRpc3BhdGNoZWQgYnkgdGhlIFNlc3Npb24gb2JqZWN0IGFzIHdlbGwgYXMgYnkgdGhlIGFmZmVjdGVkIFN1YnNjcmliZXIvUHVibGlzaGVyIG9iamVjdFxuICAgICAqL1xuICAgIHZpZGVvRGltZW5zaW9uczogeyB3aWR0aDogbnVtYmVyLCBoZWlnaHQ6IG51bWJlciB9O1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGVlID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuXG4gICAgcHJpdmF0ZSB3ZWJSdGNQZWVyOiBXZWJSdGNQZWVyO1xuICAgIHByaXZhdGUgbWVkaWFTdHJlYW06IE1lZGlhU3RyZWFtO1xuICAgIHByaXZhdGUgd2ViUnRjU3RhdHM6IFdlYlJ0Y1N0YXRzO1xuXG4gICAgcHJpdmF0ZSBpc1N1YnNjcmliZVRvUmVtb3RlID0gZmFsc2U7XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgaXNMb2NhbFN0cmVhbVJlYWR5VG9QdWJsaXNoID0gZmFsc2U7XG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGlzTG9jYWxTdHJlYW1QdWJsaXNoZWQgPSBmYWxzZTtcbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgcHVibGlzaGVkT25jZSA9IGZhbHNlO1xuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBzZXNzaW9uOiBTZXNzaW9uO1xuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBpbmJvdW5kU3RyZWFtT3B0czogSW5ib3VuZFN0cmVhbU9wdGlvbnM7XG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIG91dGJvdW5kU3RyZWFtT3B0czogT3V0Ym91bmRTdHJlYW1PcHRpb25zO1xuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBzcGVlY2hFdmVudDogYW55O1xuXG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgY29uc3RydWN0b3Ioc2Vzc2lvbjogU2Vzc2lvbiwgb3B0aW9uczogSW5ib3VuZFN0cmVhbU9wdGlvbnMgfCBPdXRib3VuZFN0cmVhbU9wdGlvbnMgfCB7fSkge1xuXG4gICAgICAgIHRoaXMuc2Vzc2lvbiA9IHNlc3Npb247XG5cbiAgICAgICAgaWYgKG9wdGlvbnMuaGFzT3duUHJvcGVydHkoJ2lkJykpIHtcbiAgICAgICAgICAgIC8vIEluYm91bmRTdHJlYW1PcHRpb25zOiBzdHJlYW0gYmVsb25ncyB0byBhIFN1YnNjcmliZXJcbiAgICAgICAgICAgIHRoaXMuaW5ib3VuZFN0cmVhbU9wdHMgPSA8SW5ib3VuZFN0cmVhbU9wdGlvbnM+b3B0aW9ucztcbiAgICAgICAgICAgIHRoaXMuc3RyZWFtSWQgPSB0aGlzLmluYm91bmRTdHJlYW1PcHRzLmlkO1xuICAgICAgICAgICAgdGhpcy5oYXNBdWRpbyA9IHRoaXMuaW5ib3VuZFN0cmVhbU9wdHMuaGFzQXVkaW87XG4gICAgICAgICAgICB0aGlzLmhhc1ZpZGVvID0gdGhpcy5pbmJvdW5kU3RyZWFtT3B0cy5oYXNWaWRlbztcbiAgICAgICAgICAgIGlmICh0aGlzLmhhc0F1ZGlvKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5hdWRpb0FjdGl2ZSA9IHRoaXMuaW5ib3VuZFN0cmVhbU9wdHMuYXVkaW9BY3RpdmU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodGhpcy5oYXNWaWRlbykge1xuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9BY3RpdmUgPSB0aGlzLmluYm91bmRTdHJlYW1PcHRzLnZpZGVvQWN0aXZlO1xuICAgICAgICAgICAgICAgIHRoaXMudHlwZU9mVmlkZW8gPSAoIXRoaXMuaW5ib3VuZFN0cmVhbU9wdHMudHlwZU9mVmlkZW8pID8gdW5kZWZpbmVkIDogdGhpcy5pbmJvdW5kU3RyZWFtT3B0cy50eXBlT2ZWaWRlbztcbiAgICAgICAgICAgICAgICB0aGlzLmZyYW1lUmF0ZSA9ICh0aGlzLmluYm91bmRTdHJlYW1PcHRzLmZyYW1lUmF0ZSA9PT0gLTEpID8gdW5kZWZpbmVkIDogdGhpcy5pbmJvdW5kU3RyZWFtT3B0cy5mcmFtZVJhdGU7XG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb0RpbWVuc2lvbnMgPSB0aGlzLmluYm91bmRTdHJlYW1PcHRzLnZpZGVvRGltZW5zaW9ucztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIE91dGJvdW5kU3RyZWFtT3B0aW9uczogc3RyZWFtIGJlbG9uZ3MgdG8gYSBQdWJsaXNoZXJcbiAgICAgICAgICAgIHRoaXMub3V0Ym91bmRTdHJlYW1PcHRzID0gPE91dGJvdW5kU3RyZWFtT3B0aW9ucz5vcHRpb25zO1xuXG4gICAgICAgICAgICB0aGlzLmhhc0F1ZGlvID0gdGhpcy5pc1NlbmRBdWRpbygpO1xuICAgICAgICAgICAgdGhpcy5oYXNWaWRlbyA9IHRoaXMuaXNTZW5kVmlkZW8oKTtcblxuICAgICAgICAgICAgaWYgKHRoaXMuaGFzQXVkaW8pIHtcbiAgICAgICAgICAgICAgICB0aGlzLmF1ZGlvQWN0aXZlID0gISF0aGlzLm91dGJvdW5kU3RyZWFtT3B0cy5wdWJsaXNoZXJQcm9wZXJ0aWVzLnB1Ymxpc2hBdWRpbztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0aGlzLmhhc1ZpZGVvKSB7XG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb0FjdGl2ZSA9ICEhdGhpcy5vdXRib3VuZFN0cmVhbU9wdHMucHVibGlzaGVyUHJvcGVydGllcy5wdWJsaXNoVmlkZW87XG4gICAgICAgICAgICAgICAgdGhpcy5mcmFtZVJhdGUgPSB0aGlzLm91dGJvdW5kU3RyZWFtT3B0cy5wdWJsaXNoZXJQcm9wZXJ0aWVzLmZyYW1lUmF0ZTtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5vdXRib3VuZFN0cmVhbU9wdHMucHVibGlzaGVyUHJvcGVydGllcy52aWRlb1NvdXJjZSBpbnN0YW5jZW9mIE1lZGlhU3RyZWFtVHJhY2spIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy50eXBlT2ZWaWRlbyA9ICdDVVNUT00nO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMudHlwZU9mVmlkZW8gPSB0aGlzLmlzU2VuZFNjcmVlbigpID8gJ1NDUkVFTicgOiAnQ0FNRVJBJztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLmVlLm9uKCdtZWRpYXN0cmVhbS11cGRhdGVkJywgKCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5zdHJlYW1NYW5hZ2VyLnVwZGF0ZU1lZGlhU3RyZWFtKHRoaXMubWVkaWFTdHJlYW0pO1xuICAgICAgICAgICAgY29uc29sZS5kZWJ1ZygnVmlkZW8gc3JjT2JqZWN0IFsnICsgdGhpcy5tZWRpYVN0cmVhbSArICddIHVwZGF0ZWQgaW4gc3RyZWFtIFsnICsgdGhpcy5zdHJlYW1JZCArICddJyk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuXG4gICAgLyogSGlkZGVuIG1ldGhvZHMgKi9cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBnZXRNZWRpYVN0cmVhbSgpOiBNZWRpYVN0cmVhbSB7XG4gICAgICAgIHJldHVybiB0aGlzLm1lZGlhU3RyZWFtO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBzZXRNZWRpYVN0cmVhbShtZWRpYVN0cmVhbTogTWVkaWFTdHJlYW0pOiB2b2lkIHtcbiAgICAgICAgdGhpcy5tZWRpYVN0cmVhbSA9IG1lZGlhU3RyZWFtO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICB1cGRhdGVNZWRpYVN0cmVhbUluVmlkZW9zKCkge1xuICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnbWVkaWFzdHJlYW0tdXBkYXRlZCcpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBnZXRXZWJSdGNQZWVyKCk6IFdlYlJ0Y1BlZXIge1xuICAgICAgICByZXR1cm4gdGhpcy53ZWJSdGNQZWVyO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBnZXRSVENQZWVyQ29ubmVjdGlvbigpOiBSVENQZWVyQ29ubmVjdGlvbiB7XG4gICAgICAgIHJldHVybiB0aGlzLndlYlJ0Y1BlZXIucGM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHN1YnNjcmliZVRvTXlSZW1vdGUodmFsdWU6IGJvb2xlYW4pOiB2b2lkIHtcbiAgICAgICAgdGhpcy5pc1N1YnNjcmliZVRvUmVtb3RlID0gdmFsdWU7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHNldE91dGJvdW5kU3RyZWFtT3B0aW9ucyhvdXRib3VuZFN0cmVhbU9wdHM6IE91dGJvdW5kU3RyZWFtT3B0aW9ucyk6IHZvaWQge1xuICAgICAgICB0aGlzLm91dGJvdW5kU3RyZWFtT3B0cyA9IG91dGJvdW5kU3RyZWFtT3B0cztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgc3Vic2NyaWJlKCk6IFByb21pc2U8YW55PiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICB0aGlzLmluaXRXZWJSdGNQZWVyUmVjZWl2ZSgpXG4gICAgICAgICAgICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgcHVibGlzaCgpOiBQcm9taXNlPGFueT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgaWYgKHRoaXMuaXNMb2NhbFN0cmVhbVJlYWR5VG9QdWJsaXNoKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5pbml0V2ViUnRjUGVlclNlbmQoKVxuICAgICAgICAgICAgICAgICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy5lZS5vbmNlKCdzdHJlYW0tcmVhZHktdG8tcHVibGlzaCcsICgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5wdWJsaXNoKClcbiAgICAgICAgICAgICAgICAgICAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgICAgICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBkaXNwb3NlV2ViUnRjUGVlcigpOiB2b2lkIHtcbiAgICAgICAgaWYgKHRoaXMud2ViUnRjUGVlcikge1xuICAgICAgICAgICAgdGhpcy53ZWJSdGNQZWVyLmRpc3Bvc2UoKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5zcGVlY2hFdmVudCkge1xuICAgICAgICAgICAgdGhpcy5zcGVlY2hFdmVudC5zdG9wKCk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLnN0b3BXZWJSdGNTdGF0cygpO1xuXG4gICAgICAgIGNvbnNvbGUuaW5mbygoISF0aGlzLm91dGJvdW5kU3RyZWFtT3B0cyA/ICdPdXRib3VuZCAnIDogJ0luYm91bmQgJykgKyBcIldlYlJUQ1BlZXIgZnJvbSAnU3RyZWFtJyB3aXRoIGlkIFtcIiArIHRoaXMuc3RyZWFtSWQgKyAnXSBpcyBub3cgY2xvc2VkJyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGRpc3Bvc2VNZWRpYVN0cmVhbSgpOiB2b2lkIHtcbiAgICAgICAgaWYgKHRoaXMubWVkaWFTdHJlYW0pIHtcbiAgICAgICAgICAgIHRoaXMubWVkaWFTdHJlYW0uZ2V0QXVkaW9UcmFja3MoKS5mb3JFYWNoKCh0cmFjaykgPT4ge1xuICAgICAgICAgICAgICAgIHRyYWNrLnN0b3AoKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgdGhpcy5tZWRpYVN0cmVhbS5nZXRWaWRlb1RyYWNrcygpLmZvckVhY2goKHRyYWNrKSA9PiB7XG4gICAgICAgICAgICAgICAgdHJhY2suc3RvcCgpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBkZWxldGUgdGhpcy5tZWRpYVN0cmVhbTtcbiAgICAgICAgfVxuICAgICAgICBjb25zb2xlLmluZm8oKCEhdGhpcy5vdXRib3VuZFN0cmVhbU9wdHMgPyAnTG9jYWwgJyA6ICdSZW1vdGUgJykgKyBcIk1lZGlhU3RyZWFtIGZyb20gJ1N0cmVhbScgd2l0aCBpZCBbXCIgKyB0aGlzLnN0cmVhbUlkICsgJ10gaXMgbm93IGRpc3Bvc2VkJyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGRpc3BsYXlNeVJlbW90ZSgpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuaXNTdWJzY3JpYmVUb1JlbW90ZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgaXNTZW5kQXVkaW8oKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiAoISF0aGlzLm91dGJvdW5kU3RyZWFtT3B0cyAmJlxuICAgICAgICAgICAgdGhpcy5vdXRib3VuZFN0cmVhbU9wdHMucHVibGlzaGVyUHJvcGVydGllcy5hdWRpb1NvdXJjZSAhPT0gbnVsbCAmJlxuICAgICAgICAgICAgdGhpcy5vdXRib3VuZFN0cmVhbU9wdHMucHVibGlzaGVyUHJvcGVydGllcy5hdWRpb1NvdXJjZSAhPT0gZmFsc2UpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBpc1NlbmRWaWRlbygpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuICghIXRoaXMub3V0Ym91bmRTdHJlYW1PcHRzICYmXG4gICAgICAgICAgICB0aGlzLm91dGJvdW5kU3RyZWFtT3B0cy5wdWJsaXNoZXJQcm9wZXJ0aWVzLnZpZGVvU291cmNlICE9PSBudWxsICYmXG4gICAgICAgICAgICB0aGlzLm91dGJvdW5kU3RyZWFtT3B0cy5wdWJsaXNoZXJQcm9wZXJ0aWVzLnZpZGVvU291cmNlICE9PSBmYWxzZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGlzU2VuZFNjcmVlbigpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuICghIXRoaXMub3V0Ym91bmRTdHJlYW1PcHRzICYmXG4gICAgICAgICAgICB0aGlzLm91dGJvdW5kU3RyZWFtT3B0cy5wdWJsaXNoZXJQcm9wZXJ0aWVzLnZpZGVvU291cmNlID09PSAnc2NyZWVuJyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHNldFNwZWVjaEV2ZW50SWZOb3RFeGlzdHMoKTogdm9pZCB7XG4gICAgICAgIGlmICghdGhpcy5zcGVlY2hFdmVudCkge1xuICAgICAgICAgICAgY29uc3QgaGFya09wdGlvbnMgPSB0aGlzLnNlc3Npb24ub3BlbnZpZHUuYWR2YW5jZWRDb25maWd1cmF0aW9uLnB1Ymxpc2hlclNwZWFraW5nRXZlbnRzT3B0aW9ucyB8fCB7fTtcbiAgICAgICAgICAgIGhhcmtPcHRpb25zLmludGVydmFsID0gKHR5cGVvZiBoYXJrT3B0aW9ucy5pbnRlcnZhbCA9PT0gJ251bWJlcicpID8gaGFya09wdGlvbnMuaW50ZXJ2YWwgOiA1MDtcbiAgICAgICAgICAgIGhhcmtPcHRpb25zLnRocmVzaG9sZCA9ICh0eXBlb2YgaGFya09wdGlvbnMudGhyZXNob2xkID09PSAnbnVtYmVyJykgPyBoYXJrT3B0aW9ucy50aHJlc2hvbGQgOiAtNTA7XG5cbiAgICAgICAgICAgIHRoaXMuc3BlZWNoRXZlbnQgPSBoYXJrKHRoaXMubWVkaWFTdHJlYW0sIGhhcmtPcHRpb25zKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBlbmFibGVTcGVha2luZ0V2ZW50cygpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5zZXRTcGVlY2hFdmVudElmTm90RXhpc3RzKCk7XG4gICAgICAgIHRoaXMuc3BlZWNoRXZlbnQub24oJ3NwZWFraW5nJywgKCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5zZXNzaW9uLmVtaXRFdmVudCgncHVibGlzaGVyU3RhcnRTcGVha2luZycsIFtuZXcgUHVibGlzaGVyU3BlYWtpbmdFdmVudCh0aGlzLnNlc3Npb24sICdwdWJsaXNoZXJTdGFydFNwZWFraW5nJywgdGhpcy5jb25uZWN0aW9uLCB0aGlzLnN0cmVhbUlkKV0pO1xuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy5zcGVlY2hFdmVudC5vbignc3RvcHBlZF9zcGVha2luZycsICgpID0+IHtcbiAgICAgICAgICAgIHRoaXMuc2Vzc2lvbi5lbWl0RXZlbnQoJ3B1Ymxpc2hlclN0b3BTcGVha2luZycsIFtuZXcgUHVibGlzaGVyU3BlYWtpbmdFdmVudCh0aGlzLnNlc3Npb24sICdwdWJsaXNoZXJTdG9wU3BlYWtpbmcnLCB0aGlzLmNvbm5lY3Rpb24sIHRoaXMuc3RyZWFtSWQpXSk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBlbmFibGVPbmNlU3BlYWtpbmdFdmVudHMoKTogdm9pZCB7XG4gICAgICAgIHRoaXMuc2V0U3BlZWNoRXZlbnRJZk5vdEV4aXN0cygpO1xuICAgICAgICB0aGlzLnNwZWVjaEV2ZW50Lm9uKCdzcGVha2luZycsICgpID0+IHtcbiAgICAgICAgICAgIHRoaXMuc2Vzc2lvbi5lbWl0RXZlbnQoJ3B1Ymxpc2hlclN0YXJ0U3BlYWtpbmcnLCBbbmV3IFB1Ymxpc2hlclNwZWFraW5nRXZlbnQodGhpcy5zZXNzaW9uLCAncHVibGlzaGVyU3RhcnRTcGVha2luZycsIHRoaXMuY29ubmVjdGlvbiwgdGhpcy5zdHJlYW1JZCldKTtcbiAgICAgICAgICAgIHRoaXMuZGlzYWJsZVNwZWFraW5nRXZlbnRzKCk7XG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLnNwZWVjaEV2ZW50Lm9uKCdzdG9wcGVkX3NwZWFraW5nJywgKCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5zZXNzaW9uLmVtaXRFdmVudCgncHVibGlzaGVyU3RvcFNwZWFraW5nJywgW25ldyBQdWJsaXNoZXJTcGVha2luZ0V2ZW50KHRoaXMuc2Vzc2lvbiwgJ3B1Ymxpc2hlclN0b3BTcGVha2luZycsIHRoaXMuY29ubmVjdGlvbiwgdGhpcy5zdHJlYW1JZCldKTtcbiAgICAgICAgICAgIHRoaXMuZGlzYWJsZVNwZWFraW5nRXZlbnRzKCk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBkaXNhYmxlU3BlYWtpbmdFdmVudHMoKTogdm9pZCB7XG4gICAgICAgIHRoaXMuc3BlZWNoRXZlbnQuc3RvcCgpO1xuICAgICAgICB0aGlzLnNwZWVjaEV2ZW50ID0gdW5kZWZpbmVkO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBpc0xvY2FsKCk6IGJvb2xlYW4ge1xuICAgICAgICAvLyBpbmJvdW5kIG9wdGlvbnMgdW5kZWZpbmVkIGFuZCBvdXRib3VuZCBvcHRpb25zIGRlZmluZWRcbiAgICAgICAgcmV0dXJuICghdGhpcy5pbmJvdW5kU3RyZWFtT3B0cyAmJiAhIXRoaXMub3V0Ym91bmRTdHJlYW1PcHRzKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgZ2V0U2VsZWN0ZWRJY2VDYW5kaWRhdGUoKTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIHRoaXMud2ViUnRjU3RhdHMuZ2V0U2VsZWN0ZWRJY2VDYW5kaWRhdGVJbmZvKClcbiAgICAgICAgICAgICAgICAudGhlbihyZXBvcnQgPT4gcmVzb2x2ZShyZXBvcnQpKVxuICAgICAgICAgICAgICAgIC5jYXRjaChlcnJvciA9PiByZWplY3QoZXJyb3IpKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGdldFJlbW90ZUljZUNhbmRpZGF0ZUxpc3QoKTogUlRDSWNlQ2FuZGlkYXRlW10ge1xuICAgICAgICByZXR1cm4gdGhpcy53ZWJSdGNQZWVyLnJlbW90ZUNhbmRpZGF0ZXNRdWV1ZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgZ2V0TG9jYWxJY2VDYW5kaWRhdGVMaXN0KCk6IFJUQ0ljZUNhbmRpZGF0ZVtdIHtcbiAgICAgICAgcmV0dXJuIHRoaXMud2ViUnRjUGVlci5sb2NhbENhbmRpZGF0ZXNRdWV1ZTtcbiAgICB9XG5cbiAgICAvKiBQcml2YXRlIG1ldGhvZHMgKi9cblxuICAgIHByaXZhdGUgaW5pdFdlYlJ0Y1BlZXJTZW5kKCk6IFByb21pc2U8YW55PiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG5cbiAgICAgICAgICAgIGNvbnN0IHVzZXJNZWRpYUNvbnN0cmFpbnRzID0ge1xuICAgICAgICAgICAgICAgIGF1ZGlvOiB0aGlzLmlzU2VuZEF1ZGlvKCksXG4gICAgICAgICAgICAgICAgdmlkZW86IHRoaXMuaXNTZW5kVmlkZW8oKVxuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgY29uc3Qgb3B0aW9ucyA9IHtcbiAgICAgICAgICAgICAgICBtZWRpYVN0cmVhbTogdGhpcy5tZWRpYVN0cmVhbSxcbiAgICAgICAgICAgICAgICBtZWRpYUNvbnN0cmFpbnRzOiB1c2VyTWVkaWFDb25zdHJhaW50cyxcbiAgICAgICAgICAgICAgICBvbmljZWNhbmRpZGF0ZTogdGhpcy5jb25uZWN0aW9uLnNlbmRJY2VDYW5kaWRhdGUuYmluZCh0aGlzLmNvbm5lY3Rpb24pLFxuICAgICAgICAgICAgICAgIGljZVNlcnZlcnM6IHRoaXMuZ2V0SWNlU2VydmVyc0NvbmYoKSxcbiAgICAgICAgICAgICAgICBzaW11bGNhc3Q6IGZhbHNlXG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICBjb25zdCBzdWNjZXNzQ2FsbGJhY2sgPSAoc2RwT2ZmZXJQYXJhbSkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuZGVidWcoJ1NlbmRpbmcgU0RQIG9mZmVyIHRvIHB1Ymxpc2ggYXMgJ1xuICAgICAgICAgICAgICAgICAgICArIHRoaXMuc3RyZWFtSWQsIHNkcE9mZmVyUGFyYW0pO1xuXG4gICAgICAgICAgICAgICAgbGV0IHR5cGVPZlZpZGVvID0gJyc7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuaXNTZW5kVmlkZW8oKSkge1xuICAgICAgICAgICAgICAgICAgICB0eXBlT2ZWaWRlbyA9IHRoaXMub3V0Ym91bmRTdHJlYW1PcHRzLnB1Ymxpc2hlclByb3BlcnRpZXMudmlkZW9Tb3VyY2UgaW5zdGFuY2VvZiBNZWRpYVN0cmVhbVRyYWNrID8gJ0NVU1RPTScgOiAodGhpcy5pc1NlbmRTY3JlZW4oKSA/ICdTQ1JFRU4nIDogJ0NBTUVSQScpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMuc2Vzc2lvbi5vcGVudmlkdS5zZW5kUmVxdWVzdCgncHVibGlzaFZpZGVvJywge1xuICAgICAgICAgICAgICAgICAgICBzZHBPZmZlcjogc2RwT2ZmZXJQYXJhbSxcbiAgICAgICAgICAgICAgICAgICAgZG9Mb29wYmFjazogdGhpcy5kaXNwbGF5TXlSZW1vdGUoKSB8fCBmYWxzZSxcbiAgICAgICAgICAgICAgICAgICAgaGFzQXVkaW86IHRoaXMuaXNTZW5kQXVkaW8oKSxcbiAgICAgICAgICAgICAgICAgICAgaGFzVmlkZW86IHRoaXMuaXNTZW5kVmlkZW8oKSxcbiAgICAgICAgICAgICAgICAgICAgYXVkaW9BY3RpdmU6IHRoaXMuYXVkaW9BY3RpdmUsXG4gICAgICAgICAgICAgICAgICAgIHZpZGVvQWN0aXZlOiB0aGlzLnZpZGVvQWN0aXZlLFxuICAgICAgICAgICAgICAgICAgICB0eXBlT2ZWaWRlbyxcbiAgICAgICAgICAgICAgICAgICAgZnJhbWVSYXRlOiAhIXRoaXMuZnJhbWVSYXRlID8gdGhpcy5mcmFtZVJhdGUgOiAtMSxcbiAgICAgICAgICAgICAgICAgICAgdmlkZW9EaW1lbnNpb25zOiBKU09OLnN0cmluZ2lmeSh0aGlzLnZpZGVvRGltZW5zaW9ucylcbiAgICAgICAgICAgICAgICB9LCAoZXJyb3IsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yLmNvZGUgPT09IDQwMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChuZXcgT3BlblZpZHVFcnJvcihPcGVuVmlkdUVycm9yTmFtZS5PUEVOVklEVV9QRVJNSVNTSU9OX0RFTklFRCwgXCJZb3UgZG9uJ3QgaGF2ZSBwZXJtaXNzaW9ucyB0byBwdWJsaXNoXCIpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KCdFcnJvciBvbiBwdWJsaXNoVmlkZW86ICcgKyBKU09OLnN0cmluZ2lmeShlcnJvcikpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy53ZWJSdGNQZWVyLnByb2Nlc3NBbnN3ZXIocmVzcG9uc2Uuc2RwQW5zd2VyKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdHJlYW1JZCA9IHJlc3BvbnNlLmlkO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmlzTG9jYWxTdHJlYW1QdWJsaXNoZWQgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnB1Ymxpc2hlZE9uY2UgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5kaXNwbGF5TXlSZW1vdGUoKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5yZW1vdGVQZWVyU3VjY2Vzc2Z1bGx5RXN0YWJsaXNoZWQoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnc3RyZWFtLWNyZWF0ZWQtYnktcHVibGlzaGVyJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuaW5pdFdlYlJ0Y1N0YXRzKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oXCInUHVibGlzaGVyJyBzdWNjZXNzZnVsbHkgcHVibGlzaGVkIHRvIHNlc3Npb25cIik7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIGlmICh0aGlzLmRpc3BsYXlNeVJlbW90ZSgpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy53ZWJSdGNQZWVyID0gbmV3IFdlYlJ0Y1BlZXJTZW5kcmVjdihvcHRpb25zKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy53ZWJSdGNQZWVyID0gbmV3IFdlYlJ0Y1BlZXJTZW5kb25seShvcHRpb25zKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMud2ViUnRjUGVlci5nZW5lcmF0ZU9mZmVyKCkudGhlbihvZmZlciA9PiB7XG4gICAgICAgICAgICAgICAgc3VjY2Vzc0NhbGxiYWNrKG9mZmVyKTtcbiAgICAgICAgICAgIH0pLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICAgICAgICByZWplY3QobmV3IEVycm9yKCcocHVibGlzaCkgU0RQIG9mZmVyIGVycm9yOiAnICsgSlNPTi5zdHJpbmdpZnkoZXJyb3IpKSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBpbml0V2ViUnRjUGVlclJlY2VpdmUoKTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcblxuICAgICAgICAgICAgY29uc3Qgb2ZmZXJDb25zdHJhaW50cyA9IHtcbiAgICAgICAgICAgICAgICBhdWRpbzogdGhpcy5pbmJvdW5kU3RyZWFtT3B0cy5oYXNBdWRpbyxcbiAgICAgICAgICAgICAgICB2aWRlbzogdGhpcy5pbmJvdW5kU3RyZWFtT3B0cy5oYXNWaWRlb1xuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGNvbnNvbGUuZGVidWcoXCInU2Vzc2lvbi5zdWJzY3JpYmUoU3RyZWFtKScgY2FsbGVkLiBDb25zdHJhaW50cyBvZiBnZW5lcmF0ZSBTRFAgb2ZmZXJcIixcbiAgICAgICAgICAgICAgICBvZmZlckNvbnN0cmFpbnRzKTtcbiAgICAgICAgICAgIGNvbnN0IG9wdGlvbnMgPSB7XG4gICAgICAgICAgICAgICAgb25pY2VjYW5kaWRhdGU6IHRoaXMuY29ubmVjdGlvbi5zZW5kSWNlQ2FuZGlkYXRlLmJpbmQodGhpcy5jb25uZWN0aW9uKSxcbiAgICAgICAgICAgICAgICBtZWRpYUNvbnN0cmFpbnRzOiBvZmZlckNvbnN0cmFpbnRzLFxuICAgICAgICAgICAgICAgIGljZVNlcnZlcnM6IHRoaXMuZ2V0SWNlU2VydmVyc0NvbmYoKSxcbiAgICAgICAgICAgICAgICBzaW11bGNhc3Q6IGZhbHNlXG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICBjb25zdCBzdWNjZXNzQ2FsbGJhY2sgPSAoc2RwT2ZmZXJQYXJhbSkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuZGVidWcoJ1NlbmRpbmcgU0RQIG9mZmVyIHRvIHN1YnNjcmliZSB0byAnXG4gICAgICAgICAgICAgICAgICAgICsgdGhpcy5zdHJlYW1JZCwgc2RwT2ZmZXJQYXJhbSk7XG4gICAgICAgICAgICAgICAgdGhpcy5zZXNzaW9uLm9wZW52aWR1LnNlbmRSZXF1ZXN0KCdyZWNlaXZlVmlkZW9Gcm9tJywge1xuICAgICAgICAgICAgICAgICAgICBzZW5kZXI6IHRoaXMuc3RyZWFtSWQsXG4gICAgICAgICAgICAgICAgICAgIHNkcE9mZmVyOiBzZHBPZmZlclBhcmFtXG4gICAgICAgICAgICAgICAgfSwgKGVycm9yLCByZXNwb25zZSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBpZiAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChuZXcgRXJyb3IoJ0Vycm9yIG9uIHJlY3ZWaWRlb0Zyb206ICcgKyBKU09OLnN0cmluZ2lmeShlcnJvcikpKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMud2ViUnRjUGVlci5wcm9jZXNzQW5zd2VyKHJlc3BvbnNlLnNkcEFuc3dlcikudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5yZW1vdGVQZWVyU3VjY2Vzc2Z1bGx5RXN0YWJsaXNoZWQoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmluaXRXZWJSdGNTdGF0cygpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIHRoaXMud2ViUnRjUGVlciA9IG5ldyBXZWJSdGNQZWVyUmVjdm9ubHkob3B0aW9ucyk7XG4gICAgICAgICAgICB0aGlzLndlYlJ0Y1BlZXIuZ2VuZXJhdGVPZmZlcigpXG4gICAgICAgICAgICAgICAgLnRoZW4ob2ZmZXIgPT4ge1xuICAgICAgICAgICAgICAgICAgICBzdWNjZXNzQ2FsbGJhY2sob2ZmZXIpO1xuICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICAgICAgICAgICAgcmVqZWN0KG5ldyBFcnJvcignKHN1YnNjcmliZSkgU0RQIG9mZmVyIGVycm9yOiAnICsgSlNPTi5zdHJpbmdpZnkoZXJyb3IpKSk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIHByaXZhdGUgcmVtb3RlUGVlclN1Y2Nlc3NmdWxseUVzdGFibGlzaGVkKCk6IHZvaWQge1xuICAgICAgICB0aGlzLm1lZGlhU3RyZWFtID0gdGhpcy53ZWJSdGNQZWVyLnBjLmdldFJlbW90ZVN0cmVhbXMoKVswXTtcbiAgICAgICAgY29uc29sZS5kZWJ1ZygnUGVlciByZW1vdGUgc3RyZWFtJywgdGhpcy5tZWRpYVN0cmVhbSk7XG5cbiAgICAgICAgaWYgKCEhdGhpcy5tZWRpYVN0cmVhbSkge1xuICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ21lZGlhc3RyZWFtLXVwZGF0ZWQnKTtcbiAgICAgICAgICAgIGlmICghdGhpcy5kaXNwbGF5TXlSZW1vdGUoKSAmJiAhIXRoaXMubWVkaWFTdHJlYW0uZ2V0QXVkaW9UcmFja3MoKVswXSAmJiB0aGlzLnNlc3Npb24uc3BlYWtpbmdFdmVudHNFbmFibGVkKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5lbmFibGVTcGVha2luZ0V2ZW50cygpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBpbml0V2ViUnRjU3RhdHMoKTogdm9pZCB7XG4gICAgICAgIHRoaXMud2ViUnRjU3RhdHMgPSBuZXcgV2ViUnRjU3RhdHModGhpcyk7XG4gICAgICAgIHRoaXMud2ViUnRjU3RhdHMuaW5pdFdlYlJ0Y1N0YXRzKCk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBzdG9wV2ViUnRjU3RhdHMoKTogdm9pZCB7XG4gICAgICAgIGlmICghIXRoaXMud2ViUnRjU3RhdHMgJiYgdGhpcy53ZWJSdGNTdGF0cy5pc0VuYWJsZWQoKSkge1xuICAgICAgICAgICAgdGhpcy53ZWJSdGNTdGF0cy5zdG9wV2ViUnRjU3RhdHMoKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgZ2V0SWNlU2VydmVyc0NvbmYoKTogUlRDSWNlU2VydmVyW10gfCB1bmRlZmluZWQge1xuICAgICAgICBsZXQgcmV0dXJuVmFsdWU7XG4gICAgICAgIGlmICghIXRoaXMuc2Vzc2lvbi5vcGVudmlkdS5hZHZhbmNlZENvbmZpZ3VyYXRpb24uaWNlU2VydmVycykge1xuICAgICAgICAgICAgcmV0dXJuVmFsdWUgPSB0aGlzLnNlc3Npb24ub3BlbnZpZHUuYWR2YW5jZWRDb25maWd1cmF0aW9uLmljZVNlcnZlcnMgPT09ICdmcmVlaWNlJyA/XG4gICAgICAgICAgICAgICAgdW5kZWZpbmVkIDpcbiAgICAgICAgICAgICAgICB0aGlzLnNlc3Npb24ub3BlbnZpZHUuYWR2YW5jZWRDb25maWd1cmF0aW9uLmljZVNlcnZlcnM7XG4gICAgICAgIH0gZWxzZSBpZiAodGhpcy5zZXNzaW9uLm9wZW52aWR1LmljZVNlcnZlcnMpIHtcbiAgICAgICAgICAgIHJldHVyblZhbHVlID0gdGhpcy5zZXNzaW9uLm9wZW52aWR1LmljZVNlcnZlcnM7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm5WYWx1ZSA9IHVuZGVmaW5lZDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcmV0dXJuVmFsdWU7XG4gICAgfVxuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBTdHJlYW0gfSBmcm9tICcuL1N0cmVhbSc7XG5pbXBvcnQgeyBFdmVudERpc3BhdGNoZXIgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHVibGljL0V2ZW50RGlzcGF0Y2hlcic7XG5pbXBvcnQgeyBTdHJlYW1NYW5hZ2VyVmlkZW8gfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHVibGljL1N0cmVhbU1hbmFnZXJWaWRlbyc7XG5pbXBvcnQgeyBFdmVudCB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL0V2ZW50JztcbmltcG9ydCB7IFN0cmVhbU1hbmFnZXJFdmVudCB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1N0cmVhbU1hbmFnZXJFdmVudCc7XG5pbXBvcnQgeyBWaWRlb0VsZW1lbnRFdmVudCB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1ZpZGVvRWxlbWVudEV2ZW50JztcbmltcG9ydCB7IFZpZGVvSW5zZXJ0TW9kZSB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRW51bXMvVmlkZW9JbnNlcnRNb2RlJztcblxuaW1wb3J0IEV2ZW50RW1pdHRlciA9IHJlcXVpcmUoJ3dvbGZ5ODctZXZlbnRlbWl0dGVyJyk7XG5cblxuLyoqXG4gKiBJbnRlcmZhY2UgaW4gY2hhcmdlIG9mIGRpc3BsYXlpbmcgdGhlIG1lZGlhIHN0cmVhbXMgaW4gdGhlIEhUTUwgRE9NLiBUaGlzIHdyYXBzIGFueSBbW1B1Ymxpc2hlcl1dIGFuZCBbW1N1YnNjcmliZXJdXSBvYmplY3QuXG4gKiBZb3UgY2FuIGluc2VydCBhcyBtYW55IHZpZGVvIHBsYXllcnMgZm8gdGhlIHNhbWUgU3RyZWFtIGFzIHlvdSB3YW50IGJ5IGNhbGxpbmcgW1tTdHJlYW1NYW5hZ2VyLmFkZFZpZGVvRWxlbWVudF1dIG9yXG4gKiBbW1N0cmVhbU1hbmFnZXIuY3JlYXRlVmlkZW9FbGVtZW50XV0uXG4gKlxuICogVGhlIHVzZSBvZiBTdHJlYW1NYW5hZ2VyIHdyYXBwZXIgaXMgcGFydGljdWxhcmx5IHVzZWZ1bCB3aGVuIHlvdSBkb24ndCBuZWVkIHRvIGRpZmZlcmVudGlhdGUgYmV0d2VlbiBQdWJsaXNoZXIgb3IgU3Vic2NyaWJlciBzdHJlYW1zIG9yIGp1c3RcbiAqIHdhbnQgdG8gZGlyZWN0bHkgbWFuYWdlIHlvdXIgb3duIHZpZGVvIGVsZW1lbnRzIChldmVuIG1vcmUgdGhhbiBvbmUgdmlkZW8gZWxlbWVudCBwZXIgU3RyZWFtKS4gVGhpcyBzY2VuYXJpbyBpcyBwcmV0dHkgY29tbW9uIGluXG4gKiBkZWNsYXJhdGl2ZSwgTVZDIGZyb250ZW5kIGZyYW1ld29ya3Mgc3VjaCBhcyBBbmd1bGFyLCBSZWFjdCBvciBWdWUuanNcbiAqL1xuZXhwb3J0IGNsYXNzIFN0cmVhbU1hbmFnZXIgaW1wbGVtZW50cyBFdmVudERpc3BhdGNoZXIge1xuXG4gICAgLyoqXG4gICAgICogVGhlIFN0cmVhbSByZXByZXNlbnRlZCBpbiB0aGUgRE9NIGJ5IHRoZSBQdWJsaXNoZXIvU3Vic2NyaWJlclxuICAgICAqL1xuICAgIHN0cmVhbTogU3RyZWFtO1xuXG4gICAgLyoqXG4gICAgICogQWxsIHRoZSB2aWRlb3MgZGlzcGxheWluZyB0aGUgU3RyZWFtIG9mIHRoaXMgUHVibGlzaGVyL1N1YnNjcmliZXJcbiAgICAgKi9cbiAgICB2aWRlb3M6IFN0cmVhbU1hbmFnZXJWaWRlb1tdID0gW107XG5cbiAgICAvKipcbiAgICAgKiBXaGV0aGVyIHRoZSBTdHJlYW0gcmVwcmVzZW50ZWQgaW4gdGhlIERPTSBpcyBsb2NhbCBvciByZW1vdGVcbiAgICAgKiAtIGBmYWxzZWAgZm9yIFtbUHVibGlzaGVyXV1cbiAgICAgKiAtIGB0cnVlYCBmb3IgW1tTdWJzY3JpYmVyXV1cbiAgICAgKi9cbiAgICByZW1vdGU6IGJvb2xlYW47XG5cbiAgICAvKipcbiAgICAgKiBUaGUgRE9NIEhUTUxFbGVtZW50IGFzc2lnbmVkIGFzIHRhcmdldCBlbGVtZW50IHdoZW4gY3JlYXRpbmcgdGhlIHZpZGVvIGZvciB0aGUgUHVibGlzaGVyL1N1YnNjcmliZXIuIFRoaXMgcHJvcGVydHkgaXMgb25seSBkZWZpbmVkIGlmOlxuICAgICAqIC0gW1tQdWJsaXNoZXJdXSBoYXMgYmVlbiBpbml0aWFsaXplZCBieSBjYWxsaW5nIG1ldGhvZCBbW09wZW5WaWR1LmluaXRQdWJsaXNoZXJdXSB3aXRoIGEgdmFsaWQgYHRhcmdldEVsZW1lbnRgIHBhcmFtZXRlclxuICAgICAqIC0gW1tTdWJzY3JpYmVyXV0gaGFzIGJlZW4gaW5pdGlhbGl6ZWQgYnkgY2FsbGluZyBtZXRob2QgW1tTZXNzaW9uLnN1YnNjcmliZV1dIHdpdGggYSB2YWxpZCBgdGFyZ2V0RWxlbWVudGAgcGFyYW1ldGVyXG4gICAgICovXG4gICAgdGFyZ2V0RWxlbWVudDogSFRNTEVsZW1lbnQ7XG5cbiAgICAvKipcbiAgICAgKiBgaWRgIGF0dHJpYnV0ZSBvZiB0aGUgRE9NIHZpZGVvIGVsZW1lbnQgZGlzcGxheWluZyB0aGUgUHVibGlzaGVyL1N1YnNjcmliZXIncyBzdHJlYW0uIFRoaXMgcHJvcGVydHkgaXMgb25seSBkZWZpbmVkIGlmOlxuICAgICAqIC0gW1tQdWJsaXNoZXJdXSBoYXMgYmVlbiBpbml0aWFsaXplZCBieSBjYWxsaW5nIG1ldGhvZCBbW09wZW5WaWR1LmluaXRQdWJsaXNoZXJdXSB3aXRoIGEgdmFsaWQgYHRhcmdldEVsZW1lbnRgIHBhcmFtZXRlclxuICAgICAqIC0gW1tTdWJzY3JpYmVyXV0gaGFzIGJlZW4gaW5pdGlhbGl6ZWQgYnkgY2FsbGluZyBtZXRob2QgW1tTZXNzaW9uLnN1YnNjcmliZV1dIHdpdGggYSB2YWxpZCBgdGFyZ2V0RWxlbWVudGAgcGFyYW1ldGVyXG4gICAgICovXG4gICAgaWQ6IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBmaXJzdFZpZGVvRWxlbWVudDogU3RyZWFtTWFuYWdlclZpZGVvO1xuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBsYXp5TGF1bmNoVmlkZW9FbGVtZW50Q3JlYXRlZEV2ZW50ID0gZmFsc2U7XG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGVsZW1lbnQ6IEhUTUxFbGVtZW50O1xuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgZWUgPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHByb3RlY3RlZCBjYW5QbGF5TGlzdGVuZXI6IEV2ZW50TGlzdGVuZXJPckV2ZW50TGlzdGVuZXJPYmplY3Q7XG5cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3RvcihzdHJlYW06IFN0cmVhbSwgdGFyZ2V0RWxlbWVudD86IEhUTUxFbGVtZW50IHwgc3RyaW5nKSB7XG4gICAgICAgIHRoaXMuc3RyZWFtID0gc3RyZWFtO1xuICAgICAgICB0aGlzLnN0cmVhbS5zdHJlYW1NYW5hZ2VyID0gdGhpcztcbiAgICAgICAgdGhpcy5yZW1vdGUgPSAhdGhpcy5zdHJlYW0uaXNMb2NhbCgpO1xuXG4gICAgICAgIGlmICghIXRhcmdldEVsZW1lbnQpIHtcbiAgICAgICAgICAgIGxldCB0YXJnRWw7XG4gICAgICAgICAgICBpZiAodHlwZW9mIHRhcmdldEVsZW1lbnQgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAgICAgdGFyZ0VsID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQodGFyZ2V0RWxlbWVudCk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHRhcmdldEVsZW1lbnQgaW5zdGFuY2VvZiBIVE1MRWxlbWVudCkge1xuICAgICAgICAgICAgICAgIHRhcmdFbCA9IHRhcmdldEVsZW1lbnQ7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICghIXRhcmdFbCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZmlyc3RWaWRlb0VsZW1lbnQgPSB7XG4gICAgICAgICAgICAgICAgICAgIHRhcmdldEVsZW1lbnQ6IHRhcmdFbCxcbiAgICAgICAgICAgICAgICAgICAgdmlkZW86IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3ZpZGVvJyksXG4gICAgICAgICAgICAgICAgICAgIGlkOiAnJ1xuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgdGhpcy50YXJnZXRFbGVtZW50ID0gdGFyZ0VsO1xuICAgICAgICAgICAgICAgIHRoaXMuZWxlbWVudCA9IHRhcmdFbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICB0aGlzLmNhblBsYXlMaXN0ZW5lciA9ICgpID0+IHtcbiAgICAgICAgICAgIGlmICh0aGlzLnN0cmVhbS5pc0xvY2FsKCkpIHtcbiAgICAgICAgICAgICAgICBpZiAoIXRoaXMuc3RyZWFtLmRpc3BsYXlNeVJlbW90ZSgpKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbyhcIllvdXIgbG9jYWwgJ1N0cmVhbScgd2l0aCBpZCBbXCIgKyB0aGlzLnN0cmVhbS5zdHJlYW1JZCArICddIHZpZGVvIGlzIG5vdyBwbGF5aW5nJyk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCd2aWRlb1BsYXlpbmcnLCBbbmV3IFZpZGVvRWxlbWVudEV2ZW50KHRoaXMudmlkZW9zWzBdLnZpZGVvLCB0aGlzLCAndmlkZW9QbGF5aW5nJyldKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oXCJZb3VyIG93biByZW1vdGUgJ1N0cmVhbScgd2l0aCBpZCBbXCIgKyB0aGlzLnN0cmVhbS5zdHJlYW1JZCArICddIHZpZGVvIGlzIG5vdyBwbGF5aW5nJyk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdyZW1vdGVWaWRlb1BsYXlpbmcnLCBbbmV3IFZpZGVvRWxlbWVudEV2ZW50KHRoaXMudmlkZW9zWzBdLnZpZGVvLCB0aGlzLCAncmVtb3RlVmlkZW9QbGF5aW5nJyldKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbyhcIlJlbW90ZSAnU3RyZWFtJyB3aXRoIGlkIFtcIiArIHRoaXMuc3RyZWFtLnN0cmVhbUlkICsgJ10gdmlkZW8gaXMgbm93IHBsYXlpbmcnKTtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgndmlkZW9QbGF5aW5nJywgW25ldyBWaWRlb0VsZW1lbnRFdmVudCh0aGlzLnZpZGVvc1swXS52aWRlbywgdGhpcywgJ3ZpZGVvUGxheWluZycpXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnc3RyZWFtUGxheWluZycsIFtuZXcgU3RyZWFtTWFuYWdlckV2ZW50KHRoaXMpXSk7XG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2VlIFtbRXZlbnREaXNwYXRjaGVyLm9uXV1cbiAgICAgKi9cbiAgICBvbih0eXBlOiBzdHJpbmcsIGhhbmRsZXI6IChldmVudDogRXZlbnQpID0+IHZvaWQpOiBFdmVudERpc3BhdGNoZXIge1xuICAgICAgICB0aGlzLmVlLm9uKHR5cGUsIGV2ZW50ID0+IHtcbiAgICAgICAgICAgIGlmIChldmVudCkge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbyhcIkV2ZW50ICdcIiArIHR5cGUgKyBcIicgdHJpZ2dlcmVkIGJ5ICdcIiArICh0aGlzLnJlbW90ZSA/ICdTdWJzY3JpYmVyJyA6ICdQdWJsaXNoZXInKSArIFwiJ1wiLCBldmVudCk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbyhcIkV2ZW50ICdcIiArIHR5cGUgKyBcIicgdHJpZ2dlcmVkIGJ5ICdcIiArICh0aGlzLnJlbW90ZSA/ICdTdWJzY3JpYmVyJyA6ICdQdWJsaXNoZXInKSArIFwiJ1wiKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGhhbmRsZXIoZXZlbnQpO1xuICAgICAgICB9KTtcbiAgICAgICAgaWYgKHR5cGUgPT09ICd2aWRlb0VsZW1lbnRDcmVhdGVkJykge1xuICAgICAgICAgICAgaWYgKCEhdGhpcy5zdHJlYW0gJiYgdGhpcy5sYXp5TGF1bmNoVmlkZW9FbGVtZW50Q3JlYXRlZEV2ZW50KSB7XG4gICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3ZpZGVvRWxlbWVudENyZWF0ZWQnLCBbbmV3IFZpZGVvRWxlbWVudEV2ZW50KHRoaXMudmlkZW9zWzBdLnZpZGVvLCB0aGlzLCAndmlkZW9FbGVtZW50Q3JlYXRlZCcpXSk7XG4gICAgICAgICAgICAgICAgdGhpcy5sYXp5TGF1bmNoVmlkZW9FbGVtZW50Q3JlYXRlZEV2ZW50ID0gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHR5cGUgPT09ICdzdHJlYW1QbGF5aW5nJyB8fCB0eXBlID09PSAndmlkZW9QbGF5aW5nJykge1xuICAgICAgICAgICAgaWYgKHRoaXMudmlkZW9zWzBdICYmIHRoaXMudmlkZW9zWzBdLnZpZGVvICYmXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8uY3VycmVudFRpbWUgPiAwICYmXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8ucGF1c2VkID09PSBmYWxzZSAmJlxuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9zWzBdLnZpZGVvLmVuZGVkID09PSBmYWxzZSAmJlxuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9zWzBdLnZpZGVvLnJlYWR5U3RhdGUgPT09IDQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnc3RyZWFtUGxheWluZycsIFtuZXcgU3RyZWFtTWFuYWdlckV2ZW50KHRoaXMpXSk7XG4gICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3ZpZGVvUGxheWluZycsIFtuZXcgVmlkZW9FbGVtZW50RXZlbnQodGhpcy52aWRlb3NbMF0udmlkZW8sIHRoaXMsICd2aWRlb1BsYXlpbmcnKV0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNlZSBbW0V2ZW50RGlzcGF0Y2hlci5vbmNlXV1cbiAgICAgKi9cbiAgICBvbmNlKHR5cGU6IHN0cmluZywgaGFuZGxlcjogKGV2ZW50OiBFdmVudCkgPT4gdm9pZCk6IFN0cmVhbU1hbmFnZXIge1xuICAgICAgICB0aGlzLmVlLm9uY2UodHlwZSwgZXZlbnQgPT4ge1xuICAgICAgICAgICAgaWYgKGV2ZW50KSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5pbmZvKFwiRXZlbnQgJ1wiICsgdHlwZSArIFwiJyB0cmlnZ2VyZWQgb25jZVwiLCBldmVudCk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbyhcIkV2ZW50ICdcIiArIHR5cGUgKyBcIicgdHJpZ2dlcmVkIG9uY2VcIik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBoYW5kbGVyKGV2ZW50KTtcbiAgICAgICAgfSk7XG4gICAgICAgIGlmICh0eXBlID09PSAndmlkZW9FbGVtZW50Q3JlYXRlZCcpIHtcbiAgICAgICAgICAgIGlmICghIXRoaXMuc3RyZWFtICYmIHRoaXMubGF6eUxhdW5jaFZpZGVvRWxlbWVudENyZWF0ZWRFdmVudCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCd2aWRlb0VsZW1lbnRDcmVhdGVkJywgW25ldyBWaWRlb0VsZW1lbnRFdmVudCh0aGlzLnZpZGVvc1swXS52aWRlbywgdGhpcywgJ3ZpZGVvRWxlbWVudENyZWF0ZWQnKV0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmICh0eXBlID09PSAnc3RyZWFtUGxheWluZycgfHwgdHlwZSA9PT0gJ3ZpZGVvUGxheWluZycpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLnZpZGVvc1swXSAmJiB0aGlzLnZpZGVvc1swXS52aWRlbyAmJlxuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9zWzBdLnZpZGVvLmN1cnJlbnRUaW1lID4gMCAmJlxuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9zWzBdLnZpZGVvLnBhdXNlZCA9PT0gZmFsc2UgJiZcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvc1swXS52aWRlby5lbmRlZCA9PT0gZmFsc2UgJiZcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvc1swXS52aWRlby5yZWFkeVN0YXRlID09PSA0KSB7XG4gICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3N0cmVhbVBsYXlpbmcnLCBbbmV3IFN0cmVhbU1hbmFnZXJFdmVudCh0aGlzKV0pO1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCd2aWRlb1BsYXlpbmcnLCBbbmV3IFZpZGVvRWxlbWVudEV2ZW50KHRoaXMudmlkZW9zWzBdLnZpZGVvLCB0aGlzLCAndmlkZW9QbGF5aW5nJyldKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZWUgW1tFdmVudERpc3BhdGNoZXIub2ZmXV1cbiAgICAgKi9cbiAgICBvZmYodHlwZTogc3RyaW5nLCBoYW5kbGVyPzogKGV2ZW50OiBFdmVudCkgPT4gdm9pZCk6IFN0cmVhbU1hbmFnZXIge1xuICAgICAgICBpZiAoIWhhbmRsZXIpIHtcbiAgICAgICAgICAgIHRoaXMuZWUucmVtb3ZlQWxsTGlzdGVuZXJzKHR5cGUpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5lZS5vZmYodHlwZSwgaGFuZGxlcik7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogTWFrZXMgYHZpZGVvYCBlbGVtZW50IHBhcmFtZXRlciBkaXNwbGF5IHRoaXMgW1tzdHJlYW1dXS4gVGhpcyBpcyB1c2VmdWwgd2hlbiB5b3UgYXJlXG4gICAgICogW21hbmFnaW5nIHRoZSB2aWRlbyBlbGVtZW50cyBvbiB5b3VyIG93bl0oL2RvY3MvaG93LWRvLWkvbWFuYWdlLXZpZGVvcy8jeW91LXRha2UtY2FyZS1vZi10aGUtdmlkZW8tcGxheWVycylcbiAgICAgKlxuICAgICAqIENhbGxpbmcgdGhpcyBtZXRob2Qgd2l0aCBhIHZpZGVvIGFscmVhZHkgYWRkZWQgdG8gb3RoZXIgUHVibGlzaGVyL1N1YnNjcmliZXIgd2lsbCBjYXVzZSB0aGUgdmlkZW8gZWxlbWVudCB0byBiZVxuICAgICAqIGRpc2Fzc29jaWF0ZWQgZnJvbSB0aGF0IHByZXZpb3VzIFB1Ymxpc2hlci9TdWJzY3JpYmVyIGFuZCB0byBiZSBhc3NvY2lhdGVkIHRvIHRoaXMgb25lLlxuICAgICAqXG4gICAgICogQHJldHVybnMgMSBpZiB0aGUgdmlkZW8gd2Fzbid0IGFzc29jaWF0ZWQgdG8gYW55IG90aGVyIFB1Ymxpc2hlci9TdWJzY3JpYmVyIGFuZCBoYXMgYmVlbiBzdWNjZXNzZnVsbHkgYWRkZWQgdG8gdGhpcyBvbmUuXG4gICAgICogMCBpZiB0aGUgdmlkZW8gd2FzIGFscmVhZHkgYWRkZWQgdG8gdGhpcyBQdWJsaXNoZXIvU3Vic2NyaWJlci4gLTEgaWYgdGhlIHZpZGVvIHdhcyBwcmV2aW91c2x5IGFzc29jaWF0ZWQgdG8gYW55IG90aGVyXG4gICAgICogUHVibGlzaGVyL1N1YnNjcmliZXIgYW5kIGhhcyBiZWVuIHN1Y2Nlc3NmdWxseSBkaXNhc3NvY2lhdGVkIGZyb20gdGhhdCBvbmUgYW5kIHByb3Blcmx5IGFkZGVkIHRvIHRoaXMgb25lLlxuICAgICAqL1xuICAgIGFkZFZpZGVvRWxlbWVudCh2aWRlbzogSFRNTFZpZGVvRWxlbWVudCk6IG51bWJlciB7XG5cbiAgICAgICAgdGhpcy5pbml0aWFsaXplVmlkZW9Qcm9wZXJ0aWVzKHZpZGVvKTtcblxuICAgICAgICAvLyBJZiB0aGUgdmlkZW8gZWxlbWVudCBpcyBhbHJlYWR5IHBhcnQgb2YgdGhpcyBTdHJlYW1NYW5hZ2VyIGRvIG5vdGhpbmdcbiAgICAgICAgZm9yIChjb25zdCB2IG9mIHRoaXMudmlkZW9zKSB7XG4gICAgICAgICAgICBpZiAodi52aWRlbyA9PT0gdmlkZW8pIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gMDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGxldCByZXR1cm5OdW1iZXIgPSAxO1xuXG4gICAgICAgIGZvciAoY29uc3Qgc3RyZWFtTWFuYWdlciBvZiB0aGlzLnN0cmVhbS5zZXNzaW9uLnN0cmVhbU1hbmFnZXJzKSB7XG4gICAgICAgICAgICBpZiAoc3RyZWFtTWFuYWdlci5kaXNhc3NvY2lhdGVWaWRlbyh2aWRlbykpIHtcbiAgICAgICAgICAgICAgICByZXR1cm5OdW1iZXIgPSAtMTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuc3RyZWFtLnNlc3Npb24uc3RyZWFtTWFuYWdlcnMuZm9yRWFjaChzdHJlYW1NYW5hZ2VyID0+IHtcbiAgICAgICAgICAgIHN0cmVhbU1hbmFnZXIuZGlzYXNzb2NpYXRlVmlkZW8odmlkZW8pO1xuICAgICAgICB9KTtcblxuICAgICAgICB0aGlzLnB1c2hOZXdTdHJlYW1NYW5hZ2VyVmlkZW8oe1xuICAgICAgICAgICAgdmlkZW8sXG4gICAgICAgICAgICBpZDogdmlkZW8uaWRcbiAgICAgICAgfSk7XG5cbiAgICAgICAgY29uc29sZS5pbmZvKCdOZXcgdmlkZW8gZWxlbWVudCBhc3NvY2lhdGVkIHRvICcsIHRoaXMpO1xuXG4gICAgICAgIHJldHVybiByZXR1cm5OdW1iZXI7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIG5ldyB2aWRlbyBlbGVtZW50IGRpc3BsYXlpbmcgdGhpcyBbW3N0cmVhbV1dLiBUaGlzIGFsbG93cyB5b3UgdG8gaGF2ZSBtdWx0aXBsZSB2aWRlbyBlbGVtZW50cyBkaXNwbGF5aW5nIHRoZSBzYW1lIG1lZGlhIHN0cmVhbS5cbiAgICAgKlxuICAgICAqICMjIyMgRXZlbnRzIGRpc3BhdGNoZWRcbiAgICAgKlxuICAgICAqIFRoZSBQdWJsaXNoZXIvU3Vic2NyaWJlciBvYmplY3Qgd2lsbCBkaXNwYXRjaCBhIGB2aWRlb0VsZW1lbnRDcmVhdGVkYCBldmVudCBvbmNlIHRoZSBIVE1MIHZpZGVvIGVsZW1lbnQgaGFzIGJlZW4gYWRkZWQgdG8gRE9NLiBTZWUgW1tWaWRlb0VsZW1lbnRFdmVudF1dXG4gICAgICpcbiAgICAgKiBAcGFyYW0gdGFyZ2V0RWxlbWVudCBIVE1MIERPTSBlbGVtZW50IChvciBpdHMgYGlkYCBhdHRyaWJ1dGUpIGluIHdoaWNoIHRoZSB2aWRlbyBlbGVtZW50IG9mIHRoZSBQdWJsaXNoZXIvU3Vic2NyaWJlciB3aWxsIGJlIGluc2VydGVkXG4gICAgICogQHBhcmFtIGluc2VydE1vZGUgSG93IHRoZSB2aWRlbyBlbGVtZW50IHdpbGwgYmUgaW5zZXJ0ZWQgYWNjb3JkaW5nbHkgdG8gYHRhcmdldEVsZW1ldGBcbiAgICAgKi9cbiAgICBjcmVhdGVWaWRlb0VsZW1lbnQodGFyZ2V0RWxlbWVudD86IHN0cmluZyB8IEhUTUxFbGVtZW50LCBpbnNlcnRNb2RlPzogVmlkZW9JbnNlcnRNb2RlKTogSFRNTFZpZGVvRWxlbWVudCB7XG4gICAgICAgIGxldCB0YXJnRWw7XG4gICAgICAgIGlmICh0eXBlb2YgdGFyZ2V0RWxlbWVudCA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgIHRhcmdFbCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKHRhcmdFbCk7XG4gICAgICAgICAgICBpZiAoIXRhcmdFbCkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIlRoZSBwcm92aWRlZCAndGFyZ2V0RWxlbWVudCcgY291bGRuJ3QgYmUgcmVzb2x2ZWQgdG8gYW55IEhUTUwgZWxlbWVudDogXCIgKyB0YXJnZXRFbGVtZW50KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIGlmICh0YXJnZXRFbGVtZW50IGluc3RhbmNlb2YgSFRNTEVsZW1lbnQpIHtcbiAgICAgICAgICAgIHRhcmdFbCA9IHRhcmdldEVsZW1lbnQ7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJUaGUgcHJvdmlkZWQgJ3RhcmdldEVsZW1lbnQnIGNvdWxkbid0IGJlIHJlc29sdmVkIHRvIGFueSBIVE1MIGVsZW1lbnQ6IFwiICsgdGFyZ2V0RWxlbWVudCk7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCB2aWRlbyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3ZpZGVvJyk7XG4gICAgICAgIHRoaXMuaW5pdGlhbGl6ZVZpZGVvUHJvcGVydGllcyh2aWRlbyk7XG5cbiAgICAgICAgbGV0IGluc01vZGUgPSAhIWluc2VydE1vZGUgPyBpbnNlcnRNb2RlIDogVmlkZW9JbnNlcnRNb2RlLkFQUEVORDtcbiAgICAgICAgc3dpdGNoIChpbnNNb2RlKSB7XG4gICAgICAgICAgICBjYXNlIFZpZGVvSW5zZXJ0TW9kZS5BRlRFUjpcbiAgICAgICAgICAgICAgICB0YXJnRWwucGFyZW50Tm9kZSEhLmluc2VydEJlZm9yZSh2aWRlbywgdGFyZ0VsLm5leHRTaWJsaW5nKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgVmlkZW9JbnNlcnRNb2RlLkFQUEVORDpcbiAgICAgICAgICAgICAgICB0YXJnRWwuYXBwZW5kQ2hpbGQodmlkZW8pO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBWaWRlb0luc2VydE1vZGUuQkVGT1JFOlxuICAgICAgICAgICAgICAgIHRhcmdFbC5wYXJlbnROb2RlISEuaW5zZXJ0QmVmb3JlKHZpZGVvLCB0YXJnRWwpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBWaWRlb0luc2VydE1vZGUuUFJFUEVORDpcbiAgICAgICAgICAgICAgICB0YXJnRWwuaW5zZXJ0QmVmb3JlKHZpZGVvLCB0YXJnRWwuY2hpbGROb2Rlc1swXSk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIFZpZGVvSW5zZXJ0TW9kZS5SRVBMQUNFOlxuICAgICAgICAgICAgICAgIHRhcmdFbC5wYXJlbnROb2RlISEucmVwbGFjZUNoaWxkKHZpZGVvLCB0YXJnRWwpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICBpbnNNb2RlID0gVmlkZW9JbnNlcnRNb2RlLkFQUEVORDtcbiAgICAgICAgICAgICAgICB0YXJnRWwuYXBwZW5kQ2hpbGQodmlkZW8pO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgdjogU3RyZWFtTWFuYWdlclZpZGVvID0ge1xuICAgICAgICAgICAgdGFyZ2V0RWxlbWVudDogdGFyZ0VsLFxuICAgICAgICAgICAgdmlkZW8sXG4gICAgICAgICAgICBpbnNlcnRNb2RlOiBpbnNNb2RlLFxuICAgICAgICAgICAgaWQ6IHZpZGVvLmlkXG4gICAgICAgIH07XG4gICAgICAgIHRoaXMucHVzaE5ld1N0cmVhbU1hbmFnZXJWaWRlbyh2KTtcblxuICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgndmlkZW9FbGVtZW50Q3JlYXRlZCcsIFtuZXcgVmlkZW9FbGVtZW50RXZlbnQodi52aWRlbywgdGhpcywgJ3ZpZGVvRWxlbWVudENyZWF0ZWQnKV0pO1xuXG4gICAgICAgIHRoaXMubGF6eUxhdW5jaFZpZGVvRWxlbWVudENyZWF0ZWRFdmVudCA9ICEhdGhpcy5maXJzdFZpZGVvRWxlbWVudDtcblxuICAgICAgICByZXR1cm4gdmlkZW87XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGluaXRpYWxpemVWaWRlb1Byb3BlcnRpZXModmlkZW86IEhUTUxWaWRlb0VsZW1lbnQpOiB2b2lkIHtcbiAgICAgICAgaWYgKCEodGhpcy5zdHJlYW0uaXNMb2NhbCgpICYmIHRoaXMuc3RyZWFtLmRpc3BsYXlNeVJlbW90ZSgpKSkge1xuICAgICAgICAgICAgLy8gQXZvaWQgc2V0dGluZyB0aGUgTWVkaWFTdHJlYW0gaW50byB0aGUgc3JjT2JqZWN0IGlmIHJlbW90ZSBzdWJzY3JpcHRpb24gYmVmb3JlIHB1Ymxpc2hpbmdcbiAgICAgICAgICAgIHZpZGVvLnNyY09iamVjdCA9IHRoaXMuc3RyZWFtLmdldE1lZGlhU3RyZWFtKCk7XG4gICAgICAgIH1cbiAgICAgICAgdmlkZW8uYXV0b3BsYXkgPSB0cnVlO1xuICAgICAgICB2aWRlby5jb250cm9scyA9IGZhbHNlO1xuICAgICAgICBpZiAoIXZpZGVvLmlkKSB7XG4gICAgICAgICAgICB2aWRlby5pZCA9ICh0aGlzLnJlbW90ZSA/ICdyZW1vdGUtJyA6ICdsb2NhbC0nKSArICd2aWRlby0nICsgdGhpcy5zdHJlYW0uc3RyZWFtSWQ7XG4gICAgICAgICAgICAvLyBERVBSRUNBVEVEIHByb3BlcnR5OiBhc3NpZ24gb25jZSB0aGUgcHJvcGVydHkgaWQgaWYgdGhlIHVzZXIgcHJvdmlkZWQgYSB2YWxpZCB0YXJnZXRFbGVtZW50XG4gICAgICAgICAgICBpZiAoIXRoaXMuaWQgJiYgISF0aGlzLnRhcmdldEVsZW1lbnQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmlkID0gdmlkZW8uaWQ7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCF0aGlzLnJlbW90ZSAmJiAhdGhpcy5zdHJlYW0uZGlzcGxheU15UmVtb3RlKCkpIHtcbiAgICAgICAgICAgIHZpZGVvLm11dGVkID0gdHJ1ZTtcbiAgICAgICAgICAgIGlmICh0aGlzLnN0cmVhbS5vdXRib3VuZFN0cmVhbU9wdHMucHVibGlzaGVyUHJvcGVydGllcy5taXJyb3IpIHtcbiAgICAgICAgICAgICAgICB0aGlzLm1pcnJvclZpZGVvKHZpZGVvKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICByZW1vdmVBbGxWaWRlb3MoKTogdm9pZCB7XG4gICAgICAgIGZvciAobGV0IGkgPSB0aGlzLnN0cmVhbS5zZXNzaW9uLnN0cmVhbU1hbmFnZXJzLmxlbmd0aCAtIDE7IGkgPj0gMDsgLS1pKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5zdHJlYW0uc2Vzc2lvbi5zdHJlYW1NYW5hZ2Vyc1tpXSA9PT0gdGhpcykge1xuICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtLnNlc3Npb24uc3RyZWFtTWFuYWdlcnMuc3BsaWNlKGksIDEpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy52aWRlb3MuZm9yRWFjaChzdHJlYW1NYW5hZ2VyVmlkZW8gPT4ge1xuICAgICAgICAgICAgLy8gUmVtb3ZlIG9uY2FucGxheSBldmVudCBsaXN0ZW5lciAob25seSBPcGVuVmlkdSBicm93c2VyIG9uZSwgbm90IHRoZSB1c2VyIG9uZXMpXG4gICAgICAgICAgICBzdHJlYW1NYW5hZ2VyVmlkZW8udmlkZW8ucmVtb3ZlRXZlbnRMaXN0ZW5lcignY2FucGxheScsIHRoaXMuY2FuUGxheUxpc3RlbmVyKTtcbiAgICAgICAgICAgIGlmICghIXN0cmVhbU1hbmFnZXJWaWRlby50YXJnZXRFbGVtZW50KSB7XG4gICAgICAgICAgICAgICAgLy8gT25seSByZW1vdmUgZnJvbSBET00gdmlkZW9zIGNyZWF0ZWQgYnkgT3BlblZpZHUgQnJvd3NlciAodGhvc2UgZ2VuZXJhdGVkIGJ5IHBhc3NpbmcgYSB2YWxpZCB0YXJnZXRFbGVtZW50IGluIE9wZW5WaWR1LmluaXRQdWJsaXNoZXJcbiAgICAgICAgICAgICAgICAvLyBhbmQgU2Vzc2lvbi5zdWJzY3JpYmUgb3IgdGhvc2UgY3JlYXRlZCBieSBTdHJlYW1NYW5hZ2VyLmNyZWF0ZVZpZGVvRWxlbWVudCkuIEFsbCB0aGlzIHZpZGVvcyB0cmlnZ2VyZWQgYSB2aWRlb0VsZW1lbnRDcmVhdGVkIGV2ZW50XG4gICAgICAgICAgICAgICAgc3RyZWFtTWFuYWdlclZpZGVvLnZpZGVvLnBhcmVudE5vZGUhLnJlbW92ZUNoaWxkKHN0cmVhbU1hbmFnZXJWaWRlby52aWRlbyk7XG4gICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3ZpZGVvRWxlbWVudERlc3Ryb3llZCcsIFtuZXcgVmlkZW9FbGVtZW50RXZlbnQoc3RyZWFtTWFuYWdlclZpZGVvLnZpZGVvLCB0aGlzLCAndmlkZW9FbGVtZW50RGVzdHJveWVkJyldKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIFJlbW92ZSBzcmNPYmplY3QgZnJvbSB0aGUgdmlkZW9cbiAgICAgICAgICAgIHN0cmVhbU1hbmFnZXJWaWRlby52aWRlby5zcmNPYmplY3QgPSBudWxsO1xuICAgICAgICAgICAgLy8gUmVtb3ZlIGZyb20gY29sbGVjdGlvbiBvZiB2aWRlb3MgZXZlcnkgdmlkZW8gbWFuYWdlZCBieSBPcGVuVmlkdSBCcm93c2VyXG4gICAgICAgICAgICB0aGlzLnZpZGVvcy5maWx0ZXIodiA9PiAhdi50YXJnZXRFbGVtZW50KTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGRpc2Fzc29jaWF0ZVZpZGVvKHZpZGVvOiBIVE1MVmlkZW9FbGVtZW50KTogYm9vbGVhbiB7XG4gICAgICAgIGxldCBkaXNhc3NvY2lhdGVkID0gZmFsc2U7XG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy52aWRlb3MubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGlmICh0aGlzLnZpZGVvc1tpXS52aWRlbyA9PT0gdmlkZW8pIHtcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvcy5zcGxpY2UoaSwgMSk7XG4gICAgICAgICAgICAgICAgZGlzYXNzb2NpYXRlZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgY29uc29sZS5pbmZvKCdWaWRlbyBlbGVtZW50IGRpc2Fzc29jaWF0ZWQgZnJvbSAnLCB0aGlzKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZGlzYXNzb2NpYXRlZDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgYWRkUGxheUV2ZW50VG9GaXJzdFZpZGVvKCkge1xuICAgICAgICBpZiAoKCEhdGhpcy52aWRlb3NbMF0pICYmICghIXRoaXMudmlkZW9zWzBdLnZpZGVvKSAmJiAodGhpcy52aWRlb3NbMF0udmlkZW8ub25jYW5wbGF5ID09PSBudWxsKSkge1xuICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8uYWRkRXZlbnRMaXN0ZW5lcignY2FucGxheScsIHRoaXMuY2FuUGxheUxpc3RlbmVyKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICB1cGRhdGVNZWRpYVN0cmVhbShtZWRpYVN0cmVhbTogTWVkaWFTdHJlYW0pIHtcbiAgICAgICAgdGhpcy52aWRlb3MuZm9yRWFjaChzdHJlYW1NYW5hZ2VyVmlkZW8gPT4ge1xuICAgICAgICAgICAgc3RyZWFtTWFuYWdlclZpZGVvLnZpZGVvLnNyY09iamVjdCA9IG1lZGlhU3RyZWFtO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgZW1pdEV2ZW50KHR5cGU6IHN0cmluZywgZXZlbnRBcnJheTogYW55W10pOiB2b2lkIHtcbiAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQodHlwZSwgZXZlbnRBcnJheSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBwdXNoTmV3U3RyZWFtTWFuYWdlclZpZGVvKHN0cmVhbU1hbmFnZXJWaWRlbzogU3RyZWFtTWFuYWdlclZpZGVvKSB7XG4gICAgICAgIHRoaXMudmlkZW9zLnB1c2goc3RyZWFtTWFuYWdlclZpZGVvKTtcbiAgICAgICAgdGhpcy5hZGRQbGF5RXZlbnRUb0ZpcnN0VmlkZW8oKTtcbiAgICAgICAgaWYgKHRoaXMuc3RyZWFtLnNlc3Npb24uc3RyZWFtTWFuYWdlcnMuaW5kZXhPZih0aGlzKSA9PT0gLTEpIHtcbiAgICAgICAgICAgIHRoaXMuc3RyZWFtLnNlc3Npb24uc3RyZWFtTWFuYWdlcnMucHVzaCh0aGlzKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgbWlycm9yVmlkZW8odmlkZW8pOiB2b2lkIHtcbiAgICAgICAgdmlkZW8uc3R5bGUudHJhbnNmb3JtID0gJ3JvdGF0ZVkoMTgwZGVnKSc7XG4gICAgICAgIHZpZGVvLnN0eWxlLndlYmtpdFRyYW5zZm9ybSA9ICdyb3RhdGVZKDE4MGRlZyknO1xuICAgIH1cblxufSIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTctMjAxOCBPcGVuVmlkdSAoaHR0cHM6Ly9vcGVudmlkdS5pby8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuaW1wb3J0IHsgU3RyZWFtIH0gZnJvbSAnLi9TdHJlYW0nO1xuaW1wb3J0IHsgU3RyZWFtTWFuYWdlciB9IGZyb20gJy4vU3RyZWFtTWFuYWdlcic7XG5pbXBvcnQgeyBTdWJzY3JpYmVyUHJvcGVydGllcyB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvSW50ZXJmYWNlcy9QdWJsaWMvU3Vic2NyaWJlclByb3BlcnRpZXMnO1xuXG5cbi8qKlxuICogUGFja3MgcmVtb3RlIG1lZGlhIHN0cmVhbXMuIFBhcnRpY2lwYW50cyBhdXRvbWF0aWNhbGx5IHJlY2VpdmUgdGhlbSB3aGVuIG90aGVycyBwdWJsaXNoIHRoZWlyIHN0cmVhbXMuIEluaXRpYWxpemVkIHdpdGggW1tTZXNzaW9uLnN1YnNjcmliZV1dIG1ldGhvZFxuICovXG5leHBvcnQgY2xhc3MgU3Vic2NyaWJlciBleHRlbmRzIFN0cmVhbU1hbmFnZXIge1xuXG4gICAgcHJpdmF0ZSBwcm9wZXJ0aWVzOiBTdWJzY3JpYmVyUHJvcGVydGllcztcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3RvcihzdHJlYW06IFN0cmVhbSwgdGFyZ0VsOiBzdHJpbmcgfCBIVE1MRWxlbWVudCwgcHJvcGVydGllczogU3Vic2NyaWJlclByb3BlcnRpZXMpIHtcbiAgICAgICAgc3VwZXIoc3RyZWFtLCB0YXJnRWwpO1xuICAgICAgICB0aGlzLmVsZW1lbnQgPSB0aGlzLnRhcmdldEVsZW1lbnQ7XG4gICAgICAgIHRoaXMuc3RyZWFtID0gc3RyZWFtO1xuICAgICAgICB0aGlzLnByb3BlcnRpZXMgPSBwcm9wZXJ0aWVzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFN1YnNjcmliZSBvciB1bnN1YnNjcmliZSBmcm9tIHRoZSBhdWRpbyBzdHJlYW0gKGlmIGF2YWlsYWJsZSkuIENhbGxpbmcgdGhpcyBtZXRob2QgdHdpY2UgaW4gYSByb3cgcGFzc2luZyBzYW1lIHZhbHVlIHdpbGwgaGF2ZSBubyBlZmZlY3RcbiAgICAgKiBAcGFyYW0gdmFsdWUgYHRydWVgIHRvIHN1YnNjcmliZSB0byB0aGUgYXVkaW8gc3RyZWFtLCBgZmFsc2VgIHRvIHVuc3Vic2NyaWJlIGZyb20gaXRcbiAgICAgKi9cbiAgICBzdWJzY3JpYmVUb0F1ZGlvKHZhbHVlOiBib29sZWFuKTogU3Vic2NyaWJlciB7XG4gICAgICAgIHRoaXMuc3RyZWFtLmdldE1lZGlhU3RyZWFtKCkuZ2V0QXVkaW9UcmFja3MoKS5mb3JFYWNoKCh0cmFjaykgPT4ge1xuICAgICAgICAgICAgdHJhY2suZW5hYmxlZCA9IHZhbHVlO1xuICAgICAgICB9KTtcbiAgICAgICAgY29uc29sZS5pbmZvKFwiJ1N1YnNjcmliZXInIGhhcyBcIiArICh2YWx1ZSA/ICdzdWJzY3JpYmVkIHRvJyA6ICd1bnN1YnNjcmliZWQgZnJvbScpICsgJyBpdHMgYXVkaW8gc3RyZWFtJyk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFN1YnNjcmliZSBvciB1bnN1YnNjcmliZSBmcm9tIHRoZSB2aWRlbyBzdHJlYW0gKGlmIGF2YWlsYWJsZSkuIENhbGxpbmcgdGhpcyBtZXRob2QgdHdpY2UgaW4gYSByb3cgcGFzc2luZyBzYW1lIHZhbHVlIHdpbGwgaGF2ZSBubyBlZmZlY3RcbiAgICAgKiBAcGFyYW0gdmFsdWUgYHRydWVgIHRvIHN1YnNjcmliZSB0byB0aGUgdmlkZW8gc3RyZWFtLCBgZmFsc2VgIHRvIHVuc3Vic2NyaWJlIGZyb20gaXRcbiAgICAgKi9cbiAgICBzdWJzY3JpYmVUb1ZpZGVvKHZhbHVlOiBib29sZWFuKTogU3Vic2NyaWJlciB7XG4gICAgICAgIHRoaXMuc3RyZWFtLmdldE1lZGlhU3RyZWFtKCkuZ2V0VmlkZW9UcmFja3MoKS5mb3JFYWNoKCh0cmFjaykgPT4ge1xuICAgICAgICAgICAgdHJhY2suZW5hYmxlZCA9IHZhbHVlO1xuICAgICAgICB9KTtcbiAgICAgICAgY29uc29sZS5pbmZvKFwiJ1N1YnNjcmliZXInIGhhcyBcIiArICh2YWx1ZSA/ICdzdWJzY3JpYmVkIHRvJyA6ICd1bnN1YnNjcmliZWQgZnJvbScpICsgJyBpdHMgdmlkZW8gc3RyZWFtJyk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxufSIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTctMjAxOCBPcGVuVmlkdSAoaHR0cHM6Ly9vcGVudmlkdS5pby8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuZXhwb3J0IGVudW0gTG9jYWxSZWNvcmRlclN0YXRlIHtcbiAgICBSRUFEWSA9ICdSRUFEWScsXG4gICAgUkVDT1JESU5HID0gJ1JFQ09SRElORycsXG4gICAgUEFVU0VEID0gJ1BBVVNFRCcsXG4gICAgRklOSVNIRUQgPSAnRklOSVNIRUQnXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG4vKipcbiAqIERlZmluZXMgcHJvcGVydHkgW1tPcGVuVmlkdUVycm9yLm5hbWVdXVxuICovXG5leHBvcnQgZW51bSBPcGVuVmlkdUVycm9yTmFtZSB7XG5cbiAgICAvKipcbiAgICAgKiBCcm93c2VyIGlzIG5vdCBzdXBwb3J0ZWQgYnkgT3BlblZpZHUuXG4gICAgICogUmV0dXJuZWQgdXBvbiB1bnN1Y2Nlc3NmdWwgW1tTZXNzaW9uLmNvbm5lY3RdXVxuICAgICAqL1xuICAgIEJST1dTRVJfTk9UX1NVUFBPUlRFRCA9ICdCUk9XU0VSX05PVF9TVVBQT1JURUQnLFxuXG4gICAgLyoqXG4gICAgICogVGhlIHVzZXIgaGFzbid0IGdyYW50ZWQgcGVybWlzc2lvbnMgdG8gdGhlIHJlcXVpcmVkIGlucHV0IGRldmljZSB3aGVuIHRoZSBicm93c2VyIGFza2VkIGZvciB0aGVtLlxuICAgICAqIFJldHVybmVkIHVwb24gdW5zdWNjZXNzZnVsIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dIG9yIFtbT3BlblZpZHUuZ2V0VXNlck1lZGlhXV1cbiAgICAgKi9cbiAgICBERVZJQ0VfQUNDRVNTX0RFTklFRCA9ICdERVZJQ0VfQUNDRVNTX0RFTklFRCcsXG5cbiAgICAvKipcbiAgICAgKiBUaGUgdXNlciBoYXNuJ3QgZ3JhbnRlZCBwZXJtaXNzaW9ucyB0byBjYXB0dXJlIHNvbWUgZGVza3RvcCBzY3JlZW4gd2hlbiB0aGUgYnJvd3NlciBhc2tlZCBmb3IgdGhlbS5cbiAgICAgKiBSZXR1cm5lZCB1cG9uIHVuc3VjY2Vzc2Z1bCBbW09wZW5WaWR1LmluaXRQdWJsaXNoZXJdXSBvciBbW09wZW5WaWR1LmdldFVzZXJNZWRpYV1dXG4gICAgICovXG4gICAgU0NSRUVOX0NBUFRVUkVfREVOSUVEID0gJ1NDUkVFTl9DQVBUVVJFX0RFTklFRCcsXG5cbiAgICAvKipcbiAgICAgKiBCcm93c2VyIGRvZXMgbm90IHN1cHBvcnQgc2NyZWVuIHNoYXJpbmcuXG4gICAgICogUmV0dXJuZWQgdXBvbiB1bnN1Y2Nlc3NmdWwgW1tPcGVuVmlkdS5pbml0UHVibGlzaGVyXV1cbiAgICAgKi9cbiAgICBTQ1JFRU5fU0hBUklOR19OT1RfU1VQUE9SVEVEID0gJ1NDUkVFTl9TSEFSSU5HX05PVF9TVVBQT1JURUQnLFxuXG4gICAgLyoqXG4gICAgICogT25seSBmb3IgQ2hyb21lLCB0aGVyZSdzIG5vIHNjcmVlbiBzaGFyaW5nIGV4dGVuc2lvbiBpbnN0YWxsZWRcbiAgICAgKiBSZXR1cm5lZCB1cG9uIHVuc3VjY2Vzc2Z1bCBbW09wZW5WaWR1LmluaXRQdWJsaXNoZXJdXVxuICAgICAqL1xuICAgIFNDUkVFTl9FWFRFTlNJT05fTk9UX0lOU1RBTExFRCA9ICdTQ1JFRU5fRVhURU5TSU9OX05PVF9JTlNUQUxMRUQnLFxuXG4gICAgLyoqXG4gICAgICogT25seSBmb3IgQ2hyb21lLCB0aGUgc2NyZWVuIHNoYXJpbmcgZXh0ZW5zaW9uIGlzIGluc3RhbGxlZCBidXQgaXMgZGlzYWJsZWRcbiAgICAgKiBSZXR1cm5lZCB1cG9uIHVuc3VjY2Vzc2Z1bCBbW09wZW5WaWR1LmluaXRQdWJsaXNoZXJdXVxuICAgICAqL1xuICAgIFNDUkVFTl9FWFRFTlNJT05fRElTQUJMRUQgPSAnU0NSRUVOX0VYVEVOU0lPTl9ESVNBQkxFRCcsXG5cbiAgICAvKipcbiAgICAgKiBObyB2aWRlbyBpbnB1dCBkZXZpY2UgZm91bmQgd2l0aCB0aGUgcHJvdmlkZWQgZGV2aWNlSWQgKHByb3BlcnR5IFtbUHVibGlzaGVyUHJvcGVydGllcy52aWRlb1NvdXJjZV1dKVxuICAgICAqIFJldHVybmVkIHVwb24gdW5zdWNjZXNzZnVsIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dXG4gICAgICovXG4gICAgSU5QVVRfVklERU9fREVWSUNFX05PVF9GT1VORCA9ICdJTlBVVF9WSURFT19ERVZJQ0VfTk9UX0ZPVU5EJyxcblxuICAgIC8qKlxuICAgICAqIE5vIGF1ZGlvIGlucHV0IGRldmljZSBmb3VuZCB3aXRoIHRoZSBwcm92aWRlZCBkZXZpY2VJZCAocHJvcGVydHkgW1tQdWJsaXNoZXJQcm9wZXJ0aWVzLmF1ZGlvU291cmNlXV0pXG4gICAgICogUmV0dXJuZWQgdXBvbiB1bnN1Y2Nlc3NmdWwgW1tPcGVuVmlkdS5pbml0UHVibGlzaGVyXV1cbiAgICAgKi9cbiAgICBJTlBVVF9BVURJT19ERVZJQ0VfTk9UX0ZPVU5EID0gJ0lOUFVUX0FVRElPX0RFVklDRV9OT1RfRk9VTkQnLFxuXG4gICAgLyoqXG4gICAgICogTWV0aG9kIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dIGhhcyBiZWVuIGNhbGxlZCB3aXRoIHByb3BlcnRpZXMgYHZpZGVvU291cmNlYCBhbmQgYGF1ZGlvU291cmNlYCBvZlxuICAgICAqIFtbUHVibGlzaGVyUHJvcGVydGllc11dIHBhcmFtZXRlciBib3RoIHNldCB0byAqZmFsc2UqIG9yICpudWxsKlxuICAgICAqL1xuICAgIE5PX0lOUFVUX1NPVVJDRV9TRVQgPSAnTk9fSU5QVVRfU09VUkNFX1NFVCcsXG5cbiAgICAvKipcbiAgICAgKiBTb21lIG1lZGlhIHByb3BlcnR5IG9mIFtbUHVibGlzaGVyUHJvcGVydGllc11dIHN1Y2ggYXMgYGZyYW1lUmF0ZWAgb3IgYHJlc29sdXRpb25gIGlzIG5vdCBzdXBwb3J0ZWRcbiAgICAgKiBieSB0aGUgaW5wdXQgZGV2aWNlcyAod2hlbmV2ZXIgaXQgaXMgcG9zc2libGUgdGhleSBhcmUgYXV0b21hdGljYWxseSBhZGp1c3RlZCB0byB0aGUgbW9zdCBzaW1pbGFyIHZhbHVlKS5cbiAgICAgKiBSZXR1cm5lZCB1cG9uIHVuc3VjY2Vzc2Z1bCBbW09wZW5WaWR1LmluaXRQdWJsaXNoZXJdXVxuICAgICAqL1xuICAgIFBVQkxJU0hFUl9QUk9QRVJUSUVTX0VSUk9SID0gJ1BVQkxJU0hFUl9QUk9QRVJUSUVTX0VSUk9SJyxcblxuICAgIC8qKlxuICAgICAqIFRoZSBjbGllbnQgdHJpZWQgdG8gY2FsbCBhIG1ldGhvZCB3aXRob3V0IHRoZSByZXF1aXJlZCBwZXJtaXNzaW9ucy4gVGhpcyBjYW4gb2NjdXIgZm9yIG1ldGhvZHMgW1tTZXNzaW9uLnB1Ymxpc2hdXSxcbiAgICAgKiBbW1Nlc3Npb24uZm9yY2VVbnB1Ymxpc2hdXSBhbmQgW1tTZXNzaW9uLmZvcmNlRGlzY29ubmVjdF1dXG4gICAgICovXG4gICAgT1BFTlZJRFVfUEVSTUlTU0lPTl9ERU5JRUQgPSAnT1BFTlZJRFVfUEVSTUlTU0lPTl9ERU5JRUQnLFxuXG4gICAgLyoqXG4gICAgICogX05vdCBpbiB1c2UgeWV0X1xuICAgICAqL1xuICAgIE9QRU5WSURVX05PVF9DT05ORUNURUQgPSAnT1BFTlZJRFVfTk9UX0NPTk5FQ1RFRCcsXG5cbiAgICAvKipcbiAgICAgKiBfTm90IGluIHVzZSB5ZXRfXG4gICAgICovXG4gICAgR0VORVJJQ19FUlJPUiA9ICdHRU5FUklDX0VSUk9SJ1xufVxuXG4vKipcbiAqIFNpbXBsZSBvYmplY3QgdG8gaWRlbnRpZnkgcnVudGltZSBlcnJvcnMgb24gdGhlIGNsaWVudCBzaWRlXG4gKi9cbmV4cG9ydCBjbGFzcyBPcGVuVmlkdUVycm9yIHtcblxuICAgIG5hbWU6IE9wZW5WaWR1RXJyb3JOYW1lO1xuICAgIG1lc3NhZ2U6IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3RvcihuYW1lOiBPcGVuVmlkdUVycm9yTmFtZSwgbWVzc2FnZTogc3RyaW5nKSB7XG4gICAgICAgIHRoaXMubmFtZSA9IG5hbWU7XG4gICAgICAgIHRoaXMubWVzc2FnZSA9IG1lc3NhZ2U7XG4gICAgfVxuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG4vKipcbiAqIEhvdyB0aGUgdmlkZW8gd2lsbCBiZSBpbnNlcnRlZCBpbiB0aGUgRE9NIGZvciBQdWJsaXNoZXJzIGFuZCBTdWJzY3JpYmVycy4gU2VlIFtbUHVibGlzaGVyUHJvcGVydGllcy5pbnNlcnRNb2RlXV0gYW5kIFtbU3Vic2NyaWJlclByb3BlcnRpZXMuaW5zZXJ0TW9kZV1dXG4gKi9cbmV4cG9ydCBlbnVtIFZpZGVvSW5zZXJ0TW9kZSB7XG5cbiAgICAvKipcbiAgICAgKiBWaWRlbyBpbnNlcnRlZCBhZnRlciB0aGUgdGFyZ2V0IGVsZW1lbnQgKGFzIG5leHQgc2libGluZylcbiAgICAgKi9cbiAgICBBRlRFUiA9ICdBRlRFUicsXG4gICAgLyoqXG4gICAgICogVmlkZW8gaW5zZXJ0ZWQgYXMgbGFzdCBjaGlsZCBvZiB0aGUgdGFyZ2V0IGVsZW1lbnRcbiAgICAgKi9cbiAgICBBUFBFTkQgPSAnQVBQRU5EJyxcbiAgICAvKipcbiAgICAgKiBWaWRlbyBpbnNlcnRlZCBiZWZvcmUgdGhlIHRhcmdldCBlbGVtZW50IChhcyBwcmV2aW91cyBzaWJsaW5nKVxuICAgICAqL1xuICAgIEJFRk9SRSA9ICdCRUZPUkUnLFxuICAgIC8qKlxuICAgICAqIFZpZGVvIGluc2VydGVkIGFzIGZpcnN0IGNoaWxkIG9mIHRoZSB0YXJnZXQgZWxlbWVudFxuICAgICAqL1xuICAgIFBSRVBFTkQgPSAnUFJFUEVORCcsXG4gICAgLyoqXG4gICAgICogVmlkZW8gcmVwbGFjZXMgdGFyZ2V0IGVsZW1lbnRcbiAgICAgKi9cbiAgICBSRVBMQUNFID0gJ1JFUExBQ0UnXG5cbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IEV2ZW50IH0gZnJvbSAnLi9FdmVudCc7XG5pbXBvcnQgeyBDb25uZWN0aW9uIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvQ29ubmVjdGlvbic7XG5pbXBvcnQgeyBTZXNzaW9uIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvU2Vzc2lvbic7XG5cblxuLyoqXG4gKiBEZWZpbmVzIHRoZSBmb2xsb3dpbmcgZXZlbnRzOlxuICogLSBgY29ubmVjdGlvbkNyZWF0ZWRgOiBkaXNwYXRjaGVkIGJ5IFtbU2Vzc2lvbl1dXG4gKiAtIGBjb25uZWN0aW9uRGVzdHJveWVkYDogZGlzcGF0Y2hlZCBieSBbW1Nlc3Npb25dXVxuICovXG5leHBvcnQgY2xhc3MgQ29ubmVjdGlvbkV2ZW50IGV4dGVuZHMgRXZlbnQge1xuXG4gICAgLyoqXG4gICAgICogQ29ubmVjdGlvbiBvYmplY3QgdGhhdCB3YXMgY3JlYXRlZCBvciBkZXN0cm95ZWRcbiAgICAgKi9cbiAgICBjb25uZWN0aW9uOiBDb25uZWN0aW9uO1xuXG4gICAgLyoqXG4gICAgICogRm9yICdjb25uZWN0aW9uRGVzdHJveWVkJyBldmVudDpcbiAgICAgKiAtIFwiZGlzY29ubmVjdFwiOiB0aGUgcmVtb3RlIHVzZXIgaGFzIGNhbGxlZCBgU2Vzc2lvbi5kaXNjb25uZWN0KClgXG4gICAgICogLSBcImZvcmNlRGlzY29ubmVjdEJ5VXNlclwiOiB0aGUgcmVtb3RlIHVzZXIgaGFzIGJlZW4gZXZpY3RlZCBmcm9tIHRoZSBTZXNzaW9uIGJ5IG90aGVyIHVzZXIgY2FsbGluZyBgU2Vzc2lvbi5mb3JjZURpc2Nvbm5lY3QoKWBcbiAgICAgKiAtIFwiZm9yY2VEaXNjb25uZWN0QnlTZXJ2ZXJcIjogdGhlIHJlbW90ZSB1c2VyIGhhcyBiZWVuIGV2aWN0ZWQgZnJvbSB0aGUgU2Vzc2lvbiBieSB0aGUgYXBwbGljYXRpb25cbiAgICAgKiAtIFwic2Vzc2lvbkNsb3NlZEJ5U2VydmVyXCI6IHRoZSBTZXNzaW9uIGhhcyBiZWVuIGNsb3NlZCBieSB0aGUgYXBwbGljYXRpb25cbiAgICAgKiAtIFwibmV0d29ya0Rpc2Nvbm5lY3RcIjogdGhlIHJlbW90ZSB1c2VyIG5ldHdvcmsgY29ubmVjdGlvbiBoYXMgZHJvcHBlZFxuICAgICAqXG4gICAgICogRm9yICdjb25uZWN0aW9uQ3JlYXRlZCcgZW1wdHkgc3RyaW5nXG4gICAgICovXG4gICAgcmVhc29uOiBzdHJpbmc7XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgY29uc3RydWN0b3IoY2FuY2VsYWJsZTogYm9vbGVhbiwgdGFyZ2V0OiBTZXNzaW9uLCB0eXBlOiBzdHJpbmcsIGNvbm5lY3Rpb246IENvbm5lY3Rpb24sIHJlYXNvbjogc3RyaW5nKSB7XG4gICAgICAgIHN1cGVyKGNhbmNlbGFibGUsIHRhcmdldCwgdHlwZSk7XG4gICAgICAgIHRoaXMuY29ubmVjdGlvbiA9IGNvbm5lY3Rpb247XG4gICAgICAgIHRoaXMucmVhc29uID0gcmVhc29uO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6bm8tZW1wdHlcbiAgICBjYWxsRGVmYXVsdEJlaGF2aW9yKCkgeyB9XG5cbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IFN0cmVhbU1hbmFnZXIgfSBmcm9tICcuLi8uLi9PcGVuVmlkdS9TdHJlYW1NYW5hZ2VyJztcbmltcG9ydCB7IFNlc3Npb24gfSBmcm9tICcuLi8uLi9PcGVuVmlkdS9TZXNzaW9uJztcblxuZXhwb3J0IGFic3RyYWN0IGNsYXNzIEV2ZW50IHtcblxuICAgIC8qKlxuICAgICAqIFdoZXRoZXIgdGhlIGV2ZW50IGhhcyBhIGRlZmF1bHQgYmVoYXZpb3IgdGhhdCBtYXkgYmUgcHJldmVudGVkIGJ5IGNhbGxpbmcgW1tFdmVudC5wcmV2ZW50RGVmYXVsdF1dXG4gICAgICovXG4gICAgY2FuY2VsYWJsZTogYm9vbGVhbjtcblxuICAgIC8qKlxuICAgICAqIFRoZSBvYmplY3QgdGhhdCBkaXNwYXRjaGVkIHRoZSBldmVudFxuICAgICAqL1xuICAgIHRhcmdldDogU2Vzc2lvbiB8IFN0cmVhbU1hbmFnZXI7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgdHlwZSBvZiBldmVudC4gVGhpcyBpcyB0aGUgc2FtZSBzdHJpbmcgeW91IHBhc3MgYXMgZmlyc3QgcGFyYW1ldGVyIHdoZW4gY2FsbGluZyBtZXRob2QgYG9uKClgIG9mIGFueSBvYmplY3QgaW1wbGVtZW50aW5nIFtbRXZlbnREaXNwYXRjaGVyXV0gaW50ZXJmYWNlXG4gICAgICovXG4gICAgdHlwZTogc3RyaW5nO1xuXG4gICAgcHJpdmF0ZSBoYXNCZWVuUHJldmVudGVkID0gZmFsc2U7XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgY29uc3RydWN0b3IoY2FuY2VsYWJsZTogYm9vbGVhbiwgdGFyZ2V0OiBTZXNzaW9uIHwgU3RyZWFtTWFuYWdlciwgdHlwZTogc3RyaW5nKSB7XG4gICAgICAgIHRoaXMuY2FuY2VsYWJsZSA9IGNhbmNlbGFibGU7XG4gICAgICAgIHRoaXMudGFyZ2V0ID0gdGFyZ2V0O1xuICAgICAgICB0aGlzLnR5cGUgPSB0eXBlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFdoZXRoZXIgdGhlIGRlZmF1bHQgYmVhaGl2b3VyIG9mIHRoZSBldmVudCBoYXMgYmVlbiBwcmV2ZW50ZWQgb3Igbm90LiBDYWxsIFtbRXZlbnQucHJldmVudERlZmF1bHRdXSB0byBwcmV2ZW50IGl0XG4gICAgICovXG4gICAgaXNEZWZhdWx0UHJldmVudGVkKCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gdGhpcy5oYXNCZWVuUHJldmVudGVkO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFByZXZlbnRzIHRoZSBkZWZhdWx0IGJlaGF2aW9yIG9mIHRoZSBldmVudC4gVGhlIGZvbGxvd2luZyBldmVudHMgaGF2ZSBhIGRlZmF1bHQgYmVoYXZpb3I6XG4gICAgICpcbiAgICAgKiAtIGBzZXNzaW9uRGlzY29ubmVjdGVkYDogZGlzcGF0Y2hlZCBieSBbW1Nlc3Npb25dXSBvYmplY3QsIGF1dG9tYXRpY2FsbHkgdW5zdWJzY3JpYmVzIHRoZSBsZWF2aW5nIHBhcnRpY2lwYW50IGZyb20gZXZlcnkgU3Vic2NyaWJlciBvYmplY3Qgb2YgdGhlIHNlc3Npb24gKHRoaXMgaW5jbHVkZXMgY2xvc2luZyB0aGUgV2ViUlRDUGVlciBjb25uZWN0aW9uIGFuZCBkaXNwb3NpbmcgYWxsIE1lZGlhU3RyZWFtVHJhY2tzKVxuICAgICAqIGFuZCBhbHNvIGRlbGV0ZXMgYW55IEhUTUwgdmlkZW8gZWxlbWVudCBhc3NvY2lhdGVkIHRvIGVhY2ggU3Vic2NyaWJlciAob25seSB0aG9zZSBjcmVhdGVkIGJ5IE9wZW5WaWR1IEJyb3dzZXIsIGVpdGhlciBieSBwYXNzaW5nIGEgdmFsaWQgcGFyYW1ldGVyIGFzIGB0YXJnZXRFbGVtZW50YCBpbiBtZXRob2QgW1tTZXNzaW9uLnN1YnNjcmliZV1dIG9yXG4gICAgICogYnkgY2FsbGluZyBbW1N1YnNjcmliZXIuY3JlYXRlVmlkZW9FbGVtZW50XV0pLiBGb3IgZXZlcnkgdmlkZW8gcmVtb3ZlZCwgZWFjaCBTdWJzY3JpYmVyIG9iamVjdCB3aWxsIGFsc28gZGlzcGF0Y2ggYSBgdmlkZW9FbGVtZW50RGVzdHJveWVkYCBldmVudC5cbiAgICAgKlxuICAgICAqIC0gYHN0cmVhbURlc3Ryb3llZGA6XG4gICAgICogICAtIElmIGRpc3BhdGNoZWQgYnkgYSBbW1B1Ymxpc2hlcl1dICgqeW91KiBoYXZlIHVucHVibGlzaGVkKTogYXV0b21hdGljYWxseSBzdG9wcyBhbGwgbWVkaWEgdHJhY2tzIGFuZCBkZWxldGVzIGFueSBIVE1MIHZpZGVvIGVsZW1lbnQgYXNzb2NpYXRlZCB0byBpdCAob25seSB0aG9zZSBjcmVhdGVkIGJ5IE9wZW5WaWR1IEJyb3dzZXIsIGVpdGhlciBieSBwYXNzaW5nIGEgdmFsaWQgcGFyYW1ldGVyIGFzIGB0YXJnZXRFbGVtZW50YFxuICAgICAqIGluIG1ldGhvZCBbW09wZW5WaWR1LmluaXRQdWJsaXNoZXJdXSBvciBieSBjYWxsaW5nIFtbUHVibGlzaGVyLmNyZWF0ZVZpZGVvRWxlbWVudF1dKS4gRm9yIGV2ZXJ5IHZpZGVvIHJlbW92ZWQsIHRoZSBQdWJsaXNoZXIgb2JqZWN0IHdpbGwgYWxzbyBkaXNwYXRjaCBhIGB2aWRlb0VsZW1lbnREZXN0cm95ZWRgIGV2ZW50LlxuICAgICAqICAgLSBJZiBkaXNwYXRjaGVkIGJ5IFtbU2Vzc2lvbl1dICgqb3RoZXIgdXNlciogaGFzIHVucHVibGlzaGVkKTogYXV0b21hdGljYWxseSB1bnN1YnNjcmliZXMgdGhlIHByb3BlciBTdWJzY3JpYmVyIG9iamVjdCBmcm9tIHRoZSBzZXNzaW9uICh0aGlzIGluY2x1ZGVzIGNsb3NpbmcgdGhlIFdlYlJUQ1BlZXIgY29ubmVjdGlvbiBhbmQgZGlzcG9zaW5nIGFsbCBNZWRpYVN0cmVhbVRyYWNrcylcbiAgICAgKiBhbmQgYWxzbyBkZWxldGVzIGFueSBIVE1MIHZpZGVvIGVsZW1lbnQgYXNzb2NpYXRlZCB0byB0aGF0IFN1YnNjcmliZXIgKG9ubHkgdGhvc2UgY3JlYXRlZCBieSBPcGVuVmlkdSBCcm93c2VyLCBlaXRoZXIgYnkgcGFzc2luZyBhIHZhbGlkIHBhcmFtZXRlciBhcyBgdGFyZ2V0RWxlbWVudGAgaW4gbWV0aG9kIFtbU2Vzc2lvbi5zdWJzY3JpYmVdXSBvclxuICAgICAqIGJ5IGNhbGxpbmcgW1tTdWJzY3JpYmVyLmNyZWF0ZVZpZGVvRWxlbWVudF1dKS4gRm9yIGV2ZXJ5IHZpZGVvIHJlbW92ZWQsIHRoZSBTdWJzY3JpYmVyIG9iamVjdCB3aWxsIGFsc28gZGlzcGF0Y2ggYSBgdmlkZW9FbGVtZW50RGVzdHJveWVkYCBldmVudC5cbiAgICAgKi9cbiAgICBwcmV2ZW50RGVmYXVsdCgpIHtcbiAgICAgICAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lOm5vLWVtcHR5XG4gICAgICAgIHRoaXMuY2FsbERlZmF1bHRCZWhhdmlvciA9ICgpID0+IHsgfTtcbiAgICAgICAgdGhpcy5oYXNCZWVuUHJldmVudGVkID0gdHJ1ZTtcbiAgICB9XG5cbiAgICBwcm90ZWN0ZWQgYWJzdHJhY3QgY2FsbERlZmF1bHRCZWhhdmlvcigpO1xuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBFdmVudCB9IGZyb20gJy4vRXZlbnQnO1xuaW1wb3J0IHsgQ29ubmVjdGlvbiB9IGZyb20gJy4uLy4uL09wZW5WaWR1L0Nvbm5lY3Rpb24nO1xuaW1wb3J0IHsgU2Vzc2lvbiB9IGZyb20gJy4uLy4uJztcblxuXG4vKipcbiAqIERlZmluZXMgdGhlIGZvbGxvd2luZyBldmVudHM6XG4gKiAtIGBwdWJsaXNoZXJTdGFydFNwZWFraW5nYDogZGlzcGF0Y2hlZCBieSBbW1Nlc3Npb25dXVxuICogLSBgcHVibGlzaGVyU3RvcFNwZWFraW5nYDogZGlzcGF0Y2hlZCBieSBbW1Nlc3Npb25dXVxuICpcbiAqIE1vcmUgaW5mb3JtYXRpb246XG4gKiAtIFRoaXMgZXZlbnRzIHdpbGwgb25seSBiZSB0cmlnZ2VyZWQgZm9yICoqcmVtb3RlIHN0cmVhbXMgdGhhdCBoYXZlIGF1ZGlvIHRyYWNrcyoqIChbW1N0cmVhbS5oYXNBdWRpb11dIG11c3QgYmUgdHJ1ZSlcbiAqIC0gQm90aCBldmVudHMgc2hhcmUgdGhlIHNhbWUgbGlmZWN5Y2xlLiBUaGF0IG1lYW5zIHRoYXQgeW91IGNhbiBzdWJzY3JpYmUgdG8gb25seSBvbmUgb2YgdGhlbSBpZiB5b3Ugd2FudCwgYnV0IGlmIHlvdSBjYWxsIGBTZXNzaW9uLm9mZigncHVibGlzaGVyU3RvcFNwZWFraW5nJylgLFxuICoga2VlcCBpbiBtaW5kIHRoYXQgdGhpcyB3aWxsIGFsc28gaW50ZXJuYWxseSByZW1vdmUgYW55ICdwdWJsaXNoZXJTdGFydFNwZWFraW5nJyBldmVudFxuICogLSBZb3UgY2FuIGZ1cnRoZXIgY29uZmlndXJlIGhvdyB0aGUgZXZlbnRzIGFyZSBkaXNwYXRjaGVkIGJ5IHNldHRpbmcgcHJvcGVydHkgYHB1Ymxpc2hlclNwZWFraW5nRXZlbnRzT3B0aW9uc2AgaW4gdGhlIGNhbGwgb2YgW1tPcGVuVmlkdS5zZXRBZHZhbmNlZENvbmZpZ3VyYXRpb25dXVxuICovXG5leHBvcnQgY2xhc3MgUHVibGlzaGVyU3BlYWtpbmdFdmVudCBleHRlbmRzIEV2ZW50IHtcblxuICAgIC8qKlxuICAgICAqIFRoZSBjbGllbnQgdGhhdCBzdGFydGVkIG9yIHN0b3BwZWQgc3BlYWtpbmdcbiAgICAgKi9cbiAgICBjb25uZWN0aW9uOiBDb25uZWN0aW9uO1xuXG4gICAgLyoqXG4gICAgICogVGhlIHN0cmVhbUlkIG9mIHRoZSBTdHJlYW0gYWZmZWN0ZWQgYnkgdGhlIHNwZWFraW5nIGV2ZW50XG4gICAgICovXG4gICAgc3RyZWFtSWQ6IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3Rvcih0YXJnZXQ6IFNlc3Npb24sIHR5cGU6IHN0cmluZywgY29ubmVjdGlvbjogQ29ubmVjdGlvbiwgc3RyZWFtSWQ6IHN0cmluZykge1xuICAgICAgICBzdXBlcihmYWxzZSwgdGFyZ2V0LCB0eXBlKTtcbiAgICAgICAgdGhpcy50eXBlID0gdHlwZTtcbiAgICAgICAgdGhpcy5jb25uZWN0aW9uID0gY29ubmVjdGlvbjtcbiAgICAgICAgdGhpcy5zdHJlYW1JZCA9IHN0cmVhbUlkO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6bm8tZW1wdHlcbiAgICBjYWxsRGVmYXVsdEJlaGF2aW9yKCkgeyB9XG5cbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IEV2ZW50IH0gZnJvbSAnLi9FdmVudCc7XG5pbXBvcnQgeyBTZXNzaW9uIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvU2Vzc2lvbic7XG5cblxuLyoqXG4gKiBEZWZpbmVzIHRoZSBmb2xsb3dpbmcgZXZlbnRzOlxuICogLSBgcmVjb3JkaW5nU3RhcnRlZGA6IGRpc3BhdGNoZWQgYnkgW1tTZXNzaW9uXV1cbiAqIC0gYHJlY29yZGluZ1N0b3BwZWRgOiBkaXNwYXRjaGVkIGJ5IFtbU2Vzc2lvbl1dXG4gKi9cbmV4cG9ydCBjbGFzcyBSZWNvcmRpbmdFdmVudCBleHRlbmRzIEV2ZW50IHtcblxuICAgIC8qKlxuICAgICAqIFRoZSByZWNvcmRpbmcgSUQgZ2VuZXJhdGVkIGluIG9wZW52aWR1LXNlcnZlclxuICAgICAqL1xuICAgIGlkOiBzdHJpbmc7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgcmVjb3JkaW5nIG5hbWUgeW91IHN1cHBsaWVkIHRvIG9wZW52aWR1LXNlcnZlci4gRm9yIGV4YW1wbGUsIHRvIG5hbWUgeW91ciByZWNvcmRpbmcgZmlsZSBNWV9SRUNPUkRJTkc6XG4gICAgICogLSBXaXRoICoqQVBJIFJFU1QqKjogUE9TVCB0byBgL2FwaS9yZWNvcmRpbmdzL3N0YXJ0YCBwYXNzaW5nIEpTT04gYm9keSBge1wic2Vzc2lvblwiOlwic2Vzc2lvbklkXCIsXCJuYW1lXCI6XCJNWV9SRUNPUkRJTkdcIn1gXG4gICAgICogLSBXaXRoICoqb3BlbnZpZHUtamF2YS1jbGllbnQqKjogYE9wZW5WaWR1LnN0YXJ0UmVjb3JkaW5nKHNlc3Npb25JZCwgXCJNWV9SRUNPUkRJTkdcIilgIG9yIGBPcGVuVmlkdS5zdGFydFJlY29yZGluZyhzZXNzaW9uSWQsIG5ldyBSZWNvcmRpbmdQcm9wZXJ0aWVzLkJ1aWxkZXIoKS5uYW1lKFwiTVlfUkVDT1JESU5HXCIpLmJ1aWxkKCkpYFxuICAgICAqIC0gV2l0aCAqKm9wZW52aWR1LW5vZGUtY2xpZW50Kio6IGBPcGVuVmlkdS5zdGFydFJlY29yZGluZyhzZXNzaW9uSWQsIFwiTVlfUkVDT1JESU5HXCIpYCBvciBgT3BlblZpZHUuc3RhcnRSZWNvcmRpbmcoc2Vzc2lvbklkLCB7bmFtZTogXCJNWV9SRUNPUkRJTkdcIn0pYFxuICAgICAqXG4gICAgICogSWYgbm8gbmFtZSBpcyBzdXBwbGllZCwgdGhpcyBwcm9wZXJ0eSB3aWxsIGJlIHVuZGVmaW5lZCBhbmQgdGhlIHJlY29yZGVkIGZpbGUgd2lsbCBiZSBuYW1lZCBhZnRlciBwcm9wZXJ0eSBbW2lkXV1cbiAgICAgKi9cbiAgICBuYW1lPzogc3RyaW5nO1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHRhcmdldDogU2Vzc2lvbiwgdHlwZTogc3RyaW5nLCBpZDogc3RyaW5nLCBuYW1lOiBzdHJpbmcpIHtcbiAgICAgICAgc3VwZXIoZmFsc2UsIHRhcmdldCwgdHlwZSk7XG4gICAgICAgIHRoaXMuaWQgPSBpZDtcbiAgICAgICAgaWYgKG5hbWUgIT09IGlkKSB7XG4gICAgICAgICAgICB0aGlzLm5hbWUgPSBuYW1lO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZTpuby1lbXB0eVxuICAgIGNhbGxEZWZhdWx0QmVoYXZpb3IoKSB7IH1cblxufSIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTctMjAxOCBPcGVuVmlkdSAoaHR0cHM6Ly9vcGVudmlkdS5pby8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuaW1wb3J0IHsgRXZlbnQgfSBmcm9tICcuL0V2ZW50JztcbmltcG9ydCB7IFNlc3Npb24gfSBmcm9tICcuLi8uLi9PcGVuVmlkdS9TZXNzaW9uJztcblxuXG4vKipcbiAqIERlZmluZXMgZXZlbnQgYHNlc3Npb25EaXNjb25uZWN0ZWRgIGRpc3BhdGNoZWQgYnkgW1tTZXNzaW9uXV1cbiAqL1xuZXhwb3J0IGNsYXNzIFNlc3Npb25EaXNjb25uZWN0ZWRFdmVudCBleHRlbmRzIEV2ZW50IHtcblxuICAgIC8qKlxuICAgICAqIC0gXCJkaXNjb25uZWN0XCI6IHlvdSBoYXZlIGNhbGxlZCBgU2Vzc2lvbi5kaXNjb25uZWN0KClgXG4gICAgICogLSBcImZvcmNlRGlzY29ubmVjdEJ5VXNlclwiOiB5b3UgaGF2ZSBiZWVuIGV2aWN0ZWQgZnJvbSB0aGUgU2Vzc2lvbiBieSBvdGhlciB1c2VyIGNhbGxpbmcgYFNlc3Npb24uZm9yY2VEaXNjb25uZWN0KClgXG4gICAgICogLSBcImZvcmNlRGlzY29ubmVjdEJ5U2VydmVyXCI6IHlvdSBoYXZlIGJlZW4gZXZpY3RlZCBmcm9tIHRoZSBTZXNzaW9uIGJ5IHRoZSBhcHBsaWNhdGlvblxuICAgICAqIC0gXCJzZXNzaW9uQ2xvc2VkQnlTZXJ2ZXJcIjogdGhlIFNlc3Npb24gaGFzIGJlZW4gY2xvc2VkIGJ5IHRoZSBhcHBsaWNhdGlvblxuICAgICAqIC0gXCJuZXR3b3JrRGlzY29ubmVjdFwiOiB5b3VyIG5ldHdvcmsgY29ubmVjdGlvbiBoYXMgZHJvcHBlZFxuICAgICAqL1xuICAgIHJlYXNvbjogc3RyaW5nO1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHRhcmdldDogU2Vzc2lvbiwgcmVhc29uOiBzdHJpbmcpIHtcbiAgICAgICAgc3VwZXIodHJ1ZSwgdGFyZ2V0LCAnc2Vzc2lvbkRpc2Nvbm5lY3RlZCcpO1xuICAgICAgICB0aGlzLnJlYXNvbiA9IHJlYXNvbjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgY2FsbERlZmF1bHRCZWhhdmlvcigpIHtcblxuICAgICAgICBjb25zb2xlLmluZm8oXCJDYWxsaW5nIGRlZmF1bHQgYmVoYXZpb3IgdXBvbiAnXCIgKyB0aGlzLnR5cGUgKyBcIicgZXZlbnQgZGlzcGF0Y2hlZCBieSAnU2Vzc2lvbidcIik7XG5cbiAgICAgICAgY29uc3Qgc2Vzc2lvbiA9IDxTZXNzaW9uPnRoaXMudGFyZ2V0O1xuXG4gICAgICAgIC8vIERpc3Bvc2UgYW5kIGRlbGV0ZSBhbGwgcmVtb3RlIENvbm5lY3Rpb25zXG4gICAgICAgIGZvciAoY29uc3QgY29ubmVjdGlvbklkIGluIHNlc3Npb24ucmVtb3RlQ29ubmVjdGlvbnMpIHtcbiAgICAgICAgICAgIGlmICghIXNlc3Npb24ucmVtb3RlQ29ubmVjdGlvbnNbY29ubmVjdGlvbklkXS5zdHJlYW0pIHtcbiAgICAgICAgICAgICAgICBzZXNzaW9uLnJlbW90ZUNvbm5lY3Rpb25zW2Nvbm5lY3Rpb25JZF0uc3RyZWFtLmRpc3Bvc2VXZWJSdGNQZWVyKCk7XG4gICAgICAgICAgICAgICAgc2Vzc2lvbi5yZW1vdGVDb25uZWN0aW9uc1tjb25uZWN0aW9uSWRdLnN0cmVhbS5kaXNwb3NlTWVkaWFTdHJlYW0oKTtcbiAgICAgICAgICAgICAgICBpZiAoc2Vzc2lvbi5yZW1vdGVDb25uZWN0aW9uc1tjb25uZWN0aW9uSWRdLnN0cmVhbS5zdHJlYW1NYW5hZ2VyKSB7XG4gICAgICAgICAgICAgICAgICAgIHNlc3Npb24ucmVtb3RlQ29ubmVjdGlvbnNbY29ubmVjdGlvbklkXS5zdHJlYW0uc3RyZWFtTWFuYWdlci5yZW1vdmVBbGxWaWRlb3MoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZGVsZXRlIHNlc3Npb24ucmVtb3RlU3RyZWFtc0NyZWF0ZWRbc2Vzc2lvbi5yZW1vdGVDb25uZWN0aW9uc1tjb25uZWN0aW9uSWRdLnN0cmVhbS5zdHJlYW1JZF07XG4gICAgICAgICAgICAgICAgc2Vzc2lvbi5yZW1vdGVDb25uZWN0aW9uc1tjb25uZWN0aW9uSWRdLmRpc3Bvc2UoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGRlbGV0ZSBzZXNzaW9uLnJlbW90ZUNvbm5lY3Rpb25zW2Nvbm5lY3Rpb25JZF07XG4gICAgICAgIH1cbiAgICB9XG5cbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IEV2ZW50IH0gZnJvbSAnLi9FdmVudCc7XG5pbXBvcnQgeyBDb25uZWN0aW9uIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvQ29ubmVjdGlvbic7XG5pbXBvcnQgeyBTZXNzaW9uIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvU2Vzc2lvbic7XG5cblxuLyoqXG4gKiBEZWZpbmVzIHRoZSBmb2xsb3dpbmcgZXZlbnRzOlxuICogLSBgc2lnbmFsYDogZGlzcGF0Y2hlZCBieSBbW1Nlc3Npb25dXVxuICogLSBgc2lnbmFsOlRZUEVgOiBkaXNwYXRjaGVkIGJ5IFtbU2Vzc2lvbl1dXG4gKi9cbmV4cG9ydCBjbGFzcyBTaWduYWxFdmVudCBleHRlbmRzIEV2ZW50IHtcblxuICAgIC8qKlxuICAgICAqIFRoZSB0eXBlIG9mIHNpZ25hbCAoY2FuIGJlIGVtcHR5KS5cbiAgICAgKlxuICAgICAqIFRoZSBjbGllbnQgbXVzdCBiZSBzdWJzY3JpYmVkIHRvIGBTZXNzaW9uLm9uKCdzaWduYWw6dHlwZScsIGZ1bmN0aW9uKHNpZ25hbEV2ZW50KSB7Li4ufSlgIHRvIHJlY2VpdmUgdGhpcyBvYmplY3QgaW4gdGhlIGNhbGxiYWNrLlxuICAgICAqXG4gICAgICogU3Vic2NyaWJpbmcgdG8gYFNlc3Npb24ub24oJ3NpZ25hbCcsIGZ1bmN0aW9uKHNpZ25hbEV2ZW50KSB7Li4ufSlgIHdpbGwgdHJpZ2dlciBhbGwgdHlwZXMgb2Ygc2lnbmFscy5cbiAgICAgKi9cbiAgICB0eXBlOiBzdHJpbmc7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgbWVzc2FnZSBvZiB0aGUgc2lnbmFsIChjYW4gYmUgZW10cHkpXG4gICAgICovXG4gICAgZGF0YTogc3RyaW5nO1xuXG4gICAgLyoqXG4gICAgICogVGhlIGNsaWVudCB0aGF0IHNlbnQgdGhlIHNpZ25hbFxuICAgICAqL1xuICAgIGZyb206IENvbm5lY3Rpb247XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgY29uc3RydWN0b3IodGFyZ2V0OiBTZXNzaW9uLCB0eXBlOiBzdHJpbmcsIGRhdGE6IHN0cmluZywgZnJvbTogQ29ubmVjdGlvbikge1xuICAgICAgICBzdXBlcihmYWxzZSwgdGFyZ2V0LCB0eXBlKTtcbiAgICAgICAgdGhpcy50eXBlID0gdHlwZTtcbiAgICAgICAgdGhpcy5kYXRhID0gZGF0YTtcbiAgICAgICAgdGhpcy5mcm9tID0gZnJvbTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lOm5vLWVtcHR5XG4gICAgY2FsbERlZmF1bHRCZWhhdmlvcigpIHsgfVxuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBFdmVudCB9IGZyb20gJy4vRXZlbnQnO1xuaW1wb3J0IHsgUHVibGlzaGVyIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvUHVibGlzaGVyJztcbmltcG9ydCB7IFNlc3Npb24gfSBmcm9tICcuLi8uLi9PcGVuVmlkdS9TZXNzaW9uJztcbmltcG9ydCB7IFN0cmVhbSB9IGZyb20gJy4uLy4uL09wZW5WaWR1L1N0cmVhbSc7XG5cblxuLyoqXG4gKiBEZWZpbmVzIHRoZSBmb2xsb3dpbmcgZXZlbnRzOlxuICogLSBgc3RyZWFtQ3JlYXRlZGA6IGRpc3BhdGNoZWQgYnkgW1tTZXNzaW9uXV0gYW5kIFtbUHVibGlzaGVyXV1cbiAqIC0gYHN0cmVhbURlc3Ryb3llZGA6IGRpc3BhdGNoZWQgYnkgW1tTZXNzaW9uXV0gYW5kIFtbUHVibGlzaGVyXV1cbiAqL1xuZXhwb3J0IGNsYXNzIFN0cmVhbUV2ZW50IGV4dGVuZHMgRXZlbnQge1xuXG4gICAgLyoqXG4gICAgICogU3RyZWFtIG9iamVjdCB0aGF0IHdhcyBjcmVhdGVkIG9yIGRlc3Ryb3llZFxuICAgICAqL1xuICAgIHN0cmVhbTogU3RyZWFtO1xuXG4gICAgLyoqXG4gICAgICogRm9yICdzdHJlYW1EZXN0cm95ZWQnIGV2ZW50OlxuICAgICAqIC0gXCJ1bnB1Ymxpc2hcIjogbWV0aG9kIGBTZXNzaW9uLnVucHVibGlzaCgpYCBoYXMgYmVlbiBjYWxsZWRcbiAgICAgKiAtIFwiZGlzY29ubmVjdFwiOiBtZXRob2QgYFNlc3Npb24uZGlzY29ubmVjdCgpYCBoYXMgYmVlbiBjYWxsZWRcbiAgICAgKiAtIFwiZm9yY2VVbnB1Ymxpc2hCeVVzZXJcIjogc29tZSB1c2VyIGhhcyBjYWxsZWQgYFNlc3Npb24uZm9yY2VVbnB1Ymxpc2goKWAgb3ZlciB0aGUgU3RyZWFtXG4gICAgICogLSBcImZvcmNlRGlzY29ubmVjdEJ5VXNlclwiOiBzb21lIHVzZXIgaGFzIGNhbGxlZCBgU2Vzc2lvbi5mb3JjZURpc2Nvbm5lY3QoKWAgb3ZlciB0aGUgU3RyZWFtXG4gICAgICogLSBcImZvcmNlVW5wdWJsaXNoQnlTZXJ2ZXJcIjogdGhlIHVzZXIncyBzdHJlYW0gaGFzIGJlZW4gdW5wdWJsaXNoZWQgZnJvbSB0aGUgU2Vzc2lvbiBieSB0aGUgYXBwbGljYXRpb25cbiAgICAgKiAtIFwiZm9yY2VEaXNjb25uZWN0QnlTZXJ2ZXJcIjogdGhlIHVzZXIgaGFzIGJlZW4gZXZpY3RlZCBmcm9tIHRoZSBTZXNzaW9uIGJ5IHRoZSBhcHBsaWNhdGlvblxuICAgICAqIC0gXCJzZXNzaW9uQ2xvc2VkQnlTZXJ2ZXJcIjogdGhlIFNlc3Npb24gaGFzIGJlZW4gY2xvc2VkIGJ5IHRoZSBhcHBsaWNhdGlvblxuICAgICAqIC0gXCJuZXR3b3JrRGlzY29ubmVjdFwiOiB0aGUgdXNlcidzIG5ldHdvcmsgY29ubmVjdGlvbiBoYXMgZHJvcHBlZFxuICAgICAqXG4gICAgICogRm9yICdzdHJlYW1DcmVhdGVkJyBlbXB0eSBzdHJpbmdcbiAgICAgKi9cbiAgICByZWFzb246IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3RvcihjYW5jZWxhYmxlOiBib29sZWFuLCB0YXJnZXQ6IFNlc3Npb24gfCBQdWJsaXNoZXIsIHR5cGU6IHN0cmluZywgc3RyZWFtOiBTdHJlYW0sIHJlYXNvbjogc3RyaW5nKSB7XG4gICAgICAgIHN1cGVyKGNhbmNlbGFibGUsIHRhcmdldCwgdHlwZSk7XG4gICAgICAgIHRoaXMuc3RyZWFtID0gc3RyZWFtO1xuICAgICAgICB0aGlzLnJlYXNvbiA9IHJlYXNvbjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgY2FsbERlZmF1bHRCZWhhdmlvcigpIHtcbiAgICAgICAgaWYgKHRoaXMudHlwZSA9PT0gJ3N0cmVhbURlc3Ryb3llZCcpIHtcblxuICAgICAgICAgICAgaWYgKHRoaXMudGFyZ2V0IGluc3RhbmNlb2YgU2Vzc2lvbikge1xuICAgICAgICAgICAgICAgIC8vIFJlbW90ZSBTdHJlYW1cbiAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oXCJDYWxsaW5nIGRlZmF1bHQgYmVoYXZpb3IgdXBvbiAnXCIgKyB0aGlzLnR5cGUgKyBcIicgZXZlbnQgZGlzcGF0Y2hlZCBieSAnU2Vzc2lvbidcIik7XG4gICAgICAgICAgICAgICAgdGhpcy5zdHJlYW0uZGlzcG9zZVdlYlJ0Y1BlZXIoKTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAodGhpcy50YXJnZXQgaW5zdGFuY2VvZiBQdWJsaXNoZXIpIHtcbiAgICAgICAgICAgICAgICAvLyBMb2NhbCBTdHJlYW1cbiAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oXCJDYWxsaW5nIGRlZmF1bHQgYmVoYXZpb3IgdXBvbiAnXCIgKyB0aGlzLnR5cGUgKyBcIicgZXZlbnQgZGlzcGF0Y2hlZCBieSAnUHVibGlzaGVyJ1wiKTtcbiAgICAgICAgICAgICAgICBjbGVhckludGVydmFsKCg8UHVibGlzaGVyPnRoaXMudGFyZ2V0KS5zY3JlZW5TaGFyZVJlc2l6ZUludGVydmFsKTtcbiAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbS5pc0xvY2FsU3RyZWFtUmVhZHlUb1B1Ymxpc2ggPSBmYWxzZTtcblxuICAgICAgICAgICAgICAgIC8vIERlbGV0ZSBQdWJsaXNoZXIgb2JqZWN0IGZyb20gT3BlblZpZHUgcHVibGlzaGVycyBhcnJheVxuICAgICAgICAgICAgICAgIGNvbnN0IG9wZW52aWR1UHVibGlzaGVycyA9ICg8UHVibGlzaGVyPnRoaXMudGFyZ2V0KS5vcGVudmlkdS5wdWJsaXNoZXJzO1xuICAgICAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgb3BlbnZpZHVQdWJsaXNoZXJzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChvcGVudmlkdVB1Ymxpc2hlcnNbaV0gPT09ICg8UHVibGlzaGVyPnRoaXMudGFyZ2V0KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgb3BlbnZpZHVQdWJsaXNoZXJzLnNwbGljZShpLCAxKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBEaXNwb3NlIHRoZSBNZWRpYVN0cmVhbSBsb2NhbCBvYmplY3RcbiAgICAgICAgICAgIHRoaXMuc3RyZWFtLmRpc3Bvc2VNZWRpYVN0cmVhbSgpO1xuXG4gICAgICAgICAgICAvLyBSZW1vdmUgZnJvbSBET00gYWxsIHZpZGVvIGVsZW1lbnRzIGFzc29jaWF0ZWQgdG8gdGhpcyBTdHJlYW0sIGlmIHRoZXJlJ3MgYSBTdHJlYW1NYW5hZ2VyIGRlZmluZWRcbiAgICAgICAgICAgIC8vIChtZXRob2QgU2Vzc2lvbi5zdWJzY3JpYmUgbXVzdCBoYXZlIGJlZW4gY2FsbGVkKVxuICAgICAgICAgICAgaWYgKHRoaXMuc3RyZWFtLnN0cmVhbU1hbmFnZXIpIHRoaXMuc3RyZWFtLnN0cmVhbU1hbmFnZXIucmVtb3ZlQWxsVmlkZW9zKCk7XG5cbiAgICAgICAgICAgIC8vIERlbGV0ZSBzdHJlYW0gZnJvbSBTZXNzaW9uLnJlbW90ZVN0cmVhbXNDcmVhdGVkIG1hcFxuICAgICAgICAgICAgZGVsZXRlIHRoaXMuc3RyZWFtLnNlc3Npb24ucmVtb3RlU3RyZWFtc0NyZWF0ZWRbdGhpcy5zdHJlYW0uc3RyZWFtSWRdO1xuXG4gICAgICAgICAgICAvLyBEZWxldGUgU3RyZWFtT3B0aW9uc1NlcnZlciBmcm9tIHJlbW90ZSBDb25uZWN0aW9uXG4gICAgICAgICAgICBjb25zdCByZW1vdGVDb25uZWN0aW9uID0gdGhpcy5zdHJlYW0uc2Vzc2lvbi5yZW1vdGVDb25uZWN0aW9uc1t0aGlzLnN0cmVhbS5jb25uZWN0aW9uLmNvbm5lY3Rpb25JZF07XG4gICAgICAgICAgICBpZiAoISFyZW1vdGVDb25uZWN0aW9uICYmICEhcmVtb3RlQ29ubmVjdGlvbi5vcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgY29uc3Qgc3RyZWFtT3B0aW9uc1NlcnZlciA9IHJlbW90ZUNvbm5lY3Rpb24ub3B0aW9ucy5zdHJlYW1zO1xuICAgICAgICAgICAgICAgIGZvciAobGV0IGkgPSBzdHJlYW1PcHRpb25zU2VydmVyLmxlbmd0aCAtIDE7IGkgPj0gMDsgLS1pKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChzdHJlYW1PcHRpb25zU2VydmVyW2ldLmlkID09PSB0aGlzLnN0cmVhbS5zdHJlYW1JZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgc3RyZWFtT3B0aW9uc1NlcnZlci5zcGxpY2UoaSwgMSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgfVxuICAgIH1cblxufSIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTctMjAxOCBPcGVuVmlkdSAoaHR0cHM6Ly9vcGVudmlkdS5pby8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuaW1wb3J0IHsgRXZlbnQgfSBmcm9tICcuL0V2ZW50JztcbmltcG9ydCB7IFN0cmVhbU1hbmFnZXIgfSBmcm9tICcuLi8uLi9PcGVuVmlkdS9TdHJlYW1NYW5hZ2VyJztcblxuLyoqXG4gKiBEZWZpbmVzIHRoZSBmb2xsb3dpbmcgZXZlbnRzOlxuICogLSBgc3RyZWFtUGxheWluZ2A6IGRpc3BhdGNoZWQgYnkgW1tTdHJlYW1NYW5hZ2VyXV0gKFtbUHVibGlzaGVyXV0gYW5kIFtbU3Vic2NyaWJlcl1dKVxuICovXG5leHBvcnQgY2xhc3MgU3RyZWFtTWFuYWdlckV2ZW50IGV4dGVuZHMgRXZlbnQge1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHRhcmdldDogU3RyZWFtTWFuYWdlcikge1xuICAgICAgICBzdXBlcihmYWxzZSwgdGFyZ2V0LCAnc3RyZWFtUGxheWluZycpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6bm8tZW1wdHlcbiAgICBjYWxsRGVmYXVsdEJlaGF2aW9yKCkgeyB9XG5cbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IEV2ZW50IH0gZnJvbSAnLi9FdmVudCc7XG5pbXBvcnQgeyBTZXNzaW9uIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvU2Vzc2lvbic7XG5pbXBvcnQgeyBTdHJlYW0gfSBmcm9tICcuLi8uLi9PcGVuVmlkdS9TdHJlYW0nO1xuaW1wb3J0IHsgU3RyZWFtTWFuYWdlciB9IGZyb20gJy4uLy4uL09wZW5WaWR1L1N0cmVhbU1hbmFnZXInO1xuXG4vKipcbiAqIERlZmluZXMgZXZlbnQgYHN0cmVhbVByb3BlcnR5Q2hhbmdlZGAgZGlzcGF0Y2hlZCBieSBbW1Nlc3Npb25dXSBhcyB3ZWxsIGFzIGJ5IFtbU3RyZWFtTWFuYWdlcl1dIChbW1B1Ymxpc2hlcl1dIGFuZCBbW1N1YnNjcmliZXJdXSkuXG4gKiBUaGlzIGV2ZW50IGlzIGZpcmVkIHdoZW4gYW55IHJlbW90ZSBzdHJlYW0gKG93bmVkIGJ5IGEgU3Vic2NyaWJlcikgb3IgbG9jYWwgc3RyZWFtIChvd25lZCBieSBhIFB1Ymxpc2hlcikgdW5kZXJnb2VzXG4gKiBhbnkgY2hhbmdlIGluIGFueSBvZiBpdHMgbXV0YWJsZSBwcm9wZXJ0aWVzIChzZWUgW1tjaGFuZ2VkUHJvcGVydHldXSkuXG4gKi9cbmV4cG9ydCBjbGFzcyBTdHJlYW1Qcm9wZXJ0eUNoYW5nZWRFdmVudCBleHRlbmRzIEV2ZW50IHtcblxuICAgIC8qKlxuICAgICAqIFRoZSBTdHJlYW0gd2hvc2UgcHJvcGVydHkgaGFzIGNoYW5nZWQuIFlvdSBjYW4gYWx3YXlzIGlkZW50aWZ5IHRoZSB1c2VyIHB1Ymxpc2hpbmcgdGhlIGNoYW5nZWQgc3RyZWFtIGJ5IGNvbnN1bHRpbmcgcHJvcGVydHkgW1tTdHJlYW0uY29ubmVjdGlvbl1dXG4gICAgICovXG4gICAgc3RyZWFtOiBTdHJlYW07XG5cbiAgICAvKipcbiAgICAgKiBUaGUgcHJvcGVydHkgb2YgdGhlIHN0cmVhbSB0aGF0IGNoYW5nZWQuIFRoaXMgdmFsdWUgaXMgZWl0aGVyIGBcInZpZGVvQWN0aXZlXCJgLCBgXCJhdWRpb0FjdGl2ZVwiYCBvciBgXCJ2aWRlb0RpbWVuc2lvbnNcImBcbiAgICAgKi9cbiAgICBjaGFuZ2VkUHJvcGVydHk6IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIENhdXNlIG9mIHRoZSBjaGFuZ2Ugb24gdGhlIHN0cmVhbSdzIHByb3BlcnR5OlxuICAgICAqIC0gRm9yIGB2aWRlb0FjdGl2ZWA6IGBcInB1Ymxpc2hWaWRlb1wiYFxuICAgICAqIC0gRm9yIGBhdWRpb0FjdGl2ZWA6IGBcInB1Ymxpc2hBdWRpb1wiYFxuICAgICAqIC0gRm9yIGB2aWRlb0RpbWVuc2lvbnNgOiBgXCJkZXZpY2VSb3RhdGVkXCJgIG9yIGBcInNjcmVlblJlc2l6ZWRcImBcbiAgICAgKi9cbiAgICByZWFzb246IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIE5ldyB2YWx1ZSBvZiB0aGUgcHJvcGVydHkgKGFmdGVyIGNoYW5nZSwgY3VycmVudCB2YWx1ZSlcbiAgICAgKi9cbiAgICBuZXdWYWx1ZTogT2JqZWN0O1xuXG4gICAgLyoqXG4gICAgICogUHJldmlvdXMgdmFsdWUgb2YgdGhlIHByb3BlcnR5IChiZWZvcmUgY2hhbmdlKVxuICAgICAqL1xuICAgIG9sZFZhbHVlOiBPYmplY3Q7XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgY29uc3RydWN0b3IodGFyZ2V0OiBTZXNzaW9uIHwgU3RyZWFtTWFuYWdlciwgc3RyZWFtOiBTdHJlYW0sIGNoYW5nZWRQcm9wZXJ0eTogc3RyaW5nLCBuZXdWYWx1ZTogT2JqZWN0LCBvbGRWYWx1ZTogT2JqZWN0LCByZWFzb246IHN0cmluZykge1xuICAgICAgICBzdXBlcihmYWxzZSwgdGFyZ2V0LCAnc3RyZWFtUHJvcGVydHlDaGFuZ2VkJyk7XG4gICAgICAgIHRoaXMuc3RyZWFtID0gc3RyZWFtO1xuICAgICAgICB0aGlzLmNoYW5nZWRQcm9wZXJ0eSA9IGNoYW5nZWRQcm9wZXJ0eTtcbiAgICAgICAgdGhpcy5uZXdWYWx1ZSA9IG5ld1ZhbHVlO1xuICAgICAgICB0aGlzLm9sZFZhbHVlID0gb2xkVmFsdWU7XG4gICAgICAgIHRoaXMucmVhc29uID0gcmVhc29uO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6bm8tZW1wdHlcbiAgICBjYWxsRGVmYXVsdEJlaGF2aW9yKCkgeyB9XG5cbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IEV2ZW50IH0gZnJvbSAnLi9FdmVudCc7XG5pbXBvcnQgeyBTdHJlYW1NYW5hZ2VyIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvU3RyZWFtTWFuYWdlcic7XG5cblxuLyoqXG4gKiBEZWZpbmVzIHRoZSBmb2xsb3dpbmcgZXZlbnRzOlxuICogLSBgdmlkZW9FbGVtZW50Q3JlYXRlZGA6IGRpc3BhdGNoZWQgYnkgW1tQdWJsaXNoZXJdXSBhbmQgW1tTdWJzY3JpYmVyXV0gd2hlbmV2ZXIgYSBuZXcgSFRNTCB2aWRlbyBlbGVtZW50IGhhcyBiZWVuIGluc2VydGVkIGludG8gRE9NIGJ5IE9wZW5WaWR1IEJyb3dzZXIgbGlicmFyeS4gU2VlXG4gKiBbTWFuYWdlIHZpZGVvIHBsYXllcnNdKC9kb2NzL2hvdy1kby1pL21hbmFnZS12aWRlb3MpIHNlY3Rpb24uXG4gKiAtIGB2aWRlb0VsZW1lbnREZXN0cm95ZWRgOiBkaXNwYXRjaGVkIGJ5IFtbUHVibGlzaGVyXV0gYW5kIFtbU3Vic2NyaWJlcl1dIHdoZW5ldmVyIGFuIEhUTUwgdmlkZW8gZWxlbWVudCBoYXMgYmVlbiByZW1vdmVkIGZyb20gRE9NIGJ5IE9wZW5WaWR1IEJyb3dzZXIgbGlicmFyeS5cbiAqL1xuZXhwb3J0IGNsYXNzIFZpZGVvRWxlbWVudEV2ZW50IGV4dGVuZHMgRXZlbnQge1xuXG4gICAgLyoqXG4gICAgICogVmlkZW8gZWxlbWVudCB0aGF0IHdhcyBjcmVhdGVkIG9yIGRlc3Ryb3llZFxuICAgICAqL1xuICAgIGVsZW1lbnQ6IEhUTUxWaWRlb0VsZW1lbnQ7XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgY29uc3RydWN0b3IoZWxlbWVudDogSFRNTFZpZGVvRWxlbWVudCwgdGFyZ2V0OiBTdHJlYW1NYW5hZ2VyLCB0eXBlOiBzdHJpbmcpIHtcbiAgICAgICAgc3VwZXIoZmFsc2UsIHRhcmdldCwgdHlwZSk7XG4gICAgICAgIHRoaXMuZWxlbWVudCA9IGVsZW1lbnQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZTpuby1lbXB0eVxuICAgIGNhbGxEZWZhdWx0QmVoYXZpb3IoKSB7IH1cblxufSIsImZ1bmN0aW9uIE1hcHBlcigpXG57XG4gIHZhciBzb3VyY2VzID0ge307XG5cblxuICB0aGlzLmZvckVhY2ggPSBmdW5jdGlvbihjYWxsYmFjaylcbiAge1xuICAgIGZvcih2YXIga2V5IGluIHNvdXJjZXMpXG4gICAge1xuICAgICAgdmFyIHNvdXJjZSA9IHNvdXJjZXNba2V5XTtcblxuICAgICAgZm9yKHZhciBrZXkyIGluIHNvdXJjZSlcbiAgICAgICAgY2FsbGJhY2soc291cmNlW2tleTJdKTtcbiAgICB9O1xuICB9O1xuXG4gIHRoaXMuZ2V0ID0gZnVuY3Rpb24oaWQsIHNvdXJjZSlcbiAge1xuICAgIHZhciBpZHMgPSBzb3VyY2VzW3NvdXJjZV07XG4gICAgaWYoaWRzID09IHVuZGVmaW5lZClcbiAgICAgIHJldHVybiB1bmRlZmluZWQ7XG5cbiAgICByZXR1cm4gaWRzW2lkXTtcbiAgfTtcblxuICB0aGlzLnJlbW92ZSA9IGZ1bmN0aW9uKGlkLCBzb3VyY2UpXG4gIHtcbiAgICB2YXIgaWRzID0gc291cmNlc1tzb3VyY2VdO1xuICAgIGlmKGlkcyA9PSB1bmRlZmluZWQpXG4gICAgICByZXR1cm47XG5cbiAgICBkZWxldGUgaWRzW2lkXTtcblxuICAgIC8vIENoZWNrIGl0J3MgZW1wdHlcbiAgICBmb3IodmFyIGkgaW4gaWRzKXtyZXR1cm4gZmFsc2V9XG5cbiAgICBkZWxldGUgc291cmNlc1tzb3VyY2VdO1xuICB9O1xuXG4gIHRoaXMuc2V0ID0gZnVuY3Rpb24odmFsdWUsIGlkLCBzb3VyY2UpXG4gIHtcbiAgICBpZih2YWx1ZSA9PSB1bmRlZmluZWQpXG4gICAgICByZXR1cm4gdGhpcy5yZW1vdmUoaWQsIHNvdXJjZSk7XG5cbiAgICB2YXIgaWRzID0gc291cmNlc1tzb3VyY2VdO1xuICAgIGlmKGlkcyA9PSB1bmRlZmluZWQpXG4gICAgICBzb3VyY2VzW3NvdXJjZV0gPSBpZHMgPSB7fTtcblxuICAgIGlkc1tpZF0gPSB2YWx1ZTtcbiAgfTtcbn07XG5cblxuTWFwcGVyLnByb3RvdHlwZS5wb3AgPSBmdW5jdGlvbihpZCwgc291cmNlKVxue1xuICB2YXIgdmFsdWUgPSB0aGlzLmdldChpZCwgc291cmNlKTtcbiAgaWYodmFsdWUgPT0gdW5kZWZpbmVkKVxuICAgIHJldHVybiB1bmRlZmluZWQ7XG5cbiAgdGhpcy5yZW1vdmUoaWQsIHNvdXJjZSk7XG5cbiAgcmV0dXJuIHZhbHVlO1xufTtcblxuXG5tb2R1bGUuZXhwb3J0cyA9IE1hcHBlcjtcbiIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTQgS3VyZW50byAoaHR0cDovL2t1cmVudG8ub3JnLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG52YXIgSnNvblJwY0NsaWVudCAgPSByZXF1aXJlKCcuL2pzb25ycGNjbGllbnQnKTtcblxuXG5leHBvcnRzLkpzb25ScGNDbGllbnQgID0gSnNvblJwY0NsaWVudDsiLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE0IEt1cmVudG8gKGh0dHA6Ly9rdXJlbnRvLm9yZy8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxudmFyIFJwY0J1aWxkZXIgPSByZXF1aXJlKCcuLi8nKTtcbnZhciBXZWJTb2NrZXRXaXRoUmVjb25uZWN0aW9uID0gcmVxdWlyZSgnLi90cmFuc3BvcnRzL3dlYlNvY2tldFdpdGhSZWNvbm5lY3Rpb24nKTtcblxuRGF0ZS5ub3cgPSBEYXRlLm5vdyB8fCBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gK25ldyBEYXRlO1xufTtcblxudmFyIFBJTkdfSU5URVJWQUwgPSA1MDAwO1xuXG52YXIgUkVDT05ORUNUSU5HID0gJ1JFQ09OTkVDVElORyc7XG52YXIgQ09OTkVDVEVEID0gJ0NPTk5FQ1RFRCc7XG52YXIgRElTQ09OTkVDVEVEID0gJ0RJU0NPTk5FQ1RFRCc7XG5cbnZhciBMb2dnZXIgPSBjb25zb2xlO1xuXG4vKipcbiAqXG4gKiBoZWFydGJlYXQ6IGludGVydmFsIGluIG1zIGZvciBlYWNoIGhlYXJ0YmVhdCBtZXNzYWdlLFxuICogc2VuZENsb3NlTWVzc2FnZSA6IHRydWUgLyBmYWxzZSwgYmVmb3JlIGNsb3NpbmcgdGhlIGNvbm5lY3Rpb24sIGl0IHNlbmRzIGEgY2xvc2VTZXNzaW9uIG1lc3NhZ2VcbiAqIDxwcmU+XG4gKiB3cyA6IHtcbiAqIFx0dXJpIDogVVJJIHRvIGNvbm50ZWN0IHRvLFxuICogIHVzZVNvY2tKUyA6IHRydWUgKHVzZSBTb2NrSlMpIC8gZmFsc2UgKHVzZSBXZWJTb2NrZXQpIGJ5IGRlZmF1bHQsXG4gKiBcdG9uY29ubmVjdGVkIDogY2FsbGJhY2sgbWV0aG9kIHRvIGludm9rZSB3aGVuIGNvbm5lY3Rpb24gaXMgc3VjY2Vzc2Z1bCxcbiAqIFx0b25kaXNjb25uZWN0IDogY2FsbGJhY2sgbWV0aG9kIHRvIGludm9rZSB3aGVuIHRoZSBjb25uZWN0aW9uIGlzIGxvc3QsXG4gKiBcdG9ucmVjb25uZWN0aW5nIDogY2FsbGJhY2sgbWV0aG9kIHRvIGludm9rZSB3aGVuIHRoZSBjbGllbnQgaXMgcmVjb25uZWN0aW5nLFxuICogXHRvbnJlY29ubmVjdGVkIDogY2FsbGJhY2sgbWV0aG9kIHRvIGludm9rZSB3aGVuIHRoZSBjbGllbnQgc3VjY2Vzc2Z1bGx5IHJlY29ubmVjdHMsXG4gKiBcdG9uZXJyb3IgOiBjYWxsYmFjayBtZXRob2QgdG8gaW52b2tlIHdoZW4gdGhlcmUgaXMgYW4gZXJyb3JcbiAqIH0sXG4gKiBycGMgOiB7XG4gKiBcdHJlcXVlc3RUaW1lb3V0IDogdGltZW91dCBmb3IgYSByZXF1ZXN0LFxuICogXHRzZXNzaW9uU3RhdHVzQ2hhbmdlZDogY2FsbGJhY2sgbWV0aG9kIGZvciBjaGFuZ2VzIGluIHNlc3Npb24gc3RhdHVzLFxuICogXHRtZWRpYVJlbmVnb3RpYXRpb246IG1lZGlhUmVuZWdvdGlhdGlvblxuICogfVxuICogPC9wcmU+XG4gKi9cbmZ1bmN0aW9uIEpzb25ScGNDbGllbnQoY29uZmlndXJhdGlvbikge1xuXG4gICAgdmFyIHNlbGYgPSB0aGlzO1xuXG4gICAgdmFyIHdzQ29uZmlnID0gY29uZmlndXJhdGlvbi53cztcblxuICAgIHZhciBub3RSZWNvbm5lY3RJZk51bUxlc3NUaGFuID0gLTE7XG5cbiAgICB2YXIgcGluZ05leHROdW0gPSAwO1xuICAgIHZhciBlbmFibGVkUGluZ3MgPSB0cnVlO1xuICAgIHZhciBwaW5nUG9uZ1N0YXJ0ZWQgPSBmYWxzZTtcbiAgICB2YXIgcGluZ0ludGVydmFsO1xuXG4gICAgdmFyIHN0YXR1cyA9IERJU0NPTk5FQ1RFRDtcblxuICAgIHZhciBvbnJlY29ubmVjdGluZyA9IHdzQ29uZmlnLm9ucmVjb25uZWN0aW5nO1xuICAgIHZhciBvbnJlY29ubmVjdGVkID0gd3NDb25maWcub25yZWNvbm5lY3RlZDtcbiAgICB2YXIgb25jb25uZWN0ZWQgPSB3c0NvbmZpZy5vbmNvbm5lY3RlZDtcbiAgICB2YXIgb25lcnJvciA9IHdzQ29uZmlnLm9uZXJyb3I7XG5cbiAgICBjb25maWd1cmF0aW9uLnJwYy5wdWxsID0gZnVuY3Rpb24ocGFyYW1zLCByZXF1ZXN0KSB7XG4gICAgICAgIHJlcXVlc3QucmVwbHkobnVsbCwgXCJwdXNoXCIpO1xuICAgIH1cblxuICAgIHdzQ29uZmlnLm9ucmVjb25uZWN0aW5nID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIExvZ2dlci5kZWJ1ZyhcIi0tLS0tLS0tLSBPTlJFQ09OTkVDVElORyAtLS0tLS0tLS0tLVwiKTtcbiAgICAgICAgaWYgKHN0YXR1cyA9PT0gUkVDT05ORUNUSU5HKSB7XG4gICAgICAgICAgICBMb2dnZXIuZXJyb3IoXCJXZWJzb2NrZXQgYWxyZWFkeSBpbiBSRUNPTk5FQ1RJTkcgc3RhdGUgd2hlbiByZWNlaXZpbmcgYSBuZXcgT05SRUNPTk5FQ1RJTkcgbWVzc2FnZS4gSWdub3JpbmcgaXRcIik7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBzdGF0dXMgPSBSRUNPTk5FQ1RJTkc7XG4gICAgICAgIGlmIChvbnJlY29ubmVjdGluZykge1xuICAgICAgICAgICAgb25yZWNvbm5lY3RpbmcoKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHdzQ29uZmlnLm9ucmVjb25uZWN0ZWQgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgTG9nZ2VyLmRlYnVnKFwiLS0tLS0tLS0tIE9OUkVDT05ORUNURUQgLS0tLS0tLS0tLS1cIik7XG4gICAgICAgIGlmIChzdGF0dXMgPT09IENPTk5FQ1RFRCkge1xuICAgICAgICAgICAgTG9nZ2VyLmVycm9yKFwiV2Vic29ja2V0IGFscmVhZHkgaW4gQ09OTkVDVEVEIHN0YXRlIHdoZW4gcmVjZWl2aW5nIGEgbmV3IE9OUkVDT05ORUNURUQgbWVzc2FnZS4gSWdub3JpbmcgaXRcIik7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgc3RhdHVzID0gQ09OTkVDVEVEO1xuXG4gICAgICAgIGVuYWJsZWRQaW5ncyA9IHRydWU7XG4gICAgICAgIHVwZGF0ZU5vdFJlY29ubmVjdElmTGVzc1RoYW4oKTtcbiAgICAgICAgdXNlUGluZygpO1xuXG4gICAgICAgIGlmIChvbnJlY29ubmVjdGVkKSB7XG4gICAgICAgICAgICBvbnJlY29ubmVjdGVkKCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB3c0NvbmZpZy5vbmNvbm5lY3RlZCA9IGZ1bmN0aW9uKCkge1xuICAgICAgICBMb2dnZXIuZGVidWcoXCItLS0tLS0tLS0gT05DT05ORUNURUQgLS0tLS0tLS0tLS1cIik7XG4gICAgICAgIGlmIChzdGF0dXMgPT09IENPTk5FQ1RFRCkge1xuICAgICAgICAgICAgTG9nZ2VyLmVycm9yKFwiV2Vic29ja2V0IGFscmVhZHkgaW4gQ09OTkVDVEVEIHN0YXRlIHdoZW4gcmVjZWl2aW5nIGEgbmV3IE9OQ09OTkVDVEVEIG1lc3NhZ2UuIElnbm9yaW5nIGl0XCIpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHN0YXR1cyA9IENPTk5FQ1RFRDtcblxuICAgICAgICBlbmFibGVkUGluZ3MgPSB0cnVlO1xuICAgICAgICB1c2VQaW5nKCk7XG5cbiAgICAgICAgaWYgKG9uY29ubmVjdGVkKSB7XG4gICAgICAgICAgICBvbmNvbm5lY3RlZCgpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgd3NDb25maWcub25lcnJvciA9IGZ1bmN0aW9uKGVycm9yKSB7XG4gICAgICAgIExvZ2dlci5kZWJ1ZyhcIi0tLS0tLS0tLSBPTkVSUk9SIC0tLS0tLS0tLS0tXCIpO1xuXG4gICAgICAgIHN0YXR1cyA9IERJU0NPTk5FQ1RFRDtcblxuICAgICAgICBpZiAob25lcnJvcikge1xuICAgICAgICAgICAgb25lcnJvcihlcnJvcik7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB2YXIgd3MgPSBuZXcgV2ViU29ja2V0V2l0aFJlY29ubmVjdGlvbih3c0NvbmZpZyk7XG5cbiAgICBMb2dnZXIuZGVidWcoJ0Nvbm5lY3Rpbmcgd2Vic29ja2V0IHRvIFVSSTogJyArIHdzQ29uZmlnLnVyaSk7XG5cbiAgICB2YXIgcnBjQnVpbGRlck9wdGlvbnMgPSB7XG4gICAgICAgIHJlcXVlc3RfdGltZW91dDogY29uZmlndXJhdGlvbi5ycGMucmVxdWVzdFRpbWVvdXQsXG4gICAgICAgIHBpbmdfcmVxdWVzdF90aW1lb3V0OiBjb25maWd1cmF0aW9uLnJwYy5oZWFydGJlYXRSZXF1ZXN0VGltZW91dFxuICAgIH07XG5cbiAgICB2YXIgcnBjID0gbmV3IFJwY0J1aWxkZXIoUnBjQnVpbGRlci5wYWNrZXJzLkpzb25SUEMsIHJwY0J1aWxkZXJPcHRpb25zLCB3cyxcbiAgICAgICAgZnVuY3Rpb24ocmVxdWVzdCkge1xuXG4gICAgICAgICAgICBMb2dnZXIuZGVidWcoJ1JlY2VpdmVkIHJlcXVlc3Q6ICcgKyBKU09OLnN0cmluZ2lmeShyZXF1ZXN0KSk7XG5cbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgdmFyIGZ1bmMgPSBjb25maWd1cmF0aW9uLnJwY1tyZXF1ZXN0Lm1ldGhvZF07XG5cbiAgICAgICAgICAgICAgICBpZiAoZnVuYyA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgIExvZ2dlci5lcnJvcihcIk1ldGhvZCBcIiArIHJlcXVlc3QubWV0aG9kICsgXCIgbm90IHJlZ2lzdGVyZWQgaW4gY2xpZW50XCIpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGZ1bmMocmVxdWVzdC5wYXJhbXMsIHJlcXVlc3QpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgICAgIExvZ2dlci5lcnJvcignRXhjZXB0aW9uIHByb2Nlc3NpbmcgcmVxdWVzdDogJyArIEpTT04uc3RyaW5naWZ5KHJlcXVlc3QpKTtcbiAgICAgICAgICAgICAgICBMb2dnZXIuZXJyb3IoZXJyKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG5cbiAgICB0aGlzLnNlbmQgPSBmdW5jdGlvbihtZXRob2QsIHBhcmFtcywgY2FsbGJhY2spIHtcbiAgICAgICAgaWYgKG1ldGhvZCAhPT0gJ3BpbmcnKSB7XG4gICAgICAgICAgICBMb2dnZXIuZGVidWcoJ1JlcXVlc3Q6IG1ldGhvZDonICsgbWV0aG9kICsgXCIgcGFyYW1zOlwiICsgSlNPTi5zdHJpbmdpZnkocGFyYW1zKSk7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgcmVxdWVzdFRpbWUgPSBEYXRlLm5vdygpO1xuXG4gICAgICAgIHJwYy5lbmNvZGUobWV0aG9kLCBwYXJhbXMsIGZ1bmN0aW9uKGVycm9yLCByZXN1bHQpIHtcbiAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgIExvZ2dlci5lcnJvcihcIkVSUk9SOlwiICsgZXJyb3IubWVzc2FnZSArIFwiIGluIFJlcXVlc3Q6IG1ldGhvZDpcIiArXG4gICAgICAgICAgICAgICAgICAgICAgICBtZXRob2QgKyBcIiBwYXJhbXM6XCIgKyBKU09OLnN0cmluZ2lmeShwYXJhbXMpICsgXCIgcmVxdWVzdDpcIiArXG4gICAgICAgICAgICAgICAgICAgICAgICBlcnJvci5yZXF1ZXN0KTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yLmRhdGEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIExvZ2dlci5lcnJvcihcIkVSUk9SIERBVEE6XCIgKyBKU09OLnN0cmluZ2lmeShlcnJvci5kYXRhKSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGNhdGNoIChlKSB7fVxuICAgICAgICAgICAgICAgIGVycm9yLnJlcXVlc3RUaW1lID0gcmVxdWVzdFRpbWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoY2FsbGJhY2spIHtcbiAgICAgICAgICAgICAgICBpZiAocmVzdWx0ICE9IHVuZGVmaW5lZCAmJiByZXN1bHQudmFsdWUgIT09ICdwb25nJykge1xuICAgICAgICAgICAgICAgICAgICBMb2dnZXIuZGVidWcoJ1Jlc3BvbnNlOiAnICsgSlNPTi5zdHJpbmdpZnkocmVzdWx0KSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNhbGxiYWNrKGVycm9yLCByZXN1bHQpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiB1cGRhdGVOb3RSZWNvbm5lY3RJZkxlc3NUaGFuKCkge1xuICAgICAgICBMb2dnZXIuZGVidWcoXCJub3RSZWNvbm5lY3RJZk51bUxlc3NUaGFuID0gXCIgKyBwaW5nTmV4dE51bSArICcgKG9sZD0nICtcbiAgICAgICAgICAgIG5vdFJlY29ubmVjdElmTnVtTGVzc1RoYW4gKyAnKScpO1xuICAgICAgICBub3RSZWNvbm5lY3RJZk51bUxlc3NUaGFuID0gcGluZ05leHROdW07XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gc2VuZFBpbmcoKSB7XG4gICAgICAgIGlmIChlbmFibGVkUGluZ3MpIHtcbiAgICAgICAgICAgIHZhciBwYXJhbXMgPSBudWxsO1xuICAgICAgICAgICAgaWYgKHBpbmdOZXh0TnVtID09IDAgfHwgcGluZ05leHROdW0gPT0gbm90UmVjb25uZWN0SWZOdW1MZXNzVGhhbikge1xuICAgICAgICAgICAgICAgIHBhcmFtcyA9IHtcbiAgICAgICAgICAgICAgICAgICAgaW50ZXJ2YWw6IGNvbmZpZ3VyYXRpb24uaGVhcnRiZWF0IHx8IFBJTkdfSU5URVJWQUxcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcGluZ05leHROdW0rKztcblxuICAgICAgICAgICAgc2VsZi5zZW5kKCdwaW5nJywgcGFyYW1zLCAoZnVuY3Rpb24ocGluZ051bSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmdW5jdGlvbihlcnJvciwgcmVzdWx0KSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFwiRXJyb3IgaW4gcGluZyByZXF1ZXN0ICNcIiArIHBpbmdOdW0gKyBcIiAoXCIgK1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yLm1lc3NhZ2UgKyBcIilcIik7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocGluZ051bSA+IG5vdFJlY29ubmVjdElmTnVtTGVzc1RoYW4pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbmFibGVkUGluZ3MgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB1cGRhdGVOb3RSZWNvbm5lY3RJZkxlc3NUaGFuKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFwiU2VydmVyIGRpZCBub3QgcmVzcG9uZCB0byBwaW5nIG1lc3NhZ2UgI1wiICtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGluZ051bSArIFwiLiBSZWNvbm5lY3RpbmcuLi4gXCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdzLnJlY29ubmVjdFdzKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KShwaW5nTmV4dE51bSkpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFwiVHJ5aW5nIHRvIHNlbmQgcGluZywgYnV0IHBpbmcgaXMgbm90IGVuYWJsZWRcIik7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKlxuICAgICogSWYgY29uZmlndXJhdGlvbi5oZWFyYmVhdCBoYXMgYW55IHZhbHVlLCB0aGUgcGluZy1wb25nIHdpbGwgd29yayB3aXRoIHRoZSBpbnRlcnZhbFxuICAgICogb2YgY29uZmlndXJhdGlvbi5oZWFyYmVhdFxuICAgICovXG4gICAgZnVuY3Rpb24gdXNlUGluZygpIHtcbiAgICAgICAgaWYgKCFwaW5nUG9uZ1N0YXJ0ZWQpIHtcbiAgICAgICAgICAgIExvZ2dlci5kZWJ1ZyhcIlN0YXJ0aW5nIHBpbmcgKGlmIGNvbmZpZ3VyZWQpXCIpXG4gICAgICAgICAgICBwaW5nUG9uZ1N0YXJ0ZWQgPSB0cnVlO1xuXG4gICAgICAgICAgICBpZiAoY29uZmlndXJhdGlvbi5oZWFydGJlYXQgIT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgcGluZ0ludGVydmFsID0gc2V0SW50ZXJ2YWwoc2VuZFBpbmcsIGNvbmZpZ3VyYXRpb24uaGVhcnRiZWF0KTtcbiAgICAgICAgICAgICAgICBzZW5kUGluZygpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgdGhpcy5jbG9zZSA9IGZ1bmN0aW9uKCkge1xuICAgICAgICBMb2dnZXIuZGVidWcoXCJDbG9zaW5nIGpzb25ScGNDbGllbnQgZXhwbGljaXRseSBieSBjbGllbnRcIik7XG5cbiAgICAgICAgaWYgKHBpbmdJbnRlcnZhbCAhPSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIExvZ2dlci5kZWJ1ZyhcIkNsZWFyaW5nIHBpbmcgaW50ZXJ2YWxcIik7XG4gICAgICAgICAgICBjbGVhckludGVydmFsKHBpbmdJbnRlcnZhbCk7XG4gICAgICAgIH1cbiAgICAgICAgcGluZ1BvbmdTdGFydGVkID0gZmFsc2U7XG4gICAgICAgIGVuYWJsZWRQaW5ncyA9IGZhbHNlO1xuXG4gICAgICAgIGlmIChjb25maWd1cmF0aW9uLnNlbmRDbG9zZU1lc3NhZ2UpIHtcbiAgICAgICAgICAgIExvZ2dlci5kZWJ1ZyhcIlNlbmRpbmcgY2xvc2UgbWVzc2FnZVwiKVxuICAgICAgICAgICAgdGhpcy5zZW5kKCdjbG9zZVNlc3Npb24nLCBudWxsLCBmdW5jdGlvbihlcnJvciwgcmVzdWx0KSB7XG4gICAgICAgICAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgIExvZ2dlci5lcnJvcihcIkVycm9yIHNlbmRpbmcgY2xvc2UgbWVzc2FnZTogXCIgKyBKU09OLnN0cmluZ2lmeShlcnJvcikpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB3cy5jbG9zZSgpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0gZWxzZSB7XG5cdFx0XHR3cy5jbG9zZSgpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gVGhpcyBtZXRob2QgaXMgb25seSBmb3IgdGVzdGluZ1xuICAgIHRoaXMuZm9yY2VDbG9zZSA9IGZ1bmN0aW9uKG1pbGxpcykge1xuICAgICAgICB3cy5mb3JjZUNsb3NlKG1pbGxpcyk7XG4gICAgfVxuXG4gICAgdGhpcy5yZWNvbm5lY3QgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgd3MucmVjb25uZWN0V3MoKTtcbiAgICB9XG59XG5cblxubW9kdWxlLmV4cG9ydHMgPSBKc29uUnBjQ2xpZW50O1xuIiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNCBLdXJlbnRvIChodHRwOi8va3VyZW50by5vcmcvKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbnZhciBXZWJTb2NrZXRXaXRoUmVjb25uZWN0aW9uICA9IHJlcXVpcmUoJy4vd2ViU29ja2V0V2l0aFJlY29ubmVjdGlvbicpO1xuXG5cbmV4cG9ydHMuV2ViU29ja2V0V2l0aFJlY29ubmVjdGlvbiAgPSBXZWJTb2NrZXRXaXRoUmVjb25uZWN0aW9uOyIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTMtMjAxNSBLdXJlbnRvIChodHRwOi8va3VyZW50by5vcmcvKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuXCJ1c2Ugc3RyaWN0XCI7XG5cbnZhciBCcm93c2VyV2ViU29ja2V0ID0gZ2xvYmFsLldlYlNvY2tldCB8fCBnbG9iYWwuTW96V2ViU29ja2V0O1xuXG52YXIgTG9nZ2VyID0gY29uc29sZTtcblxuLyoqXG4gKiBHZXQgZWl0aGVyIHRoZSBgV2ViU29ja2V0YCBvciBgTW96V2ViU29ja2V0YCBnbG9iYWxzXG4gKiBpbiB0aGUgYnJvd3NlciBvciB0cnkgdG8gcmVzb2x2ZSBXZWJTb2NrZXQtY29tcGF0aWJsZVxuICogaW50ZXJmYWNlIGV4cG9zZWQgYnkgYHdzYCBmb3IgTm9kZS1saWtlIGVudmlyb25tZW50LlxuICovXG5cbi8qdmFyIFdlYlNvY2tldCA9IEJyb3dzZXJXZWJTb2NrZXQ7XG5pZiAoIVdlYlNvY2tldCAmJiB0eXBlb2Ygd2luZG93ID09PSAndW5kZWZpbmVkJykge1xuICAgIHRyeSB7XG4gICAgICAgIFdlYlNvY2tldCA9IHJlcXVpcmUoJ3dzJyk7XG4gICAgfSBjYXRjaCAoZSkgeyB9XG59Ki9cblxuLy92YXIgU29ja0pTID0gcmVxdWlyZSgnc29ja2pzLWNsaWVudCcpO1xuXG52YXIgTUFYX1JFVFJJRVMgPSAyMDAwOyAvLyBGb3JldmVyLi4uXG52YXIgUkVUUllfVElNRV9NUyA9IDMwMDA7IC8vIEZJWE1FOiBJbXBsZW1lbnQgZXhwb25lbnRpYWwgd2FpdCB0aW1lcy4uLlxuXG52YXIgQ09OTkVDVElORyA9IDA7XG52YXIgT1BFTiA9IDE7XG52YXIgQ0xPU0lORyA9IDI7XG52YXIgQ0xPU0VEID0gMztcblxuLypcbmNvbmZpZyA9IHtcblx0XHR1cmkgOiB3c1VyaSxcblx0XHR1c2VTb2NrSlMgOiB0cnVlICh1c2UgU29ja0pTKSAvIGZhbHNlICh1c2UgV2ViU29ja2V0KSBieSBkZWZhdWx0LFxuXHRcdG9uY29ubmVjdGVkIDogY2FsbGJhY2sgbWV0aG9kIHRvIGludm9rZSB3aGVuIGNvbm5lY3Rpb24gaXMgc3VjY2Vzc2Z1bCxcblx0XHRvbmRpc2Nvbm5lY3QgOiBjYWxsYmFjayBtZXRob2QgdG8gaW52b2tlIHdoZW4gdGhlIGNvbm5lY3Rpb24gaXMgbG9zdCxcblx0XHRvbnJlY29ubmVjdGluZyA6IGNhbGxiYWNrIG1ldGhvZCB0byBpbnZva2Ugd2hlbiB0aGUgY2xpZW50IGlzIHJlY29ubmVjdGluZyxcblx0XHRvbnJlY29ubmVjdGVkIDogY2FsbGJhY2sgbWV0aG9kIHRvIGludm9rZSB3aGVuIHRoZSBjbGllbnQgc3VjY2Vzc2Z1bGx5IHJlY29ubmVjdHMsXG5cdH07XG4qL1xuZnVuY3Rpb24gV2ViU29ja2V0V2l0aFJlY29ubmVjdGlvbihjb25maWcpIHtcblxuICAgIHZhciBjbG9zaW5nID0gZmFsc2U7XG4gICAgdmFyIHJlZ2lzdGVyTWVzc2FnZUhhbmRsZXI7XG4gICAgdmFyIHdzVXJpID0gY29uZmlnLnVyaTtcbiAgICB2YXIgdXNlU29ja0pTID0gY29uZmlnLnVzZVNvY2tKUztcbiAgICB2YXIgcmVjb25uZWN0aW5nID0gZmFsc2U7XG5cbiAgICB2YXIgZm9yY2luZ0Rpc2Nvbm5lY3Rpb24gPSBmYWxzZTtcblxuICAgIHZhciB3cztcblxuICAgIGlmICh1c2VTb2NrSlMpIHtcbiAgICAgICAgd3MgPSBuZXcgU29ja0pTKHdzVXJpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICB3cyA9IG5ldyBXZWJTb2NrZXQod3NVcmkpO1xuICAgIH1cblxuICAgIHdzLm9ub3BlbiA9IGZ1bmN0aW9uKCkge1xuICAgICAgICBsb2dDb25uZWN0ZWQod3MsIHdzVXJpKTtcbiAgICAgICAgaWYgKGNvbmZpZy5vbmNvbm5lY3RlZCkge1xuICAgICAgICAgICAgY29uZmlnLm9uY29ubmVjdGVkKCk7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgd3Mub25lcnJvciA9IGZ1bmN0aW9uKGVycm9yKSB7XG4gICAgICAgIExvZ2dlci5lcnJvcihcIkNvdWxkIG5vdCBjb25uZWN0IHRvIFwiICsgd3NVcmkgKyBcIiAoaW52b2tpbmcgb25lcnJvciBpZiBkZWZpbmVkKVwiLCBlcnJvcik7XG4gICAgICAgIGlmIChjb25maWcub25lcnJvcikge1xuICAgICAgICAgICAgY29uZmlnLm9uZXJyb3IoZXJyb3IpO1xuICAgICAgICB9XG4gICAgfTtcblxuICAgIGZ1bmN0aW9uIGxvZ0Nvbm5lY3RlZCh3cywgd3NVcmkpIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIExvZ2dlci5kZWJ1ZyhcIldlYlNvY2tldCBjb25uZWN0ZWQgdG8gXCIgKyB3c1VyaSk7XG4gICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgIExvZ2dlci5lcnJvcihlKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHZhciByZWNvbm5lY3Rpb25PbkNsb3NlID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIGlmICh3cy5yZWFkeVN0YXRlID09PSBDTE9TRUQpIHtcbiAgICAgICAgICAgIGlmIChjbG9zaW5nKSB7XG4gICAgICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFwiQ29ubmVjdGlvbiBjbG9zZWQgYnkgdXNlclwiKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFwiQ29ubmVjdGlvbiBjbG9zZWQgdW5leHBlY3RlY2x5LiBSZWNvbm5lY3RpbmcuLi5cIik7XG4gICAgICAgICAgICAgICAgcmVjb25uZWN0VG9TYW1lVXJpKE1BWF9SRVRSSUVTLCAxKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIExvZ2dlci5kZWJ1ZyhcIkNsb3NlIGNhbGxiYWNrIGZyb20gcHJldmlvdXMgd2Vic29ja2V0LiBJZ25vcmluZyBpdFwiKTtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICB3cy5vbmNsb3NlID0gcmVjb25uZWN0aW9uT25DbG9zZTtcblxuICAgIGZ1bmN0aW9uIHJlY29ubmVjdFRvU2FtZVVyaShtYXhSZXRyaWVzLCBudW1SZXRyaWVzKSB7XG4gICAgICAgIExvZ2dlci5kZWJ1ZyhcInJlY29ubmVjdFRvU2FtZVVyaSAoYXR0ZW1wdCAjXCIgKyBudW1SZXRyaWVzICsgXCIsIG1heD1cIiArIG1heFJldHJpZXMgKyBcIilcIik7XG5cbiAgICAgICAgaWYgKG51bVJldHJpZXMgPT09IDEpIHtcbiAgICAgICAgICAgIGlmIChyZWNvbm5lY3RpbmcpIHtcbiAgICAgICAgICAgICAgICBMb2dnZXIud2FybihcIlRyeWluZyB0byByZWNvbm5lY3RUb05ld1VyaSB3aGVuIHJlY29ubmVjdGluZy4uLiBJZ25vcmluZyB0aGlzIHJlY29ubmVjdGlvbi5cIilcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJlY29ubmVjdGluZyA9IHRydWU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChjb25maWcub25yZWNvbm5lY3RpbmcpIHtcbiAgICAgICAgICAgICAgICBjb25maWcub25yZWNvbm5lY3RpbmcoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChmb3JjaW5nRGlzY29ubmVjdGlvbikge1xuICAgICAgICAgICAgcmVjb25uZWN0VG9OZXdVcmkobWF4UmV0cmllcywgbnVtUmV0cmllcywgd3NVcmkpO1xuXG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBpZiAoY29uZmlnLm5ld1dzVXJpT25SZWNvbm5lY3Rpb24pIHtcbiAgICAgICAgICAgICAgICBjb25maWcubmV3V3NVcmlPblJlY29ubmVjdGlvbihmdW5jdGlvbihlcnJvciwgbmV3V3NVcmkpIHtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIExvZ2dlci5kZWJ1ZyhlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlY29ubmVjdFRvU2FtZVVyaShtYXhSZXRyaWVzLCBudW1SZXRyaWVzICsgMSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9LCBSRVRSWV9USU1FX01TKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlY29ubmVjdFRvTmV3VXJpKG1heFJldHJpZXMsIG51bVJldHJpZXMsIG5ld1dzVXJpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJlY29ubmVjdFRvTmV3VXJpKG1heFJldHJpZXMsIG51bVJldHJpZXMsIHdzVXJpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIFRPRE8gVGVzdCByZXRyaWVzLiBIb3cgdG8gZm9yY2Ugbm90IGNvbm5lY3Rpb24/XG4gICAgZnVuY3Rpb24gcmVjb25uZWN0VG9OZXdVcmkobWF4UmV0cmllcywgbnVtUmV0cmllcywgcmVjb25uZWN0V3NVcmkpIHtcbiAgICAgICAgTG9nZ2VyLmRlYnVnKFwiUmVjb25uZWN0aW9uIGF0dGVtcHQgI1wiICsgbnVtUmV0cmllcyk7XG5cbiAgICAgICAgd3MuY2xvc2UoKTtcblxuICAgICAgICB3c1VyaSA9IHJlY29ubmVjdFdzVXJpIHx8IHdzVXJpO1xuXG4gICAgICAgIHZhciBuZXdXcztcbiAgICAgICAgaWYgKHVzZVNvY2tKUykge1xuICAgICAgICAgICAgbmV3V3MgPSBuZXcgU29ja0pTKHdzVXJpKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIG5ld1dzID0gbmV3IFdlYlNvY2tldCh3c1VyaSk7XG4gICAgICAgIH1cblxuICAgICAgICBuZXdXcy5vbm9wZW4gPSBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIExvZ2dlci5kZWJ1ZyhcIlJlY29ubmVjdGVkIGFmdGVyIFwiICsgbnVtUmV0cmllcyArIFwiIGF0dGVtcHRzLi4uXCIpO1xuICAgICAgICAgICAgbG9nQ29ubmVjdGVkKG5ld1dzLCB3c1VyaSk7XG4gICAgICAgICAgICByZWNvbm5lY3RpbmcgPSBmYWxzZTtcbiAgICAgICAgICAgIHJlZ2lzdGVyTWVzc2FnZUhhbmRsZXIoKTtcbiAgICAgICAgICAgIGlmIChjb25maWcub25yZWNvbm5lY3RlZCgpKSB7XG4gICAgICAgICAgICAgICAgY29uZmlnLm9ucmVjb25uZWN0ZWQoKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgbmV3V3Mub25jbG9zZSA9IHJlY29ubmVjdGlvbk9uQ2xvc2U7XG4gICAgICAgIH07XG5cbiAgICAgICAgdmFyIG9uRXJyb3JPckNsb3NlID0gZnVuY3Rpb24oZXJyb3IpIHtcbiAgICAgICAgICAgIExvZ2dlci53YXJuKFwiUmVjb25uZWN0aW9uIGVycm9yOiBcIiwgZXJyb3IpO1xuXG4gICAgICAgICAgICBpZiAobnVtUmV0cmllcyA9PT0gbWF4UmV0cmllcykge1xuICAgICAgICAgICAgICAgIGlmIChjb25maWcub25kaXNjb25uZWN0KSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbmZpZy5vbmRpc2Nvbm5lY3QoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlY29ubmVjdFRvU2FtZVVyaShtYXhSZXRyaWVzLCBudW1SZXRyaWVzICsgMSk7XG4gICAgICAgICAgICAgICAgfSwgUkVUUllfVElNRV9NUyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG5cbiAgICAgICAgbmV3V3Mub25lcnJvciA9IG9uRXJyb3JPckNsb3NlO1xuXG4gICAgICAgIHdzID0gbmV3V3M7XG4gICAgfVxuXG4gICAgdGhpcy5jbG9zZSA9IGZ1bmN0aW9uKCkge1xuICAgICAgICBjbG9zaW5nID0gdHJ1ZTtcbiAgICAgICAgd3MuY2xvc2UoKTtcbiAgICB9O1xuXG5cbiAgICAvLyBUaGlzIG1ldGhvZCBpcyBvbmx5IGZvciB0ZXN0aW5nXG4gICAgdGhpcy5mb3JjZUNsb3NlID0gZnVuY3Rpb24obWlsbGlzKSB7XG4gICAgICAgIExvZ2dlci5kZWJ1ZyhcIlRlc3Rpbmc6IEZvcmNlIFdlYlNvY2tldCBjbG9zZVwiKTtcblxuICAgICAgICBpZiAobWlsbGlzKSB7XG4gICAgICAgICAgICBMb2dnZXIuZGVidWcoXCJUZXN0aW5nOiBDaGFuZ2Ugd3NVcmkgZm9yIFwiICsgbWlsbGlzICsgXCIgbWlsbGlzIHRvIHNpbXVsYXRlIG5ldCBmYWlsdXJlXCIpO1xuICAgICAgICAgICAgdmFyIGdvb2RXc1VyaSA9IHdzVXJpO1xuICAgICAgICAgICAgd3NVcmkgPSBcIndzczovLzIxLjIzNC4xMi4zNC40OjQ0My9cIjtcblxuICAgICAgICAgICAgZm9yY2luZ0Rpc2Nvbm5lY3Rpb24gPSB0cnVlO1xuXG4gICAgICAgICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgIExvZ2dlci5kZWJ1ZyhcIlRlc3Rpbmc6IFJlY292ZXIgZ29vZCB3c1VyaSBcIiArIGdvb2RXc1VyaSk7XG4gICAgICAgICAgICAgICAgd3NVcmkgPSBnb29kV3NVcmk7XG5cbiAgICAgICAgICAgICAgICBmb3JjaW5nRGlzY29ubmVjdGlvbiA9IGZhbHNlO1xuXG4gICAgICAgICAgICB9LCBtaWxsaXMpO1xuICAgICAgICB9XG5cbiAgICAgICAgd3MuY2xvc2UoKTtcbiAgICB9O1xuXG4gICAgdGhpcy5yZWNvbm5lY3RXcyA9IGZ1bmN0aW9uKCkge1xuICAgICAgICBMb2dnZXIuZGVidWcoXCJyZWNvbm5lY3RXc1wiKTtcbiAgICAgICAgcmVjb25uZWN0VG9TYW1lVXJpKE1BWF9SRVRSSUVTLCAxKTtcbiAgICB9O1xuXG4gICAgdGhpcy5zZW5kID0gZnVuY3Rpb24obWVzc2FnZSkge1xuICAgICAgICB3cy5zZW5kKG1lc3NhZ2UpO1xuICAgIH07XG5cbiAgICB0aGlzLmFkZEV2ZW50TGlzdGVuZXIgPSBmdW5jdGlvbih0eXBlLCBjYWxsYmFjaykge1xuICAgICAgICByZWdpc3Rlck1lc3NhZ2VIYW5kbGVyID0gZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICB3cy5hZGRFdmVudExpc3RlbmVyKHR5cGUsIGNhbGxiYWNrKTtcbiAgICAgICAgfTtcblxuICAgICAgICByZWdpc3Rlck1lc3NhZ2VIYW5kbGVyKCk7XG4gICAgfTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBXZWJTb2NrZXRXaXRoUmVjb25uZWN0aW9uO1xuIiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNCBLdXJlbnRvIChodHRwOi8va3VyZW50by5vcmcvKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cblxudmFyIGRlZmluZVByb3BlcnR5X0lFOCA9IGZhbHNlXG5pZihPYmplY3QuZGVmaW5lUHJvcGVydHkpXG57XG4gIHRyeVxuICB7XG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHt9LCBcInhcIiwge30pO1xuICB9XG4gIGNhdGNoKGUpXG4gIHtcbiAgICBkZWZpbmVQcm9wZXJ0eV9JRTggPSB0cnVlXG4gIH1cbn1cblxuLy8gaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvSmF2YVNjcmlwdC9SZWZlcmVuY2UvR2xvYmFsX09iamVjdHMvRnVuY3Rpb24vYmluZFxuaWYgKCFGdW5jdGlvbi5wcm90b3R5cGUuYmluZCkge1xuICBGdW5jdGlvbi5wcm90b3R5cGUuYmluZCA9IGZ1bmN0aW9uKG9UaGlzKSB7XG4gICAgaWYgKHR5cGVvZiB0aGlzICE9PSAnZnVuY3Rpb24nKSB7XG4gICAgICAvLyBjbG9zZXN0IHRoaW5nIHBvc3NpYmxlIHRvIHRoZSBFQ01BU2NyaXB0IDVcbiAgICAgIC8vIGludGVybmFsIElzQ2FsbGFibGUgZnVuY3Rpb25cbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ0Z1bmN0aW9uLnByb3RvdHlwZS5iaW5kIC0gd2hhdCBpcyB0cnlpbmcgdG8gYmUgYm91bmQgaXMgbm90IGNhbGxhYmxlJyk7XG4gICAgfVxuXG4gICAgdmFyIGFBcmdzICAgPSBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMsIDEpLFxuICAgICAgICBmVG9CaW5kID0gdGhpcyxcbiAgICAgICAgZk5PUCAgICA9IGZ1bmN0aW9uKCkge30sXG4gICAgICAgIGZCb3VuZCAgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgICByZXR1cm4gZlRvQmluZC5hcHBseSh0aGlzIGluc3RhbmNlb2YgZk5PUCAmJiBvVGhpc1xuICAgICAgICAgICAgICAgICA/IHRoaXNcbiAgICAgICAgICAgICAgICAgOiBvVGhpcyxcbiAgICAgICAgICAgICAgICAgYUFyZ3MuY29uY2F0KEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3VtZW50cykpKTtcbiAgICAgICAgfTtcblxuICAgIGZOT1AucHJvdG90eXBlID0gdGhpcy5wcm90b3R5cGU7XG4gICAgZkJvdW5kLnByb3RvdHlwZSA9IG5ldyBmTk9QKCk7XG5cbiAgICByZXR1cm4gZkJvdW5kO1xuICB9O1xufVxuXG5cbnZhciBFdmVudEVtaXR0ZXIgPSByZXF1aXJlKCdldmVudHMnKS5FdmVudEVtaXR0ZXI7XG5cbnZhciBpbmhlcml0cyA9IHJlcXVpcmUoJ2luaGVyaXRzJyk7XG5cbnZhciBwYWNrZXJzID0gcmVxdWlyZSgnLi9wYWNrZXJzJyk7XG52YXIgTWFwcGVyID0gcmVxdWlyZSgnLi9NYXBwZXInKTtcblxuXG52YXIgQkFTRV9USU1FT1VUID0gNTAwMDtcblxuXG5mdW5jdGlvbiB1bmlmeVJlc3BvbnNlTWV0aG9kcyhyZXNwb25zZU1ldGhvZHMpXG57XG4gIGlmKCFyZXNwb25zZU1ldGhvZHMpIHJldHVybiB7fTtcblxuICBmb3IodmFyIGtleSBpbiByZXNwb25zZU1ldGhvZHMpXG4gIHtcbiAgICB2YXIgdmFsdWUgPSByZXNwb25zZU1ldGhvZHNba2V5XTtcblxuICAgIGlmKHR5cGVvZiB2YWx1ZSA9PSAnc3RyaW5nJylcbiAgICAgIHJlc3BvbnNlTWV0aG9kc1trZXldID1cbiAgICAgIHtcbiAgICAgICAgcmVzcG9uc2U6IHZhbHVlXG4gICAgICB9XG4gIH07XG5cbiAgcmV0dXJuIHJlc3BvbnNlTWV0aG9kcztcbn07XG5cbmZ1bmN0aW9uIHVuaWZ5VHJhbnNwb3J0KHRyYW5zcG9ydClcbntcbiAgaWYoIXRyYW5zcG9ydCkgcmV0dXJuO1xuXG4gIC8vIFRyYW5zcG9ydCBhcyBhIGZ1bmN0aW9uXG4gIGlmKHRyYW5zcG9ydCBpbnN0YW5jZW9mIEZ1bmN0aW9uKVxuICAgIHJldHVybiB7c2VuZDogdHJhbnNwb3J0fTtcblxuICAvLyBXZWJTb2NrZXQgJiBEYXRhQ2hhbm5lbFxuICBpZih0cmFuc3BvcnQuc2VuZCBpbnN0YW5jZW9mIEZ1bmN0aW9uKVxuICAgIHJldHVybiB0cmFuc3BvcnQ7XG5cbiAgLy8gTWVzc2FnZSBBUEkgKEludGVyLXdpbmRvdyAmIFdlYldvcmtlcilcbiAgaWYodHJhbnNwb3J0LnBvc3RNZXNzYWdlIGluc3RhbmNlb2YgRnVuY3Rpb24pXG4gIHtcbiAgICB0cmFuc3BvcnQuc2VuZCA9IHRyYW5zcG9ydC5wb3N0TWVzc2FnZTtcbiAgICByZXR1cm4gdHJhbnNwb3J0O1xuICB9XG5cbiAgLy8gU3RyZWFtIEFQSVxuICBpZih0cmFuc3BvcnQud3JpdGUgaW5zdGFuY2VvZiBGdW5jdGlvbilcbiAge1xuICAgIHRyYW5zcG9ydC5zZW5kID0gdHJhbnNwb3J0LndyaXRlO1xuICAgIHJldHVybiB0cmFuc3BvcnQ7XG4gIH1cblxuICAvLyBUcmFuc3BvcnRzIHRoYXQgb25seSBjYW4gcmVjZWl2ZSBtZXNzYWdlcywgYnV0IG5vdCBzZW5kXG4gIGlmKHRyYW5zcG9ydC5vbm1lc3NhZ2UgIT09IHVuZGVmaW5lZCkgcmV0dXJuO1xuICBpZih0cmFuc3BvcnQucGF1c2UgaW5zdGFuY2VvZiBGdW5jdGlvbikgcmV0dXJuO1xuXG4gIHRocm93IG5ldyBTeW50YXhFcnJvcihcIlRyYW5zcG9ydCBpcyBub3QgYSBmdW5jdGlvbiBub3IgYSB2YWxpZCBvYmplY3RcIik7XG59O1xuXG5cbi8qKlxuICogUmVwcmVzZW50YXRpb24gb2YgYSBSUEMgbm90aWZpY2F0aW9uXG4gKlxuICogQGNsYXNzXG4gKlxuICogQGNvbnN0cnVjdG9yXG4gKlxuICogQHBhcmFtIHtTdHJpbmd9IG1ldGhvZCAtbWV0aG9kIG9mIHRoZSBub3RpZmljYXRpb25cbiAqIEBwYXJhbSBwYXJhbXMgLSBwYXJhbWV0ZXJzIG9mIHRoZSBub3RpZmljYXRpb25cbiAqL1xuZnVuY3Rpb24gUnBjTm90aWZpY2F0aW9uKG1ldGhvZCwgcGFyYW1zKVxue1xuICBpZihkZWZpbmVQcm9wZXJ0eV9JRTgpXG4gIHtcbiAgICB0aGlzLm1ldGhvZCA9IG1ldGhvZFxuICAgIHRoaXMucGFyYW1zID0gcGFyYW1zXG4gIH1cbiAgZWxzZVxuICB7XG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRoaXMsICdtZXRob2QnLCB7dmFsdWU6IG1ldGhvZCwgZW51bWVyYWJsZTogdHJ1ZX0pO1xuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0aGlzLCAncGFyYW1zJywge3ZhbHVlOiBwYXJhbXMsIGVudW1lcmFibGU6IHRydWV9KTtcbiAgfVxufTtcblxuXG4vKipcbiAqIEBjbGFzc1xuICpcbiAqIEBjb25zdHJ1Y3RvclxuICpcbiAqIEBwYXJhbSB7b2JqZWN0fSBwYWNrZXJcbiAqXG4gKiBAcGFyYW0ge29iamVjdH0gW29wdGlvbnNdXG4gKlxuICogQHBhcmFtIHtvYmplY3R9IFt0cmFuc3BvcnRdXG4gKlxuICogQHBhcmFtIHtGdW5jdGlvbn0gW29uUmVxdWVzdF1cbiAqL1xuZnVuY3Rpb24gUnBjQnVpbGRlcihwYWNrZXIsIG9wdGlvbnMsIHRyYW5zcG9ydCwgb25SZXF1ZXN0KVxue1xuICB2YXIgc2VsZiA9IHRoaXM7XG5cbiAgaWYoIXBhY2tlcilcbiAgICB0aHJvdyBuZXcgU3ludGF4RXJyb3IoJ1BhY2tlciBpcyBub3QgZGVmaW5lZCcpO1xuXG4gIGlmKCFwYWNrZXIucGFjayB8fCAhcGFja2VyLnVucGFjaylcbiAgICB0aHJvdyBuZXcgU3ludGF4RXJyb3IoJ1BhY2tlciBpcyBpbnZhbGlkJyk7XG5cbiAgdmFyIHJlc3BvbnNlTWV0aG9kcyA9IHVuaWZ5UmVzcG9uc2VNZXRob2RzKHBhY2tlci5yZXNwb25zZU1ldGhvZHMpO1xuXG5cbiAgaWYob3B0aW9ucyBpbnN0YW5jZW9mIEZ1bmN0aW9uKVxuICB7XG4gICAgaWYodHJhbnNwb3J0ICE9IHVuZGVmaW5lZClcbiAgICAgIHRocm93IG5ldyBTeW50YXhFcnJvcihcIlRoZXJlIGNhbid0IGJlIHBhcmFtZXRlcnMgYWZ0ZXIgb25SZXF1ZXN0XCIpO1xuXG4gICAgb25SZXF1ZXN0ID0gb3B0aW9ucztcbiAgICB0cmFuc3BvcnQgPSB1bmRlZmluZWQ7XG4gICAgb3B0aW9ucyAgID0gdW5kZWZpbmVkO1xuICB9O1xuXG4gIGlmKG9wdGlvbnMgJiYgb3B0aW9ucy5zZW5kIGluc3RhbmNlb2YgRnVuY3Rpb24pXG4gIHtcbiAgICBpZih0cmFuc3BvcnQgJiYgISh0cmFuc3BvcnQgaW5zdGFuY2VvZiBGdW5jdGlvbikpXG4gICAgICB0aHJvdyBuZXcgU3ludGF4RXJyb3IoXCJPbmx5IGEgZnVuY3Rpb24gY2FuIGJlIGFmdGVyIHRyYW5zcG9ydFwiKTtcblxuICAgIG9uUmVxdWVzdCA9IHRyYW5zcG9ydDtcbiAgICB0cmFuc3BvcnQgPSBvcHRpb25zO1xuICAgIG9wdGlvbnMgICA9IHVuZGVmaW5lZDtcbiAgfTtcblxuICBpZih0cmFuc3BvcnQgaW5zdGFuY2VvZiBGdW5jdGlvbilcbiAge1xuICAgIGlmKG9uUmVxdWVzdCAhPSB1bmRlZmluZWQpXG4gICAgICB0aHJvdyBuZXcgU3ludGF4RXJyb3IoXCJUaGVyZSBjYW4ndCBiZSBwYXJhbWV0ZXJzIGFmdGVyIG9uUmVxdWVzdFwiKTtcblxuICAgIG9uUmVxdWVzdCA9IHRyYW5zcG9ydDtcbiAgICB0cmFuc3BvcnQgPSB1bmRlZmluZWQ7XG4gIH07XG5cbiAgaWYodHJhbnNwb3J0ICYmIHRyYW5zcG9ydC5zZW5kIGluc3RhbmNlb2YgRnVuY3Rpb24pXG4gICAgaWYob25SZXF1ZXN0ICYmICEob25SZXF1ZXN0IGluc3RhbmNlb2YgRnVuY3Rpb24pKVxuICAgICAgdGhyb3cgbmV3IFN5bnRheEVycm9yKFwiT25seSBhIGZ1bmN0aW9uIGNhbiBiZSBhZnRlciB0cmFuc3BvcnRcIik7XG5cbiAgb3B0aW9ucyA9IG9wdGlvbnMgfHwge307XG5cblxuICBFdmVudEVtaXR0ZXIuY2FsbCh0aGlzKTtcblxuICBpZihvblJlcXVlc3QpXG4gICAgdGhpcy5vbigncmVxdWVzdCcsIG9uUmVxdWVzdCk7XG5cblxuICBpZihkZWZpbmVQcm9wZXJ0eV9JRTgpXG4gICAgdGhpcy5wZWVySUQgPSBvcHRpb25zLnBlZXJJRFxuICBlbHNlXG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRoaXMsICdwZWVySUQnLCB7dmFsdWU6IG9wdGlvbnMucGVlcklEfSk7XG5cbiAgdmFyIG1heF9yZXRyaWVzID0gb3B0aW9ucy5tYXhfcmV0cmllcyB8fCAwO1xuXG5cbiAgZnVuY3Rpb24gdHJhbnNwb3J0TWVzc2FnZShldmVudClcbiAge1xuICAgIHNlbGYuZGVjb2RlKGV2ZW50LmRhdGEgfHwgZXZlbnQpO1xuICB9O1xuXG4gIHRoaXMuZ2V0VHJhbnNwb3J0ID0gZnVuY3Rpb24oKVxuICB7XG4gICAgcmV0dXJuIHRyYW5zcG9ydDtcbiAgfVxuICB0aGlzLnNldFRyYW5zcG9ydCA9IGZ1bmN0aW9uKHZhbHVlKVxuICB7XG4gICAgLy8gUmVtb3ZlIGxpc3RlbmVyIGZyb20gb2xkIHRyYW5zcG9ydFxuICAgIGlmKHRyYW5zcG9ydClcbiAgICB7XG4gICAgICAvLyBXM0MgdHJhbnNwb3J0c1xuICAgICAgaWYodHJhbnNwb3J0LnJlbW92ZUV2ZW50TGlzdGVuZXIpXG4gICAgICAgIHRyYW5zcG9ydC5yZW1vdmVFdmVudExpc3RlbmVyKCdtZXNzYWdlJywgdHJhbnNwb3J0TWVzc2FnZSk7XG5cbiAgICAgIC8vIE5vZGUuanMgU3RyZWFtcyBBUElcbiAgICAgIGVsc2UgaWYodHJhbnNwb3J0LnJlbW92ZUxpc3RlbmVyKVxuICAgICAgICB0cmFuc3BvcnQucmVtb3ZlTGlzdGVuZXIoJ2RhdGEnLCB0cmFuc3BvcnRNZXNzYWdlKTtcbiAgICB9O1xuXG4gICAgLy8gU2V0IGxpc3RlbmVyIG9uIG5ldyB0cmFuc3BvcnRcbiAgICBpZih2YWx1ZSlcbiAgICB7XG4gICAgICAvLyBXM0MgdHJhbnNwb3J0c1xuICAgICAgaWYodmFsdWUuYWRkRXZlbnRMaXN0ZW5lcilcbiAgICAgICAgdmFsdWUuYWRkRXZlbnRMaXN0ZW5lcignbWVzc2FnZScsIHRyYW5zcG9ydE1lc3NhZ2UpO1xuXG4gICAgICAvLyBOb2RlLmpzIFN0cmVhbXMgQVBJXG4gICAgICBlbHNlIGlmKHZhbHVlLmFkZExpc3RlbmVyKVxuICAgICAgICB2YWx1ZS5hZGRMaXN0ZW5lcignZGF0YScsIHRyYW5zcG9ydE1lc3NhZ2UpO1xuICAgIH07XG5cbiAgICB0cmFuc3BvcnQgPSB1bmlmeVRyYW5zcG9ydCh2YWx1ZSk7XG4gIH1cblxuICBpZighZGVmaW5lUHJvcGVydHlfSUU4KVxuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0aGlzLCAndHJhbnNwb3J0JyxcbiAgICB7XG4gICAgICBnZXQ6IHRoaXMuZ2V0VHJhbnNwb3J0LmJpbmQodGhpcyksXG4gICAgICBzZXQ6IHRoaXMuc2V0VHJhbnNwb3J0LmJpbmQodGhpcylcbiAgICB9KVxuXG4gIHRoaXMuc2V0VHJhbnNwb3J0KHRyYW5zcG9ydCk7XG5cblxuICB2YXIgcmVxdWVzdF90aW1lb3V0ICAgICAgPSBvcHRpb25zLnJlcXVlc3RfdGltZW91dCAgICAgIHx8IEJBU0VfVElNRU9VVDtcbiAgdmFyIHBpbmdfcmVxdWVzdF90aW1lb3V0ID0gb3B0aW9ucy5waW5nX3JlcXVlc3RfdGltZW91dCB8fCByZXF1ZXN0X3RpbWVvdXQ7XG4gIHZhciByZXNwb25zZV90aW1lb3V0ICAgICA9IG9wdGlvbnMucmVzcG9uc2VfdGltZW91dCAgICAgfHwgQkFTRV9USU1FT1VUO1xuICB2YXIgZHVwbGljYXRlc190aW1lb3V0ICAgPSBvcHRpb25zLmR1cGxpY2F0ZXNfdGltZW91dCAgIHx8IEJBU0VfVElNRU9VVDtcblxuXG4gIHZhciByZXF1ZXN0SUQgPSAwO1xuXG4gIHZhciByZXF1ZXN0cyAgPSBuZXcgTWFwcGVyKCk7XG4gIHZhciByZXNwb25zZXMgPSBuZXcgTWFwcGVyKCk7XG4gIHZhciBwcm9jZXNzZWRSZXNwb25zZXMgPSBuZXcgTWFwcGVyKCk7XG5cbiAgdmFyIG1lc3NhZ2UyS2V5ID0ge307XG5cblxuICAvKipcbiAgICogU3RvcmUgdGhlIHJlc3BvbnNlIHRvIHByZXZlbnQgdG8gcHJvY2VzcyBkdXBsaWNhdGUgcmVxdWVzdCBsYXRlclxuICAgKi9cbiAgZnVuY3Rpb24gc3RvcmVSZXNwb25zZShtZXNzYWdlLCBpZCwgZGVzdClcbiAge1xuICAgIHZhciByZXNwb25zZSA9XG4gICAge1xuICAgICAgbWVzc2FnZTogbWVzc2FnZSxcbiAgICAgIC8qKiBUaW1lb3V0IHRvIGF1dG8tY2xlYW4gb2xkIHJlc3BvbnNlcyAqL1xuICAgICAgdGltZW91dDogc2V0VGltZW91dChmdW5jdGlvbigpXG4gICAgICB7XG4gICAgICAgIHJlc3BvbnNlcy5yZW1vdmUoaWQsIGRlc3QpO1xuICAgICAgfSxcbiAgICAgIHJlc3BvbnNlX3RpbWVvdXQpXG4gICAgfTtcblxuICAgIHJlc3BvbnNlcy5zZXQocmVzcG9uc2UsIGlkLCBkZXN0KTtcbiAgfTtcblxuICAvKipcbiAgICogU3RvcmUgdGhlIHJlc3BvbnNlIHRvIGlnbm9yZSBkdXBsaWNhdGVkIG1lc3NhZ2VzIGxhdGVyXG4gICAqL1xuICBmdW5jdGlvbiBzdG9yZVByb2Nlc3NlZFJlc3BvbnNlKGFjaywgZnJvbSlcbiAge1xuICAgIHZhciB0aW1lb3V0ID0gc2V0VGltZW91dChmdW5jdGlvbigpXG4gICAge1xuICAgICAgcHJvY2Vzc2VkUmVzcG9uc2VzLnJlbW92ZShhY2ssIGZyb20pO1xuICAgIH0sXG4gICAgZHVwbGljYXRlc190aW1lb3V0KTtcblxuICAgIHByb2Nlc3NlZFJlc3BvbnNlcy5zZXQodGltZW91dCwgYWNrLCBmcm9tKTtcbiAgfTtcblxuXG4gIC8qKlxuICAgKiBSZXByZXNlbnRhdGlvbiBvZiBhIFJQQyByZXF1ZXN0XG4gICAqXG4gICAqIEBjbGFzc1xuICAgKiBAZXh0ZW5kcyBScGNOb3RpZmljYXRpb25cbiAgICpcbiAgICogQGNvbnN0cnVjdG9yXG4gICAqXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBtZXRob2QgLW1ldGhvZCBvZiB0aGUgbm90aWZpY2F0aW9uXG4gICAqIEBwYXJhbSBwYXJhbXMgLSBwYXJhbWV0ZXJzIG9mIHRoZSBub3RpZmljYXRpb25cbiAgICogQHBhcmFtIHtJbnRlZ2VyfSBpZCAtIGlkZW50aWZpZXIgb2YgdGhlIHJlcXVlc3RcbiAgICogQHBhcmFtIFtmcm9tXSAtIHNvdXJjZSBvZiB0aGUgbm90aWZpY2F0aW9uXG4gICAqL1xuICBmdW5jdGlvbiBScGNSZXF1ZXN0KG1ldGhvZCwgcGFyYW1zLCBpZCwgZnJvbSwgdHJhbnNwb3J0KVxuICB7XG4gICAgUnBjTm90aWZpY2F0aW9uLmNhbGwodGhpcywgbWV0aG9kLCBwYXJhbXMpO1xuXG4gICAgdGhpcy5nZXRUcmFuc3BvcnQgPSBmdW5jdGlvbigpXG4gICAge1xuICAgICAgcmV0dXJuIHRyYW5zcG9ydDtcbiAgICB9XG4gICAgdGhpcy5zZXRUcmFuc3BvcnQgPSBmdW5jdGlvbih2YWx1ZSlcbiAgICB7XG4gICAgICB0cmFuc3BvcnQgPSB1bmlmeVRyYW5zcG9ydCh2YWx1ZSk7XG4gICAgfVxuXG4gICAgaWYoIWRlZmluZVByb3BlcnR5X0lFOClcbiAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0aGlzLCAndHJhbnNwb3J0JyxcbiAgICAgIHtcbiAgICAgICAgZ2V0OiB0aGlzLmdldFRyYW5zcG9ydC5iaW5kKHRoaXMpLFxuICAgICAgICBzZXQ6IHRoaXMuc2V0VHJhbnNwb3J0LmJpbmQodGhpcylcbiAgICAgIH0pXG5cbiAgICB2YXIgcmVzcG9uc2UgPSByZXNwb25zZXMuZ2V0KGlkLCBmcm9tKTtcblxuICAgIC8qKlxuICAgICAqIEBjb25zdGFudCB7Qm9vbGVhbn0gZHVwbGljYXRlZFxuICAgICAqL1xuICAgIGlmKCEodHJhbnNwb3J0IHx8IHNlbGYuZ2V0VHJhbnNwb3J0KCkpKVxuICAgIHtcbiAgICAgIGlmKGRlZmluZVByb3BlcnR5X0lFOClcbiAgICAgICAgdGhpcy5kdXBsaWNhdGVkID0gQm9vbGVhbihyZXNwb25zZSlcbiAgICAgIGVsc2VcbiAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRoaXMsICdkdXBsaWNhdGVkJyxcbiAgICAgICAge1xuICAgICAgICAgIHZhbHVlOiBCb29sZWFuKHJlc3BvbnNlKVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICB2YXIgcmVzcG9uc2VNZXRob2QgPSByZXNwb25zZU1ldGhvZHNbbWV0aG9kXTtcblxuICAgIHRoaXMucGFjayA9IHBhY2tlci5wYWNrLmJpbmQocGFja2VyLCB0aGlzLCBpZClcblxuICAgIC8qKlxuICAgICAqIEdlbmVyYXRlIGEgcmVzcG9uc2UgdG8gdGhpcyByZXF1ZXN0XG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0Vycm9yfSBbZXJyb3JdXG4gICAgICogQHBhcmFtIHsqfSBbcmVzdWx0XVxuICAgICAqXG4gICAgICogQHJldHVybnMge3N0cmluZ31cbiAgICAgKi9cbiAgICB0aGlzLnJlcGx5ID0gZnVuY3Rpb24oZXJyb3IsIHJlc3VsdCwgdHJhbnNwb3J0KVxuICAgIHtcbiAgICAgIC8vIEZpeCBvcHRpb25hbCBwYXJhbWV0ZXJzXG4gICAgICBpZihlcnJvciBpbnN0YW5jZW9mIEZ1bmN0aW9uIHx8IGVycm9yICYmIGVycm9yLnNlbmQgaW5zdGFuY2VvZiBGdW5jdGlvbilcbiAgICAgIHtcbiAgICAgICAgaWYocmVzdWx0ICE9IHVuZGVmaW5lZClcbiAgICAgICAgICB0aHJvdyBuZXcgU3ludGF4RXJyb3IoXCJUaGVyZSBjYW4ndCBiZSBwYXJhbWV0ZXJzIGFmdGVyIGNhbGxiYWNrXCIpO1xuXG4gICAgICAgIHRyYW5zcG9ydCA9IGVycm9yO1xuICAgICAgICByZXN1bHQgPSBudWxsO1xuICAgICAgICBlcnJvciA9IHVuZGVmaW5lZDtcbiAgICAgIH1cblxuICAgICAgZWxzZSBpZihyZXN1bHQgaW5zdGFuY2VvZiBGdW5jdGlvblxuICAgICAgfHwgcmVzdWx0ICYmIHJlc3VsdC5zZW5kIGluc3RhbmNlb2YgRnVuY3Rpb24pXG4gICAgICB7XG4gICAgICAgIGlmKHRyYW5zcG9ydCAhPSB1bmRlZmluZWQpXG4gICAgICAgICAgdGhyb3cgbmV3IFN5bnRheEVycm9yKFwiVGhlcmUgY2FuJ3QgYmUgcGFyYW1ldGVycyBhZnRlciBjYWxsYmFja1wiKTtcblxuICAgICAgICB0cmFuc3BvcnQgPSByZXN1bHQ7XG4gICAgICAgIHJlc3VsdCA9IG51bGw7XG4gICAgICB9O1xuXG4gICAgICB0cmFuc3BvcnQgPSB1bmlmeVRyYW5zcG9ydCh0cmFuc3BvcnQpO1xuXG4gICAgICAvLyBEdXBsaWNhdGVkIHJlcXVlc3QsIHJlbW92ZSBvbGQgcmVzcG9uc2UgdGltZW91dFxuICAgICAgaWYocmVzcG9uc2UpXG4gICAgICAgIGNsZWFyVGltZW91dChyZXNwb25zZS50aW1lb3V0KTtcblxuICAgICAgaWYoZnJvbSAhPSB1bmRlZmluZWQpXG4gICAgICB7XG4gICAgICAgIGlmKGVycm9yKVxuICAgICAgICAgIGVycm9yLmRlc3QgPSBmcm9tO1xuXG4gICAgICAgIGlmKHJlc3VsdClcbiAgICAgICAgICByZXN1bHQuZGVzdCA9IGZyb207XG4gICAgICB9O1xuXG4gICAgICB2YXIgbWVzc2FnZTtcblxuICAgICAgLy8gTmV3IHJlcXVlc3Qgb3Igb3ZlcnJpZGVuIG9uZSwgY3JlYXRlIG5ldyByZXNwb25zZSB3aXRoIHByb3ZpZGVkIGRhdGFcbiAgICAgIGlmKGVycm9yIHx8IHJlc3VsdCAhPSB1bmRlZmluZWQpXG4gICAgICB7XG4gICAgICAgIGlmKHNlbGYucGVlcklEICE9IHVuZGVmaW5lZClcbiAgICAgICAge1xuICAgICAgICAgIGlmKGVycm9yKVxuICAgICAgICAgICAgZXJyb3IuZnJvbSA9IHNlbGYucGVlcklEO1xuICAgICAgICAgIGVsc2VcbiAgICAgICAgICAgIHJlc3VsdC5mcm9tID0gc2VsZi5wZWVySUQ7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBQcm90b2NvbCBpbmRpY2F0ZXMgdGhhdCByZXNwb25zZXMgaGFzIG93biByZXF1ZXN0IG1ldGhvZHNcbiAgICAgICAgaWYocmVzcG9uc2VNZXRob2QpXG4gICAgICAgIHtcbiAgICAgICAgICBpZihyZXNwb25zZU1ldGhvZC5lcnJvciA9PSB1bmRlZmluZWQgJiYgZXJyb3IpXG4gICAgICAgICAgICBtZXNzYWdlID1cbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgZXJyb3I6IGVycm9yXG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgZWxzZVxuICAgICAgICAgIHtcbiAgICAgICAgICAgIHZhciBtZXRob2QgPSBlcnJvclxuICAgICAgICAgICAgICAgICAgICAgICA/IHJlc3BvbnNlTWV0aG9kLmVycm9yXG4gICAgICAgICAgICAgICAgICAgICAgIDogcmVzcG9uc2VNZXRob2QucmVzcG9uc2U7XG5cbiAgICAgICAgICAgIG1lc3NhZ2UgPVxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICBtZXRob2Q6IG1ldGhvZCxcbiAgICAgICAgICAgICAgcGFyYW1zOiBlcnJvciB8fCByZXN1bHRcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGVsc2VcbiAgICAgICAgICBtZXNzYWdlID1cbiAgICAgICAgICB7XG4gICAgICAgICAgICBlcnJvcjogIGVycm9yLFxuICAgICAgICAgICAgcmVzdWx0OiByZXN1bHRcbiAgICAgICAgICB9O1xuXG4gICAgICAgIG1lc3NhZ2UgPSBwYWNrZXIucGFjayhtZXNzYWdlLCBpZCk7XG4gICAgICB9XG5cbiAgICAgIC8vIER1cGxpY2F0ZSAmIG5vdC1vdmVycmlkZW4gcmVxdWVzdCwgcmUtc2VuZCBvbGQgcmVzcG9uc2VcbiAgICAgIGVsc2UgaWYocmVzcG9uc2UpXG4gICAgICAgIG1lc3NhZ2UgPSByZXNwb25zZS5tZXNzYWdlO1xuXG4gICAgICAvLyBOZXcgZW1wdHkgcmVwbHksIHJlc3BvbnNlIG51bGwgdmFsdWVcbiAgICAgIGVsc2VcbiAgICAgICAgbWVzc2FnZSA9IHBhY2tlci5wYWNrKHtyZXN1bHQ6IG51bGx9LCBpZCk7XG5cbiAgICAgIC8vIFN0b3JlIHRoZSByZXNwb25zZSB0byBwcmV2ZW50IHRvIHByb2Nlc3MgYSBkdXBsaWNhdGVkIHJlcXVlc3QgbGF0ZXJcbiAgICAgIHN0b3JlUmVzcG9uc2UobWVzc2FnZSwgaWQsIGZyb20pO1xuXG4gICAgICAvLyBSZXR1cm4gdGhlIHN0b3JlZCByZXNwb25zZSBzbyBpdCBjYW4gYmUgZGlyZWN0bHkgc2VuZCBiYWNrXG4gICAgICB0cmFuc3BvcnQgPSB0cmFuc3BvcnQgfHwgdGhpcy5nZXRUcmFuc3BvcnQoKSB8fCBzZWxmLmdldFRyYW5zcG9ydCgpO1xuXG4gICAgICBpZih0cmFuc3BvcnQpXG4gICAgICAgIHJldHVybiB0cmFuc3BvcnQuc2VuZChtZXNzYWdlKTtcblxuICAgICAgcmV0dXJuIG1lc3NhZ2U7XG4gICAgfVxuICB9O1xuICBpbmhlcml0cyhScGNSZXF1ZXN0LCBScGNOb3RpZmljYXRpb24pO1xuXG5cbiAgZnVuY3Rpb24gY2FuY2VsKG1lc3NhZ2UpXG4gIHtcbiAgICB2YXIga2V5ID0gbWVzc2FnZTJLZXlbbWVzc2FnZV07XG4gICAgaWYoIWtleSkgcmV0dXJuO1xuXG4gICAgZGVsZXRlIG1lc3NhZ2UyS2V5W21lc3NhZ2VdO1xuXG4gICAgdmFyIHJlcXVlc3QgPSByZXF1ZXN0cy5wb3Aoa2V5LmlkLCBrZXkuZGVzdCk7XG4gICAgaWYoIXJlcXVlc3QpIHJldHVybjtcblxuICAgIGNsZWFyVGltZW91dChyZXF1ZXN0LnRpbWVvdXQpO1xuXG4gICAgLy8gU3RhcnQgZHVwbGljYXRlZCByZXNwb25zZXMgdGltZW91dFxuICAgIHN0b3JlUHJvY2Vzc2VkUmVzcG9uc2Uoa2V5LmlkLCBrZXkuZGVzdCk7XG4gIH07XG5cbiAgLyoqXG4gICAqIEFsbG93IHRvIGNhbmNlbCBhIHJlcXVlc3QgYW5kIGRvbid0IHdhaXQgZm9yIGEgcmVzcG9uc2VcbiAgICpcbiAgICogSWYgYG1lc3NhZ2VgIGlzIG5vdCBnaXZlbiwgY2FuY2VsIGFsbCB0aGUgcmVxdWVzdFxuICAgKi9cbiAgdGhpcy5jYW5jZWwgPSBmdW5jdGlvbihtZXNzYWdlKVxuICB7XG4gICAgaWYobWVzc2FnZSkgcmV0dXJuIGNhbmNlbChtZXNzYWdlKTtcblxuICAgIGZvcih2YXIgbWVzc2FnZSBpbiBtZXNzYWdlMktleSlcbiAgICAgIGNhbmNlbChtZXNzYWdlKTtcbiAgfTtcblxuXG4gIHRoaXMuY2xvc2UgPSBmdW5jdGlvbigpXG4gIHtcbiAgICAvLyBQcmV2ZW50IHRvIHJlY2VpdmUgbmV3IG1lc3NhZ2VzXG4gICAgdmFyIHRyYW5zcG9ydCA9IHRoaXMuZ2V0VHJhbnNwb3J0KCk7XG4gICAgaWYodHJhbnNwb3J0ICYmIHRyYW5zcG9ydC5jbG9zZSlcbiAgICAgICB0cmFuc3BvcnQuY2xvc2UoKTtcblxuICAgIC8vIFJlcXVlc3QgJiBwcm9jZXNzZWQgcmVzcG9uc2VzXG4gICAgdGhpcy5jYW5jZWwoKTtcblxuICAgIHByb2Nlc3NlZFJlc3BvbnNlcy5mb3JFYWNoKGNsZWFyVGltZW91dCk7XG5cbiAgICAvLyBSZXNwb25zZXNcbiAgICByZXNwb25zZXMuZm9yRWFjaChmdW5jdGlvbihyZXNwb25zZSlcbiAgICB7XG4gICAgICBjbGVhclRpbWVvdXQocmVzcG9uc2UudGltZW91dCk7XG4gICAgfSk7XG4gIH07XG5cblxuICAvKipcbiAgICogR2VuZXJhdGVzIGFuZCBlbmNvZGUgYSBKc29uUlBDIDIuMCBtZXNzYWdlXG4gICAqXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBtZXRob2QgLW1ldGhvZCBvZiB0aGUgbm90aWZpY2F0aW9uXG4gICAqIEBwYXJhbSBwYXJhbXMgLSBwYXJhbWV0ZXJzIG9mIHRoZSBub3RpZmljYXRpb25cbiAgICogQHBhcmFtIFtkZXN0XSAtIGRlc3RpbmF0aW9uIG9mIHRoZSBub3RpZmljYXRpb25cbiAgICogQHBhcmFtIHtvYmplY3R9IFt0cmFuc3BvcnRdIC0gdHJhbnNwb3J0IHdoZXJlIHRvIHNlbmQgdGhlIG1lc3NhZ2VcbiAgICogQHBhcmFtIFtjYWxsYmFja10gLSBmdW5jdGlvbiBjYWxsZWQgd2hlbiBhIHJlc3BvbnNlIHRvIHRoaXMgcmVxdWVzdCBpc1xuICAgKiAgIHJlY2VpdmVkLiBJZiBub3QgZGVmaW5lZCwgYSBub3RpZmljYXRpb24gd2lsbCBiZSBzZW5kIGluc3RlYWRcbiAgICpcbiAgICogQHJldHVybnMge3N0cmluZ30gQSByYXcgSnNvblJQQyAyLjAgcmVxdWVzdCBvciBub3RpZmljYXRpb24gc3RyaW5nXG4gICAqL1xuICB0aGlzLmVuY29kZSA9IGZ1bmN0aW9uKG1ldGhvZCwgcGFyYW1zLCBkZXN0LCB0cmFuc3BvcnQsIGNhbGxiYWNrKVxuICB7XG4gICAgLy8gRml4IG9wdGlvbmFsIHBhcmFtZXRlcnNcbiAgICBpZihwYXJhbXMgaW5zdGFuY2VvZiBGdW5jdGlvbilcbiAgICB7XG4gICAgICBpZihkZXN0ICE9IHVuZGVmaW5lZClcbiAgICAgICAgdGhyb3cgbmV3IFN5bnRheEVycm9yKFwiVGhlcmUgY2FuJ3QgYmUgcGFyYW1ldGVycyBhZnRlciBjYWxsYmFja1wiKTtcblxuICAgICAgY2FsbGJhY2sgID0gcGFyYW1zO1xuICAgICAgdHJhbnNwb3J0ID0gdW5kZWZpbmVkO1xuICAgICAgZGVzdCAgICAgID0gdW5kZWZpbmVkO1xuICAgICAgcGFyYW1zICAgID0gdW5kZWZpbmVkO1xuICAgIH1cblxuICAgIGVsc2UgaWYoZGVzdCBpbnN0YW5jZW9mIEZ1bmN0aW9uKVxuICAgIHtcbiAgICAgIGlmKHRyYW5zcG9ydCAhPSB1bmRlZmluZWQpXG4gICAgICAgIHRocm93IG5ldyBTeW50YXhFcnJvcihcIlRoZXJlIGNhbid0IGJlIHBhcmFtZXRlcnMgYWZ0ZXIgY2FsbGJhY2tcIik7XG5cbiAgICAgIGNhbGxiYWNrICA9IGRlc3Q7XG4gICAgICB0cmFuc3BvcnQgPSB1bmRlZmluZWQ7XG4gICAgICBkZXN0ICAgICAgPSB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgZWxzZSBpZih0cmFuc3BvcnQgaW5zdGFuY2VvZiBGdW5jdGlvbilcbiAgICB7XG4gICAgICBpZihjYWxsYmFjayAhPSB1bmRlZmluZWQpXG4gICAgICAgIHRocm93IG5ldyBTeW50YXhFcnJvcihcIlRoZXJlIGNhbid0IGJlIHBhcmFtZXRlcnMgYWZ0ZXIgY2FsbGJhY2tcIik7XG5cbiAgICAgIGNhbGxiYWNrICA9IHRyYW5zcG9ydDtcbiAgICAgIHRyYW5zcG9ydCA9IHVuZGVmaW5lZDtcbiAgICB9O1xuXG4gICAgaWYoc2VsZi5wZWVySUQgIT0gdW5kZWZpbmVkKVxuICAgIHtcbiAgICAgIHBhcmFtcyA9IHBhcmFtcyB8fCB7fTtcblxuICAgICAgcGFyYW1zLmZyb20gPSBzZWxmLnBlZXJJRDtcbiAgICB9O1xuXG4gICAgaWYoZGVzdCAhPSB1bmRlZmluZWQpXG4gICAge1xuICAgICAgcGFyYW1zID0gcGFyYW1zIHx8IHt9O1xuXG4gICAgICBwYXJhbXMuZGVzdCA9IGRlc3Q7XG4gICAgfTtcblxuICAgIC8vIEVuY29kZSBtZXNzYWdlXG4gICAgdmFyIG1lc3NhZ2UgPVxuICAgIHtcbiAgICAgIG1ldGhvZDogbWV0aG9kLFxuICAgICAgcGFyYW1zOiBwYXJhbXNcbiAgICB9O1xuXG4gICAgaWYoY2FsbGJhY2spXG4gICAge1xuICAgICAgdmFyIGlkID0gcmVxdWVzdElEKys7XG4gICAgICB2YXIgcmV0cmllZCA9IDA7XG5cbiAgICAgIG1lc3NhZ2UgPSBwYWNrZXIucGFjayhtZXNzYWdlLCBpZCk7XG5cbiAgICAgIGZ1bmN0aW9uIGRpc3BhdGNoQ2FsbGJhY2soZXJyb3IsIHJlc3VsdClcbiAgICAgIHtcbiAgICAgICAgc2VsZi5jYW5jZWwobWVzc2FnZSk7XG5cbiAgICAgICAgY2FsbGJhY2soZXJyb3IsIHJlc3VsdCk7XG4gICAgICB9O1xuXG4gICAgICB2YXIgcmVxdWVzdCA9XG4gICAgICB7XG4gICAgICAgIG1lc3NhZ2U6ICAgICAgICAgbWVzc2FnZSxcbiAgICAgICAgY2FsbGJhY2s6ICAgICAgICBkaXNwYXRjaENhbGxiYWNrLFxuICAgICAgICByZXNwb25zZU1ldGhvZHM6IHJlc3BvbnNlTWV0aG9kc1ttZXRob2RdIHx8IHt9XG4gICAgICB9O1xuXG4gICAgICB2YXIgZW5jb2RlX3RyYW5zcG9ydCA9IHVuaWZ5VHJhbnNwb3J0KHRyYW5zcG9ydCk7XG5cbiAgICAgIGZ1bmN0aW9uIHNlbmRSZXF1ZXN0KHRyYW5zcG9ydClcbiAgICAgIHtcbiAgICAgICAgdmFyIHJ0ID0gKG1ldGhvZCA9PT0gJ3BpbmcnID8gcGluZ19yZXF1ZXN0X3RpbWVvdXQgOiByZXF1ZXN0X3RpbWVvdXQpO1xuICAgICAgICByZXF1ZXN0LnRpbWVvdXQgPSBzZXRUaW1lb3V0KHRpbWVvdXQsIHJ0Kk1hdGgucG93KDIsIHJldHJpZWQrKykpO1xuICAgICAgICBtZXNzYWdlMktleVttZXNzYWdlXSA9IHtpZDogaWQsIGRlc3Q6IGRlc3R9O1xuICAgICAgICByZXF1ZXN0cy5zZXQocmVxdWVzdCwgaWQsIGRlc3QpO1xuXG4gICAgICAgIHRyYW5zcG9ydCA9IHRyYW5zcG9ydCB8fCBlbmNvZGVfdHJhbnNwb3J0IHx8IHNlbGYuZ2V0VHJhbnNwb3J0KCk7XG4gICAgICAgIGlmKHRyYW5zcG9ydClcbiAgICAgICAgICByZXR1cm4gdHJhbnNwb3J0LnNlbmQobWVzc2FnZSk7XG5cbiAgICAgICAgcmV0dXJuIG1lc3NhZ2U7XG4gICAgICB9O1xuXG4gICAgICBmdW5jdGlvbiByZXRyeSh0cmFuc3BvcnQpXG4gICAgICB7XG4gICAgICAgIHRyYW5zcG9ydCA9IHVuaWZ5VHJhbnNwb3J0KHRyYW5zcG9ydCk7XG5cbiAgICAgICAgY29uc29sZS53YXJuKHJldHJpZWQrJyByZXRyeSBmb3IgcmVxdWVzdCBtZXNzYWdlOicsbWVzc2FnZSk7XG5cbiAgICAgICAgdmFyIHRpbWVvdXQgPSBwcm9jZXNzZWRSZXNwb25zZXMucG9wKGlkLCBkZXN0KTtcbiAgICAgICAgY2xlYXJUaW1lb3V0KHRpbWVvdXQpO1xuXG4gICAgICAgIHJldHVybiBzZW5kUmVxdWVzdCh0cmFuc3BvcnQpO1xuICAgICAgfTtcblxuICAgICAgZnVuY3Rpb24gdGltZW91dCgpXG4gICAgICB7XG4gICAgICAgIGlmKHJldHJpZWQgPCBtYXhfcmV0cmllcylcbiAgICAgICAgICByZXR1cm4gcmV0cnkodHJhbnNwb3J0KTtcblxuICAgICAgICB2YXIgZXJyb3IgPSBuZXcgRXJyb3IoJ1JlcXVlc3QgaGFzIHRpbWVkIG91dCcpO1xuICAgICAgICAgICAgZXJyb3IucmVxdWVzdCA9IG1lc3NhZ2U7XG5cbiAgICAgICAgZXJyb3IucmV0cnkgPSByZXRyeTtcblxuICAgICAgICBkaXNwYXRjaENhbGxiYWNrKGVycm9yKVxuICAgICAgfTtcblxuICAgICAgcmV0dXJuIHNlbmRSZXF1ZXN0KHRyYW5zcG9ydCk7XG4gICAgfTtcblxuICAgIC8vIFJldHVybiB0aGUgcGFja2VkIG1lc3NhZ2VcbiAgICBtZXNzYWdlID0gcGFja2VyLnBhY2sobWVzc2FnZSk7XG5cbiAgICB0cmFuc3BvcnQgPSB0cmFuc3BvcnQgfHwgdGhpcy5nZXRUcmFuc3BvcnQoKTtcbiAgICBpZih0cmFuc3BvcnQpXG4gICAgICByZXR1cm4gdHJhbnNwb3J0LnNlbmQobWVzc2FnZSk7XG5cbiAgICByZXR1cm4gbWVzc2FnZTtcbiAgfTtcblxuICAvKipcbiAgICogRGVjb2RlIGFuZCBwcm9jZXNzIGEgSnNvblJQQyAyLjAgbWVzc2FnZVxuICAgKlxuICAgKiBAcGFyYW0ge3N0cmluZ30gbWVzc2FnZSAtIHN0cmluZyB3aXRoIHRoZSBjb250ZW50IG9mIHRoZSBtZXNzYWdlXG4gICAqXG4gICAqIEByZXR1cm5zIHtScGNOb3RpZmljYXRpb258UnBjUmVxdWVzdHx1bmRlZmluZWR9IC0gdGhlIHJlcHJlc2VudGF0aW9uIG9mIHRoZVxuICAgKiAgIG5vdGlmaWNhdGlvbiBvciB0aGUgcmVxdWVzdC4gSWYgYSByZXNwb25zZSB3YXMgcHJvY2Vzc2VkLCBpdCB3aWxsIHJldHVyblxuICAgKiAgIGB1bmRlZmluZWRgIHRvIG5vdGlmeSB0aGF0IGl0IHdhcyBwcm9jZXNzZWRcbiAgICpcbiAgICogQHRocm93cyB7VHlwZUVycm9yfSAtIE1lc3NhZ2UgaXMgbm90IGRlZmluZWRcbiAgICovXG4gIHRoaXMuZGVjb2RlID0gZnVuY3Rpb24obWVzc2FnZSwgdHJhbnNwb3J0KVxuICB7XG4gICAgaWYoIW1lc3NhZ2UpXG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiTWVzc2FnZSBpcyBub3QgZGVmaW5lZFwiKTtcblxuICAgIHRyeVxuICAgIHtcbiAgICAgIG1lc3NhZ2UgPSBwYWNrZXIudW5wYWNrKG1lc3NhZ2UpO1xuICAgIH1cbiAgICBjYXRjaChlKVxuICAgIHtcbiAgICAgIC8vIElnbm9yZSBpbnZhbGlkIG1lc3NhZ2VzXG4gICAgICByZXR1cm4gY29uc29sZS5kZWJ1ZyhlLCBtZXNzYWdlKTtcbiAgICB9O1xuXG4gICAgdmFyIGlkICAgICA9IG1lc3NhZ2UuaWQ7XG4gICAgdmFyIGFjayAgICA9IG1lc3NhZ2UuYWNrO1xuICAgIHZhciBtZXRob2QgPSBtZXNzYWdlLm1ldGhvZDtcbiAgICB2YXIgcGFyYW1zID0gbWVzc2FnZS5wYXJhbXMgfHwge307XG5cbiAgICB2YXIgZnJvbSA9IHBhcmFtcy5mcm9tO1xuICAgIHZhciBkZXN0ID0gcGFyYW1zLmRlc3Q7XG5cbiAgICAvLyBJZ25vcmUgbWVzc2FnZXMgc2VuZCBieSB1c1xuICAgIGlmKHNlbGYucGVlcklEICE9IHVuZGVmaW5lZCAmJiBmcm9tID09IHNlbGYucGVlcklEKSByZXR1cm47XG5cbiAgICAvLyBOb3RpZmljYXRpb25cbiAgICBpZihpZCA9PSB1bmRlZmluZWQgJiYgYWNrID09IHVuZGVmaW5lZClcbiAgICB7XG4gICAgICB2YXIgbm90aWZpY2F0aW9uID0gbmV3IFJwY05vdGlmaWNhdGlvbihtZXRob2QsIHBhcmFtcyk7XG5cbiAgICAgIGlmKHNlbGYuZW1pdCgncmVxdWVzdCcsIG5vdGlmaWNhdGlvbikpIHJldHVybjtcbiAgICAgIHJldHVybiBub3RpZmljYXRpb247XG4gICAgfTtcblxuXG4gICAgZnVuY3Rpb24gcHJvY2Vzc1JlcXVlc3QoKVxuICAgIHtcbiAgICAgIC8vIElmIHdlIGhhdmUgYSB0cmFuc3BvcnQgYW5kIGl0J3MgYSBkdXBsaWNhdGVkIHJlcXVlc3QsIHJlcGx5IGlubWVkaWF0bHlcbiAgICAgIHRyYW5zcG9ydCA9IHVuaWZ5VHJhbnNwb3J0KHRyYW5zcG9ydCkgfHwgc2VsZi5nZXRUcmFuc3BvcnQoKTtcbiAgICAgIGlmKHRyYW5zcG9ydClcbiAgICAgIHtcbiAgICAgICAgdmFyIHJlc3BvbnNlID0gcmVzcG9uc2VzLmdldChpZCwgZnJvbSk7XG4gICAgICAgIGlmKHJlc3BvbnNlKVxuICAgICAgICAgIHJldHVybiB0cmFuc3BvcnQuc2VuZChyZXNwb25zZS5tZXNzYWdlKTtcbiAgICAgIH07XG5cbiAgICAgIHZhciBpZEFjayA9IChpZCAhPSB1bmRlZmluZWQpID8gaWQgOiBhY2s7XG4gICAgICB2YXIgcmVxdWVzdCA9IG5ldyBScGNSZXF1ZXN0KG1ldGhvZCwgcGFyYW1zLCBpZEFjaywgZnJvbSwgdHJhbnNwb3J0KTtcblxuICAgICAgaWYoc2VsZi5lbWl0KCdyZXF1ZXN0JywgcmVxdWVzdCkpIHJldHVybjtcbiAgICAgIHJldHVybiByZXF1ZXN0O1xuICAgIH07XG5cbiAgICBmdW5jdGlvbiBwcm9jZXNzUmVzcG9uc2UocmVxdWVzdCwgZXJyb3IsIHJlc3VsdClcbiAgICB7XG4gICAgICByZXF1ZXN0LmNhbGxiYWNrKGVycm9yLCByZXN1bHQpO1xuICAgIH07XG5cbiAgICBmdW5jdGlvbiBkdXBsaWNhdGVkUmVzcG9uc2UodGltZW91dClcbiAgICB7XG4gICAgICBjb25zb2xlLndhcm4oXCJSZXNwb25zZSBhbHJlYWR5IHByb2Nlc3NlZFwiLCBtZXNzYWdlKTtcblxuICAgICAgLy8gVXBkYXRlIGR1cGxpY2F0ZWQgcmVzcG9uc2VzIHRpbWVvdXRcbiAgICAgIGNsZWFyVGltZW91dCh0aW1lb3V0KTtcbiAgICAgIHN0b3JlUHJvY2Vzc2VkUmVzcG9uc2UoYWNrLCBmcm9tKTtcbiAgICB9O1xuXG5cbiAgICAvLyBSZXF1ZXN0LCBvciByZXNwb25zZSB3aXRoIG93biBtZXRob2RcbiAgICBpZihtZXRob2QpXG4gICAge1xuICAgICAgLy8gQ2hlY2sgaWYgaXQncyBhIHJlc3BvbnNlIHdpdGggb3duIG1ldGhvZFxuICAgICAgaWYoZGVzdCA9PSB1bmRlZmluZWQgfHwgZGVzdCA9PSBzZWxmLnBlZXJJRClcbiAgICAgIHtcbiAgICAgICAgdmFyIHJlcXVlc3QgPSByZXF1ZXN0cy5nZXQoYWNrLCBmcm9tKTtcbiAgICAgICAgaWYocmVxdWVzdClcbiAgICAgICAge1xuICAgICAgICAgIHZhciByZXNwb25zZU1ldGhvZHMgPSByZXF1ZXN0LnJlc3BvbnNlTWV0aG9kcztcblxuICAgICAgICAgIGlmKG1ldGhvZCA9PSByZXNwb25zZU1ldGhvZHMuZXJyb3IpXG4gICAgICAgICAgICByZXR1cm4gcHJvY2Vzc1Jlc3BvbnNlKHJlcXVlc3QsIHBhcmFtcyk7XG5cbiAgICAgICAgICBpZihtZXRob2QgPT0gcmVzcG9uc2VNZXRob2RzLnJlc3BvbnNlKVxuICAgICAgICAgICAgcmV0dXJuIHByb2Nlc3NSZXNwb25zZShyZXF1ZXN0LCBudWxsLCBwYXJhbXMpO1xuXG4gICAgICAgICAgcmV0dXJuIHByb2Nlc3NSZXF1ZXN0KCk7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgcHJvY2Vzc2VkID0gcHJvY2Vzc2VkUmVzcG9uc2VzLmdldChhY2ssIGZyb20pO1xuICAgICAgICBpZihwcm9jZXNzZWQpXG4gICAgICAgICAgcmV0dXJuIGR1cGxpY2F0ZWRSZXNwb25zZShwcm9jZXNzZWQpO1xuICAgICAgfVxuXG4gICAgICAvLyBSZXF1ZXN0XG4gICAgICByZXR1cm4gcHJvY2Vzc1JlcXVlc3QoKTtcbiAgICB9O1xuXG4gICAgdmFyIGVycm9yICA9IG1lc3NhZ2UuZXJyb3I7XG4gICAgdmFyIHJlc3VsdCA9IG1lc3NhZ2UucmVzdWx0O1xuXG4gICAgLy8gSWdub3JlIHJlc3BvbnNlcyBub3Qgc2VuZCB0byB1c1xuICAgIGlmKGVycm9yICAmJiBlcnJvci5kZXN0ICAmJiBlcnJvci5kZXN0ICAhPSBzZWxmLnBlZXJJRCkgcmV0dXJuO1xuICAgIGlmKHJlc3VsdCAmJiByZXN1bHQuZGVzdCAmJiByZXN1bHQuZGVzdCAhPSBzZWxmLnBlZXJJRCkgcmV0dXJuO1xuXG4gICAgLy8gUmVzcG9uc2VcbiAgICB2YXIgcmVxdWVzdCA9IHJlcXVlc3RzLmdldChhY2ssIGZyb20pO1xuICAgIGlmKCFyZXF1ZXN0KVxuICAgIHtcbiAgICAgIHZhciBwcm9jZXNzZWQgPSBwcm9jZXNzZWRSZXNwb25zZXMuZ2V0KGFjaywgZnJvbSk7XG4gICAgICBpZihwcm9jZXNzZWQpXG4gICAgICAgIHJldHVybiBkdXBsaWNhdGVkUmVzcG9uc2UocHJvY2Vzc2VkKTtcblxuICAgICAgcmV0dXJuIGNvbnNvbGUud2FybihcIk5vIGNhbGxiYWNrIHdhcyBkZWZpbmVkIGZvciB0aGlzIG1lc3NhZ2VcIiwgbWVzc2FnZSk7XG4gICAgfTtcblxuICAgIC8vIFByb2Nlc3MgcmVzcG9uc2VcbiAgICBwcm9jZXNzUmVzcG9uc2UocmVxdWVzdCwgZXJyb3IsIHJlc3VsdCk7XG4gIH07XG59O1xuaW5oZXJpdHMoUnBjQnVpbGRlciwgRXZlbnRFbWl0dGVyKTtcblxuXG5ScGNCdWlsZGVyLlJwY05vdGlmaWNhdGlvbiA9IFJwY05vdGlmaWNhdGlvbjtcblxuXG5tb2R1bGUuZXhwb3J0cyA9IFJwY0J1aWxkZXI7XG5cbnZhciBjbGllbnRzID0gcmVxdWlyZSgnLi9jbGllbnRzJyk7XG52YXIgdHJhbnNwb3J0cyA9IHJlcXVpcmUoJy4vY2xpZW50cy90cmFuc3BvcnRzJyk7XG5cblJwY0J1aWxkZXIuY2xpZW50cyA9IGNsaWVudHM7XG5ScGNCdWlsZGVyLmNsaWVudHMudHJhbnNwb3J0cyA9IHRyYW5zcG9ydHM7XG5ScGNCdWlsZGVyLnBhY2tlcnMgPSBwYWNrZXJzO1xuIiwiLyoqXG4gKiBKc29uUlBDIDIuMCBwYWNrZXJcbiAqL1xuXG4vKipcbiAqIFBhY2sgYSBKc29uUlBDIDIuMCBtZXNzYWdlXG4gKlxuICogQHBhcmFtIHtPYmplY3R9IG1lc3NhZ2UgLSBvYmplY3QgdG8gYmUgcGFja2FnZWQuIEl0IHJlcXVpcmVzIHRvIGhhdmUgYWxsIHRoZVxuICogICBmaWVsZHMgbmVlZGVkIGJ5IHRoZSBKc29uUlBDIDIuMCBtZXNzYWdlIHRoYXQgaXQncyBnb2luZyB0byBiZSBnZW5lcmF0ZWRcbiAqXG4gKiBAcmV0dXJuIHtTdHJpbmd9IC0gdGhlIHN0cmluZ2lmaWVkIEpzb25SUEMgMi4wIG1lc3NhZ2VcbiAqL1xuZnVuY3Rpb24gcGFjayhtZXNzYWdlLCBpZClcbntcbiAgdmFyIHJlc3VsdCA9XG4gIHtcbiAgICBqc29ucnBjOiBcIjIuMFwiXG4gIH07XG5cbiAgLy8gUmVxdWVzdFxuICBpZihtZXNzYWdlLm1ldGhvZClcbiAge1xuICAgIHJlc3VsdC5tZXRob2QgPSBtZXNzYWdlLm1ldGhvZDtcblxuICAgIGlmKG1lc3NhZ2UucGFyYW1zKVxuICAgICAgcmVzdWx0LnBhcmFtcyA9IG1lc3NhZ2UucGFyYW1zO1xuXG4gICAgLy8gUmVxdWVzdCBpcyBhIG5vdGlmaWNhdGlvblxuICAgIGlmKGlkICE9IHVuZGVmaW5lZClcbiAgICAgIHJlc3VsdC5pZCA9IGlkO1xuICB9XG5cbiAgLy8gUmVzcG9uc2VcbiAgZWxzZSBpZihpZCAhPSB1bmRlZmluZWQpXG4gIHtcbiAgICBpZihtZXNzYWdlLmVycm9yKVxuICAgIHtcbiAgICAgIGlmKG1lc3NhZ2UucmVzdWx0ICE9PSB1bmRlZmluZWQpXG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJCb3RoIHJlc3VsdCBhbmQgZXJyb3IgYXJlIGRlZmluZWRcIik7XG5cbiAgICAgIHJlc3VsdC5lcnJvciA9IG1lc3NhZ2UuZXJyb3I7XG4gICAgfVxuICAgIGVsc2UgaWYobWVzc2FnZS5yZXN1bHQgIT09IHVuZGVmaW5lZClcbiAgICAgIHJlc3VsdC5yZXN1bHQgPSBtZXNzYWdlLnJlc3VsdDtcbiAgICBlbHNlXG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiTm8gcmVzdWx0IG9yIGVycm9yIGlzIGRlZmluZWRcIik7XG5cbiAgICByZXN1bHQuaWQgPSBpZDtcbiAgfTtcblxuICByZXR1cm4gSlNPTi5zdHJpbmdpZnkocmVzdWx0KTtcbn07XG5cbi8qKlxuICogVW5wYWNrIGEgSnNvblJQQyAyLjAgbWVzc2FnZVxuICpcbiAqIEBwYXJhbSB7U3RyaW5nfSBtZXNzYWdlIC0gc3RyaW5nIHdpdGggdGhlIGNvbnRlbnQgb2YgdGhlIEpzb25SUEMgMi4wIG1lc3NhZ2VcbiAqXG4gKiBAdGhyb3dzIHtUeXBlRXJyb3J9IC0gSW52YWxpZCBKc29uUlBDIHZlcnNpb25cbiAqXG4gKiBAcmV0dXJuIHtPYmplY3R9IC0gb2JqZWN0IGZpbGxlZCB3aXRoIHRoZSBKc29uUlBDIDIuMCBtZXNzYWdlIGNvbnRlbnRcbiAqL1xuZnVuY3Rpb24gdW5wYWNrKG1lc3NhZ2UpXG57XG4gIHZhciByZXN1bHQgPSBtZXNzYWdlO1xuXG4gIGlmKHR5cGVvZiBtZXNzYWdlID09PSAnc3RyaW5nJyB8fCBtZXNzYWdlIGluc3RhbmNlb2YgU3RyaW5nKSB7XG4gICAgcmVzdWx0ID0gSlNPTi5wYXJzZShtZXNzYWdlKTtcbiAgfVxuXG4gIC8vIENoZWNrIGlmIGl0J3MgYSB2YWxpZCBtZXNzYWdlXG5cbiAgdmFyIHZlcnNpb24gPSByZXN1bHQuanNvbnJwYztcbiAgaWYodmVyc2lvbiAhPT0gJzIuMCcpXG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkludmFsaWQgSnNvblJQQyB2ZXJzaW9uICdcIiArIHZlcnNpb24gKyBcIic6IFwiICsgbWVzc2FnZSk7XG5cbiAgLy8gUmVzcG9uc2VcbiAgaWYocmVzdWx0Lm1ldGhvZCA9PSB1bmRlZmluZWQpXG4gIHtcbiAgICBpZihyZXN1bHQuaWQgPT0gdW5kZWZpbmVkKVxuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkludmFsaWQgbWVzc2FnZTogXCIrbWVzc2FnZSk7XG5cbiAgICB2YXIgcmVzdWx0X2RlZmluZWQgPSByZXN1bHQucmVzdWx0ICE9PSB1bmRlZmluZWQ7XG4gICAgdmFyIGVycm9yX2RlZmluZWQgID0gcmVzdWx0LmVycm9yICAhPT0gdW5kZWZpbmVkO1xuXG4gICAgLy8gQ2hlY2sgb25seSByZXN1bHQgb3IgZXJyb3IgaXMgZGVmaW5lZCwgbm90IGJvdGggb3Igbm9uZVxuICAgIGlmKHJlc3VsdF9kZWZpbmVkICYmIGVycm9yX2RlZmluZWQpXG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQm90aCByZXN1bHQgYW5kIGVycm9yIGFyZSBkZWZpbmVkOiBcIittZXNzYWdlKTtcblxuICAgIGlmKCFyZXN1bHRfZGVmaW5lZCAmJiAhZXJyb3JfZGVmaW5lZClcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJObyByZXN1bHQgb3IgZXJyb3IgaXMgZGVmaW5lZDogXCIrbWVzc2FnZSk7XG5cbiAgICByZXN1bHQuYWNrID0gcmVzdWx0LmlkO1xuICAgIGRlbGV0ZSByZXN1bHQuaWQ7XG4gIH1cblxuICAvLyBSZXR1cm4gdW5wYWNrZWQgbWVzc2FnZVxuICByZXR1cm4gcmVzdWx0O1xufTtcblxuXG5leHBvcnRzLnBhY2sgICA9IHBhY2s7XG5leHBvcnRzLnVucGFjayA9IHVucGFjaztcbiIsImZ1bmN0aW9uIHBhY2sobWVzc2FnZSlcbntcbiAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIk5vdCB5ZXQgaW1wbGVtZW50ZWRcIik7XG59O1xuXG5mdW5jdGlvbiB1bnBhY2sobWVzc2FnZSlcbntcbiAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIk5vdCB5ZXQgaW1wbGVtZW50ZWRcIik7XG59O1xuXG5cbmV4cG9ydHMucGFjayAgID0gcGFjaztcbmV4cG9ydHMudW5wYWNrID0gdW5wYWNrO1xuIiwidmFyIEpzb25SUEMgPSByZXF1aXJlKCcuL0pzb25SUEMnKTtcbnZhciBYbWxSUEMgID0gcmVxdWlyZSgnLi9YbWxSUEMnKTtcblxuXG5leHBvcnRzLkpzb25SUEMgPSBKc29uUlBDO1xuZXhwb3J0cy5YbWxSUEMgID0gWG1sUlBDO1xuIiwiLy8gTGFzdCB0aW1lIHVwZGF0ZWQgb24gSnVuZSAwOCwgMjAxOFxuXG4vLyBMYXRlc3QgZmlsZSBjYW4gYmUgZm91bmQgaGVyZTogaHR0cHM6Ly9jZG4ud2VicnRjLWV4cGVyaW1lbnQuY29tL2dldFNjcmVlbklkLmpzXG5cbi8vIE11YXogS2hhbiAgICAgICAgIC0gd3d3Lk11YXpLaGFuLmNvbVxuLy8gTUlUIExpY2Vuc2UgICAgICAgLSB3d3cuV2ViUlRDLUV4cGVyaW1lbnQuY29tL2xpY2VuY2Vcbi8vIERvY3VtZW50YXRpb24gICAgIC0gaHR0cHM6Ly9naXRodWIuY29tL211YXota2hhbi9nZXRTY3JlZW5JZC5cblxuLy8gX19fX19fX19fX19fX19cbi8vIGdldFNjcmVlbklkLmpzXG5cbi8qXG5nZXRTY3JlZW5JZChmdW5jdGlvbiAoZXJyb3IsIHNvdXJjZUlkLCBzY3JlZW5fY29uc3RyYWludHMpIHtcbiAgICAvLyBlcnJvciAgICA9PSBudWxsIHx8ICdwZXJtaXNzaW9uLWRlbmllZCcgfHwgJ25vdC1pbnN0YWxsZWQnIHx8ICdpbnN0YWxsZWQtZGlzYWJsZWQnIHx8ICdub3QtY2hyb21lJ1xuICAgIC8vIHNvdXJjZUlkID09IG51bGwgfHwgJ3N0cmluZycgfHwgJ2ZpcmVmb3gnXG4gICAgXG4gICAgaWYobWljcm9zb2Z0RWRnZSkge1xuICAgICAgICBuYXZpZ2F0b3IuZ2V0RGlzcGxheU1lZGlhKHNjcmVlbl9jb25zdHJhaW50cykudGhlbihvblN1Y2Nlc3MsIG9uRmFpbHVyZSk7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICBuYXZpZ2F0b3IubWVkaWFEZXZpY2VzLmdldFVzZXJNZWRpYShzY3JlZW5fY29uc3RyYWludHMpLnRoZW4ob25TdWNjZXNzKWNhdGNoKG9uRmFpbHVyZSk7XG4gICAgfVxufSwgJ3Bhc3Mgc2Vjb25kIHBhcmFtZXRlciBvbmx5IGlmIHlvdSB3YW50IHN5c3RlbSBhdWRpbycpO1xuKi9cblxud2luZG93LmdldFNjcmVlbklkID0gZnVuY3Rpb24gKGNhbGxiYWNrLCBjdXN0b21fcGFyYW1ldGVyKSB7XG4gICAgaWYgKG5hdmlnYXRvci51c2VyQWdlbnQuaW5kZXhPZignRWRnZScpICE9PSAtMSAmJiAoISFuYXZpZ2F0b3IubXNTYXZlT3JPcGVuQmxvYiB8fCAhIW5hdmlnYXRvci5tc1NhdmVCbG9iKSkge1xuICAgICAgICAvLyBtaWNyb3NvZnQgZWRnZSA9PiBuYXZpZ2F0b3IuZ2V0RGlzcGxheU1lZGlhKHNjcmVlbl9jb25zdHJhaW50cykudGhlbihvblN1Y2Nlc3MsIG9uRmFpbHVyZSk7XG4gICAgICAgIGNhbGxiYWNrKHtcbiAgICAgICAgICAgIHZpZGVvOiB0cnVlXG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gZm9yIEZpcmVmb3g6XG4gICAgLy8gc291cmNlSWQgPT0gJ2ZpcmVmb3gnXG4gICAgLy8gc2NyZWVuX2NvbnN0cmFpbnRzID0gey4uLn1cbiAgICBpZiAoISFuYXZpZ2F0b3IubW96R2V0VXNlck1lZGlhKSB7XG4gICAgICAgIGNhbGxiYWNrKG51bGwsICdmaXJlZm94Jywge1xuICAgICAgICAgICAgdmlkZW86IHtcbiAgICAgICAgICAgICAgICBtb3pNZWRpYVNvdXJjZTogJ3dpbmRvdycsXG4gICAgICAgICAgICAgICAgbWVkaWFTb3VyY2U6ICd3aW5kb3cnXG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ21lc3NhZ2UnLCBvbklGcmFtZUNhbGxiYWNrKTtcblxuICAgIGZ1bmN0aW9uIG9uSUZyYW1lQ2FsbGJhY2soZXZlbnQpIHtcbiAgICAgICAgaWYgKCFldmVudC5kYXRhKSByZXR1cm47XG5cbiAgICAgICAgaWYgKGV2ZW50LmRhdGEuY2hyb21lTWVkaWFTb3VyY2VJZCkge1xuICAgICAgICAgICAgaWYgKGV2ZW50LmRhdGEuY2hyb21lTWVkaWFTb3VyY2VJZCA9PT0gJ1Blcm1pc3Npb25EZW5pZWRFcnJvcicpIHtcbiAgICAgICAgICAgICAgICBjYWxsYmFjaygncGVybWlzc2lvbi1kZW5pZWQnKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY2FsbGJhY2sobnVsbCwgZXZlbnQuZGF0YS5jaHJvbWVNZWRpYVNvdXJjZUlkLCBnZXRTY3JlZW5Db25zdHJhaW50cyhudWxsLCBldmVudC5kYXRhLmNocm9tZU1lZGlhU291cmNlSWQsIGV2ZW50LmRhdGEuY2FuUmVxdWVzdEF1ZGlvVHJhY2spKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gdGhpcyBldmVudCBsaXN0ZW5lciBpcyBubyBtb3JlIG5lZWRlZFxuICAgICAgICAgICAgd2luZG93LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ21lc3NhZ2UnLCBvbklGcmFtZUNhbGxiYWNrKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChldmVudC5kYXRhLmNocm9tZUV4dGVuc2lvblN0YXR1cykge1xuICAgICAgICAgICAgY2FsbGJhY2soZXZlbnQuZGF0YS5jaHJvbWVFeHRlbnNpb25TdGF0dXMsIG51bGwsIGdldFNjcmVlbkNvbnN0cmFpbnRzKGV2ZW50LmRhdGEuY2hyb21lRXh0ZW5zaW9uU3RhdHVzKSk7XG5cbiAgICAgICAgICAgIC8vIHRoaXMgZXZlbnQgbGlzdGVuZXIgaXMgbm8gbW9yZSBuZWVkZWRcbiAgICAgICAgICAgIHdpbmRvdy5yZW1vdmVFdmVudExpc3RlbmVyKCdtZXNzYWdlJywgb25JRnJhbWVDYWxsYmFjayk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoIWN1c3RvbV9wYXJhbWV0ZXIpIHtcbiAgICAgICAgc2V0VGltZW91dChwb3N0R2V0U291cmNlSWRNZXNzYWdlLCAxMDApO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBwb3N0R2V0U291cmNlSWRNZXNzYWdlKGN1c3RvbV9wYXJhbWV0ZXIpO1xuICAgICAgICB9LCAxMDApO1xuICAgIH1cbn07XG5cbmZ1bmN0aW9uIGdldFNjcmVlbkNvbnN0cmFpbnRzKGVycm9yLCBzb3VyY2VJZCwgY2FuUmVxdWVzdEF1ZGlvVHJhY2spIHtcbiAgICB2YXIgc2NyZWVuX2NvbnN0cmFpbnRzID0ge1xuICAgICAgICBhdWRpbzogZmFsc2UsXG4gICAgICAgIHZpZGVvOiB7XG4gICAgICAgICAgICBtYW5kYXRvcnk6IHtcbiAgICAgICAgICAgICAgICBjaHJvbWVNZWRpYVNvdXJjZTogZXJyb3IgPyAnc2NyZWVuJyA6ICdkZXNrdG9wJyxcbiAgICAgICAgICAgICAgICBtYXhXaWR0aDogd2luZG93LnNjcmVlbi53aWR0aCA+IDE5MjAgPyB3aW5kb3cuc2NyZWVuLndpZHRoIDogMTkyMCxcbiAgICAgICAgICAgICAgICBtYXhIZWlnaHQ6IHdpbmRvdy5zY3JlZW4uaGVpZ2h0ID4gMTA4MCA/IHdpbmRvdy5zY3JlZW4uaGVpZ2h0IDogMTA4MFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIG9wdGlvbmFsOiBbXVxuICAgICAgICB9XG4gICAgfTtcblxuICAgIGlmICghIWNhblJlcXVlc3RBdWRpb1RyYWNrKSB7XG4gICAgICAgIHNjcmVlbl9jb25zdHJhaW50cy5hdWRpbyA9IHtcbiAgICAgICAgICAgIG1hbmRhdG9yeToge1xuICAgICAgICAgICAgICAgIGNocm9tZU1lZGlhU291cmNlOiBlcnJvciA/ICdzY3JlZW4nIDogJ2Rlc2t0b3AnLFxuICAgICAgICAgICAgICAgIC8vIGVjaG9DYW5jZWxsYXRpb246IHRydWVcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBvcHRpb25hbDogW11cbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICBpZiAoc291cmNlSWQpIHtcbiAgICAgICAgc2NyZWVuX2NvbnN0cmFpbnRzLnZpZGVvLm1hbmRhdG9yeS5jaHJvbWVNZWRpYVNvdXJjZUlkID0gc291cmNlSWQ7XG5cbiAgICAgICAgaWYgKHNjcmVlbl9jb25zdHJhaW50cy5hdWRpbyAmJiBzY3JlZW5fY29uc3RyYWludHMuYXVkaW8ubWFuZGF0b3J5KSB7XG4gICAgICAgICAgICBzY3JlZW5fY29uc3RyYWludHMuYXVkaW8ubWFuZGF0b3J5LmNocm9tZU1lZGlhU291cmNlSWQgPSBzb3VyY2VJZDtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBzY3JlZW5fY29uc3RyYWludHM7XG59XG5cbmZ1bmN0aW9uIHBvc3RHZXRTb3VyY2VJZE1lc3NhZ2UoY3VzdG9tX3BhcmFtZXRlcikge1xuICAgIGlmICghaWZyYW1lKSB7XG4gICAgICAgIGxvYWRJRnJhbWUoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcG9zdEdldFNvdXJjZUlkTWVzc2FnZShjdXN0b21fcGFyYW1ldGVyKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAoIWlmcmFtZS5pc0xvYWRlZCkge1xuICAgICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHBvc3RHZXRTb3VyY2VJZE1lc3NhZ2UoY3VzdG9tX3BhcmFtZXRlcik7XG4gICAgICAgIH0sIDEwMCk7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAoIWN1c3RvbV9wYXJhbWV0ZXIpIHtcbiAgICAgICAgaWZyYW1lLmNvbnRlbnRXaW5kb3cucG9zdE1lc3NhZ2Uoe1xuICAgICAgICAgICAgY2FwdHVyZVNvdXJjZUlkOiB0cnVlXG4gICAgICAgIH0sICcqJyk7XG4gICAgfVxuICAgIGVsc2UgaWYgKCEhY3VzdG9tX3BhcmFtZXRlci5mb3JFYWNoKSB7XG4gICAgICAgIGlmcmFtZS5jb250ZW50V2luZG93LnBvc3RNZXNzYWdlKHtcbiAgICAgICAgICAgIGNhcHR1cmVDdXN0b21Tb3VyY2VJZDogY3VzdG9tX3BhcmFtZXRlclxuICAgICAgICB9LCAnKicpO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgaWZyYW1lLmNvbnRlbnRXaW5kb3cucG9zdE1lc3NhZ2Uoe1xuICAgICAgICAgICAgY2FwdHVyZVNvdXJjZUlkV2l0aEF1ZGlvOiB0cnVlXG4gICAgICAgIH0sICcqJyk7XG4gICAgfVxufVxuXG52YXIgaWZyYW1lO1xuXG4vLyB0aGlzIGZ1bmN0aW9uIGlzIHVzZWQgaW4gUlRDTXVsdGlDb25uZWN0aW9uIHYzXG53aW5kb3cuZ2V0U2NyZWVuQ29uc3RyYWludHMgPSBmdW5jdGlvbiAoY2FsbGJhY2spIHtcbiAgICBsb2FkSUZyYW1lKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgZ2V0U2NyZWVuSWQoZnVuY3Rpb24gKGVycm9yLCBzb3VyY2VJZCwgc2NyZWVuX2NvbnN0cmFpbnRzKSB7XG4gICAgICAgICAgICBpZiAoIXNjcmVlbl9jb25zdHJhaW50cykge1xuICAgICAgICAgICAgICAgIHNjcmVlbl9jb25zdHJhaW50cyA9IHtcbiAgICAgICAgICAgICAgICAgICAgdmlkZW86IHRydWVcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBjYWxsYmFjayhlcnJvciwgc2NyZWVuX2NvbnN0cmFpbnRzLnZpZGVvKTtcbiAgICAgICAgfSk7XG4gICAgfSk7XG59O1xuXG5mdW5jdGlvbiBsb2FkSUZyYW1lKGxvYWRDYWxsYmFjaykge1xuICAgIGlmIChpZnJhbWUpIHtcbiAgICAgICAgbG9hZENhbGxiYWNrKCk7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZnJhbWUgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdpZnJhbWUnKTtcbiAgICBpZnJhbWUub25sb2FkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZnJhbWUuaXNMb2FkZWQgPSB0cnVlO1xuICAgICAgICBsb2FkQ2FsbGJhY2soKTtcbiAgICB9O1xuICAgIGlmcmFtZS5zcmMgPSAnaHR0cHM6Ly9vcGVudmlkdS5naXRodWIuaW8vb3BlbnZpZHUtc2NyZWVuLXNoYXJpbmctY2hyb21lLWV4dGVuc2lvbi8nO1xuICAgIGlmcmFtZS5zdHlsZS5kaXNwbGF5ID0gJ25vbmUnO1xuICAgIChkb2N1bWVudC5ib2R5IHx8IGRvY3VtZW50LmRvY3VtZW50RWxlbWVudCkuYXBwZW5kQ2hpbGQoaWZyYW1lKTtcbn1cblxud2luZG93LmdldENocm9tZUV4dGVuc2lvblN0YXR1cyA9IGZ1bmN0aW9uIChjYWxsYmFjaykge1xuICAgIC8vIGZvciBGaXJlZm94OlxuICAgIGlmICghIW5hdmlnYXRvci5tb3pHZXRVc2VyTWVkaWEpIHtcbiAgICAgICAgY2FsbGJhY2soJ2luc3RhbGxlZC1lbmFibGVkJyk7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcignbWVzc2FnZScsIG9uSUZyYW1lQ2FsbGJhY2spO1xuXG4gICAgZnVuY3Rpb24gb25JRnJhbWVDYWxsYmFjayhldmVudCkge1xuICAgICAgICBpZiAoIWV2ZW50LmRhdGEpIHJldHVybjtcblxuICAgICAgICBpZiAoZXZlbnQuZGF0YS5jaHJvbWVFeHRlbnNpb25TdGF0dXMpIHtcbiAgICAgICAgICAgIGNhbGxiYWNrKGV2ZW50LmRhdGEuY2hyb21lRXh0ZW5zaW9uU3RhdHVzKTtcblxuICAgICAgICAgICAgLy8gdGhpcyBldmVudCBsaXN0ZW5lciBpcyBubyBtb3JlIG5lZWRlZFxuICAgICAgICAgICAgd2luZG93LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ21lc3NhZ2UnLCBvbklGcmFtZUNhbGxiYWNrKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHNldFRpbWVvdXQocG9zdEdldENocm9tZUV4dGVuc2lvblN0YXR1c01lc3NhZ2UsIDEwMCk7XG59O1xuXG5mdW5jdGlvbiBwb3N0R2V0Q2hyb21lRXh0ZW5zaW9uU3RhdHVzTWVzc2FnZSgpIHtcbiAgICBpZiAoIWlmcmFtZSkge1xuICAgICAgICBsb2FkSUZyYW1lKHBvc3RHZXRDaHJvbWVFeHRlbnNpb25TdGF0dXNNZXNzYWdlKTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmICghaWZyYW1lLmlzTG9hZGVkKSB7XG4gICAgICAgIHNldFRpbWVvdXQocG9zdEdldENocm9tZUV4dGVuc2lvblN0YXR1c01lc3NhZ2UsIDEwMCk7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZnJhbWUuY29udGVudFdpbmRvdy5wb3N0TWVzc2FnZSh7XG4gICAgICAgIGdldENocm9tZUV4dGVuc2lvblN0YXR1czogdHJ1ZVxuICAgIH0sICcqJyk7XG59XG5cbmV4cG9ydHMuZ2V0U2NyZWVuSWQgPSBnZXRTY3JlZW5JZDsiLCIvLyBnbG9iYWwgdmFyaWFibGVzXG52YXIgY2hyb21lTWVkaWFTb3VyY2UgPSAnc2NyZWVuJztcbnZhciBzb3VyY2VJZDtcbnZhciBzY3JlZW5DYWxsYmFjaztcbnZhciBpc0ZpcmVmb3ggPSB0eXBlb2Ygd2luZG93Lkluc3RhbGxUcmlnZ2VyICE9PSAndW5kZWZpbmVkJztcbnZhciBpc09wZXJhID0gISF3aW5kb3cub3BlcmEgfHwgbmF2aWdhdG9yLnVzZXJBZ2VudC5pbmRleE9mKCcgT1BSLycpID49IDA7XG52YXIgaXNDaHJvbWUgPSAhIXdpbmRvdy5jaHJvbWUgJiYgIWlzT3BlcmE7XG5cbndpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdtZXNzYWdlJywgZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgaWYgKGV2ZW50Lm9yaWdpbiAhPSB3aW5kb3cubG9jYXRpb24ub3JpZ2luKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgb25NZXNzYWdlQ2FsbGJhY2soZXZlbnQuZGF0YSk7XG59KTtcblxuLy8gYW5kIHRoZSBmdW5jdGlvbiB0aGF0IGhhbmRsZXMgcmVjZWl2ZWQgbWVzc2FnZXNcbmZ1bmN0aW9uIG9uTWVzc2FnZUNhbGxiYWNrKGRhdGEpIHtcbiAgICAvLyBcImNhbmNlbFwiIGJ1dHRvbiBpcyBjbGlja2VkXG4gICAgaWYgKGRhdGEgPT0gJ1Blcm1pc3Npb25EZW5pZWRFcnJvcicpIHtcbiAgICAgICAgaWYgKHNjcmVlbkNhbGxiYWNrKVxuICAgICAgICAgICAgcmV0dXJuIHNjcmVlbkNhbGxiYWNrKCdQZXJtaXNzaW9uRGVuaWVkRXJyb3InKTtcbiAgICAgICAgZWxzZVxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdQZXJtaXNzaW9uRGVuaWVkRXJyb3InKTtcbiAgICB9XG4gICAgLy8gZXh0ZW5zaW9uIG5vdGlmaWVkIGhpcyBwcmVzZW5jZVxuICAgIGlmIChkYXRhID09ICdydGNtdWx0aWNvbm5lY3Rpb24tZXh0ZW5zaW9uLWxvYWRlZCcpIHtcbiAgICAgICAgY2hyb21lTWVkaWFTb3VyY2UgPSAnZGVza3RvcCc7XG4gICAgfVxuICAgIC8vIGV4dGVuc2lvbiBzaGFyZWQgdGVtcCBzb3VyY2VJZFxuICAgIGlmIChkYXRhLnNvdXJjZUlkICYmIHNjcmVlbkNhbGxiYWNrKSB7XG4gICAgICAgIHNjcmVlbkNhbGxiYWNrKHNvdXJjZUlkID0gZGF0YS5zb3VyY2VJZCwgZGF0YS5jYW5SZXF1ZXN0QXVkaW9UcmFjayA9PT0gdHJ1ZSk7XG4gICAgfVxufVxuXG4vLyB0aGlzIG1ldGhvZCBjYW4gYmUgdXNlZCB0byBjaGVjayBpZiBjaHJvbWUgZXh0ZW5zaW9uIGlzIGluc3RhbGxlZCAmIGVuYWJsZWQuXG5mdW5jdGlvbiBpc0Nocm9tZUV4dGVuc2lvbkF2YWlsYWJsZShjYWxsYmFjaykge1xuICAgIGlmICghY2FsbGJhY2spIHJldHVybjtcbiAgICBpZiAoY2hyb21lTWVkaWFTb3VyY2UgPT0gJ2Rlc2t0b3AnKSByZXR1cm4gY2FsbGJhY2sodHJ1ZSk7XG5cbiAgICAvLyBhc2sgZXh0ZW5zaW9uIGlmIGl0IGlzIGF2YWlsYWJsZVxuICAgIHdpbmRvdy5wb3N0TWVzc2FnZSgnYXJlLXlvdS10aGVyZScsICcqJyk7XG4gICAgc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmIChjaHJvbWVNZWRpYVNvdXJjZSA9PSAnc2NyZWVuJykge1xuICAgICAgICAgICAgY2FsbGJhY2soZmFsc2UpO1xuICAgICAgICB9IGVsc2UgY2FsbGJhY2sodHJ1ZSk7XG4gICAgfSwgMjAwMCk7XG59XG5cbi8vIHRoaXMgZnVuY3Rpb24gY2FuIGJlIHVzZWQgdG8gZ2V0IFwic291cmNlLWlkXCIgZnJvbSB0aGUgZXh0ZW5zaW9uXG5mdW5jdGlvbiBnZXRTb3VyY2VJZChjYWxsYmFjaykge1xuICAgIGlmICghY2FsbGJhY2spXG4gICAgICAgIHRocm93ICdcImNhbGxiYWNrXCIgcGFyYW1ldGVyIGlzIG1hbmRhdG9yeS4nO1xuICAgIGlmIChzb3VyY2VJZClcbiAgICAgICAgcmV0dXJuIGNhbGxiYWNrKHNvdXJjZUlkKTtcbiAgICBzY3JlZW5DYWxsYmFjayA9IGNhbGxiYWNrO1xuICAgIHdpbmRvdy5wb3N0TWVzc2FnZSgnZ2V0LXNvdXJjZUlkJywgJyonKTtcbn1cblxuLy8gdGhpcyBmdW5jdGlvbiBjYW4gYmUgdXNlZCB0byBnZXQgXCJzb3VyY2UtaWRcIiBmcm9tIHRoZSBleHRlbnNpb25cbmZ1bmN0aW9uIGdldEN1c3RvbVNvdXJjZUlkKGFyciwgY2FsbGJhY2spIHtcbiAgICBpZiAoIWFyciB8fCAhYXJyLmZvckVhY2gpIHRocm93ICdcImFyclwiIHBhcmFtZXRlciBpcyBtYW5kYXRvcnkgYW5kIGl0IG11c3QgYmUgYW4gYXJyYXkuJztcbiAgICBpZiAoIWNhbGxiYWNrKSB0aHJvdyAnXCJjYWxsYmFja1wiIHBhcmFtZXRlciBpcyBtYW5kYXRvcnkuJztcblxuICAgIGlmIChzb3VyY2VJZCkgcmV0dXJuIGNhbGxiYWNrKHNvdXJjZUlkKTtcblxuICAgIHNjcmVlbkNhbGxiYWNrID0gY2FsbGJhY2s7XG4gICAgd2luZG93LnBvc3RNZXNzYWdlKHtcbiAgICAgICAgJ2dldC1jdXN0b20tc291cmNlSWQnOiBhcnJcbiAgICB9LCAnKicpO1xufVxuXG4vLyB0aGlzIGZ1bmN0aW9uIGNhbiBiZSB1c2VkIHRvIGdldCBcInNvdXJjZS1pZFwiIGZyb20gdGhlIGV4dGVuc2lvblxuZnVuY3Rpb24gZ2V0U291cmNlSWRXaXRoQXVkaW8oY2FsbGJhY2spIHtcbiAgICBpZiAoIWNhbGxiYWNrKSB0aHJvdyAnXCJjYWxsYmFja1wiIHBhcmFtZXRlciBpcyBtYW5kYXRvcnkuJztcbiAgICBpZiAoc291cmNlSWQpIHJldHVybiBjYWxsYmFjayhzb3VyY2VJZCk7XG5cbiAgICBzY3JlZW5DYWxsYmFjayA9IGNhbGxiYWNrO1xuICAgIHdpbmRvdy5wb3N0TWVzc2FnZSgnYXVkaW8tcGx1cy10YWInLCAnKicpO1xufVxuXG5mdW5jdGlvbiBnZXRDaHJvbWVFeHRlbnNpb25TdGF0dXMoZXh0ZW5zaW9uaWQsIGNhbGxiYWNrKSB7XG4gICAgaWYgKGlzRmlyZWZveClcbiAgICAgICAgcmV0dXJuIGNhbGxiYWNrKCdub3QtY2hyb21lJyk7XG4gICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggIT0gMikge1xuICAgICAgICBjYWxsYmFjayA9IGV4dGVuc2lvbmlkO1xuICAgICAgICBleHRlbnNpb25pZCA9ICdsZmNnZmVwYWZub2JkbG9lY2NobmZhY2xpYmVuam9sZCc7IC8vIGRlZmF1bHQgZXh0ZW5zaW9uLWlkXG4gICAgfVxuICAgIHZhciBpbWFnZSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2ltZycpO1xuICAgIGltYWdlLnNyYyA9ICdjaHJvbWUtZXh0ZW5zaW9uOi8vJyArIGV4dGVuc2lvbmlkICsgJy9pY29uLnBuZyc7XG4gICAgaW1hZ2Uub25sb2FkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBjaHJvbWVNZWRpYVNvdXJjZSA9ICdzY3JlZW4nO1xuICAgICAgICB3aW5kb3cucG9zdE1lc3NhZ2UoJ2FyZS15b3UtdGhlcmUnLCAnKicpO1xuICAgICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIGlmIChjaHJvbWVNZWRpYVNvdXJjZSA9PSAnc2NyZWVuJykge1xuICAgICAgICAgICAgICAgIGNhbGxiYWNrKCdpbnN0YWxsZWQtZGlzYWJsZWQnKTtcbiAgICAgICAgICAgIH0gZWxzZVxuICAgICAgICAgICAgICAgIGNhbGxiYWNrKCdpbnN0YWxsZWQtZW5hYmxlZCcpO1xuICAgICAgICB9LCAyMDAwKTtcbiAgICB9O1xuICAgIGltYWdlLm9uZXJyb3IgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGNhbGxiYWNrKCdub3QtaW5zdGFsbGVkJyk7XG4gICAgfTtcbn1cblxuZnVuY3Rpb24gZ2V0U2NyZWVuQ29uc3RyYWludHNXaXRoQXVkaW8oY2FsbGJhY2spIHtcbiAgICBnZXRTY3JlZW5Db25zdHJhaW50cyhjYWxsYmFjaywgdHJ1ZSk7XG59XG5cbi8vIHRoaXMgZnVuY3Rpb24gZXhwbGFpbnMgaG93IHRvIHVzZSBhYm92ZSBtZXRob2RzL29iamVjdHNcbmZ1bmN0aW9uIGdldFNjcmVlbkNvbnN0cmFpbnRzKGNhbGxiYWNrLCBjYXB0dXJlU291cmNlSWRXaXRoQXVkaW8pIHtcbiAgICBzb3VyY2VJZCA9ICcnO1xuICAgIHZhciBmaXJlZm94U2NyZWVuQ29uc3RyYWludHMgPSB7XG4gICAgICAgIG1vek1lZGlhU291cmNlOiAnd2luZG93JyxcbiAgICAgICAgbWVkaWFTb3VyY2U6ICd3aW5kb3cnXG4gICAgfTtcbiAgICBpZiAoaXNGaXJlZm94KVxuICAgICAgICByZXR1cm4gY2FsbGJhY2sobnVsbCwgZmlyZWZveFNjcmVlbkNvbnN0cmFpbnRzKTtcbiAgICAvLyB0aGlzIHN0YXRlbWVudCBkZWZpbmVzIGdldFVzZXJNZWRpYSBjb25zdHJhaW50c1xuICAgIC8vIHRoYXQgd2lsbCBiZSB1c2VkIHRvIGNhcHR1cmUgY29udGVudCBvZiBzY3JlZW5cbiAgICB2YXIgc2NyZWVuX2NvbnN0cmFpbnRzID0ge1xuICAgICAgICBtYW5kYXRvcnk6IHtcbiAgICAgICAgICAgIGNocm9tZU1lZGlhU291cmNlOiBjaHJvbWVNZWRpYVNvdXJjZSxcbiAgICAgICAgICAgIG1heFdpZHRoOiBzY3JlZW4ud2lkdGggPiAxOTIwID8gc2NyZWVuLndpZHRoIDogMTkyMCxcbiAgICAgICAgICAgIG1heEhlaWdodDogc2NyZWVuLmhlaWdodCA+IDEwODAgPyBzY3JlZW4uaGVpZ2h0IDogMTA4MFxuICAgICAgICB9LFxuICAgICAgICBvcHRpb25hbDogW11cbiAgICB9O1xuICAgIC8vIHRoaXMgc3RhdGVtZW50IHZlcmlmaWVzIGNocm9tZSBleHRlbnNpb24gYXZhaWxhYmlsaXR5XG4gICAgLy8gaWYgaW5zdGFsbGVkIGFuZCBhdmFpbGFibGUgdGhlbiBpdCB3aWxsIGludm9rZSBleHRlbnNpb24gQVBJXG4gICAgLy8gb3RoZXJ3aXNlIGl0IHdpbGwgZmFsbGJhY2sgdG8gY29tbWFuZC1saW5lIGJhc2VkIHNjcmVlbiBjYXB0dXJpbmcgQVBJXG4gICAgaWYgKGNocm9tZU1lZGlhU291cmNlID09ICdkZXNrdG9wJyAmJiAhc291cmNlSWQpIHtcbiAgICAgICAgaWYgKGNhcHR1cmVTb3VyY2VJZFdpdGhBdWRpbykge1xuICAgICAgICAgICAgZ2V0U291cmNlSWRXaXRoQXVkaW8oZnVuY3Rpb24gKHNvdXJjZUlkLCBjYW5SZXF1ZXN0QXVkaW9UcmFjaykge1xuICAgICAgICAgICAgICAgIHNjcmVlbl9jb25zdHJhaW50cy5tYW5kYXRvcnkuY2hyb21lTWVkaWFTb3VyY2VJZCA9IHNvdXJjZUlkO1xuXG4gICAgICAgICAgICAgICAgaWYgKGNhblJlcXVlc3RBdWRpb1RyYWNrKSB7XG4gICAgICAgICAgICAgICAgICAgIHNjcmVlbl9jb25zdHJhaW50cy5jYW5SZXF1ZXN0QXVkaW9UcmFjayA9IHRydWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNhbGxiYWNrKHNvdXJjZUlkID09ICdQZXJtaXNzaW9uRGVuaWVkRXJyb3InID8gc291cmNlSWQgOiBudWxsLCBzY3JlZW5fY29uc3RyYWludHMpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBnZXRTb3VyY2VJZChmdW5jdGlvbiAoc291cmNlSWQpIHtcbiAgICAgICAgICAgICAgICBzY3JlZW5fY29uc3RyYWludHMubWFuZGF0b3J5LmNocm9tZU1lZGlhU291cmNlSWQgPSBzb3VyY2VJZDtcbiAgICAgICAgICAgICAgICBjYWxsYmFjayhzb3VyY2VJZCA9PSAnUGVybWlzc2lvbkRlbmllZEVycm9yJyA/IHNvdXJjZUlkIDogbnVsbCwgc2NyZWVuX2NvbnN0cmFpbnRzKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyB0aGlzIHN0YXRlbWVudCBzZXRzIGdldHMgJ3NvdXJjZUlkXCIgYW5kIHNldHMgXCJjaHJvbWVNZWRpYVNvdXJjZUlkXCIgXG4gICAgaWYgKGNocm9tZU1lZGlhU291cmNlID09ICdkZXNrdG9wJykge1xuICAgICAgICBzY3JlZW5fY29uc3RyYWludHMubWFuZGF0b3J5LmNocm9tZU1lZGlhU291cmNlSWQgPSBzb3VyY2VJZDtcbiAgICB9XG5cbiAgICAvLyBub3cgaW52b2tpbmcgbmF0aXZlIGdldFVzZXJNZWRpYSBBUElcbiAgICBjYWxsYmFjayhudWxsLCBzY3JlZW5fY29uc3RyYWludHMpO1xufVxuXG5leHBvcnRzLmdldFNjcmVlbkNvbnN0cmFpbnRzID0gZ2V0U2NyZWVuQ29uc3RyYWludHM7XG5leHBvcnRzLmdldFNjcmVlbkNvbnN0cmFpbnRzV2l0aEF1ZGlvID0gZ2V0U2NyZWVuQ29uc3RyYWludHNXaXRoQXVkaW87XG5leHBvcnRzLmlzQ2hyb21lRXh0ZW5zaW9uQXZhaWxhYmxlID0gaXNDaHJvbWVFeHRlbnNpb25BdmFpbGFibGU7XG5leHBvcnRzLmdldENocm9tZUV4dGVuc2lvblN0YXR1cyA9IGdldENocm9tZUV4dGVuc2lvblN0YXR1cztcbmV4cG9ydHMuZ2V0U291cmNlSWQgPSBnZXRTb3VyY2VJZDsiLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCBmcmVlaWNlID0gcmVxdWlyZSgnZnJlZWljZScpO1xuaW1wb3J0IHV1aWQgPSByZXF1aXJlKCd1dWlkJyk7XG5pbXBvcnQgcGxhdGZvcm0gPSByZXF1aXJlKCdwbGF0Zm9ybScpO1xuXG5cbmV4cG9ydCBpbnRlcmZhY2UgV2ViUnRjUGVlckNvbmZpZ3VyYXRpb24ge1xuICAgIG1lZGlhQ29uc3RyYWludHM6IHtcbiAgICAgICAgYXVkaW86IGJvb2xlYW4sXG4gICAgICAgIHZpZGVvOiBib29sZWFuXG4gICAgfTtcbiAgICBzaW11bGNhc3Q6IGJvb2xlYW47XG4gICAgb25pY2VjYW5kaWRhdGU6IChldmVudCkgPT4gdm9pZDtcbiAgICBpY2VTZXJ2ZXJzOiBSVENJY2VTZXJ2ZXJbXSB8IHVuZGVmaW5lZDtcbiAgICBtZWRpYVN0cmVhbT86IE1lZGlhU3RyZWFtO1xuICAgIG1vZGU/OiBzdHJpbmc7IC8vIHNlbmRvbmx5LCByZWNvbmx5LCBzZW5kcmVjdlxuICAgIGlkPzogc3RyaW5nO1xufVxuXG5leHBvcnQgY2xhc3MgV2ViUnRjUGVlciB7XG5cbiAgICBwYzogUlRDUGVlckNvbm5lY3Rpb247XG4gICAgaWQ6IHN0cmluZztcbiAgICByZW1vdGVDYW5kaWRhdGVzUXVldWU6IFJUQ0ljZUNhbmRpZGF0ZVtdID0gW107XG4gICAgbG9jYWxDYW5kaWRhdGVzUXVldWU6IFJUQ0ljZUNhbmRpZGF0ZVtdID0gW107XG5cbiAgICBpY2VDYW5kaWRhdGVMaXN0OiBSVENJY2VDYW5kaWRhdGVbXSA9IFtdO1xuXG4gICAgcHJpdmF0ZSBjYW5kaWRhdGVnYXRoZXJpbmdkb25lID0gZmFsc2U7XG5cbiAgICBjb25zdHJ1Y3Rvcihwcml2YXRlIGNvbmZpZ3VyYXRpb246IFdlYlJ0Y1BlZXJDb25maWd1cmF0aW9uKSB7XG4gICAgICAgIHRoaXMuY29uZmlndXJhdGlvbi5pY2VTZXJ2ZXJzID0gKCEhdGhpcy5jb25maWd1cmF0aW9uLmljZVNlcnZlcnMgJiYgdGhpcy5jb25maWd1cmF0aW9uLmljZVNlcnZlcnMubGVuZ3RoID4gMCkgPyB0aGlzLmNvbmZpZ3VyYXRpb24uaWNlU2VydmVycyA6IGZyZWVpY2UoKTtcblxuICAgICAgICB0aGlzLnBjID0gbmV3IFJUQ1BlZXJDb25uZWN0aW9uKHsgaWNlU2VydmVyczogdGhpcy5jb25maWd1cmF0aW9uLmljZVNlcnZlcnMgfSk7XG4gICAgICAgIHRoaXMuaWQgPSAhIWNvbmZpZ3VyYXRpb24uaWQgPyBjb25maWd1cmF0aW9uLmlkIDogdXVpZC52NCgpO1xuXG4gICAgICAgIHRoaXMucGMub25pY2VjYW5kaWRhdGUgPSBldmVudCA9PiB7XG4gICAgICAgICAgICBjb25zdCBjYW5kaWRhdGU6IFJUQ0ljZUNhbmRpZGF0ZSA9IGV2ZW50LmNhbmRpZGF0ZTtcbiAgICAgICAgICAgIGlmIChjYW5kaWRhdGUpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmxvY2FsQ2FuZGlkYXRlc1F1ZXVlLnB1c2goPFJUQ0ljZUNhbmRpZGF0ZT57IGNhbmRpZGF0ZTogY2FuZGlkYXRlLmNhbmRpZGF0ZSB9KTtcbiAgICAgICAgICAgICAgICB0aGlzLmNhbmRpZGF0ZWdhdGhlcmluZ2RvbmUgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB0aGlzLmNvbmZpZ3VyYXRpb24ub25pY2VjYW5kaWRhdGUoZXZlbnQuY2FuZGlkYXRlKTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoIXRoaXMuY2FuZGlkYXRlZ2F0aGVyaW5nZG9uZSkge1xuICAgICAgICAgICAgICAgIHRoaXMuY2FuZGlkYXRlZ2F0aGVyaW5nZG9uZSA9IHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG5cbiAgICAgICAgdGhpcy5wYy5vbnNpZ25hbGluZ3N0YXRlY2hhbmdlID0gKCkgPT4ge1xuICAgICAgICAgICAgaWYgKHRoaXMucGMuc2lnbmFsaW5nU3RhdGUgPT09ICdzdGFibGUnKSB7XG4gICAgICAgICAgICAgICAgd2hpbGUgKHRoaXMuaWNlQ2FuZGlkYXRlTGlzdC5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMucGMuYWRkSWNlQ2FuZGlkYXRlKDxSVENJY2VDYW5kaWRhdGU+dGhpcy5pY2VDYW5kaWRhdGVMaXN0LnNoaWZ0KCkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcblxuICAgICAgICB0aGlzLnN0YXJ0KCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhpcyBmdW5jdGlvbiBjcmVhdGVzIHRoZSBSVENQZWVyQ29ubmVjdGlvbiBvYmplY3QgdGFraW5nIGludG8gYWNjb3VudCB0aGVcbiAgICAgKiBwcm9wZXJ0aWVzIHJlY2VpdmVkIGluIHRoZSBjb25zdHJ1Y3Rvci4gSXQgc3RhcnRzIHRoZSBTRFAgbmVnb3RpYXRpb25cbiAgICAgKiBwcm9jZXNzOiBnZW5lcmF0ZXMgdGhlIFNEUCBvZmZlciBhbmQgaW52b2tlcyB0aGUgb25zZHBvZmZlciBjYWxsYmFjay4gVGhpc1xuICAgICAqIGNhbGxiYWNrIGlzIGV4cGVjdGVkIHRvIHNlbmQgdGhlIFNEUCBvZmZlciwgaW4gb3JkZXIgdG8gb2J0YWluIGFuIFNEUFxuICAgICAqIGFuc3dlciBmcm9tIGFub3RoZXIgcGVlci5cbiAgICAgKi9cbiAgICBzdGFydCgpOiBQcm9taXNlPGFueT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgaWYgKHRoaXMucGMuc2lnbmFsaW5nU3RhdGUgPT09ICdjbG9zZWQnKSB7XG4gICAgICAgICAgICAgICAgcmVqZWN0KCdUaGUgcGVlciBjb25uZWN0aW9uIG9iamVjdCBpcyBpbiBcImNsb3NlZFwiIHN0YXRlLiBUaGlzIGlzIG1vc3QgbGlrZWx5IGR1ZSB0byBhbiBpbnZvY2F0aW9uIG9mIHRoZSBkaXNwb3NlIG1ldGhvZCBiZWZvcmUgYWNjZXB0aW5nIGluIHRoZSBkaWFsb2d1ZScpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCEhdGhpcy5jb25maWd1cmF0aW9uLm1lZGlhU3RyZWFtKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5wYy5hZGRTdHJlYW0odGhpcy5jb25maWd1cmF0aW9uLm1lZGlhU3RyZWFtKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gW0hhY2tdIGh0dHBzOi8vY29kZS5nb29nbGUuY29tL3AvY2hyb21pdW0vaXNzdWVzL2RldGFpbD9pZD00NDM1NThcbiAgICAgICAgICAgIGlmICh0aGlzLmNvbmZpZ3VyYXRpb24ubW9kZSA9PT0gJ3NlbmRvbmx5JyAmJlxuICAgICAgICAgICAgICAgIChwbGF0Zm9ybS5uYW1lID09PSAnQ2hyb21lJyAmJiBwbGF0Zm9ybS52ZXJzaW9uIS50b1N0cmluZygpLnN1YnN0cmluZygwLCAyKSA9PT0gJzM5JykpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmNvbmZpZ3VyYXRpb24ubW9kZSA9ICdzZW5kcmVjdic7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhpcyBtZXRob2QgZnJlZXMgdGhlIHJlc291cmNlcyB1c2VkIGJ5IFdlYlJ0Y1BlZXJcbiAgICAgKi9cbiAgICBkaXNwb3NlKCkge1xuICAgICAgICBjb25zb2xlLmRlYnVnKCdEaXNwb3NpbmcgV2ViUnRjUGVlcicpO1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgaWYgKHRoaXMucGMpIHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5wYy5zaWduYWxpbmdTdGF0ZSA9PT0gJ2Nsb3NlZCcpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLnJlbW90ZUNhbmRpZGF0ZXNRdWV1ZSA9IFtdO1xuICAgICAgICAgICAgICAgIHRoaXMubG9jYWxDYW5kaWRhdGVzUXVldWUgPSBbXTtcblxuICAgICAgICAgICAgICAgIHRoaXMucGMuZ2V0TG9jYWxTdHJlYW1zKCkuZm9yRWFjaChzdHIgPT4ge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbVN0b3Aoc3RyKTtcbiAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAgIC8vIEZJWE1FIFRoaXMgaXMgbm90IHlldCBpbXBsZW1lbnRlZCBpbiBmaXJlZm94XG4gICAgICAgICAgICAgICAgLy8gaWYodmlkZW9TdHJlYW0pIHBjLnJlbW92ZVN0cmVhbSh2aWRlb1N0cmVhbSk7XG4gICAgICAgICAgICAgICAgLy8gaWYoYXVkaW9TdHJlYW0pIHBjLnJlbW92ZVN0cmVhbShhdWRpb1N0cmVhbSk7XG5cbiAgICAgICAgICAgICAgICB0aGlzLnBjLmNsb3NlKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgY29uc29sZS53YXJuKCdFeGNlcHRpb24gZGlzcG9zaW5nIHdlYnJ0YyBwZWVyICcgKyBlcnIpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogMSkgRnVuY3Rpb24gdGhhdCBjcmVhdGVzIGFuIG9mZmVyLCBzZXRzIGl0IGFzIGxvY2FsIGRlc2NyaXB0aW9uIGFuZCByZXR1cm5zIHRoZSBvZmZlciBwYXJhbVxuICAgICAqIHRvIHNlbmQgdG8gT3BlblZpZHUgU2VydmVyICh3aWxsIGJlIHRoZSByZW1vdGUgZGVzY3JpcHRpb24gb2Ygb3RoZXIgcGVlcilcbiAgICAgKi9cbiAgICBnZW5lcmF0ZU9mZmVyKCk6IFByb21pc2U8c3RyaW5nPiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICBsZXQgb2ZmZXJBdWRpbywgb2ZmZXJWaWRlbyA9IHRydWU7XG5cbiAgICAgICAgICAgIC8vIENvbnN0cmFpbnRzIG11c3QgaGF2ZSBib3RoIGJsb2Nrc1xuICAgICAgICAgICAgaWYgKCEhdGhpcy5jb25maWd1cmF0aW9uLm1lZGlhQ29uc3RyYWludHMpIHtcbiAgICAgICAgICAgICAgICBvZmZlckF1ZGlvID0gKHR5cGVvZiB0aGlzLmNvbmZpZ3VyYXRpb24ubWVkaWFDb25zdHJhaW50cy5hdWRpbyA9PT0gJ2Jvb2xlYW4nKSA/XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuY29uZmlndXJhdGlvbi5tZWRpYUNvbnN0cmFpbnRzLmF1ZGlvIDogdHJ1ZTtcbiAgICAgICAgICAgICAgICBvZmZlclZpZGVvID0gKHR5cGVvZiB0aGlzLmNvbmZpZ3VyYXRpb24ubWVkaWFDb25zdHJhaW50cy52aWRlbyA9PT0gJ2Jvb2xlYW4nKSA/XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuY29uZmlndXJhdGlvbi5tZWRpYUNvbnN0cmFpbnRzLnZpZGVvIDogdHJ1ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgY29uc3QgY29uc3RyYWludHM6IFJUQ09mZmVyT3B0aW9ucyA9IHtcbiAgICAgICAgICAgICAgICBvZmZlclRvUmVjZWl2ZUF1ZGlvOiArICh0aGlzLmNvbmZpZ3VyYXRpb24ubW9kZSAhPT0gJ3NlbmRvbmx5JyAmJiBvZmZlckF1ZGlvKSxcbiAgICAgICAgICAgICAgICBvZmZlclRvUmVjZWl2ZVZpZGVvOiArICh0aGlzLmNvbmZpZ3VyYXRpb24ubW9kZSAhPT0gJ3NlbmRvbmx5JyAmJiBvZmZlclZpZGVvKVxuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgY29uc29sZS5kZWJ1ZygnUlRDUGVlckNvbm5lY3Rpb24gY29uc3RyYWludHM6ICcgKyBKU09OLnN0cmluZ2lmeShjb25zdHJhaW50cykpO1xuXG4gICAgICAgICAgICB0aGlzLnBjLmNyZWF0ZU9mZmVyKGNvbnN0cmFpbnRzKS50aGVuKG9mZmVyID0+IHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmRlYnVnKCdDcmVhdGVkIFNEUCBvZmZlcicpO1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLnBjLnNldExvY2FsRGVzY3JpcHRpb24ob2ZmZXIpO1xuICAgICAgICAgICAgfSkudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3QgbG9jYWxEZXNjcmlwdGlvbiA9IHRoaXMucGMubG9jYWxEZXNjcmlwdGlvbjtcbiAgICAgICAgICAgICAgICBpZiAoISFsb2NhbERlc2NyaXB0aW9uKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZGVidWcoJ0xvY2FsIGRlc2NyaXB0aW9uIHNldCcsIGxvY2FsRGVzY3JpcHRpb24uc2RwKTtcbiAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSg8c3RyaW5nPmxvY2FsRGVzY3JpcHRpb24uc2RwKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICByZWplY3QoJ0xvY2FsIGRlc2NyaXB0aW9uIGlzIG5vdCBkZWZpbmVkJyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSkuY2F0Y2goZXJyb3IgPT4gcmVqZWN0KGVycm9yKSk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIDIpIEZ1bmN0aW9uIHRvIGludm9rZSB3aGVuIGEgU0RQIG9mZmVyIGlzIHJlY2VpdmVkLiBTZXRzIGl0IGFzIHJlbW90ZSBkZXNjcmlwdGlvbixcbiAgICAgKiBnZW5lcmF0ZXMgYW5kIGFuc3dlciBhbmQgcmV0dXJucyBpdCB0byBzZW5kIGl0IHRvIE9wZW5WaWR1IFNlcnZlclxuICAgICAqL1xuICAgIHByb2Nlc3NPZmZlcihzZHBPZmZlcjogc3RyaW5nKTogUHJvbWlzZTxDb25zdHJhaW5ET01TdHJpbmc+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IG9mZmVyOiBSVENTZXNzaW9uRGVzY3JpcHRpb25Jbml0ID0ge1xuICAgICAgICAgICAgICAgIHR5cGU6ICdvZmZlcicsXG4gICAgICAgICAgICAgICAgc2RwOiBzZHBPZmZlclxuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgY29uc29sZS5kZWJ1ZygnU0RQIG9mZmVyIHJlY2VpdmVkLCBzZXR0aW5nIHJlbW90ZSBkZXNjcmlwdGlvbicpO1xuXG4gICAgICAgICAgICBpZiAodGhpcy5wYy5zaWduYWxpbmdTdGF0ZSA9PT0gJ2Nsb3NlZCcpIHtcbiAgICAgICAgICAgICAgICByZWplY3QoJ1BlZXJDb25uZWN0aW9uIGlzIGNsb3NlZCcpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLnBjLnNldFJlbW90ZURlc2NyaXB0aW9uKG9mZmVyKVxuICAgICAgICAgICAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMucGMuY3JlYXRlQW5zd2VyKCk7XG4gICAgICAgICAgICAgICAgfSkudGhlbihhbnN3ZXIgPT4ge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmRlYnVnKCdDcmVhdGVkIFNEUCBhbnN3ZXInKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMucGMuc2V0TG9jYWxEZXNjcmlwdGlvbihhbnN3ZXIpO1xuICAgICAgICAgICAgICAgIH0pLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBsb2NhbERlc2NyaXB0aW9uID0gdGhpcy5wYy5sb2NhbERlc2NyaXB0aW9uO1xuICAgICAgICAgICAgICAgICAgICBpZiAoISFsb2NhbERlc2NyaXB0aW9uKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmRlYnVnKCdMb2NhbCBkZXNjcmlwdGlvbiBzZXQnLCBsb2NhbERlc2NyaXB0aW9uLnNkcCk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXNvbHZlKDxzdHJpbmc+bG9jYWxEZXNjcmlwdGlvbi5zZHApO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KCdMb2NhbCBkZXNjcmlwdGlvbiBpcyBub3QgZGVmaW5lZCcpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSkuY2F0Y2goZXJyb3IgPT4gcmVqZWN0KGVycm9yKSk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIDMpIEZ1bmN0aW9uIGludm9rZWQgd2hlbiBhIFNEUCBhbnN3ZXIgaXMgcmVjZWl2ZWQuIEZpbmFsIHN0ZXAgaW4gU0RQIG5lZ290aWF0aW9uLCB0aGUgcGVlclxuICAgICAqIGp1c3QgbmVlZHMgdG8gc2V0IHRoZSBhbnN3ZXIgYXMgaXRzIHJlbW90ZSBkZXNjcmlwdGlvblxuICAgICAqL1xuICAgIHByb2Nlc3NBbnN3ZXIoc2RwQW5zd2VyOiBzdHJpbmcpOiBQcm9taXNlPHN0cmluZz4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuXG4gICAgICAgICAgICBjb25zdCBhbnN3ZXI6IFJUQ1Nlc3Npb25EZXNjcmlwdGlvbkluaXQgPSB7XG4gICAgICAgICAgICAgICAgdHlwZTogJ2Fuc3dlcicsXG4gICAgICAgICAgICAgICAgc2RwOiBzZHBBbnN3ZXJcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIGNvbnNvbGUuZGVidWcoJ1NEUCBhbnN3ZXIgcmVjZWl2ZWQsIHNldHRpbmcgcmVtb3RlIGRlc2NyaXB0aW9uJyk7XG5cbiAgICAgICAgICAgIGlmICh0aGlzLnBjLnNpZ25hbGluZ1N0YXRlID09PSAnY2xvc2VkJykge1xuICAgICAgICAgICAgICAgIHJlamVjdCgnUlRDUGVlckNvbm5lY3Rpb24gaXMgY2xvc2VkJyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMucGMuc2V0UmVtb3RlRGVzY3JpcHRpb24oYW5zd2VyKS50aGVuKCgpID0+IHJlc29sdmUoKSkuY2F0Y2goZXJyb3IgPT4gcmVqZWN0KGVycm9yKSk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENhbGxiYWNrIGZ1bmN0aW9uIGludm9rZWQgd2hlbiBhbiBJQ0UgY2FuZGlkYXRlIGlzIHJlY2VpdmVkXG4gICAgICovXG4gICAgYWRkSWNlQ2FuZGlkYXRlKGljZUNhbmRpZGF0ZTogUlRDSWNlQ2FuZGlkYXRlKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICBjb25zb2xlLmRlYnVnKCdSZW1vdGUgSUNFIGNhbmRpZGF0ZSByZWNlaXZlZCcsIGljZUNhbmRpZGF0ZSk7XG4gICAgICAgICAgICB0aGlzLnJlbW90ZUNhbmRpZGF0ZXNRdWV1ZS5wdXNoKGljZUNhbmRpZGF0ZSk7XG4gICAgICAgICAgICBzd2l0Y2ggKHRoaXMucGMuc2lnbmFsaW5nU3RhdGUpIHtcbiAgICAgICAgICAgICAgICBjYXNlICdjbG9zZWQnOlxuICAgICAgICAgICAgICAgICAgICByZWplY3QobmV3IEVycm9yKCdQZWVyQ29ubmVjdGlvbiBvYmplY3QgaXMgY2xvc2VkJykpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlICdzdGFibGUnOlxuICAgICAgICAgICAgICAgICAgICBpZiAoISF0aGlzLnBjLnJlbW90ZURlc2NyaXB0aW9uKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnBjLmFkZEljZUNhbmRpZGF0ZShpY2VDYW5kaWRhdGUpLnRoZW4oKCkgPT4gcmVzb2x2ZSgpKS5jYXRjaChlcnJvciA9PiByZWplY3QoZXJyb3IpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICB0aGlzLmljZUNhbmRpZGF0ZUxpc3QucHVzaChpY2VDYW5kaWRhdGUpO1xuICAgICAgICAgICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIHByaXZhdGUgc3RyZWFtU3RvcChzdHJlYW06IE1lZGlhU3RyZWFtKTogdm9pZCB7XG4gICAgICAgIHN0cmVhbS5nZXRUcmFja3MoKS5mb3JFYWNoKHRyYWNrID0+IHtcbiAgICAgICAgICAgIHRyYWNrLnN0b3AoKTtcbiAgICAgICAgICAgIHN0cmVhbS5yZW1vdmVUcmFjayh0cmFjayk7XG4gICAgICAgIH0pO1xuICAgIH1cbn1cblxuXG5leHBvcnQgY2xhc3MgV2ViUnRjUGVlclJlY3Zvbmx5IGV4dGVuZHMgV2ViUnRjUGVlciB7XG4gICAgY29uc3RydWN0b3IoY29uZmlndXJhdGlvbjogV2ViUnRjUGVlckNvbmZpZ3VyYXRpb24pIHtcbiAgICAgICAgY29uZmlndXJhdGlvbi5tb2RlID0gJ3JlY3Zvbmx5JztcbiAgICAgICAgc3VwZXIoY29uZmlndXJhdGlvbik7XG4gICAgfVxufVxuXG5leHBvcnQgY2xhc3MgV2ViUnRjUGVlclNlbmRvbmx5IGV4dGVuZHMgV2ViUnRjUGVlciB7XG4gICAgY29uc3RydWN0b3IoY29uZmlndXJhdGlvbjogV2ViUnRjUGVlckNvbmZpZ3VyYXRpb24pIHtcbiAgICAgICAgY29uZmlndXJhdGlvbi5tb2RlID0gJ3NlbmRvbmx5JztcbiAgICAgICAgc3VwZXIoY29uZmlndXJhdGlvbik7XG4gICAgfVxufVxuXG5leHBvcnQgY2xhc3MgV2ViUnRjUGVlclNlbmRyZWN2IGV4dGVuZHMgV2ViUnRjUGVlciB7XG4gICAgY29uc3RydWN0b3IoY29uZmlndXJhdGlvbjogV2ViUnRjUGVlckNvbmZpZ3VyYXRpb24pIHtcbiAgICAgICAgY29uZmlndXJhdGlvbi5tb2RlID0gJ3NlbmRyZWN2JztcbiAgICAgICAgc3VwZXIoY29uZmlndXJhdGlvbik7XG4gICAgfVxufSIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTctMjAxOCBPcGVuVmlkdSAoaHR0cHM6Ly9vcGVudmlkdS5pby8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuLy8gdHNsaW50OmRpc2FibGU6bm8tc3RyaW5nLWxpdGVyYWxcblxuaW1wb3J0IHsgU3RyZWFtIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvU3RyZWFtJztcbmltcG9ydCBwbGF0Zm9ybSA9IHJlcXVpcmUoJ3BsYXRmb3JtJyk7XG5cbmV4cG9ydCBjbGFzcyBXZWJSdGNTdGF0cyB7XG5cbiAgICBwcml2YXRlIHdlYlJ0Y1N0YXRzRW5hYmxlZCA9IGZhbHNlO1xuICAgIHByaXZhdGUgd2ViUnRjU3RhdHNJbnRlcnZhbElkOiBOb2RlSlMuVGltZXI7XG4gICAgcHJpdmF0ZSBzdGF0c0ludGVydmFsID0gMTtcbiAgICBwcml2YXRlIHN0YXRzOiBhbnkgPSB7XG4gICAgICAgIGluYm91bmQ6IHtcbiAgICAgICAgICAgIGF1ZGlvOiB7XG4gICAgICAgICAgICAgICAgYnl0ZXNSZWNlaXZlZDogMCxcbiAgICAgICAgICAgICAgICBwYWNrZXRzUmVjZWl2ZWQ6IDAsXG4gICAgICAgICAgICAgICAgcGFja2V0c0xvc3Q6IDBcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB2aWRlbzoge1xuICAgICAgICAgICAgICAgIGJ5dGVzUmVjZWl2ZWQ6IDAsXG4gICAgICAgICAgICAgICAgcGFja2V0c1JlY2VpdmVkOiAwLFxuICAgICAgICAgICAgICAgIHBhY2tldHNMb3N0OiAwLFxuICAgICAgICAgICAgICAgIGZyYW1lc0RlY29kZWQ6IDAsXG4gICAgICAgICAgICAgICAgbmFja0NvdW50OiAwXG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIG91dGJvdW5kOiB7XG4gICAgICAgICAgICBhdWRpbzoge1xuICAgICAgICAgICAgICAgIGJ5dGVzU2VudDogMCxcbiAgICAgICAgICAgICAgICBwYWNrZXRzU2VudDogMCxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB2aWRlbzoge1xuICAgICAgICAgICAgICAgIGJ5dGVzU2VudDogMCxcbiAgICAgICAgICAgICAgICBwYWNrZXRzU2VudDogMCxcbiAgICAgICAgICAgICAgICBmcmFtZXNFbmNvZGVkOiAwLFxuICAgICAgICAgICAgICAgIG5hY2tDb3VudDogMFxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfTtcblxuICAgIGNvbnN0cnVjdG9yKHByaXZhdGUgc3RyZWFtOiBTdHJlYW0pIHsgfVxuXG4gICAgcHVibGljIGlzRW5hYmxlZCgpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuIHRoaXMud2ViUnRjU3RhdHNFbmFibGVkO1xuICAgIH1cblxuICAgIHB1YmxpYyBpbml0V2ViUnRjU3RhdHMoKTogdm9pZCB7XG5cbiAgICAgICAgY29uc3QgZWxhc3Rlc3RJbnN0cnVtZW50YXRpb24gPSBsb2NhbFN0b3JhZ2UuZ2V0SXRlbSgnZWxhc3Rlc3QtaW5zdHJ1bWVudGF0aW9uJyk7XG5cbiAgICAgICAgaWYgKGVsYXN0ZXN0SW5zdHJ1bWVudGF0aW9uKSB7XG4gICAgICAgICAgICAvLyBFbGFzVGVzdCBpbnN0cnVtZW50YXRpb24gb2JqZWN0IGZvdW5kIGluIGxvY2FsIHN0b3JhZ2VcblxuICAgICAgICAgICAgY29uc29sZS53YXJuKCdXZWJSdGMgc3RhdHMgZW5hYmxlZCBmb3Igc3RyZWFtICcgKyB0aGlzLnN0cmVhbS5zdHJlYW1JZCArICcgb2YgY29ubmVjdGlvbiAnICsgdGhpcy5zdHJlYW0uY29ubmVjdGlvbi5jb25uZWN0aW9uSWQpO1xuXG4gICAgICAgICAgICB0aGlzLndlYlJ0Y1N0YXRzRW5hYmxlZCA9IHRydWU7XG5cbiAgICAgICAgICAgIGNvbnN0IGluc3RydW1lbnRhdGlvbiA9IEpTT04ucGFyc2UoZWxhc3Rlc3RJbnN0cnVtZW50YXRpb24pO1xuICAgICAgICAgICAgdGhpcy5zdGF0c0ludGVydmFsID0gaW5zdHJ1bWVudGF0aW9uLndlYnJ0Yy5pbnRlcnZhbDsgIC8vIEludGVydmFsIGluIHNlY29uZHNcblxuICAgICAgICAgICAgY29uc29sZS53YXJuKCdsb2NhbFN0b3JhZ2UgaXRlbTogJyArIEpTT04uc3RyaW5naWZ5KGluc3RydW1lbnRhdGlvbikpO1xuXG4gICAgICAgICAgICB0aGlzLndlYlJ0Y1N0YXRzSW50ZXJ2YWxJZCA9IHNldEludGVydmFsKCgpID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLnNlbmRTdGF0c1RvSHR0cEVuZHBvaW50KGluc3RydW1lbnRhdGlvbik7XG4gICAgICAgICAgICB9LCB0aGlzLnN0YXRzSW50ZXJ2YWwgKiAxMDAwKTtcblxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc29sZS5kZWJ1ZygnV2ViUnRjIHN0YXRzIG5vdCBlbmFibGVkJyk7XG4gICAgfVxuXG4gICAgcHVibGljIHN0b3BXZWJSdGNTdGF0cygpIHtcbiAgICAgICAgaWYgKHRoaXMud2ViUnRjU3RhdHNFbmFibGVkKSB7XG4gICAgICAgICAgICBjbGVhckludGVydmFsKHRoaXMud2ViUnRjU3RhdHNJbnRlcnZhbElkKTtcbiAgICAgICAgICAgIGNvbnNvbGUud2FybignV2ViUnRjIHN0YXRzIHN0b3BwZWQgZm9yIGRpc3Bvc2VkIHN0cmVhbSAnICsgdGhpcy5zdHJlYW0uc3RyZWFtSWQgKyAnIG9mIGNvbm5lY3Rpb24gJyArIHRoaXMuc3RyZWFtLmNvbm5lY3Rpb24uY29ubmVjdGlvbklkKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHB1YmxpYyBnZXRTZWxlY3RlZEljZUNhbmRpZGF0ZUluZm8oKTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIHRoaXMuZ2V0U3RhdHNBZ25vc3RpYyh0aGlzLnN0cmVhbS5nZXRSVENQZWVyQ29ubmVjdGlvbigpLFxuICAgICAgICAgICAgICAgIChzdGF0cykgPT4ge1xuICAgICAgICAgICAgICAgICAgICBpZiAoKHBsYXRmb3JtLm5hbWUhLmluZGV4T2YoJ0Nocm9tZScpICE9PSAtMSkgfHwgKHBsYXRmb3JtLm5hbWUhLmluZGV4T2YoJ09wZXJhJykgIT09IC0xKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGxvY2FsQ2FuZGlkYXRlSWQsIHJlbW90ZUNhbmRpZGF0ZUlkLCBnb29nQ2FuZGlkYXRlUGFpcjtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGxvY2FsQ2FuZGlkYXRlcyA9IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgcmVtb3RlQ2FuZGlkYXRlcyA9IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChjb25zdCBrZXkgaW4gc3RhdHMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBzdGF0ID0gc3RhdHNba2V5XTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoc3RhdC50eXBlID09PSAnbG9jYWxjYW5kaWRhdGUnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxvY2FsQ2FuZGlkYXRlc1tzdGF0LmlkXSA9IHN0YXQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChzdGF0LnR5cGUgPT09ICdyZW1vdGVjYW5kaWRhdGUnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlbW90ZUNhbmRpZGF0ZXNbc3RhdC5pZF0gPSBzdGF0O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoc3RhdC50eXBlID09PSAnZ29vZ0NhbmRpZGF0ZVBhaXInICYmIChzdGF0Lmdvb2dBY3RpdmVDb25uZWN0aW9uID09PSAndHJ1ZScpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdvb2dDYW5kaWRhdGVQYWlyID0gc3RhdDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbG9jYWxDYW5kaWRhdGVJZCA9IHN0YXQubG9jYWxDYW5kaWRhdGVJZDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3RlQ2FuZGlkYXRlSWQgPSBzdGF0LnJlbW90ZUNhbmRpZGF0ZUlkO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBmaW5hbExvY2FsQ2FuZGlkYXRlID0gbG9jYWxDYW5kaWRhdGVzW2xvY2FsQ2FuZGlkYXRlSWRdO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCEhZmluYWxMb2NhbENhbmRpZGF0ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGNhbmRMaXN0ID0gdGhpcy5zdHJlYW0uZ2V0TG9jYWxJY2VDYW5kaWRhdGVMaXN0KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgY2FuZCA9IGNhbmRMaXN0LmZpbHRlcigoYzogUlRDSWNlQ2FuZGlkYXRlKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAoISFjLmNhbmRpZGF0ZSAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5jYW5kaWRhdGUuaW5kZXhPZihmaW5hbExvY2FsQ2FuZGlkYXRlLmlwQWRkcmVzcykgPj0gMCAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5jYW5kaWRhdGUuaW5kZXhPZihmaW5hbExvY2FsQ2FuZGlkYXRlLnBvcnROdW1iZXIpID49IDAgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuY2FuZGlkYXRlLmluZGV4T2YoZmluYWxMb2NhbENhbmRpZGF0ZS5wcmlvcml0eSkgPj0gMCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZmluYWxMb2NhbENhbmRpZGF0ZS5yYXcgPSAhIWNhbmRbMF0gPyBjYW5kWzBdLmNhbmRpZGF0ZSA6ICdFUlJPUjogQ2Fubm90IGZpbmQgbG9jYWwgY2FuZGlkYXRlIGluIGxpc3Qgb2Ygc2VudCBJQ0UgY2FuZGlkYXRlcyc7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbmFsTG9jYWxDYW5kaWRhdGUgPSAnRVJST1I6IE5vIGFjdGl2ZSBsb2NhbCBJQ0UgY2FuZGlkYXRlLiBQcm9iYWJseSBJQ0UtVENQIGlzIGJlaW5nIHVzZWQnO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICBsZXQgZmluYWxSZW1vdGVDYW5kaWRhdGUgPSByZW1vdGVDYW5kaWRhdGVzW3JlbW90ZUNhbmRpZGF0ZUlkXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghIWZpbmFsUmVtb3RlQ2FuZGlkYXRlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgY2FuZExpc3QgPSB0aGlzLnN0cmVhbS5nZXRSZW1vdGVJY2VDYW5kaWRhdGVMaXN0KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgY2FuZCA9IGNhbmRMaXN0LmZpbHRlcigoYzogUlRDSWNlQ2FuZGlkYXRlKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAoISFjLmNhbmRpZGF0ZSAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5jYW5kaWRhdGUuaW5kZXhPZihmaW5hbFJlbW90ZUNhbmRpZGF0ZS5pcEFkZHJlc3MpID49IDAgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuY2FuZGlkYXRlLmluZGV4T2YoZmluYWxSZW1vdGVDYW5kaWRhdGUucG9ydE51bWJlcikgPj0gMCAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5jYW5kaWRhdGUuaW5kZXhPZihmaW5hbFJlbW90ZUNhbmRpZGF0ZS5wcmlvcml0eSkgPj0gMCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZmluYWxSZW1vdGVDYW5kaWRhdGUucmF3ID0gISFjYW5kWzBdID8gY2FuZFswXS5jYW5kaWRhdGUgOiAnRVJST1I6IENhbm5vdCBmaW5kIHJlbW90ZSBjYW5kaWRhdGUgaW4gbGlzdCBvZiByZWNlaXZlZCBJQ0UgY2FuZGlkYXRlcyc7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbmFsUmVtb3RlQ2FuZGlkYXRlID0gJ0VSUk9SOiBObyBhY3RpdmUgcmVtb3RlIElDRSBjYW5kaWRhdGUuIFByb2JhYmx5IElDRS1UQ1AgaXMgYmVpbmcgdXNlZCc7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdvb2dDYW5kaWRhdGVQYWlyLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxvY2FsQ2FuZGlkYXRlOiBmaW5hbExvY2FsQ2FuZGlkYXRlLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlbW90ZUNhbmRpZGF0ZTogZmluYWxSZW1vdGVDYW5kaWRhdGVcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KCdTZWxlY3RlZCBJQ0UgY2FuZGlkYXRlIGluZm8gb25seSBhdmFpbGFibGUgZm9yIENocm9tZScpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAoZXJyb3IpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBzZW5kU3RhdHNUb0h0dHBFbmRwb2ludChpbnN0cnVtZW50YXRpb24pOiB2b2lkIHtcblxuICAgICAgICBjb25zdCBzZW5kUG9zdCA9IChqc29uKSA9PiB7XG4gICAgICAgICAgICBjb25zdCBodHRwOiBYTUxIdHRwUmVxdWVzdCA9IG5ldyBYTUxIdHRwUmVxdWVzdCgpO1xuICAgICAgICAgICAgY29uc3QgdXJsOiBzdHJpbmcgPSBpbnN0cnVtZW50YXRpb24ud2VicnRjLmh0dHBFbmRwb2ludDtcbiAgICAgICAgICAgIGh0dHAub3BlbignUE9TVCcsIHVybCwgdHJ1ZSk7XG5cbiAgICAgICAgICAgIGh0dHAuc2V0UmVxdWVzdEhlYWRlcignQ29udGVudC10eXBlJywgJ2FwcGxpY2F0aW9uL2pzb24nKTtcblxuICAgICAgICAgICAgaHR0cC5vbnJlYWR5c3RhdGVjaGFuZ2UgPSAoKSA9PiB7IC8vIENhbGwgYSBmdW5jdGlvbiB3aGVuIHRoZSBzdGF0ZSBjaGFuZ2VzLlxuICAgICAgICAgICAgICAgIGlmIChodHRwLnJlYWR5U3RhdGUgPT09IDQgJiYgaHR0cC5zdGF0dXMgPT09IDIwMCkge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmxvZygnV2ViUnRjIHN0YXRzIHN1Y2Nlc3NmdWxseSBzZW50IHRvICcgKyB1cmwgKyAnIGZvciBzdHJlYW0gJyArIHRoaXMuc3RyZWFtLnN0cmVhbUlkICsgJyBvZiBjb25uZWN0aW9uICcgKyB0aGlzLnN0cmVhbS5jb25uZWN0aW9uLmNvbm5lY3Rpb25JZCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGh0dHAuc2VuZChqc29uKTtcbiAgICAgICAgfTtcblxuICAgICAgICBjb25zdCBmID0gKHN0YXRzKSA9PiB7XG5cbiAgICAgICAgICAgIGlmIChwbGF0Zm9ybS5uYW1lIS5pbmRleE9mKCdGaXJlZm94JykgIT09IC0xKSB7XG4gICAgICAgICAgICAgICAgc3RhdHMuZm9yRWFjaCgoc3RhdCkgPT4ge1xuXG4gICAgICAgICAgICAgICAgICAgIGxldCBqc29uID0ge307XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKChzdGF0LnR5cGUgPT09ICdpbmJvdW5kLXJ0cCcpICYmXG4gICAgICAgICAgICAgICAgICAgICAgICAoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gQXZvaWQgZmlyZWZveCBlbXB0eSBvdXRib3VuZC1ydHAgc3RhdGlzdGljc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0YXQubmFja0NvdW50ICE9PSBudWxsICYmXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhdC5pc1JlbW90ZSA9PT0gZmFsc2UgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGF0LmlkLnN0YXJ0c1dpdGgoJ2luYm91bmQnKSAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0YXQucmVtb3RlSWQuc3RhcnRzV2l0aCgnaW5ib3VuZCcpXG4gICAgICAgICAgICAgICAgICAgICAgICApKSB7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG1ldHJpY0lkID0gJ3dlYnJ0Y19pbmJvdW5kXycgKyBzdGF0Lm1lZGlhVHlwZSArICdfJyArIHN0YXQuc3NyYztcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGppdCA9IHN0YXQuaml0dGVyICogMTAwMDtcblxuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgbWV0cmljcyA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBieXRlc1JlY2VpdmVkOiAoc3RhdC5ieXRlc1JlY2VpdmVkIC0gdGhpcy5zdGF0cy5pbmJvdW5kW3N0YXQubWVkaWFUeXBlXS5ieXRlc1JlY2VpdmVkKSAvIHRoaXMuc3RhdHNJbnRlcnZhbCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBqaXR0ZXI6IGppdCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYWNrZXRzUmVjZWl2ZWQ6IChzdGF0LnBhY2tldHNSZWNlaXZlZCAtIHRoaXMuc3RhdHMuaW5ib3VuZFtzdGF0Lm1lZGlhVHlwZV0ucGFja2V0c1JlY2VpdmVkKSAvIHRoaXMuc3RhdHNJbnRlcnZhbCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYWNrZXRzTG9zdDogKHN0YXQucGFja2V0c0xvc3QgLSB0aGlzLnN0YXRzLmluYm91bmRbc3RhdC5tZWRpYVR5cGVdLnBhY2tldHNMb3N0KSAvIHRoaXMuc3RhdHNJbnRlcnZhbFxuICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHVuaXRzID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ5dGVzUmVjZWl2ZWQ6ICdieXRlcycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaml0dGVyOiAnbXMnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhY2tldHNSZWNlaXZlZDogJ3BhY2tldHMnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhY2tldHNMb3N0OiAncGFja2V0cydcbiAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoc3RhdC5tZWRpYVR5cGUgPT09ICd2aWRlbycpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXRyaWNzWydmcmFtZXNEZWNvZGVkJ10gPSAoc3RhdC5mcmFtZXNEZWNvZGVkIC0gdGhpcy5zdGF0cy5pbmJvdW5kLnZpZGVvLmZyYW1lc0RlY29kZWQpIC8gdGhpcy5zdGF0c0ludGVydmFsO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1ldHJpY3NbJ25hY2tDb3VudCddID0gKHN0YXQubmFja0NvdW50IC0gdGhpcy5zdGF0cy5pbmJvdW5kLnZpZGVvLm5hY2tDb3VudCkgLyB0aGlzLnN0YXRzSW50ZXJ2YWw7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdW5pdHNbJ2ZyYW1lc0RlY29kZWQnXSA9ICdmcmFtZXMnO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVuaXRzWyduYWNrQ291bnQnXSA9ICdwYWNrZXRzJztcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdHMuaW5ib3VuZC52aWRlby5mcmFtZXNEZWNvZGVkID0gc3RhdC5mcmFtZXNEZWNvZGVkO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdHMuaW5ib3VuZC52aWRlby5uYWNrQ291bnQgPSBzdGF0Lm5hY2tDb3VudDtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0cy5pbmJvdW5kW3N0YXQubWVkaWFUeXBlXS5ieXRlc1JlY2VpdmVkID0gc3RhdC5ieXRlc1JlY2VpdmVkO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0cy5pbmJvdW5kW3N0YXQubWVkaWFUeXBlXS5wYWNrZXRzUmVjZWl2ZWQgPSBzdGF0LnBhY2tldHNSZWNlaXZlZDtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdHMuaW5ib3VuZFtzdGF0Lm1lZGlhVHlwZV0ucGFja2V0c0xvc3QgPSBzdGF0LnBhY2tldHNMb3N0O1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBqc29uID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICdAdGltZXN0YW1wJzogbmV3IERhdGUoc3RhdC50aW1lc3RhbXApLnRvSVNPU3RyaW5nKCksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJ2V4ZWMnOiBpbnN0cnVtZW50YXRpb24uZXhlYyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAnY29tcG9uZW50JzogaW5zdHJ1bWVudGF0aW9uLmNvbXBvbmVudCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAnc3RyZWFtJzogJ3dlYlJ0YycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJ3R5cGUnOiBtZXRyaWNJZCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAnc3RyZWFtX3R5cGUnOiAnY29tcG9zZWRfbWV0cmljcycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJ3VuaXRzJzogdW5pdHNcbiAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICBqc29uW21ldHJpY0lkXSA9IG1ldHJpY3M7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIHNlbmRQb3N0KEpTT04uc3RyaW5naWZ5KGpzb24pKTtcblxuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKChzdGF0LnR5cGUgPT09ICdvdXRib3VuZC1ydHAnKSAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEF2b2lkIGZpcmVmb3ggZW1wdHkgaW5ib3VuZC1ydHAgc3RhdGlzdGljc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0YXQuaXNSZW1vdGUgPT09IGZhbHNlICYmXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhdC5pZC50b0xvd2VyQ2FzZSgpLmluY2x1ZGVzKCdvdXRib3VuZCcpXG4gICAgICAgICAgICAgICAgICAgICAgICApKSB7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG1ldHJpY0lkID0gJ3dlYnJ0Y19vdXRib3VuZF8nICsgc3RhdC5tZWRpYVR5cGUgKyAnXycgKyBzdGF0LnNzcmM7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG1ldHJpY3MgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnl0ZXNTZW50OiAoc3RhdC5ieXRlc1NlbnQgLSB0aGlzLnN0YXRzLm91dGJvdW5kW3N0YXQubWVkaWFUeXBlXS5ieXRlc1NlbnQpIC8gdGhpcy5zdGF0c0ludGVydmFsLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhY2tldHNTZW50OiAoc3RhdC5wYWNrZXRzU2VudCAtIHRoaXMuc3RhdHMub3V0Ym91bmRbc3RhdC5tZWRpYVR5cGVdLnBhY2tldHNTZW50KSAvIHRoaXMuc3RhdHNJbnRlcnZhbFxuICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHVuaXRzID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ5dGVzU2VudDogJ2J5dGVzJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYWNrZXRzU2VudDogJ3BhY2tldHMnXG4gICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHN0YXQubWVkaWFUeXBlID09PSAndmlkZW8nKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbWV0cmljc1snZnJhbWVzRW5jb2RlZCddID0gKHN0YXQuZnJhbWVzRW5jb2RlZCAtIHRoaXMuc3RhdHMub3V0Ym91bmQudmlkZW8uZnJhbWVzRW5jb2RlZCkgLyB0aGlzLnN0YXRzSW50ZXJ2YWw7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdW5pdHNbJ2ZyYW1lc0VuY29kZWQnXSA9ICdmcmFtZXMnO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0cy5vdXRib3VuZC52aWRlby5mcmFtZXNFbmNvZGVkID0gc3RhdC5mcmFtZXNFbmNvZGVkO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXRzLm91dGJvdW5kW3N0YXQubWVkaWFUeXBlXS5ieXRlc1NlbnQgPSBzdGF0LmJ5dGVzU2VudDtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdHMub3V0Ym91bmRbc3RhdC5tZWRpYVR5cGVdLnBhY2tldHNTZW50ID0gc3RhdC5wYWNrZXRzU2VudDtcblxuICAgICAgICAgICAgICAgICAgICAgICAganNvbiA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAnQHRpbWVzdGFtcCc6IG5ldyBEYXRlKHN0YXQudGltZXN0YW1wKS50b0lTT1N0cmluZygpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICdleGVjJzogaW5zdHJ1bWVudGF0aW9uLmV4ZWMsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJ2NvbXBvbmVudCc6IGluc3RydW1lbnRhdGlvbi5jb21wb25lbnQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJ3N0cmVhbSc6ICd3ZWJSdGMnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICd0eXBlJzogbWV0cmljSWQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJ3N0cmVhbV90eXBlJzogJ2NvbXBvc2VkX21ldHJpY3MnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICd1bml0cyc6IHVuaXRzXG4gICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAganNvblttZXRyaWNJZF0gPSBtZXRyaWNzO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBzZW5kUG9zdChKU09OLnN0cmluZ2lmeShqc29uKSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoKHBsYXRmb3JtLm5hbWUhLmluZGV4T2YoJ0Nocm9tZScpICE9PSAtMSkgfHwgKHBsYXRmb3JtLm5hbWUhLmluZGV4T2YoJ09wZXJhJykgIT09IC0xKSkge1xuICAgICAgICAgICAgICAgIGZvciAoY29uc3Qga2V5IG9mIE9iamVjdC5rZXlzKHN0YXRzKSkge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBzdGF0ID0gc3RhdHNba2V5XTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHN0YXQudHlwZSA9PT0gJ3NzcmMnKSB7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBqc29uID0ge307XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICgnYnl0ZXNSZWNlaXZlZCcgaW4gc3RhdCAmJiAoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKHN0YXQubWVkaWFUeXBlID09PSAnYXVkaW8nICYmICdhdWRpb091dHB1dExldmVsJyBpbiBzdGF0KSB8fFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIChzdGF0Lm1lZGlhVHlwZSA9PT0gJ3ZpZGVvJyAmJiAncXBTdW0nIGluIHN0YXQpXG4gICAgICAgICAgICAgICAgICAgICAgICApKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaW5ib3VuZC1ydHBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBtZXRyaWNJZCA9ICd3ZWJydGNfaW5ib3VuZF8nICsgc3RhdC5tZWRpYVR5cGUgKyAnXycgKyBzdGF0LnNzcmM7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBtZXRyaWNzID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBieXRlc1JlY2VpdmVkOiAoc3RhdC5ieXRlc1JlY2VpdmVkIC0gdGhpcy5zdGF0cy5pbmJvdW5kW3N0YXQubWVkaWFUeXBlXS5ieXRlc1JlY2VpdmVkKSAvIHRoaXMuc3RhdHNJbnRlcnZhbCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaml0dGVyOiBzdGF0Lmdvb2dKaXR0ZXJCdWZmZXJNcyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFja2V0c1JlY2VpdmVkOiAoc3RhdC5wYWNrZXRzUmVjZWl2ZWQgLSB0aGlzLnN0YXRzLmluYm91bmRbc3RhdC5tZWRpYVR5cGVdLnBhY2tldHNSZWNlaXZlZCkgLyB0aGlzLnN0YXRzSW50ZXJ2YWwsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhY2tldHNMb3N0OiAoc3RhdC5wYWNrZXRzTG9zdCAtIHRoaXMuc3RhdHMuaW5ib3VuZFtzdGF0Lm1lZGlhVHlwZV0ucGFja2V0c0xvc3QpIC8gdGhpcy5zdGF0c0ludGVydmFsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB1bml0cyA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnl0ZXNSZWNlaXZlZDogJ2J5dGVzJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaml0dGVyOiAnbXMnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYWNrZXRzUmVjZWl2ZWQ6ICdwYWNrZXRzJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFja2V0c0xvc3Q6ICdwYWNrZXRzJ1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHN0YXQubWVkaWFUeXBlID09PSAndmlkZW8nKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1ldHJpY3NbJ2ZyYW1lc0RlY29kZWQnXSA9IChzdGF0LmZyYW1lc0RlY29kZWQgLSB0aGlzLnN0YXRzLmluYm91bmQudmlkZW8uZnJhbWVzRGVjb2RlZCkgLyB0aGlzLnN0YXRzSW50ZXJ2YWw7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1ldHJpY3NbJ25hY2tDb3VudCddID0gKHN0YXQuZ29vZ05hY2tzU2VudCAtIHRoaXMuc3RhdHMuaW5ib3VuZC52aWRlby5uYWNrQ291bnQpIC8gdGhpcy5zdGF0c0ludGVydmFsO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1bml0c1snZnJhbWVzRGVjb2RlZCddID0gJ2ZyYW1lcyc7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVuaXRzWyduYWNrQ291bnQnXSA9ICdwYWNrZXRzJztcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXRzLmluYm91bmQudmlkZW8uZnJhbWVzRGVjb2RlZCA9IHN0YXQuZnJhbWVzRGVjb2RlZDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0cy5pbmJvdW5kLnZpZGVvLm5hY2tDb3VudCA9IHN0YXQuZ29vZ05hY2tzU2VudDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXRzLmluYm91bmRbc3RhdC5tZWRpYVR5cGVdLmJ5dGVzUmVjZWl2ZWQgPSBzdGF0LmJ5dGVzUmVjZWl2ZWQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0cy5pbmJvdW5kW3N0YXQubWVkaWFUeXBlXS5wYWNrZXRzUmVjZWl2ZWQgPSBzdGF0LnBhY2tldHNSZWNlaXZlZDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXRzLmluYm91bmRbc3RhdC5tZWRpYVR5cGVdLnBhY2tldHNMb3N0ID0gc3RhdC5wYWNrZXRzTG9zdDtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGpzb24gPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdAdGltZXN0YW1wJzogbmV3IERhdGUoc3RhdC50aW1lc3RhbXApLnRvSVNPU3RyaW5nKCksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdleGVjJzogaW5zdHJ1bWVudGF0aW9uLmV4ZWMsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdjb21wb25lbnQnOiBpbnN0cnVtZW50YXRpb24uY29tcG9uZW50LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnc3RyZWFtJzogJ3dlYlJ0YycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICd0eXBlJzogbWV0cmljSWQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdzdHJlYW1fdHlwZSc6ICdjb21wb3NlZF9tZXRyaWNzJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ3VuaXRzJzogdW5pdHNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGpzb25bbWV0cmljSWRdID0gbWV0cmljcztcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbmRQb3N0KEpTT04uc3RyaW5naWZ5KGpzb24pKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoJ2J5dGVzU2VudCcgaW4gc3RhdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIG91dGJvdW5kLXJ0cFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG1ldHJpY0lkID0gJ3dlYnJ0Y19vdXRib3VuZF8nICsgc3RhdC5tZWRpYVR5cGUgKyAnXycgKyBzdGF0LnNzcmM7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBtZXRyaWNzID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBieXRlc1NlbnQ6IChzdGF0LmJ5dGVzU2VudCAtIHRoaXMuc3RhdHMub3V0Ym91bmRbc3RhdC5tZWRpYVR5cGVdLmJ5dGVzU2VudCkgLyB0aGlzLnN0YXRzSW50ZXJ2YWwsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhY2tldHNTZW50OiAoc3RhdC5wYWNrZXRzU2VudCAtIHRoaXMuc3RhdHMub3V0Ym91bmRbc3RhdC5tZWRpYVR5cGVdLnBhY2tldHNTZW50KSAvIHRoaXMuc3RhdHNJbnRlcnZhbFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgdW5pdHMgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ5dGVzU2VudDogJ2J5dGVzJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFja2V0c1NlbnQ6ICdwYWNrZXRzJ1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHN0YXQubWVkaWFUeXBlID09PSAndmlkZW8nKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1ldHJpY3NbJ2ZyYW1lc0VuY29kZWQnXSA9IChzdGF0LmZyYW1lc0VuY29kZWQgLSB0aGlzLnN0YXRzLm91dGJvdW5kLnZpZGVvLmZyYW1lc0VuY29kZWQpIC8gdGhpcy5zdGF0c0ludGVydmFsO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1bml0c1snZnJhbWVzRW5jb2RlZCddID0gJ2ZyYW1lcyc7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0cy5vdXRib3VuZC52aWRlby5mcmFtZXNFbmNvZGVkID0gc3RhdC5mcmFtZXNFbmNvZGVkO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdHMub3V0Ym91bmRbc3RhdC5tZWRpYVR5cGVdLmJ5dGVzU2VudCA9IHN0YXQuYnl0ZXNTZW50O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdHMub3V0Ym91bmRbc3RhdC5tZWRpYVR5cGVdLnBhY2tldHNTZW50ID0gc3RhdC5wYWNrZXRzU2VudDtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGpzb24gPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdAdGltZXN0YW1wJzogbmV3IERhdGUoc3RhdC50aW1lc3RhbXApLnRvSVNPU3RyaW5nKCksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdleGVjJzogaW5zdHJ1bWVudGF0aW9uLmV4ZWMsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdjb21wb25lbnQnOiBpbnN0cnVtZW50YXRpb24uY29tcG9uZW50LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnc3RyZWFtJzogJ3dlYlJ0YycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICd0eXBlJzogbWV0cmljSWQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdzdHJlYW1fdHlwZSc6ICdjb21wb3NlZF9tZXRyaWNzJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ3VuaXRzJzogdW5pdHNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGpzb25bbWV0cmljSWRdID0gbWV0cmljcztcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbmRQb3N0KEpTT04uc3RyaW5naWZ5KGpzb24pKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcblxuICAgICAgICB0aGlzLmdldFN0YXRzQWdub3N0aWModGhpcy5zdHJlYW0uZ2V0UlRDUGVlckNvbm5lY3Rpb24oKSwgZiwgKGVycm9yKSA9PiB7IGNvbnNvbGUubG9nKGVycm9yKTsgfSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBzdGFuZGFyZGl6ZVJlcG9ydChyZXNwb25zZSkge1xuICAgICAgICBjb25zb2xlLmxvZyhyZXNwb25zZSk7XG4gICAgICAgIGNvbnN0IHN0YW5kYXJkUmVwb3J0ID0ge307XG5cbiAgICAgICAgaWYgKHBsYXRmb3JtLm5hbWUhLmluZGV4T2YoJ0ZpcmVmb3gnKSAhPT0gLTEpIHtcbiAgICAgICAgICAgIE9iamVjdC5rZXlzKHJlc3BvbnNlKS5mb3JFYWNoKGtleSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5sb2cocmVzcG9uc2Vba2V5XSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHJldHVybiByZXNwb25zZTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJlc3BvbnNlLnJlc3VsdCgpLmZvckVhY2gocmVwb3J0ID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHN0YW5kYXJkU3RhdHMgPSB7XG4gICAgICAgICAgICAgICAgaWQ6IHJlcG9ydC5pZCxcbiAgICAgICAgICAgICAgICB0aW1lc3RhbXA6IHJlcG9ydC50aW1lc3RhbXAsXG4gICAgICAgICAgICAgICAgdHlwZTogcmVwb3J0LnR5cGVcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICByZXBvcnQubmFtZXMoKS5mb3JFYWNoKChuYW1lKSA9PiB7XG4gICAgICAgICAgICAgICAgc3RhbmRhcmRTdGF0c1tuYW1lXSA9IHJlcG9ydC5zdGF0KG5hbWUpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBzdGFuZGFyZFJlcG9ydFtzdGFuZGFyZFN0YXRzLmlkXSA9IHN0YW5kYXJkU3RhdHM7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHJldHVybiBzdGFuZGFyZFJlcG9ydDtcbiAgICB9XG5cbiAgICBwcml2YXRlIGdldFN0YXRzQWdub3N0aWMocGMsIHN1Y2Nlc3NDYiwgZmFpbHVyZUNiKSB7XG4gICAgICAgIGlmIChwbGF0Zm9ybS5uYW1lIS5pbmRleE9mKCdGaXJlZm94JykgIT09IC0xKSB7XG4gICAgICAgICAgICAvLyBnZXRTdGF0cyB0YWtlcyBhcmdzIGluIGRpZmZlcmVudCBvcmRlciBpbiBDaHJvbWUgYW5kIEZpcmVmb3hcbiAgICAgICAgICAgIHJldHVybiBwYy5nZXRTdGF0cyhudWxsKS50aGVuKHJlc3BvbnNlID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCByZXBvcnQgPSB0aGlzLnN0YW5kYXJkaXplUmVwb3J0KHJlc3BvbnNlKTtcbiAgICAgICAgICAgICAgICBzdWNjZXNzQ2IocmVwb3J0KTtcbiAgICAgICAgICAgIH0pLmNhdGNoKGZhaWx1cmVDYik7XG4gICAgICAgIH0gZWxzZSBpZiAoKHBsYXRmb3JtLm5hbWUhLmluZGV4T2YoJ0Nocm9tZScpICE9PSAtMSkgfHwgKHBsYXRmb3JtLm5hbWUhLmluZGV4T2YoJ09wZXJhJykgIT09IC0xKSkge1xuICAgICAgICAgICAgLy8gSW4gQ2hyb21lLCB0aGUgZmlyc3QgdHdvIGFyZ3VtZW50cyBhcmUgcmV2ZXJzZWRcbiAgICAgICAgICAgIHJldHVybiBwYy5nZXRTdGF0cygocmVzcG9uc2UpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCByZXBvcnQgPSB0aGlzLnN0YW5kYXJkaXplUmVwb3J0KHJlc3BvbnNlKTtcbiAgICAgICAgICAgICAgICBzdWNjZXNzQ2IocmVwb3J0KTtcbiAgICAgICAgICAgIH0sIG51bGwsIGZhaWx1cmVDYik7XG4gICAgICAgIH1cbiAgICB9XG5cbn0iXX0=
diff --git a/openvidu-js-java/pom.xml b/openvidu-js-java/pom.xml
index 9cc3b8542..7a2d5402b 100644
--- a/openvidu-js-java/pom.xml
+++ b/openvidu-js-java/pom.xml
@@ -95,7 +95,7 @@
io.openvidu
openvidu-java-client
- 2.2.0
+ 2.4.0
diff --git a/openvidu-js-java/src/main/resources/static/index.html b/openvidu-js-java/src/main/resources/static/index.html
index aad0434d6..b19cc80a5 100644
--- a/openvidu-js-java/src/main/resources/static/index.html
+++ b/openvidu-js-java/src/main/resources/static/index.html
@@ -14,7 +14,7 @@
-
+
+
+
diff --git a/openvidu-mvc-node/package.json b/openvidu-mvc-node/package.json
index 289606a89..6acd79601 100644
--- a/openvidu-mvc-node/package.json
+++ b/openvidu-mvc-node/package.json
@@ -21,6 +21,6 @@
"ejs": "2.6.1",
"express": "4.16.3",
"express-session": "1.15.6",
- "openvidu-node-client": "2.2.0"
+ "openvidu-node-client": "2.4.0"
}
}
diff --git a/openvidu-mvc-node/public/openvidu-browser-2.3.0.js b/openvidu-mvc-node/public/openvidu-browser-2.3.0.js
deleted file mode 100644
index 83a78adcf..000000000
--- a/openvidu-mvc-node/public/openvidu-browser-2.3.0.js
+++ /dev/null
@@ -1,7700 +0,0 @@
-(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 1)
- er = arguments[1];
- if (er instanceof Error) {
- throw er; // Unhandled 'error' event
- } else {
- // At least give some kind of context to the user
- var err = new Error('Unhandled "error" event. (' + er + ')');
- err.context = er;
- throw err;
- }
- return false;
- }
-
- handler = events[type];
-
- if (!handler)
- return false;
-
- var isFn = typeof handler === 'function';
- len = arguments.length;
- switch (len) {
- // fast cases
- case 1:
- emitNone(handler, isFn, this);
- break;
- case 2:
- emitOne(handler, isFn, this, arguments[1]);
- break;
- case 3:
- emitTwo(handler, isFn, this, arguments[1], arguments[2]);
- break;
- case 4:
- emitThree(handler, isFn, this, arguments[1], arguments[2], arguments[3]);
- break;
- // slower
- default:
- args = new Array(len - 1);
- for (i = 1; i < len; i++)
- args[i - 1] = arguments[i];
- emitMany(handler, isFn, this, args);
- }
-
- return true;
-};
-
-function _addListener(target, type, listener, prepend) {
- var m;
- var events;
- var existing;
-
- if (typeof listener !== 'function')
- throw new TypeError('"listener" argument must be a function');
-
- events = target._events;
- if (!events) {
- events = target._events = objectCreate(null);
- target._eventsCount = 0;
- } else {
- // To avoid recursion in the case that type === "newListener"! Before
- // adding it to the listeners, first emit "newListener".
- if (events.newListener) {
- target.emit('newListener', type,
- listener.listener ? listener.listener : listener);
-
- // Re-assign `events` because a newListener handler could have caused the
- // this._events to be assigned to a new object
- events = target._events;
- }
- existing = events[type];
- }
-
- if (!existing) {
- // Optimize the case of one listener. Don't need the extra array object.
- existing = events[type] = listener;
- ++target._eventsCount;
- } else {
- if (typeof existing === 'function') {
- // Adding the second element, need to change to array.
- existing = events[type] =
- prepend ? [listener, existing] : [existing, listener];
- } else {
- // If we've already got an array, just append.
- if (prepend) {
- existing.unshift(listener);
- } else {
- existing.push(listener);
- }
- }
-
- // Check for listener leak
- if (!existing.warned) {
- m = $getMaxListeners(target);
- if (m && m > 0 && existing.length > m) {
- existing.warned = true;
- var w = new Error('Possible EventEmitter memory leak detected. ' +
- existing.length + ' "' + String(type) + '" listeners ' +
- 'added. Use emitter.setMaxListeners() to ' +
- 'increase limit.');
- w.name = 'MaxListenersExceededWarning';
- w.emitter = target;
- w.type = type;
- w.count = existing.length;
- if (typeof console === 'object' && console.warn) {
- console.warn('%s: %s', w.name, w.message);
- }
- }
- }
- }
-
- return target;
-}
-
-EventEmitter.prototype.addListener = function addListener(type, listener) {
- return _addListener(this, type, listener, false);
-};
-
-EventEmitter.prototype.on = EventEmitter.prototype.addListener;
-
-EventEmitter.prototype.prependListener =
- function prependListener(type, listener) {
- return _addListener(this, type, listener, true);
- };
-
-function onceWrapper() {
- if (!this.fired) {
- this.target.removeListener(this.type, this.wrapFn);
- this.fired = true;
- switch (arguments.length) {
- case 0:
- return this.listener.call(this.target);
- case 1:
- return this.listener.call(this.target, arguments[0]);
- case 2:
- return this.listener.call(this.target, arguments[0], arguments[1]);
- case 3:
- return this.listener.call(this.target, arguments[0], arguments[1],
- arguments[2]);
- default:
- var args = new Array(arguments.length);
- for (var i = 0; i < args.length; ++i)
- args[i] = arguments[i];
- this.listener.apply(this.target, args);
- }
- }
-}
-
-function _onceWrap(target, type, listener) {
- var state = { fired: false, wrapFn: undefined, target: target, type: type, listener: listener };
- var wrapped = bind.call(onceWrapper, state);
- wrapped.listener = listener;
- state.wrapFn = wrapped;
- return wrapped;
-}
-
-EventEmitter.prototype.once = function once(type, listener) {
- if (typeof listener !== 'function')
- throw new TypeError('"listener" argument must be a function');
- this.on(type, _onceWrap(this, type, listener));
- return this;
-};
-
-EventEmitter.prototype.prependOnceListener =
- function prependOnceListener(type, listener) {
- if (typeof listener !== 'function')
- throw new TypeError('"listener" argument must be a function');
- this.prependListener(type, _onceWrap(this, type, listener));
- return this;
- };
-
-// Emits a 'removeListener' event if and only if the listener was removed.
-EventEmitter.prototype.removeListener =
- function removeListener(type, listener) {
- var list, events, position, i, originalListener;
-
- if (typeof listener !== 'function')
- throw new TypeError('"listener" argument must be a function');
-
- events = this._events;
- if (!events)
- return this;
-
- list = events[type];
- if (!list)
- return this;
-
- if (list === listener || list.listener === listener) {
- if (--this._eventsCount === 0)
- this._events = objectCreate(null);
- else {
- delete events[type];
- if (events.removeListener)
- this.emit('removeListener', type, list.listener || listener);
- }
- } else if (typeof list !== 'function') {
- position = -1;
-
- for (i = list.length - 1; i >= 0; i--) {
- if (list[i] === listener || list[i].listener === listener) {
- originalListener = list[i].listener;
- position = i;
- break;
- }
- }
-
- if (position < 0)
- return this;
-
- if (position === 0)
- list.shift();
- else
- spliceOne(list, position);
-
- if (list.length === 1)
- events[type] = list[0];
-
- if (events.removeListener)
- this.emit('removeListener', type, originalListener || listener);
- }
-
- return this;
- };
-
-EventEmitter.prototype.removeAllListeners =
- function removeAllListeners(type) {
- var listeners, events, i;
-
- events = this._events;
- if (!events)
- return this;
-
- // not listening for removeListener, no need to emit
- if (!events.removeListener) {
- if (arguments.length === 0) {
- this._events = objectCreate(null);
- this._eventsCount = 0;
- } else if (events[type]) {
- if (--this._eventsCount === 0)
- this._events = objectCreate(null);
- else
- delete events[type];
- }
- return this;
- }
-
- // emit removeListener for all listeners on all events
- if (arguments.length === 0) {
- var keys = objectKeys(events);
- var key;
- for (i = 0; i < keys.length; ++i) {
- key = keys[i];
- if (key === 'removeListener') continue;
- this.removeAllListeners(key);
- }
- this.removeAllListeners('removeListener');
- this._events = objectCreate(null);
- this._eventsCount = 0;
- return this;
- }
-
- listeners = events[type];
-
- if (typeof listeners === 'function') {
- this.removeListener(type, listeners);
- } else if (listeners) {
- // LIFO order
- for (i = listeners.length - 1; i >= 0; i--) {
- this.removeListener(type, listeners[i]);
- }
- }
-
- return this;
- };
-
-function _listeners(target, type, unwrap) {
- var events = target._events;
-
- if (!events)
- return [];
-
- var evlistener = events[type];
- if (!evlistener)
- return [];
-
- if (typeof evlistener === 'function')
- return unwrap ? [evlistener.listener || evlistener] : [evlistener];
-
- return unwrap ? unwrapListeners(evlistener) : arrayClone(evlistener, evlistener.length);
-}
-
-EventEmitter.prototype.listeners = function listeners(type) {
- return _listeners(this, type, true);
-};
-
-EventEmitter.prototype.rawListeners = function rawListeners(type) {
- return _listeners(this, type, false);
-};
-
-EventEmitter.listenerCount = function(emitter, type) {
- if (typeof emitter.listenerCount === 'function') {
- return emitter.listenerCount(type);
- } else {
- return listenerCount.call(emitter, type);
- }
-};
-
-EventEmitter.prototype.listenerCount = listenerCount;
-function listenerCount(type) {
- var events = this._events;
-
- if (events) {
- var evlistener = events[type];
-
- if (typeof evlistener === 'function') {
- return 1;
- } else if (evlistener) {
- return evlistener.length;
- }
- }
-
- return 0;
-}
-
-EventEmitter.prototype.eventNames = function eventNames() {
- return this._eventsCount > 0 ? Reflect.ownKeys(this._events) : [];
-};
-
-// About 1.5x faster than the two-arg version of Array#splice().
-function spliceOne(list, index) {
- for (var i = index, k = i + 1, n = list.length; k < n; i += 1, k += 1)
- list[i] = list[k];
- list.pop();
-}
-
-function arrayClone(arr, n) {
- var copy = new Array(n);
- for (var i = 0; i < n; ++i)
- copy[i] = arr[i];
- return copy;
-}
-
-function unwrapListeners(arr) {
- var ret = new Array(arr.length);
- for (var i = 0; i < ret.length; ++i) {
- ret[i] = arr[i].listener || arr[i];
- }
- return ret;
-}
-
-function objectCreatePolyfill(proto) {
- var F = function() {};
- F.prototype = proto;
- return new F;
-}
-function objectKeysPolyfill(obj) {
- var keys = [];
- for (var k in obj) if (Object.prototype.hasOwnProperty.call(obj, k)) {
- keys.push(k);
- }
- return k;
-}
-function functionBindPolyfill(context) {
- var fn = this;
- return function () {
- return fn.apply(context, arguments);
- };
-}
-
-},{}],2:[function(require,module,exports){
-/* jshint node: true */
-'use strict';
-
-var normalice = require('normalice');
-
-/**
- # freeice
-
- The `freeice` module is a simple way of getting random STUN or TURN server
- for your WebRTC application. The list of servers (just STUN at this stage)
- were sourced from this [gist](https://gist.github.com/zziuni/3741933).
-
- ## Example Use
-
- The following demonstrates how you can use `freeice` with
- [rtc-quickconnect](https://github.com/rtc-io/rtc-quickconnect):
-
- <<< examples/quickconnect.js
-
- As the `freeice` module generates ice servers in a list compliant with the
- WebRTC spec you will be able to use it with raw `RTCPeerConnection`
- constructors and other WebRTC libraries.
-
- ## Hey, don't use my STUN/TURN server!
-
- If for some reason your free STUN or TURN server ends up in the
- list of servers ([stun](https://github.com/DamonOehlman/freeice/blob/master/stun.json) or
- [turn](https://github.com/DamonOehlman/freeice/blob/master/turn.json))
- that is used in this module, you can feel
- free to open an issue on this repository and those servers will be removed
- within 24 hours (or sooner). This is the quickest and probably the most
- polite way to have something removed (and provides us some visibility
- if someone opens a pull request requesting that a server is added).
-
- ## Please add my server!
-
- If you have a server that you wish to add to the list, that's awesome! I'm
- sure I speak on behalf of a whole pile of WebRTC developers who say thanks.
- To get it into the list, feel free to either open a pull request or if you
- find that process a bit daunting then just create an issue requesting
- the addition of the server (make sure you provide all the details, and if
- you have a Terms of Service then including that in the PR/issue would be
- awesome).
-
- ## I know of a free server, can I add it?
-
- Sure, if you do your homework and make sure it is ok to use (I'm currently
- in the process of reviewing the terms of those STUN servers included from
- the original list). If it's ok to go, then please see the previous entry
- for how to add it.
-
- ## Current List of Servers
-
- * current as at the time of last `README.md` file generation
-
- ### STUN
-
- <<< stun.json
-
- ### TURN
-
- <<< turn.json
-
-**/
-
-var freeice = module.exports = function(opts) {
- // if a list of servers has been provided, then use it instead of defaults
- var servers = {
- stun: (opts || {}).stun || require('./stun.json'),
- turn: (opts || {}).turn || require('./turn.json')
- };
-
- var stunCount = (opts || {}).stunCount || 2;
- var turnCount = (opts || {}).turnCount || 0;
- var selected;
-
- function getServers(type, count) {
- var out = [];
- var input = [].concat(servers[type]);
- var idx;
-
- while (input.length && out.length < count) {
- idx = (Math.random() * input.length) | 0;
- out = out.concat(input.splice(idx, 1));
- }
-
- return out.map(function(url) {
- //If it's a not a string, don't try to "normalice" it otherwise using type:url will screw it up
- if ((typeof url !== 'string') && (! (url instanceof String))) {
- return url;
- } else {
- return normalice(type + ':' + url);
- }
- });
- }
-
- // add stun servers
- selected = [].concat(getServers('stun', stunCount));
-
- if (turnCount) {
- selected = selected.concat(getServers('turn', turnCount));
- }
-
- return selected;
-};
-
-},{"./stun.json":3,"./turn.json":4,"normalice":7}],3:[function(require,module,exports){
-module.exports=[
- "stun.l.google.com:19302",
- "stun1.l.google.com:19302",
- "stun2.l.google.com:19302",
- "stun3.l.google.com:19302",
- "stun4.l.google.com:19302",
- "stun.ekiga.net",
- "stun.ideasip.com",
- "stun.schlund.de",
- "stun.stunprotocol.org:3478",
- "stun.voiparound.com",
- "stun.voipbuster.com",
- "stun.voipstunt.com",
- "stun.voxgratia.org",
- "stun.services.mozilla.com"
-]
-
-},{}],4:[function(require,module,exports){
-module.exports=[]
-
-},{}],5:[function(require,module,exports){
-var WildEmitter = require('wildemitter');
-
-function getMaxVolume (analyser, fftBins) {
- var maxVolume = -Infinity;
- analyser.getFloatFrequencyData(fftBins);
-
- for(var i=4, ii=fftBins.length; i < ii; i++) {
- if (fftBins[i] > maxVolume && fftBins[i] < 0) {
- maxVolume = fftBins[i];
- }
- };
-
- return maxVolume;
-}
-
-
-var audioContextType;
-if (typeof window !== 'undefined') {
- audioContextType = window.AudioContext || window.webkitAudioContext;
-}
-// use a single audio context due to hardware limits
-var audioContext = null;
-module.exports = function(stream, options) {
- var harker = new WildEmitter();
-
-
- // make it not break in non-supported browsers
- if (!audioContextType) return harker;
-
- //Config
- var options = options || {},
- smoothing = (options.smoothing || 0.1),
- interval = (options.interval || 50),
- threshold = options.threshold,
- play = options.play,
- history = options.history || 10,
- running = true;
-
- //Setup Audio Context
- if (!audioContext) {
- audioContext = new audioContextType();
- }
- var sourceNode, fftBins, analyser;
-
- analyser = audioContext.createAnalyser();
- analyser.fftSize = 512;
- analyser.smoothingTimeConstant = smoothing;
- fftBins = new Float32Array(analyser.frequencyBinCount);
-
- if (stream.jquery) stream = stream[0];
- if (stream instanceof HTMLAudioElement || stream instanceof HTMLVideoElement) {
- //Audio Tag
- sourceNode = audioContext.createMediaElementSource(stream);
- if (typeof play === 'undefined') play = true;
- threshold = threshold || -50;
- } else {
- //WebRTC Stream
- sourceNode = audioContext.createMediaStreamSource(stream);
- threshold = threshold || -50;
- }
-
- sourceNode.connect(analyser);
- if (play) analyser.connect(audioContext.destination);
-
- harker.speaking = false;
-
- harker.suspend = function() {
- audioContext.suspend();
- }
- harker.resume = function() {
- audioContext.resume();
- }
- Object.defineProperty(harker, 'state', { get: function() {
- return audioContext.state;
- }});
- audioContext.onstatechange = function() {
- harker.emit('state_change', audioContext.state);
- }
-
- harker.setThreshold = function(t) {
- threshold = t;
- };
-
- harker.setInterval = function(i) {
- interval = i;
- };
-
- harker.stop = function() {
- running = false;
- harker.emit('volume_change', -100, threshold);
- if (harker.speaking) {
- harker.speaking = false;
- harker.emit('stopped_speaking');
- }
- analyser.disconnect();
- sourceNode.disconnect();
- };
- harker.speakingHistory = [];
- for (var i = 0; i < history; i++) {
- harker.speakingHistory.push(0);
- }
-
- // Poll the analyser node to determine if speaking
- // and emit events if changed
- var looper = function() {
- setTimeout(function() {
-
- //check if stop has been called
- if(!running) {
- return;
- }
-
- var currentVolume = getMaxVolume(analyser, fftBins);
-
- harker.emit('volume_change', currentVolume, threshold);
-
- var history = 0;
- if (currentVolume > threshold && !harker.speaking) {
- // trigger quickly, short history
- for (var i = harker.speakingHistory.length - 3; i < harker.speakingHistory.length; i++) {
- history += harker.speakingHistory[i];
- }
- if (history >= 2) {
- harker.speaking = true;
- harker.emit('speaking');
- }
- } else if (currentVolume < threshold && harker.speaking) {
- for (var i = 0; i < harker.speakingHistory.length; i++) {
- history += harker.speakingHistory[i];
- }
- if (history == 0) {
- harker.speaking = false;
- harker.emit('stopped_speaking');
- }
- }
- harker.speakingHistory.shift();
- harker.speakingHistory.push(0 + (currentVolume > threshold));
-
- looper();
- }, interval);
- };
- looper();
-
-
- return harker;
-}
-
-},{"wildemitter":14}],6:[function(require,module,exports){
-if (typeof Object.create === 'function') {
- // implementation from standard node.js 'util' module
- module.exports = function inherits(ctor, superCtor) {
- ctor.super_ = superCtor
- ctor.prototype = Object.create(superCtor.prototype, {
- constructor: {
- value: ctor,
- enumerable: false,
- writable: true,
- configurable: true
- }
- });
- };
-} else {
- // old school shim for old browsers
- module.exports = function inherits(ctor, superCtor) {
- ctor.super_ = superCtor
- var TempCtor = function () {}
- TempCtor.prototype = superCtor.prototype
- ctor.prototype = new TempCtor()
- ctor.prototype.constructor = ctor
- }
-}
-
-},{}],7:[function(require,module,exports){
-/**
- # normalice
-
- Normalize an ice server configuration object (or plain old string) into a format
- that is usable in all browsers supporting WebRTC. Primarily this module is designed
- to help with the transition of the `url` attribute of the configuration object to
- the `urls` attribute.
-
- ## Example Usage
-
- <<< examples/simple.js
-
-**/
-
-var protocols = [
- 'stun:',
- 'turn:'
-];
-
-module.exports = function(input) {
- var url = (input || {}).url || input;
- var protocol;
- var parts;
- var output = {};
-
- // if we don't have a string url, then allow the input to passthrough
- if (typeof url != 'string' && (! (url instanceof String))) {
- return input;
- }
-
- // trim the url string, and convert to an array
- url = url.trim();
-
- // if the protocol is not known, then passthrough
- protocol = protocols[protocols.indexOf(url.slice(0, 5))];
- if (! protocol) {
- return input;
- }
-
- // now let's attack the remaining url parts
- url = url.slice(5);
- parts = url.split('@');
-
- output.username = input.username;
- output.credential = input.credential;
- // if we have an authentication part, then set the credentials
- if (parts.length > 1) {
- url = parts[1];
- parts = parts[0].split(':');
-
- // add the output credential and username
- output.username = parts[0];
- output.credential = (input || {}).credential || parts[1] || '';
- }
-
- output.url = protocol + url;
- output.urls = [ output.url ];
-
- return output;
-};
-
-},{}],8:[function(require,module,exports){
-(function (global){
-/*!
- * Platform.js
- * Copyright 2014-2018 Benjamin Tan
- * Copyright 2011-2013 John-David Dalton
- * Available under MIT license
- */
-;(function() {
- 'use strict';
-
- /** Used to determine if values are of the language type `Object`. */
- var objectTypes = {
- 'function': true,
- 'object': true
- };
-
- /** Used as a reference to the global object. */
- var root = (objectTypes[typeof window] && window) || this;
-
- /** Backup possible global object. */
- var oldRoot = root;
-
- /** Detect free variable `exports`. */
- var freeExports = objectTypes[typeof exports] && exports;
-
- /** Detect free variable `module`. */
- var freeModule = objectTypes[typeof module] && module && !module.nodeType && module;
-
- /** Detect free variable `global` from Node.js or Browserified code and use it as `root`. */
- var freeGlobal = freeExports && freeModule && typeof global == 'object' && global;
- if (freeGlobal && (freeGlobal.global === freeGlobal || freeGlobal.window === freeGlobal || freeGlobal.self === freeGlobal)) {
- root = freeGlobal;
- }
-
- /**
- * Used as the maximum length of an array-like object.
- * See the [ES6 spec](http://people.mozilla.org/~jorendorff/es6-draft.html#sec-tolength)
- * for more details.
- */
- var maxSafeInteger = Math.pow(2, 53) - 1;
-
- /** Regular expression to detect Opera. */
- var reOpera = /\bOpera/;
-
- /** Possible global object. */
- var thisBinding = this;
-
- /** Used for native method references. */
- var objectProto = Object.prototype;
-
- /** Used to check for own properties of an object. */
- var hasOwnProperty = objectProto.hasOwnProperty;
-
- /** Used to resolve the internal `[[Class]]` of values. */
- var toString = objectProto.toString;
-
- /*--------------------------------------------------------------------------*/
-
- /**
- * Capitalizes a string value.
- *
- * @private
- * @param {string} string The string to capitalize.
- * @returns {string} The capitalized string.
- */
- function capitalize(string) {
- string = String(string);
- return string.charAt(0).toUpperCase() + string.slice(1);
- }
-
- /**
- * A utility function to clean up the OS name.
- *
- * @private
- * @param {string} os The OS name to clean up.
- * @param {string} [pattern] A `RegExp` pattern matching the OS name.
- * @param {string} [label] A label for the OS.
- */
- function cleanupOS(os, pattern, label) {
- // Platform tokens are defined at:
- // http://msdn.microsoft.com/en-us/library/ms537503(VS.85).aspx
- // http://web.archive.org/web/20081122053950/http://msdn.microsoft.com/en-us/library/ms537503(VS.85).aspx
- var data = {
- '10.0': '10',
- '6.4': '10 Technical Preview',
- '6.3': '8.1',
- '6.2': '8',
- '6.1': 'Server 2008 R2 / 7',
- '6.0': 'Server 2008 / Vista',
- '5.2': 'Server 2003 / XP 64-bit',
- '5.1': 'XP',
- '5.01': '2000 SP1',
- '5.0': '2000',
- '4.0': 'NT',
- '4.90': 'ME'
- };
- // Detect Windows version from platform tokens.
- if (pattern && label && /^Win/i.test(os) && !/^Windows Phone /i.test(os) &&
- (data = data[/[\d.]+$/.exec(os)])) {
- os = 'Windows ' + data;
- }
- // Correct character case and cleanup string.
- os = String(os);
-
- if (pattern && label) {
- os = os.replace(RegExp(pattern, 'i'), label);
- }
-
- os = format(
- os.replace(/ ce$/i, ' CE')
- .replace(/\bhpw/i, 'web')
- .replace(/\bMacintosh\b/, 'Mac OS')
- .replace(/_PowerPC\b/i, ' OS')
- .replace(/\b(OS X) [^ \d]+/i, '$1')
- .replace(/\bMac (OS X)\b/, '$1')
- .replace(/\/(\d)/, ' $1')
- .replace(/_/g, '.')
- .replace(/(?: BePC|[ .]*fc[ \d.]+)$/i, '')
- .replace(/\bx86\.64\b/gi, 'x86_64')
- .replace(/\b(Windows Phone) OS\b/, '$1')
- .replace(/\b(Chrome OS \w+) [\d.]+\b/, '$1')
- .split(' on ')[0]
- );
-
- return os;
- }
-
- /**
- * An iteration utility for arrays and objects.
- *
- * @private
- * @param {Array|Object} object The object to iterate over.
- * @param {Function} callback The function called per iteration.
- */
- function each(object, callback) {
- var index = -1,
- length = object ? object.length : 0;
-
- if (typeof length == 'number' && length > -1 && length <= maxSafeInteger) {
- while (++index < length) {
- callback(object[index], index, object);
- }
- } else {
- forOwn(object, callback);
- }
- }
-
- /**
- * Trim and conditionally capitalize string values.
- *
- * @private
- * @param {string} string The string to format.
- * @returns {string} The formatted string.
- */
- function format(string) {
- string = trim(string);
- return /^(?:webOS|i(?:OS|P))/.test(string)
- ? string
- : capitalize(string);
- }
-
- /**
- * Iterates over an object's own properties, executing the `callback` for each.
- *
- * @private
- * @param {Object} object The object to iterate over.
- * @param {Function} callback The function executed per own property.
- */
- function forOwn(object, callback) {
- for (var key in object) {
- if (hasOwnProperty.call(object, key)) {
- callback(object[key], key, object);
- }
- }
- }
-
- /**
- * Gets the internal `[[Class]]` of a value.
- *
- * @private
- * @param {*} value The value.
- * @returns {string} The `[[Class]]`.
- */
- function getClassOf(value) {
- return value == null
- ? capitalize(value)
- : toString.call(value).slice(8, -1);
- }
-
- /**
- * Host objects can return type values that are different from their actual
- * data type. The objects we are concerned with usually return non-primitive
- * types of "object", "function", or "unknown".
- *
- * @private
- * @param {*} object The owner of the property.
- * @param {string} property The property to check.
- * @returns {boolean} Returns `true` if the property value is a non-primitive, else `false`.
- */
- function isHostType(object, property) {
- var type = object != null ? typeof object[property] : 'number';
- return !/^(?:boolean|number|string|undefined)$/.test(type) &&
- (type == 'object' ? !!object[property] : true);
- }
-
- /**
- * Prepares a string for use in a `RegExp` by making hyphens and spaces optional.
- *
- * @private
- * @param {string} string The string to qualify.
- * @returns {string} The qualified string.
- */
- function qualify(string) {
- return String(string).replace(/([ -])(?!$)/g, '$1?');
- }
-
- /**
- * A bare-bones `Array#reduce` like utility function.
- *
- * @private
- * @param {Array} array The array to iterate over.
- * @param {Function} callback The function called per iteration.
- * @returns {*} The accumulated result.
- */
- function reduce(array, callback) {
- var accumulator = null;
- each(array, function(value, index) {
- accumulator = callback(accumulator, value, index, array);
- });
- return accumulator;
- }
-
- /**
- * Removes leading and trailing whitespace from a string.
- *
- * @private
- * @param {string} string The string to trim.
- * @returns {string} The trimmed string.
- */
- function trim(string) {
- return String(string).replace(/^ +| +$/g, '');
- }
-
- /*--------------------------------------------------------------------------*/
-
- /**
- * Creates a new platform object.
- *
- * @memberOf platform
- * @param {Object|string} [ua=navigator.userAgent] The user agent string or
- * context object.
- * @returns {Object} A platform object.
- */
- function parse(ua) {
-
- /** The environment context object. */
- var context = root;
-
- /** Used to flag when a custom context is provided. */
- var isCustomContext = ua && typeof ua == 'object' && getClassOf(ua) != 'String';
-
- // Juggle arguments.
- if (isCustomContext) {
- context = ua;
- ua = null;
- }
-
- /** Browser navigator object. */
- var nav = context.navigator || {};
-
- /** Browser user agent string. */
- var userAgent = nav.userAgent || '';
-
- ua || (ua = userAgent);
-
- /** Used to flag when `thisBinding` is the [ModuleScope]. */
- var isModuleScope = isCustomContext || thisBinding == oldRoot;
-
- /** Used to detect if browser is like Chrome. */
- var likeChrome = isCustomContext
- ? !!nav.likeChrome
- : /\bChrome\b/.test(ua) && !/internal|\n/i.test(toString.toString());
-
- /** Internal `[[Class]]` value shortcuts. */
- var objectClass = 'Object',
- airRuntimeClass = isCustomContext ? objectClass : 'ScriptBridgingProxyObject',
- enviroClass = isCustomContext ? objectClass : 'Environment',
- javaClass = (isCustomContext && context.java) ? 'JavaPackage' : getClassOf(context.java),
- phantomClass = isCustomContext ? objectClass : 'RuntimeObject';
-
- /** Detect Java environments. */
- var java = /\bJava/.test(javaClass) && context.java;
-
- /** Detect Rhino. */
- var rhino = java && getClassOf(context.environment) == enviroClass;
-
- /** A character to represent alpha. */
- var alpha = java ? 'a' : '\u03b1';
-
- /** A character to represent beta. */
- var beta = java ? 'b' : '\u03b2';
-
- /** Browser document object. */
- var doc = context.document || {};
-
- /**
- * Detect Opera browser (Presto-based).
- * http://www.howtocreate.co.uk/operaStuff/operaObject.html
- * http://dev.opera.com/articles/view/opera-mini-web-content-authoring-guidelines/#operamini
- */
- var opera = context.operamini || context.opera;
-
- /** Opera `[[Class]]`. */
- var operaClass = reOpera.test(operaClass = (isCustomContext && opera) ? opera['[[Class]]'] : getClassOf(opera))
- ? operaClass
- : (opera = null);
-
- /*------------------------------------------------------------------------*/
-
- /** Temporary variable used over the script's lifetime. */
- var data;
-
- /** The CPU architecture. */
- var arch = ua;
-
- /** Platform description array. */
- var description = [];
-
- /** Platform alpha/beta indicator. */
- var prerelease = null;
-
- /** A flag to indicate that environment features should be used to resolve the platform. */
- var useFeatures = ua == userAgent;
-
- /** The browser/environment version. */
- var version = useFeatures && opera && typeof opera.version == 'function' && opera.version();
-
- /** A flag to indicate if the OS ends with "/ Version" */
- var isSpecialCasedOS;
-
- /* Detectable layout engines (order is important). */
- var layout = getLayout([
- { 'label': 'EdgeHTML', 'pattern': 'Edge' },
- 'Trident',
- { 'label': 'WebKit', 'pattern': 'AppleWebKit' },
- 'iCab',
- 'Presto',
- 'NetFront',
- 'Tasman',
- 'KHTML',
- 'Gecko'
- ]);
-
- /* Detectable browser names (order is important). */
- var name = getName([
- 'Adobe AIR',
- 'Arora',
- 'Avant Browser',
- 'Breach',
- 'Camino',
- 'Electron',
- 'Epiphany',
- 'Fennec',
- 'Flock',
- 'Galeon',
- 'GreenBrowser',
- 'iCab',
- 'Iceweasel',
- 'K-Meleon',
- 'Konqueror',
- 'Lunascape',
- 'Maxthon',
- { 'label': 'Microsoft Edge', 'pattern': 'Edge' },
- 'Midori',
- 'Nook Browser',
- 'PaleMoon',
- 'PhantomJS',
- 'Raven',
- 'Rekonq',
- 'RockMelt',
- { 'label': 'Samsung Internet', 'pattern': 'SamsungBrowser' },
- 'SeaMonkey',
- { 'label': 'Silk', 'pattern': '(?:Cloud9|Silk-Accelerated)' },
- 'Sleipnir',
- 'SlimBrowser',
- { 'label': 'SRWare Iron', 'pattern': 'Iron' },
- 'Sunrise',
- 'Swiftfox',
- 'Waterfox',
- 'WebPositive',
- 'Opera Mini',
- { 'label': 'Opera Mini', 'pattern': 'OPiOS' },
- 'Opera',
- { 'label': 'Opera', 'pattern': 'OPR' },
- 'Chrome',
- { 'label': 'Chrome Mobile', 'pattern': '(?:CriOS|CrMo)' },
- { 'label': 'Firefox', 'pattern': '(?:Firefox|Minefield)' },
- { 'label': 'Firefox for iOS', 'pattern': 'FxiOS' },
- { 'label': 'IE', 'pattern': 'IEMobile' },
- { 'label': 'IE', 'pattern': 'MSIE' },
- 'Safari'
- ]);
-
- /* Detectable products (order is important). */
- var product = getProduct([
- { 'label': 'BlackBerry', 'pattern': 'BB10' },
- 'BlackBerry',
- { 'label': 'Galaxy S', 'pattern': 'GT-I9000' },
- { 'label': 'Galaxy S2', 'pattern': 'GT-I9100' },
- { 'label': 'Galaxy S3', 'pattern': 'GT-I9300' },
- { 'label': 'Galaxy S4', 'pattern': 'GT-I9500' },
- { 'label': 'Galaxy S5', 'pattern': 'SM-G900' },
- { 'label': 'Galaxy S6', 'pattern': 'SM-G920' },
- { 'label': 'Galaxy S6 Edge', 'pattern': 'SM-G925' },
- { 'label': 'Galaxy S7', 'pattern': 'SM-G930' },
- { 'label': 'Galaxy S7 Edge', 'pattern': 'SM-G935' },
- 'Google TV',
- 'Lumia',
- 'iPad',
- 'iPod',
- 'iPhone',
- 'Kindle',
- { 'label': 'Kindle Fire', 'pattern': '(?:Cloud9|Silk-Accelerated)' },
- 'Nexus',
- 'Nook',
- 'PlayBook',
- 'PlayStation Vita',
- 'PlayStation',
- 'TouchPad',
- 'Transformer',
- { 'label': 'Wii U', 'pattern': 'WiiU' },
- 'Wii',
- 'Xbox One',
- { 'label': 'Xbox 360', 'pattern': 'Xbox' },
- 'Xoom'
- ]);
-
- /* Detectable manufacturers. */
- var manufacturer = getManufacturer({
- 'Apple': { 'iPad': 1, 'iPhone': 1, 'iPod': 1 },
- 'Archos': {},
- 'Amazon': { 'Kindle': 1, 'Kindle Fire': 1 },
- 'Asus': { 'Transformer': 1 },
- 'Barnes & Noble': { 'Nook': 1 },
- 'BlackBerry': { 'PlayBook': 1 },
- 'Google': { 'Google TV': 1, 'Nexus': 1 },
- 'HP': { 'TouchPad': 1 },
- 'HTC': {},
- 'LG': {},
- 'Microsoft': { 'Xbox': 1, 'Xbox One': 1 },
- 'Motorola': { 'Xoom': 1 },
- 'Nintendo': { 'Wii U': 1, 'Wii': 1 },
- 'Nokia': { 'Lumia': 1 },
- 'Samsung': { 'Galaxy S': 1, 'Galaxy S2': 1, 'Galaxy S3': 1, 'Galaxy S4': 1 },
- 'Sony': { 'PlayStation': 1, 'PlayStation Vita': 1 }
- });
-
- /* Detectable operating systems (order is important). */
- var os = getOS([
- 'Windows Phone',
- 'Android',
- 'CentOS',
- { 'label': 'Chrome OS', 'pattern': 'CrOS' },
- 'Debian',
- 'Fedora',
- 'FreeBSD',
- 'Gentoo',
- 'Haiku',
- 'Kubuntu',
- 'Linux Mint',
- 'OpenBSD',
- 'Red Hat',
- 'SuSE',
- 'Ubuntu',
- 'Xubuntu',
- 'Cygwin',
- 'Symbian OS',
- 'hpwOS',
- 'webOS ',
- 'webOS',
- 'Tablet OS',
- 'Tizen',
- 'Linux',
- 'Mac OS X',
- 'Macintosh',
- 'Mac',
- 'Windows 98;',
- 'Windows '
- ]);
-
- /*------------------------------------------------------------------------*/
-
- /**
- * Picks the layout engine from an array of guesses.
- *
- * @private
- * @param {Array} guesses An array of guesses.
- * @returns {null|string} The detected layout engine.
- */
- function getLayout(guesses) {
- return reduce(guesses, function(result, guess) {
- return result || RegExp('\\b' + (
- guess.pattern || qualify(guess)
- ) + '\\b', 'i').exec(ua) && (guess.label || guess);
- });
- }
-
- /**
- * Picks the manufacturer from an array of guesses.
- *
- * @private
- * @param {Array} guesses An object of guesses.
- * @returns {null|string} The detected manufacturer.
- */
- function getManufacturer(guesses) {
- return reduce(guesses, function(result, value, key) {
- // Lookup the manufacturer by product or scan the UA for the manufacturer.
- return result || (
- value[product] ||
- value[/^[a-z]+(?: +[a-z]+\b)*/i.exec(product)] ||
- RegExp('\\b' + qualify(key) + '(?:\\b|\\w*\\d)', 'i').exec(ua)
- ) && key;
- });
- }
-
- /**
- * Picks the browser name from an array of guesses.
- *
- * @private
- * @param {Array} guesses An array of guesses.
- * @returns {null|string} The detected browser name.
- */
- function getName(guesses) {
- return reduce(guesses, function(result, guess) {
- return result || RegExp('\\b' + (
- guess.pattern || qualify(guess)
- ) + '\\b', 'i').exec(ua) && (guess.label || guess);
- });
- }
-
- /**
- * Picks the OS name from an array of guesses.
- *
- * @private
- * @param {Array} guesses An array of guesses.
- * @returns {null|string} The detected OS name.
- */
- function getOS(guesses) {
- return reduce(guesses, function(result, guess) {
- var pattern = guess.pattern || qualify(guess);
- if (!result && (result =
- RegExp('\\b' + pattern + '(?:/[\\d.]+|[ \\w.]*)', 'i').exec(ua)
- )) {
- result = cleanupOS(result, pattern, guess.label || guess);
- }
- return result;
- });
- }
-
- /**
- * Picks the product name from an array of guesses.
- *
- * @private
- * @param {Array} guesses An array of guesses.
- * @returns {null|string} The detected product name.
- */
- function getProduct(guesses) {
- return reduce(guesses, function(result, guess) {
- var pattern = guess.pattern || qualify(guess);
- if (!result && (result =
- RegExp('\\b' + pattern + ' *\\d+[.\\w_]*', 'i').exec(ua) ||
- RegExp('\\b' + pattern + ' *\\w+-[\\w]*', 'i').exec(ua) ||
- RegExp('\\b' + pattern + '(?:; *(?:[a-z]+[_-])?[a-z]+\\d+|[^ ();-]*)', 'i').exec(ua)
- )) {
- // Split by forward slash and append product version if needed.
- if ((result = String((guess.label && !RegExp(pattern, 'i').test(guess.label)) ? guess.label : result).split('/'))[1] && !/[\d.]+/.test(result[0])) {
- result[0] += ' ' + result[1];
- }
- // Correct character case and cleanup string.
- guess = guess.label || guess;
- result = format(result[0]
- .replace(RegExp(pattern, 'i'), guess)
- .replace(RegExp('; *(?:' + guess + '[_-])?', 'i'), ' ')
- .replace(RegExp('(' + guess + ')[-_.]?(\\w)', 'i'), '$1 $2'));
- }
- return result;
- });
- }
-
- /**
- * Resolves the version using an array of UA patterns.
- *
- * @private
- * @param {Array} patterns An array of UA patterns.
- * @returns {null|string} The detected version.
- */
- function getVersion(patterns) {
- return reduce(patterns, function(result, pattern) {
- return result || (RegExp(pattern +
- '(?:-[\\d.]+/|(?: for [\\w-]+)?[ /-])([\\d.]+[^ ();/_-]*)', 'i').exec(ua) || 0)[1] || null;
- });
- }
-
- /**
- * Returns `platform.description` when the platform object is coerced to a string.
- *
- * @name toString
- * @memberOf platform
- * @returns {string} Returns `platform.description` if available, else an empty string.
- */
- function toStringPlatform() {
- return this.description || '';
- }
-
- /*------------------------------------------------------------------------*/
-
- // Convert layout to an array so we can add extra details.
- layout && (layout = [layout]);
-
- // Detect product names that contain their manufacturer's name.
- if (manufacturer && !product) {
- product = getProduct([manufacturer]);
- }
- // Clean up Google TV.
- if ((data = /\bGoogle TV\b/.exec(product))) {
- product = data[0];
- }
- // Detect simulators.
- if (/\bSimulator\b/i.test(ua)) {
- product = (product ? product + ' ' : '') + 'Simulator';
- }
- // Detect Opera Mini 8+ running in Turbo/Uncompressed mode on iOS.
- if (name == 'Opera Mini' && /\bOPiOS\b/.test(ua)) {
- description.push('running in Turbo/Uncompressed mode');
- }
- // Detect IE Mobile 11.
- if (name == 'IE' && /\blike iPhone OS\b/.test(ua)) {
- data = parse(ua.replace(/like iPhone OS/, ''));
- manufacturer = data.manufacturer;
- product = data.product;
- }
- // Detect iOS.
- else if (/^iP/.test(product)) {
- name || (name = 'Safari');
- os = 'iOS' + ((data = / OS ([\d_]+)/i.exec(ua))
- ? ' ' + data[1].replace(/_/g, '.')
- : '');
- }
- // Detect Kubuntu.
- else if (name == 'Konqueror' && !/buntu/i.test(os)) {
- os = 'Kubuntu';
- }
- // Detect Android browsers.
- else if ((manufacturer && manufacturer != 'Google' &&
- ((/Chrome/.test(name) && !/\bMobile Safari\b/i.test(ua)) || /\bVita\b/.test(product))) ||
- (/\bAndroid\b/.test(os) && /^Chrome/.test(name) && /\bVersion\//i.test(ua))) {
- name = 'Android Browser';
- os = /\bAndroid\b/.test(os) ? os : 'Android';
- }
- // Detect Silk desktop/accelerated modes.
- else if (name == 'Silk') {
- if (!/\bMobi/i.test(ua)) {
- os = 'Android';
- description.unshift('desktop mode');
- }
- if (/Accelerated *= *true/i.test(ua)) {
- description.unshift('accelerated');
- }
- }
- // Detect PaleMoon identifying as Firefox.
- else if (name == 'PaleMoon' && (data = /\bFirefox\/([\d.]+)\b/.exec(ua))) {
- description.push('identifying as Firefox ' + data[1]);
- }
- // Detect Firefox OS and products running Firefox.
- else if (name == 'Firefox' && (data = /\b(Mobile|Tablet|TV)\b/i.exec(ua))) {
- os || (os = 'Firefox OS');
- product || (product = data[1]);
- }
- // Detect false positives for Firefox/Safari.
- else if (!name || (data = !/\bMinefield\b/i.test(ua) && /\b(?:Firefox|Safari)\b/.exec(name))) {
- // Escape the `/` for Firefox 1.
- if (name && !product && /[\/,]|^[^(]+?\)/.test(ua.slice(ua.indexOf(data + '/') + 8))) {
- // Clear name of false positives.
- name = null;
- }
- // Reassign a generic name.
- if ((data = product || manufacturer || os) &&
- (product || manufacturer || /\b(?:Android|Symbian OS|Tablet OS|webOS)\b/.test(os))) {
- name = /[a-z]+(?: Hat)?/i.exec(/\bAndroid\b/.test(os) ? os : data) + ' Browser';
- }
- }
- // Add Chrome version to description for Electron.
- else if (name == 'Electron' && (data = (/\bChrome\/([\d.]+)\b/.exec(ua) || 0)[1])) {
- description.push('Chromium ' + data);
- }
- // Detect non-Opera (Presto-based) versions (order is important).
- if (!version) {
- version = getVersion([
- '(?:Cloud9|CriOS|CrMo|Edge|FxiOS|IEMobile|Iron|Opera ?Mini|OPiOS|OPR|Raven|SamsungBrowser|Silk(?!/[\\d.]+$))',
- 'Version',
- qualify(name),
- '(?:Firefox|Minefield|NetFront)'
- ]);
- }
- // Detect stubborn layout engines.
- if ((data =
- layout == 'iCab' && parseFloat(version) > 3 && 'WebKit' ||
- /\bOpera\b/.test(name) && (/\bOPR\b/.test(ua) ? 'Blink' : 'Presto') ||
- /\b(?:Midori|Nook|Safari)\b/i.test(ua) && !/^(?:Trident|EdgeHTML)$/.test(layout) && 'WebKit' ||
- !layout && /\bMSIE\b/i.test(ua) && (os == 'Mac OS' ? 'Tasman' : 'Trident') ||
- layout == 'WebKit' && /\bPlayStation\b(?! Vita\b)/i.test(name) && 'NetFront'
- )) {
- layout = [data];
- }
- // Detect Windows Phone 7 desktop mode.
- if (name == 'IE' && (data = (/; *(?:XBLWP|ZuneWP)(\d+)/i.exec(ua) || 0)[1])) {
- name += ' Mobile';
- os = 'Windows Phone ' + (/\+$/.test(data) ? data : data + '.x');
- description.unshift('desktop mode');
- }
- // Detect Windows Phone 8.x desktop mode.
- else if (/\bWPDesktop\b/i.test(ua)) {
- name = 'IE Mobile';
- os = 'Windows Phone 8.x';
- description.unshift('desktop mode');
- version || (version = (/\brv:([\d.]+)/.exec(ua) || 0)[1]);
- }
- // Detect IE 11 identifying as other browsers.
- else if (name != 'IE' && layout == 'Trident' && (data = /\brv:([\d.]+)/.exec(ua))) {
- if (name) {
- description.push('identifying as ' + name + (version ? ' ' + version : ''));
- }
- name = 'IE';
- version = data[1];
- }
- // Leverage environment features.
- if (useFeatures) {
- // Detect server-side environments.
- // Rhino has a global function while others have a global object.
- if (isHostType(context, 'global')) {
- if (java) {
- data = java.lang.System;
- arch = data.getProperty('os.arch');
- os = os || data.getProperty('os.name') + ' ' + data.getProperty('os.version');
- }
- if (rhino) {
- try {
- version = context.require('ringo/engine').version.join('.');
- name = 'RingoJS';
- } catch(e) {
- if ((data = context.system) && data.global.system == context.system) {
- name = 'Narwhal';
- os || (os = data[0].os || null);
- }
- }
- if (!name) {
- name = 'Rhino';
- }
- }
- else if (
- typeof context.process == 'object' && !context.process.browser &&
- (data = context.process)
- ) {
- if (typeof data.versions == 'object') {
- if (typeof data.versions.electron == 'string') {
- description.push('Node ' + data.versions.node);
- name = 'Electron';
- version = data.versions.electron;
- } else if (typeof data.versions.nw == 'string') {
- description.push('Chromium ' + version, 'Node ' + data.versions.node);
- name = 'NW.js';
- version = data.versions.nw;
- }
- }
- if (!name) {
- name = 'Node.js';
- arch = data.arch;
- os = data.platform;
- version = /[\d.]+/.exec(data.version);
- version = version ? version[0] : null;
- }
- }
- }
- // Detect Adobe AIR.
- else if (getClassOf((data = context.runtime)) == airRuntimeClass) {
- name = 'Adobe AIR';
- os = data.flash.system.Capabilities.os;
- }
- // Detect PhantomJS.
- else if (getClassOf((data = context.phantom)) == phantomClass) {
- name = 'PhantomJS';
- version = (data = data.version || null) && (data.major + '.' + data.minor + '.' + data.patch);
- }
- // Detect IE compatibility modes.
- else if (typeof doc.documentMode == 'number' && (data = /\bTrident\/(\d+)/i.exec(ua))) {
- // We're in compatibility mode when the Trident version + 4 doesn't
- // equal the document mode.
- version = [version, doc.documentMode];
- if ((data = +data[1] + 4) != version[1]) {
- description.push('IE ' + version[1] + ' mode');
- layout && (layout[1] = '');
- version[1] = data;
- }
- version = name == 'IE' ? String(version[1].toFixed(1)) : version[0];
- }
- // Detect IE 11 masking as other browsers.
- else if (typeof doc.documentMode == 'number' && /^(?:Chrome|Firefox)\b/.test(name)) {
- description.push('masking as ' + name + ' ' + version);
- name = 'IE';
- version = '11.0';
- layout = ['Trident'];
- os = 'Windows';
- }
- os = os && format(os);
- }
- // Detect prerelease phases.
- if (version && (data =
- /(?:[ab]|dp|pre|[ab]\d+pre)(?:\d+\+?)?$/i.exec(version) ||
- /(?:alpha|beta)(?: ?\d)?/i.exec(ua + ';' + (useFeatures && nav.appMinorVersion)) ||
- /\bMinefield\b/i.test(ua) && 'a'
- )) {
- prerelease = /b/i.test(data) ? 'beta' : 'alpha';
- version = version.replace(RegExp(data + '\\+?$'), '') +
- (prerelease == 'beta' ? beta : alpha) + (/\d+\+?/.exec(data) || '');
- }
- // Detect Firefox Mobile.
- if (name == 'Fennec' || name == 'Firefox' && /\b(?:Android|Firefox OS)\b/.test(os)) {
- name = 'Firefox Mobile';
- }
- // Obscure Maxthon's unreliable version.
- else if (name == 'Maxthon' && version) {
- version = version.replace(/\.[\d.]+/, '.x');
- }
- // Detect Xbox 360 and Xbox One.
- else if (/\bXbox\b/i.test(product)) {
- if (product == 'Xbox 360') {
- os = null;
- }
- if (product == 'Xbox 360' && /\bIEMobile\b/.test(ua)) {
- description.unshift('mobile mode');
- }
- }
- // Add mobile postfix.
- else if ((/^(?:Chrome|IE|Opera)$/.test(name) || name && !product && !/Browser|Mobi/.test(name)) &&
- (os == 'Windows CE' || /Mobi/i.test(ua))) {
- name += ' Mobile';
- }
- // Detect IE platform preview.
- else if (name == 'IE' && useFeatures) {
- try {
- if (context.external === null) {
- description.unshift('platform preview');
- }
- } catch(e) {
- description.unshift('embedded');
- }
- }
- // Detect BlackBerry OS version.
- // http://docs.blackberry.com/en/developers/deliverables/18169/HTTP_headers_sent_by_BB_Browser_1234911_11.jsp
- else if ((/\bBlackBerry\b/.test(product) || /\bBB10\b/.test(ua)) && (data =
- (RegExp(product.replace(/ +/g, ' *') + '/([.\\d]+)', 'i').exec(ua) || 0)[1] ||
- version
- )) {
- data = [data, /BB10/.test(ua)];
- os = (data[1] ? (product = null, manufacturer = 'BlackBerry') : 'Device Software') + ' ' + data[0];
- version = null;
- }
- // Detect Opera identifying/masking itself as another browser.
- // http://www.opera.com/support/kb/view/843/
- else if (this != forOwn && product != 'Wii' && (
- (useFeatures && opera) ||
- (/Opera/.test(name) && /\b(?:MSIE|Firefox)\b/i.test(ua)) ||
- (name == 'Firefox' && /\bOS X (?:\d+\.){2,}/.test(os)) ||
- (name == 'IE' && (
- (os && !/^Win/.test(os) && version > 5.5) ||
- /\bWindows XP\b/.test(os) && version > 8 ||
- version == 8 && !/\bTrident\b/.test(ua)
- ))
- ) && !reOpera.test((data = parse.call(forOwn, ua.replace(reOpera, '') + ';'))) && data.name) {
- // When "identifying", the UA contains both Opera and the other browser's name.
- data = 'ing as ' + data.name + ((data = data.version) ? ' ' + data : '');
- if (reOpera.test(name)) {
- if (/\bIE\b/.test(data) && os == 'Mac OS') {
- os = null;
- }
- data = 'identify' + data;
- }
- // When "masking", the UA contains only the other browser's name.
- else {
- data = 'mask' + data;
- if (operaClass) {
- name = format(operaClass.replace(/([a-z])([A-Z])/g, '$1 $2'));
- } else {
- name = 'Opera';
- }
- if (/\bIE\b/.test(data)) {
- os = null;
- }
- if (!useFeatures) {
- version = null;
- }
- }
- layout = ['Presto'];
- description.push(data);
- }
- // Detect WebKit Nightly and approximate Chrome/Safari versions.
- if ((data = (/\bAppleWebKit\/([\d.]+\+?)/i.exec(ua) || 0)[1])) {
- // Correct build number for numeric comparison.
- // (e.g. "532.5" becomes "532.05")
- data = [parseFloat(data.replace(/\.(\d)$/, '.0$1')), data];
- // Nightly builds are postfixed with a "+".
- if (name == 'Safari' && data[1].slice(-1) == '+') {
- name = 'WebKit Nightly';
- prerelease = 'alpha';
- version = data[1].slice(0, -1);
- }
- // Clear incorrect browser versions.
- else if (version == data[1] ||
- version == (data[2] = (/\bSafari\/([\d.]+\+?)/i.exec(ua) || 0)[1])) {
- version = null;
- }
- // Use the full Chrome version when available.
- data[1] = (/\bChrome\/([\d.]+)/i.exec(ua) || 0)[1];
- // Detect Blink layout engine.
- if (data[0] == 537.36 && data[2] == 537.36 && parseFloat(data[1]) >= 28 && layout == 'WebKit') {
- layout = ['Blink'];
- }
- // Detect JavaScriptCore.
- // http://stackoverflow.com/questions/6768474/how-can-i-detect-which-javascript-engine-v8-or-jsc-is-used-at-runtime-in-androi
- if (!useFeatures || (!likeChrome && !data[1])) {
- layout && (layout[1] = 'like Safari');
- data = (data = data[0], data < 400 ? 1 : data < 500 ? 2 : data < 526 ? 3 : data < 533 ? 4 : data < 534 ? '4+' : data < 535 ? 5 : data < 537 ? 6 : data < 538 ? 7 : data < 601 ? 8 : '8');
- } else {
- layout && (layout[1] = 'like Chrome');
- data = data[1] || (data = data[0], data < 530 ? 1 : data < 532 ? 2 : data < 532.05 ? 3 : data < 533 ? 4 : data < 534.03 ? 5 : data < 534.07 ? 6 : data < 534.10 ? 7 : data < 534.13 ? 8 : data < 534.16 ? 9 : data < 534.24 ? 10 : data < 534.30 ? 11 : data < 535.01 ? 12 : data < 535.02 ? '13+' : data < 535.07 ? 15 : data < 535.11 ? 16 : data < 535.19 ? 17 : data < 536.05 ? 18 : data < 536.10 ? 19 : data < 537.01 ? 20 : data < 537.11 ? '21+' : data < 537.13 ? 23 : data < 537.18 ? 24 : data < 537.24 ? 25 : data < 537.36 ? 26 : layout != 'Blink' ? '27' : '28');
- }
- // Add the postfix of ".x" or "+" for approximate versions.
- layout && (layout[1] += ' ' + (data += typeof data == 'number' ? '.x' : /[.+]/.test(data) ? '' : '+'));
- // Obscure version for some Safari 1-2 releases.
- if (name == 'Safari' && (!version || parseInt(version) > 45)) {
- version = data;
- }
- }
- // Detect Opera desktop modes.
- if (name == 'Opera' && (data = /\bzbov|zvav$/.exec(os))) {
- name += ' ';
- description.unshift('desktop mode');
- if (data == 'zvav') {
- name += 'Mini';
- version = null;
- } else {
- name += 'Mobile';
- }
- os = os.replace(RegExp(' *' + data + '$'), '');
- }
- // Detect Chrome desktop mode.
- else if (name == 'Safari' && /\bChrome\b/.exec(layout && layout[1])) {
- description.unshift('desktop mode');
- name = 'Chrome Mobile';
- version = null;
-
- if (/\bOS X\b/.test(os)) {
- manufacturer = 'Apple';
- os = 'iOS 4.3+';
- } else {
- os = null;
- }
- }
- // Strip incorrect OS versions.
- if (version && version.indexOf((data = /[\d.]+$/.exec(os))) == 0 &&
- ua.indexOf('/' + data + '-') > -1) {
- os = trim(os.replace(data, ''));
- }
- // Add layout engine.
- if (layout && !/\b(?:Avant|Nook)\b/.test(name) && (
- /Browser|Lunascape|Maxthon/.test(name) ||
- name != 'Safari' && /^iOS/.test(os) && /\bSafari\b/.test(layout[1]) ||
- /^(?:Adobe|Arora|Breach|Midori|Opera|Phantom|Rekonq|Rock|Samsung Internet|Sleipnir|Web)/.test(name) && layout[1])) {
- // Don't add layout details to description if they are falsey.
- (data = layout[layout.length - 1]) && description.push(data);
- }
- // Combine contextual information.
- if (description.length) {
- description = ['(' + description.join('; ') + ')'];
- }
- // Append manufacturer to description.
- if (manufacturer && product && product.indexOf(manufacturer) < 0) {
- description.push('on ' + manufacturer);
- }
- // Append product to description.
- if (product) {
- description.push((/^on /.test(description[description.length - 1]) ? '' : 'on ') + product);
- }
- // Parse the OS into an object.
- if (os) {
- data = / ([\d.+]+)$/.exec(os);
- isSpecialCasedOS = data && os.charAt(os.length - data[0].length - 1) == '/';
- os = {
- 'architecture': 32,
- 'family': (data && !isSpecialCasedOS) ? os.replace(data[0], '') : os,
- 'version': data ? data[1] : null,
- 'toString': function() {
- var version = this.version;
- return this.family + ((version && !isSpecialCasedOS) ? ' ' + version : '') + (this.architecture == 64 ? ' 64-bit' : '');
- }
- };
- }
- // Add browser/OS architecture.
- if ((data = /\b(?:AMD|IA|Win|WOW|x86_|x)64\b/i.exec(arch)) && !/\bi686\b/i.test(arch)) {
- if (os) {
- os.architecture = 64;
- os.family = os.family.replace(RegExp(' *' + data), '');
- }
- if (
- name && (/\bWOW64\b/i.test(ua) ||
- (useFeatures && /\w(?:86|32)$/.test(nav.cpuClass || nav.platform) && !/\bWin64; x64\b/i.test(ua)))
- ) {
- description.unshift('32-bit');
- }
- }
- // Chrome 39 and above on OS X is always 64-bit.
- else if (
- os && /^OS X/.test(os.family) &&
- name == 'Chrome' && parseFloat(version) >= 39
- ) {
- os.architecture = 64;
- }
-
- ua || (ua = null);
-
- /*------------------------------------------------------------------------*/
-
- /**
- * The platform object.
- *
- * @name platform
- * @type Object
- */
- var platform = {};
-
- /**
- * The platform description.
- *
- * @memberOf platform
- * @type string|null
- */
- platform.description = ua;
-
- /**
- * The name of the browser's layout engine.
- *
- * The list of common layout engines include:
- * "Blink", "EdgeHTML", "Gecko", "Trident" and "WebKit"
- *
- * @memberOf platform
- * @type string|null
- */
- platform.layout = layout && layout[0];
-
- /**
- * The name of the product's manufacturer.
- *
- * The list of manufacturers include:
- * "Apple", "Archos", "Amazon", "Asus", "Barnes & Noble", "BlackBerry",
- * "Google", "HP", "HTC", "LG", "Microsoft", "Motorola", "Nintendo",
- * "Nokia", "Samsung" and "Sony"
- *
- * @memberOf platform
- * @type string|null
- */
- platform.manufacturer = manufacturer;
-
- /**
- * The name of the browser/environment.
- *
- * The list of common browser names include:
- * "Chrome", "Electron", "Firefox", "Firefox for iOS", "IE",
- * "Microsoft Edge", "PhantomJS", "Safari", "SeaMonkey", "Silk",
- * "Opera Mini" and "Opera"
- *
- * Mobile versions of some browsers have "Mobile" appended to their name:
- * eg. "Chrome Mobile", "Firefox Mobile", "IE Mobile" and "Opera Mobile"
- *
- * @memberOf platform
- * @type string|null
- */
- platform.name = name;
-
- /**
- * The alpha/beta release indicator.
- *
- * @memberOf platform
- * @type string|null
- */
- platform.prerelease = prerelease;
-
- /**
- * The name of the product hosting the browser.
- *
- * The list of common products include:
- *
- * "BlackBerry", "Galaxy S4", "Lumia", "iPad", "iPod", "iPhone", "Kindle",
- * "Kindle Fire", "Nexus", "Nook", "PlayBook", "TouchPad" and "Transformer"
- *
- * @memberOf platform
- * @type string|null
- */
- platform.product = product;
-
- /**
- * The browser's user agent string.
- *
- * @memberOf platform
- * @type string|null
- */
- platform.ua = ua;
-
- /**
- * The browser/environment version.
- *
- * @memberOf platform
- * @type string|null
- */
- platform.version = name && version;
-
- /**
- * The name of the operating system.
- *
- * @memberOf platform
- * @type Object
- */
- platform.os = os || {
-
- /**
- * The CPU architecture the OS is built for.
- *
- * @memberOf platform.os
- * @type number|null
- */
- 'architecture': null,
-
- /**
- * The family of the OS.
- *
- * Common values include:
- * "Windows", "Windows Server 2008 R2 / 7", "Windows Server 2008 / Vista",
- * "Windows XP", "OS X", "Ubuntu", "Debian", "Fedora", "Red Hat", "SuSE",
- * "Android", "iOS" and "Windows Phone"
- *
- * @memberOf platform.os
- * @type string|null
- */
- 'family': null,
-
- /**
- * The version of the OS.
- *
- * @memberOf platform.os
- * @type string|null
- */
- 'version': null,
-
- /**
- * Returns the OS string.
- *
- * @memberOf platform.os
- * @returns {string} The OS string.
- */
- 'toString': function() { return 'null'; }
- };
-
- platform.parse = parse;
- platform.toString = toStringPlatform;
-
- if (platform.version) {
- description.unshift(version);
- }
- if (platform.name) {
- description.unshift(name);
- }
- if (os && name && !(os == String(os).split(' ')[0] && (os == name.split(' ')[0] || product))) {
- description.push(product ? '(' + os + ')' : 'on ' + os);
- }
- if (description.length) {
- platform.description = description.join(' ');
- }
- return platform;
- }
-
- /*--------------------------------------------------------------------------*/
-
- // Export platform.
- var platform = parse();
-
- // Some AMD build optimizers, like r.js, check for condition patterns like the following:
- if (typeof define == 'function' && typeof define.amd == 'object' && define.amd) {
- // Expose platform on the global object to prevent errors when platform is
- // loaded by a script tag in the presence of an AMD loader.
- // See http://requirejs.org/docs/errors.html#mismatch for more details.
- root.platform = platform;
-
- // Define as an anonymous module so platform can be aliased through path mapping.
- define(function() {
- return platform;
- });
- }
- // Check for `exports` after `define` in case a build optimizer adds an `exports` object.
- else if (freeExports && freeModule) {
- // Export for CommonJS support.
- forOwn(platform, function(value, key) {
- freeExports[key] = value;
- });
- }
- else {
- // Export to the global object.
- root.platform = platform;
- }
-}.call(this));
-
-}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
-
-},{}],9:[function(require,module,exports){
-var v1 = require('./v1');
-var v4 = require('./v4');
-
-var uuid = v4;
-uuid.v1 = v1;
-uuid.v4 = v4;
-
-module.exports = uuid;
-
-},{"./v1":12,"./v4":13}],10:[function(require,module,exports){
-/**
- * Convert array of 16 byte values to UUID string format of the form:
- * XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
- */
-var byteToHex = [];
-for (var i = 0; i < 256; ++i) {
- byteToHex[i] = (i + 0x100).toString(16).substr(1);
-}
-
-function bytesToUuid(buf, offset) {
- var i = offset || 0;
- var bth = byteToHex;
- // join used to fix memory issue caused by concatenation: https://bugs.chromium.org/p/v8/issues/detail?id=3175#c4
- return ([bth[buf[i++]], bth[buf[i++]],
- bth[buf[i++]], bth[buf[i++]], '-',
- bth[buf[i++]], bth[buf[i++]], '-',
- bth[buf[i++]], bth[buf[i++]], '-',
- bth[buf[i++]], bth[buf[i++]], '-',
- bth[buf[i++]], bth[buf[i++]],
- bth[buf[i++]], bth[buf[i++]],
- bth[buf[i++]], bth[buf[i++]]]).join('');
-}
-
-module.exports = bytesToUuid;
-
-},{}],11:[function(require,module,exports){
-// Unique ID creation requires a high quality random # generator. In the
-// browser this is a little complicated due to unknown quality of Math.random()
-// and inconsistent support for the `crypto` API. We do the best we can via
-// feature-detection
-
-// getRandomValues needs to be invoked in a context where "this" is a Crypto
-// implementation. Also, find the complete implementation of crypto on IE11.
-var getRandomValues = (typeof(crypto) != 'undefined' && crypto.getRandomValues && crypto.getRandomValues.bind(crypto)) ||
- (typeof(msCrypto) != 'undefined' && typeof window.msCrypto.getRandomValues == 'function' && msCrypto.getRandomValues.bind(msCrypto));
-
-if (getRandomValues) {
- // WHATWG crypto RNG - http://wiki.whatwg.org/wiki/Crypto
- var rnds8 = new Uint8Array(16); // eslint-disable-line no-undef
-
- module.exports = function whatwgRNG() {
- getRandomValues(rnds8);
- return rnds8;
- };
-} else {
- // Math.random()-based (RNG)
- //
- // If all else fails, use Math.random(). It's fast, but is of unspecified
- // quality.
- var rnds = new Array(16);
-
- module.exports = function mathRNG() {
- for (var i = 0, r; i < 16; i++) {
- if ((i & 0x03) === 0) r = Math.random() * 0x100000000;
- rnds[i] = r >>> ((i & 0x03) << 3) & 0xff;
- }
-
- return rnds;
- };
-}
-
-},{}],12:[function(require,module,exports){
-var rng = require('./lib/rng');
-var bytesToUuid = require('./lib/bytesToUuid');
-
-// **`v1()` - Generate time-based UUID**
-//
-// Inspired by https://github.com/LiosK/UUID.js
-// and http://docs.python.org/library/uuid.html
-
-var _nodeId;
-var _clockseq;
-
-// Previous uuid creation time
-var _lastMSecs = 0;
-var _lastNSecs = 0;
-
-// See https://github.com/broofa/node-uuid for API details
-function v1(options, buf, offset) {
- var i = buf && offset || 0;
- var b = buf || [];
-
- options = options || {};
- var node = options.node || _nodeId;
- var clockseq = options.clockseq !== undefined ? options.clockseq : _clockseq;
-
- // node and clockseq need to be initialized to random values if they're not
- // specified. We do this lazily to minimize issues related to insufficient
- // system entropy. See #189
- if (node == null || clockseq == null) {
- var seedBytes = rng();
- if (node == null) {
- // Per 4.5, create and 48-bit node id, (47 random bits + multicast bit = 1)
- node = _nodeId = [
- seedBytes[0] | 0x01,
- seedBytes[1], seedBytes[2], seedBytes[3], seedBytes[4], seedBytes[5]
- ];
- }
- if (clockseq == null) {
- // Per 4.2.2, randomize (14 bit) clockseq
- clockseq = _clockseq = (seedBytes[6] << 8 | seedBytes[7]) & 0x3fff;
- }
- }
-
- // UUID timestamps are 100 nano-second units since the Gregorian epoch,
- // (1582-10-15 00:00). JSNumbers aren't precise enough for this, so
- // time is handled internally as 'msecs' (integer milliseconds) and 'nsecs'
- // (100-nanoseconds offset from msecs) since unix epoch, 1970-01-01 00:00.
- var msecs = options.msecs !== undefined ? options.msecs : new Date().getTime();
-
- // Per 4.2.1.2, use count of uuid's generated during the current clock
- // cycle to simulate higher resolution clock
- var nsecs = options.nsecs !== undefined ? options.nsecs : _lastNSecs + 1;
-
- // Time since last uuid creation (in msecs)
- var dt = (msecs - _lastMSecs) + (nsecs - _lastNSecs)/10000;
-
- // Per 4.2.1.2, Bump clockseq on clock regression
- if (dt < 0 && options.clockseq === undefined) {
- clockseq = clockseq + 1 & 0x3fff;
- }
-
- // Reset nsecs if clock regresses (new clockseq) or we've moved onto a new
- // time interval
- if ((dt < 0 || msecs > _lastMSecs) && options.nsecs === undefined) {
- nsecs = 0;
- }
-
- // Per 4.2.1.2 Throw error if too many uuids are requested
- if (nsecs >= 10000) {
- throw new Error('uuid.v1(): Can\'t create more than 10M uuids/sec');
- }
-
- _lastMSecs = msecs;
- _lastNSecs = nsecs;
- _clockseq = clockseq;
-
- // Per 4.1.4 - Convert from unix epoch to Gregorian epoch
- msecs += 12219292800000;
-
- // `time_low`
- var tl = ((msecs & 0xfffffff) * 10000 + nsecs) % 0x100000000;
- b[i++] = tl >>> 24 & 0xff;
- b[i++] = tl >>> 16 & 0xff;
- b[i++] = tl >>> 8 & 0xff;
- b[i++] = tl & 0xff;
-
- // `time_mid`
- var tmh = (msecs / 0x100000000 * 10000) & 0xfffffff;
- b[i++] = tmh >>> 8 & 0xff;
- b[i++] = tmh & 0xff;
-
- // `time_high_and_version`
- b[i++] = tmh >>> 24 & 0xf | 0x10; // include version
- b[i++] = tmh >>> 16 & 0xff;
-
- // `clock_seq_hi_and_reserved` (Per 4.2.2 - include variant)
- b[i++] = clockseq >>> 8 | 0x80;
-
- // `clock_seq_low`
- b[i++] = clockseq & 0xff;
-
- // `node`
- for (var n = 0; n < 6; ++n) {
- b[i + n] = node[n];
- }
-
- return buf ? buf : bytesToUuid(b);
-}
-
-module.exports = v1;
-
-},{"./lib/bytesToUuid":10,"./lib/rng":11}],13:[function(require,module,exports){
-var rng = require('./lib/rng');
-var bytesToUuid = require('./lib/bytesToUuid');
-
-function v4(options, buf, offset) {
- var i = buf && offset || 0;
-
- if (typeof(options) == 'string') {
- buf = options === 'binary' ? new Array(16) : null;
- options = null;
- }
- options = options || {};
-
- var rnds = options.random || (options.rng || rng)();
-
- // Per 4.4, set bits for version and `clock_seq_hi_and_reserved`
- rnds[6] = (rnds[6] & 0x0f) | 0x40;
- rnds[8] = (rnds[8] & 0x3f) | 0x80;
-
- // Copy bytes to buffer, if provided
- if (buf) {
- for (var ii = 0; ii < 16; ++ii) {
- buf[i + ii] = rnds[ii];
- }
- }
-
- return buf || bytesToUuid(rnds);
-}
-
-module.exports = v4;
-
-},{"./lib/bytesToUuid":10,"./lib/rng":11}],14:[function(require,module,exports){
-/*
-WildEmitter.js is a slim little event emitter by @henrikjoreteg largely based
-on @visionmedia's Emitter from UI Kit.
-
-Why? I wanted it standalone.
-
-I also wanted support for wildcard emitters like this:
-
-emitter.on('*', function (eventName, other, event, payloads) {
-
-});
-
-emitter.on('somenamespace*', function (eventName, payloads) {
-
-});
-
-Please note that callbacks triggered by wildcard registered events also get
-the event name as the first argument.
-*/
-
-module.exports = WildEmitter;
-
-function WildEmitter() { }
-
-WildEmitter.mixin = function (constructor) {
- var prototype = constructor.prototype || constructor;
-
- prototype.isWildEmitter= true;
-
- // Listen on the given `event` with `fn`. Store a group name if present.
- prototype.on = function (event, groupName, fn) {
- this.callbacks = this.callbacks || {};
- var hasGroup = (arguments.length === 3),
- group = hasGroup ? arguments[1] : undefined,
- func = hasGroup ? arguments[2] : arguments[1];
- func._groupName = group;
- (this.callbacks[event] = this.callbacks[event] || []).push(func);
- return this;
- };
-
- // Adds an `event` listener that will be invoked a single
- // time then automatically removed.
- prototype.once = function (event, groupName, fn) {
- var self = this,
- hasGroup = (arguments.length === 3),
- group = hasGroup ? arguments[1] : undefined,
- func = hasGroup ? arguments[2] : arguments[1];
- function on() {
- self.off(event, on);
- func.apply(this, arguments);
- }
- this.on(event, group, on);
- return this;
- };
-
- // Unbinds an entire group
- prototype.releaseGroup = function (groupName) {
- this.callbacks = this.callbacks || {};
- var item, i, len, handlers;
- for (item in this.callbacks) {
- handlers = this.callbacks[item];
- for (i = 0, len = handlers.length; i < len; i++) {
- if (handlers[i]._groupName === groupName) {
- //console.log('removing');
- // remove it and shorten the array we're looping through
- handlers.splice(i, 1);
- i--;
- len--;
- }
- }
- }
- return this;
- };
-
- // Remove the given callback for `event` or all
- // registered callbacks.
- prototype.off = function (event, fn) {
- this.callbacks = this.callbacks || {};
- var callbacks = this.callbacks[event],
- i;
-
- if (!callbacks) return this;
-
- // remove all handlers
- if (arguments.length === 1) {
- delete this.callbacks[event];
- return this;
- }
-
- // remove specific handler
- i = callbacks.indexOf(fn);
- callbacks.splice(i, 1);
- if (callbacks.length === 0) {
- delete this.callbacks[event];
- }
- return this;
- };
-
- /// Emit `event` with the given args.
- // also calls any `*` handlers
- prototype.emit = function (event) {
- this.callbacks = this.callbacks || {};
- var args = [].slice.call(arguments, 1),
- callbacks = this.callbacks[event],
- specialCallbacks = this.getWildcardCallbacks(event),
- i,
- len,
- item,
- listeners;
-
- if (callbacks) {
- listeners = callbacks.slice();
- for (i = 0, len = listeners.length; i < len; ++i) {
- if (!listeners[i]) {
- break;
- }
- listeners[i].apply(this, args);
- }
- }
-
- if (specialCallbacks) {
- len = specialCallbacks.length;
- listeners = specialCallbacks.slice();
- for (i = 0, len = listeners.length; i < len; ++i) {
- if (!listeners[i]) {
- break;
- }
- listeners[i].apply(this, [event].concat(args));
- }
- }
-
- return this;
- };
-
- // Helper for for finding special wildcard event handlers that match the event
- prototype.getWildcardCallbacks = function (eventName) {
- this.callbacks = this.callbacks || {};
- var item,
- split,
- result = [];
-
- for (item in this.callbacks) {
- split = item.split('*');
- if (item === '*' || (split.length === 2 && eventName.slice(0, split[0].length) === split[0])) {
- result = result.concat(this.callbacks[item]);
- }
- }
- return result;
- };
-
-};
-
-WildEmitter.mixin(WildEmitter);
-
-},{}],15:[function(require,module,exports){
-/*!
- * EventEmitter v5.2.5 - git.io/ee
- * Unlicense - http://unlicense.org/
- * Oliver Caldwell - http://oli.me.uk/
- * @preserve
- */
-
-;(function (exports) {
- 'use strict';
-
- /**
- * Class for managing events.
- * Can be extended to provide event functionality in other classes.
- *
- * @class EventEmitter Manages event registering and emitting.
- */
- function EventEmitter() {}
-
- // Shortcuts to improve speed and size
- var proto = EventEmitter.prototype;
- var originalGlobalValue = exports.EventEmitter;
-
- /**
- * Finds the index of the listener for the event in its storage array.
- *
- * @param {Function[]} listeners Array of listeners to search through.
- * @param {Function} listener Method to look for.
- * @return {Number} Index of the specified listener, -1 if not found
- * @api private
- */
- function indexOfListener(listeners, listener) {
- var i = listeners.length;
- while (i--) {
- if (listeners[i].listener === listener) {
- return i;
- }
- }
-
- return -1;
- }
-
- /**
- * Alias a method while keeping the context correct, to allow for overwriting of target method.
- *
- * @param {String} name The name of the target method.
- * @return {Function} The aliased method
- * @api private
- */
- function alias(name) {
- return function aliasClosure() {
- return this[name].apply(this, arguments);
- };
- }
-
- /**
- * Returns the listener array for the specified event.
- * Will initialise the event object and listener arrays if required.
- * Will return an object if you use a regex search. The object contains keys for each matched event. So /ba[rz]/ might return an object containing bar and baz. But only if you have either defined them with defineEvent or added some listeners to them.
- * Each property in the object response is an array of listener functions.
- *
- * @param {String|RegExp} evt Name of the event to return the listeners from.
- * @return {Function[]|Object} All listener functions for the event.
- */
- proto.getListeners = function getListeners(evt) {
- var events = this._getEvents();
- var response;
- var key;
-
- // Return a concatenated array of all matching events if
- // the selector is a regular expression.
- if (evt instanceof RegExp) {
- response = {};
- for (key in events) {
- if (events.hasOwnProperty(key) && evt.test(key)) {
- response[key] = events[key];
- }
- }
- }
- else {
- response = events[evt] || (events[evt] = []);
- }
-
- return response;
- };
-
- /**
- * Takes a list of listener objects and flattens it into a list of listener functions.
- *
- * @param {Object[]} listeners Raw listener objects.
- * @return {Function[]} Just the listener functions.
- */
- proto.flattenListeners = function flattenListeners(listeners) {
- var flatListeners = [];
- var i;
-
- for (i = 0; i < listeners.length; i += 1) {
- flatListeners.push(listeners[i].listener);
- }
-
- return flatListeners;
- };
-
- /**
- * Fetches the requested listeners via getListeners but will always return the results inside an object. This is mainly for internal use but others may find it useful.
- *
- * @param {String|RegExp} evt Name of the event to return the listeners from.
- * @return {Object} All listener functions for an event in an object.
- */
- proto.getListenersAsObject = function getListenersAsObject(evt) {
- var listeners = this.getListeners(evt);
- var response;
-
- if (listeners instanceof Array) {
- response = {};
- response[evt] = listeners;
- }
-
- return response || listeners;
- };
-
- function isValidListener (listener) {
- if (typeof listener === 'function' || listener instanceof RegExp) {
- return true
- } else if (listener && typeof listener === 'object') {
- return isValidListener(listener.listener)
- } else {
- return false
- }
- }
-
- /**
- * Adds a listener function to the specified event.
- * The listener will not be added if it is a duplicate.
- * If the listener returns true then it will be removed after it is called.
- * If you pass a regular expression as the event name then the listener will be added to all events that match it.
- *
- * @param {String|RegExp} evt Name of the event to attach the listener to.
- * @param {Function} listener Method to be called when the event is emitted. If the function returns true then it will be removed after calling.
- * @return {Object} Current instance of EventEmitter for chaining.
- */
- proto.addListener = function addListener(evt, listener) {
- if (!isValidListener(listener)) {
- throw new TypeError('listener must be a function');
- }
-
- var listeners = this.getListenersAsObject(evt);
- var listenerIsWrapped = typeof listener === 'object';
- var key;
-
- for (key in listeners) {
- if (listeners.hasOwnProperty(key) && indexOfListener(listeners[key], listener) === -1) {
- listeners[key].push(listenerIsWrapped ? listener : {
- listener: listener,
- once: false
- });
- }
- }
-
- return this;
- };
-
- /**
- * Alias of addListener
- */
- proto.on = alias('addListener');
-
- /**
- * Semi-alias of addListener. It will add a listener that will be
- * automatically removed after its first execution.
- *
- * @param {String|RegExp} evt Name of the event to attach the listener to.
- * @param {Function} listener Method to be called when the event is emitted. If the function returns true then it will be removed after calling.
- * @return {Object} Current instance of EventEmitter for chaining.
- */
- proto.addOnceListener = function addOnceListener(evt, listener) {
- return this.addListener(evt, {
- listener: listener,
- once: true
- });
- };
-
- /**
- * Alias of addOnceListener.
- */
- proto.once = alias('addOnceListener');
-
- /**
- * Defines an event name. This is required if you want to use a regex to add a listener to multiple events at once. If you don't do this then how do you expect it to know what event to add to? Should it just add to every possible match for a regex? No. That is scary and bad.
- * You need to tell it what event names should be matched by a regex.
- *
- * @param {String} evt Name of the event to create.
- * @return {Object} Current instance of EventEmitter for chaining.
- */
- proto.defineEvent = function defineEvent(evt) {
- this.getListeners(evt);
- return this;
- };
-
- /**
- * Uses defineEvent to define multiple events.
- *
- * @param {String[]} evts An array of event names to define.
- * @return {Object} Current instance of EventEmitter for chaining.
- */
- proto.defineEvents = function defineEvents(evts) {
- for (var i = 0; i < evts.length; i += 1) {
- this.defineEvent(evts[i]);
- }
- return this;
- };
-
- /**
- * Removes a listener function from the specified event.
- * When passed a regular expression as the event name, it will remove the listener from all events that match it.
- *
- * @param {String|RegExp} evt Name of the event to remove the listener from.
- * @param {Function} listener Method to remove from the event.
- * @return {Object} Current instance of EventEmitter for chaining.
- */
- proto.removeListener = function removeListener(evt, listener) {
- var listeners = this.getListenersAsObject(evt);
- var index;
- var key;
-
- for (key in listeners) {
- if (listeners.hasOwnProperty(key)) {
- index = indexOfListener(listeners[key], listener);
-
- if (index !== -1) {
- listeners[key].splice(index, 1);
- }
- }
- }
-
- return this;
- };
-
- /**
- * Alias of removeListener
- */
- proto.off = alias('removeListener');
-
- /**
- * Adds listeners in bulk using the manipulateListeners method.
- * If you pass an object as the first argument you can add to multiple events at once. The object should contain key value pairs of events and listeners or listener arrays. You can also pass it an event name and an array of listeners to be added.
- * You can also pass it a regular expression to add the array of listeners to all events that match it.
- * Yeah, this function does quite a bit. That's probably a bad thing.
- *
- * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to add to multiple events at once.
- * @param {Function[]} [listeners] An optional array of listener functions to add.
- * @return {Object} Current instance of EventEmitter for chaining.
- */
- proto.addListeners = function addListeners(evt, listeners) {
- // Pass through to manipulateListeners
- return this.manipulateListeners(false, evt, listeners);
- };
-
- /**
- * Removes listeners in bulk using the manipulateListeners method.
- * If you pass an object as the first argument you can remove from multiple events at once. The object should contain key value pairs of events and listeners or listener arrays.
- * You can also pass it an event name and an array of listeners to be removed.
- * You can also pass it a regular expression to remove the listeners from all events that match it.
- *
- * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to remove from multiple events at once.
- * @param {Function[]} [listeners] An optional array of listener functions to remove.
- * @return {Object} Current instance of EventEmitter for chaining.
- */
- proto.removeListeners = function removeListeners(evt, listeners) {
- // Pass through to manipulateListeners
- return this.manipulateListeners(true, evt, listeners);
- };
-
- /**
- * Edits listeners in bulk. The addListeners and removeListeners methods both use this to do their job. You should really use those instead, this is a little lower level.
- * The first argument will determine if the listeners are removed (true) or added (false).
- * If you pass an object as the second argument you can add/remove from multiple events at once. The object should contain key value pairs of events and listeners or listener arrays.
- * You can also pass it an event name and an array of listeners to be added/removed.
- * You can also pass it a regular expression to manipulate the listeners of all events that match it.
- *
- * @param {Boolean} remove True if you want to remove listeners, false if you want to add.
- * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to add/remove from multiple events at once.
- * @param {Function[]} [listeners] An optional array of listener functions to add/remove.
- * @return {Object} Current instance of EventEmitter for chaining.
- */
- proto.manipulateListeners = function manipulateListeners(remove, evt, listeners) {
- var i;
- var value;
- var single = remove ? this.removeListener : this.addListener;
- var multiple = remove ? this.removeListeners : this.addListeners;
-
- // If evt is an object then pass each of its properties to this method
- if (typeof evt === 'object' && !(evt instanceof RegExp)) {
- for (i in evt) {
- if (evt.hasOwnProperty(i) && (value = evt[i])) {
- // Pass the single listener straight through to the singular method
- if (typeof value === 'function') {
- single.call(this, i, value);
- }
- else {
- // Otherwise pass back to the multiple function
- multiple.call(this, i, value);
- }
- }
- }
- }
- else {
- // So evt must be a string
- // And listeners must be an array of listeners
- // Loop over it and pass each one to the multiple method
- i = listeners.length;
- while (i--) {
- single.call(this, evt, listeners[i]);
- }
- }
-
- return this;
- };
-
- /**
- * Removes all listeners from a specified event.
- * If you do not specify an event then all listeners will be removed.
- * That means every event will be emptied.
- * You can also pass a regex to remove all events that match it.
- *
- * @param {String|RegExp} [evt] Optional name of the event to remove all listeners for. Will remove from every event if not passed.
- * @return {Object} Current instance of EventEmitter for chaining.
- */
- proto.removeEvent = function removeEvent(evt) {
- var type = typeof evt;
- var events = this._getEvents();
- var key;
-
- // Remove different things depending on the state of evt
- if (type === 'string') {
- // Remove all listeners for the specified event
- delete events[evt];
- }
- else if (evt instanceof RegExp) {
- // Remove all events matching the regex.
- for (key in events) {
- if (events.hasOwnProperty(key) && evt.test(key)) {
- delete events[key];
- }
- }
- }
- else {
- // Remove all listeners in all events
- delete this._events;
- }
-
- return this;
- };
-
- /**
- * Alias of removeEvent.
- *
- * Added to mirror the node API.
- */
- proto.removeAllListeners = alias('removeEvent');
-
- /**
- * Emits an event of your choice.
- * When emitted, every listener attached to that event will be executed.
- * If you pass the optional argument array then those arguments will be passed to every listener upon execution.
- * Because it uses `apply`, your array of arguments will be passed as if you wrote them out separately.
- * So they will not arrive within the array on the other side, they will be separate.
- * You can also pass a regular expression to emit to all events that match it.
- *
- * @param {String|RegExp} evt Name of the event to emit and execute listeners for.
- * @param {Array} [args] Optional array of arguments to be passed to each listener.
- * @return {Object} Current instance of EventEmitter for chaining.
- */
- proto.emitEvent = function emitEvent(evt, args) {
- var listenersMap = this.getListenersAsObject(evt);
- var listeners;
- var listener;
- var i;
- var key;
- var response;
-
- for (key in listenersMap) {
- if (listenersMap.hasOwnProperty(key)) {
- listeners = listenersMap[key].slice(0);
-
- for (i = 0; i < listeners.length; i++) {
- // If the listener returns true then it shall be removed from the event
- // The function is executed either with a basic call or an apply if there is an args array
- listener = listeners[i];
-
- if (listener.once === true) {
- this.removeListener(evt, listener.listener);
- }
-
- response = listener.listener.apply(this, args || []);
-
- if (response === this._getOnceReturnValue()) {
- this.removeListener(evt, listener.listener);
- }
- }
- }
- }
-
- return this;
- };
-
- /**
- * Alias of emitEvent
- */
- proto.trigger = alias('emitEvent');
-
- /**
- * Subtly different from emitEvent in that it will pass its arguments on to the listeners, as opposed to taking a single array of arguments to pass on.
- * As with emitEvent, you can pass a regex in place of the event name to emit to all events that match it.
- *
- * @param {String|RegExp} evt Name of the event to emit and execute listeners for.
- * @param {...*} Optional additional arguments to be passed to each listener.
- * @return {Object} Current instance of EventEmitter for chaining.
- */
- proto.emit = function emit(evt) {
- var args = Array.prototype.slice.call(arguments, 1);
- return this.emitEvent(evt, args);
- };
-
- /**
- * Sets the current value to check against when executing listeners. If a
- * listeners return value matches the one set here then it will be removed
- * after execution. This value defaults to true.
- *
- * @param {*} value The new value to check for when executing listeners.
- * @return {Object} Current instance of EventEmitter for chaining.
- */
- proto.setOnceReturnValue = function setOnceReturnValue(value) {
- this._onceReturnValue = value;
- return this;
- };
-
- /**
- * Fetches the current value to check against when executing listeners. If
- * the listeners return value matches this one then it should be removed
- * automatically. It will return true by default.
- *
- * @return {*|Boolean} The current value to check for or the default, true.
- * @api private
- */
- proto._getOnceReturnValue = function _getOnceReturnValue() {
- if (this.hasOwnProperty('_onceReturnValue')) {
- return this._onceReturnValue;
- }
- else {
- return true;
- }
- };
-
- /**
- * Fetches the events object and creates one if required.
- *
- * @return {Object} The events storage object.
- * @api private
- */
- proto._getEvents = function _getEvents() {
- return this._events || (this._events = {});
- };
-
- /**
- * Reverts the global {@link EventEmitter} to its previous value and returns a reference to this version.
- *
- * @return {Function} Non conflicting EventEmitter class.
- */
- EventEmitter.noConflict = function noConflict() {
- exports.EventEmitter = originalGlobalValue;
- return EventEmitter;
- };
-
- // Expose the class either via AMD, CommonJS or the global object
- if (typeof define === 'function' && define.amd) {
- define(function () {
- return EventEmitter;
- });
- }
- else if (typeof module === 'object' && module.exports){
- module.exports = EventEmitter;
- }
- else {
- exports.EventEmitter = EventEmitter;
- }
-}(typeof window !== 'undefined' ? window : this || {}));
-
-},{}],16:[function(require,module,exports){
-"use strict";
-Object.defineProperty(exports, "__esModule", { value: true });
-var OpenVidu_1 = require("./OpenVidu/OpenVidu");
-if (window) {
- window['OpenVidu'] = OpenVidu_1.OpenVidu;
-}
-
-},{"./OpenVidu/OpenVidu":19}],17:[function(require,module,exports){
-"use strict";
-Object.defineProperty(exports, "__esModule", { value: true });
-var Stream_1 = require("./Stream");
-var Connection = (function () {
- function Connection(session, opts) {
- this.session = session;
- this.disposed = false;
- var msg = "'Connection' created ";
- if (!!opts) {
- msg += "(remote) with 'connectionId' [" + opts.id + ']';
- }
- else {
- msg += '(local)';
- }
- console.info(msg);
- this.options = opts;
- if (!!opts) {
- this.connectionId = opts.id;
- if (opts.metadata) {
- this.data = opts.metadata;
- }
- if (opts.streams) {
- this.initRemoteStreams(opts.streams);
- }
- }
- this.creationTime = new Date().getTime();
- }
- Connection.prototype.sendIceCandidate = function (candidate) {
- console.debug((!!this.stream.outboundStreamOpts ? 'Local' : 'Remote'), 'candidate for', this.connectionId, JSON.stringify(candidate));
- this.session.openvidu.sendRequest('onIceCandidate', {
- endpointName: this.connectionId,
- candidate: candidate.candidate,
- sdpMid: candidate.sdpMid,
- sdpMLineIndex: candidate.sdpMLineIndex
- }, function (error, response) {
- if (error) {
- console.error('Error sending ICE candidate: '
- + JSON.stringify(error));
- }
- });
- };
- Connection.prototype.initRemoteStreams = function (options) {
- var _this = this;
- options.forEach(function (opts) {
- var streamOptions = {
- id: opts.id,
- connection: _this,
- hasAudio: opts.hasAudio,
- hasVideo: opts.hasVideo,
- audioActive: opts.audioActive,
- videoActive: opts.videoActive,
- typeOfVideo: opts.typeOfVideo,
- frameRate: opts.frameRate,
- videoDimensions: !!opts.videoDimensions ? JSON.parse(opts.videoDimensions) : undefined
- };
- var stream = new Stream_1.Stream(_this.session, streamOptions);
- _this.addStream(stream);
- });
- console.info("Remote 'Connection' with 'connectionId' [" + this.connectionId + '] is now configured for receiving Streams with options: ', this.stream.inboundStreamOpts);
- };
- Connection.prototype.addStream = function (stream) {
- stream.connection = this;
- this.stream = stream;
- };
- Connection.prototype.removeStream = function (streamId) {
- delete this.stream;
- };
- Connection.prototype.dispose = function () {
- if (!!this.stream) {
- delete this.stream;
- }
- this.disposed = true;
- };
- return Connection;
-}());
-exports.Connection = Connection;
-
-},{"./Stream":22}],18:[function(require,module,exports){
-"use strict";
-Object.defineProperty(exports, "__esModule", { value: true });
-var LocalRecorderState_1 = require("../OpenViduInternal/Enums/LocalRecorderState");
-var LocalRecorder = (function () {
- function LocalRecorder(stream) {
- this.stream = stream;
- this.chunks = [];
- this.count = 0;
- this.connectionId = (!!this.stream.connection) ? this.stream.connection.connectionId : 'default-connection';
- this.id = this.stream.streamId + '_' + this.connectionId + '_localrecord';
- this.state = LocalRecorderState_1.LocalRecorderState.READY;
- }
- LocalRecorder.prototype.record = function () {
- var _this = this;
- return new Promise(function (resolve, reject) {
- try {
- if (typeof MediaRecorder === 'undefined') {
- console.error('MediaRecorder not supported on your browser. See compatibility in https://caniuse.com/#search=MediaRecorder');
- throw (Error('MediaRecorder not supported on your browser. See compatibility in https://caniuse.com/#search=MediaRecorder'));
- }
- if (_this.state !== LocalRecorderState_1.LocalRecorderState.READY) {
- throw (Error('\'LocalRecord.record()\' needs \'LocalRecord.state\' to be \'READY\' (current value: \'' + _this.state + '\'). Call \'LocalRecorder.clean()\' or init a new LocalRecorder before'));
- }
- console.log("Starting local recording of stream '" + _this.stream.streamId + "' of connection '" + _this.connectionId + "'");
- if (typeof MediaRecorder.isTypeSupported === 'function') {
- var options = void 0;
- if (MediaRecorder.isTypeSupported('video/webm;codecs=vp9')) {
- options = { mimeType: 'video/webm;codecs=vp9' };
- }
- else if (MediaRecorder.isTypeSupported('video/webm;codecs=h264')) {
- options = { mimeType: 'video/webm;codecs=h264' };
- }
- else if (MediaRecorder.isTypeSupported('video/webm;codecs=vp8')) {
- options = { mimeType: 'video/webm;codecs=vp8' };
- }
- console.log('Using mimeType ' + options.mimeType);
- _this.mediaRecorder = new MediaRecorder(_this.stream.getMediaStream(), options);
- }
- else {
- console.warn('isTypeSupported is not supported, using default codecs for browser');
- _this.mediaRecorder = new MediaRecorder(_this.stream.getMediaStream());
- }
- _this.mediaRecorder.start(10);
- }
- catch (err) {
- reject(err);
- }
- _this.mediaRecorder.ondataavailable = function (e) {
- _this.chunks.push(e.data);
- };
- _this.mediaRecorder.onerror = function (e) {
- console.error('MediaRecorder error: ', e);
- };
- _this.mediaRecorder.onstart = function () {
- console.log('MediaRecorder started (state=' + _this.mediaRecorder.state + ')');
- };
- _this.mediaRecorder.onstop = function () {
- _this.onStopDefault();
- };
- _this.mediaRecorder.onpause = function () {
- console.log('MediaRecorder paused (state=' + _this.mediaRecorder.state + ')');
- };
- _this.mediaRecorder.onresume = function () {
- console.log('MediaRecorder resumed (state=' + _this.mediaRecorder.state + ')');
- };
- _this.mediaRecorder.onwarning = function (e) {
- console.log('MediaRecorder warning: ' + e);
- };
- _this.state = LocalRecorderState_1.LocalRecorderState.RECORDING;
- resolve();
- });
- };
- LocalRecorder.prototype.stop = function () {
- var _this = this;
- return new Promise(function (resolve, reject) {
- try {
- if (_this.state === LocalRecorderState_1.LocalRecorderState.READY || _this.state === LocalRecorderState_1.LocalRecorderState.FINISHED) {
- throw (Error('\'LocalRecord.stop()\' needs \'LocalRecord.state\' to be \'RECORDING\' or \'PAUSED\' (current value: \'' + _this.state + '\'). Call \'LocalRecorder.start()\' before'));
- }
- _this.mediaRecorder.onstop = function () {
- _this.onStopDefault();
- resolve();
- };
- _this.mediaRecorder.stop();
- }
- catch (e) {
- reject(e);
- }
- });
- };
- LocalRecorder.prototype.pause = function () {
- var _this = this;
- return new Promise(function (resolve, reject) {
- try {
- if (_this.state !== LocalRecorderState_1.LocalRecorderState.RECORDING) {
- reject(Error('\'LocalRecord.pause()\' needs \'LocalRecord.state\' to be \'RECORDING\' (current value: \'' + _this.state + '\'). Call \'LocalRecorder.start()\' or \'LocalRecorder.resume()\' before'));
- }
- _this.mediaRecorder.pause();
- _this.state = LocalRecorderState_1.LocalRecorderState.PAUSED;
- }
- catch (error) {
- reject(error);
- }
- });
- };
- LocalRecorder.prototype.resume = function () {
- var _this = this;
- return new Promise(function (resolve, reject) {
- try {
- if (_this.state !== LocalRecorderState_1.LocalRecorderState.PAUSED) {
- throw (Error('\'LocalRecord.resume()\' needs \'LocalRecord.state\' to be \'PAUSED\' (current value: \'' + _this.state + '\'). Call \'LocalRecorder.pause()\' before'));
- }
- _this.mediaRecorder.resume();
- _this.state = LocalRecorderState_1.LocalRecorderState.RECORDING;
- }
- catch (error) {
- reject(error);
- }
- });
- };
- LocalRecorder.prototype.preview = function (parentElement) {
- if (this.state !== LocalRecorderState_1.LocalRecorderState.FINISHED) {
- throw (Error('\'LocalRecord.preview()\' needs \'LocalRecord.state\' to be \'FINISHED\' (current value: \'' + this.state + '\'). Call \'LocalRecorder.stop()\' before'));
- }
- this.videoPreview = document.createElement('video');
- this.videoPreview.id = this.id;
- this.videoPreview.autoplay = true;
- if (typeof parentElement === 'string') {
- this.htmlParentElementId = parentElement;
- var parentElementDom = document.getElementById(parentElement);
- if (parentElementDom) {
- this.videoPreview = parentElementDom.appendChild(this.videoPreview);
- }
- }
- else {
- this.htmlParentElementId = parentElement.id;
- this.videoPreview = parentElement.appendChild(this.videoPreview);
- }
- this.videoPreview.src = this.videoPreviewSrc;
- return this.videoPreview;
- };
- LocalRecorder.prototype.clean = function () {
- var _this = this;
- var f = function () {
- delete _this.blob;
- _this.chunks = [];
- _this.count = 0;
- delete _this.mediaRecorder;
- _this.state = LocalRecorderState_1.LocalRecorderState.READY;
- };
- if (this.state === LocalRecorderState_1.LocalRecorderState.RECORDING || this.state === LocalRecorderState_1.LocalRecorderState.PAUSED) {
- this.stop().then(function () { return f(); }).catch(function () { return f(); });
- }
- else {
- f();
- }
- };
- LocalRecorder.prototype.download = function () {
- if (this.state !== LocalRecorderState_1.LocalRecorderState.FINISHED) {
- throw (Error('\'LocalRecord.download()\' needs \'LocalRecord.state\' to be \'FINISHED\' (current value: \'' + this.state + '\'). Call \'LocalRecorder.stop()\' before'));
- }
- else {
- var a = document.createElement('a');
- a.style.display = 'none';
- document.body.appendChild(a);
- var url = window.URL.createObjectURL(this.blob);
- a.href = url;
- a.download = this.id + '.webm';
- a.click();
- window.URL.revokeObjectURL(url);
- document.body.removeChild(a);
- }
- };
- LocalRecorder.prototype.getBlob = function () {
- if (this.state !== LocalRecorderState_1.LocalRecorderState.FINISHED) {
- throw (Error('Call \'LocalRecord.stop()\' before getting Blob file'));
- }
- else {
- return this.blob;
- }
- };
- LocalRecorder.prototype.uploadAsBinary = function (endpoint, headers) {
- var _this = this;
- return new Promise(function (resolve, reject) {
- if (_this.state !== LocalRecorderState_1.LocalRecorderState.FINISHED) {
- reject(Error('\'LocalRecord.uploadAsBinary()\' needs \'LocalRecord.state\' to be \'FINISHED\' (current value: \'' + _this.state + '\'). Call \'LocalRecorder.stop()\' before'));
- }
- else {
- var http_1 = new XMLHttpRequest();
- http_1.open('POST', endpoint, true);
- if (typeof headers === 'object') {
- for (var _i = 0, _a = Object.keys(headers); _i < _a.length; _i++) {
- var key = _a[_i];
- http_1.setRequestHeader(key, headers[key]);
- }
- }
- http_1.onreadystatechange = function () {
- if (http_1.readyState === 4) {
- if (http_1.status.toString().charAt(0) === '2') {
- resolve(http_1.responseText);
- }
- else {
- reject(http_1.status);
- }
- }
- };
- http_1.send(_this.blob);
- }
- });
- };
- LocalRecorder.prototype.uploadAsMultipartfile = function (endpoint, headers) {
- var _this = this;
- return new Promise(function (resolve, reject) {
- if (_this.state !== LocalRecorderState_1.LocalRecorderState.FINISHED) {
- reject(Error('\'LocalRecord.uploadAsMultipartfile()\' needs \'LocalRecord.state\' to be \'FINISHED\' (current value: \'' + _this.state + '\'). Call \'LocalRecorder.stop()\' before'));
- }
- else {
- var http_2 = new XMLHttpRequest();
- http_2.open('POST', endpoint, true);
- if (typeof headers === 'object') {
- for (var _i = 0, _a = Object.keys(headers); _i < _a.length; _i++) {
- var key = _a[_i];
- http_2.setRequestHeader(key, headers[key]);
- }
- }
- var sendable = new FormData();
- sendable.append('file', _this.blob, _this.id + '.webm');
- http_2.onreadystatechange = function () {
- if (http_2.readyState === 4) {
- if (http_2.status.toString().charAt(0) === '2') {
- resolve(http_2.responseText);
- }
- else {
- reject(http_2.status);
- }
- }
- };
- http_2.send(sendable);
- }
- });
- };
- LocalRecorder.prototype.onStopDefault = function () {
- console.log('MediaRecorder stopped (state=' + this.mediaRecorder.state + ')');
- this.blob = new Blob(this.chunks, { type: 'video/webm' });
- this.chunks = [];
- this.videoPreviewSrc = window.URL.createObjectURL(this.blob);
- this.state = LocalRecorderState_1.LocalRecorderState.FINISHED;
- };
- return LocalRecorder;
-}());
-exports.LocalRecorder = LocalRecorder;
-
-},{"../OpenViduInternal/Enums/LocalRecorderState":25}],19:[function(require,module,exports){
-"use strict";
-Object.defineProperty(exports, "__esModule", { value: true });
-var LocalRecorder_1 = require("./LocalRecorder");
-var Publisher_1 = require("./Publisher");
-var Session_1 = require("./Session");
-var StreamPropertyChangedEvent_1 = require("../OpenViduInternal/Events/StreamPropertyChangedEvent");
-var OpenViduError_1 = require("../OpenViduInternal/Enums/OpenViduError");
-var VideoInsertMode_1 = require("../OpenViduInternal/Enums/VideoInsertMode");
-var screenSharingAuto = require("../OpenViduInternal/ScreenSharing/Screen-Capturing-Auto");
-var screenSharing = require("../OpenViduInternal/ScreenSharing/Screen-Capturing");
-var RpcBuilder = require("../OpenViduInternal/KurentoUtils/kurento-jsonrpc");
-var platform = require("platform");
-var OpenVidu = (function () {
- function OpenVidu() {
- var _this = this;
- this.publishers = [];
- this.secret = '';
- this.recorder = false;
- this.advancedConfiguration = {};
- console.info("'OpenVidu' initialized");
- if (platform.name.toLowerCase().indexOf('mobile') !== -1) {
- window.onorientationchange = function () {
- _this.publishers.forEach(function (publisher) {
- if (!!publisher.stream && !!publisher.stream.hasVideo && !!publisher.stream.streamManager.videos[0]) {
- var attempts_1 = 0;
- var oldWidth_1 = publisher.stream.videoDimensions.width;
- var oldHeight_1 = publisher.stream.videoDimensions.height;
- var firefoxSettings_1 = publisher.stream.getMediaStream().getVideoTracks()[0].getSettings();
- var newWidth_1 = (platform.name.toLowerCase().indexOf('firefox') !== -1) ? firefoxSettings_1.width : publisher.videoReference.videoWidth;
- var newHeight_1 = (platform.name.toLowerCase().indexOf('firefox') !== -1) ? firefoxSettings_1.height : publisher.videoReference.videoHeight;
- var repeatUntilChange_1 = setInterval(function () {
- firefoxSettings_1 = publisher.stream.getMediaStream().getVideoTracks()[0].getSettings();
- newWidth_1 = (platform.name.toLowerCase().indexOf('firefox') !== -1) ? firefoxSettings_1.width : publisher.videoReference.videoWidth;
- newHeight_1 = (platform.name.toLowerCase().indexOf('firefox') !== -1) ? firefoxSettings_1.height : publisher.videoReference.videoHeight;
- sendStreamPropertyChangedEvent_1(oldWidth_1, oldHeight_1, newWidth_1, newHeight_1);
- }, 100);
- var sendStreamPropertyChangedEvent_1 = function (oldWidth, oldHeight, newWidth, newHeight) {
- attempts_1++;
- if (attempts_1 > 4) {
- clearTimeout(repeatUntilChange_1);
- }
- if (newWidth !== oldWidth || newHeight !== oldHeight) {
- publisher.stream.videoDimensions = {
- width: newWidth || 0,
- height: newHeight || 0
- };
- _this.sendRequest('streamPropertyChanged', {
- streamId: publisher.stream.streamId,
- property: 'videoDimensions',
- newValue: JSON.stringify(publisher.stream.videoDimensions),
- reason: 'deviceRotated'
- }, function (error, response) {
- if (error) {
- console.error("Error sending 'streamPropertyChanged' event", error);
- }
- else {
- _this.session.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent_1.StreamPropertyChangedEvent(_this.session, publisher.stream, 'videoDimensions', publisher.stream.videoDimensions, { width: oldWidth, height: oldHeight }, 'deviceRotated')]);
- publisher.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent_1.StreamPropertyChangedEvent(publisher, publisher.stream, 'videoDimensions', publisher.stream.videoDimensions, { width: oldWidth, height: oldHeight }, 'deviceRotated')]);
- }
- });
- clearTimeout(repeatUntilChange_1);
- }
- };
- }
- });
- };
- }
- }
- OpenVidu.prototype.initSession = function () {
- this.session = new Session_1.Session(this);
- return this.session;
- };
- OpenVidu.prototype.initPublisher = function (targetElement, param2, param3) {
- var properties;
- if (!!param2 && (typeof param2 !== 'function')) {
- properties = param2;
- properties = {
- audioSource: (typeof properties.audioSource !== 'undefined') ? properties.audioSource : undefined,
- frameRate: this.isMediaStreamTrack(properties.videoSource) ? undefined : ((typeof properties.frameRate !== 'undefined') ? properties.frameRate : undefined),
- insertMode: (typeof properties.insertMode !== 'undefined') ? ((typeof properties.insertMode === 'string') ? VideoInsertMode_1.VideoInsertMode[properties.insertMode] : properties.insertMode) : VideoInsertMode_1.VideoInsertMode.APPEND,
- mirror: (typeof properties.mirror !== 'undefined') ? properties.mirror : true,
- publishAudio: (typeof properties.publishAudio !== 'undefined') ? properties.publishAudio : true,
- publishVideo: (typeof properties.publishVideo !== 'undefined') ? properties.publishVideo : true,
- resolution: this.isMediaStreamTrack(properties.videoSource) ? undefined : ((typeof properties.resolution !== 'undefined') ? properties.resolution : '640x480'),
- videoSource: (typeof properties.videoSource !== 'undefined') ? properties.videoSource : undefined
- };
- }
- else {
- properties = {
- insertMode: VideoInsertMode_1.VideoInsertMode.APPEND,
- mirror: true,
- publishAudio: true,
- publishVideo: true,
- resolution: '640x480'
- };
- }
- var publisher = new Publisher_1.Publisher(targetElement, properties, this);
- var completionHandler;
- if (!!param2 && (typeof param2 === 'function')) {
- completionHandler = param2;
- }
- else if (!!param3) {
- completionHandler = param3;
- }
- publisher.initialize()
- .then(function () {
- if (completionHandler !== undefined) {
- completionHandler(undefined);
- }
- publisher.emitEvent('accessAllowed', []);
- }).catch(function (error) {
- if (completionHandler !== undefined) {
- completionHandler(error);
- }
- publisher.emitEvent('accessDenied', []);
- });
- this.publishers.push(publisher);
- return publisher;
- };
- OpenVidu.prototype.initPublisherAsync = function (targetElement, properties) {
- var _this = this;
- return new Promise(function (resolve, reject) {
- var publisher;
- var callback = function (error) {
- if (!!error) {
- reject(error);
- }
- else {
- resolve(publisher);
- }
- };
- if (!!properties) {
- publisher = _this.initPublisher(targetElement, properties, callback);
- }
- else {
- publisher = _this.initPublisher(targetElement, callback);
- }
- });
- };
- OpenVidu.prototype.initLocalRecorder = function (stream) {
- return new LocalRecorder_1.LocalRecorder(stream);
- };
- OpenVidu.prototype.checkSystemRequirements = function () {
- var browser = platform.name;
- var version = platform.version;
- if ((browser !== 'Chrome') && (browser !== 'Chrome Mobile') &&
- (browser !== 'Firefox') && (browser !== 'Firefox Mobile') && (browser !== 'Firefox for iOS') &&
- (browser !== 'Opera') && (browser !== 'Opera Mobile') &&
- (browser !== 'Safari')) {
- return 0;
- }
- else {
- return 1;
- }
- };
- OpenVidu.prototype.getDevices = function () {
- return new Promise(function (resolve, reject) {
- navigator.mediaDevices.enumerateDevices().then(function (deviceInfos) {
- var devices = [];
- deviceInfos.forEach(function (deviceInfo) {
- if (deviceInfo.kind === 'audioinput' || deviceInfo.kind === 'videoinput') {
- devices.push({
- kind: deviceInfo.kind,
- deviceId: deviceInfo.deviceId,
- label: deviceInfo.label
- });
- }
- });
- resolve(devices);
- }).catch(function (error) {
- console.error('Error getting devices', error);
- reject(error);
- });
- });
- };
- OpenVidu.prototype.getUserMedia = function (options) {
- var _this = this;
- return new Promise(function (resolve, reject) {
- _this.generateMediaConstraints(options)
- .then(function (constraints) {
- navigator.mediaDevices.getUserMedia(constraints)
- .then(function (mediaStream) {
- resolve(mediaStream);
- })
- .catch(function (error) {
- var errorName;
- var errorMessage = error.toString();
- if (!(options.videoSource === 'screen')) {
- errorName = OpenViduError_1.OpenViduErrorName.DEVICE_ACCESS_DENIED;
- }
- else {
- errorName = OpenViduError_1.OpenViduErrorName.SCREEN_CAPTURE_DENIED;
- }
- reject(new OpenViduError_1.OpenViduError(errorName, errorMessage));
- });
- })
- .catch(function (error) {
- reject(error);
- });
- });
- };
- OpenVidu.prototype.enableProdMode = function () {
- console.log = function () { };
- console.debug = function () { };
- console.info = function () { };
- console.warn = function () { };
- };
- OpenVidu.prototype.setAdvancedConfiguration = function (configuration) {
- this.advancedConfiguration = configuration;
- };
- OpenVidu.prototype.generateMediaConstraints = function (publisherProperties) {
- var _this = this;
- return new Promise(function (resolve, reject) {
- var audio, video;
- if (publisherProperties.audioSource === null || publisherProperties.audioSource === false) {
- audio = false;
- }
- else if (publisherProperties.audioSource === undefined) {
- audio = true;
- }
- else {
- audio = publisherProperties.audioSource;
- }
- if (publisherProperties.videoSource === null || publisherProperties.videoSource === false) {
- video = false;
- }
- else {
- video = {
- height: {
- ideal: 480
- },
- width: {
- ideal: 640
- }
- };
- }
- var mediaConstraints = {
- audio: audio,
- video: video
- };
- if (typeof mediaConstraints.audio === 'string') {
- mediaConstraints.audio = { deviceId: { exact: mediaConstraints.audio } };
- }
- if (mediaConstraints.video) {
- if (!!publisherProperties.resolution) {
- var widthAndHeight = publisherProperties.resolution.toLowerCase().split('x');
- var width = Number(widthAndHeight[0]);
- var height = Number(widthAndHeight[1]);
- mediaConstraints.video.width.ideal = width;
- mediaConstraints.video.height.ideal = height;
- }
- if (!!publisherProperties.frameRate) {
- mediaConstraints.video.frameRate = { ideal: publisherProperties.frameRate };
- }
- if (!!publisherProperties.videoSource && typeof publisherProperties.videoSource === 'string') {
- if (publisherProperties.videoSource === 'screen') {
- if (platform.name !== 'Chrome' && platform.name.indexOf('Firefox') === -1) {
- var error = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_SHARING_NOT_SUPPORTED, 'You can only screen share in desktop Chrome and Firefox. Detected browser: ' + platform.name);
- console.error(error);
- reject(error);
- }
- else {
- if (!!_this.advancedConfiguration.screenShareChromeExtension && !(platform.name.indexOf('Firefox') !== -1)) {
- screenSharing.getScreenConstraints(function (error, screenConstraints) {
- if (!!error || !!screenConstraints.mandatory && screenConstraints.mandatory.chromeMediaSource === 'screen') {
- if (error === 'permission-denied' || error === 'PermissionDeniedError') {
- var error_1 = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_CAPTURE_DENIED, 'You must allow access to one window of your desktop');
- console.error(error_1);
- reject(error_1);
- }
- else {
- var extensionId = _this.advancedConfiguration.screenShareChromeExtension.split('/').pop().trim();
- screenSharing.getChromeExtensionStatus(extensionId, function (status) {
- if (status === 'installed-disabled') {
- var error_2 = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_EXTENSION_DISABLED, 'You must enable the screen extension');
- console.error(error_2);
- reject(error_2);
- }
- if (status === 'not-installed') {
- var error_3 = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_EXTENSION_NOT_INSTALLED, _this.advancedConfiguration.screenShareChromeExtension);
- console.error(error_3);
- reject(error_3);
- }
- });
- }
- }
- else {
- mediaConstraints.video = screenConstraints;
- resolve(mediaConstraints);
- }
- });
- }
- else {
- screenSharingAuto.getScreenId(function (error, sourceId, screenConstraints) {
- if (!!error) {
- if (error === 'not-installed') {
- var extensionUrl = !!_this.advancedConfiguration.screenShareChromeExtension ? _this.advancedConfiguration.screenShareChromeExtension :
- 'https://chrome.google.com/webstore/detail/openvidu-screensharing/lfcgfepafnobdloecchnfaclibenjold';
- var error_4 = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_EXTENSION_NOT_INSTALLED, extensionUrl);
- console.error(error_4);
- reject(error_4);
- }
- else if (error === 'installed-disabled') {
- var error_5 = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_EXTENSION_DISABLED, 'You must enable the screen extension');
- console.error(error_5);
- reject(error_5);
- }
- else if (error === 'permission-denied') {
- var error_6 = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_CAPTURE_DENIED, 'You must allow access to one window of your desktop');
- console.error(error_6);
- reject(error_6);
- }
- }
- else {
- mediaConstraints.video = screenConstraints.video;
- resolve(mediaConstraints);
- }
- });
- }
- publisherProperties.videoSource = 'screen';
- }
- }
- else {
- mediaConstraints.video['deviceId'] = { exact: publisherProperties.videoSource };
- resolve(mediaConstraints);
- }
- }
- else {
- resolve(mediaConstraints);
- }
- }
- else {
- resolve(mediaConstraints);
- }
- });
- };
- OpenVidu.prototype.startWs = function (onConnectSucces) {
- var config = {
- heartbeat: 5000,
- sendCloseMessage: false,
- ws: {
- uri: this.wsUri,
- useSockJS: false,
- onconnected: onConnectSucces,
- ondisconnect: this.disconnectCallback.bind(this),
- onreconnecting: this.reconnectingCallback.bind(this),
- onreconnected: this.reconnectedCallback.bind(this)
- },
- rpc: {
- requestTimeout: 10000,
- participantJoined: this.session.onParticipantJoined.bind(this.session),
- participantPublished: this.session.onParticipantPublished.bind(this.session),
- participantUnpublished: this.session.onParticipantUnpublished.bind(this.session),
- participantLeft: this.session.onParticipantLeft.bind(this.session),
- participantEvicted: this.session.onParticipantEvicted.bind(this.session),
- recordingStarted: this.session.onRecordingStarted.bind(this.session),
- recordingStopped: this.session.onRecordingStopped.bind(this.session),
- sendMessage: this.session.onNewMessage.bind(this.session),
- streamPropertyChanged: this.session.onStreamPropertyChanged.bind(this.session),
- iceCandidate: this.session.recvIceCandidate.bind(this.session),
- mediaError: this.session.onMediaError.bind(this.session)
- }
- };
- this.jsonRpcClient = new RpcBuilder.clients.JsonRpcClient(config);
- };
- OpenVidu.prototype.closeWs = function () {
- this.jsonRpcClient.close();
- };
- OpenVidu.prototype.sendRequest = function (method, params, callback) {
- if (params && params instanceof Function) {
- callback = params;
- params = {};
- }
- console.debug('Sending request: {method:"' + method + '", params: ' + JSON.stringify(params) + '}');
- this.jsonRpcClient.send(method, params, callback);
- };
- OpenVidu.prototype.isMediaStreamTrack = function (mediaSource) {
- var is = (!!mediaSource &&
- mediaSource.enabled !== undefined && typeof mediaSource.enabled === 'boolean' &&
- mediaSource.id !== undefined && typeof mediaSource.id === 'string' &&
- mediaSource.kind !== undefined && typeof mediaSource.kind === 'string' &&
- mediaSource.label !== undefined && typeof mediaSource.label === 'string' &&
- mediaSource.muted !== undefined && typeof mediaSource.muted === 'boolean' &&
- mediaSource.readyState !== undefined && typeof mediaSource.readyState === 'string');
- return is;
- };
- OpenVidu.prototype.getWsUri = function () {
- return this.wsUri;
- };
- OpenVidu.prototype.getSecret = function () {
- return this.secret;
- };
- OpenVidu.prototype.getRecorder = function () {
- return this.recorder;
- };
- OpenVidu.prototype.disconnectCallback = function () {
- console.warn('Websocket connection lost');
- if (this.isRoomAvailable()) {
- this.session.onLostConnection();
- }
- else {
- alert('Connection error. Please reload page.');
- }
- };
- OpenVidu.prototype.reconnectingCallback = function () {
- console.warn('Websocket connection lost (reconnecting)');
- if (this.isRoomAvailable()) {
- this.session.onLostConnection();
- }
- else {
- alert('Connection error. Please reload page.');
- }
- };
- OpenVidu.prototype.reconnectedCallback = function () {
- console.warn('Websocket reconnected');
- if (this.isRoomAvailable()) {
- this.session.onRecoveredConnection();
- }
- else {
- alert('Connection error. Please reload page.');
- }
- };
- OpenVidu.prototype.isRoomAvailable = function () {
- if (this.session !== undefined && this.session instanceof Session_1.Session) {
- return true;
- }
- else {
- console.warn('Session instance not found');
- return false;
- }
- };
- return OpenVidu;
-}());
-exports.OpenVidu = OpenVidu;
-
-},{"../OpenViduInternal/Enums/OpenViduError":26,"../OpenViduInternal/Enums/VideoInsertMode":27,"../OpenViduInternal/Events/StreamPropertyChangedEvent":36,"../OpenViduInternal/KurentoUtils/kurento-jsonrpc":43,"../OpenViduInternal/ScreenSharing/Screen-Capturing":48,"../OpenViduInternal/ScreenSharing/Screen-Capturing-Auto":47,"./LocalRecorder":18,"./Publisher":20,"./Session":21,"platform":8}],20:[function(require,module,exports){
-"use strict";
-var __extends = (this && this.__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 __());
- };
-})();
-Object.defineProperty(exports, "__esModule", { value: true });
-var Session_1 = require("./Session");
-var Stream_1 = require("./Stream");
-var StreamManager_1 = require("./StreamManager");
-var StreamEvent_1 = require("../OpenViduInternal/Events/StreamEvent");
-var StreamPropertyChangedEvent_1 = require("../OpenViduInternal/Events/StreamPropertyChangedEvent");
-var VideoElementEvent_1 = require("../OpenViduInternal/Events/VideoElementEvent");
-var OpenViduError_1 = require("../OpenViduInternal/Enums/OpenViduError");
-var platform = require("platform");
-var Publisher = (function (_super) {
- __extends(Publisher, _super);
- function Publisher(targEl, properties, openvidu) {
- var _this = _super.call(this, new Stream_1.Stream((!!openvidu.session) ? openvidu.session : new Session_1.Session(openvidu), { publisherProperties: properties, mediaConstraints: {} }), targEl) || this;
- _this.accessAllowed = false;
- _this.isSubscribedToRemote = false;
- _this.accessDenied = false;
- _this.properties = properties;
- _this.openvidu = openvidu;
- _this.stream.ee.on('local-stream-destroyed', function (reason) {
- _this.stream.isLocalStreamPublished = false;
- var streamEvent = new StreamEvent_1.StreamEvent(true, _this, 'streamDestroyed', _this.stream, reason);
- _this.emitEvent('streamDestroyed', [streamEvent]);
- streamEvent.callDefaultBehavior();
- });
- return _this;
- }
- Publisher.prototype.publishAudio = function (value) {
- var _this = this;
- if (this.stream.audioActive !== value) {
- this.stream.getMediaStream().getAudioTracks().forEach(function (track) {
- track.enabled = value;
- });
- this.session.openvidu.sendRequest('streamPropertyChanged', {
- streamId: this.stream.streamId,
- property: 'audioActive',
- newValue: value,
- reason: 'publishAudio'
- }, function (error, response) {
- if (error) {
- console.error("Error sending 'streamPropertyChanged' event", error);
- }
- else {
- _this.session.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent_1.StreamPropertyChangedEvent(_this.session, _this.stream, 'audioActive', value, !value, 'publishAudio')]);
- _this.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent_1.StreamPropertyChangedEvent(_this, _this.stream, 'audioActive', value, !value, 'publishAudio')]);
- }
- });
- this.stream.audioActive = value;
- console.info("'Publisher' has " + (value ? 'published' : 'unpublished') + ' its audio stream');
- }
- };
- Publisher.prototype.publishVideo = function (value) {
- var _this = this;
- if (this.stream.videoActive !== value) {
- this.stream.getMediaStream().getVideoTracks().forEach(function (track) {
- track.enabled = value;
- });
- this.session.openvidu.sendRequest('streamPropertyChanged', {
- streamId: this.stream.streamId,
- property: 'videoActive',
- newValue: value,
- reason: 'publishVideo'
- }, function (error, response) {
- if (error) {
- console.error("Error sending 'streamPropertyChanged' event", error);
- }
- else {
- _this.session.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent_1.StreamPropertyChangedEvent(_this.session, _this.stream, 'videoActive', value, !value, 'publishVideo')]);
- _this.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent_1.StreamPropertyChangedEvent(_this, _this.stream, 'videoActive', value, !value, 'publishVideo')]);
- }
- });
- this.stream.videoActive = value;
- console.info("'Publisher' has " + (value ? 'published' : 'unpublished') + ' its video stream');
- }
- };
- Publisher.prototype.subscribeToRemote = function (value) {
- value = (value !== undefined) ? value : true;
- this.isSubscribedToRemote = value;
- this.stream.subscribeToMyRemote(value);
- };
- Publisher.prototype.on = function (type, handler) {
- var _this = this;
- _super.prototype.on.call(this, type, handler);
- if (type === 'streamCreated') {
- if (!!this.stream && this.stream.isLocalStreamPublished) {
- this.emitEvent('streamCreated', [new StreamEvent_1.StreamEvent(false, this, 'streamCreated', this.stream, '')]);
- }
- else {
- this.stream.ee.on('stream-created-by-publisher', function () {
- _this.emitEvent('streamCreated', [new StreamEvent_1.StreamEvent(false, _this, 'streamCreated', _this.stream, '')]);
- });
- }
- }
- if (type === 'remoteVideoPlaying') {
- if (this.stream.displayMyRemote() && this.videos[0] && this.videos[0].video &&
- this.videos[0].video.currentTime > 0 &&
- this.videos[0].video.paused === false &&
- this.videos[0].video.ended === false &&
- this.videos[0].video.readyState === 4) {
- this.emitEvent('remoteVideoPlaying', [new VideoElementEvent_1.VideoElementEvent(this.videos[0].video, this, 'remoteVideoPlaying')]);
- }
- }
- if (type === 'accessAllowed') {
- if (this.accessAllowed) {
- this.emitEvent('accessAllowed', []);
- }
- }
- if (type === 'accessDenied') {
- if (this.accessDenied) {
- this.emitEvent('accessDenied', []);
- }
- }
- return this;
- };
- Publisher.prototype.once = function (type, handler) {
- var _this = this;
- _super.prototype.once.call(this, type, handler);
- if (type === 'streamCreated') {
- if (!!this.stream && this.stream.isLocalStreamPublished) {
- this.emitEvent('streamCreated', [new StreamEvent_1.StreamEvent(false, this, 'streamCreated', this.stream, '')]);
- }
- else {
- this.stream.ee.once('stream-created-by-publisher', function () {
- _this.emitEvent('streamCreated', [new StreamEvent_1.StreamEvent(false, _this, 'streamCreated', _this.stream, '')]);
- });
- }
- }
- if (type === 'remoteVideoPlaying') {
- if (this.stream.displayMyRemote() && this.videos[0] && this.videos[0].video &&
- this.videos[0].video.currentTime > 0 &&
- this.videos[0].video.paused === false &&
- this.videos[0].video.ended === false &&
- this.videos[0].video.readyState === 4) {
- this.emitEvent('remoteVideoPlaying', [new VideoElementEvent_1.VideoElementEvent(this.videos[0].video, this, 'remoteVideoPlaying')]);
- }
- }
- if (type === 'accessAllowed') {
- if (this.accessAllowed) {
- this.emitEvent('accessAllowed', []);
- }
- }
- if (type === 'accessDenied') {
- if (this.accessDenied) {
- this.emitEvent('accessDenied', []);
- }
- }
- return this;
- };
- Publisher.prototype.initialize = function () {
- var _this = this;
- return new Promise(function (resolve, reject) {
- var errorCallback = function (openViduError) {
- _this.accessDenied = true;
- _this.accessAllowed = false;
- reject(openViduError);
- };
- var successCallback = function (mediaStream) {
- _this.accessAllowed = true;
- _this.accessDenied = false;
- if (_this.openvidu.isMediaStreamTrack(_this.properties.audioSource)) {
- mediaStream.removeTrack(mediaStream.getAudioTracks()[0]);
- mediaStream.addTrack(_this.properties.audioSource);
- }
- if (_this.openvidu.isMediaStreamTrack(_this.properties.videoSource)) {
- mediaStream.removeTrack(mediaStream.getVideoTracks()[0]);
- mediaStream.addTrack(_this.properties.videoSource);
- }
- if (!!mediaStream.getAudioTracks()[0]) {
- mediaStream.getAudioTracks()[0].enabled = !!_this.stream.outboundStreamOpts.publisherProperties.publishAudio;
- }
- if (!!mediaStream.getVideoTracks()[0]) {
- mediaStream.getVideoTracks()[0].enabled = !!_this.stream.outboundStreamOpts.publisherProperties.publishVideo;
- }
- _this.videoReference = document.createElement('video');
- _this.videoReference.srcObject = mediaStream;
- _this.stream.setMediaStream(mediaStream);
- if (!_this.stream.displayMyRemote()) {
- _this.stream.updateMediaStreamInVideos();
- }
- if (!!_this.firstVideoElement) {
- _this.createVideoElement(_this.firstVideoElement.targetElement, _this.properties.insertMode);
- }
- delete _this.firstVideoElement;
- if (_this.stream.isSendVideo()) {
- if (!_this.stream.isSendScreen()) {
- var _a = mediaStream.getVideoTracks()[0].getSettings(), width = _a.width, height = _a.height;
- if (platform.name.toLowerCase().indexOf('mobile') !== -1 && (window.innerHeight > window.innerWidth)) {
- _this.stream.videoDimensions = {
- width: height || 0,
- height: width || 0
- };
- }
- else {
- _this.stream.videoDimensions = {
- width: width || 0,
- height: height || 0
- };
- }
- _this.stream.isLocalStreamReadyToPublish = true;
- _this.stream.ee.emitEvent('stream-ready-to-publish', []);
- }
- else {
- _this.videoReference.onloadedmetadata = function () {
- _this.stream.videoDimensions = {
- width: _this.videoReference.videoWidth,
- height: _this.videoReference.videoHeight
- };
- _this.screenShareResizeInterval = setInterval(function () {
- var firefoxSettings = mediaStream.getVideoTracks()[0].getSettings();
- var newWidth = (platform.name === 'Chrome') ? _this.videoReference.videoWidth : firefoxSettings.width;
- var newHeight = (platform.name === 'Chrome') ? _this.videoReference.videoHeight : firefoxSettings.height;
- if (_this.stream.isLocalStreamPublished &&
- (newWidth !== _this.stream.videoDimensions.width ||
- newHeight !== _this.stream.videoDimensions.height)) {
- var oldValue_1 = { width: _this.stream.videoDimensions.width, height: _this.stream.videoDimensions.height };
- _this.stream.videoDimensions = {
- width: newWidth || 0,
- height: newHeight || 0
- };
- _this.session.openvidu.sendRequest('streamPropertyChanged', {
- streamId: _this.stream.streamId,
- property: 'videoDimensions',
- newValue: JSON.stringify(_this.stream.videoDimensions),
- reason: 'screenResized'
- }, function (error, response) {
- if (error) {
- console.error("Error sending 'streamPropertyChanged' event", error);
- }
- else {
- _this.session.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent_1.StreamPropertyChangedEvent(_this.session, _this.stream, 'videoDimensions', _this.stream.videoDimensions, oldValue_1, 'screenResized')]);
- _this.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent_1.StreamPropertyChangedEvent(_this, _this.stream, 'videoDimensions', _this.stream.videoDimensions, oldValue_1, 'screenResized')]);
- }
- });
- }
- }, 500);
- _this.stream.isLocalStreamReadyToPublish = true;
- _this.stream.ee.emitEvent('stream-ready-to-publish', []);
- };
- }
- }
- else {
- _this.stream.isLocalStreamReadyToPublish = true;
- _this.stream.ee.emitEvent('stream-ready-to-publish', []);
- }
- resolve();
- };
- _this.openvidu.generateMediaConstraints(_this.properties)
- .then(function (constraints) {
- var outboundStreamOptions = {
- mediaConstraints: constraints,
- publisherProperties: _this.properties
- };
- _this.stream.setOutboundStreamOptions(outboundStreamOptions);
- var constraintsAux = {};
- var timeForDialogEvent = 1250;
- if (_this.stream.isSendVideo() || _this.stream.isSendAudio()) {
- var definedAudioConstraint_1 = ((constraints.audio === undefined) ? true : constraints.audio);
- constraintsAux.audio = _this.stream.isSendScreen() ? false : definedAudioConstraint_1;
- constraintsAux.video = constraints.video;
- var startTime_1 = Date.now();
- _this.setPermissionDialogTimer(timeForDialogEvent);
- navigator.mediaDevices.getUserMedia(constraintsAux)
- .then(function (mediaStream) {
- _this.clearPermissionDialogTimer(startTime_1, timeForDialogEvent);
- if (_this.stream.isSendScreen() && _this.stream.isSendAudio()) {
- constraintsAux.audio = definedAudioConstraint_1;
- constraintsAux.video = false;
- startTime_1 = Date.now();
- _this.setPermissionDialogTimer(timeForDialogEvent);
- navigator.mediaDevices.getUserMedia(constraintsAux)
- .then(function (audioOnlyStream) {
- _this.clearPermissionDialogTimer(startTime_1, timeForDialogEvent);
- mediaStream.addTrack(audioOnlyStream.getAudioTracks()[0]);
- successCallback(mediaStream);
- })
- .catch(function (error) {
- _this.clearPermissionDialogTimer(startTime_1, timeForDialogEvent);
- var errorName, errorMessage;
- switch (error.name.toLowerCase()) {
- case 'notfounderror':
- errorName = OpenViduError_1.OpenViduErrorName.INPUT_AUDIO_DEVICE_NOT_FOUND;
- errorMessage = error.toString();
- errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage));
- break;
- case 'notallowederror':
- errorName = OpenViduError_1.OpenViduErrorName.DEVICE_ACCESS_DENIED;
- errorMessage = error.toString();
- errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage));
- break;
- case 'overconstrainederror':
- if (error.constraint.toLowerCase() === 'deviceid') {
- errorName = OpenViduError_1.OpenViduErrorName.INPUT_AUDIO_DEVICE_NOT_FOUND;
- errorMessage = "Audio input device with deviceId '" + constraints.video.deviceId.exact + "' not found";
- }
- else {
- errorName = OpenViduError_1.OpenViduErrorName.PUBLISHER_PROPERTIES_ERROR;
- errorMessage = "Audio input device doesn't support the value passed for constraint '" + error.constraint + "'";
- }
- errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage));
- break;
- }
- });
- }
- else {
- successCallback(mediaStream);
- }
- })
- .catch(function (error) {
- _this.clearPermissionDialogTimer(startTime_1, timeForDialogEvent);
- var errorName, errorMessage;
- switch (error.name.toLowerCase()) {
- case 'notfounderror':
- navigator.mediaDevices.getUserMedia({
- audio: false,
- video: constraints.video
- })
- .then(function (mediaStream) {
- mediaStream.getVideoTracks().forEach(function (track) {
- track.stop();
- });
- errorName = OpenViduError_1.OpenViduErrorName.INPUT_AUDIO_DEVICE_NOT_FOUND;
- errorMessage = error.toString();
- errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage));
- }).catch(function (e) {
- errorName = OpenViduError_1.OpenViduErrorName.INPUT_VIDEO_DEVICE_NOT_FOUND;
- errorMessage = error.toString();
- errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage));
- });
- break;
- case 'notallowederror':
- errorName = _this.stream.isSendScreen() ? OpenViduError_1.OpenViduErrorName.SCREEN_CAPTURE_DENIED : OpenViduError_1.OpenViduErrorName.DEVICE_ACCESS_DENIED;
- errorMessage = error.toString();
- errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage));
- break;
- case 'overconstrainederror':
- navigator.mediaDevices.getUserMedia({
- audio: false,
- video: constraints.video
- })
- .then(function (mediaStream) {
- mediaStream.getVideoTracks().forEach(function (track) {
- track.stop();
- });
- if (error.constraint.toLowerCase() === 'deviceid') {
- errorName = OpenViduError_1.OpenViduErrorName.INPUT_AUDIO_DEVICE_NOT_FOUND;
- errorMessage = "Audio input device with deviceId '" + constraints.audio.deviceId.exact + "' not found";
- }
- else {
- errorName = OpenViduError_1.OpenViduErrorName.PUBLISHER_PROPERTIES_ERROR;
- errorMessage = "Audio input device doesn't support the value passed for constraint '" + error.constraint + "'";
- }
- errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage));
- }).catch(function (e) {
- if (error.constraint.toLowerCase() === 'deviceid') {
- errorName = OpenViduError_1.OpenViduErrorName.INPUT_VIDEO_DEVICE_NOT_FOUND;
- errorMessage = "Video input device with deviceId '" + constraints.video.deviceId.exact + "' not found";
- }
- else {
- errorName = OpenViduError_1.OpenViduErrorName.PUBLISHER_PROPERTIES_ERROR;
- errorMessage = "Video input device doesn't support the value passed for constraint '" + error.constraint + "'";
- }
- errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage));
- });
- break;
- }
- });
- }
- else {
- reject(new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.NO_INPUT_SOURCE_SET, "Properties 'audioSource' and 'videoSource' cannot be set to false or null at the same time when calling 'OpenVidu.initPublisher'"));
- }
- })
- .catch(function (error) {
- errorCallback(error);
- });
- });
- };
- Publisher.prototype.updateSession = function (session) {
- this.session = session;
- this.stream.session = session;
- };
- Publisher.prototype.reestablishStreamPlayingEvent = function () {
- if (this.ee.getListeners('streamPlaying').length > 0) {
- this.addPlayEventToFirstVideo();
- }
- };
- Publisher.prototype.setPermissionDialogTimer = function (waitTime) {
- var _this = this;
- this.permissionDialogTimeout = setTimeout(function () {
- _this.emitEvent('accessDialogOpened', []);
- }, waitTime);
- };
- Publisher.prototype.clearPermissionDialogTimer = function (startTime, waitTime) {
- clearTimeout(this.permissionDialogTimeout);
- if ((Date.now() - startTime) > waitTime) {
- this.emitEvent('accessDialogClosed', []);
- }
- };
- return Publisher;
-}(StreamManager_1.StreamManager));
-exports.Publisher = Publisher;
-
-},{"../OpenViduInternal/Enums/OpenViduError":26,"../OpenViduInternal/Events/StreamEvent":34,"../OpenViduInternal/Events/StreamPropertyChangedEvent":36,"../OpenViduInternal/Events/VideoElementEvent":37,"./Session":21,"./Stream":22,"./StreamManager":23,"platform":8}],21:[function(require,module,exports){
-"use strict";
-Object.defineProperty(exports, "__esModule", { value: true });
-var Connection_1 = require("./Connection");
-var Subscriber_1 = require("./Subscriber");
-var ConnectionEvent_1 = require("../OpenViduInternal/Events/ConnectionEvent");
-var RecordingEvent_1 = require("../OpenViduInternal/Events/RecordingEvent");
-var SessionDisconnectedEvent_1 = require("../OpenViduInternal/Events/SessionDisconnectedEvent");
-var SignalEvent_1 = require("../OpenViduInternal/Events/SignalEvent");
-var StreamEvent_1 = require("../OpenViduInternal/Events/StreamEvent");
-var StreamPropertyChangedEvent_1 = require("../OpenViduInternal/Events/StreamPropertyChangedEvent");
-var OpenViduError_1 = require("../OpenViduInternal/Enums/OpenViduError");
-var VideoInsertMode_1 = require("../OpenViduInternal/Enums/VideoInsertMode");
-var platform = require("platform");
-var EventEmitter = require("wolfy87-eventemitter");
-var Session = (function () {
- function Session(openvidu) {
- this.streamManagers = [];
- this.remoteStreamsCreated = {};
- this.remoteConnections = {};
- this.speakingEventsEnabled = false;
- this.ee = new EventEmitter();
- this.openvidu = openvidu;
- }
- Session.prototype.connect = function (token, metadata) {
- var _this = this;
- return new Promise(function (resolve, reject) {
- _this.processToken(token);
- if (_this.openvidu.checkSystemRequirements()) {
- _this.options = {
- sessionId: _this.sessionId,
- participantId: token,
- metadata: !!metadata ? _this.stringClientMetadata(metadata) : ''
- };
- _this.connectAux(token).then(function () {
- resolve();
- }).catch(function (error) {
- reject(error);
- });
- }
- else {
- reject(new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.BROWSER_NOT_SUPPORTED, 'Browser ' + platform.name + ' ' + platform.version + ' is not supported in OpenVidu'));
- }
- });
- };
- Session.prototype.disconnect = function () {
- this.leave(false, 'disconnect');
- };
- Session.prototype.subscribe = function (stream, targetElement, param3, param4) {
- var properties = {};
- if (!!param3 && typeof param3 !== 'function') {
- properties = {
- insertMode: (typeof param3.insertMode !== 'undefined') ? ((typeof param3.insertMode === 'string') ? VideoInsertMode_1.VideoInsertMode[param3.insertMode] : properties.insertMode) : VideoInsertMode_1.VideoInsertMode.APPEND,
- subscribeToAudio: (typeof param3.subscribeToAudio !== 'undefined') ? param3.subscribeToAudio : true,
- subscribeToVideo: (typeof param3.subscribeToVideo !== 'undefined') ? param3.subscribeToVideo : true
- };
- }
- else {
- properties = {
- insertMode: VideoInsertMode_1.VideoInsertMode.APPEND,
- subscribeToAudio: true,
- subscribeToVideo: true
- };
- }
- var completionHandler;
- if (!!param3 && (typeof param3 === 'function')) {
- completionHandler = param3;
- }
- else if (!!param4) {
- completionHandler = param4;
- }
- console.info('Subscribing to ' + stream.connection.connectionId);
- stream.subscribe()
- .then(function () {
- console.info('Subscribed correctly to ' + stream.connection.connectionId);
- if (completionHandler !== undefined) {
- completionHandler(undefined);
- }
- })
- .catch(function (error) {
- if (completionHandler !== undefined) {
- completionHandler(error);
- }
- });
- var subscriber = new Subscriber_1.Subscriber(stream, targetElement, properties);
- if (!!subscriber.targetElement) {
- stream.streamManager.createVideoElement(subscriber.targetElement, properties.insertMode);
- }
- return subscriber;
- };
- Session.prototype.subscribeAsync = function (stream, targetElement, properties) {
- var _this = this;
- return new Promise(function (resolve, reject) {
- var subscriber;
- var callback = function (error) {
- if (!!error) {
- reject(error);
- }
- else {
- resolve(subscriber);
- }
- };
- if (!!properties) {
- subscriber = _this.subscribe(stream, targetElement, properties, callback);
- }
- else {
- subscriber = _this.subscribe(stream, targetElement, callback);
- }
- });
- };
- Session.prototype.unsubscribe = function (subscriber) {
- var connectionId = subscriber.stream.connection.connectionId;
- console.info('Unsubscribing from ' + connectionId);
- this.openvidu.sendRequest('unsubscribeFromVideo', { sender: subscriber.stream.connection.connectionId }, function (error, response) {
- if (error) {
- console.error('Error unsubscribing from ' + connectionId, error);
- }
- else {
- console.info('Unsubscribed correctly from ' + connectionId);
- }
- subscriber.stream.disposeWebRtcPeer();
- subscriber.stream.disposeMediaStream();
- });
- subscriber.stream.streamManager.removeAllVideos();
- };
- Session.prototype.publish = function (publisher) {
- var _this = this;
- return new Promise(function (resolve, reject) {
- publisher.session = _this;
- publisher.stream.session = _this;
- if (!publisher.stream.publishedOnce) {
- _this.connection.addStream(publisher.stream);
- publisher.stream.publish()
- .then(function () {
- resolve();
- })
- .catch(function (error) {
- reject(error);
- });
- }
- else {
- publisher.initialize()
- .then(function () {
- _this.connection.addStream(publisher.stream);
- publisher.reestablishStreamPlayingEvent();
- publisher.stream.publish()
- .then(function () {
- resolve();
- })
- .catch(function (error) {
- reject(error);
- });
- }).catch(function (error) {
- reject(error);
- });
- }
- });
- };
- Session.prototype.unpublish = function (publisher) {
- var stream = publisher.stream;
- if (!stream.connection) {
- console.error('The associated Connection object of this Publisher is null', stream);
- return;
- }
- else if (stream.connection !== this.connection) {
- console.error('The associated Connection object of this Publisher is not your local Connection.' +
- "Only moderators can force unpublish on remote Streams via 'forceUnpublish' method", stream);
- return;
- }
- else {
- console.info('Unpublishing local media (' + stream.connection.connectionId + ')');
- this.openvidu.sendRequest('unpublishVideo', function (error, response) {
- if (error) {
- console.error(error);
- }
- else {
- console.info('Media unpublished correctly');
- }
- });
- stream.disposeWebRtcPeer();
- delete stream.connection.stream;
- var streamEvent = new StreamEvent_1.StreamEvent(true, publisher, 'streamDestroyed', publisher.stream, 'unpublish');
- publisher.emitEvent('streamDestroyed', [streamEvent]);
- streamEvent.callDefaultBehavior();
- }
- };
- Session.prototype.forceDisconnect = function (connection) {
- var _this = this;
- return new Promise(function (resolve, reject) {
- console.info('Forcing disconnect for connection ' + connection.connectionId);
- _this.openvidu.sendRequest('forceDisconnect', { connectionId: connection.connectionId }, function (error, response) {
- if (error) {
- console.error('Error forcing disconnect for Connection ' + connection.connectionId, error);
- if (error.code === 401) {
- reject(new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.OPENVIDU_PERMISSION_DENIED, "You don't have permissions to force a disconnection"));
- }
- else {
- reject(error);
- }
- }
- else {
- console.info('Forcing disconnect correctly for Connection ' + connection.connectionId);
- resolve();
- }
- });
- });
- };
- Session.prototype.forceUnpublish = function (stream) {
- var _this = this;
- return new Promise(function (resolve, reject) {
- console.info('Forcing unpublish for stream ' + stream.streamId);
- _this.openvidu.sendRequest('forceUnpublish', { streamId: stream.streamId }, function (error, response) {
- if (error) {
- console.error('Error forcing unpublish for Stream ' + stream.streamId, error);
- if (error.code === 401) {
- reject(new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.OPENVIDU_PERMISSION_DENIED, "You don't have permissions to force an unpublishing"));
- }
- else {
- reject(error);
- }
- }
- else {
- console.info('Forcing unpublish correctly for Stream ' + stream.streamId);
- resolve();
- }
- });
- });
- };
- Session.prototype.signal = function (signal) {
- var _this = this;
- return new Promise(function (resolve, reject) {
- var signalMessage = {};
- if (signal.to && signal.to.length > 0) {
- var connectionIds_1 = [];
- signal.to.forEach(function (connection) {
- connectionIds_1.push(connection.connectionId);
- });
- signalMessage['to'] = connectionIds_1;
- }
- else {
- signalMessage['to'] = [];
- }
- signalMessage['data'] = signal.data ? signal.data : '';
- signalMessage['type'] = signal.type ? signal.type : '';
- _this.openvidu.sendRequest('sendMessage', {
- message: JSON.stringify(signalMessage)
- }, function (error, response) {
- if (!!error) {
- reject(error);
- }
- else {
- resolve();
- }
- });
- });
- };
- Session.prototype.on = function (type, handler) {
- this.ee.on(type, function (event) {
- if (event) {
- console.info("Event '" + type + "' triggered by 'Session'", event);
- }
- else {
- console.info("Event '" + type + "' triggered by 'Session'");
- }
- handler(event);
- });
- if (type === 'publisherStartSpeaking' || type === 'publisherStopSpeaking') {
- this.speakingEventsEnabled = true;
- for (var connectionId in this.remoteConnections) {
- var str = this.remoteConnections[connectionId].stream;
- if (!!str && !str.speechEvent && str.hasAudio) {
- str.enableSpeakingEvents();
- }
- }
- }
- return this;
- };
- Session.prototype.once = function (type, handler) {
- this.ee.once(type, function (event) {
- if (event) {
- console.info("Event '" + type + "' triggered by 'Session'", event);
- }
- else {
- console.info("Event '" + type + "' triggered by 'Session'");
- }
- handler(event);
- });
- if (type === 'publisherStartSpeaking' || type === 'publisherStopSpeaking') {
- this.speakingEventsEnabled = true;
- for (var connectionId in this.remoteConnections) {
- var str = this.remoteConnections[connectionId].stream;
- if (!!str && !str.speechEvent && str.hasAudio) {
- str.enableOnceSpeakingEvents();
- }
- }
- }
- return this;
- };
- Session.prototype.off = function (type, handler) {
- if (!handler) {
- this.ee.removeAllListeners(type);
- }
- else {
- this.ee.off(type, handler);
- }
- if (type === 'publisherStartSpeaking' || type === 'publisherStopSpeaking') {
- this.speakingEventsEnabled = false;
- for (var connectionId in this.remoteConnections) {
- var str = this.remoteConnections[connectionId].stream;
- if (!!str && !!str.speechEvent) {
- str.disableSpeakingEvents();
- }
- }
- }
- return this;
- };
- Session.prototype.onParticipantJoined = function (response) {
- var _this = this;
- this.getConnection(response.id, '')
- .then(function (connection) {
- console.warn('Connection ' + response.id + ' already exists in connections list');
- })
- .catch(function (openViduError) {
- var connection = new Connection_1.Connection(_this, response);
- _this.remoteConnections[response.id] = connection;
- _this.ee.emitEvent('connectionCreated', [new ConnectionEvent_1.ConnectionEvent(false, _this, 'connectionCreated', connection, '')]);
- });
- };
- Session.prototype.onParticipantLeft = function (msg) {
- var _this = this;
- this.getRemoteConnection(msg.connectionId, 'Remote connection ' + msg.connectionId + " unknown when 'onParticipantLeft'. " +
- 'Existing remote connections: ' + JSON.stringify(Object.keys(this.remoteConnections)))
- .then(function (connection) {
- if (!!connection.stream) {
- var stream = connection.stream;
- var streamEvent = new StreamEvent_1.StreamEvent(true, _this, 'streamDestroyed', stream, msg.reason);
- _this.ee.emitEvent('streamDestroyed', [streamEvent]);
- streamEvent.callDefaultBehavior();
- delete _this.remoteStreamsCreated[stream.streamId];
- }
- delete _this.remoteConnections[connection.connectionId];
- _this.ee.emitEvent('connectionDestroyed', [new ConnectionEvent_1.ConnectionEvent(false, _this, 'connectionDestroyed', connection, msg.reason)]);
- })
- .catch(function (openViduError) {
- console.error(openViduError);
- });
- };
- Session.prototype.onParticipantPublished = function (response) {
- var _this = this;
- var afterConnectionFound = function (connection) {
- _this.remoteConnections[connection.connectionId] = connection;
- if (!_this.remoteStreamsCreated[connection.stream.streamId]) {
- _this.ee.emitEvent('streamCreated', [new StreamEvent_1.StreamEvent(false, _this, 'streamCreated', connection.stream, '')]);
- }
- _this.remoteStreamsCreated[connection.stream.streamId] = true;
- };
- var connection;
- this.getRemoteConnection(response.id, "Remote connection '" + response.id + "' unknown when 'onParticipantPublished'. " +
- 'Existing remote connections: ' + JSON.stringify(Object.keys(this.remoteConnections)))
- .then(function (con) {
- connection = con;
- response.metadata = con.data;
- connection.options = response;
- connection.initRemoteStreams(response.streams);
- afterConnectionFound(connection);
- })
- .catch(function (openViduError) {
- connection = new Connection_1.Connection(_this, response);
- afterConnectionFound(connection);
- });
- };
- Session.prototype.onParticipantUnpublished = function (msg) {
- var _this = this;
- if (msg.connectionId === this.connection.connectionId) {
- this.stopPublisherStream(msg.reason);
- }
- else {
- this.getRemoteConnection(msg.connectionId, "Remote connection '" + msg.connectionId + "' unknown when 'onParticipantUnpublished'. " +
- 'Existing remote connections: ' + JSON.stringify(Object.keys(this.remoteConnections)))
- .then(function (connection) {
- var streamEvent = new StreamEvent_1.StreamEvent(true, _this, 'streamDestroyed', connection.stream, msg.reason);
- _this.ee.emitEvent('streamDestroyed', [streamEvent]);
- streamEvent.callDefaultBehavior();
- var streamId = connection.stream.streamId;
- delete _this.remoteStreamsCreated[streamId];
- connection.removeStream(streamId);
- })
- .catch(function (openViduError) {
- console.error(openViduError);
- });
- }
- };
- Session.prototype.onParticipantEvicted = function (msg) {
- if (msg.connectionId === this.connection.connectionId) {
- if (!!this.sessionId && !this.connection.disposed) {
- this.leave(true, msg.reason);
- }
- }
- };
- Session.prototype.onNewMessage = function (msg) {
- var _this = this;
- console.info('New signal: ' + JSON.stringify(msg));
- this.getConnection(msg.from, "Connection '" + msg.from + "' unknow when 'onNewMessage'. Existing remote connections: "
- + JSON.stringify(Object.keys(this.remoteConnections)) + '. Existing local connection: ' + this.connection.connectionId)
- .then(function (connection) {
- _this.ee.emitEvent('signal', [new SignalEvent_1.SignalEvent(_this, msg.type, msg.data, connection)]);
- _this.ee.emitEvent('signal:' + msg.type, [new SignalEvent_1.SignalEvent(_this, msg.type, msg.data, connection)]);
- })
- .catch(function (openViduError) {
- console.error(openViduError);
- });
- };
- Session.prototype.onStreamPropertyChanged = function (msg) {
- var _this = this;
- this.getRemoteConnection(msg.connectionId, 'Remote connection ' + msg.connectionId + " unknown when 'onStreamPropertyChanged'. " +
- 'Existing remote connections: ' + JSON.stringify(Object.keys(this.remoteConnections)))
- .then(function (connection) {
- if (!!connection.stream && connection.stream.streamId === msg.streamId) {
- var stream = connection.stream;
- var oldValue = void 0;
- switch (msg.property) {
- case 'audioActive':
- oldValue = stream.audioActive;
- msg.newValue = msg.newValue === 'true';
- stream.audioActive = msg.newValue;
- break;
- case 'videoActive':
- oldValue = stream.videoActive;
- msg.newValue = msg.newValue === 'true';
- stream.videoActive = msg.newValue;
- break;
- case 'videoDimensions':
- oldValue = stream.videoDimensions;
- msg.newValue = JSON.parse(JSON.parse(msg.newValue));
- stream.videoDimensions = msg.newValue;
- break;
- }
- _this.ee.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent_1.StreamPropertyChangedEvent(_this, stream, msg.property, msg.newValue, oldValue, msg.reason)]);
- stream.streamManager.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent_1.StreamPropertyChangedEvent(stream.streamManager, stream, msg.property, msg.newValue, oldValue, msg.reason)]);
- }
- else {
- console.error("No stream with streamId '" + msg.streamId + "' found for connection '" + msg.connectionId + "' on 'streamPropertyChanged' event");
- }
- })
- .catch(function (openViduError) {
- console.error(openViduError);
- });
- };
- Session.prototype.recvIceCandidate = function (msg) {
- var candidate = {
- candidate: msg.candidate,
- sdpMid: msg.sdpMid,
- sdpMLineIndex: msg.sdpMLineIndex,
- toJSON: function () {
- return { candidate: msg.candidate };
- }
- };
- this.getConnection(msg.endpointName, 'Connection not found for endpoint ' + msg.endpointName + '. Ice candidate will be ignored: ' + candidate)
- .then(function (connection) {
- var stream = connection.stream;
- stream.getWebRtcPeer().addIceCandidate(candidate).catch(function (error) {
- console.error('Error adding candidate for ' + stream.streamId
- + ' stream of endpoint ' + msg.endpointName + ': ' + error);
- });
- })
- .catch(function (openViduError) {
- console.error(openViduError);
- });
- };
- Session.prototype.onSessionClosed = function (msg) {
- console.info('Session closed: ' + JSON.stringify(msg));
- var s = msg.sessionId;
- if (s !== undefined) {
- this.ee.emitEvent('session-closed', [{
- session: s
- }]);
- }
- else {
- console.warn('Session undefined on session closed', msg);
- }
- };
- Session.prototype.onLostConnection = function () {
- console.warn('Lost connection in Session ' + this.sessionId);
- if (!!this.sessionId && !this.connection.disposed) {
- this.leave(true, 'networkDisconnect');
- }
- };
- Session.prototype.onRecoveredConnection = function () {
- console.warn('Recovered connection in Session ' + this.sessionId);
- this.ee.emitEvent('connectionRecovered', []);
- };
- Session.prototype.onMediaError = function (params) {
- console.error('Media error: ' + JSON.stringify(params));
- var err = params.error;
- if (err) {
- this.ee.emitEvent('error-media', [{
- error: err
- }]);
- }
- else {
- console.warn('Received undefined media error. Params:', params);
- }
- };
- Session.prototype.onRecordingStarted = function (response) {
- this.ee.emitEvent('recordingStarted', [new RecordingEvent_1.RecordingEvent(this, 'recordingStarted', response.id, response.name)]);
- };
- Session.prototype.onRecordingStopped = function (response) {
- this.ee.emitEvent('recordingStopped', [new RecordingEvent_1.RecordingEvent(this, 'recordingStopped', response.id, response.name)]);
- };
- Session.prototype.emitEvent = function (type, eventArray) {
- this.ee.emitEvent(type, eventArray);
- };
- Session.prototype.leave = function (forced, reason) {
- var _this = this;
- forced = !!forced;
- console.info('Leaving Session (forced=' + forced + ')');
- if (!!this.connection) {
- if (!this.connection.disposed && !forced) {
- this.openvidu.sendRequest('leaveRoom', function (error, response) {
- if (error) {
- console.error(error);
- }
- _this.openvidu.closeWs();
- });
- }
- else {
- this.openvidu.closeWs();
- }
- this.stopPublisherStream(reason);
- if (!this.connection.disposed) {
- var sessionDisconnectEvent = new SessionDisconnectedEvent_1.SessionDisconnectedEvent(this, reason);
- this.ee.emitEvent('sessionDisconnected', [sessionDisconnectEvent]);
- sessionDisconnectEvent.callDefaultBehavior();
- }
- }
- else {
- console.warn('You were not connected to the session ' + this.sessionId);
- }
- };
- Session.prototype.connectAux = function (token) {
- var _this = this;
- return new Promise(function (resolve, reject) {
- _this.openvidu.startWs(function (error) {
- if (!!error) {
- reject(error);
- }
- else {
- var joinParams = {
- token: (!!token) ? token : '',
- session: _this.sessionId,
- metadata: !!_this.options.metadata ? _this.options.metadata : '',
- secret: _this.openvidu.getSecret(),
- recorder: _this.openvidu.getRecorder(),
- };
- _this.openvidu.sendRequest('joinRoom', joinParams, function (error, response) {
- if (!!error) {
- reject(error);
- }
- else {
- _this.capabilities = {
- subscribe: true,
- publish: _this.openvidu.role !== 'SUBSCRIBER',
- forceUnpublish: _this.openvidu.role === 'MODERATOR',
- forceDisconnect: _this.openvidu.role === 'MODERATOR'
- };
- _this.connection = new Connection_1.Connection(_this);
- _this.connection.connectionId = response.id;
- _this.connection.data = response.metadata;
- var events_1 = {
- connections: new Array(),
- streams: new Array()
- };
- var existingParticipants = response.value;
- existingParticipants.forEach(function (participant) {
- var connection = new Connection_1.Connection(_this, participant);
- _this.remoteConnections[connection.connectionId] = connection;
- events_1.connections.push(connection);
- if (!!connection.stream) {
- _this.remoteStreamsCreated[connection.stream.streamId] = true;
- events_1.streams.push(connection.stream);
- }
- });
- _this.ee.emitEvent('connectionCreated', [new ConnectionEvent_1.ConnectionEvent(false, _this, 'connectionCreated', _this.connection, '')]);
- events_1.connections.forEach(function (connection) {
- _this.ee.emitEvent('connectionCreated', [new ConnectionEvent_1.ConnectionEvent(false, _this, 'connectionCreated', connection, '')]);
- });
- events_1.streams.forEach(function (stream) {
- _this.ee.emitEvent('streamCreated', [new StreamEvent_1.StreamEvent(false, _this, 'streamCreated', stream, '')]);
- });
- resolve();
- }
- });
- }
- });
- });
- };
- Session.prototype.stopPublisherStream = function (reason) {
- if (!!this.connection.stream) {
- this.connection.stream.disposeWebRtcPeer();
- if (this.connection.stream.isLocalStreamPublished) {
- this.connection.stream.ee.emitEvent('local-stream-destroyed', [reason]);
- }
- }
- };
- Session.prototype.stringClientMetadata = function (metadata) {
- if (typeof metadata !== 'string') {
- return JSON.stringify(metadata);
- }
- else {
- return metadata;
- }
- };
- Session.prototype.getConnection = function (connectionId, errorMessage) {
- var _this = this;
- return new Promise(function (resolve, reject) {
- var connection = _this.remoteConnections[connectionId];
- if (!!connection) {
- resolve(connection);
- }
- else {
- if (_this.connection.connectionId === connectionId) {
- resolve(_this.connection);
- }
- else {
- reject(new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.GENERIC_ERROR, errorMessage));
- }
- }
- });
- };
- Session.prototype.getRemoteConnection = function (connectionId, errorMessage) {
- var _this = this;
- return new Promise(function (resolve, reject) {
- var connection = _this.remoteConnections[connectionId];
- if (!!connection) {
- resolve(connection);
- }
- else {
- reject(new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.GENERIC_ERROR, errorMessage));
- }
- });
- };
- Session.prototype.processToken = function (token) {
- var url = new URL(token);
- this.sessionId = url.searchParams.get('sessionId');
- var secret = url.searchParams.get('secret');
- var recorder = url.searchParams.get('recorder');
- var turnUsername = url.searchParams.get('turnUsername');
- var turnCredential = url.searchParams.get('turnCredential');
- var role = url.searchParams.get('role');
- if (!!secret) {
- this.openvidu.secret = secret;
- }
- if (!!recorder) {
- this.openvidu.recorder = true;
- }
- if (!!turnUsername && !!turnCredential) {
- var stunUrl = 'stun:' + url.hostname + ':3478';
- var turnUrl1 = 'turn:' + url.hostname + ':3478';
- var turnUrl2 = turnUrl1 + '?transport=tcp';
- this.openvidu.iceServers = [
- { urls: [stunUrl] },
- { urls: [turnUrl1, turnUrl2], username: turnUsername, credential: turnCredential }
- ];
- console.log('TURN temp credentials [' + turnUsername + ':' + turnCredential + ']');
- }
- if (!!role) {
- this.openvidu.role = role;
- }
- this.openvidu.wsUri = 'wss://' + url.host + '/openvidu';
- };
- return Session;
-}());
-exports.Session = Session;
-
-},{"../OpenViduInternal/Enums/OpenViduError":26,"../OpenViduInternal/Enums/VideoInsertMode":27,"../OpenViduInternal/Events/ConnectionEvent":28,"../OpenViduInternal/Events/RecordingEvent":31,"../OpenViduInternal/Events/SessionDisconnectedEvent":32,"../OpenViduInternal/Events/SignalEvent":33,"../OpenViduInternal/Events/StreamEvent":34,"../OpenViduInternal/Events/StreamPropertyChangedEvent":36,"./Connection":17,"./Subscriber":24,"platform":8,"wolfy87-eventemitter":15}],22:[function(require,module,exports){
-"use strict";
-Object.defineProperty(exports, "__esModule", { value: true });
-var WebRtcPeer_1 = require("../OpenViduInternal/WebRtcPeer/WebRtcPeer");
-var WebRtcStats_1 = require("../OpenViduInternal/WebRtcStats/WebRtcStats");
-var PublisherSpeakingEvent_1 = require("../OpenViduInternal/Events/PublisherSpeakingEvent");
-var EventEmitter = require("wolfy87-eventemitter");
-var hark = require("hark");
-var OpenViduError_1 = require("../OpenViduInternal/Enums/OpenViduError");
-var Stream = (function () {
- function Stream(session, options) {
- var _this = this;
- this.ee = new EventEmitter();
- this.isSubscribeToRemote = false;
- this.isLocalStreamReadyToPublish = false;
- this.isLocalStreamPublished = false;
- this.publishedOnce = false;
- this.session = session;
- if (options.hasOwnProperty('id')) {
- this.inboundStreamOpts = options;
- this.streamId = this.inboundStreamOpts.id;
- this.hasAudio = this.inboundStreamOpts.hasAudio;
- this.hasVideo = this.inboundStreamOpts.hasVideo;
- if (this.hasAudio) {
- this.audioActive = this.inboundStreamOpts.audioActive;
- }
- if (this.hasVideo) {
- this.videoActive = this.inboundStreamOpts.videoActive;
- this.typeOfVideo = (!this.inboundStreamOpts.typeOfVideo) ? undefined : this.inboundStreamOpts.typeOfVideo;
- this.frameRate = (this.inboundStreamOpts.frameRate === -1) ? undefined : this.inboundStreamOpts.frameRate;
- this.videoDimensions = this.inboundStreamOpts.videoDimensions;
- }
- }
- else {
- this.outboundStreamOpts = options;
- this.hasAudio = this.isSendAudio();
- this.hasVideo = this.isSendVideo();
- if (this.hasAudio) {
- this.audioActive = !!this.outboundStreamOpts.publisherProperties.publishAudio;
- }
- if (this.hasVideo) {
- this.videoActive = !!this.outboundStreamOpts.publisherProperties.publishVideo;
- this.frameRate = this.outboundStreamOpts.publisherProperties.frameRate;
- if (this.outboundStreamOpts.publisherProperties.videoSource instanceof MediaStreamTrack) {
- this.typeOfVideo = 'CUSTOM';
- }
- else {
- this.typeOfVideo = this.isSendScreen() ? 'SCREEN' : 'CAMERA';
- }
- }
- }
- this.ee.on('mediastream-updated', function () {
- _this.streamManager.updateMediaStream(_this.mediaStream);
- console.debug('Video srcObject [' + _this.mediaStream + '] updated in stream [' + _this.streamId + ']');
- });
- }
- Stream.prototype.getMediaStream = function () {
- return this.mediaStream;
- };
- Stream.prototype.setMediaStream = function (mediaStream) {
- this.mediaStream = mediaStream;
- };
- Stream.prototype.updateMediaStreamInVideos = function () {
- this.ee.emitEvent('mediastream-updated');
- };
- Stream.prototype.getWebRtcPeer = function () {
- return this.webRtcPeer;
- };
- Stream.prototype.getRTCPeerConnection = function () {
- return this.webRtcPeer.pc;
- };
- Stream.prototype.subscribeToMyRemote = function (value) {
- this.isSubscribeToRemote = value;
- };
- Stream.prototype.setOutboundStreamOptions = function (outboundStreamOpts) {
- this.outboundStreamOpts = outboundStreamOpts;
- };
- Stream.prototype.subscribe = function () {
- var _this = this;
- return new Promise(function (resolve, reject) {
- _this.initWebRtcPeerReceive()
- .then(function () {
- resolve();
- })
- .catch(function (error) {
- reject(error);
- });
- });
- };
- Stream.prototype.publish = function () {
- var _this = this;
- return new Promise(function (resolve, reject) {
- if (_this.isLocalStreamReadyToPublish) {
- _this.initWebRtcPeerSend()
- .then(function () {
- resolve();
- })
- .catch(function (error) {
- reject(error);
- });
- }
- else {
- _this.ee.once('stream-ready-to-publish', function () {
- _this.publish()
- .then(function () {
- resolve();
- })
- .catch(function (error) {
- reject(error);
- });
- });
- }
- });
- };
- Stream.prototype.disposeWebRtcPeer = function () {
- if (this.webRtcPeer) {
- this.webRtcPeer.dispose();
- }
- if (this.speechEvent) {
- this.speechEvent.stop();
- }
- this.stopWebRtcStats();
- console.info((!!this.outboundStreamOpts ? 'Outbound ' : 'Inbound ') + "WebRTCPeer from 'Stream' with id [" + this.streamId + '] is now closed');
- };
- Stream.prototype.disposeMediaStream = function () {
- if (this.mediaStream) {
- this.mediaStream.getAudioTracks().forEach(function (track) {
- track.stop();
- });
- this.mediaStream.getVideoTracks().forEach(function (track) {
- track.stop();
- });
- delete this.mediaStream;
- }
- console.info((!!this.outboundStreamOpts ? 'Local ' : 'Remote ') + "MediaStream from 'Stream' with id [" + this.streamId + '] is now disposed');
- };
- Stream.prototype.displayMyRemote = function () {
- return this.isSubscribeToRemote;
- };
- Stream.prototype.isSendAudio = function () {
- return (!!this.outboundStreamOpts &&
- this.outboundStreamOpts.publisherProperties.audioSource !== null &&
- this.outboundStreamOpts.publisherProperties.audioSource !== false);
- };
- Stream.prototype.isSendVideo = function () {
- return (!!this.outboundStreamOpts &&
- this.outboundStreamOpts.publisherProperties.videoSource !== null &&
- this.outboundStreamOpts.publisherProperties.videoSource !== false);
- };
- Stream.prototype.isSendScreen = function () {
- return (!!this.outboundStreamOpts &&
- this.outboundStreamOpts.publisherProperties.videoSource === 'screen');
- };
- Stream.prototype.setSpeechEventIfNotExists = function () {
- if (!this.speechEvent) {
- var harkOptions = this.session.openvidu.advancedConfiguration.publisherSpeakingEventsOptions || {};
- harkOptions.interval = (typeof harkOptions.interval === 'number') ? harkOptions.interval : 50;
- harkOptions.threshold = (typeof harkOptions.threshold === 'number') ? harkOptions.threshold : -50;
- this.speechEvent = hark(this.mediaStream, harkOptions);
- }
- };
- Stream.prototype.enableSpeakingEvents = function () {
- var _this = this;
- this.setSpeechEventIfNotExists();
- this.speechEvent.on('speaking', function () {
- _this.session.emitEvent('publisherStartSpeaking', [new PublisherSpeakingEvent_1.PublisherSpeakingEvent(_this.session, 'publisherStartSpeaking', _this.connection, _this.streamId)]);
- });
- this.speechEvent.on('stopped_speaking', function () {
- _this.session.emitEvent('publisherStopSpeaking', [new PublisherSpeakingEvent_1.PublisherSpeakingEvent(_this.session, 'publisherStopSpeaking', _this.connection, _this.streamId)]);
- });
- };
- Stream.prototype.enableOnceSpeakingEvents = function () {
- var _this = this;
- this.setSpeechEventIfNotExists();
- this.speechEvent.on('speaking', function () {
- _this.session.emitEvent('publisherStartSpeaking', [new PublisherSpeakingEvent_1.PublisherSpeakingEvent(_this.session, 'publisherStartSpeaking', _this.connection, _this.streamId)]);
- _this.disableSpeakingEvents();
- });
- this.speechEvent.on('stopped_speaking', function () {
- _this.session.emitEvent('publisherStopSpeaking', [new PublisherSpeakingEvent_1.PublisherSpeakingEvent(_this.session, 'publisherStopSpeaking', _this.connection, _this.streamId)]);
- _this.disableSpeakingEvents();
- });
- };
- Stream.prototype.disableSpeakingEvents = function () {
- this.speechEvent.stop();
- this.speechEvent = undefined;
- };
- Stream.prototype.isLocal = function () {
- return (!this.inboundStreamOpts && !!this.outboundStreamOpts);
- };
- Stream.prototype.getSelectedIceCandidate = function () {
- var _this = this;
- return new Promise(function (resolve, reject) {
- _this.webRtcStats.getSelectedIceCandidateInfo()
- .then(function (report) { return resolve(report); })
- .catch(function (error) { return reject(error); });
- });
- };
- Stream.prototype.getRemoteIceCandidateList = function () {
- return this.webRtcPeer.remoteCandidatesQueue;
- };
- Stream.prototype.getLocalIceCandidateList = function () {
- return this.webRtcPeer.localCandidatesQueue;
- };
- Stream.prototype.initWebRtcPeerSend = function () {
- var _this = this;
- return new Promise(function (resolve, reject) {
- var userMediaConstraints = {
- audio: _this.isSendAudio(),
- video: _this.isSendVideo()
- };
- var options = {
- mediaStream: _this.mediaStream,
- mediaConstraints: userMediaConstraints,
- onicecandidate: _this.connection.sendIceCandidate.bind(_this.connection),
- iceServers: _this.getIceServersConf(),
- simulcast: false
- };
- var successCallback = function (sdpOfferParam) {
- console.debug('Sending SDP offer to publish as '
- + _this.streamId, sdpOfferParam);
- var typeOfVideo = '';
- if (_this.isSendVideo()) {
- typeOfVideo = _this.outboundStreamOpts.publisherProperties.videoSource instanceof MediaStreamTrack ? 'CUSTOM' : (_this.isSendScreen() ? 'SCREEN' : 'CAMERA');
- }
- _this.session.openvidu.sendRequest('publishVideo', {
- sdpOffer: sdpOfferParam,
- doLoopback: _this.displayMyRemote() || false,
- hasAudio: _this.isSendAudio(),
- hasVideo: _this.isSendVideo(),
- audioActive: _this.audioActive,
- videoActive: _this.videoActive,
- typeOfVideo: typeOfVideo,
- frameRate: !!_this.frameRate ? _this.frameRate : -1,
- videoDimensions: JSON.stringify(_this.videoDimensions)
- }, function (error, response) {
- if (error) {
- if (error.code === 401) {
- reject(new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.OPENVIDU_PERMISSION_DENIED, "You don't have permissions to publish"));
- }
- else {
- reject('Error on publishVideo: ' + JSON.stringify(error));
- }
- }
- else {
- _this.webRtcPeer.processAnswer(response.sdpAnswer)
- .then(function () {
- _this.streamId = response.id;
- _this.isLocalStreamPublished = true;
- _this.publishedOnce = true;
- if (_this.displayMyRemote()) {
- _this.remotePeerSuccessfullyEstablished();
- }
- _this.ee.emitEvent('stream-created-by-publisher');
- _this.initWebRtcStats();
- resolve();
- })
- .catch(function (error) {
- reject(error);
- });
- console.info("'Publisher' successfully published to session");
- }
- });
- };
- if (_this.displayMyRemote()) {
- _this.webRtcPeer = new WebRtcPeer_1.WebRtcPeerSendrecv(options);
- }
- else {
- _this.webRtcPeer = new WebRtcPeer_1.WebRtcPeerSendonly(options);
- }
- _this.webRtcPeer.generateOffer().then(function (offer) {
- successCallback(offer);
- }).catch(function (error) {
- reject(new Error('(publish) SDP offer error: ' + JSON.stringify(error)));
- });
- });
- };
- Stream.prototype.initWebRtcPeerReceive = function () {
- var _this = this;
- return new Promise(function (resolve, reject) {
- var offerConstraints = {
- audio: _this.inboundStreamOpts.hasAudio,
- video: _this.inboundStreamOpts.hasVideo
- };
- console.debug("'Session.subscribe(Stream)' called. Constraints of generate SDP offer", offerConstraints);
- var options = {
- onicecandidate: _this.connection.sendIceCandidate.bind(_this.connection),
- mediaConstraints: offerConstraints,
- iceServers: _this.getIceServersConf(),
- simulcast: false
- };
- var successCallback = function (sdpOfferParam) {
- console.debug('Sending SDP offer to subscribe to '
- + _this.streamId, sdpOfferParam);
- _this.session.openvidu.sendRequest('receiveVideoFrom', {
- sender: _this.streamId,
- sdpOffer: sdpOfferParam
- }, function (error, response) {
- if (error) {
- reject(new Error('Error on recvVideoFrom: ' + JSON.stringify(error)));
- }
- else {
- _this.webRtcPeer.processAnswer(response.sdpAnswer).then(function () {
- _this.remotePeerSuccessfullyEstablished();
- _this.initWebRtcStats();
- resolve();
- }).catch(function (error) {
- reject(error);
- });
- }
- });
- };
- _this.webRtcPeer = new WebRtcPeer_1.WebRtcPeerRecvonly(options);
- _this.webRtcPeer.generateOffer()
- .then(function (offer) {
- successCallback(offer);
- })
- .catch(function (error) {
- reject(new Error('(subscribe) SDP offer error: ' + JSON.stringify(error)));
- });
- });
- };
- Stream.prototype.remotePeerSuccessfullyEstablished = function () {
- this.mediaStream = this.webRtcPeer.pc.getRemoteStreams()[0];
- console.debug('Peer remote stream', this.mediaStream);
- if (!!this.mediaStream) {
- this.ee.emitEvent('mediastream-updated');
- if (!this.displayMyRemote() && !!this.mediaStream.getAudioTracks()[0] && this.session.speakingEventsEnabled) {
- this.enableSpeakingEvents();
- }
- }
- };
- Stream.prototype.initWebRtcStats = function () {
- this.webRtcStats = new WebRtcStats_1.WebRtcStats(this);
- this.webRtcStats.initWebRtcStats();
- };
- Stream.prototype.stopWebRtcStats = function () {
- if (!!this.webRtcStats && this.webRtcStats.isEnabled()) {
- this.webRtcStats.stopWebRtcStats();
- }
- };
- Stream.prototype.getIceServersConf = function () {
- var returnValue;
- if (!!this.session.openvidu.advancedConfiguration.iceServers) {
- returnValue = this.session.openvidu.advancedConfiguration.iceServers === 'freeice' ?
- undefined :
- this.session.openvidu.advancedConfiguration.iceServers;
- }
- else if (this.session.openvidu.iceServers) {
- returnValue = this.session.openvidu.iceServers;
- }
- else {
- returnValue = undefined;
- }
- return returnValue;
- };
- return Stream;
-}());
-exports.Stream = Stream;
-
-},{"../OpenViduInternal/Enums/OpenViduError":26,"../OpenViduInternal/Events/PublisherSpeakingEvent":30,"../OpenViduInternal/WebRtcPeer/WebRtcPeer":49,"../OpenViduInternal/WebRtcStats/WebRtcStats":50,"hark":5,"wolfy87-eventemitter":15}],23:[function(require,module,exports){
-"use strict";
-Object.defineProperty(exports, "__esModule", { value: true });
-var StreamManagerEvent_1 = require("../OpenViduInternal/Events/StreamManagerEvent");
-var VideoElementEvent_1 = require("../OpenViduInternal/Events/VideoElementEvent");
-var VideoInsertMode_1 = require("../OpenViduInternal/Enums/VideoInsertMode");
-var EventEmitter = require("wolfy87-eventemitter");
-var StreamManager = (function () {
- function StreamManager(stream, targetElement) {
- var _this = this;
- this.videos = [];
- this.lazyLaunchVideoElementCreatedEvent = false;
- this.ee = new EventEmitter();
- this.stream = stream;
- this.stream.streamManager = this;
- this.remote = !this.stream.isLocal();
- if (!!targetElement) {
- var targEl = void 0;
- if (typeof targetElement === 'string') {
- targEl = document.getElementById(targetElement);
- }
- else if (targetElement instanceof HTMLElement) {
- targEl = targetElement;
- }
- if (!!targEl) {
- this.firstVideoElement = {
- targetElement: targEl,
- video: document.createElement('video'),
- id: ''
- };
- this.targetElement = targEl;
- this.element = targEl;
- }
- }
- this.canPlayListener = function () {
- if (_this.stream.isLocal()) {
- if (!_this.stream.displayMyRemote()) {
- console.info("Your local 'Stream' with id [" + _this.stream.streamId + '] video is now playing');
- _this.ee.emitEvent('videoPlaying', [new VideoElementEvent_1.VideoElementEvent(_this.videos[0].video, _this, 'videoPlaying')]);
- }
- else {
- console.info("Your own remote 'Stream' with id [" + _this.stream.streamId + '] video is now playing');
- _this.ee.emitEvent('remoteVideoPlaying', [new VideoElementEvent_1.VideoElementEvent(_this.videos[0].video, _this, 'remoteVideoPlaying')]);
- }
- }
- else {
- console.info("Remote 'Stream' with id [" + _this.stream.streamId + '] video is now playing');
- _this.ee.emitEvent('videoPlaying', [new VideoElementEvent_1.VideoElementEvent(_this.videos[0].video, _this, 'videoPlaying')]);
- }
- _this.ee.emitEvent('streamPlaying', [new StreamManagerEvent_1.StreamManagerEvent(_this)]);
- };
- }
- StreamManager.prototype.on = function (type, handler) {
- var _this = this;
- this.ee.on(type, function (event) {
- if (event) {
- console.info("Event '" + type + "' triggered by '" + (_this.remote ? 'Subscriber' : 'Publisher') + "'", event);
- }
- else {
- console.info("Event '" + type + "' triggered by '" + (_this.remote ? 'Subscriber' : 'Publisher') + "'");
- }
- handler(event);
- });
- if (type === 'videoElementCreated') {
- if (!!this.stream && this.lazyLaunchVideoElementCreatedEvent) {
- this.ee.emitEvent('videoElementCreated', [new VideoElementEvent_1.VideoElementEvent(this.videos[0].video, this, 'videoElementCreated')]);
- this.lazyLaunchVideoElementCreatedEvent = false;
- }
- }
- if (type === 'streamPlaying' || type === 'videoPlaying') {
- if (this.videos[0] && this.videos[0].video &&
- this.videos[0].video.currentTime > 0 &&
- this.videos[0].video.paused === false &&
- this.videos[0].video.ended === false &&
- this.videos[0].video.readyState === 4) {
- this.ee.emitEvent('streamPlaying', [new StreamManagerEvent_1.StreamManagerEvent(this)]);
- this.ee.emitEvent('videoPlaying', [new VideoElementEvent_1.VideoElementEvent(this.videos[0].video, this, 'videoPlaying')]);
- }
- }
- return this;
- };
- StreamManager.prototype.once = function (type, handler) {
- this.ee.once(type, function (event) {
- if (event) {
- console.info("Event '" + type + "' triggered once", event);
- }
- else {
- console.info("Event '" + type + "' triggered once");
- }
- handler(event);
- });
- if (type === 'videoElementCreated') {
- if (!!this.stream && this.lazyLaunchVideoElementCreatedEvent) {
- this.ee.emitEvent('videoElementCreated', [new VideoElementEvent_1.VideoElementEvent(this.videos[0].video, this, 'videoElementCreated')]);
- }
- }
- if (type === 'streamPlaying' || type === 'videoPlaying') {
- if (this.videos[0] && this.videos[0].video &&
- this.videos[0].video.currentTime > 0 &&
- this.videos[0].video.paused === false &&
- this.videos[0].video.ended === false &&
- this.videos[0].video.readyState === 4) {
- this.ee.emitEvent('streamPlaying', [new StreamManagerEvent_1.StreamManagerEvent(this)]);
- this.ee.emitEvent('videoPlaying', [new VideoElementEvent_1.VideoElementEvent(this.videos[0].video, this, 'videoPlaying')]);
- }
- }
- return this;
- };
- StreamManager.prototype.off = function (type, handler) {
- if (!handler) {
- this.ee.removeAllListeners(type);
- }
- else {
- this.ee.off(type, handler);
- }
- return this;
- };
- StreamManager.prototype.addVideoElement = function (video) {
- this.initializeVideoProperties(video);
- for (var _i = 0, _a = this.videos; _i < _a.length; _i++) {
- var v = _a[_i];
- if (v.video === video) {
- return 0;
- }
- }
- var returnNumber = 1;
- for (var _b = 0, _c = this.stream.session.streamManagers; _b < _c.length; _b++) {
- var streamManager = _c[_b];
- if (streamManager.disassociateVideo(video)) {
- returnNumber = -1;
- break;
- }
- }
- this.stream.session.streamManagers.forEach(function (streamManager) {
- streamManager.disassociateVideo(video);
- });
- this.pushNewStreamManagerVideo({
- video: video,
- id: video.id
- });
- console.info('New video element associated to ', this);
- return returnNumber;
- };
- StreamManager.prototype.createVideoElement = function (targetElement, insertMode) {
- var targEl;
- if (typeof targetElement === 'string') {
- targEl = document.getElementById(targEl);
- if (!targEl) {
- throw new Error("The provided 'targetElement' couldn't be resolved to any HTML element: " + targetElement);
- }
- }
- else if (targetElement instanceof HTMLElement) {
- targEl = targetElement;
- }
- else {
- throw new Error("The provided 'targetElement' couldn't be resolved to any HTML element: " + targetElement);
- }
- var video = document.createElement('video');
- this.initializeVideoProperties(video);
- var insMode = !!insertMode ? insertMode : VideoInsertMode_1.VideoInsertMode.APPEND;
- switch (insMode) {
- case VideoInsertMode_1.VideoInsertMode.AFTER:
- targEl.parentNode.insertBefore(video, targEl.nextSibling);
- break;
- case VideoInsertMode_1.VideoInsertMode.APPEND:
- targEl.appendChild(video);
- break;
- case VideoInsertMode_1.VideoInsertMode.BEFORE:
- targEl.parentNode.insertBefore(video, targEl);
- break;
- case VideoInsertMode_1.VideoInsertMode.PREPEND:
- targEl.insertBefore(video, targEl.childNodes[0]);
- break;
- case VideoInsertMode_1.VideoInsertMode.REPLACE:
- targEl.parentNode.replaceChild(video, targEl);
- break;
- default:
- insMode = VideoInsertMode_1.VideoInsertMode.APPEND;
- targEl.appendChild(video);
- break;
- }
- var v = {
- targetElement: targEl,
- video: video,
- insertMode: insMode,
- id: video.id
- };
- this.pushNewStreamManagerVideo(v);
- this.ee.emitEvent('videoElementCreated', [new VideoElementEvent_1.VideoElementEvent(v.video, this, 'videoElementCreated')]);
- this.lazyLaunchVideoElementCreatedEvent = !!this.firstVideoElement;
- return video;
- };
- StreamManager.prototype.initializeVideoProperties = function (video) {
- if (!(this.stream.isLocal() && this.stream.displayMyRemote())) {
- video.srcObject = this.stream.getMediaStream();
- }
- video.autoplay = true;
- video.controls = false;
- if (!video.id) {
- video.id = (this.remote ? 'remote-' : 'local-') + 'video-' + this.stream.streamId;
- if (!this.id && !!this.targetElement) {
- this.id = video.id;
- }
- }
- if (!this.remote && !this.stream.displayMyRemote()) {
- video.muted = true;
- if (this.stream.outboundStreamOpts.publisherProperties.mirror) {
- this.mirrorVideo(video);
- }
- }
- };
- StreamManager.prototype.removeAllVideos = function () {
- var _this = this;
- for (var i = this.stream.session.streamManagers.length - 1; i >= 0; --i) {
- if (this.stream.session.streamManagers[i] === this) {
- this.stream.session.streamManagers.splice(i, 1);
- }
- }
- this.videos.slice().reverse().forEach(function (streamManagerVideo, index, videos) {
- streamManagerVideo.video.removeEventListener('canplay', _this.canPlayListener);
- if (!!streamManagerVideo.targetElement) {
- streamManagerVideo.video.parentNode.removeChild(streamManagerVideo.video);
- _this.ee.emitEvent('videoElementDestroyed', [new VideoElementEvent_1.VideoElementEvent(streamManagerVideo.video, _this, 'videoElementDestroyed')]);
- _this.videos.splice(videos.length - 1 - index, 1);
- }
- else {
- streamManagerVideo.video.srcObject = null;
- }
- });
- };
- StreamManager.prototype.disassociateVideo = function (video) {
- var disassociated = false;
- for (var i = 0; i < this.videos.length; i++) {
- if (this.videos[i].video === video) {
- this.videos.splice(i, 1);
- disassociated = true;
- console.info('Video element disassociated from ', this);
- break;
- }
- }
- return disassociated;
- };
- StreamManager.prototype.addPlayEventToFirstVideo = function () {
- if ((!!this.videos[0]) && (!!this.videos[0].video) && (this.videos[0].video.oncanplay === null)) {
- this.videos[0].video.addEventListener('canplay', this.canPlayListener);
- }
- };
- StreamManager.prototype.updateMediaStream = function (mediaStream) {
- this.videos.forEach(function (streamManagerVideo) {
- streamManagerVideo.video.srcObject = mediaStream;
- });
- };
- StreamManager.prototype.emitEvent = function (type, eventArray) {
- this.ee.emitEvent(type, eventArray);
- };
- StreamManager.prototype.pushNewStreamManagerVideo = function (streamManagerVideo) {
- this.videos.push(streamManagerVideo);
- this.addPlayEventToFirstVideo();
- if (this.stream.session.streamManagers.indexOf(this) === -1) {
- this.stream.session.streamManagers.push(this);
- }
- };
- StreamManager.prototype.mirrorVideo = function (video) {
- video.style.transform = 'rotateY(180deg)';
- video.style.webkitTransform = 'rotateY(180deg)';
- };
- return StreamManager;
-}());
-exports.StreamManager = StreamManager;
-
-},{"../OpenViduInternal/Enums/VideoInsertMode":27,"../OpenViduInternal/Events/StreamManagerEvent":35,"../OpenViduInternal/Events/VideoElementEvent":37,"wolfy87-eventemitter":15}],24:[function(require,module,exports){
-"use strict";
-var __extends = (this && this.__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 __());
- };
-})();
-Object.defineProperty(exports, "__esModule", { value: true });
-var StreamManager_1 = require("./StreamManager");
-var Subscriber = (function (_super) {
- __extends(Subscriber, _super);
- function Subscriber(stream, targEl, properties) {
- var _this = _super.call(this, stream, targEl) || this;
- _this.element = _this.targetElement;
- _this.stream = stream;
- _this.properties = properties;
- return _this;
- }
- Subscriber.prototype.subscribeToAudio = function (value) {
- this.stream.getMediaStream().getAudioTracks().forEach(function (track) {
- track.enabled = value;
- });
- console.info("'Subscriber' has " + (value ? 'subscribed to' : 'unsubscribed from') + ' its audio stream');
- return this;
- };
- Subscriber.prototype.subscribeToVideo = function (value) {
- this.stream.getMediaStream().getVideoTracks().forEach(function (track) {
- track.enabled = value;
- });
- console.info("'Subscriber' has " + (value ? 'subscribed to' : 'unsubscribed from') + ' its video stream');
- return this;
- };
- return Subscriber;
-}(StreamManager_1.StreamManager));
-exports.Subscriber = Subscriber;
-
-},{"./StreamManager":23}],25:[function(require,module,exports){
-"use strict";
-Object.defineProperty(exports, "__esModule", { value: true });
-var LocalRecorderState;
-(function (LocalRecorderState) {
- LocalRecorderState["READY"] = "READY";
- LocalRecorderState["RECORDING"] = "RECORDING";
- LocalRecorderState["PAUSED"] = "PAUSED";
- LocalRecorderState["FINISHED"] = "FINISHED";
-})(LocalRecorderState = exports.LocalRecorderState || (exports.LocalRecorderState = {}));
-
-},{}],26:[function(require,module,exports){
-"use strict";
-Object.defineProperty(exports, "__esModule", { value: true });
-var OpenViduErrorName;
-(function (OpenViduErrorName) {
- OpenViduErrorName["BROWSER_NOT_SUPPORTED"] = "BROWSER_NOT_SUPPORTED";
- OpenViduErrorName["DEVICE_ACCESS_DENIED"] = "DEVICE_ACCESS_DENIED";
- OpenViduErrorName["SCREEN_CAPTURE_DENIED"] = "SCREEN_CAPTURE_DENIED";
- OpenViduErrorName["SCREEN_SHARING_NOT_SUPPORTED"] = "SCREEN_SHARING_NOT_SUPPORTED";
- OpenViduErrorName["SCREEN_EXTENSION_NOT_INSTALLED"] = "SCREEN_EXTENSION_NOT_INSTALLED";
- OpenViduErrorName["SCREEN_EXTENSION_DISABLED"] = "SCREEN_EXTENSION_DISABLED";
- OpenViduErrorName["INPUT_VIDEO_DEVICE_NOT_FOUND"] = "INPUT_VIDEO_DEVICE_NOT_FOUND";
- OpenViduErrorName["INPUT_AUDIO_DEVICE_NOT_FOUND"] = "INPUT_AUDIO_DEVICE_NOT_FOUND";
- OpenViduErrorName["NO_INPUT_SOURCE_SET"] = "NO_INPUT_SOURCE_SET";
- OpenViduErrorName["PUBLISHER_PROPERTIES_ERROR"] = "PUBLISHER_PROPERTIES_ERROR";
- OpenViduErrorName["OPENVIDU_PERMISSION_DENIED"] = "OPENVIDU_PERMISSION_DENIED";
- OpenViduErrorName["OPENVIDU_NOT_CONNECTED"] = "OPENVIDU_NOT_CONNECTED";
- OpenViduErrorName["GENERIC_ERROR"] = "GENERIC_ERROR";
-})(OpenViduErrorName = exports.OpenViduErrorName || (exports.OpenViduErrorName = {}));
-var OpenViduError = (function () {
- function OpenViduError(name, message) {
- this.name = name;
- this.message = message;
- }
- return OpenViduError;
-}());
-exports.OpenViduError = OpenViduError;
-
-},{}],27:[function(require,module,exports){
-"use strict";
-Object.defineProperty(exports, "__esModule", { value: true });
-var VideoInsertMode;
-(function (VideoInsertMode) {
- VideoInsertMode["AFTER"] = "AFTER";
- VideoInsertMode["APPEND"] = "APPEND";
- VideoInsertMode["BEFORE"] = "BEFORE";
- VideoInsertMode["PREPEND"] = "PREPEND";
- VideoInsertMode["REPLACE"] = "REPLACE";
-})(VideoInsertMode = exports.VideoInsertMode || (exports.VideoInsertMode = {}));
-
-},{}],28:[function(require,module,exports){
-"use strict";
-var __extends = (this && this.__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 __());
- };
-})();
-Object.defineProperty(exports, "__esModule", { value: true });
-var Event_1 = require("./Event");
-var ConnectionEvent = (function (_super) {
- __extends(ConnectionEvent, _super);
- function ConnectionEvent(cancelable, target, type, connection, reason) {
- var _this = _super.call(this, cancelable, target, type) || this;
- _this.connection = connection;
- _this.reason = reason;
- return _this;
- }
- ConnectionEvent.prototype.callDefaultBehavior = function () { };
- return ConnectionEvent;
-}(Event_1.Event));
-exports.ConnectionEvent = ConnectionEvent;
-
-},{"./Event":29}],29:[function(require,module,exports){
-"use strict";
-Object.defineProperty(exports, "__esModule", { value: true });
-var Event = (function () {
- function Event(cancelable, target, type) {
- this.hasBeenPrevented = false;
- this.cancelable = cancelable;
- this.target = target;
- this.type = type;
- }
- Event.prototype.isDefaultPrevented = function () {
- return this.hasBeenPrevented;
- };
- Event.prototype.preventDefault = function () {
- this.callDefaultBehavior = function () { };
- this.hasBeenPrevented = true;
- };
- return Event;
-}());
-exports.Event = Event;
-
-},{}],30:[function(require,module,exports){
-"use strict";
-var __extends = (this && this.__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 __());
- };
-})();
-Object.defineProperty(exports, "__esModule", { value: true });
-var Event_1 = require("./Event");
-var PublisherSpeakingEvent = (function (_super) {
- __extends(PublisherSpeakingEvent, _super);
- function PublisherSpeakingEvent(target, type, connection, streamId) {
- var _this = _super.call(this, false, target, type) || this;
- _this.type = type;
- _this.connection = connection;
- _this.streamId = streamId;
- return _this;
- }
- PublisherSpeakingEvent.prototype.callDefaultBehavior = function () { };
- return PublisherSpeakingEvent;
-}(Event_1.Event));
-exports.PublisherSpeakingEvent = PublisherSpeakingEvent;
-
-},{"./Event":29}],31:[function(require,module,exports){
-"use strict";
-var __extends = (this && this.__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 __());
- };
-})();
-Object.defineProperty(exports, "__esModule", { value: true });
-var Event_1 = require("./Event");
-var RecordingEvent = (function (_super) {
- __extends(RecordingEvent, _super);
- function RecordingEvent(target, type, id, name) {
- var _this = _super.call(this, false, target, type) || this;
- _this.id = id;
- if (name !== id) {
- _this.name = name;
- }
- return _this;
- }
- RecordingEvent.prototype.callDefaultBehavior = function () { };
- return RecordingEvent;
-}(Event_1.Event));
-exports.RecordingEvent = RecordingEvent;
-
-},{"./Event":29}],32:[function(require,module,exports){
-"use strict";
-var __extends = (this && this.__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 __());
- };
-})();
-Object.defineProperty(exports, "__esModule", { value: true });
-var Event_1 = require("./Event");
-var SessionDisconnectedEvent = (function (_super) {
- __extends(SessionDisconnectedEvent, _super);
- function SessionDisconnectedEvent(target, reason) {
- var _this = _super.call(this, true, target, 'sessionDisconnected') || this;
- _this.reason = reason;
- return _this;
- }
- SessionDisconnectedEvent.prototype.callDefaultBehavior = function () {
- console.info("Calling default behavior upon '" + this.type + "' event dispatched by 'Session'");
- var session = this.target;
- for (var connectionId in session.remoteConnections) {
- if (!!session.remoteConnections[connectionId].stream) {
- session.remoteConnections[connectionId].stream.disposeWebRtcPeer();
- session.remoteConnections[connectionId].stream.disposeMediaStream();
- if (session.remoteConnections[connectionId].stream.streamManager) {
- session.remoteConnections[connectionId].stream.streamManager.removeAllVideos();
- }
- delete session.remoteStreamsCreated[session.remoteConnections[connectionId].stream.streamId];
- session.remoteConnections[connectionId].dispose();
- }
- delete session.remoteConnections[connectionId];
- }
- };
- return SessionDisconnectedEvent;
-}(Event_1.Event));
-exports.SessionDisconnectedEvent = SessionDisconnectedEvent;
-
-},{"./Event":29}],33:[function(require,module,exports){
-"use strict";
-var __extends = (this && this.__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 __());
- };
-})();
-Object.defineProperty(exports, "__esModule", { value: true });
-var Event_1 = require("./Event");
-var SignalEvent = (function (_super) {
- __extends(SignalEvent, _super);
- function SignalEvent(target, type, data, from) {
- var _this = _super.call(this, false, target, type) || this;
- _this.type = type;
- _this.data = data;
- _this.from = from;
- return _this;
- }
- SignalEvent.prototype.callDefaultBehavior = function () { };
- return SignalEvent;
-}(Event_1.Event));
-exports.SignalEvent = SignalEvent;
-
-},{"./Event":29}],34:[function(require,module,exports){
-"use strict";
-var __extends = (this && this.__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 __());
- };
-})();
-Object.defineProperty(exports, "__esModule", { value: true });
-var Event_1 = require("./Event");
-var Publisher_1 = require("../../OpenVidu/Publisher");
-var Session_1 = require("../../OpenVidu/Session");
-var StreamEvent = (function (_super) {
- __extends(StreamEvent, _super);
- function StreamEvent(cancelable, target, type, stream, reason) {
- var _this = _super.call(this, cancelable, target, type) || this;
- _this.stream = stream;
- _this.reason = reason;
- return _this;
- }
- StreamEvent.prototype.callDefaultBehavior = function () {
- if (this.type === 'streamDestroyed') {
- if (this.target instanceof Session_1.Session) {
- console.info("Calling default behavior upon '" + this.type + "' event dispatched by 'Session'");
- this.stream.disposeWebRtcPeer();
- }
- else if (this.target instanceof Publisher_1.Publisher) {
- console.info("Calling default behavior upon '" + this.type + "' event dispatched by 'Publisher'");
- clearInterval(this.target.screenShareResizeInterval);
- this.stream.isLocalStreamReadyToPublish = false;
- var openviduPublishers = this.target.openvidu.publishers;
- for (var i = 0; i < openviduPublishers.length; i++) {
- if (openviduPublishers[i] === this.target) {
- openviduPublishers.splice(i, 1);
- break;
- }
- }
- }
- this.stream.disposeMediaStream();
- if (this.stream.streamManager)
- this.stream.streamManager.removeAllVideos();
- delete this.stream.session.remoteStreamsCreated[this.stream.streamId];
- var remoteConnection = this.stream.session.remoteConnections[this.stream.connection.connectionId];
- if (!!remoteConnection && !!remoteConnection.options) {
- var streamOptionsServer = remoteConnection.options.streams;
- for (var i = streamOptionsServer.length - 1; i >= 0; --i) {
- if (streamOptionsServer[i].id === this.stream.streamId) {
- streamOptionsServer.splice(i, 1);
- }
- }
- }
- }
- };
- return StreamEvent;
-}(Event_1.Event));
-exports.StreamEvent = StreamEvent;
-
-},{"../../OpenVidu/Publisher":20,"../../OpenVidu/Session":21,"./Event":29}],35:[function(require,module,exports){
-"use strict";
-var __extends = (this && this.__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 __());
- };
-})();
-Object.defineProperty(exports, "__esModule", { value: true });
-var Event_1 = require("./Event");
-var StreamManagerEvent = (function (_super) {
- __extends(StreamManagerEvent, _super);
- function StreamManagerEvent(target) {
- return _super.call(this, false, target, 'streamPlaying') || this;
- }
- StreamManagerEvent.prototype.callDefaultBehavior = function () { };
- return StreamManagerEvent;
-}(Event_1.Event));
-exports.StreamManagerEvent = StreamManagerEvent;
-
-},{"./Event":29}],36:[function(require,module,exports){
-"use strict";
-var __extends = (this && this.__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 __());
- };
-})();
-Object.defineProperty(exports, "__esModule", { value: true });
-var Event_1 = require("./Event");
-var StreamPropertyChangedEvent = (function (_super) {
- __extends(StreamPropertyChangedEvent, _super);
- function StreamPropertyChangedEvent(target, stream, changedProperty, newValue, oldValue, reason) {
- var _this = _super.call(this, false, target, 'streamPropertyChanged') || this;
- _this.stream = stream;
- _this.changedProperty = changedProperty;
- _this.newValue = newValue;
- _this.oldValue = oldValue;
- _this.reason = reason;
- return _this;
- }
- StreamPropertyChangedEvent.prototype.callDefaultBehavior = function () { };
- return StreamPropertyChangedEvent;
-}(Event_1.Event));
-exports.StreamPropertyChangedEvent = StreamPropertyChangedEvent;
-
-},{"./Event":29}],37:[function(require,module,exports){
-"use strict";
-var __extends = (this && this.__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 __());
- };
-})();
-Object.defineProperty(exports, "__esModule", { value: true });
-var Event_1 = require("./Event");
-var VideoElementEvent = (function (_super) {
- __extends(VideoElementEvent, _super);
- function VideoElementEvent(element, target, type) {
- var _this = _super.call(this, false, target, type) || this;
- _this.element = element;
- return _this;
- }
- VideoElementEvent.prototype.callDefaultBehavior = function () { };
- return VideoElementEvent;
-}(Event_1.Event));
-exports.VideoElementEvent = VideoElementEvent;
-
-},{"./Event":29}],38:[function(require,module,exports){
-function Mapper() {
- var sources = {};
- this.forEach = function (callback) {
- for (var key in sources) {
- var source = sources[key];
- for (var key2 in source)
- callback(source[key2]);
- }
- ;
- };
- this.get = function (id, source) {
- var ids = sources[source];
- if (ids == undefined)
- return undefined;
- return ids[id];
- };
- this.remove = function (id, source) {
- var ids = sources[source];
- if (ids == undefined)
- return;
- delete ids[id];
- for (var i in ids) {
- return false;
- }
- delete sources[source];
- };
- this.set = function (value, id, source) {
- if (value == undefined)
- return this.remove(id, source);
- var ids = sources[source];
- if (ids == undefined)
- sources[source] = ids = {};
- ids[id] = value;
- };
-}
-;
-Mapper.prototype.pop = function (id, source) {
- var value = this.get(id, source);
- if (value == undefined)
- return undefined;
- this.remove(id, source);
- return value;
-};
-module.exports = Mapper;
-
-},{}],39:[function(require,module,exports){
-var JsonRpcClient = require('./jsonrpcclient');
-exports.JsonRpcClient = JsonRpcClient;
-
-},{"./jsonrpcclient":40}],40:[function(require,module,exports){
-var RpcBuilder = require('../');
-var WebSocketWithReconnection = require('./transports/webSocketWithReconnection');
-Date.now = Date.now || function () {
- return +new Date;
-};
-var PING_INTERVAL = 5000;
-var RECONNECTING = 'RECONNECTING';
-var CONNECTED = 'CONNECTED';
-var DISCONNECTED = 'DISCONNECTED';
-var Logger = console;
-function JsonRpcClient(configuration) {
- var self = this;
- var wsConfig = configuration.ws;
- var notReconnectIfNumLessThan = -1;
- var pingNextNum = 0;
- var enabledPings = true;
- var pingPongStarted = false;
- var pingInterval;
- var status = DISCONNECTED;
- var onreconnecting = wsConfig.onreconnecting;
- var onreconnected = wsConfig.onreconnected;
- var onconnected = wsConfig.onconnected;
- var onerror = wsConfig.onerror;
- configuration.rpc.pull = function (params, request) {
- request.reply(null, "push");
- };
- wsConfig.onreconnecting = function () {
- Logger.debug("--------- ONRECONNECTING -----------");
- if (status === RECONNECTING) {
- Logger.error("Websocket already in RECONNECTING state when receiving a new ONRECONNECTING message. Ignoring it");
- return;
- }
- status = RECONNECTING;
- if (onreconnecting) {
- onreconnecting();
- }
- };
- wsConfig.onreconnected = function () {
- Logger.debug("--------- ONRECONNECTED -----------");
- if (status === CONNECTED) {
- Logger.error("Websocket already in CONNECTED state when receiving a new ONRECONNECTED message. Ignoring it");
- return;
- }
- status = CONNECTED;
- enabledPings = true;
- updateNotReconnectIfLessThan();
- usePing();
- if (onreconnected) {
- onreconnected();
- }
- };
- wsConfig.onconnected = function () {
- Logger.debug("--------- ONCONNECTED -----------");
- if (status === CONNECTED) {
- Logger.error("Websocket already in CONNECTED state when receiving a new ONCONNECTED message. Ignoring it");
- return;
- }
- status = CONNECTED;
- enabledPings = true;
- usePing();
- if (onconnected) {
- onconnected();
- }
- };
- wsConfig.onerror = function (error) {
- Logger.debug("--------- ONERROR -----------");
- status = DISCONNECTED;
- if (onerror) {
- onerror(error);
- }
- };
- var ws = new WebSocketWithReconnection(wsConfig);
- Logger.debug('Connecting websocket to URI: ' + wsConfig.uri);
- var rpcBuilderOptions = {
- request_timeout: configuration.rpc.requestTimeout,
- ping_request_timeout: configuration.rpc.heartbeatRequestTimeout
- };
- var rpc = new RpcBuilder(RpcBuilder.packers.JsonRPC, rpcBuilderOptions, ws, function (request) {
- Logger.debug('Received request: ' + JSON.stringify(request));
- try {
- var func = configuration.rpc[request.method];
- if (func === undefined) {
- Logger.error("Method " + request.method + " not registered in client");
- }
- else {
- func(request.params, request);
- }
- }
- catch (err) {
- Logger.error('Exception processing request: ' + JSON.stringify(request));
- Logger.error(err);
- }
- });
- this.send = function (method, params, callback) {
- if (method !== 'ping') {
- Logger.debug('Request: method:' + method + " params:" + JSON.stringify(params));
- }
- var requestTime = Date.now();
- rpc.encode(method, params, function (error, result) {
- if (error) {
- try {
- Logger.error("ERROR:" + error.message + " in Request: method:" +
- method + " params:" + JSON.stringify(params) + " request:" +
- error.request);
- if (error.data) {
- Logger.error("ERROR DATA:" + JSON.stringify(error.data));
- }
- }
- catch (e) { }
- error.requestTime = requestTime;
- }
- if (callback) {
- if (result != undefined && result.value !== 'pong') {
- Logger.debug('Response: ' + JSON.stringify(result));
- }
- callback(error, result);
- }
- });
- };
- function updateNotReconnectIfLessThan() {
- Logger.debug("notReconnectIfNumLessThan = " + pingNextNum + ' (old=' +
- notReconnectIfNumLessThan + ')');
- notReconnectIfNumLessThan = pingNextNum;
- }
- function sendPing() {
- if (enabledPings) {
- var params = null;
- if (pingNextNum == 0 || pingNextNum == notReconnectIfNumLessThan) {
- params = {
- interval: configuration.heartbeat || PING_INTERVAL
- };
- }
- pingNextNum++;
- self.send('ping', params, (function (pingNum) {
- return function (error, result) {
- if (error) {
- Logger.debug("Error in ping request #" + pingNum + " (" +
- error.message + ")");
- if (pingNum > notReconnectIfNumLessThan) {
- enabledPings = false;
- updateNotReconnectIfLessThan();
- Logger.debug("Server did not respond to ping message #" +
- pingNum + ". Reconnecting... ");
- ws.reconnectWs();
- }
- }
- };
- })(pingNextNum));
- }
- else {
- Logger.debug("Trying to send ping, but ping is not enabled");
- }
- }
- function usePing() {
- if (!pingPongStarted) {
- Logger.debug("Starting ping (if configured)");
- pingPongStarted = true;
- if (configuration.heartbeat != undefined) {
- pingInterval = setInterval(sendPing, configuration.heartbeat);
- sendPing();
- }
- }
- }
- this.close = function () {
- Logger.debug("Closing jsonRpcClient explicitly by client");
- if (pingInterval != undefined) {
- Logger.debug("Clearing ping interval");
- clearInterval(pingInterval);
- }
- pingPongStarted = false;
- enabledPings = false;
- if (configuration.sendCloseMessage) {
- Logger.debug("Sending close message");
- this.send('closeSession', null, function (error, result) {
- if (error) {
- Logger.error("Error sending close message: " + JSON.stringify(error));
- }
- ws.close();
- });
- }
- else {
- ws.close();
- }
- };
- this.forceClose = function (millis) {
- ws.forceClose(millis);
- };
- this.reconnect = function () {
- ws.reconnectWs();
- };
-}
-module.exports = JsonRpcClient;
-
-},{"../":43,"./transports/webSocketWithReconnection":42}],41:[function(require,module,exports){
-var WebSocketWithReconnection = require('./webSocketWithReconnection');
-exports.WebSocketWithReconnection = WebSocketWithReconnection;
-
-},{"./webSocketWithReconnection":42}],42:[function(require,module,exports){
-(function (global){
-"use strict";
-var BrowserWebSocket = global.WebSocket || global.MozWebSocket;
-var Logger = console;
-var MAX_RETRIES = 2000;
-var RETRY_TIME_MS = 3000;
-var CONNECTING = 0;
-var OPEN = 1;
-var CLOSING = 2;
-var CLOSED = 3;
-function WebSocketWithReconnection(config) {
- var closing = false;
- var registerMessageHandler;
- var wsUri = config.uri;
- var useSockJS = config.useSockJS;
- var reconnecting = false;
- var forcingDisconnection = false;
- var ws;
- if (useSockJS) {
- ws = new SockJS(wsUri);
- }
- else {
- ws = new WebSocket(wsUri);
- }
- ws.onopen = function () {
- logConnected(ws, wsUri);
- if (config.onconnected) {
- config.onconnected();
- }
- };
- ws.onerror = function (error) {
- Logger.error("Could not connect to " + wsUri + " (invoking onerror if defined)", error);
- if (config.onerror) {
- config.onerror(error);
- }
- };
- function logConnected(ws, wsUri) {
- try {
- Logger.debug("WebSocket connected to " + wsUri);
- }
- catch (e) {
- Logger.error(e);
- }
- }
- var reconnectionOnClose = function () {
- if (ws.readyState === CLOSED) {
- if (closing) {
- Logger.debug("Connection closed by user");
- }
- else {
- Logger.debug("Connection closed unexpectecly. Reconnecting...");
- reconnectToSameUri(MAX_RETRIES, 1);
- }
- }
- else {
- Logger.debug("Close callback from previous websocket. Ignoring it");
- }
- };
- ws.onclose = reconnectionOnClose;
- function reconnectToSameUri(maxRetries, numRetries) {
- Logger.debug("reconnectToSameUri (attempt #" + numRetries + ", max=" + maxRetries + ")");
- if (numRetries === 1) {
- if (reconnecting) {
- Logger.warn("Trying to reconnectToNewUri when reconnecting... Ignoring this reconnection.");
- return;
- }
- else {
- reconnecting = true;
- }
- if (config.onreconnecting) {
- config.onreconnecting();
- }
- }
- if (forcingDisconnection) {
- reconnectToNewUri(maxRetries, numRetries, wsUri);
- }
- else {
- if (config.newWsUriOnReconnection) {
- config.newWsUriOnReconnection(function (error, newWsUri) {
- if (error) {
- Logger.debug(error);
- setTimeout(function () {
- reconnectToSameUri(maxRetries, numRetries + 1);
- }, RETRY_TIME_MS);
- }
- else {
- reconnectToNewUri(maxRetries, numRetries, newWsUri);
- }
- });
- }
- else {
- reconnectToNewUri(maxRetries, numRetries, wsUri);
- }
- }
- }
- function reconnectToNewUri(maxRetries, numRetries, reconnectWsUri) {
- Logger.debug("Reconnection attempt #" + numRetries);
- ws.close();
- wsUri = reconnectWsUri || wsUri;
- var newWs;
- if (useSockJS) {
- newWs = new SockJS(wsUri);
- }
- else {
- newWs = new WebSocket(wsUri);
- }
- newWs.onopen = function () {
- Logger.debug("Reconnected after " + numRetries + " attempts...");
- logConnected(newWs, wsUri);
- reconnecting = false;
- registerMessageHandler();
- if (config.onreconnected()) {
- config.onreconnected();
- }
- newWs.onclose = reconnectionOnClose;
- };
- var onErrorOrClose = function (error) {
- Logger.warn("Reconnection error: ", error);
- if (numRetries === maxRetries) {
- if (config.ondisconnect) {
- config.ondisconnect();
- }
- }
- else {
- setTimeout(function () {
- reconnectToSameUri(maxRetries, numRetries + 1);
- }, RETRY_TIME_MS);
- }
- };
- newWs.onerror = onErrorOrClose;
- ws = newWs;
- }
- this.close = function () {
- closing = true;
- ws.close();
- };
- this.forceClose = function (millis) {
- Logger.debug("Testing: Force WebSocket close");
- if (millis) {
- Logger.debug("Testing: Change wsUri for " + millis + " millis to simulate net failure");
- var goodWsUri = wsUri;
- wsUri = "wss://21.234.12.34.4:443/";
- forcingDisconnection = true;
- setTimeout(function () {
- Logger.debug("Testing: Recover good wsUri " + goodWsUri);
- wsUri = goodWsUri;
- forcingDisconnection = false;
- }, millis);
- }
- ws.close();
- };
- this.reconnectWs = function () {
- Logger.debug("reconnectWs");
- reconnectToSameUri(MAX_RETRIES, 1, wsUri);
- };
- this.send = function (message) {
- ws.send(message);
- };
- this.addEventListener = function (type, callback) {
- registerMessageHandler = function () {
- ws.addEventListener(type, callback);
- };
- registerMessageHandler();
- };
-}
-module.exports = WebSocketWithReconnection;
-
-}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
-
-},{}],43:[function(require,module,exports){
-var defineProperty_IE8 = false;
-if (Object.defineProperty) {
- try {
- Object.defineProperty({}, "x", {});
- }
- catch (e) {
- defineProperty_IE8 = true;
- }
-}
-if (!Function.prototype.bind) {
- Function.prototype.bind = function (oThis) {
- if (typeof this !== 'function') {
- throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable');
- }
- var aArgs = Array.prototype.slice.call(arguments, 1), fToBind = this, fNOP = function () { }, fBound = function () {
- return fToBind.apply(this instanceof fNOP && oThis
- ? this
- : oThis, aArgs.concat(Array.prototype.slice.call(arguments)));
- };
- fNOP.prototype = this.prototype;
- fBound.prototype = new fNOP();
- return fBound;
- };
-}
-var EventEmitter = require('events').EventEmitter;
-var inherits = require('inherits');
-var packers = require('./packers');
-var Mapper = require('./Mapper');
-var BASE_TIMEOUT = 5000;
-function unifyResponseMethods(responseMethods) {
- if (!responseMethods)
- return {};
- for (var key in responseMethods) {
- var value = responseMethods[key];
- if (typeof value == 'string')
- responseMethods[key] =
- {
- response: value
- };
- }
- ;
- return responseMethods;
-}
-;
-function unifyTransport(transport) {
- if (!transport)
- return;
- if (transport instanceof Function)
- return { send: transport };
- if (transport.send instanceof Function)
- return transport;
- if (transport.postMessage instanceof Function) {
- transport.send = transport.postMessage;
- return transport;
- }
- if (transport.write instanceof Function) {
- transport.send = transport.write;
- return transport;
- }
- if (transport.onmessage !== undefined)
- return;
- if (transport.pause instanceof Function)
- return;
- throw new SyntaxError("Transport is not a function nor a valid object");
-}
-;
-function RpcNotification(method, params) {
- if (defineProperty_IE8) {
- this.method = method;
- this.params = params;
- }
- else {
- Object.defineProperty(this, 'method', { value: method, enumerable: true });
- Object.defineProperty(this, 'params', { value: params, enumerable: true });
- }
-}
-;
-function RpcBuilder(packer, options, transport, onRequest) {
- var self = this;
- if (!packer)
- throw new SyntaxError('Packer is not defined');
- if (!packer.pack || !packer.unpack)
- throw new SyntaxError('Packer is invalid');
- var responseMethods = unifyResponseMethods(packer.responseMethods);
- if (options instanceof Function) {
- if (transport != undefined)
- throw new SyntaxError("There can't be parameters after onRequest");
- onRequest = options;
- transport = undefined;
- options = undefined;
- }
- ;
- if (options && options.send instanceof Function) {
- if (transport && !(transport instanceof Function))
- throw new SyntaxError("Only a function can be after transport");
- onRequest = transport;
- transport = options;
- options = undefined;
- }
- ;
- if (transport instanceof Function) {
- if (onRequest != undefined)
- throw new SyntaxError("There can't be parameters after onRequest");
- onRequest = transport;
- transport = undefined;
- }
- ;
- if (transport && transport.send instanceof Function)
- if (onRequest && !(onRequest instanceof Function))
- throw new SyntaxError("Only a function can be after transport");
- options = options || {};
- EventEmitter.call(this);
- if (onRequest)
- this.on('request', onRequest);
- if (defineProperty_IE8)
- this.peerID = options.peerID;
- else
- Object.defineProperty(this, 'peerID', { value: options.peerID });
- var max_retries = options.max_retries || 0;
- function transportMessage(event) {
- self.decode(event.data || event);
- }
- ;
- this.getTransport = function () {
- return transport;
- };
- this.setTransport = function (value) {
- if (transport) {
- if (transport.removeEventListener)
- transport.removeEventListener('message', transportMessage);
- else if (transport.removeListener)
- transport.removeListener('data', transportMessage);
- }
- ;
- if (value) {
- if (value.addEventListener)
- value.addEventListener('message', transportMessage);
- else if (value.addListener)
- value.addListener('data', transportMessage);
- }
- ;
- transport = unifyTransport(value);
- };
- if (!defineProperty_IE8)
- Object.defineProperty(this, 'transport', {
- get: this.getTransport.bind(this),
- set: this.setTransport.bind(this)
- });
- this.setTransport(transport);
- var request_timeout = options.request_timeout || BASE_TIMEOUT;
- var ping_request_timeout = options.ping_request_timeout || request_timeout;
- var response_timeout = options.response_timeout || BASE_TIMEOUT;
- var duplicates_timeout = options.duplicates_timeout || BASE_TIMEOUT;
- var requestID = 0;
- var requests = new Mapper();
- var responses = new Mapper();
- var processedResponses = new Mapper();
- var message2Key = {};
- function storeResponse(message, id, dest) {
- var response = {
- message: message,
- timeout: setTimeout(function () {
- responses.remove(id, dest);
- }, response_timeout)
- };
- responses.set(response, id, dest);
- }
- ;
- function storeProcessedResponse(ack, from) {
- var timeout = setTimeout(function () {
- processedResponses.remove(ack, from);
- }, duplicates_timeout);
- processedResponses.set(timeout, ack, from);
- }
- ;
- function RpcRequest(method, params, id, from, transport) {
- RpcNotification.call(this, method, params);
- this.getTransport = function () {
- return transport;
- };
- this.setTransport = function (value) {
- transport = unifyTransport(value);
- };
- if (!defineProperty_IE8)
- Object.defineProperty(this, 'transport', {
- get: this.getTransport.bind(this),
- set: this.setTransport.bind(this)
- });
- var response = responses.get(id, from);
- if (!(transport || self.getTransport())) {
- if (defineProperty_IE8)
- this.duplicated = Boolean(response);
- else
- Object.defineProperty(this, 'duplicated', {
- value: Boolean(response)
- });
- }
- var responseMethod = responseMethods[method];
- this.pack = packer.pack.bind(packer, this, id);
- this.reply = function (error, result, transport) {
- if (error instanceof Function || error && error.send instanceof Function) {
- if (result != undefined)
- throw new SyntaxError("There can't be parameters after callback");
- transport = error;
- result = null;
- error = undefined;
- }
- else if (result instanceof Function
- || result && result.send instanceof Function) {
- if (transport != undefined)
- throw new SyntaxError("There can't be parameters after callback");
- transport = result;
- result = null;
- }
- ;
- transport = unifyTransport(transport);
- if (response)
- clearTimeout(response.timeout);
- if (from != undefined) {
- if (error)
- error.dest = from;
- if (result)
- result.dest = from;
- }
- ;
- var message;
- if (error || result != undefined) {
- if (self.peerID != undefined) {
- if (error)
- error.from = self.peerID;
- else
- result.from = self.peerID;
- }
- if (responseMethod) {
- if (responseMethod.error == undefined && error)
- message =
- {
- error: error
- };
- else {
- var method = error
- ? responseMethod.error
- : responseMethod.response;
- message =
- {
- method: method,
- params: error || result
- };
- }
- }
- else
- message =
- {
- error: error,
- result: result
- };
- message = packer.pack(message, id);
- }
- else if (response)
- message = response.message;
- else
- message = packer.pack({ result: null }, id);
- storeResponse(message, id, from);
- transport = transport || this.getTransport() || self.getTransport();
- if (transport)
- return transport.send(message);
- return message;
- };
- }
- ;
- inherits(RpcRequest, RpcNotification);
- function cancel(message) {
- var key = message2Key[message];
- if (!key)
- return;
- delete message2Key[message];
- var request = requests.pop(key.id, key.dest);
- if (!request)
- return;
- clearTimeout(request.timeout);
- storeProcessedResponse(key.id, key.dest);
- }
- ;
- this.cancel = function (message) {
- if (message)
- return cancel(message);
- for (var message in message2Key)
- cancel(message);
- };
- this.close = function () {
- var transport = this.getTransport();
- if (transport && transport.close)
- transport.close();
- this.cancel();
- processedResponses.forEach(clearTimeout);
- responses.forEach(function (response) {
- clearTimeout(response.timeout);
- });
- };
- this.encode = function (method, params, dest, transport, callback) {
- if (params instanceof Function) {
- if (dest != undefined)
- throw new SyntaxError("There can't be parameters after callback");
- callback = params;
- transport = undefined;
- dest = undefined;
- params = undefined;
- }
- else if (dest instanceof Function) {
- if (transport != undefined)
- throw new SyntaxError("There can't be parameters after callback");
- callback = dest;
- transport = undefined;
- dest = undefined;
- }
- else if (transport instanceof Function) {
- if (callback != undefined)
- throw new SyntaxError("There can't be parameters after callback");
- callback = transport;
- transport = undefined;
- }
- ;
- if (self.peerID != undefined) {
- params = params || {};
- params.from = self.peerID;
- }
- ;
- if (dest != undefined) {
- params = params || {};
- params.dest = dest;
- }
- ;
- var message = {
- method: method,
- params: params
- };
- if (callback) {
- var id = requestID++;
- var retried = 0;
- message = packer.pack(message, id);
- function dispatchCallback(error, result) {
- self.cancel(message);
- callback(error, result);
- }
- ;
- var request = {
- message: message,
- callback: dispatchCallback,
- responseMethods: responseMethods[method] || {}
- };
- var encode_transport = unifyTransport(transport);
- function sendRequest(transport) {
- var rt = (method === 'ping' ? ping_request_timeout : request_timeout);
- request.timeout = setTimeout(timeout, rt * Math.pow(2, retried++));
- message2Key[message] = { id: id, dest: dest };
- requests.set(request, id, dest);
- transport = transport || encode_transport || self.getTransport();
- if (transport)
- return transport.send(message);
- return message;
- }
- ;
- function retry(transport) {
- transport = unifyTransport(transport);
- console.warn(retried + ' retry for request message:', message);
- var timeout = processedResponses.pop(id, dest);
- clearTimeout(timeout);
- return sendRequest(transport);
- }
- ;
- function timeout() {
- if (retried < max_retries)
- return retry(transport);
- var error = new Error('Request has timed out');
- error.request = message;
- error.retry = retry;
- dispatchCallback(error);
- }
- ;
- return sendRequest(transport);
- }
- ;
- message = packer.pack(message);
- transport = transport || this.getTransport();
- if (transport)
- return transport.send(message);
- return message;
- };
- this.decode = function (message, transport) {
- if (!message)
- throw new TypeError("Message is not defined");
- try {
- message = packer.unpack(message);
- }
- catch (e) {
- return console.debug(e, message);
- }
- ;
- var id = message.id;
- var ack = message.ack;
- var method = message.method;
- var params = message.params || {};
- var from = params.from;
- var dest = params.dest;
- if (self.peerID != undefined && from == self.peerID)
- return;
- if (id == undefined && ack == undefined) {
- var notification = new RpcNotification(method, params);
- if (self.emit('request', notification))
- return;
- return notification;
- }
- ;
- function processRequest() {
- transport = unifyTransport(transport) || self.getTransport();
- if (transport) {
- var response = responses.get(id, from);
- if (response)
- return transport.send(response.message);
- }
- ;
- var idAck = (id != undefined) ? id : ack;
- var request = new RpcRequest(method, params, idAck, from, transport);
- if (self.emit('request', request))
- return;
- return request;
- }
- ;
- function processResponse(request, error, result) {
- request.callback(error, result);
- }
- ;
- function duplicatedResponse(timeout) {
- console.warn("Response already processed", message);
- clearTimeout(timeout);
- storeProcessedResponse(ack, from);
- }
- ;
- if (method) {
- if (dest == undefined || dest == self.peerID) {
- var request = requests.get(ack, from);
- if (request) {
- var responseMethods = request.responseMethods;
- if (method == responseMethods.error)
- return processResponse(request, params);
- if (method == responseMethods.response)
- return processResponse(request, null, params);
- return processRequest();
- }
- var processed = processedResponses.get(ack, from);
- if (processed)
- return duplicatedResponse(processed);
- }
- return processRequest();
- }
- ;
- var error = message.error;
- var result = message.result;
- if (error && error.dest && error.dest != self.peerID)
- return;
- if (result && result.dest && result.dest != self.peerID)
- return;
- var request = requests.get(ack, from);
- if (!request) {
- var processed = processedResponses.get(ack, from);
- if (processed)
- return duplicatedResponse(processed);
- return console.warn("No callback was defined for this message", message);
- }
- ;
- processResponse(request, error, result);
- };
-}
-;
-inherits(RpcBuilder, EventEmitter);
-RpcBuilder.RpcNotification = RpcNotification;
-module.exports = RpcBuilder;
-var clients = require('./clients');
-var transports = require('./clients/transports');
-RpcBuilder.clients = clients;
-RpcBuilder.clients.transports = transports;
-RpcBuilder.packers = packers;
-
-},{"./Mapper":38,"./clients":39,"./clients/transports":41,"./packers":46,"events":1,"inherits":6}],44:[function(require,module,exports){
-function pack(message, id) {
- var result = {
- jsonrpc: "2.0"
- };
- if (message.method) {
- result.method = message.method;
- if (message.params)
- result.params = message.params;
- if (id != undefined)
- result.id = id;
- }
- else if (id != undefined) {
- if (message.error) {
- if (message.result !== undefined)
- throw new TypeError("Both result and error are defined");
- result.error = message.error;
- }
- else if (message.result !== undefined)
- result.result = message.result;
- else
- throw new TypeError("No result or error is defined");
- result.id = id;
- }
- ;
- return JSON.stringify(result);
-}
-;
-function unpack(message) {
- var result = message;
- if (typeof message === 'string' || message instanceof String) {
- result = JSON.parse(message);
- }
- var version = result.jsonrpc;
- if (version !== '2.0')
- throw new TypeError("Invalid JsonRPC version '" + version + "': " + message);
- if (result.method == undefined) {
- if (result.id == undefined)
- throw new TypeError("Invalid message: " + message);
- var result_defined = result.result !== undefined;
- var error_defined = result.error !== undefined;
- if (result_defined && error_defined)
- throw new TypeError("Both result and error are defined: " + message);
- if (!result_defined && !error_defined)
- throw new TypeError("No result or error is defined: " + message);
- result.ack = result.id;
- delete result.id;
- }
- return result;
-}
-;
-exports.pack = pack;
-exports.unpack = unpack;
-
-},{}],45:[function(require,module,exports){
-function pack(message) {
- throw new TypeError("Not yet implemented");
-}
-;
-function unpack(message) {
- throw new TypeError("Not yet implemented");
-}
-;
-exports.pack = pack;
-exports.unpack = unpack;
-
-},{}],46:[function(require,module,exports){
-var JsonRPC = require('./JsonRPC');
-var XmlRPC = require('./XmlRPC');
-exports.JsonRPC = JsonRPC;
-exports.XmlRPC = XmlRPC;
-
-},{"./JsonRPC":44,"./XmlRPC":45}],47:[function(require,module,exports){
-window.getScreenId = function (callback, custom_parameter) {
- if (navigator.userAgent.indexOf('Edge') !== -1 && (!!navigator.msSaveOrOpenBlob || !!navigator.msSaveBlob)) {
- callback({
- video: true
- });
- return;
- }
- if (!!navigator.mozGetUserMedia) {
- callback(null, 'firefox', {
- video: {
- mozMediaSource: 'window',
- mediaSource: 'window'
- }
- });
- return;
- }
- window.addEventListener('message', onIFrameCallback);
- function onIFrameCallback(event) {
- if (!event.data)
- return;
- if (event.data.chromeMediaSourceId) {
- if (event.data.chromeMediaSourceId === 'PermissionDeniedError') {
- callback('permission-denied');
- }
- else {
- callback(null, event.data.chromeMediaSourceId, getScreenConstraints(null, event.data.chromeMediaSourceId, event.data.canRequestAudioTrack));
- }
- window.removeEventListener('message', onIFrameCallback);
- }
- if (event.data.chromeExtensionStatus) {
- callback(event.data.chromeExtensionStatus, null, getScreenConstraints(event.data.chromeExtensionStatus));
- window.removeEventListener('message', onIFrameCallback);
- }
- }
- if (!custom_parameter) {
- setTimeout(postGetSourceIdMessage, 100);
- }
- else {
- setTimeout(function () {
- postGetSourceIdMessage(custom_parameter);
- }, 100);
- }
-};
-function getScreenConstraints(error, sourceId, canRequestAudioTrack) {
- var screen_constraints = {
- audio: false,
- video: {
- mandatory: {
- chromeMediaSource: error ? 'screen' : 'desktop',
- maxWidth: window.screen.width > 1920 ? window.screen.width : 1920,
- maxHeight: window.screen.height > 1080 ? window.screen.height : 1080
- },
- optional: []
- }
- };
- if (!!canRequestAudioTrack) {
- screen_constraints.audio = {
- mandatory: {
- chromeMediaSource: error ? 'screen' : 'desktop',
- },
- optional: []
- };
- }
- if (sourceId) {
- screen_constraints.video.mandatory.chromeMediaSourceId = sourceId;
- if (screen_constraints.audio && screen_constraints.audio.mandatory) {
- screen_constraints.audio.mandatory.chromeMediaSourceId = sourceId;
- }
- }
- return screen_constraints;
-}
-function postGetSourceIdMessage(custom_parameter) {
- if (!iframe) {
- loadIFrame(function () {
- postGetSourceIdMessage(custom_parameter);
- });
- return;
- }
- if (!iframe.isLoaded) {
- setTimeout(function () {
- postGetSourceIdMessage(custom_parameter);
- }, 100);
- return;
- }
- if (!custom_parameter) {
- iframe.contentWindow.postMessage({
- captureSourceId: true
- }, '*');
- }
- else if (!!custom_parameter.forEach) {
- iframe.contentWindow.postMessage({
- captureCustomSourceId: custom_parameter
- }, '*');
- }
- else {
- iframe.contentWindow.postMessage({
- captureSourceIdWithAudio: true
- }, '*');
- }
-}
-var iframe;
-window.getScreenConstraints = function (callback) {
- loadIFrame(function () {
- getScreenId(function (error, sourceId, screen_constraints) {
- if (!screen_constraints) {
- screen_constraints = {
- video: true
- };
- }
- callback(error, screen_constraints.video);
- });
- });
-};
-function loadIFrame(loadCallback) {
- if (iframe) {
- loadCallback();
- return;
- }
- iframe = document.createElement('iframe');
- iframe.onload = function () {
- iframe.isLoaded = true;
- loadCallback();
- };
- iframe.src = 'https://openvidu.github.io/openvidu-screen-sharing-chrome-extension/';
- iframe.style.display = 'none';
- (document.body || document.documentElement).appendChild(iframe);
-}
-window.getChromeExtensionStatus = function (callback) {
- if (!!navigator.mozGetUserMedia) {
- callback('installed-enabled');
- return;
- }
- window.addEventListener('message', onIFrameCallback);
- function onIFrameCallback(event) {
- if (!event.data)
- return;
- if (event.data.chromeExtensionStatus) {
- callback(event.data.chromeExtensionStatus);
- window.removeEventListener('message', onIFrameCallback);
- }
- }
- setTimeout(postGetChromeExtensionStatusMessage, 100);
-};
-function postGetChromeExtensionStatusMessage() {
- if (!iframe) {
- loadIFrame(postGetChromeExtensionStatusMessage);
- return;
- }
- if (!iframe.isLoaded) {
- setTimeout(postGetChromeExtensionStatusMessage, 100);
- return;
- }
- iframe.contentWindow.postMessage({
- getChromeExtensionStatus: true
- }, '*');
-}
-exports.getScreenId = getScreenId;
-
-},{}],48:[function(require,module,exports){
-var chromeMediaSource = 'screen';
-var sourceId;
-var screenCallback;
-var isFirefox = typeof window.InstallTrigger !== 'undefined';
-var isOpera = !!window.opera || navigator.userAgent.indexOf(' OPR/') >= 0;
-var isChrome = !!window.chrome && !isOpera;
-window.addEventListener('message', function (event) {
- if (event.origin != window.location.origin) {
- return;
- }
- onMessageCallback(event.data);
-});
-function onMessageCallback(data) {
- if (data == 'PermissionDeniedError') {
- if (screenCallback)
- return screenCallback('PermissionDeniedError');
- else
- throw new Error('PermissionDeniedError');
- }
- if (data == 'rtcmulticonnection-extension-loaded') {
- chromeMediaSource = 'desktop';
- }
- if (data.sourceId && screenCallback) {
- screenCallback(sourceId = data.sourceId, data.canRequestAudioTrack === true);
- }
-}
-function isChromeExtensionAvailable(callback) {
- if (!callback)
- return;
- if (chromeMediaSource == 'desktop')
- return callback(true);
- window.postMessage('are-you-there', '*');
- setTimeout(function () {
- if (chromeMediaSource == 'screen') {
- callback(false);
- }
- else
- callback(true);
- }, 2000);
-}
-function getSourceId(callback) {
- if (!callback)
- throw '"callback" parameter is mandatory.';
- if (sourceId)
- return callback(sourceId);
- screenCallback = callback;
- window.postMessage('get-sourceId', '*');
-}
-function getCustomSourceId(arr, callback) {
- if (!arr || !arr.forEach)
- throw '"arr" parameter is mandatory and it must be an array.';
- if (!callback)
- throw '"callback" parameter is mandatory.';
- if (sourceId)
- return callback(sourceId);
- screenCallback = callback;
- window.postMessage({
- 'get-custom-sourceId': arr
- }, '*');
-}
-function getSourceIdWithAudio(callback) {
- if (!callback)
- throw '"callback" parameter is mandatory.';
- if (sourceId)
- return callback(sourceId);
- screenCallback = callback;
- window.postMessage('audio-plus-tab', '*');
-}
-function getChromeExtensionStatus(extensionid, callback) {
- if (isFirefox)
- return callback('not-chrome');
- if (arguments.length != 2) {
- callback = extensionid;
- extensionid = 'lfcgfepafnobdloecchnfaclibenjold';
- }
- var image = document.createElement('img');
- image.src = 'chrome-extension://' + extensionid + '/icon.png';
- image.onload = function () {
- chromeMediaSource = 'screen';
- window.postMessage('are-you-there', '*');
- setTimeout(function () {
- if (chromeMediaSource == 'screen') {
- callback('installed-disabled');
- }
- else
- callback('installed-enabled');
- }, 2000);
- };
- image.onerror = function () {
- callback('not-installed');
- };
-}
-function getScreenConstraintsWithAudio(callback) {
- getScreenConstraints(callback, true);
-}
-function getScreenConstraints(callback, captureSourceIdWithAudio) {
- sourceId = '';
- var firefoxScreenConstraints = {
- mozMediaSource: 'window',
- mediaSource: 'window'
- };
- if (isFirefox)
- return callback(null, firefoxScreenConstraints);
- var screen_constraints = {
- mandatory: {
- chromeMediaSource: chromeMediaSource,
- maxWidth: screen.width > 1920 ? screen.width : 1920,
- maxHeight: screen.height > 1080 ? screen.height : 1080
- },
- optional: []
- };
- if (chromeMediaSource == 'desktop' && !sourceId) {
- if (captureSourceIdWithAudio) {
- getSourceIdWithAudio(function (sourceId, canRequestAudioTrack) {
- screen_constraints.mandatory.chromeMediaSourceId = sourceId;
- if (canRequestAudioTrack) {
- screen_constraints.canRequestAudioTrack = true;
- }
- callback(sourceId == 'PermissionDeniedError' ? sourceId : null, screen_constraints);
- });
- }
- else {
- getSourceId(function (sourceId) {
- screen_constraints.mandatory.chromeMediaSourceId = sourceId;
- callback(sourceId == 'PermissionDeniedError' ? sourceId : null, screen_constraints);
- });
- }
- return;
- }
- if (chromeMediaSource == 'desktop') {
- screen_constraints.mandatory.chromeMediaSourceId = sourceId;
- }
- callback(null, screen_constraints);
-}
-exports.getScreenConstraints = getScreenConstraints;
-exports.getScreenConstraintsWithAudio = getScreenConstraintsWithAudio;
-exports.isChromeExtensionAvailable = isChromeExtensionAvailable;
-exports.getChromeExtensionStatus = getChromeExtensionStatus;
-exports.getSourceId = getSourceId;
-
-},{}],49:[function(require,module,exports){
-"use strict";
-var __extends = (this && this.__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 __());
- };
-})();
-Object.defineProperty(exports, "__esModule", { value: true });
-var freeice = require("freeice");
-var uuid = require("uuid");
-var platform = require("platform");
-var WebRtcPeer = (function () {
- function WebRtcPeer(configuration) {
- var _this = this;
- this.configuration = configuration;
- this.remoteCandidatesQueue = [];
- this.localCandidatesQueue = [];
- this.iceCandidateList = [];
- this.candidategatheringdone = false;
- this.configuration.iceServers = (!!this.configuration.iceServers && this.configuration.iceServers.length > 0) ? this.configuration.iceServers : freeice();
- this.pc = new RTCPeerConnection({ iceServers: this.configuration.iceServers });
- this.id = !!configuration.id ? configuration.id : uuid.v4();
- this.pc.onicecandidate = function (event) {
- var candidate = event.candidate;
- if (candidate) {
- _this.localCandidatesQueue.push({ candidate: candidate.candidate });
- _this.candidategatheringdone = false;
- _this.configuration.onicecandidate(event.candidate);
- }
- else if (!_this.candidategatheringdone) {
- _this.candidategatheringdone = true;
- }
- };
- this.pc.onsignalingstatechange = function () {
- if (_this.pc.signalingState === 'stable') {
- while (_this.iceCandidateList.length > 0) {
- _this.pc.addIceCandidate(_this.iceCandidateList.shift());
- }
- }
- };
- this.start();
- }
- WebRtcPeer.prototype.start = function () {
- var _this = this;
- return new Promise(function (resolve, reject) {
- if (_this.pc.signalingState === 'closed') {
- reject('The peer connection object is in "closed" state. This is most likely due to an invocation of the dispose method before accepting in the dialogue');
- }
- if (!!_this.configuration.mediaStream) {
- _this.pc.addStream(_this.configuration.mediaStream);
- }
- if (_this.configuration.mode === 'sendonly' &&
- (platform.name === 'Chrome' && platform.version.toString().substring(0, 2) === '39')) {
- _this.configuration.mode = 'sendrecv';
- }
- resolve();
- });
- };
- WebRtcPeer.prototype.dispose = function () {
- var _this = this;
- console.debug('Disposing WebRtcPeer');
- try {
- if (this.pc) {
- if (this.pc.signalingState === 'closed') {
- return;
- }
- this.remoteCandidatesQueue = [];
- this.localCandidatesQueue = [];
- this.pc.getLocalStreams().forEach(function (str) {
- _this.streamStop(str);
- });
- this.pc.close();
- }
- }
- catch (err) {
- console.warn('Exception disposing webrtc peer ' + err);
- }
- };
- WebRtcPeer.prototype.generateOffer = function () {
- var _this = this;
- return new Promise(function (resolve, reject) {
- var offerAudio, offerVideo = true;
- if (!!_this.configuration.mediaConstraints) {
- offerAudio = (typeof _this.configuration.mediaConstraints.audio === 'boolean') ?
- _this.configuration.mediaConstraints.audio : true;
- offerVideo = (typeof _this.configuration.mediaConstraints.video === 'boolean') ?
- _this.configuration.mediaConstraints.video : true;
- }
- var constraints = {
- offerToReceiveAudio: +(_this.configuration.mode !== 'sendonly' && offerAudio),
- offerToReceiveVideo: +(_this.configuration.mode !== 'sendonly' && offerVideo)
- };
- console.debug('RTCPeerConnection constraints: ' + JSON.stringify(constraints));
- _this.pc.createOffer(constraints).then(function (offer) {
- console.debug('Created SDP offer');
- return _this.pc.setLocalDescription(offer);
- }).then(function () {
- var localDescription = _this.pc.localDescription;
- if (!!localDescription) {
- console.debug('Local description set', localDescription.sdp);
- resolve(localDescription.sdp);
- }
- else {
- reject('Local description is not defined');
- }
- }).catch(function (error) { return reject(error); });
- });
- };
- WebRtcPeer.prototype.processOffer = function (sdpOffer) {
- var _this = this;
- return new Promise(function (resolve, reject) {
- var offer = {
- type: 'offer',
- sdp: sdpOffer
- };
- console.debug('SDP offer received, setting remote description');
- if (_this.pc.signalingState === 'closed') {
- reject('PeerConnection is closed');
- }
- _this.pc.setRemoteDescription(offer)
- .then(function () {
- return _this.pc.createAnswer();
- }).then(function (answer) {
- console.debug('Created SDP answer');
- return _this.pc.setLocalDescription(answer);
- }).then(function () {
- var localDescription = _this.pc.localDescription;
- if (!!localDescription) {
- console.debug('Local description set', localDescription.sdp);
- resolve(localDescription.sdp);
- }
- else {
- reject('Local description is not defined');
- }
- }).catch(function (error) { return reject(error); });
- });
- };
- WebRtcPeer.prototype.processAnswer = function (sdpAnswer) {
- var _this = this;
- return new Promise(function (resolve, reject) {
- var answer = {
- type: 'answer',
- sdp: sdpAnswer
- };
- console.debug('SDP answer received, setting remote description');
- if (_this.pc.signalingState === 'closed') {
- reject('RTCPeerConnection is closed');
- }
- _this.pc.setRemoteDescription(answer).then(function () { return resolve(); }).catch(function (error) { return reject(error); });
- });
- };
- WebRtcPeer.prototype.addIceCandidate = function (iceCandidate) {
- var _this = this;
- return new Promise(function (resolve, reject) {
- console.debug('Remote ICE candidate received', iceCandidate);
- _this.remoteCandidatesQueue.push(iceCandidate);
- switch (_this.pc.signalingState) {
- case 'closed':
- reject(new Error('PeerConnection object is closed'));
- break;
- case 'stable':
- if (!!_this.pc.remoteDescription) {
- _this.pc.addIceCandidate(iceCandidate).then(function () { return resolve(); }).catch(function (error) { return reject(error); });
- }
- break;
- default:
- _this.iceCandidateList.push(iceCandidate);
- resolve();
- }
- });
- };
- WebRtcPeer.prototype.streamStop = function (stream) {
- stream.getTracks().forEach(function (track) {
- track.stop();
- stream.removeTrack(track);
- });
- };
- return WebRtcPeer;
-}());
-exports.WebRtcPeer = WebRtcPeer;
-var WebRtcPeerRecvonly = (function (_super) {
- __extends(WebRtcPeerRecvonly, _super);
- function WebRtcPeerRecvonly(configuration) {
- var _this = this;
- configuration.mode = 'recvonly';
- _this = _super.call(this, configuration) || this;
- return _this;
- }
- return WebRtcPeerRecvonly;
-}(WebRtcPeer));
-exports.WebRtcPeerRecvonly = WebRtcPeerRecvonly;
-var WebRtcPeerSendonly = (function (_super) {
- __extends(WebRtcPeerSendonly, _super);
- function WebRtcPeerSendonly(configuration) {
- var _this = this;
- configuration.mode = 'sendonly';
- _this = _super.call(this, configuration) || this;
- return _this;
- }
- return WebRtcPeerSendonly;
-}(WebRtcPeer));
-exports.WebRtcPeerSendonly = WebRtcPeerSendonly;
-var WebRtcPeerSendrecv = (function (_super) {
- __extends(WebRtcPeerSendrecv, _super);
- function WebRtcPeerSendrecv(configuration) {
- var _this = this;
- configuration.mode = 'sendrecv';
- _this = _super.call(this, configuration) || this;
- return _this;
- }
- return WebRtcPeerSendrecv;
-}(WebRtcPeer));
-exports.WebRtcPeerSendrecv = WebRtcPeerSendrecv;
-
-},{"freeice":2,"platform":8,"uuid":9}],50:[function(require,module,exports){
-"use strict";
-Object.defineProperty(exports, "__esModule", { value: true });
-var platform = require("platform");
-var WebRtcStats = (function () {
- function WebRtcStats(stream) {
- this.stream = stream;
- this.webRtcStatsEnabled = false;
- this.statsInterval = 1;
- this.stats = {
- inbound: {
- audio: {
- bytesReceived: 0,
- packetsReceived: 0,
- packetsLost: 0
- },
- video: {
- bytesReceived: 0,
- packetsReceived: 0,
- packetsLost: 0,
- framesDecoded: 0,
- nackCount: 0
- }
- },
- outbound: {
- audio: {
- bytesSent: 0,
- packetsSent: 0,
- },
- video: {
- bytesSent: 0,
- packetsSent: 0,
- framesEncoded: 0,
- nackCount: 0
- }
- }
- };
- }
- WebRtcStats.prototype.isEnabled = function () {
- return this.webRtcStatsEnabled;
- };
- WebRtcStats.prototype.initWebRtcStats = function () {
- var _this = this;
- var elastestInstrumentation = localStorage.getItem('elastest-instrumentation');
- if (elastestInstrumentation) {
- console.warn('WebRtc stats enabled for stream ' + this.stream.streamId + ' of connection ' + this.stream.connection.connectionId);
- this.webRtcStatsEnabled = true;
- var instrumentation_1 = JSON.parse(elastestInstrumentation);
- this.statsInterval = instrumentation_1.webrtc.interval;
- console.warn('localStorage item: ' + JSON.stringify(instrumentation_1));
- this.webRtcStatsIntervalId = setInterval(function () {
- _this.sendStatsToHttpEndpoint(instrumentation_1);
- }, this.statsInterval * 1000);
- return;
- }
- console.debug('WebRtc stats not enabled');
- };
- WebRtcStats.prototype.stopWebRtcStats = function () {
- if (this.webRtcStatsEnabled) {
- clearInterval(this.webRtcStatsIntervalId);
- console.warn('WebRtc stats stopped for disposed stream ' + this.stream.streamId + ' of connection ' + this.stream.connection.connectionId);
- }
- };
- WebRtcStats.prototype.getSelectedIceCandidateInfo = function () {
- var _this = this;
- return new Promise(function (resolve, reject) {
- _this.getStatsAgnostic(_this.stream.getRTCPeerConnection(), function (stats) {
- if ((platform.name.indexOf('Chrome') !== -1) || (platform.name.indexOf('Opera') !== -1)) {
- var localCandidateId = void 0, remoteCandidateId = void 0, googCandidatePair = void 0;
- var localCandidates = {};
- var remoteCandidates = {};
- for (var key in stats) {
- var stat = stats[key];
- if (stat.type === 'localcandidate') {
- localCandidates[stat.id] = stat;
- }
- else if (stat.type === 'remotecandidate') {
- remoteCandidates[stat.id] = stat;
- }
- else if (stat.type === 'googCandidatePair' && (stat.googActiveConnection === 'true')) {
- googCandidatePair = stat;
- localCandidateId = stat.localCandidateId;
- remoteCandidateId = stat.remoteCandidateId;
- }
- }
- var finalLocalCandidate_1 = localCandidates[localCandidateId];
- if (!!finalLocalCandidate_1) {
- var candList = _this.stream.getLocalIceCandidateList();
- var cand = candList.filter(function (c) {
- return (!!c.candidate &&
- c.candidate.indexOf(finalLocalCandidate_1.ipAddress) >= 0 &&
- c.candidate.indexOf(finalLocalCandidate_1.portNumber) >= 0 &&
- c.candidate.indexOf(finalLocalCandidate_1.priority) >= 0);
- });
- finalLocalCandidate_1.raw = !!cand[0] ? cand[0].candidate : 'ERROR: Cannot find local candidate in list of sent ICE candidates';
- }
- else {
- finalLocalCandidate_1 = 'ERROR: No active local ICE candidate. Probably ICE-TCP is being used';
- }
- var finalRemoteCandidate_1 = remoteCandidates[remoteCandidateId];
- if (!!finalRemoteCandidate_1) {
- var candList = _this.stream.getRemoteIceCandidateList();
- var cand = candList.filter(function (c) {
- return (!!c.candidate &&
- c.candidate.indexOf(finalRemoteCandidate_1.ipAddress) >= 0 &&
- c.candidate.indexOf(finalRemoteCandidate_1.portNumber) >= 0 &&
- c.candidate.indexOf(finalRemoteCandidate_1.priority) >= 0);
- });
- finalRemoteCandidate_1.raw = !!cand[0] ? cand[0].candidate : 'ERROR: Cannot find remote candidate in list of received ICE candidates';
- }
- else {
- finalRemoteCandidate_1 = 'ERROR: No active remote ICE candidate. Probably ICE-TCP is being used';
- }
- resolve({
- googCandidatePair: googCandidatePair,
- localCandidate: finalLocalCandidate_1,
- remoteCandidate: finalRemoteCandidate_1
- });
- }
- else {
- reject('Selected ICE candidate info only available for Chrome');
- }
- }, function (error) {
- reject(error);
- });
- });
- };
- WebRtcStats.prototype.sendStatsToHttpEndpoint = function (instrumentation) {
- var _this = this;
- var sendPost = function (json) {
- var http = new XMLHttpRequest();
- var url = instrumentation.webrtc.httpEndpoint;
- http.open('POST', url, true);
- http.setRequestHeader('Content-type', 'application/json');
- http.onreadystatechange = function () {
- if (http.readyState === 4 && http.status === 200) {
- console.log('WebRtc stats successfully sent to ' + url + ' for stream ' + _this.stream.streamId + ' of connection ' + _this.stream.connection.connectionId);
- }
- };
- http.send(json);
- };
- var f = function (stats) {
- if (platform.name.indexOf('Firefox') !== -1) {
- stats.forEach(function (stat) {
- var json = {};
- if ((stat.type === 'inbound-rtp') &&
- (stat.nackCount !== null &&
- stat.isRemote === false &&
- stat.id.startsWith('inbound') &&
- stat.remoteId.startsWith('inbound'))) {
- var metricId = 'webrtc_inbound_' + stat.mediaType + '_' + stat.ssrc;
- var jit = stat.jitter * 1000;
- var metrics = {
- bytesReceived: (stat.bytesReceived - _this.stats.inbound[stat.mediaType].bytesReceived) / _this.statsInterval,
- jitter: jit,
- packetsReceived: (stat.packetsReceived - _this.stats.inbound[stat.mediaType].packetsReceived) / _this.statsInterval,
- packetsLost: (stat.packetsLost - _this.stats.inbound[stat.mediaType].packetsLost) / _this.statsInterval
- };
- var units = {
- bytesReceived: 'bytes',
- jitter: 'ms',
- packetsReceived: 'packets',
- packetsLost: 'packets'
- };
- if (stat.mediaType === 'video') {
- metrics['framesDecoded'] = (stat.framesDecoded - _this.stats.inbound.video.framesDecoded) / _this.statsInterval;
- metrics['nackCount'] = (stat.nackCount - _this.stats.inbound.video.nackCount) / _this.statsInterval;
- units['framesDecoded'] = 'frames';
- units['nackCount'] = 'packets';
- _this.stats.inbound.video.framesDecoded = stat.framesDecoded;
- _this.stats.inbound.video.nackCount = stat.nackCount;
- }
- _this.stats.inbound[stat.mediaType].bytesReceived = stat.bytesReceived;
- _this.stats.inbound[stat.mediaType].packetsReceived = stat.packetsReceived;
- _this.stats.inbound[stat.mediaType].packetsLost = stat.packetsLost;
- json = {
- '@timestamp': new Date(stat.timestamp).toISOString(),
- 'exec': instrumentation.exec,
- 'component': instrumentation.component,
- 'stream': 'webRtc',
- 'type': metricId,
- 'stream_type': 'composed_metrics',
- 'units': units
- };
- json[metricId] = metrics;
- sendPost(JSON.stringify(json));
- }
- else if ((stat.type === 'outbound-rtp') &&
- (stat.isRemote === false &&
- stat.id.toLowerCase().includes('outbound'))) {
- var metricId = 'webrtc_outbound_' + stat.mediaType + '_' + stat.ssrc;
- var metrics = {
- bytesSent: (stat.bytesSent - _this.stats.outbound[stat.mediaType].bytesSent) / _this.statsInterval,
- packetsSent: (stat.packetsSent - _this.stats.outbound[stat.mediaType].packetsSent) / _this.statsInterval
- };
- var units = {
- bytesSent: 'bytes',
- packetsSent: 'packets'
- };
- if (stat.mediaType === 'video') {
- metrics['framesEncoded'] = (stat.framesEncoded - _this.stats.outbound.video.framesEncoded) / _this.statsInterval;
- units['framesEncoded'] = 'frames';
- _this.stats.outbound.video.framesEncoded = stat.framesEncoded;
- }
- _this.stats.outbound[stat.mediaType].bytesSent = stat.bytesSent;
- _this.stats.outbound[stat.mediaType].packetsSent = stat.packetsSent;
- json = {
- '@timestamp': new Date(stat.timestamp).toISOString(),
- 'exec': instrumentation.exec,
- 'component': instrumentation.component,
- 'stream': 'webRtc',
- 'type': metricId,
- 'stream_type': 'composed_metrics',
- 'units': units
- };
- json[metricId] = metrics;
- sendPost(JSON.stringify(json));
- }
- });
- }
- else if ((platform.name.indexOf('Chrome') !== -1) || (platform.name.indexOf('Opera') !== -1)) {
- for (var _i = 0, _a = Object.keys(stats); _i < _a.length; _i++) {
- var key = _a[_i];
- var stat = stats[key];
- if (stat.type === 'ssrc') {
- var json = {};
- if ('bytesReceived' in stat && ((stat.mediaType === 'audio' && 'audioOutputLevel' in stat) ||
- (stat.mediaType === 'video' && 'qpSum' in stat))) {
- var metricId = 'webrtc_inbound_' + stat.mediaType + '_' + stat.ssrc;
- var metrics = {
- bytesReceived: (stat.bytesReceived - _this.stats.inbound[stat.mediaType].bytesReceived) / _this.statsInterval,
- jitter: stat.googJitterBufferMs,
- packetsReceived: (stat.packetsReceived - _this.stats.inbound[stat.mediaType].packetsReceived) / _this.statsInterval,
- packetsLost: (stat.packetsLost - _this.stats.inbound[stat.mediaType].packetsLost) / _this.statsInterval
- };
- var units = {
- bytesReceived: 'bytes',
- jitter: 'ms',
- packetsReceived: 'packets',
- packetsLost: 'packets'
- };
- if (stat.mediaType === 'video') {
- metrics['framesDecoded'] = (stat.framesDecoded - _this.stats.inbound.video.framesDecoded) / _this.statsInterval;
- metrics['nackCount'] = (stat.googNacksSent - _this.stats.inbound.video.nackCount) / _this.statsInterval;
- units['framesDecoded'] = 'frames';
- units['nackCount'] = 'packets';
- _this.stats.inbound.video.framesDecoded = stat.framesDecoded;
- _this.stats.inbound.video.nackCount = stat.googNacksSent;
- }
- _this.stats.inbound[stat.mediaType].bytesReceived = stat.bytesReceived;
- _this.stats.inbound[stat.mediaType].packetsReceived = stat.packetsReceived;
- _this.stats.inbound[stat.mediaType].packetsLost = stat.packetsLost;
- json = {
- '@timestamp': new Date(stat.timestamp).toISOString(),
- 'exec': instrumentation.exec,
- 'component': instrumentation.component,
- 'stream': 'webRtc',
- 'type': metricId,
- 'stream_type': 'composed_metrics',
- 'units': units
- };
- json[metricId] = metrics;
- sendPost(JSON.stringify(json));
- }
- else if ('bytesSent' in stat) {
- var metricId = 'webrtc_outbound_' + stat.mediaType + '_' + stat.ssrc;
- var metrics = {
- bytesSent: (stat.bytesSent - _this.stats.outbound[stat.mediaType].bytesSent) / _this.statsInterval,
- packetsSent: (stat.packetsSent - _this.stats.outbound[stat.mediaType].packetsSent) / _this.statsInterval
- };
- var units = {
- bytesSent: 'bytes',
- packetsSent: 'packets'
- };
- if (stat.mediaType === 'video') {
- metrics['framesEncoded'] = (stat.framesEncoded - _this.stats.outbound.video.framesEncoded) / _this.statsInterval;
- units['framesEncoded'] = 'frames';
- _this.stats.outbound.video.framesEncoded = stat.framesEncoded;
- }
- _this.stats.outbound[stat.mediaType].bytesSent = stat.bytesSent;
- _this.stats.outbound[stat.mediaType].packetsSent = stat.packetsSent;
- json = {
- '@timestamp': new Date(stat.timestamp).toISOString(),
- 'exec': instrumentation.exec,
- 'component': instrumentation.component,
- 'stream': 'webRtc',
- 'type': metricId,
- 'stream_type': 'composed_metrics',
- 'units': units
- };
- json[metricId] = metrics;
- sendPost(JSON.stringify(json));
- }
- }
- }
- }
- };
- this.getStatsAgnostic(this.stream.getRTCPeerConnection(), f, function (error) { console.log(error); });
- };
- WebRtcStats.prototype.standardizeReport = function (response) {
- console.log(response);
- var standardReport = {};
- if (platform.name.indexOf('Firefox') !== -1) {
- Object.keys(response).forEach(function (key) {
- console.log(response[key]);
- });
- return response;
- }
- response.result().forEach(function (report) {
- var standardStats = {
- id: report.id,
- timestamp: report.timestamp,
- type: report.type
- };
- report.names().forEach(function (name) {
- standardStats[name] = report.stat(name);
- });
- standardReport[standardStats.id] = standardStats;
- });
- return standardReport;
- };
- WebRtcStats.prototype.getStatsAgnostic = function (pc, successCb, failureCb) {
- var _this = this;
- if (platform.name.indexOf('Firefox') !== -1) {
- return pc.getStats(null).then(function (response) {
- var report = _this.standardizeReport(response);
- successCb(report);
- }).catch(failureCb);
- }
- else if ((platform.name.indexOf('Chrome') !== -1) || (platform.name.indexOf('Opera') !== -1)) {
- return pc.getStats(function (response) {
- var report = _this.standardizeReport(response);
- successCb(report);
- }, null, failureCb);
- }
- };
- return WebRtcStats;
-}());
-exports.WebRtcStats = WebRtcStats;
-
-},{"platform":8}]},{},[16])
-//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL25vZGVfbW9kdWxlcy9icm93c2VyLXBhY2svX3ByZWx1ZGUuanMiLCIuLi9ub2RlX21vZHVsZXMvZXZlbnRzL2V2ZW50cy5qcyIsIi4uL25vZGVfbW9kdWxlcy9mcmVlaWNlL2luZGV4LmpzIiwiLi4vbm9kZV9tb2R1bGVzL2ZyZWVpY2Uvc3R1bi5qc29uIiwiLi4vbm9kZV9tb2R1bGVzL2ZyZWVpY2UvdHVybi5qc29uIiwiLi4vbm9kZV9tb2R1bGVzL2hhcmsvaGFyay5qcyIsIi4uL25vZGVfbW9kdWxlcy9pbmhlcml0cy9pbmhlcml0c19icm93c2VyLmpzIiwiLi4vbm9kZV9tb2R1bGVzL25vcm1hbGljZS9pbmRleC5qcyIsIi4uL25vZGVfbW9kdWxlcy9wbGF0Zm9ybS9wbGF0Zm9ybS5qcyIsIi4uL25vZGVfbW9kdWxlcy91dWlkL2luZGV4LmpzIiwiLi4vbm9kZV9tb2R1bGVzL3V1aWQvbGliL2J5dGVzVG9VdWlkLmpzIiwiLi4vbm9kZV9tb2R1bGVzL3V1aWQvbGliL3JuZy1icm93c2VyLmpzIiwiLi4vbm9kZV9tb2R1bGVzL3V1aWQvdjEuanMiLCIuLi9ub2RlX21vZHVsZXMvdXVpZC92NC5qcyIsIi4uL25vZGVfbW9kdWxlcy93aWxkZW1pdHRlci93aWxkZW1pdHRlci5qcyIsIi4uL25vZGVfbW9kdWxlcy93b2xmeTg3LWV2ZW50ZW1pdHRlci9FdmVudEVtaXR0ZXIuanMiLCJNYWluLnRzIiwiT3BlblZpZHUvQ29ubmVjdGlvbi50cyIsIk9wZW5WaWR1L0xvY2FsUmVjb3JkZXIudHMiLCJPcGVuVmlkdS9PcGVuVmlkdS50cyIsIk9wZW5WaWR1L1B1Ymxpc2hlci50cyIsIk9wZW5WaWR1L1Nlc3Npb24udHMiLCJPcGVuVmlkdS9TdHJlYW0udHMiLCJPcGVuVmlkdS9TdHJlYW1NYW5hZ2VyLnRzIiwiT3BlblZpZHUvU3Vic2NyaWJlci50cyIsIk9wZW5WaWR1SW50ZXJuYWwvRW51bXMvTG9jYWxSZWNvcmRlclN0YXRlLnRzIiwiT3BlblZpZHVJbnRlcm5hbC9FbnVtcy9PcGVuVmlkdUVycm9yLnRzIiwiT3BlblZpZHVJbnRlcm5hbC9FbnVtcy9WaWRlb0luc2VydE1vZGUudHMiLCJPcGVuVmlkdUludGVybmFsL0V2ZW50cy9Db25uZWN0aW9uRXZlbnQudHMiLCJPcGVuVmlkdUludGVybmFsL0V2ZW50cy9FdmVudC50cyIsIk9wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1B1Ymxpc2hlclNwZWFraW5nRXZlbnQudHMiLCJPcGVuVmlkdUludGVybmFsL0V2ZW50cy9SZWNvcmRpbmdFdmVudC50cyIsIk9wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1Nlc3Npb25EaXNjb25uZWN0ZWRFdmVudC50cyIsIk9wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1NpZ25hbEV2ZW50LnRzIiwiT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvU3RyZWFtRXZlbnQudHMiLCJPcGVuVmlkdUludGVybmFsL0V2ZW50cy9TdHJlYW1NYW5hZ2VyRXZlbnQudHMiLCJPcGVuVmlkdUludGVybmFsL0V2ZW50cy9TdHJlYW1Qcm9wZXJ0eUNoYW5nZWRFdmVudC50cyIsIk9wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1ZpZGVvRWxlbWVudEV2ZW50LnRzIiwiT3BlblZpZHVJbnRlcm5hbC9LdXJlbnRvVXRpbHMva3VyZW50by1qc29ucnBjL01hcHBlci5qcyIsIk9wZW5WaWR1SW50ZXJuYWwvS3VyZW50b1V0aWxzL2t1cmVudG8tanNvbnJwYy9jbGllbnRzL2luZGV4LmpzIiwiT3BlblZpZHVJbnRlcm5hbC9LdXJlbnRvVXRpbHMva3VyZW50by1qc29ucnBjL2NsaWVudHMvanNvbnJwY2NsaWVudC5qcyIsIk9wZW5WaWR1SW50ZXJuYWwvS3VyZW50b1V0aWxzL2t1cmVudG8tanNvbnJwYy9jbGllbnRzL3RyYW5zcG9ydHMvaW5kZXguanMiLCJPcGVuVmlkdUludGVybmFsL0t1cmVudG9VdGlscy9rdXJlbnRvLWpzb25ycGMvY2xpZW50cy90cmFuc3BvcnRzL3dlYlNvY2tldFdpdGhSZWNvbm5lY3Rpb24uanMiLCJPcGVuVmlkdUludGVybmFsL0t1cmVudG9VdGlscy9rdXJlbnRvLWpzb25ycGMvaW5kZXguanMiLCJPcGVuVmlkdUludGVybmFsL0t1cmVudG9VdGlscy9rdXJlbnRvLWpzb25ycGMvcGFja2Vycy9Kc29uUlBDLmpzIiwiT3BlblZpZHVJbnRlcm5hbC9LdXJlbnRvVXRpbHMva3VyZW50by1qc29ucnBjL3BhY2tlcnMvWG1sUlBDLmpzIiwiT3BlblZpZHVJbnRlcm5hbC9LdXJlbnRvVXRpbHMva3VyZW50by1qc29ucnBjL3BhY2tlcnMvaW5kZXguanMiLCJPcGVuVmlkdUludGVybmFsL1NjcmVlblNoYXJpbmcvU2NyZWVuLUNhcHR1cmluZy1BdXRvLmpzIiwiT3BlblZpZHVJbnRlcm5hbC9TY3JlZW5TaGFyaW5nL1NjcmVlbi1DYXB0dXJpbmcuanMiLCJPcGVuVmlkdUludGVybmFsL1dlYlJ0Y1BlZXIvV2ViUnRjUGVlci50cyIsIk9wZW5WaWR1SW50ZXJuYWwvV2ViUnRjU3RhdHMvV2ViUnRjU3RhdHMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7QUNBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzNnQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDekdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDaEJBO0FBQ0E7O0FDREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2xKQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdkJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUM1REE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7O0FDanNDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDUkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDeEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbENBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDN0dBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM3QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDekpBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7O0FDdGVBLGdEQUErQztBQUUvQyxJQUFJLE1BQU0s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O1FBQWpELGlCQWNDO1FBYkcsSUFBSSxRQUFRLENBQUMsSUFBSyxDQUFDLE9BQU8sQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLENBQUMsRUFBRTtZQUUxQyxPQUFPLEVBQUUsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLENBQUMsSUFBSSxDQUFDLFVBQUEsUUFBUTtnQkFDbEMsSUFBTSxNQUFNLEdBQUcsS0FBSSxDQUFDLGlCQUFpQixDQUFDLFFBQVEsQ0FBQyxDQUFDO2dCQUNoRCxTQUFTLENBQUMsTUFBTSxDQUFDLENBQUM7WUFDdEIsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLFNBQVMsQ0FBQyxDQUFDO1NBQ3ZCO2FBQU0sSUFBSSxDQUFDLFFBQVEsQ0FBQyxJQUFLLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSyxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxFQUFFO1lBRTlGLE9BQU8sRUFBRSxDQUFDLFFBQVEsQ0FBQyxVQUFDLFFBQVE7Z0JBQ3hCLElBQU0sTUFBTSxHQUFHLEtBQUksQ0FBQyxpQkFBaUIsQ0FBQyxRQUFRLENBQUMsQ0FBQztnQkFDaEQsU0FBUyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1lBQ3RCLENBQUMsRUFBRSxJQUFJLEVBQUUsU0FBUyxDQUFDLENBQUM7U0FDdkI7SUFDTCxDQUFDO0lBRUwsa0JBQUM7QUFBRCxDQXJZQSxBQXFZQyxJQUFBO0FBcllZLGtDQUFXIiwiZmlsZSI6ImdlbmVyYXRlZC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzQ29udGVudCI6WyIoZnVuY3Rpb24oKXtmdW5jdGlvbiByKGUsbix0KXtmdW5jdGlvbiBvKGksZil7aWYoIW5baV0pe2lmKCFlW2ldKXt2YXIgYz1cImZ1bmN0aW9uXCI9PXR5cGVvZiByZXF1aXJlJiZyZXF1aXJlO2lmKCFmJiZjKXJldHVybiBjKGksITApO2lmKHUpcmV0dXJuIHUoaSwhMCk7dmFyIGE9bmV3IEVycm9yKFwiQ2Fubm90IGZpbmQgbW9kdWxlICdcIitpK1wiJ1wiKTt0aHJvdyBhLmNvZGU9XCJNT0RVTEVfTk9UX0ZPVU5EXCIsYX12YXIgcD1uW2ldPXtleHBvcnRzOnt9fTtlW2ldWzBdLmNhbGwocC5leHBvcnRzLGZ1bmN0aW9uKHIpe3ZhciBuPWVbaV1bMV1bcl07cmV0dXJuIG8obnx8cil9LHAscC5leHBvcnRzLHIsZSxuLHQpfXJldHVybiBuW2ldLmV4cG9ydHN9Zm9yKHZhciB1PVwiZnVuY3Rpb25cIj09dHlwZW9mIHJlcXVpcmUmJnJlcXVpcmUsaT0wO2k8dC5sZW5ndGg7aSsrKW8odFtpXSk7cmV0dXJuIG99cmV0dXJuIHJ9KSgpIiwiLy8gQ29weXJpZ2h0IEpveWVudCwgSW5jLiBhbmQgb3RoZXIgTm9kZSBjb250cmlidXRvcnMuXG4vL1xuLy8gUGVybWlzc2lvbiBpcyBoZXJlYnkgZ3JhbnRlZCwgZnJlZSBvZiBjaGFyZ2UsIHRvIGFueSBwZXJzb24gb2J0YWluaW5nIGFcbi8vIGNvcHkgb2YgdGhpcyBzb2Z0d2FyZSBhbmQgYXNzb2NpYXRlZCBkb2N1bWVudGF0aW9uIGZpbGVzICh0aGVcbi8vIFwiU29mdHdhcmVcIiksIHRvIGRlYWwgaW4gdGhlIFNvZnR3YXJlIHdpdGhvdXQgcmVzdHJpY3Rpb24sIGluY2x1ZGluZ1xuLy8gd2l0aG91dCBsaW1pdGF0aW9uIHRoZSByaWdodHMgdG8gdXNlLCBjb3B5LCBtb2RpZnksIG1lcmdlLCBwdWJsaXNoLFxuLy8gZGlzdHJpYnV0ZSwgc3VibGljZW5zZSwgYW5kL29yIHNlbGwgY29waWVzIG9mIHRoZSBTb2Z0d2FyZSwgYW5kIHRvIHBlcm1pdFxuLy8gcGVyc29ucyB0byB3aG9tIHRoZSBTb2Z0d2FyZSBpcyBmdXJuaXNoZWQgdG8gZG8gc28sIHN1YmplY3QgdG8gdGhlXG4vLyBmb2xsb3dpbmcgY29uZGl0aW9uczpcbi8vXG4vLyBUaGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSBhbmQgdGhpcyBwZXJtaXNzaW9uIG5vdGljZSBzaGFsbCBiZSBpbmNsdWRlZFxuLy8gaW4gYWxsIGNvcGllcyBvciBzdWJzdGFudGlhbCBwb3J0aW9ucyBvZiB0aGUgU29mdHdhcmUuXG4vL1xuLy8gVEhFIFNPRlRXQVJFIElTIFBST1ZJREVEIFwiQVMgSVNcIiwgV0lUSE9VVCBXQVJSQU5UWSBPRiBBTlkgS0lORCwgRVhQUkVTU1xuLy8gT1IgSU1QTElFRCwgSU5DTFVESU5HIEJVVCBOT1QgTElNSVRFRCBUTyBUSEUgV0FSUkFOVElFUyBPRlxuLy8gTUVSQ0hBTlRBQklMSVRZLCBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBTkQgTk9OSU5GUklOR0VNRU5ULiBJTlxuLy8gTk8gRVZFTlQgU0hBTEwgVEhFIEFVVEhPUlMgT1IgQ09QWVJJR0hUIEhPTERFUlMgQkUgTElBQkxFIEZPUiBBTlkgQ0xBSU0sXG4vLyBEQU1BR0VTIE9SIE9USEVSIExJQUJJTElUWSwgV0hFVEhFUiBJTiBBTiBBQ1RJT04gT0YgQ09OVFJBQ1QsIFRPUlQgT1Jcbi8vIE9USEVSV0lTRSwgQVJJU0lORyBGUk9NLCBPVVQgT0YgT1IgSU4gQ09OTkVDVElPTiBXSVRIIFRIRSBTT0ZUV0FSRSBPUiBUSEVcbi8vIFVTRSBPUiBPVEhFUiBERUFMSU5HUyBJTiBUSEUgU09GVFdBUkUuXG5cbnZhciBvYmplY3RDcmVhdGUgPSBPYmplY3QuY3JlYXRlIHx8IG9iamVjdENyZWF0ZVBvbHlmaWxsXG52YXIgb2JqZWN0S2V5cyA9IE9iamVjdC5rZXlzIHx8IG9iamVjdEtleXNQb2x5ZmlsbFxudmFyIGJpbmQgPSBGdW5jdGlvbi5wcm90b3R5cGUuYmluZCB8fCBmdW5jdGlvbkJpbmRQb2x5ZmlsbFxuXG5mdW5jdGlvbiBFdmVudEVtaXR0ZXIoKSB7XG4gIGlmICghdGhpcy5fZXZlbnRzIHx8ICFPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwodGhpcywgJ19ldmVudHMnKSkge1xuICAgIHRoaXMuX2V2ZW50cyA9IG9iamVjdENyZWF0ZShudWxsKTtcbiAgICB0aGlzLl9ldmVudHNDb3VudCA9IDA7XG4gIH1cblxuICB0aGlzLl9tYXhMaXN0ZW5lcnMgPSB0aGlzLl9tYXhMaXN0ZW5lcnMgfHwgdW5kZWZpbmVkO1xufVxubW9kdWxlLmV4cG9ydHMgPSBFdmVudEVtaXR0ZXI7XG5cbi8vIEJhY2t3YXJkcy1jb21wYXQgd2l0aCBub2RlIDAuMTAueFxuRXZlbnRFbWl0dGVyLkV2ZW50RW1pdHRlciA9IEV2ZW50RW1pdHRlcjtcblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5fZXZlbnRzID0gdW5kZWZpbmVkO1xuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5fbWF4TGlzdGVuZXJzID0gdW5kZWZpbmVkO1xuXG4vLyBCeSBkZWZhdWx0IEV2ZW50RW1pdHRlcnMgd2lsbCBwcmludCBhIHdhcm5pbmcgaWYgbW9yZSB0aGFuIDEwIGxpc3RlbmVycyBhcmVcbi8vIGFkZGVkIHRvIGl0LiBUaGlzIGlzIGEgdXNlZnVsIGRlZmF1bHQgd2hpY2ggaGVscHMgZmluZGluZyBtZW1vcnkgbGVha3MuXG52YXIgZGVmYXVsdE1heExpc3RlbmVycyA9IDEwO1xuXG52YXIgaGFzRGVmaW5lUHJvcGVydHk7XG50cnkge1xuICB2YXIgbyA9IHt9O1xuICBpZiAoT2JqZWN0LmRlZmluZVByb3BlcnR5KSBPYmplY3QuZGVmaW5lUHJvcGVydHkobywgJ3gnLCB7IHZhbHVlOiAwIH0pO1xuICBoYXNEZWZpbmVQcm9wZXJ0eSA9IG8ueCA9PT0gMDtcbn0gY2F0Y2ggKGVycikgeyBoYXNEZWZpbmVQcm9wZXJ0eSA9IGZhbHNlIH1cbmlmIChoYXNEZWZpbmVQcm9wZXJ0eSkge1xuICBPYmplY3QuZGVmaW5lUHJvcGVydHkoRXZlbnRFbWl0dGVyLCAnZGVmYXVsdE1heExpc3RlbmVycycsIHtcbiAgICBlbnVtZXJhYmxlOiB0cnVlLFxuICAgIGdldDogZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4gZGVmYXVsdE1heExpc3RlbmVycztcbiAgICB9LFxuICAgIHNldDogZnVuY3Rpb24oYXJnKSB7XG4gICAgICAvLyBjaGVjayB3aGV0aGVyIHRoZSBpbnB1dCBpcyBhIHBvc2l0aXZlIG51bWJlciAod2hvc2UgdmFsdWUgaXMgemVybyBvclxuICAgICAgLy8gZ3JlYXRlciBhbmQgbm90IGEgTmFOKS5cbiAgICAgIGlmICh0eXBlb2YgYXJnICE9PSAnbnVtYmVyJyB8fCBhcmcgPCAwIHx8IGFyZyAhPT0gYXJnKVxuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdcImRlZmF1bHRNYXhMaXN0ZW5lcnNcIiBtdXN0IGJlIGEgcG9zaXRpdmUgbnVtYmVyJyk7XG4gICAgICBkZWZhdWx0TWF4TGlzdGVuZXJzID0gYXJnO1xuICAgIH1cbiAgfSk7XG59IGVsc2Uge1xuICBFdmVudEVtaXR0ZXIuZGVmYXVsdE1heExpc3RlbmVycyA9IGRlZmF1bHRNYXhMaXN0ZW5lcnM7XG59XG5cbi8vIE9idmlvdXNseSBub3QgYWxsIEVtaXR0ZXJzIHNob3VsZCBiZSBsaW1pdGVkIHRvIDEwLiBUaGlzIGZ1bmN0aW9uIGFsbG93c1xuLy8gdGhhdCB0byBiZSBpbmNyZWFzZWQuIFNldCB0byB6ZXJvIGZvciB1bmxpbWl0ZWQuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLnNldE1heExpc3RlbmVycyA9IGZ1bmN0aW9uIHNldE1heExpc3RlbmVycyhuKSB7XG4gIGlmICh0eXBlb2YgbiAhPT0gJ251bWJlcicgfHwgbiA8IDAgfHwgaXNOYU4obikpXG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcignXCJuXCIgYXJndW1lbnQgbXVzdCBiZSBhIHBvc2l0aXZlIG51bWJlcicpO1xuICB0aGlzLl9tYXhMaXN0ZW5lcnMgPSBuO1xuICByZXR1cm4gdGhpcztcbn07XG5cbmZ1bmN0aW9uICRnZXRNYXhMaXN0ZW5lcnModGhhdCkge1xuICBpZiAodGhhdC5fbWF4TGlzdGVuZXJzID09PSB1bmRlZmluZWQpXG4gICAgcmV0dXJuIEV2ZW50RW1pdHRlci5kZWZhdWx0TWF4TGlzdGVuZXJzO1xuICByZXR1cm4gdGhhdC5fbWF4TGlzdGVuZXJzO1xufVxuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLmdldE1heExpc3RlbmVycyA9IGZ1bmN0aW9uIGdldE1heExpc3RlbmVycygpIHtcbiAgcmV0dXJuICRnZXRNYXhMaXN0ZW5lcnModGhpcyk7XG59O1xuXG4vLyBUaGVzZSBzdGFuZGFsb25lIGVtaXQqIGZ1bmN0aW9ucyBhcmUgdXNlZCB0byBvcHRpbWl6ZSBjYWxsaW5nIG9mIGV2ZW50XG4vLyBoYW5kbGVycyBmb3IgZmFzdCBjYXNlcyBiZWNhdXNlIGVtaXQoKSBpdHNlbGYgb2Z0ZW4gaGFzIGEgdmFyaWFibGUgbnVtYmVyIG9mXG4vLyBhcmd1bWVudHMgYW5kIGNhbiBiZSBkZW9wdGltaXplZCBiZWNhdXNlIG9mIHRoYXQuIFRoZXNlIGZ1bmN0aW9ucyBhbHdheXMgaGF2ZVxuLy8gdGhlIHNhbWUgbnVtYmVyIG9mIGFyZ3VtZW50cyBhbmQgdGh1cyBkbyBub3QgZ2V0IGRlb3B0aW1pemVkLCBzbyB0aGUgY29kZVxuLy8gaW5zaWRlIHRoZW0gY2FuIGV4ZWN1dGUgZmFzdGVyLlxuZnVuY3Rpb24gZW1pdE5vbmUoaGFuZGxlciwgaXNGbiwgc2VsZikge1xuICBpZiAoaXNGbilcbiAgICBoYW5kbGVyLmNhbGwoc2VsZik7XG4gIGVsc2Uge1xuICAgIHZhciBsZW4gPSBoYW5kbGVyLmxlbmd0aDtcbiAgICB2YXIgbGlzdGVuZXJzID0gYXJyYXlDbG9uZShoYW5kbGVyLCBsZW4pO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuOyArK2kpXG4gICAgICBsaXN0ZW5lcnNbaV0uY2FsbChzZWxmKTtcbiAgfVxufVxuZnVuY3Rpb24gZW1pdE9uZShoYW5kbGVyLCBpc0ZuLCBzZWxmLCBhcmcxKSB7XG4gIGlmIChpc0ZuKVxuICAgIGhhbmRsZXIuY2FsbChzZWxmLCBhcmcxKTtcbiAgZWxzZSB7XG4gICAgdmFyIGxlbiA9IGhhbmRsZXIubGVuZ3RoO1xuICAgIHZhciBsaXN0ZW5lcnMgPSBhcnJheUNsb25lKGhhbmRsZXIsIGxlbik7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW47ICsraSlcbiAgICAgIGxpc3RlbmVyc1tpXS5jYWxsKHNlbGYsIGFyZzEpO1xuICB9XG59XG5mdW5jdGlvbiBlbWl0VHdvKGhhbmRsZXIsIGlzRm4sIHNlbGYsIGFyZzEsIGFyZzIpIHtcbiAgaWYgKGlzRm4pXG4gICAgaGFuZGxlci5jYWxsKHNlbGYsIGFyZzEsIGFyZzIpO1xuICBlbHNlIHtcbiAgICB2YXIgbGVuID0gaGFuZGxlci5sZW5ndGg7XG4gICAgdmFyIGxpc3RlbmVycyA9IGFycmF5Q2xvbmUoaGFuZGxlciwgbGVuKTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgKytpKVxuICAgICAgbGlzdGVuZXJzW2ldLmNhbGwoc2VsZiwgYXJnMSwgYXJnMik7XG4gIH1cbn1cbmZ1bmN0aW9uIGVtaXRUaHJlZShoYW5kbGVyLCBpc0ZuLCBzZWxmLCBhcmcxLCBhcmcyLCBhcmczKSB7XG4gIGlmIChpc0ZuKVxuICAgIGhhbmRsZXIuY2FsbChzZWxmLCBhcmcxLCBhcmcyLCBhcmczKTtcbiAgZWxzZSB7XG4gICAgdmFyIGxlbiA9IGhhbmRsZXIubGVuZ3RoO1xuICAgIHZhciBsaXN0ZW5lcnMgPSBhcnJheUNsb25lKGhhbmRsZXIsIGxlbik7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW47ICsraSlcbiAgICAgIGxpc3RlbmVyc1tpXS5jYWxsKHNlbGYsIGFyZzEsIGFyZzIsIGFyZzMpO1xuICB9XG59XG5cbmZ1bmN0aW9uIGVtaXRNYW55KGhhbmRsZXIsIGlzRm4sIHNlbGYsIGFyZ3MpIHtcbiAgaWYgKGlzRm4pXG4gICAgaGFuZGxlci5hcHBseShzZWxmLCBhcmdzKTtcbiAgZWxzZSB7XG4gICAgdmFyIGxlbiA9IGhhbmRsZXIubGVuZ3RoO1xuICAgIHZhciBsaXN0ZW5lcnMgPSBhcnJheUNsb25lKGhhbmRsZXIsIGxlbik7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW47ICsraSlcbiAgICAgIGxpc3RlbmVyc1tpXS5hcHBseShzZWxmLCBhcmdzKTtcbiAgfVxufVxuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLmVtaXQgPSBmdW5jdGlvbiBlbWl0KHR5cGUpIHtcbiAgdmFyIGVyLCBoYW5kbGVyLCBsZW4sIGFyZ3MsIGksIGV2ZW50cztcbiAgdmFyIGRvRXJyb3IgPSAodHlwZSA9PT0gJ2Vycm9yJyk7XG5cbiAgZXZlbnRzID0gdGhpcy5fZXZlbnRzO1xuICBpZiAoZXZlbnRzKVxuICAgIGRvRXJyb3IgPSAoZG9FcnJvciAmJiBldmVudHMuZXJyb3IgPT0gbnVsbCk7XG4gIGVsc2UgaWYgKCFkb0Vycm9yKVxuICAgIHJldHVybiBmYWxzZTtcblxuICAvLyBJZiB0aGVyZSBpcyBubyAnZXJyb3InIGV2ZW50IGxpc3RlbmVyIHRoZW4gdGhyb3cuXG4gIGlmIChkb0Vycm9yKSB7XG4gICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPiAxKVxuICAgICAgZXIgPSBhcmd1bWVudHNbMV07XG4gICAgaWYgKGVyIGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICAgIHRocm93IGVyOyAvLyBVbmhhbmRsZWQgJ2Vycm9yJyBldmVudFxuICAgIH0gZWxzZSB7XG4gICAgICAvLyBBdCBsZWFzdCBnaXZlIHNvbWUga2luZCBvZiBjb250ZXh0IHRvIHRoZSB1c2VyXG4gICAgICB2YXIgZXJyID0gbmV3IEVycm9yKCdVbmhhbmRsZWQgXCJlcnJvclwiIGV2ZW50LiAoJyArIGVyICsgJyknKTtcbiAgICAgIGVyci5jb250ZXh0ID0gZXI7XG4gICAgICB0aHJvdyBlcnI7XG4gICAgfVxuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIGhhbmRsZXIgPSBldmVudHNbdHlwZV07XG5cbiAgaWYgKCFoYW5kbGVyKVxuICAgIHJldHVybiBmYWxzZTtcblxuICB2YXIgaXNGbiA9IHR5cGVvZiBoYW5kbGVyID09PSAnZnVuY3Rpb24nO1xuICBsZW4gPSBhcmd1bWVudHMubGVuZ3RoO1xuICBzd2l0Y2ggKGxlbikge1xuICAgICAgLy8gZmFzdCBjYXNlc1xuICAgIGNhc2UgMTpcbiAgICAgIGVtaXROb25lKGhhbmRsZXIsIGlzRm4sIHRoaXMpO1xuICAgICAgYnJlYWs7XG4gICAgY2FzZSAyOlxuICAgICAgZW1pdE9uZShoYW5kbGVyLCBpc0ZuLCB0aGlzLCBhcmd1bWVudHNbMV0pO1xuICAgICAgYnJlYWs7XG4gICAgY2FzZSAzOlxuICAgICAgZW1pdFR3byhoYW5kbGVyLCBpc0ZuLCB0aGlzLCBhcmd1bWVudHNbMV0sIGFyZ3VtZW50c1syXSk7XG4gICAgICBicmVhaztcbiAgICBjYXNlIDQ6XG4gICAgICBlbWl0VGhyZWUoaGFuZGxlciwgaXNGbiwgdGhpcywgYXJndW1lbnRzWzFdLCBhcmd1bWVudHNbMl0sIGFyZ3VtZW50c1szXSk7XG4gICAgICBicmVhaztcbiAgICAgIC8vIHNsb3dlclxuICAgIGRlZmF1bHQ6XG4gICAgICBhcmdzID0gbmV3IEFycmF5KGxlbiAtIDEpO1xuICAgICAgZm9yIChpID0gMTsgaSA8IGxlbjsgaSsrKVxuICAgICAgICBhcmdzW2kgLSAxXSA9IGFyZ3VtZW50c1tpXTtcbiAgICAgIGVtaXRNYW55KGhhbmRsZXIsIGlzRm4sIHRoaXMsIGFyZ3MpO1xuICB9XG5cbiAgcmV0dXJuIHRydWU7XG59O1xuXG5mdW5jdGlvbiBfYWRkTGlzdGVuZXIodGFyZ2V0LCB0eXBlLCBsaXN0ZW5lciwgcHJlcGVuZCkge1xuICB2YXIgbTtcbiAgdmFyIGV2ZW50cztcbiAgdmFyIGV4aXN0aW5nO1xuXG4gIGlmICh0eXBlb2YgbGlzdGVuZXIgIT09ICdmdW5jdGlvbicpXG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcignXCJsaXN0ZW5lclwiIGFyZ3VtZW50IG11c3QgYmUgYSBmdW5jdGlvbicpO1xuXG4gIGV2ZW50cyA9IHRhcmdldC5fZXZlbnRzO1xuICBpZiAoIWV2ZW50cykge1xuICAgIGV2ZW50cyA9IHRhcmdldC5fZXZlbnRzID0gb2JqZWN0Q3JlYXRlKG51bGwpO1xuICAgIHRhcmdldC5fZXZlbnRzQ291bnQgPSAwO1xuICB9IGVsc2Uge1xuICAgIC8vIFRvIGF2b2lkIHJlY3Vyc2lvbiBpbiB0aGUgY2FzZSB0aGF0IHR5cGUgPT09IFwibmV3TGlzdGVuZXJcIiEgQmVmb3JlXG4gICAgLy8gYWRkaW5nIGl0IHRvIHRoZSBsaXN0ZW5lcnMsIGZpcnN0IGVtaXQgXCJuZXdMaXN0ZW5lclwiLlxuICAgIGlmIChldmVudHMubmV3TGlzdGVuZXIpIHtcbiAgICAgIHRhcmdldC5lbWl0KCduZXdMaXN0ZW5lcicsIHR5cGUsXG4gICAgICAgICAgbGlzdGVuZXIubGlzdGVuZXIgPyBsaXN0ZW5lci5saXN0ZW5lciA6IGxpc3RlbmVyKTtcblxuICAgICAgLy8gUmUtYXNzaWduIGBldmVudHNgIGJlY2F1c2UgYSBuZXdMaXN0ZW5lciBoYW5kbGVyIGNvdWxkIGhhdmUgY2F1c2VkIHRoZVxuICAgICAgLy8gdGhpcy5fZXZlbnRzIHRvIGJlIGFzc2lnbmVkIHRvIGEgbmV3IG9iamVjdFxuICAgICAgZXZlbnRzID0gdGFyZ2V0Ll9ldmVudHM7XG4gICAgfVxuICAgIGV4aXN0aW5nID0gZXZlbnRzW3R5cGVdO1xuICB9XG5cbiAgaWYgKCFleGlzdGluZykge1xuICAgIC8vIE9wdGltaXplIHRoZSBjYXNlIG9mIG9uZSBsaXN0ZW5lci4gRG9uJ3QgbmVlZCB0aGUgZXh0cmEgYXJyYXkgb2JqZWN0LlxuICAgIGV4aXN0aW5nID0gZXZlbnRzW3R5cGVdID0gbGlzdGVuZXI7XG4gICAgKyt0YXJnZXQuX2V2ZW50c0NvdW50O1xuICB9IGVsc2Uge1xuICAgIGlmICh0eXBlb2YgZXhpc3RpbmcgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgIC8vIEFkZGluZyB0aGUgc2Vjb25kIGVsZW1lbnQsIG5lZWQgdG8gY2hhbmdlIHRvIGFycmF5LlxuICAgICAgZXhpc3RpbmcgPSBldmVudHNbdHlwZV0gPVxuICAgICAgICAgIHByZXBlbmQgPyBbbGlzdGVuZXIsIGV4aXN0aW5nXSA6IFtleGlzdGluZywgbGlzdGVuZXJdO1xuICAgIH0gZWxzZSB7XG4gICAgICAvLyBJZiB3ZSd2ZSBhbHJlYWR5IGdvdCBhbiBhcnJheSwganVzdCBhcHBlbmQuXG4gICAgICBpZiAocHJlcGVuZCkge1xuICAgICAgICBleGlzdGluZy51bnNoaWZ0KGxpc3RlbmVyKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGV4aXN0aW5nLnB1c2gobGlzdGVuZXIpO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIENoZWNrIGZvciBsaXN0ZW5lciBsZWFrXG4gICAgaWYgKCFleGlzdGluZy53YXJuZWQpIHtcbiAgICAgIG0gPSAkZ2V0TWF4TGlzdGVuZXJzKHRhcmdldCk7XG4gICAgICBpZiAobSAmJiBtID4gMCAmJiBleGlzdGluZy5sZW5ndGggPiBtKSB7XG4gICAgICAgIGV4aXN0aW5nLndhcm5lZCA9IHRydWU7XG4gICAgICAgIHZhciB3ID0gbmV3IEVycm9yKCdQb3NzaWJsZSBFdmVudEVtaXR0ZXIgbWVtb3J5IGxlYWsgZGV0ZWN0ZWQuICcgK1xuICAgICAgICAgICAgZXhpc3RpbmcubGVuZ3RoICsgJyBcIicgKyBTdHJpbmcodHlwZSkgKyAnXCIgbGlzdGVuZXJzICcgK1xuICAgICAgICAgICAgJ2FkZGVkLiBVc2UgZW1pdHRlci5zZXRNYXhMaXN0ZW5lcnMoKSB0byAnICtcbiAgICAgICAgICAgICdpbmNyZWFzZSBsaW1pdC4nKTtcbiAgICAgICAgdy5uYW1lID0gJ01heExpc3RlbmVyc0V4Y2VlZGVkV2FybmluZyc7XG4gICAgICAgIHcuZW1pdHRlciA9IHRhcmdldDtcbiAgICAgICAgdy50eXBlID0gdHlwZTtcbiAgICAgICAgdy5jb3VudCA9IGV4aXN0aW5nLmxlbmd0aDtcbiAgICAgICAgaWYgKHR5cGVvZiBjb25zb2xlID09PSAnb2JqZWN0JyAmJiBjb25zb2xlLndhcm4pIHtcbiAgICAgICAgICBjb25zb2xlLndhcm4oJyVzOiAlcycsIHcubmFtZSwgdy5tZXNzYWdlKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHJldHVybiB0YXJnZXQ7XG59XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUuYWRkTGlzdGVuZXIgPSBmdW5jdGlvbiBhZGRMaXN0ZW5lcih0eXBlLCBsaXN0ZW5lcikge1xuICByZXR1cm4gX2FkZExpc3RlbmVyKHRoaXMsIHR5cGUsIGxpc3RlbmVyLCBmYWxzZSk7XG59O1xuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLm9uID0gRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5hZGRMaXN0ZW5lcjtcblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5wcmVwZW5kTGlzdGVuZXIgPVxuICAgIGZ1bmN0aW9uIHByZXBlbmRMaXN0ZW5lcih0eXBlLCBsaXN0ZW5lcikge1xuICAgICAgcmV0dXJuIF9hZGRMaXN0ZW5lcih0aGlzLCB0eXBlLCBsaXN0ZW5lciwgdHJ1ZSk7XG4gICAgfTtcblxuZnVuY3Rpb24gb25jZVdyYXBwZXIoKSB7XG4gIGlmICghdGhpcy5maXJlZCkge1xuICAgIHRoaXMudGFyZ2V0LnJlbW92ZUxpc3RlbmVyKHRoaXMudHlwZSwgdGhpcy53cmFwRm4pO1xuICAgIHRoaXMuZmlyZWQgPSB0cnVlO1xuICAgIHN3aXRjaCAoYXJndW1lbnRzLmxlbmd0aCkge1xuICAgICAgY2FzZSAwOlxuICAgICAgICByZXR1cm4gdGhpcy5saXN0ZW5lci5jYWxsKHRoaXMudGFyZ2V0KTtcbiAgICAgIGNhc2UgMTpcbiAgICAgICAgcmV0dXJuIHRoaXMubGlzdGVuZXIuY2FsbCh0aGlzLnRhcmdldCwgYXJndW1lbnRzWzBdKTtcbiAgICAgIGNhc2UgMjpcbiAgICAgICAgcmV0dXJuIHRoaXMubGlzdGVuZXIuY2FsbCh0aGlzLnRhcmdldCwgYXJndW1lbnRzWzBdLCBhcmd1bWVudHNbMV0pO1xuICAgICAgY2FzZSAzOlxuICAgICAgICByZXR1cm4gdGhpcy5saXN0ZW5lci5jYWxsKHRoaXMudGFyZ2V0LCBhcmd1bWVudHNbMF0sIGFyZ3VtZW50c1sxXSxcbiAgICAgICAgICAgIGFyZ3VtZW50c1syXSk7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB2YXIgYXJncyA9IG5ldyBBcnJheShhcmd1bWVudHMubGVuZ3RoKTtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBhcmdzLmxlbmd0aDsgKytpKVxuICAgICAgICAgIGFyZ3NbaV0gPSBhcmd1bWVudHNbaV07XG4gICAgICAgIHRoaXMubGlzdGVuZXIuYXBwbHkodGhpcy50YXJnZXQsIGFyZ3MpO1xuICAgIH1cbiAgfVxufVxuXG5mdW5jdGlvbiBfb25jZVdyYXAodGFyZ2V0LCB0eXBlLCBsaXN0ZW5lcikge1xuICB2YXIgc3RhdGUgPSB7IGZpcmVkOiBmYWxzZSwgd3JhcEZuOiB1bmRlZmluZWQsIHRhcmdldDogdGFyZ2V0LCB0eXBlOiB0eXBlLCBsaXN0ZW5lcjogbGlzdGVuZXIgfTtcbiAgdmFyIHdyYXBwZWQgPSBiaW5kLmNhbGwob25jZVdyYXBwZXIsIHN0YXRlKTtcbiAgd3JhcHBlZC5saXN0ZW5lciA9IGxpc3RlbmVyO1xuICBzdGF0ZS53cmFwRm4gPSB3cmFwcGVkO1xuICByZXR1cm4gd3JhcHBlZDtcbn1cblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5vbmNlID0gZnVuY3Rpb24gb25jZSh0eXBlLCBsaXN0ZW5lcikge1xuICBpZiAodHlwZW9mIGxpc3RlbmVyICE9PSAnZnVuY3Rpb24nKVxuICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ1wibGlzdGVuZXJcIiBhcmd1bWVudCBtdXN0IGJlIGEgZnVuY3Rpb24nKTtcbiAgdGhpcy5vbih0eXBlLCBfb25jZVdyYXAodGhpcywgdHlwZSwgbGlzdGVuZXIpKTtcbiAgcmV0dXJuIHRoaXM7XG59O1xuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLnByZXBlbmRPbmNlTGlzdGVuZXIgPVxuICAgIGZ1bmN0aW9uIHByZXBlbmRPbmNlTGlzdGVuZXIodHlwZSwgbGlzdGVuZXIpIHtcbiAgICAgIGlmICh0eXBlb2YgbGlzdGVuZXIgIT09ICdmdW5jdGlvbicpXG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ1wibGlzdGVuZXJcIiBhcmd1bWVudCBtdXN0IGJlIGEgZnVuY3Rpb24nKTtcbiAgICAgIHRoaXMucHJlcGVuZExpc3RlbmVyKHR5cGUsIF9vbmNlV3JhcCh0aGlzLCB0eXBlLCBsaXN0ZW5lcikpO1xuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcblxuLy8gRW1pdHMgYSAncmVtb3ZlTGlzdGVuZXInIGV2ZW50IGlmIGFuZCBvbmx5IGlmIHRoZSBsaXN0ZW5lciB3YXMgcmVtb3ZlZC5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUucmVtb3ZlTGlzdGVuZXIgPVxuICAgIGZ1bmN0aW9uIHJlbW92ZUxpc3RlbmVyKHR5cGUsIGxpc3RlbmVyKSB7XG4gICAgICB2YXIgbGlzdCwgZXZlbnRzLCBwb3NpdGlvbiwgaSwgb3JpZ2luYWxMaXN0ZW5lcjtcblxuICAgICAgaWYgKHR5cGVvZiBsaXN0ZW5lciAhPT0gJ2Z1bmN0aW9uJylcbiAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignXCJsaXN0ZW5lclwiIGFyZ3VtZW50IG11c3QgYmUgYSBmdW5jdGlvbicpO1xuXG4gICAgICBldmVudHMgPSB0aGlzLl9ldmVudHM7XG4gICAgICBpZiAoIWV2ZW50cylcbiAgICAgICAgcmV0dXJuIHRoaXM7XG5cbiAgICAgIGxpc3QgPSBldmVudHNbdHlwZV07XG4gICAgICBpZiAoIWxpc3QpXG4gICAgICAgIHJldHVybiB0aGlzO1xuXG4gICAgICBpZiAobGlzdCA9PT0gbGlzdGVuZXIgfHwgbGlzdC5saXN0ZW5lciA9PT0gbGlzdGVuZXIpIHtcbiAgICAgICAgaWYgKC0tdGhpcy5fZXZlbnRzQ291bnQgPT09IDApXG4gICAgICAgICAgdGhpcy5fZXZlbnRzID0gb2JqZWN0Q3JlYXRlKG51bGwpO1xuICAgICAgICBlbHNlIHtcbiAgICAgICAgICBkZWxldGUgZXZlbnRzW3R5cGVdO1xuICAgICAgICAgIGlmIChldmVudHMucmVtb3ZlTGlzdGVuZXIpXG4gICAgICAgICAgICB0aGlzLmVtaXQoJ3JlbW92ZUxpc3RlbmVyJywgdHlwZSwgbGlzdC5saXN0ZW5lciB8fCBsaXN0ZW5lcik7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSBpZiAodHlwZW9mIGxpc3QgIT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgcG9zaXRpb24gPSAtMTtcblxuICAgICAgICBmb3IgKGkgPSBsaXN0Lmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgICAgICAgaWYgKGxpc3RbaV0gPT09IGxpc3RlbmVyIHx8IGxpc3RbaV0ubGlzdGVuZXIgPT09IGxpc3RlbmVyKSB7XG4gICAgICAgICAgICBvcmlnaW5hbExpc3RlbmVyID0gbGlzdFtpXS5saXN0ZW5lcjtcbiAgICAgICAgICAgIHBvc2l0aW9uID0gaTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChwb3NpdGlvbiA8IDApXG4gICAgICAgICAgcmV0dXJuIHRoaXM7XG5cbiAgICAgICAgaWYgKHBvc2l0aW9uID09PSAwKVxuICAgICAgICAgIGxpc3Quc2hpZnQoKTtcbiAgICAgICAgZWxzZVxuICAgICAgICAgIHNwbGljZU9uZShsaXN0LCBwb3NpdGlvbik7XG5cbiAgICAgICAgaWYgKGxpc3QubGVuZ3RoID09PSAxKVxuICAgICAgICAgIGV2ZW50c1t0eXBlXSA9IGxpc3RbMF07XG5cbiAgICAgICAgaWYgKGV2ZW50cy5yZW1vdmVMaXN0ZW5lcilcbiAgICAgICAgICB0aGlzLmVtaXQoJ3JlbW92ZUxpc3RlbmVyJywgdHlwZSwgb3JpZ2luYWxMaXN0ZW5lciB8fCBsaXN0ZW5lcik7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUucmVtb3ZlQWxsTGlzdGVuZXJzID1cbiAgICBmdW5jdGlvbiByZW1vdmVBbGxMaXN0ZW5lcnModHlwZSkge1xuICAgICAgdmFyIGxpc3RlbmVycywgZXZlbnRzLCBpO1xuXG4gICAgICBldmVudHMgPSB0aGlzLl9ldmVudHM7XG4gICAgICBpZiAoIWV2ZW50cylcbiAgICAgICAgcmV0dXJuIHRoaXM7XG5cbiAgICAgIC8vIG5vdCBsaXN0ZW5pbmcgZm9yIHJlbW92ZUxpc3RlbmVyLCBubyBuZWVkIHRvIGVtaXRcbiAgICAgIGlmICghZXZlbnRzLnJlbW92ZUxpc3RlbmVyKSB7XG4gICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgdGhpcy5fZXZlbnRzID0gb2JqZWN0Q3JlYXRlKG51bGwpO1xuICAgICAgICAgIHRoaXMuX2V2ZW50c0NvdW50ID0gMDtcbiAgICAgICAgfSBlbHNlIGlmIChldmVudHNbdHlwZV0pIHtcbiAgICAgICAgICBpZiAoLS10aGlzLl9ldmVudHNDb3VudCA9PT0gMClcbiAgICAgICAgICAgIHRoaXMuX2V2ZW50cyA9IG9iamVjdENyZWF0ZShudWxsKTtcbiAgICAgICAgICBlbHNlXG4gICAgICAgICAgICBkZWxldGUgZXZlbnRzW3R5cGVdO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgfVxuXG4gICAgICAvLyBlbWl0IHJlbW92ZUxpc3RlbmVyIGZvciBhbGwgbGlzdGVuZXJzIG9uIGFsbCBldmVudHNcbiAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgIHZhciBrZXlzID0gb2JqZWN0S2V5cyhldmVudHMpO1xuICAgICAgICB2YXIga2V5O1xuICAgICAgICBmb3IgKGkgPSAwOyBpIDwga2V5cy5sZW5ndGg7ICsraSkge1xuICAgICAgICAgIGtleSA9IGtleXNbaV07XG4gICAgICAgICAgaWYgKGtleSA9PT0gJ3JlbW92ZUxpc3RlbmVyJykgY29udGludWU7XG4gICAgICAgICAgdGhpcy5yZW1vdmVBbGxMaXN0ZW5lcnMoa2V5KTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnJlbW92ZUFsbExpc3RlbmVycygncmVtb3ZlTGlzdGVuZXInKTtcbiAgICAgICAgdGhpcy5fZXZlbnRzID0gb2JqZWN0Q3JlYXRlKG51bGwpO1xuICAgICAgICB0aGlzLl9ldmVudHNDb3VudCA9IDA7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgfVxuXG4gICAgICBsaXN0ZW5lcnMgPSBldmVudHNbdHlwZV07XG5cbiAgICAgIGlmICh0eXBlb2YgbGlzdGVuZXJzID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgIHRoaXMucmVtb3ZlTGlzdGVuZXIodHlwZSwgbGlzdGVuZXJzKTtcbiAgICAgIH0gZWxzZSBpZiAobGlzdGVuZXJzKSB7XG4gICAgICAgIC8vIExJRk8gb3JkZXJcbiAgICAgICAgZm9yIChpID0gbGlzdGVuZXJzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgICAgICAgdGhpcy5yZW1vdmVMaXN0ZW5lcih0eXBlLCBsaXN0ZW5lcnNbaV0pO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG5cbmZ1bmN0aW9uIF9saXN0ZW5lcnModGFyZ2V0LCB0eXBlLCB1bndyYXApIHtcbiAgdmFyIGV2ZW50cyA9IHRhcmdldC5fZXZlbnRzO1xuXG4gIGlmICghZXZlbnRzKVxuICAgIHJldHVybiBbXTtcblxuICB2YXIgZXZsaXN0ZW5lciA9IGV2ZW50c1t0eXBlXTtcbiAgaWYgKCFldmxpc3RlbmVyKVxuICAgIHJldHVybiBbXTtcblxuICBpZiAodHlwZW9mIGV2bGlzdGVuZXIgPT09ICdmdW5jdGlvbicpXG4gICAgcmV0dXJuIHVud3JhcCA/IFtldmxpc3RlbmVyLmxpc3RlbmVyIHx8IGV2bGlzdGVuZXJdIDogW2V2bGlzdGVuZXJdO1xuXG4gIHJldHVybiB1bndyYXAgPyB1bndyYXBMaXN0ZW5lcnMoZXZsaXN0ZW5lcikgOiBhcnJheUNsb25lKGV2bGlzdGVuZXIsIGV2bGlzdGVuZXIubGVuZ3RoKTtcbn1cblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5saXN0ZW5lcnMgPSBmdW5jdGlvbiBsaXN0ZW5lcnModHlwZSkge1xuICByZXR1cm4gX2xpc3RlbmVycyh0aGlzLCB0eXBlLCB0cnVlKTtcbn07XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUucmF3TGlzdGVuZXJzID0gZnVuY3Rpb24gcmF3TGlzdGVuZXJzKHR5cGUpIHtcbiAgcmV0dXJuIF9saXN0ZW5lcnModGhpcywgdHlwZSwgZmFsc2UpO1xufTtcblxuRXZlbnRFbWl0dGVyLmxpc3RlbmVyQ291bnQgPSBmdW5jdGlvbihlbWl0dGVyLCB0eXBlKSB7XG4gIGlmICh0eXBlb2YgZW1pdHRlci5saXN0ZW5lckNvdW50ID09PSAnZnVuY3Rpb24nKSB7XG4gICAgcmV0dXJuIGVtaXR0ZXIubGlzdGVuZXJDb3VudCh0eXBlKTtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gbGlzdGVuZXJDb3VudC5jYWxsKGVtaXR0ZXIsIHR5cGUpO1xuICB9XG59O1xuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLmxpc3RlbmVyQ291bnQgPSBsaXN0ZW5lckNvdW50O1xuZnVuY3Rpb24gbGlzdGVuZXJDb3VudCh0eXBlKSB7XG4gIHZhciBldmVudHMgPSB0aGlzLl9ldmVudHM7XG5cbiAgaWYgKGV2ZW50cykge1xuICAgIHZhciBldmxpc3RlbmVyID0gZXZlbnRzW3R5cGVdO1xuXG4gICAgaWYgKHR5cGVvZiBldmxpc3RlbmVyID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICByZXR1cm4gMTtcbiAgICB9IGVsc2UgaWYgKGV2bGlzdGVuZXIpIHtcbiAgICAgIHJldHVybiBldmxpc3RlbmVyLmxlbmd0aDtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gMDtcbn1cblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5ldmVudE5hbWVzID0gZnVuY3Rpb24gZXZlbnROYW1lcygpIHtcbiAgcmV0dXJuIHRoaXMuX2V2ZW50c0NvdW50ID4gMCA/IFJlZmxlY3Qub3duS2V5cyh0aGlzLl9ldmVudHMpIDogW107XG59O1xuXG4vLyBBYm91dCAxLjV4IGZhc3RlciB0aGFuIHRoZSB0d28tYXJnIHZlcnNpb24gb2YgQXJyYXkjc3BsaWNlKCkuXG5mdW5jdGlvbiBzcGxpY2VPbmUobGlzdCwgaW5kZXgpIHtcbiAgZm9yICh2YXIgaSA9IGluZGV4LCBrID0gaSArIDEsIG4gPSBsaXN0Lmxlbmd0aDsgayA8IG47IGkgKz0gMSwgayArPSAxKVxuICAgIGxpc3RbaV0gPSBsaXN0W2tdO1xuICBsaXN0LnBvcCgpO1xufVxuXG5mdW5jdGlvbiBhcnJheUNsb25lKGFyciwgbikge1xuICB2YXIgY29weSA9IG5ldyBBcnJheShuKTtcbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBuOyArK2kpXG4gICAgY29weVtpXSA9IGFycltpXTtcbiAgcmV0dXJuIGNvcHk7XG59XG5cbmZ1bmN0aW9uIHVud3JhcExpc3RlbmVycyhhcnIpIHtcbiAgdmFyIHJldCA9IG5ldyBBcnJheShhcnIubGVuZ3RoKTtcbiAgZm9yICh2YXIgaSA9IDA7IGkgPCByZXQubGVuZ3RoOyArK2kpIHtcbiAgICByZXRbaV0gPSBhcnJbaV0ubGlzdGVuZXIgfHwgYXJyW2ldO1xuICB9XG4gIHJldHVybiByZXQ7XG59XG5cbmZ1bmN0aW9uIG9iamVjdENyZWF0ZVBvbHlmaWxsKHByb3RvKSB7XG4gIHZhciBGID0gZnVuY3Rpb24oKSB7fTtcbiAgRi5wcm90b3R5cGUgPSBwcm90bztcbiAgcmV0dXJuIG5ldyBGO1xufVxuZnVuY3Rpb24gb2JqZWN0S2V5c1BvbHlmaWxsKG9iaikge1xuICB2YXIga2V5cyA9IFtdO1xuICBmb3IgKHZhciBrIGluIG9iaikgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChvYmosIGspKSB7XG4gICAga2V5cy5wdXNoKGspO1xuICB9XG4gIHJldHVybiBrO1xufVxuZnVuY3Rpb24gZnVuY3Rpb25CaW5kUG9seWZpbGwoY29udGV4dCkge1xuICB2YXIgZm4gPSB0aGlzO1xuICByZXR1cm4gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiBmbi5hcHBseShjb250ZXh0LCBhcmd1bWVudHMpO1xuICB9O1xufVxuIiwiLyoganNoaW50IG5vZGU6IHRydWUgKi9cbid1c2Ugc3RyaWN0JztcblxudmFyIG5vcm1hbGljZSA9IHJlcXVpcmUoJ25vcm1hbGljZScpO1xuXG4vKipcbiAgIyBmcmVlaWNlXG5cbiAgVGhlIGBmcmVlaWNlYCBtb2R1bGUgaXMgYSBzaW1wbGUgd2F5IG9mIGdldHRpbmcgcmFuZG9tIFNUVU4gb3IgVFVSTiBzZXJ2ZXJcbiAgZm9yIHlvdXIgV2ViUlRDIGFwcGxpY2F0aW9uLiAgVGhlIGxpc3Qgb2Ygc2VydmVycyAoanVzdCBTVFVOIGF0IHRoaXMgc3RhZ2UpXG4gIHdlcmUgc291cmNlZCBmcm9tIHRoaXMgW2dpc3RdKGh0dHBzOi8vZ2lzdC5naXRodWIuY29tL3p6aXVuaS8zNzQxOTMzKS5cblxuICAjIyBFeGFtcGxlIFVzZVxuXG4gIFRoZSBmb2xsb3dpbmcgZGVtb25zdHJhdGVzIGhvdyB5b3UgY2FuIHVzZSBgZnJlZWljZWAgd2l0aFxuICBbcnRjLXF1aWNrY29ubmVjdF0oaHR0cHM6Ly9naXRodWIuY29tL3J0Yy1pby9ydGMtcXVpY2tjb25uZWN0KTpcblxuICA8PDwgZXhhbXBsZXMvcXVpY2tjb25uZWN0LmpzXG5cbiAgQXMgdGhlIGBmcmVlaWNlYCBtb2R1bGUgZ2VuZXJhdGVzIGljZSBzZXJ2ZXJzIGluIGEgbGlzdCBjb21wbGlhbnQgd2l0aCB0aGVcbiAgV2ViUlRDIHNwZWMgeW91IHdpbGwgYmUgYWJsZSB0byB1c2UgaXQgd2l0aCByYXcgYFJUQ1BlZXJDb25uZWN0aW9uYFxuICBjb25zdHJ1Y3RvcnMgYW5kIG90aGVyIFdlYlJUQyBsaWJyYXJpZXMuXG5cbiAgIyMgSGV5LCBkb24ndCB1c2UgbXkgU1RVTi9UVVJOIHNlcnZlciFcblxuICBJZiBmb3Igc29tZSByZWFzb24geW91ciBmcmVlIFNUVU4gb3IgVFVSTiBzZXJ2ZXIgZW5kcyB1cCBpbiB0aGVcbiAgbGlzdCBvZiBzZXJ2ZXJzIChbc3R1bl0oaHR0cHM6Ly9naXRodWIuY29tL0RhbW9uT2VobG1hbi9mcmVlaWNlL2Jsb2IvbWFzdGVyL3N0dW4uanNvbikgb3JcbiAgW3R1cm5dKGh0dHBzOi8vZ2l0aHViLmNvbS9EYW1vbk9laGxtYW4vZnJlZWljZS9ibG9iL21hc3Rlci90dXJuLmpzb24pKVxuICB0aGF0IGlzIHVzZWQgaW4gdGhpcyBtb2R1bGUsIHlvdSBjYW4gZmVlbFxuICBmcmVlIHRvIG9wZW4gYW4gaXNzdWUgb24gdGhpcyByZXBvc2l0b3J5IGFuZCB0aG9zZSBzZXJ2ZXJzIHdpbGwgYmUgcmVtb3ZlZFxuICB3aXRoaW4gMjQgaG91cnMgKG9yIHNvb25lcikuICBUaGlzIGlzIHRoZSBxdWlja2VzdCBhbmQgcHJvYmFibHkgdGhlIG1vc3RcbiAgcG9saXRlIHdheSB0byBoYXZlIHNvbWV0aGluZyByZW1vdmVkIChhbmQgcHJvdmlkZXMgdXMgc29tZSB2aXNpYmlsaXR5XG4gIGlmIHNvbWVvbmUgb3BlbnMgYSBwdWxsIHJlcXVlc3QgcmVxdWVzdGluZyB0aGF0IGEgc2VydmVyIGlzIGFkZGVkKS5cblxuICAjIyBQbGVhc2UgYWRkIG15IHNlcnZlciFcblxuICBJZiB5b3UgaGF2ZSBhIHNlcnZlciB0aGF0IHlvdSB3aXNoIHRvIGFkZCB0byB0aGUgbGlzdCwgdGhhdCdzIGF3ZXNvbWUhIEknbVxuICBzdXJlIEkgc3BlYWsgb24gYmVoYWxmIG9mIGEgd2hvbGUgcGlsZSBvZiBXZWJSVEMgZGV2ZWxvcGVycyB3aG8gc2F5IHRoYW5rcy5cbiAgVG8gZ2V0IGl0IGludG8gdGhlIGxpc3QsIGZlZWwgZnJlZSB0byBlaXRoZXIgb3BlbiBhIHB1bGwgcmVxdWVzdCBvciBpZiB5b3VcbiAgZmluZCB0aGF0IHByb2Nlc3MgYSBiaXQgZGF1bnRpbmcgdGhlbiBqdXN0IGNyZWF0ZSBhbiBpc3N1ZSByZXF1ZXN0aW5nXG4gIHRoZSBhZGRpdGlvbiBvZiB0aGUgc2VydmVyIChtYWtlIHN1cmUgeW91IHByb3ZpZGUgYWxsIHRoZSBkZXRhaWxzLCBhbmQgaWZcbiAgeW91IGhhdmUgYSBUZXJtcyBvZiBTZXJ2aWNlIHRoZW4gaW5jbHVkaW5nIHRoYXQgaW4gdGhlIFBSL2lzc3VlIHdvdWxkIGJlXG4gIGF3ZXNvbWUpLlxuXG4gICMjIEkga25vdyBvZiBhIGZyZWUgc2VydmVyLCBjYW4gSSBhZGQgaXQ/XG5cbiAgU3VyZSwgaWYgeW91IGRvIHlvdXIgaG9tZXdvcmsgYW5kIG1ha2Ugc3VyZSBpdCBpcyBvayB0byB1c2UgKEknbSBjdXJyZW50bHlcbiAgaW4gdGhlIHByb2Nlc3Mgb2YgcmV2aWV3aW5nIHRoZSB0ZXJtcyBvZiB0aG9zZSBTVFVOIHNlcnZlcnMgaW5jbHVkZWQgZnJvbVxuICB0aGUgb3JpZ2luYWwgbGlzdCkuICBJZiBpdCdzIG9rIHRvIGdvLCB0aGVuIHBsZWFzZSBzZWUgdGhlIHByZXZpb3VzIGVudHJ5XG4gIGZvciBob3cgdG8gYWRkIGl0LlxuXG4gICMjIEN1cnJlbnQgTGlzdCBvZiBTZXJ2ZXJzXG5cbiAgKiBjdXJyZW50IGFzIGF0IHRoZSB0aW1lIG9mIGxhc3QgYFJFQURNRS5tZGAgZmlsZSBnZW5lcmF0aW9uXG5cbiAgIyMjIFNUVU5cblxuICA8PDwgc3R1bi5qc29uXG5cbiAgIyMjIFRVUk5cblxuICA8PDwgdHVybi5qc29uXG5cbioqL1xuXG52YXIgZnJlZWljZSA9IG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24ob3B0cykge1xuICAvLyBpZiBhIGxpc3Qgb2Ygc2VydmVycyBoYXMgYmVlbiBwcm92aWRlZCwgdGhlbiB1c2UgaXQgaW5zdGVhZCBvZiBkZWZhdWx0c1xuICB2YXIgc2VydmVycyA9IHtcbiAgICBzdHVuOiAob3B0cyB8fCB7fSkuc3R1biB8fCByZXF1aXJlKCcuL3N0dW4uanNvbicpLFxuICAgIHR1cm46IChvcHRzIHx8IHt9KS50dXJuIHx8IHJlcXVpcmUoJy4vdHVybi5qc29uJylcbiAgfTtcblxuICB2YXIgc3R1bkNvdW50ID0gKG9wdHMgfHwge30pLnN0dW5Db3VudCB8fCAyO1xuICB2YXIgdHVybkNvdW50ID0gKG9wdHMgfHwge30pLnR1cm5Db3VudCB8fCAwO1xuICB2YXIgc2VsZWN0ZWQ7XG5cbiAgZnVuY3Rpb24gZ2V0U2VydmVycyh0eXBlLCBjb3VudCkge1xuICAgIHZhciBvdXQgPSBbXTtcbiAgICB2YXIgaW5wdXQgPSBbXS5jb25jYXQoc2VydmVyc1t0eXBlXSk7XG4gICAgdmFyIGlkeDtcblxuICAgIHdoaWxlIChpbnB1dC5sZW5ndGggJiYgb3V0Lmxlbmd0aCA8IGNvdW50KSB7XG4gICAgICBpZHggPSAoTWF0aC5yYW5kb20oKSAqIGlucHV0Lmxlbmd0aCkgfCAwO1xuICAgICAgb3V0ID0gb3V0LmNvbmNhdChpbnB1dC5zcGxpY2UoaWR4LCAxKSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIG91dC5tYXAoZnVuY3Rpb24odXJsKSB7XG4gICAgICAgIC8vSWYgaXQncyBhIG5vdCBhIHN0cmluZywgZG9uJ3QgdHJ5IHRvIFwibm9ybWFsaWNlXCIgaXQgb3RoZXJ3aXNlIHVzaW5nIHR5cGU6dXJsIHdpbGwgc2NyZXcgaXQgdXBcbiAgICAgICAgaWYgKCh0eXBlb2YgdXJsICE9PSAnc3RyaW5nJykgJiYgKCEgKHVybCBpbnN0YW5jZW9mIFN0cmluZykpKSB7XG4gICAgICAgICAgICByZXR1cm4gdXJsO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIG5vcm1hbGljZSh0eXBlICsgJzonICsgdXJsKTtcbiAgICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgLy8gYWRkIHN0dW4gc2VydmVyc1xuICBzZWxlY3RlZCA9IFtdLmNvbmNhdChnZXRTZXJ2ZXJzKCdzdHVuJywgc3R1bkNvdW50KSk7XG5cbiAgaWYgKHR1cm5Db3VudCkge1xuICAgIHNlbGVjdGVkID0gc2VsZWN0ZWQuY29uY2F0KGdldFNlcnZlcnMoJ3R1cm4nLCB0dXJuQ291bnQpKTtcbiAgfVxuXG4gIHJldHVybiBzZWxlY3RlZDtcbn07XG4iLCJtb2R1bGUuZXhwb3J0cz1bXG4gIFwic3R1bi5sLmdvb2dsZS5jb206MTkzMDJcIixcbiAgXCJzdHVuMS5sLmdvb2dsZS5jb206MTkzMDJcIixcbiAgXCJzdHVuMi5sLmdvb2dsZS5jb206MTkzMDJcIixcbiAgXCJzdHVuMy5sLmdvb2dsZS5jb206MTkzMDJcIixcbiAgXCJzdHVuNC5sLmdvb2dsZS5jb206MTkzMDJcIixcbiAgXCJzdHVuLmVraWdhLm5ldFwiLFxuICBcInN0dW4uaWRlYXNpcC5jb21cIixcbiAgXCJzdHVuLnNjaGx1bmQuZGVcIixcbiAgXCJzdHVuLnN0dW5wcm90b2NvbC5vcmc6MzQ3OFwiLFxuICBcInN0dW4udm9pcGFyb3VuZC5jb21cIixcbiAgXCJzdHVuLnZvaXBidXN0ZXIuY29tXCIsXG4gIFwic3R1bi52b2lwc3R1bnQuY29tXCIsXG4gIFwic3R1bi52b3hncmF0aWEub3JnXCIsXG4gIFwic3R1bi5zZXJ2aWNlcy5tb3ppbGxhLmNvbVwiXG5dXG4iLCJtb2R1bGUuZXhwb3J0cz1bXVxuIiwidmFyIFdpbGRFbWl0dGVyID0gcmVxdWlyZSgnd2lsZGVtaXR0ZXInKTtcblxuZnVuY3Rpb24gZ2V0TWF4Vm9sdW1lIChhbmFseXNlciwgZmZ0Qmlucykge1xuICB2YXIgbWF4Vm9sdW1lID0gLUluZmluaXR5O1xuICBhbmFseXNlci5nZXRGbG9hdEZyZXF1ZW5jeURhdGEoZmZ0Qmlucyk7XG5cbiAgZm9yKHZhciBpPTQsIGlpPWZmdEJpbnMubGVuZ3RoOyBpIDwgaWk7IGkrKykge1xuICAgIGlmIChmZnRCaW5zW2ldID4gbWF4Vm9sdW1lICYmIGZmdEJpbnNbaV0gPCAwKSB7XG4gICAgICBtYXhWb2x1bWUgPSBmZnRCaW5zW2ldO1xuICAgIH1cbiAgfTtcblxuICByZXR1cm4gbWF4Vm9sdW1lO1xufVxuXG5cbnZhciBhdWRpb0NvbnRleHRUeXBlO1xuaWYgKHR5cGVvZiB3aW5kb3cgIT09ICd1bmRlZmluZWQnKSB7XG4gIGF1ZGlvQ29udGV4dFR5cGUgPSB3aW5kb3cuQXVkaW9Db250ZXh0IHx8IHdpbmRvdy53ZWJraXRBdWRpb0NvbnRleHQ7XG59XG4vLyB1c2UgYSBzaW5nbGUgYXVkaW8gY29udGV4dCBkdWUgdG8gaGFyZHdhcmUgbGltaXRzXG52YXIgYXVkaW9Db250ZXh0ID0gbnVsbDtcbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24oc3RyZWFtLCBvcHRpb25zKSB7XG4gIHZhciBoYXJrZXIgPSBuZXcgV2lsZEVtaXR0ZXIoKTtcblxuXG4gIC8vIG1ha2UgaXQgbm90IGJyZWFrIGluIG5vbi1zdXBwb3J0ZWQgYnJvd3NlcnNcbiAgaWYgKCFhdWRpb0NvbnRleHRUeXBlKSByZXR1cm4gaGFya2VyO1xuXG4gIC8vQ29uZmlnXG4gIHZhciBvcHRpb25zID0gb3B0aW9ucyB8fCB7fSxcbiAgICAgIHNtb290aGluZyA9IChvcHRpb25zLnNtb290aGluZyB8fCAwLjEpLFxuICAgICAgaW50ZXJ2YWwgPSAob3B0aW9ucy5pbnRlcnZhbCB8fCA1MCksXG4gICAgICB0aHJlc2hvbGQgPSBvcHRpb25zLnRocmVzaG9sZCxcbiAgICAgIHBsYXkgPSBvcHRpb25zLnBsYXksXG4gICAgICBoaXN0b3J5ID0gb3B0aW9ucy5oaXN0b3J5IHx8IDEwLFxuICAgICAgcnVubmluZyA9IHRydWU7XG5cbiAgLy9TZXR1cCBBdWRpbyBDb250ZXh0XG4gIGlmICghYXVkaW9Db250ZXh0KSB7XG4gICAgYXVkaW9Db250ZXh0ID0gbmV3IGF1ZGlvQ29udGV4dFR5cGUoKTtcbiAgfVxuICB2YXIgc291cmNlTm9kZSwgZmZ0QmlucywgYW5hbHlzZXI7XG5cbiAgYW5hbHlzZXIgPSBhdWRpb0NvbnRleHQuY3JlYXRlQW5hbHlzZXIoKTtcbiAgYW5hbHlzZXIuZmZ0U2l6ZSA9IDUxMjtcbiAgYW5hbHlzZXIuc21vb3RoaW5nVGltZUNvbnN0YW50ID0gc21vb3RoaW5nO1xuICBmZnRCaW5zID0gbmV3IEZsb2F0MzJBcnJheShhbmFseXNlci5mcmVxdWVuY3lCaW5Db3VudCk7XG5cbiAgaWYgKHN0cmVhbS5qcXVlcnkpIHN0cmVhbSA9IHN0cmVhbVswXTtcbiAgaWYgKHN0cmVhbSBpbnN0YW5jZW9mIEhUTUxBdWRpb0VsZW1lbnQgfHwgc3RyZWFtIGluc3RhbmNlb2YgSFRNTFZpZGVvRWxlbWVudCkge1xuICAgIC8vQXVkaW8gVGFnXG4gICAgc291cmNlTm9kZSA9IGF1ZGlvQ29udGV4dC5jcmVhdGVNZWRpYUVsZW1lbnRTb3VyY2Uoc3RyZWFtKTtcbiAgICBpZiAodHlwZW9mIHBsYXkgPT09ICd1bmRlZmluZWQnKSBwbGF5ID0gdHJ1ZTtcbiAgICB0aHJlc2hvbGQgPSB0aHJlc2hvbGQgfHwgLTUwO1xuICB9IGVsc2Uge1xuICAgIC8vV2ViUlRDIFN0cmVhbVxuICAgIHNvdXJjZU5vZGUgPSBhdWRpb0NvbnRleHQuY3JlYXRlTWVkaWFTdHJlYW1Tb3VyY2Uoc3RyZWFtKTtcbiAgICB0aHJlc2hvbGQgPSB0aHJlc2hvbGQgfHwgLTUwO1xuICB9XG5cbiAgc291cmNlTm9kZS5jb25uZWN0KGFuYWx5c2VyKTtcbiAgaWYgKHBsYXkpIGFuYWx5c2VyLmNvbm5lY3QoYXVkaW9Db250ZXh0LmRlc3RpbmF0aW9uKTtcblxuICBoYXJrZXIuc3BlYWtpbmcgPSBmYWxzZTtcblxuICBoYXJrZXIuc3VzcGVuZCA9IGZ1bmN0aW9uKCkge1xuICAgIGF1ZGlvQ29udGV4dC5zdXNwZW5kKCk7XG4gIH1cbiAgaGFya2VyLnJlc3VtZSA9IGZ1bmN0aW9uKCkge1xuICAgIGF1ZGlvQ29udGV4dC5yZXN1bWUoKTtcbiAgfVxuICBPYmplY3QuZGVmaW5lUHJvcGVydHkoaGFya2VyLCAnc3RhdGUnLCB7IGdldDogZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIGF1ZGlvQ29udGV4dC5zdGF0ZTtcbiAgfX0pO1xuICBhdWRpb0NvbnRleHQub25zdGF0ZWNoYW5nZSA9IGZ1bmN0aW9uKCkge1xuICAgIGhhcmtlci5lbWl0KCdzdGF0ZV9jaGFuZ2UnLCBhdWRpb0NvbnRleHQuc3RhdGUpO1xuICB9XG5cbiAgaGFya2VyLnNldFRocmVzaG9sZCA9IGZ1bmN0aW9uKHQpIHtcbiAgICB0aHJlc2hvbGQgPSB0O1xuICB9O1xuXG4gIGhhcmtlci5zZXRJbnRlcnZhbCA9IGZ1bmN0aW9uKGkpIHtcbiAgICBpbnRlcnZhbCA9IGk7XG4gIH07XG5cbiAgaGFya2VyLnN0b3AgPSBmdW5jdGlvbigpIHtcbiAgICBydW5uaW5nID0gZmFsc2U7XG4gICAgaGFya2VyLmVtaXQoJ3ZvbHVtZV9jaGFuZ2UnLCAtMTAwLCB0aHJlc2hvbGQpO1xuICAgIGlmIChoYXJrZXIuc3BlYWtpbmcpIHtcbiAgICAgIGhhcmtlci5zcGVha2luZyA9IGZhbHNlO1xuICAgICAgaGFya2VyLmVtaXQoJ3N0b3BwZWRfc3BlYWtpbmcnKTtcbiAgICB9XG4gICAgYW5hbHlzZXIuZGlzY29ubmVjdCgpO1xuICAgIHNvdXJjZU5vZGUuZGlzY29ubmVjdCgpO1xuICB9O1xuICBoYXJrZXIuc3BlYWtpbmdIaXN0b3J5ID0gW107XG4gIGZvciAodmFyIGkgPSAwOyBpIDwgaGlzdG9yeTsgaSsrKSB7XG4gICAgICBoYXJrZXIuc3BlYWtpbmdIaXN0b3J5LnB1c2goMCk7XG4gIH1cblxuICAvLyBQb2xsIHRoZSBhbmFseXNlciBub2RlIHRvIGRldGVybWluZSBpZiBzcGVha2luZ1xuICAvLyBhbmQgZW1pdCBldmVudHMgaWYgY2hhbmdlZFxuICB2YXIgbG9vcGVyID0gZnVuY3Rpb24oKSB7XG4gICAgc2V0VGltZW91dChmdW5jdGlvbigpIHtcblxuICAgICAgLy9jaGVjayBpZiBzdG9wIGhhcyBiZWVuIGNhbGxlZFxuICAgICAgaWYoIXJ1bm5pbmcpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICB2YXIgY3VycmVudFZvbHVtZSA9IGdldE1heFZvbHVtZShhbmFseXNlciwgZmZ0Qmlucyk7XG5cbiAgICAgIGhhcmtlci5lbWl0KCd2b2x1bWVfY2hhbmdlJywgY3VycmVudFZvbHVtZSwgdGhyZXNob2xkKTtcblxuICAgICAgdmFyIGhpc3RvcnkgPSAwO1xuICAgICAgaWYgKGN1cnJlbnRWb2x1bWUgPiB0aHJlc2hvbGQgJiYgIWhhcmtlci5zcGVha2luZykge1xuICAgICAgICAvLyB0cmlnZ2VyIHF1aWNrbHksIHNob3J0IGhpc3RvcnlcbiAgICAgICAgZm9yICh2YXIgaSA9IGhhcmtlci5zcGVha2luZ0hpc3RvcnkubGVuZ3RoIC0gMzsgaSA8IGhhcmtlci5zcGVha2luZ0hpc3RvcnkubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICBoaXN0b3J5ICs9IGhhcmtlci5zcGVha2luZ0hpc3RvcnlbaV07XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGhpc3RvcnkgPj0gMikge1xuICAgICAgICAgIGhhcmtlci5zcGVha2luZyA9IHRydWU7XG4gICAgICAgICAgaGFya2VyLmVtaXQoJ3NwZWFraW5nJyk7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSBpZiAoY3VycmVudFZvbHVtZSA8IHRocmVzaG9sZCAmJiBoYXJrZXIuc3BlYWtpbmcpIHtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBoYXJrZXIuc3BlYWtpbmdIaXN0b3J5Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgaGlzdG9yeSArPSBoYXJrZXIuc3BlYWtpbmdIaXN0b3J5W2ldO1xuICAgICAgICB9XG4gICAgICAgIGlmIChoaXN0b3J5ID09IDApIHtcbiAgICAgICAgICBoYXJrZXIuc3BlYWtpbmcgPSBmYWxzZTtcbiAgICAgICAgICBoYXJrZXIuZW1pdCgnc3RvcHBlZF9zcGVha2luZycpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBoYXJrZXIuc3BlYWtpbmdIaXN0b3J5LnNoaWZ0KCk7XG4gICAgICBoYXJrZXIuc3BlYWtpbmdIaXN0b3J5LnB1c2goMCArIChjdXJyZW50Vm9sdW1lID4gdGhyZXNob2xkKSk7XG5cbiAgICAgIGxvb3BlcigpO1xuICAgIH0sIGludGVydmFsKTtcbiAgfTtcbiAgbG9vcGVyKCk7XG5cblxuICByZXR1cm4gaGFya2VyO1xufVxuIiwiaWYgKHR5cGVvZiBPYmplY3QuY3JlYXRlID09PSAnZnVuY3Rpb24nKSB7XG4gIC8vIGltcGxlbWVudGF0aW9uIGZyb20gc3RhbmRhcmQgbm9kZS5qcyAndXRpbCcgbW9kdWxlXG4gIG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gaW5oZXJpdHMoY3Rvciwgc3VwZXJDdG9yKSB7XG4gICAgY3Rvci5zdXBlcl8gPSBzdXBlckN0b3JcbiAgICBjdG9yLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoc3VwZXJDdG9yLnByb3RvdHlwZSwge1xuICAgICAgY29uc3RydWN0b3I6IHtcbiAgICAgICAgdmFsdWU6IGN0b3IsXG4gICAgICAgIGVudW1lcmFibGU6IGZhbHNlLFxuICAgICAgICB3cml0YWJsZTogdHJ1ZSxcbiAgICAgICAgY29uZmlndXJhYmxlOiB0cnVlXG4gICAgICB9XG4gICAgfSk7XG4gIH07XG59IGVsc2Uge1xuICAvLyBvbGQgc2Nob29sIHNoaW0gZm9yIG9sZCBicm93c2Vyc1xuICBtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGluaGVyaXRzKGN0b3IsIHN1cGVyQ3Rvcikge1xuICAgIGN0b3Iuc3VwZXJfID0gc3VwZXJDdG9yXG4gICAgdmFyIFRlbXBDdG9yID0gZnVuY3Rpb24gKCkge31cbiAgICBUZW1wQ3Rvci5wcm90b3R5cGUgPSBzdXBlckN0b3IucHJvdG90eXBlXG4gICAgY3Rvci5wcm90b3R5cGUgPSBuZXcgVGVtcEN0b3IoKVxuICAgIGN0b3IucHJvdG90eXBlLmNvbnN0cnVjdG9yID0gY3RvclxuICB9XG59XG4iLCIvKipcbiAgIyBub3JtYWxpY2VcblxuICBOb3JtYWxpemUgYW4gaWNlIHNlcnZlciBjb25maWd1cmF0aW9uIG9iamVjdCAob3IgcGxhaW4gb2xkIHN0cmluZykgaW50byBhIGZvcm1hdFxuICB0aGF0IGlzIHVzYWJsZSBpbiBhbGwgYnJvd3NlcnMgc3VwcG9ydGluZyBXZWJSVEMuICBQcmltYXJpbHkgdGhpcyBtb2R1bGUgaXMgZGVzaWduZWRcbiAgdG8gaGVscCB3aXRoIHRoZSB0cmFuc2l0aW9uIG9mIHRoZSBgdXJsYCBhdHRyaWJ1dGUgb2YgdGhlIGNvbmZpZ3VyYXRpb24gb2JqZWN0IHRvXG4gIHRoZSBgdXJsc2AgYXR0cmlidXRlLlxuXG4gICMjIEV4YW1wbGUgVXNhZ2VcblxuICA8PDwgZXhhbXBsZXMvc2ltcGxlLmpzXG5cbioqL1xuXG52YXIgcHJvdG9jb2xzID0gW1xuICAnc3R1bjonLFxuICAndHVybjonXG5dO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKGlucHV0KSB7XG4gIHZhciB1cmwgPSAoaW5wdXQgfHwge30pLnVybCB8fCBpbnB1dDtcbiAgdmFyIHByb3RvY29sO1xuICB2YXIgcGFydHM7XG4gIHZhciBvdXRwdXQgPSB7fTtcblxuICAvLyBpZiB3ZSBkb24ndCBoYXZlIGEgc3RyaW5nIHVybCwgdGhlbiBhbGxvdyB0aGUgaW5wdXQgdG8gcGFzc3Rocm91Z2hcbiAgaWYgKHR5cGVvZiB1cmwgIT0gJ3N0cmluZycgJiYgKCEgKHVybCBpbnN0YW5jZW9mIFN0cmluZykpKSB7XG4gICAgcmV0dXJuIGlucHV0O1xuICB9XG5cbiAgLy8gdHJpbSB0aGUgdXJsIHN0cmluZywgYW5kIGNvbnZlcnQgdG8gYW4gYXJyYXlcbiAgdXJsID0gdXJsLnRyaW0oKTtcblxuICAvLyBpZiB0aGUgcHJvdG9jb2wgaXMgbm90IGtub3duLCB0aGVuIHBhc3N0aHJvdWdoXG4gIHByb3RvY29sID0gcHJvdG9jb2xzW3Byb3RvY29scy5pbmRleE9mKHVybC5zbGljZSgwLCA1KSldO1xuICBpZiAoISBwcm90b2NvbCkge1xuICAgIHJldHVybiBpbnB1dDtcbiAgfVxuXG4gIC8vIG5vdyBsZXQncyBhdHRhY2sgdGhlIHJlbWFpbmluZyB1cmwgcGFydHNcbiAgdXJsID0gdXJsLnNsaWNlKDUpO1xuICBwYXJ0cyA9IHVybC5zcGxpdCgnQCcpO1xuXG4gIG91dHB1dC51c2VybmFtZSA9IGlucHV0LnVzZXJuYW1lO1xuICBvdXRwdXQuY3JlZGVudGlhbCA9IGlucHV0LmNyZWRlbnRpYWw7XG4gIC8vIGlmIHdlIGhhdmUgYW4gYXV0aGVudGljYXRpb24gcGFydCwgdGhlbiBzZXQgdGhlIGNyZWRlbnRpYWxzXG4gIGlmIChwYXJ0cy5sZW5ndGggPiAxKSB7XG4gICAgdXJsID0gcGFydHNbMV07XG4gICAgcGFydHMgPSBwYXJ0c1swXS5zcGxpdCgnOicpO1xuXG4gICAgLy8gYWRkIHRoZSBvdXRwdXQgY3JlZGVudGlhbCBhbmQgdXNlcm5hbWVcbiAgICBvdXRwdXQudXNlcm5hbWUgPSBwYXJ0c1swXTtcbiAgICBvdXRwdXQuY3JlZGVudGlhbCA9IChpbnB1dCB8fCB7fSkuY3JlZGVudGlhbCB8fCBwYXJ0c1sxXSB8fCAnJztcbiAgfVxuXG4gIG91dHB1dC51cmwgPSBwcm90b2NvbCArIHVybDtcbiAgb3V0cHV0LnVybHMgPSBbIG91dHB1dC51cmwgXTtcblxuICByZXR1cm4gb3V0cHV0O1xufTtcbiIsIi8qIVxuICogUGxhdGZvcm0uanMgPGh0dHBzOi8vbXRocy5iZS9wbGF0Zm9ybT5cbiAqIENvcHlyaWdodCAyMDE0LTIwMTggQmVuamFtaW4gVGFuIDxodHRwczovL2Juam1udDRuLm5vdy5zaC8+XG4gKiBDb3B5cmlnaHQgMjAxMS0yMDEzIEpvaG4tRGF2aWQgRGFsdG9uIDxodHRwOi8vYWxseW91Y2FubGVldC5jb20vPlxuICogQXZhaWxhYmxlIHVuZGVyIE1JVCBsaWNlbnNlIDxodHRwczovL210aHMuYmUvbWl0PlxuICovXG47KGZ1bmN0aW9uKCkge1xuICAndXNlIHN0cmljdCc7XG5cbiAgLyoqIFVzZWQgdG8gZGV0ZXJtaW5lIGlmIHZhbHVlcyBhcmUgb2YgdGhlIGxhbmd1YWdlIHR5cGUgYE9iamVjdGAuICovXG4gIHZhciBvYmplY3RUeXBlcyA9IHtcbiAgICAnZnVuY3Rpb24nOiB0cnVlLFxuICAgICdvYmplY3QnOiB0cnVlXG4gIH07XG5cbiAgLyoqIFVzZWQgYXMgYSByZWZlcmVuY2UgdG8gdGhlIGdsb2JhbCBvYmplY3QuICovXG4gIHZhciByb290ID0gKG9iamVjdFR5cGVzW3R5cGVvZiB3aW5kb3ddICYmIHdpbmRvdykgfHwgdGhpcztcblxuICAvKiogQmFja3VwIHBvc3NpYmxlIGdsb2JhbCBvYmplY3QuICovXG4gIHZhciBvbGRSb290ID0gcm9vdDtcblxuICAvKiogRGV0ZWN0IGZyZWUgdmFyaWFibGUgYGV4cG9ydHNgLiAqL1xuICB2YXIgZnJlZUV4cG9ydHMgPSBvYmplY3RUeXBlc1t0eXBlb2YgZXhwb3J0c10gJiYgZXhwb3J0cztcblxuICAvKiogRGV0ZWN0IGZyZWUgdmFyaWFibGUgYG1vZHVsZWAuICovXG4gIHZhciBmcmVlTW9kdWxlID0gb2JqZWN0VHlwZXNbdHlwZW9mIG1vZHVsZV0gJiYgbW9kdWxlICYmICFtb2R1bGUubm9kZVR5cGUgJiYgbW9kdWxlO1xuXG4gIC8qKiBEZXRlY3QgZnJlZSB2YXJpYWJsZSBgZ2xvYmFsYCBmcm9tIE5vZGUuanMgb3IgQnJvd3NlcmlmaWVkIGNvZGUgYW5kIHVzZSBpdCBhcyBgcm9vdGAuICovXG4gIHZhciBmcmVlR2xvYmFsID0gZnJlZUV4cG9ydHMgJiYgZnJlZU1vZHVsZSAmJiB0eXBlb2YgZ2xvYmFsID09ICdvYmplY3QnICYmIGdsb2JhbDtcbiAgaWYgKGZyZWVHbG9iYWwgJiYgKGZyZWVHbG9iYWwuZ2xvYmFsID09PSBmcmVlR2xvYmFsIHx8IGZyZWVHbG9iYWwud2luZG93ID09PSBmcmVlR2xvYmFsIHx8IGZyZWVHbG9iYWwuc2VsZiA9PT0gZnJlZUdsb2JhbCkpIHtcbiAgICByb290ID0gZnJlZUdsb2JhbDtcbiAgfVxuXG4gIC8qKlxuICAgKiBVc2VkIGFzIHRoZSBtYXhpbXVtIGxlbmd0aCBvZiBhbiBhcnJheS1saWtlIG9iamVjdC5cbiAgICogU2VlIHRoZSBbRVM2IHNwZWNdKGh0dHA6Ly9wZW9wbGUubW96aWxsYS5vcmcvfmpvcmVuZG9yZmYvZXM2LWRyYWZ0Lmh0bWwjc2VjLXRvbGVuZ3RoKVxuICAgKiBmb3IgbW9yZSBkZXRhaWxzLlxuICAgKi9cbiAgdmFyIG1heFNhZmVJbnRlZ2VyID0gTWF0aC5wb3coMiwgNTMpIC0gMTtcblxuICAvKiogUmVndWxhciBleHByZXNzaW9uIHRvIGRldGVjdCBPcGVyYS4gKi9cbiAgdmFyIHJlT3BlcmEgPSAvXFxiT3BlcmEvO1xuXG4gIC8qKiBQb3NzaWJsZSBnbG9iYWwgb2JqZWN0LiAqL1xuICB2YXIgdGhpc0JpbmRpbmcgPSB0aGlzO1xuXG4gIC8qKiBVc2VkIGZvciBuYXRpdmUgbWV0aG9kIHJlZmVyZW5jZXMuICovXG4gIHZhciBvYmplY3RQcm90byA9IE9iamVjdC5wcm90b3R5cGU7XG5cbiAgLyoqIFVzZWQgdG8gY2hlY2sgZm9yIG93biBwcm9wZXJ0aWVzIG9mIGFuIG9iamVjdC4gKi9cbiAgdmFyIGhhc093blByb3BlcnR5ID0gb2JqZWN0UHJvdG8uaGFzT3duUHJvcGVydHk7XG5cbiAgLyoqIFVzZWQgdG8gcmVzb2x2ZSB0aGUgaW50ZXJuYWwgYFtbQ2xhc3NdXWAgb2YgdmFsdWVzLiAqL1xuICB2YXIgdG9TdHJpbmcgPSBvYmplY3RQcm90by50b1N0cmluZztcblxuICAvKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cblxuICAvKipcbiAgICogQ2FwaXRhbGl6ZXMgYSBzdHJpbmcgdmFsdWUuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBzdHJpbmcgVGhlIHN0cmluZyB0byBjYXBpdGFsaXplLlxuICAgKiBAcmV0dXJucyB7c3RyaW5nfSBUaGUgY2FwaXRhbGl6ZWQgc3RyaW5nLlxuICAgKi9cbiAgZnVuY3Rpb24gY2FwaXRhbGl6ZShzdHJpbmcpIHtcbiAgICBzdHJpbmcgPSBTdHJpbmcoc3RyaW5nKTtcbiAgICByZXR1cm4gc3RyaW5nLmNoYXJBdCgwKS50b1VwcGVyQ2FzZSgpICsgc3RyaW5nLnNsaWNlKDEpO1xuICB9XG5cbiAgLyoqXG4gICAqIEEgdXRpbGl0eSBmdW5jdGlvbiB0byBjbGVhbiB1cCB0aGUgT1MgbmFtZS5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtzdHJpbmd9IG9zIFRoZSBPUyBuYW1lIHRvIGNsZWFuIHVwLlxuICAgKiBAcGFyYW0ge3N0cmluZ30gW3BhdHRlcm5dIEEgYFJlZ0V4cGAgcGF0dGVybiBtYXRjaGluZyB0aGUgT1MgbmFtZS5cbiAgICogQHBhcmFtIHtzdHJpbmd9IFtsYWJlbF0gQSBsYWJlbCBmb3IgdGhlIE9TLlxuICAgKi9cbiAgZnVuY3Rpb24gY2xlYW51cE9TKG9zLCBwYXR0ZXJuLCBsYWJlbCkge1xuICAgIC8vIFBsYXRmb3JtIHRva2VucyBhcmUgZGVmaW5lZCBhdDpcbiAgICAvLyBodHRwOi8vbXNkbi5taWNyb3NvZnQuY29tL2VuLXVzL2xpYnJhcnkvbXM1Mzc1MDMoVlMuODUpLmFzcHhcbiAgICAvLyBodHRwOi8vd2ViLmFyY2hpdmUub3JnL3dlYi8yMDA4MTEyMjA1Mzk1MC9odHRwOi8vbXNkbi5taWNyb3NvZnQuY29tL2VuLXVzL2xpYnJhcnkvbXM1Mzc1MDMoVlMuODUpLmFzcHhcbiAgICB2YXIgZGF0YSA9IHtcbiAgICAgICcxMC4wJzogJzEwJyxcbiAgICAgICc2LjQnOiAgJzEwIFRlY2huaWNhbCBQcmV2aWV3JyxcbiAgICAgICc2LjMnOiAgJzguMScsXG4gICAgICAnNi4yJzogICc4JyxcbiAgICAgICc2LjEnOiAgJ1NlcnZlciAyMDA4IFIyIC8gNycsXG4gICAgICAnNi4wJzogICdTZXJ2ZXIgMjAwOCAvIFZpc3RhJyxcbiAgICAgICc1LjInOiAgJ1NlcnZlciAyMDAzIC8gWFAgNjQtYml0JyxcbiAgICAgICc1LjEnOiAgJ1hQJyxcbiAgICAgICc1LjAxJzogJzIwMDAgU1AxJyxcbiAgICAgICc1LjAnOiAgJzIwMDAnLFxuICAgICAgJzQuMCc6ICAnTlQnLFxuICAgICAgJzQuOTAnOiAnTUUnXG4gICAgfTtcbiAgICAvLyBEZXRlY3QgV2luZG93cyB2ZXJzaW9uIGZyb20gcGxhdGZvcm0gdG9rZW5zLlxuICAgIGlmIChwYXR0ZXJuICYmIGxhYmVsICYmIC9eV2luL2kudGVzdChvcykgJiYgIS9eV2luZG93cyBQaG9uZSAvaS50ZXN0KG9zKSAmJlxuICAgICAgICAoZGF0YSA9IGRhdGFbL1tcXGQuXSskLy5leGVjKG9zKV0pKSB7XG4gICAgICBvcyA9ICdXaW5kb3dzICcgKyBkYXRhO1xuICAgIH1cbiAgICAvLyBDb3JyZWN0IGNoYXJhY3RlciBjYXNlIGFuZCBjbGVhbnVwIHN0cmluZy5cbiAgICBvcyA9IFN0cmluZyhvcyk7XG5cbiAgICBpZiAocGF0dGVybiAmJiBsYWJlbCkge1xuICAgICAgb3MgPSBvcy5yZXBsYWNlKFJlZ0V4cChwYXR0ZXJuLCAnaScpLCBsYWJlbCk7XG4gICAgfVxuXG4gICAgb3MgPSBmb3JtYXQoXG4gICAgICBvcy5yZXBsYWNlKC8gY2UkL2ksICcgQ0UnKVxuICAgICAgICAucmVwbGFjZSgvXFxiaHB3L2ksICd3ZWInKVxuICAgICAgICAucmVwbGFjZSgvXFxiTWFjaW50b3NoXFxiLywgJ01hYyBPUycpXG4gICAgICAgIC5yZXBsYWNlKC9fUG93ZXJQQ1xcYi9pLCAnIE9TJylcbiAgICAgICAgLnJlcGxhY2UoL1xcYihPUyBYKSBbXiBcXGRdKy9pLCAnJDEnKVxuICAgICAgICAucmVwbGFjZSgvXFxiTWFjIChPUyBYKVxcYi8sICckMScpXG4gICAgICAgIC5yZXBsYWNlKC9cXC8oXFxkKS8sICcgJDEnKVxuICAgICAgICAucmVwbGFjZSgvXy9nLCAnLicpXG4gICAgICAgIC5yZXBsYWNlKC8oPzogQmVQQ3xbIC5dKmZjWyBcXGQuXSspJC9pLCAnJylcbiAgICAgICAgLnJlcGxhY2UoL1xcYng4NlxcLjY0XFxiL2dpLCAneDg2XzY0JylcbiAgICAgICAgLnJlcGxhY2UoL1xcYihXaW5kb3dzIFBob25lKSBPU1xcYi8sICckMScpXG4gICAgICAgIC5yZXBsYWNlKC9cXGIoQ2hyb21lIE9TIFxcdyspIFtcXGQuXStcXGIvLCAnJDEnKVxuICAgICAgICAuc3BsaXQoJyBvbiAnKVswXVxuICAgICk7XG5cbiAgICByZXR1cm4gb3M7XG4gIH1cblxuICAvKipcbiAgICogQW4gaXRlcmF0aW9uIHV0aWxpdHkgZm9yIGFycmF5cyBhbmQgb2JqZWN0cy5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtBcnJheXxPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIGl0ZXJhdGUgb3Zlci5cbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gY2FsbGJhY2sgVGhlIGZ1bmN0aW9uIGNhbGxlZCBwZXIgaXRlcmF0aW9uLlxuICAgKi9cbiAgZnVuY3Rpb24gZWFjaChvYmplY3QsIGNhbGxiYWNrKSB7XG4gICAgdmFyIGluZGV4ID0gLTEsXG4gICAgICAgIGxlbmd0aCA9IG9iamVjdCA/IG9iamVjdC5sZW5ndGggOiAwO1xuXG4gICAgaWYgKHR5cGVvZiBsZW5ndGggPT0gJ251bWJlcicgJiYgbGVuZ3RoID4gLTEgJiYgbGVuZ3RoIDw9IG1heFNhZmVJbnRlZ2VyKSB7XG4gICAgICB3aGlsZSAoKytpbmRleCA8IGxlbmd0aCkge1xuICAgICAgICBjYWxsYmFjayhvYmplY3RbaW5kZXhdLCBpbmRleCwgb2JqZWN0KTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgZm9yT3duKG9iamVjdCwgY2FsbGJhY2spO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBUcmltIGFuZCBjb25kaXRpb25hbGx5IGNhcGl0YWxpemUgc3RyaW5nIHZhbHVlcy5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtzdHJpbmd9IHN0cmluZyBUaGUgc3RyaW5nIHRvIGZvcm1hdC5cbiAgICogQHJldHVybnMge3N0cmluZ30gVGhlIGZvcm1hdHRlZCBzdHJpbmcuXG4gICAqL1xuICBmdW5jdGlvbiBmb3JtYXQoc3RyaW5nKSB7XG4gICAgc3RyaW5nID0gdHJpbShzdHJpbmcpO1xuICAgIHJldHVybiAvXig/OndlYk9TfGkoPzpPU3xQKSkvLnRlc3Qoc3RyaW5nKVxuICAgICAgPyBzdHJpbmdcbiAgICAgIDogY2FwaXRhbGl6ZShzdHJpbmcpO1xuICB9XG5cbiAgLyoqXG4gICAqIEl0ZXJhdGVzIG92ZXIgYW4gb2JqZWN0J3Mgb3duIHByb3BlcnRpZXMsIGV4ZWN1dGluZyB0aGUgYGNhbGxiYWNrYCBmb3IgZWFjaC5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIGl0ZXJhdGUgb3Zlci5cbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gY2FsbGJhY2sgVGhlIGZ1bmN0aW9uIGV4ZWN1dGVkIHBlciBvd24gcHJvcGVydHkuXG4gICAqL1xuICBmdW5jdGlvbiBmb3JPd24ob2JqZWN0LCBjYWxsYmFjaykge1xuICAgIGZvciAodmFyIGtleSBpbiBvYmplY3QpIHtcbiAgICAgIGlmIChoYXNPd25Qcm9wZXJ0eS5jYWxsKG9iamVjdCwga2V5KSkge1xuICAgICAgICBjYWxsYmFjayhvYmplY3Rba2V5XSwga2V5LCBvYmplY3QpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBHZXRzIHRoZSBpbnRlcm5hbCBgW1tDbGFzc11dYCBvZiBhIHZhbHVlLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZS5cbiAgICogQHJldHVybnMge3N0cmluZ30gVGhlIGBbW0NsYXNzXV1gLlxuICAgKi9cbiAgZnVuY3Rpb24gZ2V0Q2xhc3NPZih2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZSA9PSBudWxsXG4gICAgICA/IGNhcGl0YWxpemUodmFsdWUpXG4gICAgICA6IHRvU3RyaW5nLmNhbGwodmFsdWUpLnNsaWNlKDgsIC0xKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBIb3N0IG9iamVjdHMgY2FuIHJldHVybiB0eXBlIHZhbHVlcyB0aGF0IGFyZSBkaWZmZXJlbnQgZnJvbSB0aGVpciBhY3R1YWxcbiAgICogZGF0YSB0eXBlLiBUaGUgb2JqZWN0cyB3ZSBhcmUgY29uY2VybmVkIHdpdGggdXN1YWxseSByZXR1cm4gbm9uLXByaW1pdGl2ZVxuICAgKiB0eXBlcyBvZiBcIm9iamVjdFwiLCBcImZ1bmN0aW9uXCIsIG9yIFwidW5rbm93blwiLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0geyp9IG9iamVjdCBUaGUgb3duZXIgb2YgdGhlIHByb3BlcnR5LlxuICAgKiBAcGFyYW0ge3N0cmluZ30gcHJvcGVydHkgVGhlIHByb3BlcnR5IHRvIGNoZWNrLlxuICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgdGhlIHByb3BlcnR5IHZhbHVlIGlzIGEgbm9uLXByaW1pdGl2ZSwgZWxzZSBgZmFsc2VgLlxuICAgKi9cbiAgZnVuY3Rpb24gaXNIb3N0VHlwZShvYmplY3QsIHByb3BlcnR5KSB7XG4gICAgdmFyIHR5cGUgPSBvYmplY3QgIT0gbnVsbCA/IHR5cGVvZiBvYmplY3RbcHJvcGVydHldIDogJ251bWJlcic7XG4gICAgcmV0dXJuICEvXig/OmJvb2xlYW58bnVtYmVyfHN0cmluZ3x1bmRlZmluZWQpJC8udGVzdCh0eXBlKSAmJlxuICAgICAgKHR5cGUgPT0gJ29iamVjdCcgPyAhIW9iamVjdFtwcm9wZXJ0eV0gOiB0cnVlKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBQcmVwYXJlcyBhIHN0cmluZyBmb3IgdXNlIGluIGEgYFJlZ0V4cGAgYnkgbWFraW5nIGh5cGhlbnMgYW5kIHNwYWNlcyBvcHRpb25hbC5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtzdHJpbmd9IHN0cmluZyBUaGUgc3RyaW5nIHRvIHF1YWxpZnkuXG4gICAqIEByZXR1cm5zIHtzdHJpbmd9IFRoZSBxdWFsaWZpZWQgc3RyaW5nLlxuICAgKi9cbiAgZnVuY3Rpb24gcXVhbGlmeShzdHJpbmcpIHtcbiAgICByZXR1cm4gU3RyaW5nKHN0cmluZykucmVwbGFjZSgvKFsgLV0pKD8hJCkvZywgJyQxPycpO1xuICB9XG5cbiAgLyoqXG4gICAqIEEgYmFyZS1ib25lcyBgQXJyYXkjcmVkdWNlYCBsaWtlIHV0aWxpdHkgZnVuY3Rpb24uXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBpdGVyYXRlIG92ZXIuXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IGNhbGxiYWNrIFRoZSBmdW5jdGlvbiBjYWxsZWQgcGVyIGl0ZXJhdGlvbi5cbiAgICogQHJldHVybnMgeyp9IFRoZSBhY2N1bXVsYXRlZCByZXN1bHQuXG4gICAqL1xuICBmdW5jdGlvbiByZWR1Y2UoYXJyYXksIGNhbGxiYWNrKSB7XG4gICAgdmFyIGFjY3VtdWxhdG9yID0gbnVsbDtcbiAgICBlYWNoKGFycmF5LCBmdW5jdGlvbih2YWx1ZSwgaW5kZXgpIHtcbiAgICAgIGFjY3VtdWxhdG9yID0gY2FsbGJhY2soYWNjdW11bGF0b3IsIHZhbHVlLCBpbmRleCwgYXJyYXkpO1xuICAgIH0pO1xuICAgIHJldHVybiBhY2N1bXVsYXRvcjtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZW1vdmVzIGxlYWRpbmcgYW5kIHRyYWlsaW5nIHdoaXRlc3BhY2UgZnJvbSBhIHN0cmluZy5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtzdHJpbmd9IHN0cmluZyBUaGUgc3RyaW5nIHRvIHRyaW0uXG4gICAqIEByZXR1cm5zIHtzdHJpbmd9IFRoZSB0cmltbWVkIHN0cmluZy5cbiAgICovXG4gIGZ1bmN0aW9uIHRyaW0oc3RyaW5nKSB7XG4gICAgcmV0dXJuIFN0cmluZyhzdHJpbmcpLnJlcGxhY2UoL14gK3wgKyQvZywgJycpO1xuICB9XG5cbiAgLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG5cbiAgLyoqXG4gICAqIENyZWF0ZXMgYSBuZXcgcGxhdGZvcm0gb2JqZWN0LlxuICAgKlxuICAgKiBAbWVtYmVyT2YgcGxhdGZvcm1cbiAgICogQHBhcmFtIHtPYmplY3R8c3RyaW5nfSBbdWE9bmF2aWdhdG9yLnVzZXJBZ2VudF0gVGhlIHVzZXIgYWdlbnQgc3RyaW5nIG9yXG4gICAqICBjb250ZXh0IG9iamVjdC5cbiAgICogQHJldHVybnMge09iamVjdH0gQSBwbGF0Zm9ybSBvYmplY3QuXG4gICAqL1xuICBmdW5jdGlvbiBwYXJzZSh1YSkge1xuXG4gICAgLyoqIFRoZSBlbnZpcm9ubWVudCBjb250ZXh0IG9iamVjdC4gKi9cbiAgICB2YXIgY29udGV4dCA9IHJvb3Q7XG5cbiAgICAvKiogVXNlZCB0byBmbGFnIHdoZW4gYSBjdXN0b20gY29udGV4dCBpcyBwcm92aWRlZC4gKi9cbiAgICB2YXIgaXNDdXN0b21Db250ZXh0ID0gdWEgJiYgdHlwZW9mIHVhID09ICdvYmplY3QnICYmIGdldENsYXNzT2YodWEpICE9ICdTdHJpbmcnO1xuXG4gICAgLy8gSnVnZ2xlIGFyZ3VtZW50cy5cbiAgICBpZiAoaXNDdXN0b21Db250ZXh0KSB7XG4gICAgICBjb250ZXh0ID0gdWE7XG4gICAgICB1YSA9IG51bGw7XG4gICAgfVxuXG4gICAgLyoqIEJyb3dzZXIgbmF2aWdhdG9yIG9iamVjdC4gKi9cbiAgICB2YXIgbmF2ID0gY29udGV4dC5uYXZpZ2F0b3IgfHwge307XG5cbiAgICAvKiogQnJvd3NlciB1c2VyIGFnZW50IHN0cmluZy4gKi9cbiAgICB2YXIgdXNlckFnZW50ID0gbmF2LnVzZXJBZ2VudCB8fCAnJztcblxuICAgIHVhIHx8ICh1YSA9IHVzZXJBZ2VudCk7XG5cbiAgICAvKiogVXNlZCB0byBmbGFnIHdoZW4gYHRoaXNCaW5kaW5nYCBpcyB0aGUgW01vZHVsZVNjb3BlXS4gKi9cbiAgICB2YXIgaXNNb2R1bGVTY29wZSA9IGlzQ3VzdG9tQ29udGV4dCB8fCB0aGlzQmluZGluZyA9PSBvbGRSb290O1xuXG4gICAgLyoqIFVzZWQgdG8gZGV0ZWN0IGlmIGJyb3dzZXIgaXMgbGlrZSBDaHJvbWUuICovXG4gICAgdmFyIGxpa2VDaHJvbWUgPSBpc0N1c3RvbUNvbnRleHRcbiAgICAgID8gISFuYXYubGlrZUNocm9tZVxuICAgICAgOiAvXFxiQ2hyb21lXFxiLy50ZXN0KHVhKSAmJiAhL2ludGVybmFsfFxcbi9pLnRlc3QodG9TdHJpbmcudG9TdHJpbmcoKSk7XG5cbiAgICAvKiogSW50ZXJuYWwgYFtbQ2xhc3NdXWAgdmFsdWUgc2hvcnRjdXRzLiAqL1xuICAgIHZhciBvYmplY3RDbGFzcyA9ICdPYmplY3QnLFxuICAgICAgICBhaXJSdW50aW1lQ2xhc3MgPSBpc0N1c3RvbUNvbnRleHQgPyBvYmplY3RDbGFzcyA6ICdTY3JpcHRCcmlkZ2luZ1Byb3h5T2JqZWN0JyxcbiAgICAgICAgZW52aXJvQ2xhc3MgPSBpc0N1c3RvbUNvbnRleHQgPyBvYmplY3RDbGFzcyA6ICdFbnZpcm9ubWVudCcsXG4gICAgICAgIGphdmFDbGFzcyA9IChpc0N1c3RvbUNvbnRleHQgJiYgY29udGV4dC5qYXZhKSA/ICdKYXZhUGFja2FnZScgOiBnZXRDbGFzc09mKGNvbnRleHQuamF2YSksXG4gICAgICAgIHBoYW50b21DbGFzcyA9IGlzQ3VzdG9tQ29udGV4dCA/IG9iamVjdENsYXNzIDogJ1J1bnRpbWVPYmplY3QnO1xuXG4gICAgLyoqIERldGVjdCBKYXZhIGVudmlyb25tZW50cy4gKi9cbiAgICB2YXIgamF2YSA9IC9cXGJKYXZhLy50ZXN0KGphdmFDbGFzcykgJiYgY29udGV4dC5qYXZhO1xuXG4gICAgLyoqIERldGVjdCBSaGluby4gKi9cbiAgICB2YXIgcmhpbm8gPSBqYXZhICYmIGdldENsYXNzT2YoY29udGV4dC5lbnZpcm9ubWVudCkgPT0gZW52aXJvQ2xhc3M7XG5cbiAgICAvKiogQSBjaGFyYWN0ZXIgdG8gcmVwcmVzZW50IGFscGhhLiAqL1xuICAgIHZhciBhbHBoYSA9IGphdmEgPyAnYScgOiAnXFx1MDNiMSc7XG5cbiAgICAvKiogQSBjaGFyYWN0ZXIgdG8gcmVwcmVzZW50IGJldGEuICovXG4gICAgdmFyIGJldGEgPSBqYXZhID8gJ2InIDogJ1xcdTAzYjInO1xuXG4gICAgLyoqIEJyb3dzZXIgZG9jdW1lbnQgb2JqZWN0LiAqL1xuICAgIHZhciBkb2MgPSBjb250ZXh0LmRvY3VtZW50IHx8IHt9O1xuXG4gICAgLyoqXG4gICAgICogRGV0ZWN0IE9wZXJhIGJyb3dzZXIgKFByZXN0by1iYXNlZCkuXG4gICAgICogaHR0cDovL3d3dy5ob3d0b2NyZWF0ZS5jby51ay9vcGVyYVN0dWZmL29wZXJhT2JqZWN0Lmh0bWxcbiAgICAgKiBodHRwOi8vZGV2Lm9wZXJhLmNvbS9hcnRpY2xlcy92aWV3L29wZXJhLW1pbmktd2ViLWNvbnRlbnQtYXV0aG9yaW5nLWd1aWRlbGluZXMvI29wZXJhbWluaVxuICAgICAqL1xuICAgIHZhciBvcGVyYSA9IGNvbnRleHQub3BlcmFtaW5pIHx8IGNvbnRleHQub3BlcmE7XG5cbiAgICAvKiogT3BlcmEgYFtbQ2xhc3NdXWAuICovXG4gICAgdmFyIG9wZXJhQ2xhc3MgPSByZU9wZXJhLnRlc3Qob3BlcmFDbGFzcyA9IChpc0N1c3RvbUNvbnRleHQgJiYgb3BlcmEpID8gb3BlcmFbJ1tbQ2xhc3NdXSddIDogZ2V0Q2xhc3NPZihvcGVyYSkpXG4gICAgICA/IG9wZXJhQ2xhc3NcbiAgICAgIDogKG9wZXJhID0gbnVsbCk7XG5cbiAgICAvKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG5cbiAgICAvKiogVGVtcG9yYXJ5IHZhcmlhYmxlIHVzZWQgb3ZlciB0aGUgc2NyaXB0J3MgbGlmZXRpbWUuICovXG4gICAgdmFyIGRhdGE7XG5cbiAgICAvKiogVGhlIENQVSBhcmNoaXRlY3R1cmUuICovXG4gICAgdmFyIGFyY2ggPSB1YTtcblxuICAgIC8qKiBQbGF0Zm9ybSBkZXNjcmlwdGlvbiBhcnJheS4gKi9cbiAgICB2YXIgZGVzY3JpcHRpb24gPSBbXTtcblxuICAgIC8qKiBQbGF0Zm9ybSBhbHBoYS9iZXRhIGluZGljYXRvci4gKi9cbiAgICB2YXIgcHJlcmVsZWFzZSA9IG51bGw7XG5cbiAgICAvKiogQSBmbGFnIHRvIGluZGljYXRlIHRoYXQgZW52aXJvbm1lbnQgZmVhdHVyZXMgc2hvdWxkIGJlIHVzZWQgdG8gcmVzb2x2ZSB0aGUgcGxhdGZvcm0uICovXG4gICAgdmFyIHVzZUZlYXR1cmVzID0gdWEgPT0gdXNlckFnZW50O1xuXG4gICAgLyoqIFRoZSBicm93c2VyL2Vudmlyb25tZW50IHZlcnNpb24uICovXG4gICAgdmFyIHZlcnNpb24gPSB1c2VGZWF0dXJlcyAmJiBvcGVyYSAmJiB0eXBlb2Ygb3BlcmEudmVyc2lvbiA9PSAnZnVuY3Rpb24nICYmIG9wZXJhLnZlcnNpb24oKTtcblxuICAgIC8qKiBBIGZsYWcgdG8gaW5kaWNhdGUgaWYgdGhlIE9TIGVuZHMgd2l0aCBcIi8gVmVyc2lvblwiICovXG4gICAgdmFyIGlzU3BlY2lhbENhc2VkT1M7XG5cbiAgICAvKiBEZXRlY3RhYmxlIGxheW91dCBlbmdpbmVzIChvcmRlciBpcyBpbXBvcnRhbnQpLiAqL1xuICAgIHZhciBsYXlvdXQgPSBnZXRMYXlvdXQoW1xuICAgICAgeyAnbGFiZWwnOiAnRWRnZUhUTUwnLCAncGF0dGVybic6ICdFZGdlJyB9LFxuICAgICAgJ1RyaWRlbnQnLFxuICAgICAgeyAnbGFiZWwnOiAnV2ViS2l0JywgJ3BhdHRlcm4nOiAnQXBwbGVXZWJLaXQnIH0sXG4gICAgICAnaUNhYicsXG4gICAgICAnUHJlc3RvJyxcbiAgICAgICdOZXRGcm9udCcsXG4gICAgICAnVGFzbWFuJyxcbiAgICAgICdLSFRNTCcsXG4gICAgICAnR2Vja28nXG4gICAgXSk7XG5cbiAgICAvKiBEZXRlY3RhYmxlIGJyb3dzZXIgbmFtZXMgKG9yZGVyIGlzIGltcG9ydGFudCkuICovXG4gICAgdmFyIG5hbWUgPSBnZXROYW1lKFtcbiAgICAgICdBZG9iZSBBSVInLFxuICAgICAgJ0Fyb3JhJyxcbiAgICAgICdBdmFudCBCcm93c2VyJyxcbiAgICAgICdCcmVhY2gnLFxuICAgICAgJ0NhbWlubycsXG4gICAgICAnRWxlY3Ryb24nLFxuICAgICAgJ0VwaXBoYW55JyxcbiAgICAgICdGZW5uZWMnLFxuICAgICAgJ0Zsb2NrJyxcbiAgICAgICdHYWxlb24nLFxuICAgICAgJ0dyZWVuQnJvd3NlcicsXG4gICAgICAnaUNhYicsXG4gICAgICAnSWNld2Vhc2VsJyxcbiAgICAgICdLLU1lbGVvbicsXG4gICAgICAnS29ucXVlcm9yJyxcbiAgICAgICdMdW5hc2NhcGUnLFxuICAgICAgJ01heHRob24nLFxuICAgICAgeyAnbGFiZWwnOiAnTWljcm9zb2Z0IEVkZ2UnLCAncGF0dGVybic6ICdFZGdlJyB9LFxuICAgICAgJ01pZG9yaScsXG4gICAgICAnTm9vayBCcm93c2VyJyxcbiAgICAgICdQYWxlTW9vbicsXG4gICAgICAnUGhhbnRvbUpTJyxcbiAgICAgICdSYXZlbicsXG4gICAgICAnUmVrb25xJyxcbiAgICAgICdSb2NrTWVsdCcsXG4gICAgICB7ICdsYWJlbCc6ICdTYW1zdW5nIEludGVybmV0JywgJ3BhdHRlcm4nOiAnU2Ftc3VuZ0Jyb3dzZXInIH0sXG4gICAgICAnU2VhTW9ua2V5JyxcbiAgICAgIHsgJ2xhYmVsJzogJ1NpbGsnLCAncGF0dGVybic6ICcoPzpDbG91ZDl8U2lsay1BY2NlbGVyYXRlZCknIH0sXG4gICAgICAnU2xlaXBuaXInLFxuICAgICAgJ1NsaW1Ccm93c2VyJyxcbiAgICAgIHsgJ2xhYmVsJzogJ1NSV2FyZSBJcm9uJywgJ3BhdHRlcm4nOiAnSXJvbicgfSxcbiAgICAgICdTdW5yaXNlJyxcbiAgICAgICdTd2lmdGZveCcsXG4gICAgICAnV2F0ZXJmb3gnLFxuICAgICAgJ1dlYlBvc2l0aXZlJyxcbiAgICAgICdPcGVyYSBNaW5pJyxcbiAgICAgIHsgJ2xhYmVsJzogJ09wZXJhIE1pbmknLCAncGF0dGVybic6ICdPUGlPUycgfSxcbiAgICAgICdPcGVyYScsXG4gICAgICB7ICdsYWJlbCc6ICdPcGVyYScsICdwYXR0ZXJuJzogJ09QUicgfSxcbiAgICAgICdDaHJvbWUnLFxuICAgICAgeyAnbGFiZWwnOiAnQ2hyb21lIE1vYmlsZScsICdwYXR0ZXJuJzogJyg/OkNyaU9TfENyTW8pJyB9LFxuICAgICAgeyAnbGFiZWwnOiAnRmlyZWZveCcsICdwYXR0ZXJuJzogJyg/OkZpcmVmb3h8TWluZWZpZWxkKScgfSxcbiAgICAgIHsgJ2xhYmVsJzogJ0ZpcmVmb3ggZm9yIGlPUycsICdwYXR0ZXJuJzogJ0Z4aU9TJyB9LFxuICAgICAgeyAnbGFiZWwnOiAnSUUnLCAncGF0dGVybic6ICdJRU1vYmlsZScgfSxcbiAgICAgIHsgJ2xhYmVsJzogJ0lFJywgJ3BhdHRlcm4nOiAnTVNJRScgfSxcbiAgICAgICdTYWZhcmknXG4gICAgXSk7XG5cbiAgICAvKiBEZXRlY3RhYmxlIHByb2R1Y3RzIChvcmRlciBpcyBpbXBvcnRhbnQpLiAqL1xuICAgIHZhciBwcm9kdWN0ID0gZ2V0UHJvZHVjdChbXG4gICAgICB7ICdsYWJlbCc6ICdCbGFja0JlcnJ5JywgJ3BhdHRlcm4nOiAnQkIxMCcgfSxcbiAgICAgICdCbGFja0JlcnJ5JyxcbiAgICAgIHsgJ2xhYmVsJzogJ0dhbGF4eSBTJywgJ3BhdHRlcm4nOiAnR1QtSTkwMDAnIH0sXG4gICAgICB7ICdsYWJlbCc6ICdHYWxheHkgUzInLCAncGF0dGVybic6ICdHVC1JOTEwMCcgfSxcbiAgICAgIHsgJ2xhYmVsJzogJ0dhbGF4eSBTMycsICdwYXR0ZXJuJzogJ0dULUk5MzAwJyB9LFxuICAgICAgeyAnbGFiZWwnOiAnR2FsYXh5IFM0JywgJ3BhdHRlcm4nOiAnR1QtSTk1MDAnIH0sXG4gICAgICB7ICdsYWJlbCc6ICdHYWxheHkgUzUnLCAncGF0dGVybic6ICdTTS1HOTAwJyB9LFxuICAgICAgeyAnbGFiZWwnOiAnR2FsYXh5IFM2JywgJ3BhdHRlcm4nOiAnU00tRzkyMCcgfSxcbiAgICAgIHsgJ2xhYmVsJzogJ0dhbGF4eSBTNiBFZGdlJywgJ3BhdHRlcm4nOiAnU00tRzkyNScgfSxcbiAgICAgIHsgJ2xhYmVsJzogJ0dhbGF4eSBTNycsICdwYXR0ZXJuJzogJ1NNLUc5MzAnIH0sXG4gICAgICB7ICdsYWJlbCc6ICdHYWxheHkgUzcgRWRnZScsICdwYXR0ZXJuJzogJ1NNLUc5MzUnIH0sXG4gICAgICAnR29vZ2xlIFRWJyxcbiAgICAgICdMdW1pYScsXG4gICAgICAnaVBhZCcsXG4gICAgICAnaVBvZCcsXG4gICAgICAnaVBob25lJyxcbiAgICAgICdLaW5kbGUnLFxuICAgICAgeyAnbGFiZWwnOiAnS2luZGxlIEZpcmUnLCAncGF0dGVybic6ICcoPzpDbG91ZDl8U2lsay1BY2NlbGVyYXRlZCknIH0sXG4gICAgICAnTmV4dXMnLFxuICAgICAgJ05vb2snLFxuICAgICAgJ1BsYXlCb29rJyxcbiAgICAgICdQbGF5U3RhdGlvbiBWaXRhJyxcbiAgICAgICdQbGF5U3RhdGlvbicsXG4gICAgICAnVG91Y2hQYWQnLFxuICAgICAgJ1RyYW5zZm9ybWVyJyxcbiAgICAgIHsgJ2xhYmVsJzogJ1dpaSBVJywgJ3BhdHRlcm4nOiAnV2lpVScgfSxcbiAgICAgICdXaWknLFxuICAgICAgJ1hib3ggT25lJyxcbiAgICAgIHsgJ2xhYmVsJzogJ1hib3ggMzYwJywgJ3BhdHRlcm4nOiAnWGJveCcgfSxcbiAgICAgICdYb29tJ1xuICAgIF0pO1xuXG4gICAgLyogRGV0ZWN0YWJsZSBtYW51ZmFjdHVyZXJzLiAqL1xuICAgIHZhciBtYW51ZmFjdHVyZXIgPSBnZXRNYW51ZmFjdHVyZXIoe1xuICAgICAgJ0FwcGxlJzogeyAnaVBhZCc6IDEsICdpUGhvbmUnOiAxLCAnaVBvZCc6IDEgfSxcbiAgICAgICdBcmNob3MnOiB7fSxcbiAgICAgICdBbWF6b24nOiB7ICdLaW5kbGUnOiAxLCAnS2luZGxlIEZpcmUnOiAxIH0sXG4gICAgICAnQXN1cyc6IHsgJ1RyYW5zZm9ybWVyJzogMSB9LFxuICAgICAgJ0Jhcm5lcyAmIE5vYmxlJzogeyAnTm9vayc6IDEgfSxcbiAgICAgICdCbGFja0JlcnJ5JzogeyAnUGxheUJvb2snOiAxIH0sXG4gICAgICAnR29vZ2xlJzogeyAnR29vZ2xlIFRWJzogMSwgJ05leHVzJzogMSB9LFxuICAgICAgJ0hQJzogeyAnVG91Y2hQYWQnOiAxIH0sXG4gICAgICAnSFRDJzoge30sXG4gICAgICAnTEcnOiB7fSxcbiAgICAgICdNaWNyb3NvZnQnOiB7ICdYYm94JzogMSwgJ1hib3ggT25lJzogMSB9LFxuICAgICAgJ01vdG9yb2xhJzogeyAnWG9vbSc6IDEgfSxcbiAgICAgICdOaW50ZW5kbyc6IHsgJ1dpaSBVJzogMSwgICdXaWknOiAxIH0sXG4gICAgICAnTm9raWEnOiB7ICdMdW1pYSc6IDEgfSxcbiAgICAgICdTYW1zdW5nJzogeyAnR2FsYXh5IFMnOiAxLCAnR2FsYXh5IFMyJzogMSwgJ0dhbGF4eSBTMyc6IDEsICdHYWxheHkgUzQnOiAxIH0sXG4gICAgICAnU29ueSc6IHsgJ1BsYXlTdGF0aW9uJzogMSwgJ1BsYXlTdGF0aW9uIFZpdGEnOiAxIH1cbiAgICB9KTtcblxuICAgIC8qIERldGVjdGFibGUgb3BlcmF0aW5nIHN5c3RlbXMgKG9yZGVyIGlzIGltcG9ydGFudCkuICovXG4gICAgdmFyIG9zID0gZ2V0T1MoW1xuICAgICAgJ1dpbmRvd3MgUGhvbmUnLFxuICAgICAgJ0FuZHJvaWQnLFxuICAgICAgJ0NlbnRPUycsXG4gICAgICB7ICdsYWJlbCc6ICdDaHJvbWUgT1MnLCAncGF0dGVybic6ICdDck9TJyB9LFxuICAgICAgJ0RlYmlhbicsXG4gICAgICAnRmVkb3JhJyxcbiAgICAgICdGcmVlQlNEJyxcbiAgICAgICdHZW50b28nLFxuICAgICAgJ0hhaWt1JyxcbiAgICAgICdLdWJ1bnR1JyxcbiAgICAgICdMaW51eCBNaW50JyxcbiAgICAgICdPcGVuQlNEJyxcbiAgICAgICdSZWQgSGF0JyxcbiAgICAgICdTdVNFJyxcbiAgICAgICdVYnVudHUnLFxuICAgICAgJ1h1YnVudHUnLFxuICAgICAgJ0N5Z3dpbicsXG4gICAgICAnU3ltYmlhbiBPUycsXG4gICAgICAnaHB3T1MnLFxuICAgICAgJ3dlYk9TICcsXG4gICAgICAnd2ViT1MnLFxuICAgICAgJ1RhYmxldCBPUycsXG4gICAgICAnVGl6ZW4nLFxuICAgICAgJ0xpbnV4JyxcbiAgICAgICdNYWMgT1MgWCcsXG4gICAgICAnTWFjaW50b3NoJyxcbiAgICAgICdNYWMnLFxuICAgICAgJ1dpbmRvd3MgOTg7JyxcbiAgICAgICdXaW5kb3dzICdcbiAgICBdKTtcblxuICAgIC8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cblxuICAgIC8qKlxuICAgICAqIFBpY2tzIHRoZSBsYXlvdXQgZW5naW5lIGZyb20gYW4gYXJyYXkgb2YgZ3Vlc3Nlcy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtBcnJheX0gZ3Vlc3NlcyBBbiBhcnJheSBvZiBndWVzc2VzLlxuICAgICAqIEByZXR1cm5zIHtudWxsfHN0cmluZ30gVGhlIGRldGVjdGVkIGxheW91dCBlbmdpbmUuXG4gICAgICovXG4gICAgZnVuY3Rpb24gZ2V0TGF5b3V0KGd1ZXNzZXMpIHtcbiAgICAgIHJldHVybiByZWR1Y2UoZ3Vlc3NlcywgZnVuY3Rpb24ocmVzdWx0LCBndWVzcykge1xuICAgICAgICByZXR1cm4gcmVzdWx0IHx8IFJlZ0V4cCgnXFxcXGInICsgKFxuICAgICAgICAgIGd1ZXNzLnBhdHRlcm4gfHwgcXVhbGlmeShndWVzcylcbiAgICAgICAgKSArICdcXFxcYicsICdpJykuZXhlYyh1YSkgJiYgKGd1ZXNzLmxhYmVsIHx8IGd1ZXNzKTtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFBpY2tzIHRoZSBtYW51ZmFjdHVyZXIgZnJvbSBhbiBhcnJheSBvZiBndWVzc2VzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBndWVzc2VzIEFuIG9iamVjdCBvZiBndWVzc2VzLlxuICAgICAqIEByZXR1cm5zIHtudWxsfHN0cmluZ30gVGhlIGRldGVjdGVkIG1hbnVmYWN0dXJlci5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBnZXRNYW51ZmFjdHVyZXIoZ3Vlc3Nlcykge1xuICAgICAgcmV0dXJuIHJlZHVjZShndWVzc2VzLCBmdW5jdGlvbihyZXN1bHQsIHZhbHVlLCBrZXkpIHtcbiAgICAgICAgLy8gTG9va3VwIHRoZSBtYW51ZmFjdHVyZXIgYnkgcHJvZHVjdCBvciBzY2FuIHRoZSBVQSBmb3IgdGhlIG1hbnVmYWN0dXJlci5cbiAgICAgICAgcmV0dXJuIHJlc3VsdCB8fCAoXG4gICAgICAgICAgdmFsdWVbcHJvZHVjdF0gfHxcbiAgICAgICAgICB2YWx1ZVsvXlthLXpdKyg/OiArW2Etel0rXFxiKSovaS5leGVjKHByb2R1Y3QpXSB8fFxuICAgICAgICAgIFJlZ0V4cCgnXFxcXGInICsgcXVhbGlmeShrZXkpICsgJyg/OlxcXFxifFxcXFx3KlxcXFxkKScsICdpJykuZXhlYyh1YSlcbiAgICAgICAgKSAmJiBrZXk7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBQaWNrcyB0aGUgYnJvd3NlciBuYW1lIGZyb20gYW4gYXJyYXkgb2YgZ3Vlc3Nlcy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtBcnJheX0gZ3Vlc3NlcyBBbiBhcnJheSBvZiBndWVzc2VzLlxuICAgICAqIEByZXR1cm5zIHtudWxsfHN0cmluZ30gVGhlIGRldGVjdGVkIGJyb3dzZXIgbmFtZS5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBnZXROYW1lKGd1ZXNzZXMpIHtcbiAgICAgIHJldHVybiByZWR1Y2UoZ3Vlc3NlcywgZnVuY3Rpb24ocmVzdWx0LCBndWVzcykge1xuICAgICAgICByZXR1cm4gcmVzdWx0IHx8IFJlZ0V4cCgnXFxcXGInICsgKFxuICAgICAgICAgIGd1ZXNzLnBhdHRlcm4gfHwgcXVhbGlmeShndWVzcylcbiAgICAgICAgKSArICdcXFxcYicsICdpJykuZXhlYyh1YSkgJiYgKGd1ZXNzLmxhYmVsIHx8IGd1ZXNzKTtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFBpY2tzIHRoZSBPUyBuYW1lIGZyb20gYW4gYXJyYXkgb2YgZ3Vlc3Nlcy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtBcnJheX0gZ3Vlc3NlcyBBbiBhcnJheSBvZiBndWVzc2VzLlxuICAgICAqIEByZXR1cm5zIHtudWxsfHN0cmluZ30gVGhlIGRldGVjdGVkIE9TIG5hbWUuXG4gICAgICovXG4gICAgZnVuY3Rpb24gZ2V0T1MoZ3Vlc3Nlcykge1xuICAgICAgcmV0dXJuIHJlZHVjZShndWVzc2VzLCBmdW5jdGlvbihyZXN1bHQsIGd1ZXNzKSB7XG4gICAgICAgIHZhciBwYXR0ZXJuID0gZ3Vlc3MucGF0dGVybiB8fCBxdWFsaWZ5KGd1ZXNzKTtcbiAgICAgICAgaWYgKCFyZXN1bHQgJiYgKHJlc3VsdCA9XG4gICAgICAgICAgICAgIFJlZ0V4cCgnXFxcXGInICsgcGF0dGVybiArICcoPzovW1xcXFxkLl0rfFsgXFxcXHcuXSopJywgJ2knKS5leGVjKHVhKVxuICAgICAgICAgICAgKSkge1xuICAgICAgICAgIHJlc3VsdCA9IGNsZWFudXBPUyhyZXN1bHQsIHBhdHRlcm4sIGd1ZXNzLmxhYmVsIHx8IGd1ZXNzKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUGlja3MgdGhlIHByb2R1Y3QgbmFtZSBmcm9tIGFuIGFycmF5IG9mIGd1ZXNzZXMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGd1ZXNzZXMgQW4gYXJyYXkgb2YgZ3Vlc3Nlcy5cbiAgICAgKiBAcmV0dXJucyB7bnVsbHxzdHJpbmd9IFRoZSBkZXRlY3RlZCBwcm9kdWN0IG5hbWUuXG4gICAgICovXG4gICAgZnVuY3Rpb24gZ2V0UHJvZHVjdChndWVzc2VzKSB7XG4gICAgICByZXR1cm4gcmVkdWNlKGd1ZXNzZXMsIGZ1bmN0aW9uKHJlc3VsdCwgZ3Vlc3MpIHtcbiAgICAgICAgdmFyIHBhdHRlcm4gPSBndWVzcy5wYXR0ZXJuIHx8IHF1YWxpZnkoZ3Vlc3MpO1xuICAgICAgICBpZiAoIXJlc3VsdCAmJiAocmVzdWx0ID1cbiAgICAgICAgICAgICAgUmVnRXhwKCdcXFxcYicgKyBwYXR0ZXJuICsgJyAqXFxcXGQrWy5cXFxcd19dKicsICdpJykuZXhlYyh1YSkgfHxcbiAgICAgICAgICAgICAgUmVnRXhwKCdcXFxcYicgKyBwYXR0ZXJuICsgJyAqXFxcXHcrLVtcXFxcd10qJywgJ2knKS5leGVjKHVhKSB8fFxuICAgICAgICAgICAgICBSZWdFeHAoJ1xcXFxiJyArIHBhdHRlcm4gKyAnKD86OyAqKD86W2Etel0rW18tXSk/W2Etel0rXFxcXGQrfFteICgpOy1dKiknLCAnaScpLmV4ZWModWEpXG4gICAgICAgICAgICApKSB7XG4gICAgICAgICAgLy8gU3BsaXQgYnkgZm9yd2FyZCBzbGFzaCBhbmQgYXBwZW5kIHByb2R1Y3QgdmVyc2lvbiBpZiBuZWVkZWQuXG4gICAgICAgICAgaWYgKChyZXN1bHQgPSBTdHJpbmcoKGd1ZXNzLmxhYmVsICYmICFSZWdFeHAocGF0dGVybiwgJ2knKS50ZXN0KGd1ZXNzLmxhYmVsKSkgPyBndWVzcy5sYWJlbCA6IHJlc3VsdCkuc3BsaXQoJy8nKSlbMV0gJiYgIS9bXFxkLl0rLy50ZXN0KHJlc3VsdFswXSkpIHtcbiAgICAgICAgICAgIHJlc3VsdFswXSArPSAnICcgKyByZXN1bHRbMV07XG4gICAgICAgICAgfVxuICAgICAgICAgIC8vIENvcnJlY3QgY2hhcmFjdGVyIGNhc2UgYW5kIGNsZWFudXAgc3RyaW5nLlxuICAgICAgICAgIGd1ZXNzID0gZ3Vlc3MubGFiZWwgfHwgZ3Vlc3M7XG4gICAgICAgICAgcmVzdWx0ID0gZm9ybWF0KHJlc3VsdFswXVxuICAgICAgICAgICAgLnJlcGxhY2UoUmVnRXhwKHBhdHRlcm4sICdpJyksIGd1ZXNzKVxuICAgICAgICAgICAgLnJlcGxhY2UoUmVnRXhwKCc7ICooPzonICsgZ3Vlc3MgKyAnW18tXSk/JywgJ2knKSwgJyAnKVxuICAgICAgICAgICAgLnJlcGxhY2UoUmVnRXhwKCcoJyArIGd1ZXNzICsgJylbLV8uXT8oXFxcXHcpJywgJ2knKSwgJyQxICQyJykpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXNvbHZlcyB0aGUgdmVyc2lvbiB1c2luZyBhbiBhcnJheSBvZiBVQSBwYXR0ZXJucy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtBcnJheX0gcGF0dGVybnMgQW4gYXJyYXkgb2YgVUEgcGF0dGVybnMuXG4gICAgICogQHJldHVybnMge251bGx8c3RyaW5nfSBUaGUgZGV0ZWN0ZWQgdmVyc2lvbi5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBnZXRWZXJzaW9uKHBhdHRlcm5zKSB7XG4gICAgICByZXR1cm4gcmVkdWNlKHBhdHRlcm5zLCBmdW5jdGlvbihyZXN1bHQsIHBhdHRlcm4pIHtcbiAgICAgICAgcmV0dXJuIHJlc3VsdCB8fCAoUmVnRXhwKHBhdHRlcm4gK1xuICAgICAgICAgICcoPzotW1xcXFxkLl0rL3woPzogZm9yIFtcXFxcdy1dKyk/WyAvLV0pKFtcXFxcZC5dK1teICgpOy9fLV0qKScsICdpJykuZXhlYyh1YSkgfHwgMClbMV0gfHwgbnVsbDtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgYHBsYXRmb3JtLmRlc2NyaXB0aW9uYCB3aGVuIHRoZSBwbGF0Zm9ybSBvYmplY3QgaXMgY29lcmNlZCB0byBhIHN0cmluZy5cbiAgICAgKlxuICAgICAqIEBuYW1lIHRvU3RyaW5nXG4gICAgICogQG1lbWJlck9mIHBsYXRmb3JtXG4gICAgICogQHJldHVybnMge3N0cmluZ30gUmV0dXJucyBgcGxhdGZvcm0uZGVzY3JpcHRpb25gIGlmIGF2YWlsYWJsZSwgZWxzZSBhbiBlbXB0eSBzdHJpbmcuXG4gICAgICovXG4gICAgZnVuY3Rpb24gdG9TdHJpbmdQbGF0Zm9ybSgpIHtcbiAgICAgIHJldHVybiB0aGlzLmRlc2NyaXB0aW9uIHx8ICcnO1xuICAgIH1cblxuICAgIC8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cblxuICAgIC8vIENvbnZlcnQgbGF5b3V0IHRvIGFuIGFycmF5IHNvIHdlIGNhbiBhZGQgZXh0cmEgZGV0YWlscy5cbiAgICBsYXlvdXQgJiYgKGxheW91dCA9IFtsYXlvdXRdKTtcblxuICAgIC8vIERldGVjdCBwcm9kdWN0IG5hbWVzIHRoYXQgY29udGFpbiB0aGVpciBtYW51ZmFjdHVyZXIncyBuYW1lLlxuICAgIGlmIChtYW51ZmFjdHVyZXIgJiYgIXByb2R1Y3QpIHtcbiAgICAgIHByb2R1Y3QgPSBnZXRQcm9kdWN0KFttYW51ZmFjdHVyZXJdKTtcbiAgICB9XG4gICAgLy8gQ2xlYW4gdXAgR29vZ2xlIFRWLlxuICAgIGlmICgoZGF0YSA9IC9cXGJHb29nbGUgVFZcXGIvLmV4ZWMocHJvZHVjdCkpKSB7XG4gICAgICBwcm9kdWN0ID0gZGF0YVswXTtcbiAgICB9XG4gICAgLy8gRGV0ZWN0IHNpbXVsYXRvcnMuXG4gICAgaWYgKC9cXGJTaW11bGF0b3JcXGIvaS50ZXN0KHVhKSkge1xuICAgICAgcHJvZHVjdCA9IChwcm9kdWN0ID8gcHJvZHVjdCArICcgJyA6ICcnKSArICdTaW11bGF0b3InO1xuICAgIH1cbiAgICAvLyBEZXRlY3QgT3BlcmEgTWluaSA4KyBydW5uaW5nIGluIFR1cmJvL1VuY29tcHJlc3NlZCBtb2RlIG9uIGlPUy5cbiAgICBpZiAobmFtZSA9PSAnT3BlcmEgTWluaScgJiYgL1xcYk9QaU9TXFxiLy50ZXN0KHVhKSkge1xuICAgICAgZGVzY3JpcHRpb24ucHVzaCgncnVubmluZyBpbiBUdXJiby9VbmNvbXByZXNzZWQgbW9kZScpO1xuICAgIH1cbiAgICAvLyBEZXRlY3QgSUUgTW9iaWxlIDExLlxuICAgIGlmIChuYW1lID09ICdJRScgJiYgL1xcYmxpa2UgaVBob25lIE9TXFxiLy50ZXN0KHVhKSkge1xuICAgICAgZGF0YSA9IHBhcnNlKHVhLnJlcGxhY2UoL2xpa2UgaVBob25lIE9TLywgJycpKTtcbiAgICAgIG1hbnVmYWN0dXJlciA9IGRhdGEubWFudWZhY3R1cmVyO1xuICAgICAgcHJvZHVjdCA9IGRhdGEucHJvZHVjdDtcbiAgICB9XG4gICAgLy8gRGV0ZWN0IGlPUy5cbiAgICBlbHNlIGlmICgvXmlQLy50ZXN0KHByb2R1Y3QpKSB7XG4gICAgICBuYW1lIHx8IChuYW1lID0gJ1NhZmFyaScpO1xuICAgICAgb3MgPSAnaU9TJyArICgoZGF0YSA9IC8gT1MgKFtcXGRfXSspL2kuZXhlYyh1YSkpXG4gICAgICAgID8gJyAnICsgZGF0YVsxXS5yZXBsYWNlKC9fL2csICcuJylcbiAgICAgICAgOiAnJyk7XG4gICAgfVxuICAgIC8vIERldGVjdCBLdWJ1bnR1LlxuICAgIGVsc2UgaWYgKG5hbWUgPT0gJ0tvbnF1ZXJvcicgJiYgIS9idW50dS9pLnRlc3Qob3MpKSB7XG4gICAgICBvcyA9ICdLdWJ1bnR1JztcbiAgICB9XG4gICAgLy8gRGV0ZWN0IEFuZHJvaWQgYnJvd3NlcnMuXG4gICAgZWxzZSBpZiAoKG1hbnVmYWN0dXJlciAmJiBtYW51ZmFjdHVyZXIgIT0gJ0dvb2dsZScgJiZcbiAgICAgICAgKCgvQ2hyb21lLy50ZXN0KG5hbWUpICYmICEvXFxiTW9iaWxlIFNhZmFyaVxcYi9pLnRlc3QodWEpKSB8fCAvXFxiVml0YVxcYi8udGVzdChwcm9kdWN0KSkpIHx8XG4gICAgICAgICgvXFxiQW5kcm9pZFxcYi8udGVzdChvcykgJiYgL15DaHJvbWUvLnRlc3QobmFtZSkgJiYgL1xcYlZlcnNpb25cXC8vaS50ZXN0KHVhKSkpIHtcbiAgICAgIG5hbWUgPSAnQW5kcm9pZCBCcm93c2VyJztcbiAgICAgIG9zID0gL1xcYkFuZHJvaWRcXGIvLnRlc3Qob3MpID8gb3MgOiAnQW5kcm9pZCc7XG4gICAgfVxuICAgIC8vIERldGVjdCBTaWxrIGRlc2t0b3AvYWNjZWxlcmF0ZWQgbW9kZXMuXG4gICAgZWxzZSBpZiAobmFtZSA9PSAnU2lsaycpIHtcbiAgICAgIGlmICghL1xcYk1vYmkvaS50ZXN0KHVhKSkge1xuICAgICAgICBvcyA9ICdBbmRyb2lkJztcbiAgICAgICAgZGVzY3JpcHRpb24udW5zaGlmdCgnZGVza3RvcCBtb2RlJyk7XG4gICAgICB9XG4gICAgICBpZiAoL0FjY2VsZXJhdGVkICo9ICp0cnVlL2kudGVzdCh1YSkpIHtcbiAgICAgICAgZGVzY3JpcHRpb24udW5zaGlmdCgnYWNjZWxlcmF0ZWQnKTtcbiAgICAgIH1cbiAgICB9XG4gICAgLy8gRGV0ZWN0IFBhbGVNb29uIGlkZW50aWZ5aW5nIGFzIEZpcmVmb3guXG4gICAgZWxzZSBpZiAobmFtZSA9PSAnUGFsZU1vb24nICYmIChkYXRhID0gL1xcYkZpcmVmb3hcXC8oW1xcZC5dKylcXGIvLmV4ZWModWEpKSkge1xuICAgICAgZGVzY3JpcHRpb24ucHVzaCgnaWRlbnRpZnlpbmcgYXMgRmlyZWZveCAnICsgZGF0YVsxXSk7XG4gICAgfVxuICAgIC8vIERldGVjdCBGaXJlZm94IE9TIGFuZCBwcm9kdWN0cyBydW5uaW5nIEZpcmVmb3guXG4gICAgZWxzZSBpZiAobmFtZSA9PSAnRmlyZWZveCcgJiYgKGRhdGEgPSAvXFxiKE1vYmlsZXxUYWJsZXR8VFYpXFxiL2kuZXhlYyh1YSkpKSB7XG4gICAgICBvcyB8fCAob3MgPSAnRmlyZWZveCBPUycpO1xuICAgICAgcHJvZHVjdCB8fCAocHJvZHVjdCA9IGRhdGFbMV0pO1xuICAgIH1cbiAgICAvLyBEZXRlY3QgZmFsc2UgcG9zaXRpdmVzIGZvciBGaXJlZm94L1NhZmFyaS5cbiAgICBlbHNlIGlmICghbmFtZSB8fCAoZGF0YSA9ICEvXFxiTWluZWZpZWxkXFxiL2kudGVzdCh1YSkgJiYgL1xcYig/OkZpcmVmb3h8U2FmYXJpKVxcYi8uZXhlYyhuYW1lKSkpIHtcbiAgICAgIC8vIEVzY2FwZSB0aGUgYC9gIGZvciBGaXJlZm94IDEuXG4gICAgICBpZiAobmFtZSAmJiAhcHJvZHVjdCAmJiAvW1xcLyxdfF5bXihdKz9cXCkvLnRlc3QodWEuc2xpY2UodWEuaW5kZXhPZihkYXRhICsgJy8nKSArIDgpKSkge1xuICAgICAgICAvLyBDbGVhciBuYW1lIG9mIGZhbHNlIHBvc2l0aXZlcy5cbiAgICAgICAgbmFtZSA9IG51bGw7XG4gICAgICB9XG4gICAgICAvLyBSZWFzc2lnbiBhIGdlbmVyaWMgbmFtZS5cbiAgICAgIGlmICgoZGF0YSA9IHByb2R1Y3QgfHwgbWFudWZhY3R1cmVyIHx8IG9zKSAmJlxuICAgICAgICAgIChwcm9kdWN0IHx8IG1hbnVmYWN0dXJlciB8fCAvXFxiKD86QW5kcm9pZHxTeW1iaWFuIE9TfFRhYmxldCBPU3x3ZWJPUylcXGIvLnRlc3Qob3MpKSkge1xuICAgICAgICBuYW1lID0gL1thLXpdKyg/OiBIYXQpPy9pLmV4ZWMoL1xcYkFuZHJvaWRcXGIvLnRlc3Qob3MpID8gb3MgOiBkYXRhKSArICcgQnJvd3Nlcic7XG4gICAgICB9XG4gICAgfVxuICAgIC8vIEFkZCBDaHJvbWUgdmVyc2lvbiB0byBkZXNjcmlwdGlvbiBmb3IgRWxlY3Ryb24uXG4gICAgZWxzZSBpZiAobmFtZSA9PSAnRWxlY3Ryb24nICYmIChkYXRhID0gKC9cXGJDaHJvbWVcXC8oW1xcZC5dKylcXGIvLmV4ZWModWEpIHx8IDApWzFdKSkge1xuICAgICAgZGVzY3JpcHRpb24ucHVzaCgnQ2hyb21pdW0gJyArIGRhdGEpO1xuICAgIH1cbiAgICAvLyBEZXRlY3Qgbm9uLU9wZXJhIChQcmVzdG8tYmFzZWQpIHZlcnNpb25zIChvcmRlciBpcyBpbXBvcnRhbnQpLlxuICAgIGlmICghdmVyc2lvbikge1xuICAgICAgdmVyc2lvbiA9IGdldFZlcnNpb24oW1xuICAgICAgICAnKD86Q2xvdWQ5fENyaU9TfENyTW98RWRnZXxGeGlPU3xJRU1vYmlsZXxJcm9ufE9wZXJhID9NaW5pfE9QaU9TfE9QUnxSYXZlbnxTYW1zdW5nQnJvd3NlcnxTaWxrKD8hL1tcXFxcZC5dKyQpKScsXG4gICAgICAgICdWZXJzaW9uJyxcbiAgICAgICAgcXVhbGlmeShuYW1lKSxcbiAgICAgICAgJyg/OkZpcmVmb3h8TWluZWZpZWxkfE5ldEZyb250KSdcbiAgICAgIF0pO1xuICAgIH1cbiAgICAvLyBEZXRlY3Qgc3R1YmJvcm4gbGF5b3V0IGVuZ2luZXMuXG4gICAgaWYgKChkYXRhID1cbiAgICAgICAgICBsYXlvdXQgPT0gJ2lDYWInICYmIHBhcnNlRmxvYXQodmVyc2lvbikgPiAzICYmICdXZWJLaXQnIHx8XG4gICAgICAgICAgL1xcYk9wZXJhXFxiLy50ZXN0KG5hbWUpICYmICgvXFxiT1BSXFxiLy50ZXN0KHVhKSA/ICdCbGluaycgOiAnUHJlc3RvJykgfHxcbiAgICAgICAgICAvXFxiKD86TWlkb3JpfE5vb2t8U2FmYXJpKVxcYi9pLnRlc3QodWEpICYmICEvXig/OlRyaWRlbnR8RWRnZUhUTUwpJC8udGVzdChsYXlvdXQpICYmICdXZWJLaXQnIHx8XG4gICAgICAgICAgIWxheW91dCAmJiAvXFxiTVNJRVxcYi9pLnRlc3QodWEpICYmIChvcyA9PSAnTWFjIE9TJyA/ICdUYXNtYW4nIDogJ1RyaWRlbnQnKSB8fFxuICAgICAgICAgIGxheW91dCA9PSAnV2ViS2l0JyAmJiAvXFxiUGxheVN0YXRpb25cXGIoPyEgVml0YVxcYikvaS50ZXN0KG5hbWUpICYmICdOZXRGcm9udCdcbiAgICAgICAgKSkge1xuICAgICAgbGF5b3V0ID0gW2RhdGFdO1xuICAgIH1cbiAgICAvLyBEZXRlY3QgV2luZG93cyBQaG9uZSA3IGRlc2t0b3AgbW9kZS5cbiAgICBpZiAobmFtZSA9PSAnSUUnICYmIChkYXRhID0gKC87ICooPzpYQkxXUHxadW5lV1ApKFxcZCspL2kuZXhlYyh1YSkgfHwgMClbMV0pKSB7XG4gICAgICBuYW1lICs9ICcgTW9iaWxlJztcbiAgICAgIG9zID0gJ1dpbmRvd3MgUGhvbmUgJyArICgvXFwrJC8udGVzdChkYXRhKSA/IGRhdGEgOiBkYXRhICsgJy54Jyk7XG4gICAgICBkZXNjcmlwdGlvbi51bnNoaWZ0KCdkZXNrdG9wIG1vZGUnKTtcbiAgICB9XG4gICAgLy8gRGV0ZWN0IFdpbmRvd3MgUGhvbmUgOC54IGRlc2t0b3AgbW9kZS5cbiAgICBlbHNlIGlmICgvXFxiV1BEZXNrdG9wXFxiL2kudGVzdCh1YSkpIHtcbiAgICAgIG5hbWUgPSAnSUUgTW9iaWxlJztcbiAgICAgIG9zID0gJ1dpbmRvd3MgUGhvbmUgOC54JztcbiAgICAgIGRlc2NyaXB0aW9uLnVuc2hpZnQoJ2Rlc2t0b3AgbW9kZScpO1xuICAgICAgdmVyc2lvbiB8fCAodmVyc2lvbiA9ICgvXFxicnY6KFtcXGQuXSspLy5leGVjKHVhKSB8fCAwKVsxXSk7XG4gICAgfVxuICAgIC8vIERldGVjdCBJRSAxMSBpZGVudGlmeWluZyBhcyBvdGhlciBicm93c2Vycy5cbiAgICBlbHNlIGlmIChuYW1lICE9ICdJRScgJiYgbGF5b3V0ID09ICdUcmlkZW50JyAmJiAoZGF0YSA9IC9cXGJydjooW1xcZC5dKykvLmV4ZWModWEpKSkge1xuICAgICAgaWYgKG5hbWUpIHtcbiAgICAgICAgZGVzY3JpcHRpb24ucHVzaCgnaWRlbnRpZnlpbmcgYXMgJyArIG5hbWUgKyAodmVyc2lvbiA/ICcgJyArIHZlcnNpb24gOiAnJykpO1xuICAgICAgfVxuICAgICAgbmFtZSA9ICdJRSc7XG4gICAgICB2ZXJzaW9uID0gZGF0YVsxXTtcbiAgICB9XG4gICAgLy8gTGV2ZXJhZ2UgZW52aXJvbm1lbnQgZmVhdHVyZXMuXG4gICAgaWYgKHVzZUZlYXR1cmVzKSB7XG4gICAgICAvLyBEZXRlY3Qgc2VydmVyLXNpZGUgZW52aXJvbm1lbnRzLlxuICAgICAgLy8gUmhpbm8gaGFzIGEgZ2xvYmFsIGZ1bmN0aW9uIHdoaWxlIG90aGVycyBoYXZlIGEgZ2xvYmFsIG9iamVjdC5cbiAgICAgIGlmIChpc0hvc3RUeXBlKGNvbnRleHQsICdnbG9iYWwnKSkge1xuICAgICAgICBpZiAoamF2YSkge1xuICAgICAgICAgIGRhdGEgPSBqYXZhLmxhbmcuU3lzdGVtO1xuICAgICAgICAgIGFyY2ggPSBkYXRhLmdldFByb3BlcnR5KCdvcy5hcmNoJyk7XG4gICAgICAgICAgb3MgPSBvcyB8fCBkYXRhLmdldFByb3BlcnR5KCdvcy5uYW1lJykgKyAnICcgKyBkYXRhLmdldFByb3BlcnR5KCdvcy52ZXJzaW9uJyk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHJoaW5vKSB7XG4gICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIHZlcnNpb24gPSBjb250ZXh0LnJlcXVpcmUoJ3JpbmdvL2VuZ2luZScpLnZlcnNpb24uam9pbignLicpO1xuICAgICAgICAgICAgbmFtZSA9ICdSaW5nb0pTJztcbiAgICAgICAgICB9IGNhdGNoKGUpIHtcbiAgICAgICAgICAgIGlmICgoZGF0YSA9IGNvbnRleHQuc3lzdGVtKSAmJiBkYXRhLmdsb2JhbC5zeXN0ZW0gPT0gY29udGV4dC5zeXN0ZW0pIHtcbiAgICAgICAgICAgICAgbmFtZSA9ICdOYXJ3aGFsJztcbiAgICAgICAgICAgICAgb3MgfHwgKG9zID0gZGF0YVswXS5vcyB8fCBudWxsKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKCFuYW1lKSB7XG4gICAgICAgICAgICBuYW1lID0gJ1JoaW5vJztcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAoXG4gICAgICAgICAgdHlwZW9mIGNvbnRleHQucHJvY2VzcyA9PSAnb2JqZWN0JyAmJiAhY29udGV4dC5wcm9jZXNzLmJyb3dzZXIgJiZcbiAgICAgICAgICAoZGF0YSA9IGNvbnRleHQucHJvY2VzcylcbiAgICAgICAgKSB7XG4gICAgICAgICAgaWYgKHR5cGVvZiBkYXRhLnZlcnNpb25zID09ICdvYmplY3QnKSB7XG4gICAgICAgICAgICBpZiAodHlwZW9mIGRhdGEudmVyc2lvbnMuZWxlY3Ryb24gPT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgICAgZGVzY3JpcHRpb24ucHVzaCgnTm9kZSAnICsgZGF0YS52ZXJzaW9ucy5ub2RlKTtcbiAgICAgICAgICAgICAgbmFtZSA9ICdFbGVjdHJvbic7XG4gICAgICAgICAgICAgIHZlcnNpb24gPSBkYXRhLnZlcnNpb25zLmVsZWN0cm9uO1xuICAgICAgICAgICAgfSBlbHNlIGlmICh0eXBlb2YgZGF0YS52ZXJzaW9ucy5udyA9PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgICBkZXNjcmlwdGlvbi5wdXNoKCdDaHJvbWl1bSAnICsgdmVyc2lvbiwgJ05vZGUgJyArIGRhdGEudmVyc2lvbnMubm9kZSk7XG4gICAgICAgICAgICAgIG5hbWUgPSAnTlcuanMnO1xuICAgICAgICAgICAgICB2ZXJzaW9uID0gZGF0YS52ZXJzaW9ucy5udztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKCFuYW1lKSB7XG4gICAgICAgICAgICBuYW1lID0gJ05vZGUuanMnO1xuICAgICAgICAgICAgYXJjaCA9IGRhdGEuYXJjaDtcbiAgICAgICAgICAgIG9zID0gZGF0YS5wbGF0Zm9ybTtcbiAgICAgICAgICAgIHZlcnNpb24gPSAvW1xcZC5dKy8uZXhlYyhkYXRhLnZlcnNpb24pO1xuICAgICAgICAgICAgdmVyc2lvbiA9IHZlcnNpb24gPyB2ZXJzaW9uWzBdIDogbnVsbDtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIC8vIERldGVjdCBBZG9iZSBBSVIuXG4gICAgICBlbHNlIGlmIChnZXRDbGFzc09mKChkYXRhID0gY29udGV4dC5ydW50aW1lKSkgPT0gYWlyUnVudGltZUNsYXNzKSB7XG4gICAgICAgIG5hbWUgPSAnQWRvYmUgQUlSJztcbiAgICAgICAgb3MgPSBkYXRhLmZsYXNoLnN5c3RlbS5DYXBhYmlsaXRpZXMub3M7XG4gICAgICB9XG4gICAgICAvLyBEZXRlY3QgUGhhbnRvbUpTLlxuICAgICAgZWxzZSBpZiAoZ2V0Q2xhc3NPZigoZGF0YSA9IGNvbnRleHQucGhhbnRvbSkpID09IHBoYW50b21DbGFzcykge1xuICAgICAgICBuYW1lID0gJ1BoYW50b21KUyc7XG4gICAgICAgIHZlcnNpb24gPSAoZGF0YSA9IGRhdGEudmVyc2lvbiB8fCBudWxsKSAmJiAoZGF0YS5tYWpvciArICcuJyArIGRhdGEubWlub3IgKyAnLicgKyBkYXRhLnBhdGNoKTtcbiAgICAgIH1cbiAgICAgIC8vIERldGVjdCBJRSBjb21wYXRpYmlsaXR5IG1vZGVzLlxuICAgICAgZWxzZSBpZiAodHlwZW9mIGRvYy5kb2N1bWVudE1vZGUgPT0gJ251bWJlcicgJiYgKGRhdGEgPSAvXFxiVHJpZGVudFxcLyhcXGQrKS9pLmV4ZWModWEpKSkge1xuICAgICAgICAvLyBXZSdyZSBpbiBjb21wYXRpYmlsaXR5IG1vZGUgd2hlbiB0aGUgVHJpZGVudCB2ZXJzaW9uICsgNCBkb2Vzbid0XG4gICAgICAgIC8vIGVxdWFsIHRoZSBkb2N1bWVudCBtb2RlLlxuICAgICAgICB2ZXJzaW9uID0gW3ZlcnNpb24sIGRvYy5kb2N1bWVudE1vZGVdO1xuICAgICAgICBpZiAoKGRhdGEgPSArZGF0YVsxXSArIDQpICE9IHZlcnNpb25bMV0pIHtcbiAgICAgICAgICBkZXNjcmlwdGlvbi5wdXNoKCdJRSAnICsgdmVyc2lvblsxXSArICcgbW9kZScpO1xuICAgICAgICAgIGxheW91dCAmJiAobGF5b3V0WzFdID0gJycpO1xuICAgICAgICAgIHZlcnNpb25bMV0gPSBkYXRhO1xuICAgICAgICB9XG4gICAgICAgIHZlcnNpb24gPSBuYW1lID09ICdJRScgPyBTdHJpbmcodmVyc2lvblsxXS50b0ZpeGVkKDEpKSA6IHZlcnNpb25bMF07XG4gICAgICB9XG4gICAgICAvLyBEZXRlY3QgSUUgMTEgbWFza2luZyBhcyBvdGhlciBicm93c2Vycy5cbiAgICAgIGVsc2UgaWYgKHR5cGVvZiBkb2MuZG9jdW1lbnRNb2RlID09ICdudW1iZXInICYmIC9eKD86Q2hyb21lfEZpcmVmb3gpXFxiLy50ZXN0KG5hbWUpKSB7XG4gICAgICAgIGRlc2NyaXB0aW9uLnB1c2goJ21hc2tpbmcgYXMgJyArIG5hbWUgKyAnICcgKyB2ZXJzaW9uKTtcbiAgICAgICAgbmFtZSA9ICdJRSc7XG4gICAgICAgIHZlcnNpb24gPSAnMTEuMCc7XG4gICAgICAgIGxheW91dCA9IFsnVHJpZGVudCddO1xuICAgICAgICBvcyA9ICdXaW5kb3dzJztcbiAgICAgIH1cbiAgICAgIG9zID0gb3MgJiYgZm9ybWF0KG9zKTtcbiAgICB9XG4gICAgLy8gRGV0ZWN0IHByZXJlbGVhc2UgcGhhc2VzLlxuICAgIGlmICh2ZXJzaW9uICYmIChkYXRhID1cbiAgICAgICAgICAvKD86W2FiXXxkcHxwcmV8W2FiXVxcZCtwcmUpKD86XFxkK1xcKz8pPyQvaS5leGVjKHZlcnNpb24pIHx8XG4gICAgICAgICAgLyg/OmFscGhhfGJldGEpKD86ID9cXGQpPy9pLmV4ZWModWEgKyAnOycgKyAodXNlRmVhdHVyZXMgJiYgbmF2LmFwcE1pbm9yVmVyc2lvbikpIHx8XG4gICAgICAgICAgL1xcYk1pbmVmaWVsZFxcYi9pLnRlc3QodWEpICYmICdhJ1xuICAgICAgICApKSB7XG4gICAgICBwcmVyZWxlYXNlID0gL2IvaS50ZXN0KGRhdGEpID8gJ2JldGEnIDogJ2FscGhhJztcbiAgICAgIHZlcnNpb24gPSB2ZXJzaW9uLnJlcGxhY2UoUmVnRXhwKGRhdGEgKyAnXFxcXCs/JCcpLCAnJykgK1xuICAgICAgICAocHJlcmVsZWFzZSA9PSAnYmV0YScgPyBiZXRhIDogYWxwaGEpICsgKC9cXGQrXFwrPy8uZXhlYyhkYXRhKSB8fCAnJyk7XG4gICAgfVxuICAgIC8vIERldGVjdCBGaXJlZm94IE1vYmlsZS5cbiAgICBpZiAobmFtZSA9PSAnRmVubmVjJyB8fCBuYW1lID09ICdGaXJlZm94JyAmJiAvXFxiKD86QW5kcm9pZHxGaXJlZm94IE9TKVxcYi8udGVzdChvcykpIHtcbiAgICAgIG5hbWUgPSAnRmlyZWZveCBNb2JpbGUnO1xuICAgIH1cbiAgICAvLyBPYnNjdXJlIE1heHRob24ncyB1bnJlbGlhYmxlIHZlcnNpb24uXG4gICAgZWxzZSBpZiAobmFtZSA9PSAnTWF4dGhvbicgJiYgdmVyc2lvbikge1xuICAgICAgdmVyc2lvbiA9IHZlcnNpb24ucmVwbGFjZSgvXFwuW1xcZC5dKy8sICcueCcpO1xuICAgIH1cbiAgICAvLyBEZXRlY3QgWGJveCAzNjAgYW5kIFhib3ggT25lLlxuICAgIGVsc2UgaWYgKC9cXGJYYm94XFxiL2kudGVzdChwcm9kdWN0KSkge1xuICAgICAgaWYgKHByb2R1Y3QgPT0gJ1hib3ggMzYwJykge1xuICAgICAgICBvcyA9IG51bGw7XG4gICAgICB9XG4gICAgICBpZiAocHJvZHVjdCA9PSAnWGJveCAzNjAnICYmIC9cXGJJRU1vYmlsZVxcYi8udGVzdCh1YSkpIHtcbiAgICAgICAgZGVzY3JpcHRpb24udW5zaGlmdCgnbW9iaWxlIG1vZGUnKTtcbiAgICAgIH1cbiAgICB9XG4gICAgLy8gQWRkIG1vYmlsZSBwb3N0Zml4LlxuICAgIGVsc2UgaWYgKCgvXig/OkNocm9tZXxJRXxPcGVyYSkkLy50ZXN0KG5hbWUpIHx8IG5hbWUgJiYgIXByb2R1Y3QgJiYgIS9Ccm93c2VyfE1vYmkvLnRlc3QobmFtZSkpICYmXG4gICAgICAgIChvcyA9PSAnV2luZG93cyBDRScgfHwgL01vYmkvaS50ZXN0KHVhKSkpIHtcbiAgICAgIG5hbWUgKz0gJyBNb2JpbGUnO1xuICAgIH1cbiAgICAvLyBEZXRlY3QgSUUgcGxhdGZvcm0gcHJldmlldy5cbiAgICBlbHNlIGlmIChuYW1lID09ICdJRScgJiYgdXNlRmVhdHVyZXMpIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIGlmIChjb250ZXh0LmV4dGVybmFsID09PSBudWxsKSB7XG4gICAgICAgICAgZGVzY3JpcHRpb24udW5zaGlmdCgncGxhdGZvcm0gcHJldmlldycpO1xuICAgICAgICB9XG4gICAgICB9IGNhdGNoKGUpIHtcbiAgICAgICAgZGVzY3JpcHRpb24udW5zaGlmdCgnZW1iZWRkZWQnKTtcbiAgICAgIH1cbiAgICB9XG4gICAgLy8gRGV0ZWN0IEJsYWNrQmVycnkgT1MgdmVyc2lvbi5cbiAgICAvLyBodHRwOi8vZG9jcy5ibGFja2JlcnJ5LmNvbS9lbi9kZXZlbG9wZXJzL2RlbGl2ZXJhYmxlcy8xODE2OS9IVFRQX2hlYWRlcnNfc2VudF9ieV9CQl9Ccm93c2VyXzEyMzQ5MTFfMTEuanNwXG4gICAgZWxzZSBpZiAoKC9cXGJCbGFja0JlcnJ5XFxiLy50ZXN0KHByb2R1Y3QpIHx8IC9cXGJCQjEwXFxiLy50ZXN0KHVhKSkgJiYgKGRhdGEgPVxuICAgICAgICAgIChSZWdFeHAocHJvZHVjdC5yZXBsYWNlKC8gKy9nLCAnIConKSArICcvKFsuXFxcXGRdKyknLCAnaScpLmV4ZWModWEpIHx8IDApWzFdIHx8XG4gICAgICAgICAgdmVyc2lvblxuICAgICAgICApKSB7XG4gICAgICBkYXRhID0gW2RhdGEsIC9CQjEwLy50ZXN0KHVhKV07XG4gICAgICBvcyA9IChkYXRhWzFdID8gKHByb2R1Y3QgPSBudWxsLCBtYW51ZmFjdHVyZXIgPSAnQmxhY2tCZXJyeScpIDogJ0RldmljZSBTb2Z0d2FyZScpICsgJyAnICsgZGF0YVswXTtcbiAgICAgIHZlcnNpb24gPSBudWxsO1xuICAgIH1cbiAgICAvLyBEZXRlY3QgT3BlcmEgaWRlbnRpZnlpbmcvbWFza2luZyBpdHNlbGYgYXMgYW5vdGhlciBicm93c2VyLlxuICAgIC8vIGh0dHA6Ly93d3cub3BlcmEuY29tL3N1cHBvcnQva2Ivdmlldy84NDMvXG4gICAgZWxzZSBpZiAodGhpcyAhPSBmb3JPd24gJiYgcHJvZHVjdCAhPSAnV2lpJyAmJiAoXG4gICAgICAgICAgKHVzZUZlYXR1cmVzICYmIG9wZXJhKSB8fFxuICAgICAgICAgICgvT3BlcmEvLnRlc3QobmFtZSkgJiYgL1xcYig/Ok1TSUV8RmlyZWZveClcXGIvaS50ZXN0KHVhKSkgfHxcbiAgICAgICAgICAobmFtZSA9PSAnRmlyZWZveCcgJiYgL1xcYk9TIFggKD86XFxkK1xcLil7Mix9Ly50ZXN0KG9zKSkgfHxcbiAgICAgICAgICAobmFtZSA9PSAnSUUnICYmIChcbiAgICAgICAgICAgIChvcyAmJiAhL15XaW4vLnRlc3Qob3MpICYmIHZlcnNpb24gPiA1LjUpIHx8XG4gICAgICAgICAgICAvXFxiV2luZG93cyBYUFxcYi8udGVzdChvcykgJiYgdmVyc2lvbiA+IDggfHxcbiAgICAgICAgICAgIHZlcnNpb24gPT0gOCAmJiAhL1xcYlRyaWRlbnRcXGIvLnRlc3QodWEpXG4gICAgICAgICAgKSlcbiAgICAgICAgKSAmJiAhcmVPcGVyYS50ZXN0KChkYXRhID0gcGFyc2UuY2FsbChmb3JPd24sIHVhLnJlcGxhY2UocmVPcGVyYSwgJycpICsgJzsnKSkpICYmIGRhdGEubmFtZSkge1xuICAgICAgLy8gV2hlbiBcImlkZW50aWZ5aW5nXCIsIHRoZSBVQSBjb250YWlucyBib3RoIE9wZXJhIGFuZCB0aGUgb3RoZXIgYnJvd3NlcidzIG5hbWUuXG4gICAgICBkYXRhID0gJ2luZyBhcyAnICsgZGF0YS5uYW1lICsgKChkYXRhID0gZGF0YS52ZXJzaW9uKSA/ICcgJyArIGRhdGEgOiAnJyk7XG4gICAgICBpZiAocmVPcGVyYS50ZXN0KG5hbWUpKSB7XG4gICAgICAgIGlmICgvXFxiSUVcXGIvLnRlc3QoZGF0YSkgJiYgb3MgPT0gJ01hYyBPUycpIHtcbiAgICAgICAgICBvcyA9IG51bGw7XG4gICAgICAgIH1cbiAgICAgICAgZGF0YSA9ICdpZGVudGlmeScgKyBkYXRhO1xuICAgICAgfVxuICAgICAgLy8gV2hlbiBcIm1hc2tpbmdcIiwgdGhlIFVBIGNvbnRhaW5zIG9ubHkgdGhlIG90aGVyIGJyb3dzZXIncyBuYW1lLlxuICAgICAgZWxzZSB7XG4gICAgICAgIGRhdGEgPSAnbWFzaycgKyBkYXRhO1xuICAgICAgICBpZiAob3BlcmFDbGFzcykge1xuICAgICAgICAgIG5hbWUgPSBmb3JtYXQob3BlcmFDbGFzcy5yZXBsYWNlKC8oW2Etel0pKFtBLVpdKS9nLCAnJDEgJDInKSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgbmFtZSA9ICdPcGVyYSc7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKC9cXGJJRVxcYi8udGVzdChkYXRhKSkge1xuICAgICAgICAgIG9zID0gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIXVzZUZlYXR1cmVzKSB7XG4gICAgICAgICAgdmVyc2lvbiA9IG51bGw7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGxheW91dCA9IFsnUHJlc3RvJ107XG4gICAgICBkZXNjcmlwdGlvbi5wdXNoKGRhdGEpO1xuICAgIH1cbiAgICAvLyBEZXRlY3QgV2ViS2l0IE5pZ2h0bHkgYW5kIGFwcHJveGltYXRlIENocm9tZS9TYWZhcmkgdmVyc2lvbnMuXG4gICAgaWYgKChkYXRhID0gKC9cXGJBcHBsZVdlYktpdFxcLyhbXFxkLl0rXFwrPykvaS5leGVjKHVhKSB8fCAwKVsxXSkpIHtcbiAgICAgIC8vIENvcnJlY3QgYnVpbGQgbnVtYmVyIGZvciBudW1lcmljIGNvbXBhcmlzb24uXG4gICAgICAvLyAoZS5nLiBcIjUzMi41XCIgYmVjb21lcyBcIjUzMi4wNVwiKVxuICAgICAgZGF0YSA9IFtwYXJzZUZsb2F0KGRhdGEucmVwbGFjZSgvXFwuKFxcZCkkLywgJy4wJDEnKSksIGRhdGFdO1xuICAgICAgLy8gTmlnaHRseSBidWlsZHMgYXJlIHBvc3RmaXhlZCB3aXRoIGEgXCIrXCIuXG4gICAgICBpZiAobmFtZSA9PSAnU2FmYXJpJyAmJiBkYXRhWzFdLnNsaWNlKC0xKSA9PSAnKycpIHtcbiAgICAgICAgbmFtZSA9ICdXZWJLaXQgTmlnaHRseSc7XG4gICAgICAgIHByZXJlbGVhc2UgPSAnYWxwaGEnO1xuICAgICAgICB2ZXJzaW9uID0gZGF0YVsxXS5zbGljZSgwLCAtMSk7XG4gICAgICB9XG4gICAgICAvLyBDbGVhciBpbmNvcnJlY3QgYnJvd3NlciB2ZXJzaW9ucy5cbiAgICAgIGVsc2UgaWYgKHZlcnNpb24gPT0gZGF0YVsxXSB8fFxuICAgICAgICAgIHZlcnNpb24gPT0gKGRhdGFbMl0gPSAoL1xcYlNhZmFyaVxcLyhbXFxkLl0rXFwrPykvaS5leGVjKHVhKSB8fCAwKVsxXSkpIHtcbiAgICAgICAgdmVyc2lvbiA9IG51bGw7XG4gICAgICB9XG4gICAgICAvLyBVc2UgdGhlIGZ1bGwgQ2hyb21lIHZlcnNpb24gd2hlbiBhdmFpbGFibGUuXG4gICAgICBkYXRhWzFdID0gKC9cXGJDaHJvbWVcXC8oW1xcZC5dKykvaS5leGVjKHVhKSB8fCAwKVsxXTtcbiAgICAgIC8vIERldGVjdCBCbGluayBsYXlvdXQgZW5naW5lLlxuICAgICAgaWYgKGRhdGFbMF0gPT0gNTM3LjM2ICYmIGRhdGFbMl0gPT0gNTM3LjM2ICYmIHBhcnNlRmxvYXQoZGF0YVsxXSkgPj0gMjggJiYgbGF5b3V0ID09ICdXZWJLaXQnKSB7XG4gICAgICAgIGxheW91dCA9IFsnQmxpbmsnXTtcbiAgICAgIH1cbiAgICAgIC8vIERldGVjdCBKYXZhU2NyaXB0Q29yZS5cbiAgICAgIC8vIGh0dHA6Ly9zdGFja292ZXJmbG93LmNvbS9xdWVzdGlvbnMvNjc2ODQ3NC9ob3ctY2FuLWktZGV0ZWN0LXdoaWNoLWphdmFzY3JpcHQtZW5naW5lLXY4LW9yLWpzYy1pcy11c2VkLWF0LXJ1bnRpbWUtaW4tYW5kcm9pXG4gICAgICBpZiAoIXVzZUZlYXR1cmVzIHx8ICghbGlrZUNocm9tZSAmJiAhZGF0YVsxXSkpIHtcbiAgICAgICAgbGF5b3V0ICYmIChsYXlvdXRbMV0gPSAnbGlrZSBTYWZhcmknKTtcbiAgICAgICAgZGF0YSA9IChkYXRhID0gZGF0YVswXSwgZGF0YSA8IDQwMCA/IDEgOiBkYXRhIDwgNTAwID8gMiA6IGRhdGEgPCA1MjYgPyAzIDogZGF0YSA8IDUzMyA/IDQgOiBkYXRhIDwgNTM0ID8gJzQrJyA6IGRhdGEgPCA1MzUgPyA1IDogZGF0YSA8IDUzNyA/IDYgOiBkYXRhIDwgNTM4ID8gNyA6IGRhdGEgPCA2MDEgPyA4IDogJzgnKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGxheW91dCAmJiAobGF5b3V0WzFdID0gJ2xpa2UgQ2hyb21lJyk7XG4gICAgICAgIGRhdGEgPSBkYXRhWzFdIHx8IChkYXRhID0gZGF0YVswXSwgZGF0YSA8IDUzMCA/IDEgOiBkYXRhIDwgNTMyID8gMiA6IGRhdGEgPCA1MzIuMDUgPyAzIDogZGF0YSA8IDUzMyA/IDQgOiBkYXRhIDwgNTM0LjAzID8gNSA6IGRhdGEgPCA1MzQuMDcgPyA2IDogZGF0YSA8IDUzNC4xMCA/IDcgOiBkYXRhIDwgNTM0LjEzID8gOCA6IGRhdGEgPCA1MzQuMTYgPyA5IDogZGF0YSA8IDUzNC4yNCA/IDEwIDogZGF0YSA8IDUzNC4zMCA/IDExIDogZGF0YSA8IDUzNS4wMSA/IDEyIDogZGF0YSA8IDUzNS4wMiA/ICcxMysnIDogZGF0YSA8IDUzNS4wNyA/IDE1IDogZGF0YSA8IDUzNS4xMSA/IDE2IDogZGF0YSA8IDUzNS4xOSA/IDE3IDogZGF0YSA8IDUzNi4wNSA/IDE4IDogZGF0YSA8IDUzNi4xMCA/IDE5IDogZGF0YSA8IDUzNy4wMSA/IDIwIDogZGF0YSA8IDUzNy4xMSA/ICcyMSsnIDogZGF0YSA8IDUzNy4xMyA/IDIzIDogZGF0YSA8IDUzNy4xOCA/IDI0IDogZGF0YSA8IDUzNy4yNCA/IDI1IDogZGF0YSA8IDUzNy4zNiA/IDI2IDogbGF5b3V0ICE9ICdCbGluaycgPyAnMjcnIDogJzI4Jyk7XG4gICAgICB9XG4gICAgICAvLyBBZGQgdGhlIHBvc3RmaXggb2YgXCIueFwiIG9yIFwiK1wiIGZvciBhcHByb3hpbWF0ZSB2ZXJzaW9ucy5cbiAgICAgIGxheW91dCAmJiAobGF5b3V0WzFdICs9ICcgJyArIChkYXRhICs9IHR5cGVvZiBkYXRhID09ICdudW1iZXInID8gJy54JyA6IC9bLitdLy50ZXN0KGRhdGEpID8gJycgOiAnKycpKTtcbiAgICAgIC8vIE9ic2N1cmUgdmVyc2lvbiBmb3Igc29tZSBTYWZhcmkgMS0yIHJlbGVhc2VzLlxuICAgICAgaWYgKG5hbWUgPT0gJ1NhZmFyaScgJiYgKCF2ZXJzaW9uIHx8IHBhcnNlSW50KHZlcnNpb24pID4gNDUpKSB7XG4gICAgICAgIHZlcnNpb24gPSBkYXRhO1xuICAgICAgfVxuICAgIH1cbiAgICAvLyBEZXRlY3QgT3BlcmEgZGVza3RvcCBtb2Rlcy5cbiAgICBpZiAobmFtZSA9PSAnT3BlcmEnICYmICAoZGF0YSA9IC9cXGJ6Ym92fHp2YXYkLy5leGVjKG9zKSkpIHtcbiAgICAgIG5hbWUgKz0gJyAnO1xuICAgICAgZGVzY3JpcHRpb24udW5zaGlmdCgnZGVza3RvcCBtb2RlJyk7XG4gICAgICBpZiAoZGF0YSA9PSAnenZhdicpIHtcbiAgICAgICAgbmFtZSArPSAnTWluaSc7XG4gICAgICAgIHZlcnNpb24gPSBudWxsO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbmFtZSArPSAnTW9iaWxlJztcbiAgICAgIH1cbiAgICAgIG9zID0gb3MucmVwbGFjZShSZWdFeHAoJyAqJyArIGRhdGEgKyAnJCcpLCAnJyk7XG4gICAgfVxuICAgIC8vIERldGVjdCBDaHJvbWUgZGVza3RvcCBtb2RlLlxuICAgIGVsc2UgaWYgKG5hbWUgPT0gJ1NhZmFyaScgJiYgL1xcYkNocm9tZVxcYi8uZXhlYyhsYXlvdXQgJiYgbGF5b3V0WzFdKSkge1xuICAgICAgZGVzY3JpcHRpb24udW5zaGlmdCgnZGVza3RvcCBtb2RlJyk7XG4gICAgICBuYW1lID0gJ0Nocm9tZSBNb2JpbGUnO1xuICAgICAgdmVyc2lvbiA9IG51bGw7XG5cbiAgICAgIGlmICgvXFxiT1MgWFxcYi8udGVzdChvcykpIHtcbiAgICAgICAgbWFudWZhY3R1cmVyID0gJ0FwcGxlJztcbiAgICAgICAgb3MgPSAnaU9TIDQuMysnO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgb3MgPSBudWxsO1xuICAgICAgfVxuICAgIH1cbiAgICAvLyBTdHJpcCBpbmNvcnJlY3QgT1MgdmVyc2lvbnMuXG4gICAgaWYgKHZlcnNpb24gJiYgdmVyc2lvbi5pbmRleE9mKChkYXRhID0gL1tcXGQuXSskLy5leGVjKG9zKSkpID09IDAgJiZcbiAgICAgICAgdWEuaW5kZXhPZignLycgKyBkYXRhICsgJy0nKSA+IC0xKSB7XG4gICAgICBvcyA9IHRyaW0ob3MucmVwbGFjZShkYXRhLCAnJykpO1xuICAgIH1cbiAgICAvLyBBZGQgbGF5b3V0IGVuZ2luZS5cbiAgICBpZiAobGF5b3V0ICYmICEvXFxiKD86QXZhbnR8Tm9vaylcXGIvLnRlc3QobmFtZSkgJiYgKFxuICAgICAgICAvQnJvd3NlcnxMdW5hc2NhcGV8TWF4dGhvbi8udGVzdChuYW1lKSB8fFxuICAgICAgICBuYW1lICE9ICdTYWZhcmknICYmIC9eaU9TLy50ZXN0KG9zKSAmJiAvXFxiU2FmYXJpXFxiLy50ZXN0KGxheW91dFsxXSkgfHxcbiAgICAgICAgL14oPzpBZG9iZXxBcm9yYXxCcmVhY2h8TWlkb3JpfE9wZXJhfFBoYW50b218UmVrb25xfFJvY2t8U2Ftc3VuZyBJbnRlcm5ldHxTbGVpcG5pcnxXZWIpLy50ZXN0KG5hbWUpICYmIGxheW91dFsxXSkpIHtcbiAgICAgIC8vIERvbid0IGFkZCBsYXlvdXQgZGV0YWlscyB0byBkZXNjcmlwdGlvbiBpZiB0aGV5IGFyZSBmYWxzZXkuXG4gICAgICAoZGF0YSA9IGxheW91dFtsYXlvdXQubGVuZ3RoIC0gMV0pICYmIGRlc2NyaXB0aW9uLnB1c2goZGF0YSk7XG4gICAgfVxuICAgIC8vIENvbWJpbmUgY29udGV4dHVhbCBpbmZvcm1hdGlvbi5cbiAgICBpZiAoZGVzY3JpcHRpb24ubGVuZ3RoKSB7XG4gICAgICBkZXNjcmlwdGlvbiA9IFsnKCcgKyBkZXNjcmlwdGlvbi5qb2luKCc7ICcpICsgJyknXTtcbiAgICB9XG4gICAgLy8gQXBwZW5kIG1hbnVmYWN0dXJlciB0byBkZXNjcmlwdGlvbi5cbiAgICBpZiAobWFudWZhY3R1cmVyICYmIHByb2R1Y3QgJiYgcHJvZHVjdC5pbmRleE9mKG1hbnVmYWN0dXJlcikgPCAwKSB7XG4gICAgICBkZXNjcmlwdGlvbi5wdXNoKCdvbiAnICsgbWFudWZhY3R1cmVyKTtcbiAgICB9XG4gICAgLy8gQXBwZW5kIHByb2R1Y3QgdG8gZGVzY3JpcHRpb24uXG4gICAgaWYgKHByb2R1Y3QpIHtcbiAgICAgIGRlc2NyaXB0aW9uLnB1c2goKC9eb24gLy50ZXN0KGRlc2NyaXB0aW9uW2Rlc2NyaXB0aW9uLmxlbmd0aCAtIDFdKSA/ICcnIDogJ29uICcpICsgcHJvZHVjdCk7XG4gICAgfVxuICAgIC8vIFBhcnNlIHRoZSBPUyBpbnRvIGFuIG9iamVjdC5cbiAgICBpZiAob3MpIHtcbiAgICAgIGRhdGEgPSAvIChbXFxkLitdKykkLy5leGVjKG9zKTtcbiAgICAgIGlzU3BlY2lhbENhc2VkT1MgPSBkYXRhICYmIG9zLmNoYXJBdChvcy5sZW5ndGggLSBkYXRhWzBdLmxlbmd0aCAtIDEpID09ICcvJztcbiAgICAgIG9zID0ge1xuICAgICAgICAnYXJjaGl0ZWN0dXJlJzogMzIsXG4gICAgICAgICdmYW1pbHknOiAoZGF0YSAmJiAhaXNTcGVjaWFsQ2FzZWRPUykgPyBvcy5yZXBsYWNlKGRhdGFbMF0sICcnKSA6IG9zLFxuICAgICAgICAndmVyc2lvbic6IGRhdGEgPyBkYXRhWzFdIDogbnVsbCxcbiAgICAgICAgJ3RvU3RyaW5nJzogZnVuY3Rpb24oKSB7XG4gICAgICAgICAgdmFyIHZlcnNpb24gPSB0aGlzLnZlcnNpb247XG4gICAgICAgICAgcmV0dXJuIHRoaXMuZmFtaWx5ICsgKCh2ZXJzaW9uICYmICFpc1NwZWNpYWxDYXNlZE9TKSA/ICcgJyArIHZlcnNpb24gOiAnJykgKyAodGhpcy5hcmNoaXRlY3R1cmUgPT0gNjQgPyAnIDY0LWJpdCcgOiAnJyk7XG4gICAgICAgIH1cbiAgICAgIH07XG4gICAgfVxuICAgIC8vIEFkZCBicm93c2VyL09TIGFyY2hpdGVjdHVyZS5cbiAgICBpZiAoKGRhdGEgPSAvXFxiKD86QU1EfElBfFdpbnxXT1d8eDg2X3x4KTY0XFxiL2kuZXhlYyhhcmNoKSkgJiYgIS9cXGJpNjg2XFxiL2kudGVzdChhcmNoKSkge1xuICAgICAgaWYgKG9zKSB7XG4gICAgICAgIG9zLmFyY2hpdGVjdHVyZSA9IDY0O1xuICAgICAgICBvcy5mYW1pbHkgPSBvcy5mYW1pbHkucmVwbGFjZShSZWdFeHAoJyAqJyArIGRhdGEpLCAnJyk7XG4gICAgICB9XG4gICAgICBpZiAoXG4gICAgICAgICAgbmFtZSAmJiAoL1xcYldPVzY0XFxiL2kudGVzdCh1YSkgfHxcbiAgICAgICAgICAodXNlRmVhdHVyZXMgJiYgL1xcdyg/Ojg2fDMyKSQvLnRlc3QobmF2LmNwdUNsYXNzIHx8IG5hdi5wbGF0Zm9ybSkgJiYgIS9cXGJXaW42NDsgeDY0XFxiL2kudGVzdCh1YSkpKVxuICAgICAgKSB7XG4gICAgICAgIGRlc2NyaXB0aW9uLnVuc2hpZnQoJzMyLWJpdCcpO1xuICAgICAgfVxuICAgIH1cbiAgICAvLyBDaHJvbWUgMzkgYW5kIGFib3ZlIG9uIE9TIFggaXMgYWx3YXlzIDY0LWJpdC5cbiAgICBlbHNlIGlmIChcbiAgICAgICAgb3MgJiYgL15PUyBYLy50ZXN0KG9zLmZhbWlseSkgJiZcbiAgICAgICAgbmFtZSA9PSAnQ2hyb21lJyAmJiBwYXJzZUZsb2F0KHZlcnNpb24pID49IDM5XG4gICAgKSB7XG4gICAgICBvcy5hcmNoaXRlY3R1cmUgPSA2NDtcbiAgICB9XG5cbiAgICB1YSB8fCAodWEgPSBudWxsKTtcblxuICAgIC8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cblxuICAgIC8qKlxuICAgICAqIFRoZSBwbGF0Zm9ybSBvYmplY3QuXG4gICAgICpcbiAgICAgKiBAbmFtZSBwbGF0Zm9ybVxuICAgICAqIEB0eXBlIE9iamVjdFxuICAgICAqL1xuICAgIHZhciBwbGF0Zm9ybSA9IHt9O1xuXG4gICAgLyoqXG4gICAgICogVGhlIHBsYXRmb3JtIGRlc2NyaXB0aW9uLlxuICAgICAqXG4gICAgICogQG1lbWJlck9mIHBsYXRmb3JtXG4gICAgICogQHR5cGUgc3RyaW5nfG51bGxcbiAgICAgKi9cbiAgICBwbGF0Zm9ybS5kZXNjcmlwdGlvbiA9IHVhO1xuXG4gICAgLyoqXG4gICAgICogVGhlIG5hbWUgb2YgdGhlIGJyb3dzZXIncyBsYXlvdXQgZW5naW5lLlxuICAgICAqXG4gICAgICogVGhlIGxpc3Qgb2YgY29tbW9uIGxheW91dCBlbmdpbmVzIGluY2x1ZGU6XG4gICAgICogXCJCbGlua1wiLCBcIkVkZ2VIVE1MXCIsIFwiR2Vja29cIiwgXCJUcmlkZW50XCIgYW5kIFwiV2ViS2l0XCJcbiAgICAgKlxuICAgICAqIEBtZW1iZXJPZiBwbGF0Zm9ybVxuICAgICAqIEB0eXBlIHN0cmluZ3xudWxsXG4gICAgICovXG4gICAgcGxhdGZvcm0ubGF5b3V0ID0gbGF5b3V0ICYmIGxheW91dFswXTtcblxuICAgIC8qKlxuICAgICAqIFRoZSBuYW1lIG9mIHRoZSBwcm9kdWN0J3MgbWFudWZhY3R1cmVyLlxuICAgICAqXG4gICAgICogVGhlIGxpc3Qgb2YgbWFudWZhY3R1cmVycyBpbmNsdWRlOlxuICAgICAqIFwiQXBwbGVcIiwgXCJBcmNob3NcIiwgXCJBbWF6b25cIiwgXCJBc3VzXCIsIFwiQmFybmVzICYgTm9ibGVcIiwgXCJCbGFja0JlcnJ5XCIsXG4gICAgICogXCJHb29nbGVcIiwgXCJIUFwiLCBcIkhUQ1wiLCBcIkxHXCIsIFwiTWljcm9zb2Z0XCIsIFwiTW90b3JvbGFcIiwgXCJOaW50ZW5kb1wiLFxuICAgICAqIFwiTm9raWFcIiwgXCJTYW1zdW5nXCIgYW5kIFwiU29ueVwiXG4gICAgICpcbiAgICAgKiBAbWVtYmVyT2YgcGxhdGZvcm1cbiAgICAgKiBAdHlwZSBzdHJpbmd8bnVsbFxuICAgICAqL1xuICAgIHBsYXRmb3JtLm1hbnVmYWN0dXJlciA9IG1hbnVmYWN0dXJlcjtcblxuICAgIC8qKlxuICAgICAqIFRoZSBuYW1lIG9mIHRoZSBicm93c2VyL2Vudmlyb25tZW50LlxuICAgICAqXG4gICAgICogVGhlIGxpc3Qgb2YgY29tbW9uIGJyb3dzZXIgbmFtZXMgaW5jbHVkZTpcbiAgICAgKiBcIkNocm9tZVwiLCBcIkVsZWN0cm9uXCIsIFwiRmlyZWZveFwiLCBcIkZpcmVmb3ggZm9yIGlPU1wiLCBcIklFXCIsXG4gICAgICogXCJNaWNyb3NvZnQgRWRnZVwiLCBcIlBoYW50b21KU1wiLCBcIlNhZmFyaVwiLCBcIlNlYU1vbmtleVwiLCBcIlNpbGtcIixcbiAgICAgKiBcIk9wZXJhIE1pbmlcIiBhbmQgXCJPcGVyYVwiXG4gICAgICpcbiAgICAgKiBNb2JpbGUgdmVyc2lvbnMgb2Ygc29tZSBicm93c2VycyBoYXZlIFwiTW9iaWxlXCIgYXBwZW5kZWQgdG8gdGhlaXIgbmFtZTpcbiAgICAgKiBlZy4gXCJDaHJvbWUgTW9iaWxlXCIsIFwiRmlyZWZveCBNb2JpbGVcIiwgXCJJRSBNb2JpbGVcIiBhbmQgXCJPcGVyYSBNb2JpbGVcIlxuICAgICAqXG4gICAgICogQG1lbWJlck9mIHBsYXRmb3JtXG4gICAgICogQHR5cGUgc3RyaW5nfG51bGxcbiAgICAgKi9cbiAgICBwbGF0Zm9ybS5uYW1lID0gbmFtZTtcblxuICAgIC8qKlxuICAgICAqIFRoZSBhbHBoYS9iZXRhIHJlbGVhc2UgaW5kaWNhdG9yLlxuICAgICAqXG4gICAgICogQG1lbWJlck9mIHBsYXRmb3JtXG4gICAgICogQHR5cGUgc3RyaW5nfG51bGxcbiAgICAgKi9cbiAgICBwbGF0Zm9ybS5wcmVyZWxlYXNlID0gcHJlcmVsZWFzZTtcblxuICAgIC8qKlxuICAgICAqIFRoZSBuYW1lIG9mIHRoZSBwcm9kdWN0IGhvc3RpbmcgdGhlIGJyb3dzZXIuXG4gICAgICpcbiAgICAgKiBUaGUgbGlzdCBvZiBjb21tb24gcHJvZHVjdHMgaW5jbHVkZTpcbiAgICAgKlxuICAgICAqIFwiQmxhY2tCZXJyeVwiLCBcIkdhbGF4eSBTNFwiLCBcIkx1bWlhXCIsIFwiaVBhZFwiLCBcImlQb2RcIiwgXCJpUGhvbmVcIiwgXCJLaW5kbGVcIixcbiAgICAgKiBcIktpbmRsZSBGaXJlXCIsIFwiTmV4dXNcIiwgXCJOb29rXCIsIFwiUGxheUJvb2tcIiwgXCJUb3VjaFBhZFwiIGFuZCBcIlRyYW5zZm9ybWVyXCJcbiAgICAgKlxuICAgICAqIEBtZW1iZXJPZiBwbGF0Zm9ybVxuICAgICAqIEB0eXBlIHN0cmluZ3xudWxsXG4gICAgICovXG4gICAgcGxhdGZvcm0ucHJvZHVjdCA9IHByb2R1Y3Q7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYnJvd3NlcidzIHVzZXIgYWdlbnQgc3RyaW5nLlxuICAgICAqXG4gICAgICogQG1lbWJlck9mIHBsYXRmb3JtXG4gICAgICogQHR5cGUgc3RyaW5nfG51bGxcbiAgICAgKi9cbiAgICBwbGF0Zm9ybS51YSA9IHVhO1xuXG4gICAgLyoqXG4gICAgICogVGhlIGJyb3dzZXIvZW52aXJvbm1lbnQgdmVyc2lvbi5cbiAgICAgKlxuICAgICAqIEBtZW1iZXJPZiBwbGF0Zm9ybVxuICAgICAqIEB0eXBlIHN0cmluZ3xudWxsXG4gICAgICovXG4gICAgcGxhdGZvcm0udmVyc2lvbiA9IG5hbWUgJiYgdmVyc2lvbjtcblxuICAgIC8qKlxuICAgICAqIFRoZSBuYW1lIG9mIHRoZSBvcGVyYXRpbmcgc3lzdGVtLlxuICAgICAqXG4gICAgICogQG1lbWJlck9mIHBsYXRmb3JtXG4gICAgICogQHR5cGUgT2JqZWN0XG4gICAgICovXG4gICAgcGxhdGZvcm0ub3MgPSBvcyB8fCB7XG5cbiAgICAgIC8qKlxuICAgICAgICogVGhlIENQVSBhcmNoaXRlY3R1cmUgdGhlIE9TIGlzIGJ1aWx0IGZvci5cbiAgICAgICAqXG4gICAgICAgKiBAbWVtYmVyT2YgcGxhdGZvcm0ub3NcbiAgICAgICAqIEB0eXBlIG51bWJlcnxudWxsXG4gICAgICAgKi9cbiAgICAgICdhcmNoaXRlY3R1cmUnOiBudWxsLFxuXG4gICAgICAvKipcbiAgICAgICAqIFRoZSBmYW1pbHkgb2YgdGhlIE9TLlxuICAgICAgICpcbiAgICAgICAqIENvbW1vbiB2YWx1ZXMgaW5jbHVkZTpcbiAgICAgICAqIFwiV2luZG93c1wiLCBcIldpbmRvd3MgU2VydmVyIDIwMDggUjIgLyA3XCIsIFwiV2luZG93cyBTZXJ2ZXIgMjAwOCAvIFZpc3RhXCIsXG4gICAgICAgKiBcIldpbmRvd3MgWFBcIiwgXCJPUyBYXCIsIFwiVWJ1bnR1XCIsIFwiRGViaWFuXCIsIFwiRmVkb3JhXCIsIFwiUmVkIEhhdFwiLCBcIlN1U0VcIixcbiAgICAgICAqIFwiQW5kcm9pZFwiLCBcImlPU1wiIGFuZCBcIldpbmRvd3MgUGhvbmVcIlxuICAgICAgICpcbiAgICAgICAqIEBtZW1iZXJPZiBwbGF0Zm9ybS5vc1xuICAgICAgICogQHR5cGUgc3RyaW5nfG51bGxcbiAgICAgICAqL1xuICAgICAgJ2ZhbWlseSc6IG51bGwsXG5cbiAgICAgIC8qKlxuICAgICAgICogVGhlIHZlcnNpb24gb2YgdGhlIE9TLlxuICAgICAgICpcbiAgICAgICAqIEBtZW1iZXJPZiBwbGF0Zm9ybS5vc1xuICAgICAgICogQHR5cGUgc3RyaW5nfG51bGxcbiAgICAgICAqL1xuICAgICAgJ3ZlcnNpb24nOiBudWxsLFxuXG4gICAgICAvKipcbiAgICAgICAqIFJldHVybnMgdGhlIE9TIHN0cmluZy5cbiAgICAgICAqXG4gICAgICAgKiBAbWVtYmVyT2YgcGxhdGZvcm0ub3NcbiAgICAgICAqIEByZXR1cm5zIHtzdHJpbmd9IFRoZSBPUyBzdHJpbmcuXG4gICAgICAgKi9cbiAgICAgICd0b1N0cmluZyc6IGZ1bmN0aW9uKCkgeyByZXR1cm4gJ251bGwnOyB9XG4gICAgfTtcblxuICAgIHBsYXRmb3JtLnBhcnNlID0gcGFyc2U7XG4gICAgcGxhdGZvcm0udG9TdHJpbmcgPSB0b1N0cmluZ1BsYXRmb3JtO1xuXG4gICAgaWYgKHBsYXRmb3JtLnZlcnNpb24pIHtcbiAgICAgIGRlc2NyaXB0aW9uLnVuc2hpZnQodmVyc2lvbik7XG4gICAgfVxuICAgIGlmIChwbGF0Zm9ybS5uYW1lKSB7XG4gICAgICBkZXNjcmlwdGlvbi51bnNoaWZ0KG5hbWUpO1xuICAgIH1cbiAgICBpZiAob3MgJiYgbmFtZSAmJiAhKG9zID09IFN0cmluZyhvcykuc3BsaXQoJyAnKVswXSAmJiAob3MgPT0gbmFtZS5zcGxpdCgnICcpWzBdIHx8IHByb2R1Y3QpKSkge1xuICAgICAgZGVzY3JpcHRpb24ucHVzaChwcm9kdWN0ID8gJygnICsgb3MgKyAnKScgOiAnb24gJyArIG9zKTtcbiAgICB9XG4gICAgaWYgKGRlc2NyaXB0aW9uLmxlbmd0aCkge1xuICAgICAgcGxhdGZvcm0uZGVzY3JpcHRpb24gPSBkZXNjcmlwdGlvbi5qb2luKCcgJyk7XG4gICAgfVxuICAgIHJldHVybiBwbGF0Zm9ybTtcbiAgfVxuXG4gIC8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuXG4gIC8vIEV4cG9ydCBwbGF0Zm9ybS5cbiAgdmFyIHBsYXRmb3JtID0gcGFyc2UoKTtcblxuICAvLyBTb21lIEFNRCBidWlsZCBvcHRpbWl6ZXJzLCBsaWtlIHIuanMsIGNoZWNrIGZvciBjb25kaXRpb24gcGF0dGVybnMgbGlrZSB0aGUgZm9sbG93aW5nOlxuICBpZiAodHlwZW9mIGRlZmluZSA9PSAnZnVuY3Rpb24nICYmIHR5cGVvZiBkZWZpbmUuYW1kID09ICdvYmplY3QnICYmIGRlZmluZS5hbWQpIHtcbiAgICAvLyBFeHBvc2UgcGxhdGZvcm0gb24gdGhlIGdsb2JhbCBvYmplY3QgdG8gcHJldmVudCBlcnJvcnMgd2hlbiBwbGF0Zm9ybSBpc1xuICAgIC8vIGxvYWRlZCBieSBhIHNjcmlwdCB0YWcgaW4gdGhlIHByZXNlbmNlIG9mIGFuIEFNRCBsb2FkZXIuXG4gICAgLy8gU2VlIGh0dHA6Ly9yZXF1aXJlanMub3JnL2RvY3MvZXJyb3JzLmh0bWwjbWlzbWF0Y2ggZm9yIG1vcmUgZGV0YWlscy5cbiAgICByb290LnBsYXRmb3JtID0gcGxhdGZvcm07XG5cbiAgICAvLyBEZWZpbmUgYXMgYW4gYW5vbnltb3VzIG1vZHVsZSBzbyBwbGF0Zm9ybSBjYW4gYmUgYWxpYXNlZCB0aHJvdWdoIHBhdGggbWFwcGluZy5cbiAgICBkZWZpbmUoZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4gcGxhdGZvcm07XG4gICAgfSk7XG4gIH1cbiAgLy8gQ2hlY2sgZm9yIGBleHBvcnRzYCBhZnRlciBgZGVmaW5lYCBpbiBjYXNlIGEgYnVpbGQgb3B0aW1pemVyIGFkZHMgYW4gYGV4cG9ydHNgIG9iamVjdC5cbiAgZWxzZSBpZiAoZnJlZUV4cG9ydHMgJiYgZnJlZU1vZHVsZSkge1xuICAgIC8vIEV4cG9ydCBmb3IgQ29tbW9uSlMgc3VwcG9ydC5cbiAgICBmb3JPd24ocGxhdGZvcm0sIGZ1bmN0aW9uKHZhbHVlLCBrZXkpIHtcbiAgICAgIGZyZWVFeHBvcnRzW2tleV0gPSB2YWx1ZTtcbiAgICB9KTtcbiAgfVxuICBlbHNlIHtcbiAgICAvLyBFeHBvcnQgdG8gdGhlIGdsb2JhbCBvYmplY3QuXG4gICAgcm9vdC5wbGF0Zm9ybSA9IHBsYXRmb3JtO1xuICB9XG59LmNhbGwodGhpcykpO1xuIiwidmFyIHYxID0gcmVxdWlyZSgnLi92MScpO1xudmFyIHY0ID0gcmVxdWlyZSgnLi92NCcpO1xuXG52YXIgdXVpZCA9IHY0O1xudXVpZC52MSA9IHYxO1xudXVpZC52NCA9IHY0O1xuXG5tb2R1bGUuZXhwb3J0cyA9IHV1aWQ7XG4iLCIvKipcbiAqIENvbnZlcnQgYXJyYXkgb2YgMTYgYnl0ZSB2YWx1ZXMgdG8gVVVJRCBzdHJpbmcgZm9ybWF0IG9mIHRoZSBmb3JtOlxuICogWFhYWFhYWFgtWFhYWC1YWFhYLVhYWFgtWFhYWFhYWFhYWFhYXG4gKi9cbnZhciBieXRlVG9IZXggPSBbXTtcbmZvciAodmFyIGkgPSAwOyBpIDwgMjU2OyArK2kpIHtcbiAgYnl0ZVRvSGV4W2ldID0gKGkgKyAweDEwMCkudG9TdHJpbmcoMTYpLnN1YnN0cigxKTtcbn1cblxuZnVuY3Rpb24gYnl0ZXNUb1V1aWQoYnVmLCBvZmZzZXQpIHtcbiAgdmFyIGkgPSBvZmZzZXQgfHwgMDtcbiAgdmFyIGJ0aCA9IGJ5dGVUb0hleDtcbiAgLy8gam9pbiB1c2VkIHRvIGZpeCBtZW1vcnkgaXNzdWUgY2F1c2VkIGJ5IGNvbmNhdGVuYXRpb246IGh0dHBzOi8vYnVncy5jaHJvbWl1bS5vcmcvcC92OC9pc3N1ZXMvZGV0YWlsP2lkPTMxNzUjYzRcbiAgcmV0dXJuIChbYnRoW2J1ZltpKytdXSwgYnRoW2J1ZltpKytdXSwgXG5cdGJ0aFtidWZbaSsrXV0sIGJ0aFtidWZbaSsrXV0sICctJyxcblx0YnRoW2J1ZltpKytdXSwgYnRoW2J1ZltpKytdXSwgJy0nLFxuXHRidGhbYnVmW2krK11dLCBidGhbYnVmW2krK11dLCAnLScsXG5cdGJ0aFtidWZbaSsrXV0sIGJ0aFtidWZbaSsrXV0sICctJyxcblx0YnRoW2J1ZltpKytdXSwgYnRoW2J1ZltpKytdXSxcblx0YnRoW2J1ZltpKytdXSwgYnRoW2J1ZltpKytdXSxcblx0YnRoW2J1ZltpKytdXSwgYnRoW2J1ZltpKytdXV0pLmpvaW4oJycpO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGJ5dGVzVG9VdWlkO1xuIiwiLy8gVW5pcXVlIElEIGNyZWF0aW9uIHJlcXVpcmVzIGEgaGlnaCBxdWFsaXR5IHJhbmRvbSAjIGdlbmVyYXRvci4gIEluIHRoZVxuLy8gYnJvd3NlciB0aGlzIGlzIGEgbGl0dGxlIGNvbXBsaWNhdGVkIGR1ZSB0byB1bmtub3duIHF1YWxpdHkgb2YgTWF0aC5yYW5kb20oKVxuLy8gYW5kIGluY29uc2lzdGVudCBzdXBwb3J0IGZvciB0aGUgYGNyeXB0b2AgQVBJLiAgV2UgZG8gdGhlIGJlc3Qgd2UgY2FuIHZpYVxuLy8gZmVhdHVyZS1kZXRlY3Rpb25cblxuLy8gZ2V0UmFuZG9tVmFsdWVzIG5lZWRzIHRvIGJlIGludm9rZWQgaW4gYSBjb250ZXh0IHdoZXJlIFwidGhpc1wiIGlzIGEgQ3J5cHRvXG4vLyBpbXBsZW1lbnRhdGlvbi4gQWxzbywgZmluZCB0aGUgY29tcGxldGUgaW1wbGVtZW50YXRpb24gb2YgY3J5cHRvIG9uIElFMTEuXG52YXIgZ2V0UmFuZG9tVmFsdWVzID0gKHR5cGVvZihjcnlwdG8pICE9ICd1bmRlZmluZWQnICYmIGNyeXB0by5nZXRSYW5kb21WYWx1ZXMgJiYgY3J5cHRvLmdldFJhbmRvbVZhbHVlcy5iaW5kKGNyeXB0bykpIHx8XG4gICAgICAgICAgICAgICAgICAgICAgKHR5cGVvZihtc0NyeXB0bykgIT0gJ3VuZGVmaW5lZCcgJiYgdHlwZW9mIHdpbmRvdy5tc0NyeXB0by5nZXRSYW5kb21WYWx1ZXMgPT0gJ2Z1bmN0aW9uJyAmJiBtc0NyeXB0by5nZXRSYW5kb21WYWx1ZXMuYmluZChtc0NyeXB0bykpO1xuXG5pZiAoZ2V0UmFuZG9tVmFsdWVzKSB7XG4gIC8vIFdIQVRXRyBjcnlwdG8gUk5HIC0gaHR0cDovL3dpa2kud2hhdHdnLm9yZy93aWtpL0NyeXB0b1xuICB2YXIgcm5kczggPSBuZXcgVWludDhBcnJheSgxNik7IC8vIGVzbGludC1kaXNhYmxlLWxpbmUgbm8tdW5kZWZcblxuICBtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHdoYXR3Z1JORygpIHtcbiAgICBnZXRSYW5kb21WYWx1ZXMocm5kczgpO1xuICAgIHJldHVybiBybmRzODtcbiAgfTtcbn0gZWxzZSB7XG4gIC8vIE1hdGgucmFuZG9tKCktYmFzZWQgKFJORylcbiAgLy9cbiAgLy8gSWYgYWxsIGVsc2UgZmFpbHMsIHVzZSBNYXRoLnJhbmRvbSgpLiAgSXQncyBmYXN0LCBidXQgaXMgb2YgdW5zcGVjaWZpZWRcbiAgLy8gcXVhbGl0eS5cbiAgdmFyIHJuZHMgPSBuZXcgQXJyYXkoMTYpO1xuXG4gIG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gbWF0aFJORygpIHtcbiAgICBmb3IgKHZhciBpID0gMCwgcjsgaSA8IDE2OyBpKyspIHtcbiAgICAgIGlmICgoaSAmIDB4MDMpID09PSAwKSByID0gTWF0aC5yYW5kb20oKSAqIDB4MTAwMDAwMDAwO1xuICAgICAgcm5kc1tpXSA9IHIgPj4+ICgoaSAmIDB4MDMpIDw8IDMpICYgMHhmZjtcbiAgICB9XG5cbiAgICByZXR1cm4gcm5kcztcbiAgfTtcbn1cbiIsInZhciBybmcgPSByZXF1aXJlKCcuL2xpYi9ybmcnKTtcbnZhciBieXRlc1RvVXVpZCA9IHJlcXVpcmUoJy4vbGliL2J5dGVzVG9VdWlkJyk7XG5cbi8vICoqYHYxKClgIC0gR2VuZXJhdGUgdGltZS1iYXNlZCBVVUlEKipcbi8vXG4vLyBJbnNwaXJlZCBieSBodHRwczovL2dpdGh1Yi5jb20vTGlvc0svVVVJRC5qc1xuLy8gYW5kIGh0dHA6Ly9kb2NzLnB5dGhvbi5vcmcvbGlicmFyeS91dWlkLmh0bWxcblxudmFyIF9ub2RlSWQ7XG52YXIgX2Nsb2Nrc2VxO1xuXG4vLyBQcmV2aW91cyB1dWlkIGNyZWF0aW9uIHRpbWVcbnZhciBfbGFzdE1TZWNzID0gMDtcbnZhciBfbGFzdE5TZWNzID0gMDtcblxuLy8gU2VlIGh0dHBzOi8vZ2l0aHViLmNvbS9icm9vZmEvbm9kZS11dWlkIGZvciBBUEkgZGV0YWlsc1xuZnVuY3Rpb24gdjEob3B0aW9ucywgYnVmLCBvZmZzZXQpIHtcbiAgdmFyIGkgPSBidWYgJiYgb2Zmc2V0IHx8IDA7XG4gIHZhciBiID0gYnVmIHx8IFtdO1xuXG4gIG9wdGlvbnMgPSBvcHRpb25zIHx8IHt9O1xuICB2YXIgbm9kZSA9IG9wdGlvbnMubm9kZSB8fCBfbm9kZUlkO1xuICB2YXIgY2xvY2tzZXEgPSBvcHRpb25zLmNsb2Nrc2VxICE9PSB1bmRlZmluZWQgPyBvcHRpb25zLmNsb2Nrc2VxIDogX2Nsb2Nrc2VxO1xuXG4gIC8vIG5vZGUgYW5kIGNsb2Nrc2VxIG5lZWQgdG8gYmUgaW5pdGlhbGl6ZWQgdG8gcmFuZG9tIHZhbHVlcyBpZiB0aGV5J3JlIG5vdFxuICAvLyBzcGVjaWZpZWQuICBXZSBkbyB0aGlzIGxhemlseSB0byBtaW5pbWl6ZSBpc3N1ZXMgcmVsYXRlZCB0byBpbnN1ZmZpY2llbnRcbiAgLy8gc3lzdGVtIGVudHJvcHkuICBTZWUgIzE4OVxuICBpZiAobm9kZSA9PSBudWxsIHx8IGNsb2Nrc2VxID09IG51bGwpIHtcbiAgICB2YXIgc2VlZEJ5dGVzID0gcm5nKCk7XG4gICAgaWYgKG5vZGUgPT0gbnVsbCkge1xuICAgICAgLy8gUGVyIDQuNSwgY3JlYXRlIGFuZCA0OC1iaXQgbm9kZSBpZCwgKDQ3IHJhbmRvbSBiaXRzICsgbXVsdGljYXN0IGJpdCA9IDEpXG4gICAgICBub2RlID0gX25vZGVJZCA9IFtcbiAgICAgICAgc2VlZEJ5dGVzWzBdIHwgMHgwMSxcbiAgICAgICAgc2VlZEJ5dGVzWzFdLCBzZWVkQnl0ZXNbMl0sIHNlZWRCeXRlc1szXSwgc2VlZEJ5dGVzWzRdLCBzZWVkQnl0ZXNbNV1cbiAgICAgIF07XG4gICAgfVxuICAgIGlmIChjbG9ja3NlcSA9PSBudWxsKSB7XG4gICAgICAvLyBQZXIgNC4yLjIsIHJhbmRvbWl6ZSAoMTQgYml0KSBjbG9ja3NlcVxuICAgICAgY2xvY2tzZXEgPSBfY2xvY2tzZXEgPSAoc2VlZEJ5dGVzWzZdIDw8IDggfCBzZWVkQnl0ZXNbN10pICYgMHgzZmZmO1xuICAgIH1cbiAgfVxuXG4gIC8vIFVVSUQgdGltZXN0YW1wcyBhcmUgMTAwIG5hbm8tc2Vjb25kIHVuaXRzIHNpbmNlIHRoZSBHcmVnb3JpYW4gZXBvY2gsXG4gIC8vICgxNTgyLTEwLTE1IDAwOjAwKS4gIEpTTnVtYmVycyBhcmVuJ3QgcHJlY2lzZSBlbm91Z2ggZm9yIHRoaXMsIHNvXG4gIC8vIHRpbWUgaXMgaGFuZGxlZCBpbnRlcm5hbGx5IGFzICdtc2VjcycgKGludGVnZXIgbWlsbGlzZWNvbmRzKSBhbmQgJ25zZWNzJ1xuICAvLyAoMTAwLW5hbm9zZWNvbmRzIG9mZnNldCBmcm9tIG1zZWNzKSBzaW5jZSB1bml4IGVwb2NoLCAxOTcwLTAxLTAxIDAwOjAwLlxuICB2YXIgbXNlY3MgPSBvcHRpb25zLm1zZWNzICE9PSB1bmRlZmluZWQgPyBvcHRpb25zLm1zZWNzIDogbmV3IERhdGUoKS5nZXRUaW1lKCk7XG5cbiAgLy8gUGVyIDQuMi4xLjIsIHVzZSBjb3VudCBvZiB1dWlkJ3MgZ2VuZXJhdGVkIGR1cmluZyB0aGUgY3VycmVudCBjbG9ja1xuICAvLyBjeWNsZSB0byBzaW11bGF0ZSBoaWdoZXIgcmVzb2x1dGlvbiBjbG9ja1xuICB2YXIgbnNlY3MgPSBvcHRpb25zLm5zZWNzICE9PSB1bmRlZmluZWQgPyBvcHRpb25zLm5zZWNzIDogX2xhc3ROU2VjcyArIDE7XG5cbiAgLy8gVGltZSBzaW5jZSBsYXN0IHV1aWQgY3JlYXRpb24gKGluIG1zZWNzKVxuICB2YXIgZHQgPSAobXNlY3MgLSBfbGFzdE1TZWNzKSArIChuc2VjcyAtIF9sYXN0TlNlY3MpLzEwMDAwO1xuXG4gIC8vIFBlciA0LjIuMS4yLCBCdW1wIGNsb2Nrc2VxIG9uIGNsb2NrIHJlZ3Jlc3Npb25cbiAgaWYgKGR0IDwgMCAmJiBvcHRpb25zLmNsb2Nrc2VxID09PSB1bmRlZmluZWQpIHtcbiAgICBjbG9ja3NlcSA9IGNsb2Nrc2VxICsgMSAmIDB4M2ZmZjtcbiAgfVxuXG4gIC8vIFJlc2V0IG5zZWNzIGlmIGNsb2NrIHJlZ3Jlc3NlcyAobmV3IGNsb2Nrc2VxKSBvciB3ZSd2ZSBtb3ZlZCBvbnRvIGEgbmV3XG4gIC8vIHRpbWUgaW50ZXJ2YWxcbiAgaWYgKChkdCA8IDAgfHwgbXNlY3MgPiBfbGFzdE1TZWNzKSAmJiBvcHRpb25zLm5zZWNzID09PSB1bmRlZmluZWQpIHtcbiAgICBuc2VjcyA9IDA7XG4gIH1cblxuICAvLyBQZXIgNC4yLjEuMiBUaHJvdyBlcnJvciBpZiB0b28gbWFueSB1dWlkcyBhcmUgcmVxdWVzdGVkXG4gIGlmIChuc2VjcyA+PSAxMDAwMCkge1xuICAgIHRocm93IG5ldyBFcnJvcigndXVpZC52MSgpOiBDYW5cXCd0IGNyZWF0ZSBtb3JlIHRoYW4gMTBNIHV1aWRzL3NlYycpO1xuICB9XG5cbiAgX2xhc3RNU2VjcyA9IG1zZWNzO1xuICBfbGFzdE5TZWNzID0gbnNlY3M7XG4gIF9jbG9ja3NlcSA9IGNsb2Nrc2VxO1xuXG4gIC8vIFBlciA0LjEuNCAtIENvbnZlcnQgZnJvbSB1bml4IGVwb2NoIHRvIEdyZWdvcmlhbiBlcG9jaFxuICBtc2VjcyArPSAxMjIxOTI5MjgwMDAwMDtcblxuICAvLyBgdGltZV9sb3dgXG4gIHZhciB0bCA9ICgobXNlY3MgJiAweGZmZmZmZmYpICogMTAwMDAgKyBuc2VjcykgJSAweDEwMDAwMDAwMDtcbiAgYltpKytdID0gdGwgPj4+IDI0ICYgMHhmZjtcbiAgYltpKytdID0gdGwgPj4+IDE2ICYgMHhmZjtcbiAgYltpKytdID0gdGwgPj4+IDggJiAweGZmO1xuICBiW2krK10gPSB0bCAmIDB4ZmY7XG5cbiAgLy8gYHRpbWVfbWlkYFxuICB2YXIgdG1oID0gKG1zZWNzIC8gMHgxMDAwMDAwMDAgKiAxMDAwMCkgJiAweGZmZmZmZmY7XG4gIGJbaSsrXSA9IHRtaCA+Pj4gOCAmIDB4ZmY7XG4gIGJbaSsrXSA9IHRtaCAmIDB4ZmY7XG5cbiAgLy8gYHRpbWVfaGlnaF9hbmRfdmVyc2lvbmBcbiAgYltpKytdID0gdG1oID4+PiAyNCAmIDB4ZiB8IDB4MTA7IC8vIGluY2x1ZGUgdmVyc2lvblxuICBiW2krK10gPSB0bWggPj4+IDE2ICYgMHhmZjtcblxuICAvLyBgY2xvY2tfc2VxX2hpX2FuZF9yZXNlcnZlZGAgKFBlciA0LjIuMiAtIGluY2x1ZGUgdmFyaWFudClcbiAgYltpKytdID0gY2xvY2tzZXEgPj4+IDggfCAweDgwO1xuXG4gIC8vIGBjbG9ja19zZXFfbG93YFxuICBiW2krK10gPSBjbG9ja3NlcSAmIDB4ZmY7XG5cbiAgLy8gYG5vZGVgXG4gIGZvciAodmFyIG4gPSAwOyBuIDwgNjsgKytuKSB7XG4gICAgYltpICsgbl0gPSBub2RlW25dO1xuICB9XG5cbiAgcmV0dXJuIGJ1ZiA/IGJ1ZiA6IGJ5dGVzVG9VdWlkKGIpO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHYxO1xuIiwidmFyIHJuZyA9IHJlcXVpcmUoJy4vbGliL3JuZycpO1xudmFyIGJ5dGVzVG9VdWlkID0gcmVxdWlyZSgnLi9saWIvYnl0ZXNUb1V1aWQnKTtcblxuZnVuY3Rpb24gdjQob3B0aW9ucywgYnVmLCBvZmZzZXQpIHtcbiAgdmFyIGkgPSBidWYgJiYgb2Zmc2V0IHx8IDA7XG5cbiAgaWYgKHR5cGVvZihvcHRpb25zKSA9PSAnc3RyaW5nJykge1xuICAgIGJ1ZiA9IG9wdGlvbnMgPT09ICdiaW5hcnknID8gbmV3IEFycmF5KDE2KSA6IG51bGw7XG4gICAgb3B0aW9ucyA9IG51bGw7XG4gIH1cbiAgb3B0aW9ucyA9IG9wdGlvbnMgfHwge307XG5cbiAgdmFyIHJuZHMgPSBvcHRpb25zLnJhbmRvbSB8fCAob3B0aW9ucy5ybmcgfHwgcm5nKSgpO1xuXG4gIC8vIFBlciA0LjQsIHNldCBiaXRzIGZvciB2ZXJzaW9uIGFuZCBgY2xvY2tfc2VxX2hpX2FuZF9yZXNlcnZlZGBcbiAgcm5kc1s2XSA9IChybmRzWzZdICYgMHgwZikgfCAweDQwO1xuICBybmRzWzhdID0gKHJuZHNbOF0gJiAweDNmKSB8IDB4ODA7XG5cbiAgLy8gQ29weSBieXRlcyB0byBidWZmZXIsIGlmIHByb3ZpZGVkXG4gIGlmIChidWYpIHtcbiAgICBmb3IgKHZhciBpaSA9IDA7IGlpIDwgMTY7ICsraWkpIHtcbiAgICAgIGJ1ZltpICsgaWldID0gcm5kc1tpaV07XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGJ1ZiB8fCBieXRlc1RvVXVpZChybmRzKTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSB2NDtcbiIsIi8qXHJcbldpbGRFbWl0dGVyLmpzIGlzIGEgc2xpbSBsaXR0bGUgZXZlbnQgZW1pdHRlciBieSBAaGVucmlram9yZXRlZyBsYXJnZWx5IGJhc2VkXHJcbm9uIEB2aXNpb25tZWRpYSdzIEVtaXR0ZXIgZnJvbSBVSSBLaXQuXHJcblxyXG5XaHk/IEkgd2FudGVkIGl0IHN0YW5kYWxvbmUuXHJcblxyXG5JIGFsc28gd2FudGVkIHN1cHBvcnQgZm9yIHdpbGRjYXJkIGVtaXR0ZXJzIGxpa2UgdGhpczpcclxuXHJcbmVtaXR0ZXIub24oJyonLCBmdW5jdGlvbiAoZXZlbnROYW1lLCBvdGhlciwgZXZlbnQsIHBheWxvYWRzKSB7XHJcblxyXG59KTtcclxuXHJcbmVtaXR0ZXIub24oJ3NvbWVuYW1lc3BhY2UqJywgZnVuY3Rpb24gKGV2ZW50TmFtZSwgcGF5bG9hZHMpIHtcclxuXHJcbn0pO1xyXG5cclxuUGxlYXNlIG5vdGUgdGhhdCBjYWxsYmFja3MgdHJpZ2dlcmVkIGJ5IHdpbGRjYXJkIHJlZ2lzdGVyZWQgZXZlbnRzIGFsc28gZ2V0XHJcbnRoZSBldmVudCBuYW1lIGFzIHRoZSBmaXJzdCBhcmd1bWVudC5cclxuKi9cclxuXHJcbm1vZHVsZS5leHBvcnRzID0gV2lsZEVtaXR0ZXI7XHJcblxyXG5mdW5jdGlvbiBXaWxkRW1pdHRlcigpIHsgfVxyXG5cclxuV2lsZEVtaXR0ZXIubWl4aW4gPSBmdW5jdGlvbiAoY29uc3RydWN0b3IpIHtcclxuICAgIHZhciBwcm90b3R5cGUgPSBjb25zdHJ1Y3Rvci5wcm90b3R5cGUgfHwgY29uc3RydWN0b3I7XHJcblxyXG4gICAgcHJvdG90eXBlLmlzV2lsZEVtaXR0ZXI9IHRydWU7XHJcblxyXG4gICAgLy8gTGlzdGVuIG9uIHRoZSBnaXZlbiBgZXZlbnRgIHdpdGggYGZuYC4gU3RvcmUgYSBncm91cCBuYW1lIGlmIHByZXNlbnQuXHJcbiAgICBwcm90b3R5cGUub24gPSBmdW5jdGlvbiAoZXZlbnQsIGdyb3VwTmFtZSwgZm4pIHtcclxuICAgICAgICB0aGlzLmNhbGxiYWNrcyA9IHRoaXMuY2FsbGJhY2tzIHx8IHt9O1xyXG4gICAgICAgIHZhciBoYXNHcm91cCA9IChhcmd1bWVudHMubGVuZ3RoID09PSAzKSxcclxuICAgICAgICAgICAgZ3JvdXAgPSBoYXNHcm91cCA/IGFyZ3VtZW50c1sxXSA6IHVuZGVmaW5lZCxcclxuICAgICAgICAgICAgZnVuYyA9IGhhc0dyb3VwID8gYXJndW1lbnRzWzJdIDogYXJndW1lbnRzWzFdO1xyXG4gICAgICAgIGZ1bmMuX2dyb3VwTmFtZSA9IGdyb3VwO1xyXG4gICAgICAgICh0aGlzLmNhbGxiYWNrc1tldmVudF0gPSB0aGlzLmNhbGxiYWNrc1tldmVudF0gfHwgW10pLnB1c2goZnVuYyk7XHJcbiAgICAgICAgcmV0dXJuIHRoaXM7XHJcbiAgICB9O1xyXG5cclxuICAgIC8vIEFkZHMgYW4gYGV2ZW50YCBsaXN0ZW5lciB0aGF0IHdpbGwgYmUgaW52b2tlZCBhIHNpbmdsZVxyXG4gICAgLy8gdGltZSB0aGVuIGF1dG9tYXRpY2FsbHkgcmVtb3ZlZC5cclxuICAgIHByb3RvdHlwZS5vbmNlID0gZnVuY3Rpb24gKGV2ZW50LCBncm91cE5hbWUsIGZuKSB7XHJcbiAgICAgICAgdmFyIHNlbGYgPSB0aGlzLFxyXG4gICAgICAgICAgICBoYXNHcm91cCA9IChhcmd1bWVudHMubGVuZ3RoID09PSAzKSxcclxuICAgICAgICAgICAgZ3JvdXAgPSBoYXNHcm91cCA/IGFyZ3VtZW50c1sxXSA6IHVuZGVmaW5lZCxcclxuICAgICAgICAgICAgZnVuYyA9IGhhc0dyb3VwID8gYXJndW1lbnRzWzJdIDogYXJndW1lbnRzWzFdO1xyXG4gICAgICAgIGZ1bmN0aW9uIG9uKCkge1xyXG4gICAgICAgICAgICBzZWxmLm9mZihldmVudCwgb24pO1xyXG4gICAgICAgICAgICBmdW5jLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHRoaXMub24oZXZlbnQsIGdyb3VwLCBvbik7XHJcbiAgICAgICAgcmV0dXJuIHRoaXM7XHJcbiAgICB9O1xyXG5cclxuICAgIC8vIFVuYmluZHMgYW4gZW50aXJlIGdyb3VwXHJcbiAgICBwcm90b3R5cGUucmVsZWFzZUdyb3VwID0gZnVuY3Rpb24gKGdyb3VwTmFtZSkge1xyXG4gICAgICAgIHRoaXMuY2FsbGJhY2tzID0gdGhpcy5jYWxsYmFja3MgfHwge307XHJcbiAgICAgICAgdmFyIGl0ZW0sIGksIGxlbiwgaGFuZGxlcnM7XHJcbiAgICAgICAgZm9yIChpdGVtIGluIHRoaXMuY2FsbGJhY2tzKSB7XHJcbiAgICAgICAgICAgIGhhbmRsZXJzID0gdGhpcy5jYWxsYmFja3NbaXRlbV07XHJcbiAgICAgICAgICAgIGZvciAoaSA9IDAsIGxlbiA9IGhhbmRsZXJzLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XHJcbiAgICAgICAgICAgICAgICBpZiAoaGFuZGxlcnNbaV0uX2dyb3VwTmFtZSA9PT0gZ3JvdXBOYW1lKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgLy9jb25zb2xlLmxvZygncmVtb3ZpbmcnKTtcclxuICAgICAgICAgICAgICAgICAgICAvLyByZW1vdmUgaXQgYW5kIHNob3J0ZW4gdGhlIGFycmF5IHdlJ3JlIGxvb3BpbmcgdGhyb3VnaFxyXG4gICAgICAgICAgICAgICAgICAgIGhhbmRsZXJzLnNwbGljZShpLCAxKTtcclxuICAgICAgICAgICAgICAgICAgICBpLS07XHJcbiAgICAgICAgICAgICAgICAgICAgbGVuLS07XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgICAgcmV0dXJuIHRoaXM7XHJcbiAgICB9O1xyXG5cclxuICAgIC8vIFJlbW92ZSB0aGUgZ2l2ZW4gY2FsbGJhY2sgZm9yIGBldmVudGAgb3IgYWxsXHJcbiAgICAvLyByZWdpc3RlcmVkIGNhbGxiYWNrcy5cclxuICAgIHByb3RvdHlwZS5vZmYgPSBmdW5jdGlvbiAoZXZlbnQsIGZuKSB7XHJcbiAgICAgICAgdGhpcy5jYWxsYmFja3MgPSB0aGlzLmNhbGxiYWNrcyB8fCB7fTtcclxuICAgICAgICB2YXIgY2FsbGJhY2tzID0gdGhpcy5jYWxsYmFja3NbZXZlbnRdLFxyXG4gICAgICAgICAgICBpO1xyXG5cclxuICAgICAgICBpZiAoIWNhbGxiYWNrcykgcmV0dXJuIHRoaXM7XHJcblxyXG4gICAgICAgIC8vIHJlbW92ZSBhbGwgaGFuZGxlcnNcclxuICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMSkge1xyXG4gICAgICAgICAgICBkZWxldGUgdGhpcy5jYWxsYmFja3NbZXZlbnRdO1xyXG4gICAgICAgICAgICByZXR1cm4gdGhpcztcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC8vIHJlbW92ZSBzcGVjaWZpYyBoYW5kbGVyXHJcbiAgICAgICAgaSA9IGNhbGxiYWNrcy5pbmRleE9mKGZuKTtcclxuICAgICAgICBjYWxsYmFja3Muc3BsaWNlKGksIDEpO1xyXG4gICAgICAgIGlmIChjYWxsYmFja3MubGVuZ3RoID09PSAwKSB7XHJcbiAgICAgICAgICAgIGRlbGV0ZSB0aGlzLmNhbGxiYWNrc1tldmVudF07XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJldHVybiB0aGlzO1xyXG4gICAgfTtcclxuXHJcbiAgICAvLy8gRW1pdCBgZXZlbnRgIHdpdGggdGhlIGdpdmVuIGFyZ3MuXHJcbiAgICAvLyBhbHNvIGNhbGxzIGFueSBgKmAgaGFuZGxlcnNcclxuICAgIHByb3RvdHlwZS5lbWl0ID0gZnVuY3Rpb24gKGV2ZW50KSB7XHJcbiAgICAgICAgdGhpcy5jYWxsYmFja3MgPSB0aGlzLmNhbGxiYWNrcyB8fCB7fTtcclxuICAgICAgICB2YXIgYXJncyA9IFtdLnNsaWNlLmNhbGwoYXJndW1lbnRzLCAxKSxcclxuICAgICAgICAgICAgY2FsbGJhY2tzID0gdGhpcy5jYWxsYmFja3NbZXZlbnRdLFxyXG4gICAgICAgICAgICBzcGVjaWFsQ2FsbGJhY2tzID0gdGhpcy5nZXRXaWxkY2FyZENhbGxiYWNrcyhldmVudCksXHJcbiAgICAgICAgICAgIGksXHJcbiAgICAgICAgICAgIGxlbixcclxuICAgICAgICAgICAgaXRlbSxcclxuICAgICAgICAgICAgbGlzdGVuZXJzO1xyXG5cclxuICAgICAgICBpZiAoY2FsbGJhY2tzKSB7XHJcbiAgICAgICAgICAgIGxpc3RlbmVycyA9IGNhbGxiYWNrcy5zbGljZSgpO1xyXG4gICAgICAgICAgICBmb3IgKGkgPSAwLCBsZW4gPSBsaXN0ZW5lcnMubGVuZ3RoOyBpIDwgbGVuOyArK2kpIHtcclxuICAgICAgICAgICAgICAgIGlmICghbGlzdGVuZXJzW2ldKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICBsaXN0ZW5lcnNbaV0uYXBwbHkodGhpcywgYXJncyk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGlmIChzcGVjaWFsQ2FsbGJhY2tzKSB7XHJcbiAgICAgICAgICAgIGxlbiA9IHNwZWNpYWxDYWxsYmFja3MubGVuZ3RoO1xyXG4gICAgICAgICAgICBsaXN0ZW5lcnMgPSBzcGVjaWFsQ2FsbGJhY2tzLnNsaWNlKCk7XHJcbiAgICAgICAgICAgIGZvciAoaSA9IDAsIGxlbiA9IGxpc3RlbmVycy5sZW5ndGg7IGkgPCBsZW47ICsraSkge1xyXG4gICAgICAgICAgICAgICAgaWYgKCFsaXN0ZW5lcnNbaV0pIHtcclxuICAgICAgICAgICAgICAgICAgICBicmVhaztcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIGxpc3RlbmVyc1tpXS5hcHBseSh0aGlzLCBbZXZlbnRdLmNvbmNhdChhcmdzKSk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHJldHVybiB0aGlzO1xyXG4gICAgfTtcclxuXHJcbiAgICAvLyBIZWxwZXIgZm9yIGZvciBmaW5kaW5nIHNwZWNpYWwgd2lsZGNhcmQgZXZlbnQgaGFuZGxlcnMgdGhhdCBtYXRjaCB0aGUgZXZlbnRcclxuICAgIHByb3RvdHlwZS5nZXRXaWxkY2FyZENhbGxiYWNrcyA9IGZ1bmN0aW9uIChldmVudE5hbWUpIHtcclxuICAgICAgICB0aGlzLmNhbGxiYWNrcyA9IHRoaXMuY2FsbGJhY2tzIHx8IHt9O1xyXG4gICAgICAgIHZhciBpdGVtLFxyXG4gICAgICAgICAgICBzcGxpdCxcclxuICAgICAgICAgICAgcmVzdWx0ID0gW107XHJcblxyXG4gICAgICAgIGZvciAoaXRlbSBpbiB0aGlzLmNhbGxiYWNrcykge1xyXG4gICAgICAgICAgICBzcGxpdCA9IGl0ZW0uc3BsaXQoJyonKTtcclxuICAgICAgICAgICAgaWYgKGl0ZW0gPT09ICcqJyB8fCAoc3BsaXQubGVuZ3RoID09PSAyICYmIGV2ZW50TmFtZS5zbGljZSgwLCBzcGxpdFswXS5sZW5ndGgpID09PSBzcGxpdFswXSkpIHtcclxuICAgICAgICAgICAgICAgIHJlc3VsdCA9IHJlc3VsdC5jb25jYXQodGhpcy5jYWxsYmFja3NbaXRlbV0pO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJldHVybiByZXN1bHQ7XHJcbiAgICB9O1xyXG5cclxufTtcclxuXHJcbldpbGRFbWl0dGVyLm1peGluKFdpbGRFbWl0dGVyKTtcclxuIiwiLyohXG4gKiBFdmVudEVtaXR0ZXIgdjUuMi41IC0gZ2l0LmlvL2VlXG4gKiBVbmxpY2Vuc2UgLSBodHRwOi8vdW5saWNlbnNlLm9yZy9cbiAqIE9saXZlciBDYWxkd2VsbCAtIGh0dHA6Ly9vbGkubWUudWsvXG4gKiBAcHJlc2VydmVcbiAqL1xuXG47KGZ1bmN0aW9uIChleHBvcnRzKSB7XG4gICAgJ3VzZSBzdHJpY3QnO1xuXG4gICAgLyoqXG4gICAgICogQ2xhc3MgZm9yIG1hbmFnaW5nIGV2ZW50cy5cbiAgICAgKiBDYW4gYmUgZXh0ZW5kZWQgdG8gcHJvdmlkZSBldmVudCBmdW5jdGlvbmFsaXR5IGluIG90aGVyIGNsYXNzZXMuXG4gICAgICpcbiAgICAgKiBAY2xhc3MgRXZlbnRFbWl0dGVyIE1hbmFnZXMgZXZlbnQgcmVnaXN0ZXJpbmcgYW5kIGVtaXR0aW5nLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIEV2ZW50RW1pdHRlcigpIHt9XG5cbiAgICAvLyBTaG9ydGN1dHMgdG8gaW1wcm92ZSBzcGVlZCBhbmQgc2l6ZVxuICAgIHZhciBwcm90byA9IEV2ZW50RW1pdHRlci5wcm90b3R5cGU7XG4gICAgdmFyIG9yaWdpbmFsR2xvYmFsVmFsdWUgPSBleHBvcnRzLkV2ZW50RW1pdHRlcjtcblxuICAgIC8qKlxuICAgICAqIEZpbmRzIHRoZSBpbmRleCBvZiB0aGUgbGlzdGVuZXIgZm9yIHRoZSBldmVudCBpbiBpdHMgc3RvcmFnZSBhcnJheS5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb25bXX0gbGlzdGVuZXJzIEFycmF5IG9mIGxpc3RlbmVycyB0byBzZWFyY2ggdGhyb3VnaC5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBsaXN0ZW5lciBNZXRob2QgdG8gbG9vayBmb3IuXG4gICAgICogQHJldHVybiB7TnVtYmVyfSBJbmRleCBvZiB0aGUgc3BlY2lmaWVkIGxpc3RlbmVyLCAtMSBpZiBub3QgZm91bmRcbiAgICAgKiBAYXBpIHByaXZhdGVcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBpbmRleE9mTGlzdGVuZXIobGlzdGVuZXJzLCBsaXN0ZW5lcikge1xuICAgICAgICB2YXIgaSA9IGxpc3RlbmVycy5sZW5ndGg7XG4gICAgICAgIHdoaWxlIChpLS0pIHtcbiAgICAgICAgICAgIGlmIChsaXN0ZW5lcnNbaV0ubGlzdGVuZXIgPT09IGxpc3RlbmVyKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gLTE7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQWxpYXMgYSBtZXRob2Qgd2hpbGUga2VlcGluZyB0aGUgY29udGV4dCBjb3JyZWN0LCB0byBhbGxvdyBmb3Igb3ZlcndyaXRpbmcgb2YgdGFyZ2V0IG1ldGhvZC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfSBuYW1lIFRoZSBuYW1lIG9mIHRoZSB0YXJnZXQgbWV0aG9kLlxuICAgICAqIEByZXR1cm4ge0Z1bmN0aW9ufSBUaGUgYWxpYXNlZCBtZXRob2RcbiAgICAgKiBAYXBpIHByaXZhdGVcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBhbGlhcyhuYW1lKSB7XG4gICAgICAgIHJldHVybiBmdW5jdGlvbiBhbGlhc0Nsb3N1cmUoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpc1tuYW1lXS5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgICAgICB9O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgdGhlIGxpc3RlbmVyIGFycmF5IGZvciB0aGUgc3BlY2lmaWVkIGV2ZW50LlxuICAgICAqIFdpbGwgaW5pdGlhbGlzZSB0aGUgZXZlbnQgb2JqZWN0IGFuZCBsaXN0ZW5lciBhcnJheXMgaWYgcmVxdWlyZWQuXG4gICAgICogV2lsbCByZXR1cm4gYW4gb2JqZWN0IGlmIHlvdSB1c2UgYSByZWdleCBzZWFyY2guIFRoZSBvYmplY3QgY29udGFpbnMga2V5cyBmb3IgZWFjaCBtYXRjaGVkIGV2ZW50LiBTbyAvYmFbcnpdLyBtaWdodCByZXR1cm4gYW4gb2JqZWN0IGNvbnRhaW5pbmcgYmFyIGFuZCBiYXouIEJ1dCBvbmx5IGlmIHlvdSBoYXZlIGVpdGhlciBkZWZpbmVkIHRoZW0gd2l0aCBkZWZpbmVFdmVudCBvciBhZGRlZCBzb21lIGxpc3RlbmVycyB0byB0aGVtLlxuICAgICAqIEVhY2ggcHJvcGVydHkgaW4gdGhlIG9iamVjdCByZXNwb25zZSBpcyBhbiBhcnJheSBvZiBsaXN0ZW5lciBmdW5jdGlvbnMuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1N0cmluZ3xSZWdFeHB9IGV2dCBOYW1lIG9mIHRoZSBldmVudCB0byByZXR1cm4gdGhlIGxpc3RlbmVycyBmcm9tLlxuICAgICAqIEByZXR1cm4ge0Z1bmN0aW9uW118T2JqZWN0fSBBbGwgbGlzdGVuZXIgZnVuY3Rpb25zIGZvciB0aGUgZXZlbnQuXG4gICAgICovXG4gICAgcHJvdG8uZ2V0TGlzdGVuZXJzID0gZnVuY3Rpb24gZ2V0TGlzdGVuZXJzKGV2dCkge1xuICAgICAgICB2YXIgZXZlbnRzID0gdGhpcy5fZ2V0RXZlbnRzKCk7XG4gICAgICAgIHZhciByZXNwb25zZTtcbiAgICAgICAgdmFyIGtleTtcblxuICAgICAgICAvLyBSZXR1cm4gYSBjb25jYXRlbmF0ZWQgYXJyYXkgb2YgYWxsIG1hdGNoaW5nIGV2ZW50cyBpZlxuICAgICAgICAvLyB0aGUgc2VsZWN0b3IgaXMgYSByZWd1bGFyIGV4cHJlc3Npb24uXG4gICAgICAgIGlmIChldnQgaW5zdGFuY2VvZiBSZWdFeHApIHtcbiAgICAgICAgICAgIHJlc3BvbnNlID0ge307XG4gICAgICAgICAgICBmb3IgKGtleSBpbiBldmVudHMpIHtcbiAgICAgICAgICAgICAgICBpZiAoZXZlbnRzLmhhc093blByb3BlcnR5KGtleSkgJiYgZXZ0LnRlc3Qoa2V5KSkge1xuICAgICAgICAgICAgICAgICAgICByZXNwb25zZVtrZXldID0gZXZlbnRzW2tleV07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgcmVzcG9uc2UgPSBldmVudHNbZXZ0XSB8fCAoZXZlbnRzW2V2dF0gPSBbXSk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gcmVzcG9uc2U7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIFRha2VzIGEgbGlzdCBvZiBsaXN0ZW5lciBvYmplY3RzIGFuZCBmbGF0dGVucyBpdCBpbnRvIGEgbGlzdCBvZiBsaXN0ZW5lciBmdW5jdGlvbnMuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge09iamVjdFtdfSBsaXN0ZW5lcnMgUmF3IGxpc3RlbmVyIG9iamVjdHMuXG4gICAgICogQHJldHVybiB7RnVuY3Rpb25bXX0gSnVzdCB0aGUgbGlzdGVuZXIgZnVuY3Rpb25zLlxuICAgICAqL1xuICAgIHByb3RvLmZsYXR0ZW5MaXN0ZW5lcnMgPSBmdW5jdGlvbiBmbGF0dGVuTGlzdGVuZXJzKGxpc3RlbmVycykge1xuICAgICAgICB2YXIgZmxhdExpc3RlbmVycyA9IFtdO1xuICAgICAgICB2YXIgaTtcblxuICAgICAgICBmb3IgKGkgPSAwOyBpIDwgbGlzdGVuZXJzLmxlbmd0aDsgaSArPSAxKSB7XG4gICAgICAgICAgICBmbGF0TGlzdGVuZXJzLnB1c2gobGlzdGVuZXJzW2ldLmxpc3RlbmVyKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBmbGF0TGlzdGVuZXJzO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBGZXRjaGVzIHRoZSByZXF1ZXN0ZWQgbGlzdGVuZXJzIHZpYSBnZXRMaXN0ZW5lcnMgYnV0IHdpbGwgYWx3YXlzIHJldHVybiB0aGUgcmVzdWx0cyBpbnNpZGUgYW4gb2JqZWN0LiBUaGlzIGlzIG1haW5seSBmb3IgaW50ZXJuYWwgdXNlIGJ1dCBvdGhlcnMgbWF5IGZpbmQgaXQgdXNlZnVsLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtTdHJpbmd8UmVnRXhwfSBldnQgTmFtZSBvZiB0aGUgZXZlbnQgdG8gcmV0dXJuIHRoZSBsaXN0ZW5lcnMgZnJvbS5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEFsbCBsaXN0ZW5lciBmdW5jdGlvbnMgZm9yIGFuIGV2ZW50IGluIGFuIG9iamVjdC5cbiAgICAgKi9cbiAgICBwcm90by5nZXRMaXN0ZW5lcnNBc09iamVjdCA9IGZ1bmN0aW9uIGdldExpc3RlbmVyc0FzT2JqZWN0KGV2dCkge1xuICAgICAgICB2YXIgbGlzdGVuZXJzID0gdGhpcy5nZXRMaXN0ZW5lcnMoZXZ0KTtcbiAgICAgICAgdmFyIHJlc3BvbnNlO1xuXG4gICAgICAgIGlmIChsaXN0ZW5lcnMgaW5zdGFuY2VvZiBBcnJheSkge1xuICAgICAgICAgICAgcmVzcG9uc2UgPSB7fTtcbiAgICAgICAgICAgIHJlc3BvbnNlW2V2dF0gPSBsaXN0ZW5lcnM7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gcmVzcG9uc2UgfHwgbGlzdGVuZXJzO1xuICAgIH07XG5cbiAgICBmdW5jdGlvbiBpc1ZhbGlkTGlzdGVuZXIgKGxpc3RlbmVyKSB7XG4gICAgICAgIGlmICh0eXBlb2YgbGlzdGVuZXIgPT09ICdmdW5jdGlvbicgfHwgbGlzdGVuZXIgaW5zdGFuY2VvZiBSZWdFeHApIHtcbiAgICAgICAgICAgIHJldHVybiB0cnVlXG4gICAgICAgIH0gZWxzZSBpZiAobGlzdGVuZXIgJiYgdHlwZW9mIGxpc3RlbmVyID09PSAnb2JqZWN0Jykge1xuICAgICAgICAgICAgcmV0dXJuIGlzVmFsaWRMaXN0ZW5lcihsaXN0ZW5lci5saXN0ZW5lcilcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQWRkcyBhIGxpc3RlbmVyIGZ1bmN0aW9uIHRvIHRoZSBzcGVjaWZpZWQgZXZlbnQuXG4gICAgICogVGhlIGxpc3RlbmVyIHdpbGwgbm90IGJlIGFkZGVkIGlmIGl0IGlzIGEgZHVwbGljYXRlLlxuICAgICAqIElmIHRoZSBsaXN0ZW5lciByZXR1cm5zIHRydWUgdGhlbiBpdCB3aWxsIGJlIHJlbW92ZWQgYWZ0ZXIgaXQgaXMgY2FsbGVkLlxuICAgICAqIElmIHlvdSBwYXNzIGEgcmVndWxhciBleHByZXNzaW9uIGFzIHRoZSBldmVudCBuYW1lIHRoZW4gdGhlIGxpc3RlbmVyIHdpbGwgYmUgYWRkZWQgdG8gYWxsIGV2ZW50cyB0aGF0IG1hdGNoIGl0LlxuICAgICAqXG4gICAgICogQHBhcmFtIHtTdHJpbmd8UmVnRXhwfSBldnQgTmFtZSBvZiB0aGUgZXZlbnQgdG8gYXR0YWNoIHRoZSBsaXN0ZW5lciB0by5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBsaXN0ZW5lciBNZXRob2QgdG8gYmUgY2FsbGVkIHdoZW4gdGhlIGV2ZW50IGlzIGVtaXR0ZWQuIElmIHRoZSBmdW5jdGlvbiByZXR1cm5zIHRydWUgdGhlbiBpdCB3aWxsIGJlIHJlbW92ZWQgYWZ0ZXIgY2FsbGluZy5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEN1cnJlbnQgaW5zdGFuY2Ugb2YgRXZlbnRFbWl0dGVyIGZvciBjaGFpbmluZy5cbiAgICAgKi9cbiAgICBwcm90by5hZGRMaXN0ZW5lciA9IGZ1bmN0aW9uIGFkZExpc3RlbmVyKGV2dCwgbGlzdGVuZXIpIHtcbiAgICAgICAgaWYgKCFpc1ZhbGlkTGlzdGVuZXIobGlzdGVuZXIpKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdsaXN0ZW5lciBtdXN0IGJlIGEgZnVuY3Rpb24nKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBsaXN0ZW5lcnMgPSB0aGlzLmdldExpc3RlbmVyc0FzT2JqZWN0KGV2dCk7XG4gICAgICAgIHZhciBsaXN0ZW5lcklzV3JhcHBlZCA9IHR5cGVvZiBsaXN0ZW5lciA9PT0gJ29iamVjdCc7XG4gICAgICAgIHZhciBrZXk7XG5cbiAgICAgICAgZm9yIChrZXkgaW4gbGlzdGVuZXJzKSB7XG4gICAgICAgICAgICBpZiAobGlzdGVuZXJzLmhhc093blByb3BlcnR5KGtleSkgJiYgaW5kZXhPZkxpc3RlbmVyKGxpc3RlbmVyc1trZXldLCBsaXN0ZW5lcikgPT09IC0xKSB7XG4gICAgICAgICAgICAgICAgbGlzdGVuZXJzW2tleV0ucHVzaChsaXN0ZW5lcklzV3JhcHBlZCA/IGxpc3RlbmVyIDoge1xuICAgICAgICAgICAgICAgICAgICBsaXN0ZW5lcjogbGlzdGVuZXIsXG4gICAgICAgICAgICAgICAgICAgIG9uY2U6IGZhbHNlXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogQWxpYXMgb2YgYWRkTGlzdGVuZXJcbiAgICAgKi9cbiAgICBwcm90by5vbiA9IGFsaWFzKCdhZGRMaXN0ZW5lcicpO1xuXG4gICAgLyoqXG4gICAgICogU2VtaS1hbGlhcyBvZiBhZGRMaXN0ZW5lci4gSXQgd2lsbCBhZGQgYSBsaXN0ZW5lciB0aGF0IHdpbGwgYmVcbiAgICAgKiBhdXRvbWF0aWNhbGx5IHJlbW92ZWQgYWZ0ZXIgaXRzIGZpcnN0IGV4ZWN1dGlvbi5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfFJlZ0V4cH0gZXZ0IE5hbWUgb2YgdGhlIGV2ZW50IHRvIGF0dGFjaCB0aGUgbGlzdGVuZXIgdG8uXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gbGlzdGVuZXIgTWV0aG9kIHRvIGJlIGNhbGxlZCB3aGVuIHRoZSBldmVudCBpcyBlbWl0dGVkLiBJZiB0aGUgZnVuY3Rpb24gcmV0dXJucyB0cnVlIHRoZW4gaXQgd2lsbCBiZSByZW1vdmVkIGFmdGVyIGNhbGxpbmcuXG4gICAgICogQHJldHVybiB7T2JqZWN0fSBDdXJyZW50IGluc3RhbmNlIG9mIEV2ZW50RW1pdHRlciBmb3IgY2hhaW5pbmcuXG4gICAgICovXG4gICAgcHJvdG8uYWRkT25jZUxpc3RlbmVyID0gZnVuY3Rpb24gYWRkT25jZUxpc3RlbmVyKGV2dCwgbGlzdGVuZXIpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuYWRkTGlzdGVuZXIoZXZ0LCB7XG4gICAgICAgICAgICBsaXN0ZW5lcjogbGlzdGVuZXIsXG4gICAgICAgICAgICBvbmNlOiB0cnVlXG4gICAgICAgIH0pO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBBbGlhcyBvZiBhZGRPbmNlTGlzdGVuZXIuXG4gICAgICovXG4gICAgcHJvdG8ub25jZSA9IGFsaWFzKCdhZGRPbmNlTGlzdGVuZXInKTtcblxuICAgIC8qKlxuICAgICAqIERlZmluZXMgYW4gZXZlbnQgbmFtZS4gVGhpcyBpcyByZXF1aXJlZCBpZiB5b3Ugd2FudCB0byB1c2UgYSByZWdleCB0byBhZGQgYSBsaXN0ZW5lciB0byBtdWx0aXBsZSBldmVudHMgYXQgb25jZS4gSWYgeW91IGRvbid0IGRvIHRoaXMgdGhlbiBob3cgZG8geW91IGV4cGVjdCBpdCB0byBrbm93IHdoYXQgZXZlbnQgdG8gYWRkIHRvPyBTaG91bGQgaXQganVzdCBhZGQgdG8gZXZlcnkgcG9zc2libGUgbWF0Y2ggZm9yIGEgcmVnZXg/IE5vLiBUaGF0IGlzIHNjYXJ5IGFuZCBiYWQuXG4gICAgICogWW91IG5lZWQgdG8gdGVsbCBpdCB3aGF0IGV2ZW50IG5hbWVzIHNob3VsZCBiZSBtYXRjaGVkIGJ5IGEgcmVnZXguXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1N0cmluZ30gZXZ0IE5hbWUgb2YgdGhlIGV2ZW50IHRvIGNyZWF0ZS5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEN1cnJlbnQgaW5zdGFuY2Ugb2YgRXZlbnRFbWl0dGVyIGZvciBjaGFpbmluZy5cbiAgICAgKi9cbiAgICBwcm90by5kZWZpbmVFdmVudCA9IGZ1bmN0aW9uIGRlZmluZUV2ZW50KGV2dCkge1xuICAgICAgICB0aGlzLmdldExpc3RlbmVycyhldnQpO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogVXNlcyBkZWZpbmVFdmVudCB0byBkZWZpbmUgbXVsdGlwbGUgZXZlbnRzLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtTdHJpbmdbXX0gZXZ0cyBBbiBhcnJheSBvZiBldmVudCBuYW1lcyB0byBkZWZpbmUuXG4gICAgICogQHJldHVybiB7T2JqZWN0fSBDdXJyZW50IGluc3RhbmNlIG9mIEV2ZW50RW1pdHRlciBmb3IgY2hhaW5pbmcuXG4gICAgICovXG4gICAgcHJvdG8uZGVmaW5lRXZlbnRzID0gZnVuY3Rpb24gZGVmaW5lRXZlbnRzKGV2dHMpIHtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBldnRzLmxlbmd0aDsgaSArPSAxKSB7XG4gICAgICAgICAgICB0aGlzLmRlZmluZUV2ZW50KGV2dHNbaV0pO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBSZW1vdmVzIGEgbGlzdGVuZXIgZnVuY3Rpb24gZnJvbSB0aGUgc3BlY2lmaWVkIGV2ZW50LlxuICAgICAqIFdoZW4gcGFzc2VkIGEgcmVndWxhciBleHByZXNzaW9uIGFzIHRoZSBldmVudCBuYW1lLCBpdCB3aWxsIHJlbW92ZSB0aGUgbGlzdGVuZXIgZnJvbSBhbGwgZXZlbnRzIHRoYXQgbWF0Y2ggaXQuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1N0cmluZ3xSZWdFeHB9IGV2dCBOYW1lIG9mIHRoZSBldmVudCB0byByZW1vdmUgdGhlIGxpc3RlbmVyIGZyb20uXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gbGlzdGVuZXIgTWV0aG9kIHRvIHJlbW92ZSBmcm9tIHRoZSBldmVudC5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEN1cnJlbnQgaW5zdGFuY2Ugb2YgRXZlbnRFbWl0dGVyIGZvciBjaGFpbmluZy5cbiAgICAgKi9cbiAgICBwcm90by5yZW1vdmVMaXN0ZW5lciA9IGZ1bmN0aW9uIHJlbW92ZUxpc3RlbmVyKGV2dCwgbGlzdGVuZXIpIHtcbiAgICAgICAgdmFyIGxpc3RlbmVycyA9IHRoaXMuZ2V0TGlzdGVuZXJzQXNPYmplY3QoZXZ0KTtcbiAgICAgICAgdmFyIGluZGV4O1xuICAgICAgICB2YXIga2V5O1xuXG4gICAgICAgIGZvciAoa2V5IGluIGxpc3RlbmVycykge1xuICAgICAgICAgICAgaWYgKGxpc3RlbmVycy5oYXNPd25Qcm9wZXJ0eShrZXkpKSB7XG4gICAgICAgICAgICAgICAgaW5kZXggPSBpbmRleE9mTGlzdGVuZXIobGlzdGVuZXJzW2tleV0sIGxpc3RlbmVyKTtcblxuICAgICAgICAgICAgICAgIGlmIChpbmRleCAhPT0gLTEpIHtcbiAgICAgICAgICAgICAgICAgICAgbGlzdGVuZXJzW2tleV0uc3BsaWNlKGluZGV4LCAxKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogQWxpYXMgb2YgcmVtb3ZlTGlzdGVuZXJcbiAgICAgKi9cbiAgICBwcm90by5vZmYgPSBhbGlhcygncmVtb3ZlTGlzdGVuZXInKTtcblxuICAgIC8qKlxuICAgICAqIEFkZHMgbGlzdGVuZXJzIGluIGJ1bGsgdXNpbmcgdGhlIG1hbmlwdWxhdGVMaXN0ZW5lcnMgbWV0aG9kLlxuICAgICAqIElmIHlvdSBwYXNzIGFuIG9iamVjdCBhcyB0aGUgZmlyc3QgYXJndW1lbnQgeW91IGNhbiBhZGQgdG8gbXVsdGlwbGUgZXZlbnRzIGF0IG9uY2UuIFRoZSBvYmplY3Qgc2hvdWxkIGNvbnRhaW4ga2V5IHZhbHVlIHBhaXJzIG9mIGV2ZW50cyBhbmQgbGlzdGVuZXJzIG9yIGxpc3RlbmVyIGFycmF5cy4gWW91IGNhbiBhbHNvIHBhc3MgaXQgYW4gZXZlbnQgbmFtZSBhbmQgYW4gYXJyYXkgb2YgbGlzdGVuZXJzIHRvIGJlIGFkZGVkLlxuICAgICAqIFlvdSBjYW4gYWxzbyBwYXNzIGl0IGEgcmVndWxhciBleHByZXNzaW9uIHRvIGFkZCB0aGUgYXJyYXkgb2YgbGlzdGVuZXJzIHRvIGFsbCBldmVudHMgdGhhdCBtYXRjaCBpdC5cbiAgICAgKiBZZWFoLCB0aGlzIGZ1bmN0aW9uIGRvZXMgcXVpdGUgYSBiaXQuIFRoYXQncyBwcm9iYWJseSBhIGJhZCB0aGluZy5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfE9iamVjdHxSZWdFeHB9IGV2dCBBbiBldmVudCBuYW1lIGlmIHlvdSB3aWxsIHBhc3MgYW4gYXJyYXkgb2YgbGlzdGVuZXJzIG5leHQuIEFuIG9iamVjdCBpZiB5b3Ugd2lzaCB0byBhZGQgdG8gbXVsdGlwbGUgZXZlbnRzIGF0IG9uY2UuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbltdfSBbbGlzdGVuZXJzXSBBbiBvcHRpb25hbCBhcnJheSBvZiBsaXN0ZW5lciBmdW5jdGlvbnMgdG8gYWRkLlxuICAgICAqIEByZXR1cm4ge09iamVjdH0gQ3VycmVudCBpbnN0YW5jZSBvZiBFdmVudEVtaXR0ZXIgZm9yIGNoYWluaW5nLlxuICAgICAqL1xuICAgIHByb3RvLmFkZExpc3RlbmVycyA9IGZ1bmN0aW9uIGFkZExpc3RlbmVycyhldnQsIGxpc3RlbmVycykge1xuICAgICAgICAvLyBQYXNzIHRocm91Z2ggdG8gbWFuaXB1bGF0ZUxpc3RlbmVyc1xuICAgICAgICByZXR1cm4gdGhpcy5tYW5pcHVsYXRlTGlzdGVuZXJzKGZhbHNlLCBldnQsIGxpc3RlbmVycyk7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIFJlbW92ZXMgbGlzdGVuZXJzIGluIGJ1bGsgdXNpbmcgdGhlIG1hbmlwdWxhdGVMaXN0ZW5lcnMgbWV0aG9kLlxuICAgICAqIElmIHlvdSBwYXNzIGFuIG9iamVjdCBhcyB0aGUgZmlyc3QgYXJndW1lbnQgeW91IGNhbiByZW1vdmUgZnJvbSBtdWx0aXBsZSBldmVudHMgYXQgb25jZS4gVGhlIG9iamVjdCBzaG91bGQgY29udGFpbiBrZXkgdmFsdWUgcGFpcnMgb2YgZXZlbnRzIGFuZCBsaXN0ZW5lcnMgb3IgbGlzdGVuZXIgYXJyYXlzLlxuICAgICAqIFlvdSBjYW4gYWxzbyBwYXNzIGl0IGFuIGV2ZW50IG5hbWUgYW5kIGFuIGFycmF5IG9mIGxpc3RlbmVycyB0byBiZSByZW1vdmVkLlxuICAgICAqIFlvdSBjYW4gYWxzbyBwYXNzIGl0IGEgcmVndWxhciBleHByZXNzaW9uIHRvIHJlbW92ZSB0aGUgbGlzdGVuZXJzIGZyb20gYWxsIGV2ZW50cyB0aGF0IG1hdGNoIGl0LlxuICAgICAqXG4gICAgICogQHBhcmFtIHtTdHJpbmd8T2JqZWN0fFJlZ0V4cH0gZXZ0IEFuIGV2ZW50IG5hbWUgaWYgeW91IHdpbGwgcGFzcyBhbiBhcnJheSBvZiBsaXN0ZW5lcnMgbmV4dC4gQW4gb2JqZWN0IGlmIHlvdSB3aXNoIHRvIHJlbW92ZSBmcm9tIG11bHRpcGxlIGV2ZW50cyBhdCBvbmNlLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb25bXX0gW2xpc3RlbmVyc10gQW4gb3B0aW9uYWwgYXJyYXkgb2YgbGlzdGVuZXIgZnVuY3Rpb25zIHRvIHJlbW92ZS5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEN1cnJlbnQgaW5zdGFuY2Ugb2YgRXZlbnRFbWl0dGVyIGZvciBjaGFpbmluZy5cbiAgICAgKi9cbiAgICBwcm90by5yZW1vdmVMaXN0ZW5lcnMgPSBmdW5jdGlvbiByZW1vdmVMaXN0ZW5lcnMoZXZ0LCBsaXN0ZW5lcnMpIHtcbiAgICAgICAgLy8gUGFzcyB0aHJvdWdoIHRvIG1hbmlwdWxhdGVMaXN0ZW5lcnNcbiAgICAgICAgcmV0dXJuIHRoaXMubWFuaXB1bGF0ZUxpc3RlbmVycyh0cnVlLCBldnQsIGxpc3RlbmVycyk7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEVkaXRzIGxpc3RlbmVycyBpbiBidWxrLiBUaGUgYWRkTGlzdGVuZXJzIGFuZCByZW1vdmVMaXN0ZW5lcnMgbWV0aG9kcyBib3RoIHVzZSB0aGlzIHRvIGRvIHRoZWlyIGpvYi4gWW91IHNob3VsZCByZWFsbHkgdXNlIHRob3NlIGluc3RlYWQsIHRoaXMgaXMgYSBsaXR0bGUgbG93ZXIgbGV2ZWwuXG4gICAgICogVGhlIGZpcnN0IGFyZ3VtZW50IHdpbGwgZGV0ZXJtaW5lIGlmIHRoZSBsaXN0ZW5lcnMgYXJlIHJlbW92ZWQgKHRydWUpIG9yIGFkZGVkIChmYWxzZSkuXG4gICAgICogSWYgeW91IHBhc3MgYW4gb2JqZWN0IGFzIHRoZSBzZWNvbmQgYXJndW1lbnQgeW91IGNhbiBhZGQvcmVtb3ZlIGZyb20gbXVsdGlwbGUgZXZlbnRzIGF0IG9uY2UuIFRoZSBvYmplY3Qgc2hvdWxkIGNvbnRhaW4ga2V5IHZhbHVlIHBhaXJzIG9mIGV2ZW50cyBhbmQgbGlzdGVuZXJzIG9yIGxpc3RlbmVyIGFycmF5cy5cbiAgICAgKiBZb3UgY2FuIGFsc28gcGFzcyBpdCBhbiBldmVudCBuYW1lIGFuZCBhbiBhcnJheSBvZiBsaXN0ZW5lcnMgdG8gYmUgYWRkZWQvcmVtb3ZlZC5cbiAgICAgKiBZb3UgY2FuIGFsc28gcGFzcyBpdCBhIHJlZ3VsYXIgZXhwcmVzc2lvbiB0byBtYW5pcHVsYXRlIHRoZSBsaXN0ZW5lcnMgb2YgYWxsIGV2ZW50cyB0aGF0IG1hdGNoIGl0LlxuICAgICAqXG4gICAgICogQHBhcmFtIHtCb29sZWFufSByZW1vdmUgVHJ1ZSBpZiB5b3Ugd2FudCB0byByZW1vdmUgbGlzdGVuZXJzLCBmYWxzZSBpZiB5b3Ugd2FudCB0byBhZGQuXG4gICAgICogQHBhcmFtIHtTdHJpbmd8T2JqZWN0fFJlZ0V4cH0gZXZ0IEFuIGV2ZW50IG5hbWUgaWYgeW91IHdpbGwgcGFzcyBhbiBhcnJheSBvZiBsaXN0ZW5lcnMgbmV4dC4gQW4gb2JqZWN0IGlmIHlvdSB3aXNoIHRvIGFkZC9yZW1vdmUgZnJvbSBtdWx0aXBsZSBldmVudHMgYXQgb25jZS5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9uW119IFtsaXN0ZW5lcnNdIEFuIG9wdGlvbmFsIGFycmF5IG9mIGxpc3RlbmVyIGZ1bmN0aW9ucyB0byBhZGQvcmVtb3ZlLlxuICAgICAqIEByZXR1cm4ge09iamVjdH0gQ3VycmVudCBpbnN0YW5jZSBvZiBFdmVudEVtaXR0ZXIgZm9yIGNoYWluaW5nLlxuICAgICAqL1xuICAgIHByb3RvLm1hbmlwdWxhdGVMaXN0ZW5lcnMgPSBmdW5jdGlvbiBtYW5pcHVsYXRlTGlzdGVuZXJzKHJlbW92ZSwgZXZ0LCBsaXN0ZW5lcnMpIHtcbiAgICAgICAgdmFyIGk7XG4gICAgICAgIHZhciB2YWx1ZTtcbiAgICAgICAgdmFyIHNpbmdsZSA9IHJlbW92ZSA/IHRoaXMucmVtb3ZlTGlzdGVuZXIgOiB0aGlzLmFkZExpc3RlbmVyO1xuICAgICAgICB2YXIgbXVsdGlwbGUgPSByZW1vdmUgPyB0aGlzLnJlbW92ZUxpc3RlbmVycyA6IHRoaXMuYWRkTGlzdGVuZXJzO1xuXG4gICAgICAgIC8vIElmIGV2dCBpcyBhbiBvYmplY3QgdGhlbiBwYXNzIGVhY2ggb2YgaXRzIHByb3BlcnRpZXMgdG8gdGhpcyBtZXRob2RcbiAgICAgICAgaWYgKHR5cGVvZiBldnQgPT09ICdvYmplY3QnICYmICEoZXZ0IGluc3RhbmNlb2YgUmVnRXhwKSkge1xuICAgICAgICAgICAgZm9yIChpIGluIGV2dCkge1xuICAgICAgICAgICAgICAgIGlmIChldnQuaGFzT3duUHJvcGVydHkoaSkgJiYgKHZhbHVlID0gZXZ0W2ldKSkge1xuICAgICAgICAgICAgICAgICAgICAvLyBQYXNzIHRoZSBzaW5nbGUgbGlzdGVuZXIgc3RyYWlnaHQgdGhyb3VnaCB0byB0aGUgc2luZ3VsYXIgbWV0aG9kXG4gICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgdmFsdWUgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNpbmdsZS5jYWxsKHRoaXMsIGksIHZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIE90aGVyd2lzZSBwYXNzIGJhY2sgdG8gdGhlIG11bHRpcGxlIGZ1bmN0aW9uXG4gICAgICAgICAgICAgICAgICAgICAgICBtdWx0aXBsZS5jYWxsKHRoaXMsIGksIHZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIC8vIFNvIGV2dCBtdXN0IGJlIGEgc3RyaW5nXG4gICAgICAgICAgICAvLyBBbmQgbGlzdGVuZXJzIG11c3QgYmUgYW4gYXJyYXkgb2YgbGlzdGVuZXJzXG4gICAgICAgICAgICAvLyBMb29wIG92ZXIgaXQgYW5kIHBhc3MgZWFjaCBvbmUgdG8gdGhlIG11bHRpcGxlIG1ldGhvZFxuICAgICAgICAgICAgaSA9IGxpc3RlbmVycy5sZW5ndGg7XG4gICAgICAgICAgICB3aGlsZSAoaS0tKSB7XG4gICAgICAgICAgICAgICAgc2luZ2xlLmNhbGwodGhpcywgZXZ0LCBsaXN0ZW5lcnNbaV0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIFJlbW92ZXMgYWxsIGxpc3RlbmVycyBmcm9tIGEgc3BlY2lmaWVkIGV2ZW50LlxuICAgICAqIElmIHlvdSBkbyBub3Qgc3BlY2lmeSBhbiBldmVudCB0aGVuIGFsbCBsaXN0ZW5lcnMgd2lsbCBiZSByZW1vdmVkLlxuICAgICAqIFRoYXQgbWVhbnMgZXZlcnkgZXZlbnQgd2lsbCBiZSBlbXB0aWVkLlxuICAgICAqIFlvdSBjYW4gYWxzbyBwYXNzIGEgcmVnZXggdG8gcmVtb3ZlIGFsbCBldmVudHMgdGhhdCBtYXRjaCBpdC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfFJlZ0V4cH0gW2V2dF0gT3B0aW9uYWwgbmFtZSBvZiB0aGUgZXZlbnQgdG8gcmVtb3ZlIGFsbCBsaXN0ZW5lcnMgZm9yLiBXaWxsIHJlbW92ZSBmcm9tIGV2ZXJ5IGV2ZW50IGlmIG5vdCBwYXNzZWQuXG4gICAgICogQHJldHVybiB7T2JqZWN0fSBDdXJyZW50IGluc3RhbmNlIG9mIEV2ZW50RW1pdHRlciBmb3IgY2hhaW5pbmcuXG4gICAgICovXG4gICAgcHJvdG8ucmVtb3ZlRXZlbnQgPSBmdW5jdGlvbiByZW1vdmVFdmVudChldnQpIHtcbiAgICAgICAgdmFyIHR5cGUgPSB0eXBlb2YgZXZ0O1xuICAgICAgICB2YXIgZXZlbnRzID0gdGhpcy5fZ2V0RXZlbnRzKCk7XG4gICAgICAgIHZhciBrZXk7XG5cbiAgICAgICAgLy8gUmVtb3ZlIGRpZmZlcmVudCB0aGluZ3MgZGVwZW5kaW5nIG9uIHRoZSBzdGF0ZSBvZiBldnRcbiAgICAgICAgaWYgKHR5cGUgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAvLyBSZW1vdmUgYWxsIGxpc3RlbmVycyBmb3IgdGhlIHNwZWNpZmllZCBldmVudFxuICAgICAgICAgICAgZGVsZXRlIGV2ZW50c1tldnRdO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKGV2dCBpbnN0YW5jZW9mIFJlZ0V4cCkge1xuICAgICAgICAgICAgLy8gUmVtb3ZlIGFsbCBldmVudHMgbWF0Y2hpbmcgdGhlIHJlZ2V4LlxuICAgICAgICAgICAgZm9yIChrZXkgaW4gZXZlbnRzKSB7XG4gICAgICAgICAgICAgICAgaWYgKGV2ZW50cy5oYXNPd25Qcm9wZXJ0eShrZXkpICYmIGV2dC50ZXN0KGtleSkpIHtcbiAgICAgICAgICAgICAgICAgICAgZGVsZXRlIGV2ZW50c1trZXldO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIC8vIFJlbW92ZSBhbGwgbGlzdGVuZXJzIGluIGFsbCBldmVudHNcbiAgICAgICAgICAgIGRlbGV0ZSB0aGlzLl9ldmVudHM7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogQWxpYXMgb2YgcmVtb3ZlRXZlbnQuXG4gICAgICpcbiAgICAgKiBBZGRlZCB0byBtaXJyb3IgdGhlIG5vZGUgQVBJLlxuICAgICAqL1xuICAgIHByb3RvLnJlbW92ZUFsbExpc3RlbmVycyA9IGFsaWFzKCdyZW1vdmVFdmVudCcpO1xuXG4gICAgLyoqXG4gICAgICogRW1pdHMgYW4gZXZlbnQgb2YgeW91ciBjaG9pY2UuXG4gICAgICogV2hlbiBlbWl0dGVkLCBldmVyeSBsaXN0ZW5lciBhdHRhY2hlZCB0byB0aGF0IGV2ZW50IHdpbGwgYmUgZXhlY3V0ZWQuXG4gICAgICogSWYgeW91IHBhc3MgdGhlIG9wdGlvbmFsIGFyZ3VtZW50IGFycmF5IHRoZW4gdGhvc2UgYXJndW1lbnRzIHdpbGwgYmUgcGFzc2VkIHRvIGV2ZXJ5IGxpc3RlbmVyIHVwb24gZXhlY3V0aW9uLlxuICAgICAqIEJlY2F1c2UgaXQgdXNlcyBgYXBwbHlgLCB5b3VyIGFycmF5IG9mIGFyZ3VtZW50cyB3aWxsIGJlIHBhc3NlZCBhcyBpZiB5b3Ugd3JvdGUgdGhlbSBvdXQgc2VwYXJhdGVseS5cbiAgICAgKiBTbyB0aGV5IHdpbGwgbm90IGFycml2ZSB3aXRoaW4gdGhlIGFycmF5IG9uIHRoZSBvdGhlciBzaWRlLCB0aGV5IHdpbGwgYmUgc2VwYXJhdGUuXG4gICAgICogWW91IGNhbiBhbHNvIHBhc3MgYSByZWd1bGFyIGV4cHJlc3Npb24gdG8gZW1pdCB0byBhbGwgZXZlbnRzIHRoYXQgbWF0Y2ggaXQuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1N0cmluZ3xSZWdFeHB9IGV2dCBOYW1lIG9mIHRoZSBldmVudCB0byBlbWl0IGFuZCBleGVjdXRlIGxpc3RlbmVycyBmb3IuXG4gICAgICogQHBhcmFtIHtBcnJheX0gW2FyZ3NdIE9wdGlvbmFsIGFycmF5IG9mIGFyZ3VtZW50cyB0byBiZSBwYXNzZWQgdG8gZWFjaCBsaXN0ZW5lci5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEN1cnJlbnQgaW5zdGFuY2Ugb2YgRXZlbnRFbWl0dGVyIGZvciBjaGFpbmluZy5cbiAgICAgKi9cbiAgICBwcm90by5lbWl0RXZlbnQgPSBmdW5jdGlvbiBlbWl0RXZlbnQoZXZ0LCBhcmdzKSB7XG4gICAgICAgIHZhciBsaXN0ZW5lcnNNYXAgPSB0aGlzLmdldExpc3RlbmVyc0FzT2JqZWN0KGV2dCk7XG4gICAgICAgIHZhciBsaXN0ZW5lcnM7XG4gICAgICAgIHZhciBsaXN0ZW5lcjtcbiAgICAgICAgdmFyIGk7XG4gICAgICAgIHZhciBrZXk7XG4gICAgICAgIHZhciByZXNwb25zZTtcblxuICAgICAgICBmb3IgKGtleSBpbiBsaXN0ZW5lcnNNYXApIHtcbiAgICAgICAgICAgIGlmIChsaXN0ZW5lcnNNYXAuaGFzT3duUHJvcGVydHkoa2V5KSkge1xuICAgICAgICAgICAgICAgIGxpc3RlbmVycyA9IGxpc3RlbmVyc01hcFtrZXldLnNsaWNlKDApO1xuXG4gICAgICAgICAgICAgICAgZm9yIChpID0gMDsgaSA8IGxpc3RlbmVycy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAvLyBJZiB0aGUgbGlzdGVuZXIgcmV0dXJucyB0cnVlIHRoZW4gaXQgc2hhbGwgYmUgcmVtb3ZlZCBmcm9tIHRoZSBldmVudFxuICAgICAgICAgICAgICAgICAgICAvLyBUaGUgZnVuY3Rpb24gaXMgZXhlY3V0ZWQgZWl0aGVyIHdpdGggYSBiYXNpYyBjYWxsIG9yIGFuIGFwcGx5IGlmIHRoZXJlIGlzIGFuIGFyZ3MgYXJyYXlcbiAgICAgICAgICAgICAgICAgICAgbGlzdGVuZXIgPSBsaXN0ZW5lcnNbaV07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGxpc3RlbmVyLm9uY2UgPT09IHRydWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucmVtb3ZlTGlzdGVuZXIoZXZ0LCBsaXN0ZW5lci5saXN0ZW5lcik7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICByZXNwb25zZSA9IGxpc3RlbmVyLmxpc3RlbmVyLmFwcGx5KHRoaXMsIGFyZ3MgfHwgW10pO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChyZXNwb25zZSA9PT0gdGhpcy5fZ2V0T25jZVJldHVyblZhbHVlKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucmVtb3ZlTGlzdGVuZXIoZXZ0LCBsaXN0ZW5lci5saXN0ZW5lcik7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogQWxpYXMgb2YgZW1pdEV2ZW50XG4gICAgICovXG4gICAgcHJvdG8udHJpZ2dlciA9IGFsaWFzKCdlbWl0RXZlbnQnKTtcblxuICAgIC8qKlxuICAgICAqIFN1YnRseSBkaWZmZXJlbnQgZnJvbSBlbWl0RXZlbnQgaW4gdGhhdCBpdCB3aWxsIHBhc3MgaXRzIGFyZ3VtZW50cyBvbiB0byB0aGUgbGlzdGVuZXJzLCBhcyBvcHBvc2VkIHRvIHRha2luZyBhIHNpbmdsZSBhcnJheSBvZiBhcmd1bWVudHMgdG8gcGFzcyBvbi5cbiAgICAgKiBBcyB3aXRoIGVtaXRFdmVudCwgeW91IGNhbiBwYXNzIGEgcmVnZXggaW4gcGxhY2Ugb2YgdGhlIGV2ZW50IG5hbWUgdG8gZW1pdCB0byBhbGwgZXZlbnRzIHRoYXQgbWF0Y2ggaXQuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1N0cmluZ3xSZWdFeHB9IGV2dCBOYW1lIG9mIHRoZSBldmVudCB0byBlbWl0IGFuZCBleGVjdXRlIGxpc3RlbmVycyBmb3IuXG4gICAgICogQHBhcmFtIHsuLi4qfSBPcHRpb25hbCBhZGRpdGlvbmFsIGFyZ3VtZW50cyB0byBiZSBwYXNzZWQgdG8gZWFjaCBsaXN0ZW5lci5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEN1cnJlbnQgaW5zdGFuY2Ugb2YgRXZlbnRFbWl0dGVyIGZvciBjaGFpbmluZy5cbiAgICAgKi9cbiAgICBwcm90by5lbWl0ID0gZnVuY3Rpb24gZW1pdChldnQpIHtcbiAgICAgICAgdmFyIGFyZ3MgPSBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMsIDEpO1xuICAgICAgICByZXR1cm4gdGhpcy5lbWl0RXZlbnQoZXZ0LCBhcmdzKTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogU2V0cyB0aGUgY3VycmVudCB2YWx1ZSB0byBjaGVjayBhZ2FpbnN0IHdoZW4gZXhlY3V0aW5nIGxpc3RlbmVycy4gSWYgYVxuICAgICAqIGxpc3RlbmVycyByZXR1cm4gdmFsdWUgbWF0Y2hlcyB0aGUgb25lIHNldCBoZXJlIHRoZW4gaXQgd2lsbCBiZSByZW1vdmVkXG4gICAgICogYWZ0ZXIgZXhlY3V0aW9uLiBUaGlzIHZhbHVlIGRlZmF1bHRzIHRvIHRydWUuXG4gICAgICpcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSBuZXcgdmFsdWUgdG8gY2hlY2sgZm9yIHdoZW4gZXhlY3V0aW5nIGxpc3RlbmVycy5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEN1cnJlbnQgaW5zdGFuY2Ugb2YgRXZlbnRFbWl0dGVyIGZvciBjaGFpbmluZy5cbiAgICAgKi9cbiAgICBwcm90by5zZXRPbmNlUmV0dXJuVmFsdWUgPSBmdW5jdGlvbiBzZXRPbmNlUmV0dXJuVmFsdWUodmFsdWUpIHtcbiAgICAgICAgdGhpcy5fb25jZVJldHVyblZhbHVlID0gdmFsdWU7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBGZXRjaGVzIHRoZSBjdXJyZW50IHZhbHVlIHRvIGNoZWNrIGFnYWluc3Qgd2hlbiBleGVjdXRpbmcgbGlzdGVuZXJzLiBJZlxuICAgICAqIHRoZSBsaXN0ZW5lcnMgcmV0dXJuIHZhbHVlIG1hdGNoZXMgdGhpcyBvbmUgdGhlbiBpdCBzaG91bGQgYmUgcmVtb3ZlZFxuICAgICAqIGF1dG9tYXRpY2FsbHkuIEl0IHdpbGwgcmV0dXJuIHRydWUgYnkgZGVmYXVsdC5cbiAgICAgKlxuICAgICAqIEByZXR1cm4geyp8Qm9vbGVhbn0gVGhlIGN1cnJlbnQgdmFsdWUgdG8gY2hlY2sgZm9yIG9yIHRoZSBkZWZhdWx0LCB0cnVlLlxuICAgICAqIEBhcGkgcHJpdmF0ZVxuICAgICAqL1xuICAgIHByb3RvLl9nZXRPbmNlUmV0dXJuVmFsdWUgPSBmdW5jdGlvbiBfZ2V0T25jZVJldHVyblZhbHVlKCkge1xuICAgICAgICBpZiAodGhpcy5oYXNPd25Qcm9wZXJ0eSgnX29uY2VSZXR1cm5WYWx1ZScpKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5fb25jZVJldHVyblZhbHVlO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogRmV0Y2hlcyB0aGUgZXZlbnRzIG9iamVjdCBhbmQgY3JlYXRlcyBvbmUgaWYgcmVxdWlyZWQuXG4gICAgICpcbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IFRoZSBldmVudHMgc3RvcmFnZSBvYmplY3QuXG4gICAgICogQGFwaSBwcml2YXRlXG4gICAgICovXG4gICAgcHJvdG8uX2dldEV2ZW50cyA9IGZ1bmN0aW9uIF9nZXRFdmVudHMoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9ldmVudHMgfHwgKHRoaXMuX2V2ZW50cyA9IHt9KTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogUmV2ZXJ0cyB0aGUgZ2xvYmFsIHtAbGluayBFdmVudEVtaXR0ZXJ9IHRvIGl0cyBwcmV2aW91cyB2YWx1ZSBhbmQgcmV0dXJucyBhIHJlZmVyZW5jZSB0byB0aGlzIHZlcnNpb24uXG4gICAgICpcbiAgICAgKiBAcmV0dXJuIHtGdW5jdGlvbn0gTm9uIGNvbmZsaWN0aW5nIEV2ZW50RW1pdHRlciBjbGFzcy5cbiAgICAgKi9cbiAgICBFdmVudEVtaXR0ZXIubm9Db25mbGljdCA9IGZ1bmN0aW9uIG5vQ29uZmxpY3QoKSB7XG4gICAgICAgIGV4cG9ydHMuRXZlbnRFbWl0dGVyID0gb3JpZ2luYWxHbG9iYWxWYWx1ZTtcbiAgICAgICAgcmV0dXJuIEV2ZW50RW1pdHRlcjtcbiAgICB9O1xuXG4gICAgLy8gRXhwb3NlIHRoZSBjbGFzcyBlaXRoZXIgdmlhIEFNRCwgQ29tbW9uSlMgb3IgdGhlIGdsb2JhbCBvYmplY3RcbiAgICBpZiAodHlwZW9mIGRlZmluZSA9PT0gJ2Z1bmN0aW9uJyAmJiBkZWZpbmUuYW1kKSB7XG4gICAgICAgIGRlZmluZShmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gRXZlbnRFbWl0dGVyO1xuICAgICAgICB9KTtcbiAgICB9XG4gICAgZWxzZSBpZiAodHlwZW9mIG1vZHVsZSA9PT0gJ29iamVjdCcgJiYgbW9kdWxlLmV4cG9ydHMpe1xuICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IEV2ZW50RW1pdHRlcjtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIGV4cG9ydHMuRXZlbnRFbWl0dGVyID0gRXZlbnRFbWl0dGVyO1xuICAgIH1cbn0odHlwZW9mIHdpbmRvdyAhPT0gJ3VuZGVmaW5lZCcgPyB3aW5kb3cgOiB0aGlzIHx8IHt9KSk7XG4iLCJpbXBvcnQgeyBPcGVuVmlkdSB9IGZyb20gJy4vT3BlblZpZHUvT3BlblZpZHUnO1xuXG5pZiAod2luZG93KSB7XG4gICAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lOm5vLXN0cmluZy1saXRlcmFsXG4gICAgd2luZG93WydPcGVuVmlkdSddID0gT3BlblZpZHU7XG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBTZXNzaW9uIH0gZnJvbSAnLi9TZXNzaW9uJztcbmltcG9ydCB7IFN0cmVhbSB9IGZyb20gJy4vU3RyZWFtJztcbmltcG9ydCB7IENvbm5lY3Rpb25PcHRpb25zIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9JbnRlcmZhY2VzL1ByaXZhdGUvQ29ubmVjdGlvbk9wdGlvbnMnO1xuaW1wb3J0IHsgSW5ib3VuZFN0cmVhbU9wdGlvbnMgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHJpdmF0ZS9JbmJvdW5kU3RyZWFtT3B0aW9ucyc7XG5pbXBvcnQgeyBTdHJlYW1PcHRpb25zU2VydmVyIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9JbnRlcmZhY2VzL1ByaXZhdGUvU3RyZWFtT3B0aW9uc1NlcnZlcic7XG5cblxuLyoqXG4gKiBSZXByZXNlbnRzIGVhY2ggb25lIG9mIHRoZSB1c2VyJ3MgY29ubmVjdGlvbiB0byB0aGUgc2Vzc2lvbiAodGhlIGxvY2FsIG9uZSBhbmQgb3RoZXIgdXNlcidzIGNvbm5lY3Rpb25zKS5cbiAqIFRoZXJlZm9yZSBlYWNoIFtbU2Vzc2lvbl1dIGFuZCBbW1N0cmVhbV1dIG9iamVjdCBoYXMgYW4gYXR0cmlidXRlIG9mIHR5cGUgQ29ubmVjdGlvblxuICovXG5leHBvcnQgY2xhc3MgQ29ubmVjdGlvbiB7XG5cbiAgICAvKipcbiAgICAgKiBVbmlxdWUgaWRlbnRpZmllciBvZiB0aGUgY29ubmVjdGlvblxuICAgICAqL1xuICAgIGNvbm5lY3Rpb25JZDogc3RyaW5nO1xuXG4gICAgLyoqXG4gICAgICogVGltZSB3aGVuIHRoaXMgY29ubmVjdGlvbiB3YXMgY3JlYXRlZCAoVVRDIG1pbGxpc2Vjb25kcylcbiAgICAgKi9cbiAgICBjcmVhdGlvblRpbWU6IG51bWJlcjtcblxuICAgIC8qKlxuICAgICAqIERhdGEgYXNzb2NpYXRlZCB0byB0aGlzIGNvbm5lY3Rpb24gKGFuZCB0aGVyZWZvcmUgdG8gY2VydGFpbiB1c2VyKS4gVGhpcyBpcyBhbiBpbXBvcnRhbnQgZmllbGQ6XG4gICAgICogaXQgYWxsb3dzIHlvdSB0byBicm9hZGNhc3QgYWxsIHRoZSBpbmZvcm1hdGlvbiB5b3Ugd2FudCBmb3IgZWFjaCB1c2VyIChhIHVzZXJuYW1lLCBmb3IgZXhhbXBsZSlcbiAgICAgKi9cbiAgICBkYXRhOiBzdHJpbmc7XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgc3RyZWFtOiBTdHJlYW07XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgb3B0aW9uczogQ29ubmVjdGlvbk9wdGlvbnMgfCB1bmRlZmluZWQ7XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgZGlzcG9zZWQgPSBmYWxzZTtcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3Rvcihwcml2YXRlIHNlc3Npb246IFNlc3Npb24sIG9wdHM/OiBDb25uZWN0aW9uT3B0aW9ucykge1xuXG4gICAgICAgIGxldCBtc2cgPSBcIidDb25uZWN0aW9uJyBjcmVhdGVkIFwiO1xuICAgICAgICBpZiAoISFvcHRzKSB7XG4gICAgICAgICAgICBtc2cgKz0gXCIocmVtb3RlKSB3aXRoICdjb25uZWN0aW9uSWQnIFtcIiArIG9wdHMuaWQgKyAnXSc7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBtc2cgKz0gJyhsb2NhbCknO1xuICAgICAgICB9XG4gICAgICAgIGNvbnNvbGUuaW5mbyhtc2cpO1xuXG4gICAgICAgIHRoaXMub3B0aW9ucyA9IG9wdHM7XG5cbiAgICAgICAgaWYgKCEhb3B0cykge1xuICAgICAgICAgICAgLy8gQ29ubmVjdGlvbiBpcyByZW1vdGVcbiAgICAgICAgICAgIHRoaXMuY29ubmVjdGlvbklkID0gb3B0cy5pZDtcbiAgICAgICAgICAgIGlmIChvcHRzLm1ldGFkYXRhKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5kYXRhID0gb3B0cy5tZXRhZGF0YTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChvcHRzLnN0cmVhbXMpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmluaXRSZW1vdGVTdHJlYW1zKG9wdHMuc3RyZWFtcyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLmNyZWF0aW9uVGltZSA9IG5ldyBEYXRlKCkuZ2V0VGltZSgpO1xuICAgIH1cblxuXG4gICAgLyogSGlkZGVuIG1ldGhvZHMgKi9cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBzZW5kSWNlQ2FuZGlkYXRlKGNhbmRpZGF0ZTogUlRDSWNlQ2FuZGlkYXRlKTogdm9pZCB7XG5cbiAgICAgICAgY29uc29sZS5kZWJ1ZygoISF0aGlzLnN0cmVhbS5vdXRib3VuZFN0cmVhbU9wdHMgPyAnTG9jYWwnIDogJ1JlbW90ZScpLCAnY2FuZGlkYXRlIGZvcicsXG4gICAgICAgICAgICB0aGlzLmNvbm5lY3Rpb25JZCwgSlNPTi5zdHJpbmdpZnkoY2FuZGlkYXRlKSk7XG5cbiAgICAgICAgdGhpcy5zZXNzaW9uLm9wZW52aWR1LnNlbmRSZXF1ZXN0KCdvbkljZUNhbmRpZGF0ZScsIHtcbiAgICAgICAgICAgIGVuZHBvaW50TmFtZTogdGhpcy5jb25uZWN0aW9uSWQsXG4gICAgICAgICAgICBjYW5kaWRhdGU6IGNhbmRpZGF0ZS5jYW5kaWRhdGUsXG4gICAgICAgICAgICBzZHBNaWQ6IGNhbmRpZGF0ZS5zZHBNaWQsXG4gICAgICAgICAgICBzZHBNTGluZUluZGV4OiBjYW5kaWRhdGUuc2RwTUxpbmVJbmRleFxuICAgICAgICB9LCAoZXJyb3IsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICBpZiAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKCdFcnJvciBzZW5kaW5nIElDRSBjYW5kaWRhdGU6ICdcbiAgICAgICAgICAgICAgICAgICAgKyBKU09OLnN0cmluZ2lmeShlcnJvcikpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgaW5pdFJlbW90ZVN0cmVhbXMob3B0aW9uczogU3RyZWFtT3B0aW9uc1NlcnZlcltdKTogdm9pZCB7XG5cbiAgICAgICAgLy8gVGhpcyBpcyByZWFkeSBmb3Igc3VwcG9ydGluZyBtdWx0aXBsZSBzdHJlYW1zIHBlciBDb25uZWN0aW9uIG9iamVjdC4gUmlnaHQgbm93IHRoZSBsb29wIHdpbGwgYWx3YXlzIHJ1biBqdXN0IG9uY2VcbiAgICAgICAgLy8gdGhpcy5zdHJlYW0gc2hvdWxkIGFsc28gYmUgcmVwbGFjZWQgYnkgYSBjb2xsZWN0aW9uIG9mIHN0cmVhbXMgdG8gc3VwcG9ydCBtdWx0aXBsZSBzdHJlYW1zIHBlciBDb25uZWN0aW9uXG4gICAgICAgIG9wdGlvbnMuZm9yRWFjaChvcHRzID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHN0cmVhbU9wdGlvbnM6IEluYm91bmRTdHJlYW1PcHRpb25zID0ge1xuICAgICAgICAgICAgICAgIGlkOiBvcHRzLmlkLFxuICAgICAgICAgICAgICAgIGNvbm5lY3Rpb246IHRoaXMsXG4gICAgICAgICAgICAgICAgaGFzQXVkaW86IG9wdHMuaGFzQXVkaW8sXG4gICAgICAgICAgICAgICAgaGFzVmlkZW86IG9wdHMuaGFzVmlkZW8sXG4gICAgICAgICAgICAgICAgYXVkaW9BY3RpdmU6IG9wdHMuYXVkaW9BY3RpdmUsXG4gICAgICAgICAgICAgICAgdmlkZW9BY3RpdmU6IG9wdHMudmlkZW9BY3RpdmUsXG4gICAgICAgICAgICAgICAgdHlwZU9mVmlkZW86IG9wdHMudHlwZU9mVmlkZW8sXG4gICAgICAgICAgICAgICAgZnJhbWVSYXRlOiBvcHRzLmZyYW1lUmF0ZSxcbiAgICAgICAgICAgICAgICB2aWRlb0RpbWVuc2lvbnM6ICEhb3B0cy52aWRlb0RpbWVuc2lvbnMgPyBKU09OLnBhcnNlKG9wdHMudmlkZW9EaW1lbnNpb25zKSA6IHVuZGVmaW5lZFxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGNvbnN0IHN0cmVhbSA9IG5ldyBTdHJlYW0odGhpcy5zZXNzaW9uLCBzdHJlYW1PcHRpb25zKTtcblxuICAgICAgICAgICAgdGhpcy5hZGRTdHJlYW0oc3RyZWFtKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgY29uc29sZS5pbmZvKFwiUmVtb3RlICdDb25uZWN0aW9uJyB3aXRoICdjb25uZWN0aW9uSWQnIFtcIiArIHRoaXMuY29ubmVjdGlvbklkICsgJ10gaXMgbm93IGNvbmZpZ3VyZWQgZm9yIHJlY2VpdmluZyBTdHJlYW1zIHdpdGggb3B0aW9uczogJywgdGhpcy5zdHJlYW0uaW5ib3VuZFN0cmVhbU9wdHMpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBhZGRTdHJlYW0oc3RyZWFtOiBTdHJlYW0pOiB2b2lkIHtcbiAgICAgICAgc3RyZWFtLmNvbm5lY3Rpb24gPSB0aGlzO1xuICAgICAgICB0aGlzLnN0cmVhbSA9IHN0cmVhbTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgcmVtb3ZlU3RyZWFtKHN0cmVhbUlkOiBzdHJpbmcpOiB2b2lkIHtcbiAgICAgICAgZGVsZXRlIHRoaXMuc3RyZWFtO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBkaXNwb3NlKCk6IHZvaWQge1xuICAgICAgICBpZiAoISF0aGlzLnN0cmVhbSkge1xuICAgICAgICAgICAgZGVsZXRlIHRoaXMuc3RyZWFtO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuZGlzcG9zZWQgPSB0cnVlO1xuICAgIH1cblxufSIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTctMjAxOCBPcGVuVmlkdSAoaHR0cHM6Ly9vcGVudmlkdS5pby8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuaW1wb3J0IHsgU3RyZWFtIH0gZnJvbSAnLi9TdHJlYW0nO1xuaW1wb3J0IHsgTG9jYWxSZWNvcmRlclN0YXRlIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FbnVtcy9Mb2NhbFJlY29yZGVyU3RhdGUnO1xuXG4vKipcbiAqIEBoaWRkZW5cbiAqL1xuZGVjbGFyZSB2YXIgTWVkaWFSZWNvcmRlcjogYW55O1xuXG5cbi8qKlxuICogRWFzeSByZWNvcmRpbmcgb2YgW1tTdHJlYW1dXSBvYmplY3RzIHN0cmFpZ2h0YXdheSBmcm9tIHRoZSBicm93c2VyLlxuICpcbiAqID4gV0FSTklORzogUGVyZm9ybWluZyBicm93c2VyIGxvY2FsIHJlY29yZGluZyBvZiAqKnJlbW90ZSBzdHJlYW1zKiogbWF5IGNhdXNlIHNvbWUgdHJvdWJsZXMuIEEgbG9uZyB3YWl0aW5nIHRpbWUgbWF5IGJlIHJlcXVpcmVkIGFmdGVyIGNhbGxpbmcgX0xvY2FsUmVjb3JkZXIuc3RvcCgpXyBpbiB0aGlzIGNhc2VcbiAqL1xuZXhwb3J0IGNsYXNzIExvY2FsUmVjb3JkZXIge1xuXG4gICAgc3RhdGU6IExvY2FsUmVjb3JkZXJTdGF0ZTtcblxuICAgIHByaXZhdGUgY29ubmVjdGlvbklkOiBzdHJpbmc7XG4gICAgcHJpdmF0ZSBtZWRpYVJlY29yZGVyOiBhbnk7XG4gICAgcHJpdmF0ZSBjaHVua3M6IGFueVtdID0gW107XG4gICAgcHJpdmF0ZSBibG9iOiBCbG9iO1xuICAgIHByaXZhdGUgY291bnQgPSAwO1xuICAgIHByaXZhdGUgaWQ6IHN0cmluZztcbiAgICBwcml2YXRlIHZpZGVvUHJldmlld1NyYzogc3RyaW5nO1xuICAgIHByaXZhdGUgaHRtbFBhcmVudEVsZW1lbnRJZDogc3RyaW5nO1xuICAgIHByaXZhdGUgdmlkZW9QcmV2aWV3OiBIVE1MVmlkZW9FbGVtZW50O1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHByaXZhdGUgc3RyZWFtOiBTdHJlYW0pIHtcbiAgICAgICAgdGhpcy5jb25uZWN0aW9uSWQgPSAoISF0aGlzLnN0cmVhbS5jb25uZWN0aW9uKSA/IHRoaXMuc3RyZWFtLmNvbm5lY3Rpb24uY29ubmVjdGlvbklkIDogJ2RlZmF1bHQtY29ubmVjdGlvbic7XG4gICAgICAgIHRoaXMuaWQgPSB0aGlzLnN0cmVhbS5zdHJlYW1JZCArICdfJyArIHRoaXMuY29ubmVjdGlvbklkICsgJ19sb2NhbHJlY29yZCc7XG4gICAgICAgIHRoaXMuc3RhdGUgPSBMb2NhbFJlY29yZGVyU3RhdGUuUkVBRFk7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBTdGFydHMgdGhlIHJlY29yZGluZyBvZiB0aGUgU3RyZWFtLiBbW3N0YXRlXV0gcHJvcGVydHkgbXVzdCBiZSBgUkVBRFlgLiBBZnRlciBtZXRob2Qgc3VjY2VlZHMgaXMgc2V0IHRvIGBSRUNPUkRJTkdgXG4gICAgICogQHJldHVybnMgQSBQcm9taXNlICh0byB3aGljaCB5b3UgY2FuIG9wdGlvbmFsbHkgc3Vic2NyaWJlIHRvKSB0aGF0IGlzIHJlc29sdmVkIGlmIHRoZSByZWNvcmRpbmcgc3VjY2Vzc2Z1bGx5IHN0YXJ0ZWQgYW5kIHJlamVjdGVkIHdpdGggYW4gRXJyb3Igb2JqZWN0IGlmIG5vdFxuICAgICAqL1xuICAgIHJlY29yZCgpOiBQcm9taXNlPGFueT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuXG4gICAgICAgICAgICB0cnkge1xuXG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBNZWRpYVJlY29yZGVyID09PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKCdNZWRpYVJlY29yZGVyIG5vdCBzdXBwb3J0ZWQgb24geW91ciBicm93c2VyLiBTZWUgY29tcGF0aWJpbGl0eSBpbiBodHRwczovL2Nhbml1c2UuY29tLyNzZWFyY2g9TWVkaWFSZWNvcmRlcicpO1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyAoRXJyb3IoJ01lZGlhUmVjb3JkZXIgbm90IHN1cHBvcnRlZCBvbiB5b3VyIGJyb3dzZXIuIFNlZSBjb21wYXRpYmlsaXR5IGluIGh0dHBzOi8vY2FuaXVzZS5jb20vI3NlYXJjaD1NZWRpYVJlY29yZGVyJykpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAodGhpcy5zdGF0ZSAhPT0gTG9jYWxSZWNvcmRlclN0YXRlLlJFQURZKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IChFcnJvcignXFwnTG9jYWxSZWNvcmQucmVjb3JkKClcXCcgbmVlZHMgXFwnTG9jYWxSZWNvcmQuc3RhdGVcXCcgdG8gYmUgXFwnUkVBRFlcXCcgKGN1cnJlbnQgdmFsdWU6IFxcJycgKyB0aGlzLnN0YXRlICsgJ1xcJykuIENhbGwgXFwnTG9jYWxSZWNvcmRlci5jbGVhbigpXFwnIG9yIGluaXQgYSBuZXcgTG9jYWxSZWNvcmRlciBiZWZvcmUnKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKFwiU3RhcnRpbmcgbG9jYWwgcmVjb3JkaW5nIG9mIHN0cmVhbSAnXCIgKyB0aGlzLnN0cmVhbS5zdHJlYW1JZCArIFwiJyBvZiBjb25uZWN0aW9uICdcIiArIHRoaXMuY29ubmVjdGlvbklkICsgXCInXCIpO1xuXG5cbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIE1lZGlhUmVjb3JkZXIuaXNUeXBlU3VwcG9ydGVkID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICAgICAgICAgIGxldCBvcHRpb25zO1xuICAgICAgICAgICAgICAgICAgICBpZiAoTWVkaWFSZWNvcmRlci5pc1R5cGVTdXBwb3J0ZWQoJ3ZpZGVvL3dlYm07Y29kZWNzPXZwOScpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBvcHRpb25zID0geyBtaW1lVHlwZTogJ3ZpZGVvL3dlYm07Y29kZWNzPXZwOScgfTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChNZWRpYVJlY29yZGVyLmlzVHlwZVN1cHBvcnRlZCgndmlkZW8vd2VibTtjb2RlY3M9aDI2NCcpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBvcHRpb25zID0geyBtaW1lVHlwZTogJ3ZpZGVvL3dlYm07Y29kZWNzPWgyNjQnIH07XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoTWVkaWFSZWNvcmRlci5pc1R5cGVTdXBwb3J0ZWQoJ3ZpZGVvL3dlYm07Y29kZWNzPXZwOCcpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBvcHRpb25zID0geyBtaW1lVHlwZTogJ3ZpZGVvL3dlYm07Y29kZWNzPXZwOCcgfTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmxvZygnVXNpbmcgbWltZVR5cGUgJyArIG9wdGlvbnMubWltZVR5cGUpO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLm1lZGlhUmVjb3JkZXIgPSBuZXcgTWVkaWFSZWNvcmRlcih0aGlzLnN0cmVhbS5nZXRNZWRpYVN0cmVhbSgpLCBvcHRpb25zKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLndhcm4oJ2lzVHlwZVN1cHBvcnRlZCBpcyBub3Qgc3VwcG9ydGVkLCB1c2luZyBkZWZhdWx0IGNvZGVjcyBmb3IgYnJvd3NlcicpO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLm1lZGlhUmVjb3JkZXIgPSBuZXcgTWVkaWFSZWNvcmRlcih0aGlzLnN0cmVhbS5nZXRNZWRpYVN0cmVhbSgpKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB0aGlzLm1lZGlhUmVjb3JkZXIuc3RhcnQoMTApO1xuXG4gICAgICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAgICAgICByZWplY3QoZXJyKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5tZWRpYVJlY29yZGVyLm9uZGF0YWF2YWlsYWJsZSA9IChlKSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5jaHVua3MucHVzaChlLmRhdGEpO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgdGhpcy5tZWRpYVJlY29yZGVyLm9uZXJyb3IgPSAoZSkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ01lZGlhUmVjb3JkZXIgZXJyb3I6ICcsIGUpO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgdGhpcy5tZWRpYVJlY29yZGVyLm9uc3RhcnQgPSAoKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5sb2coJ01lZGlhUmVjb3JkZXIgc3RhcnRlZCAoc3RhdGU9JyArIHRoaXMubWVkaWFSZWNvcmRlci5zdGF0ZSArICcpJyk7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICB0aGlzLm1lZGlhUmVjb3JkZXIub25zdG9wID0gKCkgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMub25TdG9wRGVmYXVsdCgpO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgdGhpcy5tZWRpYVJlY29yZGVyLm9ucGF1c2UgPSAoKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5sb2coJ01lZGlhUmVjb3JkZXIgcGF1c2VkIChzdGF0ZT0nICsgdGhpcy5tZWRpYVJlY29yZGVyLnN0YXRlICsgJyknKTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIHRoaXMubWVkaWFSZWNvcmRlci5vbnJlc3VtZSA9ICgpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmxvZygnTWVkaWFSZWNvcmRlciByZXN1bWVkIChzdGF0ZT0nICsgdGhpcy5tZWRpYVJlY29yZGVyLnN0YXRlICsgJyknKTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIHRoaXMubWVkaWFSZWNvcmRlci5vbndhcm5pbmcgPSAoZSkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKCdNZWRpYVJlY29yZGVyIHdhcm5pbmc6ICcgKyBlKTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIHRoaXMuc3RhdGUgPSBMb2NhbFJlY29yZGVyU3RhdGUuUkVDT1JESU5HO1xuICAgICAgICAgICAgcmVzb2x2ZSgpO1xuXG4gICAgICAgIH0pO1xuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogRW5kcyB0aGUgcmVjb3JkaW5nIG9mIHRoZSBTdHJlYW0uIFtbc3RhdGVdXSBwcm9wZXJ0eSBtdXN0IGJlIGBSRUNPUkRJTkdgIG9yIGBQQVVTRURgLiBBZnRlciBtZXRob2Qgc3VjY2VlZHMgaXMgc2V0IHRvIGBGSU5JU0hFRGBcbiAgICAgKiBAcmV0dXJucyBBIFByb21pc2UgKHRvIHdoaWNoIHlvdSBjYW4gb3B0aW9uYWxseSBzdWJzY3JpYmUgdG8pIHRoYXQgaXMgcmVzb2x2ZWQgaWYgdGhlIHJlY29yZGluZyBzdWNjZXNzZnVsbHkgc3RvcHBlZCBhbmQgcmVqZWN0ZWQgd2l0aCBhbiBFcnJvciBvYmplY3QgaWYgbm90XG4gICAgICovXG4gICAgc3RvcCgpOiBQcm9taXNlPGFueT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5zdGF0ZSA9PT0gTG9jYWxSZWNvcmRlclN0YXRlLlJFQURZIHx8IHRoaXMuc3RhdGUgPT09IExvY2FsUmVjb3JkZXJTdGF0ZS5GSU5JU0hFRCkge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyAoRXJyb3IoJ1xcJ0xvY2FsUmVjb3JkLnN0b3AoKVxcJyBuZWVkcyBcXCdMb2NhbFJlY29yZC5zdGF0ZVxcJyB0byBiZSBcXCdSRUNPUkRJTkdcXCcgb3IgXFwnUEFVU0VEXFwnIChjdXJyZW50IHZhbHVlOiBcXCcnICsgdGhpcy5zdGF0ZSArICdcXCcpLiBDYWxsIFxcJ0xvY2FsUmVjb3JkZXIuc3RhcnQoKVxcJyBiZWZvcmUnKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRoaXMubWVkaWFSZWNvcmRlci5vbnN0b3AgPSAoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMub25TdG9wRGVmYXVsdCgpO1xuICAgICAgICAgICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB0aGlzLm1lZGlhUmVjb3JkZXIuc3RvcCgpO1xuICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICAgIHJlamVjdChlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBQYXVzZXMgdGhlIHJlY29yZGluZyBvZiB0aGUgU3RyZWFtLiBbW3N0YXRlXV0gcHJvcGVydHkgbXVzdCBiZSBgUkVDT1JESU5HYC4gQWZ0ZXIgbWV0aG9kIHN1Y2NlZWRzIGlzIHNldCB0byBgUEFVU0VEYFxuICAgICAqIEByZXR1cm5zIEEgUHJvbWlzZSAodG8gd2hpY2ggeW91IGNhbiBvcHRpb25hbGx5IHN1YnNjcmliZSB0bykgdGhhdCBpcyByZXNvbHZlZCBpZiB0aGUgcmVjb3JkaW5nIHdhcyBzdWNjZXNzZnVsbHkgcGF1c2VkIGFuZCByZWplY3RlZCB3aXRoIGFuIEVycm9yIG9iamVjdCBpZiBub3RcbiAgICAgKi9cbiAgICBwYXVzZSgpOiBQcm9taXNlPGFueT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5zdGF0ZSAhPT0gTG9jYWxSZWNvcmRlclN0YXRlLlJFQ09SRElORykge1xuICAgICAgICAgICAgICAgICAgICByZWplY3QoRXJyb3IoJ1xcJ0xvY2FsUmVjb3JkLnBhdXNlKClcXCcgbmVlZHMgXFwnTG9jYWxSZWNvcmQuc3RhdGVcXCcgdG8gYmUgXFwnUkVDT1JESU5HXFwnIChjdXJyZW50IHZhbHVlOiBcXCcnICsgdGhpcy5zdGF0ZSArICdcXCcpLiBDYWxsIFxcJ0xvY2FsUmVjb3JkZXIuc3RhcnQoKVxcJyBvciBcXCdMb2NhbFJlY29yZGVyLnJlc3VtZSgpXFwnIGJlZm9yZScpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhpcy5tZWRpYVJlY29yZGVyLnBhdXNlKCk7XG4gICAgICAgICAgICAgICAgdGhpcy5zdGF0ZSA9IExvY2FsUmVjb3JkZXJTdGF0ZS5QQVVTRUQ7XG4gICAgICAgICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlc3VtZXMgdGhlIHJlY29yZGluZyBvZiB0aGUgU3RyZWFtLiBbW3N0YXRlXV0gcHJvcGVydHkgbXVzdCBiZSBgUEFVU0VEYC4gQWZ0ZXIgbWV0aG9kIHN1Y2NlZWRzIGlzIHNldCB0byBgUkVDT1JESU5HYFxuICAgICAqIEByZXR1cm5zIEEgUHJvbWlzZSAodG8gd2hpY2ggeW91IGNhbiBvcHRpb25hbGx5IHN1YnNjcmliZSB0bykgdGhhdCBpcyByZXNvbHZlZCBpZiB0aGUgcmVjb3JkaW5nIHdhcyBzdWNjZXNzZnVsbHkgcmVzdW1lZCBhbmQgcmVqZWN0ZWQgd2l0aCBhbiBFcnJvciBvYmplY3QgaWYgbm90XG4gICAgICovXG4gICAgcmVzdW1lKCk6IFByb21pc2U8YW55PiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLnN0YXRlICE9PSBMb2NhbFJlY29yZGVyU3RhdGUuUEFVU0VEKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IChFcnJvcignXFwnTG9jYWxSZWNvcmQucmVzdW1lKClcXCcgbmVlZHMgXFwnTG9jYWxSZWNvcmQuc3RhdGVcXCcgdG8gYmUgXFwnUEFVU0VEXFwnIChjdXJyZW50IHZhbHVlOiBcXCcnICsgdGhpcy5zdGF0ZSArICdcXCcpLiBDYWxsIFxcJ0xvY2FsUmVjb3JkZXIucGF1c2UoKVxcJyBiZWZvcmUnKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRoaXMubWVkaWFSZWNvcmRlci5yZXN1bWUoKTtcbiAgICAgICAgICAgICAgICB0aGlzLnN0YXRlID0gTG9jYWxSZWNvcmRlclN0YXRlLlJFQ09SRElORztcbiAgICAgICAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBQcmV2aWV3cyB0aGUgcmVjb3JkaW5nLCBhcHBlbmRpbmcgYSBuZXcgSFRNTFZpZGVvRWxlbWVudCB0byBlbGVtZW50IHdpdGggaWQgYHBhcmVudElkYC4gW1tzdGF0ZV1dIHByb3BlcnR5IG11c3QgYmUgYEZJTklTSEVEYFxuICAgICAqL1xuICAgIHByZXZpZXcocGFyZW50RWxlbWVudCk6IEhUTUxWaWRlb0VsZW1lbnQge1xuXG4gICAgICAgIGlmICh0aGlzLnN0YXRlICE9PSBMb2NhbFJlY29yZGVyU3RhdGUuRklOSVNIRUQpIHtcbiAgICAgICAgICAgIHRocm93IChFcnJvcignXFwnTG9jYWxSZWNvcmQucHJldmlldygpXFwnIG5lZWRzIFxcJ0xvY2FsUmVjb3JkLnN0YXRlXFwnIHRvIGJlIFxcJ0ZJTklTSEVEXFwnIChjdXJyZW50IHZhbHVlOiBcXCcnICsgdGhpcy5zdGF0ZSArICdcXCcpLiBDYWxsIFxcJ0xvY2FsUmVjb3JkZXIuc3RvcCgpXFwnIGJlZm9yZScpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMudmlkZW9QcmV2aWV3ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgndmlkZW8nKTtcblxuICAgICAgICB0aGlzLnZpZGVvUHJldmlldy5pZCA9IHRoaXMuaWQ7XG4gICAgICAgIHRoaXMudmlkZW9QcmV2aWV3LmF1dG9wbGF5ID0gdHJ1ZTtcblxuICAgICAgICBpZiAodHlwZW9mIHBhcmVudEVsZW1lbnQgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICB0aGlzLmh0bWxQYXJlbnRFbGVtZW50SWQgPSBwYXJlbnRFbGVtZW50O1xuXG4gICAgICAgICAgICBjb25zdCBwYXJlbnRFbGVtZW50RG9tID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQocGFyZW50RWxlbWVudCk7XG4gICAgICAgICAgICBpZiAocGFyZW50RWxlbWVudERvbSkge1xuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9QcmV2aWV3ID0gcGFyZW50RWxlbWVudERvbS5hcHBlbmRDaGlsZCh0aGlzLnZpZGVvUHJldmlldyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLmh0bWxQYXJlbnRFbGVtZW50SWQgPSBwYXJlbnRFbGVtZW50LmlkO1xuICAgICAgICAgICAgdGhpcy52aWRlb1ByZXZpZXcgPSBwYXJlbnRFbGVtZW50LmFwcGVuZENoaWxkKHRoaXMudmlkZW9QcmV2aWV3KTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMudmlkZW9QcmV2aWV3LnNyYyA9IHRoaXMudmlkZW9QcmV2aWV3U3JjO1xuXG4gICAgICAgIHJldHVybiB0aGlzLnZpZGVvUHJldmlldztcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIEdyYWNlZnVsbHkgc3RvcHMgYW5kIGNsZWFucyB0aGUgY3VycmVudCByZWNvcmRpbmcgKFdBUk5JTkc6IGl0IGlzIGNvbXBsZXRlbHkgZGlzbWlzc2VkKS4gU2V0cyBbW3N0YXRlXV0gdG8gYFJFQURZYCBzbyB0aGUgcmVjb3JkaW5nIGNhbiBzdGFydCBhZ2FpblxuICAgICAqL1xuICAgIGNsZWFuKCk6IHZvaWQge1xuICAgICAgICBjb25zdCBmID0gKCkgPT4ge1xuICAgICAgICAgICAgZGVsZXRlIHRoaXMuYmxvYjtcbiAgICAgICAgICAgIHRoaXMuY2h1bmtzID0gW107XG4gICAgICAgICAgICB0aGlzLmNvdW50ID0gMDtcbiAgICAgICAgICAgIGRlbGV0ZSB0aGlzLm1lZGlhUmVjb3JkZXI7XG4gICAgICAgICAgICB0aGlzLnN0YXRlID0gTG9jYWxSZWNvcmRlclN0YXRlLlJFQURZO1xuICAgICAgICB9O1xuICAgICAgICBpZiAodGhpcy5zdGF0ZSA9PT0gTG9jYWxSZWNvcmRlclN0YXRlLlJFQ09SRElORyB8fCB0aGlzLnN0YXRlID09PSBMb2NhbFJlY29yZGVyU3RhdGUuUEFVU0VEKSB7XG4gICAgICAgICAgICB0aGlzLnN0b3AoKS50aGVuKCgpID0+IGYoKSkuY2F0Y2goKCkgPT4gZigpKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGYoKTtcbiAgICAgICAgfVxuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogRG93bmxvYWRzIHRoZSByZWNvcmRlZCB2aWRlbyB0aHJvdWdoIHRoZSBicm93c2VyLiBbW3N0YXRlXV0gcHJvcGVydHkgbXVzdCBiZSBgRklOSVNIRURgXG4gICAgICovXG4gICAgZG93bmxvYWQoKTogdm9pZCB7XG4gICAgICAgIGlmICh0aGlzLnN0YXRlICE9PSBMb2NhbFJlY29yZGVyU3RhdGUuRklOSVNIRUQpIHtcbiAgICAgICAgICAgIHRocm93IChFcnJvcignXFwnTG9jYWxSZWNvcmQuZG93bmxvYWQoKVxcJyBuZWVkcyBcXCdMb2NhbFJlY29yZC5zdGF0ZVxcJyB0byBiZSBcXCdGSU5JU0hFRFxcJyAoY3VycmVudCB2YWx1ZTogXFwnJyArIHRoaXMuc3RhdGUgKyAnXFwnKS4gQ2FsbCBcXCdMb2NhbFJlY29yZGVyLnN0b3AoKVxcJyBiZWZvcmUnKSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjb25zdCBhOiBIVE1MQW5jaG9yRWxlbWVudCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2EnKTtcbiAgICAgICAgICAgIGEuc3R5bGUuZGlzcGxheSA9ICdub25lJztcbiAgICAgICAgICAgIGRvY3VtZW50LmJvZHkuYXBwZW5kQ2hpbGQoYSk7XG5cbiAgICAgICAgICAgIGNvbnN0IHVybCA9IHdpbmRvdy5VUkwuY3JlYXRlT2JqZWN0VVJMKHRoaXMuYmxvYik7XG4gICAgICAgICAgICBhLmhyZWYgPSB1cmw7XG4gICAgICAgICAgICBhLmRvd25sb2FkID0gdGhpcy5pZCArICcud2VibSc7XG4gICAgICAgICAgICBhLmNsaWNrKCk7XG4gICAgICAgICAgICB3aW5kb3cuVVJMLnJldm9rZU9iamVjdFVSTCh1cmwpO1xuXG4gICAgICAgICAgICBkb2N1bWVudC5ib2R5LnJlbW92ZUNoaWxkKGEpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0cyB0aGUgcmF3IEJsb2IgZmlsZS4gTWV0aG9kcyBwcmV2aWV3LCBkb3dubG9hZCwgdXBsb2FkQXNCaW5hcnkgYW5kIHVwbG9hZEFzTXVsdGlwYXJ0ZmlsZSB1c2UgdGhpcyBzYW1lIGZpbGUgdG8gcGVyZm9ybSB0aGVpciBzcGVjaWZpYyBhY3Rpb25zLiBbW3N0YXRlXV0gcHJvcGVydHkgbXVzdCBiZSBgRklOSVNIRURgXG4gICAgICovXG4gICAgZ2V0QmxvYigpOiBCbG9iIHtcbiAgICAgICAgaWYgKHRoaXMuc3RhdGUgIT09IExvY2FsUmVjb3JkZXJTdGF0ZS5GSU5JU0hFRCkge1xuICAgICAgICAgICAgdGhyb3cgKEVycm9yKCdDYWxsIFxcJ0xvY2FsUmVjb3JkLnN0b3AoKVxcJyBiZWZvcmUgZ2V0dGluZyBCbG9iIGZpbGUnKSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5ibG9iO1xuICAgICAgICB9XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBVcGxvYWRzIHRoZSByZWNvcmRlZCB2aWRlbyBhcyBhIGJpbmFyeSBmaWxlIHBlcmZvcm1pbmcgYW4gSFRUUC9QT1NUIG9wZXJhdGlvbiB0byBVUkwgYGVuZHBvaW50YC4gW1tzdGF0ZV1dIHByb3BlcnR5IG11c3QgYmUgYEZJTklTSEVEYC4gT3B0aW9uYWwgSFRUUCBoZWFkZXJzIGNhbiBiZSBwYXNzZWQgYXMgc2Vjb25kIHBhcmFtZXRlci4gRm9yIGV4YW1wbGU6XG4gICAgICogYGBgXG4gICAgICogdmFyIGhlYWRlcnMgPSB7XG4gICAgICogIFwiQ29va2llXCI6IFwiJFZlcnNpb249MTsgU2tpbj1uZXc7XCIsXG4gICAgICogIFwiQXV0aG9yaXphdGlvblwiOlwiQmFzaWMgUVd4aFpHcGJqcHVJSE5sY3RaUT09XCJcbiAgICAgKiB9XG4gICAgICogYGBgXG4gICAgICogQHJldHVybnMgQSBQcm9taXNlICh0byB3aGljaCB5b3UgY2FuIG9wdGlvbmFsbHkgc3Vic2NyaWJlIHRvKSB0aGF0IGlzIHJlc29sdmVkIHdpdGggdGhlIGBodHRwLnJlc3BvbnNlVGV4dGAgZnJvbSBzZXJ2ZXIgaWYgdGhlIG9wZXJhdGlvbiB3YXMgc3VjY2Vzc2Z1bCBhbmQgcmVqZWN0ZWQgd2l0aCB0aGUgZmFpbGVkIGBodHRwLnN0YXR1c2AgaWYgbm90XG4gICAgICovXG4gICAgdXBsb2FkQXNCaW5hcnkoZW5kcG9pbnQ6IHN0cmluZywgaGVhZGVycz86IGFueSk6IFByb21pc2U8YW55PiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICBpZiAodGhpcy5zdGF0ZSAhPT0gTG9jYWxSZWNvcmRlclN0YXRlLkZJTklTSEVEKSB7XG4gICAgICAgICAgICAgICAgcmVqZWN0KEVycm9yKCdcXCdMb2NhbFJlY29yZC51cGxvYWRBc0JpbmFyeSgpXFwnIG5lZWRzIFxcJ0xvY2FsUmVjb3JkLnN0YXRlXFwnIHRvIGJlIFxcJ0ZJTklTSEVEXFwnIChjdXJyZW50IHZhbHVlOiBcXCcnICsgdGhpcy5zdGF0ZSArICdcXCcpLiBDYWxsIFxcJ0xvY2FsUmVjb3JkZXIuc3RvcCgpXFwnIGJlZm9yZScpKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY29uc3QgaHR0cCA9IG5ldyBYTUxIdHRwUmVxdWVzdCgpO1xuICAgICAgICAgICAgICAgIGh0dHAub3BlbignUE9TVCcsIGVuZHBvaW50LCB0cnVlKTtcblxuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgaGVhZGVycyA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgICAgICAgICAgICAgZm9yIChjb25zdCBrZXkgb2YgT2JqZWN0LmtleXMoaGVhZGVycykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGh0dHAuc2V0UmVxdWVzdEhlYWRlcihrZXksIGhlYWRlcnNba2V5XSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBodHRwLm9ucmVhZHlzdGF0ZWNoYW5nZSA9ICgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGh0dHAucmVhZHlTdGF0ZSA9PT0gNCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGh0dHAuc3RhdHVzLnRvU3RyaW5nKCkuY2hhckF0KDApID09PSAnMicpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBTdWNjZXNzIHJlc3BvbnNlIGZyb20gc2VydmVyIChIVFRQIHN0YXR1cyBzdGFuZGFyZDogMlhYIGlzIHN1Y2Nlc3MpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZShodHRwLnJlc3BvbnNlVGV4dCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChodHRwLnN0YXR1cyk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIGh0dHAuc2VuZCh0aGlzLmJsb2IpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFVwbG9hZHMgdGhlIHJlY29yZGVkIHZpZGVvIGFzIGEgbXVsdGlwYXJ0IGZpbGUgcGVyZm9ybWluZyBhbiBIVFRQL1BPU1Qgb3BlcmF0aW9uIHRvIFVSTCBgZW5kcG9pbnRgLiBbW3N0YXRlXV0gcHJvcGVydHkgbXVzdCBiZSBgRklOSVNIRURgLiBPcHRpb25hbCBIVFRQIGhlYWRlcnMgY2FuIGJlIHBhc3NlZCBhcyBzZWNvbmQgcGFyYW1ldGVyLiBGb3IgZXhhbXBsZTpcbiAgICAgKiBgYGBcbiAgICAgKiB2YXIgaGVhZGVycyA9IHtcbiAgICAgKiAgXCJDb29raWVcIjogXCIkVmVyc2lvbj0xOyBTa2luPW5ldztcIixcbiAgICAgKiAgXCJBdXRob3JpemF0aW9uXCI6XCJCYXNpYyBRV3hoWkdwYmpwdUlITmxjdFpRPT1cIlxuICAgICAqIH1cbiAgICAgKiBgYGBcbiAgICAgKiBAcmV0dXJucyBBIFByb21pc2UgKHRvIHdoaWNoIHlvdSBjYW4gb3B0aW9uYWxseSBzdWJzY3JpYmUgdG8pIHRoYXQgaXMgcmVzb2x2ZWQgd2l0aCB0aGUgYGh0dHAucmVzcG9uc2VUZXh0YCBmcm9tIHNlcnZlciBpZiB0aGUgb3BlcmF0aW9uIHdhcyBzdWNjZXNzZnVsIGFuZCByZWplY3RlZCB3aXRoIHRoZSBmYWlsZWQgYGh0dHAuc3RhdHVzYCBpZiBub3Q6XG4gICAgICovXG4gICAgdXBsb2FkQXNNdWx0aXBhcnRmaWxlKGVuZHBvaW50OiBzdHJpbmcsIGhlYWRlcnM/OiBhbnkpOiBQcm9taXNlPGFueT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgaWYgKHRoaXMuc3RhdGUgIT09IExvY2FsUmVjb3JkZXJTdGF0ZS5GSU5JU0hFRCkge1xuICAgICAgICAgICAgICAgIHJlamVjdChFcnJvcignXFwnTG9jYWxSZWNvcmQudXBsb2FkQXNNdWx0aXBhcnRmaWxlKClcXCcgbmVlZHMgXFwnTG9jYWxSZWNvcmQuc3RhdGVcXCcgdG8gYmUgXFwnRklOSVNIRURcXCcgKGN1cnJlbnQgdmFsdWU6IFxcJycgKyB0aGlzLnN0YXRlICsgJ1xcJykuIENhbGwgXFwnTG9jYWxSZWNvcmRlci5zdG9wKClcXCcgYmVmb3JlJykpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBjb25zdCBodHRwID0gbmV3IFhNTEh0dHBSZXF1ZXN0KCk7XG4gICAgICAgICAgICAgICAgaHR0cC5vcGVuKCdQT1NUJywgZW5kcG9pbnQsIHRydWUpO1xuXG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBoZWFkZXJzID09PSAnb2JqZWN0Jykge1xuICAgICAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IGtleSBvZiBPYmplY3Qua2V5cyhoZWFkZXJzKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaHR0cC5zZXRSZXF1ZXN0SGVhZGVyKGtleSwgaGVhZGVyc1trZXldKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGNvbnN0IHNlbmRhYmxlID0gbmV3IEZvcm1EYXRhKCk7XG4gICAgICAgICAgICAgICAgc2VuZGFibGUuYXBwZW5kKCdmaWxlJywgdGhpcy5ibG9iLCB0aGlzLmlkICsgJy53ZWJtJyk7XG5cbiAgICAgICAgICAgICAgICBodHRwLm9ucmVhZHlzdGF0ZWNoYW5nZSA9ICgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGh0dHAucmVhZHlTdGF0ZSA9PT0gNCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGh0dHAuc3RhdHVzLnRvU3RyaW5nKCkuY2hhckF0KDApID09PSAnMicpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBTdWNjZXNzIHJlc3BvbnNlIGZyb20gc2VydmVyIChIVFRQIHN0YXR1cyBzdGFuZGFyZDogMlhYIGlzIHN1Y2Nlc3MpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZShodHRwLnJlc3BvbnNlVGV4dCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChodHRwLnN0YXR1cyk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICAgICAgaHR0cC5zZW5kKHNlbmRhYmxlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG5cbiAgICAvKiBQcml2YXRlIG1ldGhvZHMgKi9cblxuICAgIHByaXZhdGUgb25TdG9wRGVmYXVsdCgpOiB2b2lkIHtcbiAgICAgICAgY29uc29sZS5sb2coJ01lZGlhUmVjb3JkZXIgc3RvcHBlZCAgKHN0YXRlPScgKyB0aGlzLm1lZGlhUmVjb3JkZXIuc3RhdGUgKyAnKScpO1xuXG4gICAgICAgIHRoaXMuYmxvYiA9IG5ldyBCbG9iKHRoaXMuY2h1bmtzLCB7IHR5cGU6ICd2aWRlby93ZWJtJyB9KTtcbiAgICAgICAgdGhpcy5jaHVua3MgPSBbXTtcblxuICAgICAgICB0aGlzLnZpZGVvUHJldmlld1NyYyA9IHdpbmRvdy5VUkwuY3JlYXRlT2JqZWN0VVJMKHRoaXMuYmxvYik7XG5cbiAgICAgICAgdGhpcy5zdGF0ZSA9IExvY2FsUmVjb3JkZXJTdGF0ZS5GSU5JU0hFRDtcbiAgICB9XG5cbn1cbiIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTctMjAxOCBPcGVuVmlkdSAoaHR0cHM6Ly9vcGVudmlkdS5pby8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuaW1wb3J0IHsgTG9jYWxSZWNvcmRlciB9IGZyb20gJy4vTG9jYWxSZWNvcmRlcic7XG5pbXBvcnQgeyBQdWJsaXNoZXIgfSBmcm9tICcuL1B1Ymxpc2hlcic7XG5pbXBvcnQgeyBTZXNzaW9uIH0gZnJvbSAnLi9TZXNzaW9uJztcbmltcG9ydCB7IFN0cmVhbSB9IGZyb20gJy4vU3RyZWFtJztcbmltcG9ydCB7IFN0cmVhbVByb3BlcnR5Q2hhbmdlZEV2ZW50IH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvU3RyZWFtUHJvcGVydHlDaGFuZ2VkRXZlbnQnO1xuaW1wb3J0IHsgRGV2aWNlIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9JbnRlcmZhY2VzL1B1YmxpYy9EZXZpY2UnO1xuaW1wb3J0IHsgT3BlblZpZHVBZHZhbmNlZENvbmZpZ3VyYXRpb24gfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHVibGljL09wZW5WaWR1QWR2YW5jZWRDb25maWd1cmF0aW9uJztcbmltcG9ydCB7IFB1Ymxpc2hlclByb3BlcnRpZXMgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHVibGljL1B1Ymxpc2hlclByb3BlcnRpZXMnO1xuaW1wb3J0IHsgT3BlblZpZHVFcnJvciwgT3BlblZpZHVFcnJvck5hbWUgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0VudW1zL09wZW5WaWR1RXJyb3InO1xuaW1wb3J0IHsgVmlkZW9JbnNlcnRNb2RlIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FbnVtcy9WaWRlb0luc2VydE1vZGUnO1xuXG5pbXBvcnQgKiBhcyBzY3JlZW5TaGFyaW5nQXV0byBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL1NjcmVlblNoYXJpbmcvU2NyZWVuLUNhcHR1cmluZy1BdXRvJztcbmltcG9ydCAqIGFzIHNjcmVlblNoYXJpbmcgZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9TY3JlZW5TaGFyaW5nL1NjcmVlbi1DYXB0dXJpbmcnO1xuXG5pbXBvcnQgUnBjQnVpbGRlciA9IHJlcXVpcmUoJy4uL09wZW5WaWR1SW50ZXJuYWwvS3VyZW50b1V0aWxzL2t1cmVudG8tanNvbnJwYycpO1xuaW1wb3J0IHBsYXRmb3JtID0gcmVxdWlyZSgncGxhdGZvcm0nKTtcblxuXG4vKipcbiAqIEVudHJ5cG9pbnQgb2YgT3BlblZpZHUgQnJvd3NlciBsaWJyYXJ5LlxuICogVXNlIGl0IHRvIGluaXRpYWxpemUgb2JqZWN0cyBvZiB0eXBlIFtbU2Vzc2lvbl1dLCBbW1B1Ymxpc2hlcl1dIGFuZCBbW0xvY2FsUmVjb3JkZXJdXVxuICovXG5leHBvcnQgY2xhc3MgT3BlblZpZHUge1xuXG4gIHByaXZhdGUganNvblJwY0NsaWVudDogYW55O1xuXG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICBzZXNzaW9uOiBTZXNzaW9uO1xuICAvKipcbiAgICogQGhpZGRlblxuICAgKi9cbiAgcHVibGlzaGVyczogUHVibGlzaGVyW10gPSBbXTtcbiAgLyoqXG4gICAqIEBoaWRkZW5cbiAgICovXG4gIHdzVXJpOiBzdHJpbmc7XG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICBzZWNyZXQgPSAnJztcbiAgLyoqXG4gICAqIEBoaWRkZW5cbiAgICovXG4gIHJlY29yZGVyID0gZmFsc2U7XG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICBpY2VTZXJ2ZXJzOiBSVENJY2VTZXJ2ZXJbXTtcbiAgLyoqXG4gICAqIEBoaWRkZW5cbiAgICovXG4gIHJvbGU6IHN0cmluZztcbiAgLyoqXG4gICAqIEBoaWRkZW5cbiAgICovXG4gIGFkdmFuY2VkQ29uZmlndXJhdGlvbjogT3BlblZpZHVBZHZhbmNlZENvbmZpZ3VyYXRpb24gPSB7fTtcblxuICBjb25zdHJ1Y3RvcigpIHtcbiAgICBjb25zb2xlLmluZm8oXCInT3BlblZpZHUnIGluaXRpYWxpemVkXCIpO1xuXG4gICAgaWYgKHBsYXRmb3JtLm5hbWUhIS50b0xvd2VyQ2FzZSgpLmluZGV4T2YoJ21vYmlsZScpICE9PSAtMSkge1xuICAgICAgLy8gTGlzdGVuIHRvIG9yaWVudGF0aW9uY2hhbmdlIG9ubHkgb24gbW9iaWxlIGJyb3dzZXJzXG4gICAgICAoPGFueT53aW5kb3cpLm9ub3JpZW50YXRpb25jaGFuZ2UgPSAoKSA9PiB7XG4gICAgICAgIHRoaXMucHVibGlzaGVycy5mb3JFYWNoKHB1Ymxpc2hlciA9PiB7XG4gICAgICAgICAgaWYgKCEhcHVibGlzaGVyLnN0cmVhbSAmJiAhIXB1Ymxpc2hlci5zdHJlYW0uaGFzVmlkZW8gJiYgISFwdWJsaXNoZXIuc3RyZWFtLnN0cmVhbU1hbmFnZXIudmlkZW9zWzBdKSB7XG5cbiAgICAgICAgICAgIGxldCBhdHRlbXB0cyA9IDA7XG5cbiAgICAgICAgICAgIGNvbnN0IG9sZFdpZHRoID0gcHVibGlzaGVyLnN0cmVhbS52aWRlb0RpbWVuc2lvbnMud2lkdGg7XG4gICAgICAgICAgICBjb25zdCBvbGRIZWlnaHQgPSBwdWJsaXNoZXIuc3RyZWFtLnZpZGVvRGltZW5zaW9ucy5oZWlnaHQ7XG4gICAgICAgICAgICAvLyBOZXcgcmVzb2x1dGlvbiBnb3QgZnJvbSBkaWZmZXJlbnQgcGxhY2VzIGZvciBDaHJvbWUgYW5kIEZpcmVmb3guIENocm9tZSBuZWVkcyBhIHZpZGVvV2lkdGggYW5kIHZpZGVvSGVpZ2h0IG9mIGEgdmlkZW9FbGVtZW50LlxuICAgICAgICAgICAgLy8gRmlyZWZveCBuZWVkcyBnZXRTZXR0aW5ncyBmcm9tIHRoZSB2aWRlb1RyYWNrXG4gICAgICAgICAgICBsZXQgZmlyZWZveFNldHRpbmdzID0gcHVibGlzaGVyLnN0cmVhbS5nZXRNZWRpYVN0cmVhbSgpLmdldFZpZGVvVHJhY2tzKClbMF0uZ2V0U2V0dGluZ3MoKTtcbiAgICAgICAgICAgIGxldCBuZXdXaWR0aCA9IChwbGF0Zm9ybS5uYW1lISEudG9Mb3dlckNhc2UoKS5pbmRleE9mKCdmaXJlZm94JykgIT09IC0xKSA/IGZpcmVmb3hTZXR0aW5ncy53aWR0aCA6IHB1Ymxpc2hlci52aWRlb1JlZmVyZW5jZS52aWRlb1dpZHRoO1xuICAgICAgICAgICAgbGV0IG5ld0hlaWdodCA9IChwbGF0Zm9ybS5uYW1lISEudG9Mb3dlckNhc2UoKS5pbmRleE9mKCdmaXJlZm94JykgIT09IC0xKSA/IGZpcmVmb3hTZXR0aW5ncy5oZWlnaHQgOiBwdWJsaXNoZXIudmlkZW9SZWZlcmVuY2UudmlkZW9IZWlnaHQ7XG5cbiAgICAgICAgICAgIGNvbnN0IHJlcGVhdFVudGlsQ2hhbmdlID0gc2V0SW50ZXJ2YWwoKCkgPT4ge1xuICAgICAgICAgICAgICBmaXJlZm94U2V0dGluZ3MgPSBwdWJsaXNoZXIuc3RyZWFtLmdldE1lZGlhU3RyZWFtKCkuZ2V0VmlkZW9UcmFja3MoKVswXS5nZXRTZXR0aW5ncygpO1xuICAgICAgICAgICAgICBuZXdXaWR0aCA9IChwbGF0Zm9ybS5uYW1lISEudG9Mb3dlckNhc2UoKS5pbmRleE9mKCdmaXJlZm94JykgIT09IC0xKSA/IGZpcmVmb3hTZXR0aW5ncy53aWR0aCA6IHB1Ymxpc2hlci52aWRlb1JlZmVyZW5jZS52aWRlb1dpZHRoO1xuICAgICAgICAgICAgICBuZXdIZWlnaHQgPSAocGxhdGZvcm0ubmFtZSEhLnRvTG93ZXJDYXNlKCkuaW5kZXhPZignZmlyZWZveCcpICE9PSAtMSkgPyBmaXJlZm94U2V0dGluZ3MuaGVpZ2h0IDogcHVibGlzaGVyLnZpZGVvUmVmZXJlbmNlLnZpZGVvSGVpZ2h0O1xuICAgICAgICAgICAgICBzZW5kU3RyZWFtUHJvcGVydHlDaGFuZ2VkRXZlbnQob2xkV2lkdGgsIG9sZEhlaWdodCwgbmV3V2lkdGgsIG5ld0hlaWdodCk7XG4gICAgICAgICAgICB9LCAxMDApO1xuXG4gICAgICAgICAgICBjb25zdCBzZW5kU3RyZWFtUHJvcGVydHlDaGFuZ2VkRXZlbnQgPSAob2xkV2lkdGgsIG9sZEhlaWdodCwgbmV3V2lkdGgsIG5ld0hlaWdodCkgPT4ge1xuICAgICAgICAgICAgICBhdHRlbXB0cysrO1xuICAgICAgICAgICAgICBpZiAoYXR0ZW1wdHMgPiA0KSB7XG4gICAgICAgICAgICAgICAgY2xlYXJUaW1lb3V0KHJlcGVhdFVudGlsQ2hhbmdlKTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICBpZiAobmV3V2lkdGggIT09IG9sZFdpZHRoIHx8IG5ld0hlaWdodCAhPT0gb2xkSGVpZ2h0KSB7XG4gICAgICAgICAgICAgICAgcHVibGlzaGVyLnN0cmVhbS52aWRlb0RpbWVuc2lvbnMgPSB7XG4gICAgICAgICAgICAgICAgICB3aWR0aDogbmV3V2lkdGggfHwgMCxcbiAgICAgICAgICAgICAgICAgIGhlaWdodDogbmV3SGVpZ2h0IHx8IDBcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIHRoaXMuc2VuZFJlcXVlc3QoXG4gICAgICAgICAgICAgICAgICAnc3RyZWFtUHJvcGVydHlDaGFuZ2VkJyxcbiAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgc3RyZWFtSWQ6IHB1Ymxpc2hlci5zdHJlYW0uc3RyZWFtSWQsXG4gICAgICAgICAgICAgICAgICAgIHByb3BlcnR5OiAndmlkZW9EaW1lbnNpb25zJyxcbiAgICAgICAgICAgICAgICAgICAgbmV3VmFsdWU6IEpTT04uc3RyaW5naWZ5KHB1Ymxpc2hlci5zdHJlYW0udmlkZW9EaW1lbnNpb25zKSxcbiAgICAgICAgICAgICAgICAgICAgcmVhc29uOiAnZGV2aWNlUm90YXRlZCdcbiAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAoZXJyb3IsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoXCJFcnJvciBzZW5kaW5nICdzdHJlYW1Qcm9wZXJ0eUNoYW5nZWQnIGV2ZW50XCIsIGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICB0aGlzLnNlc3Npb24uZW1pdEV2ZW50KCdzdHJlYW1Qcm9wZXJ0eUNoYW5nZWQnLCBbbmV3IFN0cmVhbVByb3BlcnR5Q2hhbmdlZEV2ZW50KHRoaXMuc2Vzc2lvbiwgcHVibGlzaGVyLnN0cmVhbSwgJ3ZpZGVvRGltZW5zaW9ucycsIHB1Ymxpc2hlci5zdHJlYW0udmlkZW9EaW1lbnNpb25zLCB7IHdpZHRoOiBvbGRXaWR0aCwgaGVpZ2h0OiBvbGRIZWlnaHQgfSwgJ2RldmljZVJvdGF0ZWQnKV0pO1xuICAgICAgICAgICAgICAgICAgICAgIHB1Ymxpc2hlci5lbWl0RXZlbnQoJ3N0cmVhbVByb3BlcnR5Q2hhbmdlZCcsIFtuZXcgU3RyZWFtUHJvcGVydHlDaGFuZ2VkRXZlbnQocHVibGlzaGVyLCBwdWJsaXNoZXIuc3RyZWFtLCAndmlkZW9EaW1lbnNpb25zJywgcHVibGlzaGVyLnN0cmVhbS52aWRlb0RpbWVuc2lvbnMsIHsgd2lkdGg6IG9sZFdpZHRoLCBoZWlnaHQ6IG9sZEhlaWdodCB9LCAnZGV2aWNlUm90YXRlZCcpXSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIGNsZWFyVGltZW91dChyZXBlYXRVbnRpbENoYW5nZSk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH07XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgIH07XG4gICAgfVxuICB9XG5cblxuICAvKipcbiAgICogUmV0dXJucyBuZXcgc2Vzc2lvblxuICAgKi9cbiAgaW5pdFNlc3Npb24oKTogU2Vzc2lvbiB7XG4gICAgdGhpcy5zZXNzaW9uID0gbmV3IFNlc3Npb24odGhpcyk7XG4gICAgcmV0dXJuIHRoaXMuc2Vzc2lvbjtcbiAgfVxuXG5cbiAgaW5pdFB1Ymxpc2hlcih0YXJnZXRFbGVtZW50OiBzdHJpbmcgfCBIVE1MRWxlbWVudCk6IFB1Ymxpc2hlcjtcbiAgaW5pdFB1Ymxpc2hlcih0YXJnZXRFbGVtZW50OiBzdHJpbmcgfCBIVE1MRWxlbWVudCwgcHJvcGVydGllczogUHVibGlzaGVyUHJvcGVydGllcyk6IFB1Ymxpc2hlcjtcbiAgaW5pdFB1Ymxpc2hlcih0YXJnZXRFbGVtZW50OiBzdHJpbmcgfCBIVE1MRWxlbWVudCwgY29tcGxldGlvbkhhbmRsZXI6IChlcnJvcjogRXJyb3IgfCB1bmRlZmluZWQpID0+IHZvaWQpOiBQdWJsaXNoZXI7XG4gIGluaXRQdWJsaXNoZXIodGFyZ2V0RWxlbWVudDogc3RyaW5nIHwgSFRNTEVsZW1lbnQsIHByb3BlcnRpZXM6IFB1Ymxpc2hlclByb3BlcnRpZXMsIGNvbXBsZXRpb25IYW5kbGVyOiAoZXJyb3I6IEVycm9yIHwgdW5kZWZpbmVkKSA9PiB2b2lkKTogUHVibGlzaGVyO1xuXG4gIC8qKlxuICAgKiBSZXR1cm5zIGEgbmV3IHB1Ymxpc2hlclxuICAgKlxuICAgKiAjIyMjIEV2ZW50cyBkaXNwYXRjaGVkXG4gICAqXG4gICAqIFRoZSBbW1B1Ymxpc2hlcl1dIG9iamVjdCB3aWxsIGRpc3BhdGNoIGFuIGBhY2Nlc3NEaWFsb2dPcGVuZWRgIGV2ZW50LCBvbmx5IGlmIHRoZSBwb3AtdXAgc2hvd24gYnkgdGhlIGJyb3dzZXIgdG8gcmVxdWVzdCBwZXJtaXNzaW9ucyBmb3IgdGhlIGNhbWVyYSBpcyBvcGVuZWQuIFlvdSBjYW4gdXNlIHRoaXMgZXZlbnQgdG8gYWxlcnQgdGhlIHVzZXIgYWJvdXQgZ3JhbnRpbmcgcGVybWlzc2lvbnNcbiAgICogZm9yIHlvdXIgd2Vic2l0ZS4gQW4gYGFjY2Vzc0RpYWxvZ0Nsb3NlZGAgZXZlbnQgd2lsbCBhbHNvIGJlIGRpc3BhdGNoZWQgYWZ0ZXIgdXNlciBjbGlja3Mgb24gXCJBbGxvd1wiIG9yIFwiQmxvY2tcIiBpbiB0aGUgcG9wLXVwLlxuICAgKlxuICAgKiBUaGUgW1tQdWJsaXNoZXJdXSBvYmplY3Qgd2lsbCBkaXNwYXRjaCBhbiBgYWNjZXNzQWxsb3dlZGAgb3IgYGFjY2Vzc0RlbmllZGAgZXZlbnQgb25jZSBpdCBoYXMgYmVlbiBncmFudGVkIGFjY2VzcyB0byB0aGUgcmVxdWVzdGVkIGlucHV0IGRldmljZXMgb3Igbm90LlxuICAgKlxuICAgKiBUaGUgW1tQdWJsaXNoZXJdXSBvYmplY3Qgd2lsbCBkaXNwYXRjaCBhIGB2aWRlb0VsZW1lbnRDcmVhdGVkYCBldmVudCBvbmNlIGEgSFRNTCB2aWRlbyBlbGVtZW50IGhhcyBiZWVuIGFkZGVkIHRvIERPTSAob25seSBpZiB5b3VcbiAgICogW2xldCBPcGVuVmlkdSB0YWtlIGNhcmUgb2YgdGhlIHZpZGVvIHBsYXllcnNdKC9kb2NzL2hvdy1kby1pL21hbmFnZS12aWRlb3MvI2xldC1vcGVudmlkdS10YWtlLWNhcmUtb2YtdGhlLXZpZGVvLXBsYXllcnMpKS4gU2VlIFtbVmlkZW9FbGVtZW50RXZlbnRdXSB0byBsZWFybiBtb3JlLlxuICAgKlxuICAgKiBUaGUgW1tQdWJsaXNoZXJdXSBvYmplY3Qgd2lsbCBkaXNwYXRjaCBhIGBzdHJlYW1QbGF5aW5nYCBldmVudCBvbmNlIHRoZSBsb2NhbCBzdHJlYW1zIHN0YXJ0cyBwbGF5aW5nLiBTZWUgW1tTdHJlYW1NYW5hZ2VyRXZlbnRdXSB0byBsZWFybiBtb3JlLlxuICAgKlxuICAgKiBAcGFyYW0gdGFyZ2V0RWxlbWVudCAgSFRNTCBET00gZWxlbWVudCAob3IgaXRzIGBpZGAgYXR0cmlidXRlKSBpbiB3aGljaCB0aGUgdmlkZW8gZWxlbWVudCBvZiB0aGUgUHVibGlzaGVyIHdpbGwgYmUgaW5zZXJ0ZWQgKHNlZSBbW1B1Ymxpc2hlclByb3BlcnRpZXMuaW5zZXJ0TW9kZV1dKS4gSWYgKm51bGwqIG9yICp1bmRlZmluZWQqIG5vIGRlZmF1bHQgdmlkZW8gd2lsbCBiZSBjcmVhdGVkIGZvciB0aGlzIFB1Ymxpc2hlci5cbiAgICogWW91IGNhbiBhbHdheXMgY2FsbCBtZXRob2QgW1tQdWJsaXNoZXIuYWRkVmlkZW9FbGVtZW50XV0gb3IgW1tQdWJsaXNoZXIuY3JlYXRlVmlkZW9FbGVtZW50XV0gdG8gbWFuYWdlIHRoZSB2aWRlbyBlbGVtZW50cyBvbiB5b3VyIG93biAoc2VlIFtNYW5hZ2UgdmlkZW8gcGxheWVyc10oL2RvY3MvaG93LWRvLWkvbWFuYWdlLXZpZGVvcykgc2VjdGlvbilcbiAgICogQHBhcmFtIGNvbXBsZXRpb25IYW5kbGVyIGBlcnJvcmAgcGFyYW1ldGVyIGlzIG51bGwgaWYgYGluaXRQdWJsaXNoZXJgIHN1Y2NlZWRzLCBhbmQgaXMgZGVmaW5lZCBpZiBpdCBmYWlscy5cbiAgICogICAgICAgICAgICAgICAgICAgICAgICAgIGBjb21wbGV0aW9uSGFuZGxlcmAgZnVuY3Rpb24gaXMgY2FsbGVkIGJlZm9yZSB0aGUgUHVibGlzaGVyIGRpc3BhdGNoZXMgYW4gYGFjY2Vzc0FsbG93ZWRgIG9yIGFuIGBhY2Nlc3NEZW5pZWRgIGV2ZW50XG4gICAqL1xuICBpbml0UHVibGlzaGVyKHRhcmdldEVsZW1lbnQ6IHN0cmluZyB8IEhUTUxFbGVtZW50LCBwYXJhbTI/LCBwYXJhbTM/KTogUHVibGlzaGVyIHtcblxuICAgIGxldCBwcm9wZXJ0aWVzOiBQdWJsaXNoZXJQcm9wZXJ0aWVzO1xuXG4gICAgaWYgKCEhcGFyYW0yICYmICh0eXBlb2YgcGFyYW0yICE9PSAnZnVuY3Rpb24nKSkge1xuXG4gICAgICAvLyBNYXRjaGVzICdpbml0UHVibGlzaGVyKHRhcmdldEVsZW1lbnQsIHByb3BlcnRpZXMpJyBvciAnaW5pdFB1Ymxpc2hlcih0YXJnZXRFbGVtZW50LCBwcm9wZXJ0aWVzLCBjb21wbGV0aW9uSGFuZGxlciknXG5cbiAgICAgIHByb3BlcnRpZXMgPSAoPFB1Ymxpc2hlclByb3BlcnRpZXM+cGFyYW0yKTtcblxuICAgICAgcHJvcGVydGllcyA9IHtcbiAgICAgICAgYXVkaW9Tb3VyY2U6ICh0eXBlb2YgcHJvcGVydGllcy5hdWRpb1NvdXJjZSAhPT0gJ3VuZGVmaW5lZCcpID8gcHJvcGVydGllcy5hdWRpb1NvdXJjZSA6IHVuZGVmaW5lZCxcbiAgICAgICAgZnJhbWVSYXRlOiB0aGlzLmlzTWVkaWFTdHJlYW1UcmFjayhwcm9wZXJ0aWVzLnZpZGVvU291cmNlKSA/IHVuZGVmaW5lZCA6ICgodHlwZW9mIHByb3BlcnRpZXMuZnJhbWVSYXRlICE9PSAndW5kZWZpbmVkJykgPyBwcm9wZXJ0aWVzLmZyYW1lUmF0ZSA6IHVuZGVmaW5lZCksXG4gICAgICAgIGluc2VydE1vZGU6ICh0eXBlb2YgcHJvcGVydGllcy5pbnNlcnRNb2RlICE9PSAndW5kZWZpbmVkJykgPyAoKHR5cGVvZiBwcm9wZXJ0aWVzLmluc2VydE1vZGUgPT09ICdzdHJpbmcnKSA/IFZpZGVvSW5zZXJ0TW9kZVtwcm9wZXJ0aWVzLmluc2VydE1vZGVdIDogcHJvcGVydGllcy5pbnNlcnRNb2RlKSA6IFZpZGVvSW5zZXJ0TW9kZS5BUFBFTkQsXG4gICAgICAgIG1pcnJvcjogKHR5cGVvZiBwcm9wZXJ0aWVzLm1pcnJvciAhPT0gJ3VuZGVmaW5lZCcpID8gcHJvcGVydGllcy5taXJyb3IgOiB0cnVlLFxuICAgICAgICBwdWJsaXNoQXVkaW86ICh0eXBlb2YgcHJvcGVydGllcy5wdWJsaXNoQXVkaW8gIT09ICd1bmRlZmluZWQnKSA/IHByb3BlcnRpZXMucHVibGlzaEF1ZGlvIDogdHJ1ZSxcbiAgICAgICAgcHVibGlzaFZpZGVvOiAodHlwZW9mIHByb3BlcnRpZXMucHVibGlzaFZpZGVvICE9PSAndW5kZWZpbmVkJykgPyBwcm9wZXJ0aWVzLnB1Ymxpc2hWaWRlbyA6IHRydWUsXG4gICAgICAgIHJlc29sdXRpb246IHRoaXMuaXNNZWRpYVN0cmVhbVRyYWNrKHByb3BlcnRpZXMudmlkZW9Tb3VyY2UpID8gdW5kZWZpbmVkIDogKCh0eXBlb2YgcHJvcGVydGllcy5yZXNvbHV0aW9uICE9PSAndW5kZWZpbmVkJykgPyBwcm9wZXJ0aWVzLnJlc29sdXRpb24gOiAnNjQweDQ4MCcpLFxuICAgICAgICB2aWRlb1NvdXJjZTogKHR5cGVvZiBwcm9wZXJ0aWVzLnZpZGVvU291cmNlICE9PSAndW5kZWZpbmVkJykgPyBwcm9wZXJ0aWVzLnZpZGVvU291cmNlIDogdW5kZWZpbmVkXG4gICAgICB9O1xuICAgIH0gZWxzZSB7XG5cbiAgICAgIC8vIE1hdGNoZXMgJ2luaXRQdWJsaXNoZXIodGFyZ2V0RWxlbWVudCknIG9yICdpbml0UHVibGlzaGVyKHRhcmdldEVsZW1lbnQsIGNvbXBsZXRpb25IYW5kbGVyKSdcblxuICAgICAgcHJvcGVydGllcyA9IHtcbiAgICAgICAgaW5zZXJ0TW9kZTogVmlkZW9JbnNlcnRNb2RlLkFQUEVORCxcbiAgICAgICAgbWlycm9yOiB0cnVlLFxuICAgICAgICBwdWJsaXNoQXVkaW86IHRydWUsXG4gICAgICAgIHB1Ymxpc2hWaWRlbzogdHJ1ZSxcbiAgICAgICAgcmVzb2x1dGlvbjogJzY0MHg0ODAnXG4gICAgICB9O1xuICAgIH1cblxuICAgIGNvbnN0IHB1Ymxpc2hlcjogUHVibGlzaGVyID0gbmV3IFB1Ymxpc2hlcih0YXJnZXRFbGVtZW50LCBwcm9wZXJ0aWVzLCB0aGlzKTtcblxuICAgIGxldCBjb21wbGV0aW9uSGFuZGxlcjogKGVycm9yOiBFcnJvciB8IHVuZGVmaW5lZCkgPT4gdm9pZDtcbiAgICBpZiAoISFwYXJhbTIgJiYgKHR5cGVvZiBwYXJhbTIgPT09ICdmdW5jdGlvbicpKSB7XG4gICAgICBjb21wbGV0aW9uSGFuZGxlciA9IHBhcmFtMjtcbiAgICB9IGVsc2UgaWYgKCEhcGFyYW0zKSB7XG4gICAgICBjb21wbGV0aW9uSGFuZGxlciA9IHBhcmFtMztcbiAgICB9XG5cbiAgICBwdWJsaXNoZXIuaW5pdGlhbGl6ZSgpXG4gICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgIGlmIChjb21wbGV0aW9uSGFuZGxlciAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgY29tcGxldGlvbkhhbmRsZXIodW5kZWZpbmVkKTtcbiAgICAgICAgfVxuICAgICAgICBwdWJsaXNoZXIuZW1pdEV2ZW50KCdhY2Nlc3NBbGxvd2VkJywgW10pO1xuICAgICAgfSkuY2F0Y2goKGVycm9yKSA9PiB7XG4gICAgICAgIGlmIChjb21wbGV0aW9uSGFuZGxlciAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgY29tcGxldGlvbkhhbmRsZXIoZXJyb3IpO1xuICAgICAgICB9XG4gICAgICAgIHB1Ymxpc2hlci5lbWl0RXZlbnQoJ2FjY2Vzc0RlbmllZCcsIFtdKTtcbiAgICAgIH0pO1xuXG4gICAgdGhpcy5wdWJsaXNoZXJzLnB1c2gocHVibGlzaGVyKTtcbiAgICByZXR1cm4gcHVibGlzaGVyO1xuICB9XG5cblxuICAvKipcbiAgICogUHJvbWlzaWZpZWQgdmVyc2lvbiBvZiBbW09wZW5WaWR1LmluaXRQdWJsaXNoZXJdXVxuICAgKlxuICAgKiA+IFdBUk5JTkc6IGV2ZW50cyBgYWNjZXNzRGlhbG9nT3BlbmVkYCBhbmQgYGFjY2Vzc0RpYWxvZ0Nsb3NlZGAgd2lsbCBub3QgYmUgZGlzcGF0Y2hlZCBpZiB1c2luZyB0aGlzIG1ldGhvZCBpbnN0ZWFkIG9mIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dXG4gICAqL1xuICBpbml0UHVibGlzaGVyQXN5bmModGFyZ2V0RWxlbWVudDogc3RyaW5nIHwgSFRNTEVsZW1lbnQpOiBQcm9taXNlPFB1Ymxpc2hlcj47XG4gIGluaXRQdWJsaXNoZXJBc3luYyh0YXJnZXRFbGVtZW50OiBzdHJpbmcgfCBIVE1MRWxlbWVudCwgcHJvcGVydGllczogUHVibGlzaGVyUHJvcGVydGllcyk6IFByb21pc2U8UHVibGlzaGVyPjtcblxuICBpbml0UHVibGlzaGVyQXN5bmModGFyZ2V0RWxlbWVudDogc3RyaW5nIHwgSFRNTEVsZW1lbnQsIHByb3BlcnRpZXM/OiBQdWJsaXNoZXJQcm9wZXJ0aWVzKTogUHJvbWlzZTxQdWJsaXNoZXI+IHtcbiAgICByZXR1cm4gbmV3IFByb21pc2U8UHVibGlzaGVyPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG5cbiAgICAgIGxldCBwdWJsaXNoZXI6IFB1Ymxpc2hlcjtcblxuICAgICAgY29uc3QgY2FsbGJhY2sgPSAoZXJyb3I6IEVycm9yKSA9PiB7XG4gICAgICAgIGlmICghIWVycm9yKSB7XG4gICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICByZXNvbHZlKHB1Ymxpc2hlcik7XG4gICAgICAgIH1cbiAgICAgIH07XG5cbiAgICAgIGlmICghIXByb3BlcnRpZXMpIHtcbiAgICAgICAgcHVibGlzaGVyID0gdGhpcy5pbml0UHVibGlzaGVyKHRhcmdldEVsZW1lbnQsIHByb3BlcnRpZXMsIGNhbGxiYWNrKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHB1Ymxpc2hlciA9IHRoaXMuaW5pdFB1Ymxpc2hlcih0YXJnZXRFbGVtZW50LCBjYWxsYmFjayk7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIGEgbmV3IGxvY2FsIHJlY29yZGVyIGZvciByZWNvcmRpbmcgc3RyZWFtcyBzdHJhaWdodCBhd2F5IGZyb20gdGhlIGJyb3dzZXJcbiAgICogQHBhcmFtIHN0cmVhbSAgU3RyZWFtIHRvIHJlY29yZFxuICAgKi9cbiAgaW5pdExvY2FsUmVjb3JkZXIoc3RyZWFtOiBTdHJlYW0pOiBMb2NhbFJlY29yZGVyIHtcbiAgICByZXR1cm4gbmV3IExvY2FsUmVjb3JkZXIoc3RyZWFtKTtcbiAgfVxuXG5cbiAgLyoqXG4gICAqIENoZWNrcyBpZiB0aGUgYnJvd3NlciBzdXBwb3J0cyBPcGVuVmlkdVxuICAgKiBAcmV0dXJucyAxIGlmIHRoZSBicm93c2VyIHN1cHBvcnRzIE9wZW5WaWR1LCAwIG90aGVyd2lzZVxuICAgKi9cbiAgY2hlY2tTeXN0ZW1SZXF1aXJlbWVudHMoKTogbnVtYmVyIHtcbiAgICBjb25zdCBicm93c2VyID0gcGxhdGZvcm0ubmFtZTtcbiAgICBjb25zdCB2ZXJzaW9uID0gcGxhdGZvcm0udmVyc2lvbjtcblxuICAgIGlmICgoYnJvd3NlciAhPT0gJ0Nocm9tZScpICYmIChicm93c2VyICE9PSAnQ2hyb21lIE1vYmlsZScpICYmXG4gICAgICAoYnJvd3NlciAhPT0gJ0ZpcmVmb3gnKSAmJiAoYnJvd3NlciAhPT0gJ0ZpcmVmb3ggTW9iaWxlJykgJiYgKGJyb3dzZXIgIT09ICdGaXJlZm94IGZvciBpT1MnKSAmJlxuICAgICAgKGJyb3dzZXIgIT09ICdPcGVyYScpICYmIChicm93c2VyICE9PSAnT3BlcmEgTW9iaWxlJykgJiZcbiAgICAgIChicm93c2VyICE9PSAnU2FmYXJpJykpIHtcbiAgICAgIHJldHVybiAwO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gMTtcbiAgICB9XG4gIH1cblxuXG4gIC8qKlxuICAgKiBDb2xsZWN0cyBpbmZvcm1hdGlvbiBhYm91dCB0aGUgbWVkaWEgaW5wdXQgZGV2aWNlcyBhdmFpbGFibGUgb24gdGhlIHN5c3RlbS4gWW91IGNhbiBwYXNzIHByb3BlcnR5IGBkZXZpY2VJZGAgb2YgYSBbW0RldmljZV1dIG9iamVjdCBhcyB2YWx1ZSBvZiBgYXVkaW9Tb3VyY2VgIG9yIGB2aWRlb1NvdXJjZWAgcHJvcGVydGllcyBpbiBbW2luaXRQdWJsaXNoZXJdXSBtZXRob2RcbiAgICovXG4gIGdldERldmljZXMoKTogUHJvbWlzZTxEZXZpY2VbXT4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZTxEZXZpY2VbXT4oKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgbmF2aWdhdG9yLm1lZGlhRGV2aWNlcy5lbnVtZXJhdGVEZXZpY2VzKCkudGhlbigoZGV2aWNlSW5mb3MpID0+IHtcbiAgICAgICAgY29uc3QgZGV2aWNlczogRGV2aWNlW10gPSBbXTtcbiAgICAgICAgZGV2aWNlSW5mb3MuZm9yRWFjaChkZXZpY2VJbmZvID0+IHtcbiAgICAgICAgICBpZiAoZGV2aWNlSW5mby5raW5kID09PSAnYXVkaW9pbnB1dCcgfHwgZGV2aWNlSW5mby5raW5kID09PSAndmlkZW9pbnB1dCcpIHtcbiAgICAgICAgICAgIGRldmljZXMucHVzaCh7XG4gICAgICAgICAgICAgIGtpbmQ6IGRldmljZUluZm8ua2luZCxcbiAgICAgICAgICAgICAgZGV2aWNlSWQ6IGRldmljZUluZm8uZGV2aWNlSWQsXG4gICAgICAgICAgICAgIGxhYmVsOiBkZXZpY2VJbmZvLmxhYmVsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICByZXNvbHZlKGRldmljZXMpO1xuICAgICAgfSkuY2F0Y2goKGVycm9yKSA9PiB7XG4gICAgICAgIGNvbnNvbGUuZXJyb3IoJ0Vycm9yIGdldHRpbmcgZGV2aWNlcycsIGVycm9yKTtcbiAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9XG5cblxuICAvKipcbiAgICogR2V0IGEgTWVkaWFTdHJlYW0gb2JqZWN0IHRoYXQgeW91IGNhbiBjdXN0b21pemUgYmVmb3JlIGNhbGxpbmcgW1tpbml0UHVibGlzaGVyXV0gKHBhc3MgX01lZGlhU3RyZWFtVHJhY2tfIHByb3BlcnR5IG9mIHRoZSBfTWVkaWFTdHJlYW1fIHZhbHVlIHJlc29sdmVkIGJ5IHRoZSBQcm9taXNlIGFzIGBhdWRpb1NvdXJjZWAgb3IgYHZpZGVvU291cmNlYCBwcm9wZXJ0aWVzIGluIFtbaW5pdFB1Ymxpc2hlcl1dKVxuICAgKlxuICAgKiBQYXJhbWV0ZXIgYG9wdGlvbnNgIGlzIHRoZSBzYW1lIGFzIGluIFtbaW5pdFB1Ymxpc2hlcl1dIHNlY29uZCBwYXJhbWV0ZXIgKG9mIHR5cGUgW1tQdWJsaXNoZXJQcm9wZXJ0aWVzXV0pLCBidXQgb25seSB0aGUgZm9sbG93aW5nIHByb3BlcnRpZXMgd2lsbCBiZSBhcHBsaWVkOiBgYXVkaW9Tb3VyY2VgLCBgdmlkZW9Tb3VyY2VgLCBgZnJhbWVSYXRlYCwgYHJlc29sdXRpb25gXG4gICAqXG4gICAqIFRvIGN1c3RvbWl6ZSB0aGUgUHVibGlzaGVyJ3MgdmlkZW8sIHRoZSBBUEkgZm9yIEhUTUxDYW52YXNFbGVtZW50IGlzIHZlcnkgdXNlZnVsLiBGb3IgZXhhbXBsZSwgdG8gZ2V0IGEgYmxhY2stYW5kLXdoaXRlIHZpZGVvIGF0IDEwIGZwcyBhbmQgSEQgcmVzb2x1dGlvbiB3aXRoIG5vIHNvdW5kOlxuICAgKiBgYGBcbiAgICogdmFyIE9WID0gbmV3IE9wZW5WaWR1KCk7XG4gICAqIHZhciBGUkFNRV9SQVRFID0gMTA7XG4gICAqXG4gICAqIE9WLmdldFVzZXJNZWRpYSh7XG4gICAqICAgIGF1ZGlvU291cmNlOiBmYWxzZTtcbiAgICogICAgdmlkZW9Tb3VyY2U6IHVuZGVmaW5lZCxcbiAgICogICAgcmVzb2x1dGlvbjogJzEyODB4NzIwJyxcbiAgICogICAgZnJhbWVSYXRlOiBGUkFNRV9SQVRFXG4gICAqIH0pXG4gICAqIC50aGVuKG1lZGlhU3RyZWFtID0+IHtcbiAgICpcbiAgICogICAgdmFyIHZpZGVvVHJhY2sgPSBtZWRpYVN0cmVhbS5nZXRWaWRlb1RyYWNrcygpWzBdO1xuICAgKiAgICB2YXIgdmlkZW8gPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCd2aWRlbycpO1xuICAgKiAgICB2aWRlby5zcmNPYmplY3QgPSBuZXcgTWVkaWFTdHJlYW0oW3ZpZGVvVHJhY2tdKTtcbiAgICpcbiAgICogICAgdmFyIGNhbnZhcyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2NhbnZhcycpO1xuICAgKiAgICB2YXIgY3R4ID0gY2FudmFzLmdldENvbnRleHQoJzJkJyk7XG4gICAqICAgIGN0eC5maWx0ZXIgPSAnZ3JheXNjYWxlKDEwMCUpJztcbiAgICpcbiAgICogICAgdmlkZW8uYWRkRXZlbnRMaXN0ZW5lcigncGxheScsICgpID0+IHtcbiAgICogICAgICB2YXIgbG9vcCA9ICgpID0+IHtcbiAgICogICAgICAgIGlmICghdmlkZW8ucGF1c2VkICYmICF2aWRlby5lbmRlZCkge1xuICAgKiAgICAgICAgICBjdHguZHJhd0ltYWdlKHZpZGVvLCAwLCAwLCAzMDAsIDE3MCk7XG4gICAqICAgICAgICAgIHNldFRpbWVvdXQobG9vcCwgMTAwMC8gRlJBTUVfUkFURSk7IC8vIERyYXdpbmcgYXQgMTAgZnBzXG4gICAqICAgICAgICB9XG4gICAqICAgICAgfTtcbiAgICogICAgICBsb29wKCk7XG4gICAqICAgIH0pO1xuICAgKiAgICB2aWRlby5wbGF5KCk7XG4gICAqXG4gICAqICAgIHZhciBncmF5VmlkZW9UcmFjayA9IGNhbnZhcy5jYXB0dXJlU3RyZWFtKEZSQU1FX1JBVEUpLmdldFZpZGVvVHJhY2tzKClbMF07XG4gICAqICAgIHZhciBwdWJsaXNoZXIgPSB0aGlzLk9WLmluaXRQdWJsaXNoZXIoXG4gICAqICAgICAgbXlIdG1sVGFyZ2V0LFxuICAgKiAgICAgIHtcbiAgICogICAgICAgIGF1ZGlvU291cmNlOiBmYWxzZSxcbiAgICogICAgICAgIHZpZGVvU291cmNlOiBncmF5VmlkZW9UcmFja1xuICAgKiAgICAgIH0pO1xuICAgKiB9KTtcbiAgICogYGBgXG4gICAqL1xuICBnZXRVc2VyTWVkaWEob3B0aW9uczogUHVibGlzaGVyUHJvcGVydGllcyk6IFByb21pc2U8TWVkaWFTdHJlYW0+IHtcbiAgICByZXR1cm4gbmV3IFByb21pc2U8TWVkaWFTdHJlYW0+KChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIHRoaXMuZ2VuZXJhdGVNZWRpYUNvbnN0cmFpbnRzKG9wdGlvbnMpXG4gICAgICAgIC50aGVuKGNvbnN0cmFpbnRzID0+IHtcbiAgICAgICAgICBuYXZpZ2F0b3IubWVkaWFEZXZpY2VzLmdldFVzZXJNZWRpYShjb25zdHJhaW50cylcbiAgICAgICAgICAgIC50aGVuKG1lZGlhU3RyZWFtID0+IHtcbiAgICAgICAgICAgICAgcmVzb2x2ZShtZWRpYVN0cmVhbSk7XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICAgICAgbGV0IGVycm9yTmFtZTogT3BlblZpZHVFcnJvck5hbWU7XG4gICAgICAgICAgICAgIGNvbnN0IGVycm9yTWVzc2FnZSA9IGVycm9yLnRvU3RyaW5nKCk7XG4gICAgICAgICAgICAgIGlmICghKG9wdGlvbnMudmlkZW9Tb3VyY2UgPT09ICdzY3JlZW4nKSkge1xuICAgICAgICAgICAgICAgIGVycm9yTmFtZSA9IE9wZW5WaWR1RXJyb3JOYW1lLkRFVklDRV9BQ0NFU1NfREVOSUVEO1xuICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGVycm9yTmFtZSA9IE9wZW5WaWR1RXJyb3JOYW1lLlNDUkVFTl9DQVBUVVJFX0RFTklFRDtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICByZWplY3QobmV3IE9wZW5WaWR1RXJyb3IoZXJyb3JOYW1lLCBlcnJvck1lc3NhZ2UpKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KVxuICAgICAgICAuY2F0Y2goKGVycm9yOiBPcGVuVmlkdUVycm9yKSA9PiB7XG4gICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgfSk7XG4gICAgfSk7XG4gIH1cblxuXG4gIC8qIHRzbGludDpkaXNhYmxlOm5vLWVtcHR5ICovXG4gIC8qKlxuICAgKiBEaXNhYmxlIGFsbCBsb2dnaW5nIGV4Y2VwdCBlcnJvciBsZXZlbFxuICAgKi9cbiAgZW5hYmxlUHJvZE1vZGUoKTogdm9pZCB7XG4gICAgY29uc29sZS5sb2cgPSAoKSA9PiB7IH07XG4gICAgY29uc29sZS5kZWJ1ZyA9ICgpID0+IHsgfTtcbiAgICBjb25zb2xlLmluZm8gPSAoKSA9PiB7IH07XG4gICAgY29uc29sZS53YXJuID0gKCkgPT4geyB9O1xuICB9XG4gIC8qIHRzbGludDplbmFibGU6bm8tZW1wdHkgKi9cblxuXG4gIC8qKlxuICAgKiBTZXQgT3BlblZpZHUgYWR2YW5jZWQgY29uZmlndXJhdGlvbiBvcHRpb25zLiBDdXJyZW50bHkgYGNvbmZpZ3VyYXRpb25gIGlzIGFuIG9iamVjdCB3aXRoIHRoZSBmb2xsb3dpbmcgb3B0aW9uYWwgcHJvcGVydGllcyAoc2VlIFtbT3BlblZpZHVBZHZhbmNlZENvbmZpZ3VyYXRpb25dXSBmb3IgbW9yZSBkZXRhaWxzKTpcbiAgICogLSBgaWNlU2VydmVyc2A6IHNldCBjdXN0b20gU1RVTi9UVVJOIHNlcnZlcnMgdG8gYmUgdXNlZCBieSBPcGVuVmlkdSBCcm93c2VyXG4gICAqIC0gYHNjcmVlblNoYXJlQ2hyb21lRXh0ZW5zaW9uYDogdXJsIHRvIGEgY3VzdG9tIHNjcmVlbiBzaGFyZSBleHRlbnNpb24gZm9yIENocm9tZSB0byBiZSB1c2VkIGluc3RlYWQgb2YgdGhlIGRlZmF1bHQgb25lLCBiYXNlZCBvbiBvdXJzIFtodHRwczovL2dpdGh1Yi5jb20vT3BlblZpZHUvb3BlbnZpZHUtc2NyZWVuLXNoYXJpbmctY2hyb21lLWV4dGVuc2lvbl0oaHR0cHM6Ly9naXRodWIuY29tL09wZW5WaWR1L29wZW52aWR1LXNjcmVlbi1zaGFyaW5nLWNocm9tZS1leHRlbnNpb24pXG4gICAqIC0gYHB1Ymxpc2hlclNwZWFraW5nRXZlbnRzT3B0aW9uc2A6IGN1c3RvbSBjb25maWd1cmF0aW9uIGZvciB0aGUgW1tQdWJsaXNoZXJTcGVha2luZ0V2ZW50XV0gZmVhdHVyZVxuICAgKi9cbiAgc2V0QWR2YW5jZWRDb25maWd1cmF0aW9uKGNvbmZpZ3VyYXRpb246IE9wZW5WaWR1QWR2YW5jZWRDb25maWd1cmF0aW9uKTogdm9pZCB7XG4gICAgdGhpcy5hZHZhbmNlZENvbmZpZ3VyYXRpb24gPSBjb25maWd1cmF0aW9uO1xuICB9XG5cblxuICAvKiBIaWRkZW4gbWV0aG9kcyAqL1xuXG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICBnZW5lcmF0ZU1lZGlhQ29uc3RyYWludHMocHVibGlzaGVyUHJvcGVydGllczogUHVibGlzaGVyUHJvcGVydGllcyk6IFByb21pc2U8TWVkaWFTdHJlYW1Db25zdHJhaW50cz4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZTxNZWRpYVN0cmVhbUNvbnN0cmFpbnRzPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICBsZXQgYXVkaW8sIHZpZGVvO1xuXG4gICAgICBpZiAocHVibGlzaGVyUHJvcGVydGllcy5hdWRpb1NvdXJjZSA9PT0gbnVsbCB8fCBwdWJsaXNoZXJQcm9wZXJ0aWVzLmF1ZGlvU291cmNlID09PSBmYWxzZSkge1xuICAgICAgICBhdWRpbyA9IGZhbHNlO1xuICAgICAgfSBlbHNlIGlmIChwdWJsaXNoZXJQcm9wZXJ0aWVzLmF1ZGlvU291cmNlID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgYXVkaW8gPSB0cnVlO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgYXVkaW8gPSBwdWJsaXNoZXJQcm9wZXJ0aWVzLmF1ZGlvU291cmNlO1xuICAgICAgfVxuXG4gICAgICBpZiAocHVibGlzaGVyUHJvcGVydGllcy52aWRlb1NvdXJjZSA9PT0gbnVsbCB8fCBwdWJsaXNoZXJQcm9wZXJ0aWVzLnZpZGVvU291cmNlID09PSBmYWxzZSkge1xuICAgICAgICB2aWRlbyA9IGZhbHNlO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdmlkZW8gPSB7XG4gICAgICAgICAgaGVpZ2h0OiB7XG4gICAgICAgICAgICBpZGVhbDogNDgwXG4gICAgICAgICAgfSxcbiAgICAgICAgICB3aWR0aDoge1xuICAgICAgICAgICAgaWRlYWw6IDY0MFxuICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgbWVkaWFDb25zdHJhaW50czogTWVkaWFTdHJlYW1Db25zdHJhaW50cyA9IHtcbiAgICAgICAgYXVkaW8sXG4gICAgICAgIHZpZGVvXG4gICAgICB9O1xuXG4gICAgICBpZiAodHlwZW9mIG1lZGlhQ29uc3RyYWludHMuYXVkaW8gPT09ICdzdHJpbmcnKSB7XG4gICAgICAgIG1lZGlhQ29uc3RyYWludHMuYXVkaW8gPSB7IGRldmljZUlkOiB7IGV4YWN0OiBtZWRpYUNvbnN0cmFpbnRzLmF1ZGlvIH0gfTtcbiAgICAgIH1cblxuICAgICAgaWYgKG1lZGlhQ29uc3RyYWludHMudmlkZW8pIHtcblxuICAgICAgICBpZiAoISFwdWJsaXNoZXJQcm9wZXJ0aWVzLnJlc29sdXRpb24pIHtcbiAgICAgICAgICBjb25zdCB3aWR0aEFuZEhlaWdodCA9IHB1Ymxpc2hlclByb3BlcnRpZXMucmVzb2x1dGlvbi50b0xvd2VyQ2FzZSgpLnNwbGl0KCd4Jyk7XG4gICAgICAgICAgY29uc3Qgd2lkdGggPSBOdW1iZXIod2lkdGhBbmRIZWlnaHRbMF0pO1xuICAgICAgICAgIGNvbnN0IGhlaWdodCA9IE51bWJlcih3aWR0aEFuZEhlaWdodFsxXSk7XG4gICAgICAgICAgKG1lZGlhQ29uc3RyYWludHMudmlkZW8gYXMgYW55KS53aWR0aC5pZGVhbCA9IHdpZHRoO1xuICAgICAgICAgIChtZWRpYUNvbnN0cmFpbnRzLnZpZGVvIGFzIGFueSkuaGVpZ2h0LmlkZWFsID0gaGVpZ2h0O1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCEhcHVibGlzaGVyUHJvcGVydGllcy5mcmFtZVJhdGUpIHtcbiAgICAgICAgICAobWVkaWFDb25zdHJhaW50cy52aWRlbyBhcyBhbnkpLmZyYW1lUmF0ZSA9IHsgaWRlYWw6IHB1Ymxpc2hlclByb3BlcnRpZXMuZnJhbWVSYXRlIH07XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoISFwdWJsaXNoZXJQcm9wZXJ0aWVzLnZpZGVvU291cmNlICYmIHR5cGVvZiBwdWJsaXNoZXJQcm9wZXJ0aWVzLnZpZGVvU291cmNlID09PSAnc3RyaW5nJykge1xuXG4gICAgICAgICAgaWYgKHB1Ymxpc2hlclByb3BlcnRpZXMudmlkZW9Tb3VyY2UgPT09ICdzY3JlZW4nKSB7XG5cbiAgICAgICAgICAgIGlmIChwbGF0Zm9ybS5uYW1lICE9PSAnQ2hyb21lJyAmJiBwbGF0Zm9ybS5uYW1lIS5pbmRleE9mKCdGaXJlZm94JykgPT09IC0xKSB7XG4gICAgICAgICAgICAgIGNvbnN0IGVycm9yID0gbmV3IE9wZW5WaWR1RXJyb3IoT3BlblZpZHVFcnJvck5hbWUuU0NSRUVOX1NIQVJJTkdfTk9UX1NVUFBPUlRFRCwgJ1lvdSBjYW4gb25seSBzY3JlZW4gc2hhcmUgaW4gZGVza3RvcCBDaHJvbWUgYW5kIEZpcmVmb3guIERldGVjdGVkIGJyb3dzZXI6ICcgKyBwbGF0Zm9ybS5uYW1lKTtcbiAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihlcnJvcik7XG4gICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICB9IGVsc2Uge1xuXG4gICAgICAgICAgICAgIGlmICghIXRoaXMuYWR2YW5jZWRDb25maWd1cmF0aW9uLnNjcmVlblNoYXJlQ2hyb21lRXh0ZW5zaW9uICYmICEocGxhdGZvcm0ubmFtZSEuaW5kZXhPZignRmlyZWZveCcpICE9PSAtMSkpIHtcblxuICAgICAgICAgICAgICAgIC8vIEN1c3RvbSBzY3JlZW4gc2hhcmluZyBleHRlbnNpb24gZm9yIENocm9tZVxuXG4gICAgICAgICAgICAgICAgc2NyZWVuU2hhcmluZy5nZXRTY3JlZW5Db25zdHJhaW50cygoZXJyb3IsIHNjcmVlbkNvbnN0cmFpbnRzKSA9PiB7XG4gICAgICAgICAgICAgICAgICBpZiAoISFlcnJvciB8fCAhIXNjcmVlbkNvbnN0cmFpbnRzLm1hbmRhdG9yeSAmJiBzY3JlZW5Db25zdHJhaW50cy5tYW5kYXRvcnkuY2hyb21lTWVkaWFTb3VyY2UgPT09ICdzY3JlZW4nKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnJvciA9PT0gJ3Blcm1pc3Npb24tZGVuaWVkJyB8fCBlcnJvciA9PT0gJ1Blcm1pc3Npb25EZW5pZWRFcnJvcicpIHtcbiAgICAgICAgICAgICAgICAgICAgICBjb25zdCBlcnJvciA9IG5ldyBPcGVuVmlkdUVycm9yKE9wZW5WaWR1RXJyb3JOYW1lLlNDUkVFTl9DQVBUVVJFX0RFTklFRCwgJ1lvdSBtdXN0IGFsbG93IGFjY2VzcyB0byBvbmUgd2luZG93IG9mIHlvdXIgZGVza3RvcCcpO1xuICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgY29uc3QgZXh0ZW5zaW9uSWQgPSB0aGlzLmFkdmFuY2VkQ29uZmlndXJhdGlvbi5zY3JlZW5TaGFyZUNocm9tZUV4dGVuc2lvbiEuc3BsaXQoJy8nKS5wb3AoKSEhLnRyaW0oKTtcbiAgICAgICAgICAgICAgICAgICAgICBzY3JlZW5TaGFyaW5nLmdldENocm9tZUV4dGVuc2lvblN0YXR1cyhleHRlbnNpb25JZCwgKHN0YXR1cykgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHN0YXR1cyA9PT0gJ2luc3RhbGxlZC1kaXNhYmxlZCcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZXJyb3IgPSBuZXcgT3BlblZpZHVFcnJvcihPcGVuVmlkdUVycm9yTmFtZS5TQ1JFRU5fRVhURU5TSU9OX0RJU0FCTEVELCAnWW91IG11c3QgZW5hYmxlIHRoZSBzY3JlZW4gZXh0ZW5zaW9uJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHN0YXR1cyA9PT0gJ25vdC1pbnN0YWxsZWQnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGVycm9yID0gbmV3IE9wZW5WaWR1RXJyb3IoT3BlblZpZHVFcnJvck5hbWUuU0NSRUVOX0VYVEVOU0lPTl9OT1RfSU5TVEFMTEVELCAoPHN0cmluZz50aGlzLmFkdmFuY2VkQ29uZmlndXJhdGlvbi5zY3JlZW5TaGFyZUNocm9tZUV4dGVuc2lvbikpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgbWVkaWFDb25zdHJhaW50cy52aWRlbyA9IHNjcmVlbkNvbnN0cmFpbnRzO1xuICAgICAgICAgICAgICAgICAgICByZXNvbHZlKG1lZGlhQ29uc3RyYWludHMpO1xuICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICB9IGVsc2Uge1xuXG4gICAgICAgICAgICAgICAgLy8gRGVmYXVsdCBzY3JlZW4gc2hhcmluZyBleHRlbnNpb24gZm9yIENocm9tZVxuXG4gICAgICAgICAgICAgICAgc2NyZWVuU2hhcmluZ0F1dG8uZ2V0U2NyZWVuSWQoKGVycm9yLCBzb3VyY2VJZCwgc2NyZWVuQ29uc3RyYWludHMpID0+IHtcbiAgICAgICAgICAgICAgICAgIGlmICghIWVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnJvciA9PT0gJ25vdC1pbnN0YWxsZWQnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgY29uc3QgZXh0ZW5zaW9uVXJsID0gISF0aGlzLmFkdmFuY2VkQ29uZmlndXJhdGlvbi5zY3JlZW5TaGFyZUNocm9tZUV4dGVuc2lvbiA/IHRoaXMuYWR2YW5jZWRDb25maWd1cmF0aW9uLnNjcmVlblNoYXJlQ2hyb21lRXh0ZW5zaW9uIDpcbiAgICAgICAgICAgICAgICAgICAgICAgICdodHRwczovL2Nocm9tZS5nb29nbGUuY29tL3dlYnN0b3JlL2RldGFpbC9vcGVudmlkdS1zY3JlZW5zaGFyaW5nL2xmY2dmZXBhZm5vYmRsb2VjY2huZmFjbGliZW5qb2xkJztcbiAgICAgICAgICAgICAgICAgICAgICBjb25zdCBlcnJvciA9IG5ldyBPcGVuVmlkdUVycm9yKE9wZW5WaWR1RXJyb3JOYW1lLlNDUkVFTl9FWFRFTlNJT05fTk9UX0lOU1RBTExFRCwgZXh0ZW5zaW9uVXJsKTtcbiAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGVycm9yID09PSAnaW5zdGFsbGVkLWRpc2FibGVkJykge1xuICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGVycm9yID0gbmV3IE9wZW5WaWR1RXJyb3IoT3BlblZpZHVFcnJvck5hbWUuU0NSRUVOX0VYVEVOU0lPTl9ESVNBQkxFRCwgJ1lvdSBtdXN0IGVuYWJsZSB0aGUgc2NyZWVuIGV4dGVuc2lvbicpO1xuICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoZXJyb3IgPT09ICdwZXJtaXNzaW9uLWRlbmllZCcpIHtcbiAgICAgICAgICAgICAgICAgICAgICBjb25zdCBlcnJvciA9IG5ldyBPcGVuVmlkdUVycm9yKE9wZW5WaWR1RXJyb3JOYW1lLlNDUkVFTl9DQVBUVVJFX0RFTklFRCwgJ1lvdSBtdXN0IGFsbG93IGFjY2VzcyB0byBvbmUgd2luZG93IG9mIHlvdXIgZGVza3RvcCcpO1xuICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIG1lZGlhQ29uc3RyYWludHMudmlkZW8gPSBzY3JlZW5Db25zdHJhaW50cy52aWRlbztcbiAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZShtZWRpYUNvbnN0cmFpbnRzKTtcbiAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgIHB1Ymxpc2hlclByb3BlcnRpZXMudmlkZW9Tb3VyY2UgPSAnc2NyZWVuJztcblxuICAgICAgICAgICAgfVxuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6bm8tc3RyaW5nLWxpdGVyYWxcbiAgICAgICAgICAgIG1lZGlhQ29uc3RyYWludHMudmlkZW9bJ2RldmljZUlkJ10gPSB7IGV4YWN0OiBwdWJsaXNoZXJQcm9wZXJ0aWVzLnZpZGVvU291cmNlIH07XG4gICAgICAgICAgICByZXNvbHZlKG1lZGlhQ29uc3RyYWludHMpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICByZXNvbHZlKG1lZGlhQ29uc3RyYWludHMpO1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXNvbHZlKG1lZGlhQ29uc3RyYWludHMpO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIEBoaWRkZW5cbiAgICovXG4gIHN0YXJ0V3Mob25Db25uZWN0U3VjY2VzOiAoZXJyb3I6IEVycm9yKSA9PiB2b2lkKTogdm9pZCB7XG4gICAgY29uc3QgY29uZmlnID0ge1xuICAgICAgaGVhcnRiZWF0OiA1MDAwLFxuICAgICAgc2VuZENsb3NlTWVzc2FnZTogZmFsc2UsXG4gICAgICB3czoge1xuICAgICAgICB1cmk6IHRoaXMud3NVcmksXG4gICAgICAgIHVzZVNvY2tKUzogZmFsc2UsXG4gICAgICAgIG9uY29ubmVjdGVkOiBvbkNvbm5lY3RTdWNjZXMsXG4gICAgICAgIG9uZGlzY29ubmVjdDogdGhpcy5kaXNjb25uZWN0Q2FsbGJhY2suYmluZCh0aGlzKSxcbiAgICAgICAgb25yZWNvbm5lY3Rpbmc6IHRoaXMucmVjb25uZWN0aW5nQ2FsbGJhY2suYmluZCh0aGlzKSxcbiAgICAgICAgb25yZWNvbm5lY3RlZDogdGhpcy5yZWNvbm5lY3RlZENhbGxiYWNrLmJpbmQodGhpcylcbiAgICAgIH0sXG4gICAgICBycGM6IHtcbiAgICAgICAgcmVxdWVzdFRpbWVvdXQ6IDEwMDAwLFxuICAgICAgICBwYXJ0aWNpcGFudEpvaW5lZDogdGhpcy5zZXNzaW9uLm9uUGFydGljaXBhbnRKb2luZWQuYmluZCh0aGlzLnNlc3Npb24pLFxuICAgICAgICBwYXJ0aWNpcGFudFB1Ymxpc2hlZDogdGhpcy5zZXNzaW9uLm9uUGFydGljaXBhbnRQdWJsaXNoZWQuYmluZCh0aGlzLnNlc3Npb24pLFxuICAgICAgICBwYXJ0aWNpcGFudFVucHVibGlzaGVkOiB0aGlzLnNlc3Npb24ub25QYXJ0aWNpcGFudFVucHVibGlzaGVkLmJpbmQodGhpcy5zZXNzaW9uKSxcbiAgICAgICAgcGFydGljaXBhbnRMZWZ0OiB0aGlzLnNlc3Npb24ub25QYXJ0aWNpcGFudExlZnQuYmluZCh0aGlzLnNlc3Npb24pLFxuICAgICAgICBwYXJ0aWNpcGFudEV2aWN0ZWQ6IHRoaXMuc2Vzc2lvbi5vblBhcnRpY2lwYW50RXZpY3RlZC5iaW5kKHRoaXMuc2Vzc2lvbiksXG4gICAgICAgIHJlY29yZGluZ1N0YXJ0ZWQ6IHRoaXMuc2Vzc2lvbi5vblJlY29yZGluZ1N0YXJ0ZWQuYmluZCh0aGlzLnNlc3Npb24pLFxuICAgICAgICByZWNvcmRpbmdTdG9wcGVkOiB0aGlzLnNlc3Npb24ub25SZWNvcmRpbmdTdG9wcGVkLmJpbmQodGhpcy5zZXNzaW9uKSxcbiAgICAgICAgc2VuZE1lc3NhZ2U6IHRoaXMuc2Vzc2lvbi5vbk5ld01lc3NhZ2UuYmluZCh0aGlzLnNlc3Npb24pLFxuICAgICAgICBzdHJlYW1Qcm9wZXJ0eUNoYW5nZWQ6IHRoaXMuc2Vzc2lvbi5vblN0cmVhbVByb3BlcnR5Q2hhbmdlZC5iaW5kKHRoaXMuc2Vzc2lvbiksXG4gICAgICAgIGljZUNhbmRpZGF0ZTogdGhpcy5zZXNzaW9uLnJlY3ZJY2VDYW5kaWRhdGUuYmluZCh0aGlzLnNlc3Npb24pLFxuICAgICAgICBtZWRpYUVycm9yOiB0aGlzLnNlc3Npb24ub25NZWRpYUVycm9yLmJpbmQodGhpcy5zZXNzaW9uKVxuICAgICAgfVxuICAgIH07XG4gICAgdGhpcy5qc29uUnBjQ2xpZW50ID0gbmV3IFJwY0J1aWxkZXIuY2xpZW50cy5Kc29uUnBjQ2xpZW50KGNvbmZpZyk7XG4gIH1cblxuICAvKipcbiAgICogQGhpZGRlblxuICAgKi9cbiAgY2xvc2VXcygpOiB2b2lkIHtcbiAgICB0aGlzLmpzb25ScGNDbGllbnQuY2xvc2UoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICBzZW5kUmVxdWVzdChtZXRob2Q6IHN0cmluZywgcGFyYW1zOiBhbnksIGNhbGxiYWNrPyk6IHZvaWQge1xuICAgIGlmIChwYXJhbXMgJiYgcGFyYW1zIGluc3RhbmNlb2YgRnVuY3Rpb24pIHtcbiAgICAgIGNhbGxiYWNrID0gcGFyYW1zO1xuICAgICAgcGFyYW1zID0ge307XG4gICAgfVxuICAgIGNvbnNvbGUuZGVidWcoJ1NlbmRpbmcgcmVxdWVzdDoge21ldGhvZDpcIicgKyBtZXRob2QgKyAnXCIsIHBhcmFtczogJyArIEpTT04uc3RyaW5naWZ5KHBhcmFtcykgKyAnfScpO1xuICAgIHRoaXMuanNvblJwY0NsaWVudC5zZW5kKG1ldGhvZCwgcGFyYW1zLCBjYWxsYmFjayk7XG4gIH1cblxuICAvKipcbiAgICogQGhpZGRlblxuICAgKi9cbiAgaXNNZWRpYVN0cmVhbVRyYWNrKG1lZGlhU291cmNlOiBhbnkpOiBib29sZWFuIHtcbiAgICBjb25zdCBpcyA9ICghIW1lZGlhU291cmNlICYmXG4gICAgICBtZWRpYVNvdXJjZS5lbmFibGVkICE9PSB1bmRlZmluZWQgJiYgdHlwZW9mIG1lZGlhU291cmNlLmVuYWJsZWQgPT09ICdib29sZWFuJyAmJlxuICAgICAgbWVkaWFTb3VyY2UuaWQgIT09IHVuZGVmaW5lZCAmJiB0eXBlb2YgbWVkaWFTb3VyY2UuaWQgPT09ICdzdHJpbmcnICYmXG4gICAgICBtZWRpYVNvdXJjZS5raW5kICE9PSB1bmRlZmluZWQgJiYgdHlwZW9mIG1lZGlhU291cmNlLmtpbmQgPT09ICdzdHJpbmcnICYmXG4gICAgICBtZWRpYVNvdXJjZS5sYWJlbCAhPT0gdW5kZWZpbmVkICYmIHR5cGVvZiBtZWRpYVNvdXJjZS5sYWJlbCA9PT0gJ3N0cmluZycgJiZcbiAgICAgIG1lZGlhU291cmNlLm11dGVkICE9PSB1bmRlZmluZWQgJiYgdHlwZW9mIG1lZGlhU291cmNlLm11dGVkID09PSAnYm9vbGVhbicgJiZcbiAgICAgIG1lZGlhU291cmNlLnJlYWR5U3RhdGUgIT09IHVuZGVmaW5lZCAmJiB0eXBlb2YgbWVkaWFTb3VyY2UucmVhZHlTdGF0ZSA9PT0gJ3N0cmluZycpO1xuICAgIHJldHVybiBpcztcbiAgfVxuXG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICBnZXRXc1VyaSgpOiBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLndzVXJpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBoaWRkZW5cbiAgICovXG4gIGdldFNlY3JldCgpOiBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLnNlY3JldDtcbiAgfVxuXG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICBnZXRSZWNvcmRlcigpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5yZWNvcmRlcjtcbiAgfVxuXG5cbiAgLyogUHJpdmF0ZSBtZXRob2RzICovXG5cbiAgcHJpdmF0ZSBkaXNjb25uZWN0Q2FsbGJhY2soKTogdm9pZCB7XG4gICAgY29uc29sZS53YXJuKCdXZWJzb2NrZXQgY29ubmVjdGlvbiBsb3N0Jyk7XG4gICAgaWYgKHRoaXMuaXNSb29tQXZhaWxhYmxlKCkpIHtcbiAgICAgIHRoaXMuc2Vzc2lvbi5vbkxvc3RDb25uZWN0aW9uKCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGFsZXJ0KCdDb25uZWN0aW9uIGVycm9yLiBQbGVhc2UgcmVsb2FkIHBhZ2UuJyk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSByZWNvbm5lY3RpbmdDYWxsYmFjaygpOiB2b2lkIHtcbiAgICBjb25zb2xlLndhcm4oJ1dlYnNvY2tldCBjb25uZWN0aW9uIGxvc3QgKHJlY29ubmVjdGluZyknKTtcbiAgICBpZiAodGhpcy5pc1Jvb21BdmFpbGFibGUoKSkge1xuICAgICAgdGhpcy5zZXNzaW9uLm9uTG9zdENvbm5lY3Rpb24oKTtcbiAgICB9IGVsc2Uge1xuICAgICAgYWxlcnQoJ0Nvbm5lY3Rpb24gZXJyb3IuIFBsZWFzZSByZWxvYWQgcGFnZS4nKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIHJlY29ubmVjdGVkQ2FsbGJhY2soKTogdm9pZCB7XG4gICAgY29uc29sZS53YXJuKCdXZWJzb2NrZXQgcmVjb25uZWN0ZWQnKTtcbiAgICBpZiAodGhpcy5pc1Jvb21BdmFpbGFibGUoKSkge1xuICAgICAgdGhpcy5zZXNzaW9uLm9uUmVjb3ZlcmVkQ29ubmVjdGlvbigpO1xuICAgIH0gZWxzZSB7XG4gICAgICBhbGVydCgnQ29ubmVjdGlvbiBlcnJvci4gUGxlYXNlIHJlbG9hZCBwYWdlLicpO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgaXNSb29tQXZhaWxhYmxlKCk6IGJvb2xlYW4ge1xuICAgIGlmICh0aGlzLnNlc3Npb24gIT09IHVuZGVmaW5lZCAmJiB0aGlzLnNlc3Npb24gaW5zdGFuY2VvZiBTZXNzaW9uKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9IGVsc2Uge1xuICAgICAgY29uc29sZS53YXJuKCdTZXNzaW9uIGluc3RhbmNlIG5vdCBmb3VuZCcpO1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfVxuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBPcGVuVmlkdSB9IGZyb20gJy4vT3BlblZpZHUnO1xuaW1wb3J0IHsgU2Vzc2lvbiB9IGZyb20gJy4vU2Vzc2lvbic7XG5pbXBvcnQgeyBTdHJlYW0gfSBmcm9tICcuL1N0cmVhbSc7XG5pbXBvcnQgeyBTdHJlYW1NYW5hZ2VyIH0gZnJvbSAnLi9TdHJlYW1NYW5hZ2VyJztcbmltcG9ydCB7IEV2ZW50RGlzcGF0Y2hlciB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvSW50ZXJmYWNlcy9QdWJsaWMvRXZlbnREaXNwYXRjaGVyJztcbmltcG9ydCB7IFB1Ymxpc2hlclByb3BlcnRpZXMgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHVibGljL1B1Ymxpc2hlclByb3BlcnRpZXMnO1xuaW1wb3J0IHsgRXZlbnQgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0V2ZW50cy9FdmVudCc7XG5pbXBvcnQgeyBTdHJlYW1FdmVudCB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1N0cmVhbUV2ZW50JztcbmltcG9ydCB7IFN0cmVhbVByb3BlcnR5Q2hhbmdlZEV2ZW50IH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvU3RyZWFtUHJvcGVydHlDaGFuZ2VkRXZlbnQnO1xuaW1wb3J0IHsgVmlkZW9FbGVtZW50RXZlbnQgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0V2ZW50cy9WaWRlb0VsZW1lbnRFdmVudCc7XG5pbXBvcnQgeyBPcGVuVmlkdUVycm9yLCBPcGVuVmlkdUVycm9yTmFtZSB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRW51bXMvT3BlblZpZHVFcnJvcic7XG5pbXBvcnQgeyBWaWRlb0luc2VydE1vZGUgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0VudW1zL1ZpZGVvSW5zZXJ0TW9kZSc7XG5cbmltcG9ydCBwbGF0Zm9ybSA9IHJlcXVpcmUoJ3BsYXRmb3JtJyk7XG5cblxuLyoqXG4gKiBQYWNrcyBsb2NhbCBtZWRpYSBzdHJlYW1zLiBQYXJ0aWNpcGFudHMgY2FuIHB1Ymxpc2ggaXQgdG8gYSBzZXNzaW9uLiBJbml0aWFsaXplZCB3aXRoIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dIG1ldGhvZFxuICovXG5leHBvcnQgY2xhc3MgUHVibGlzaGVyIGV4dGVuZHMgU3RyZWFtTWFuYWdlciB7XG5cbiAgICAvKipcbiAgICAgKiBXaGV0aGVyIHRoZSBQdWJsaXNoZXIgaGFzIGJlZW4gZ3JhbnRlZCBhY2Nlc3MgdG8gdGhlIHJlcXVlc3RlZCBpbnB1dCBkZXZpY2VzIG9yIG5vdFxuICAgICAqL1xuICAgIGFjY2Vzc0FsbG93ZWQgPSBmYWxzZTtcblxuICAgIC8qKlxuICAgICAqIFdoZXRoZXIgeW91IGhhdmUgY2FsbGVkIFtbUHVibGlzaGVyLnN1YnNjcmliZVRvUmVtb3RlXV0gd2l0aCB2YWx1ZSBgdHJ1ZWAgb3IgYGZhbHNlYCAoKmZhbHNlKiBieSBkZWZhdWx0KVxuICAgICAqL1xuICAgIGlzU3Vic2NyaWJlZFRvUmVtb3RlID0gZmFsc2U7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgW1tTZXNzaW9uXV0gdG8gd2hpY2ggdGhlIFB1Ymxpc2hlciBiZWxvbmdzXG4gICAgICovXG4gICAgc2Vzc2lvbjogU2Vzc2lvbjsgLy8gSW5pdGlhbGl6ZWQgYnkgU2Vzc2lvbi5wdWJsaXNoKFB1Ymxpc2hlcilcblxuICAgIHByaXZhdGUgYWNjZXNzRGVuaWVkID0gZmFsc2U7XG4gICAgcHJpdmF0ZSBwcm9wZXJ0aWVzOiBQdWJsaXNoZXJQcm9wZXJ0aWVzO1xuICAgIHByaXZhdGUgcGVybWlzc2lvbkRpYWxvZ1RpbWVvdXQ6IE5vZGVKUy5UaW1lcjtcblxuICAgIC8qKlxuICAgICAqIGhpZGRlblxuICAgICAqL1xuICAgIG9wZW52aWR1OiBPcGVuVmlkdTtcbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgdmlkZW9SZWZlcmVuY2U6IEhUTUxWaWRlb0VsZW1lbnQ7XG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHNjcmVlblNoYXJlUmVzaXplSW50ZXJ2YWw6IE5vZGVKUy5UaW1lcjtcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3Rvcih0YXJnRWw6IHN0cmluZyB8IEhUTUxFbGVtZW50LCBwcm9wZXJ0aWVzOiBQdWJsaXNoZXJQcm9wZXJ0aWVzLCBvcGVudmlkdTogT3BlblZpZHUpIHtcbiAgICAgICAgc3VwZXIobmV3IFN0cmVhbSgoISFvcGVudmlkdS5zZXNzaW9uKSA/IG9wZW52aWR1LnNlc3Npb24gOiBuZXcgU2Vzc2lvbihvcGVudmlkdSksIHsgcHVibGlzaGVyUHJvcGVydGllczogcHJvcGVydGllcywgbWVkaWFDb25zdHJhaW50czoge30gfSksIHRhcmdFbCk7XG4gICAgICAgIHRoaXMucHJvcGVydGllcyA9IHByb3BlcnRpZXM7XG4gICAgICAgIHRoaXMub3BlbnZpZHUgPSBvcGVudmlkdTtcblxuICAgICAgICB0aGlzLnN0cmVhbS5lZS5vbignbG9jYWwtc3RyZWFtLWRlc3Ryb3llZCcsIChyZWFzb246IHN0cmluZykgPT4ge1xuICAgICAgICAgICAgdGhpcy5zdHJlYW0uaXNMb2NhbFN0cmVhbVB1Ymxpc2hlZCA9IGZhbHNlO1xuICAgICAgICAgICAgY29uc3Qgc3RyZWFtRXZlbnQgPSBuZXcgU3RyZWFtRXZlbnQodHJ1ZSwgdGhpcywgJ3N0cmVhbURlc3Ryb3llZCcsIHRoaXMuc3RyZWFtLCByZWFzb24pO1xuICAgICAgICAgICAgdGhpcy5lbWl0RXZlbnQoJ3N0cmVhbURlc3Ryb3llZCcsIFtzdHJlYW1FdmVudF0pO1xuICAgICAgICAgICAgc3RyZWFtRXZlbnQuY2FsbERlZmF1bHRCZWhhdmlvcigpO1xuICAgICAgICB9KTtcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFB1Ymxpc2ggb3IgdW5wdWJsaXNoIHRoZSBhdWRpbyBzdHJlYW0gKGlmIGF2YWlsYWJsZSkuIENhbGxpbmcgdGhpcyBtZXRob2QgdHdpY2UgaW4gYSByb3cgcGFzc2luZyBzYW1lIHZhbHVlIHdpbGwgaGF2ZSBubyBlZmZlY3RcbiAgICAgKlxuICAgICAqICMjIyMgRXZlbnRzIGRpc3BhdGNoZWRcbiAgICAgKlxuICAgICAqIFRoZSBbW1Nlc3Npb25dXSBvYmplY3Qgb2YgdGhlIGxvY2FsIHBhcnRpY2lwYW50IHdpbGwgZGlzcGF0Y2ggYSBgc3RyZWFtUHJvcGVydHlDaGFuZ2VkYCBldmVudCB3aXRoIGBjaGFuZ2VkUHJvcGVydHlgIHNldCB0byBgXCJhdWRpb0FjdGl2ZVwiYCBhbmQgYHJlYXNvbmAgc2V0IHRvIGBcInB1Ymxpc2hBdWRpb1wiYFxuICAgICAqIFRoZSBbW1B1Ymxpc2hlcl1dIG9iamVjdCBvZiB0aGUgbG9jYWwgcGFydGljaXBhbnQgd2lsbCBhbHNvIGRpc3BhdGNoIHRoZSBleGFjdCBzYW1lIGV2ZW50XG4gICAgICpcbiAgICAgKiBUaGUgW1tTZXNzaW9uXV0gb2JqZWN0IG9mIGV2ZXJ5IG90aGVyIHBhcnRpY2lwYW50IGNvbm5lY3RlZCB0byB0aGUgc2Vzc2lvbiB3aWxsIGRpc3BhdGNoIGEgYHN0cmVhbVByb3BlcnR5Q2hhbmdlZGAgZXZlbnQgd2l0aCBgY2hhbmdlZFByb3BlcnR5YCBzZXQgdG8gYFwiYXVkaW9BY3RpdmVcImAgYW5kIGByZWFzb25gIHNldCB0byBgXCJwdWJsaXNoQXVkaW9cImBcbiAgICAgKiBUaGUgcmVzcGVjdGl2ZSBbW1N1YnNjcmliZXJdXSBvYmplY3Qgb2YgZXZlcnkgb3RoZXIgcGFydGljaXBhbnQgcmVjZWl2aW5nIHRoaXMgUHVibGlzaGVyJ3Mgc3RyZWFtIHdpbGwgYWxzbyBkaXNwYXRjaCB0aGUgZXhhY3Qgc2FtZSBldmVudFxuICAgICAqXG4gICAgICogU2VlIFtbU3RyZWFtUHJvcGVydHlDaGFuZ2VkRXZlbnRdXSB0byBsZWFybiBtb3JlLlxuICAgICAqXG4gICAgICogQHBhcmFtIHZhbHVlIGB0cnVlYCB0byBwdWJsaXNoIHRoZSBhdWRpbyBzdHJlYW0sIGBmYWxzZWAgdG8gdW5wdWJsaXNoIGl0XG4gICAgICovXG4gICAgcHVibGlzaEF1ZGlvKHZhbHVlOiBib29sZWFuKTogdm9pZCB7XG4gICAgICAgIGlmICh0aGlzLnN0cmVhbS5hdWRpb0FjdGl2ZSAhPT0gdmFsdWUpIHtcbiAgICAgICAgICAgIHRoaXMuc3RyZWFtLmdldE1lZGlhU3RyZWFtKCkuZ2V0QXVkaW9UcmFja3MoKS5mb3JFYWNoKCh0cmFjaykgPT4ge1xuICAgICAgICAgICAgICAgIHRyYWNrLmVuYWJsZWQgPSB2YWx1ZTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgdGhpcy5zZXNzaW9uLm9wZW52aWR1LnNlbmRSZXF1ZXN0KFxuICAgICAgICAgICAgICAgICdzdHJlYW1Qcm9wZXJ0eUNoYW5nZWQnLFxuICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgc3RyZWFtSWQ6IHRoaXMuc3RyZWFtLnN0cmVhbUlkLFxuICAgICAgICAgICAgICAgICAgICBwcm9wZXJ0eTogJ2F1ZGlvQWN0aXZlJyxcbiAgICAgICAgICAgICAgICAgICAgbmV3VmFsdWU6IHZhbHVlLFxuICAgICAgICAgICAgICAgICAgICByZWFzb246ICdwdWJsaXNoQXVkaW8nXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAoZXJyb3IsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihcIkVycm9yIHNlbmRpbmcgJ3N0cmVhbVByb3BlcnR5Q2hhbmdlZCcgZXZlbnRcIiwgZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXNzaW9uLmVtaXRFdmVudCgnc3RyZWFtUHJvcGVydHlDaGFuZ2VkJywgW25ldyBTdHJlYW1Qcm9wZXJ0eUNoYW5nZWRFdmVudCh0aGlzLnNlc3Npb24sIHRoaXMuc3RyZWFtLCAnYXVkaW9BY3RpdmUnLCB2YWx1ZSwgIXZhbHVlLCAncHVibGlzaEF1ZGlvJyldKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZW1pdEV2ZW50KCdzdHJlYW1Qcm9wZXJ0eUNoYW5nZWQnLCBbbmV3IFN0cmVhbVByb3BlcnR5Q2hhbmdlZEV2ZW50KHRoaXMsIHRoaXMuc3RyZWFtLCAnYXVkaW9BY3RpdmUnLCB2YWx1ZSwgIXZhbHVlLCAncHVibGlzaEF1ZGlvJyldKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgdGhpcy5zdHJlYW0uYXVkaW9BY3RpdmUgPSB2YWx1ZTtcbiAgICAgICAgICAgIGNvbnNvbGUuaW5mbyhcIidQdWJsaXNoZXInIGhhcyBcIiArICh2YWx1ZSA/ICdwdWJsaXNoZWQnIDogJ3VucHVibGlzaGVkJykgKyAnIGl0cyBhdWRpbyBzdHJlYW0nKTtcbiAgICAgICAgfVxuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogUHVibGlzaCBvciB1bnB1Ymxpc2ggdGhlIHZpZGVvIHN0cmVhbSAoaWYgYXZhaWxhYmxlKS4gQ2FsbGluZyB0aGlzIG1ldGhvZCB0d2ljZSBpbiBhIHJvdyBwYXNzaW5nIHNhbWUgdmFsdWUgd2lsbCBoYXZlIG5vIGVmZmVjdFxuICAgICAqXG4gICAgICogIyMjIyBFdmVudHMgZGlzcGF0Y2hlZFxuICAgICAqXG4gICAgICogVGhlIFtbU2Vzc2lvbl1dIG9iamVjdCBvZiB0aGUgbG9jYWwgcGFydGljaXBhbnQgd2lsbCBkaXNwYXRjaCBhIGBzdHJlYW1Qcm9wZXJ0eUNoYW5nZWRgIGV2ZW50IHdpdGggYGNoYW5nZWRQcm9wZXJ0eWAgc2V0IHRvIGBcInZpZGVvQWN0aXZlXCJgIGFuZCBgcmVhc29uYCBzZXQgdG8gYFwicHVibGlzaFZpZGVvXCJgXG4gICAgICogVGhlIFtbUHVibGlzaGVyXV0gb2JqZWN0IG9mIHRoZSBsb2NhbCBwYXJ0aWNpcGFudCB3aWxsIGFsc28gZGlzcGF0Y2ggdGhlIGV4YWN0IHNhbWUgZXZlbnRcbiAgICAgKlxuICAgICAqIFRoZSBbW1Nlc3Npb25dXSBvYmplY3Qgb2YgZXZlcnkgb3RoZXIgcGFydGljaXBhbnQgY29ubmVjdGVkIHRvIHRoZSBzZXNzaW9uIHdpbGwgZGlzcGF0Y2ggYSBgc3RyZWFtUHJvcGVydHlDaGFuZ2VkYCBldmVudCB3aXRoIGBjaGFuZ2VkUHJvcGVydHlgIHNldCB0byBgXCJ2aWRlb0FjdGl2ZVwiYCBhbmQgYHJlYXNvbmAgc2V0IHRvIGBcInB1Ymxpc2hWaWRlb1wiYFxuICAgICAqIFRoZSByZXNwZWN0aXZlIFtbU3Vic2NyaWJlcl1dIG9iamVjdCBvZiBldmVyeSBvdGhlciBwYXJ0aWNpcGFudCByZWNlaXZpbmcgdGhpcyBQdWJsaXNoZXIncyBzdHJlYW0gd2lsbCBhbHNvIGRpc3BhdGNoIHRoZSBleGFjdCBzYW1lIGV2ZW50XG4gICAgICpcbiAgICAgKiBTZWUgW1tTdHJlYW1Qcm9wZXJ0eUNoYW5nZWRFdmVudF1dIHRvIGxlYXJuIG1vcmUuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gdmFsdWUgYHRydWVgIHRvIHB1Ymxpc2ggdGhlIHZpZGVvIHN0cmVhbSwgYGZhbHNlYCB0byB1bnB1Ymxpc2ggaXRcbiAgICAgKi9cbiAgICBwdWJsaXNoVmlkZW8odmFsdWU6IGJvb2xlYW4pOiB2b2lkIHtcbiAgICAgICAgaWYgKHRoaXMuc3RyZWFtLnZpZGVvQWN0aXZlICE9PSB2YWx1ZSkge1xuICAgICAgICAgICAgdGhpcy5zdHJlYW0uZ2V0TWVkaWFTdHJlYW0oKS5nZXRWaWRlb1RyYWNrcygpLmZvckVhY2goKHRyYWNrKSA9PiB7XG4gICAgICAgICAgICAgICAgdHJhY2suZW5hYmxlZCA9IHZhbHVlO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB0aGlzLnNlc3Npb24ub3BlbnZpZHUuc2VuZFJlcXVlc3QoXG4gICAgICAgICAgICAgICAgJ3N0cmVhbVByb3BlcnR5Q2hhbmdlZCcsXG4gICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICBzdHJlYW1JZDogdGhpcy5zdHJlYW0uc3RyZWFtSWQsXG4gICAgICAgICAgICAgICAgICAgIHByb3BlcnR5OiAndmlkZW9BY3RpdmUnLFxuICAgICAgICAgICAgICAgICAgICBuZXdWYWx1ZTogdmFsdWUsXG4gICAgICAgICAgICAgICAgICAgIHJlYXNvbjogJ3B1Ymxpc2hWaWRlbydcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIChlcnJvciwgcmVzcG9uc2UpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKFwiRXJyb3Igc2VuZGluZyAnc3RyZWFtUHJvcGVydHlDaGFuZ2VkJyBldmVudFwiLCBlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnNlc3Npb24uZW1pdEV2ZW50KCdzdHJlYW1Qcm9wZXJ0eUNoYW5nZWQnLCBbbmV3IFN0cmVhbVByb3BlcnR5Q2hhbmdlZEV2ZW50KHRoaXMuc2Vzc2lvbiwgdGhpcy5zdHJlYW0sICd2aWRlb0FjdGl2ZScsIHZhbHVlLCAhdmFsdWUsICdwdWJsaXNoVmlkZW8nKV0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5lbWl0RXZlbnQoJ3N0cmVhbVByb3BlcnR5Q2hhbmdlZCcsIFtuZXcgU3RyZWFtUHJvcGVydHlDaGFuZ2VkRXZlbnQodGhpcywgdGhpcy5zdHJlYW0sICd2aWRlb0FjdGl2ZScsIHZhbHVlLCAhdmFsdWUsICdwdWJsaXNoVmlkZW8nKV0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB0aGlzLnN0cmVhbS52aWRlb0FjdGl2ZSA9IHZhbHVlO1xuICAgICAgICAgICAgY29uc29sZS5pbmZvKFwiJ1B1Ymxpc2hlcicgaGFzIFwiICsgKHZhbHVlID8gJ3B1Ymxpc2hlZCcgOiAndW5wdWJsaXNoZWQnKSArICcgaXRzIHZpZGVvIHN0cmVhbScpO1xuICAgICAgICB9XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBDYWxsIHRoaXMgbWV0aG9kIGJlZm9yZSBbW1Nlc3Npb24ucHVibGlzaF1dIGlmIHlvdSBwcmVmZXIgdG8gc3Vic2NyaWJlIHRvIHlvdXIgUHVibGlzaGVyJ3MgcmVtb3RlIHN0cmVhbSBpbnN0ZWFkIG9mIHVzaW5nIHRoZSBsb2NhbCBzdHJlYW0sIGFzIGFueSBvdGhlciB1c2VyIHdvdWxkIGRvLlxuICAgICAqL1xuICAgIHN1YnNjcmliZVRvUmVtb3RlKHZhbHVlPzogYm9vbGVhbik6IHZvaWQge1xuICAgICAgICB2YWx1ZSA9ICh2YWx1ZSAhPT0gdW5kZWZpbmVkKSA/IHZhbHVlIDogdHJ1ZTtcbiAgICAgICAgdGhpcy5pc1N1YnNjcmliZWRUb1JlbW90ZSA9IHZhbHVlO1xuICAgICAgICB0aGlzLnN0cmVhbS5zdWJzY3JpYmVUb015UmVtb3RlKHZhbHVlKTtcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFNlZSBbW0V2ZW50RGlzcGF0Y2hlci5vbl1dXG4gICAgICovXG4gICAgb24odHlwZTogc3RyaW5nLCBoYW5kbGVyOiAoZXZlbnQ6IEV2ZW50KSA9PiB2b2lkKTogRXZlbnREaXNwYXRjaGVyIHtcbiAgICAgICAgc3VwZXIub24odHlwZSwgaGFuZGxlcik7XG4gICAgICAgIGlmICh0eXBlID09PSAnc3RyZWFtQ3JlYXRlZCcpIHtcbiAgICAgICAgICAgIGlmICghIXRoaXMuc3RyZWFtICYmIHRoaXMuc3RyZWFtLmlzTG9jYWxTdHJlYW1QdWJsaXNoZWQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVtaXRFdmVudCgnc3RyZWFtQ3JlYXRlZCcsIFtuZXcgU3RyZWFtRXZlbnQoZmFsc2UsIHRoaXMsICdzdHJlYW1DcmVhdGVkJywgdGhpcy5zdHJlYW0sICcnKV0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbS5lZS5vbignc3RyZWFtLWNyZWF0ZWQtYnktcHVibGlzaGVyJywgKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmVtaXRFdmVudCgnc3RyZWFtQ3JlYXRlZCcsIFtuZXcgU3RyZWFtRXZlbnQoZmFsc2UsIHRoaXMsICdzdHJlYW1DcmVhdGVkJywgdGhpcy5zdHJlYW0sICcnKV0pO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmICh0eXBlID09PSAncmVtb3RlVmlkZW9QbGF5aW5nJykge1xuICAgICAgICAgICAgaWYgKHRoaXMuc3RyZWFtLmRpc3BsYXlNeVJlbW90ZSgpICYmIHRoaXMudmlkZW9zWzBdICYmIHRoaXMudmlkZW9zWzBdLnZpZGVvICYmXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8uY3VycmVudFRpbWUgPiAwICYmXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8ucGF1c2VkID09PSBmYWxzZSAmJlxuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9zWzBdLnZpZGVvLmVuZGVkID09PSBmYWxzZSAmJlxuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9zWzBdLnZpZGVvLnJlYWR5U3RhdGUgPT09IDQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVtaXRFdmVudCgncmVtb3RlVmlkZW9QbGF5aW5nJywgW25ldyBWaWRlb0VsZW1lbnRFdmVudCh0aGlzLnZpZGVvc1swXS52aWRlbywgdGhpcywgJ3JlbW90ZVZpZGVvUGxheWluZycpXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHR5cGUgPT09ICdhY2Nlc3NBbGxvd2VkJykge1xuICAgICAgICAgICAgaWYgKHRoaXMuYWNjZXNzQWxsb3dlZCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZW1pdEV2ZW50KCdhY2Nlc3NBbGxvd2VkJywgW10pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmICh0eXBlID09PSAnYWNjZXNzRGVuaWVkJykge1xuICAgICAgICAgICAgaWYgKHRoaXMuYWNjZXNzRGVuaWVkKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5lbWl0RXZlbnQoJ2FjY2Vzc0RlbmllZCcsIFtdKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFNlZSBbW0V2ZW50RGlzcGF0Y2hlci5vbmNlXV1cbiAgICAgKi9cbiAgICBvbmNlKHR5cGU6IHN0cmluZywgaGFuZGxlcjogKGV2ZW50OiBFdmVudCkgPT4gdm9pZCk6IFB1Ymxpc2hlciB7XG4gICAgICAgIHN1cGVyLm9uY2UodHlwZSwgaGFuZGxlcik7XG4gICAgICAgIGlmICh0eXBlID09PSAnc3RyZWFtQ3JlYXRlZCcpIHtcbiAgICAgICAgICAgIGlmICghIXRoaXMuc3RyZWFtICYmIHRoaXMuc3RyZWFtLmlzTG9jYWxTdHJlYW1QdWJsaXNoZWQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVtaXRFdmVudCgnc3RyZWFtQ3JlYXRlZCcsIFtuZXcgU3RyZWFtRXZlbnQoZmFsc2UsIHRoaXMsICdzdHJlYW1DcmVhdGVkJywgdGhpcy5zdHJlYW0sICcnKV0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbS5lZS5vbmNlKCdzdHJlYW0tY3JlYXRlZC1ieS1wdWJsaXNoZXInLCAoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZW1pdEV2ZW50KCdzdHJlYW1DcmVhdGVkJywgW25ldyBTdHJlYW1FdmVudChmYWxzZSwgdGhpcywgJ3N0cmVhbUNyZWF0ZWQnLCB0aGlzLnN0cmVhbSwgJycpXSk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHR5cGUgPT09ICdyZW1vdGVWaWRlb1BsYXlpbmcnKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5zdHJlYW0uZGlzcGxheU15UmVtb3RlKCkgJiYgdGhpcy52aWRlb3NbMF0gJiYgdGhpcy52aWRlb3NbMF0udmlkZW8gJiZcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvc1swXS52aWRlby5jdXJyZW50VGltZSA+IDAgJiZcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvc1swXS52aWRlby5wYXVzZWQgPT09IGZhbHNlICYmXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8uZW5kZWQgPT09IGZhbHNlICYmXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8ucmVhZHlTdGF0ZSA9PT0gNCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZW1pdEV2ZW50KCdyZW1vdGVWaWRlb1BsYXlpbmcnLCBbbmV3IFZpZGVvRWxlbWVudEV2ZW50KHRoaXMudmlkZW9zWzBdLnZpZGVvLCB0aGlzLCAncmVtb3RlVmlkZW9QbGF5aW5nJyldKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAodHlwZSA9PT0gJ2FjY2Vzc0FsbG93ZWQnKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5hY2Nlc3NBbGxvd2VkKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5lbWl0RXZlbnQoJ2FjY2Vzc0FsbG93ZWQnLCBbXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHR5cGUgPT09ICdhY2Nlc3NEZW5pZWQnKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5hY2Nlc3NEZW5pZWQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVtaXRFdmVudCgnYWNjZXNzRGVuaWVkJywgW10pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuXG4gICAgLyogSGlkZGVuIG1ldGhvZHMgKi9cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBpbml0aWFsaXplKCk6IFByb21pc2U8YW55PiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG5cbiAgICAgICAgICAgIGNvbnN0IGVycm9yQ2FsbGJhY2sgPSAob3BlblZpZHVFcnJvcjogT3BlblZpZHVFcnJvcikgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuYWNjZXNzRGVuaWVkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB0aGlzLmFjY2Vzc0FsbG93ZWQgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICByZWplY3Qob3BlblZpZHVFcnJvcik7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICBjb25zdCBzdWNjZXNzQ2FsbGJhY2sgPSAobWVkaWFTdHJlYW06IE1lZGlhU3RyZWFtKSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5hY2Nlc3NBbGxvd2VkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB0aGlzLmFjY2Vzc0RlbmllZCA9IGZhbHNlO1xuXG4gICAgICAgICAgICAgICAgaWYgKHRoaXMub3BlbnZpZHUuaXNNZWRpYVN0cmVhbVRyYWNrKHRoaXMucHJvcGVydGllcy5hdWRpb1NvdXJjZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgbWVkaWFTdHJlYW0ucmVtb3ZlVHJhY2sobWVkaWFTdHJlYW0uZ2V0QXVkaW9UcmFja3MoKVswXSk7XG4gICAgICAgICAgICAgICAgICAgIG1lZGlhU3RyZWFtLmFkZFRyYWNrKCg8TWVkaWFTdHJlYW1UcmFjaz50aGlzLnByb3BlcnRpZXMuYXVkaW9Tb3VyY2UpKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAodGhpcy5vcGVudmlkdS5pc01lZGlhU3RyZWFtVHJhY2sodGhpcy5wcm9wZXJ0aWVzLnZpZGVvU291cmNlKSkge1xuICAgICAgICAgICAgICAgICAgICBtZWRpYVN0cmVhbS5yZW1vdmVUcmFjayhtZWRpYVN0cmVhbS5nZXRWaWRlb1RyYWNrcygpWzBdKTtcbiAgICAgICAgICAgICAgICAgICAgbWVkaWFTdHJlYW0uYWRkVHJhY2soKDxNZWRpYVN0cmVhbVRyYWNrPnRoaXMucHJvcGVydGllcy52aWRlb1NvdXJjZSkpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIEFwcGx5IFB1Ymxpc2hlclByb3BlcnRpZXMucHVibGlzaEF1ZGlvIGFuZCBQdWJsaXNoZXJQcm9wZXJ0aWVzLnB1Ymxpc2hWaWRlb1xuICAgICAgICAgICAgICAgIGlmICghIW1lZGlhU3RyZWFtLmdldEF1ZGlvVHJhY2tzKClbMF0pIHtcbiAgICAgICAgICAgICAgICAgICAgbWVkaWFTdHJlYW0uZ2V0QXVkaW9UcmFja3MoKVswXS5lbmFibGVkID0gISF0aGlzLnN0cmVhbS5vdXRib3VuZFN0cmVhbU9wdHMucHVibGlzaGVyUHJvcGVydGllcy5wdWJsaXNoQXVkaW87XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmICghIW1lZGlhU3RyZWFtLmdldFZpZGVvVHJhY2tzKClbMF0pIHtcbiAgICAgICAgICAgICAgICAgICAgbWVkaWFTdHJlYW0uZ2V0VmlkZW9UcmFja3MoKVswXS5lbmFibGVkID0gISF0aGlzLnN0cmVhbS5vdXRib3VuZFN0cmVhbU9wdHMucHVibGlzaGVyUHJvcGVydGllcy5wdWJsaXNoVmlkZW87XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb1JlZmVyZW5jZSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3ZpZGVvJyk7XG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb1JlZmVyZW5jZS5zcmNPYmplY3QgPSBtZWRpYVN0cmVhbTtcblxuICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtLnNldE1lZGlhU3RyZWFtKG1lZGlhU3RyZWFtKTtcbiAgICAgICAgICAgICAgICBpZiAoIXRoaXMuc3RyZWFtLmRpc3BsYXlNeVJlbW90ZSgpKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIFdoZW4gd2UgYXJlIHN1YnNjcmliZWQgdG8gb3VyIHJlbW90ZSB3ZSBkb24ndCBzdGlsbCBzZXQgdGhlIE1lZGlhU3RyZWFtIG9iamVjdCBpbiB0aGUgdmlkZW8gZWxlbWVudHMgdG9cbiAgICAgICAgICAgICAgICAgICAgLy8gYXZvaWQgZWFybHkgJ3N0cmVhbVBsYXlpbmcnIGV2ZW50XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtLnVwZGF0ZU1lZGlhU3RyZWFtSW5WaWRlb3MoKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoISF0aGlzLmZpcnN0VmlkZW9FbGVtZW50KSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuY3JlYXRlVmlkZW9FbGVtZW50KHRoaXMuZmlyc3RWaWRlb0VsZW1lbnQudGFyZ2V0RWxlbWVudCwgPFZpZGVvSW5zZXJ0TW9kZT50aGlzLnByb3BlcnRpZXMuaW5zZXJ0TW9kZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGRlbGV0ZSB0aGlzLmZpcnN0VmlkZW9FbGVtZW50O1xuXG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuc3RyZWFtLmlzU2VuZFZpZGVvKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCF0aGlzLnN0cmVhbS5pc1NlbmRTY3JlZW4oKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gV2l0aCBubyBzY3JlZW4gc2hhcmUsIHZpZGVvIGRpbWVuc2lvbiBjYW4gYmUgc2V0IGRpcmVjdGx5IGZyb20gTWVkaWFTdHJlYW0gKGdldFNldHRpbmdzKVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gT3JpZW50YXRpb24gbXVzdCBiZSBjaGVja2VkIGZvciBtb2JpbGUgZGV2aWNlcyAod2lkdGggYW5kIGhlaWdodCBhcmUgcmV2ZXJzZWQpXG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB7IHdpZHRoLCBoZWlnaHQgfSA9IG1lZGlhU3RyZWFtLmdldFZpZGVvVHJhY2tzKClbMF0uZ2V0U2V0dGluZ3MoKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHBsYXRmb3JtLm5hbWUhIS50b0xvd2VyQ2FzZSgpLmluZGV4T2YoJ21vYmlsZScpICE9PSAtMSAmJiAod2luZG93LmlubmVySGVpZ2h0ID4gd2luZG93LmlubmVyV2lkdGgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gTW9iaWxlIHBvcnRyYWl0IG1vZGVcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbS52aWRlb0RpbWVuc2lvbnMgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdpZHRoOiBoZWlnaHQgfHwgMCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaGVpZ2h0OiB3aWR0aCB8fCAwXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdHJlYW0udmlkZW9EaW1lbnNpb25zID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3aWR0aDogd2lkdGggfHwgMCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaGVpZ2h0OiBoZWlnaHQgfHwgMFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbS5pc0xvY2FsU3RyZWFtUmVhZHlUb1B1Ymxpc2ggPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdHJlYW0uZWUuZW1pdEV2ZW50KCdzdHJlYW0tcmVhZHktdG8tcHVibGlzaCcsIFtdKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIFdpdGggc2NyZWVuIHNoYXJlLCB2aWRlbyBkaW1lbnNpb24gbXVzdCBiZSBnb3QgZnJvbSBhIHZpZGVvIGVsZW1lbnQgKG9ubG9hZGVkbWV0YWRhdGEgZXZlbnQpXG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnZpZGVvUmVmZXJlbmNlLm9ubG9hZGVkbWV0YWRhdGEgPSAoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdHJlYW0udmlkZW9EaW1lbnNpb25zID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3aWR0aDogdGhpcy52aWRlb1JlZmVyZW5jZS52aWRlb1dpZHRoLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBoZWlnaHQ6IHRoaXMudmlkZW9SZWZlcmVuY2UudmlkZW9IZWlnaHRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc2NyZWVuU2hhcmVSZXNpemVJbnRlcnZhbCA9IHNldEludGVydmFsKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZmlyZWZveFNldHRpbmdzID0gbWVkaWFTdHJlYW0uZ2V0VmlkZW9UcmFja3MoKVswXS5nZXRTZXR0aW5ncygpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBuZXdXaWR0aCA9IChwbGF0Zm9ybS5uYW1lID09PSAnQ2hyb21lJykgPyB0aGlzLnZpZGVvUmVmZXJlbmNlLnZpZGVvV2lkdGggOiBmaXJlZm94U2V0dGluZ3Mud2lkdGg7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG5ld0hlaWdodCA9IChwbGF0Zm9ybS5uYW1lID09PSAnQ2hyb21lJykgPyB0aGlzLnZpZGVvUmVmZXJlbmNlLnZpZGVvSGVpZ2h0IDogZmlyZWZveFNldHRpbmdzLmhlaWdodDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuc3RyZWFtLmlzTG9jYWxTdHJlYW1QdWJsaXNoZWQgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChuZXdXaWR0aCAhPT0gdGhpcy5zdHJlYW0udmlkZW9EaW1lbnNpb25zLndpZHRoIHx8XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3SGVpZ2h0ICE9PSB0aGlzLnN0cmVhbS52aWRlb0RpbWVuc2lvbnMuaGVpZ2h0KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3Qgb2xkVmFsdWUgPSB7IHdpZHRoOiB0aGlzLnN0cmVhbS52aWRlb0RpbWVuc2lvbnMud2lkdGgsIGhlaWdodDogdGhpcy5zdHJlYW0udmlkZW9EaW1lbnNpb25zLmhlaWdodCB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdHJlYW0udmlkZW9EaW1lbnNpb25zID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdpZHRoOiBuZXdXaWR0aCB8fCAwLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhlaWdodDogbmV3SGVpZ2h0IHx8IDBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnNlc3Npb24ub3BlbnZpZHUuc2VuZFJlcXVlc3QoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ3N0cmVhbVByb3BlcnR5Q2hhbmdlZCcsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJlYW1JZDogdGhpcy5zdHJlYW0uc3RyZWFtSWQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByb3BlcnR5OiAndmlkZW9EaW1lbnNpb25zJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3VmFsdWU6IEpTT04uc3RyaW5naWZ5KHRoaXMuc3RyZWFtLnZpZGVvRGltZW5zaW9ucyksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlYXNvbjogJ3NjcmVlblJlc2l6ZWQnXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoZXJyb3IsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihcIkVycm9yIHNlbmRpbmcgJ3N0cmVhbVByb3BlcnR5Q2hhbmdlZCcgZXZlbnRcIiwgZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXNzaW9uLmVtaXRFdmVudCgnc3RyZWFtUHJvcGVydHlDaGFuZ2VkJywgW25ldyBTdHJlYW1Qcm9wZXJ0eUNoYW5nZWRFdmVudCh0aGlzLnNlc3Npb24sIHRoaXMuc3RyZWFtLCAndmlkZW9EaW1lbnNpb25zJywgdGhpcy5zdHJlYW0udmlkZW9EaW1lbnNpb25zLCBvbGRWYWx1ZSwgJ3NjcmVlblJlc2l6ZWQnKV0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5lbWl0RXZlbnQoJ3N0cmVhbVByb3BlcnR5Q2hhbmdlZCcsIFtuZXcgU3RyZWFtUHJvcGVydHlDaGFuZ2VkRXZlbnQodGhpcywgdGhpcy5zdHJlYW0sICd2aWRlb0RpbWVuc2lvbnMnLCB0aGlzLnN0cmVhbS52aWRlb0RpbWVuc2lvbnMsIG9sZFZhbHVlLCAnc2NyZWVuUmVzaXplZCcpXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0sIDUwMCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdHJlYW0uaXNMb2NhbFN0cmVhbVJlYWR5VG9QdWJsaXNoID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbS5lZS5lbWl0RXZlbnQoJ3N0cmVhbS1yZWFkeS10by1wdWJsaXNoJywgW10pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtLmlzTG9jYWxTdHJlYW1SZWFkeVRvUHVibGlzaCA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtLmVlLmVtaXRFdmVudCgnc3RyZWFtLXJlYWR5LXRvLXB1Ymxpc2gnLCBbXSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIHRoaXMub3BlbnZpZHUuZ2VuZXJhdGVNZWRpYUNvbnN0cmFpbnRzKHRoaXMucHJvcGVydGllcylcbiAgICAgICAgICAgICAgICAudGhlbihjb25zdHJhaW50cyA9PiB7XG5cbiAgICAgICAgICAgICAgICAgICAgY29uc3Qgb3V0Ym91bmRTdHJlYW1PcHRpb25zID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgbWVkaWFDb25zdHJhaW50czogY29uc3RyYWludHMsXG4gICAgICAgICAgICAgICAgICAgICAgICBwdWJsaXNoZXJQcm9wZXJ0aWVzOiB0aGlzLnByb3BlcnRpZXNcbiAgICAgICAgICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbS5zZXRPdXRib3VuZFN0cmVhbU9wdGlvbnMob3V0Ym91bmRTdHJlYW1PcHRpb25zKTtcblxuICAgICAgICAgICAgICAgICAgICBjb25zdCBjb25zdHJhaW50c0F1eDogTWVkaWFTdHJlYW1Db25zdHJhaW50cyA9IHt9O1xuICAgICAgICAgICAgICAgICAgICBjb25zdCB0aW1lRm9yRGlhbG9nRXZlbnQgPSAxMjUwO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLnN0cmVhbS5pc1NlbmRWaWRlbygpIHx8IHRoaXMuc3RyZWFtLmlzU2VuZEF1ZGlvKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGRlZmluZWRBdWRpb0NvbnN0cmFpbnQgPSAoKGNvbnN0cmFpbnRzLmF1ZGlvID09PSB1bmRlZmluZWQpID8gdHJ1ZSA6IGNvbnN0cmFpbnRzLmF1ZGlvKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0cmFpbnRzQXV4LmF1ZGlvID0gdGhpcy5zdHJlYW0uaXNTZW5kU2NyZWVuKCkgPyBmYWxzZSA6IGRlZmluZWRBdWRpb0NvbnN0cmFpbnQ7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdHJhaW50c0F1eC52aWRlbyA9IGNvbnN0cmFpbnRzLnZpZGVvO1xuICAgICAgICAgICAgICAgICAgICAgICAgbGV0IHN0YXJ0VGltZSA9IERhdGUubm93KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnNldFBlcm1pc3Npb25EaWFsb2dUaW1lcih0aW1lRm9yRGlhbG9nRXZlbnQpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBuYXZpZ2F0b3IubWVkaWFEZXZpY2VzLmdldFVzZXJNZWRpYShjb25zdHJhaW50c0F1eClcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAudGhlbihtZWRpYVN0cmVhbSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY2xlYXJQZXJtaXNzaW9uRGlhbG9nVGltZXIoc3RhcnRUaW1lLCB0aW1lRm9yRGlhbG9nRXZlbnQpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLnN0cmVhbS5pc1NlbmRTY3JlZW4oKSAmJiB0aGlzLnN0cmVhbS5pc1NlbmRBdWRpbygpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBXaGVuIGdldHRpbmcgZGVza3RvcCBhcyB1c2VyIG1lZGlhIGF1ZGlvIGNvbnN0cmFpbnQgbXVzdCBiZSBmYWxzZS4gTm93IHdlIGNhbiBhc2sgZm9yIGl0IGlmIHJlcXVpcmVkXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdHJhaW50c0F1eC5hdWRpbyA9IGRlZmluZWRBdWRpb0NvbnN0cmFpbnQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdHJhaW50c0F1eC52aWRlbyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhcnRUaW1lID0gRGF0ZS5ub3coKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc2V0UGVybWlzc2lvbkRpYWxvZ1RpbWVyKHRpbWVGb3JEaWFsb2dFdmVudCk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hdmlnYXRvci5tZWRpYURldmljZXMuZ2V0VXNlck1lZGlhKGNvbnN0cmFpbnRzQXV4KVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC50aGVuKGF1ZGlvT25seVN0cmVhbSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY2xlYXJQZXJtaXNzaW9uRGlhbG9nVGltZXIoc3RhcnRUaW1lLCB0aW1lRm9yRGlhbG9nRXZlbnQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZWRpYVN0cmVhbS5hZGRUcmFjayhhdWRpb09ubHlTdHJlYW0uZ2V0QXVkaW9UcmFja3MoKVswXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN1Y2Nlc3NDYWxsYmFjayhtZWRpYVN0cmVhbSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNsZWFyUGVybWlzc2lvbkRpYWxvZ1RpbWVyKHN0YXJ0VGltZSwgdGltZUZvckRpYWxvZ0V2ZW50KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGVycm9yTmFtZSwgZXJyb3JNZXNzYWdlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzd2l0Y2ggKGVycm9yLm5hbWUudG9Mb3dlckNhc2UoKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAnbm90Zm91bmRlcnJvcic6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JOYW1lID0gT3BlblZpZHVFcnJvck5hbWUuSU5QVVRfQVVESU9fREVWSUNFX05PVF9GT1VORDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck1lc3NhZ2UgPSBlcnJvci50b1N0cmluZygpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yQ2FsbGJhY2sobmV3IE9wZW5WaWR1RXJyb3IoZXJyb3JOYW1lLCBlcnJvck1lc3NhZ2UpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJ25vdGFsbG93ZWRlcnJvcic6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JOYW1lID0gT3BlblZpZHVFcnJvck5hbWUuREVWSUNFX0FDQ0VTU19ERU5JRUQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JNZXNzYWdlID0gZXJyb3IudG9TdHJpbmcoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvckNhbGxiYWNrKG5ldyBPcGVuVmlkdUVycm9yKGVycm9yTmFtZSwgZXJyb3JNZXNzYWdlKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlICdvdmVyY29uc3RyYWluZWRlcnJvcic6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yLmNvbnN0cmFpbnQudG9Mb3dlckNhc2UoKSA9PT0gJ2RldmljZWlkJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck5hbWUgPSBPcGVuVmlkdUVycm9yTmFtZS5JTlBVVF9BVURJT19ERVZJQ0VfTk9UX0ZPVU5EO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck1lc3NhZ2UgPSBcIkF1ZGlvIGlucHV0IGRldmljZSB3aXRoIGRldmljZUlkICdcIiArICg8Q29uc3RyYWluRE9NU3RyaW5nUGFyYW1ldGVycz4oPE1lZGlhVHJhY2tDb25zdHJhaW50cz5jb25zdHJhaW50cy52aWRlbykuZGV2aWNlSWQhISkuZXhhY3QgKyBcIicgbm90IGZvdW5kXCI7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JOYW1lID0gT3BlblZpZHVFcnJvck5hbWUuUFVCTElTSEVSX1BST1BFUlRJRVNfRVJST1I7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yTWVzc2FnZSA9IFwiQXVkaW8gaW5wdXQgZGV2aWNlIGRvZXNuJ3Qgc3VwcG9ydCB0aGUgdmFsdWUgcGFzc2VkIGZvciBjb25zdHJhaW50ICdcIiArIGVycm9yLmNvbnN0cmFpbnQgKyBcIidcIjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JDYWxsYmFjayhuZXcgT3BlblZpZHVFcnJvcihlcnJvck5hbWUsIGVycm9yTWVzc2FnZSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdWNjZXNzQ2FsbGJhY2sobWVkaWFTdHJlYW0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNsZWFyUGVybWlzc2lvbkRpYWxvZ1RpbWVyKHN0YXJ0VGltZSwgdGltZUZvckRpYWxvZ0V2ZW50KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGVycm9yTmFtZSwgZXJyb3JNZXNzYWdlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzd2l0Y2ggKGVycm9yLm5hbWUudG9Mb3dlckNhc2UoKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAnbm90Zm91bmRlcnJvcic6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmF2aWdhdG9yLm1lZGlhRGV2aWNlcy5nZXRVc2VyTWVkaWEoe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhdWRpbzogZmFsc2UsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZpZGVvOiBjb25zdHJhaW50cy52aWRlb1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC50aGVuKG1lZGlhU3RyZWFtID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1lZGlhU3RyZWFtLmdldFZpZGVvVHJhY2tzKCkuZm9yRWFjaCgodHJhY2spID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cmFjay5zdG9wKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yTmFtZSA9IE9wZW5WaWR1RXJyb3JOYW1lLklOUFVUX0FVRElPX0RFVklDRV9OT1RfRk9VTkQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck1lc3NhZ2UgPSBlcnJvci50b1N0cmluZygpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JDYWxsYmFjayhuZXcgT3BlblZpZHVFcnJvcihlcnJvck5hbWUsIGVycm9yTWVzc2FnZSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KS5jYXRjaChlID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yTmFtZSA9IE9wZW5WaWR1RXJyb3JOYW1lLklOUFVUX1ZJREVPX0RFVklDRV9OT1RfRk9VTkQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck1lc3NhZ2UgPSBlcnJvci50b1N0cmluZygpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JDYWxsYmFjayhuZXcgT3BlblZpZHVFcnJvcihlcnJvck5hbWUsIGVycm9yTWVzc2FnZSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJ25vdGFsbG93ZWRlcnJvcic6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JOYW1lID0gdGhpcy5zdHJlYW0uaXNTZW5kU2NyZWVuKCkgPyBPcGVuVmlkdUVycm9yTmFtZS5TQ1JFRU5fQ0FQVFVSRV9ERU5JRUQgOiBPcGVuVmlkdUVycm9yTmFtZS5ERVZJQ0VfQUNDRVNTX0RFTklFRDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck1lc3NhZ2UgPSBlcnJvci50b1N0cmluZygpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yQ2FsbGJhY2sobmV3IE9wZW5WaWR1RXJyb3IoZXJyb3JOYW1lLCBlcnJvck1lc3NhZ2UpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJ292ZXJjb25zdHJhaW5lZGVycm9yJzpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYXZpZ2F0b3IubWVkaWFEZXZpY2VzLmdldFVzZXJNZWRpYSh7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGF1ZGlvOiBmYWxzZSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmlkZW86IGNvbnN0cmFpbnRzLnZpZGVvXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLnRoZW4obWVkaWFTdHJlYW0gPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWVkaWFTdHJlYW0uZ2V0VmlkZW9UcmFja3MoKS5mb3JFYWNoKCh0cmFjaykgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRyYWNrLnN0b3AoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yLmNvbnN0cmFpbnQudG9Mb3dlckNhc2UoKSA9PT0gJ2RldmljZWlkJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yTmFtZSA9IE9wZW5WaWR1RXJyb3JOYW1lLklOUFVUX0FVRElPX0RFVklDRV9OT1RfRk9VTkQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JNZXNzYWdlID0gXCJBdWRpbyBpbnB1dCBkZXZpY2Ugd2l0aCBkZXZpY2VJZCAnXCIgKyAoPENvbnN0cmFpbkRPTVN0cmluZ1BhcmFtZXRlcnM+KDxNZWRpYVRyYWNrQ29uc3RyYWludHM+Y29uc3RyYWludHMuYXVkaW8pLmRldmljZUlkISEpLmV4YWN0ICsgXCInIG5vdCBmb3VuZFwiO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck5hbWUgPSBPcGVuVmlkdUVycm9yTmFtZS5QVUJMSVNIRVJfUFJPUEVSVElFU19FUlJPUjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck1lc3NhZ2UgPSBcIkF1ZGlvIGlucHV0IGRldmljZSBkb2Vzbid0IHN1cHBvcnQgdGhlIHZhbHVlIHBhc3NlZCBmb3IgY29uc3RyYWludCAnXCIgKyBlcnJvci5jb25zdHJhaW50ICsgXCInXCI7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvckNhbGxiYWNrKG5ldyBPcGVuVmlkdUVycm9yKGVycm9yTmFtZSwgZXJyb3JNZXNzYWdlKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pLmNhdGNoKGUgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yLmNvbnN0cmFpbnQudG9Mb3dlckNhc2UoKSA9PT0gJ2RldmljZWlkJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yTmFtZSA9IE9wZW5WaWR1RXJyb3JOYW1lLklOUFVUX1ZJREVPX0RFVklDRV9OT1RfRk9VTkQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JNZXNzYWdlID0gXCJWaWRlbyBpbnB1dCBkZXZpY2Ugd2l0aCBkZXZpY2VJZCAnXCIgKyAoPENvbnN0cmFpbkRPTVN0cmluZ1BhcmFtZXRlcnM+KDxNZWRpYVRyYWNrQ29uc3RyYWludHM+Y29uc3RyYWludHMudmlkZW8pLmRldmljZUlkISEpLmV4YWN0ICsgXCInIG5vdCBmb3VuZFwiO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck5hbWUgPSBPcGVuVmlkdUVycm9yTmFtZS5QVUJMSVNIRVJfUFJPUEVSVElFU19FUlJPUjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck1lc3NhZ2UgPSBcIlZpZGVvIGlucHV0IGRldmljZSBkb2Vzbid0IHN1cHBvcnQgdGhlIHZhbHVlIHBhc3NlZCBmb3IgY29uc3RyYWludCAnXCIgKyBlcnJvci5jb25zdHJhaW50ICsgXCInXCI7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvckNhbGxiYWNrKG5ldyBPcGVuVmlkdUVycm9yKGVycm9yTmFtZSwgZXJyb3JNZXNzYWdlKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZWplY3QobmV3IE9wZW5WaWR1RXJyb3IoT3BlblZpZHVFcnJvck5hbWUuTk9fSU5QVVRfU09VUkNFX1NFVCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBcIlByb3BlcnRpZXMgJ2F1ZGlvU291cmNlJyBhbmQgJ3ZpZGVvU291cmNlJyBjYW5ub3QgYmUgc2V0IHRvIGZhbHNlIG9yIG51bGwgYXQgdGhlIHNhbWUgdGltZSB3aGVuIGNhbGxpbmcgJ09wZW5WaWR1LmluaXRQdWJsaXNoZXInXCIpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgLmNhdGNoKChlcnJvcjogT3BlblZpZHVFcnJvcikgPT4ge1xuICAgICAgICAgICAgICAgICAgICBlcnJvckNhbGxiYWNrKGVycm9yKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHVwZGF0ZVNlc3Npb24oc2Vzc2lvbjogU2Vzc2lvbik6IHZvaWQge1xuICAgICAgICB0aGlzLnNlc3Npb24gPSBzZXNzaW9uO1xuICAgICAgICB0aGlzLnN0cmVhbS5zZXNzaW9uID0gc2Vzc2lvbjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgcmVlc3RhYmxpc2hTdHJlYW1QbGF5aW5nRXZlbnQoKSB7XG4gICAgICAgIGlmICh0aGlzLmVlLmdldExpc3RlbmVycygnc3RyZWFtUGxheWluZycpLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgIHRoaXMuYWRkUGxheUV2ZW50VG9GaXJzdFZpZGVvKCk7XG4gICAgICAgIH1cbiAgICB9XG5cblxuICAgIC8qIFByaXZhdGUgbWV0aG9kcyAqL1xuXG4gICAgcHJpdmF0ZSBzZXRQZXJtaXNzaW9uRGlhbG9nVGltZXIod2FpdFRpbWU6IG51bWJlcik6IHZvaWQge1xuICAgICAgICB0aGlzLnBlcm1pc3Npb25EaWFsb2dUaW1lb3V0ID0gc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgICAgICB0aGlzLmVtaXRFdmVudCgnYWNjZXNzRGlhbG9nT3BlbmVkJywgW10pO1xuICAgICAgICB9LCB3YWl0VGltZSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBjbGVhclBlcm1pc3Npb25EaWFsb2dUaW1lcihzdGFydFRpbWU6IG51bWJlciwgd2FpdFRpbWU6IG51bWJlcik6IHZvaWQge1xuICAgICAgICBjbGVhclRpbWVvdXQodGhpcy5wZXJtaXNzaW9uRGlhbG9nVGltZW91dCk7XG4gICAgICAgIGlmICgoRGF0ZS5ub3coKSAtIHN0YXJ0VGltZSkgPiB3YWl0VGltZSkge1xuICAgICAgICAgICAgLy8gUGVybWlzc2lvbiBkaWFsb2cgd2FzIHNob3duIGFuZCBub3cgaXMgY2xvc2VkXG4gICAgICAgICAgICB0aGlzLmVtaXRFdmVudCgnYWNjZXNzRGlhbG9nQ2xvc2VkJywgW10pO1xuICAgICAgICB9XG4gICAgfVxuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBDb25uZWN0aW9uIH0gZnJvbSAnLi9Db25uZWN0aW9uJztcbmltcG9ydCB7IE9wZW5WaWR1IH0gZnJvbSAnLi9PcGVuVmlkdSc7XG5pbXBvcnQgeyBQdWJsaXNoZXIgfSBmcm9tICcuL1B1Ymxpc2hlcic7XG5pbXBvcnQgeyBTdHJlYW0gfSBmcm9tICcuL1N0cmVhbSc7XG5pbXBvcnQgeyBTdHJlYW1NYW5hZ2VyIH0gZnJvbSAnLi9TdHJlYW1NYW5hZ2VyJztcbmltcG9ydCB7IFN1YnNjcmliZXIgfSBmcm9tICcuL1N1YnNjcmliZXInO1xuaW1wb3J0IHsgQ2FwYWJpbGl0aWVzIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9JbnRlcmZhY2VzL1B1YmxpYy9DYXBhYmlsaXRpZXMnO1xuaW1wb3J0IHsgRXZlbnREaXNwYXRjaGVyIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9JbnRlcmZhY2VzL1B1YmxpYy9FdmVudERpc3BhdGNoZXInO1xuaW1wb3J0IHsgU2lnbmFsT3B0aW9ucyB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvSW50ZXJmYWNlcy9QdWJsaWMvU2lnbmFsT3B0aW9ucyc7XG5pbXBvcnQgeyBTdWJzY3JpYmVyUHJvcGVydGllcyB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvSW50ZXJmYWNlcy9QdWJsaWMvU3Vic2NyaWJlclByb3BlcnRpZXMnO1xuaW1wb3J0IHsgQ29ubmVjdGlvbk9wdGlvbnMgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHJpdmF0ZS9Db25uZWN0aW9uT3B0aW9ucyc7XG5pbXBvcnQgeyBPYmpNYXAgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHJpdmF0ZS9PYmpNYXAnO1xuaW1wb3J0IHsgU2Vzc2lvbk9wdGlvbnMgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHJpdmF0ZS9TZXNzaW9uT3B0aW9ucyc7XG5pbXBvcnQgeyBDb25uZWN0aW9uRXZlbnQgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0V2ZW50cy9Db25uZWN0aW9uRXZlbnQnO1xuaW1wb3J0IHsgUHVibGlzaGVyU3BlYWtpbmdFdmVudCB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1B1Ymxpc2hlclNwZWFraW5nRXZlbnQnO1xuaW1wb3J0IHsgUmVjb3JkaW5nRXZlbnQgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0V2ZW50cy9SZWNvcmRpbmdFdmVudCc7XG5pbXBvcnQgeyBTZXNzaW9uRGlzY29ubmVjdGVkRXZlbnQgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0V2ZW50cy9TZXNzaW9uRGlzY29ubmVjdGVkRXZlbnQnO1xuaW1wb3J0IHsgU2lnbmFsRXZlbnQgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0V2ZW50cy9TaWduYWxFdmVudCc7XG5pbXBvcnQgeyBTdHJlYW1FdmVudCB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1N0cmVhbUV2ZW50JztcbmltcG9ydCB7IFN0cmVhbVByb3BlcnR5Q2hhbmdlZEV2ZW50IH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvU3RyZWFtUHJvcGVydHlDaGFuZ2VkRXZlbnQnO1xuaW1wb3J0IHsgT3BlblZpZHVFcnJvciwgT3BlblZpZHVFcnJvck5hbWUgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0VudW1zL09wZW5WaWR1RXJyb3InO1xuaW1wb3J0IHsgVmlkZW9JbnNlcnRNb2RlIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FbnVtcy9WaWRlb0luc2VydE1vZGUnO1xuXG5pbXBvcnQgcGxhdGZvcm0gPSByZXF1aXJlKCdwbGF0Zm9ybScpO1xuaW1wb3J0IEV2ZW50RW1pdHRlciA9IHJlcXVpcmUoJ3dvbGZ5ODctZXZlbnRlbWl0dGVyJyk7XG5cblxuLyoqXG4gKiBSZXByZXNlbnRzIGEgdmlkZW8gY2FsbC4gSXQgY2FuIGFsc28gYmUgc2VlbiBhcyBhIHZpZGVvY29uZmVyZW5jZSByb29tIHdoZXJlIG11bHRpcGxlIHVzZXJzIGNhbiBjb25uZWN0LlxuICogUGFydGljaXBhbnRzIHdobyBwdWJsaXNoIHRoZWlyIHZpZGVvcyB0byBhIHNlc3Npb24gY2FuIGJlIHNlZW4gYnkgdGhlIHJlc3Qgb2YgdXNlcnMgY29ubmVjdGVkIHRvIHRoYXQgc3BlY2lmaWMgc2Vzc2lvbi5cbiAqIEluaXRpYWxpemVkIHdpdGggW1tPcGVuVmlkdS5pbml0U2Vzc2lvbl1dIG1ldGhvZFxuICovXG5leHBvcnQgY2xhc3MgU2Vzc2lvbiBpbXBsZW1lbnRzIEV2ZW50RGlzcGF0Y2hlciB7XG5cbiAgICAvKipcbiAgICAgKiBMb2NhbCBjb25uZWN0aW9uIHRvIHRoZSBTZXNzaW9uLiBUaGlzIG9iamVjdCBpcyBkZWZpbmVkIG9ubHkgYWZ0ZXIgW1tTZXNzaW9uLmNvbm5lY3RdXSBoYXMgYmVlbiBzdWNjZXNzZnVsbHkgZXhlY3V0ZWQsIGFuZCBjYW4gYmUgcmV0cmlldmVkIHN1YnNjcmliaW5nIHRvIGBjb25uZWN0aW9uQ3JlYXRlZGAgZXZlbnRcbiAgICAgKi9cbiAgICBjb25uZWN0aW9uOiBDb25uZWN0aW9uO1xuXG4gICAgLyoqXG4gICAgICogVW5pcXVlIGlkZW50aWZpZXIgb2YgdGhlIFNlc3Npb25cbiAgICAgKi9cbiAgICBzZXNzaW9uSWQ6IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIENvbGxlY3Rpb24gb2YgYWxsIFN0cmVhbU1hbmFnZXJzIG9mIHRoaXMgU2Vzc2lvbiAoW1tQdWJsaXNoZXJdXSBhbmQgW1tTdWJzY3JpYmVyXV0pXG4gICAgICovXG4gICAgc3RyZWFtTWFuYWdlcnM6IFN0cmVhbU1hbmFnZXJbXSA9IFtdO1xuXG4gICAgLyoqXG4gICAgICogT2JqZWN0IGRlZmluaW5nIHRoZSBtZXRob2RzIHRoYXQgdGhlIGNsaWVudCBpcyBhYmxlIHRvIGNhbGwuIFRoZXNlIGFyZSBkZWZpbmVkIGJ5IHRoZSByb2xlIG9mIHRoZSB0b2tlbiB1c2VkIHRvIGNvbm5lY3QgdG8gdGhlIFNlc3Npb24uXG4gICAgICogVGhpcyBvYmplY3QgaXMgb25seSBkZWZpbmVkIGFmdGVyIFtbU2Vzc2lvbi5jb25uZWN0XV0gaGFzIGJlZW4gc3VjY2Vzc2Z1bGx5IHJlc29sdmVkXG4gICAgICovXG4gICAgY2FwYWJpbGl0aWVzOiBDYXBhYmlsaXRpZXM7XG5cbiAgICAvLyBUaGlzIG1hcCBpcyBvbmx5IHVzZWQgdG8gYXZvaWQgcmFjZSBjb25kaXRpb24gYmV0d2VlbiAnam9pblJvb20nIHJlc3BvbnNlIGFuZCAnb25QYXJ0aWNpcGFudFB1Ymxpc2hlZCcgbm90aWZpY2F0aW9uXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHJlbW90ZVN0cmVhbXNDcmVhdGVkOiBPYmpNYXA8Ym9vbGVhbj4gPSB7fTtcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICByZW1vdGVDb25uZWN0aW9uczogT2JqTWFwPENvbm5lY3Rpb24+ID0ge307XG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIG9wZW52aWR1OiBPcGVuVmlkdTtcbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgb3B0aW9uczogU2Vzc2lvbk9wdGlvbnM7XG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHNwZWFraW5nRXZlbnRzRW5hYmxlZCA9IGZhbHNlO1xuXG4gICAgcHJpdmF0ZSBlZSA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3RvcihvcGVudmlkdTogT3BlblZpZHUpIHtcbiAgICAgICAgdGhpcy5vcGVudmlkdSA9IG9wZW52aWR1O1xuICAgIH1cblxuICAgIGNvbm5lY3QodG9rZW46IHN0cmluZyk6IFByb21pc2U8YW55PjtcbiAgICBjb25uZWN0KHRva2VuOiBzdHJpbmcsIG1ldGFkYXRhOiBhbnkpOiBQcm9taXNlPGFueT47XG5cbiAgICAvKipcbiAgICAgKiBDb25uZWN0cyB0byB0aGUgc2Vzc2lvbiB1c2luZyBgdG9rZW5gLiBQYXJhbWV0ZXIgYG1ldGFkYXRhYCBhbGxvd3MgeW91IHRvIHBhc3MgZXh0cmEgZGF0YSB0byBzaGFyZSB3aXRoIG90aGVyIHVzZXJzIHdoZW5cbiAgICAgKiB0aGV5IHJlY2VpdmUgYHN0cmVhbUNyZWF0ZWRgIGV2ZW50LiBUaGUgc3RydWN0dXJlIG9mIGBtZXRhZGF0YWAgc3RyaW5nIGlzIHVwIHRvIHlvdSAobWF5YmUgc29tZSBzdGFuZGFyaXplZCBmb3JtYXRcbiAgICAgKiBhcyBKU09OIG9yIFhNTCBpcyBhIGdvb2QgaWRlYSksIHRoZSBvbmx5IHJlc3RyaWN0aW9uIGlzIGEgbWF4aW11bSBsZW5ndGggb2YgMTAwMDAgY2hhcnMuXG4gICAgICpcbiAgICAgKiBUaGlzIG1ldGFkYXRhIGlzIG5vdCBjb25zaWRlcmVkIHNlY3VyZSwgYXMgaXQgaXMgZ2VuZXJhdGVkIGluIHRoZSBjbGllbnQgc2lkZS4gVG8gcGFzcyBzZWN1cml6ZWQgZGF0YSwgYWRkIGl0IGFzIGEgcGFyYW1ldGVyIGluIHRoZVxuICAgICAqIHRva2VuIGdlbmVyYXRpb24gb3BlcmF0aW9uICh0aHJvdWdoIHRoZSBBUEkgUkVTVCwgb3BlbnZpZHUtamF2YS1jbGllbnQgb3Igb3BlbnZpZHUtbm9kZS1jbGllbnQpLlxuICAgICAqXG4gICAgICogT25seSBhZnRlciB0aGUgcmV0dXJuZWQgUHJvbWlzZSBpcyBzdWNjZXNzZnVsbHkgcmVzb2x2ZWQgW1tTZXNzaW9uLmNvbm5lY3Rpb25dXSBvYmplY3Qgd2lsbCBiZSBhdmFpbGFibGUgYW5kIHByb3Blcmx5IGRlZmluZWQuXG4gICAgICpcbiAgICAgKiAjIyMjIEV2ZW50cyBkaXNwYXRjaGVkXG4gICAgICpcbiAgICAgKiBUaGUgW1tTZXNzaW9uXV0gb2JqZWN0IG9mIHRoZSBsb2NhbCBwYXJ0aWNpcGFudCB3aWxsIGZpcnN0IGRpc3BhdGNoIG9uZSBvciBtb3JlIGBjb25uZWN0aW9uQ3JlYXRlZGAgZXZlbnRzIHVwb24gc3VjY2Vzc2Z1bCB0ZXJtaW5hdGlvbiBvZiB0aGlzIG1ldGhvZDpcbiAgICAgKiAtIEZpcnN0IG9uZSBmb3IgeW91ciBvd24gbG9jYWwgQ29ubmVjdGlvbiBvYmplY3QsIHNvIHlvdSBjYW4gcmV0cmlldmUgW1tTZXNzaW9uLmNvbm5lY3Rpb25dXSBwcm9wZXJ0eS5cbiAgICAgKiAtIFRoZW4gb25lIGZvciBlYWNoIHJlbW90ZSBDb25uZWN0aW9uIHByZXZpb3VzbHkgY29ubmVjdGVkIHRvIHRoZSBTZXNzaW9uLCBpZiBhbnkuIEFueSBvdGhlciByZW1vdGUgdXNlciBjb25uZWN0aW5nIHRvIHRoZSBTZXNzaW9uIGFmdGVyIHlvdSBoYXZlXG4gICAgICogc3VjY2Vzc2Z1bGx5IGNvbm5lY3RlZCB3aWxsIGFsc28gZGlzcGF0Y2ggYSBgY29ubmVjdGlvbkNyZWF0ZWRgIGV2ZW50IHdoZW4gdGhleSBkbyBzby5cbiAgICAgKlxuICAgICAqIFRoZSBbW1Nlc3Npb25dXSBvYmplY3Qgb2YgdGhlIGxvY2FsIHBhcnRpY2lwYW50IHdpbGwgYWxzbyBkaXNwYXRjaCBhIGBzdHJlYW1DcmVhdGVkYCBldmVudCBmb3IgZWFjaCByZW1vdGUgYWN0aXZlIFtbUHVibGlzaGVyXV0gdGhhdCB3YXMgYWxyZWFkeSBzdHJlYW1pbmdcbiAgICAgKiB3aGVuIGNvbm5lY3RpbmcsIGp1c3QgYWZ0ZXIgZGlzcGF0Y2hpbmcgYWxsIHJlbW90ZSBgY29ubmVjdGlvbkNyZWF0ZWRgIGV2ZW50cy5cbiAgICAgKlxuICAgICAqIFRoZSBbW1Nlc3Npb25dXSBvYmplY3Qgb2YgZXZlcnkgb3RoZXIgcGFydGljaXBhbnQgY29ubmVjdGVkIHRvIHRoZSBzZXNzaW9uIHdpbGwgZGlzcGF0Y2ggYSBgY29ubmVjdGlvbkNyZWF0ZWRgIGV2ZW50LlxuICAgICAqXG4gICAgICogU2VlIFtbQ29ubmVjdGlvbkV2ZW50XV0gYW5kIFtbU3RyZWFtRXZlbnRdXSB0byBsZWFybiBtb3JlLlxuICAgICAqXG4gICAgICogQHJldHVybnMgQSBQcm9taXNlIHRvIHdoaWNoIHlvdSBtdXN0IHN1YnNjcmliZSB0aGF0IGlzIHJlc29sdmVkIGlmIHRoZSB0aGUgY29ubmVjdGlvbiB0byB0aGUgU2Vzc2lvbiB3YXMgc3VjY2Vzc2Z1bCBhbmQgcmVqZWN0ZWQgd2l0aCBhbiBFcnJvciBvYmplY3QgaWYgbm90XG4gICAgICpcbiAgICAgKi9cbiAgICBjb25uZWN0KHRva2VuOiBzdHJpbmcsIG1ldGFkYXRhPzogYW55KTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcblxuICAgICAgICAgICAgdGhpcy5wcm9jZXNzVG9rZW4odG9rZW4pO1xuXG4gICAgICAgICAgICBpZiAodGhpcy5vcGVudmlkdS5jaGVja1N5c3RlbVJlcXVpcmVtZW50cygpKSB7XG4gICAgICAgICAgICAgICAgLy8gRWFybHkgY29uZmlndXJhdGlvbiB0byBkZWFjdGl2YXRlIGF1dG9tYXRpYyBzdWJzY3JpcHRpb24gdG8gc3RyZWFtc1xuICAgICAgICAgICAgICAgIHRoaXMub3B0aW9ucyA9IHtcbiAgICAgICAgICAgICAgICAgICAgc2Vzc2lvbklkOiB0aGlzLnNlc3Npb25JZCxcbiAgICAgICAgICAgICAgICAgICAgcGFydGljaXBhbnRJZDogdG9rZW4sXG4gICAgICAgICAgICAgICAgICAgIG1ldGFkYXRhOiAhIW1ldGFkYXRhID8gdGhpcy5zdHJpbmdDbGllbnRNZXRhZGF0YShtZXRhZGF0YSkgOiAnJ1xuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgdGhpcy5jb25uZWN0QXV4KHRva2VuKS50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgICAgICAgIH0pLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmVqZWN0KG5ldyBPcGVuVmlkdUVycm9yKE9wZW5WaWR1RXJyb3JOYW1lLkJST1dTRVJfTk9UX1NVUFBPUlRFRCwgJ0Jyb3dzZXIgJyArIHBsYXRmb3JtLm5hbWUgKyAnICcgKyBwbGF0Zm9ybS52ZXJzaW9uICsgJyBpcyBub3Qgc3VwcG9ydGVkIGluIE9wZW5WaWR1JykpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBMZWF2ZXMgdGhlIHNlc3Npb24sIGRlc3Ryb3lpbmcgYWxsIHN0cmVhbXMgYW5kIGRlbGV0aW5nIHRoZSB1c2VyIGFzIGEgcGFydGljaXBhbnQuXG4gICAgICpcbiAgICAgKiAjIyMjIEV2ZW50cyBkaXNwYXRjaGVkXG4gICAgICpcbiAgICAgKiBUaGUgW1tTZXNzaW9uXV0gb2JqZWN0IG9mIHRoZSBsb2NhbCBwYXJ0aWNpcGFudCB3aWxsIGRpc3BhdGNoIGEgYHNlc3Npb25EaXNjb25uZWN0ZWRgIGV2ZW50LlxuICAgICAqIFRoaXMgZXZlbnQgd2lsbCBhdXRvbWF0aWNhbGx5IHVuc3Vic2NyaWJlIHRoZSBsZWF2aW5nIHBhcnRpY2lwYW50IGZyb20gZXZlcnkgU3Vic2NyaWJlciBvYmplY3Qgb2YgdGhlIHNlc3Npb24gKHRoaXMgaW5jbHVkZXMgY2xvc2luZyB0aGUgV2ViUlRDUGVlciBjb25uZWN0aW9uIGFuZCBkaXNwb3NpbmcgYWxsIE1lZGlhU3RyZWFtVHJhY2tzKVxuICAgICAqIGFuZCBhbHNvIGRlbGV0ZXMgYW55IEhUTUwgdmlkZW8gZWxlbWVudCBhc3NvY2lhdGVkIHRvIGVhY2ggU3Vic2NyaWJlciAob25seSB0aG9zZSBbY3JlYXRlZCBieSBPcGVuVmlkdSBCcm93c2VyXSgvZG9jcy9ob3ctZG8taS9tYW5hZ2UtdmlkZW9zLyNsZXQtb3BlbnZpZHUtdGFrZS1jYXJlLW9mLXRoZS12aWRlby1wbGF5ZXJzKSkuXG4gICAgICogRm9yIGV2ZXJ5IHZpZGVvIHJlbW92ZWQsIGVhY2ggU3Vic2NyaWJlciBvYmplY3Qgd2lsbCBkaXNwYXRjaCBhIGB2aWRlb0VsZW1lbnREZXN0cm95ZWRgIGV2ZW50LlxuICAgICAqIENhbGwgYGV2ZW50LnByZXZlbnREZWZhdWx0KClgIHVwb24gZXZlbnQgYHNlc3Npb25EaXNjb25uZWN0ZWRgIHRvIGF2b2lkIHRoaXMgYmVoYXZpb3IgYW5kIHRha2UgY2FyZSBvZiBkaXNwb3NpbmcgYW5kIGNsZWFuaW5nIGFsbCB0aGUgU3Vic2NyaWJlciBvYmplY3RzIHlvdXJzZWxmLlxuICAgICAqIFNlZSBbW1Nlc3Npb25EaXNjb25uZWN0ZWRFdmVudF1dIGFuZCBbW1ZpZGVvRWxlbWVudEV2ZW50XV0gdG8gbGVhcm4gbW9yZSB0byBsZWFybiBtb3JlLlxuICAgICAqXG4gICAgICogVGhlIFtbUHVibGlzaGVyXV0gb2JqZWN0IG9mIHRoZSBsb2NhbCBwYXJ0aWNpcGFudCB3aWxsIGRpc3BhdGNoIGEgYHN0cmVhbURlc3Ryb3llZGAgZXZlbnQgaWYgdGhlcmUgaXMgYSBbW1B1Ymxpc2hlcl1dIG9iamVjdCBwdWJsaXNoaW5nIHRvIHRoZSBzZXNzaW9uLlxuICAgICAqIFRoaXMgZXZlbnQgd2lsbCBhdXRvbWF0aWNhbGx5IHN0b3AgYWxsIG1lZGlhIHRyYWNrcyBhbmQgZGVsZXRlIGFueSBIVE1MIHZpZGVvIGVsZW1lbnQgYXNzb2NpYXRlZCB0byBpdCAob25seSB0aG9zZSBbY3JlYXRlZCBieSBPcGVuVmlkdSBCcm93c2VyXSgvZG9jcy9ob3ctZG8taS9tYW5hZ2UtdmlkZW9zLyNsZXQtb3BlbnZpZHUtdGFrZS1jYXJlLW9mLXRoZS12aWRlby1wbGF5ZXJzKSkuXG4gICAgICogRm9yIGV2ZXJ5IHZpZGVvIHJlbW92ZWQsIHRoZSBQdWJsaXNoZXIgb2JqZWN0IHdpbGwgZGlzcGF0Y2ggYSBgdmlkZW9FbGVtZW50RGVzdHJveWVkYCBldmVudC5cbiAgICAgKiBDYWxsIGBldmVudC5wcmV2ZW50RGVmYXVsdCgpYCB1cG9uIGV2ZW50IGBzdHJlYW1EZXN0cm95ZWRgIGlmIHlvdSB3YW50IHRvIGNsZWFuIHRoZSBQdWJsaXNoZXIgb2JqZWN0IG9uIHlvdXIgb3duIG9yIHJlLXB1Ymxpc2ggaXQgaW4gYSBkaWZmZXJlbnQgU2Vzc2lvbiAodG8gZG8gc28gaXQgaXMgYSBtYW5kYXRvcnkgcmVxdWlyZW1lbnQgdG8gY2FsbCBgU2Vzc2lvbi51bnB1Ymxpc2goKWBcbiAgICAgKiBvci9hbmQgYFNlc3Npb24uZGlzY29ubmVjdCgpYCBpbiB0aGUgcHJldmlvdXMgc2Vzc2lvbikuIFNlZSBbW1N0cmVhbUV2ZW50XV0gYW5kIFtbVmlkZW9FbGVtZW50RXZlbnRdXSB0byBsZWFybiBtb3JlLlxuICAgICAqXG4gICAgICogVGhlIFtbU2Vzc2lvbl1dIG9iamVjdCBvZiBldmVyeSBvdGhlciBwYXJ0aWNpcGFudCBjb25uZWN0ZWQgdG8gdGhlIHNlc3Npb24gd2lsbCBkaXNwYXRjaCBhIGBzdHJlYW1EZXN0cm95ZWRgIGV2ZW50IGlmIHRoZSBkaXNjb25uZWN0ZWQgcGFydGljaXBhbnQgd2FzIHB1Ymxpc2hpbmcuXG4gICAgICogVGhpcyBldmVudCB3aWxsIGF1dG9tYXRpY2FsbHkgdW5zdWJzY3JpYmUgdGhlIFN1YnNjcmliZXIgb2JqZWN0IGZyb20gdGhlIHNlc3Npb24gKHRoaXMgaW5jbHVkZXMgY2xvc2luZyB0aGUgV2ViUlRDUGVlciBjb25uZWN0aW9uIGFuZCBkaXNwb3NpbmcgYWxsIE1lZGlhU3RyZWFtVHJhY2tzKVxuICAgICAqIGFuZCBhbHNvIGRlbGV0ZXMgYW55IEhUTUwgdmlkZW8gZWxlbWVudCBhc3NvY2lhdGVkIHRvIHRoYXQgU3Vic2NyaWJlciAob25seSB0aG9zZSBbY3JlYXRlZCBieSBPcGVuVmlkdSBCcm93c2VyXSgvZG9jcy9ob3ctZG8taS9tYW5hZ2UtdmlkZW9zLyNsZXQtb3BlbnZpZHUtdGFrZS1jYXJlLW9mLXRoZS12aWRlby1wbGF5ZXJzKSkuXG4gICAgICogRm9yIGV2ZXJ5IHZpZGVvIHJlbW92ZWQsIHRoZSBTdWJzY3JpYmVyIG9iamVjdCB3aWxsIGRpc3BhdGNoIGEgYHZpZGVvRWxlbWVudERlc3Ryb3llZGAgZXZlbnQuXG4gICAgICogQ2FsbCBgZXZlbnQucHJldmVudERlZmF1bHQoKWAgdXBvbiBldmVudCBgc3RyZWFtRGVzdHJveWVkYCB0byBhdm9pZCB0aGlzIGRlZmF1bHQgYmVoYXZpb3IgYW5kIHRha2UgY2FyZSBvZiBkaXNwb3NpbmcgYW5kIGNsZWFuaW5nIHRoZSBTdWJzY3JpYmVyIG9iamVjdCB5b3Vyc2VsZi5cbiAgICAgKiBTZWUgW1tTdHJlYW1FdmVudF1dIGFuZCBbW1ZpZGVvRWxlbWVudEV2ZW50XV0gdG8gbGVhcm4gbW9yZS5cbiAgICAgKlxuICAgICAqIFRoZSBbW1Nlc3Npb25dXSBvYmplY3Qgb2YgZXZlcnkgb3RoZXIgcGFydGljaXBhbnQgY29ubmVjdGVkIHRvIHRoZSBzZXNzaW9uIHdpbGwgZGlzcGF0Y2ggYSBgY29ubmVjdGlvbkRlc3Ryb3llZGAgZXZlbnQgaW4gYW55IGNhc2UuIFNlZSBbW0Nvbm5lY3Rpb25FdmVudF1dIHRvIGxlYXJuIG1vcmUuXG4gICAgICovXG4gICAgZGlzY29ubmVjdCgpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5sZWF2ZShmYWxzZSwgJ2Rpc2Nvbm5lY3QnKTtcbiAgICB9XG5cbiAgICBzdWJzY3JpYmUoc3RyZWFtOiBTdHJlYW0sIHRhcmdldEVsZW1lbnQ6IHN0cmluZyB8IEhUTUxFbGVtZW50KTogU3Vic2NyaWJlcjtcbiAgICBzdWJzY3JpYmUoc3RyZWFtOiBTdHJlYW0sIHRhcmdldEVsZW1lbnQ6IHN0cmluZyB8IEhUTUxFbGVtZW50LCBwcm9wZXJ0aWVzOiBTdWJzY3JpYmVyUHJvcGVydGllcyk6IFN1YnNjcmliZXI7XG4gICAgc3Vic2NyaWJlKHN0cmVhbTogU3RyZWFtLCB0YXJnZXRFbGVtZW50OiBzdHJpbmcgfCBIVE1MRWxlbWVudCwgY29tcGxldGlvbkhhbmRsZXI6IChlcnJvcjogRXJyb3IgfCB1bmRlZmluZWQpID0+IHZvaWQpOiBTdWJzY3JpYmVyO1xuICAgIHN1YnNjcmliZShzdHJlYW06IFN0cmVhbSwgdGFyZ2V0RWxlbWVudDogc3RyaW5nIHwgSFRNTEVsZW1lbnQsIHByb3BlcnRpZXM6IFN1YnNjcmliZXJQcm9wZXJ0aWVzLCBjb21wbGV0aW9uSGFuZGxlcjogKGVycm9yOiBFcnJvciB8IHVuZGVmaW5lZCkgPT4gdm9pZCk6IFN1YnNjcmliZXI7XG5cbiAgICAvKipcbiAgICAgKiBTdWJzY3JpYmVzIHRvIGEgYHN0cmVhbWAsIGFkZGluZyBhIG5ldyBIVE1MIHZpZGVvIGVsZW1lbnQgdG8gRE9NIHdpdGggYHN1YnNjcmliZXJQcm9wZXJ0aWVzYCBzZXR0aW5ncy4gVGhpcyBtZXRob2QgaXMgdXN1YWxseSBjYWxsZWQgaW4gdGhlIGNhbGxiYWNrIG9mIGBzdHJlYW1DcmVhdGVkYCBldmVudC5cbiAgICAgKlxuICAgICAqICMjIyMgRXZlbnRzIGRpc3BhdGNoZWRcbiAgICAgKlxuICAgICAqIFRoZSBbW1N1YnNjcmliZXJdXSBvYmplY3Qgd2lsbCBkaXNwYXRjaCBhIGB2aWRlb0VsZW1lbnRDcmVhdGVkYCBldmVudCBvbmNlIHRoZSBIVE1MIHZpZGVvIGVsZW1lbnQgaGFzIGJlZW4gYWRkZWQgdG8gRE9NIChvbmx5IGlmIHlvdVxuICAgICAqIFtsZXQgT3BlblZpZHUgdGFrZSBjYXJlIG9mIHRoZSB2aWRlbyBwbGF5ZXJzXSgvZG9jcy9ob3ctZG8taS9tYW5hZ2UtdmlkZW9zLyNsZXQtb3BlbnZpZHUtdGFrZS1jYXJlLW9mLXRoZS12aWRlby1wbGF5ZXJzKSkuIFNlZSBbW1ZpZGVvRWxlbWVudEV2ZW50XV0gdG8gbGVhcm4gbW9yZS5cbiAgICAgKlxuICAgICAqIFRoZSBbW1N1YnNjcmliZXJdXSBvYmplY3Qgd2lsbCBkaXNwYXRjaCBhIGBzdHJlYW1QbGF5aW5nYCBldmVudCBvbmNlIHRoZSByZW1vdGUgc3RyZWFtIHN0YXJ0cyBwbGF5aW5nLiBTZWUgW1tTdHJlYW1NYW5hZ2VyRXZlbnRdXSB0byBsZWFybiBtb3JlLlxuICAgICAqXG4gICAgICogQHBhcmFtIHN0cmVhbSBTdHJlYW0gb2JqZWN0IHRvIHN1YnNjcmliZSB0b1xuICAgICAqIEBwYXJhbSB0YXJnZXRFbGVtZW50IEhUTUwgRE9NIGVsZW1lbnQgKG9yIGl0cyBgaWRgIGF0dHJpYnV0ZSkgaW4gd2hpY2ggdGhlIHZpZGVvIGVsZW1lbnQgb2YgdGhlIFN1YnNjcmliZXIgd2lsbCBiZSBpbnNlcnRlZCAoc2VlIFtbU3Vic2NyaWJlclByb3BlcnRpZXMuaW5zZXJ0TW9kZV1dKS4gSWYgKm51bGwqIG9yICp1bmRlZmluZWQqIG5vIGRlZmF1bHQgdmlkZW8gd2lsbCBiZSBjcmVhdGVkIGZvciB0aGlzIFN1YnNjcmliZXIuXG4gICAgICogWW91IGNhbiBhbHdheXMgY2FsbCBtZXRob2QgW1tTdWJzY3JpYmVyLmFkZFZpZGVvRWxlbWVudF1dIG9yIFtbU3Vic2NyaWJlci5jcmVhdGVWaWRlb0VsZW1lbnRdXSB0byBtYW5hZ2UgdGhlIHZpZGVvIGVsZW1lbnRzIG9uIHlvdXIgb3duIChzZWUgW01hbmFnZSB2aWRlbyBwbGF5ZXJzXSgvZG9jcy9ob3ctZG8taS9tYW5hZ2UtdmlkZW9zKSBzZWN0aW9uKVxuICAgICAqIEBwYXJhbSBjb21wbGV0aW9uSGFuZGxlciBgZXJyb3JgIHBhcmFtZXRlciBpcyBudWxsIGlmIGBzdWJzY3JpYmVgIHN1Y2NlZWRzLCBhbmQgaXMgZGVmaW5lZCBpZiBpdCBmYWlscy5cbiAgICAgKi9cbiAgICBzdWJzY3JpYmUoc3RyZWFtOiBTdHJlYW0sIHRhcmdldEVsZW1lbnQ6IHN0cmluZyB8IEhUTUxFbGVtZW50LCBwYXJhbTM/OiAoKGVycm9yOiBFcnJvciB8IHVuZGVmaW5lZCkgPT4gdm9pZCkgfCBTdWJzY3JpYmVyUHJvcGVydGllcywgcGFyYW00PzogKChlcnJvcjogRXJyb3IgfCB1bmRlZmluZWQpID0+IHZvaWQpKTogU3Vic2NyaWJlciB7XG4gICAgICAgIGxldCBwcm9wZXJ0aWVzOiBTdWJzY3JpYmVyUHJvcGVydGllcyA9IHt9O1xuICAgICAgICBpZiAoISFwYXJhbTMgJiYgdHlwZW9mIHBhcmFtMyAhPT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgcHJvcGVydGllcyA9IHtcbiAgICAgICAgICAgICAgICBpbnNlcnRNb2RlOiAodHlwZW9mIHBhcmFtMy5pbnNlcnRNb2RlICE9PSAndW5kZWZpbmVkJykgPyAoKHR5cGVvZiBwYXJhbTMuaW5zZXJ0TW9kZSA9PT0gJ3N0cmluZycpID8gVmlkZW9JbnNlcnRNb2RlW3BhcmFtMy5pbnNlcnRNb2RlXSA6IHByb3BlcnRpZXMuaW5zZXJ0TW9kZSkgOiBWaWRlb0luc2VydE1vZGUuQVBQRU5ELFxuICAgICAgICAgICAgICAgIHN1YnNjcmliZVRvQXVkaW86ICh0eXBlb2YgcGFyYW0zLnN1YnNjcmliZVRvQXVkaW8gIT09ICd1bmRlZmluZWQnKSA/IHBhcmFtMy5zdWJzY3JpYmVUb0F1ZGlvIDogdHJ1ZSxcbiAgICAgICAgICAgICAgICBzdWJzY3JpYmVUb1ZpZGVvOiAodHlwZW9mIHBhcmFtMy5zdWJzY3JpYmVUb1ZpZGVvICE9PSAndW5kZWZpbmVkJykgPyBwYXJhbTMuc3Vic2NyaWJlVG9WaWRlbyA6IHRydWVcbiAgICAgICAgICAgIH07XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBwcm9wZXJ0aWVzID0ge1xuICAgICAgICAgICAgICAgIGluc2VydE1vZGU6IFZpZGVvSW5zZXJ0TW9kZS5BUFBFTkQsXG4gICAgICAgICAgICAgICAgc3Vic2NyaWJlVG9BdWRpbzogdHJ1ZSxcbiAgICAgICAgICAgICAgICBzdWJzY3JpYmVUb1ZpZGVvOiB0cnVlXG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG5cbiAgICAgICAgbGV0IGNvbXBsZXRpb25IYW5kbGVyOiAoZXJyb3I6IEVycm9yIHwgdW5kZWZpbmVkKSA9PiB2b2lkO1xuICAgICAgICBpZiAoISFwYXJhbTMgJiYgKHR5cGVvZiBwYXJhbTMgPT09ICdmdW5jdGlvbicpKSB7XG4gICAgICAgICAgICBjb21wbGV0aW9uSGFuZGxlciA9IHBhcmFtMztcbiAgICAgICAgfSBlbHNlIGlmICghIXBhcmFtNCkge1xuICAgICAgICAgICAgY29tcGxldGlvbkhhbmRsZXIgPSBwYXJhbTQ7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zb2xlLmluZm8oJ1N1YnNjcmliaW5nIHRvICcgKyBzdHJlYW0uY29ubmVjdGlvbi5jb25uZWN0aW9uSWQpO1xuXG4gICAgICAgIHN0cmVhbS5zdWJzY3JpYmUoKVxuICAgICAgICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbygnU3Vic2NyaWJlZCBjb3JyZWN0bHkgdG8gJyArIHN0cmVhbS5jb25uZWN0aW9uLmNvbm5lY3Rpb25JZCk7XG4gICAgICAgICAgICAgICAgaWYgKGNvbXBsZXRpb25IYW5kbGVyICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgY29tcGxldGlvbkhhbmRsZXIodW5kZWZpbmVkKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICAgICAgICBpZiAoY29tcGxldGlvbkhhbmRsZXIgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICBjb21wbGV0aW9uSGFuZGxlcihlcnJvcik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIGNvbnN0IHN1YnNjcmliZXIgPSBuZXcgU3Vic2NyaWJlcihzdHJlYW0sIHRhcmdldEVsZW1lbnQsIHByb3BlcnRpZXMpO1xuICAgICAgICBpZiAoISFzdWJzY3JpYmVyLnRhcmdldEVsZW1lbnQpIHtcbiAgICAgICAgICAgIHN0cmVhbS5zdHJlYW1NYW5hZ2VyLmNyZWF0ZVZpZGVvRWxlbWVudChzdWJzY3JpYmVyLnRhcmdldEVsZW1lbnQsIDxWaWRlb0luc2VydE1vZGU+cHJvcGVydGllcy5pbnNlcnRNb2RlKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gc3Vic2NyaWJlcjtcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFByb21pc2lmaWVkIHZlcnNpb24gb2YgW1tTZXNzaW9uLnN1YnNjcmliZV1dXG4gICAgICovXG4gICAgc3Vic2NyaWJlQXN5bmMoc3RyZWFtOiBTdHJlYW0sIHRhcmdldEVsZW1lbnQ6IHN0cmluZyB8IEhUTUxFbGVtZW50KTogUHJvbWlzZTxTdWJzY3JpYmVyPjtcbiAgICBzdWJzY3JpYmVBc3luYyhzdHJlYW06IFN0cmVhbSwgdGFyZ2V0RWxlbWVudDogc3RyaW5nIHwgSFRNTEVsZW1lbnQsIHByb3BlcnRpZXM6IFN1YnNjcmliZXJQcm9wZXJ0aWVzKTogUHJvbWlzZTxTdWJzY3JpYmVyPjtcblxuICAgIHN1YnNjcmliZUFzeW5jKHN0cmVhbTogU3RyZWFtLCB0YXJnZXRFbGVtZW50OiBzdHJpbmcgfCBIVE1MRWxlbWVudCwgcHJvcGVydGllcz86IFN1YnNjcmliZXJQcm9wZXJ0aWVzKTogUHJvbWlzZTxTdWJzY3JpYmVyPiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZTxTdWJzY3JpYmVyPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG5cbiAgICAgICAgICAgIGxldCBzdWJzY3JpYmVyOiBTdWJzY3JpYmVyO1xuXG4gICAgICAgICAgICBjb25zdCBjYWxsYmFjayA9IChlcnJvcjogRXJyb3IpID0+IHtcbiAgICAgICAgICAgICAgICBpZiAoISFlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc29sdmUoc3Vic2NyaWJlcik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgaWYgKCEhcHJvcGVydGllcykge1xuICAgICAgICAgICAgICAgIHN1YnNjcmliZXIgPSB0aGlzLnN1YnNjcmliZShzdHJlYW0sIHRhcmdldEVsZW1lbnQsIHByb3BlcnRpZXMsIGNhbGxiYWNrKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgc3Vic2NyaWJlciA9IHRoaXMuc3Vic2NyaWJlKHN0cmVhbSwgdGFyZ2V0RWxlbWVudCwgY2FsbGJhY2spO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgIH0pO1xuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogVW5zdWJzY3JpYmVzIGZyb20gYHN1YnNjcmliZXJgLCBhdXRvbWF0aWNhbGx5IHJlbW92aW5nIGl0cyBhc3NvY2lhdGVkIEhUTUwgdmlkZW8gZWxlbWVudHMuXG4gICAgICpcbiAgICAgKiAjIyMjIEV2ZW50cyBkaXNwYXRjaGVkXG4gICAgICpcbiAgICAgKiBUaGUgW1tTdWJzY3JpYmVyXV0gb2JqZWN0IHdpbGwgZGlzcGF0Y2ggYSBgdmlkZW9FbGVtZW50RGVzdHJveWVkYCBldmVudCBmb3IgZWFjaCB2aWRlbyBhc3NvY2lhdGVkIHRvIGl0IHRoYXQgd2FzIHJlbW92ZWQgZnJvbSBET00uXG4gICAgICogT25seSB2aWRlb3MgW2NyZWF0ZWQgYnkgT3BlblZpZHUgQnJvd3Nlcl0oL2RvY3MvaG93LWRvLWkvbWFuYWdlLXZpZGVvcy8jbGV0LW9wZW52aWR1LXRha2UtY2FyZS1vZi10aGUtdmlkZW8tcGxheWVycykpIHdpbGwgYmUgYXV0b21hdGljYWxseSByZW1vdmVkXG4gICAgICpcbiAgICAgKiBTZWUgW1tWaWRlb0VsZW1lbnRFdmVudF1dIHRvIGxlYXJuIG1vcmVcbiAgICAgKi9cbiAgICB1bnN1YnNjcmliZShzdWJzY3JpYmVyOiBTdWJzY3JpYmVyKTogdm9pZCB7XG4gICAgICAgIGNvbnN0IGNvbm5lY3Rpb25JZCA9IHN1YnNjcmliZXIuc3RyZWFtLmNvbm5lY3Rpb24uY29ubmVjdGlvbklkO1xuXG4gICAgICAgIGNvbnNvbGUuaW5mbygnVW5zdWJzY3JpYmluZyBmcm9tICcgKyBjb25uZWN0aW9uSWQpO1xuXG4gICAgICAgIHRoaXMub3BlbnZpZHUuc2VuZFJlcXVlc3QoXG4gICAgICAgICAgICAndW5zdWJzY3JpYmVGcm9tVmlkZW8nLFxuICAgICAgICAgICAgeyBzZW5kZXI6IHN1YnNjcmliZXIuc3RyZWFtLmNvbm5lY3Rpb24uY29ubmVjdGlvbklkIH0sXG4gICAgICAgICAgICAoZXJyb3IsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ0Vycm9yIHVuc3Vic2NyaWJpbmcgZnJvbSAnICsgY29ubmVjdGlvbklkLCBlcnJvcik7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS5pbmZvKCdVbnN1YnNjcmliZWQgY29ycmVjdGx5IGZyb20gJyArIGNvbm5lY3Rpb25JZCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHN1YnNjcmliZXIuc3RyZWFtLmRpc3Bvc2VXZWJSdGNQZWVyKCk7XG4gICAgICAgICAgICAgICAgc3Vic2NyaWJlci5zdHJlYW0uZGlzcG9zZU1lZGlhU3RyZWFtKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICk7XG4gICAgICAgIHN1YnNjcmliZXIuc3RyZWFtLnN0cmVhbU1hbmFnZXIucmVtb3ZlQWxsVmlkZW9zKCk7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBQdWJsaXNoZXMgdG8gdGhlIFNlc3Npb24gdGhlIFB1Ymxpc2hlciBvYmplY3RcbiAgICAgKlxuICAgICAqICMjIyMgRXZlbnRzIGRpc3BhdGNoZWRcbiAgICAgKlxuICAgICAqIFRoZSBsb2NhbCBbW1B1Ymxpc2hlcl1dIG9iamVjdCB3aWxsIGRpc3BhdGNoIGEgYHN0cmVhbUNyZWF0ZWRgIGV2ZW50IHVwb24gc3VjY2Vzc2Z1bCB0ZXJtaW5hdGlvbiBvZiB0aGlzIG1ldGhvZC4gU2VlIFtbU3RyZWFtRXZlbnRdXSB0byBsZWFybiBtb3JlLlxuICAgICAqXG4gICAgICogVGhlIGxvY2FsIFtbUHVibGlzaGVyXV0gb2JqZWN0IHdpbGwgZGlzcGF0Y2ggYSBgc3RyZWFtUGxheWluZ2Agb25jZSB0aGUgbWVkaWEgc3RyZWFtIHN0YXJ0cyBwbGF5aW5nLiBTZWUgW1tTdHJlYW1NYW5hZ2VyRXZlbnRdXSB0byBsZWFybiBtb3JlLlxuICAgICAqXG4gICAgICogVGhlIFtbU2Vzc2lvbl1dIG9iamVjdCBvZiBldmVyeSBvdGhlciBwYXJ0aWNpcGFudCBjb25uZWN0ZWQgdG8gdGhlIHNlc3Npb24gd2lsbCBkaXNwYXRjaCBhIGBzdHJlYW1DcmVhdGVkYCBldmVudCBzbyB0aGV5IGNhbiBzdWJzY3JpYmUgdG8gaXQuIFNlZSBbW1N0cmVhbUV2ZW50XV0gdG8gbGVhcm4gbW9yZS5cbiAgICAgKlxuICAgICAqIEByZXR1cm5zIEEgUHJvbWlzZSAodG8gd2hpY2ggeW91IGNhbiBvcHRpb25hbGx5IHN1YnNjcmliZSB0bykgdGhhdCBpcyByZXNvbHZlZCBvbmx5IGFmdGVyIHRoZSBwdWJsaXNoZXIgd2FzIHN1Y2Nlc3NmdWxseSBwdWJsaXNoZWQgYW5kIHJlamVjdGVkIHdpdGggYW4gRXJyb3Igb2JqZWN0IGlmIG5vdFxuICAgICAqL1xuICAgIHB1Ymxpc2gocHVibGlzaGVyOiBQdWJsaXNoZXIpOiBQcm9taXNlPGFueT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgcHVibGlzaGVyLnNlc3Npb24gPSB0aGlzO1xuICAgICAgICAgICAgcHVibGlzaGVyLnN0cmVhbS5zZXNzaW9uID0gdGhpcztcblxuICAgICAgICAgICAgaWYgKCFwdWJsaXNoZXIuc3RyZWFtLnB1Ymxpc2hlZE9uY2UpIHtcbiAgICAgICAgICAgICAgICAvLyAnU2Vzc2lvbi51bnB1Ymxpc2goUHVibGlzaGVyKScgaGFzIE5PVCBiZWVuIGNhbGxlZFxuICAgICAgICAgICAgICAgIHRoaXMuY29ubmVjdGlvbi5hZGRTdHJlYW0ocHVibGlzaGVyLnN0cmVhbSk7XG4gICAgICAgICAgICAgICAgcHVibGlzaGVyLnN0cmVhbS5wdWJsaXNoKClcbiAgICAgICAgICAgICAgICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIC8vICdTZXNzaW9uLnVucHVibGlzaChQdWJsaXNoZXIpJyBoYXMgYmVlbiBjYWxsZWQuIE11c3QgaW5pdGlhbGl6ZSBhZ2FpbiBQdWJsaXNoZXJcbiAgICAgICAgICAgICAgICBwdWJsaXNoZXIuaW5pdGlhbGl6ZSgpXG4gICAgICAgICAgICAgICAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY29ubmVjdGlvbi5hZGRTdHJlYW0ocHVibGlzaGVyLnN0cmVhbSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBwdWJsaXNoZXIucmVlc3RhYmxpc2hTdHJlYW1QbGF5aW5nRXZlbnQoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHB1Ymxpc2hlci5zdHJlYW0ucHVibGlzaCgpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICB9KS5jYXRjaCgoZXJyb3IpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFVucHVibGlzaGVzIGZyb20gdGhlIFNlc3Npb24gdGhlIFB1Ymxpc2hlciBvYmplY3QuXG4gICAgICpcbiAgICAgKiAjIyMjIEV2ZW50cyBkaXNwYXRjaGVkXG4gICAgICpcbiAgICAgKiBUaGUgW1tQdWJsaXNoZXJdXSBvYmplY3Qgb2YgdGhlIGxvY2FsIHBhcnRpY2lwYW50IHdpbGwgZGlzcGF0Y2ggYSBgc3RyZWFtRGVzdHJveWVkYCBldmVudC5cbiAgICAgKiBUaGlzIGV2ZW50IHdpbGwgYXV0b21hdGljYWxseSBzdG9wIGFsbCBtZWRpYSB0cmFja3MgYW5kIGRlbGV0ZSBhbnkgSFRNTCB2aWRlbyBlbGVtZW50IGFzc29jaWF0ZWQgdG8gdGhpcyBQdWJsaXNoZXJcbiAgICAgKiAob25seSB0aG9zZSB2aWRlb3MgW2NyZWF0ZWQgYnkgT3BlblZpZHUgQnJvd3Nlcl0oL2RvY3MvaG93LWRvLWkvbWFuYWdlLXZpZGVvcy8jbGV0LW9wZW52aWR1LXRha2UtY2FyZS1vZi10aGUtdmlkZW8tcGxheWVycykpLlxuICAgICAqIEZvciBldmVyeSB2aWRlbyByZW1vdmVkLCB0aGUgUHVibGlzaGVyIG9iamVjdCB3aWxsIGRpc3BhdGNoIGEgYHZpZGVvRWxlbWVudERlc3Ryb3llZGAgZXZlbnQuXG4gICAgICogQ2FsbCBgZXZlbnQucHJldmVudERlZmF1bHQoKWAgdXBvbiBldmVudCBgc3RyZWFtRGVzdHJveWVkYCBpZiB5b3Ugd2FudCB0byBjbGVhbiB0aGUgUHVibGlzaGVyIG9iamVjdCBvbiB5b3VyIG93biBvciByZS1wdWJsaXNoIGl0IGluIGEgZGlmZmVyZW50IFNlc3Npb24uXG4gICAgICpcbiAgICAgKiBUaGUgW1tTZXNzaW9uXV0gb2JqZWN0IG9mIGV2ZXJ5IG90aGVyIHBhcnRpY2lwYW50IGNvbm5lY3RlZCB0byB0aGUgc2Vzc2lvbiB3aWxsIGRpc3BhdGNoIGEgYHN0cmVhbURlc3Ryb3llZGAgZXZlbnQuXG4gICAgICogVGhpcyBldmVudCB3aWxsIGF1dG9tYXRpY2FsbHkgdW5zdWJzY3JpYmUgdGhlIFN1YnNjcmliZXIgb2JqZWN0IGZyb20gdGhlIHNlc3Npb24gKHRoaXMgaW5jbHVkZXMgY2xvc2luZyB0aGUgV2ViUlRDUGVlciBjb25uZWN0aW9uIGFuZCBkaXNwb3NpbmcgYWxsIE1lZGlhU3RyZWFtVHJhY2tzKSBhbmRcbiAgICAgKiBkZWxldGUgYW55IEhUTUwgdmlkZW8gZWxlbWVudCBhc3NvY2lhdGVkIHRvIGl0IChvbmx5IHRob3NlIFtjcmVhdGVkIGJ5IE9wZW5WaWR1IEJyb3dzZXJdKC9kb2NzL2hvdy1kby1pL21hbmFnZS12aWRlb3MvI2xldC1vcGVudmlkdS10YWtlLWNhcmUtb2YtdGhlLXZpZGVvLXBsYXllcnMpKS5cbiAgICAgKiBGb3IgZXZlcnkgdmlkZW8gcmVtb3ZlZCwgdGhlIFN1YnNjcmliZXIgb2JqZWN0IHdpbGwgZGlzcGF0Y2ggYSBgdmlkZW9FbGVtZW50RGVzdHJveWVkYCBldmVudC5cbiAgICAgKiBDYWxsIGBldmVudC5wcmV2ZW50RGVmYXVsdCgpYCB1cG9uIGV2ZW50IGBzdHJlYW1EZXN0cm95ZWRgIHRvIGF2b2lkIHRoaXMgZGVmYXVsdCBiZWhhdmlvciBhbmQgdGFrZSBjYXJlIG9mIGRpc3Bvc2luZyBhbmQgY2xlYW5pbmcgdGhlIFN1YnNjcmliZXIgb2JqZWN0IG9uIHlvdXIgb3duLlxuICAgICAqXG4gICAgICogU2VlIFtbU3RyZWFtRXZlbnRdXSBhbmQgW1tWaWRlb0VsZW1lbnRFdmVudF1dIHRvIGxlYXJuIG1vcmUuXG4gICAgICovXG4gICAgdW5wdWJsaXNoKHB1Ymxpc2hlcjogUHVibGlzaGVyKTogdm9pZCB7XG5cbiAgICAgICAgY29uc3Qgc3RyZWFtID0gcHVibGlzaGVyLnN0cmVhbTtcblxuICAgICAgICBpZiAoIXN0cmVhbS5jb25uZWN0aW9uKSB7XG4gICAgICAgICAgICBjb25zb2xlLmVycm9yKCdUaGUgYXNzb2NpYXRlZCBDb25uZWN0aW9uIG9iamVjdCBvZiB0aGlzIFB1Ymxpc2hlciBpcyBudWxsJywgc3RyZWFtKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfSBlbHNlIGlmIChzdHJlYW0uY29ubmVjdGlvbiAhPT0gdGhpcy5jb25uZWN0aW9uKSB7XG4gICAgICAgICAgICBjb25zb2xlLmVycm9yKCdUaGUgYXNzb2NpYXRlZCBDb25uZWN0aW9uIG9iamVjdCBvZiB0aGlzIFB1Ymxpc2hlciBpcyBub3QgeW91ciBsb2NhbCBDb25uZWN0aW9uLicgK1xuICAgICAgICAgICAgICAgIFwiT25seSBtb2RlcmF0b3JzIGNhbiBmb3JjZSB1bnB1Ymxpc2ggb24gcmVtb3RlIFN0cmVhbXMgdmlhICdmb3JjZVVucHVibGlzaCcgbWV0aG9kXCIsIHN0cmVhbSk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH0gZWxzZSB7XG5cbiAgICAgICAgICAgIGNvbnNvbGUuaW5mbygnVW5wdWJsaXNoaW5nIGxvY2FsIG1lZGlhICgnICsgc3RyZWFtLmNvbm5lY3Rpb24uY29ubmVjdGlvbklkICsgJyknKTtcblxuICAgICAgICAgICAgdGhpcy5vcGVudmlkdS5zZW5kUmVxdWVzdCgndW5wdWJsaXNoVmlkZW8nLCAoZXJyb3IsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoZXJyb3IpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbygnTWVkaWEgdW5wdWJsaXNoZWQgY29ycmVjdGx5Jyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIHN0cmVhbS5kaXNwb3NlV2ViUnRjUGVlcigpO1xuICAgICAgICAgICAgZGVsZXRlIHN0cmVhbS5jb25uZWN0aW9uLnN0cmVhbTtcblxuICAgICAgICAgICAgY29uc3Qgc3RyZWFtRXZlbnQgPSBuZXcgU3RyZWFtRXZlbnQodHJ1ZSwgcHVibGlzaGVyLCAnc3RyZWFtRGVzdHJveWVkJywgcHVibGlzaGVyLnN0cmVhbSwgJ3VucHVibGlzaCcpO1xuICAgICAgICAgICAgcHVibGlzaGVyLmVtaXRFdmVudCgnc3RyZWFtRGVzdHJveWVkJywgW3N0cmVhbUV2ZW50XSk7XG4gICAgICAgICAgICBzdHJlYW1FdmVudC5jYWxsRGVmYXVsdEJlaGF2aW9yKCk7XG4gICAgICAgIH1cbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIEZvcmNlcyBzb21lIHVzZXIgdG8gbGVhdmUgdGhlIHNlc3Npb25cbiAgICAgKlxuICAgICAqICMjIyMgRXZlbnRzIGRpc3BhdGNoZWRcbiAgICAgKlxuICAgICAqIFRoZSBiZWhhdmlvciBpcyB0aGUgc2FtZSBhcyB3aGVuIHNvbWUgdXNlciBjYWxscyBbW1Nlc3Npb24uZGlzY29ubmVjdF1dLCBidXQgYHJlYXNvbmAgcHJvcGVydHkgaW4gYWxsIGV2ZW50cyB3aWxsIGJlIGBcImZvcmNlRGlzY29ubmVjdEJ5VXNlclwiYC5cbiAgICAgKlxuICAgICAqIFRoZSBbW1Nlc3Npb25dXSBvYmplY3Qgb2YgZXZlcnkgcGFydGljaXBhbnQgd2lsbCBkaXNwYXRjaCBhIGBzdHJlYW1EZXN0cm95ZWRgIGV2ZW50IGlmIHRoZSBldmljdGVkIHVzZXIgd2FzIHB1Ymxpc2hpbmcgYSBzdHJlYW0sIHdpdGggcHJvcGVydHkgYHJlYXNvbmAgc2V0IHRvIGBcImZvcmNlRGlzY29ubmVjdEJ5VXNlclwiYC5cbiAgICAgKiBUaGUgW1tTZXNzaW9uXV0gb2JqZWN0IG9mIGV2ZXJ5IHBhcnRpY2lwYW50IGV4Y2VwdCB0aGUgZXZpY3RlZCBvbmUgd2lsbCBkaXNwYXRjaCBhIGBjb25uZWN0aW9uRGVzdHJveWVkYCBldmVudCBmb3IgdGhlIGV2aWN0ZWQgdXNlciwgd2l0aCBwcm9wZXJ0eSBgcmVhc29uYCBzZXQgdG8gYFwiZm9yY2VEaXNjb25uZWN0QnlVc2VyXCJgLlxuICAgICAqXG4gICAgICogSWYgYW55LCB0aGUgW1tQdWJsaXNoZXJdXSBvYmplY3Qgb2YgdGhlIGV2aWN0ZWQgcGFydGljaXBhbnQgd2lsbCBhbHNvIGRpc3BhdGNoIGEgYHN0cmVhbURlc3Ryb3llZGAgZXZlbnQgd2l0aCBwcm9wZXJ0eSBgcmVhc29uYCBzZXQgdG8gYFwiZm9yY2VEaXNjb25uZWN0QnlVc2VyXCJgLlxuICAgICAqIFRoZSBbW1Nlc3Npb25dXSBvYmplY3Qgb2YgdGhlIGV2aWN0ZWQgcGFydGljaXBhbnQgd2lsbCBkaXNwYXRjaCBhIGBzZXNzaW9uRGlzY29ubmVjdGVkYCBldmVudCB3aXRoIHByb3BlcnR5IGByZWFzb25gIHNldCB0byBgXCJmb3JjZURpc2Nvbm5lY3RCeVVzZXJcImAuXG4gICAgICpcbiAgICAgKiBTZWUgW1tTdHJlYW1FdmVudF1dLCBbW0Nvbm5lY3Rpb25FdmVudF1dIGFuZCBbW1Nlc3Npb25EaXNjb25uZWN0ZWRFdmVudF1dIHRvIGxlYXJuIG1vcmUuXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyBBIFByb21pc2UgKHRvIHdoaWNoIHlvdSBjYW4gb3B0aW9uYWxseSBzdWJzY3JpYmUgdG8pIHRoYXQgaXMgcmVzb2x2ZWQgb25seSBhZnRlciB0aGUgcGFydGljaXBhbnQgaGFzIGJlZW4gc3VjY2Vzc2Z1bGx5IGV2aWN0ZWQgZnJvbSB0aGUgc2Vzc2lvbiBhbmQgcmVqZWN0ZWQgd2l0aCBhbiBFcnJvciBvYmplY3QgaWYgbm90XG4gICAgICovXG4gICAgZm9yY2VEaXNjb25uZWN0KGNvbm5lY3Rpb246IENvbm5lY3Rpb24pOiBQcm9taXNlPGFueT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgY29uc29sZS5pbmZvKCdGb3JjaW5nIGRpc2Nvbm5lY3QgZm9yIGNvbm5lY3Rpb24gJyArIGNvbm5lY3Rpb24uY29ubmVjdGlvbklkKTtcbiAgICAgICAgICAgIHRoaXMub3BlbnZpZHUuc2VuZFJlcXVlc3QoXG4gICAgICAgICAgICAgICAgJ2ZvcmNlRGlzY29ubmVjdCcsXG4gICAgICAgICAgICAgICAgeyBjb25uZWN0aW9uSWQ6IGNvbm5lY3Rpb24uY29ubmVjdGlvbklkIH0sXG4gICAgICAgICAgICAgICAgKGVycm9yLCByZXNwb25zZSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBpZiAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ0Vycm9yIGZvcmNpbmcgZGlzY29ubmVjdCBmb3IgQ29ubmVjdGlvbiAnICsgY29ubmVjdGlvbi5jb25uZWN0aW9uSWQsIGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChlcnJvci5jb2RlID09PSA0MDEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWplY3QobmV3IE9wZW5WaWR1RXJyb3IoT3BlblZpZHVFcnJvck5hbWUuT1BFTlZJRFVfUEVSTUlTU0lPTl9ERU5JRUQsIFwiWW91IGRvbid0IGhhdmUgcGVybWlzc2lvbnMgdG8gZm9yY2UgYSBkaXNjb25uZWN0aW9uXCIpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbygnRm9yY2luZyBkaXNjb25uZWN0IGNvcnJlY3RseSBmb3IgQ29ubmVjdGlvbiAnICsgY29ubmVjdGlvbi5jb25uZWN0aW9uSWQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBGb3JjZXMgc29tZSB1c2VyIHRvIHVucHVibGlzaCBhIFN0cmVhbVxuICAgICAqXG4gICAgICogIyMjIyBFdmVudHMgZGlzcGF0Y2hlZFxuICAgICAqXG4gICAgICogVGhlIGJlaGF2aW9yIGlzIHRoZSBzYW1lIGFzIHdoZW4gc29tZSB1c2VyIGNhbGxzIFtbU2Vzc2lvbi51bnB1Ymxpc2hdXSwgYnV0IGByZWFzb25gIHByb3BlcnR5IGluIGFsbCBldmVudHMgd2lsbCBiZSBgXCJmb3JjZVVucHVibGlzaEJ5VXNlclwiYFxuICAgICAqXG4gICAgICogVGhlIFtbU2Vzc2lvbl1dIG9iamVjdCBvZiBldmVyeSBwYXJ0aWNpcGFudCB3aWxsIGRpc3BhdGNoIGEgYHN0cmVhbURlc3Ryb3llZGAgZXZlbnQgd2l0aCBwcm9wZXJ0eSBgcmVhc29uYCBzZXQgdG8gYFwiZm9yY2VEaXNjb25uZWN0QnlVc2VyXCJgXG4gICAgICpcbiAgICAgKiBUaGUgW1tQdWJsaXNoZXJdXSBvYmplY3Qgb2YgdGhlIGFmZmVjdGVkIHBhcnRpY2lwYW50IHdpbGwgYWxzbyBkaXNwYXRjaCBhIGBzdHJlYW1EZXN0cm95ZWRgIGV2ZW50IHdpdGggcHJvcGVydHkgYHJlYXNvbmAgc2V0IHRvIGBcImZvcmNlRGlzY29ubmVjdEJ5VXNlclwiYFxuICAgICAqXG4gICAgICogU2VlIFtbU3RyZWFtRXZlbnRdXSB0byBsZWFybiBtb3JlLlxuICAgICAqXG4gICAgICogQHJldHVybnMgQSBQcm9taXNlICh0byB3aGljaCB5b3UgY2FuIG9wdGlvbmFsbHkgc3Vic2NyaWJlIHRvKSB0aGF0IGlzIHJlc29sdmVkIG9ubHkgYWZ0ZXIgdGhlIHJlbW90ZSBTdHJlYW0gaGFzIGJlZW4gc3VjY2Vzc2Z1bGx5IHVucHVibGlzaGVkIGZyb20gdGhlIHNlc3Npb24gYW5kIHJlamVjdGVkIHdpdGggYW4gRXJyb3Igb2JqZWN0IGlmIG5vdFxuICAgICAqL1xuICAgIGZvcmNlVW5wdWJsaXNoKHN0cmVhbTogU3RyZWFtKTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIGNvbnNvbGUuaW5mbygnRm9yY2luZyB1bnB1Ymxpc2ggZm9yIHN0cmVhbSAnICsgc3RyZWFtLnN0cmVhbUlkKTtcbiAgICAgICAgICAgIHRoaXMub3BlbnZpZHUuc2VuZFJlcXVlc3QoXG4gICAgICAgICAgICAgICAgJ2ZvcmNlVW5wdWJsaXNoJyxcbiAgICAgICAgICAgICAgICB7IHN0cmVhbUlkOiBzdHJlYW0uc3RyZWFtSWQgfSxcbiAgICAgICAgICAgICAgICAoZXJyb3IsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcignRXJyb3IgZm9yY2luZyB1bnB1Ymxpc2ggZm9yIFN0cmVhbSAnICsgc3RyZWFtLnN0cmVhbUlkLCBlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZXJyb3IuY29kZSA9PT0gNDAxKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KG5ldyBPcGVuVmlkdUVycm9yKE9wZW5WaWR1RXJyb3JOYW1lLk9QRU5WSURVX1BFUk1JU1NJT05fREVOSUVELCBcIllvdSBkb24ndCBoYXZlIHBlcm1pc3Npb25zIHRvIGZvcmNlIGFuIHVucHVibGlzaGluZ1wiKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oJ0ZvcmNpbmcgdW5wdWJsaXNoIGNvcnJlY3RseSBmb3IgU3RyZWFtICcgKyBzdHJlYW0uc3RyZWFtSWQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBTZW5kcyBvbmUgc2lnbmFsLiBgc2lnbmFsYCBvYmplY3QgaGFzIHRoZSBmb2xsb3dpbmcgb3B0aW9uYWwgcHJvcGVydGllczpcbiAgICAgKiBgYGBqc29uXG4gICAgICoge2RhdGE6c3RyaW5nLCB0bzpDb25uZWN0aW9uW10sIHR5cGU6c3RyaW5nfVxuICAgICAqIGBgYFxuICAgICAqIEFsbCB1c2VycyBzdWJzY3JpYmVkIHRvIHRoYXQgc2lnbmFsIChgc2Vzc2lvbi5vbignc2lnbmFsOnR5cGUnLCAuLi4pYCBvciBgc2Vzc2lvbi5vbignc2lnbmFsJywgLi4uKWAgZm9yIGFsbCBzaWduYWxzKSBhbmQgd2hvc2UgQ29ubmVjdGlvbiBvYmplY3RzIGFyZSBpbiBgdG9gIGFycmF5IHdpbGwgcmVjZWl2ZSBpdC4gVGhlaXIgbG9jYWxcbiAgICAgKiBTZXNzaW9uIG9iamVjdHMgd2lsbCBkaXNwYXRjaCBhIGBzaWduYWxgIG9yIGBzaWduYWw6dHlwZWAgZXZlbnQuIFNlZSBbW1NpZ25hbEV2ZW50XV0gdG8gbGVhcm4gbW9yZS5cbiAgICAgKlxuICAgICAqIEByZXR1cm5zIEEgUHJvbWlzZSAodG8gd2hpY2ggeW91IGNhbiBvcHRpb25hbGx5IHN1YnNjcmliZSB0bykgdGhhdCBpcyByZXNvbHZlZCBpZiB0aGUgbWVzc2FnZSBzdWNjZXNzZnVsbHkgcmVhY2hlZCBvcGVudmlkdS1zZXJ2ZXIgYW5kIHJlamVjdGVkIHdpdGggYW4gRXJyb3Igb2JqZWN0IGlmIG5vdC4gX1RoaXMgZG9lc24ndFxuICAgICAqIG1lYW4gdGhhdCBvcGVudmlkdS1zZXJ2ZXIgY291bGQgcmVzZW5kIHRoZSBtZXNzYWdlIHRvIGFsbCB0aGUgbGlzdGVkIHJlY2VpdmVycy5fXG4gICAgICovXG4gICAgLyogdHNsaW50OmRpc2FibGU6bm8tc3RyaW5nLWxpdGVyYWwgKi9cbiAgICBzaWduYWwoc2lnbmFsOiBTaWduYWxPcHRpb25zKTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcblxuICAgICAgICAgICAgY29uc3Qgc2lnbmFsTWVzc2FnZSA9IHt9O1xuXG4gICAgICAgICAgICBpZiAoc2lnbmFsLnRvICYmIHNpZ25hbC50by5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgY29ubmVjdGlvbklkczogc3RyaW5nW10gPSBbXTtcblxuICAgICAgICAgICAgICAgIHNpZ25hbC50by5mb3JFYWNoKGNvbm5lY3Rpb24gPT4ge1xuICAgICAgICAgICAgICAgICAgICBjb25uZWN0aW9uSWRzLnB1c2goY29ubmVjdGlvbi5jb25uZWN0aW9uSWQpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIHNpZ25hbE1lc3NhZ2VbJ3RvJ10gPSBjb25uZWN0aW9uSWRzO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBzaWduYWxNZXNzYWdlWyd0byddID0gW107XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHNpZ25hbE1lc3NhZ2VbJ2RhdGEnXSA9IHNpZ25hbC5kYXRhID8gc2lnbmFsLmRhdGEgOiAnJztcbiAgICAgICAgICAgIHNpZ25hbE1lc3NhZ2VbJ3R5cGUnXSA9IHNpZ25hbC50eXBlID8gc2lnbmFsLnR5cGUgOiAnJztcblxuICAgICAgICAgICAgdGhpcy5vcGVudmlkdS5zZW5kUmVxdWVzdCgnc2VuZE1lc3NhZ2UnLCB7XG4gICAgICAgICAgICAgICAgbWVzc2FnZTogSlNPTi5zdHJpbmdpZnkoc2lnbmFsTWVzc2FnZSlcbiAgICAgICAgICAgIH0sIChlcnJvciwgcmVzcG9uc2UpID0+IHtcbiAgICAgICAgICAgICAgICBpZiAoISFlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgfVxuICAgIC8qIHRzbGludDplbmFibGU6bm8tc3RyaW5nLWxpdGVyYWwgKi9cblxuXG4gICAgLyoqXG4gICAgICogU2VlIFtbRXZlbnREaXNwYXRjaGVyLm9uXV1cbiAgICAgKi9cbiAgICBvbih0eXBlOiBzdHJpbmcsIGhhbmRsZXI6IChldmVudDogU2Vzc2lvbkRpc2Nvbm5lY3RlZEV2ZW50IHwgU2lnbmFsRXZlbnQgfCBTdHJlYW1FdmVudCB8IENvbm5lY3Rpb25FdmVudCB8IFB1Ymxpc2hlclNwZWFraW5nRXZlbnQgfCBSZWNvcmRpbmdFdmVudCkgPT4gdm9pZCk6IEV2ZW50RGlzcGF0Y2hlciB7XG5cbiAgICAgICAgdGhpcy5lZS5vbih0eXBlLCBldmVudCA9PiB7XG4gICAgICAgICAgICBpZiAoZXZlbnQpIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oXCJFdmVudCAnXCIgKyB0eXBlICsgXCInIHRyaWdnZXJlZCBieSAnU2Vzc2lvbidcIiwgZXZlbnQpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oXCJFdmVudCAnXCIgKyB0eXBlICsgXCInIHRyaWdnZXJlZCBieSAnU2Vzc2lvbidcIik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBoYW5kbGVyKGV2ZW50KTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgaWYgKHR5cGUgPT09ICdwdWJsaXNoZXJTdGFydFNwZWFraW5nJyB8fCB0eXBlID09PSAncHVibGlzaGVyU3RvcFNwZWFraW5nJykge1xuICAgICAgICAgICAgdGhpcy5zcGVha2luZ0V2ZW50c0VuYWJsZWQgPSB0cnVlO1xuICAgICAgICAgICAgLy8gSWYgdGhlcmUgYXJlIGFscmVhZHkgYXZhaWxhYmxlIHJlbW90ZSBzdHJlYW1zLCBlbmFibGUgaGFyayAnc3BlYWtpbmcnIGV2ZW50IGluIGFsbCBvZiB0aGVtXG4gICAgICAgICAgICBmb3IgKGNvbnN0IGNvbm5lY3Rpb25JZCBpbiB0aGlzLnJlbW90ZUNvbm5lY3Rpb25zKSB7XG4gICAgICAgICAgICAgICAgY29uc3Qgc3RyID0gdGhpcy5yZW1vdGVDb25uZWN0aW9uc1tjb25uZWN0aW9uSWRdLnN0cmVhbTtcbiAgICAgICAgICAgICAgICBpZiAoISFzdHIgJiYgIXN0ci5zcGVlY2hFdmVudCAmJiBzdHIuaGFzQXVkaW8pIHtcbiAgICAgICAgICAgICAgICAgICAgc3RyLmVuYWJsZVNwZWFraW5nRXZlbnRzKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBTZWUgW1tFdmVudERpc3BhdGNoZXIub25jZV1dXG4gICAgICovXG4gICAgb25jZSh0eXBlOiBzdHJpbmcsIGhhbmRsZXI6IChldmVudDogU2Vzc2lvbkRpc2Nvbm5lY3RlZEV2ZW50IHwgU2lnbmFsRXZlbnQgfCBTdHJlYW1FdmVudCB8IENvbm5lY3Rpb25FdmVudCB8IFB1Ymxpc2hlclNwZWFraW5nRXZlbnQgfCBSZWNvcmRpbmdFdmVudCkgPT4gdm9pZCk6IFNlc3Npb24ge1xuICAgICAgICB0aGlzLmVlLm9uY2UodHlwZSwgZXZlbnQgPT4ge1xuICAgICAgICAgICAgaWYgKGV2ZW50KSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5pbmZvKFwiRXZlbnQgJ1wiICsgdHlwZSArIFwiJyB0cmlnZ2VyZWQgYnkgJ1Nlc3Npb24nXCIsIGV2ZW50KTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5pbmZvKFwiRXZlbnQgJ1wiICsgdHlwZSArIFwiJyB0cmlnZ2VyZWQgYnkgJ1Nlc3Npb24nXCIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaGFuZGxlcihldmVudCk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGlmICh0eXBlID09PSAncHVibGlzaGVyU3RhcnRTcGVha2luZycgfHwgdHlwZSA9PT0gJ3B1Ymxpc2hlclN0b3BTcGVha2luZycpIHtcbiAgICAgICAgICAgIHRoaXMuc3BlYWtpbmdFdmVudHNFbmFibGVkID0gdHJ1ZTtcblxuICAgICAgICAgICAgLy8gSWYgdGhlcmUgYXJlIGFscmVhZHkgYXZhaWxhYmxlIHJlbW90ZSBzdHJlYW1zLCBlbmFibGUgaGFyayBpbiBhbGwgb2YgdGhlbVxuICAgICAgICAgICAgZm9yIChjb25zdCBjb25uZWN0aW9uSWQgaW4gdGhpcy5yZW1vdGVDb25uZWN0aW9ucykge1xuICAgICAgICAgICAgICAgIGNvbnN0IHN0ciA9IHRoaXMucmVtb3RlQ29ubmVjdGlvbnNbY29ubmVjdGlvbklkXS5zdHJlYW07XG4gICAgICAgICAgICAgICAgaWYgKCEhc3RyICYmICFzdHIuc3BlZWNoRXZlbnQgJiYgc3RyLmhhc0F1ZGlvKSB7XG4gICAgICAgICAgICAgICAgICAgIHN0ci5lbmFibGVPbmNlU3BlYWtpbmdFdmVudHMoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFNlZSBbW0V2ZW50RGlzcGF0Y2hlci5vZmZdXVxuICAgICAqL1xuICAgIG9mZih0eXBlOiBzdHJpbmcsIGhhbmRsZXI/OiAoZXZlbnQ6IFNlc3Npb25EaXNjb25uZWN0ZWRFdmVudCB8IFNpZ25hbEV2ZW50IHwgU3RyZWFtRXZlbnQgfCBDb25uZWN0aW9uRXZlbnQgfCBQdWJsaXNoZXJTcGVha2luZ0V2ZW50IHwgUmVjb3JkaW5nRXZlbnQpID0+IHZvaWQpOiBTZXNzaW9uIHtcblxuICAgICAgICBpZiAoIWhhbmRsZXIpIHtcbiAgICAgICAgICAgIHRoaXMuZWUucmVtb3ZlQWxsTGlzdGVuZXJzKHR5cGUpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5lZS5vZmYodHlwZSwgaGFuZGxlcik7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodHlwZSA9PT0gJ3B1Ymxpc2hlclN0YXJ0U3BlYWtpbmcnIHx8IHR5cGUgPT09ICdwdWJsaXNoZXJTdG9wU3BlYWtpbmcnKSB7XG4gICAgICAgICAgICB0aGlzLnNwZWFraW5nRXZlbnRzRW5hYmxlZCA9IGZhbHNlO1xuXG4gICAgICAgICAgICAvLyBJZiB0aGVyZSBhcmUgYWxyZWFkeSBhdmFpbGFibGUgcmVtb3RlIHN0cmVhbXMsIGRpc2FibGFlIGhhcmsgaW4gYWxsIG9mIHRoZW1cbiAgICAgICAgICAgIGZvciAoY29uc3QgY29ubmVjdGlvbklkIGluIHRoaXMucmVtb3RlQ29ubmVjdGlvbnMpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBzdHIgPSB0aGlzLnJlbW90ZUNvbm5lY3Rpb25zW2Nvbm5lY3Rpb25JZF0uc3RyZWFtO1xuICAgICAgICAgICAgICAgIGlmICghIXN0ciAmJiAhIXN0ci5zcGVlY2hFdmVudCkge1xuICAgICAgICAgICAgICAgICAgICBzdHIuZGlzYWJsZVNwZWFraW5nRXZlbnRzKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuXG4gICAgLyogSGlkZGVuIG1ldGhvZHMgKi9cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvblBhcnRpY2lwYW50Sm9pbmVkKHJlc3BvbnNlOiBDb25uZWN0aW9uT3B0aW9ucyk6IHZvaWQge1xuICAgICAgICAvLyBDb25uZWN0aW9uIHNob3VsZG4ndCBleGlzdFxuICAgICAgICB0aGlzLmdldENvbm5lY3Rpb24ocmVzcG9uc2UuaWQsICcnKVxuXG4gICAgICAgICAgICAudGhlbihjb25uZWN0aW9uID0+IHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLndhcm4oJ0Nvbm5lY3Rpb24gJyArIHJlc3BvbnNlLmlkICsgJyBhbHJlYWR5IGV4aXN0cyBpbiBjb25uZWN0aW9ucyBsaXN0Jyk7XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLmNhdGNoKG9wZW5WaWR1RXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IGNvbm5lY3Rpb24gPSBuZXcgQ29ubmVjdGlvbih0aGlzLCByZXNwb25zZSk7XG4gICAgICAgICAgICAgICAgdGhpcy5yZW1vdGVDb25uZWN0aW9uc1tyZXNwb25zZS5pZF0gPSBjb25uZWN0aW9uO1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdjb25uZWN0aW9uQ3JlYXRlZCcsIFtuZXcgQ29ubmVjdGlvbkV2ZW50KGZhbHNlLCB0aGlzLCAnY29ubmVjdGlvbkNyZWF0ZWQnLCBjb25uZWN0aW9uLCAnJyldKTtcbiAgICAgICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvblBhcnRpY2lwYW50TGVmdChtc2cpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5nZXRSZW1vdGVDb25uZWN0aW9uKG1zZy5jb25uZWN0aW9uSWQsICdSZW1vdGUgY29ubmVjdGlvbiAnICsgbXNnLmNvbm5lY3Rpb25JZCArIFwiIHVua25vd24gd2hlbiAnb25QYXJ0aWNpcGFudExlZnQnLiBcIiArXG4gICAgICAgICAgICAnRXhpc3RpbmcgcmVtb3RlIGNvbm5lY3Rpb25zOiAnICsgSlNPTi5zdHJpbmdpZnkoT2JqZWN0LmtleXModGhpcy5yZW1vdGVDb25uZWN0aW9ucykpKVxuXG4gICAgICAgICAgICAudGhlbihjb25uZWN0aW9uID0+IHtcbiAgICAgICAgICAgICAgICBpZiAoISFjb25uZWN0aW9uLnN0cmVhbSkge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBzdHJlYW0gPSBjb25uZWN0aW9uLnN0cmVhbTtcblxuICAgICAgICAgICAgICAgICAgICBjb25zdCBzdHJlYW1FdmVudCA9IG5ldyBTdHJlYW1FdmVudCh0cnVlLCB0aGlzLCAnc3RyZWFtRGVzdHJveWVkJywgc3RyZWFtLCBtc2cucmVhc29uKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3N0cmVhbURlc3Ryb3llZCcsIFtzdHJlYW1FdmVudF0pO1xuICAgICAgICAgICAgICAgICAgICBzdHJlYW1FdmVudC5jYWxsRGVmYXVsdEJlaGF2aW9yKCk7XG5cbiAgICAgICAgICAgICAgICAgICAgZGVsZXRlIHRoaXMucmVtb3RlU3RyZWFtc0NyZWF0ZWRbc3RyZWFtLnN0cmVhbUlkXTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZGVsZXRlIHRoaXMucmVtb3RlQ29ubmVjdGlvbnNbY29ubmVjdGlvbi5jb25uZWN0aW9uSWRdO1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdjb25uZWN0aW9uRGVzdHJveWVkJywgW25ldyBDb25uZWN0aW9uRXZlbnQoZmFsc2UsIHRoaXMsICdjb25uZWN0aW9uRGVzdHJveWVkJywgY29ubmVjdGlvbiwgbXNnLnJlYXNvbildKTtcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAuY2F0Y2gob3BlblZpZHVFcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihvcGVuVmlkdUVycm9yKTtcbiAgICAgICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvblBhcnRpY2lwYW50UHVibGlzaGVkKHJlc3BvbnNlOiBDb25uZWN0aW9uT3B0aW9ucyk6IHZvaWQge1xuXG4gICAgICAgIGNvbnN0IGFmdGVyQ29ubmVjdGlvbkZvdW5kID0gKGNvbm5lY3Rpb24pID0+IHtcbiAgICAgICAgICAgIHRoaXMucmVtb3RlQ29ubmVjdGlvbnNbY29ubmVjdGlvbi5jb25uZWN0aW9uSWRdID0gY29ubmVjdGlvbjtcblxuICAgICAgICAgICAgaWYgKCF0aGlzLnJlbW90ZVN0cmVhbXNDcmVhdGVkW2Nvbm5lY3Rpb24uc3RyZWFtLnN0cmVhbUlkXSkge1xuICAgICAgICAgICAgICAgIC8vIEF2b2lkIHJhY2UgY29uZGl0aW9uIGJldHdlZW4gc3RyZWFtLnN1YnNjcmliZSgpIGluIFwib25QYXJ0aWNpcGFudFB1Ymxpc2hlZFwiIGFuZCBpbiBcImpvaW5Sb29tXCIgcnBjIGNhbGxiYWNrXG4gICAgICAgICAgICAgICAgLy8gVGhpcyBjb25kaXRpb24gaXMgZmFsc2UgaWYgb3BlbnZpZHUtc2VydmVyIHNlbmRzIFwicGFydGljaXBhbnRQdWJsaXNoZWRcIiBldmVudCB0byBhIHN1YnNjcmliZXIgcGFydGljaXBhbnQgdGhhdCBoYXNcbiAgICAgICAgICAgICAgICAvLyBhbHJlYWR5IHN1YnNjcmliZWQgdG8gY2VydGFpbiBzdHJlYW0gaW4gdGhlIGNhbGxiYWNrIG9mIFwiam9pblJvb21cIiBtZXRob2RcblxuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdzdHJlYW1DcmVhdGVkJywgW25ldyBTdHJlYW1FdmVudChmYWxzZSwgdGhpcywgJ3N0cmVhbUNyZWF0ZWQnLCBjb25uZWN0aW9uLnN0cmVhbSwgJycpXSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMucmVtb3RlU3RyZWFtc0NyZWF0ZWRbY29ubmVjdGlvbi5zdHJlYW0uc3RyZWFtSWRdID0gdHJ1ZTtcbiAgICAgICAgfTtcblxuICAgICAgICAvLyBHZXQgdGhlIGV4aXN0aW5nIENvbm5lY3Rpb24gY3JlYXRlZCBvbiAnb25QYXJ0aWNpcGFudEpvaW5lZCcgZm9yXG4gICAgICAgIC8vIGV4aXN0aW5nIHBhcnRpY2lwYW50cyBvciBjcmVhdGUgYSBuZXcgb25lIGZvciBuZXcgcGFydGljaXBhbnRzXG4gICAgICAgIGxldCBjb25uZWN0aW9uOiBDb25uZWN0aW9uO1xuICAgICAgICB0aGlzLmdldFJlbW90ZUNvbm5lY3Rpb24ocmVzcG9uc2UuaWQsIFwiUmVtb3RlIGNvbm5lY3Rpb24gJ1wiICsgcmVzcG9uc2UuaWQgKyBcIicgdW5rbm93biB3aGVuICdvblBhcnRpY2lwYW50UHVibGlzaGVkJy4gXCIgK1xuICAgICAgICAgICAgJ0V4aXN0aW5nIHJlbW90ZSBjb25uZWN0aW9uczogJyArIEpTT04uc3RyaW5naWZ5KE9iamVjdC5rZXlzKHRoaXMucmVtb3RlQ29ubmVjdGlvbnMpKSlcblxuICAgICAgICAgICAgLnRoZW4oY29uID0+IHtcbiAgICAgICAgICAgICAgICAvLyBVcGRhdGUgZXhpc3RpbmcgQ29ubmVjdGlvblxuICAgICAgICAgICAgICAgIGNvbm5lY3Rpb24gPSBjb247XG4gICAgICAgICAgICAgICAgcmVzcG9uc2UubWV0YWRhdGEgPSBjb24uZGF0YTtcbiAgICAgICAgICAgICAgICBjb25uZWN0aW9uLm9wdGlvbnMgPSByZXNwb25zZTtcbiAgICAgICAgICAgICAgICBjb25uZWN0aW9uLmluaXRSZW1vdGVTdHJlYW1zKHJlc3BvbnNlLnN0cmVhbXMpO1xuICAgICAgICAgICAgICAgIGFmdGVyQ29ubmVjdGlvbkZvdW5kKGNvbm5lY3Rpb24pO1xuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIC5jYXRjaChvcGVuVmlkdUVycm9yID0+IHtcbiAgICAgICAgICAgICAgICAvLyBDcmVhdGUgbmV3IENvbm5lY3Rpb25cbiAgICAgICAgICAgICAgICBjb25uZWN0aW9uID0gbmV3IENvbm5lY3Rpb24odGhpcywgcmVzcG9uc2UpO1xuICAgICAgICAgICAgICAgIGFmdGVyQ29ubmVjdGlvbkZvdW5kKGNvbm5lY3Rpb24pO1xuICAgICAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIG9uUGFydGljaXBhbnRVbnB1Ymxpc2hlZChtc2cpOiB2b2lkIHtcbiAgICAgICAgaWYgKG1zZy5jb25uZWN0aW9uSWQgPT09IHRoaXMuY29ubmVjdGlvbi5jb25uZWN0aW9uSWQpIHtcbiAgICAgICAgICAgIC8vIFlvdXIgc3RyZWFtIGhhcyBiZWVuIGZvcmNlZGx5IHVucHVibGlzaGVkIGZyb20gdGhlIHNlc3Npb25cbiAgICAgICAgICAgIHRoaXMuc3RvcFB1Ymxpc2hlclN0cmVhbShtc2cucmVhc29uKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuZ2V0UmVtb3RlQ29ubmVjdGlvbihtc2cuY29ubmVjdGlvbklkLCBcIlJlbW90ZSBjb25uZWN0aW9uICdcIiArIG1zZy5jb25uZWN0aW9uSWQgKyBcIicgdW5rbm93biB3aGVuICdvblBhcnRpY2lwYW50VW5wdWJsaXNoZWQnLiBcIiArXG4gICAgICAgICAgICAgICAgJ0V4aXN0aW5nIHJlbW90ZSBjb25uZWN0aW9uczogJyArIEpTT04uc3RyaW5naWZ5KE9iamVjdC5rZXlzKHRoaXMucmVtb3RlQ29ubmVjdGlvbnMpKSlcblxuICAgICAgICAgICAgICAgIC50aGVuKGNvbm5lY3Rpb24gPT4ge1xuXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHN0cmVhbUV2ZW50ID0gbmV3IFN0cmVhbUV2ZW50KHRydWUsIHRoaXMsICdzdHJlYW1EZXN0cm95ZWQnLCBjb25uZWN0aW9uLnN0cmVhbSwgbXNnLnJlYXNvbik7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdzdHJlYW1EZXN0cm95ZWQnLCBbc3RyZWFtRXZlbnRdKTtcbiAgICAgICAgICAgICAgICAgICAgc3RyZWFtRXZlbnQuY2FsbERlZmF1bHRCZWhhdmlvcigpO1xuXG4gICAgICAgICAgICAgICAgICAgIC8vIERlbGV0aW5nIHRoZSByZW1vdGUgc3RyZWFtXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHN0cmVhbUlkOiBzdHJpbmcgPSBjb25uZWN0aW9uLnN0cmVhbS5zdHJlYW1JZDtcbiAgICAgICAgICAgICAgICAgICAgZGVsZXRlIHRoaXMucmVtb3RlU3RyZWFtc0NyZWF0ZWRbc3RyZWFtSWRdO1xuICAgICAgICAgICAgICAgICAgICBjb25uZWN0aW9uLnJlbW92ZVN0cmVhbShzdHJlYW1JZCk7XG4gICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAuY2F0Y2gob3BlblZpZHVFcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3Iob3BlblZpZHVFcnJvcik7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgb25QYXJ0aWNpcGFudEV2aWN0ZWQobXNnKTogdm9pZCB7XG4gICAgICAgIGlmIChtc2cuY29ubmVjdGlvbklkID09PSB0aGlzLmNvbm5lY3Rpb24uY29ubmVjdGlvbklkKSB7XG4gICAgICAgICAgICAvLyBZb3UgaGF2ZSBiZWVuIGV2aWN0ZWQgZnJvbSB0aGUgc2Vzc2lvblxuICAgICAgICAgICAgaWYgKCEhdGhpcy5zZXNzaW9uSWQgJiYgIXRoaXMuY29ubmVjdGlvbi5kaXNwb3NlZCkge1xuICAgICAgICAgICAgICAgIHRoaXMubGVhdmUodHJ1ZSwgbXNnLnJlYXNvbik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgb25OZXdNZXNzYWdlKG1zZyk6IHZvaWQge1xuXG4gICAgICAgIGNvbnNvbGUuaW5mbygnTmV3IHNpZ25hbDogJyArIEpTT04uc3RyaW5naWZ5KG1zZykpO1xuXG4gICAgICAgIHRoaXMuZ2V0Q29ubmVjdGlvbihtc2cuZnJvbSwgXCJDb25uZWN0aW9uICdcIiArIG1zZy5mcm9tICsgXCInIHVua25vdyB3aGVuICdvbk5ld01lc3NhZ2UnLiBFeGlzdGluZyByZW1vdGUgY29ubmVjdGlvbnM6IFwiXG4gICAgICAgICAgICArIEpTT04uc3RyaW5naWZ5KE9iamVjdC5rZXlzKHRoaXMucmVtb3RlQ29ubmVjdGlvbnMpKSArICcuIEV4aXN0aW5nIGxvY2FsIGNvbm5lY3Rpb246ICcgKyB0aGlzLmNvbm5lY3Rpb24uY29ubmVjdGlvbklkKVxuXG4gICAgICAgICAgICAudGhlbihjb25uZWN0aW9uID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnc2lnbmFsJywgW25ldyBTaWduYWxFdmVudCh0aGlzLCBtc2cudHlwZSwgbXNnLmRhdGEsIGNvbm5lY3Rpb24pXSk7XG4gICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3NpZ25hbDonICsgbXNnLnR5cGUsIFtuZXcgU2lnbmFsRXZlbnQodGhpcywgbXNnLnR5cGUsIG1zZy5kYXRhLCBjb25uZWN0aW9uKV0pO1xuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIC5jYXRjaChvcGVuVmlkdUVycm9yID0+IHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKG9wZW5WaWR1RXJyb3IpO1xuICAgICAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIG9uU3RyZWFtUHJvcGVydHlDaGFuZ2VkKG1zZyk6IHZvaWQge1xuICAgICAgICB0aGlzLmdldFJlbW90ZUNvbm5lY3Rpb24obXNnLmNvbm5lY3Rpb25JZCwgJ1JlbW90ZSBjb25uZWN0aW9uICcgKyBtc2cuY29ubmVjdGlvbklkICsgXCIgdW5rbm93biB3aGVuICdvblN0cmVhbVByb3BlcnR5Q2hhbmdlZCcuIFwiICtcbiAgICAgICAgICAgICdFeGlzdGluZyByZW1vdGUgY29ubmVjdGlvbnM6ICcgKyBKU09OLnN0cmluZ2lmeShPYmplY3Qua2V5cyh0aGlzLnJlbW90ZUNvbm5lY3Rpb25zKSkpXG5cbiAgICAgICAgICAgIC50aGVuKGNvbm5lY3Rpb24gPT4ge1xuICAgICAgICAgICAgICAgIGlmICghIWNvbm5lY3Rpb24uc3RyZWFtICYmIGNvbm5lY3Rpb24uc3RyZWFtLnN0cmVhbUlkID09PSBtc2cuc3RyZWFtSWQpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3Qgc3RyZWFtID0gY29ubmVjdGlvbi5zdHJlYW07XG4gICAgICAgICAgICAgICAgICAgIGxldCBvbGRWYWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgc3dpdGNoIChtc2cucHJvcGVydHkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJ2F1ZGlvQWN0aXZlJzpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvbGRWYWx1ZSA9IHN0cmVhbS5hdWRpb0FjdGl2ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtc2cubmV3VmFsdWUgPSBtc2cubmV3VmFsdWUgPT09ICd0cnVlJztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJlYW0uYXVkaW9BY3RpdmUgPSBtc2cubmV3VmFsdWU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlICd2aWRlb0FjdGl2ZSc6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgb2xkVmFsdWUgPSBzdHJlYW0udmlkZW9BY3RpdmU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbXNnLm5ld1ZhbHVlID0gbXNnLm5ld1ZhbHVlID09PSAndHJ1ZSc7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyZWFtLnZpZGVvQWN0aXZlID0gbXNnLm5ld1ZhbHVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAndmlkZW9EaW1lbnNpb25zJzpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvbGRWYWx1ZSA9IHN0cmVhbS52aWRlb0RpbWVuc2lvbnM7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbXNnLm5ld1ZhbHVlID0gSlNPTi5wYXJzZShKU09OLnBhcnNlKG1zZy5uZXdWYWx1ZSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cmVhbS52aWRlb0RpbWVuc2lvbnMgPSBtc2cubmV3VmFsdWU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnc3RyZWFtUHJvcGVydHlDaGFuZ2VkJywgW25ldyBTdHJlYW1Qcm9wZXJ0eUNoYW5nZWRFdmVudCh0aGlzLCBzdHJlYW0sIG1zZy5wcm9wZXJ0eSwgbXNnLm5ld1ZhbHVlLCBvbGRWYWx1ZSwgbXNnLnJlYXNvbildKTtcbiAgICAgICAgICAgICAgICAgICAgc3RyZWFtLnN0cmVhbU1hbmFnZXIuZW1pdEV2ZW50KCdzdHJlYW1Qcm9wZXJ0eUNoYW5nZWQnLCBbbmV3IFN0cmVhbVByb3BlcnR5Q2hhbmdlZEV2ZW50KHN0cmVhbS5zdHJlYW1NYW5hZ2VyLCBzdHJlYW0sIG1zZy5wcm9wZXJ0eSwgbXNnLm5ld1ZhbHVlLCBvbGRWYWx1ZSwgbXNnLnJlYXNvbildKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKFwiTm8gc3RyZWFtIHdpdGggc3RyZWFtSWQgJ1wiICsgbXNnLnN0cmVhbUlkICsgXCInIGZvdW5kIGZvciBjb25uZWN0aW9uICdcIiArIG1zZy5jb25uZWN0aW9uSWQgKyBcIicgb24gJ3N0cmVhbVByb3BlcnR5Q2hhbmdlZCcgZXZlbnRcIik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIC5jYXRjaChvcGVuVmlkdUVycm9yID0+IHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKG9wZW5WaWR1RXJyb3IpO1xuICAgICAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHJlY3ZJY2VDYW5kaWRhdGUobXNnKTogdm9pZCB7XG4gICAgICAgIGNvbnN0IGNhbmRpZGF0ZSA9IHtcbiAgICAgICAgICAgIGNhbmRpZGF0ZTogbXNnLmNhbmRpZGF0ZSxcbiAgICAgICAgICAgIHNkcE1pZDogbXNnLnNkcE1pZCxcbiAgICAgICAgICAgIHNkcE1MaW5lSW5kZXg6IG1zZy5zZHBNTGluZUluZGV4LFxuICAgICAgICAgICAgdG9KU09OOiAoKSA9PiB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHsgY2FuZGlkYXRlOiBtc2cuY2FuZGlkYXRlIH07XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuZ2V0Q29ubmVjdGlvbihtc2cuZW5kcG9pbnROYW1lLCAnQ29ubmVjdGlvbiBub3QgZm91bmQgZm9yIGVuZHBvaW50ICcgKyBtc2cuZW5kcG9pbnROYW1lICsgJy4gSWNlIGNhbmRpZGF0ZSB3aWxsIGJlIGlnbm9yZWQ6ICcgKyBjYW5kaWRhdGUpXG4gICAgICAgICAgICAudGhlbihjb25uZWN0aW9uID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCBzdHJlYW0gPSBjb25uZWN0aW9uLnN0cmVhbTtcbiAgICAgICAgICAgICAgICBzdHJlYW0uZ2V0V2ViUnRjUGVlcigpLmFkZEljZUNhbmRpZGF0ZShjYW5kaWRhdGUpLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcignRXJyb3IgYWRkaW5nIGNhbmRpZGF0ZSBmb3IgJyArIHN0cmVhbS5zdHJlYW1JZFxuICAgICAgICAgICAgICAgICAgICAgICAgKyAnIHN0cmVhbSBvZiBlbmRwb2ludCAnICsgbXNnLmVuZHBvaW50TmFtZSArICc6ICcgKyBlcnJvcik7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLmNhdGNoKG9wZW5WaWR1RXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3Iob3BlblZpZHVFcnJvcik7XG4gICAgICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgb25TZXNzaW9uQ2xvc2VkKG1zZyk6IHZvaWQge1xuICAgICAgICBjb25zb2xlLmluZm8oJ1Nlc3Npb24gY2xvc2VkOiAnICsgSlNPTi5zdHJpbmdpZnkobXNnKSk7XG4gICAgICAgIGNvbnN0IHMgPSBtc2cuc2Vzc2lvbklkO1xuICAgICAgICBpZiAocyAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnc2Vzc2lvbi1jbG9zZWQnLCBbe1xuICAgICAgICAgICAgICAgIHNlc3Npb246IHNcbiAgICAgICAgICAgIH1dKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvbnNvbGUud2FybignU2Vzc2lvbiB1bmRlZmluZWQgb24gc2Vzc2lvbiBjbG9zZWQnLCBtc2cpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIG9uTG9zdENvbm5lY3Rpb24oKTogdm9pZCB7XG5cbiAgICAgICAgLyppZiAoIXRoaXMuY29ubmVjdGlvbikge1xuXG4gICAgICAgICAgICBjb25zb2xlLndhcm4oJ05vdCBjb25uZWN0ZWQgdG8gc2Vzc2lvbjogaWYgeW91IGFyZSBub3QgZGVidWdnaW5nLCB0aGlzIGlzIHByb2JhYmx5IGEgY2VydGlmaWNhdGUgZXJyb3InKTtcblxuICAgICAgICAgICAgY29uc3QgdXJsID0gJ2h0dHBzOi8vJyArIHRoaXMub3BlbnZpZHUuZ2V0V3NVcmkoKS5zcGxpdCgnd3NzOi8vJylbMV0uc3BsaXQoJy9vcGVudmlkdScpWzBdO1xuICAgICAgICAgICAgaWYgKHdpbmRvdy5jb25maXJtKCdJZiB5b3UgYXJlIG5vdCBkZWJ1Z2dpbmcsIHRoaXMgaXMgcHJvYmFibHkgYSBjZXJ0aWZpY2F0ZSBlcnJvciBhdCBcXFwiJyArIHVybCArICdcXFwiXFxuXFxuQ2xpY2sgT0sgdG8gbmF2aWdhdGUgYW5kIGFjY2VwdCBpdCcpKSB7XG4gICAgICAgICAgICAgICAgbG9jYXRpb24uYXNzaWduKHVybCArICcvYWNjZXB0LWNlcnRpZmljYXRlJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH0qL1xuXG4gICAgICAgIGNvbnNvbGUud2FybignTG9zdCBjb25uZWN0aW9uIGluIFNlc3Npb24gJyArIHRoaXMuc2Vzc2lvbklkKTtcbiAgICAgICAgaWYgKCEhdGhpcy5zZXNzaW9uSWQgJiYgIXRoaXMuY29ubmVjdGlvbi5kaXNwb3NlZCkge1xuICAgICAgICAgICAgdGhpcy5sZWF2ZSh0cnVlLCAnbmV0d29ya0Rpc2Nvbm5lY3QnKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvblJlY292ZXJlZENvbm5lY3Rpb24oKTogdm9pZCB7XG4gICAgICAgIGNvbnNvbGUud2FybignUmVjb3ZlcmVkIGNvbm5lY3Rpb24gaW4gU2Vzc2lvbiAnICsgdGhpcy5zZXNzaW9uSWQpO1xuICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnY29ubmVjdGlvblJlY292ZXJlZCcsIFtdKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgb25NZWRpYUVycm9yKHBhcmFtcyk6IHZvaWQge1xuXG4gICAgICAgIGNvbnNvbGUuZXJyb3IoJ01lZGlhIGVycm9yOiAnICsgSlNPTi5zdHJpbmdpZnkocGFyYW1zKSk7XG4gICAgICAgIGNvbnN0IGVyciA9IHBhcmFtcy5lcnJvcjtcbiAgICAgICAgaWYgKGVycikge1xuICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ2Vycm9yLW1lZGlhJywgW3tcbiAgICAgICAgICAgICAgICBlcnJvcjogZXJyXG4gICAgICAgICAgICB9XSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjb25zb2xlLndhcm4oJ1JlY2VpdmVkIHVuZGVmaW5lZCBtZWRpYSBlcnJvci4gUGFyYW1zOicsIHBhcmFtcyk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgb25SZWNvcmRpbmdTdGFydGVkKHJlc3BvbnNlKTogdm9pZCB7XG4gICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdyZWNvcmRpbmdTdGFydGVkJywgW25ldyBSZWNvcmRpbmdFdmVudCh0aGlzLCAncmVjb3JkaW5nU3RhcnRlZCcsIHJlc3BvbnNlLmlkLCByZXNwb25zZS5uYW1lKV0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvblJlY29yZGluZ1N0b3BwZWQocmVzcG9uc2UpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3JlY29yZGluZ1N0b3BwZWQnLCBbbmV3IFJlY29yZGluZ0V2ZW50KHRoaXMsICdyZWNvcmRpbmdTdG9wcGVkJywgcmVzcG9uc2UuaWQsIHJlc3BvbnNlLm5hbWUpXSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGVtaXRFdmVudCh0eXBlOiBzdHJpbmcsIGV2ZW50QXJyYXk6IGFueVtdKTogdm9pZCB7XG4gICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KHR5cGUsIGV2ZW50QXJyYXkpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBsZWF2ZShmb3JjZWQ6IGJvb2xlYW4sIHJlYXNvbjogc3RyaW5nKTogdm9pZCB7XG5cbiAgICAgICAgZm9yY2VkID0gISFmb3JjZWQ7XG4gICAgICAgIGNvbnNvbGUuaW5mbygnTGVhdmluZyBTZXNzaW9uIChmb3JjZWQ9JyArIGZvcmNlZCArICcpJyk7XG5cbiAgICAgICAgaWYgKCEhdGhpcy5jb25uZWN0aW9uKSB7XG4gICAgICAgICAgICBpZiAoIXRoaXMuY29ubmVjdGlvbi5kaXNwb3NlZCAmJiAhZm9yY2VkKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5vcGVudmlkdS5zZW5kUmVxdWVzdCgnbGVhdmVSb29tJywgKGVycm9yLCByZXNwb25zZSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBpZiAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHRoaXMub3BlbnZpZHUuY2xvc2VXcygpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLm9wZW52aWR1LmNsb3NlV3MoKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5zdG9wUHVibGlzaGVyU3RyZWFtKHJlYXNvbik7XG5cbiAgICAgICAgICAgIGlmICghdGhpcy5jb25uZWN0aW9uLmRpc3Bvc2VkKSB7XG4gICAgICAgICAgICAgICAgLy8gTWFrZSBTZXNzaW9uIG9iamVjdCBkaXNwYXRjaCAnc2Vzc2lvbkRpc2Nvbm5lY3RlZCcgZXZlbnQgKGlmIGl0IGlzIG5vdCBhbHJlYWR5IGRpc3Bvc2VkKVxuICAgICAgICAgICAgICAgIGNvbnN0IHNlc3Npb25EaXNjb25uZWN0RXZlbnQgPSBuZXcgU2Vzc2lvbkRpc2Nvbm5lY3RlZEV2ZW50KHRoaXMsIHJlYXNvbik7XG4gICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3Nlc3Npb25EaXNjb25uZWN0ZWQnLCBbc2Vzc2lvbkRpc2Nvbm5lY3RFdmVudF0pO1xuICAgICAgICAgICAgICAgIHNlc3Npb25EaXNjb25uZWN0RXZlbnQuY2FsbERlZmF1bHRCZWhhdmlvcigpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY29uc29sZS53YXJuKCdZb3Ugd2VyZSBub3QgY29ubmVjdGVkIHRvIHRoZSBzZXNzaW9uICcgKyB0aGlzLnNlc3Npb25JZCk7XG4gICAgICAgIH1cbiAgICB9XG5cblxuICAgIC8qIFByaXZhdGUgbWV0aG9kcyAqL1xuXG4gICAgcHJpdmF0ZSBjb25uZWN0QXV4KHRva2VuOiBzdHJpbmcpOiBQcm9taXNlPGFueT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5vcGVudmlkdS5zdGFydFdzKChlcnJvcikgPT4ge1xuICAgICAgICAgICAgICAgIGlmICghIWVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcblxuICAgICAgICAgICAgICAgICAgICBjb25zdCBqb2luUGFyYW1zID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgdG9rZW46ICghIXRva2VuKSA/IHRva2VuIDogJycsXG4gICAgICAgICAgICAgICAgICAgICAgICBzZXNzaW9uOiB0aGlzLnNlc3Npb25JZCxcbiAgICAgICAgICAgICAgICAgICAgICAgIG1ldGFkYXRhOiAhIXRoaXMub3B0aW9ucy5tZXRhZGF0YSA/IHRoaXMub3B0aW9ucy5tZXRhZGF0YSA6ICcnLFxuICAgICAgICAgICAgICAgICAgICAgICAgc2VjcmV0OiB0aGlzLm9wZW52aWR1LmdldFNlY3JldCgpLFxuICAgICAgICAgICAgICAgICAgICAgICAgcmVjb3JkZXI6IHRoaXMub3BlbnZpZHUuZ2V0UmVjb3JkZXIoKSxcbiAgICAgICAgICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgICAgICAgICB0aGlzLm9wZW52aWR1LnNlbmRSZXF1ZXN0KCdqb2luUm9vbScsIGpvaW5QYXJhbXMsIChlcnJvciwgcmVzcG9uc2UpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghIWVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBJbml0aWFsaXplIGNhcGFiaWxpdGllcyBvYmplY3Qgd2l0aCB0aGUgcm9sZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY2FwYWJpbGl0aWVzID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdWJzY3JpYmU6IHRydWUsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHB1Ymxpc2g6IHRoaXMub3BlbnZpZHUucm9sZSAhPT0gJ1NVQlNDUklCRVInLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3JjZVVucHVibGlzaDogdGhpcy5vcGVudmlkdS5yb2xlID09PSAnTU9ERVJBVE9SJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yY2VEaXNjb25uZWN0OiB0aGlzLm9wZW52aWR1LnJvbGUgPT09ICdNT0RFUkFUT1InXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEluaXRpYWxpemUgbG9jYWwgQ29ubmVjdGlvbiBvYmplY3Qgd2l0aCB2YWx1ZXMgcmV0dXJuZWQgYnkgb3BlbnZpZHUtc2VydmVyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jb25uZWN0aW9uID0gbmV3IENvbm5lY3Rpb24odGhpcyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jb25uZWN0aW9uLmNvbm5lY3Rpb25JZCA9IHJlc3BvbnNlLmlkO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY29ubmVjdGlvbi5kYXRhID0gcmVzcG9uc2UubWV0YWRhdGE7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBJbml0aWFsaXplIHJlbW90ZSBDb25uZWN0aW9ucyB3aXRoIHZhbHVlIHJldHVybmVkIGJ5IG9wZW52aWR1LXNlcnZlclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGV2ZW50cyA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29ubmVjdGlvbnM6IG5ldyBBcnJheTxDb25uZWN0aW9uPigpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJlYW1zOiBuZXcgQXJyYXk8U3RyZWFtPigpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBleGlzdGluZ1BhcnRpY2lwYW50czogQ29ubmVjdGlvbk9wdGlvbnNbXSA9IHJlc3BvbnNlLnZhbHVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV4aXN0aW5nUGFydGljaXBhbnRzLmZvckVhY2gocGFydGljaXBhbnQgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBjb25uZWN0aW9uID0gbmV3IENvbm5lY3Rpb24odGhpcywgcGFydGljaXBhbnQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnJlbW90ZUNvbm5lY3Rpb25zW2Nvbm5lY3Rpb24uY29ubmVjdGlvbklkXSA9IGNvbm5lY3Rpb247XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV2ZW50cy5jb25uZWN0aW9ucy5wdXNoKGNvbm5lY3Rpb24pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoISFjb25uZWN0aW9uLnN0cmVhbSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5yZW1vdGVTdHJlYW1zQ3JlYXRlZFtjb25uZWN0aW9uLnN0cmVhbS5zdHJlYW1JZF0gPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXZlbnRzLnN0cmVhbXMucHVzaChjb25uZWN0aW9uLnN0cmVhbSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIE93biAnY29ubmVjdGlvbkNyZWF0ZWQnIGV2ZW50XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ2Nvbm5lY3Rpb25DcmVhdGVkJywgW25ldyBDb25uZWN0aW9uRXZlbnQoZmFsc2UsIHRoaXMsICdjb25uZWN0aW9uQ3JlYXRlZCcsIHRoaXMuY29ubmVjdGlvbiwgJycpXSk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBPbmUgJ2Nvbm5lY3Rpb25DcmVhdGVkJyBldmVudCBmb3IgZWFjaCBleGlzdGluZyBjb25uZWN0aW9uIGluIHRoZSBzZXNzaW9uXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZXZlbnRzLmNvbm5lY3Rpb25zLmZvckVhY2goY29ubmVjdGlvbiA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdjb25uZWN0aW9uQ3JlYXRlZCcsIFtuZXcgQ29ubmVjdGlvbkV2ZW50KGZhbHNlLCB0aGlzLCAnY29ubmVjdGlvbkNyZWF0ZWQnLCBjb25uZWN0aW9uLCAnJyldKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIE9uZSAnc3RyZWFtQ3JlYXRlZCcgZXZlbnQgZm9yIGVhY2ggYWN0aXZlIHN0cmVhbSBpbiB0aGUgc2Vzc2lvblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV2ZW50cy5zdHJlYW1zLmZvckVhY2goc3RyZWFtID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3N0cmVhbUNyZWF0ZWQnLCBbbmV3IFN0cmVhbUV2ZW50KGZhbHNlLCB0aGlzLCAnc3RyZWFtQ3JlYXRlZCcsIHN0cmVhbSwgJycpXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBwcml2YXRlIHN0b3BQdWJsaXNoZXJTdHJlYW0ocmVhc29uOiBzdHJpbmcpIHtcbiAgICAgICAgaWYgKCEhdGhpcy5jb25uZWN0aW9uLnN0cmVhbSkge1xuICAgICAgICAgICAgLy8gRGlzcG9zZSBQdWJsaXNoZXIncyAgbG9jYWwgc3RyZWFtXG4gICAgICAgICAgICB0aGlzLmNvbm5lY3Rpb24uc3RyZWFtLmRpc3Bvc2VXZWJSdGNQZWVyKCk7XG4gICAgICAgICAgICBpZiAodGhpcy5jb25uZWN0aW9uLnN0cmVhbS5pc0xvY2FsU3RyZWFtUHVibGlzaGVkKSB7XG4gICAgICAgICAgICAgICAgLy8gTWFrZSBQdWJsaXNoZXIgb2JqZWN0IGRpc3BhdGNoICdzdHJlYW1EZXN0cm95ZWQnIGV2ZW50IGlmIHRoZSBTdHJlYW0gd2FzIHB1Ymxpc2hlZFxuICAgICAgICAgICAgICAgIHRoaXMuY29ubmVjdGlvbi5zdHJlYW0uZWUuZW1pdEV2ZW50KCdsb2NhbC1zdHJlYW0tZGVzdHJveWVkJywgW3JlYXNvbl0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBzdHJpbmdDbGllbnRNZXRhZGF0YShtZXRhZGF0YTogYW55KTogc3RyaW5nIHtcbiAgICAgICAgaWYgKHR5cGVvZiBtZXRhZGF0YSAhPT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgIHJldHVybiBKU09OLnN0cmluZ2lmeShtZXRhZGF0YSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gbWV0YWRhdGE7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIGdldENvbm5lY3Rpb24oY29ubmVjdGlvbklkOiBzdHJpbmcsIGVycm9yTWVzc2FnZTogc3RyaW5nKTogUHJvbWlzZTxDb25uZWN0aW9uPiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZTxDb25uZWN0aW9uPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICBjb25zdCBjb25uZWN0aW9uID0gdGhpcy5yZW1vdGVDb25uZWN0aW9uc1tjb25uZWN0aW9uSWRdO1xuICAgICAgICAgICAgaWYgKCEhY29ubmVjdGlvbikge1xuICAgICAgICAgICAgICAgIC8vIFJlc29sdmUgcmVtb3RlIGNvbm5lY3Rpb25cbiAgICAgICAgICAgICAgICByZXNvbHZlKGNvbm5lY3Rpb24pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5jb25uZWN0aW9uLmNvbm5lY3Rpb25JZCA9PT0gY29ubmVjdGlvbklkKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIFJlc29sdmUgbG9jYWwgY29ubmVjdGlvblxuICAgICAgICAgICAgICAgICAgICByZXNvbHZlKHRoaXMuY29ubmVjdGlvbik7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gQ29ubmVjdGlvbiBub3QgZm91bmQuIFJlamVjdCB3aXRoIE9wZW5WaWR1RXJyb3JcbiAgICAgICAgICAgICAgICAgICAgcmVqZWN0KG5ldyBPcGVuVmlkdUVycm9yKE9wZW5WaWR1RXJyb3JOYW1lLkdFTkVSSUNfRVJST1IsIGVycm9yTWVzc2FnZSkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBnZXRSZW1vdGVDb25uZWN0aW9uKGNvbm5lY3Rpb25JZDogc3RyaW5nLCBlcnJvck1lc3NhZ2U6IHN0cmluZyk6IFByb21pc2U8Q29ubmVjdGlvbj4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2U8Q29ubmVjdGlvbj4oKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgY29uc3QgY29ubmVjdGlvbiA9IHRoaXMucmVtb3RlQ29ubmVjdGlvbnNbY29ubmVjdGlvbklkXTtcbiAgICAgICAgICAgIGlmICghIWNvbm5lY3Rpb24pIHtcbiAgICAgICAgICAgICAgICAvLyBSZXNvbHZlIHJlbW90ZSBjb25uZWN0aW9uXG4gICAgICAgICAgICAgICAgcmVzb2x2ZShjb25uZWN0aW9uKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgLy8gUmVtb3RlIGNvbm5lY3Rpb24gbm90IGZvdW5kLiBSZWplY3Qgd2l0aCBPcGVuVmlkdUVycm9yXG4gICAgICAgICAgICAgICAgcmVqZWN0KG5ldyBPcGVuVmlkdUVycm9yKE9wZW5WaWR1RXJyb3JOYW1lLkdFTkVSSUNfRVJST1IsIGVycm9yTWVzc2FnZSkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBwcml2YXRlIHByb2Nlc3NUb2tlbih0b2tlbjogc3RyaW5nKTogdm9pZCB7XG4gICAgICAgIGNvbnN0IHVybCA9IG5ldyBVUkwodG9rZW4pO1xuICAgICAgICB0aGlzLnNlc3Npb25JZCA9IDxzdHJpbmc+dXJsLnNlYXJjaFBhcmFtcy5nZXQoJ3Nlc3Npb25JZCcpO1xuICAgICAgICBjb25zdCBzZWNyZXQgPSB1cmwuc2VhcmNoUGFyYW1zLmdldCgnc2VjcmV0Jyk7XG4gICAgICAgIGNvbnN0IHJlY29yZGVyID0gdXJsLnNlYXJjaFBhcmFtcy5nZXQoJ3JlY29yZGVyJyk7XG4gICAgICAgIGNvbnN0IHR1cm5Vc2VybmFtZSA9IHVybC5zZWFyY2hQYXJhbXMuZ2V0KCd0dXJuVXNlcm5hbWUnKTtcbiAgICAgICAgY29uc3QgdHVybkNyZWRlbnRpYWwgPSB1cmwuc2VhcmNoUGFyYW1zLmdldCgndHVybkNyZWRlbnRpYWwnKTtcbiAgICAgICAgY29uc3Qgcm9sZSA9IHVybC5zZWFyY2hQYXJhbXMuZ2V0KCdyb2xlJyk7XG5cbiAgICAgICAgaWYgKCEhc2VjcmV0KSB7XG4gICAgICAgICAgICB0aGlzLm9wZW52aWR1LnNlY3JldCA9IHNlY3JldDtcbiAgICAgICAgfVxuICAgICAgICBpZiAoISFyZWNvcmRlcikge1xuICAgICAgICAgICAgdGhpcy5vcGVudmlkdS5yZWNvcmRlciA9IHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCEhdHVyblVzZXJuYW1lICYmICEhdHVybkNyZWRlbnRpYWwpIHtcbiAgICAgICAgICAgIGNvbnN0IHN0dW5VcmwgPSAnc3R1bjonICsgdXJsLmhvc3RuYW1lICsgJzozNDc4JztcbiAgICAgICAgICAgIGNvbnN0IHR1cm5VcmwxID0gJ3R1cm46JyArIHVybC5ob3N0bmFtZSArICc6MzQ3OCc7XG4gICAgICAgICAgICBjb25zdCB0dXJuVXJsMiA9IHR1cm5VcmwxICsgJz90cmFuc3BvcnQ9dGNwJztcbiAgICAgICAgICAgIHRoaXMub3BlbnZpZHUuaWNlU2VydmVycyA9IFtcbiAgICAgICAgICAgICAgICB7IHVybHM6IFtzdHVuVXJsXSB9LFxuICAgICAgICAgICAgICAgIHsgdXJsczogW3R1cm5VcmwxLCB0dXJuVXJsMl0sIHVzZXJuYW1lOiB0dXJuVXNlcm5hbWUsIGNyZWRlbnRpYWw6IHR1cm5DcmVkZW50aWFsIH1cbiAgICAgICAgICAgIF07XG4gICAgICAgICAgICBjb25zb2xlLmxvZygnVFVSTiB0ZW1wIGNyZWRlbnRpYWxzIFsnICsgdHVyblVzZXJuYW1lICsgJzonICsgdHVybkNyZWRlbnRpYWwgKyAnXScpO1xuICAgICAgICB9XG4gICAgICAgIGlmICghIXJvbGUpIHtcbiAgICAgICAgICAgIHRoaXMub3BlbnZpZHUucm9sZSA9IHJvbGU7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLm9wZW52aWR1LndzVXJpID0gJ3dzczovLycgKyB1cmwuaG9zdCArICcvb3BlbnZpZHUnO1xuICAgIH1cblxufSIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTctMjAxOCBPcGVuVmlkdSAoaHR0cHM6Ly9vcGVudmlkdS5pby8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuaW1wb3J0IHsgQ29ubmVjdGlvbiB9IGZyb20gJy4vQ29ubmVjdGlvbic7XG5pbXBvcnQgeyBTZXNzaW9uIH0gZnJvbSAnLi9TZXNzaW9uJztcbmltcG9ydCB7IFN0cmVhbU1hbmFnZXIgfSBmcm9tICcuL1N0cmVhbU1hbmFnZXInO1xuaW1wb3J0IHsgSW5ib3VuZFN0cmVhbU9wdGlvbnMgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHJpdmF0ZS9JbmJvdW5kU3RyZWFtT3B0aW9ucyc7XG5pbXBvcnQgeyBPdXRib3VuZFN0cmVhbU9wdGlvbnMgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHJpdmF0ZS9PdXRib3VuZFN0cmVhbU9wdGlvbnMnO1xuaW1wb3J0IHsgV2ViUnRjUGVlciwgV2ViUnRjUGVlclNlbmRvbmx5LCBXZWJSdGNQZWVyUmVjdm9ubHksIFdlYlJ0Y1BlZXJTZW5kcmVjdiB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvV2ViUnRjUGVlci9XZWJSdGNQZWVyJztcbmltcG9ydCB7IFdlYlJ0Y1N0YXRzIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9XZWJSdGNTdGF0cy9XZWJSdGNTdGF0cyc7XG5pbXBvcnQgeyBQdWJsaXNoZXJTcGVha2luZ0V2ZW50IH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvUHVibGlzaGVyU3BlYWtpbmdFdmVudCc7XG5cbmltcG9ydCBFdmVudEVtaXR0ZXIgPSByZXF1aXJlKCd3b2xmeTg3LWV2ZW50ZW1pdHRlcicpO1xuaW1wb3J0IGhhcmsgPSByZXF1aXJlKCdoYXJrJyk7XG5pbXBvcnQgeyBPcGVuVmlkdUVycm9yLCBPcGVuVmlkdUVycm9yTmFtZSB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRW51bXMvT3BlblZpZHVFcnJvcic7XG5cblxuLyoqXG4gKiBSZXByZXNlbnRzIGVhY2ggb25lIG9mIHRoZSBtZWRpYSBzdHJlYW1zIGF2YWlsYWJsZSBpbiBPcGVuVmlkdSBTZXJ2ZXIgZm9yIGNlcnRhaW4gc2Vzc2lvbi5cbiAqIEVhY2ggW1tQdWJsaXNoZXJdXSBhbmQgW1tTdWJzY3JpYmVyXV0gaGFzIGFuIGF0dHJpYnV0ZSBvZiB0eXBlIFN0cmVhbSwgYXMgdGhleSBnaXZlIGFjY2Vzc1xuICogdG8gb25lIG9mIHRoZW0gKHNlbmRpbmcgYW5kIHJlY2VpdmluZyBpdCwgcmVzcGVjdGl2ZWx5KVxuICovXG5leHBvcnQgY2xhc3MgU3RyZWFtIHtcblxuICAgIC8qKlxuICAgICAqIFRoZSBDb25uZWN0aW9uIG9iamVjdCB0aGF0IGlzIHB1Ymxpc2hpbmcgdGhlIHN0cmVhbVxuICAgICAqL1xuICAgIGNvbm5lY3Rpb246IENvbm5lY3Rpb247XG5cbiAgICAvKipcbiAgICAgKiBGcmFtZSByYXRlIG9mIHRoZSB2aWRlbyBpbiBmcmFtZXMgcGVyIHNlY29uZC4gVGhpcyBwcm9wZXJ0eSBpcyBvbmx5IGRlZmluZWQgaWYgdGhlIFtbUHVibGlzaGVyXV0gb2ZcbiAgICAgKiB0aGUgc3RyZWFtIHdhcyBpbml0aWFsaXplZCBwYXNzaW5nIGEgX2ZyYW1lUmF0ZV8gcHJvcGVydHkgb24gW1tPcGVuVmlkdS5pbml0UHVibGlzaGVyXV0gbWV0aG9kXG4gICAgICovXG4gICAgZnJhbWVSYXRlPzogbnVtYmVyO1xuXG4gICAgLyoqXG4gICAgICogV2hldGhlciB0aGUgc3RyZWFtIGhhcyBhIHZpZGVvIHRyYWNrIG9yIG5vdFxuICAgICAqL1xuICAgIGhhc1ZpZGVvOiBib29sZWFuO1xuXG4gICAgLyoqXG4gICAgICogV2hldGhlciB0aGUgc3RyZWFtIGhhcyBhbiBhdWRpbyB0cmFjayBvciBub3RcbiAgICAgKi9cbiAgICBoYXNBdWRpbzogYm9vbGVhbjtcblxuICAgIC8qKlxuICAgICAqIFdoZXRoZXIgdGhlIHN0cmVhbSBoYXMgdGhlIHZpZGVvIHRyYWNrIG11dGVkIG9yIHVubXV0ZWQuIElmIFtbaGFzVmlkZW9dXSBpcyBmYWxzZSwgdGhpcyBwcm9wZXJ0eSBpcyB1bmRlZmluZWQuXG4gICAgICpcbiAgICAgKiBUaGlzIHByb3BlcnR5IG1heSBjaGFuZ2UgaWYgdGhlIFB1Ymxpc2hlciBwdWJsaXNoaW5nIHRoZSBzdHJlYW0gY2FsbHMgW1tQdWJsaXNoZXIucHVibGlzaFZpZGVvXV0uIFdoZW5ldmVyIHRoaXMgaGFwcGVucyBhIFtbU3RyZWFtUHJvcGVydHlDaGFuZ2VkRXZlbnRdXSB3aWxsIGJlIGRpc3BhdGNoZWRcbiAgICAgKiBieSB0aGUgU2Vzc2lvbiBvYmplY3QgYXMgd2VsbCBhcyBieSB0aGUgYWZmZWN0ZWQgU3Vic2NyaWJlci9QdWJsaXNoZXIgb2JqZWN0XG4gICAgICovXG4gICAgdmlkZW9BY3RpdmU6IGJvb2xlYW47XG5cbiAgICAvKipcbiAgICAgKiBXaGV0aGVyIHRoZSBzdHJlYW0gaGFzIHRoZSBhdWRpbyB0cmFjayBtdXRlZCBvciB1bm11dGVkLiBJZiBbW2hhc0F1ZGlvXV0gaXMgZmFsc2UsIHRoaXMgcHJvcGVydHkgaXMgdW5kZWZpbmVkXG4gICAgICpcbiAgICAgKiBUaGlzIHByb3BlcnR5IG1heSBjaGFuZ2UgaWYgdGhlIFB1Ymxpc2hlciBwdWJsaXNoaW5nIHRoZSBzdHJlYW0gY2FsbHMgW1tQdWJsaXNoZXIucHVibGlzaEF1ZGlvXV0uIFdoZW5ldmVyIHRoaXMgaGFwcGVucyBhIFtbU3RyZWFtUHJvcGVydHlDaGFuZ2VkRXZlbnRdXSB3aWxsIGJlIGRpc3BhdGNoZWRcbiAgICAgKiBieSB0aGUgU2Vzc2lvbiBvYmplY3QgYXMgd2VsbCBhcyBieSB0aGUgYWZmZWN0ZWQgU3Vic2NyaWJlci9QdWJsaXNoZXIgb2JqZWN0XG4gICAgICovXG4gICAgYXVkaW9BY3RpdmU6IGJvb2xlYW47XG5cbiAgICAvKipcbiAgICAgKiBVbmlxdWUgaWRlbnRpZmllciBvZiB0aGUgc3RyZWFtXG4gICAgICovXG4gICAgc3RyZWFtSWQ6IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIGBcIkNBTUVSQVwiYCwgYFwiU0NSRUVOXCJgIG9yIGBcIkNVU1RPTVwiYCAodGhlIGxhdHRlciB3aGVuIFtbUHVibGlzaGVyUHJvcGVydGllcy52aWRlb1NvdXJjZV1dIGlzIGEgTWVkaWFTdHJlYW1UcmFjayB3aGVuIGNhbGxpbmcgW1tPcGVuVmlkdS5pbml0UHVibGlzaGVyXV0pLlxuICAgICAqIElmIFtbaGFzVmlkZW9dXSBpcyBmYWxzZSwgdGhpcyBwcm9wZXJ0eSBpcyB1bmRlZmluZWRcbiAgICAgKi9cbiAgICB0eXBlT2ZWaWRlbz86IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIFN0cmVhbU1hbmFnZXIgb2JqZWN0IChbW1B1Ymxpc2hlcl1dIG9yIFtbU3Vic2NyaWJlcl1dKSBpbiBjaGFyZ2Ugb2YgZGlzcGxheWluZyB0aGlzIHN0cmVhbSBpbiB0aGUgRE9NXG4gICAgICovXG4gICAgc3RyZWFtTWFuYWdlcjogU3RyZWFtTWFuYWdlcjtcblxuICAgIC8qKlxuICAgICAqIFdpZHRoIGFuZCBoZWlnaHQgaW4gcGl4ZWxzIG9mIHRoZSBlbmNvZGVkIHZpZGVvIHN0cmVhbS4gSWYgW1toYXNWaWRlb11dIGlzIGZhbHNlLCB0aGlzIHByb3BlcnR5IGlzIHVuZGVmaW5lZFxuICAgICAqXG4gICAgICogVGhpcyBwcm9wZXJ0eSBtYXkgY2hhbmdlIGlmIHRoZSBQdWJsaXNoZXIgdGhhdCBpcyBwdWJsaXNoaW5nOlxuICAgICAqIC0gSWYgaXQgaXMgYSBtb2JpbGUgZGV2aWNlLCB3aGVuZXZlciB0aGUgdXNlciByb3RhdGVzIHRoZSBkZXZpY2UuXG4gICAgICogLSBJZiBpdCBpcyBzY3JlZW4tc2hhcmluZywgd2hlbmV2ZXIgdGhlIHVzZXIgY2hhbmdlcyB0aGUgc2l6ZSBvZiB0aGUgY2FwdHVyZWQgd2luZG93LlxuICAgICAqXG4gICAgICogV2hlbmV2ZXIgdGhpcyBoYXBwZW5zIGEgW1tTdHJlYW1Qcm9wZXJ0eUNoYW5nZWRFdmVudF1dIHdpbGwgYmUgZGlzcGF0Y2hlZCBieSB0aGUgU2Vzc2lvbiBvYmplY3QgYXMgd2VsbCBhcyBieSB0aGUgYWZmZWN0ZWQgU3Vic2NyaWJlci9QdWJsaXNoZXIgb2JqZWN0XG4gICAgICovXG4gICAgdmlkZW9EaW1lbnNpb25zOiB7IHdpZHRoOiBudW1iZXIsIGhlaWdodDogbnVtYmVyIH07XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgZWUgPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG5cbiAgICBwcml2YXRlIHdlYlJ0Y1BlZXI6IFdlYlJ0Y1BlZXI7XG4gICAgcHJpdmF0ZSBtZWRpYVN0cmVhbTogTWVkaWFTdHJlYW07XG4gICAgcHJpdmF0ZSB3ZWJSdGNTdGF0czogV2ViUnRjU3RhdHM7XG5cbiAgICBwcml2YXRlIGlzU3Vic2NyaWJlVG9SZW1vdGUgPSBmYWxzZTtcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBpc0xvY2FsU3RyZWFtUmVhZHlUb1B1Ymxpc2ggPSBmYWxzZTtcbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgaXNMb2NhbFN0cmVhbVB1Ymxpc2hlZCA9IGZhbHNlO1xuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBwdWJsaXNoZWRPbmNlID0gZmFsc2U7XG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHNlc3Npb246IFNlc3Npb247XG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGluYm91bmRTdHJlYW1PcHRzOiBJbmJvdW5kU3RyZWFtT3B0aW9ucztcbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgb3V0Ym91bmRTdHJlYW1PcHRzOiBPdXRib3VuZFN0cmVhbU9wdGlvbnM7XG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHNwZWVjaEV2ZW50OiBhbnk7XG5cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3RvcihzZXNzaW9uOiBTZXNzaW9uLCBvcHRpb25zOiBJbmJvdW5kU3RyZWFtT3B0aW9ucyB8IE91dGJvdW5kU3RyZWFtT3B0aW9ucyB8IHt9KSB7XG5cbiAgICAgICAgdGhpcy5zZXNzaW9uID0gc2Vzc2lvbjtcblxuICAgICAgICBpZiAob3B0aW9ucy5oYXNPd25Qcm9wZXJ0eSgnaWQnKSkge1xuICAgICAgICAgICAgLy8gSW5ib3VuZFN0cmVhbU9wdGlvbnM6IHN0cmVhbSBiZWxvbmdzIHRvIGEgU3Vic2NyaWJlclxuICAgICAgICAgICAgdGhpcy5pbmJvdW5kU3RyZWFtT3B0cyA9IDxJbmJvdW5kU3RyZWFtT3B0aW9ucz5vcHRpb25zO1xuICAgICAgICAgICAgdGhpcy5zdHJlYW1JZCA9IHRoaXMuaW5ib3VuZFN0cmVhbU9wdHMuaWQ7XG4gICAgICAgICAgICB0aGlzLmhhc0F1ZGlvID0gdGhpcy5pbmJvdW5kU3RyZWFtT3B0cy5oYXNBdWRpbztcbiAgICAgICAgICAgIHRoaXMuaGFzVmlkZW8gPSB0aGlzLmluYm91bmRTdHJlYW1PcHRzLmhhc1ZpZGVvO1xuICAgICAgICAgICAgaWYgKHRoaXMuaGFzQXVkaW8pIHtcbiAgICAgICAgICAgICAgICB0aGlzLmF1ZGlvQWN0aXZlID0gdGhpcy5pbmJvdW5kU3RyZWFtT3B0cy5hdWRpb0FjdGl2ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0aGlzLmhhc1ZpZGVvKSB7XG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb0FjdGl2ZSA9IHRoaXMuaW5ib3VuZFN0cmVhbU9wdHMudmlkZW9BY3RpdmU7XG4gICAgICAgICAgICAgICAgdGhpcy50eXBlT2ZWaWRlbyA9ICghdGhpcy5pbmJvdW5kU3RyZWFtT3B0cy50eXBlT2ZWaWRlbykgPyB1bmRlZmluZWQgOiB0aGlzLmluYm91bmRTdHJlYW1PcHRzLnR5cGVPZlZpZGVvO1xuICAgICAgICAgICAgICAgIHRoaXMuZnJhbWVSYXRlID0gKHRoaXMuaW5ib3VuZFN0cmVhbU9wdHMuZnJhbWVSYXRlID09PSAtMSkgPyB1bmRlZmluZWQgOiB0aGlzLmluYm91bmRTdHJlYW1PcHRzLmZyYW1lUmF0ZTtcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvRGltZW5zaW9ucyA9IHRoaXMuaW5ib3VuZFN0cmVhbU9wdHMudmlkZW9EaW1lbnNpb25zO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gT3V0Ym91bmRTdHJlYW1PcHRpb25zOiBzdHJlYW0gYmVsb25ncyB0byBhIFB1Ymxpc2hlclxuICAgICAgICAgICAgdGhpcy5vdXRib3VuZFN0cmVhbU9wdHMgPSA8T3V0Ym91bmRTdHJlYW1PcHRpb25zPm9wdGlvbnM7XG5cbiAgICAgICAgICAgIHRoaXMuaGFzQXVkaW8gPSB0aGlzLmlzU2VuZEF1ZGlvKCk7XG4gICAgICAgICAgICB0aGlzLmhhc1ZpZGVvID0gdGhpcy5pc1NlbmRWaWRlbygpO1xuXG4gICAgICAgICAgICBpZiAodGhpcy5oYXNBdWRpbykge1xuICAgICAgICAgICAgICAgIHRoaXMuYXVkaW9BY3RpdmUgPSAhIXRoaXMub3V0Ym91bmRTdHJlYW1PcHRzLnB1Ymxpc2hlclByb3BlcnRpZXMucHVibGlzaEF1ZGlvO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRoaXMuaGFzVmlkZW8pIHtcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvQWN0aXZlID0gISF0aGlzLm91dGJvdW5kU3RyZWFtT3B0cy5wdWJsaXNoZXJQcm9wZXJ0aWVzLnB1Ymxpc2hWaWRlbztcbiAgICAgICAgICAgICAgICB0aGlzLmZyYW1lUmF0ZSA9IHRoaXMub3V0Ym91bmRTdHJlYW1PcHRzLnB1Ymxpc2hlclByb3BlcnRpZXMuZnJhbWVSYXRlO1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLm91dGJvdW5kU3RyZWFtT3B0cy5wdWJsaXNoZXJQcm9wZXJ0aWVzLnZpZGVvU291cmNlIGluc3RhbmNlb2YgTWVkaWFTdHJlYW1UcmFjaykge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnR5cGVPZlZpZGVvID0gJ0NVU1RPTSc7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy50eXBlT2ZWaWRlbyA9IHRoaXMuaXNTZW5kU2NyZWVuKCkgPyAnU0NSRUVOJyA6ICdDQU1FUkEnO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuZWUub24oJ21lZGlhc3RyZWFtLXVwZGF0ZWQnLCAoKSA9PiB7XG4gICAgICAgICAgICB0aGlzLnN0cmVhbU1hbmFnZXIudXBkYXRlTWVkaWFTdHJlYW0odGhpcy5tZWRpYVN0cmVhbSk7XG4gICAgICAgICAgICBjb25zb2xlLmRlYnVnKCdWaWRlbyBzcmNPYmplY3QgWycgKyB0aGlzLm1lZGlhU3RyZWFtICsgJ10gdXBkYXRlZCBpbiBzdHJlYW0gWycgKyB0aGlzLnN0cmVhbUlkICsgJ10nKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG5cbiAgICAvKiBIaWRkZW4gbWV0aG9kcyAqL1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGdldE1lZGlhU3RyZWFtKCk6IE1lZGlhU3RyZWFtIHtcbiAgICAgICAgcmV0dXJuIHRoaXMubWVkaWFTdHJlYW07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHNldE1lZGlhU3RyZWFtKG1lZGlhU3RyZWFtOiBNZWRpYVN0cmVhbSk6IHZvaWQge1xuICAgICAgICB0aGlzLm1lZGlhU3RyZWFtID0gbWVkaWFTdHJlYW07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHVwZGF0ZU1lZGlhU3RyZWFtSW5WaWRlb3MoKSB7XG4gICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdtZWRpYXN0cmVhbS11cGRhdGVkJyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGdldFdlYlJ0Y1BlZXIoKTogV2ViUnRjUGVlciB7XG4gICAgICAgIHJldHVybiB0aGlzLndlYlJ0Y1BlZXI7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGdldFJUQ1BlZXJDb25uZWN0aW9uKCk6IFJUQ1BlZXJDb25uZWN0aW9uIHtcbiAgICAgICAgcmV0dXJuIHRoaXMud2ViUnRjUGVlci5wYztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgc3Vic2NyaWJlVG9NeVJlbW90ZSh2YWx1ZTogYm9vbGVhbik6IHZvaWQge1xuICAgICAgICB0aGlzLmlzU3Vic2NyaWJlVG9SZW1vdGUgPSB2YWx1ZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgc2V0T3V0Ym91bmRTdHJlYW1PcHRpb25zKG91dGJvdW5kU3RyZWFtT3B0czogT3V0Ym91bmRTdHJlYW1PcHRpb25zKTogdm9pZCB7XG4gICAgICAgIHRoaXMub3V0Ym91bmRTdHJlYW1PcHRzID0gb3V0Ym91bmRTdHJlYW1PcHRzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBzdWJzY3JpYmUoKTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIHRoaXMuaW5pdFdlYlJ0Y1BlZXJSZWNlaXZlKClcbiAgICAgICAgICAgICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBwdWJsaXNoKCk6IFByb21pc2U8YW55PiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICBpZiAodGhpcy5pc0xvY2FsU3RyZWFtUmVhZHlUb1B1Ymxpc2gpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmluaXRXZWJSdGNQZWVyU2VuZCgpXG4gICAgICAgICAgICAgICAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLm9uY2UoJ3N0cmVhbS1yZWFkeS10by1wdWJsaXNoJywgKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnB1Ymxpc2goKVxuICAgICAgICAgICAgICAgICAgICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgICAgICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGRpc3Bvc2VXZWJSdGNQZWVyKCk6IHZvaWQge1xuICAgICAgICBpZiAodGhpcy53ZWJSdGNQZWVyKSB7XG4gICAgICAgICAgICB0aGlzLndlYlJ0Y1BlZXIuZGlzcG9zZSgpO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLnNwZWVjaEV2ZW50KSB7XG4gICAgICAgICAgICB0aGlzLnNwZWVjaEV2ZW50LnN0b3AoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuc3RvcFdlYlJ0Y1N0YXRzKCk7XG5cbiAgICAgICAgY29uc29sZS5pbmZvKCghIXRoaXMub3V0Ym91bmRTdHJlYW1PcHRzID8gJ091dGJvdW5kICcgOiAnSW5ib3VuZCAnKSArIFwiV2ViUlRDUGVlciBmcm9tICdTdHJlYW0nIHdpdGggaWQgW1wiICsgdGhpcy5zdHJlYW1JZCArICddIGlzIG5vdyBjbG9zZWQnKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgZGlzcG9zZU1lZGlhU3RyZWFtKCk6IHZvaWQge1xuICAgICAgICBpZiAodGhpcy5tZWRpYVN0cmVhbSkge1xuICAgICAgICAgICAgdGhpcy5tZWRpYVN0cmVhbS5nZXRBdWRpb1RyYWNrcygpLmZvckVhY2goKHRyYWNrKSA9PiB7XG4gICAgICAgICAgICAgICAgdHJhY2suc3RvcCgpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB0aGlzLm1lZGlhU3RyZWFtLmdldFZpZGVvVHJhY2tzKCkuZm9yRWFjaCgodHJhY2spID0+IHtcbiAgICAgICAgICAgICAgICB0cmFjay5zdG9wKCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGRlbGV0ZSB0aGlzLm1lZGlhU3RyZWFtO1xuICAgICAgICB9XG4gICAgICAgIGNvbnNvbGUuaW5mbygoISF0aGlzLm91dGJvdW5kU3RyZWFtT3B0cyA/ICdMb2NhbCAnIDogJ1JlbW90ZSAnKSArIFwiTWVkaWFTdHJlYW0gZnJvbSAnU3RyZWFtJyB3aXRoIGlkIFtcIiArIHRoaXMuc3RyZWFtSWQgKyAnXSBpcyBub3cgZGlzcG9zZWQnKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgZGlzcGxheU15UmVtb3RlKCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gdGhpcy5pc1N1YnNjcmliZVRvUmVtb3RlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBpc1NlbmRBdWRpbygpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuICghIXRoaXMub3V0Ym91bmRTdHJlYW1PcHRzICYmXG4gICAgICAgICAgICB0aGlzLm91dGJvdW5kU3RyZWFtT3B0cy5wdWJsaXNoZXJQcm9wZXJ0aWVzLmF1ZGlvU291cmNlICE9PSBudWxsICYmXG4gICAgICAgICAgICB0aGlzLm91dGJvdW5kU3RyZWFtT3B0cy5wdWJsaXNoZXJQcm9wZXJ0aWVzLmF1ZGlvU291cmNlICE9PSBmYWxzZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGlzU2VuZFZpZGVvKCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gKCEhdGhpcy5vdXRib3VuZFN0cmVhbU9wdHMgJiZcbiAgICAgICAgICAgIHRoaXMub3V0Ym91bmRTdHJlYW1PcHRzLnB1Ymxpc2hlclByb3BlcnRpZXMudmlkZW9Tb3VyY2UgIT09IG51bGwgJiZcbiAgICAgICAgICAgIHRoaXMub3V0Ym91bmRTdHJlYW1PcHRzLnB1Ymxpc2hlclByb3BlcnRpZXMudmlkZW9Tb3VyY2UgIT09IGZhbHNlKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgaXNTZW5kU2NyZWVuKCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gKCEhdGhpcy5vdXRib3VuZFN0cmVhbU9wdHMgJiZcbiAgICAgICAgICAgIHRoaXMub3V0Ym91bmRTdHJlYW1PcHRzLnB1Ymxpc2hlclByb3BlcnRpZXMudmlkZW9Tb3VyY2UgPT09ICdzY3JlZW4nKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgc2V0U3BlZWNoRXZlbnRJZk5vdEV4aXN0cygpOiB2b2lkIHtcbiAgICAgICAgaWYgKCF0aGlzLnNwZWVjaEV2ZW50KSB7XG4gICAgICAgICAgICBjb25zdCBoYXJrT3B0aW9ucyA9IHRoaXMuc2Vzc2lvbi5vcGVudmlkdS5hZHZhbmNlZENvbmZpZ3VyYXRpb24ucHVibGlzaGVyU3BlYWtpbmdFdmVudHNPcHRpb25zIHx8IHt9O1xuICAgICAgICAgICAgaGFya09wdGlvbnMuaW50ZXJ2YWwgPSAodHlwZW9mIGhhcmtPcHRpb25zLmludGVydmFsID09PSAnbnVtYmVyJykgPyBoYXJrT3B0aW9ucy5pbnRlcnZhbCA6IDUwO1xuICAgICAgICAgICAgaGFya09wdGlvbnMudGhyZXNob2xkID0gKHR5cGVvZiBoYXJrT3B0aW9ucy50aHJlc2hvbGQgPT09ICdudW1iZXInKSA/IGhhcmtPcHRpb25zLnRocmVzaG9sZCA6IC01MDtcblxuICAgICAgICAgICAgdGhpcy5zcGVlY2hFdmVudCA9IGhhcmsodGhpcy5tZWRpYVN0cmVhbSwgaGFya09wdGlvbnMpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGVuYWJsZVNwZWFraW5nRXZlbnRzKCk6IHZvaWQge1xuICAgICAgICB0aGlzLnNldFNwZWVjaEV2ZW50SWZOb3RFeGlzdHMoKTtcbiAgICAgICAgdGhpcy5zcGVlY2hFdmVudC5vbignc3BlYWtpbmcnLCAoKSA9PiB7XG4gICAgICAgICAgICB0aGlzLnNlc3Npb24uZW1pdEV2ZW50KCdwdWJsaXNoZXJTdGFydFNwZWFraW5nJywgW25ldyBQdWJsaXNoZXJTcGVha2luZ0V2ZW50KHRoaXMuc2Vzc2lvbiwgJ3B1Ymxpc2hlclN0YXJ0U3BlYWtpbmcnLCB0aGlzLmNvbm5lY3Rpb24sIHRoaXMuc3RyZWFtSWQpXSk7XG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLnNwZWVjaEV2ZW50Lm9uKCdzdG9wcGVkX3NwZWFraW5nJywgKCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5zZXNzaW9uLmVtaXRFdmVudCgncHVibGlzaGVyU3RvcFNwZWFraW5nJywgW25ldyBQdWJsaXNoZXJTcGVha2luZ0V2ZW50KHRoaXMuc2Vzc2lvbiwgJ3B1Ymxpc2hlclN0b3BTcGVha2luZycsIHRoaXMuY29ubmVjdGlvbiwgdGhpcy5zdHJlYW1JZCldKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGVuYWJsZU9uY2VTcGVha2luZ0V2ZW50cygpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5zZXRTcGVlY2hFdmVudElmTm90RXhpc3RzKCk7XG4gICAgICAgIHRoaXMuc3BlZWNoRXZlbnQub24oJ3NwZWFraW5nJywgKCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5zZXNzaW9uLmVtaXRFdmVudCgncHVibGlzaGVyU3RhcnRTcGVha2luZycsIFtuZXcgUHVibGlzaGVyU3BlYWtpbmdFdmVudCh0aGlzLnNlc3Npb24sICdwdWJsaXNoZXJTdGFydFNwZWFraW5nJywgdGhpcy5jb25uZWN0aW9uLCB0aGlzLnN0cmVhbUlkKV0pO1xuICAgICAgICAgICAgdGhpcy5kaXNhYmxlU3BlYWtpbmdFdmVudHMoKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMuc3BlZWNoRXZlbnQub24oJ3N0b3BwZWRfc3BlYWtpbmcnLCAoKSA9PiB7XG4gICAgICAgICAgICB0aGlzLnNlc3Npb24uZW1pdEV2ZW50KCdwdWJsaXNoZXJTdG9wU3BlYWtpbmcnLCBbbmV3IFB1Ymxpc2hlclNwZWFraW5nRXZlbnQodGhpcy5zZXNzaW9uLCAncHVibGlzaGVyU3RvcFNwZWFraW5nJywgdGhpcy5jb25uZWN0aW9uLCB0aGlzLnN0cmVhbUlkKV0pO1xuICAgICAgICAgICAgdGhpcy5kaXNhYmxlU3BlYWtpbmdFdmVudHMoKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGRpc2FibGVTcGVha2luZ0V2ZW50cygpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5zcGVlY2hFdmVudC5zdG9wKCk7XG4gICAgICAgIHRoaXMuc3BlZWNoRXZlbnQgPSB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGlzTG9jYWwoKTogYm9vbGVhbiB7XG4gICAgICAgIC8vIGluYm91bmQgb3B0aW9ucyB1bmRlZmluZWQgYW5kIG91dGJvdW5kIG9wdGlvbnMgZGVmaW5lZFxuICAgICAgICByZXR1cm4gKCF0aGlzLmluYm91bmRTdHJlYW1PcHRzICYmICEhdGhpcy5vdXRib3VuZFN0cmVhbU9wdHMpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBnZXRTZWxlY3RlZEljZUNhbmRpZGF0ZSgpOiBQcm9taXNlPGFueT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgdGhpcy53ZWJSdGNTdGF0cy5nZXRTZWxlY3RlZEljZUNhbmRpZGF0ZUluZm8oKVxuICAgICAgICAgICAgICAgIC50aGVuKHJlcG9ydCA9PiByZXNvbHZlKHJlcG9ydCkpXG4gICAgICAgICAgICAgICAgLmNhdGNoKGVycm9yID0+IHJlamVjdChlcnJvcikpO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgZ2V0UmVtb3RlSWNlQ2FuZGlkYXRlTGlzdCgpOiBSVENJY2VDYW5kaWRhdGVbXSB7XG4gICAgICAgIHJldHVybiB0aGlzLndlYlJ0Y1BlZXIucmVtb3RlQ2FuZGlkYXRlc1F1ZXVlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBnZXRMb2NhbEljZUNhbmRpZGF0ZUxpc3QoKTogUlRDSWNlQ2FuZGlkYXRlW10ge1xuICAgICAgICByZXR1cm4gdGhpcy53ZWJSdGNQZWVyLmxvY2FsQ2FuZGlkYXRlc1F1ZXVlO1xuICAgIH1cblxuICAgIC8qIFByaXZhdGUgbWV0aG9kcyAqL1xuXG4gICAgcHJpdmF0ZSBpbml0V2ViUnRjUGVlclNlbmQoKTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcblxuICAgICAgICAgICAgY29uc3QgdXNlck1lZGlhQ29uc3RyYWludHMgPSB7XG4gICAgICAgICAgICAgICAgYXVkaW86IHRoaXMuaXNTZW5kQXVkaW8oKSxcbiAgICAgICAgICAgICAgICB2aWRlbzogdGhpcy5pc1NlbmRWaWRlbygpXG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICBjb25zdCBvcHRpb25zID0ge1xuICAgICAgICAgICAgICAgIG1lZGlhU3RyZWFtOiB0aGlzLm1lZGlhU3RyZWFtLFxuICAgICAgICAgICAgICAgIG1lZGlhQ29uc3RyYWludHM6IHVzZXJNZWRpYUNvbnN0cmFpbnRzLFxuICAgICAgICAgICAgICAgIG9uaWNlY2FuZGlkYXRlOiB0aGlzLmNvbm5lY3Rpb24uc2VuZEljZUNhbmRpZGF0ZS5iaW5kKHRoaXMuY29ubmVjdGlvbiksXG4gICAgICAgICAgICAgICAgaWNlU2VydmVyczogdGhpcy5nZXRJY2VTZXJ2ZXJzQ29uZigpLFxuICAgICAgICAgICAgICAgIHNpbXVsY2FzdDogZmFsc2VcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIGNvbnN0IHN1Y2Nlc3NDYWxsYmFjayA9IChzZHBPZmZlclBhcmFtKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5kZWJ1ZygnU2VuZGluZyBTRFAgb2ZmZXIgdG8gcHVibGlzaCBhcyAnXG4gICAgICAgICAgICAgICAgICAgICsgdGhpcy5zdHJlYW1JZCwgc2RwT2ZmZXJQYXJhbSk7XG5cbiAgICAgICAgICAgICAgICBsZXQgdHlwZU9mVmlkZW8gPSAnJztcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5pc1NlbmRWaWRlbygpKSB7XG4gICAgICAgICAgICAgICAgICAgIHR5cGVPZlZpZGVvID0gdGhpcy5vdXRib3VuZFN0cmVhbU9wdHMucHVibGlzaGVyUHJvcGVydGllcy52aWRlb1NvdXJjZSBpbnN0YW5jZW9mIE1lZGlhU3RyZWFtVHJhY2sgPyAnQ1VTVE9NJyA6ICh0aGlzLmlzU2VuZFNjcmVlbigpID8gJ1NDUkVFTicgOiAnQ0FNRVJBJyk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdGhpcy5zZXNzaW9uLm9wZW52aWR1LnNlbmRSZXF1ZXN0KCdwdWJsaXNoVmlkZW8nLCB7XG4gICAgICAgICAgICAgICAgICAgIHNkcE9mZmVyOiBzZHBPZmZlclBhcmFtLFxuICAgICAgICAgICAgICAgICAgICBkb0xvb3BiYWNrOiB0aGlzLmRpc3BsYXlNeVJlbW90ZSgpIHx8IGZhbHNlLFxuICAgICAgICAgICAgICAgICAgICBoYXNBdWRpbzogdGhpcy5pc1NlbmRBdWRpbygpLFxuICAgICAgICAgICAgICAgICAgICBoYXNWaWRlbzogdGhpcy5pc1NlbmRWaWRlbygpLFxuICAgICAgICAgICAgICAgICAgICBhdWRpb0FjdGl2ZTogdGhpcy5hdWRpb0FjdGl2ZSxcbiAgICAgICAgICAgICAgICAgICAgdmlkZW9BY3RpdmU6IHRoaXMudmlkZW9BY3RpdmUsXG4gICAgICAgICAgICAgICAgICAgIHR5cGVPZlZpZGVvLFxuICAgICAgICAgICAgICAgICAgICBmcmFtZVJhdGU6ICEhdGhpcy5mcmFtZVJhdGUgPyB0aGlzLmZyYW1lUmF0ZSA6IC0xLFxuICAgICAgICAgICAgICAgICAgICB2aWRlb0RpbWVuc2lvbnM6IEpTT04uc3RyaW5naWZ5KHRoaXMudmlkZW9EaW1lbnNpb25zKVxuICAgICAgICAgICAgICAgIH0sIChlcnJvciwgcmVzcG9uc2UpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZXJyb3IuY29kZSA9PT0gNDAxKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KG5ldyBPcGVuVmlkdUVycm9yKE9wZW5WaWR1RXJyb3JOYW1lLk9QRU5WSURVX1BFUk1JU1NJT05fREVOSUVELCBcIllvdSBkb24ndCBoYXZlIHBlcm1pc3Npb25zIHRvIHB1Ymxpc2hcIikpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWplY3QoJ0Vycm9yIG9uIHB1Ymxpc2hWaWRlbzogJyArIEpTT04uc3RyaW5naWZ5KGVycm9yKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLndlYlJ0Y1BlZXIucHJvY2Vzc0Fuc3dlcihyZXNwb25zZS5zZHBBbnN3ZXIpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbUlkID0gcmVzcG9uc2UuaWQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuaXNMb2NhbFN0cmVhbVB1Ymxpc2hlZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucHVibGlzaGVkT25jZSA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLmRpc3BsYXlNeVJlbW90ZSgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnJlbW90ZVBlZXJTdWNjZXNzZnVsbHlFc3RhYmxpc2hlZCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdzdHJlYW0tY3JlYXRlZC1ieS1wdWJsaXNoZXInKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5pbml0V2ViUnRjU3RhdHMoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbyhcIidQdWJsaXNoZXInIHN1Y2Nlc3NmdWxseSBwdWJsaXNoZWQgdG8gc2Vzc2lvblwiKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgaWYgKHRoaXMuZGlzcGxheU15UmVtb3RlKCkpIHtcbiAgICAgICAgICAgICAgICB0aGlzLndlYlJ0Y1BlZXIgPSBuZXcgV2ViUnRjUGVlclNlbmRyZWN2KG9wdGlvbnMpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLndlYlJ0Y1BlZXIgPSBuZXcgV2ViUnRjUGVlclNlbmRvbmx5KG9wdGlvbnMpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy53ZWJSdGNQZWVyLmdlbmVyYXRlT2ZmZXIoKS50aGVuKG9mZmVyID0+IHtcbiAgICAgICAgICAgICAgICBzdWNjZXNzQ2FsbGJhY2sob2ZmZXIpO1xuICAgICAgICAgICAgfSkuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgIHJlamVjdChuZXcgRXJyb3IoJyhwdWJsaXNoKSBTRFAgb2ZmZXIgZXJyb3I6ICcgKyBKU09OLnN0cmluZ2lmeShlcnJvcikpKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGluaXRXZWJSdGNQZWVyUmVjZWl2ZSgpOiBQcm9taXNlPGFueT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuXG4gICAgICAgICAgICBjb25zdCBvZmZlckNvbnN0cmFpbnRzID0ge1xuICAgICAgICAgICAgICAgIGF1ZGlvOiB0aGlzLmluYm91bmRTdHJlYW1PcHRzLmhhc0F1ZGlvLFxuICAgICAgICAgICAgICAgIHZpZGVvOiB0aGlzLmluYm91bmRTdHJlYW1PcHRzLmhhc1ZpZGVvXG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgY29uc29sZS5kZWJ1ZyhcIidTZXNzaW9uLnN1YnNjcmliZShTdHJlYW0pJyBjYWxsZWQuIENvbnN0cmFpbnRzIG9mIGdlbmVyYXRlIFNEUCBvZmZlclwiLFxuICAgICAgICAgICAgICAgIG9mZmVyQ29uc3RyYWludHMpO1xuICAgICAgICAgICAgY29uc3Qgb3B0aW9ucyA9IHtcbiAgICAgICAgICAgICAgICBvbmljZWNhbmRpZGF0ZTogdGhpcy5jb25uZWN0aW9uLnNlbmRJY2VDYW5kaWRhdGUuYmluZCh0aGlzLmNvbm5lY3Rpb24pLFxuICAgICAgICAgICAgICAgIG1lZGlhQ29uc3RyYWludHM6IG9mZmVyQ29uc3RyYWludHMsXG4gICAgICAgICAgICAgICAgaWNlU2VydmVyczogdGhpcy5nZXRJY2VTZXJ2ZXJzQ29uZigpLFxuICAgICAgICAgICAgICAgIHNpbXVsY2FzdDogZmFsc2VcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIGNvbnN0IHN1Y2Nlc3NDYWxsYmFjayA9IChzZHBPZmZlclBhcmFtKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5kZWJ1ZygnU2VuZGluZyBTRFAgb2ZmZXIgdG8gc3Vic2NyaWJlIHRvICdcbiAgICAgICAgICAgICAgICAgICAgKyB0aGlzLnN0cmVhbUlkLCBzZHBPZmZlclBhcmFtKTtcbiAgICAgICAgICAgICAgICB0aGlzLnNlc3Npb24ub3BlbnZpZHUuc2VuZFJlcXVlc3QoJ3JlY2VpdmVWaWRlb0Zyb20nLCB7XG4gICAgICAgICAgICAgICAgICAgIHNlbmRlcjogdGhpcy5zdHJlYW1JZCxcbiAgICAgICAgICAgICAgICAgICAgc2RwT2ZmZXI6IHNkcE9mZmVyUGFyYW1cbiAgICAgICAgICAgICAgICB9LCAoZXJyb3IsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KG5ldyBFcnJvcignRXJyb3Igb24gcmVjdlZpZGVvRnJvbTogJyArIEpTT04uc3RyaW5naWZ5KGVycm9yKSkpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy53ZWJSdGNQZWVyLnByb2Nlc3NBbnN3ZXIocmVzcG9uc2Uuc2RwQW5zd2VyKS50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnJlbW90ZVBlZXJTdWNjZXNzZnVsbHlFc3RhYmxpc2hlZCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuaW5pdFdlYlJ0Y1N0YXRzKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSkuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgdGhpcy53ZWJSdGNQZWVyID0gbmV3IFdlYlJ0Y1BlZXJSZWN2b25seShvcHRpb25zKTtcbiAgICAgICAgICAgIHRoaXMud2ViUnRjUGVlci5nZW5lcmF0ZU9mZmVyKClcbiAgICAgICAgICAgICAgICAudGhlbihvZmZlciA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHN1Y2Nlc3NDYWxsYmFjayhvZmZlcik7XG4gICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgICAgICByZWplY3QobmV3IEVycm9yKCcoc3Vic2NyaWJlKSBTRFAgb2ZmZXIgZXJyb3I6ICcgKyBKU09OLnN0cmluZ2lmeShlcnJvcikpKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSByZW1vdGVQZWVyU3VjY2Vzc2Z1bGx5RXN0YWJsaXNoZWQoKTogdm9pZCB7XG4gICAgICAgIHRoaXMubWVkaWFTdHJlYW0gPSB0aGlzLndlYlJ0Y1BlZXIucGMuZ2V0UmVtb3RlU3RyZWFtcygpWzBdO1xuICAgICAgICBjb25zb2xlLmRlYnVnKCdQZWVyIHJlbW90ZSBzdHJlYW0nLCB0aGlzLm1lZGlhU3RyZWFtKTtcblxuICAgICAgICBpZiAoISF0aGlzLm1lZGlhU3RyZWFtKSB7XG4gICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnbWVkaWFzdHJlYW0tdXBkYXRlZCcpO1xuICAgICAgICAgICAgaWYgKCF0aGlzLmRpc3BsYXlNeVJlbW90ZSgpICYmICEhdGhpcy5tZWRpYVN0cmVhbS5nZXRBdWRpb1RyYWNrcygpWzBdICYmIHRoaXMuc2Vzc2lvbi5zcGVha2luZ0V2ZW50c0VuYWJsZWQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVuYWJsZVNwZWFraW5nRXZlbnRzKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIGluaXRXZWJSdGNTdGF0cygpOiB2b2lkIHtcbiAgICAgICAgdGhpcy53ZWJSdGNTdGF0cyA9IG5ldyBXZWJSdGNTdGF0cyh0aGlzKTtcbiAgICAgICAgdGhpcy53ZWJSdGNTdGF0cy5pbml0V2ViUnRjU3RhdHMoKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIHN0b3BXZWJSdGNTdGF0cygpOiB2b2lkIHtcbiAgICAgICAgaWYgKCEhdGhpcy53ZWJSdGNTdGF0cyAmJiB0aGlzLndlYlJ0Y1N0YXRzLmlzRW5hYmxlZCgpKSB7XG4gICAgICAgICAgICB0aGlzLndlYlJ0Y1N0YXRzLnN0b3BXZWJSdGNTdGF0cygpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBnZXRJY2VTZXJ2ZXJzQ29uZigpOiBSVENJY2VTZXJ2ZXJbXSB8IHVuZGVmaW5lZCB7XG4gICAgICAgIGxldCByZXR1cm5WYWx1ZTtcbiAgICAgICAgaWYgKCEhdGhpcy5zZXNzaW9uLm9wZW52aWR1LmFkdmFuY2VkQ29uZmlndXJhdGlvbi5pY2VTZXJ2ZXJzKSB7XG4gICAgICAgICAgICByZXR1cm5WYWx1ZSA9IHRoaXMuc2Vzc2lvbi5vcGVudmlkdS5hZHZhbmNlZENvbmZpZ3VyYXRpb24uaWNlU2VydmVycyA9PT0gJ2ZyZWVpY2UnID9cbiAgICAgICAgICAgICAgICB1bmRlZmluZWQgOlxuICAgICAgICAgICAgICAgIHRoaXMuc2Vzc2lvbi5vcGVudmlkdS5hZHZhbmNlZENvbmZpZ3VyYXRpb24uaWNlU2VydmVycztcbiAgICAgICAgfSBlbHNlIGlmICh0aGlzLnNlc3Npb24ub3BlbnZpZHUuaWNlU2VydmVycykge1xuICAgICAgICAgICAgcmV0dXJuVmFsdWUgPSB0aGlzLnNlc3Npb24ub3BlbnZpZHUuaWNlU2VydmVycztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVyblZhbHVlID0gdW5kZWZpbmVkO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZXR1cm5WYWx1ZTtcbiAgICB9XG5cbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IFN0cmVhbSB9IGZyb20gJy4vU3RyZWFtJztcbmltcG9ydCB7IEV2ZW50RGlzcGF0Y2hlciB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvSW50ZXJmYWNlcy9QdWJsaWMvRXZlbnREaXNwYXRjaGVyJztcbmltcG9ydCB7IFN0cmVhbU1hbmFnZXJWaWRlbyB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvSW50ZXJmYWNlcy9QdWJsaWMvU3RyZWFtTWFuYWdlclZpZGVvJztcbmltcG9ydCB7IEV2ZW50IH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvRXZlbnQnO1xuaW1wb3J0IHsgU3RyZWFtTWFuYWdlckV2ZW50IH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvU3RyZWFtTWFuYWdlckV2ZW50JztcbmltcG9ydCB7IFZpZGVvRWxlbWVudEV2ZW50IH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvVmlkZW9FbGVtZW50RXZlbnQnO1xuaW1wb3J0IHsgVmlkZW9JbnNlcnRNb2RlIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FbnVtcy9WaWRlb0luc2VydE1vZGUnO1xuXG5pbXBvcnQgRXZlbnRFbWl0dGVyID0gcmVxdWlyZSgnd29sZnk4Ny1ldmVudGVtaXR0ZXInKTtcblxuXG4vKipcbiAqIEludGVyZmFjZSBpbiBjaGFyZ2Ugb2YgZGlzcGxheWluZyB0aGUgbWVkaWEgc3RyZWFtcyBpbiB0aGUgSFRNTCBET00uIFRoaXMgd3JhcHMgYW55IFtbUHVibGlzaGVyXV0gYW5kIFtbU3Vic2NyaWJlcl1dIG9iamVjdC5cbiAqIFlvdSBjYW4gaW5zZXJ0IGFzIG1hbnkgdmlkZW8gcGxheWVycyBmbyB0aGUgc2FtZSBTdHJlYW0gYXMgeW91IHdhbnQgYnkgY2FsbGluZyBbW1N0cmVhbU1hbmFnZXIuYWRkVmlkZW9FbGVtZW50XV0gb3JcbiAqIFtbU3RyZWFtTWFuYWdlci5jcmVhdGVWaWRlb0VsZW1lbnRdXS5cbiAqXG4gKiBUaGUgdXNlIG9mIFN0cmVhbU1hbmFnZXIgd3JhcHBlciBpcyBwYXJ0aWN1bGFybHkgdXNlZnVsIHdoZW4geW91IGRvbid0IG5lZWQgdG8gZGlmZmVyZW50aWF0ZSBiZXR3ZWVuIFB1Ymxpc2hlciBvciBTdWJzY3JpYmVyIHN0cmVhbXMgb3IganVzdFxuICogd2FudCB0byBkaXJlY3RseSBtYW5hZ2UgeW91ciBvd24gdmlkZW8gZWxlbWVudHMgKGV2ZW4gbW9yZSB0aGFuIG9uZSB2aWRlbyBlbGVtZW50IHBlciBTdHJlYW0pLiBUaGlzIHNjZW5hcmlvIGlzIHByZXR0eSBjb21tb24gaW5cbiAqIGRlY2xhcmF0aXZlLCBNVkMgZnJvbnRlbmQgZnJhbWV3b3JrcyBzdWNoIGFzIEFuZ3VsYXIsIFJlYWN0IG9yIFZ1ZS5qc1xuICovXG5leHBvcnQgY2xhc3MgU3RyZWFtTWFuYWdlciBpbXBsZW1lbnRzIEV2ZW50RGlzcGF0Y2hlciB7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgU3RyZWFtIHJlcHJlc2VudGVkIGluIHRoZSBET00gYnkgdGhlIFB1Ymxpc2hlci9TdWJzY3JpYmVyXG4gICAgICovXG4gICAgc3RyZWFtOiBTdHJlYW07XG5cbiAgICAvKipcbiAgICAgKiBBbGwgdGhlIHZpZGVvcyBkaXNwbGF5aW5nIHRoZSBTdHJlYW0gb2YgdGhpcyBQdWJsaXNoZXIvU3Vic2NyaWJlclxuICAgICAqL1xuICAgIHZpZGVvczogU3RyZWFtTWFuYWdlclZpZGVvW10gPSBbXTtcblxuICAgIC8qKlxuICAgICAqIFdoZXRoZXIgdGhlIFN0cmVhbSByZXByZXNlbnRlZCBpbiB0aGUgRE9NIGlzIGxvY2FsIG9yIHJlbW90ZVxuICAgICAqIC0gYGZhbHNlYCBmb3IgW1tQdWJsaXNoZXJdXVxuICAgICAqIC0gYHRydWVgIGZvciBbW1N1YnNjcmliZXJdXVxuICAgICAqL1xuICAgIHJlbW90ZTogYm9vbGVhbjtcblxuICAgIC8qKlxuICAgICAqIFRoZSBET00gSFRNTEVsZW1lbnQgYXNzaWduZWQgYXMgdGFyZ2V0IGVsZW1lbnQgd2hlbiBjcmVhdGluZyB0aGUgdmlkZW8gZm9yIHRoZSBQdWJsaXNoZXIvU3Vic2NyaWJlci4gVGhpcyBwcm9wZXJ0eSBpcyBvbmx5IGRlZmluZWQgaWY6XG4gICAgICogLSBbW1B1Ymxpc2hlcl1dIGhhcyBiZWVuIGluaXRpYWxpemVkIGJ5IGNhbGxpbmcgbWV0aG9kIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dIHdpdGggYSB2YWxpZCBgdGFyZ2V0RWxlbWVudGAgcGFyYW1ldGVyXG4gICAgICogLSBbW1N1YnNjcmliZXJdXSBoYXMgYmVlbiBpbml0aWFsaXplZCBieSBjYWxsaW5nIG1ldGhvZCBbW1Nlc3Npb24uc3Vic2NyaWJlXV0gd2l0aCBhIHZhbGlkIGB0YXJnZXRFbGVtZW50YCBwYXJhbWV0ZXJcbiAgICAgKi9cbiAgICB0YXJnZXRFbGVtZW50OiBIVE1MRWxlbWVudDtcblxuICAgIC8qKlxuICAgICAqIGBpZGAgYXR0cmlidXRlIG9mIHRoZSBET00gdmlkZW8gZWxlbWVudCBkaXNwbGF5aW5nIHRoZSBQdWJsaXNoZXIvU3Vic2NyaWJlcidzIHN0cmVhbS4gVGhpcyBwcm9wZXJ0eSBpcyBvbmx5IGRlZmluZWQgaWY6XG4gICAgICogLSBbW1B1Ymxpc2hlcl1dIGhhcyBiZWVuIGluaXRpYWxpemVkIGJ5IGNhbGxpbmcgbWV0aG9kIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dIHdpdGggYSB2YWxpZCBgdGFyZ2V0RWxlbWVudGAgcGFyYW1ldGVyXG4gICAgICogLSBbW1N1YnNjcmliZXJdXSBoYXMgYmVlbiBpbml0aWFsaXplZCBieSBjYWxsaW5nIG1ldGhvZCBbW1Nlc3Npb24uc3Vic2NyaWJlXV0gd2l0aCBhIHZhbGlkIGB0YXJnZXRFbGVtZW50YCBwYXJhbWV0ZXJcbiAgICAgKi9cbiAgICBpZDogc3RyaW5nO1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGZpcnN0VmlkZW9FbGVtZW50OiBTdHJlYW1NYW5hZ2VyVmlkZW87XG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGxhenlMYXVuY2hWaWRlb0VsZW1lbnRDcmVhdGVkRXZlbnQgPSBmYWxzZTtcbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgZWxlbWVudDogSFRNTEVsZW1lbnQ7XG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHByb3RlY3RlZCBlZSA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgcHJvdGVjdGVkIGNhblBsYXlMaXN0ZW5lcjogRXZlbnRMaXN0ZW5lck9yRXZlbnRMaXN0ZW5lck9iamVjdDtcblxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHN0cmVhbTogU3RyZWFtLCB0YXJnZXRFbGVtZW50PzogSFRNTEVsZW1lbnQgfCBzdHJpbmcpIHtcbiAgICAgICAgdGhpcy5zdHJlYW0gPSBzdHJlYW07XG4gICAgICAgIHRoaXMuc3RyZWFtLnN0cmVhbU1hbmFnZXIgPSB0aGlzO1xuICAgICAgICB0aGlzLnJlbW90ZSA9ICF0aGlzLnN0cmVhbS5pc0xvY2FsKCk7XG5cbiAgICAgICAgaWYgKCEhdGFyZ2V0RWxlbWVudCkge1xuICAgICAgICAgICAgbGV0IHRhcmdFbDtcbiAgICAgICAgICAgIGlmICh0eXBlb2YgdGFyZ2V0RWxlbWVudCA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgICAgICB0YXJnRWwgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCh0YXJnZXRFbGVtZW50KTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAodGFyZ2V0RWxlbWVudCBpbnN0YW5jZW9mIEhUTUxFbGVtZW50KSB7XG4gICAgICAgICAgICAgICAgdGFyZ0VsID0gdGFyZ2V0RWxlbWVudDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKCEhdGFyZ0VsKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5maXJzdFZpZGVvRWxlbWVudCA9IHtcbiAgICAgICAgICAgICAgICAgICAgdGFyZ2V0RWxlbWVudDogdGFyZ0VsLFxuICAgICAgICAgICAgICAgICAgICB2aWRlbzogZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgndmlkZW8nKSxcbiAgICAgICAgICAgICAgICAgICAgaWQ6ICcnXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB0aGlzLnRhcmdldEVsZW1lbnQgPSB0YXJnRWw7XG4gICAgICAgICAgICAgICAgdGhpcy5lbGVtZW50ID0gdGFyZ0VsO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHRoaXMuY2FuUGxheUxpc3RlbmVyID0gKCkgPT4ge1xuICAgICAgICAgICAgaWYgKHRoaXMuc3RyZWFtLmlzTG9jYWwoKSkge1xuICAgICAgICAgICAgICAgIGlmICghdGhpcy5zdHJlYW0uZGlzcGxheU15UmVtb3RlKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS5pbmZvKFwiWW91ciBsb2NhbCAnU3RyZWFtJyB3aXRoIGlkIFtcIiArIHRoaXMuc3RyZWFtLnN0cmVhbUlkICsgJ10gdmlkZW8gaXMgbm93IHBsYXlpbmcnKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3ZpZGVvUGxheWluZycsIFtuZXcgVmlkZW9FbGVtZW50RXZlbnQodGhpcy52aWRlb3NbMF0udmlkZW8sIHRoaXMsICd2aWRlb1BsYXlpbmcnKV0pO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbyhcIllvdXIgb3duIHJlbW90ZSAnU3RyZWFtJyB3aXRoIGlkIFtcIiArIHRoaXMuc3RyZWFtLnN0cmVhbUlkICsgJ10gdmlkZW8gaXMgbm93IHBsYXlpbmcnKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3JlbW90ZVZpZGVvUGxheWluZycsIFtuZXcgVmlkZW9FbGVtZW50RXZlbnQodGhpcy52aWRlb3NbMF0udmlkZW8sIHRoaXMsICdyZW1vdGVWaWRlb1BsYXlpbmcnKV0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5pbmZvKFwiUmVtb3RlICdTdHJlYW0nIHdpdGggaWQgW1wiICsgdGhpcy5zdHJlYW0uc3RyZWFtSWQgKyAnXSB2aWRlbyBpcyBub3cgcGxheWluZycpO1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCd2aWRlb1BsYXlpbmcnLCBbbmV3IFZpZGVvRWxlbWVudEV2ZW50KHRoaXMudmlkZW9zWzBdLnZpZGVvLCB0aGlzLCAndmlkZW9QbGF5aW5nJyldKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdzdHJlYW1QbGF5aW5nJywgW25ldyBTdHJlYW1NYW5hZ2VyRXZlbnQodGhpcyldKTtcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZWUgW1tFdmVudERpc3BhdGNoZXIub25dXVxuICAgICAqL1xuICAgIG9uKHR5cGU6IHN0cmluZywgaGFuZGxlcjogKGV2ZW50OiBFdmVudCkgPT4gdm9pZCk6IEV2ZW50RGlzcGF0Y2hlciB7XG4gICAgICAgIHRoaXMuZWUub24odHlwZSwgZXZlbnQgPT4ge1xuICAgICAgICAgICAgaWYgKGV2ZW50KSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5pbmZvKFwiRXZlbnQgJ1wiICsgdHlwZSArIFwiJyB0cmlnZ2VyZWQgYnkgJ1wiICsgKHRoaXMucmVtb3RlID8gJ1N1YnNjcmliZXInIDogJ1B1Ymxpc2hlcicpICsgXCInXCIsIGV2ZW50KTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5pbmZvKFwiRXZlbnQgJ1wiICsgdHlwZSArIFwiJyB0cmlnZ2VyZWQgYnkgJ1wiICsgKHRoaXMucmVtb3RlID8gJ1N1YnNjcmliZXInIDogJ1B1Ymxpc2hlcicpICsgXCInXCIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaGFuZGxlcihldmVudCk7XG4gICAgICAgIH0pO1xuICAgICAgICBpZiAodHlwZSA9PT0gJ3ZpZGVvRWxlbWVudENyZWF0ZWQnKSB7XG4gICAgICAgICAgICBpZiAoISF0aGlzLnN0cmVhbSAmJiB0aGlzLmxhenlMYXVuY2hWaWRlb0VsZW1lbnRDcmVhdGVkRXZlbnQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgndmlkZW9FbGVtZW50Q3JlYXRlZCcsIFtuZXcgVmlkZW9FbGVtZW50RXZlbnQodGhpcy52aWRlb3NbMF0udmlkZW8sIHRoaXMsICd2aWRlb0VsZW1lbnRDcmVhdGVkJyldKTtcbiAgICAgICAgICAgICAgICB0aGlzLmxhenlMYXVuY2hWaWRlb0VsZW1lbnRDcmVhdGVkRXZlbnQgPSBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAodHlwZSA9PT0gJ3N0cmVhbVBsYXlpbmcnIHx8IHR5cGUgPT09ICd2aWRlb1BsYXlpbmcnKSB7XG4gICAgICAgICAgICBpZiAodGhpcy52aWRlb3NbMF0gJiYgdGhpcy52aWRlb3NbMF0udmlkZW8gJiZcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvc1swXS52aWRlby5jdXJyZW50VGltZSA+IDAgJiZcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvc1swXS52aWRlby5wYXVzZWQgPT09IGZhbHNlICYmXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8uZW5kZWQgPT09IGZhbHNlICYmXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8ucmVhZHlTdGF0ZSA9PT0gNCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdzdHJlYW1QbGF5aW5nJywgW25ldyBTdHJlYW1NYW5hZ2VyRXZlbnQodGhpcyldKTtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgndmlkZW9QbGF5aW5nJywgW25ldyBWaWRlb0VsZW1lbnRFdmVudCh0aGlzLnZpZGVvc1swXS52aWRlbywgdGhpcywgJ3ZpZGVvUGxheWluZycpXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2VlIFtbRXZlbnREaXNwYXRjaGVyLm9uY2VdXVxuICAgICAqL1xuICAgIG9uY2UodHlwZTogc3RyaW5nLCBoYW5kbGVyOiAoZXZlbnQ6IEV2ZW50KSA9PiB2b2lkKTogU3RyZWFtTWFuYWdlciB7XG4gICAgICAgIHRoaXMuZWUub25jZSh0eXBlLCBldmVudCA9PiB7XG4gICAgICAgICAgICBpZiAoZXZlbnQpIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oXCJFdmVudCAnXCIgKyB0eXBlICsgXCInIHRyaWdnZXJlZCBvbmNlXCIsIGV2ZW50KTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5pbmZvKFwiRXZlbnQgJ1wiICsgdHlwZSArIFwiJyB0cmlnZ2VyZWQgb25jZVwiKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGhhbmRsZXIoZXZlbnQpO1xuICAgICAgICB9KTtcbiAgICAgICAgaWYgKHR5cGUgPT09ICd2aWRlb0VsZW1lbnRDcmVhdGVkJykge1xuICAgICAgICAgICAgaWYgKCEhdGhpcy5zdHJlYW0gJiYgdGhpcy5sYXp5TGF1bmNoVmlkZW9FbGVtZW50Q3JlYXRlZEV2ZW50KSB7XG4gICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3ZpZGVvRWxlbWVudENyZWF0ZWQnLCBbbmV3IFZpZGVvRWxlbWVudEV2ZW50KHRoaXMudmlkZW9zWzBdLnZpZGVvLCB0aGlzLCAndmlkZW9FbGVtZW50Q3JlYXRlZCcpXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHR5cGUgPT09ICdzdHJlYW1QbGF5aW5nJyB8fCB0eXBlID09PSAndmlkZW9QbGF5aW5nJykge1xuICAgICAgICAgICAgaWYgKHRoaXMudmlkZW9zWzBdICYmIHRoaXMudmlkZW9zWzBdLnZpZGVvICYmXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8uY3VycmVudFRpbWUgPiAwICYmXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8ucGF1c2VkID09PSBmYWxzZSAmJlxuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9zWzBdLnZpZGVvLmVuZGVkID09PSBmYWxzZSAmJlxuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9zWzBdLnZpZGVvLnJlYWR5U3RhdGUgPT09IDQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnc3RyZWFtUGxheWluZycsIFtuZXcgU3RyZWFtTWFuYWdlckV2ZW50KHRoaXMpXSk7XG4gICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3ZpZGVvUGxheWluZycsIFtuZXcgVmlkZW9FbGVtZW50RXZlbnQodGhpcy52aWRlb3NbMF0udmlkZW8sIHRoaXMsICd2aWRlb1BsYXlpbmcnKV0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNlZSBbW0V2ZW50RGlzcGF0Y2hlci5vZmZdXVxuICAgICAqL1xuICAgIG9mZih0eXBlOiBzdHJpbmcsIGhhbmRsZXI/OiAoZXZlbnQ6IEV2ZW50KSA9PiB2b2lkKTogU3RyZWFtTWFuYWdlciB7XG4gICAgICAgIGlmICghaGFuZGxlcikge1xuICAgICAgICAgICAgdGhpcy5lZS5yZW1vdmVBbGxMaXN0ZW5lcnModHlwZSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLmVlLm9mZih0eXBlLCBoYW5kbGVyKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBNYWtlcyBgdmlkZW9gIGVsZW1lbnQgcGFyYW1ldGVyIGRpc3BsYXkgdGhpcyBbW3N0cmVhbV1dLiBUaGlzIGlzIHVzZWZ1bCB3aGVuIHlvdSBhcmVcbiAgICAgKiBbbWFuYWdpbmcgdGhlIHZpZGVvIGVsZW1lbnRzIG9uIHlvdXIgb3duXSgvZG9jcy9ob3ctZG8taS9tYW5hZ2UtdmlkZW9zLyN5b3UtdGFrZS1jYXJlLW9mLXRoZS12aWRlby1wbGF5ZXJzKVxuICAgICAqXG4gICAgICogQ2FsbGluZyB0aGlzIG1ldGhvZCB3aXRoIGEgdmlkZW8gYWxyZWFkeSBhZGRlZCB0byBvdGhlciBQdWJsaXNoZXIvU3Vic2NyaWJlciB3aWxsIGNhdXNlIHRoZSB2aWRlbyBlbGVtZW50IHRvIGJlXG4gICAgICogZGlzYXNzb2NpYXRlZCBmcm9tIHRoYXQgcHJldmlvdXMgUHVibGlzaGVyL1N1YnNjcmliZXIgYW5kIHRvIGJlIGFzc29jaWF0ZWQgdG8gdGhpcyBvbmUuXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyAxIGlmIHRoZSB2aWRlbyB3YXNuJ3QgYXNzb2NpYXRlZCB0byBhbnkgb3RoZXIgUHVibGlzaGVyL1N1YnNjcmliZXIgYW5kIGhhcyBiZWVuIHN1Y2Nlc3NmdWxseSBhZGRlZCB0byB0aGlzIG9uZS5cbiAgICAgKiAwIGlmIHRoZSB2aWRlbyB3YXMgYWxyZWFkeSBhZGRlZCB0byB0aGlzIFB1Ymxpc2hlci9TdWJzY3JpYmVyLiAtMSBpZiB0aGUgdmlkZW8gd2FzIHByZXZpb3VzbHkgYXNzb2NpYXRlZCB0byBhbnkgb3RoZXJcbiAgICAgKiBQdWJsaXNoZXIvU3Vic2NyaWJlciBhbmQgaGFzIGJlZW4gc3VjY2Vzc2Z1bGx5IGRpc2Fzc29jaWF0ZWQgZnJvbSB0aGF0IG9uZSBhbmQgcHJvcGVybHkgYWRkZWQgdG8gdGhpcyBvbmUuXG4gICAgICovXG4gICAgYWRkVmlkZW9FbGVtZW50KHZpZGVvOiBIVE1MVmlkZW9FbGVtZW50KTogbnVtYmVyIHtcblxuICAgICAgICB0aGlzLmluaXRpYWxpemVWaWRlb1Byb3BlcnRpZXModmlkZW8pO1xuXG4gICAgICAgIC8vIElmIHRoZSB2aWRlbyBlbGVtZW50IGlzIGFscmVhZHkgcGFydCBvZiB0aGlzIFN0cmVhbU1hbmFnZXIgZG8gbm90aGluZ1xuICAgICAgICBmb3IgKGNvbnN0IHYgb2YgdGhpcy52aWRlb3MpIHtcbiAgICAgICAgICAgIGlmICh2LnZpZGVvID09PSB2aWRlbykge1xuICAgICAgICAgICAgICAgIHJldHVybiAwO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgbGV0IHJldHVybk51bWJlciA9IDE7XG5cbiAgICAgICAgZm9yIChjb25zdCBzdHJlYW1NYW5hZ2VyIG9mIHRoaXMuc3RyZWFtLnNlc3Npb24uc3RyZWFtTWFuYWdlcnMpIHtcbiAgICAgICAgICAgIGlmIChzdHJlYW1NYW5hZ2VyLmRpc2Fzc29jaWF0ZVZpZGVvKHZpZGVvKSkge1xuICAgICAgICAgICAgICAgIHJldHVybk51bWJlciA9IC0xO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5zdHJlYW0uc2Vzc2lvbi5zdHJlYW1NYW5hZ2Vycy5mb3JFYWNoKHN0cmVhbU1hbmFnZXIgPT4ge1xuICAgICAgICAgICAgc3RyZWFtTWFuYWdlci5kaXNhc3NvY2lhdGVWaWRlbyh2aWRlbyk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHRoaXMucHVzaE5ld1N0cmVhbU1hbmFnZXJWaWRlbyh7XG4gICAgICAgICAgICB2aWRlbyxcbiAgICAgICAgICAgIGlkOiB2aWRlby5pZFxuICAgICAgICB9KTtcblxuICAgICAgICBjb25zb2xlLmluZm8oJ05ldyB2aWRlbyBlbGVtZW50IGFzc29jaWF0ZWQgdG8gJywgdGhpcyk7XG5cbiAgICAgICAgcmV0dXJuIHJldHVybk51bWJlcjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgbmV3IHZpZGVvIGVsZW1lbnQgZGlzcGxheWluZyB0aGlzIFtbc3RyZWFtXV0uIFRoaXMgYWxsb3dzIHlvdSB0byBoYXZlIG11bHRpcGxlIHZpZGVvIGVsZW1lbnRzIGRpc3BsYXlpbmcgdGhlIHNhbWUgbWVkaWEgc3RyZWFtLlxuICAgICAqXG4gICAgICogIyMjIyBFdmVudHMgZGlzcGF0Y2hlZFxuICAgICAqXG4gICAgICogVGhlIFB1Ymxpc2hlci9TdWJzY3JpYmVyIG9iamVjdCB3aWxsIGRpc3BhdGNoIGEgYHZpZGVvRWxlbWVudENyZWF0ZWRgIGV2ZW50IG9uY2UgdGhlIEhUTUwgdmlkZW8gZWxlbWVudCBoYXMgYmVlbiBhZGRlZCB0byBET00uIFNlZSBbW1ZpZGVvRWxlbWVudEV2ZW50XV1cbiAgICAgKlxuICAgICAqIEBwYXJhbSB0YXJnZXRFbGVtZW50IEhUTUwgRE9NIGVsZW1lbnQgKG9yIGl0cyBgaWRgIGF0dHJpYnV0ZSkgaW4gd2hpY2ggdGhlIHZpZGVvIGVsZW1lbnQgb2YgdGhlIFB1Ymxpc2hlci9TdWJzY3JpYmVyIHdpbGwgYmUgaW5zZXJ0ZWRcbiAgICAgKiBAcGFyYW0gaW5zZXJ0TW9kZSBIb3cgdGhlIHZpZGVvIGVsZW1lbnQgd2lsbCBiZSBpbnNlcnRlZCBhY2NvcmRpbmdseSB0byBgdGFyZ2V0RWxlbWV0YFxuICAgICAqL1xuICAgIGNyZWF0ZVZpZGVvRWxlbWVudCh0YXJnZXRFbGVtZW50Pzogc3RyaW5nIHwgSFRNTEVsZW1lbnQsIGluc2VydE1vZGU/OiBWaWRlb0luc2VydE1vZGUpOiBIVE1MVmlkZW9FbGVtZW50IHtcbiAgICAgICAgbGV0IHRhcmdFbDtcbiAgICAgICAgaWYgKHR5cGVvZiB0YXJnZXRFbGVtZW50ID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgdGFyZ0VsID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQodGFyZ0VsKTtcbiAgICAgICAgICAgIGlmICghdGFyZ0VsKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiVGhlIHByb3ZpZGVkICd0YXJnZXRFbGVtZW50JyBjb3VsZG4ndCBiZSByZXNvbHZlZCB0byBhbnkgSFRNTCBlbGVtZW50OiBcIiArIHRhcmdldEVsZW1lbnQpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2UgaWYgKHRhcmdldEVsZW1lbnQgaW5zdGFuY2VvZiBIVE1MRWxlbWVudCkge1xuICAgICAgICAgICAgdGFyZ0VsID0gdGFyZ2V0RWxlbWVudDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIlRoZSBwcm92aWRlZCAndGFyZ2V0RWxlbWVudCcgY291bGRuJ3QgYmUgcmVzb2x2ZWQgdG8gYW55IEhUTUwgZWxlbWVudDogXCIgKyB0YXJnZXRFbGVtZW50KTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHZpZGVvID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgndmlkZW8nKTtcbiAgICAgICAgdGhpcy5pbml0aWFsaXplVmlkZW9Qcm9wZXJ0aWVzKHZpZGVvKTtcblxuICAgICAgICBsZXQgaW5zTW9kZSA9ICEhaW5zZXJ0TW9kZSA/IGluc2VydE1vZGUgOiBWaWRlb0luc2VydE1vZGUuQVBQRU5EO1xuICAgICAgICBzd2l0Y2ggKGluc01vZGUpIHtcbiAgICAgICAgICAgIGNhc2UgVmlkZW9JbnNlcnRNb2RlLkFGVEVSOlxuICAgICAgICAgICAgICAgIHRhcmdFbC5wYXJlbnROb2RlISEuaW5zZXJ0QmVmb3JlKHZpZGVvLCB0YXJnRWwubmV4dFNpYmxpbmcpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBWaWRlb0luc2VydE1vZGUuQVBQRU5EOlxuICAgICAgICAgICAgICAgIHRhcmdFbC5hcHBlbmRDaGlsZCh2aWRlbyk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIFZpZGVvSW5zZXJ0TW9kZS5CRUZPUkU6XG4gICAgICAgICAgICAgICAgdGFyZ0VsLnBhcmVudE5vZGUhIS5pbnNlcnRCZWZvcmUodmlkZW8sIHRhcmdFbCk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIFZpZGVvSW5zZXJ0TW9kZS5QUkVQRU5EOlxuICAgICAgICAgICAgICAgIHRhcmdFbC5pbnNlcnRCZWZvcmUodmlkZW8sIHRhcmdFbC5jaGlsZE5vZGVzWzBdKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgVmlkZW9JbnNlcnRNb2RlLlJFUExBQ0U6XG4gICAgICAgICAgICAgICAgdGFyZ0VsLnBhcmVudE5vZGUhIS5yZXBsYWNlQ2hpbGQodmlkZW8sIHRhcmdFbCk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgIGluc01vZGUgPSBWaWRlb0luc2VydE1vZGUuQVBQRU5EO1xuICAgICAgICAgICAgICAgIHRhcmdFbC5hcHBlbmRDaGlsZCh2aWRlbyk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCB2OiBTdHJlYW1NYW5hZ2VyVmlkZW8gPSB7XG4gICAgICAgICAgICB0YXJnZXRFbGVtZW50OiB0YXJnRWwsXG4gICAgICAgICAgICB2aWRlbyxcbiAgICAgICAgICAgIGluc2VydE1vZGU6IGluc01vZGUsXG4gICAgICAgICAgICBpZDogdmlkZW8uaWRcbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5wdXNoTmV3U3RyZWFtTWFuYWdlclZpZGVvKHYpO1xuXG4gICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCd2aWRlb0VsZW1lbnRDcmVhdGVkJywgW25ldyBWaWRlb0VsZW1lbnRFdmVudCh2LnZpZGVvLCB0aGlzLCAndmlkZW9FbGVtZW50Q3JlYXRlZCcpXSk7XG5cbiAgICAgICAgdGhpcy5sYXp5TGF1bmNoVmlkZW9FbGVtZW50Q3JlYXRlZEV2ZW50ID0gISF0aGlzLmZpcnN0VmlkZW9FbGVtZW50O1xuXG4gICAgICAgIHJldHVybiB2aWRlbztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgaW5pdGlhbGl6ZVZpZGVvUHJvcGVydGllcyh2aWRlbzogSFRNTFZpZGVvRWxlbWVudCk6IHZvaWQge1xuICAgICAgICBpZiAoISh0aGlzLnN0cmVhbS5pc0xvY2FsKCkgJiYgdGhpcy5zdHJlYW0uZGlzcGxheU15UmVtb3RlKCkpKSB7XG4gICAgICAgICAgICAvLyBBdm9pZCBzZXR0aW5nIHRoZSBNZWRpYVN0cmVhbSBpbnRvIHRoZSBzcmNPYmplY3QgaWYgcmVtb3RlIHN1YnNjcmlwdGlvbiBiZWZvcmUgcHVibGlzaGluZ1xuICAgICAgICAgICAgdmlkZW8uc3JjT2JqZWN0ID0gdGhpcy5zdHJlYW0uZ2V0TWVkaWFTdHJlYW0oKTtcbiAgICAgICAgfVxuICAgICAgICB2aWRlby5hdXRvcGxheSA9IHRydWU7XG4gICAgICAgIHZpZGVvLmNvbnRyb2xzID0gZmFsc2U7XG4gICAgICAgIGlmICghdmlkZW8uaWQpIHtcbiAgICAgICAgICAgIHZpZGVvLmlkID0gKHRoaXMucmVtb3RlID8gJ3JlbW90ZS0nIDogJ2xvY2FsLScpICsgJ3ZpZGVvLScgKyB0aGlzLnN0cmVhbS5zdHJlYW1JZDtcbiAgICAgICAgICAgIC8vIERFUFJFQ0FURUQgcHJvcGVydHk6IGFzc2lnbiBvbmNlIHRoZSBwcm9wZXJ0eSBpZCBpZiB0aGUgdXNlciBwcm92aWRlZCBhIHZhbGlkIHRhcmdldEVsZW1lbnRcbiAgICAgICAgICAgIGlmICghdGhpcy5pZCAmJiAhIXRoaXMudGFyZ2V0RWxlbWVudCkge1xuICAgICAgICAgICAgICAgIHRoaXMuaWQgPSB2aWRlby5pZDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAoIXRoaXMucmVtb3RlICYmICF0aGlzLnN0cmVhbS5kaXNwbGF5TXlSZW1vdGUoKSkge1xuICAgICAgICAgICAgdmlkZW8ubXV0ZWQgPSB0cnVlO1xuICAgICAgICAgICAgaWYgKHRoaXMuc3RyZWFtLm91dGJvdW5kU3RyZWFtT3B0cy5wdWJsaXNoZXJQcm9wZXJ0aWVzLm1pcnJvcikge1xuICAgICAgICAgICAgICAgIHRoaXMubWlycm9yVmlkZW8odmlkZW8pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHJlbW92ZUFsbFZpZGVvcygpOiB2b2lkIHtcbiAgICAgICAgZm9yIChsZXQgaSA9IHRoaXMuc3RyZWFtLnNlc3Npb24uc3RyZWFtTWFuYWdlcnMubGVuZ3RoIC0gMTsgaSA+PSAwOyAtLWkpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLnN0cmVhbS5zZXNzaW9uLnN0cmVhbU1hbmFnZXJzW2ldID09PSB0aGlzKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5zdHJlYW0uc2Vzc2lvbi5zdHJlYW1NYW5hZ2Vycy5zcGxpY2UoaSwgMSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLnZpZGVvcy5zbGljZSgpLnJldmVyc2UoKS5mb3JFYWNoKChzdHJlYW1NYW5hZ2VyVmlkZW8sIGluZGV4LCB2aWRlb3MpID0+IHtcbiAgICAgICAgICAgIC8vIFJlbW92ZSBvbmNhbnBsYXkgZXZlbnQgbGlzdGVuZXIgKG9ubHkgT3BlblZpZHUgYnJvd3NlciBvbmUsIG5vdCB0aGUgdXNlciBvbmVzKVxuICAgICAgICAgICAgc3RyZWFtTWFuYWdlclZpZGVvLnZpZGVvLnJlbW92ZUV2ZW50TGlzdGVuZXIoJ2NhbnBsYXknLCB0aGlzLmNhblBsYXlMaXN0ZW5lcik7XG4gICAgICAgICAgICBpZiAoISFzdHJlYW1NYW5hZ2VyVmlkZW8udGFyZ2V0RWxlbWVudCkge1xuICAgICAgICAgICAgICAgIC8vIE9ubHkgcmVtb3ZlIHZpZGVvcyBjcmVhdGVkIGJ5IE9wZW5WaWR1IEJyb3dzZXIgKHRob3NlIGdlbmVyYXRlZCBieSBwYXNzaW5nIGEgdmFsaWQgdGFyZ2V0RWxlbWVudCBpbiBPcGVuVmlkdS5pbml0UHVibGlzaGVyIGFuZCBTZXNzaW9uLnN1YnNjcmliZVxuICAgICAgICAgICAgICAgIC8vIG9yIHRob3NlIGNyZWF0ZWQgYnkgU3RyZWFtTWFuYWdlci5jcmVhdGVWaWRlb0VsZW1lbnQpLiBUaGVzZSBhcmUgYWxzbyB0aGUgdmlkZW9zIHRoYXQgdHJpZ2dlcmVkIGEgdmlkZW9FbGVtZW50Q3JlYXRlZCBldmVudFxuICAgICAgICAgICAgICAgIHN0cmVhbU1hbmFnZXJWaWRlby52aWRlby5wYXJlbnROb2RlIS5yZW1vdmVDaGlsZChzdHJlYW1NYW5hZ2VyVmlkZW8udmlkZW8pO1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCd2aWRlb0VsZW1lbnREZXN0cm95ZWQnLCBbbmV3IFZpZGVvRWxlbWVudEV2ZW50KHN0cmVhbU1hbmFnZXJWaWRlby52aWRlbywgdGhpcywgJ3ZpZGVvRWxlbWVudERlc3Ryb3llZCcpXSk7XG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3Muc3BsaWNlKHZpZGVvcy5sZW5ndGggLSAxIC0gaW5kZXgsIDEpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAvLyBSZW1vdmUgc3JjT2JqZWN0IGluIGFsbCB2aWRlb3MgbWFuYWdlZCBieSB0aGUgdXNlclxuICAgICAgICAgICAgICAgIHN0cmVhbU1hbmFnZXJWaWRlby52aWRlby5zcmNPYmplY3QgPSBudWxsO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgZGlzYXNzb2NpYXRlVmlkZW8odmlkZW86IEhUTUxWaWRlb0VsZW1lbnQpOiBib29sZWFuIHtcbiAgICAgICAgbGV0IGRpc2Fzc29jaWF0ZWQgPSBmYWxzZTtcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLnZpZGVvcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgaWYgKHRoaXMudmlkZW9zW2ldLnZpZGVvID09PSB2aWRlbykge1xuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9zLnNwbGljZShpLCAxKTtcbiAgICAgICAgICAgICAgICBkaXNhc3NvY2lhdGVkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oJ1ZpZGVvIGVsZW1lbnQgZGlzYXNzb2NpYXRlZCBmcm9tICcsIHRoaXMpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBkaXNhc3NvY2lhdGVkO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBhZGRQbGF5RXZlbnRUb0ZpcnN0VmlkZW8oKSB7XG4gICAgICAgIGlmICgoISF0aGlzLnZpZGVvc1swXSkgJiYgKCEhdGhpcy52aWRlb3NbMF0udmlkZW8pICYmICh0aGlzLnZpZGVvc1swXS52aWRlby5vbmNhbnBsYXkgPT09IG51bGwpKSB7XG4gICAgICAgICAgICB0aGlzLnZpZGVvc1swXS52aWRlby5hZGRFdmVudExpc3RlbmVyKCdjYW5wbGF5JywgdGhpcy5jYW5QbGF5TGlzdGVuZXIpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHVwZGF0ZU1lZGlhU3RyZWFtKG1lZGlhU3RyZWFtOiBNZWRpYVN0cmVhbSkge1xuICAgICAgICB0aGlzLnZpZGVvcy5mb3JFYWNoKHN0cmVhbU1hbmFnZXJWaWRlbyA9PiB7XG4gICAgICAgICAgICBzdHJlYW1NYW5hZ2VyVmlkZW8udmlkZW8uc3JjT2JqZWN0ID0gbWVkaWFTdHJlYW07XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBlbWl0RXZlbnQodHlwZTogc3RyaW5nLCBldmVudEFycmF5OiBhbnlbXSk6IHZvaWQge1xuICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCh0eXBlLCBldmVudEFycmF5KTtcbiAgICB9XG5cbiAgICBwcml2YXRlIHB1c2hOZXdTdHJlYW1NYW5hZ2VyVmlkZW8oc3RyZWFtTWFuYWdlclZpZGVvOiBTdHJlYW1NYW5hZ2VyVmlkZW8pIHtcbiAgICAgICAgdGhpcy52aWRlb3MucHVzaChzdHJlYW1NYW5hZ2VyVmlkZW8pO1xuICAgICAgICB0aGlzLmFkZFBsYXlFdmVudFRvRmlyc3RWaWRlbygpO1xuICAgICAgICBpZiAodGhpcy5zdHJlYW0uc2Vzc2lvbi5zdHJlYW1NYW5hZ2Vycy5pbmRleE9mKHRoaXMpID09PSAtMSkge1xuICAgICAgICAgICAgdGhpcy5zdHJlYW0uc2Vzc2lvbi5zdHJlYW1NYW5hZ2Vycy5wdXNoKHRoaXMpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBtaXJyb3JWaWRlbyh2aWRlbyk6IHZvaWQge1xuICAgICAgICB2aWRlby5zdHlsZS50cmFuc2Zvcm0gPSAncm90YXRlWSgxODBkZWcpJztcbiAgICAgICAgdmlkZW8uc3R5bGUud2Via2l0VHJhbnNmb3JtID0gJ3JvdGF0ZVkoMTgwZGVnKSc7XG4gICAgfVxuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBTdHJlYW0gfSBmcm9tICcuL1N0cmVhbSc7XG5pbXBvcnQgeyBTdHJlYW1NYW5hZ2VyIH0gZnJvbSAnLi9TdHJlYW1NYW5hZ2VyJztcbmltcG9ydCB7IFN1YnNjcmliZXJQcm9wZXJ0aWVzIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9JbnRlcmZhY2VzL1B1YmxpYy9TdWJzY3JpYmVyUHJvcGVydGllcyc7XG5cblxuLyoqXG4gKiBQYWNrcyByZW1vdGUgbWVkaWEgc3RyZWFtcy4gUGFydGljaXBhbnRzIGF1dG9tYXRpY2FsbHkgcmVjZWl2ZSB0aGVtIHdoZW4gb3RoZXJzIHB1Ymxpc2ggdGhlaXIgc3RyZWFtcy4gSW5pdGlhbGl6ZWQgd2l0aCBbW1Nlc3Npb24uc3Vic2NyaWJlXV0gbWV0aG9kXG4gKi9cbmV4cG9ydCBjbGFzcyBTdWJzY3JpYmVyIGV4dGVuZHMgU3RyZWFtTWFuYWdlciB7XG5cbiAgICBwcml2YXRlIHByb3BlcnRpZXM6IFN1YnNjcmliZXJQcm9wZXJ0aWVzO1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHN0cmVhbTogU3RyZWFtLCB0YXJnRWw6IHN0cmluZyB8IEhUTUxFbGVtZW50LCBwcm9wZXJ0aWVzOiBTdWJzY3JpYmVyUHJvcGVydGllcykge1xuICAgICAgICBzdXBlcihzdHJlYW0sIHRhcmdFbCk7XG4gICAgICAgIHRoaXMuZWxlbWVudCA9IHRoaXMudGFyZ2V0RWxlbWVudDtcbiAgICAgICAgdGhpcy5zdHJlYW0gPSBzdHJlYW07XG4gICAgICAgIHRoaXMucHJvcGVydGllcyA9IHByb3BlcnRpZXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU3Vic2NyaWJlIG9yIHVuc3Vic2NyaWJlIGZyb20gdGhlIGF1ZGlvIHN0cmVhbSAoaWYgYXZhaWxhYmxlKS4gQ2FsbGluZyB0aGlzIG1ldGhvZCB0d2ljZSBpbiBhIHJvdyBwYXNzaW5nIHNhbWUgdmFsdWUgd2lsbCBoYXZlIG5vIGVmZmVjdFxuICAgICAqIEBwYXJhbSB2YWx1ZSBgdHJ1ZWAgdG8gc3Vic2NyaWJlIHRvIHRoZSBhdWRpbyBzdHJlYW0sIGBmYWxzZWAgdG8gdW5zdWJzY3JpYmUgZnJvbSBpdFxuICAgICAqL1xuICAgIHN1YnNjcmliZVRvQXVkaW8odmFsdWU6IGJvb2xlYW4pOiBTdWJzY3JpYmVyIHtcbiAgICAgICAgdGhpcy5zdHJlYW0uZ2V0TWVkaWFTdHJlYW0oKS5nZXRBdWRpb1RyYWNrcygpLmZvckVhY2goKHRyYWNrKSA9PiB7XG4gICAgICAgICAgICB0cmFjay5lbmFibGVkID0gdmFsdWU7XG4gICAgICAgIH0pO1xuICAgICAgICBjb25zb2xlLmluZm8oXCInU3Vic2NyaWJlcicgaGFzIFwiICsgKHZhbHVlID8gJ3N1YnNjcmliZWQgdG8nIDogJ3Vuc3Vic2NyaWJlZCBmcm9tJykgKyAnIGl0cyBhdWRpbyBzdHJlYW0nKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU3Vic2NyaWJlIG9yIHVuc3Vic2NyaWJlIGZyb20gdGhlIHZpZGVvIHN0cmVhbSAoaWYgYXZhaWxhYmxlKS4gQ2FsbGluZyB0aGlzIG1ldGhvZCB0d2ljZSBpbiBhIHJvdyBwYXNzaW5nIHNhbWUgdmFsdWUgd2lsbCBoYXZlIG5vIGVmZmVjdFxuICAgICAqIEBwYXJhbSB2YWx1ZSBgdHJ1ZWAgdG8gc3Vic2NyaWJlIHRvIHRoZSB2aWRlbyBzdHJlYW0sIGBmYWxzZWAgdG8gdW5zdWJzY3JpYmUgZnJvbSBpdFxuICAgICAqL1xuICAgIHN1YnNjcmliZVRvVmlkZW8odmFsdWU6IGJvb2xlYW4pOiBTdWJzY3JpYmVyIHtcbiAgICAgICAgdGhpcy5zdHJlYW0uZ2V0TWVkaWFTdHJlYW0oKS5nZXRWaWRlb1RyYWNrcygpLmZvckVhY2goKHRyYWNrKSA9PiB7XG4gICAgICAgICAgICB0cmFjay5lbmFibGVkID0gdmFsdWU7XG4gICAgICAgIH0pO1xuICAgICAgICBjb25zb2xlLmluZm8oXCInU3Vic2NyaWJlcicgaGFzIFwiICsgKHZhbHVlID8gJ3N1YnNjcmliZWQgdG8nIDogJ3Vuc3Vic2NyaWJlZCBmcm9tJykgKyAnIGl0cyB2aWRlbyBzdHJlYW0nKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5leHBvcnQgZW51bSBMb2NhbFJlY29yZGVyU3RhdGUge1xuICAgIFJFQURZID0gJ1JFQURZJyxcbiAgICBSRUNPUkRJTkcgPSAnUkVDT1JESU5HJyxcbiAgICBQQVVTRUQgPSAnUEFVU0VEJyxcbiAgICBGSU5JU0hFRCA9ICdGSU5JU0hFRCdcbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbi8qKlxuICogRGVmaW5lcyBwcm9wZXJ0eSBbW09wZW5WaWR1RXJyb3IubmFtZV1dXG4gKi9cbmV4cG9ydCBlbnVtIE9wZW5WaWR1RXJyb3JOYW1lIHtcblxuICAgIC8qKlxuICAgICAqIEJyb3dzZXIgaXMgbm90IHN1cHBvcnRlZCBieSBPcGVuVmlkdS5cbiAgICAgKiBSZXR1cm5lZCB1cG9uIHVuc3VjY2Vzc2Z1bCBbW1Nlc3Npb24uY29ubmVjdF1dXG4gICAgICovXG4gICAgQlJPV1NFUl9OT1RfU1VQUE9SVEVEID0gJ0JST1dTRVJfTk9UX1NVUFBPUlRFRCcsXG5cbiAgICAvKipcbiAgICAgKiBUaGUgdXNlciBoYXNuJ3QgZ3JhbnRlZCBwZXJtaXNzaW9ucyB0byB0aGUgcmVxdWlyZWQgaW5wdXQgZGV2aWNlIHdoZW4gdGhlIGJyb3dzZXIgYXNrZWQgZm9yIHRoZW0uXG4gICAgICogUmV0dXJuZWQgdXBvbiB1bnN1Y2Nlc3NmdWwgW1tPcGVuVmlkdS5pbml0UHVibGlzaGVyXV0gb3IgW1tPcGVuVmlkdS5nZXRVc2VyTWVkaWFdXVxuICAgICAqL1xuICAgIERFVklDRV9BQ0NFU1NfREVOSUVEID0gJ0RFVklDRV9BQ0NFU1NfREVOSUVEJyxcblxuICAgIC8qKlxuICAgICAqIFRoZSB1c2VyIGhhc24ndCBncmFudGVkIHBlcm1pc3Npb25zIHRvIGNhcHR1cmUgc29tZSBkZXNrdG9wIHNjcmVlbiB3aGVuIHRoZSBicm93c2VyIGFza2VkIGZvciB0aGVtLlxuICAgICAqIFJldHVybmVkIHVwb24gdW5zdWNjZXNzZnVsIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dIG9yIFtbT3BlblZpZHUuZ2V0VXNlck1lZGlhXV1cbiAgICAgKi9cbiAgICBTQ1JFRU5fQ0FQVFVSRV9ERU5JRUQgPSAnU0NSRUVOX0NBUFRVUkVfREVOSUVEJyxcblxuICAgIC8qKlxuICAgICAqIEJyb3dzZXIgZG9lcyBub3Qgc3VwcG9ydCBzY3JlZW4gc2hhcmluZy5cbiAgICAgKiBSZXR1cm5lZCB1cG9uIHVuc3VjY2Vzc2Z1bCBbW09wZW5WaWR1LmluaXRQdWJsaXNoZXJdXVxuICAgICAqL1xuICAgIFNDUkVFTl9TSEFSSU5HX05PVF9TVVBQT1JURUQgPSAnU0NSRUVOX1NIQVJJTkdfTk9UX1NVUFBPUlRFRCcsXG5cbiAgICAvKipcbiAgICAgKiBPbmx5IGZvciBDaHJvbWUsIHRoZXJlJ3Mgbm8gc2NyZWVuIHNoYXJpbmcgZXh0ZW5zaW9uIGluc3RhbGxlZFxuICAgICAqIFJldHVybmVkIHVwb24gdW5zdWNjZXNzZnVsIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dXG4gICAgICovXG4gICAgU0NSRUVOX0VYVEVOU0lPTl9OT1RfSU5TVEFMTEVEID0gJ1NDUkVFTl9FWFRFTlNJT05fTk9UX0lOU1RBTExFRCcsXG5cbiAgICAvKipcbiAgICAgKiBPbmx5IGZvciBDaHJvbWUsIHRoZSBzY3JlZW4gc2hhcmluZyBleHRlbnNpb24gaXMgaW5zdGFsbGVkIGJ1dCBpcyBkaXNhYmxlZFxuICAgICAqIFJldHVybmVkIHVwb24gdW5zdWNjZXNzZnVsIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dXG4gICAgICovXG4gICAgU0NSRUVOX0VYVEVOU0lPTl9ESVNBQkxFRCA9ICdTQ1JFRU5fRVhURU5TSU9OX0RJU0FCTEVEJyxcblxuICAgIC8qKlxuICAgICAqIE5vIHZpZGVvIGlucHV0IGRldmljZSBmb3VuZCB3aXRoIHRoZSBwcm92aWRlZCBkZXZpY2VJZCAocHJvcGVydHkgW1tQdWJsaXNoZXJQcm9wZXJ0aWVzLnZpZGVvU291cmNlXV0pXG4gICAgICogUmV0dXJuZWQgdXBvbiB1bnN1Y2Nlc3NmdWwgW1tPcGVuVmlkdS5pbml0UHVibGlzaGVyXV1cbiAgICAgKi9cbiAgICBJTlBVVF9WSURFT19ERVZJQ0VfTk9UX0ZPVU5EID0gJ0lOUFVUX1ZJREVPX0RFVklDRV9OT1RfRk9VTkQnLFxuXG4gICAgLyoqXG4gICAgICogTm8gYXVkaW8gaW5wdXQgZGV2aWNlIGZvdW5kIHdpdGggdGhlIHByb3ZpZGVkIGRldmljZUlkIChwcm9wZXJ0eSBbW1B1Ymxpc2hlclByb3BlcnRpZXMuYXVkaW9Tb3VyY2VdXSlcbiAgICAgKiBSZXR1cm5lZCB1cG9uIHVuc3VjY2Vzc2Z1bCBbW09wZW5WaWR1LmluaXRQdWJsaXNoZXJdXVxuICAgICAqL1xuICAgIElOUFVUX0FVRElPX0RFVklDRV9OT1RfRk9VTkQgPSAnSU5QVVRfQVVESU9fREVWSUNFX05PVF9GT1VORCcsXG5cbiAgICAvKipcbiAgICAgKiBNZXRob2QgW1tPcGVuVmlkdS5pbml0UHVibGlzaGVyXV0gaGFzIGJlZW4gY2FsbGVkIHdpdGggcHJvcGVydGllcyBgdmlkZW9Tb3VyY2VgIGFuZCBgYXVkaW9Tb3VyY2VgIG9mXG4gICAgICogW1tQdWJsaXNoZXJQcm9wZXJ0aWVzXV0gcGFyYW1ldGVyIGJvdGggc2V0IHRvICpmYWxzZSogb3IgKm51bGwqXG4gICAgICovXG4gICAgTk9fSU5QVVRfU09VUkNFX1NFVCA9ICdOT19JTlBVVF9TT1VSQ0VfU0VUJyxcblxuICAgIC8qKlxuICAgICAqIFNvbWUgbWVkaWEgcHJvcGVydHkgb2YgW1tQdWJsaXNoZXJQcm9wZXJ0aWVzXV0gc3VjaCBhcyBgZnJhbWVSYXRlYCBvciBgcmVzb2x1dGlvbmAgaXMgbm90IHN1cHBvcnRlZFxuICAgICAqIGJ5IHRoZSBpbnB1dCBkZXZpY2VzICh3aGVuZXZlciBpdCBpcyBwb3NzaWJsZSB0aGV5IGFyZSBhdXRvbWF0aWNhbGx5IGFkanVzdGVkIHRvIHRoZSBtb3N0IHNpbWlsYXIgdmFsdWUpLlxuICAgICAqIFJldHVybmVkIHVwb24gdW5zdWNjZXNzZnVsIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dXG4gICAgICovXG4gICAgUFVCTElTSEVSX1BST1BFUlRJRVNfRVJST1IgPSAnUFVCTElTSEVSX1BST1BFUlRJRVNfRVJST1InLFxuXG4gICAgLyoqXG4gICAgICogVGhlIGNsaWVudCB0cmllZCB0byBjYWxsIGEgbWV0aG9kIHdpdGhvdXQgdGhlIHJlcXVpcmVkIHBlcm1pc3Npb25zLiBUaGlzIGNhbiBvY2N1ciBmb3IgbWV0aG9kcyBbW1Nlc3Npb24ucHVibGlzaF1dLFxuICAgICAqIFtbU2Vzc2lvbi5mb3JjZVVucHVibGlzaF1dIGFuZCBbW1Nlc3Npb24uZm9yY2VEaXNjb25uZWN0XV1cbiAgICAgKi9cbiAgICBPUEVOVklEVV9QRVJNSVNTSU9OX0RFTklFRCA9ICdPUEVOVklEVV9QRVJNSVNTSU9OX0RFTklFRCcsXG5cbiAgICAvKipcbiAgICAgKiBfTm90IGluIHVzZSB5ZXRfXG4gICAgICovXG4gICAgT1BFTlZJRFVfTk9UX0NPTk5FQ1RFRCA9ICdPUEVOVklEVV9OT1RfQ09OTkVDVEVEJyxcblxuICAgIC8qKlxuICAgICAqIF9Ob3QgaW4gdXNlIHlldF9cbiAgICAgKi9cbiAgICBHRU5FUklDX0VSUk9SID0gJ0dFTkVSSUNfRVJST1InXG59XG5cbi8qKlxuICogU2ltcGxlIG9iamVjdCB0byBpZGVudGlmeSBydW50aW1lIGVycm9ycyBvbiB0aGUgY2xpZW50IHNpZGVcbiAqL1xuZXhwb3J0IGNsYXNzIE9wZW5WaWR1RXJyb3Ige1xuXG4gICAgbmFtZTogT3BlblZpZHVFcnJvck5hbWU7XG4gICAgbWVzc2FnZTogc3RyaW5nO1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKG5hbWU6IE9wZW5WaWR1RXJyb3JOYW1lLCBtZXNzYWdlOiBzdHJpbmcpIHtcbiAgICAgICAgdGhpcy5uYW1lID0gbmFtZTtcbiAgICAgICAgdGhpcy5tZXNzYWdlID0gbWVzc2FnZTtcbiAgICB9XG5cbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbi8qKlxuICogSG93IHRoZSB2aWRlbyB3aWxsIGJlIGluc2VydGVkIGluIHRoZSBET00gZm9yIFB1Ymxpc2hlcnMgYW5kIFN1YnNjcmliZXJzLiBTZWUgW1tQdWJsaXNoZXJQcm9wZXJ0aWVzLmluc2VydE1vZGVdXSBhbmQgW1tTdWJzY3JpYmVyUHJvcGVydGllcy5pbnNlcnRNb2RlXV1cbiAqL1xuZXhwb3J0IGVudW0gVmlkZW9JbnNlcnRNb2RlIHtcblxuICAgIC8qKlxuICAgICAqIFZpZGVvIGluc2VydGVkIGFmdGVyIHRoZSB0YXJnZXQgZWxlbWVudCAoYXMgbmV4dCBzaWJsaW5nKVxuICAgICAqL1xuICAgIEFGVEVSID0gJ0FGVEVSJyxcbiAgICAvKipcbiAgICAgKiBWaWRlbyBpbnNlcnRlZCBhcyBsYXN0IGNoaWxkIG9mIHRoZSB0YXJnZXQgZWxlbWVudFxuICAgICAqL1xuICAgIEFQUEVORCA9ICdBUFBFTkQnLFxuICAgIC8qKlxuICAgICAqIFZpZGVvIGluc2VydGVkIGJlZm9yZSB0aGUgdGFyZ2V0IGVsZW1lbnQgKGFzIHByZXZpb3VzIHNpYmxpbmcpXG4gICAgICovXG4gICAgQkVGT1JFID0gJ0JFRk9SRScsXG4gICAgLyoqXG4gICAgICogVmlkZW8gaW5zZXJ0ZWQgYXMgZmlyc3QgY2hpbGQgb2YgdGhlIHRhcmdldCBlbGVtZW50XG4gICAgICovXG4gICAgUFJFUEVORCA9ICdQUkVQRU5EJyxcbiAgICAvKipcbiAgICAgKiBWaWRlbyByZXBsYWNlcyB0YXJnZXQgZWxlbWVudFxuICAgICAqL1xuICAgIFJFUExBQ0UgPSAnUkVQTEFDRSdcblxufSIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTctMjAxOCBPcGVuVmlkdSAoaHR0cHM6Ly9vcGVudmlkdS5pby8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuaW1wb3J0IHsgRXZlbnQgfSBmcm9tICcuL0V2ZW50JztcbmltcG9ydCB7IENvbm5lY3Rpb24gfSBmcm9tICcuLi8uLi9PcGVuVmlkdS9Db25uZWN0aW9uJztcbmltcG9ydCB7IFNlc3Npb24gfSBmcm9tICcuLi8uLi9PcGVuVmlkdS9TZXNzaW9uJztcblxuXG4vKipcbiAqIERlZmluZXMgdGhlIGZvbGxvd2luZyBldmVudHM6XG4gKiAtIGBjb25uZWN0aW9uQ3JlYXRlZGA6IGRpc3BhdGNoZWQgYnkgW1tTZXNzaW9uXV1cbiAqIC0gYGNvbm5lY3Rpb25EZXN0cm95ZWRgOiBkaXNwYXRjaGVkIGJ5IFtbU2Vzc2lvbl1dXG4gKi9cbmV4cG9ydCBjbGFzcyBDb25uZWN0aW9uRXZlbnQgZXh0ZW5kcyBFdmVudCB7XG5cbiAgICAvKipcbiAgICAgKiBDb25uZWN0aW9uIG9iamVjdCB0aGF0IHdhcyBjcmVhdGVkIG9yIGRlc3Ryb3llZFxuICAgICAqL1xuICAgIGNvbm5lY3Rpb246IENvbm5lY3Rpb247XG5cbiAgICAvKipcbiAgICAgKiBGb3IgJ2Nvbm5lY3Rpb25EZXN0cm95ZWQnIGV2ZW50OlxuICAgICAqIC0gXCJkaXNjb25uZWN0XCI6IHRoZSByZW1vdGUgdXNlciBoYXMgY2FsbGVkIGBTZXNzaW9uLmRpc2Nvbm5lY3QoKWBcbiAgICAgKiAtIFwiZm9yY2VEaXNjb25uZWN0QnlVc2VyXCI6IHRoZSByZW1vdGUgdXNlciBoYXMgYmVlbiBldmljdGVkIGZyb20gdGhlIFNlc3Npb24gYnkgb3RoZXIgdXNlciBjYWxsaW5nIGBTZXNzaW9uLmZvcmNlRGlzY29ubmVjdCgpYFxuICAgICAqIC0gXCJmb3JjZURpc2Nvbm5lY3RCeVNlcnZlclwiOiB0aGUgcmVtb3RlIHVzZXIgaGFzIGJlZW4gZXZpY3RlZCBmcm9tIHRoZSBTZXNzaW9uIGJ5IHRoZSBhcHBsaWNhdGlvblxuICAgICAqIC0gXCJzZXNzaW9uQ2xvc2VkQnlTZXJ2ZXJcIjogdGhlIFNlc3Npb24gaGFzIGJlZW4gY2xvc2VkIGJ5IHRoZSBhcHBsaWNhdGlvblxuICAgICAqIC0gXCJuZXR3b3JrRGlzY29ubmVjdFwiOiB0aGUgcmVtb3RlIHVzZXIgbmV0d29yayBjb25uZWN0aW9uIGhhcyBkcm9wcGVkXG4gICAgICpcbiAgICAgKiBGb3IgJ2Nvbm5lY3Rpb25DcmVhdGVkJyBlbXB0eSBzdHJpbmdcbiAgICAgKi9cbiAgICByZWFzb246IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3RvcihjYW5jZWxhYmxlOiBib29sZWFuLCB0YXJnZXQ6IFNlc3Npb24sIHR5cGU6IHN0cmluZywgY29ubmVjdGlvbjogQ29ubmVjdGlvbiwgcmVhc29uOiBzdHJpbmcpIHtcbiAgICAgICAgc3VwZXIoY2FuY2VsYWJsZSwgdGFyZ2V0LCB0eXBlKTtcbiAgICAgICAgdGhpcy5jb25uZWN0aW9uID0gY29ubmVjdGlvbjtcbiAgICAgICAgdGhpcy5yZWFzb24gPSByZWFzb247XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZTpuby1lbXB0eVxuICAgIGNhbGxEZWZhdWx0QmVoYXZpb3IoKSB7IH1cblxufSIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTctMjAxOCBPcGVuVmlkdSAoaHR0cHM6Ly9vcGVudmlkdS5pby8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuaW1wb3J0IHsgU3RyZWFtTWFuYWdlciB9IGZyb20gJy4uLy4uL09wZW5WaWR1L1N0cmVhbU1hbmFnZXInO1xuaW1wb3J0IHsgU2Vzc2lvbiB9IGZyb20gJy4uLy4uL09wZW5WaWR1L1Nlc3Npb24nO1xuXG5leHBvcnQgYWJzdHJhY3QgY2xhc3MgRXZlbnQge1xuXG4gICAgLyoqXG4gICAgICogV2hldGhlciB0aGUgZXZlbnQgaGFzIGEgZGVmYXVsdCBiZWhhdmlvciB0aGF0IG1heSBiZSBwcmV2ZW50ZWQgYnkgY2FsbGluZyBbW0V2ZW50LnByZXZlbnREZWZhdWx0XV1cbiAgICAgKi9cbiAgICBjYW5jZWxhYmxlOiBib29sZWFuO1xuXG4gICAgLyoqXG4gICAgICogVGhlIG9iamVjdCB0aGF0IGRpc3BhdGNoZWQgdGhlIGV2ZW50XG4gICAgICovXG4gICAgdGFyZ2V0OiBTZXNzaW9uIHwgU3RyZWFtTWFuYWdlcjtcblxuICAgIC8qKlxuICAgICAqIFRoZSB0eXBlIG9mIGV2ZW50LiBUaGlzIGlzIHRoZSBzYW1lIHN0cmluZyB5b3UgcGFzcyBhcyBmaXJzdCBwYXJhbWV0ZXIgd2hlbiBjYWxsaW5nIG1ldGhvZCBgb24oKWAgb2YgYW55IG9iamVjdCBpbXBsZW1lbnRpbmcgW1tFdmVudERpc3BhdGNoZXJdXSBpbnRlcmZhY2VcbiAgICAgKi9cbiAgICB0eXBlOiBzdHJpbmc7XG5cbiAgICBwcml2YXRlIGhhc0JlZW5QcmV2ZW50ZWQgPSBmYWxzZTtcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3RvcihjYW5jZWxhYmxlOiBib29sZWFuLCB0YXJnZXQ6IFNlc3Npb24gfCBTdHJlYW1NYW5hZ2VyLCB0eXBlOiBzdHJpbmcpIHtcbiAgICAgICAgdGhpcy5jYW5jZWxhYmxlID0gY2FuY2VsYWJsZTtcbiAgICAgICAgdGhpcy50YXJnZXQgPSB0YXJnZXQ7XG4gICAgICAgIHRoaXMudHlwZSA9IHR5cGU7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogV2hldGhlciB0aGUgZGVmYXVsdCBiZWFoaXZvdXIgb2YgdGhlIGV2ZW50IGhhcyBiZWVuIHByZXZlbnRlZCBvciBub3QuIENhbGwgW1tFdmVudC5wcmV2ZW50RGVmYXVsdF1dIHRvIHByZXZlbnQgaXRcbiAgICAgKi9cbiAgICBpc0RlZmF1bHRQcmV2ZW50ZWQoKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiB0aGlzLmhhc0JlZW5QcmV2ZW50ZWQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUHJldmVudHMgdGhlIGRlZmF1bHQgYmVoYXZpb3Igb2YgdGhlIGV2ZW50LiBUaGUgZm9sbG93aW5nIGV2ZW50cyBoYXZlIGEgZGVmYXVsdCBiZWhhdmlvcjpcbiAgICAgKlxuICAgICAqIC0gYHNlc3Npb25EaXNjb25uZWN0ZWRgOiBkaXNwYXRjaGVkIGJ5IFtbU2Vzc2lvbl1dIG9iamVjdCwgYXV0b21hdGljYWxseSB1bnN1YnNjcmliZXMgdGhlIGxlYXZpbmcgcGFydGljaXBhbnQgZnJvbSBldmVyeSBTdWJzY3JpYmVyIG9iamVjdCBvZiB0aGUgc2Vzc2lvbiAodGhpcyBpbmNsdWRlcyBjbG9zaW5nIHRoZSBXZWJSVENQZWVyIGNvbm5lY3Rpb24gYW5kIGRpc3Bvc2luZyBhbGwgTWVkaWFTdHJlYW1UcmFja3MpXG4gICAgICogYW5kIGFsc28gZGVsZXRlcyBhbnkgSFRNTCB2aWRlbyBlbGVtZW50IGFzc29jaWF0ZWQgdG8gZWFjaCBTdWJzY3JpYmVyIChvbmx5IHRob3NlIGNyZWF0ZWQgYnkgT3BlblZpZHUgQnJvd3NlciwgZWl0aGVyIGJ5IHBhc3NpbmcgYSB2YWxpZCBwYXJhbWV0ZXIgYXMgYHRhcmdldEVsZW1lbnRgIGluIG1ldGhvZCBbW1Nlc3Npb24uc3Vic2NyaWJlXV0gb3JcbiAgICAgKiBieSBjYWxsaW5nIFtbU3Vic2NyaWJlci5jcmVhdGVWaWRlb0VsZW1lbnRdXSkuIEZvciBldmVyeSB2aWRlbyByZW1vdmVkLCBlYWNoIFN1YnNjcmliZXIgb2JqZWN0IHdpbGwgYWxzbyBkaXNwYXRjaCBhIGB2aWRlb0VsZW1lbnREZXN0cm95ZWRgIGV2ZW50LlxuICAgICAqXG4gICAgICogLSBgc3RyZWFtRGVzdHJveWVkYDpcbiAgICAgKiAgIC0gSWYgZGlzcGF0Y2hlZCBieSBhIFtbUHVibGlzaGVyXV0gKCp5b3UqIGhhdmUgdW5wdWJsaXNoZWQpOiBhdXRvbWF0aWNhbGx5IHN0b3BzIGFsbCBtZWRpYSB0cmFja3MgYW5kIGRlbGV0ZXMgYW55IEhUTUwgdmlkZW8gZWxlbWVudCBhc3NvY2lhdGVkIHRvIGl0IChvbmx5IHRob3NlIGNyZWF0ZWQgYnkgT3BlblZpZHUgQnJvd3NlciwgZWl0aGVyIGJ5IHBhc3NpbmcgYSB2YWxpZCBwYXJhbWV0ZXIgYXMgYHRhcmdldEVsZW1lbnRgXG4gICAgICogaW4gbWV0aG9kIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dIG9yIGJ5IGNhbGxpbmcgW1tQdWJsaXNoZXIuY3JlYXRlVmlkZW9FbGVtZW50XV0pLiBGb3IgZXZlcnkgdmlkZW8gcmVtb3ZlZCwgdGhlIFB1Ymxpc2hlciBvYmplY3Qgd2lsbCBhbHNvIGRpc3BhdGNoIGEgYHZpZGVvRWxlbWVudERlc3Ryb3llZGAgZXZlbnQuXG4gICAgICogICAtIElmIGRpc3BhdGNoZWQgYnkgW1tTZXNzaW9uXV0gKCpvdGhlciB1c2VyKiBoYXMgdW5wdWJsaXNoZWQpOiBhdXRvbWF0aWNhbGx5IHVuc3Vic2NyaWJlcyB0aGUgcHJvcGVyIFN1YnNjcmliZXIgb2JqZWN0IGZyb20gdGhlIHNlc3Npb24gKHRoaXMgaW5jbHVkZXMgY2xvc2luZyB0aGUgV2ViUlRDUGVlciBjb25uZWN0aW9uIGFuZCBkaXNwb3NpbmcgYWxsIE1lZGlhU3RyZWFtVHJhY2tzKVxuICAgICAqIGFuZCBhbHNvIGRlbGV0ZXMgYW55IEhUTUwgdmlkZW8gZWxlbWVudCBhc3NvY2lhdGVkIHRvIHRoYXQgU3Vic2NyaWJlciAob25seSB0aG9zZSBjcmVhdGVkIGJ5IE9wZW5WaWR1IEJyb3dzZXIsIGVpdGhlciBieSBwYXNzaW5nIGEgdmFsaWQgcGFyYW1ldGVyIGFzIGB0YXJnZXRFbGVtZW50YCBpbiBtZXRob2QgW1tTZXNzaW9uLnN1YnNjcmliZV1dIG9yXG4gICAgICogYnkgY2FsbGluZyBbW1N1YnNjcmliZXIuY3JlYXRlVmlkZW9FbGVtZW50XV0pLiBGb3IgZXZlcnkgdmlkZW8gcmVtb3ZlZCwgdGhlIFN1YnNjcmliZXIgb2JqZWN0IHdpbGwgYWxzbyBkaXNwYXRjaCBhIGB2aWRlb0VsZW1lbnREZXN0cm95ZWRgIGV2ZW50LlxuICAgICAqL1xuICAgIHByZXZlbnREZWZhdWx0KCkge1xuICAgICAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6bm8tZW1wdHlcbiAgICAgICAgdGhpcy5jYWxsRGVmYXVsdEJlaGF2aW9yID0gKCkgPT4geyB9O1xuICAgICAgICB0aGlzLmhhc0JlZW5QcmV2ZW50ZWQgPSB0cnVlO1xuICAgIH1cblxuICAgIHByb3RlY3RlZCBhYnN0cmFjdCBjYWxsRGVmYXVsdEJlaGF2aW9yKCk7XG5cbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IEV2ZW50IH0gZnJvbSAnLi9FdmVudCc7XG5pbXBvcnQgeyBDb25uZWN0aW9uIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvQ29ubmVjdGlvbic7XG5pbXBvcnQgeyBTZXNzaW9uIH0gZnJvbSAnLi4vLi4nO1xuXG5cbi8qKlxuICogRGVmaW5lcyB0aGUgZm9sbG93aW5nIGV2ZW50czpcbiAqIC0gYHB1Ymxpc2hlclN0YXJ0U3BlYWtpbmdgOiBkaXNwYXRjaGVkIGJ5IFtbU2Vzc2lvbl1dXG4gKiAtIGBwdWJsaXNoZXJTdG9wU3BlYWtpbmdgOiBkaXNwYXRjaGVkIGJ5IFtbU2Vzc2lvbl1dXG4gKlxuICogTW9yZSBpbmZvcm1hdGlvbjpcbiAqIC0gVGhpcyBldmVudHMgd2lsbCBvbmx5IGJlIHRyaWdnZXJlZCBmb3IgKipyZW1vdGUgc3RyZWFtcyB0aGF0IGhhdmUgYXVkaW8gdHJhY2tzKipcbiAqIC0gQm90aCBldmVudHMgc2hhcmUgdGhlIHNhbWUgbGlmZWN5Y2xlLiBUaGF0IG1lYW5zIHRoYXQgeW91IGNhbiBzdWJzY3JpYmUgdG8gb25seSBvbmUgb2YgdGhlbSBpZiB5b3Ugd2FudCwgYnV0IGlmIHlvdSBjYWxsIGBTZXNzaW9uLm9mZigncHVibGlzaGVyU3RvcFNwZWFraW5nJylgLFxuICoga2VlcCBpbiBtaW5kIHRoYXQgdGhpcyB3aWxsIGFsc28gaW50ZXJuYWxseSByZW1vdmUgYW55ICdwdWJsaXNoZXJTdGFydFNwZWFraW5nJyBldmVudFxuICogLSBZb3UgY2FuIGZ1cnRoZXIgY29uZmlndXJlIGhvdyB0aGUgZXZlbnRzIGFyZSBkaXNwYXRjaGVkIGJ5IHNldHRpbmcgcHJvcGVydHkgYHB1Ymxpc2hlclNwZWFraW5nRXZlbnRzT3B0aW9uc2AgaW4gdGhlIGNhbGwgb2YgW1tPcGVuVmlkdS5zZXRBZHZhbmNlZENvbmZpZ3VyYXRpb25dXVxuICovXG5leHBvcnQgY2xhc3MgUHVibGlzaGVyU3BlYWtpbmdFdmVudCBleHRlbmRzIEV2ZW50IHtcblxuICAgIC8qKlxuICAgICAqIFRoZSBjbGllbnQgdGhhdCBzdGFydGVkIG9yIHN0b3BwZWQgc3BlYWtpbmdcbiAgICAgKi9cbiAgICBjb25uZWN0aW9uOiBDb25uZWN0aW9uO1xuXG4gICAgLyoqXG4gICAgICogVGhlIHN0cmVhbUlkIG9mIHRoZSBTdHJlYW0gYWZmZWN0ZWQgYnkgdGhlIHNwZWFraW5nIGV2ZW50XG4gICAgICovXG4gICAgc3RyZWFtSWQ6IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3Rvcih0YXJnZXQ6IFNlc3Npb24sIHR5cGU6IHN0cmluZywgY29ubmVjdGlvbjogQ29ubmVjdGlvbiwgc3RyZWFtSWQ6IHN0cmluZykge1xuICAgICAgICBzdXBlcihmYWxzZSwgdGFyZ2V0LCB0eXBlKTtcbiAgICAgICAgdGhpcy50eXBlID0gdHlwZTtcbiAgICAgICAgdGhpcy5jb25uZWN0aW9uID0gY29ubmVjdGlvbjtcbiAgICAgICAgdGhpcy5zdHJlYW1JZCA9IHN0cmVhbUlkO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6bm8tZW1wdHlcbiAgICBjYWxsRGVmYXVsdEJlaGF2aW9yKCkgeyB9XG5cbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IEV2ZW50IH0gZnJvbSAnLi9FdmVudCc7XG5pbXBvcnQgeyBTZXNzaW9uIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvU2Vzc2lvbic7XG5cblxuLyoqXG4gKiBEZWZpbmVzIHRoZSBmb2xsb3dpbmcgZXZlbnRzOlxuICogLSBgcmVjb3JkaW5nU3RhcnRlZGA6IGRpc3BhdGNoZWQgYnkgW1tTZXNzaW9uXV1cbiAqIC0gYHJlY29yZGluZ1N0b3BwZWRgOiBkaXNwYXRjaGVkIGJ5IFtbU2Vzc2lvbl1dXG4gKi9cbmV4cG9ydCBjbGFzcyBSZWNvcmRpbmdFdmVudCBleHRlbmRzIEV2ZW50IHtcblxuICAgIC8qKlxuICAgICAqIFRoZSByZWNvcmRpbmcgSUQgZ2VuZXJhdGVkIGluIG9wZW52aWR1LXNlcnZlclxuICAgICAqL1xuICAgIGlkOiBzdHJpbmc7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgcmVjb3JkaW5nIG5hbWUgeW91IHN1cHBsaWVkIHRvIG9wZW52aWR1LXNlcnZlci4gRm9yIGV4YW1wbGUsIHRvIG5hbWUgeW91ciByZWNvcmRpbmcgZmlsZSBNWV9SRUNPUkRJTkc6XG4gICAgICogLSBXaXRoICoqQVBJIFJFU1QqKjogUE9TVCB0byBgL2FwaS9yZWNvcmRpbmdzL3N0YXJ0YCBwYXNzaW5nIEpTT04gYm9keSBge1wic2Vzc2lvblwiOlwic2Vzc2lvbklkXCIsXCJuYW1lXCI6XCJNWV9SRUNPUkRJTkdcIn1gXG4gICAgICogLSBXaXRoICoqb3BlbnZpZHUtamF2YS1jbGllbnQqKjogYE9wZW5WaWR1LnN0YXJ0UmVjb3JkaW5nKHNlc3Npb25JZCwgXCJNWV9SRUNPUkRJTkdcIilgIG9yIGBPcGVuVmlkdS5zdGFydFJlY29yZGluZyhzZXNzaW9uSWQsIG5ldyBSZWNvcmRpbmdQcm9wZXJ0aWVzLkJ1aWxkZXIoKS5uYW1lKFwiTVlfUkVDT1JESU5HXCIpLmJ1aWxkKCkpYFxuICAgICAqIC0gV2l0aCAqKm9wZW52aWR1LW5vZGUtY2xpZW50Kio6IGBPcGVuVmlkdS5zdGFydFJlY29yZGluZyhzZXNzaW9uSWQsIFwiTVlfUkVDT1JESU5HXCIpYCBvciBgT3BlblZpZHUuc3RhcnRSZWNvcmRpbmcoc2Vzc2lvbklkLCB7bmFtZTogXCJNWV9SRUNPUkRJTkdcIn0pYFxuICAgICAqXG4gICAgICogSWYgbm8gbmFtZSBpcyBzdXBwbGllZCwgdGhpcyBwcm9wZXJ0eSB3aWxsIGJlIHVuZGVmaW5lZCBhbmQgdGhlIHJlY29yZGVkIGZpbGUgd2lsbCBiZSBuYW1lZCBhZnRlciBwcm9wZXJ0eSBbW2lkXV1cbiAgICAgKi9cbiAgICBuYW1lPzogc3RyaW5nO1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHRhcmdldDogU2Vzc2lvbiwgdHlwZTogc3RyaW5nLCBpZDogc3RyaW5nLCBuYW1lOiBzdHJpbmcpIHtcbiAgICAgICAgc3VwZXIoZmFsc2UsIHRhcmdldCwgdHlwZSk7XG4gICAgICAgIHRoaXMuaWQgPSBpZDtcbiAgICAgICAgaWYgKG5hbWUgIT09IGlkKSB7XG4gICAgICAgICAgICB0aGlzLm5hbWUgPSBuYW1lO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZTpuby1lbXB0eVxuICAgIGNhbGxEZWZhdWx0QmVoYXZpb3IoKSB7IH1cblxufSIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTctMjAxOCBPcGVuVmlkdSAoaHR0cHM6Ly9vcGVudmlkdS5pby8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuaW1wb3J0IHsgRXZlbnQgfSBmcm9tICcuL0V2ZW50JztcbmltcG9ydCB7IFNlc3Npb24gfSBmcm9tICcuLi8uLi9PcGVuVmlkdS9TZXNzaW9uJztcblxuXG4vKipcbiAqIERlZmluZXMgZXZlbnQgYHNlc3Npb25EaXNjb25uZWN0ZWRgIGRpc3BhdGNoZWQgYnkgW1tTZXNzaW9uXV1cbiAqL1xuZXhwb3J0IGNsYXNzIFNlc3Npb25EaXNjb25uZWN0ZWRFdmVudCBleHRlbmRzIEV2ZW50IHtcblxuICAgIC8qKlxuICAgICAqIC0gXCJkaXNjb25uZWN0XCI6IHlvdSBoYXZlIGNhbGxlZCBgU2Vzc2lvbi5kaXNjb25uZWN0KClgXG4gICAgICogLSBcImZvcmNlRGlzY29ubmVjdEJ5VXNlclwiOiB5b3UgaGF2ZSBiZWVuIGV2aWN0ZWQgZnJvbSB0aGUgU2Vzc2lvbiBieSBvdGhlciB1c2VyIGNhbGxpbmcgYFNlc3Npb24uZm9yY2VEaXNjb25uZWN0KClgXG4gICAgICogLSBcImZvcmNlRGlzY29ubmVjdEJ5U2VydmVyXCI6IHlvdSBoYXZlIGJlZW4gZXZpY3RlZCBmcm9tIHRoZSBTZXNzaW9uIGJ5IHRoZSBhcHBsaWNhdGlvblxuICAgICAqIC0gXCJzZXNzaW9uQ2xvc2VkQnlTZXJ2ZXJcIjogdGhlIFNlc3Npb24gaGFzIGJlZW4gY2xvc2VkIGJ5IHRoZSBhcHBsaWNhdGlvblxuICAgICAqIC0gXCJuZXR3b3JrRGlzY29ubmVjdFwiOiB5b3VyIG5ldHdvcmsgY29ubmVjdGlvbiBoYXMgZHJvcHBlZFxuICAgICAqL1xuICAgIHJlYXNvbjogc3RyaW5nO1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHRhcmdldDogU2Vzc2lvbiwgcmVhc29uOiBzdHJpbmcpIHtcbiAgICAgICAgc3VwZXIodHJ1ZSwgdGFyZ2V0LCAnc2Vzc2lvbkRpc2Nvbm5lY3RlZCcpO1xuICAgICAgICB0aGlzLnJlYXNvbiA9IHJlYXNvbjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgY2FsbERlZmF1bHRCZWhhdmlvcigpIHtcblxuICAgICAgICBjb25zb2xlLmluZm8oXCJDYWxsaW5nIGRlZmF1bHQgYmVoYXZpb3IgdXBvbiAnXCIgKyB0aGlzLnR5cGUgKyBcIicgZXZlbnQgZGlzcGF0Y2hlZCBieSAnU2Vzc2lvbidcIik7XG5cbiAgICAgICAgY29uc3Qgc2Vzc2lvbiA9IDxTZXNzaW9uPnRoaXMudGFyZ2V0O1xuXG4gICAgICAgIC8vIERpc3Bvc2UgYW5kIGRlbGV0ZSBhbGwgcmVtb3RlIENvbm5lY3Rpb25zXG4gICAgICAgIGZvciAoY29uc3QgY29ubmVjdGlvbklkIGluIHNlc3Npb24ucmVtb3RlQ29ubmVjdGlvbnMpIHtcbiAgICAgICAgICAgIGlmICghIXNlc3Npb24ucmVtb3RlQ29ubmVjdGlvbnNbY29ubmVjdGlvbklkXS5zdHJlYW0pIHtcbiAgICAgICAgICAgICAgICBzZXNzaW9uLnJlbW90ZUNvbm5lY3Rpb25zW2Nvbm5lY3Rpb25JZF0uc3RyZWFtLmRpc3Bvc2VXZWJSdGNQZWVyKCk7XG4gICAgICAgICAgICAgICAgc2Vzc2lvbi5yZW1vdGVDb25uZWN0aW9uc1tjb25uZWN0aW9uSWRdLnN0cmVhbS5kaXNwb3NlTWVkaWFTdHJlYW0oKTtcbiAgICAgICAgICAgICAgICBpZiAoc2Vzc2lvbi5yZW1vdGVDb25uZWN0aW9uc1tjb25uZWN0aW9uSWRdLnN0cmVhbS5zdHJlYW1NYW5hZ2VyKSB7XG4gICAgICAgICAgICAgICAgICAgIHNlc3Npb24ucmVtb3RlQ29ubmVjdGlvbnNbY29ubmVjdGlvbklkXS5zdHJlYW0uc3RyZWFtTWFuYWdlci5yZW1vdmVBbGxWaWRlb3MoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZGVsZXRlIHNlc3Npb24ucmVtb3RlU3RyZWFtc0NyZWF0ZWRbc2Vzc2lvbi5yZW1vdGVDb25uZWN0aW9uc1tjb25uZWN0aW9uSWRdLnN0cmVhbS5zdHJlYW1JZF07XG4gICAgICAgICAgICAgICAgc2Vzc2lvbi5yZW1vdGVDb25uZWN0aW9uc1tjb25uZWN0aW9uSWRdLmRpc3Bvc2UoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGRlbGV0ZSBzZXNzaW9uLnJlbW90ZUNvbm5lY3Rpb25zW2Nvbm5lY3Rpb25JZF07XG4gICAgICAgIH1cbiAgICB9XG5cbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IEV2ZW50IH0gZnJvbSAnLi9FdmVudCc7XG5pbXBvcnQgeyBDb25uZWN0aW9uIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvQ29ubmVjdGlvbic7XG5pbXBvcnQgeyBTZXNzaW9uIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvU2Vzc2lvbic7XG5cblxuLyoqXG4gKiBEZWZpbmVzIHRoZSBmb2xsb3dpbmcgZXZlbnRzOlxuICogLSBgc2lnbmFsYDogZGlzcGF0Y2hlZCBieSBbW1Nlc3Npb25dXVxuICogLSBgc2lnbmFsOlRZUEVgOiBkaXNwYXRjaGVkIGJ5IFtbU2Vzc2lvbl1dXG4gKi9cbmV4cG9ydCBjbGFzcyBTaWduYWxFdmVudCBleHRlbmRzIEV2ZW50IHtcblxuICAgIC8qKlxuICAgICAqIFRoZSB0eXBlIG9mIHNpZ25hbCAoY2FuIGJlIGVtcHR5KS5cbiAgICAgKlxuICAgICAqIFRoZSBjbGllbnQgbXVzdCBiZSBzdWJzY3JpYmVkIHRvIGBTZXNzaW9uLm9uKCdzaWduYWw6dHlwZScsIGZ1bmN0aW9uKHNpZ25hbEV2ZW50KSB7Li4ufSlgIHRvIHJlY2VpdmUgdGhpcyBvYmplY3QgaW4gdGhlIGNhbGxiYWNrLlxuICAgICAqXG4gICAgICogU3Vic2NyaWJpbmcgdG8gYFNlc3Npb24ub24oJ3NpZ25hbCcsIGZ1bmN0aW9uKHNpZ25hbEV2ZW50KSB7Li4ufSlgIHdpbGwgdHJpZ2dlciBhbGwgdHlwZXMgb2Ygc2lnbmFscy5cbiAgICAgKi9cbiAgICB0eXBlOiBzdHJpbmc7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgbWVzc2FnZSBvZiB0aGUgc2lnbmFsIChjYW4gYmUgZW10cHkpXG4gICAgICovXG4gICAgZGF0YTogc3RyaW5nO1xuXG4gICAgLyoqXG4gICAgICogVGhlIGNsaWVudCB0aGF0IHNlbnQgdGhlIHNpZ25hbFxuICAgICAqL1xuICAgIGZyb206IENvbm5lY3Rpb247XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgY29uc3RydWN0b3IodGFyZ2V0OiBTZXNzaW9uLCB0eXBlOiBzdHJpbmcsIGRhdGE6IHN0cmluZywgZnJvbTogQ29ubmVjdGlvbikge1xuICAgICAgICBzdXBlcihmYWxzZSwgdGFyZ2V0LCB0eXBlKTtcbiAgICAgICAgdGhpcy50eXBlID0gdHlwZTtcbiAgICAgICAgdGhpcy5kYXRhID0gZGF0YTtcbiAgICAgICAgdGhpcy5mcm9tID0gZnJvbTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lOm5vLWVtcHR5XG4gICAgY2FsbERlZmF1bHRCZWhhdmlvcigpIHsgfVxuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBFdmVudCB9IGZyb20gJy4vRXZlbnQnO1xuaW1wb3J0IHsgUHVibGlzaGVyIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvUHVibGlzaGVyJztcbmltcG9ydCB7IFNlc3Npb24gfSBmcm9tICcuLi8uLi9PcGVuVmlkdS9TZXNzaW9uJztcbmltcG9ydCB7IFN0cmVhbSB9IGZyb20gJy4uLy4uL09wZW5WaWR1L1N0cmVhbSc7XG5cblxuLyoqXG4gKiBEZWZpbmVzIHRoZSBmb2xsb3dpbmcgZXZlbnRzOlxuICogLSBgc3RyZWFtQ3JlYXRlZGA6IGRpc3BhdGNoZWQgYnkgW1tTZXNzaW9uXV0gYW5kIFtbUHVibGlzaGVyXV1cbiAqIC0gYHN0cmVhbURlc3Ryb3llZGA6IGRpc3BhdGNoZWQgYnkgW1tTZXNzaW9uXV0gYW5kIFtbUHVibGlzaGVyXV1cbiAqL1xuZXhwb3J0IGNsYXNzIFN0cmVhbUV2ZW50IGV4dGVuZHMgRXZlbnQge1xuXG4gICAgLyoqXG4gICAgICogU3RyZWFtIG9iamVjdCB0aGF0IHdhcyBjcmVhdGVkIG9yIGRlc3Ryb3llZFxuICAgICAqL1xuICAgIHN0cmVhbTogU3RyZWFtO1xuXG4gICAgLyoqXG4gICAgICogRm9yICdzdHJlYW1EZXN0cm95ZWQnIGV2ZW50OlxuICAgICAqIC0gXCJ1bnB1Ymxpc2hcIjogbWV0aG9kIGBTZXNzaW9uLnVucHVibGlzaCgpYCBoYXMgYmVlbiBjYWxsZWRcbiAgICAgKiAtIFwiZGlzY29ubmVjdFwiOiBtZXRob2QgYFNlc3Npb24uZGlzY29ubmVjdCgpYCBoYXMgYmVlbiBjYWxsZWRcbiAgICAgKiAtIFwiZm9yY2VVbnB1Ymxpc2hCeVVzZXJcIjogc29tZSB1c2VyIGhhcyBjYWxsZWQgYFNlc3Npb24uZm9yY2VVbnB1Ymxpc2goKWAgb3ZlciB0aGUgU3RyZWFtXG4gICAgICogLSBcImZvcmNlRGlzY29ubmVjdEJ5VXNlclwiOiBzb21lIHVzZXIgaGFzIGNhbGxlZCBgU2Vzc2lvbi5mb3JjZURpc2Nvbm5lY3QoKWAgb3ZlciB0aGUgU3RyZWFtXG4gICAgICogLSBcImZvcmNlVW5wdWJsaXNoQnlTZXJ2ZXJcIjogdGhlIHVzZXIncyBzdHJlYW0gaGFzIGJlZW4gdW5wdWJsaXNoZWQgZnJvbSB0aGUgU2Vzc2lvbiBieSB0aGUgYXBwbGljYXRpb25cbiAgICAgKiAtIFwiZm9yY2VEaXNjb25uZWN0QnlTZXJ2ZXJcIjogdGhlIHVzZXIgaGFzIGJlZW4gZXZpY3RlZCBmcm9tIHRoZSBTZXNzaW9uIGJ5IHRoZSBhcHBsaWNhdGlvblxuICAgICAqIC0gXCJzZXNzaW9uQ2xvc2VkQnlTZXJ2ZXJcIjogdGhlIFNlc3Npb24gaGFzIGJlZW4gY2xvc2VkIGJ5IHRoZSBhcHBsaWNhdGlvblxuICAgICAqIC0gXCJuZXR3b3JrRGlzY29ubmVjdFwiOiB0aGUgdXNlcidzIG5ldHdvcmsgY29ubmVjdGlvbiBoYXMgZHJvcHBlZFxuICAgICAqXG4gICAgICogRm9yICdzdHJlYW1DcmVhdGVkJyBlbXB0eSBzdHJpbmdcbiAgICAgKi9cbiAgICByZWFzb246IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3RvcihjYW5jZWxhYmxlOiBib29sZWFuLCB0YXJnZXQ6IFNlc3Npb24gfCBQdWJsaXNoZXIsIHR5cGU6IHN0cmluZywgc3RyZWFtOiBTdHJlYW0sIHJlYXNvbjogc3RyaW5nKSB7XG4gICAgICAgIHN1cGVyKGNhbmNlbGFibGUsIHRhcmdldCwgdHlwZSk7XG4gICAgICAgIHRoaXMuc3RyZWFtID0gc3RyZWFtO1xuICAgICAgICB0aGlzLnJlYXNvbiA9IHJlYXNvbjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgY2FsbERlZmF1bHRCZWhhdmlvcigpIHtcbiAgICAgICAgaWYgKHRoaXMudHlwZSA9PT0gJ3N0cmVhbURlc3Ryb3llZCcpIHtcblxuICAgICAgICAgICAgaWYgKHRoaXMudGFyZ2V0IGluc3RhbmNlb2YgU2Vzc2lvbikge1xuICAgICAgICAgICAgICAgIC8vIFJlbW90ZSBTdHJlYW1cbiAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oXCJDYWxsaW5nIGRlZmF1bHQgYmVoYXZpb3IgdXBvbiAnXCIgKyB0aGlzLnR5cGUgKyBcIicgZXZlbnQgZGlzcGF0Y2hlZCBieSAnU2Vzc2lvbidcIik7XG4gICAgICAgICAgICAgICAgdGhpcy5zdHJlYW0uZGlzcG9zZVdlYlJ0Y1BlZXIoKTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAodGhpcy50YXJnZXQgaW5zdGFuY2VvZiBQdWJsaXNoZXIpIHtcbiAgICAgICAgICAgICAgICAvLyBMb2NhbCBTdHJlYW1cbiAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oXCJDYWxsaW5nIGRlZmF1bHQgYmVoYXZpb3IgdXBvbiAnXCIgKyB0aGlzLnR5cGUgKyBcIicgZXZlbnQgZGlzcGF0Y2hlZCBieSAnUHVibGlzaGVyJ1wiKTtcbiAgICAgICAgICAgICAgICBjbGVhckludGVydmFsKCg8UHVibGlzaGVyPnRoaXMudGFyZ2V0KS5zY3JlZW5TaGFyZVJlc2l6ZUludGVydmFsKTtcbiAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbS5pc0xvY2FsU3RyZWFtUmVhZHlUb1B1Ymxpc2ggPSBmYWxzZTtcblxuICAgICAgICAgICAgICAgIC8vIERlbGV0ZSBQdWJsaXNoZXIgb2JqZWN0IGZyb20gT3BlblZpZHUgcHVibGlzaGVycyBhcnJheVxuICAgICAgICAgICAgICAgIGNvbnN0IG9wZW52aWR1UHVibGlzaGVycyA9ICg8UHVibGlzaGVyPnRoaXMudGFyZ2V0KS5vcGVudmlkdS5wdWJsaXNoZXJzO1xuICAgICAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgb3BlbnZpZHVQdWJsaXNoZXJzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChvcGVudmlkdVB1Ymxpc2hlcnNbaV0gPT09ICg8UHVibGlzaGVyPnRoaXMudGFyZ2V0KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgb3BlbnZpZHVQdWJsaXNoZXJzLnNwbGljZShpLCAxKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBEaXNwb3NlIHRoZSBNZWRpYVN0cmVhbSBsb2NhbCBvYmplY3RcbiAgICAgICAgICAgIHRoaXMuc3RyZWFtLmRpc3Bvc2VNZWRpYVN0cmVhbSgpO1xuXG4gICAgICAgICAgICAvLyBSZW1vdmUgZnJvbSBET00gYWxsIHZpZGVvIGVsZW1lbnRzIGFzc29jaWF0ZWQgdG8gdGhpcyBTdHJlYW0sIGlmIHRoZXJlJ3MgYSBTdHJlYW1NYW5hZ2VyIGRlZmluZWRcbiAgICAgICAgICAgIC8vIChtZXRob2QgU2Vzc2lvbi5zdWJzY3JpYmUgbXVzdCBoYXZlIGJlZW4gY2FsbGVkKVxuICAgICAgICAgICAgaWYgKHRoaXMuc3RyZWFtLnN0cmVhbU1hbmFnZXIpIHRoaXMuc3RyZWFtLnN0cmVhbU1hbmFnZXIucmVtb3ZlQWxsVmlkZW9zKCk7XG5cbiAgICAgICAgICAgIC8vIERlbGV0ZSBzdHJlYW0gZnJvbSBTZXNzaW9uLnJlbW90ZVN0cmVhbXNDcmVhdGVkIG1hcFxuICAgICAgICAgICAgZGVsZXRlIHRoaXMuc3RyZWFtLnNlc3Npb24ucmVtb3RlU3RyZWFtc0NyZWF0ZWRbdGhpcy5zdHJlYW0uc3RyZWFtSWRdO1xuXG4gICAgICAgICAgICAvLyBEZWxldGUgU3RyZWFtT3B0aW9uc1NlcnZlciBmcm9tIHJlbW90ZSBDb25uZWN0aW9uXG4gICAgICAgICAgICBjb25zdCByZW1vdGVDb25uZWN0aW9uID0gdGhpcy5zdHJlYW0uc2Vzc2lvbi5yZW1vdGVDb25uZWN0aW9uc1t0aGlzLnN0cmVhbS5jb25uZWN0aW9uLmNvbm5lY3Rpb25JZF07XG4gICAgICAgICAgICBpZiAoISFyZW1vdGVDb25uZWN0aW9uICYmICEhcmVtb3RlQ29ubmVjdGlvbi5vcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgY29uc3Qgc3RyZWFtT3B0aW9uc1NlcnZlciA9IHJlbW90ZUNvbm5lY3Rpb24ub3B0aW9ucy5zdHJlYW1zO1xuICAgICAgICAgICAgICAgIGZvciAobGV0IGkgPSBzdHJlYW1PcHRpb25zU2VydmVyLmxlbmd0aCAtIDE7IGkgPj0gMDsgLS1pKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChzdHJlYW1PcHRpb25zU2VydmVyW2ldLmlkID09PSB0aGlzLnN0cmVhbS5zdHJlYW1JZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgc3RyZWFtT3B0aW9uc1NlcnZlci5zcGxpY2UoaSwgMSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgfVxuICAgIH1cblxufSIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTctMjAxOCBPcGVuVmlkdSAoaHR0cHM6Ly9vcGVudmlkdS5pby8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuaW1wb3J0IHsgRXZlbnQgfSBmcm9tICcuL0V2ZW50JztcbmltcG9ydCB7IFN0cmVhbU1hbmFnZXIgfSBmcm9tICcuLi8uLi9PcGVuVmlkdS9TdHJlYW1NYW5hZ2VyJztcblxuLyoqXG4gKiBEZWZpbmVzIHRoZSBmb2xsb3dpbmcgZXZlbnRzOlxuICogLSBgc3RyZWFtUGxheWluZ2A6IGRpc3BhdGNoZWQgYnkgW1tTdHJlYW1NYW5hZ2VyXV0gKFtbUHVibGlzaGVyXV0gYW5kIFtbU3Vic2NyaWJlcl1dKVxuICovXG5leHBvcnQgY2xhc3MgU3RyZWFtTWFuYWdlckV2ZW50IGV4dGVuZHMgRXZlbnQge1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHRhcmdldDogU3RyZWFtTWFuYWdlcikge1xuICAgICAgICBzdXBlcihmYWxzZSwgdGFyZ2V0LCAnc3RyZWFtUGxheWluZycpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6bm8tZW1wdHlcbiAgICBjYWxsRGVmYXVsdEJlaGF2aW9yKCkgeyB9XG5cbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IEV2ZW50IH0gZnJvbSAnLi9FdmVudCc7XG5pbXBvcnQgeyBTZXNzaW9uIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvU2Vzc2lvbic7XG5pbXBvcnQgeyBTdHJlYW0gfSBmcm9tICcuLi8uLi9PcGVuVmlkdS9TdHJlYW0nO1xuaW1wb3J0IHsgU3RyZWFtTWFuYWdlciB9IGZyb20gJy4uLy4uL09wZW5WaWR1L1N0cmVhbU1hbmFnZXInO1xuXG4vKipcbiAqIERlZmluZXMgZXZlbnQgYHN0cmVhbVByb3BlcnR5Q2hhbmdlZGAgZGlzcGF0Y2hlZCBieSBbW1Nlc3Npb25dXSBhcyB3ZWxsIGFzIGJ5IFtbU3RyZWFtTWFuYWdlcl1dIChbW1B1Ymxpc2hlcl1dIGFuZCBbW1N1YnNjcmliZXJdXSkuXG4gKiBUaGlzIGV2ZW50IGlzIGZpcmVkIHdoZW4gYW55IHJlbW90ZSBzdHJlYW0gKG93bmVkIGJ5IGEgU3Vic2NyaWJlcikgb3IgbG9jYWwgc3RyZWFtIChvd25lZCBieSBhIFB1Ymxpc2hlcikgdW5kZXJnb2VzXG4gKiBhbnkgY2hhbmdlIGluIGFueSBvZiBpdHMgbXV0YWJsZSBwcm9wZXJ0aWVzIChzZWUgW1tjaGFuZ2VkUHJvcGVydHldXSkuXG4gKi9cbmV4cG9ydCBjbGFzcyBTdHJlYW1Qcm9wZXJ0eUNoYW5nZWRFdmVudCBleHRlbmRzIEV2ZW50IHtcblxuICAgIC8qKlxuICAgICAqIFRoZSBTdHJlYW0gd2hvc2UgcHJvcGVydHkgaGFzIGNoYW5nZWQuIFlvdSBjYW4gYWx3YXlzIGlkZW50aWZ5IHRoZSB1c2VyIHB1Ymxpc2hpbmcgdGhlIGNoYW5nZWQgc3RyZWFtIGJ5IGNvbnN1bHRpbmcgcHJvcGVydHkgW1tTdHJlYW0uY29ubmVjdGlvbl1dXG4gICAgICovXG4gICAgc3RyZWFtOiBTdHJlYW07XG5cbiAgICAvKipcbiAgICAgKiBUaGUgcHJvcGVydHkgb2YgdGhlIHN0cmVhbSB0aGF0IGNoYW5nZWQuIFRoaXMgdmFsdWUgaXMgZWl0aGVyIGBcInZpZGVvQWN0aXZlXCJgLCBgXCJhdWRpb0FjdGl2ZVwiYCBvciBgXCJ2aWRlb0RpbWVuc2lvbnNcImBcbiAgICAgKi9cbiAgICBjaGFuZ2VkUHJvcGVydHk6IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIENhdXNlIG9mIHRoZSBjaGFuZ2Ugb24gdGhlIHN0cmVhbSdzIHByb3BlcnR5OlxuICAgICAqIC0gRm9yIGB2aWRlb0FjdGl2ZWA6IGBcInB1Ymxpc2hWaWRlb1wiYFxuICAgICAqIC0gRm9yIGBhdWRpb0FjdGl2ZWA6IGBcInB1Ymxpc2hBdWRpb1wiYFxuICAgICAqIC0gRm9yIGB2aWRlb0RpbWVuc2lvbnNgOiBgXCJkZXZpY2VSb3RhdGVkXCJgIG9yIGBcInNjcmVlblJlc2l6ZWRcImBcbiAgICAgKi9cbiAgICByZWFzb246IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIE5ldyB2YWx1ZSBvZiB0aGUgcHJvcGVydHkgKGFmdGVyIGNoYW5nZSwgY3VycmVudCB2YWx1ZSlcbiAgICAgKi9cbiAgICBuZXdWYWx1ZTogT2JqZWN0O1xuXG4gICAgLyoqXG4gICAgICogUHJldmlvdXMgdmFsdWUgb2YgdGhlIHByb3BlcnR5IChiZWZvcmUgY2hhbmdlKVxuICAgICAqL1xuICAgIG9sZFZhbHVlOiBPYmplY3Q7XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgY29uc3RydWN0b3IodGFyZ2V0OiBTZXNzaW9uIHwgU3RyZWFtTWFuYWdlciwgc3RyZWFtOiBTdHJlYW0sIGNoYW5nZWRQcm9wZXJ0eTogc3RyaW5nLCBuZXdWYWx1ZTogT2JqZWN0LCBvbGRWYWx1ZTogT2JqZWN0LCByZWFzb246IHN0cmluZykge1xuICAgICAgICBzdXBlcihmYWxzZSwgdGFyZ2V0LCAnc3RyZWFtUHJvcGVydHlDaGFuZ2VkJyk7XG4gICAgICAgIHRoaXMuc3RyZWFtID0gc3RyZWFtO1xuICAgICAgICB0aGlzLmNoYW5nZWRQcm9wZXJ0eSA9IGNoYW5nZWRQcm9wZXJ0eTtcbiAgICAgICAgdGhpcy5uZXdWYWx1ZSA9IG5ld1ZhbHVlO1xuICAgICAgICB0aGlzLm9sZFZhbHVlID0gb2xkVmFsdWU7XG4gICAgICAgIHRoaXMucmVhc29uID0gcmVhc29uO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6bm8tZW1wdHlcbiAgICBjYWxsRGVmYXVsdEJlaGF2aW9yKCkgeyB9XG5cbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IEV2ZW50IH0gZnJvbSAnLi9FdmVudCc7XG5pbXBvcnQgeyBTdHJlYW1NYW5hZ2VyIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvU3RyZWFtTWFuYWdlcic7XG5cblxuLyoqXG4gKiBEZWZpbmVzIHRoZSBmb2xsb3dpbmcgZXZlbnRzOlxuICogLSBgdmlkZW9FbGVtZW50Q3JlYXRlZGA6IGRpc3BhdGNoZWQgYnkgW1tQdWJsaXNoZXJdXSBhbmQgW1tTdWJzY3JpYmVyXV0gd2hlbmV2ZXIgYSBuZXcgSFRNTCB2aWRlbyBlbGVtZW50IGhhcyBiZWVuIGluc2VydGVkIGludG8gRE9NIGJ5IE9wZW5WaWR1IEJyb3dzZXIgbGlicmFyeS4gU2VlXG4gKiBbTWFuYWdlIHZpZGVvIHBsYXllcnNdKC9kb2NzL2hvdy1kby1pL21hbmFnZS12aWRlb3MpIHNlY3Rpb24uXG4gKiAtIGB2aWRlb0VsZW1lbnREZXN0cm95ZWRgOiBkaXNwYXRjaGVkIGJ5IFtbUHVibGlzaGVyXV0gYW5kIFtbU3Vic2NyaWJlcl1dIHdoZW5ldmVyIGFuIEhUTUwgdmlkZW8gZWxlbWVudCBoYXMgYmVlbiByZW1vdmVkIGZyb20gRE9NIGJ5IE9wZW5WaWR1IEJyb3dzZXIgbGlicmFyeS5cbiAqL1xuZXhwb3J0IGNsYXNzIFZpZGVvRWxlbWVudEV2ZW50IGV4dGVuZHMgRXZlbnQge1xuXG4gICAgLyoqXG4gICAgICogVmlkZW8gZWxlbWVudCB0aGF0IHdhcyBjcmVhdGVkIG9yIGRlc3Ryb3llZFxuICAgICAqL1xuICAgIGVsZW1lbnQ6IEhUTUxWaWRlb0VsZW1lbnQ7XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgY29uc3RydWN0b3IoZWxlbWVudDogSFRNTFZpZGVvRWxlbWVudCwgdGFyZ2V0OiBTdHJlYW1NYW5hZ2VyLCB0eXBlOiBzdHJpbmcpIHtcbiAgICAgICAgc3VwZXIoZmFsc2UsIHRhcmdldCwgdHlwZSk7XG4gICAgICAgIHRoaXMuZWxlbWVudCA9IGVsZW1lbnQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZTpuby1lbXB0eVxuICAgIGNhbGxEZWZhdWx0QmVoYXZpb3IoKSB7IH1cblxufSIsImZ1bmN0aW9uIE1hcHBlcigpXG57XG4gIHZhciBzb3VyY2VzID0ge307XG5cblxuICB0aGlzLmZvckVhY2ggPSBmdW5jdGlvbihjYWxsYmFjaylcbiAge1xuICAgIGZvcih2YXIga2V5IGluIHNvdXJjZXMpXG4gICAge1xuICAgICAgdmFyIHNvdXJjZSA9IHNvdXJjZXNba2V5XTtcblxuICAgICAgZm9yKHZhciBrZXkyIGluIHNvdXJjZSlcbiAgICAgICAgY2FsbGJhY2soc291cmNlW2tleTJdKTtcbiAgICB9O1xuICB9O1xuXG4gIHRoaXMuZ2V0ID0gZnVuY3Rpb24oaWQsIHNvdXJjZSlcbiAge1xuICAgIHZhciBpZHMgPSBzb3VyY2VzW3NvdXJjZV07XG4gICAgaWYoaWRzID09IHVuZGVmaW5lZClcbiAgICAgIHJldHVybiB1bmRlZmluZWQ7XG5cbiAgICByZXR1cm4gaWRzW2lkXTtcbiAgfTtcblxuICB0aGlzLnJlbW92ZSA9IGZ1bmN0aW9uKGlkLCBzb3VyY2UpXG4gIHtcbiAgICB2YXIgaWRzID0gc291cmNlc1tzb3VyY2VdO1xuICAgIGlmKGlkcyA9PSB1bmRlZmluZWQpXG4gICAgICByZXR1cm47XG5cbiAgICBkZWxldGUgaWRzW2lkXTtcblxuICAgIC8vIENoZWNrIGl0J3MgZW1wdHlcbiAgICBmb3IodmFyIGkgaW4gaWRzKXtyZXR1cm4gZmFsc2V9XG5cbiAgICBkZWxldGUgc291cmNlc1tzb3VyY2VdO1xuICB9O1xuXG4gIHRoaXMuc2V0ID0gZnVuY3Rpb24odmFsdWUsIGlkLCBzb3VyY2UpXG4gIHtcbiAgICBpZih2YWx1ZSA9PSB1bmRlZmluZWQpXG4gICAgICByZXR1cm4gdGhpcy5yZW1vdmUoaWQsIHNvdXJjZSk7XG5cbiAgICB2YXIgaWRzID0gc291cmNlc1tzb3VyY2VdO1xuICAgIGlmKGlkcyA9PSB1bmRlZmluZWQpXG4gICAgICBzb3VyY2VzW3NvdXJjZV0gPSBpZHMgPSB7fTtcblxuICAgIGlkc1tpZF0gPSB2YWx1ZTtcbiAgfTtcbn07XG5cblxuTWFwcGVyLnByb3RvdHlwZS5wb3AgPSBmdW5jdGlvbihpZCwgc291cmNlKVxue1xuICB2YXIgdmFsdWUgPSB0aGlzLmdldChpZCwgc291cmNlKTtcbiAgaWYodmFsdWUgPT0gdW5kZWZpbmVkKVxuICAgIHJldHVybiB1bmRlZmluZWQ7XG5cbiAgdGhpcy5yZW1vdmUoaWQsIHNvdXJjZSk7XG5cbiAgcmV0dXJuIHZhbHVlO1xufTtcblxuXG5tb2R1bGUuZXhwb3J0cyA9IE1hcHBlcjtcbiIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTQgS3VyZW50byAoaHR0cDovL2t1cmVudG8ub3JnLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG52YXIgSnNvblJwY0NsaWVudCAgPSByZXF1aXJlKCcuL2pzb25ycGNjbGllbnQnKTtcblxuXG5leHBvcnRzLkpzb25ScGNDbGllbnQgID0gSnNvblJwY0NsaWVudDsiLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE0IEt1cmVudG8gKGh0dHA6Ly9rdXJlbnRvLm9yZy8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxudmFyIFJwY0J1aWxkZXIgPSByZXF1aXJlKCcuLi8nKTtcbnZhciBXZWJTb2NrZXRXaXRoUmVjb25uZWN0aW9uID0gcmVxdWlyZSgnLi90cmFuc3BvcnRzL3dlYlNvY2tldFdpdGhSZWNvbm5lY3Rpb24nKTtcblxuRGF0ZS5ub3cgPSBEYXRlLm5vdyB8fCBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gK25ldyBEYXRlO1xufTtcblxudmFyIFBJTkdfSU5URVJWQUwgPSA1MDAwO1xuXG52YXIgUkVDT05ORUNUSU5HID0gJ1JFQ09OTkVDVElORyc7XG52YXIgQ09OTkVDVEVEID0gJ0NPTk5FQ1RFRCc7XG52YXIgRElTQ09OTkVDVEVEID0gJ0RJU0NPTk5FQ1RFRCc7XG5cbnZhciBMb2dnZXIgPSBjb25zb2xlO1xuXG4vKipcbiAqXG4gKiBoZWFydGJlYXQ6IGludGVydmFsIGluIG1zIGZvciBlYWNoIGhlYXJ0YmVhdCBtZXNzYWdlLFxuICogc2VuZENsb3NlTWVzc2FnZSA6IHRydWUgLyBmYWxzZSwgYmVmb3JlIGNsb3NpbmcgdGhlIGNvbm5lY3Rpb24sIGl0IHNlbmRzIGEgY2xvc2VTZXNzaW9uIG1lc3NhZ2VcbiAqIDxwcmU+XG4gKiB3cyA6IHtcbiAqIFx0dXJpIDogVVJJIHRvIGNvbm50ZWN0IHRvLFxuICogIHVzZVNvY2tKUyA6IHRydWUgKHVzZSBTb2NrSlMpIC8gZmFsc2UgKHVzZSBXZWJTb2NrZXQpIGJ5IGRlZmF1bHQsXG4gKiBcdG9uY29ubmVjdGVkIDogY2FsbGJhY2sgbWV0aG9kIHRvIGludm9rZSB3aGVuIGNvbm5lY3Rpb24gaXMgc3VjY2Vzc2Z1bCxcbiAqIFx0b25kaXNjb25uZWN0IDogY2FsbGJhY2sgbWV0aG9kIHRvIGludm9rZSB3aGVuIHRoZSBjb25uZWN0aW9uIGlzIGxvc3QsXG4gKiBcdG9ucmVjb25uZWN0aW5nIDogY2FsbGJhY2sgbWV0aG9kIHRvIGludm9rZSB3aGVuIHRoZSBjbGllbnQgaXMgcmVjb25uZWN0aW5nLFxuICogXHRvbnJlY29ubmVjdGVkIDogY2FsbGJhY2sgbWV0aG9kIHRvIGludm9rZSB3aGVuIHRoZSBjbGllbnQgc3VjY2Vzc2Z1bGx5IHJlY29ubmVjdHMsXG4gKiBcdG9uZXJyb3IgOiBjYWxsYmFjayBtZXRob2QgdG8gaW52b2tlIHdoZW4gdGhlcmUgaXMgYW4gZXJyb3JcbiAqIH0sXG4gKiBycGMgOiB7XG4gKiBcdHJlcXVlc3RUaW1lb3V0IDogdGltZW91dCBmb3IgYSByZXF1ZXN0LFxuICogXHRzZXNzaW9uU3RhdHVzQ2hhbmdlZDogY2FsbGJhY2sgbWV0aG9kIGZvciBjaGFuZ2VzIGluIHNlc3Npb24gc3RhdHVzLFxuICogXHRtZWRpYVJlbmVnb3RpYXRpb246IG1lZGlhUmVuZWdvdGlhdGlvblxuICogfVxuICogPC9wcmU+XG4gKi9cbmZ1bmN0aW9uIEpzb25ScGNDbGllbnQoY29uZmlndXJhdGlvbikge1xuXG4gICAgdmFyIHNlbGYgPSB0aGlzO1xuXG4gICAgdmFyIHdzQ29uZmlnID0gY29uZmlndXJhdGlvbi53cztcblxuICAgIHZhciBub3RSZWNvbm5lY3RJZk51bUxlc3NUaGFuID0gLTE7XG5cbiAgICB2YXIgcGluZ05leHROdW0gPSAwO1xuICAgIHZhciBlbmFibGVkUGluZ3MgPSB0cnVlO1xuICAgIHZhciBwaW5nUG9uZ1N0YXJ0ZWQgPSBmYWxzZTtcbiAgICB2YXIgcGluZ0ludGVydmFsO1xuXG4gICAgdmFyIHN0YXR1cyA9IERJU0NPTk5FQ1RFRDtcblxuICAgIHZhciBvbnJlY29ubmVjdGluZyA9IHdzQ29uZmlnLm9ucmVjb25uZWN0aW5nO1xuICAgIHZhciBvbnJlY29ubmVjdGVkID0gd3NDb25maWcub25yZWNvbm5lY3RlZDtcbiAgICB2YXIgb25jb25uZWN0ZWQgPSB3c0NvbmZpZy5vbmNvbm5lY3RlZDtcbiAgICB2YXIgb25lcnJvciA9IHdzQ29uZmlnLm9uZXJyb3I7XG5cbiAgICBjb25maWd1cmF0aW9uLnJwYy5wdWxsID0gZnVuY3Rpb24ocGFyYW1zLCByZXF1ZXN0KSB7XG4gICAgICAgIHJlcXVlc3QucmVwbHkobnVsbCwgXCJwdXNoXCIpO1xuICAgIH1cblxuICAgIHdzQ29uZmlnLm9ucmVjb25uZWN0aW5nID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIExvZ2dlci5kZWJ1ZyhcIi0tLS0tLS0tLSBPTlJFQ09OTkVDVElORyAtLS0tLS0tLS0tLVwiKTtcbiAgICAgICAgaWYgKHN0YXR1cyA9PT0gUkVDT05ORUNUSU5HKSB7XG4gICAgICAgICAgICBMb2dnZXIuZXJyb3IoXCJXZWJzb2NrZXQgYWxyZWFkeSBpbiBSRUNPTk5FQ1RJTkcgc3RhdGUgd2hlbiByZWNlaXZpbmcgYSBuZXcgT05SRUNPTk5FQ1RJTkcgbWVzc2FnZS4gSWdub3JpbmcgaXRcIik7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBzdGF0dXMgPSBSRUNPTk5FQ1RJTkc7XG4gICAgICAgIGlmIChvbnJlY29ubmVjdGluZykge1xuICAgICAgICAgICAgb25yZWNvbm5lY3RpbmcoKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHdzQ29uZmlnLm9ucmVjb25uZWN0ZWQgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgTG9nZ2VyLmRlYnVnKFwiLS0tLS0tLS0tIE9OUkVDT05ORUNURUQgLS0tLS0tLS0tLS1cIik7XG4gICAgICAgIGlmIChzdGF0dXMgPT09IENPTk5FQ1RFRCkge1xuICAgICAgICAgICAgTG9nZ2VyLmVycm9yKFwiV2Vic29ja2V0IGFscmVhZHkgaW4gQ09OTkVDVEVEIHN0YXRlIHdoZW4gcmVjZWl2aW5nIGEgbmV3IE9OUkVDT05ORUNURUQgbWVzc2FnZS4gSWdub3JpbmcgaXRcIik7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgc3RhdHVzID0gQ09OTkVDVEVEO1xuXG4gICAgICAgIGVuYWJsZWRQaW5ncyA9IHRydWU7XG4gICAgICAgIHVwZGF0ZU5vdFJlY29ubmVjdElmTGVzc1RoYW4oKTtcbiAgICAgICAgdXNlUGluZygpO1xuXG4gICAgICAgIGlmIChvbnJlY29ubmVjdGVkKSB7XG4gICAgICAgICAgICBvbnJlY29ubmVjdGVkKCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB3c0NvbmZpZy5vbmNvbm5lY3RlZCA9IGZ1bmN0aW9uKCkge1xuICAgICAgICBMb2dnZXIuZGVidWcoXCItLS0tLS0tLS0gT05DT05ORUNURUQgLS0tLS0tLS0tLS1cIik7XG4gICAgICAgIGlmIChzdGF0dXMgPT09IENPTk5FQ1RFRCkge1xuICAgICAgICAgICAgTG9nZ2VyLmVycm9yKFwiV2Vic29ja2V0IGFscmVhZHkgaW4gQ09OTkVDVEVEIHN0YXRlIHdoZW4gcmVjZWl2aW5nIGEgbmV3IE9OQ09OTkVDVEVEIG1lc3NhZ2UuIElnbm9yaW5nIGl0XCIpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHN0YXR1cyA9IENPTk5FQ1RFRDtcblxuICAgICAgICBlbmFibGVkUGluZ3MgPSB0cnVlO1xuICAgICAgICB1c2VQaW5nKCk7XG5cbiAgICAgICAgaWYgKG9uY29ubmVjdGVkKSB7XG4gICAgICAgICAgICBvbmNvbm5lY3RlZCgpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgd3NDb25maWcub25lcnJvciA9IGZ1bmN0aW9uKGVycm9yKSB7XG4gICAgICAgIExvZ2dlci5kZWJ1ZyhcIi0tLS0tLS0tLSBPTkVSUk9SIC0tLS0tLS0tLS0tXCIpO1xuXG4gICAgICAgIHN0YXR1cyA9IERJU0NPTk5FQ1RFRDtcblxuICAgICAgICBpZiAob25lcnJvcikge1xuICAgICAgICAgICAgb25lcnJvcihlcnJvcik7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB2YXIgd3MgPSBuZXcgV2ViU29ja2V0V2l0aFJlY29ubmVjdGlvbih3c0NvbmZpZyk7XG5cbiAgICBMb2dnZXIuZGVidWcoJ0Nvbm5lY3Rpbmcgd2Vic29ja2V0IHRvIFVSSTogJyArIHdzQ29uZmlnLnVyaSk7XG5cbiAgICB2YXIgcnBjQnVpbGRlck9wdGlvbnMgPSB7XG4gICAgICAgIHJlcXVlc3RfdGltZW91dDogY29uZmlndXJhdGlvbi5ycGMucmVxdWVzdFRpbWVvdXQsXG4gICAgICAgIHBpbmdfcmVxdWVzdF90aW1lb3V0OiBjb25maWd1cmF0aW9uLnJwYy5oZWFydGJlYXRSZXF1ZXN0VGltZW91dFxuICAgIH07XG5cbiAgICB2YXIgcnBjID0gbmV3IFJwY0J1aWxkZXIoUnBjQnVpbGRlci5wYWNrZXJzLkpzb25SUEMsIHJwY0J1aWxkZXJPcHRpb25zLCB3cyxcbiAgICAgICAgZnVuY3Rpb24ocmVxdWVzdCkge1xuXG4gICAgICAgICAgICBMb2dnZXIuZGVidWcoJ1JlY2VpdmVkIHJlcXVlc3Q6ICcgKyBKU09OLnN0cmluZ2lmeShyZXF1ZXN0KSk7XG5cbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgdmFyIGZ1bmMgPSBjb25maWd1cmF0aW9uLnJwY1tyZXF1ZXN0Lm1ldGhvZF07XG5cbiAgICAgICAgICAgICAgICBpZiAoZnVuYyA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgIExvZ2dlci5lcnJvcihcIk1ldGhvZCBcIiArIHJlcXVlc3QubWV0aG9kICsgXCIgbm90IHJlZ2lzdGVyZWQgaW4gY2xpZW50XCIpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGZ1bmMocmVxdWVzdC5wYXJhbXMsIHJlcXVlc3QpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgICAgIExvZ2dlci5lcnJvcignRXhjZXB0aW9uIHByb2Nlc3NpbmcgcmVxdWVzdDogJyArIEpTT04uc3RyaW5naWZ5KHJlcXVlc3QpKTtcbiAgICAgICAgICAgICAgICBMb2dnZXIuZXJyb3IoZXJyKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG5cbiAgICB0aGlzLnNlbmQgPSBmdW5jdGlvbihtZXRob2QsIHBhcmFtcywgY2FsbGJhY2spIHtcbiAgICAgICAgaWYgKG1ldGhvZCAhPT0gJ3BpbmcnKSB7XG4gICAgICAgICAgICBMb2dnZXIuZGVidWcoJ1JlcXVlc3Q6IG1ldGhvZDonICsgbWV0aG9kICsgXCIgcGFyYW1zOlwiICsgSlNPTi5zdHJpbmdpZnkocGFyYW1zKSk7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgcmVxdWVzdFRpbWUgPSBEYXRlLm5vdygpO1xuXG4gICAgICAgIHJwYy5lbmNvZGUobWV0aG9kLCBwYXJhbXMsIGZ1bmN0aW9uKGVycm9yLCByZXN1bHQpIHtcbiAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgIExvZ2dlci5lcnJvcihcIkVSUk9SOlwiICsgZXJyb3IubWVzc2FnZSArIFwiIGluIFJlcXVlc3Q6IG1ldGhvZDpcIiArXG4gICAgICAgICAgICAgICAgICAgICAgICBtZXRob2QgKyBcIiBwYXJhbXM6XCIgKyBKU09OLnN0cmluZ2lmeShwYXJhbXMpICsgXCIgcmVxdWVzdDpcIiArXG4gICAgICAgICAgICAgICAgICAgICAgICBlcnJvci5yZXF1ZXN0KTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yLmRhdGEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIExvZ2dlci5lcnJvcihcIkVSUk9SIERBVEE6XCIgKyBKU09OLnN0cmluZ2lmeShlcnJvci5kYXRhKSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGNhdGNoIChlKSB7fVxuICAgICAgICAgICAgICAgIGVycm9yLnJlcXVlc3RUaW1lID0gcmVxdWVzdFRpbWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoY2FsbGJhY2spIHtcbiAgICAgICAgICAgICAgICBpZiAocmVzdWx0ICE9IHVuZGVmaW5lZCAmJiByZXN1bHQudmFsdWUgIT09ICdwb25nJykge1xuICAgICAgICAgICAgICAgICAgICBMb2dnZXIuZGVidWcoJ1Jlc3BvbnNlOiAnICsgSlNPTi5zdHJpbmdpZnkocmVzdWx0KSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNhbGxiYWNrKGVycm9yLCByZXN1bHQpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiB1cGRhdGVOb3RSZWNvbm5lY3RJZkxlc3NUaGFuKCkge1xuICAgICAgICBMb2dnZXIuZGVidWcoXCJub3RSZWNvbm5lY3RJZk51bUxlc3NUaGFuID0gXCIgKyBwaW5nTmV4dE51bSArICcgKG9sZD0nICtcbiAgICAgICAgICAgIG5vdFJlY29ubmVjdElmTnVtTGVzc1RoYW4gKyAnKScpO1xuICAgICAgICBub3RSZWNvbm5lY3RJZk51bUxlc3NUaGFuID0gcGluZ05leHROdW07XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gc2VuZFBpbmcoKSB7XG4gICAgICAgIGlmIChlbmFibGVkUGluZ3MpIHtcbiAgICAgICAgICAgIHZhciBwYXJhbXMgPSBudWxsO1xuICAgICAgICAgICAgaWYgKHBpbmdOZXh0TnVtID09IDAgfHwgcGluZ05leHROdW0gPT0gbm90UmVjb25uZWN0SWZOdW1MZXNzVGhhbikge1xuICAgICAgICAgICAgICAgIHBhcmFtcyA9IHtcbiAgICAgICAgICAgICAgICAgICAgaW50ZXJ2YWw6IGNvbmZpZ3VyYXRpb24uaGVhcnRiZWF0IHx8IFBJTkdfSU5URVJWQUxcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcGluZ05leHROdW0rKztcblxuICAgICAgICAgICAgc2VsZi5zZW5kKCdwaW5nJywgcGFyYW1zLCAoZnVuY3Rpb24ocGluZ051bSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmdW5jdGlvbihlcnJvciwgcmVzdWx0KSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFwiRXJyb3IgaW4gcGluZyByZXF1ZXN0ICNcIiArIHBpbmdOdW0gKyBcIiAoXCIgK1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yLm1lc3NhZ2UgKyBcIilcIik7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocGluZ051bSA+IG5vdFJlY29ubmVjdElmTnVtTGVzc1RoYW4pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbmFibGVkUGluZ3MgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB1cGRhdGVOb3RSZWNvbm5lY3RJZkxlc3NUaGFuKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFwiU2VydmVyIGRpZCBub3QgcmVzcG9uZCB0byBwaW5nIG1lc3NhZ2UgI1wiICtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGluZ051bSArIFwiLiBSZWNvbm5lY3RpbmcuLi4gXCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdzLnJlY29ubmVjdFdzKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KShwaW5nTmV4dE51bSkpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFwiVHJ5aW5nIHRvIHNlbmQgcGluZywgYnV0IHBpbmcgaXMgbm90IGVuYWJsZWRcIik7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKlxuICAgICogSWYgY29uZmlndXJhdGlvbi5oZWFyYmVhdCBoYXMgYW55IHZhbHVlLCB0aGUgcGluZy1wb25nIHdpbGwgd29yayB3aXRoIHRoZSBpbnRlcnZhbFxuICAgICogb2YgY29uZmlndXJhdGlvbi5oZWFyYmVhdFxuICAgICovXG4gICAgZnVuY3Rpb24gdXNlUGluZygpIHtcbiAgICAgICAgaWYgKCFwaW5nUG9uZ1N0YXJ0ZWQpIHtcbiAgICAgICAgICAgIExvZ2dlci5kZWJ1ZyhcIlN0YXJ0aW5nIHBpbmcgKGlmIGNvbmZpZ3VyZWQpXCIpXG4gICAgICAgICAgICBwaW5nUG9uZ1N0YXJ0ZWQgPSB0cnVlO1xuXG4gICAgICAgICAgICBpZiAoY29uZmlndXJhdGlvbi5oZWFydGJlYXQgIT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgcGluZ0ludGVydmFsID0gc2V0SW50ZXJ2YWwoc2VuZFBpbmcsIGNvbmZpZ3VyYXRpb24uaGVhcnRiZWF0KTtcbiAgICAgICAgICAgICAgICBzZW5kUGluZygpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgdGhpcy5jbG9zZSA9IGZ1bmN0aW9uKCkge1xuICAgICAgICBMb2dnZXIuZGVidWcoXCJDbG9zaW5nIGpzb25ScGNDbGllbnQgZXhwbGljaXRseSBieSBjbGllbnRcIik7XG5cbiAgICAgICAgaWYgKHBpbmdJbnRlcnZhbCAhPSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIExvZ2dlci5kZWJ1ZyhcIkNsZWFyaW5nIHBpbmcgaW50ZXJ2YWxcIik7XG4gICAgICAgICAgICBjbGVhckludGVydmFsKHBpbmdJbnRlcnZhbCk7XG4gICAgICAgIH1cbiAgICAgICAgcGluZ1BvbmdTdGFydGVkID0gZmFsc2U7XG4gICAgICAgIGVuYWJsZWRQaW5ncyA9IGZhbHNlO1xuXG4gICAgICAgIGlmIChjb25maWd1cmF0aW9uLnNlbmRDbG9zZU1lc3NhZ2UpIHtcbiAgICAgICAgICAgIExvZ2dlci5kZWJ1ZyhcIlNlbmRpbmcgY2xvc2UgbWVzc2FnZVwiKVxuICAgICAgICAgICAgdGhpcy5zZW5kKCdjbG9zZVNlc3Npb24nLCBudWxsLCBmdW5jdGlvbihlcnJvciwgcmVzdWx0KSB7XG4gICAgICAgICAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgIExvZ2dlci5lcnJvcihcIkVycm9yIHNlbmRpbmcgY2xvc2UgbWVzc2FnZTogXCIgKyBKU09OLnN0cmluZ2lmeShlcnJvcikpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB3cy5jbG9zZSgpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0gZWxzZSB7XG5cdFx0XHR3cy5jbG9zZSgpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gVGhpcyBtZXRob2QgaXMgb25seSBmb3IgdGVzdGluZ1xuICAgIHRoaXMuZm9yY2VDbG9zZSA9IGZ1bmN0aW9uKG1pbGxpcykge1xuICAgICAgICB3cy5mb3JjZUNsb3NlKG1pbGxpcyk7XG4gICAgfVxuXG4gICAgdGhpcy5yZWNvbm5lY3QgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgd3MucmVjb25uZWN0V3MoKTtcbiAgICB9XG59XG5cblxubW9kdWxlLmV4cG9ydHMgPSBKc29uUnBjQ2xpZW50O1xuIiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNCBLdXJlbnRvIChodHRwOi8va3VyZW50by5vcmcvKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbnZhciBXZWJTb2NrZXRXaXRoUmVjb25uZWN0aW9uICA9IHJlcXVpcmUoJy4vd2ViU29ja2V0V2l0aFJlY29ubmVjdGlvbicpO1xuXG5cbmV4cG9ydHMuV2ViU29ja2V0V2l0aFJlY29ubmVjdGlvbiAgPSBXZWJTb2NrZXRXaXRoUmVjb25uZWN0aW9uOyIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTMtMjAxNSBLdXJlbnRvIChodHRwOi8va3VyZW50by5vcmcvKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuXCJ1c2Ugc3RyaWN0XCI7XG5cbnZhciBCcm93c2VyV2ViU29ja2V0ID0gZ2xvYmFsLldlYlNvY2tldCB8fCBnbG9iYWwuTW96V2ViU29ja2V0O1xuXG52YXIgTG9nZ2VyID0gY29uc29sZTtcblxuLyoqXG4gKiBHZXQgZWl0aGVyIHRoZSBgV2ViU29ja2V0YCBvciBgTW96V2ViU29ja2V0YCBnbG9iYWxzXG4gKiBpbiB0aGUgYnJvd3NlciBvciB0cnkgdG8gcmVzb2x2ZSBXZWJTb2NrZXQtY29tcGF0aWJsZVxuICogaW50ZXJmYWNlIGV4cG9zZWQgYnkgYHdzYCBmb3IgTm9kZS1saWtlIGVudmlyb25tZW50LlxuICovXG5cbi8qdmFyIFdlYlNvY2tldCA9IEJyb3dzZXJXZWJTb2NrZXQ7XG5pZiAoIVdlYlNvY2tldCAmJiB0eXBlb2Ygd2luZG93ID09PSAndW5kZWZpbmVkJykge1xuICAgIHRyeSB7XG4gICAgICAgIFdlYlNvY2tldCA9IHJlcXVpcmUoJ3dzJyk7XG4gICAgfSBjYXRjaCAoZSkgeyB9XG59Ki9cblxuLy92YXIgU29ja0pTID0gcmVxdWlyZSgnc29ja2pzLWNsaWVudCcpO1xuXG52YXIgTUFYX1JFVFJJRVMgPSAyMDAwOyAvLyBGb3JldmVyLi4uXG52YXIgUkVUUllfVElNRV9NUyA9IDMwMDA7IC8vIEZJWE1FOiBJbXBsZW1lbnQgZXhwb25lbnRpYWwgd2FpdCB0aW1lcy4uLlxuXG52YXIgQ09OTkVDVElORyA9IDA7XG52YXIgT1BFTiA9IDE7XG52YXIgQ0xPU0lORyA9IDI7XG52YXIgQ0xPU0VEID0gMztcblxuLypcbmNvbmZpZyA9IHtcblx0XHR1cmkgOiB3c1VyaSxcblx0XHR1c2VTb2NrSlMgOiB0cnVlICh1c2UgU29ja0pTKSAvIGZhbHNlICh1c2UgV2ViU29ja2V0KSBieSBkZWZhdWx0LFxuXHRcdG9uY29ubmVjdGVkIDogY2FsbGJhY2sgbWV0aG9kIHRvIGludm9rZSB3aGVuIGNvbm5lY3Rpb24gaXMgc3VjY2Vzc2Z1bCxcblx0XHRvbmRpc2Nvbm5lY3QgOiBjYWxsYmFjayBtZXRob2QgdG8gaW52b2tlIHdoZW4gdGhlIGNvbm5lY3Rpb24gaXMgbG9zdCxcblx0XHRvbnJlY29ubmVjdGluZyA6IGNhbGxiYWNrIG1ldGhvZCB0byBpbnZva2Ugd2hlbiB0aGUgY2xpZW50IGlzIHJlY29ubmVjdGluZyxcblx0XHRvbnJlY29ubmVjdGVkIDogY2FsbGJhY2sgbWV0aG9kIHRvIGludm9rZSB3aGVuIHRoZSBjbGllbnQgc3VjY2Vzc2Z1bGx5IHJlY29ubmVjdHMsXG5cdH07XG4qL1xuZnVuY3Rpb24gV2ViU29ja2V0V2l0aFJlY29ubmVjdGlvbihjb25maWcpIHtcblxuICAgIHZhciBjbG9zaW5nID0gZmFsc2U7XG4gICAgdmFyIHJlZ2lzdGVyTWVzc2FnZUhhbmRsZXI7XG4gICAgdmFyIHdzVXJpID0gY29uZmlnLnVyaTtcbiAgICB2YXIgdXNlU29ja0pTID0gY29uZmlnLnVzZVNvY2tKUztcbiAgICB2YXIgcmVjb25uZWN0aW5nID0gZmFsc2U7XG5cbiAgICB2YXIgZm9yY2luZ0Rpc2Nvbm5lY3Rpb24gPSBmYWxzZTtcblxuICAgIHZhciB3cztcblxuICAgIGlmICh1c2VTb2NrSlMpIHtcbiAgICAgICAgd3MgPSBuZXcgU29ja0pTKHdzVXJpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICB3cyA9IG5ldyBXZWJTb2NrZXQod3NVcmkpO1xuICAgIH1cblxuICAgIHdzLm9ub3BlbiA9IGZ1bmN0aW9uKCkge1xuICAgICAgICBsb2dDb25uZWN0ZWQod3MsIHdzVXJpKTtcbiAgICAgICAgaWYgKGNvbmZpZy5vbmNvbm5lY3RlZCkge1xuICAgICAgICAgICAgY29uZmlnLm9uY29ubmVjdGVkKCk7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgd3Mub25lcnJvciA9IGZ1bmN0aW9uKGVycm9yKSB7XG4gICAgICAgIExvZ2dlci5lcnJvcihcIkNvdWxkIG5vdCBjb25uZWN0IHRvIFwiICsgd3NVcmkgKyBcIiAoaW52b2tpbmcgb25lcnJvciBpZiBkZWZpbmVkKVwiLCBlcnJvcik7XG4gICAgICAgIGlmIChjb25maWcub25lcnJvcikge1xuICAgICAgICAgICAgY29uZmlnLm9uZXJyb3IoZXJyb3IpO1xuICAgICAgICB9XG4gICAgfTtcblxuICAgIGZ1bmN0aW9uIGxvZ0Nvbm5lY3RlZCh3cywgd3NVcmkpIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIExvZ2dlci5kZWJ1ZyhcIldlYlNvY2tldCBjb25uZWN0ZWQgdG8gXCIgKyB3c1VyaSk7XG4gICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgIExvZ2dlci5lcnJvcihlKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHZhciByZWNvbm5lY3Rpb25PbkNsb3NlID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIGlmICh3cy5yZWFkeVN0YXRlID09PSBDTE9TRUQpIHtcbiAgICAgICAgICAgIGlmIChjbG9zaW5nKSB7XG4gICAgICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFwiQ29ubmVjdGlvbiBjbG9zZWQgYnkgdXNlclwiKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFwiQ29ubmVjdGlvbiBjbG9zZWQgdW5leHBlY3RlY2x5LiBSZWNvbm5lY3RpbmcuLi5cIik7XG4gICAgICAgICAgICAgICAgcmVjb25uZWN0VG9TYW1lVXJpKE1BWF9SRVRSSUVTLCAxKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIExvZ2dlci5kZWJ1ZyhcIkNsb3NlIGNhbGxiYWNrIGZyb20gcHJldmlvdXMgd2Vic29ja2V0LiBJZ25vcmluZyBpdFwiKTtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICB3cy5vbmNsb3NlID0gcmVjb25uZWN0aW9uT25DbG9zZTtcblxuICAgIGZ1bmN0aW9uIHJlY29ubmVjdFRvU2FtZVVyaShtYXhSZXRyaWVzLCBudW1SZXRyaWVzKSB7XG4gICAgICAgIExvZ2dlci5kZWJ1ZyhcInJlY29ubmVjdFRvU2FtZVVyaSAoYXR0ZW1wdCAjXCIgKyBudW1SZXRyaWVzICsgXCIsIG1heD1cIiArIG1heFJldHJpZXMgKyBcIilcIik7XG5cbiAgICAgICAgaWYgKG51bVJldHJpZXMgPT09IDEpIHtcbiAgICAgICAgICAgIGlmIChyZWNvbm5lY3RpbmcpIHtcbiAgICAgICAgICAgICAgICBMb2dnZXIud2FybihcIlRyeWluZyB0byByZWNvbm5lY3RUb05ld1VyaSB3aGVuIHJlY29ubmVjdGluZy4uLiBJZ25vcmluZyB0aGlzIHJlY29ubmVjdGlvbi5cIilcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJlY29ubmVjdGluZyA9IHRydWU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChjb25maWcub25yZWNvbm5lY3RpbmcpIHtcbiAgICAgICAgICAgICAgICBjb25maWcub25yZWNvbm5lY3RpbmcoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChmb3JjaW5nRGlzY29ubmVjdGlvbikge1xuICAgICAgICAgICAgcmVjb25uZWN0VG9OZXdVcmkobWF4UmV0cmllcywgbnVtUmV0cmllcywgd3NVcmkpO1xuXG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBpZiAoY29uZmlnLm5ld1dzVXJpT25SZWNvbm5lY3Rpb24pIHtcbiAgICAgICAgICAgICAgICBjb25maWcubmV3V3NVcmlPblJlY29ubmVjdGlvbihmdW5jdGlvbihlcnJvciwgbmV3V3NVcmkpIHtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIExvZ2dlci5kZWJ1ZyhlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlY29ubmVjdFRvU2FtZVVyaShtYXhSZXRyaWVzLCBudW1SZXRyaWVzICsgMSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9LCBSRVRSWV9USU1FX01TKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlY29ubmVjdFRvTmV3VXJpKG1heFJldHJpZXMsIG51bVJldHJpZXMsIG5ld1dzVXJpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJlY29ubmVjdFRvTmV3VXJpKG1heFJldHJpZXMsIG51bVJldHJpZXMsIHdzVXJpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIFRPRE8gVGVzdCByZXRyaWVzLiBIb3cgdG8gZm9yY2Ugbm90IGNvbm5lY3Rpb24/XG4gICAgZnVuY3Rpb24gcmVjb25uZWN0VG9OZXdVcmkobWF4UmV0cmllcywgbnVtUmV0cmllcywgcmVjb25uZWN0V3NVcmkpIHtcbiAgICAgICAgTG9nZ2VyLmRlYnVnKFwiUmVjb25uZWN0aW9uIGF0dGVtcHQgI1wiICsgbnVtUmV0cmllcyk7XG5cbiAgICAgICAgd3MuY2xvc2UoKTtcblxuICAgICAgICB3c1VyaSA9IHJlY29ubmVjdFdzVXJpIHx8IHdzVXJpO1xuXG4gICAgICAgIHZhciBuZXdXcztcbiAgICAgICAgaWYgKHVzZVNvY2tKUykge1xuICAgICAgICAgICAgbmV3V3MgPSBuZXcgU29ja0pTKHdzVXJpKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIG5ld1dzID0gbmV3IFdlYlNvY2tldCh3c1VyaSk7XG4gICAgICAgIH1cblxuICAgICAgICBuZXdXcy5vbm9wZW4gPSBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIExvZ2dlci5kZWJ1ZyhcIlJlY29ubmVjdGVkIGFmdGVyIFwiICsgbnVtUmV0cmllcyArIFwiIGF0dGVtcHRzLi4uXCIpO1xuICAgICAgICAgICAgbG9nQ29ubmVjdGVkKG5ld1dzLCB3c1VyaSk7XG4gICAgICAgICAgICByZWNvbm5lY3RpbmcgPSBmYWxzZTtcbiAgICAgICAgICAgIHJlZ2lzdGVyTWVzc2FnZUhhbmRsZXIoKTtcbiAgICAgICAgICAgIGlmIChjb25maWcub25yZWNvbm5lY3RlZCgpKSB7XG4gICAgICAgICAgICAgICAgY29uZmlnLm9ucmVjb25uZWN0ZWQoKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgbmV3V3Mub25jbG9zZSA9IHJlY29ubmVjdGlvbk9uQ2xvc2U7XG4gICAgICAgIH07XG5cbiAgICAgICAgdmFyIG9uRXJyb3JPckNsb3NlID0gZnVuY3Rpb24oZXJyb3IpIHtcbiAgICAgICAgICAgIExvZ2dlci53YXJuKFwiUmVjb25uZWN0aW9uIGVycm9yOiBcIiwgZXJyb3IpO1xuXG4gICAgICAgICAgICBpZiAobnVtUmV0cmllcyA9PT0gbWF4UmV0cmllcykge1xuICAgICAgICAgICAgICAgIGlmIChjb25maWcub25kaXNjb25uZWN0KSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbmZpZy5vbmRpc2Nvbm5lY3QoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlY29ubmVjdFRvU2FtZVVyaShtYXhSZXRyaWVzLCBudW1SZXRyaWVzICsgMSk7XG4gICAgICAgICAgICAgICAgfSwgUkVUUllfVElNRV9NUyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG5cbiAgICAgICAgbmV3V3Mub25lcnJvciA9IG9uRXJyb3JPckNsb3NlO1xuXG4gICAgICAgIHdzID0gbmV3V3M7XG4gICAgfVxuXG4gICAgdGhpcy5jbG9zZSA9IGZ1bmN0aW9uKCkge1xuICAgICAgICBjbG9zaW5nID0gdHJ1ZTtcbiAgICAgICAgd3MuY2xvc2UoKTtcbiAgICB9O1xuXG5cbiAgICAvLyBUaGlzIG1ldGhvZCBpcyBvbmx5IGZvciB0ZXN0aW5nXG4gICAgdGhpcy5mb3JjZUNsb3NlID0gZnVuY3Rpb24obWlsbGlzKSB7XG4gICAgICAgIExvZ2dlci5kZWJ1ZyhcIlRlc3Rpbmc6IEZvcmNlIFdlYlNvY2tldCBjbG9zZVwiKTtcblxuICAgICAgICBpZiAobWlsbGlzKSB7XG4gICAgICAgICAgICBMb2dnZXIuZGVidWcoXCJUZXN0aW5nOiBDaGFuZ2Ugd3NVcmkgZm9yIFwiICsgbWlsbGlzICsgXCIgbWlsbGlzIHRvIHNpbXVsYXRlIG5ldCBmYWlsdXJlXCIpO1xuICAgICAgICAgICAgdmFyIGdvb2RXc1VyaSA9IHdzVXJpO1xuICAgICAgICAgICAgd3NVcmkgPSBcIndzczovLzIxLjIzNC4xMi4zNC40OjQ0My9cIjtcblxuICAgICAgICAgICAgZm9yY2luZ0Rpc2Nvbm5lY3Rpb24gPSB0cnVlO1xuXG4gICAgICAgICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgIExvZ2dlci5kZWJ1ZyhcIlRlc3Rpbmc6IFJlY292ZXIgZ29vZCB3c1VyaSBcIiArIGdvb2RXc1VyaSk7XG4gICAgICAgICAgICAgICAgd3NVcmkgPSBnb29kV3NVcmk7XG5cbiAgICAgICAgICAgICAgICBmb3JjaW5nRGlzY29ubmVjdGlvbiA9IGZhbHNlO1xuXG4gICAgICAgICAgICB9LCBtaWxsaXMpO1xuICAgICAgICB9XG5cbiAgICAgICAgd3MuY2xvc2UoKTtcbiAgICB9O1xuXG4gICAgdGhpcy5yZWNvbm5lY3RXcyA9IGZ1bmN0aW9uKCkge1xuICAgICAgICBMb2dnZXIuZGVidWcoXCJyZWNvbm5lY3RXc1wiKTtcbiAgICAgICAgcmVjb25uZWN0VG9TYW1lVXJpKE1BWF9SRVRSSUVTLCAxLCB3c1VyaSk7XG4gICAgfTtcblxuICAgIHRoaXMuc2VuZCA9IGZ1bmN0aW9uKG1lc3NhZ2UpIHtcbiAgICAgICAgd3Muc2VuZChtZXNzYWdlKTtcbiAgICB9O1xuXG4gICAgdGhpcy5hZGRFdmVudExpc3RlbmVyID0gZnVuY3Rpb24odHlwZSwgY2FsbGJhY2spIHtcbiAgICAgICAgcmVnaXN0ZXJNZXNzYWdlSGFuZGxlciA9IGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgd3MuYWRkRXZlbnRMaXN0ZW5lcih0eXBlLCBjYWxsYmFjayk7XG4gICAgICAgIH07XG5cbiAgICAgICAgcmVnaXN0ZXJNZXNzYWdlSGFuZGxlcigpO1xuICAgIH07XG59XG5cbm1vZHVsZS5leHBvcnRzID0gV2ViU29ja2V0V2l0aFJlY29ubmVjdGlvbjtcbiIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTQgS3VyZW50byAoaHR0cDovL2t1cmVudG8ub3JnLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5cbnZhciBkZWZpbmVQcm9wZXJ0eV9JRTggPSBmYWxzZVxuaWYoT2JqZWN0LmRlZmluZVByb3BlcnR5KVxue1xuICB0cnlcbiAge1xuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh7fSwgXCJ4XCIsIHt9KTtcbiAgfVxuICBjYXRjaChlKVxuICB7XG4gICAgZGVmaW5lUHJvcGVydHlfSUU4ID0gdHJ1ZVxuICB9XG59XG5cbi8vIGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0phdmFTY3JpcHQvUmVmZXJlbmNlL0dsb2JhbF9PYmplY3RzL0Z1bmN0aW9uL2JpbmRcbmlmICghRnVuY3Rpb24ucHJvdG90eXBlLmJpbmQpIHtcbiAgRnVuY3Rpb24ucHJvdG90eXBlLmJpbmQgPSBmdW5jdGlvbihvVGhpcykge1xuICAgIGlmICh0eXBlb2YgdGhpcyAhPT0gJ2Z1bmN0aW9uJykge1xuICAgICAgLy8gY2xvc2VzdCB0aGluZyBwb3NzaWJsZSB0byB0aGUgRUNNQVNjcmlwdCA1XG4gICAgICAvLyBpbnRlcm5hbCBJc0NhbGxhYmxlIGZ1bmN0aW9uXG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdGdW5jdGlvbi5wcm90b3R5cGUuYmluZCAtIHdoYXQgaXMgdHJ5aW5nIHRvIGJlIGJvdW5kIGlzIG5vdCBjYWxsYWJsZScpO1xuICAgIH1cblxuICAgIHZhciBhQXJncyAgID0gQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzLCAxKSxcbiAgICAgICAgZlRvQmluZCA9IHRoaXMsXG4gICAgICAgIGZOT1AgICAgPSBmdW5jdGlvbigpIHt9LFxuICAgICAgICBmQm91bmQgID0gZnVuY3Rpb24oKSB7XG4gICAgICAgICAgcmV0dXJuIGZUb0JpbmQuYXBwbHkodGhpcyBpbnN0YW5jZW9mIGZOT1AgJiYgb1RoaXNcbiAgICAgICAgICAgICAgICAgPyB0aGlzXG4gICAgICAgICAgICAgICAgIDogb1RoaXMsXG4gICAgICAgICAgICAgICAgIGFBcmdzLmNvbmNhdChBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMpKSk7XG4gICAgICAgIH07XG5cbiAgICBmTk9QLnByb3RvdHlwZSA9IHRoaXMucHJvdG90eXBlO1xuICAgIGZCb3VuZC5wcm90b3R5cGUgPSBuZXcgZk5PUCgpO1xuXG4gICAgcmV0dXJuIGZCb3VuZDtcbiAgfTtcbn1cblxuXG52YXIgRXZlbnRFbWl0dGVyID0gcmVxdWlyZSgnZXZlbnRzJykuRXZlbnRFbWl0dGVyO1xuXG52YXIgaW5oZXJpdHMgPSByZXF1aXJlKCdpbmhlcml0cycpO1xuXG52YXIgcGFja2VycyA9IHJlcXVpcmUoJy4vcGFja2VycycpO1xudmFyIE1hcHBlciA9IHJlcXVpcmUoJy4vTWFwcGVyJyk7XG5cblxudmFyIEJBU0VfVElNRU9VVCA9IDUwMDA7XG5cblxuZnVuY3Rpb24gdW5pZnlSZXNwb25zZU1ldGhvZHMocmVzcG9uc2VNZXRob2RzKVxue1xuICBpZighcmVzcG9uc2VNZXRob2RzKSByZXR1cm4ge307XG5cbiAgZm9yKHZhciBrZXkgaW4gcmVzcG9uc2VNZXRob2RzKVxuICB7XG4gICAgdmFyIHZhbHVlID0gcmVzcG9uc2VNZXRob2RzW2tleV07XG5cbiAgICBpZih0eXBlb2YgdmFsdWUgPT0gJ3N0cmluZycpXG4gICAgICByZXNwb25zZU1ldGhvZHNba2V5XSA9XG4gICAgICB7XG4gICAgICAgIHJlc3BvbnNlOiB2YWx1ZVxuICAgICAgfVxuICB9O1xuXG4gIHJldHVybiByZXNwb25zZU1ldGhvZHM7XG59O1xuXG5mdW5jdGlvbiB1bmlmeVRyYW5zcG9ydCh0cmFuc3BvcnQpXG57XG4gIGlmKCF0cmFuc3BvcnQpIHJldHVybjtcblxuICAvLyBUcmFuc3BvcnQgYXMgYSBmdW5jdGlvblxuICBpZih0cmFuc3BvcnQgaW5zdGFuY2VvZiBGdW5jdGlvbilcbiAgICByZXR1cm4ge3NlbmQ6IHRyYW5zcG9ydH07XG5cbiAgLy8gV2ViU29ja2V0ICYgRGF0YUNoYW5uZWxcbiAgaWYodHJhbnNwb3J0LnNlbmQgaW5zdGFuY2VvZiBGdW5jdGlvbilcbiAgICByZXR1cm4gdHJhbnNwb3J0O1xuXG4gIC8vIE1lc3NhZ2UgQVBJIChJbnRlci13aW5kb3cgJiBXZWJXb3JrZXIpXG4gIGlmKHRyYW5zcG9ydC5wb3N0TWVzc2FnZSBpbnN0YW5jZW9mIEZ1bmN0aW9uKVxuICB7XG4gICAgdHJhbnNwb3J0LnNlbmQgPSB0cmFuc3BvcnQucG9zdE1lc3NhZ2U7XG4gICAgcmV0dXJuIHRyYW5zcG9ydDtcbiAgfVxuXG4gIC8vIFN0cmVhbSBBUElcbiAgaWYodHJhbnNwb3J0LndyaXRlIGluc3RhbmNlb2YgRnVuY3Rpb24pXG4gIHtcbiAgICB0cmFuc3BvcnQuc2VuZCA9IHRyYW5zcG9ydC53cml0ZTtcbiAgICByZXR1cm4gdHJhbnNwb3J0O1xuICB9XG5cbiAgLy8gVHJhbnNwb3J0cyB0aGF0IG9ubHkgY2FuIHJlY2VpdmUgbWVzc2FnZXMsIGJ1dCBub3Qgc2VuZFxuICBpZih0cmFuc3BvcnQub25tZXNzYWdlICE9PSB1bmRlZmluZWQpIHJldHVybjtcbiAgaWYodHJhbnNwb3J0LnBhdXNlIGluc3RhbmNlb2YgRnVuY3Rpb24pIHJldHVybjtcblxuICB0aHJvdyBuZXcgU3ludGF4RXJyb3IoXCJUcmFuc3BvcnQgaXMgbm90IGEgZnVuY3Rpb24gbm9yIGEgdmFsaWQgb2JqZWN0XCIpO1xufTtcblxuXG4vKipcbiAqIFJlcHJlc2VudGF0aW9uIG9mIGEgUlBDIG5vdGlmaWNhdGlvblxuICpcbiAqIEBjbGFzc1xuICpcbiAqIEBjb25zdHJ1Y3RvclxuICpcbiAqIEBwYXJhbSB7U3RyaW5nfSBtZXRob2QgLW1ldGhvZCBvZiB0aGUgbm90aWZpY2F0aW9uXG4gKiBAcGFyYW0gcGFyYW1zIC0gcGFyYW1ldGVycyBvZiB0aGUgbm90aWZpY2F0aW9uXG4gKi9cbmZ1bmN0aW9uIFJwY05vdGlmaWNhdGlvbihtZXRob2QsIHBhcmFtcylcbntcbiAgaWYoZGVmaW5lUHJvcGVydHlfSUU4KVxuICB7XG4gICAgdGhpcy5tZXRob2QgPSBtZXRob2RcbiAgICB0aGlzLnBhcmFtcyA9IHBhcmFtc1xuICB9XG4gIGVsc2VcbiAge1xuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0aGlzLCAnbWV0aG9kJywge3ZhbHVlOiBtZXRob2QsIGVudW1lcmFibGU6IHRydWV9KTtcbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkodGhpcywgJ3BhcmFtcycsIHt2YWx1ZTogcGFyYW1zLCBlbnVtZXJhYmxlOiB0cnVlfSk7XG4gIH1cbn07XG5cblxuLyoqXG4gKiBAY2xhc3NcbiAqXG4gKiBAY29uc3RydWN0b3JcbiAqXG4gKiBAcGFyYW0ge29iamVjdH0gcGFja2VyXG4gKlxuICogQHBhcmFtIHtvYmplY3R9IFtvcHRpb25zXVxuICpcbiAqIEBwYXJhbSB7b2JqZWN0fSBbdHJhbnNwb3J0XVxuICpcbiAqIEBwYXJhbSB7RnVuY3Rpb259IFtvblJlcXVlc3RdXG4gKi9cbmZ1bmN0aW9uIFJwY0J1aWxkZXIocGFja2VyLCBvcHRpb25zLCB0cmFuc3BvcnQsIG9uUmVxdWVzdClcbntcbiAgdmFyIHNlbGYgPSB0aGlzO1xuXG4gIGlmKCFwYWNrZXIpXG4gICAgdGhyb3cgbmV3IFN5bnRheEVycm9yKCdQYWNrZXIgaXMgbm90IGRlZmluZWQnKTtcblxuICBpZighcGFja2VyLnBhY2sgfHwgIXBhY2tlci51bnBhY2spXG4gICAgdGhyb3cgbmV3IFN5bnRheEVycm9yKCdQYWNrZXIgaXMgaW52YWxpZCcpO1xuXG4gIHZhciByZXNwb25zZU1ldGhvZHMgPSB1bmlmeVJlc3BvbnNlTWV0aG9kcyhwYWNrZXIucmVzcG9uc2VNZXRob2RzKTtcblxuXG4gIGlmKG9wdGlvbnMgaW5zdGFuY2VvZiBGdW5jdGlvbilcbiAge1xuICAgIGlmKHRyYW5zcG9ydCAhPSB1bmRlZmluZWQpXG4gICAgICB0aHJvdyBuZXcgU3ludGF4RXJyb3IoXCJUaGVyZSBjYW4ndCBiZSBwYXJhbWV0ZXJzIGFmdGVyIG9uUmVxdWVzdFwiKTtcblxuICAgIG9uUmVxdWVzdCA9IG9wdGlvbnM7XG4gICAgdHJhbnNwb3J0ID0gdW5kZWZpbmVkO1xuICAgIG9wdGlvbnMgICA9IHVuZGVmaW5lZDtcbiAgfTtcblxuICBpZihvcHRpb25zICYmIG9wdGlvbnMuc2VuZCBpbnN0YW5jZW9mIEZ1bmN0aW9uKVxuICB7XG4gICAgaWYodHJhbnNwb3J0ICYmICEodHJhbnNwb3J0IGluc3RhbmNlb2YgRnVuY3Rpb24pKVxuICAgICAgdGhyb3cgbmV3IFN5bnRheEVycm9yKFwiT25seSBhIGZ1bmN0aW9uIGNhbiBiZSBhZnRlciB0cmFuc3BvcnRcIik7XG5cbiAgICBvblJlcXVlc3QgPSB0cmFuc3BvcnQ7XG4gICAgdHJhbnNwb3J0ID0gb3B0aW9ucztcbiAgICBvcHRpb25zICAgPSB1bmRlZmluZWQ7XG4gIH07XG5cbiAgaWYodHJhbnNwb3J0IGluc3RhbmNlb2YgRnVuY3Rpb24pXG4gIHtcbiAgICBpZihvblJlcXVlc3QgIT0gdW5kZWZpbmVkKVxuICAgICAgdGhyb3cgbmV3IFN5bnRheEVycm9yKFwiVGhlcmUgY2FuJ3QgYmUgcGFyYW1ldGVycyBhZnRlciBvblJlcXVlc3RcIik7XG5cbiAgICBvblJlcXVlc3QgPSB0cmFuc3BvcnQ7XG4gICAgdHJhbnNwb3J0ID0gdW5kZWZpbmVkO1xuICB9O1xuXG4gIGlmKHRyYW5zcG9ydCAmJiB0cmFuc3BvcnQuc2VuZCBpbnN0YW5jZW9mIEZ1bmN0aW9uKVxuICAgIGlmKG9uUmVxdWVzdCAmJiAhKG9uUmVxdWVzdCBpbnN0YW5jZW9mIEZ1bmN0aW9uKSlcbiAgICAgIHRocm93IG5ldyBTeW50YXhFcnJvcihcIk9ubHkgYSBmdW5jdGlvbiBjYW4gYmUgYWZ0ZXIgdHJhbnNwb3J0XCIpO1xuXG4gIG9wdGlvbnMgPSBvcHRpb25zIHx8IHt9O1xuXG5cbiAgRXZlbnRFbWl0dGVyLmNhbGwodGhpcyk7XG5cbiAgaWYob25SZXF1ZXN0KVxuICAgIHRoaXMub24oJ3JlcXVlc3QnLCBvblJlcXVlc3QpO1xuXG5cbiAgaWYoZGVmaW5lUHJvcGVydHlfSUU4KVxuICAgIHRoaXMucGVlcklEID0gb3B0aW9ucy5wZWVySURcbiAgZWxzZVxuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0aGlzLCAncGVlcklEJywge3ZhbHVlOiBvcHRpb25zLnBlZXJJRH0pO1xuXG4gIHZhciBtYXhfcmV0cmllcyA9IG9wdGlvbnMubWF4X3JldHJpZXMgfHwgMDtcblxuXG4gIGZ1bmN0aW9uIHRyYW5zcG9ydE1lc3NhZ2UoZXZlbnQpXG4gIHtcbiAgICBzZWxmLmRlY29kZShldmVudC5kYXRhIHx8IGV2ZW50KTtcbiAgfTtcblxuICB0aGlzLmdldFRyYW5zcG9ydCA9IGZ1bmN0aW9uKClcbiAge1xuICAgIHJldHVybiB0cmFuc3BvcnQ7XG4gIH1cbiAgdGhpcy5zZXRUcmFuc3BvcnQgPSBmdW5jdGlvbih2YWx1ZSlcbiAge1xuICAgIC8vIFJlbW92ZSBsaXN0ZW5lciBmcm9tIG9sZCB0cmFuc3BvcnRcbiAgICBpZih0cmFuc3BvcnQpXG4gICAge1xuICAgICAgLy8gVzNDIHRyYW5zcG9ydHNcbiAgICAgIGlmKHRyYW5zcG9ydC5yZW1vdmVFdmVudExpc3RlbmVyKVxuICAgICAgICB0cmFuc3BvcnQucmVtb3ZlRXZlbnRMaXN0ZW5lcignbWVzc2FnZScsIHRyYW5zcG9ydE1lc3NhZ2UpO1xuXG4gICAgICAvLyBOb2RlLmpzIFN0cmVhbXMgQVBJXG4gICAgICBlbHNlIGlmKHRyYW5zcG9ydC5yZW1vdmVMaXN0ZW5lcilcbiAgICAgICAgdHJhbnNwb3J0LnJlbW92ZUxpc3RlbmVyKCdkYXRhJywgdHJhbnNwb3J0TWVzc2FnZSk7XG4gICAgfTtcblxuICAgIC8vIFNldCBsaXN0ZW5lciBvbiBuZXcgdHJhbnNwb3J0XG4gICAgaWYodmFsdWUpXG4gICAge1xuICAgICAgLy8gVzNDIHRyYW5zcG9ydHNcbiAgICAgIGlmKHZhbHVlLmFkZEV2ZW50TGlzdGVuZXIpXG4gICAgICAgIHZhbHVlLmFkZEV2ZW50TGlzdGVuZXIoJ21lc3NhZ2UnLCB0cmFuc3BvcnRNZXNzYWdlKTtcblxuICAgICAgLy8gTm9kZS5qcyBTdHJlYW1zIEFQSVxuICAgICAgZWxzZSBpZih2YWx1ZS5hZGRMaXN0ZW5lcilcbiAgICAgICAgdmFsdWUuYWRkTGlzdGVuZXIoJ2RhdGEnLCB0cmFuc3BvcnRNZXNzYWdlKTtcbiAgICB9O1xuXG4gICAgdHJhbnNwb3J0ID0gdW5pZnlUcmFuc3BvcnQodmFsdWUpO1xuICB9XG5cbiAgaWYoIWRlZmluZVByb3BlcnR5X0lFOClcbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkodGhpcywgJ3RyYW5zcG9ydCcsXG4gICAge1xuICAgICAgZ2V0OiB0aGlzLmdldFRyYW5zcG9ydC5iaW5kKHRoaXMpLFxuICAgICAgc2V0OiB0aGlzLnNldFRyYW5zcG9ydC5iaW5kKHRoaXMpXG4gICAgfSlcblxuICB0aGlzLnNldFRyYW5zcG9ydCh0cmFuc3BvcnQpO1xuXG5cbiAgdmFyIHJlcXVlc3RfdGltZW91dCAgICAgID0gb3B0aW9ucy5yZXF1ZXN0X3RpbWVvdXQgICAgICB8fCBCQVNFX1RJTUVPVVQ7XG4gIHZhciBwaW5nX3JlcXVlc3RfdGltZW91dCA9IG9wdGlvbnMucGluZ19yZXF1ZXN0X3RpbWVvdXQgfHwgcmVxdWVzdF90aW1lb3V0O1xuICB2YXIgcmVzcG9uc2VfdGltZW91dCAgICAgPSBvcHRpb25zLnJlc3BvbnNlX3RpbWVvdXQgICAgIHx8IEJBU0VfVElNRU9VVDtcbiAgdmFyIGR1cGxpY2F0ZXNfdGltZW91dCAgID0gb3B0aW9ucy5kdXBsaWNhdGVzX3RpbWVvdXQgICB8fCBCQVNFX1RJTUVPVVQ7XG5cblxuICB2YXIgcmVxdWVzdElEID0gMDtcblxuICB2YXIgcmVxdWVzdHMgID0gbmV3IE1hcHBlcigpO1xuICB2YXIgcmVzcG9uc2VzID0gbmV3IE1hcHBlcigpO1xuICB2YXIgcHJvY2Vzc2VkUmVzcG9uc2VzID0gbmV3IE1hcHBlcigpO1xuXG4gIHZhciBtZXNzYWdlMktleSA9IHt9O1xuXG5cbiAgLyoqXG4gICAqIFN0b3JlIHRoZSByZXNwb25zZSB0byBwcmV2ZW50IHRvIHByb2Nlc3MgZHVwbGljYXRlIHJlcXVlc3QgbGF0ZXJcbiAgICovXG4gIGZ1bmN0aW9uIHN0b3JlUmVzcG9uc2UobWVzc2FnZSwgaWQsIGRlc3QpXG4gIHtcbiAgICB2YXIgcmVzcG9uc2UgPVxuICAgIHtcbiAgICAgIG1lc3NhZ2U6IG1lc3NhZ2UsXG4gICAgICAvKiogVGltZW91dCB0byBhdXRvLWNsZWFuIG9sZCByZXNwb25zZXMgKi9cbiAgICAgIHRpbWVvdXQ6IHNldFRpbWVvdXQoZnVuY3Rpb24oKVxuICAgICAge1xuICAgICAgICByZXNwb25zZXMucmVtb3ZlKGlkLCBkZXN0KTtcbiAgICAgIH0sXG4gICAgICByZXNwb25zZV90aW1lb3V0KVxuICAgIH07XG5cbiAgICByZXNwb25zZXMuc2V0KHJlc3BvbnNlLCBpZCwgZGVzdCk7XG4gIH07XG5cbiAgLyoqXG4gICAqIFN0b3JlIHRoZSByZXNwb25zZSB0byBpZ25vcmUgZHVwbGljYXRlZCBtZXNzYWdlcyBsYXRlclxuICAgKi9cbiAgZnVuY3Rpb24gc3RvcmVQcm9jZXNzZWRSZXNwb25zZShhY2ssIGZyb20pXG4gIHtcbiAgICB2YXIgdGltZW91dCA9IHNldFRpbWVvdXQoZnVuY3Rpb24oKVxuICAgIHtcbiAgICAgIHByb2Nlc3NlZFJlc3BvbnNlcy5yZW1vdmUoYWNrLCBmcm9tKTtcbiAgICB9LFxuICAgIGR1cGxpY2F0ZXNfdGltZW91dCk7XG5cbiAgICBwcm9jZXNzZWRSZXNwb25zZXMuc2V0KHRpbWVvdXQsIGFjaywgZnJvbSk7XG4gIH07XG5cblxuICAvKipcbiAgICogUmVwcmVzZW50YXRpb24gb2YgYSBSUEMgcmVxdWVzdFxuICAgKlxuICAgKiBAY2xhc3NcbiAgICogQGV4dGVuZHMgUnBjTm90aWZpY2F0aW9uXG4gICAqXG4gICAqIEBjb25zdHJ1Y3RvclxuICAgKlxuICAgKiBAcGFyYW0ge1N0cmluZ30gbWV0aG9kIC1tZXRob2Qgb2YgdGhlIG5vdGlmaWNhdGlvblxuICAgKiBAcGFyYW0gcGFyYW1zIC0gcGFyYW1ldGVycyBvZiB0aGUgbm90aWZpY2F0aW9uXG4gICAqIEBwYXJhbSB7SW50ZWdlcn0gaWQgLSBpZGVudGlmaWVyIG9mIHRoZSByZXF1ZXN0XG4gICAqIEBwYXJhbSBbZnJvbV0gLSBzb3VyY2Ugb2YgdGhlIG5vdGlmaWNhdGlvblxuICAgKi9cbiAgZnVuY3Rpb24gUnBjUmVxdWVzdChtZXRob2QsIHBhcmFtcywgaWQsIGZyb20sIHRyYW5zcG9ydClcbiAge1xuICAgIFJwY05vdGlmaWNhdGlvbi5jYWxsKHRoaXMsIG1ldGhvZCwgcGFyYW1zKTtcblxuICAgIHRoaXMuZ2V0VHJhbnNwb3J0ID0gZnVuY3Rpb24oKVxuICAgIHtcbiAgICAgIHJldHVybiB0cmFuc3BvcnQ7XG4gICAgfVxuICAgIHRoaXMuc2V0VHJhbnNwb3J0ID0gZnVuY3Rpb24odmFsdWUpXG4gICAge1xuICAgICAgdHJhbnNwb3J0ID0gdW5pZnlUcmFuc3BvcnQodmFsdWUpO1xuICAgIH1cblxuICAgIGlmKCFkZWZpbmVQcm9wZXJ0eV9JRTgpXG4gICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkodGhpcywgJ3RyYW5zcG9ydCcsXG4gICAgICB7XG4gICAgICAgIGdldDogdGhpcy5nZXRUcmFuc3BvcnQuYmluZCh0aGlzKSxcbiAgICAgICAgc2V0OiB0aGlzLnNldFRyYW5zcG9ydC5iaW5kKHRoaXMpXG4gICAgICB9KVxuXG4gICAgdmFyIHJlc3BvbnNlID0gcmVzcG9uc2VzLmdldChpZCwgZnJvbSk7XG5cbiAgICAvKipcbiAgICAgKiBAY29uc3RhbnQge0Jvb2xlYW59IGR1cGxpY2F0ZWRcbiAgICAgKi9cbiAgICBpZighKHRyYW5zcG9ydCB8fCBzZWxmLmdldFRyYW5zcG9ydCgpKSlcbiAgICB7XG4gICAgICBpZihkZWZpbmVQcm9wZXJ0eV9JRTgpXG4gICAgICAgIHRoaXMuZHVwbGljYXRlZCA9IEJvb2xlYW4ocmVzcG9uc2UpXG4gICAgICBlbHNlXG4gICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0aGlzLCAnZHVwbGljYXRlZCcsXG4gICAgICAgIHtcbiAgICAgICAgICB2YWx1ZTogQm9vbGVhbihyZXNwb25zZSlcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgdmFyIHJlc3BvbnNlTWV0aG9kID0gcmVzcG9uc2VNZXRob2RzW21ldGhvZF07XG5cbiAgICB0aGlzLnBhY2sgPSBwYWNrZXIucGFjay5iaW5kKHBhY2tlciwgdGhpcywgaWQpXG5cbiAgICAvKipcbiAgICAgKiBHZW5lcmF0ZSBhIHJlc3BvbnNlIHRvIHRoaXMgcmVxdWVzdFxuICAgICAqXG4gICAgICogQHBhcmFtIHtFcnJvcn0gW2Vycm9yXVxuICAgICAqIEBwYXJhbSB7Kn0gW3Jlc3VsdF1cbiAgICAgKlxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9XG4gICAgICovXG4gICAgdGhpcy5yZXBseSA9IGZ1bmN0aW9uKGVycm9yLCByZXN1bHQsIHRyYW5zcG9ydClcbiAgICB7XG4gICAgICAvLyBGaXggb3B0aW9uYWwgcGFyYW1ldGVyc1xuICAgICAgaWYoZXJyb3IgaW5zdGFuY2VvZiBGdW5jdGlvbiB8fCBlcnJvciAmJiBlcnJvci5zZW5kIGluc3RhbmNlb2YgRnVuY3Rpb24pXG4gICAgICB7XG4gICAgICAgIGlmKHJlc3VsdCAhPSB1bmRlZmluZWQpXG4gICAgICAgICAgdGhyb3cgbmV3IFN5bnRheEVycm9yKFwiVGhlcmUgY2FuJ3QgYmUgcGFyYW1ldGVycyBhZnRlciBjYWxsYmFja1wiKTtcblxuICAgICAgICB0cmFuc3BvcnQgPSBlcnJvcjtcbiAgICAgICAgcmVzdWx0ID0gbnVsbDtcbiAgICAgICAgZXJyb3IgPSB1bmRlZmluZWQ7XG4gICAgICB9XG5cbiAgICAgIGVsc2UgaWYocmVzdWx0IGluc3RhbmNlb2YgRnVuY3Rpb25cbiAgICAgIHx8IHJlc3VsdCAmJiByZXN1bHQuc2VuZCBpbnN0YW5jZW9mIEZ1bmN0aW9uKVxuICAgICAge1xuICAgICAgICBpZih0cmFuc3BvcnQgIT0gdW5kZWZpbmVkKVxuICAgICAgICAgIHRocm93IG5ldyBTeW50YXhFcnJvcihcIlRoZXJlIGNhbid0IGJlIHBhcmFtZXRlcnMgYWZ0ZXIgY2FsbGJhY2tcIik7XG5cbiAgICAgICAgdHJhbnNwb3J0ID0gcmVzdWx0O1xuICAgICAgICByZXN1bHQgPSBudWxsO1xuICAgICAgfTtcblxuICAgICAgdHJhbnNwb3J0ID0gdW5pZnlUcmFuc3BvcnQodHJhbnNwb3J0KTtcblxuICAgICAgLy8gRHVwbGljYXRlZCByZXF1ZXN0LCByZW1vdmUgb2xkIHJlc3BvbnNlIHRpbWVvdXRcbiAgICAgIGlmKHJlc3BvbnNlKVxuICAgICAgICBjbGVhclRpbWVvdXQocmVzcG9uc2UudGltZW91dCk7XG5cbiAgICAgIGlmKGZyb20gIT0gdW5kZWZpbmVkKVxuICAgICAge1xuICAgICAgICBpZihlcnJvcilcbiAgICAgICAgICBlcnJvci5kZXN0ID0gZnJvbTtcblxuICAgICAgICBpZihyZXN1bHQpXG4gICAgICAgICAgcmVzdWx0LmRlc3QgPSBmcm9tO1xuICAgICAgfTtcblxuICAgICAgdmFyIG1lc3NhZ2U7XG5cbiAgICAgIC8vIE5ldyByZXF1ZXN0IG9yIG92ZXJyaWRlbiBvbmUsIGNyZWF0ZSBuZXcgcmVzcG9uc2Ugd2l0aCBwcm92aWRlZCBkYXRhXG4gICAgICBpZihlcnJvciB8fCByZXN1bHQgIT0gdW5kZWZpbmVkKVxuICAgICAge1xuICAgICAgICBpZihzZWxmLnBlZXJJRCAhPSB1bmRlZmluZWQpXG4gICAgICAgIHtcbiAgICAgICAgICBpZihlcnJvcilcbiAgICAgICAgICAgIGVycm9yLmZyb20gPSBzZWxmLnBlZXJJRDtcbiAgICAgICAgICBlbHNlXG4gICAgICAgICAgICByZXN1bHQuZnJvbSA9IHNlbGYucGVlcklEO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gUHJvdG9jb2wgaW5kaWNhdGVzIHRoYXQgcmVzcG9uc2VzIGhhcyBvd24gcmVxdWVzdCBtZXRob2RzXG4gICAgICAgIGlmKHJlc3BvbnNlTWV0aG9kKVxuICAgICAgICB7XG4gICAgICAgICAgaWYocmVzcG9uc2VNZXRob2QuZXJyb3IgPT0gdW5kZWZpbmVkICYmIGVycm9yKVxuICAgICAgICAgICAgbWVzc2FnZSA9XG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIGVycm9yOiBlcnJvclxuICAgICAgICAgICAgfTtcblxuICAgICAgICAgIGVsc2VcbiAgICAgICAgICB7XG4gICAgICAgICAgICB2YXIgbWV0aG9kID0gZXJyb3JcbiAgICAgICAgICAgICAgICAgICAgICAgPyByZXNwb25zZU1ldGhvZC5lcnJvclxuICAgICAgICAgICAgICAgICAgICAgICA6IHJlc3BvbnNlTWV0aG9kLnJlc3BvbnNlO1xuXG4gICAgICAgICAgICBtZXNzYWdlID1cbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgbWV0aG9kOiBtZXRob2QsXG4gICAgICAgICAgICAgIHBhcmFtczogZXJyb3IgfHwgcmVzdWx0XG4gICAgICAgICAgICB9O1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlXG4gICAgICAgICAgbWVzc2FnZSA9XG4gICAgICAgICAge1xuICAgICAgICAgICAgZXJyb3I6ICBlcnJvcixcbiAgICAgICAgICAgIHJlc3VsdDogcmVzdWx0XG4gICAgICAgICAgfTtcblxuICAgICAgICBtZXNzYWdlID0gcGFja2VyLnBhY2sobWVzc2FnZSwgaWQpO1xuICAgICAgfVxuXG4gICAgICAvLyBEdXBsaWNhdGUgJiBub3Qtb3ZlcnJpZGVuIHJlcXVlc3QsIHJlLXNlbmQgb2xkIHJlc3BvbnNlXG4gICAgICBlbHNlIGlmKHJlc3BvbnNlKVxuICAgICAgICBtZXNzYWdlID0gcmVzcG9uc2UubWVzc2FnZTtcblxuICAgICAgLy8gTmV3IGVtcHR5IHJlcGx5LCByZXNwb25zZSBudWxsIHZhbHVlXG4gICAgICBlbHNlXG4gICAgICAgIG1lc3NhZ2UgPSBwYWNrZXIucGFjayh7cmVzdWx0OiBudWxsfSwgaWQpO1xuXG4gICAgICAvLyBTdG9yZSB0aGUgcmVzcG9uc2UgdG8gcHJldmVudCB0byBwcm9jZXNzIGEgZHVwbGljYXRlZCByZXF1ZXN0IGxhdGVyXG4gICAgICBzdG9yZVJlc3BvbnNlKG1lc3NhZ2UsIGlkLCBmcm9tKTtcblxuICAgICAgLy8gUmV0dXJuIHRoZSBzdG9yZWQgcmVzcG9uc2Ugc28gaXQgY2FuIGJlIGRpcmVjdGx5IHNlbmQgYmFja1xuICAgICAgdHJhbnNwb3J0ID0gdHJhbnNwb3J0IHx8IHRoaXMuZ2V0VHJhbnNwb3J0KCkgfHwgc2VsZi5nZXRUcmFuc3BvcnQoKTtcblxuICAgICAgaWYodHJhbnNwb3J0KVxuICAgICAgICByZXR1cm4gdHJhbnNwb3J0LnNlbmQobWVzc2FnZSk7XG5cbiAgICAgIHJldHVybiBtZXNzYWdlO1xuICAgIH1cbiAgfTtcbiAgaW5oZXJpdHMoUnBjUmVxdWVzdCwgUnBjTm90aWZpY2F0aW9uKTtcblxuXG4gIGZ1bmN0aW9uIGNhbmNlbChtZXNzYWdlKVxuICB7XG4gICAgdmFyIGtleSA9IG1lc3NhZ2UyS2V5W21lc3NhZ2VdO1xuICAgIGlmKCFrZXkpIHJldHVybjtcblxuICAgIGRlbGV0ZSBtZXNzYWdlMktleVttZXNzYWdlXTtcblxuICAgIHZhciByZXF1ZXN0ID0gcmVxdWVzdHMucG9wKGtleS5pZCwga2V5LmRlc3QpO1xuICAgIGlmKCFyZXF1ZXN0KSByZXR1cm47XG5cbiAgICBjbGVhclRpbWVvdXQocmVxdWVzdC50aW1lb3V0KTtcblxuICAgIC8vIFN0YXJ0IGR1cGxpY2F0ZWQgcmVzcG9uc2VzIHRpbWVvdXRcbiAgICBzdG9yZVByb2Nlc3NlZFJlc3BvbnNlKGtleS5pZCwga2V5LmRlc3QpO1xuICB9O1xuXG4gIC8qKlxuICAgKiBBbGxvdyB0byBjYW5jZWwgYSByZXF1ZXN0IGFuZCBkb24ndCB3YWl0IGZvciBhIHJlc3BvbnNlXG4gICAqXG4gICAqIElmIGBtZXNzYWdlYCBpcyBub3QgZ2l2ZW4sIGNhbmNlbCBhbGwgdGhlIHJlcXVlc3RcbiAgICovXG4gIHRoaXMuY2FuY2VsID0gZnVuY3Rpb24obWVzc2FnZSlcbiAge1xuICAgIGlmKG1lc3NhZ2UpIHJldHVybiBjYW5jZWwobWVzc2FnZSk7XG5cbiAgICBmb3IodmFyIG1lc3NhZ2UgaW4gbWVzc2FnZTJLZXkpXG4gICAgICBjYW5jZWwobWVzc2FnZSk7XG4gIH07XG5cblxuICB0aGlzLmNsb3NlID0gZnVuY3Rpb24oKVxuICB7XG4gICAgLy8gUHJldmVudCB0byByZWNlaXZlIG5ldyBtZXNzYWdlc1xuICAgIHZhciB0cmFuc3BvcnQgPSB0aGlzLmdldFRyYW5zcG9ydCgpO1xuICAgIGlmKHRyYW5zcG9ydCAmJiB0cmFuc3BvcnQuY2xvc2UpXG4gICAgICAgdHJhbnNwb3J0LmNsb3NlKCk7XG5cbiAgICAvLyBSZXF1ZXN0ICYgcHJvY2Vzc2VkIHJlc3BvbnNlc1xuICAgIHRoaXMuY2FuY2VsKCk7XG5cbiAgICBwcm9jZXNzZWRSZXNwb25zZXMuZm9yRWFjaChjbGVhclRpbWVvdXQpO1xuXG4gICAgLy8gUmVzcG9uc2VzXG4gICAgcmVzcG9uc2VzLmZvckVhY2goZnVuY3Rpb24ocmVzcG9uc2UpXG4gICAge1xuICAgICAgY2xlYXJUaW1lb3V0KHJlc3BvbnNlLnRpbWVvdXQpO1xuICAgIH0pO1xuICB9O1xuXG5cbiAgLyoqXG4gICAqIEdlbmVyYXRlcyBhbmQgZW5jb2RlIGEgSnNvblJQQyAyLjAgbWVzc2FnZVxuICAgKlxuICAgKiBAcGFyYW0ge1N0cmluZ30gbWV0aG9kIC1tZXRob2Qgb2YgdGhlIG5vdGlmaWNhdGlvblxuICAgKiBAcGFyYW0gcGFyYW1zIC0gcGFyYW1ldGVycyBvZiB0aGUgbm90aWZpY2F0aW9uXG4gICAqIEBwYXJhbSBbZGVzdF0gLSBkZXN0aW5hdGlvbiBvZiB0aGUgbm90aWZpY2F0aW9uXG4gICAqIEBwYXJhbSB7b2JqZWN0fSBbdHJhbnNwb3J0XSAtIHRyYW5zcG9ydCB3aGVyZSB0byBzZW5kIHRoZSBtZXNzYWdlXG4gICAqIEBwYXJhbSBbY2FsbGJhY2tdIC0gZnVuY3Rpb24gY2FsbGVkIHdoZW4gYSByZXNwb25zZSB0byB0aGlzIHJlcXVlc3QgaXNcbiAgICogICByZWNlaXZlZC4gSWYgbm90IGRlZmluZWQsIGEgbm90aWZpY2F0aW9uIHdpbGwgYmUgc2VuZCBpbnN0ZWFkXG4gICAqXG4gICAqIEByZXR1cm5zIHtzdHJpbmd9IEEgcmF3IEpzb25SUEMgMi4wIHJlcXVlc3Qgb3Igbm90aWZpY2F0aW9uIHN0cmluZ1xuICAgKi9cbiAgdGhpcy5lbmNvZGUgPSBmdW5jdGlvbihtZXRob2QsIHBhcmFtcywgZGVzdCwgdHJhbnNwb3J0LCBjYWxsYmFjaylcbiAge1xuICAgIC8vIEZpeCBvcHRpb25hbCBwYXJhbWV0ZXJzXG4gICAgaWYocGFyYW1zIGluc3RhbmNlb2YgRnVuY3Rpb24pXG4gICAge1xuICAgICAgaWYoZGVzdCAhPSB1bmRlZmluZWQpXG4gICAgICAgIHRocm93IG5ldyBTeW50YXhFcnJvcihcIlRoZXJlIGNhbid0IGJlIHBhcmFtZXRlcnMgYWZ0ZXIgY2FsbGJhY2tcIik7XG5cbiAgICAgIGNhbGxiYWNrICA9IHBhcmFtcztcbiAgICAgIHRyYW5zcG9ydCA9IHVuZGVmaW5lZDtcbiAgICAgIGRlc3QgICAgICA9IHVuZGVmaW5lZDtcbiAgICAgIHBhcmFtcyAgICA9IHVuZGVmaW5lZDtcbiAgICB9XG5cbiAgICBlbHNlIGlmKGRlc3QgaW5zdGFuY2VvZiBGdW5jdGlvbilcbiAgICB7XG4gICAgICBpZih0cmFuc3BvcnQgIT0gdW5kZWZpbmVkKVxuICAgICAgICB0aHJvdyBuZXcgU3ludGF4RXJyb3IoXCJUaGVyZSBjYW4ndCBiZSBwYXJhbWV0ZXJzIGFmdGVyIGNhbGxiYWNrXCIpO1xuXG4gICAgICBjYWxsYmFjayAgPSBkZXN0O1xuICAgICAgdHJhbnNwb3J0ID0gdW5kZWZpbmVkO1xuICAgICAgZGVzdCAgICAgID0gdW5kZWZpbmVkO1xuICAgIH1cblxuICAgIGVsc2UgaWYodHJhbnNwb3J0IGluc3RhbmNlb2YgRnVuY3Rpb24pXG4gICAge1xuICAgICAgaWYoY2FsbGJhY2sgIT0gdW5kZWZpbmVkKVxuICAgICAgICB0aHJvdyBuZXcgU3ludGF4RXJyb3IoXCJUaGVyZSBjYW4ndCBiZSBwYXJhbWV0ZXJzIGFmdGVyIGNhbGxiYWNrXCIpO1xuXG4gICAgICBjYWxsYmFjayAgPSB0cmFuc3BvcnQ7XG4gICAgICB0cmFuc3BvcnQgPSB1bmRlZmluZWQ7XG4gICAgfTtcblxuICAgIGlmKHNlbGYucGVlcklEICE9IHVuZGVmaW5lZClcbiAgICB7XG4gICAgICBwYXJhbXMgPSBwYXJhbXMgfHwge307XG5cbiAgICAgIHBhcmFtcy5mcm9tID0gc2VsZi5wZWVySUQ7XG4gICAgfTtcblxuICAgIGlmKGRlc3QgIT0gdW5kZWZpbmVkKVxuICAgIHtcbiAgICAgIHBhcmFtcyA9IHBhcmFtcyB8fCB7fTtcblxuICAgICAgcGFyYW1zLmRlc3QgPSBkZXN0O1xuICAgIH07XG5cbiAgICAvLyBFbmNvZGUgbWVzc2FnZVxuICAgIHZhciBtZXNzYWdlID1cbiAgICB7XG4gICAgICBtZXRob2Q6IG1ldGhvZCxcbiAgICAgIHBhcmFtczogcGFyYW1zXG4gICAgfTtcblxuICAgIGlmKGNhbGxiYWNrKVxuICAgIHtcbiAgICAgIHZhciBpZCA9IHJlcXVlc3RJRCsrO1xuICAgICAgdmFyIHJldHJpZWQgPSAwO1xuXG4gICAgICBtZXNzYWdlID0gcGFja2VyLnBhY2sobWVzc2FnZSwgaWQpO1xuXG4gICAgICBmdW5jdGlvbiBkaXNwYXRjaENhbGxiYWNrKGVycm9yLCByZXN1bHQpXG4gICAgICB7XG4gICAgICAgIHNlbGYuY2FuY2VsKG1lc3NhZ2UpO1xuXG4gICAgICAgIGNhbGxiYWNrKGVycm9yLCByZXN1bHQpO1xuICAgICAgfTtcblxuICAgICAgdmFyIHJlcXVlc3QgPVxuICAgICAge1xuICAgICAgICBtZXNzYWdlOiAgICAgICAgIG1lc3NhZ2UsXG4gICAgICAgIGNhbGxiYWNrOiAgICAgICAgZGlzcGF0Y2hDYWxsYmFjayxcbiAgICAgICAgcmVzcG9uc2VNZXRob2RzOiByZXNwb25zZU1ldGhvZHNbbWV0aG9kXSB8fCB7fVxuICAgICAgfTtcblxuICAgICAgdmFyIGVuY29kZV90cmFuc3BvcnQgPSB1bmlmeVRyYW5zcG9ydCh0cmFuc3BvcnQpO1xuXG4gICAgICBmdW5jdGlvbiBzZW5kUmVxdWVzdCh0cmFuc3BvcnQpXG4gICAgICB7XG4gICAgICAgIHZhciBydCA9IChtZXRob2QgPT09ICdwaW5nJyA/IHBpbmdfcmVxdWVzdF90aW1lb3V0IDogcmVxdWVzdF90aW1lb3V0KTtcbiAgICAgICAgcmVxdWVzdC50aW1lb3V0ID0gc2V0VGltZW91dCh0aW1lb3V0LCBydCpNYXRoLnBvdygyLCByZXRyaWVkKyspKTtcbiAgICAgICAgbWVzc2FnZTJLZXlbbWVzc2FnZV0gPSB7aWQ6IGlkLCBkZXN0OiBkZXN0fTtcbiAgICAgICAgcmVxdWVzdHMuc2V0KHJlcXVlc3QsIGlkLCBkZXN0KTtcblxuICAgICAgICB0cmFuc3BvcnQgPSB0cmFuc3BvcnQgfHwgZW5jb2RlX3RyYW5zcG9ydCB8fCBzZWxmLmdldFRyYW5zcG9ydCgpO1xuICAgICAgICBpZih0cmFuc3BvcnQpXG4gICAgICAgICAgcmV0dXJuIHRyYW5zcG9ydC5zZW5kKG1lc3NhZ2UpO1xuXG4gICAgICAgIHJldHVybiBtZXNzYWdlO1xuICAgICAgfTtcblxuICAgICAgZnVuY3Rpb24gcmV0cnkodHJhbnNwb3J0KVxuICAgICAge1xuICAgICAgICB0cmFuc3BvcnQgPSB1bmlmeVRyYW5zcG9ydCh0cmFuc3BvcnQpO1xuXG4gICAgICAgIGNvbnNvbGUud2FybihyZXRyaWVkKycgcmV0cnkgZm9yIHJlcXVlc3QgbWVzc2FnZTonLG1lc3NhZ2UpO1xuXG4gICAgICAgIHZhciB0aW1lb3V0ID0gcHJvY2Vzc2VkUmVzcG9uc2VzLnBvcChpZCwgZGVzdCk7XG4gICAgICAgIGNsZWFyVGltZW91dCh0aW1lb3V0KTtcblxuICAgICAgICByZXR1cm4gc2VuZFJlcXVlc3QodHJhbnNwb3J0KTtcbiAgICAgIH07XG5cbiAgICAgIGZ1bmN0aW9uIHRpbWVvdXQoKVxuICAgICAge1xuICAgICAgICBpZihyZXRyaWVkIDwgbWF4X3JldHJpZXMpXG4gICAgICAgICAgcmV0dXJuIHJldHJ5KHRyYW5zcG9ydCk7XG5cbiAgICAgICAgdmFyIGVycm9yID0gbmV3IEVycm9yKCdSZXF1ZXN0IGhhcyB0aW1lZCBvdXQnKTtcbiAgICAgICAgICAgIGVycm9yLnJlcXVlc3QgPSBtZXNzYWdlO1xuXG4gICAgICAgIGVycm9yLnJldHJ5ID0gcmV0cnk7XG5cbiAgICAgICAgZGlzcGF0Y2hDYWxsYmFjayhlcnJvcilcbiAgICAgIH07XG5cbiAgICAgIHJldHVybiBzZW5kUmVxdWVzdCh0cmFuc3BvcnQpO1xuICAgIH07XG5cbiAgICAvLyBSZXR1cm4gdGhlIHBhY2tlZCBtZXNzYWdlXG4gICAgbWVzc2FnZSA9IHBhY2tlci5wYWNrKG1lc3NhZ2UpO1xuXG4gICAgdHJhbnNwb3J0ID0gdHJhbnNwb3J0IHx8IHRoaXMuZ2V0VHJhbnNwb3J0KCk7XG4gICAgaWYodHJhbnNwb3J0KVxuICAgICAgcmV0dXJuIHRyYW5zcG9ydC5zZW5kKG1lc3NhZ2UpO1xuXG4gICAgcmV0dXJuIG1lc3NhZ2U7XG4gIH07XG5cbiAgLyoqXG4gICAqIERlY29kZSBhbmQgcHJvY2VzcyBhIEpzb25SUEMgMi4wIG1lc3NhZ2VcbiAgICpcbiAgICogQHBhcmFtIHtzdHJpbmd9IG1lc3NhZ2UgLSBzdHJpbmcgd2l0aCB0aGUgY29udGVudCBvZiB0aGUgbWVzc2FnZVxuICAgKlxuICAgKiBAcmV0dXJucyB7UnBjTm90aWZpY2F0aW9ufFJwY1JlcXVlc3R8dW5kZWZpbmVkfSAtIHRoZSByZXByZXNlbnRhdGlvbiBvZiB0aGVcbiAgICogICBub3RpZmljYXRpb24gb3IgdGhlIHJlcXVlc3QuIElmIGEgcmVzcG9uc2Ugd2FzIHByb2Nlc3NlZCwgaXQgd2lsbCByZXR1cm5cbiAgICogICBgdW5kZWZpbmVkYCB0byBub3RpZnkgdGhhdCBpdCB3YXMgcHJvY2Vzc2VkXG4gICAqXG4gICAqIEB0aHJvd3Mge1R5cGVFcnJvcn0gLSBNZXNzYWdlIGlzIG5vdCBkZWZpbmVkXG4gICAqL1xuICB0aGlzLmRlY29kZSA9IGZ1bmN0aW9uKG1lc3NhZ2UsIHRyYW5zcG9ydClcbiAge1xuICAgIGlmKCFtZXNzYWdlKVxuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIk1lc3NhZ2UgaXMgbm90IGRlZmluZWRcIik7XG5cbiAgICB0cnlcbiAgICB7XG4gICAgICBtZXNzYWdlID0gcGFja2VyLnVucGFjayhtZXNzYWdlKTtcbiAgICB9XG4gICAgY2F0Y2goZSlcbiAgICB7XG4gICAgICAvLyBJZ25vcmUgaW52YWxpZCBtZXNzYWdlc1xuICAgICAgcmV0dXJuIGNvbnNvbGUuZGVidWcoZSwgbWVzc2FnZSk7XG4gICAgfTtcblxuICAgIHZhciBpZCAgICAgPSBtZXNzYWdlLmlkO1xuICAgIHZhciBhY2sgICAgPSBtZXNzYWdlLmFjaztcbiAgICB2YXIgbWV0aG9kID0gbWVzc2FnZS5tZXRob2Q7XG4gICAgdmFyIHBhcmFtcyA9IG1lc3NhZ2UucGFyYW1zIHx8IHt9O1xuXG4gICAgdmFyIGZyb20gPSBwYXJhbXMuZnJvbTtcbiAgICB2YXIgZGVzdCA9IHBhcmFtcy5kZXN0O1xuXG4gICAgLy8gSWdub3JlIG1lc3NhZ2VzIHNlbmQgYnkgdXNcbiAgICBpZihzZWxmLnBlZXJJRCAhPSB1bmRlZmluZWQgJiYgZnJvbSA9PSBzZWxmLnBlZXJJRCkgcmV0dXJuO1xuXG4gICAgLy8gTm90aWZpY2F0aW9uXG4gICAgaWYoaWQgPT0gdW5kZWZpbmVkICYmIGFjayA9PSB1bmRlZmluZWQpXG4gICAge1xuICAgICAgdmFyIG5vdGlmaWNhdGlvbiA9IG5ldyBScGNOb3RpZmljYXRpb24obWV0aG9kLCBwYXJhbXMpO1xuXG4gICAgICBpZihzZWxmLmVtaXQoJ3JlcXVlc3QnLCBub3RpZmljYXRpb24pKSByZXR1cm47XG4gICAgICByZXR1cm4gbm90aWZpY2F0aW9uO1xuICAgIH07XG5cblxuICAgIGZ1bmN0aW9uIHByb2Nlc3NSZXF1ZXN0KClcbiAgICB7XG4gICAgICAvLyBJZiB3ZSBoYXZlIGEgdHJhbnNwb3J0IGFuZCBpdCdzIGEgZHVwbGljYXRlZCByZXF1ZXN0LCByZXBseSBpbm1lZGlhdGx5XG4gICAgICB0cmFuc3BvcnQgPSB1bmlmeVRyYW5zcG9ydCh0cmFuc3BvcnQpIHx8IHNlbGYuZ2V0VHJhbnNwb3J0KCk7XG4gICAgICBpZih0cmFuc3BvcnQpXG4gICAgICB7XG4gICAgICAgIHZhciByZXNwb25zZSA9IHJlc3BvbnNlcy5nZXQoaWQsIGZyb20pO1xuICAgICAgICBpZihyZXNwb25zZSlcbiAgICAgICAgICByZXR1cm4gdHJhbnNwb3J0LnNlbmQocmVzcG9uc2UubWVzc2FnZSk7XG4gICAgICB9O1xuXG4gICAgICB2YXIgaWRBY2sgPSAoaWQgIT0gdW5kZWZpbmVkKSA/IGlkIDogYWNrO1xuICAgICAgdmFyIHJlcXVlc3QgPSBuZXcgUnBjUmVxdWVzdChtZXRob2QsIHBhcmFtcywgaWRBY2ssIGZyb20sIHRyYW5zcG9ydCk7XG5cbiAgICAgIGlmKHNlbGYuZW1pdCgncmVxdWVzdCcsIHJlcXVlc3QpKSByZXR1cm47XG4gICAgICByZXR1cm4gcmVxdWVzdDtcbiAgICB9O1xuXG4gICAgZnVuY3Rpb24gcHJvY2Vzc1Jlc3BvbnNlKHJlcXVlc3QsIGVycm9yLCByZXN1bHQpXG4gICAge1xuICAgICAgcmVxdWVzdC5jYWxsYmFjayhlcnJvciwgcmVzdWx0KTtcbiAgICB9O1xuXG4gICAgZnVuY3Rpb24gZHVwbGljYXRlZFJlc3BvbnNlKHRpbWVvdXQpXG4gICAge1xuICAgICAgY29uc29sZS53YXJuKFwiUmVzcG9uc2UgYWxyZWFkeSBwcm9jZXNzZWRcIiwgbWVzc2FnZSk7XG5cbiAgICAgIC8vIFVwZGF0ZSBkdXBsaWNhdGVkIHJlc3BvbnNlcyB0aW1lb3V0XG4gICAgICBjbGVhclRpbWVvdXQodGltZW91dCk7XG4gICAgICBzdG9yZVByb2Nlc3NlZFJlc3BvbnNlKGFjaywgZnJvbSk7XG4gICAgfTtcblxuXG4gICAgLy8gUmVxdWVzdCwgb3IgcmVzcG9uc2Ugd2l0aCBvd24gbWV0aG9kXG4gICAgaWYobWV0aG9kKVxuICAgIHtcbiAgICAgIC8vIENoZWNrIGlmIGl0J3MgYSByZXNwb25zZSB3aXRoIG93biBtZXRob2RcbiAgICAgIGlmKGRlc3QgPT0gdW5kZWZpbmVkIHx8IGRlc3QgPT0gc2VsZi5wZWVySUQpXG4gICAgICB7XG4gICAgICAgIHZhciByZXF1ZXN0ID0gcmVxdWVzdHMuZ2V0KGFjaywgZnJvbSk7XG4gICAgICAgIGlmKHJlcXVlc3QpXG4gICAgICAgIHtcbiAgICAgICAgICB2YXIgcmVzcG9uc2VNZXRob2RzID0gcmVxdWVzdC5yZXNwb25zZU1ldGhvZHM7XG5cbiAgICAgICAgICBpZihtZXRob2QgPT0gcmVzcG9uc2VNZXRob2RzLmVycm9yKVxuICAgICAgICAgICAgcmV0dXJuIHByb2Nlc3NSZXNwb25zZShyZXF1ZXN0LCBwYXJhbXMpO1xuXG4gICAgICAgICAgaWYobWV0aG9kID09IHJlc3BvbnNlTWV0aG9kcy5yZXNwb25zZSlcbiAgICAgICAgICAgIHJldHVybiBwcm9jZXNzUmVzcG9uc2UocmVxdWVzdCwgbnVsbCwgcGFyYW1zKTtcblxuICAgICAgICAgIHJldHVybiBwcm9jZXNzUmVxdWVzdCgpO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIHByb2Nlc3NlZCA9IHByb2Nlc3NlZFJlc3BvbnNlcy5nZXQoYWNrLCBmcm9tKTtcbiAgICAgICAgaWYocHJvY2Vzc2VkKVxuICAgICAgICAgIHJldHVybiBkdXBsaWNhdGVkUmVzcG9uc2UocHJvY2Vzc2VkKTtcbiAgICAgIH1cblxuICAgICAgLy8gUmVxdWVzdFxuICAgICAgcmV0dXJuIHByb2Nlc3NSZXF1ZXN0KCk7XG4gICAgfTtcblxuICAgIHZhciBlcnJvciAgPSBtZXNzYWdlLmVycm9yO1xuICAgIHZhciByZXN1bHQgPSBtZXNzYWdlLnJlc3VsdDtcblxuICAgIC8vIElnbm9yZSByZXNwb25zZXMgbm90IHNlbmQgdG8gdXNcbiAgICBpZihlcnJvciAgJiYgZXJyb3IuZGVzdCAgJiYgZXJyb3IuZGVzdCAgIT0gc2VsZi5wZWVySUQpIHJldHVybjtcbiAgICBpZihyZXN1bHQgJiYgcmVzdWx0LmRlc3QgJiYgcmVzdWx0LmRlc3QgIT0gc2VsZi5wZWVySUQpIHJldHVybjtcblxuICAgIC8vIFJlc3BvbnNlXG4gICAgdmFyIHJlcXVlc3QgPSByZXF1ZXN0cy5nZXQoYWNrLCBmcm9tKTtcbiAgICBpZighcmVxdWVzdClcbiAgICB7XG4gICAgICB2YXIgcHJvY2Vzc2VkID0gcHJvY2Vzc2VkUmVzcG9uc2VzLmdldChhY2ssIGZyb20pO1xuICAgICAgaWYocHJvY2Vzc2VkKVxuICAgICAgICByZXR1cm4gZHVwbGljYXRlZFJlc3BvbnNlKHByb2Nlc3NlZCk7XG5cbiAgICAgIHJldHVybiBjb25zb2xlLndhcm4oXCJObyBjYWxsYmFjayB3YXMgZGVmaW5lZCBmb3IgdGhpcyBtZXNzYWdlXCIsIG1lc3NhZ2UpO1xuICAgIH07XG5cbiAgICAvLyBQcm9jZXNzIHJlc3BvbnNlXG4gICAgcHJvY2Vzc1Jlc3BvbnNlKHJlcXVlc3QsIGVycm9yLCByZXN1bHQpO1xuICB9O1xufTtcbmluaGVyaXRzKFJwY0J1aWxkZXIsIEV2ZW50RW1pdHRlcik7XG5cblxuUnBjQnVpbGRlci5ScGNOb3RpZmljYXRpb24gPSBScGNOb3RpZmljYXRpb247XG5cblxubW9kdWxlLmV4cG9ydHMgPSBScGNCdWlsZGVyO1xuXG52YXIgY2xpZW50cyA9IHJlcXVpcmUoJy4vY2xpZW50cycpO1xudmFyIHRyYW5zcG9ydHMgPSByZXF1aXJlKCcuL2NsaWVudHMvdHJhbnNwb3J0cycpO1xuXG5ScGNCdWlsZGVyLmNsaWVudHMgPSBjbGllbnRzO1xuUnBjQnVpbGRlci5jbGllbnRzLnRyYW5zcG9ydHMgPSB0cmFuc3BvcnRzO1xuUnBjQnVpbGRlci5wYWNrZXJzID0gcGFja2VycztcbiIsIi8qKlxuICogSnNvblJQQyAyLjAgcGFja2VyXG4gKi9cblxuLyoqXG4gKiBQYWNrIGEgSnNvblJQQyAyLjAgbWVzc2FnZVxuICpcbiAqIEBwYXJhbSB7T2JqZWN0fSBtZXNzYWdlIC0gb2JqZWN0IHRvIGJlIHBhY2thZ2VkLiBJdCByZXF1aXJlcyB0byBoYXZlIGFsbCB0aGVcbiAqICAgZmllbGRzIG5lZWRlZCBieSB0aGUgSnNvblJQQyAyLjAgbWVzc2FnZSB0aGF0IGl0J3MgZ29pbmcgdG8gYmUgZ2VuZXJhdGVkXG4gKlxuICogQHJldHVybiB7U3RyaW5nfSAtIHRoZSBzdHJpbmdpZmllZCBKc29uUlBDIDIuMCBtZXNzYWdlXG4gKi9cbmZ1bmN0aW9uIHBhY2sobWVzc2FnZSwgaWQpXG57XG4gIHZhciByZXN1bHQgPVxuICB7XG4gICAganNvbnJwYzogXCIyLjBcIlxuICB9O1xuXG4gIC8vIFJlcXVlc3RcbiAgaWYobWVzc2FnZS5tZXRob2QpXG4gIHtcbiAgICByZXN1bHQubWV0aG9kID0gbWVzc2FnZS5tZXRob2Q7XG5cbiAgICBpZihtZXNzYWdlLnBhcmFtcylcbiAgICAgIHJlc3VsdC5wYXJhbXMgPSBtZXNzYWdlLnBhcmFtcztcblxuICAgIC8vIFJlcXVlc3QgaXMgYSBub3RpZmljYXRpb25cbiAgICBpZihpZCAhPSB1bmRlZmluZWQpXG4gICAgICByZXN1bHQuaWQgPSBpZDtcbiAgfVxuXG4gIC8vIFJlc3BvbnNlXG4gIGVsc2UgaWYoaWQgIT0gdW5kZWZpbmVkKVxuICB7XG4gICAgaWYobWVzc2FnZS5lcnJvcilcbiAgICB7XG4gICAgICBpZihtZXNzYWdlLnJlc3VsdCAhPT0gdW5kZWZpbmVkKVxuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQm90aCByZXN1bHQgYW5kIGVycm9yIGFyZSBkZWZpbmVkXCIpO1xuXG4gICAgICByZXN1bHQuZXJyb3IgPSBtZXNzYWdlLmVycm9yO1xuICAgIH1cbiAgICBlbHNlIGlmKG1lc3NhZ2UucmVzdWx0ICE9PSB1bmRlZmluZWQpXG4gICAgICByZXN1bHQucmVzdWx0ID0gbWVzc2FnZS5yZXN1bHQ7XG4gICAgZWxzZVxuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIk5vIHJlc3VsdCBvciBlcnJvciBpcyBkZWZpbmVkXCIpO1xuXG4gICAgcmVzdWx0LmlkID0gaWQ7XG4gIH07XG5cbiAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KHJlc3VsdCk7XG59O1xuXG4vKipcbiAqIFVucGFjayBhIEpzb25SUEMgMi4wIG1lc3NhZ2VcbiAqXG4gKiBAcGFyYW0ge1N0cmluZ30gbWVzc2FnZSAtIHN0cmluZyB3aXRoIHRoZSBjb250ZW50IG9mIHRoZSBKc29uUlBDIDIuMCBtZXNzYWdlXG4gKlxuICogQHRocm93cyB7VHlwZUVycm9yfSAtIEludmFsaWQgSnNvblJQQyB2ZXJzaW9uXG4gKlxuICogQHJldHVybiB7T2JqZWN0fSAtIG9iamVjdCBmaWxsZWQgd2l0aCB0aGUgSnNvblJQQyAyLjAgbWVzc2FnZSBjb250ZW50XG4gKi9cbmZ1bmN0aW9uIHVucGFjayhtZXNzYWdlKVxue1xuICB2YXIgcmVzdWx0ID0gbWVzc2FnZTtcblxuICBpZih0eXBlb2YgbWVzc2FnZSA9PT0gJ3N0cmluZycgfHwgbWVzc2FnZSBpbnN0YW5jZW9mIFN0cmluZykge1xuICAgIHJlc3VsdCA9IEpTT04ucGFyc2UobWVzc2FnZSk7XG4gIH1cblxuICAvLyBDaGVjayBpZiBpdCdzIGEgdmFsaWQgbWVzc2FnZVxuXG4gIHZhciB2ZXJzaW9uID0gcmVzdWx0Lmpzb25ycGM7XG4gIGlmKHZlcnNpb24gIT09ICcyLjAnKVxuICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJJbnZhbGlkIEpzb25SUEMgdmVyc2lvbiAnXCIgKyB2ZXJzaW9uICsgXCInOiBcIiArIG1lc3NhZ2UpO1xuXG4gIC8vIFJlc3BvbnNlXG4gIGlmKHJlc3VsdC5tZXRob2QgPT0gdW5kZWZpbmVkKVxuICB7XG4gICAgaWYocmVzdWx0LmlkID09IHVuZGVmaW5lZClcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJJbnZhbGlkIG1lc3NhZ2U6IFwiK21lc3NhZ2UpO1xuXG4gICAgdmFyIHJlc3VsdF9kZWZpbmVkID0gcmVzdWx0LnJlc3VsdCAhPT0gdW5kZWZpbmVkO1xuICAgIHZhciBlcnJvcl9kZWZpbmVkICA9IHJlc3VsdC5lcnJvciAgIT09IHVuZGVmaW5lZDtcblxuICAgIC8vIENoZWNrIG9ubHkgcmVzdWx0IG9yIGVycm9yIGlzIGRlZmluZWQsIG5vdCBib3RoIG9yIG5vbmVcbiAgICBpZihyZXN1bHRfZGVmaW5lZCAmJiBlcnJvcl9kZWZpbmVkKVxuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkJvdGggcmVzdWx0IGFuZCBlcnJvciBhcmUgZGVmaW5lZDogXCIrbWVzc2FnZSk7XG5cbiAgICBpZighcmVzdWx0X2RlZmluZWQgJiYgIWVycm9yX2RlZmluZWQpXG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiTm8gcmVzdWx0IG9yIGVycm9yIGlzIGRlZmluZWQ6IFwiK21lc3NhZ2UpO1xuXG4gICAgcmVzdWx0LmFjayA9IHJlc3VsdC5pZDtcbiAgICBkZWxldGUgcmVzdWx0LmlkO1xuICB9XG5cbiAgLy8gUmV0dXJuIHVucGFja2VkIG1lc3NhZ2VcbiAgcmV0dXJuIHJlc3VsdDtcbn07XG5cblxuZXhwb3J0cy5wYWNrICAgPSBwYWNrO1xuZXhwb3J0cy51bnBhY2sgPSB1bnBhY2s7XG4iLCJmdW5jdGlvbiBwYWNrKG1lc3NhZ2UpXG57XG4gIHRocm93IG5ldyBUeXBlRXJyb3IoXCJOb3QgeWV0IGltcGxlbWVudGVkXCIpO1xufTtcblxuZnVuY3Rpb24gdW5wYWNrKG1lc3NhZ2UpXG57XG4gIHRocm93IG5ldyBUeXBlRXJyb3IoXCJOb3QgeWV0IGltcGxlbWVudGVkXCIpO1xufTtcblxuXG5leHBvcnRzLnBhY2sgICA9IHBhY2s7XG5leHBvcnRzLnVucGFjayA9IHVucGFjaztcbiIsInZhciBKc29uUlBDID0gcmVxdWlyZSgnLi9Kc29uUlBDJyk7XG52YXIgWG1sUlBDICA9IHJlcXVpcmUoJy4vWG1sUlBDJyk7XG5cblxuZXhwb3J0cy5Kc29uUlBDID0gSnNvblJQQztcbmV4cG9ydHMuWG1sUlBDICA9IFhtbFJQQztcbiIsIi8vIExhc3QgdGltZSB1cGRhdGVkIG9uIEp1bmUgMDgsIDIwMThcblxuLy8gTGF0ZXN0IGZpbGUgY2FuIGJlIGZvdW5kIGhlcmU6IGh0dHBzOi8vY2RuLndlYnJ0Yy1leHBlcmltZW50LmNvbS9nZXRTY3JlZW5JZC5qc1xuXG4vLyBNdWF6IEtoYW4gICAgICAgICAtIHd3dy5NdWF6S2hhbi5jb21cbi8vIE1JVCBMaWNlbnNlICAgICAgIC0gd3d3LldlYlJUQy1FeHBlcmltZW50LmNvbS9saWNlbmNlXG4vLyBEb2N1bWVudGF0aW9uICAgICAtIGh0dHBzOi8vZ2l0aHViLmNvbS9tdWF6LWtoYW4vZ2V0U2NyZWVuSWQuXG5cbi8vIF9fX19fX19fX19fX19fXG4vLyBnZXRTY3JlZW5JZC5qc1xuXG4vKlxuZ2V0U2NyZWVuSWQoZnVuY3Rpb24gKGVycm9yLCBzb3VyY2VJZCwgc2NyZWVuX2NvbnN0cmFpbnRzKSB7XG4gICAgLy8gZXJyb3IgICAgPT0gbnVsbCB8fCAncGVybWlzc2lvbi1kZW5pZWQnIHx8ICdub3QtaW5zdGFsbGVkJyB8fCAnaW5zdGFsbGVkLWRpc2FibGVkJyB8fCAnbm90LWNocm9tZSdcbiAgICAvLyBzb3VyY2VJZCA9PSBudWxsIHx8ICdzdHJpbmcnIHx8ICdmaXJlZm94J1xuICAgIFxuICAgIGlmKG1pY3Jvc29mdEVkZ2UpIHtcbiAgICAgICAgbmF2aWdhdG9yLmdldERpc3BsYXlNZWRpYShzY3JlZW5fY29uc3RyYWludHMpLnRoZW4ob25TdWNjZXNzLCBvbkZhaWx1cmUpO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgbmF2aWdhdG9yLm1lZGlhRGV2aWNlcy5nZXRVc2VyTWVkaWEoc2NyZWVuX2NvbnN0cmFpbnRzKS50aGVuKG9uU3VjY2VzcyljYXRjaChvbkZhaWx1cmUpO1xuICAgIH1cbn0sICdwYXNzIHNlY29uZCBwYXJhbWV0ZXIgb25seSBpZiB5b3Ugd2FudCBzeXN0ZW0gYXVkaW8nKTtcbiovXG5cbndpbmRvdy5nZXRTY3JlZW5JZCA9IGZ1bmN0aW9uIChjYWxsYmFjaywgY3VzdG9tX3BhcmFtZXRlcikge1xuICAgIGlmIChuYXZpZ2F0b3IudXNlckFnZW50LmluZGV4T2YoJ0VkZ2UnKSAhPT0gLTEgJiYgKCEhbmF2aWdhdG9yLm1zU2F2ZU9yT3BlbkJsb2IgfHwgISFuYXZpZ2F0b3IubXNTYXZlQmxvYikpIHtcbiAgICAgICAgLy8gbWljcm9zb2Z0IGVkZ2UgPT4gbmF2aWdhdG9yLmdldERpc3BsYXlNZWRpYShzY3JlZW5fY29uc3RyYWludHMpLnRoZW4ob25TdWNjZXNzLCBvbkZhaWx1cmUpO1xuICAgICAgICBjYWxsYmFjayh7XG4gICAgICAgICAgICB2aWRlbzogdHJ1ZVxuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8vIGZvciBGaXJlZm94OlxuICAgIC8vIHNvdXJjZUlkID09ICdmaXJlZm94J1xuICAgIC8vIHNjcmVlbl9jb25zdHJhaW50cyA9IHsuLi59XG4gICAgaWYgKCEhbmF2aWdhdG9yLm1vekdldFVzZXJNZWRpYSkge1xuICAgICAgICBjYWxsYmFjayhudWxsLCAnZmlyZWZveCcsIHtcbiAgICAgICAgICAgIHZpZGVvOiB7XG4gICAgICAgICAgICAgICAgbW96TWVkaWFTb3VyY2U6ICd3aW5kb3cnLFxuICAgICAgICAgICAgICAgIG1lZGlhU291cmNlOiAnd2luZG93J1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdtZXNzYWdlJywgb25JRnJhbWVDYWxsYmFjayk7XG5cbiAgICBmdW5jdGlvbiBvbklGcmFtZUNhbGxiYWNrKGV2ZW50KSB7XG4gICAgICAgIGlmICghZXZlbnQuZGF0YSkgcmV0dXJuO1xuXG4gICAgICAgIGlmIChldmVudC5kYXRhLmNocm9tZU1lZGlhU291cmNlSWQpIHtcbiAgICAgICAgICAgIGlmIChldmVudC5kYXRhLmNocm9tZU1lZGlhU291cmNlSWQgPT09ICdQZXJtaXNzaW9uRGVuaWVkRXJyb3InKSB7XG4gICAgICAgICAgICAgICAgY2FsbGJhY2soJ3Blcm1pc3Npb24tZGVuaWVkJyk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGNhbGxiYWNrKG51bGwsIGV2ZW50LmRhdGEuY2hyb21lTWVkaWFTb3VyY2VJZCwgZ2V0U2NyZWVuQ29uc3RyYWludHMobnVsbCwgZXZlbnQuZGF0YS5jaHJvbWVNZWRpYVNvdXJjZUlkLCBldmVudC5kYXRhLmNhblJlcXVlc3RBdWRpb1RyYWNrKSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIHRoaXMgZXZlbnQgbGlzdGVuZXIgaXMgbm8gbW9yZSBuZWVkZWRcbiAgICAgICAgICAgIHdpbmRvdy5yZW1vdmVFdmVudExpc3RlbmVyKCdtZXNzYWdlJywgb25JRnJhbWVDYWxsYmFjayk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoZXZlbnQuZGF0YS5jaHJvbWVFeHRlbnNpb25TdGF0dXMpIHtcbiAgICAgICAgICAgIGNhbGxiYWNrKGV2ZW50LmRhdGEuY2hyb21lRXh0ZW5zaW9uU3RhdHVzLCBudWxsLCBnZXRTY3JlZW5Db25zdHJhaW50cyhldmVudC5kYXRhLmNocm9tZUV4dGVuc2lvblN0YXR1cykpO1xuXG4gICAgICAgICAgICAvLyB0aGlzIGV2ZW50IGxpc3RlbmVyIGlzIG5vIG1vcmUgbmVlZGVkXG4gICAgICAgICAgICB3aW5kb3cucmVtb3ZlRXZlbnRMaXN0ZW5lcignbWVzc2FnZScsIG9uSUZyYW1lQ2FsbGJhY2spO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgaWYgKCFjdXN0b21fcGFyYW1ldGVyKSB7XG4gICAgICAgIHNldFRpbWVvdXQocG9zdEdldFNvdXJjZUlkTWVzc2FnZSwgMTAwKTtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcG9zdEdldFNvdXJjZUlkTWVzc2FnZShjdXN0b21fcGFyYW1ldGVyKTtcbiAgICAgICAgfSwgMTAwKTtcbiAgICB9XG59O1xuXG5mdW5jdGlvbiBnZXRTY3JlZW5Db25zdHJhaW50cyhlcnJvciwgc291cmNlSWQsIGNhblJlcXVlc3RBdWRpb1RyYWNrKSB7XG4gICAgdmFyIHNjcmVlbl9jb25zdHJhaW50cyA9IHtcbiAgICAgICAgYXVkaW86IGZhbHNlLFxuICAgICAgICB2aWRlbzoge1xuICAgICAgICAgICAgbWFuZGF0b3J5OiB7XG4gICAgICAgICAgICAgICAgY2hyb21lTWVkaWFTb3VyY2U6IGVycm9yID8gJ3NjcmVlbicgOiAnZGVza3RvcCcsXG4gICAgICAgICAgICAgICAgbWF4V2lkdGg6IHdpbmRvdy5zY3JlZW4ud2lkdGggPiAxOTIwID8gd2luZG93LnNjcmVlbi53aWR0aCA6IDE5MjAsXG4gICAgICAgICAgICAgICAgbWF4SGVpZ2h0OiB3aW5kb3cuc2NyZWVuLmhlaWdodCA+IDEwODAgPyB3aW5kb3cuc2NyZWVuLmhlaWdodCA6IDEwODBcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBvcHRpb25hbDogW11cbiAgICAgICAgfVxuICAgIH07XG5cbiAgICBpZiAoISFjYW5SZXF1ZXN0QXVkaW9UcmFjaykge1xuICAgICAgICBzY3JlZW5fY29uc3RyYWludHMuYXVkaW8gPSB7XG4gICAgICAgICAgICBtYW5kYXRvcnk6IHtcbiAgICAgICAgICAgICAgICBjaHJvbWVNZWRpYVNvdXJjZTogZXJyb3IgPyAnc2NyZWVuJyA6ICdkZXNrdG9wJyxcbiAgICAgICAgICAgICAgICAvLyBlY2hvQ2FuY2VsbGF0aW9uOiB0cnVlXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgb3B0aW9uYWw6IFtdXG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgaWYgKHNvdXJjZUlkKSB7XG4gICAgICAgIHNjcmVlbl9jb25zdHJhaW50cy52aWRlby5tYW5kYXRvcnkuY2hyb21lTWVkaWFTb3VyY2VJZCA9IHNvdXJjZUlkO1xuXG4gICAgICAgIGlmIChzY3JlZW5fY29uc3RyYWludHMuYXVkaW8gJiYgc2NyZWVuX2NvbnN0cmFpbnRzLmF1ZGlvLm1hbmRhdG9yeSkge1xuICAgICAgICAgICAgc2NyZWVuX2NvbnN0cmFpbnRzLmF1ZGlvLm1hbmRhdG9yeS5jaHJvbWVNZWRpYVNvdXJjZUlkID0gc291cmNlSWQ7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gc2NyZWVuX2NvbnN0cmFpbnRzO1xufVxuXG5mdW5jdGlvbiBwb3N0R2V0U291cmNlSWRNZXNzYWdlKGN1c3RvbV9wYXJhbWV0ZXIpIHtcbiAgICBpZiAoIWlmcmFtZSkge1xuICAgICAgICBsb2FkSUZyYW1lKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHBvc3RHZXRTb3VyY2VJZE1lc3NhZ2UoY3VzdG9tX3BhcmFtZXRlcik7XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYgKCFpZnJhbWUuaXNMb2FkZWQpIHtcbiAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBwb3N0R2V0U291cmNlSWRNZXNzYWdlKGN1c3RvbV9wYXJhbWV0ZXIpO1xuICAgICAgICB9LCAxMDApO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYgKCFjdXN0b21fcGFyYW1ldGVyKSB7XG4gICAgICAgIGlmcmFtZS5jb250ZW50V2luZG93LnBvc3RNZXNzYWdlKHtcbiAgICAgICAgICAgIGNhcHR1cmVTb3VyY2VJZDogdHJ1ZVxuICAgICAgICB9LCAnKicpO1xuICAgIH1cbiAgICBlbHNlIGlmICghIWN1c3RvbV9wYXJhbWV0ZXIuZm9yRWFjaCkge1xuICAgICAgICBpZnJhbWUuY29udGVudFdpbmRvdy5wb3N0TWVzc2FnZSh7XG4gICAgICAgICAgICBjYXB0dXJlQ3VzdG9tU291cmNlSWQ6IGN1c3RvbV9wYXJhbWV0ZXJcbiAgICAgICAgfSwgJyonKTtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIGlmcmFtZS5jb250ZW50V2luZG93LnBvc3RNZXNzYWdlKHtcbiAgICAgICAgICAgIGNhcHR1cmVTb3VyY2VJZFdpdGhBdWRpbzogdHJ1ZVxuICAgICAgICB9LCAnKicpO1xuICAgIH1cbn1cblxudmFyIGlmcmFtZTtcblxuLy8gdGhpcyBmdW5jdGlvbiBpcyB1c2VkIGluIFJUQ011bHRpQ29ubmVjdGlvbiB2M1xud2luZG93LmdldFNjcmVlbkNvbnN0cmFpbnRzID0gZnVuY3Rpb24gKGNhbGxiYWNrKSB7XG4gICAgbG9hZElGcmFtZShmdW5jdGlvbiAoKSB7XG4gICAgICAgIGdldFNjcmVlbklkKGZ1bmN0aW9uIChlcnJvciwgc291cmNlSWQsIHNjcmVlbl9jb25zdHJhaW50cykge1xuICAgICAgICAgICAgaWYgKCFzY3JlZW5fY29uc3RyYWludHMpIHtcbiAgICAgICAgICAgICAgICBzY3JlZW5fY29uc3RyYWludHMgPSB7XG4gICAgICAgICAgICAgICAgICAgIHZpZGVvOiB0cnVlXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgY2FsbGJhY2soZXJyb3IsIHNjcmVlbl9jb25zdHJhaW50cy52aWRlbyk7XG4gICAgICAgIH0pO1xuICAgIH0pO1xufTtcblxuZnVuY3Rpb24gbG9hZElGcmFtZShsb2FkQ2FsbGJhY2spIHtcbiAgICBpZiAoaWZyYW1lKSB7XG4gICAgICAgIGxvYWRDYWxsYmFjaygpO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWZyYW1lID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnaWZyYW1lJyk7XG4gICAgaWZyYW1lLm9ubG9hZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWZyYW1lLmlzTG9hZGVkID0gdHJ1ZTtcbiAgICAgICAgbG9hZENhbGxiYWNrKCk7XG4gICAgfTtcbiAgICBpZnJhbWUuc3JjID0gJ2h0dHBzOi8vb3BlbnZpZHUuZ2l0aHViLmlvL29wZW52aWR1LXNjcmVlbi1zaGFyaW5nLWNocm9tZS1leHRlbnNpb24vJztcbiAgICBpZnJhbWUuc3R5bGUuZGlzcGxheSA9ICdub25lJztcbiAgICAoZG9jdW1lbnQuYm9keSB8fCBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQpLmFwcGVuZENoaWxkKGlmcmFtZSk7XG59XG5cbndpbmRvdy5nZXRDaHJvbWVFeHRlbnNpb25TdGF0dXMgPSBmdW5jdGlvbiAoY2FsbGJhY2spIHtcbiAgICAvLyBmb3IgRmlyZWZveDpcbiAgICBpZiAoISFuYXZpZ2F0b3IubW96R2V0VXNlck1lZGlhKSB7XG4gICAgICAgIGNhbGxiYWNrKCdpbnN0YWxsZWQtZW5hYmxlZCcpO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ21lc3NhZ2UnLCBvbklGcmFtZUNhbGxiYWNrKTtcblxuICAgIGZ1bmN0aW9uIG9uSUZyYW1lQ2FsbGJhY2soZXZlbnQpIHtcbiAgICAgICAgaWYgKCFldmVudC5kYXRhKSByZXR1cm47XG5cbiAgICAgICAgaWYgKGV2ZW50LmRhdGEuY2hyb21lRXh0ZW5zaW9uU3RhdHVzKSB7XG4gICAgICAgICAgICBjYWxsYmFjayhldmVudC5kYXRhLmNocm9tZUV4dGVuc2lvblN0YXR1cyk7XG5cbiAgICAgICAgICAgIC8vIHRoaXMgZXZlbnQgbGlzdGVuZXIgaXMgbm8gbW9yZSBuZWVkZWRcbiAgICAgICAgICAgIHdpbmRvdy5yZW1vdmVFdmVudExpc3RlbmVyKCdtZXNzYWdlJywgb25JRnJhbWVDYWxsYmFjayk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBzZXRUaW1lb3V0KHBvc3RHZXRDaHJvbWVFeHRlbnNpb25TdGF0dXNNZXNzYWdlLCAxMDApO1xufTtcblxuZnVuY3Rpb24gcG9zdEdldENocm9tZUV4dGVuc2lvblN0YXR1c01lc3NhZ2UoKSB7XG4gICAgaWYgKCFpZnJhbWUpIHtcbiAgICAgICAgbG9hZElGcmFtZShwb3N0R2V0Q2hyb21lRXh0ZW5zaW9uU3RhdHVzTWVzc2FnZSk7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAoIWlmcmFtZS5pc0xvYWRlZCkge1xuICAgICAgICBzZXRUaW1lb3V0KHBvc3RHZXRDaHJvbWVFeHRlbnNpb25TdGF0dXNNZXNzYWdlLCAxMDApO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWZyYW1lLmNvbnRlbnRXaW5kb3cucG9zdE1lc3NhZ2Uoe1xuICAgICAgICBnZXRDaHJvbWVFeHRlbnNpb25TdGF0dXM6IHRydWVcbiAgICB9LCAnKicpO1xufVxuXG5leHBvcnRzLmdldFNjcmVlbklkID0gZ2V0U2NyZWVuSWQ7IiwiLy8gZ2xvYmFsIHZhcmlhYmxlc1xudmFyIGNocm9tZU1lZGlhU291cmNlID0gJ3NjcmVlbic7XG52YXIgc291cmNlSWQ7XG52YXIgc2NyZWVuQ2FsbGJhY2s7XG52YXIgaXNGaXJlZm94ID0gdHlwZW9mIHdpbmRvdy5JbnN0YWxsVHJpZ2dlciAhPT0gJ3VuZGVmaW5lZCc7XG52YXIgaXNPcGVyYSA9ICEhd2luZG93Lm9wZXJhIHx8IG5hdmlnYXRvci51c2VyQWdlbnQuaW5kZXhPZignIE9QUi8nKSA+PSAwO1xudmFyIGlzQ2hyb21lID0gISF3aW5kb3cuY2hyb21lICYmICFpc09wZXJhO1xuXG53aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcignbWVzc2FnZScsIGZ1bmN0aW9uIChldmVudCkge1xuICAgIGlmIChldmVudC5vcmlnaW4gIT0gd2luZG93LmxvY2F0aW9uLm9yaWdpbikge1xuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIG9uTWVzc2FnZUNhbGxiYWNrKGV2ZW50LmRhdGEpO1xufSk7XG5cbi8vIGFuZCB0aGUgZnVuY3Rpb24gdGhhdCBoYW5kbGVzIHJlY2VpdmVkIG1lc3NhZ2VzXG5mdW5jdGlvbiBvbk1lc3NhZ2VDYWxsYmFjayhkYXRhKSB7XG4gICAgLy8gXCJjYW5jZWxcIiBidXR0b24gaXMgY2xpY2tlZFxuICAgIGlmIChkYXRhID09ICdQZXJtaXNzaW9uRGVuaWVkRXJyb3InKSB7XG4gICAgICAgIGlmIChzY3JlZW5DYWxsYmFjaylcbiAgICAgICAgICAgIHJldHVybiBzY3JlZW5DYWxsYmFjaygnUGVybWlzc2lvbkRlbmllZEVycm9yJyk7XG4gICAgICAgIGVsc2VcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignUGVybWlzc2lvbkRlbmllZEVycm9yJyk7XG4gICAgfVxuICAgIC8vIGV4dGVuc2lvbiBub3RpZmllZCBoaXMgcHJlc2VuY2VcbiAgICBpZiAoZGF0YSA9PSAncnRjbXVsdGljb25uZWN0aW9uLWV4dGVuc2lvbi1sb2FkZWQnKSB7XG4gICAgICAgIGNocm9tZU1lZGlhU291cmNlID0gJ2Rlc2t0b3AnO1xuICAgIH1cbiAgICAvLyBleHRlbnNpb24gc2hhcmVkIHRlbXAgc291cmNlSWRcbiAgICBpZiAoZGF0YS5zb3VyY2VJZCAmJiBzY3JlZW5DYWxsYmFjaykge1xuICAgICAgICBzY3JlZW5DYWxsYmFjayhzb3VyY2VJZCA9IGRhdGEuc291cmNlSWQsIGRhdGEuY2FuUmVxdWVzdEF1ZGlvVHJhY2sgPT09IHRydWUpO1xuICAgIH1cbn1cblxuLy8gdGhpcyBtZXRob2QgY2FuIGJlIHVzZWQgdG8gY2hlY2sgaWYgY2hyb21lIGV4dGVuc2lvbiBpcyBpbnN0YWxsZWQgJiBlbmFibGVkLlxuZnVuY3Rpb24gaXNDaHJvbWVFeHRlbnNpb25BdmFpbGFibGUoY2FsbGJhY2spIHtcbiAgICBpZiAoIWNhbGxiYWNrKSByZXR1cm47XG4gICAgaWYgKGNocm9tZU1lZGlhU291cmNlID09ICdkZXNrdG9wJykgcmV0dXJuIGNhbGxiYWNrKHRydWUpO1xuXG4gICAgLy8gYXNrIGV4dGVuc2lvbiBpZiBpdCBpcyBhdmFpbGFibGVcbiAgICB3aW5kb3cucG9zdE1lc3NhZ2UoJ2FyZS15b3UtdGhlcmUnLCAnKicpO1xuICAgIHNldFRpbWVvdXQoZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAoY2hyb21lTWVkaWFTb3VyY2UgPT0gJ3NjcmVlbicpIHtcbiAgICAgICAgICAgIGNhbGxiYWNrKGZhbHNlKTtcbiAgICAgICAgfSBlbHNlIGNhbGxiYWNrKHRydWUpO1xuICAgIH0sIDIwMDApO1xufVxuXG4vLyB0aGlzIGZ1bmN0aW9uIGNhbiBiZSB1c2VkIHRvIGdldCBcInNvdXJjZS1pZFwiIGZyb20gdGhlIGV4dGVuc2lvblxuZnVuY3Rpb24gZ2V0U291cmNlSWQoY2FsbGJhY2spIHtcbiAgICBpZiAoIWNhbGxiYWNrKVxuICAgICAgICB0aHJvdyAnXCJjYWxsYmFja1wiIHBhcmFtZXRlciBpcyBtYW5kYXRvcnkuJztcbiAgICBpZiAoc291cmNlSWQpXG4gICAgICAgIHJldHVybiBjYWxsYmFjayhzb3VyY2VJZCk7XG4gICAgc2NyZWVuQ2FsbGJhY2sgPSBjYWxsYmFjaztcbiAgICB3aW5kb3cucG9zdE1lc3NhZ2UoJ2dldC1zb3VyY2VJZCcsICcqJyk7XG59XG5cbi8vIHRoaXMgZnVuY3Rpb24gY2FuIGJlIHVzZWQgdG8gZ2V0IFwic291cmNlLWlkXCIgZnJvbSB0aGUgZXh0ZW5zaW9uXG5mdW5jdGlvbiBnZXRDdXN0b21Tb3VyY2VJZChhcnIsIGNhbGxiYWNrKSB7XG4gICAgaWYgKCFhcnIgfHwgIWFyci5mb3JFYWNoKSB0aHJvdyAnXCJhcnJcIiBwYXJhbWV0ZXIgaXMgbWFuZGF0b3J5IGFuZCBpdCBtdXN0IGJlIGFuIGFycmF5Lic7XG4gICAgaWYgKCFjYWxsYmFjaykgdGhyb3cgJ1wiY2FsbGJhY2tcIiBwYXJhbWV0ZXIgaXMgbWFuZGF0b3J5Lic7XG5cbiAgICBpZiAoc291cmNlSWQpIHJldHVybiBjYWxsYmFjayhzb3VyY2VJZCk7XG5cbiAgICBzY3JlZW5DYWxsYmFjayA9IGNhbGxiYWNrO1xuICAgIHdpbmRvdy5wb3N0TWVzc2FnZSh7XG4gICAgICAgICdnZXQtY3VzdG9tLXNvdXJjZUlkJzogYXJyXG4gICAgfSwgJyonKTtcbn1cblxuLy8gdGhpcyBmdW5jdGlvbiBjYW4gYmUgdXNlZCB0byBnZXQgXCJzb3VyY2UtaWRcIiBmcm9tIHRoZSBleHRlbnNpb25cbmZ1bmN0aW9uIGdldFNvdXJjZUlkV2l0aEF1ZGlvKGNhbGxiYWNrKSB7XG4gICAgaWYgKCFjYWxsYmFjaykgdGhyb3cgJ1wiY2FsbGJhY2tcIiBwYXJhbWV0ZXIgaXMgbWFuZGF0b3J5Lic7XG4gICAgaWYgKHNvdXJjZUlkKSByZXR1cm4gY2FsbGJhY2soc291cmNlSWQpO1xuXG4gICAgc2NyZWVuQ2FsbGJhY2sgPSBjYWxsYmFjaztcbiAgICB3aW5kb3cucG9zdE1lc3NhZ2UoJ2F1ZGlvLXBsdXMtdGFiJywgJyonKTtcbn1cblxuZnVuY3Rpb24gZ2V0Q2hyb21lRXh0ZW5zaW9uU3RhdHVzKGV4dGVuc2lvbmlkLCBjYWxsYmFjaykge1xuICAgIGlmIChpc0ZpcmVmb3gpXG4gICAgICAgIHJldHVybiBjYWxsYmFjaygnbm90LWNocm9tZScpO1xuICAgIGlmIChhcmd1bWVudHMubGVuZ3RoICE9IDIpIHtcbiAgICAgICAgY2FsbGJhY2sgPSBleHRlbnNpb25pZDtcbiAgICAgICAgZXh0ZW5zaW9uaWQgPSAnbGZjZ2ZlcGFmbm9iZGxvZWNjaG5mYWNsaWJlbmpvbGQnOyAvLyBkZWZhdWx0IGV4dGVuc2lvbi1pZFxuICAgIH1cbiAgICB2YXIgaW1hZ2UgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdpbWcnKTtcbiAgICBpbWFnZS5zcmMgPSAnY2hyb21lLWV4dGVuc2lvbjovLycgKyBleHRlbnNpb25pZCArICcvaWNvbi5wbmcnO1xuICAgIGltYWdlLm9ubG9hZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgY2hyb21lTWVkaWFTb3VyY2UgPSAnc2NyZWVuJztcbiAgICAgICAgd2luZG93LnBvc3RNZXNzYWdlKCdhcmUteW91LXRoZXJlJywgJyonKTtcbiAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBpZiAoY2hyb21lTWVkaWFTb3VyY2UgPT0gJ3NjcmVlbicpIHtcbiAgICAgICAgICAgICAgICBjYWxsYmFjaygnaW5zdGFsbGVkLWRpc2FibGVkJyk7XG4gICAgICAgICAgICB9IGVsc2VcbiAgICAgICAgICAgICAgICBjYWxsYmFjaygnaW5zdGFsbGVkLWVuYWJsZWQnKTtcbiAgICAgICAgfSwgMjAwMCk7XG4gICAgfTtcbiAgICBpbWFnZS5vbmVycm9yID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBjYWxsYmFjaygnbm90LWluc3RhbGxlZCcpO1xuICAgIH07XG59XG5cbmZ1bmN0aW9uIGdldFNjcmVlbkNvbnN0cmFpbnRzV2l0aEF1ZGlvKGNhbGxiYWNrKSB7XG4gICAgZ2V0U2NyZWVuQ29uc3RyYWludHMoY2FsbGJhY2ssIHRydWUpO1xufVxuXG4vLyB0aGlzIGZ1bmN0aW9uIGV4cGxhaW5zIGhvdyB0byB1c2UgYWJvdmUgbWV0aG9kcy9vYmplY3RzXG5mdW5jdGlvbiBnZXRTY3JlZW5Db25zdHJhaW50cyhjYWxsYmFjaywgY2FwdHVyZVNvdXJjZUlkV2l0aEF1ZGlvKSB7XG4gICAgc291cmNlSWQgPSAnJztcbiAgICB2YXIgZmlyZWZveFNjcmVlbkNvbnN0cmFpbnRzID0ge1xuICAgICAgICBtb3pNZWRpYVNvdXJjZTogJ3dpbmRvdycsXG4gICAgICAgIG1lZGlhU291cmNlOiAnd2luZG93J1xuICAgIH07XG4gICAgaWYgKGlzRmlyZWZveClcbiAgICAgICAgcmV0dXJuIGNhbGxiYWNrKG51bGwsIGZpcmVmb3hTY3JlZW5Db25zdHJhaW50cyk7XG4gICAgLy8gdGhpcyBzdGF0ZW1lbnQgZGVmaW5lcyBnZXRVc2VyTWVkaWEgY29uc3RyYWludHNcbiAgICAvLyB0aGF0IHdpbGwgYmUgdXNlZCB0byBjYXB0dXJlIGNvbnRlbnQgb2Ygc2NyZWVuXG4gICAgdmFyIHNjcmVlbl9jb25zdHJhaW50cyA9IHtcbiAgICAgICAgbWFuZGF0b3J5OiB7XG4gICAgICAgICAgICBjaHJvbWVNZWRpYVNvdXJjZTogY2hyb21lTWVkaWFTb3VyY2UsXG4gICAgICAgICAgICBtYXhXaWR0aDogc2NyZWVuLndpZHRoID4gMTkyMCA/IHNjcmVlbi53aWR0aCA6IDE5MjAsXG4gICAgICAgICAgICBtYXhIZWlnaHQ6IHNjcmVlbi5oZWlnaHQgPiAxMDgwID8gc2NyZWVuLmhlaWdodCA6IDEwODBcbiAgICAgICAgfSxcbiAgICAgICAgb3B0aW9uYWw6IFtdXG4gICAgfTtcbiAgICAvLyB0aGlzIHN0YXRlbWVudCB2ZXJpZmllcyBjaHJvbWUgZXh0ZW5zaW9uIGF2YWlsYWJpbGl0eVxuICAgIC8vIGlmIGluc3RhbGxlZCBhbmQgYXZhaWxhYmxlIHRoZW4gaXQgd2lsbCBpbnZva2UgZXh0ZW5zaW9uIEFQSVxuICAgIC8vIG90aGVyd2lzZSBpdCB3aWxsIGZhbGxiYWNrIHRvIGNvbW1hbmQtbGluZSBiYXNlZCBzY3JlZW4gY2FwdHVyaW5nIEFQSVxuICAgIGlmIChjaHJvbWVNZWRpYVNvdXJjZSA9PSAnZGVza3RvcCcgJiYgIXNvdXJjZUlkKSB7XG4gICAgICAgIGlmIChjYXB0dXJlU291cmNlSWRXaXRoQXVkaW8pIHtcbiAgICAgICAgICAgIGdldFNvdXJjZUlkV2l0aEF1ZGlvKGZ1bmN0aW9uIChzb3VyY2VJZCwgY2FuUmVxdWVzdEF1ZGlvVHJhY2spIHtcbiAgICAgICAgICAgICAgICBzY3JlZW5fY29uc3RyYWludHMubWFuZGF0b3J5LmNocm9tZU1lZGlhU291cmNlSWQgPSBzb3VyY2VJZDtcblxuICAgICAgICAgICAgICAgIGlmIChjYW5SZXF1ZXN0QXVkaW9UcmFjaykge1xuICAgICAgICAgICAgICAgICAgICBzY3JlZW5fY29uc3RyYWludHMuY2FuUmVxdWVzdEF1ZGlvVHJhY2sgPSB0cnVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjYWxsYmFjayhzb3VyY2VJZCA9PSAnUGVybWlzc2lvbkRlbmllZEVycm9yJyA/IHNvdXJjZUlkIDogbnVsbCwgc2NyZWVuX2NvbnN0cmFpbnRzKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgZ2V0U291cmNlSWQoZnVuY3Rpb24gKHNvdXJjZUlkKSB7XG4gICAgICAgICAgICAgICAgc2NyZWVuX2NvbnN0cmFpbnRzLm1hbmRhdG9yeS5jaHJvbWVNZWRpYVNvdXJjZUlkID0gc291cmNlSWQ7XG4gICAgICAgICAgICAgICAgY2FsbGJhY2soc291cmNlSWQgPT0gJ1Blcm1pc3Npb25EZW5pZWRFcnJvcicgPyBzb3VyY2VJZCA6IG51bGwsIHNjcmVlbl9jb25zdHJhaW50cyk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gdGhpcyBzdGF0ZW1lbnQgc2V0cyBnZXRzICdzb3VyY2VJZFwiIGFuZCBzZXRzIFwiY2hyb21lTWVkaWFTb3VyY2VJZFwiIFxuICAgIGlmIChjaHJvbWVNZWRpYVNvdXJjZSA9PSAnZGVza3RvcCcpIHtcbiAgICAgICAgc2NyZWVuX2NvbnN0cmFpbnRzLm1hbmRhdG9yeS5jaHJvbWVNZWRpYVNvdXJjZUlkID0gc291cmNlSWQ7XG4gICAgfVxuXG4gICAgLy8gbm93IGludm9raW5nIG5hdGl2ZSBnZXRVc2VyTWVkaWEgQVBJXG4gICAgY2FsbGJhY2sobnVsbCwgc2NyZWVuX2NvbnN0cmFpbnRzKTtcbn1cblxuZXhwb3J0cy5nZXRTY3JlZW5Db25zdHJhaW50cyA9IGdldFNjcmVlbkNvbnN0cmFpbnRzO1xuZXhwb3J0cy5nZXRTY3JlZW5Db25zdHJhaW50c1dpdGhBdWRpbyA9IGdldFNjcmVlbkNvbnN0cmFpbnRzV2l0aEF1ZGlvO1xuZXhwb3J0cy5pc0Nocm9tZUV4dGVuc2lvbkF2YWlsYWJsZSA9IGlzQ2hyb21lRXh0ZW5zaW9uQXZhaWxhYmxlO1xuZXhwb3J0cy5nZXRDaHJvbWVFeHRlbnNpb25TdGF0dXMgPSBnZXRDaHJvbWVFeHRlbnNpb25TdGF0dXM7XG5leHBvcnRzLmdldFNvdXJjZUlkID0gZ2V0U291cmNlSWQ7IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgZnJlZWljZSA9IHJlcXVpcmUoJ2ZyZWVpY2UnKTtcbmltcG9ydCB1dWlkID0gcmVxdWlyZSgndXVpZCcpO1xuaW1wb3J0IHBsYXRmb3JtID0gcmVxdWlyZSgncGxhdGZvcm0nKTtcblxuXG5leHBvcnQgaW50ZXJmYWNlIFdlYlJ0Y1BlZXJDb25maWd1cmF0aW9uIHtcbiAgICBtZWRpYUNvbnN0cmFpbnRzOiB7XG4gICAgICAgIGF1ZGlvOiBib29sZWFuLFxuICAgICAgICB2aWRlbzogYm9vbGVhblxuICAgIH07XG4gICAgc2ltdWxjYXN0OiBib29sZWFuO1xuICAgIG9uaWNlY2FuZGlkYXRlOiAoZXZlbnQpID0+IHZvaWQ7XG4gICAgaWNlU2VydmVyczogUlRDSWNlU2VydmVyW10gfCB1bmRlZmluZWQ7XG4gICAgbWVkaWFTdHJlYW0/OiBNZWRpYVN0cmVhbTtcbiAgICBtb2RlPzogc3RyaW5nOyAvLyBzZW5kb25seSwgcmVjb25seSwgc2VuZHJlY3ZcbiAgICBpZD86IHN0cmluZztcbn1cblxuZXhwb3J0IGNsYXNzIFdlYlJ0Y1BlZXIge1xuXG4gICAgcGM6IFJUQ1BlZXJDb25uZWN0aW9uO1xuICAgIGlkOiBzdHJpbmc7XG4gICAgcmVtb3RlQ2FuZGlkYXRlc1F1ZXVlOiBSVENJY2VDYW5kaWRhdGVbXSA9IFtdO1xuICAgIGxvY2FsQ2FuZGlkYXRlc1F1ZXVlOiBSVENJY2VDYW5kaWRhdGVbXSA9IFtdO1xuXG4gICAgaWNlQ2FuZGlkYXRlTGlzdDogUlRDSWNlQ2FuZGlkYXRlW10gPSBbXTtcblxuICAgIHByaXZhdGUgY2FuZGlkYXRlZ2F0aGVyaW5nZG9uZSA9IGZhbHNlO1xuXG4gICAgY29uc3RydWN0b3IocHJpdmF0ZSBjb25maWd1cmF0aW9uOiBXZWJSdGNQZWVyQ29uZmlndXJhdGlvbikge1xuICAgICAgICB0aGlzLmNvbmZpZ3VyYXRpb24uaWNlU2VydmVycyA9ICghIXRoaXMuY29uZmlndXJhdGlvbi5pY2VTZXJ2ZXJzICYmIHRoaXMuY29uZmlndXJhdGlvbi5pY2VTZXJ2ZXJzLmxlbmd0aCA+IDApID8gdGhpcy5jb25maWd1cmF0aW9uLmljZVNlcnZlcnMgOiBmcmVlaWNlKCk7XG5cbiAgICAgICAgdGhpcy5wYyA9IG5ldyBSVENQZWVyQ29ubmVjdGlvbih7IGljZVNlcnZlcnM6IHRoaXMuY29uZmlndXJhdGlvbi5pY2VTZXJ2ZXJzIH0pO1xuICAgICAgICB0aGlzLmlkID0gISFjb25maWd1cmF0aW9uLmlkID8gY29uZmlndXJhdGlvbi5pZCA6IHV1aWQudjQoKTtcblxuICAgICAgICB0aGlzLnBjLm9uaWNlY2FuZGlkYXRlID0gZXZlbnQgPT4ge1xuICAgICAgICAgICAgY29uc3QgY2FuZGlkYXRlOiBSVENJY2VDYW5kaWRhdGUgPSBldmVudC5jYW5kaWRhdGU7XG4gICAgICAgICAgICBpZiAoY2FuZGlkYXRlKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5sb2NhbENhbmRpZGF0ZXNRdWV1ZS5wdXNoKDxSVENJY2VDYW5kaWRhdGU+eyBjYW5kaWRhdGU6IGNhbmRpZGF0ZS5jYW5kaWRhdGUgfSk7XG4gICAgICAgICAgICAgICAgdGhpcy5jYW5kaWRhdGVnYXRoZXJpbmdkb25lID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgdGhpcy5jb25maWd1cmF0aW9uLm9uaWNlY2FuZGlkYXRlKGV2ZW50LmNhbmRpZGF0ZSk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKCF0aGlzLmNhbmRpZGF0ZWdhdGhlcmluZ2RvbmUpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmNhbmRpZGF0ZWdhdGhlcmluZ2RvbmUgPSB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuXG4gICAgICAgIHRoaXMucGMub25zaWduYWxpbmdzdGF0ZWNoYW5nZSA9ICgpID0+IHtcbiAgICAgICAgICAgIGlmICh0aGlzLnBjLnNpZ25hbGluZ1N0YXRlID09PSAnc3RhYmxlJykge1xuICAgICAgICAgICAgICAgIHdoaWxlICh0aGlzLmljZUNhbmRpZGF0ZUxpc3QubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnBjLmFkZEljZUNhbmRpZGF0ZSg8UlRDSWNlQ2FuZGlkYXRlPnRoaXMuaWNlQ2FuZGlkYXRlTGlzdC5zaGlmdCgpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG5cbiAgICAgICAgdGhpcy5zdGFydCgpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoaXMgZnVuY3Rpb24gY3JlYXRlcyB0aGUgUlRDUGVlckNvbm5lY3Rpb24gb2JqZWN0IHRha2luZyBpbnRvIGFjY291bnQgdGhlXG4gICAgICogcHJvcGVydGllcyByZWNlaXZlZCBpbiB0aGUgY29uc3RydWN0b3IuIEl0IHN0YXJ0cyB0aGUgU0RQIG5lZ290aWF0aW9uXG4gICAgICogcHJvY2VzczogZ2VuZXJhdGVzIHRoZSBTRFAgb2ZmZXIgYW5kIGludm9rZXMgdGhlIG9uc2Rwb2ZmZXIgY2FsbGJhY2suIFRoaXNcbiAgICAgKiBjYWxsYmFjayBpcyBleHBlY3RlZCB0byBzZW5kIHRoZSBTRFAgb2ZmZXIsIGluIG9yZGVyIHRvIG9idGFpbiBhbiBTRFBcbiAgICAgKiBhbnN3ZXIgZnJvbSBhbm90aGVyIHBlZXIuXG4gICAgICovXG4gICAgc3RhcnQoKTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIGlmICh0aGlzLnBjLnNpZ25hbGluZ1N0YXRlID09PSAnY2xvc2VkJykge1xuICAgICAgICAgICAgICAgIHJlamVjdCgnVGhlIHBlZXIgY29ubmVjdGlvbiBvYmplY3QgaXMgaW4gXCJjbG9zZWRcIiBzdGF0ZS4gVGhpcyBpcyBtb3N0IGxpa2VseSBkdWUgdG8gYW4gaW52b2NhdGlvbiBvZiB0aGUgZGlzcG9zZSBtZXRob2QgYmVmb3JlIGFjY2VwdGluZyBpbiB0aGUgZGlhbG9ndWUnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICghIXRoaXMuY29uZmlndXJhdGlvbi5tZWRpYVN0cmVhbSkge1xuICAgICAgICAgICAgICAgIHRoaXMucGMuYWRkU3RyZWFtKHRoaXMuY29uZmlndXJhdGlvbi5tZWRpYVN0cmVhbSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIFtIYWNrXSBodHRwczovL2NvZGUuZ29vZ2xlLmNvbS9wL2Nocm9taXVtL2lzc3Vlcy9kZXRhaWw/aWQ9NDQzNTU4XG4gICAgICAgICAgICBpZiAodGhpcy5jb25maWd1cmF0aW9uLm1vZGUgPT09ICdzZW5kb25seScgJiZcbiAgICAgICAgICAgICAgICAocGxhdGZvcm0ubmFtZSA9PT0gJ0Nocm9tZScgJiYgcGxhdGZvcm0udmVyc2lvbiEudG9TdHJpbmcoKS5zdWJzdHJpbmcoMCwgMikgPT09ICczOScpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5jb25maWd1cmF0aW9uLm1vZGUgPSAnc2VuZHJlY3YnO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoaXMgbWV0aG9kIGZyZWVzIHRoZSByZXNvdXJjZXMgdXNlZCBieSBXZWJSdGNQZWVyXG4gICAgICovXG4gICAgZGlzcG9zZSgpIHtcbiAgICAgICAgY29uc29sZS5kZWJ1ZygnRGlzcG9zaW5nIFdlYlJ0Y1BlZXInKTtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGlmICh0aGlzLnBjKSB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMucGMuc2lnbmFsaW5nU3RhdGUgPT09ICdjbG9zZWQnKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhpcy5yZW1vdGVDYW5kaWRhdGVzUXVldWUgPSBbXTtcbiAgICAgICAgICAgICAgICB0aGlzLmxvY2FsQ2FuZGlkYXRlc1F1ZXVlID0gW107XG5cbiAgICAgICAgICAgICAgICB0aGlzLnBjLmdldExvY2FsU3RyZWFtcygpLmZvckVhY2goc3RyID0+IHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5zdHJlYW1TdG9wKHN0cik7XG4gICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICAvLyBGSVhNRSBUaGlzIGlzIG5vdCB5ZXQgaW1wbGVtZW50ZWQgaW4gZmlyZWZveFxuICAgICAgICAgICAgICAgIC8vIGlmKHZpZGVvU3RyZWFtKSBwYy5yZW1vdmVTdHJlYW0odmlkZW9TdHJlYW0pO1xuICAgICAgICAgICAgICAgIC8vIGlmKGF1ZGlvU3RyZWFtKSBwYy5yZW1vdmVTdHJlYW0oYXVkaW9TdHJlYW0pO1xuXG4gICAgICAgICAgICAgICAgdGhpcy5wYy5jbG9zZSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAgIGNvbnNvbGUud2FybignRXhjZXB0aW9uIGRpc3Bvc2luZyB3ZWJydGMgcGVlciAnICsgZXJyKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIDEpIEZ1bmN0aW9uIHRoYXQgY3JlYXRlcyBhbiBvZmZlciwgc2V0cyBpdCBhcyBsb2NhbCBkZXNjcmlwdGlvbiBhbmQgcmV0dXJucyB0aGUgb2ZmZXIgcGFyYW1cbiAgICAgKiB0byBzZW5kIHRvIE9wZW5WaWR1IFNlcnZlciAod2lsbCBiZSB0aGUgcmVtb3RlIGRlc2NyaXB0aW9uIG9mIG90aGVyIHBlZXIpXG4gICAgICovXG4gICAgZ2VuZXJhdGVPZmZlcigpOiBQcm9taXNlPHN0cmluZz4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgbGV0IG9mZmVyQXVkaW8sIG9mZmVyVmlkZW8gPSB0cnVlO1xuXG4gICAgICAgICAgICAvLyBDb25zdHJhaW50cyBtdXN0IGhhdmUgYm90aCBibG9ja3NcbiAgICAgICAgICAgIGlmICghIXRoaXMuY29uZmlndXJhdGlvbi5tZWRpYUNvbnN0cmFpbnRzKSB7XG4gICAgICAgICAgICAgICAgb2ZmZXJBdWRpbyA9ICh0eXBlb2YgdGhpcy5jb25maWd1cmF0aW9uLm1lZGlhQ29uc3RyYWludHMuYXVkaW8gPT09ICdib29sZWFuJykgP1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbmZpZ3VyYXRpb24ubWVkaWFDb25zdHJhaW50cy5hdWRpbyA6IHRydWU7XG4gICAgICAgICAgICAgICAgb2ZmZXJWaWRlbyA9ICh0eXBlb2YgdGhpcy5jb25maWd1cmF0aW9uLm1lZGlhQ29uc3RyYWludHMudmlkZW8gPT09ICdib29sZWFuJykgP1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbmZpZ3VyYXRpb24ubWVkaWFDb25zdHJhaW50cy52aWRlbyA6IHRydWU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGNvbnN0IGNvbnN0cmFpbnRzOiBSVENPZmZlck9wdGlvbnMgPSB7XG4gICAgICAgICAgICAgICAgb2ZmZXJUb1JlY2VpdmVBdWRpbzogKyAodGhpcy5jb25maWd1cmF0aW9uLm1vZGUgIT09ICdzZW5kb25seScgJiYgb2ZmZXJBdWRpbyksXG4gICAgICAgICAgICAgICAgb2ZmZXJUb1JlY2VpdmVWaWRlbzogKyAodGhpcy5jb25maWd1cmF0aW9uLm1vZGUgIT09ICdzZW5kb25seScgJiYgb2ZmZXJWaWRlbylcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIGNvbnNvbGUuZGVidWcoJ1JUQ1BlZXJDb25uZWN0aW9uIGNvbnN0cmFpbnRzOiAnICsgSlNPTi5zdHJpbmdpZnkoY29uc3RyYWludHMpKTtcblxuICAgICAgICAgICAgdGhpcy5wYy5jcmVhdGVPZmZlcihjb25zdHJhaW50cykudGhlbihvZmZlciA9PiB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5kZWJ1ZygnQ3JlYXRlZCBTRFAgb2ZmZXInKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5wYy5zZXRMb2NhbERlc2NyaXB0aW9uKG9mZmVyKTtcbiAgICAgICAgICAgIH0pLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IGxvY2FsRGVzY3JpcHRpb24gPSB0aGlzLnBjLmxvY2FsRGVzY3JpcHRpb247XG4gICAgICAgICAgICAgICAgaWYgKCEhbG9jYWxEZXNjcmlwdGlvbikge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmRlYnVnKCdMb2NhbCBkZXNjcmlwdGlvbiBzZXQnLCBsb2NhbERlc2NyaXB0aW9uLnNkcCk7XG4gICAgICAgICAgICAgICAgICAgIHJlc29sdmUoPHN0cmluZz5sb2NhbERlc2NyaXB0aW9uLnNkcCk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcmVqZWN0KCdMb2NhbCBkZXNjcmlwdGlvbiBpcyBub3QgZGVmaW5lZCcpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pLmNhdGNoKGVycm9yID0+IHJlamVjdChlcnJvcikpO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiAyKSBGdW5jdGlvbiB0byBpbnZva2Ugd2hlbiBhIFNEUCBvZmZlciBpcyByZWNlaXZlZC4gU2V0cyBpdCBhcyByZW1vdGUgZGVzY3JpcHRpb24sXG4gICAgICogZ2VuZXJhdGVzIGFuZCBhbnN3ZXIgYW5kIHJldHVybnMgaXQgdG8gc2VuZCBpdCB0byBPcGVuVmlkdSBTZXJ2ZXJcbiAgICAgKi9cbiAgICBwcm9jZXNzT2ZmZXIoc2RwT2ZmZXI6IHN0cmluZyk6IFByb21pc2U8Q29uc3RyYWluRE9NU3RyaW5nPiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICBjb25zdCBvZmZlcjogUlRDU2Vzc2lvbkRlc2NyaXB0aW9uSW5pdCA9IHtcbiAgICAgICAgICAgICAgICB0eXBlOiAnb2ZmZXInLFxuICAgICAgICAgICAgICAgIHNkcDogc2RwT2ZmZXJcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIGNvbnNvbGUuZGVidWcoJ1NEUCBvZmZlciByZWNlaXZlZCwgc2V0dGluZyByZW1vdGUgZGVzY3JpcHRpb24nKTtcblxuICAgICAgICAgICAgaWYgKHRoaXMucGMuc2lnbmFsaW5nU3RhdGUgPT09ICdjbG9zZWQnKSB7XG4gICAgICAgICAgICAgICAgcmVqZWN0KCdQZWVyQ29ubmVjdGlvbiBpcyBjbG9zZWQnKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5wYy5zZXRSZW1vdGVEZXNjcmlwdGlvbihvZmZlcilcbiAgICAgICAgICAgICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLnBjLmNyZWF0ZUFuc3dlcigpO1xuICAgICAgICAgICAgICAgIH0pLnRoZW4oYW5zd2VyID0+IHtcbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS5kZWJ1ZygnQ3JlYXRlZCBTRFAgYW5zd2VyJyk7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLnBjLnNldExvY2FsRGVzY3JpcHRpb24oYW5zd2VyKTtcbiAgICAgICAgICAgICAgICB9KS50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgbG9jYWxEZXNjcmlwdGlvbiA9IHRoaXMucGMubG9jYWxEZXNjcmlwdGlvbjtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCEhbG9jYWxEZXNjcmlwdGlvbikge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5kZWJ1ZygnTG9jYWwgZGVzY3JpcHRpb24gc2V0JywgbG9jYWxEZXNjcmlwdGlvbi5zZHApO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSg8c3RyaW5nPmxvY2FsRGVzY3JpcHRpb24uc2RwKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdCgnTG9jYWwgZGVzY3JpcHRpb24gaXMgbm90IGRlZmluZWQnKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pLmNhdGNoKGVycm9yID0+IHJlamVjdChlcnJvcikpO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiAzKSBGdW5jdGlvbiBpbnZva2VkIHdoZW4gYSBTRFAgYW5zd2VyIGlzIHJlY2VpdmVkLiBGaW5hbCBzdGVwIGluIFNEUCBuZWdvdGlhdGlvbiwgdGhlIHBlZXJcbiAgICAgKiBqdXN0IG5lZWRzIHRvIHNldCB0aGUgYW5zd2VyIGFzIGl0cyByZW1vdGUgZGVzY3JpcHRpb25cbiAgICAgKi9cbiAgICBwcm9jZXNzQW5zd2VyKHNkcEFuc3dlcjogc3RyaW5nKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcblxuICAgICAgICAgICAgY29uc3QgYW5zd2VyOiBSVENTZXNzaW9uRGVzY3JpcHRpb25Jbml0ID0ge1xuICAgICAgICAgICAgICAgIHR5cGU6ICdhbnN3ZXInLFxuICAgICAgICAgICAgICAgIHNkcDogc2RwQW5zd2VyXG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICBjb25zb2xlLmRlYnVnKCdTRFAgYW5zd2VyIHJlY2VpdmVkLCBzZXR0aW5nIHJlbW90ZSBkZXNjcmlwdGlvbicpO1xuXG4gICAgICAgICAgICBpZiAodGhpcy5wYy5zaWduYWxpbmdTdGF0ZSA9PT0gJ2Nsb3NlZCcpIHtcbiAgICAgICAgICAgICAgICByZWplY3QoJ1JUQ1BlZXJDb25uZWN0aW9uIGlzIGNsb3NlZCcpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLnBjLnNldFJlbW90ZURlc2NyaXB0aW9uKGFuc3dlcikudGhlbigoKSA9PiByZXNvbHZlKCkpLmNhdGNoKGVycm9yID0+IHJlamVjdChlcnJvcikpO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDYWxsYmFjayBmdW5jdGlvbiBpbnZva2VkIHdoZW4gYW4gSUNFIGNhbmRpZGF0ZSBpcyByZWNlaXZlZFxuICAgICAqL1xuICAgIGFkZEljZUNhbmRpZGF0ZShpY2VDYW5kaWRhdGU6IFJUQ0ljZUNhbmRpZGF0ZSk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgY29uc29sZS5kZWJ1ZygnUmVtb3RlIElDRSBjYW5kaWRhdGUgcmVjZWl2ZWQnLCBpY2VDYW5kaWRhdGUpO1xuICAgICAgICAgICAgdGhpcy5yZW1vdGVDYW5kaWRhdGVzUXVldWUucHVzaChpY2VDYW5kaWRhdGUpO1xuICAgICAgICAgICAgc3dpdGNoICh0aGlzLnBjLnNpZ25hbGluZ1N0YXRlKSB7XG4gICAgICAgICAgICAgICAgY2FzZSAnY2xvc2VkJzpcbiAgICAgICAgICAgICAgICAgICAgcmVqZWN0KG5ldyBFcnJvcignUGVlckNvbm5lY3Rpb24gb2JqZWN0IGlzIGNsb3NlZCcpKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAnc3RhYmxlJzpcbiAgICAgICAgICAgICAgICAgICAgaWYgKCEhdGhpcy5wYy5yZW1vdGVEZXNjcmlwdGlvbikge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5wYy5hZGRJY2VDYW5kaWRhdGUoaWNlQ2FuZGlkYXRlKS50aGVuKCgpID0+IHJlc29sdmUoKSkuY2F0Y2goZXJyb3IgPT4gcmVqZWN0KGVycm9yKSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5pY2VDYW5kaWRhdGVMaXN0LnB1c2goaWNlQ2FuZGlkYXRlKTtcbiAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBwcml2YXRlIHN0cmVhbVN0b3Aoc3RyZWFtOiBNZWRpYVN0cmVhbSk6IHZvaWQge1xuICAgICAgICBzdHJlYW0uZ2V0VHJhY2tzKCkuZm9yRWFjaCh0cmFjayA9PiB7XG4gICAgICAgICAgICB0cmFjay5zdG9wKCk7XG4gICAgICAgICAgICBzdHJlYW0ucmVtb3ZlVHJhY2sodHJhY2spO1xuICAgICAgICB9KTtcbiAgICB9XG59XG5cblxuZXhwb3J0IGNsYXNzIFdlYlJ0Y1BlZXJSZWN2b25seSBleHRlbmRzIFdlYlJ0Y1BlZXIge1xuICAgIGNvbnN0cnVjdG9yKGNvbmZpZ3VyYXRpb246IFdlYlJ0Y1BlZXJDb25maWd1cmF0aW9uKSB7XG4gICAgICAgIGNvbmZpZ3VyYXRpb24ubW9kZSA9ICdyZWN2b25seSc7XG4gICAgICAgIHN1cGVyKGNvbmZpZ3VyYXRpb24pO1xuICAgIH1cbn1cblxuZXhwb3J0IGNsYXNzIFdlYlJ0Y1BlZXJTZW5kb25seSBleHRlbmRzIFdlYlJ0Y1BlZXIge1xuICAgIGNvbnN0cnVjdG9yKGNvbmZpZ3VyYXRpb246IFdlYlJ0Y1BlZXJDb25maWd1cmF0aW9uKSB7XG4gICAgICAgIGNvbmZpZ3VyYXRpb24ubW9kZSA9ICdzZW5kb25seSc7XG4gICAgICAgIHN1cGVyKGNvbmZpZ3VyYXRpb24pO1xuICAgIH1cbn1cblxuZXhwb3J0IGNsYXNzIFdlYlJ0Y1BlZXJTZW5kcmVjdiBleHRlbmRzIFdlYlJ0Y1BlZXIge1xuICAgIGNvbnN0cnVjdG9yKGNvbmZpZ3VyYXRpb246IFdlYlJ0Y1BlZXJDb25maWd1cmF0aW9uKSB7XG4gICAgICAgIGNvbmZpZ3VyYXRpb24ubW9kZSA9ICdzZW5kcmVjdic7XG4gICAgICAgIHN1cGVyKGNvbmZpZ3VyYXRpb24pO1xuICAgIH1cbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbi8vIHRzbGludDpkaXNhYmxlOm5vLXN0cmluZy1saXRlcmFsXG5cbmltcG9ydCB7IFN0cmVhbSB9IGZyb20gJy4uLy4uL09wZW5WaWR1L1N0cmVhbSc7XG5pbXBvcnQgcGxhdGZvcm0gPSByZXF1aXJlKCdwbGF0Zm9ybScpO1xuXG5leHBvcnQgY2xhc3MgV2ViUnRjU3RhdHMge1xuXG4gICAgcHJpdmF0ZSB3ZWJSdGNTdGF0c0VuYWJsZWQgPSBmYWxzZTtcbiAgICBwcml2YXRlIHdlYlJ0Y1N0YXRzSW50ZXJ2YWxJZDogTm9kZUpTLlRpbWVyO1xuICAgIHByaXZhdGUgc3RhdHNJbnRlcnZhbCA9IDE7XG4gICAgcHJpdmF0ZSBzdGF0czogYW55ID0ge1xuICAgICAgICBpbmJvdW5kOiB7XG4gICAgICAgICAgICBhdWRpbzoge1xuICAgICAgICAgICAgICAgIGJ5dGVzUmVjZWl2ZWQ6IDAsXG4gICAgICAgICAgICAgICAgcGFja2V0c1JlY2VpdmVkOiAwLFxuICAgICAgICAgICAgICAgIHBhY2tldHNMb3N0OiAwXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgdmlkZW86IHtcbiAgICAgICAgICAgICAgICBieXRlc1JlY2VpdmVkOiAwLFxuICAgICAgICAgICAgICAgIHBhY2tldHNSZWNlaXZlZDogMCxcbiAgICAgICAgICAgICAgICBwYWNrZXRzTG9zdDogMCxcbiAgICAgICAgICAgICAgICBmcmFtZXNEZWNvZGVkOiAwLFxuICAgICAgICAgICAgICAgIG5hY2tDb3VudDogMFxuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBvdXRib3VuZDoge1xuICAgICAgICAgICAgYXVkaW86IHtcbiAgICAgICAgICAgICAgICBieXRlc1NlbnQ6IDAsXG4gICAgICAgICAgICAgICAgcGFja2V0c1NlbnQ6IDAsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgdmlkZW86IHtcbiAgICAgICAgICAgICAgICBieXRlc1NlbnQ6IDAsXG4gICAgICAgICAgICAgICAgcGFja2V0c1NlbnQ6IDAsXG4gICAgICAgICAgICAgICAgZnJhbWVzRW5jb2RlZDogMCxcbiAgICAgICAgICAgICAgICBuYWNrQ291bnQ6IDBcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH07XG5cbiAgICBjb25zdHJ1Y3Rvcihwcml2YXRlIHN0cmVhbTogU3RyZWFtKSB7IH1cblxuICAgIHB1YmxpYyBpc0VuYWJsZWQoKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiB0aGlzLndlYlJ0Y1N0YXRzRW5hYmxlZDtcbiAgICB9XG5cbiAgICBwdWJsaWMgaW5pdFdlYlJ0Y1N0YXRzKCk6IHZvaWQge1xuXG4gICAgICAgIGNvbnN0IGVsYXN0ZXN0SW5zdHJ1bWVudGF0aW9uID0gbG9jYWxTdG9yYWdlLmdldEl0ZW0oJ2VsYXN0ZXN0LWluc3RydW1lbnRhdGlvbicpO1xuXG4gICAgICAgIGlmIChlbGFzdGVzdEluc3RydW1lbnRhdGlvbikge1xuICAgICAgICAgICAgLy8gRWxhc1Rlc3QgaW5zdHJ1bWVudGF0aW9uIG9iamVjdCBmb3VuZCBpbiBsb2NhbCBzdG9yYWdlXG5cbiAgICAgICAgICAgIGNvbnNvbGUud2FybignV2ViUnRjIHN0YXRzIGVuYWJsZWQgZm9yIHN0cmVhbSAnICsgdGhpcy5zdHJlYW0uc3RyZWFtSWQgKyAnIG9mIGNvbm5lY3Rpb24gJyArIHRoaXMuc3RyZWFtLmNvbm5lY3Rpb24uY29ubmVjdGlvbklkKTtcblxuICAgICAgICAgICAgdGhpcy53ZWJSdGNTdGF0c0VuYWJsZWQgPSB0cnVlO1xuXG4gICAgICAgICAgICBjb25zdCBpbnN0cnVtZW50YXRpb24gPSBKU09OLnBhcnNlKGVsYXN0ZXN0SW5zdHJ1bWVudGF0aW9uKTtcbiAgICAgICAgICAgIHRoaXMuc3RhdHNJbnRlcnZhbCA9IGluc3RydW1lbnRhdGlvbi53ZWJydGMuaW50ZXJ2YWw7ICAvLyBJbnRlcnZhbCBpbiBzZWNvbmRzXG5cbiAgICAgICAgICAgIGNvbnNvbGUud2FybignbG9jYWxTdG9yYWdlIGl0ZW06ICcgKyBKU09OLnN0cmluZ2lmeShpbnN0cnVtZW50YXRpb24pKTtcblxuICAgICAgICAgICAgdGhpcy53ZWJSdGNTdGF0c0ludGVydmFsSWQgPSBzZXRJbnRlcnZhbCgoKSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5zZW5kU3RhdHNUb0h0dHBFbmRwb2ludChpbnN0cnVtZW50YXRpb24pO1xuICAgICAgICAgICAgfSwgdGhpcy5zdGF0c0ludGVydmFsICogMTAwMCk7XG5cbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnNvbGUuZGVidWcoJ1dlYlJ0YyBzdGF0cyBub3QgZW5hYmxlZCcpO1xuICAgIH1cblxuICAgIHB1YmxpYyBzdG9wV2ViUnRjU3RhdHMoKSB7XG4gICAgICAgIGlmICh0aGlzLndlYlJ0Y1N0YXRzRW5hYmxlZCkge1xuICAgICAgICAgICAgY2xlYXJJbnRlcnZhbCh0aGlzLndlYlJ0Y1N0YXRzSW50ZXJ2YWxJZCk7XG4gICAgICAgICAgICBjb25zb2xlLndhcm4oJ1dlYlJ0YyBzdGF0cyBzdG9wcGVkIGZvciBkaXNwb3NlZCBzdHJlYW0gJyArIHRoaXMuc3RyZWFtLnN0cmVhbUlkICsgJyBvZiBjb25uZWN0aW9uICcgKyB0aGlzLnN0cmVhbS5jb25uZWN0aW9uLmNvbm5lY3Rpb25JZCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwdWJsaWMgZ2V0U2VsZWN0ZWRJY2VDYW5kaWRhdGVJbmZvKCk6IFByb21pc2U8YW55PiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICB0aGlzLmdldFN0YXRzQWdub3N0aWModGhpcy5zdHJlYW0uZ2V0UlRDUGVlckNvbm5lY3Rpb24oKSxcbiAgICAgICAgICAgICAgICAoc3RhdHMpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKChwbGF0Zm9ybS5uYW1lIS5pbmRleE9mKCdDaHJvbWUnKSAhPT0gLTEpIHx8IChwbGF0Zm9ybS5uYW1lIS5pbmRleE9mKCdPcGVyYScpICE9PSAtMSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBsb2NhbENhbmRpZGF0ZUlkLCByZW1vdGVDYW5kaWRhdGVJZCwgZ29vZ0NhbmRpZGF0ZVBhaXI7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBsb2NhbENhbmRpZGF0ZXMgPSB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHJlbW90ZUNhbmRpZGF0ZXMgPSB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAoY29uc3Qga2V5IGluIHN0YXRzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3Qgc3RhdCA9IHN0YXRzW2tleV07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHN0YXQudHlwZSA9PT0gJ2xvY2FsY2FuZGlkYXRlJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsb2NhbENhbmRpZGF0ZXNbc3RhdC5pZF0gPSBzdGF0O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoc3RhdC50eXBlID09PSAncmVtb3RlY2FuZGlkYXRlJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZW1vdGVDYW5kaWRhdGVzW3N0YXQuaWRdID0gc3RhdDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHN0YXQudHlwZSA9PT0gJ2dvb2dDYW5kaWRhdGVQYWlyJyAmJiAoc3RhdC5nb29nQWN0aXZlQ29ubmVjdGlvbiA9PT0gJ3RydWUnKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnb29nQ2FuZGlkYXRlUGFpciA9IHN0YXQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxvY2FsQ2FuZGlkYXRlSWQgPSBzdGF0LmxvY2FsQ2FuZGlkYXRlSWQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlbW90ZUNhbmRpZGF0ZUlkID0gc3RhdC5yZW1vdGVDYW5kaWRhdGVJZDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBsZXQgZmluYWxMb2NhbENhbmRpZGF0ZSA9IGxvY2FsQ2FuZGlkYXRlc1tsb2NhbENhbmRpZGF0ZUlkXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghIWZpbmFsTG9jYWxDYW5kaWRhdGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBjYW5kTGlzdCA9IHRoaXMuc3RyZWFtLmdldExvY2FsSWNlQ2FuZGlkYXRlTGlzdCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGNhbmQgPSBjYW5kTGlzdC5maWx0ZXIoKGM6IFJUQ0ljZUNhbmRpZGF0ZSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gKCEhYy5jYW5kaWRhdGUgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuY2FuZGlkYXRlLmluZGV4T2YoZmluYWxMb2NhbENhbmRpZGF0ZS5pcEFkZHJlc3MpID49IDAgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuY2FuZGlkYXRlLmluZGV4T2YoZmluYWxMb2NhbENhbmRpZGF0ZS5wb3J0TnVtYmVyKSA+PSAwICYmXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjLmNhbmRpZGF0ZS5pbmRleE9mKGZpbmFsTG9jYWxDYW5kaWRhdGUucHJpb3JpdHkpID49IDApO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbmFsTG9jYWxDYW5kaWRhdGUucmF3ID0gISFjYW5kWzBdID8gY2FuZFswXS5jYW5kaWRhdGUgOiAnRVJST1I6IENhbm5vdCBmaW5kIGxvY2FsIGNhbmRpZGF0ZSBpbiBsaXN0IG9mIHNlbnQgSUNFIGNhbmRpZGF0ZXMnO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaW5hbExvY2FsQ2FuZGlkYXRlID0gJ0VSUk9SOiBObyBhY3RpdmUgbG9jYWwgSUNFIGNhbmRpZGF0ZS4gUHJvYmFibHkgSUNFLVRDUCBpcyBiZWluZyB1c2VkJztcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGZpbmFsUmVtb3RlQ2FuZGlkYXRlID0gcmVtb3RlQ2FuZGlkYXRlc1tyZW1vdGVDYW5kaWRhdGVJZF07XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoISFmaW5hbFJlbW90ZUNhbmRpZGF0ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGNhbmRMaXN0ID0gdGhpcy5zdHJlYW0uZ2V0UmVtb3RlSWNlQ2FuZGlkYXRlTGlzdCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGNhbmQgPSBjYW5kTGlzdC5maWx0ZXIoKGM6IFJUQ0ljZUNhbmRpZGF0ZSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gKCEhYy5jYW5kaWRhdGUgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuY2FuZGlkYXRlLmluZGV4T2YoZmluYWxSZW1vdGVDYW5kaWRhdGUuaXBBZGRyZXNzKSA+PSAwICYmXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjLmNhbmRpZGF0ZS5pbmRleE9mKGZpbmFsUmVtb3RlQ2FuZGlkYXRlLnBvcnROdW1iZXIpID49IDAgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuY2FuZGlkYXRlLmluZGV4T2YoZmluYWxSZW1vdGVDYW5kaWRhdGUucHJpb3JpdHkpID49IDApO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbmFsUmVtb3RlQ2FuZGlkYXRlLnJhdyA9ICEhY2FuZFswXSA/IGNhbmRbMF0uY2FuZGlkYXRlIDogJ0VSUk9SOiBDYW5ub3QgZmluZCByZW1vdGUgY2FuZGlkYXRlIGluIGxpc3Qgb2YgcmVjZWl2ZWQgSUNFIGNhbmRpZGF0ZXMnO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaW5hbFJlbW90ZUNhbmRpZGF0ZSA9ICdFUlJPUjogTm8gYWN0aXZlIHJlbW90ZSBJQ0UgY2FuZGlkYXRlLiBQcm9iYWJseSBJQ0UtVENQIGlzIGJlaW5nIHVzZWQnO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICByZXNvbHZlKHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBnb29nQ2FuZGlkYXRlUGFpcixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsb2NhbENhbmRpZGF0ZTogZmluYWxMb2NhbENhbmRpZGF0ZSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZW1vdGVDYW5kaWRhdGU6IGZpbmFsUmVtb3RlQ2FuZGlkYXRlXG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdCgnU2VsZWN0ZWQgSUNFIGNhbmRpZGF0ZSBpbmZvIG9ubHkgYXZhaWxhYmxlIGZvciBDaHJvbWUnKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgKGVycm9yKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIHByaXZhdGUgc2VuZFN0YXRzVG9IdHRwRW5kcG9pbnQoaW5zdHJ1bWVudGF0aW9uKTogdm9pZCB7XG5cbiAgICAgICAgY29uc3Qgc2VuZFBvc3QgPSAoanNvbikgPT4ge1xuICAgICAgICAgICAgY29uc3QgaHR0cDogWE1MSHR0cFJlcXVlc3QgPSBuZXcgWE1MSHR0cFJlcXVlc3QoKTtcbiAgICAgICAgICAgIGNvbnN0IHVybDogc3RyaW5nID0gaW5zdHJ1bWVudGF0aW9uLndlYnJ0Yy5odHRwRW5kcG9pbnQ7XG4gICAgICAgICAgICBodHRwLm9wZW4oJ1BPU1QnLCB1cmwsIHRydWUpO1xuXG4gICAgICAgICAgICBodHRwLnNldFJlcXVlc3RIZWFkZXIoJ0NvbnRlbnQtdHlwZScsICdhcHBsaWNhdGlvbi9qc29uJyk7XG5cbiAgICAgICAgICAgIGh0dHAub25yZWFkeXN0YXRlY2hhbmdlID0gKCkgPT4geyAvLyBDYWxsIGEgZnVuY3Rpb24gd2hlbiB0aGUgc3RhdGUgY2hhbmdlcy5cbiAgICAgICAgICAgICAgICBpZiAoaHR0cC5yZWFkeVN0YXRlID09PSA0ICYmIGh0dHAuc3RhdHVzID09PSAyMDApIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS5sb2coJ1dlYlJ0YyBzdGF0cyBzdWNjZXNzZnVsbHkgc2VudCB0byAnICsgdXJsICsgJyBmb3Igc3RyZWFtICcgKyB0aGlzLnN0cmVhbS5zdHJlYW1JZCArICcgb2YgY29ubmVjdGlvbiAnICsgdGhpcy5zdHJlYW0uY29ubmVjdGlvbi5jb25uZWN0aW9uSWQpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBodHRwLnNlbmQoanNvbik7XG4gICAgICAgIH07XG5cbiAgICAgICAgY29uc3QgZiA9IChzdGF0cykgPT4ge1xuXG4gICAgICAgICAgICBpZiAocGxhdGZvcm0ubmFtZSEuaW5kZXhPZignRmlyZWZveCcpICE9PSAtMSkge1xuICAgICAgICAgICAgICAgIHN0YXRzLmZvckVhY2goKHN0YXQpID0+IHtcblxuICAgICAgICAgICAgICAgICAgICBsZXQganNvbiA9IHt9O1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICgoc3RhdC50eXBlID09PSAnaW5ib3VuZC1ydHAnKSAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEF2b2lkIGZpcmVmb3ggZW1wdHkgb3V0Ym91bmQtcnRwIHN0YXRpc3RpY3NcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGF0Lm5hY2tDb3VudCAhPT0gbnVsbCAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0YXQuaXNSZW1vdGUgPT09IGZhbHNlICYmXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhdC5pZC5zdGFydHNXaXRoKCdpbmJvdW5kJykgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGF0LnJlbW90ZUlkLnN0YXJ0c1dpdGgoJ2luYm91bmQnKVxuICAgICAgICAgICAgICAgICAgICAgICAgKSkge1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBtZXRyaWNJZCA9ICd3ZWJydGNfaW5ib3VuZF8nICsgc3RhdC5tZWRpYVR5cGUgKyAnXycgKyBzdGF0LnNzcmM7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBqaXQgPSBzdGF0LmppdHRlciAqIDEwMDA7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG1ldHJpY3MgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnl0ZXNSZWNlaXZlZDogKHN0YXQuYnl0ZXNSZWNlaXZlZCAtIHRoaXMuc3RhdHMuaW5ib3VuZFtzdGF0Lm1lZGlhVHlwZV0uYnl0ZXNSZWNlaXZlZCkgLyB0aGlzLnN0YXRzSW50ZXJ2YWwsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaml0dGVyOiBqaXQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFja2V0c1JlY2VpdmVkOiAoc3RhdC5wYWNrZXRzUmVjZWl2ZWQgLSB0aGlzLnN0YXRzLmluYm91bmRbc3RhdC5tZWRpYVR5cGVdLnBhY2tldHNSZWNlaXZlZCkgLyB0aGlzLnN0YXRzSW50ZXJ2YWwsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFja2V0c0xvc3Q6IChzdGF0LnBhY2tldHNMb3N0IC0gdGhpcy5zdGF0cy5pbmJvdW5kW3N0YXQubWVkaWFUeXBlXS5wYWNrZXRzTG9zdCkgLyB0aGlzLnN0YXRzSW50ZXJ2YWxcbiAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB1bml0cyA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBieXRlc1JlY2VpdmVkOiAnYnl0ZXMnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGppdHRlcjogJ21zJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYWNrZXRzUmVjZWl2ZWQ6ICdwYWNrZXRzJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYWNrZXRzTG9zdDogJ3BhY2tldHMnXG4gICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHN0YXQubWVkaWFUeXBlID09PSAndmlkZW8nKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbWV0cmljc1snZnJhbWVzRGVjb2RlZCddID0gKHN0YXQuZnJhbWVzRGVjb2RlZCAtIHRoaXMuc3RhdHMuaW5ib3VuZC52aWRlby5mcmFtZXNEZWNvZGVkKSAvIHRoaXMuc3RhdHNJbnRlcnZhbDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXRyaWNzWyduYWNrQ291bnQnXSA9IChzdGF0Lm5hY2tDb3VudCAtIHRoaXMuc3RhdHMuaW5ib3VuZC52aWRlby5uYWNrQ291bnQpIC8gdGhpcy5zdGF0c0ludGVydmFsO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVuaXRzWydmcmFtZXNEZWNvZGVkJ10gPSAnZnJhbWVzJztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB1bml0c1snbmFja0NvdW50J10gPSAncGFja2V0cyc7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXRzLmluYm91bmQudmlkZW8uZnJhbWVzRGVjb2RlZCA9IHN0YXQuZnJhbWVzRGVjb2RlZDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXRzLmluYm91bmQudmlkZW8ubmFja0NvdW50ID0gc3RhdC5uYWNrQ291bnQ7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdHMuaW5ib3VuZFtzdGF0Lm1lZGlhVHlwZV0uYnl0ZXNSZWNlaXZlZCA9IHN0YXQuYnl0ZXNSZWNlaXZlZDtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdHMuaW5ib3VuZFtzdGF0Lm1lZGlhVHlwZV0ucGFja2V0c1JlY2VpdmVkID0gc3RhdC5wYWNrZXRzUmVjZWl2ZWQ7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXRzLmluYm91bmRbc3RhdC5tZWRpYVR5cGVdLnBhY2tldHNMb3N0ID0gc3RhdC5wYWNrZXRzTG9zdDtcblxuICAgICAgICAgICAgICAgICAgICAgICAganNvbiA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAnQHRpbWVzdGFtcCc6IG5ldyBEYXRlKHN0YXQudGltZXN0YW1wKS50b0lTT1N0cmluZygpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICdleGVjJzogaW5zdHJ1bWVudGF0aW9uLmV4ZWMsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJ2NvbXBvbmVudCc6IGluc3RydW1lbnRhdGlvbi5jb21wb25lbnQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJ3N0cmVhbSc6ICd3ZWJSdGMnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICd0eXBlJzogbWV0cmljSWQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJ3N0cmVhbV90eXBlJzogJ2NvbXBvc2VkX21ldHJpY3MnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICd1bml0cyc6IHVuaXRzXG4gICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAganNvblttZXRyaWNJZF0gPSBtZXRyaWNzO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBzZW5kUG9zdChKU09OLnN0cmluZ2lmeShqc29uKSk7XG5cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICgoc3RhdC50eXBlID09PSAnb3V0Ym91bmQtcnRwJykgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgIChcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBBdm9pZCBmaXJlZm94IGVtcHR5IGluYm91bmQtcnRwIHN0YXRpc3RpY3NcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGF0LmlzUmVtb3RlID09PSBmYWxzZSAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0YXQuaWQudG9Mb3dlckNhc2UoKS5pbmNsdWRlcygnb3V0Ym91bmQnKVxuICAgICAgICAgICAgICAgICAgICAgICAgKSkge1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBtZXRyaWNJZCA9ICd3ZWJydGNfb3V0Ym91bmRfJyArIHN0YXQubWVkaWFUeXBlICsgJ18nICsgc3RhdC5zc3JjO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBtZXRyaWNzID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ5dGVzU2VudDogKHN0YXQuYnl0ZXNTZW50IC0gdGhpcy5zdGF0cy5vdXRib3VuZFtzdGF0Lm1lZGlhVHlwZV0uYnl0ZXNTZW50KSAvIHRoaXMuc3RhdHNJbnRlcnZhbCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYWNrZXRzU2VudDogKHN0YXQucGFja2V0c1NlbnQgLSB0aGlzLnN0YXRzLm91dGJvdW5kW3N0YXQubWVkaWFUeXBlXS5wYWNrZXRzU2VudCkgLyB0aGlzLnN0YXRzSW50ZXJ2YWxcbiAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB1bml0cyA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBieXRlc1NlbnQ6ICdieXRlcycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFja2V0c1NlbnQ6ICdwYWNrZXRzJ1xuICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzdGF0Lm1lZGlhVHlwZSA9PT0gJ3ZpZGVvJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1ldHJpY3NbJ2ZyYW1lc0VuY29kZWQnXSA9IChzdGF0LmZyYW1lc0VuY29kZWQgLSB0aGlzLnN0YXRzLm91dGJvdW5kLnZpZGVvLmZyYW1lc0VuY29kZWQpIC8gdGhpcy5zdGF0c0ludGVydmFsO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVuaXRzWydmcmFtZXNFbmNvZGVkJ10gPSAnZnJhbWVzJztcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdHMub3V0Ym91bmQudmlkZW8uZnJhbWVzRW5jb2RlZCA9IHN0YXQuZnJhbWVzRW5jb2RlZDtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0cy5vdXRib3VuZFtzdGF0Lm1lZGlhVHlwZV0uYnl0ZXNTZW50ID0gc3RhdC5ieXRlc1NlbnQ7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXRzLm91dGJvdW5kW3N0YXQubWVkaWFUeXBlXS5wYWNrZXRzU2VudCA9IHN0YXQucGFja2V0c1NlbnQ7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGpzb24gPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJ0B0aW1lc3RhbXAnOiBuZXcgRGF0ZShzdGF0LnRpbWVzdGFtcCkudG9JU09TdHJpbmcoKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAnZXhlYyc6IGluc3RydW1lbnRhdGlvbi5leGVjLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICdjb21wb25lbnQnOiBpbnN0cnVtZW50YXRpb24uY29tcG9uZW50LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICdzdHJlYW0nOiAnd2ViUnRjJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAndHlwZSc6IG1ldHJpY0lkLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICdzdHJlYW1fdHlwZSc6ICdjb21wb3NlZF9tZXRyaWNzJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAndW5pdHMnOiB1bml0c1xuICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGpzb25bbWV0cmljSWRdID0gbWV0cmljcztcblxuICAgICAgICAgICAgICAgICAgICAgICAgc2VuZFBvc3QoSlNPTi5zdHJpbmdpZnkoanNvbikpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKChwbGF0Zm9ybS5uYW1lIS5pbmRleE9mKCdDaHJvbWUnKSAhPT0gLTEpIHx8IChwbGF0Zm9ybS5uYW1lIS5pbmRleE9mKCdPcGVyYScpICE9PSAtMSkpIHtcbiAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IGtleSBvZiBPYmplY3Qua2V5cyhzdGF0cykpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3Qgc3RhdCA9IHN0YXRzW2tleV07XG4gICAgICAgICAgICAgICAgICAgIGlmIChzdGF0LnR5cGUgPT09ICdzc3JjJykge1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBsZXQganNvbiA9IHt9O1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoJ2J5dGVzUmVjZWl2ZWQnIGluIHN0YXQgJiYgKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIChzdGF0Lm1lZGlhVHlwZSA9PT0gJ2F1ZGlvJyAmJiAnYXVkaW9PdXRwdXRMZXZlbCcgaW4gc3RhdCkgfHxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAoc3RhdC5tZWRpYVR5cGUgPT09ICd2aWRlbycgJiYgJ3FwU3VtJyBpbiBzdGF0KVxuICAgICAgICAgICAgICAgICAgICAgICAgKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGluYm91bmQtcnRwXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgbWV0cmljSWQgPSAnd2VicnRjX2luYm91bmRfJyArIHN0YXQubWVkaWFUeXBlICsgJ18nICsgc3RhdC5zc3JjO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgbWV0cmljcyA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnl0ZXNSZWNlaXZlZDogKHN0YXQuYnl0ZXNSZWNlaXZlZCAtIHRoaXMuc3RhdHMuaW5ib3VuZFtzdGF0Lm1lZGlhVHlwZV0uYnl0ZXNSZWNlaXZlZCkgLyB0aGlzLnN0YXRzSW50ZXJ2YWwsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGppdHRlcjogc3RhdC5nb29nSml0dGVyQnVmZmVyTXMsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhY2tldHNSZWNlaXZlZDogKHN0YXQucGFja2V0c1JlY2VpdmVkIC0gdGhpcy5zdGF0cy5pbmJvdW5kW3N0YXQubWVkaWFUeXBlXS5wYWNrZXRzUmVjZWl2ZWQpIC8gdGhpcy5zdGF0c0ludGVydmFsLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYWNrZXRzTG9zdDogKHN0YXQucGFja2V0c0xvc3QgLSB0aGlzLnN0YXRzLmluYm91bmRbc3RhdC5tZWRpYVR5cGVdLnBhY2tldHNMb3N0KSAvIHRoaXMuc3RhdHNJbnRlcnZhbFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgdW5pdHMgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ5dGVzUmVjZWl2ZWQ6ICdieXRlcycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGppdHRlcjogJ21zJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFja2V0c1JlY2VpdmVkOiAncGFja2V0cycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhY2tldHNMb3N0OiAncGFja2V0cydcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzdGF0Lm1lZGlhVHlwZSA9PT0gJ3ZpZGVvJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXRyaWNzWydmcmFtZXNEZWNvZGVkJ10gPSAoc3RhdC5mcmFtZXNEZWNvZGVkIC0gdGhpcy5zdGF0cy5pbmJvdW5kLnZpZGVvLmZyYW1lc0RlY29kZWQpIC8gdGhpcy5zdGF0c0ludGVydmFsO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXRyaWNzWyduYWNrQ291bnQnXSA9IChzdGF0Lmdvb2dOYWNrc1NlbnQgLSB0aGlzLnN0YXRzLmluYm91bmQudmlkZW8ubmFja0NvdW50KSAvIHRoaXMuc3RhdHNJbnRlcnZhbDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdW5pdHNbJ2ZyYW1lc0RlY29kZWQnXSA9ICdmcmFtZXMnO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1bml0c1snbmFja0NvdW50J10gPSAncGFja2V0cyc7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0cy5pbmJvdW5kLnZpZGVvLmZyYW1lc0RlY29kZWQgPSBzdGF0LmZyYW1lc0RlY29kZWQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdHMuaW5ib3VuZC52aWRlby5uYWNrQ291bnQgPSBzdGF0Lmdvb2dOYWNrc1NlbnQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0cy5pbmJvdW5kW3N0YXQubWVkaWFUeXBlXS5ieXRlc1JlY2VpdmVkID0gc3RhdC5ieXRlc1JlY2VpdmVkO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdHMuaW5ib3VuZFtzdGF0Lm1lZGlhVHlwZV0ucGFja2V0c1JlY2VpdmVkID0gc3RhdC5wYWNrZXRzUmVjZWl2ZWQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0cy5pbmJvdW5kW3N0YXQubWVkaWFUeXBlXS5wYWNrZXRzTG9zdCA9IHN0YXQucGFja2V0c0xvc3Q7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBqc29uID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnQHRpbWVzdGFtcCc6IG5ldyBEYXRlKHN0YXQudGltZXN0YW1wKS50b0lTT1N0cmluZygpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnZXhlYyc6IGluc3RydW1lbnRhdGlvbi5leGVjLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnY29tcG9uZW50JzogaW5zdHJ1bWVudGF0aW9uLmNvbXBvbmVudCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ3N0cmVhbSc6ICd3ZWJSdGMnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAndHlwZSc6IG1ldHJpY0lkLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnc3RyZWFtX3R5cGUnOiAnY29tcG9zZWRfbWV0cmljcycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICd1bml0cyc6IHVuaXRzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBqc29uW21ldHJpY0lkXSA9IG1ldHJpY3M7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZW5kUG9zdChKU09OLnN0cmluZ2lmeShqc29uKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKCdieXRlc1NlbnQnIGluIHN0YXQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBvdXRib3VuZC1ydHBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBtZXRyaWNJZCA9ICd3ZWJydGNfb3V0Ym91bmRfJyArIHN0YXQubWVkaWFUeXBlICsgJ18nICsgc3RhdC5zc3JjO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgbWV0cmljcyA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnl0ZXNTZW50OiAoc3RhdC5ieXRlc1NlbnQgLSB0aGlzLnN0YXRzLm91dGJvdW5kW3N0YXQubWVkaWFUeXBlXS5ieXRlc1NlbnQpIC8gdGhpcy5zdGF0c0ludGVydmFsLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYWNrZXRzU2VudDogKHN0YXQucGFja2V0c1NlbnQgLSB0aGlzLnN0YXRzLm91dGJvdW5kW3N0YXQubWVkaWFUeXBlXS5wYWNrZXRzU2VudCkgLyB0aGlzLnN0YXRzSW50ZXJ2YWxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHVuaXRzID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBieXRlc1NlbnQ6ICdieXRlcycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhY2tldHNTZW50OiAncGFja2V0cydcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzdGF0Lm1lZGlhVHlwZSA9PT0gJ3ZpZGVvJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXRyaWNzWydmcmFtZXNFbmNvZGVkJ10gPSAoc3RhdC5mcmFtZXNFbmNvZGVkIC0gdGhpcy5zdGF0cy5vdXRib3VuZC52aWRlby5mcmFtZXNFbmNvZGVkKSAvIHRoaXMuc3RhdHNJbnRlcnZhbDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdW5pdHNbJ2ZyYW1lc0VuY29kZWQnXSA9ICdmcmFtZXMnO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdHMub3V0Ym91bmQudmlkZW8uZnJhbWVzRW5jb2RlZCA9IHN0YXQuZnJhbWVzRW5jb2RlZDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXRzLm91dGJvdW5kW3N0YXQubWVkaWFUeXBlXS5ieXRlc1NlbnQgPSBzdGF0LmJ5dGVzU2VudDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXRzLm91dGJvdW5kW3N0YXQubWVkaWFUeXBlXS5wYWNrZXRzU2VudCA9IHN0YXQucGFja2V0c1NlbnQ7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBqc29uID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnQHRpbWVzdGFtcCc6IG5ldyBEYXRlKHN0YXQudGltZXN0YW1wKS50b0lTT1N0cmluZygpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnZXhlYyc6IGluc3RydW1lbnRhdGlvbi5leGVjLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnY29tcG9uZW50JzogaW5zdHJ1bWVudGF0aW9uLmNvbXBvbmVudCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ3N0cmVhbSc6ICd3ZWJSdGMnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAndHlwZSc6IG1ldHJpY0lkLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnc3RyZWFtX3R5cGUnOiAnY29tcG9zZWRfbWV0cmljcycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICd1bml0cyc6IHVuaXRzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBqc29uW21ldHJpY0lkXSA9IG1ldHJpY3M7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZW5kUG9zdChKU09OLnN0cmluZ2lmeShqc29uKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG5cbiAgICAgICAgdGhpcy5nZXRTdGF0c0Fnbm9zdGljKHRoaXMuc3RyZWFtLmdldFJUQ1BlZXJDb25uZWN0aW9uKCksIGYsIChlcnJvcikgPT4geyBjb25zb2xlLmxvZyhlcnJvcik7IH0pO1xuICAgIH1cblxuICAgIHByaXZhdGUgc3RhbmRhcmRpemVSZXBvcnQocmVzcG9uc2UpIHtcbiAgICAgICAgY29uc29sZS5sb2cocmVzcG9uc2UpO1xuICAgICAgICBjb25zdCBzdGFuZGFyZFJlcG9ydCA9IHt9O1xuXG4gICAgICAgIGlmIChwbGF0Zm9ybS5uYW1lIS5pbmRleE9mKCdGaXJlZm94JykgIT09IC0xKSB7XG4gICAgICAgICAgICBPYmplY3Qua2V5cyhyZXNwb25zZSkuZm9yRWFjaChrZXkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKHJlc3BvbnNlW2tleV0pO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICByZXR1cm4gcmVzcG9uc2U7XG4gICAgICAgIH1cblxuICAgICAgICByZXNwb25zZS5yZXN1bHQoKS5mb3JFYWNoKHJlcG9ydCA9PiB7XG4gICAgICAgICAgICBjb25zdCBzdGFuZGFyZFN0YXRzID0ge1xuICAgICAgICAgICAgICAgIGlkOiByZXBvcnQuaWQsXG4gICAgICAgICAgICAgICAgdGltZXN0YW1wOiByZXBvcnQudGltZXN0YW1wLFxuICAgICAgICAgICAgICAgIHR5cGU6IHJlcG9ydC50eXBlXG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgcmVwb3J0Lm5hbWVzKCkuZm9yRWFjaCgobmFtZSkgPT4ge1xuICAgICAgICAgICAgICAgIHN0YW5kYXJkU3RhdHNbbmFtZV0gPSByZXBvcnQuc3RhdChuYW1lKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgc3RhbmRhcmRSZXBvcnRbc3RhbmRhcmRTdGF0cy5pZF0gPSBzdGFuZGFyZFN0YXRzO1xuICAgICAgICB9KTtcblxuICAgICAgICByZXR1cm4gc3RhbmRhcmRSZXBvcnQ7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBnZXRTdGF0c0Fnbm9zdGljKHBjLCBzdWNjZXNzQ2IsIGZhaWx1cmVDYikge1xuICAgICAgICBpZiAocGxhdGZvcm0ubmFtZSEuaW5kZXhPZignRmlyZWZveCcpICE9PSAtMSkge1xuICAgICAgICAgICAgLy8gZ2V0U3RhdHMgdGFrZXMgYXJncyBpbiBkaWZmZXJlbnQgb3JkZXIgaW4gQ2hyb21lIGFuZCBGaXJlZm94XG4gICAgICAgICAgICByZXR1cm4gcGMuZ2V0U3RhdHMobnVsbCkudGhlbihyZXNwb25zZSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3QgcmVwb3J0ID0gdGhpcy5zdGFuZGFyZGl6ZVJlcG9ydChyZXNwb25zZSk7XG4gICAgICAgICAgICAgICAgc3VjY2Vzc0NiKHJlcG9ydCk7XG4gICAgICAgICAgICB9KS5jYXRjaChmYWlsdXJlQ2IpO1xuICAgICAgICB9IGVsc2UgaWYgKChwbGF0Zm9ybS5uYW1lIS5pbmRleE9mKCdDaHJvbWUnKSAhPT0gLTEpIHx8IChwbGF0Zm9ybS5uYW1lIS5pbmRleE9mKCdPcGVyYScpICE9PSAtMSkpIHtcbiAgICAgICAgICAgIC8vIEluIENocm9tZSwgdGhlIGZpcnN0IHR3byBhcmd1bWVudHMgYXJlIHJldmVyc2VkXG4gICAgICAgICAgICByZXR1cm4gcGMuZ2V0U3RhdHMoKHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3QgcmVwb3J0ID0gdGhpcy5zdGFuZGFyZGl6ZVJlcG9ydChyZXNwb25zZSk7XG4gICAgICAgICAgICAgICAgc3VjY2Vzc0NiKHJlcG9ydCk7XG4gICAgICAgICAgICB9LCBudWxsLCBmYWlsdXJlQ2IpO1xuICAgICAgICB9XG4gICAgfVxuXG59Il19
diff --git a/openvidu-mvc-node/public/openvidu-browser-2.4.0.js b/openvidu-mvc-node/public/openvidu-browser-2.4.0.js
new file mode 100644
index 000000000..61298c941
--- /dev/null
+++ b/openvidu-mvc-node/public/openvidu-browser-2.4.0.js
@@ -0,0 +1,7696 @@
+(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 1)
+ er = arguments[1];
+ if (er instanceof Error) {
+ throw er; // Unhandled 'error' event
+ } else {
+ // At least give some kind of context to the user
+ var err = new Error('Unhandled "error" event. (' + er + ')');
+ err.context = er;
+ throw err;
+ }
+ return false;
+ }
+
+ handler = events[type];
+
+ if (!handler)
+ return false;
+
+ var isFn = typeof handler === 'function';
+ len = arguments.length;
+ switch (len) {
+ // fast cases
+ case 1:
+ emitNone(handler, isFn, this);
+ break;
+ case 2:
+ emitOne(handler, isFn, this, arguments[1]);
+ break;
+ case 3:
+ emitTwo(handler, isFn, this, arguments[1], arguments[2]);
+ break;
+ case 4:
+ emitThree(handler, isFn, this, arguments[1], arguments[2], arguments[3]);
+ break;
+ // slower
+ default:
+ args = new Array(len - 1);
+ for (i = 1; i < len; i++)
+ args[i - 1] = arguments[i];
+ emitMany(handler, isFn, this, args);
+ }
+
+ return true;
+};
+
+function _addListener(target, type, listener, prepend) {
+ var m;
+ var events;
+ var existing;
+
+ if (typeof listener !== 'function')
+ throw new TypeError('"listener" argument must be a function');
+
+ events = target._events;
+ if (!events) {
+ events = target._events = objectCreate(null);
+ target._eventsCount = 0;
+ } else {
+ // To avoid recursion in the case that type === "newListener"! Before
+ // adding it to the listeners, first emit "newListener".
+ if (events.newListener) {
+ target.emit('newListener', type,
+ listener.listener ? listener.listener : listener);
+
+ // Re-assign `events` because a newListener handler could have caused the
+ // this._events to be assigned to a new object
+ events = target._events;
+ }
+ existing = events[type];
+ }
+
+ if (!existing) {
+ // Optimize the case of one listener. Don't need the extra array object.
+ existing = events[type] = listener;
+ ++target._eventsCount;
+ } else {
+ if (typeof existing === 'function') {
+ // Adding the second element, need to change to array.
+ existing = events[type] =
+ prepend ? [listener, existing] : [existing, listener];
+ } else {
+ // If we've already got an array, just append.
+ if (prepend) {
+ existing.unshift(listener);
+ } else {
+ existing.push(listener);
+ }
+ }
+
+ // Check for listener leak
+ if (!existing.warned) {
+ m = $getMaxListeners(target);
+ if (m && m > 0 && existing.length > m) {
+ existing.warned = true;
+ var w = new Error('Possible EventEmitter memory leak detected. ' +
+ existing.length + ' "' + String(type) + '" listeners ' +
+ 'added. Use emitter.setMaxListeners() to ' +
+ 'increase limit.');
+ w.name = 'MaxListenersExceededWarning';
+ w.emitter = target;
+ w.type = type;
+ w.count = existing.length;
+ if (typeof console === 'object' && console.warn) {
+ console.warn('%s: %s', w.name, w.message);
+ }
+ }
+ }
+ }
+
+ return target;
+}
+
+EventEmitter.prototype.addListener = function addListener(type, listener) {
+ return _addListener(this, type, listener, false);
+};
+
+EventEmitter.prototype.on = EventEmitter.prototype.addListener;
+
+EventEmitter.prototype.prependListener =
+ function prependListener(type, listener) {
+ return _addListener(this, type, listener, true);
+ };
+
+function onceWrapper() {
+ if (!this.fired) {
+ this.target.removeListener(this.type, this.wrapFn);
+ this.fired = true;
+ switch (arguments.length) {
+ case 0:
+ return this.listener.call(this.target);
+ case 1:
+ return this.listener.call(this.target, arguments[0]);
+ case 2:
+ return this.listener.call(this.target, arguments[0], arguments[1]);
+ case 3:
+ return this.listener.call(this.target, arguments[0], arguments[1],
+ arguments[2]);
+ default:
+ var args = new Array(arguments.length);
+ for (var i = 0; i < args.length; ++i)
+ args[i] = arguments[i];
+ this.listener.apply(this.target, args);
+ }
+ }
+}
+
+function _onceWrap(target, type, listener) {
+ var state = { fired: false, wrapFn: undefined, target: target, type: type, listener: listener };
+ var wrapped = bind.call(onceWrapper, state);
+ wrapped.listener = listener;
+ state.wrapFn = wrapped;
+ return wrapped;
+}
+
+EventEmitter.prototype.once = function once(type, listener) {
+ if (typeof listener !== 'function')
+ throw new TypeError('"listener" argument must be a function');
+ this.on(type, _onceWrap(this, type, listener));
+ return this;
+};
+
+EventEmitter.prototype.prependOnceListener =
+ function prependOnceListener(type, listener) {
+ if (typeof listener !== 'function')
+ throw new TypeError('"listener" argument must be a function');
+ this.prependListener(type, _onceWrap(this, type, listener));
+ return this;
+ };
+
+// Emits a 'removeListener' event if and only if the listener was removed.
+EventEmitter.prototype.removeListener =
+ function removeListener(type, listener) {
+ var list, events, position, i, originalListener;
+
+ if (typeof listener !== 'function')
+ throw new TypeError('"listener" argument must be a function');
+
+ events = this._events;
+ if (!events)
+ return this;
+
+ list = events[type];
+ if (!list)
+ return this;
+
+ if (list === listener || list.listener === listener) {
+ if (--this._eventsCount === 0)
+ this._events = objectCreate(null);
+ else {
+ delete events[type];
+ if (events.removeListener)
+ this.emit('removeListener', type, list.listener || listener);
+ }
+ } else if (typeof list !== 'function') {
+ position = -1;
+
+ for (i = list.length - 1; i >= 0; i--) {
+ if (list[i] === listener || list[i].listener === listener) {
+ originalListener = list[i].listener;
+ position = i;
+ break;
+ }
+ }
+
+ if (position < 0)
+ return this;
+
+ if (position === 0)
+ list.shift();
+ else
+ spliceOne(list, position);
+
+ if (list.length === 1)
+ events[type] = list[0];
+
+ if (events.removeListener)
+ this.emit('removeListener', type, originalListener || listener);
+ }
+
+ return this;
+ };
+
+EventEmitter.prototype.removeAllListeners =
+ function removeAllListeners(type) {
+ var listeners, events, i;
+
+ events = this._events;
+ if (!events)
+ return this;
+
+ // not listening for removeListener, no need to emit
+ if (!events.removeListener) {
+ if (arguments.length === 0) {
+ this._events = objectCreate(null);
+ this._eventsCount = 0;
+ } else if (events[type]) {
+ if (--this._eventsCount === 0)
+ this._events = objectCreate(null);
+ else
+ delete events[type];
+ }
+ return this;
+ }
+
+ // emit removeListener for all listeners on all events
+ if (arguments.length === 0) {
+ var keys = objectKeys(events);
+ var key;
+ for (i = 0; i < keys.length; ++i) {
+ key = keys[i];
+ if (key === 'removeListener') continue;
+ this.removeAllListeners(key);
+ }
+ this.removeAllListeners('removeListener');
+ this._events = objectCreate(null);
+ this._eventsCount = 0;
+ return this;
+ }
+
+ listeners = events[type];
+
+ if (typeof listeners === 'function') {
+ this.removeListener(type, listeners);
+ } else if (listeners) {
+ // LIFO order
+ for (i = listeners.length - 1; i >= 0; i--) {
+ this.removeListener(type, listeners[i]);
+ }
+ }
+
+ return this;
+ };
+
+function _listeners(target, type, unwrap) {
+ var events = target._events;
+
+ if (!events)
+ return [];
+
+ var evlistener = events[type];
+ if (!evlistener)
+ return [];
+
+ if (typeof evlistener === 'function')
+ return unwrap ? [evlistener.listener || evlistener] : [evlistener];
+
+ return unwrap ? unwrapListeners(evlistener) : arrayClone(evlistener, evlistener.length);
+}
+
+EventEmitter.prototype.listeners = function listeners(type) {
+ return _listeners(this, type, true);
+};
+
+EventEmitter.prototype.rawListeners = function rawListeners(type) {
+ return _listeners(this, type, false);
+};
+
+EventEmitter.listenerCount = function(emitter, type) {
+ if (typeof emitter.listenerCount === 'function') {
+ return emitter.listenerCount(type);
+ } else {
+ return listenerCount.call(emitter, type);
+ }
+};
+
+EventEmitter.prototype.listenerCount = listenerCount;
+function listenerCount(type) {
+ var events = this._events;
+
+ if (events) {
+ var evlistener = events[type];
+
+ if (typeof evlistener === 'function') {
+ return 1;
+ } else if (evlistener) {
+ return evlistener.length;
+ }
+ }
+
+ return 0;
+}
+
+EventEmitter.prototype.eventNames = function eventNames() {
+ return this._eventsCount > 0 ? Reflect.ownKeys(this._events) : [];
+};
+
+// About 1.5x faster than the two-arg version of Array#splice().
+function spliceOne(list, index) {
+ for (var i = index, k = i + 1, n = list.length; k < n; i += 1, k += 1)
+ list[i] = list[k];
+ list.pop();
+}
+
+function arrayClone(arr, n) {
+ var copy = new Array(n);
+ for (var i = 0; i < n; ++i)
+ copy[i] = arr[i];
+ return copy;
+}
+
+function unwrapListeners(arr) {
+ var ret = new Array(arr.length);
+ for (var i = 0; i < ret.length; ++i) {
+ ret[i] = arr[i].listener || arr[i];
+ }
+ return ret;
+}
+
+function objectCreatePolyfill(proto) {
+ var F = function() {};
+ F.prototype = proto;
+ return new F;
+}
+function objectKeysPolyfill(obj) {
+ var keys = [];
+ for (var k in obj) if (Object.prototype.hasOwnProperty.call(obj, k)) {
+ keys.push(k);
+ }
+ return k;
+}
+function functionBindPolyfill(context) {
+ var fn = this;
+ return function () {
+ return fn.apply(context, arguments);
+ };
+}
+
+},{}],2:[function(require,module,exports){
+/* jshint node: true */
+'use strict';
+
+var normalice = require('normalice');
+
+/**
+ # freeice
+
+ The `freeice` module is a simple way of getting random STUN or TURN server
+ for your WebRTC application. The list of servers (just STUN at this stage)
+ were sourced from this [gist](https://gist.github.com/zziuni/3741933).
+
+ ## Example Use
+
+ The following demonstrates how you can use `freeice` with
+ [rtc-quickconnect](https://github.com/rtc-io/rtc-quickconnect):
+
+ <<< examples/quickconnect.js
+
+ As the `freeice` module generates ice servers in a list compliant with the
+ WebRTC spec you will be able to use it with raw `RTCPeerConnection`
+ constructors and other WebRTC libraries.
+
+ ## Hey, don't use my STUN/TURN server!
+
+ If for some reason your free STUN or TURN server ends up in the
+ list of servers ([stun](https://github.com/DamonOehlman/freeice/blob/master/stun.json) or
+ [turn](https://github.com/DamonOehlman/freeice/blob/master/turn.json))
+ that is used in this module, you can feel
+ free to open an issue on this repository and those servers will be removed
+ within 24 hours (or sooner). This is the quickest and probably the most
+ polite way to have something removed (and provides us some visibility
+ if someone opens a pull request requesting that a server is added).
+
+ ## Please add my server!
+
+ If you have a server that you wish to add to the list, that's awesome! I'm
+ sure I speak on behalf of a whole pile of WebRTC developers who say thanks.
+ To get it into the list, feel free to either open a pull request or if you
+ find that process a bit daunting then just create an issue requesting
+ the addition of the server (make sure you provide all the details, and if
+ you have a Terms of Service then including that in the PR/issue would be
+ awesome).
+
+ ## I know of a free server, can I add it?
+
+ Sure, if you do your homework and make sure it is ok to use (I'm currently
+ in the process of reviewing the terms of those STUN servers included from
+ the original list). If it's ok to go, then please see the previous entry
+ for how to add it.
+
+ ## Current List of Servers
+
+ * current as at the time of last `README.md` file generation
+
+ ### STUN
+
+ <<< stun.json
+
+ ### TURN
+
+ <<< turn.json
+
+**/
+
+var freeice = module.exports = function(opts) {
+ // if a list of servers has been provided, then use it instead of defaults
+ var servers = {
+ stun: (opts || {}).stun || require('./stun.json'),
+ turn: (opts || {}).turn || require('./turn.json')
+ };
+
+ var stunCount = (opts || {}).stunCount || 2;
+ var turnCount = (opts || {}).turnCount || 0;
+ var selected;
+
+ function getServers(type, count) {
+ var out = [];
+ var input = [].concat(servers[type]);
+ var idx;
+
+ while (input.length && out.length < count) {
+ idx = (Math.random() * input.length) | 0;
+ out = out.concat(input.splice(idx, 1));
+ }
+
+ return out.map(function(url) {
+ //If it's a not a string, don't try to "normalice" it otherwise using type:url will screw it up
+ if ((typeof url !== 'string') && (! (url instanceof String))) {
+ return url;
+ } else {
+ return normalice(type + ':' + url);
+ }
+ });
+ }
+
+ // add stun servers
+ selected = [].concat(getServers('stun', stunCount));
+
+ if (turnCount) {
+ selected = selected.concat(getServers('turn', turnCount));
+ }
+
+ return selected;
+};
+
+},{"./stun.json":3,"./turn.json":4,"normalice":7}],3:[function(require,module,exports){
+module.exports=[
+ "stun.l.google.com:19302",
+ "stun1.l.google.com:19302",
+ "stun2.l.google.com:19302",
+ "stun3.l.google.com:19302",
+ "stun4.l.google.com:19302",
+ "stun.ekiga.net",
+ "stun.ideasip.com",
+ "stun.schlund.de",
+ "stun.stunprotocol.org:3478",
+ "stun.voiparound.com",
+ "stun.voipbuster.com",
+ "stun.voipstunt.com",
+ "stun.voxgratia.org",
+ "stun.services.mozilla.com"
+]
+
+},{}],4:[function(require,module,exports){
+module.exports=[]
+
+},{}],5:[function(require,module,exports){
+var WildEmitter = require('wildemitter');
+
+function getMaxVolume (analyser, fftBins) {
+ var maxVolume = -Infinity;
+ analyser.getFloatFrequencyData(fftBins);
+
+ for(var i=4, ii=fftBins.length; i < ii; i++) {
+ if (fftBins[i] > maxVolume && fftBins[i] < 0) {
+ maxVolume = fftBins[i];
+ }
+ };
+
+ return maxVolume;
+}
+
+
+var audioContextType;
+if (typeof window !== 'undefined') {
+ audioContextType = window.AudioContext || window.webkitAudioContext;
+}
+// use a single audio context due to hardware limits
+var audioContext = null;
+module.exports = function(stream, options) {
+ var harker = new WildEmitter();
+
+
+ // make it not break in non-supported browsers
+ if (!audioContextType) return harker;
+
+ //Config
+ var options = options || {},
+ smoothing = (options.smoothing || 0.1),
+ interval = (options.interval || 50),
+ threshold = options.threshold,
+ play = options.play,
+ history = options.history || 10,
+ running = true;
+
+ //Setup Audio Context
+ if (!audioContext) {
+ audioContext = new audioContextType();
+ }
+ var sourceNode, fftBins, analyser;
+
+ analyser = audioContext.createAnalyser();
+ analyser.fftSize = 512;
+ analyser.smoothingTimeConstant = smoothing;
+ fftBins = new Float32Array(analyser.frequencyBinCount);
+
+ if (stream.jquery) stream = stream[0];
+ if (stream instanceof HTMLAudioElement || stream instanceof HTMLVideoElement) {
+ //Audio Tag
+ sourceNode = audioContext.createMediaElementSource(stream);
+ if (typeof play === 'undefined') play = true;
+ threshold = threshold || -50;
+ } else {
+ //WebRTC Stream
+ sourceNode = audioContext.createMediaStreamSource(stream);
+ threshold = threshold || -50;
+ }
+
+ sourceNode.connect(analyser);
+ if (play) analyser.connect(audioContext.destination);
+
+ harker.speaking = false;
+
+ harker.suspend = function() {
+ audioContext.suspend();
+ }
+ harker.resume = function() {
+ audioContext.resume();
+ }
+ Object.defineProperty(harker, 'state', { get: function() {
+ return audioContext.state;
+ }});
+ audioContext.onstatechange = function() {
+ harker.emit('state_change', audioContext.state);
+ }
+
+ harker.setThreshold = function(t) {
+ threshold = t;
+ };
+
+ harker.setInterval = function(i) {
+ interval = i;
+ };
+
+ harker.stop = function() {
+ running = false;
+ harker.emit('volume_change', -100, threshold);
+ if (harker.speaking) {
+ harker.speaking = false;
+ harker.emit('stopped_speaking');
+ }
+ analyser.disconnect();
+ sourceNode.disconnect();
+ };
+ harker.speakingHistory = [];
+ for (var i = 0; i < history; i++) {
+ harker.speakingHistory.push(0);
+ }
+
+ // Poll the analyser node to determine if speaking
+ // and emit events if changed
+ var looper = function() {
+ setTimeout(function() {
+
+ //check if stop has been called
+ if(!running) {
+ return;
+ }
+
+ var currentVolume = getMaxVolume(analyser, fftBins);
+
+ harker.emit('volume_change', currentVolume, threshold);
+
+ var history = 0;
+ if (currentVolume > threshold && !harker.speaking) {
+ // trigger quickly, short history
+ for (var i = harker.speakingHistory.length - 3; i < harker.speakingHistory.length; i++) {
+ history += harker.speakingHistory[i];
+ }
+ if (history >= 2) {
+ harker.speaking = true;
+ harker.emit('speaking');
+ }
+ } else if (currentVolume < threshold && harker.speaking) {
+ for (var i = 0; i < harker.speakingHistory.length; i++) {
+ history += harker.speakingHistory[i];
+ }
+ if (history == 0) {
+ harker.speaking = false;
+ harker.emit('stopped_speaking');
+ }
+ }
+ harker.speakingHistory.shift();
+ harker.speakingHistory.push(0 + (currentVolume > threshold));
+
+ looper();
+ }, interval);
+ };
+ looper();
+
+
+ return harker;
+}
+
+},{"wildemitter":14}],6:[function(require,module,exports){
+if (typeof Object.create === 'function') {
+ // implementation from standard node.js 'util' module
+ module.exports = function inherits(ctor, superCtor) {
+ ctor.super_ = superCtor
+ ctor.prototype = Object.create(superCtor.prototype, {
+ constructor: {
+ value: ctor,
+ enumerable: false,
+ writable: true,
+ configurable: true
+ }
+ });
+ };
+} else {
+ // old school shim for old browsers
+ module.exports = function inherits(ctor, superCtor) {
+ ctor.super_ = superCtor
+ var TempCtor = function () {}
+ TempCtor.prototype = superCtor.prototype
+ ctor.prototype = new TempCtor()
+ ctor.prototype.constructor = ctor
+ }
+}
+
+},{}],7:[function(require,module,exports){
+/**
+ # normalice
+
+ Normalize an ice server configuration object (or plain old string) into a format
+ that is usable in all browsers supporting WebRTC. Primarily this module is designed
+ to help with the transition of the `url` attribute of the configuration object to
+ the `urls` attribute.
+
+ ## Example Usage
+
+ <<< examples/simple.js
+
+**/
+
+var protocols = [
+ 'stun:',
+ 'turn:'
+];
+
+module.exports = function(input) {
+ var url = (input || {}).url || input;
+ var protocol;
+ var parts;
+ var output = {};
+
+ // if we don't have a string url, then allow the input to passthrough
+ if (typeof url != 'string' && (! (url instanceof String))) {
+ return input;
+ }
+
+ // trim the url string, and convert to an array
+ url = url.trim();
+
+ // if the protocol is not known, then passthrough
+ protocol = protocols[protocols.indexOf(url.slice(0, 5))];
+ if (! protocol) {
+ return input;
+ }
+
+ // now let's attack the remaining url parts
+ url = url.slice(5);
+ parts = url.split('@');
+
+ output.username = input.username;
+ output.credential = input.credential;
+ // if we have an authentication part, then set the credentials
+ if (parts.length > 1) {
+ url = parts[1];
+ parts = parts[0].split(':');
+
+ // add the output credential and username
+ output.username = parts[0];
+ output.credential = (input || {}).credential || parts[1] || '';
+ }
+
+ output.url = protocol + url;
+ output.urls = [ output.url ];
+
+ return output;
+};
+
+},{}],8:[function(require,module,exports){
+(function (global){
+/*!
+ * Platform.js
+ * Copyright 2014-2018 Benjamin Tan
+ * Copyright 2011-2013 John-David Dalton
+ * Available under MIT license
+ */
+;(function() {
+ 'use strict';
+
+ /** Used to determine if values are of the language type `Object`. */
+ var objectTypes = {
+ 'function': true,
+ 'object': true
+ };
+
+ /** Used as a reference to the global object. */
+ var root = (objectTypes[typeof window] && window) || this;
+
+ /** Backup possible global object. */
+ var oldRoot = root;
+
+ /** Detect free variable `exports`. */
+ var freeExports = objectTypes[typeof exports] && exports;
+
+ /** Detect free variable `module`. */
+ var freeModule = objectTypes[typeof module] && module && !module.nodeType && module;
+
+ /** Detect free variable `global` from Node.js or Browserified code and use it as `root`. */
+ var freeGlobal = freeExports && freeModule && typeof global == 'object' && global;
+ if (freeGlobal && (freeGlobal.global === freeGlobal || freeGlobal.window === freeGlobal || freeGlobal.self === freeGlobal)) {
+ root = freeGlobal;
+ }
+
+ /**
+ * Used as the maximum length of an array-like object.
+ * See the [ES6 spec](http://people.mozilla.org/~jorendorff/es6-draft.html#sec-tolength)
+ * for more details.
+ */
+ var maxSafeInteger = Math.pow(2, 53) - 1;
+
+ /** Regular expression to detect Opera. */
+ var reOpera = /\bOpera/;
+
+ /** Possible global object. */
+ var thisBinding = this;
+
+ /** Used for native method references. */
+ var objectProto = Object.prototype;
+
+ /** Used to check for own properties of an object. */
+ var hasOwnProperty = objectProto.hasOwnProperty;
+
+ /** Used to resolve the internal `[[Class]]` of values. */
+ var toString = objectProto.toString;
+
+ /*--------------------------------------------------------------------------*/
+
+ /**
+ * Capitalizes a string value.
+ *
+ * @private
+ * @param {string} string The string to capitalize.
+ * @returns {string} The capitalized string.
+ */
+ function capitalize(string) {
+ string = String(string);
+ return string.charAt(0).toUpperCase() + string.slice(1);
+ }
+
+ /**
+ * A utility function to clean up the OS name.
+ *
+ * @private
+ * @param {string} os The OS name to clean up.
+ * @param {string} [pattern] A `RegExp` pattern matching the OS name.
+ * @param {string} [label] A label for the OS.
+ */
+ function cleanupOS(os, pattern, label) {
+ // Platform tokens are defined at:
+ // http://msdn.microsoft.com/en-us/library/ms537503(VS.85).aspx
+ // http://web.archive.org/web/20081122053950/http://msdn.microsoft.com/en-us/library/ms537503(VS.85).aspx
+ var data = {
+ '10.0': '10',
+ '6.4': '10 Technical Preview',
+ '6.3': '8.1',
+ '6.2': '8',
+ '6.1': 'Server 2008 R2 / 7',
+ '6.0': 'Server 2008 / Vista',
+ '5.2': 'Server 2003 / XP 64-bit',
+ '5.1': 'XP',
+ '5.01': '2000 SP1',
+ '5.0': '2000',
+ '4.0': 'NT',
+ '4.90': 'ME'
+ };
+ // Detect Windows version from platform tokens.
+ if (pattern && label && /^Win/i.test(os) && !/^Windows Phone /i.test(os) &&
+ (data = data[/[\d.]+$/.exec(os)])) {
+ os = 'Windows ' + data;
+ }
+ // Correct character case and cleanup string.
+ os = String(os);
+
+ if (pattern && label) {
+ os = os.replace(RegExp(pattern, 'i'), label);
+ }
+
+ os = format(
+ os.replace(/ ce$/i, ' CE')
+ .replace(/\bhpw/i, 'web')
+ .replace(/\bMacintosh\b/, 'Mac OS')
+ .replace(/_PowerPC\b/i, ' OS')
+ .replace(/\b(OS X) [^ \d]+/i, '$1')
+ .replace(/\bMac (OS X)\b/, '$1')
+ .replace(/\/(\d)/, ' $1')
+ .replace(/_/g, '.')
+ .replace(/(?: BePC|[ .]*fc[ \d.]+)$/i, '')
+ .replace(/\bx86\.64\b/gi, 'x86_64')
+ .replace(/\b(Windows Phone) OS\b/, '$1')
+ .replace(/\b(Chrome OS \w+) [\d.]+\b/, '$1')
+ .split(' on ')[0]
+ );
+
+ return os;
+ }
+
+ /**
+ * An iteration utility for arrays and objects.
+ *
+ * @private
+ * @param {Array|Object} object The object to iterate over.
+ * @param {Function} callback The function called per iteration.
+ */
+ function each(object, callback) {
+ var index = -1,
+ length = object ? object.length : 0;
+
+ if (typeof length == 'number' && length > -1 && length <= maxSafeInteger) {
+ while (++index < length) {
+ callback(object[index], index, object);
+ }
+ } else {
+ forOwn(object, callback);
+ }
+ }
+
+ /**
+ * Trim and conditionally capitalize string values.
+ *
+ * @private
+ * @param {string} string The string to format.
+ * @returns {string} The formatted string.
+ */
+ function format(string) {
+ string = trim(string);
+ return /^(?:webOS|i(?:OS|P))/.test(string)
+ ? string
+ : capitalize(string);
+ }
+
+ /**
+ * Iterates over an object's own properties, executing the `callback` for each.
+ *
+ * @private
+ * @param {Object} object The object to iterate over.
+ * @param {Function} callback The function executed per own property.
+ */
+ function forOwn(object, callback) {
+ for (var key in object) {
+ if (hasOwnProperty.call(object, key)) {
+ callback(object[key], key, object);
+ }
+ }
+ }
+
+ /**
+ * Gets the internal `[[Class]]` of a value.
+ *
+ * @private
+ * @param {*} value The value.
+ * @returns {string} The `[[Class]]`.
+ */
+ function getClassOf(value) {
+ return value == null
+ ? capitalize(value)
+ : toString.call(value).slice(8, -1);
+ }
+
+ /**
+ * Host objects can return type values that are different from their actual
+ * data type. The objects we are concerned with usually return non-primitive
+ * types of "object", "function", or "unknown".
+ *
+ * @private
+ * @param {*} object The owner of the property.
+ * @param {string} property The property to check.
+ * @returns {boolean} Returns `true` if the property value is a non-primitive, else `false`.
+ */
+ function isHostType(object, property) {
+ var type = object != null ? typeof object[property] : 'number';
+ return !/^(?:boolean|number|string|undefined)$/.test(type) &&
+ (type == 'object' ? !!object[property] : true);
+ }
+
+ /**
+ * Prepares a string for use in a `RegExp` by making hyphens and spaces optional.
+ *
+ * @private
+ * @param {string} string The string to qualify.
+ * @returns {string} The qualified string.
+ */
+ function qualify(string) {
+ return String(string).replace(/([ -])(?!$)/g, '$1?');
+ }
+
+ /**
+ * A bare-bones `Array#reduce` like utility function.
+ *
+ * @private
+ * @param {Array} array The array to iterate over.
+ * @param {Function} callback The function called per iteration.
+ * @returns {*} The accumulated result.
+ */
+ function reduce(array, callback) {
+ var accumulator = null;
+ each(array, function(value, index) {
+ accumulator = callback(accumulator, value, index, array);
+ });
+ return accumulator;
+ }
+
+ /**
+ * Removes leading and trailing whitespace from a string.
+ *
+ * @private
+ * @param {string} string The string to trim.
+ * @returns {string} The trimmed string.
+ */
+ function trim(string) {
+ return String(string).replace(/^ +| +$/g, '');
+ }
+
+ /*--------------------------------------------------------------------------*/
+
+ /**
+ * Creates a new platform object.
+ *
+ * @memberOf platform
+ * @param {Object|string} [ua=navigator.userAgent] The user agent string or
+ * context object.
+ * @returns {Object} A platform object.
+ */
+ function parse(ua) {
+
+ /** The environment context object. */
+ var context = root;
+
+ /** Used to flag when a custom context is provided. */
+ var isCustomContext = ua && typeof ua == 'object' && getClassOf(ua) != 'String';
+
+ // Juggle arguments.
+ if (isCustomContext) {
+ context = ua;
+ ua = null;
+ }
+
+ /** Browser navigator object. */
+ var nav = context.navigator || {};
+
+ /** Browser user agent string. */
+ var userAgent = nav.userAgent || '';
+
+ ua || (ua = userAgent);
+
+ /** Used to flag when `thisBinding` is the [ModuleScope]. */
+ var isModuleScope = isCustomContext || thisBinding == oldRoot;
+
+ /** Used to detect if browser is like Chrome. */
+ var likeChrome = isCustomContext
+ ? !!nav.likeChrome
+ : /\bChrome\b/.test(ua) && !/internal|\n/i.test(toString.toString());
+
+ /** Internal `[[Class]]` value shortcuts. */
+ var objectClass = 'Object',
+ airRuntimeClass = isCustomContext ? objectClass : 'ScriptBridgingProxyObject',
+ enviroClass = isCustomContext ? objectClass : 'Environment',
+ javaClass = (isCustomContext && context.java) ? 'JavaPackage' : getClassOf(context.java),
+ phantomClass = isCustomContext ? objectClass : 'RuntimeObject';
+
+ /** Detect Java environments. */
+ var java = /\bJava/.test(javaClass) && context.java;
+
+ /** Detect Rhino. */
+ var rhino = java && getClassOf(context.environment) == enviroClass;
+
+ /** A character to represent alpha. */
+ var alpha = java ? 'a' : '\u03b1';
+
+ /** A character to represent beta. */
+ var beta = java ? 'b' : '\u03b2';
+
+ /** Browser document object. */
+ var doc = context.document || {};
+
+ /**
+ * Detect Opera browser (Presto-based).
+ * http://www.howtocreate.co.uk/operaStuff/operaObject.html
+ * http://dev.opera.com/articles/view/opera-mini-web-content-authoring-guidelines/#operamini
+ */
+ var opera = context.operamini || context.opera;
+
+ /** Opera `[[Class]]`. */
+ var operaClass = reOpera.test(operaClass = (isCustomContext && opera) ? opera['[[Class]]'] : getClassOf(opera))
+ ? operaClass
+ : (opera = null);
+
+ /*------------------------------------------------------------------------*/
+
+ /** Temporary variable used over the script's lifetime. */
+ var data;
+
+ /** The CPU architecture. */
+ var arch = ua;
+
+ /** Platform description array. */
+ var description = [];
+
+ /** Platform alpha/beta indicator. */
+ var prerelease = null;
+
+ /** A flag to indicate that environment features should be used to resolve the platform. */
+ var useFeatures = ua == userAgent;
+
+ /** The browser/environment version. */
+ var version = useFeatures && opera && typeof opera.version == 'function' && opera.version();
+
+ /** A flag to indicate if the OS ends with "/ Version" */
+ var isSpecialCasedOS;
+
+ /* Detectable layout engines (order is important). */
+ var layout = getLayout([
+ { 'label': 'EdgeHTML', 'pattern': 'Edge' },
+ 'Trident',
+ { 'label': 'WebKit', 'pattern': 'AppleWebKit' },
+ 'iCab',
+ 'Presto',
+ 'NetFront',
+ 'Tasman',
+ 'KHTML',
+ 'Gecko'
+ ]);
+
+ /* Detectable browser names (order is important). */
+ var name = getName([
+ 'Adobe AIR',
+ 'Arora',
+ 'Avant Browser',
+ 'Breach',
+ 'Camino',
+ 'Electron',
+ 'Epiphany',
+ 'Fennec',
+ 'Flock',
+ 'Galeon',
+ 'GreenBrowser',
+ 'iCab',
+ 'Iceweasel',
+ 'K-Meleon',
+ 'Konqueror',
+ 'Lunascape',
+ 'Maxthon',
+ { 'label': 'Microsoft Edge', 'pattern': 'Edge' },
+ 'Midori',
+ 'Nook Browser',
+ 'PaleMoon',
+ 'PhantomJS',
+ 'Raven',
+ 'Rekonq',
+ 'RockMelt',
+ { 'label': 'Samsung Internet', 'pattern': 'SamsungBrowser' },
+ 'SeaMonkey',
+ { 'label': 'Silk', 'pattern': '(?:Cloud9|Silk-Accelerated)' },
+ 'Sleipnir',
+ 'SlimBrowser',
+ { 'label': 'SRWare Iron', 'pattern': 'Iron' },
+ 'Sunrise',
+ 'Swiftfox',
+ 'Waterfox',
+ 'WebPositive',
+ 'Opera Mini',
+ { 'label': 'Opera Mini', 'pattern': 'OPiOS' },
+ 'Opera',
+ { 'label': 'Opera', 'pattern': 'OPR' },
+ 'Chrome',
+ { 'label': 'Chrome Mobile', 'pattern': '(?:CriOS|CrMo)' },
+ { 'label': 'Firefox', 'pattern': '(?:Firefox|Minefield)' },
+ { 'label': 'Firefox for iOS', 'pattern': 'FxiOS' },
+ { 'label': 'IE', 'pattern': 'IEMobile' },
+ { 'label': 'IE', 'pattern': 'MSIE' },
+ 'Safari'
+ ]);
+
+ /* Detectable products (order is important). */
+ var product = getProduct([
+ { 'label': 'BlackBerry', 'pattern': 'BB10' },
+ 'BlackBerry',
+ { 'label': 'Galaxy S', 'pattern': 'GT-I9000' },
+ { 'label': 'Galaxy S2', 'pattern': 'GT-I9100' },
+ { 'label': 'Galaxy S3', 'pattern': 'GT-I9300' },
+ { 'label': 'Galaxy S4', 'pattern': 'GT-I9500' },
+ { 'label': 'Galaxy S5', 'pattern': 'SM-G900' },
+ { 'label': 'Galaxy S6', 'pattern': 'SM-G920' },
+ { 'label': 'Galaxy S6 Edge', 'pattern': 'SM-G925' },
+ { 'label': 'Galaxy S7', 'pattern': 'SM-G930' },
+ { 'label': 'Galaxy S7 Edge', 'pattern': 'SM-G935' },
+ 'Google TV',
+ 'Lumia',
+ 'iPad',
+ 'iPod',
+ 'iPhone',
+ 'Kindle',
+ { 'label': 'Kindle Fire', 'pattern': '(?:Cloud9|Silk-Accelerated)' },
+ 'Nexus',
+ 'Nook',
+ 'PlayBook',
+ 'PlayStation Vita',
+ 'PlayStation',
+ 'TouchPad',
+ 'Transformer',
+ { 'label': 'Wii U', 'pattern': 'WiiU' },
+ 'Wii',
+ 'Xbox One',
+ { 'label': 'Xbox 360', 'pattern': 'Xbox' },
+ 'Xoom'
+ ]);
+
+ /* Detectable manufacturers. */
+ var manufacturer = getManufacturer({
+ 'Apple': { 'iPad': 1, 'iPhone': 1, 'iPod': 1 },
+ 'Archos': {},
+ 'Amazon': { 'Kindle': 1, 'Kindle Fire': 1 },
+ 'Asus': { 'Transformer': 1 },
+ 'Barnes & Noble': { 'Nook': 1 },
+ 'BlackBerry': { 'PlayBook': 1 },
+ 'Google': { 'Google TV': 1, 'Nexus': 1 },
+ 'HP': { 'TouchPad': 1 },
+ 'HTC': {},
+ 'LG': {},
+ 'Microsoft': { 'Xbox': 1, 'Xbox One': 1 },
+ 'Motorola': { 'Xoom': 1 },
+ 'Nintendo': { 'Wii U': 1, 'Wii': 1 },
+ 'Nokia': { 'Lumia': 1 },
+ 'Samsung': { 'Galaxy S': 1, 'Galaxy S2': 1, 'Galaxy S3': 1, 'Galaxy S4': 1 },
+ 'Sony': { 'PlayStation': 1, 'PlayStation Vita': 1 }
+ });
+
+ /* Detectable operating systems (order is important). */
+ var os = getOS([
+ 'Windows Phone',
+ 'Android',
+ 'CentOS',
+ { 'label': 'Chrome OS', 'pattern': 'CrOS' },
+ 'Debian',
+ 'Fedora',
+ 'FreeBSD',
+ 'Gentoo',
+ 'Haiku',
+ 'Kubuntu',
+ 'Linux Mint',
+ 'OpenBSD',
+ 'Red Hat',
+ 'SuSE',
+ 'Ubuntu',
+ 'Xubuntu',
+ 'Cygwin',
+ 'Symbian OS',
+ 'hpwOS',
+ 'webOS ',
+ 'webOS',
+ 'Tablet OS',
+ 'Tizen',
+ 'Linux',
+ 'Mac OS X',
+ 'Macintosh',
+ 'Mac',
+ 'Windows 98;',
+ 'Windows '
+ ]);
+
+ /*------------------------------------------------------------------------*/
+
+ /**
+ * Picks the layout engine from an array of guesses.
+ *
+ * @private
+ * @param {Array} guesses An array of guesses.
+ * @returns {null|string} The detected layout engine.
+ */
+ function getLayout(guesses) {
+ return reduce(guesses, function(result, guess) {
+ return result || RegExp('\\b' + (
+ guess.pattern || qualify(guess)
+ ) + '\\b', 'i').exec(ua) && (guess.label || guess);
+ });
+ }
+
+ /**
+ * Picks the manufacturer from an array of guesses.
+ *
+ * @private
+ * @param {Array} guesses An object of guesses.
+ * @returns {null|string} The detected manufacturer.
+ */
+ function getManufacturer(guesses) {
+ return reduce(guesses, function(result, value, key) {
+ // Lookup the manufacturer by product or scan the UA for the manufacturer.
+ return result || (
+ value[product] ||
+ value[/^[a-z]+(?: +[a-z]+\b)*/i.exec(product)] ||
+ RegExp('\\b' + qualify(key) + '(?:\\b|\\w*\\d)', 'i').exec(ua)
+ ) && key;
+ });
+ }
+
+ /**
+ * Picks the browser name from an array of guesses.
+ *
+ * @private
+ * @param {Array} guesses An array of guesses.
+ * @returns {null|string} The detected browser name.
+ */
+ function getName(guesses) {
+ return reduce(guesses, function(result, guess) {
+ return result || RegExp('\\b' + (
+ guess.pattern || qualify(guess)
+ ) + '\\b', 'i').exec(ua) && (guess.label || guess);
+ });
+ }
+
+ /**
+ * Picks the OS name from an array of guesses.
+ *
+ * @private
+ * @param {Array} guesses An array of guesses.
+ * @returns {null|string} The detected OS name.
+ */
+ function getOS(guesses) {
+ return reduce(guesses, function(result, guess) {
+ var pattern = guess.pattern || qualify(guess);
+ if (!result && (result =
+ RegExp('\\b' + pattern + '(?:/[\\d.]+|[ \\w.]*)', 'i').exec(ua)
+ )) {
+ result = cleanupOS(result, pattern, guess.label || guess);
+ }
+ return result;
+ });
+ }
+
+ /**
+ * Picks the product name from an array of guesses.
+ *
+ * @private
+ * @param {Array} guesses An array of guesses.
+ * @returns {null|string} The detected product name.
+ */
+ function getProduct(guesses) {
+ return reduce(guesses, function(result, guess) {
+ var pattern = guess.pattern || qualify(guess);
+ if (!result && (result =
+ RegExp('\\b' + pattern + ' *\\d+[.\\w_]*', 'i').exec(ua) ||
+ RegExp('\\b' + pattern + ' *\\w+-[\\w]*', 'i').exec(ua) ||
+ RegExp('\\b' + pattern + '(?:; *(?:[a-z]+[_-])?[a-z]+\\d+|[^ ();-]*)', 'i').exec(ua)
+ )) {
+ // Split by forward slash and append product version if needed.
+ if ((result = String((guess.label && !RegExp(pattern, 'i').test(guess.label)) ? guess.label : result).split('/'))[1] && !/[\d.]+/.test(result[0])) {
+ result[0] += ' ' + result[1];
+ }
+ // Correct character case and cleanup string.
+ guess = guess.label || guess;
+ result = format(result[0]
+ .replace(RegExp(pattern, 'i'), guess)
+ .replace(RegExp('; *(?:' + guess + '[_-])?', 'i'), ' ')
+ .replace(RegExp('(' + guess + ')[-_.]?(\\w)', 'i'), '$1 $2'));
+ }
+ return result;
+ });
+ }
+
+ /**
+ * Resolves the version using an array of UA patterns.
+ *
+ * @private
+ * @param {Array} patterns An array of UA patterns.
+ * @returns {null|string} The detected version.
+ */
+ function getVersion(patterns) {
+ return reduce(patterns, function(result, pattern) {
+ return result || (RegExp(pattern +
+ '(?:-[\\d.]+/|(?: for [\\w-]+)?[ /-])([\\d.]+[^ ();/_-]*)', 'i').exec(ua) || 0)[1] || null;
+ });
+ }
+
+ /**
+ * Returns `platform.description` when the platform object is coerced to a string.
+ *
+ * @name toString
+ * @memberOf platform
+ * @returns {string} Returns `platform.description` if available, else an empty string.
+ */
+ function toStringPlatform() {
+ return this.description || '';
+ }
+
+ /*------------------------------------------------------------------------*/
+
+ // Convert layout to an array so we can add extra details.
+ layout && (layout = [layout]);
+
+ // Detect product names that contain their manufacturer's name.
+ if (manufacturer && !product) {
+ product = getProduct([manufacturer]);
+ }
+ // Clean up Google TV.
+ if ((data = /\bGoogle TV\b/.exec(product))) {
+ product = data[0];
+ }
+ // Detect simulators.
+ if (/\bSimulator\b/i.test(ua)) {
+ product = (product ? product + ' ' : '') + 'Simulator';
+ }
+ // Detect Opera Mini 8+ running in Turbo/Uncompressed mode on iOS.
+ if (name == 'Opera Mini' && /\bOPiOS\b/.test(ua)) {
+ description.push('running in Turbo/Uncompressed mode');
+ }
+ // Detect IE Mobile 11.
+ if (name == 'IE' && /\blike iPhone OS\b/.test(ua)) {
+ data = parse(ua.replace(/like iPhone OS/, ''));
+ manufacturer = data.manufacturer;
+ product = data.product;
+ }
+ // Detect iOS.
+ else if (/^iP/.test(product)) {
+ name || (name = 'Safari');
+ os = 'iOS' + ((data = / OS ([\d_]+)/i.exec(ua))
+ ? ' ' + data[1].replace(/_/g, '.')
+ : '');
+ }
+ // Detect Kubuntu.
+ else if (name == 'Konqueror' && !/buntu/i.test(os)) {
+ os = 'Kubuntu';
+ }
+ // Detect Android browsers.
+ else if ((manufacturer && manufacturer != 'Google' &&
+ ((/Chrome/.test(name) && !/\bMobile Safari\b/i.test(ua)) || /\bVita\b/.test(product))) ||
+ (/\bAndroid\b/.test(os) && /^Chrome/.test(name) && /\bVersion\//i.test(ua))) {
+ name = 'Android Browser';
+ os = /\bAndroid\b/.test(os) ? os : 'Android';
+ }
+ // Detect Silk desktop/accelerated modes.
+ else if (name == 'Silk') {
+ if (!/\bMobi/i.test(ua)) {
+ os = 'Android';
+ description.unshift('desktop mode');
+ }
+ if (/Accelerated *= *true/i.test(ua)) {
+ description.unshift('accelerated');
+ }
+ }
+ // Detect PaleMoon identifying as Firefox.
+ else if (name == 'PaleMoon' && (data = /\bFirefox\/([\d.]+)\b/.exec(ua))) {
+ description.push('identifying as Firefox ' + data[1]);
+ }
+ // Detect Firefox OS and products running Firefox.
+ else if (name == 'Firefox' && (data = /\b(Mobile|Tablet|TV)\b/i.exec(ua))) {
+ os || (os = 'Firefox OS');
+ product || (product = data[1]);
+ }
+ // Detect false positives for Firefox/Safari.
+ else if (!name || (data = !/\bMinefield\b/i.test(ua) && /\b(?:Firefox|Safari)\b/.exec(name))) {
+ // Escape the `/` for Firefox 1.
+ if (name && !product && /[\/,]|^[^(]+?\)/.test(ua.slice(ua.indexOf(data + '/') + 8))) {
+ // Clear name of false positives.
+ name = null;
+ }
+ // Reassign a generic name.
+ if ((data = product || manufacturer || os) &&
+ (product || manufacturer || /\b(?:Android|Symbian OS|Tablet OS|webOS)\b/.test(os))) {
+ name = /[a-z]+(?: Hat)?/i.exec(/\bAndroid\b/.test(os) ? os : data) + ' Browser';
+ }
+ }
+ // Add Chrome version to description for Electron.
+ else if (name == 'Electron' && (data = (/\bChrome\/([\d.]+)\b/.exec(ua) || 0)[1])) {
+ description.push('Chromium ' + data);
+ }
+ // Detect non-Opera (Presto-based) versions (order is important).
+ if (!version) {
+ version = getVersion([
+ '(?:Cloud9|CriOS|CrMo|Edge|FxiOS|IEMobile|Iron|Opera ?Mini|OPiOS|OPR|Raven|SamsungBrowser|Silk(?!/[\\d.]+$))',
+ 'Version',
+ qualify(name),
+ '(?:Firefox|Minefield|NetFront)'
+ ]);
+ }
+ // Detect stubborn layout engines.
+ if ((data =
+ layout == 'iCab' && parseFloat(version) > 3 && 'WebKit' ||
+ /\bOpera\b/.test(name) && (/\bOPR\b/.test(ua) ? 'Blink' : 'Presto') ||
+ /\b(?:Midori|Nook|Safari)\b/i.test(ua) && !/^(?:Trident|EdgeHTML)$/.test(layout) && 'WebKit' ||
+ !layout && /\bMSIE\b/i.test(ua) && (os == 'Mac OS' ? 'Tasman' : 'Trident') ||
+ layout == 'WebKit' && /\bPlayStation\b(?! Vita\b)/i.test(name) && 'NetFront'
+ )) {
+ layout = [data];
+ }
+ // Detect Windows Phone 7 desktop mode.
+ if (name == 'IE' && (data = (/; *(?:XBLWP|ZuneWP)(\d+)/i.exec(ua) || 0)[1])) {
+ name += ' Mobile';
+ os = 'Windows Phone ' + (/\+$/.test(data) ? data : data + '.x');
+ description.unshift('desktop mode');
+ }
+ // Detect Windows Phone 8.x desktop mode.
+ else if (/\bWPDesktop\b/i.test(ua)) {
+ name = 'IE Mobile';
+ os = 'Windows Phone 8.x';
+ description.unshift('desktop mode');
+ version || (version = (/\brv:([\d.]+)/.exec(ua) || 0)[1]);
+ }
+ // Detect IE 11 identifying as other browsers.
+ else if (name != 'IE' && layout == 'Trident' && (data = /\brv:([\d.]+)/.exec(ua))) {
+ if (name) {
+ description.push('identifying as ' + name + (version ? ' ' + version : ''));
+ }
+ name = 'IE';
+ version = data[1];
+ }
+ // Leverage environment features.
+ if (useFeatures) {
+ // Detect server-side environments.
+ // Rhino has a global function while others have a global object.
+ if (isHostType(context, 'global')) {
+ if (java) {
+ data = java.lang.System;
+ arch = data.getProperty('os.arch');
+ os = os || data.getProperty('os.name') + ' ' + data.getProperty('os.version');
+ }
+ if (rhino) {
+ try {
+ version = context.require('ringo/engine').version.join('.');
+ name = 'RingoJS';
+ } catch(e) {
+ if ((data = context.system) && data.global.system == context.system) {
+ name = 'Narwhal';
+ os || (os = data[0].os || null);
+ }
+ }
+ if (!name) {
+ name = 'Rhino';
+ }
+ }
+ else if (
+ typeof context.process == 'object' && !context.process.browser &&
+ (data = context.process)
+ ) {
+ if (typeof data.versions == 'object') {
+ if (typeof data.versions.electron == 'string') {
+ description.push('Node ' + data.versions.node);
+ name = 'Electron';
+ version = data.versions.electron;
+ } else if (typeof data.versions.nw == 'string') {
+ description.push('Chromium ' + version, 'Node ' + data.versions.node);
+ name = 'NW.js';
+ version = data.versions.nw;
+ }
+ }
+ if (!name) {
+ name = 'Node.js';
+ arch = data.arch;
+ os = data.platform;
+ version = /[\d.]+/.exec(data.version);
+ version = version ? version[0] : null;
+ }
+ }
+ }
+ // Detect Adobe AIR.
+ else if (getClassOf((data = context.runtime)) == airRuntimeClass) {
+ name = 'Adobe AIR';
+ os = data.flash.system.Capabilities.os;
+ }
+ // Detect PhantomJS.
+ else if (getClassOf((data = context.phantom)) == phantomClass) {
+ name = 'PhantomJS';
+ version = (data = data.version || null) && (data.major + '.' + data.minor + '.' + data.patch);
+ }
+ // Detect IE compatibility modes.
+ else if (typeof doc.documentMode == 'number' && (data = /\bTrident\/(\d+)/i.exec(ua))) {
+ // We're in compatibility mode when the Trident version + 4 doesn't
+ // equal the document mode.
+ version = [version, doc.documentMode];
+ if ((data = +data[1] + 4) != version[1]) {
+ description.push('IE ' + version[1] + ' mode');
+ layout && (layout[1] = '');
+ version[1] = data;
+ }
+ version = name == 'IE' ? String(version[1].toFixed(1)) : version[0];
+ }
+ // Detect IE 11 masking as other browsers.
+ else if (typeof doc.documentMode == 'number' && /^(?:Chrome|Firefox)\b/.test(name)) {
+ description.push('masking as ' + name + ' ' + version);
+ name = 'IE';
+ version = '11.0';
+ layout = ['Trident'];
+ os = 'Windows';
+ }
+ os = os && format(os);
+ }
+ // Detect prerelease phases.
+ if (version && (data =
+ /(?:[ab]|dp|pre|[ab]\d+pre)(?:\d+\+?)?$/i.exec(version) ||
+ /(?:alpha|beta)(?: ?\d)?/i.exec(ua + ';' + (useFeatures && nav.appMinorVersion)) ||
+ /\bMinefield\b/i.test(ua) && 'a'
+ )) {
+ prerelease = /b/i.test(data) ? 'beta' : 'alpha';
+ version = version.replace(RegExp(data + '\\+?$'), '') +
+ (prerelease == 'beta' ? beta : alpha) + (/\d+\+?/.exec(data) || '');
+ }
+ // Detect Firefox Mobile.
+ if (name == 'Fennec' || name == 'Firefox' && /\b(?:Android|Firefox OS)\b/.test(os)) {
+ name = 'Firefox Mobile';
+ }
+ // Obscure Maxthon's unreliable version.
+ else if (name == 'Maxthon' && version) {
+ version = version.replace(/\.[\d.]+/, '.x');
+ }
+ // Detect Xbox 360 and Xbox One.
+ else if (/\bXbox\b/i.test(product)) {
+ if (product == 'Xbox 360') {
+ os = null;
+ }
+ if (product == 'Xbox 360' && /\bIEMobile\b/.test(ua)) {
+ description.unshift('mobile mode');
+ }
+ }
+ // Add mobile postfix.
+ else if ((/^(?:Chrome|IE|Opera)$/.test(name) || name && !product && !/Browser|Mobi/.test(name)) &&
+ (os == 'Windows CE' || /Mobi/i.test(ua))) {
+ name += ' Mobile';
+ }
+ // Detect IE platform preview.
+ else if (name == 'IE' && useFeatures) {
+ try {
+ if (context.external === null) {
+ description.unshift('platform preview');
+ }
+ } catch(e) {
+ description.unshift('embedded');
+ }
+ }
+ // Detect BlackBerry OS version.
+ // http://docs.blackberry.com/en/developers/deliverables/18169/HTTP_headers_sent_by_BB_Browser_1234911_11.jsp
+ else if ((/\bBlackBerry\b/.test(product) || /\bBB10\b/.test(ua)) && (data =
+ (RegExp(product.replace(/ +/g, ' *') + '/([.\\d]+)', 'i').exec(ua) || 0)[1] ||
+ version
+ )) {
+ data = [data, /BB10/.test(ua)];
+ os = (data[1] ? (product = null, manufacturer = 'BlackBerry') : 'Device Software') + ' ' + data[0];
+ version = null;
+ }
+ // Detect Opera identifying/masking itself as another browser.
+ // http://www.opera.com/support/kb/view/843/
+ else if (this != forOwn && product != 'Wii' && (
+ (useFeatures && opera) ||
+ (/Opera/.test(name) && /\b(?:MSIE|Firefox)\b/i.test(ua)) ||
+ (name == 'Firefox' && /\bOS X (?:\d+\.){2,}/.test(os)) ||
+ (name == 'IE' && (
+ (os && !/^Win/.test(os) && version > 5.5) ||
+ /\bWindows XP\b/.test(os) && version > 8 ||
+ version == 8 && !/\bTrident\b/.test(ua)
+ ))
+ ) && !reOpera.test((data = parse.call(forOwn, ua.replace(reOpera, '') + ';'))) && data.name) {
+ // When "identifying", the UA contains both Opera and the other browser's name.
+ data = 'ing as ' + data.name + ((data = data.version) ? ' ' + data : '');
+ if (reOpera.test(name)) {
+ if (/\bIE\b/.test(data) && os == 'Mac OS') {
+ os = null;
+ }
+ data = 'identify' + data;
+ }
+ // When "masking", the UA contains only the other browser's name.
+ else {
+ data = 'mask' + data;
+ if (operaClass) {
+ name = format(operaClass.replace(/([a-z])([A-Z])/g, '$1 $2'));
+ } else {
+ name = 'Opera';
+ }
+ if (/\bIE\b/.test(data)) {
+ os = null;
+ }
+ if (!useFeatures) {
+ version = null;
+ }
+ }
+ layout = ['Presto'];
+ description.push(data);
+ }
+ // Detect WebKit Nightly and approximate Chrome/Safari versions.
+ if ((data = (/\bAppleWebKit\/([\d.]+\+?)/i.exec(ua) || 0)[1])) {
+ // Correct build number for numeric comparison.
+ // (e.g. "532.5" becomes "532.05")
+ data = [parseFloat(data.replace(/\.(\d)$/, '.0$1')), data];
+ // Nightly builds are postfixed with a "+".
+ if (name == 'Safari' && data[1].slice(-1) == '+') {
+ name = 'WebKit Nightly';
+ prerelease = 'alpha';
+ version = data[1].slice(0, -1);
+ }
+ // Clear incorrect browser versions.
+ else if (version == data[1] ||
+ version == (data[2] = (/\bSafari\/([\d.]+\+?)/i.exec(ua) || 0)[1])) {
+ version = null;
+ }
+ // Use the full Chrome version when available.
+ data[1] = (/\bChrome\/([\d.]+)/i.exec(ua) || 0)[1];
+ // Detect Blink layout engine.
+ if (data[0] == 537.36 && data[2] == 537.36 && parseFloat(data[1]) >= 28 && layout == 'WebKit') {
+ layout = ['Blink'];
+ }
+ // Detect JavaScriptCore.
+ // http://stackoverflow.com/questions/6768474/how-can-i-detect-which-javascript-engine-v8-or-jsc-is-used-at-runtime-in-androi
+ if (!useFeatures || (!likeChrome && !data[1])) {
+ layout && (layout[1] = 'like Safari');
+ data = (data = data[0], data < 400 ? 1 : data < 500 ? 2 : data < 526 ? 3 : data < 533 ? 4 : data < 534 ? '4+' : data < 535 ? 5 : data < 537 ? 6 : data < 538 ? 7 : data < 601 ? 8 : '8');
+ } else {
+ layout && (layout[1] = 'like Chrome');
+ data = data[1] || (data = data[0], data < 530 ? 1 : data < 532 ? 2 : data < 532.05 ? 3 : data < 533 ? 4 : data < 534.03 ? 5 : data < 534.07 ? 6 : data < 534.10 ? 7 : data < 534.13 ? 8 : data < 534.16 ? 9 : data < 534.24 ? 10 : data < 534.30 ? 11 : data < 535.01 ? 12 : data < 535.02 ? '13+' : data < 535.07 ? 15 : data < 535.11 ? 16 : data < 535.19 ? 17 : data < 536.05 ? 18 : data < 536.10 ? 19 : data < 537.01 ? 20 : data < 537.11 ? '21+' : data < 537.13 ? 23 : data < 537.18 ? 24 : data < 537.24 ? 25 : data < 537.36 ? 26 : layout != 'Blink' ? '27' : '28');
+ }
+ // Add the postfix of ".x" or "+" for approximate versions.
+ layout && (layout[1] += ' ' + (data += typeof data == 'number' ? '.x' : /[.+]/.test(data) ? '' : '+'));
+ // Obscure version for some Safari 1-2 releases.
+ if (name == 'Safari' && (!version || parseInt(version) > 45)) {
+ version = data;
+ }
+ }
+ // Detect Opera desktop modes.
+ if (name == 'Opera' && (data = /\bzbov|zvav$/.exec(os))) {
+ name += ' ';
+ description.unshift('desktop mode');
+ if (data == 'zvav') {
+ name += 'Mini';
+ version = null;
+ } else {
+ name += 'Mobile';
+ }
+ os = os.replace(RegExp(' *' + data + '$'), '');
+ }
+ // Detect Chrome desktop mode.
+ else if (name == 'Safari' && /\bChrome\b/.exec(layout && layout[1])) {
+ description.unshift('desktop mode');
+ name = 'Chrome Mobile';
+ version = null;
+
+ if (/\bOS X\b/.test(os)) {
+ manufacturer = 'Apple';
+ os = 'iOS 4.3+';
+ } else {
+ os = null;
+ }
+ }
+ // Strip incorrect OS versions.
+ if (version && version.indexOf((data = /[\d.]+$/.exec(os))) == 0 &&
+ ua.indexOf('/' + data + '-') > -1) {
+ os = trim(os.replace(data, ''));
+ }
+ // Add layout engine.
+ if (layout && !/\b(?:Avant|Nook)\b/.test(name) && (
+ /Browser|Lunascape|Maxthon/.test(name) ||
+ name != 'Safari' && /^iOS/.test(os) && /\bSafari\b/.test(layout[1]) ||
+ /^(?:Adobe|Arora|Breach|Midori|Opera|Phantom|Rekonq|Rock|Samsung Internet|Sleipnir|Web)/.test(name) && layout[1])) {
+ // Don't add layout details to description if they are falsey.
+ (data = layout[layout.length - 1]) && description.push(data);
+ }
+ // Combine contextual information.
+ if (description.length) {
+ description = ['(' + description.join('; ') + ')'];
+ }
+ // Append manufacturer to description.
+ if (manufacturer && product && product.indexOf(manufacturer) < 0) {
+ description.push('on ' + manufacturer);
+ }
+ // Append product to description.
+ if (product) {
+ description.push((/^on /.test(description[description.length - 1]) ? '' : 'on ') + product);
+ }
+ // Parse the OS into an object.
+ if (os) {
+ data = / ([\d.+]+)$/.exec(os);
+ isSpecialCasedOS = data && os.charAt(os.length - data[0].length - 1) == '/';
+ os = {
+ 'architecture': 32,
+ 'family': (data && !isSpecialCasedOS) ? os.replace(data[0], '') : os,
+ 'version': data ? data[1] : null,
+ 'toString': function() {
+ var version = this.version;
+ return this.family + ((version && !isSpecialCasedOS) ? ' ' + version : '') + (this.architecture == 64 ? ' 64-bit' : '');
+ }
+ };
+ }
+ // Add browser/OS architecture.
+ if ((data = /\b(?:AMD|IA|Win|WOW|x86_|x)64\b/i.exec(arch)) && !/\bi686\b/i.test(arch)) {
+ if (os) {
+ os.architecture = 64;
+ os.family = os.family.replace(RegExp(' *' + data), '');
+ }
+ if (
+ name && (/\bWOW64\b/i.test(ua) ||
+ (useFeatures && /\w(?:86|32)$/.test(nav.cpuClass || nav.platform) && !/\bWin64; x64\b/i.test(ua)))
+ ) {
+ description.unshift('32-bit');
+ }
+ }
+ // Chrome 39 and above on OS X is always 64-bit.
+ else if (
+ os && /^OS X/.test(os.family) &&
+ name == 'Chrome' && parseFloat(version) >= 39
+ ) {
+ os.architecture = 64;
+ }
+
+ ua || (ua = null);
+
+ /*------------------------------------------------------------------------*/
+
+ /**
+ * The platform object.
+ *
+ * @name platform
+ * @type Object
+ */
+ var platform = {};
+
+ /**
+ * The platform description.
+ *
+ * @memberOf platform
+ * @type string|null
+ */
+ platform.description = ua;
+
+ /**
+ * The name of the browser's layout engine.
+ *
+ * The list of common layout engines include:
+ * "Blink", "EdgeHTML", "Gecko", "Trident" and "WebKit"
+ *
+ * @memberOf platform
+ * @type string|null
+ */
+ platform.layout = layout && layout[0];
+
+ /**
+ * The name of the product's manufacturer.
+ *
+ * The list of manufacturers include:
+ * "Apple", "Archos", "Amazon", "Asus", "Barnes & Noble", "BlackBerry",
+ * "Google", "HP", "HTC", "LG", "Microsoft", "Motorola", "Nintendo",
+ * "Nokia", "Samsung" and "Sony"
+ *
+ * @memberOf platform
+ * @type string|null
+ */
+ platform.manufacturer = manufacturer;
+
+ /**
+ * The name of the browser/environment.
+ *
+ * The list of common browser names include:
+ * "Chrome", "Electron", "Firefox", "Firefox for iOS", "IE",
+ * "Microsoft Edge", "PhantomJS", "Safari", "SeaMonkey", "Silk",
+ * "Opera Mini" and "Opera"
+ *
+ * Mobile versions of some browsers have "Mobile" appended to their name:
+ * eg. "Chrome Mobile", "Firefox Mobile", "IE Mobile" and "Opera Mobile"
+ *
+ * @memberOf platform
+ * @type string|null
+ */
+ platform.name = name;
+
+ /**
+ * The alpha/beta release indicator.
+ *
+ * @memberOf platform
+ * @type string|null
+ */
+ platform.prerelease = prerelease;
+
+ /**
+ * The name of the product hosting the browser.
+ *
+ * The list of common products include:
+ *
+ * "BlackBerry", "Galaxy S4", "Lumia", "iPad", "iPod", "iPhone", "Kindle",
+ * "Kindle Fire", "Nexus", "Nook", "PlayBook", "TouchPad" and "Transformer"
+ *
+ * @memberOf platform
+ * @type string|null
+ */
+ platform.product = product;
+
+ /**
+ * The browser's user agent string.
+ *
+ * @memberOf platform
+ * @type string|null
+ */
+ platform.ua = ua;
+
+ /**
+ * The browser/environment version.
+ *
+ * @memberOf platform
+ * @type string|null
+ */
+ platform.version = name && version;
+
+ /**
+ * The name of the operating system.
+ *
+ * @memberOf platform
+ * @type Object
+ */
+ platform.os = os || {
+
+ /**
+ * The CPU architecture the OS is built for.
+ *
+ * @memberOf platform.os
+ * @type number|null
+ */
+ 'architecture': null,
+
+ /**
+ * The family of the OS.
+ *
+ * Common values include:
+ * "Windows", "Windows Server 2008 R2 / 7", "Windows Server 2008 / Vista",
+ * "Windows XP", "OS X", "Ubuntu", "Debian", "Fedora", "Red Hat", "SuSE",
+ * "Android", "iOS" and "Windows Phone"
+ *
+ * @memberOf platform.os
+ * @type string|null
+ */
+ 'family': null,
+
+ /**
+ * The version of the OS.
+ *
+ * @memberOf platform.os
+ * @type string|null
+ */
+ 'version': null,
+
+ /**
+ * Returns the OS string.
+ *
+ * @memberOf platform.os
+ * @returns {string} The OS string.
+ */
+ 'toString': function() { return 'null'; }
+ };
+
+ platform.parse = parse;
+ platform.toString = toStringPlatform;
+
+ if (platform.version) {
+ description.unshift(version);
+ }
+ if (platform.name) {
+ description.unshift(name);
+ }
+ if (os && name && !(os == String(os).split(' ')[0] && (os == name.split(' ')[0] || product))) {
+ description.push(product ? '(' + os + ')' : 'on ' + os);
+ }
+ if (description.length) {
+ platform.description = description.join(' ');
+ }
+ return platform;
+ }
+
+ /*--------------------------------------------------------------------------*/
+
+ // Export platform.
+ var platform = parse();
+
+ // Some AMD build optimizers, like r.js, check for condition patterns like the following:
+ if (typeof define == 'function' && typeof define.amd == 'object' && define.amd) {
+ // Expose platform on the global object to prevent errors when platform is
+ // loaded by a script tag in the presence of an AMD loader.
+ // See http://requirejs.org/docs/errors.html#mismatch for more details.
+ root.platform = platform;
+
+ // Define as an anonymous module so platform can be aliased through path mapping.
+ define(function() {
+ return platform;
+ });
+ }
+ // Check for `exports` after `define` in case a build optimizer adds an `exports` object.
+ else if (freeExports && freeModule) {
+ // Export for CommonJS support.
+ forOwn(platform, function(value, key) {
+ freeExports[key] = value;
+ });
+ }
+ else {
+ // Export to the global object.
+ root.platform = platform;
+ }
+}.call(this));
+
+}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
+
+},{}],9:[function(require,module,exports){
+var v1 = require('./v1');
+var v4 = require('./v4');
+
+var uuid = v4;
+uuid.v1 = v1;
+uuid.v4 = v4;
+
+module.exports = uuid;
+
+},{"./v1":12,"./v4":13}],10:[function(require,module,exports){
+/**
+ * Convert array of 16 byte values to UUID string format of the form:
+ * XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
+ */
+var byteToHex = [];
+for (var i = 0; i < 256; ++i) {
+ byteToHex[i] = (i + 0x100).toString(16).substr(1);
+}
+
+function bytesToUuid(buf, offset) {
+ var i = offset || 0;
+ var bth = byteToHex;
+ // join used to fix memory issue caused by concatenation: https://bugs.chromium.org/p/v8/issues/detail?id=3175#c4
+ return ([bth[buf[i++]], bth[buf[i++]],
+ bth[buf[i++]], bth[buf[i++]], '-',
+ bth[buf[i++]], bth[buf[i++]], '-',
+ bth[buf[i++]], bth[buf[i++]], '-',
+ bth[buf[i++]], bth[buf[i++]], '-',
+ bth[buf[i++]], bth[buf[i++]],
+ bth[buf[i++]], bth[buf[i++]],
+ bth[buf[i++]], bth[buf[i++]]]).join('');
+}
+
+module.exports = bytesToUuid;
+
+},{}],11:[function(require,module,exports){
+// Unique ID creation requires a high quality random # generator. In the
+// browser this is a little complicated due to unknown quality of Math.random()
+// and inconsistent support for the `crypto` API. We do the best we can via
+// feature-detection
+
+// getRandomValues needs to be invoked in a context where "this" is a Crypto
+// implementation. Also, find the complete implementation of crypto on IE11.
+var getRandomValues = (typeof(crypto) != 'undefined' && crypto.getRandomValues && crypto.getRandomValues.bind(crypto)) ||
+ (typeof(msCrypto) != 'undefined' && typeof window.msCrypto.getRandomValues == 'function' && msCrypto.getRandomValues.bind(msCrypto));
+
+if (getRandomValues) {
+ // WHATWG crypto RNG - http://wiki.whatwg.org/wiki/Crypto
+ var rnds8 = new Uint8Array(16); // eslint-disable-line no-undef
+
+ module.exports = function whatwgRNG() {
+ getRandomValues(rnds8);
+ return rnds8;
+ };
+} else {
+ // Math.random()-based (RNG)
+ //
+ // If all else fails, use Math.random(). It's fast, but is of unspecified
+ // quality.
+ var rnds = new Array(16);
+
+ module.exports = function mathRNG() {
+ for (var i = 0, r; i < 16; i++) {
+ if ((i & 0x03) === 0) r = Math.random() * 0x100000000;
+ rnds[i] = r >>> ((i & 0x03) << 3) & 0xff;
+ }
+
+ return rnds;
+ };
+}
+
+},{}],12:[function(require,module,exports){
+var rng = require('./lib/rng');
+var bytesToUuid = require('./lib/bytesToUuid');
+
+// **`v1()` - Generate time-based UUID**
+//
+// Inspired by https://github.com/LiosK/UUID.js
+// and http://docs.python.org/library/uuid.html
+
+var _nodeId;
+var _clockseq;
+
+// Previous uuid creation time
+var _lastMSecs = 0;
+var _lastNSecs = 0;
+
+// See https://github.com/broofa/node-uuid for API details
+function v1(options, buf, offset) {
+ var i = buf && offset || 0;
+ var b = buf || [];
+
+ options = options || {};
+ var node = options.node || _nodeId;
+ var clockseq = options.clockseq !== undefined ? options.clockseq : _clockseq;
+
+ // node and clockseq need to be initialized to random values if they're not
+ // specified. We do this lazily to minimize issues related to insufficient
+ // system entropy. See #189
+ if (node == null || clockseq == null) {
+ var seedBytes = rng();
+ if (node == null) {
+ // Per 4.5, create and 48-bit node id, (47 random bits + multicast bit = 1)
+ node = _nodeId = [
+ seedBytes[0] | 0x01,
+ seedBytes[1], seedBytes[2], seedBytes[3], seedBytes[4], seedBytes[5]
+ ];
+ }
+ if (clockseq == null) {
+ // Per 4.2.2, randomize (14 bit) clockseq
+ clockseq = _clockseq = (seedBytes[6] << 8 | seedBytes[7]) & 0x3fff;
+ }
+ }
+
+ // UUID timestamps are 100 nano-second units since the Gregorian epoch,
+ // (1582-10-15 00:00). JSNumbers aren't precise enough for this, so
+ // time is handled internally as 'msecs' (integer milliseconds) and 'nsecs'
+ // (100-nanoseconds offset from msecs) since unix epoch, 1970-01-01 00:00.
+ var msecs = options.msecs !== undefined ? options.msecs : new Date().getTime();
+
+ // Per 4.2.1.2, use count of uuid's generated during the current clock
+ // cycle to simulate higher resolution clock
+ var nsecs = options.nsecs !== undefined ? options.nsecs : _lastNSecs + 1;
+
+ // Time since last uuid creation (in msecs)
+ var dt = (msecs - _lastMSecs) + (nsecs - _lastNSecs)/10000;
+
+ // Per 4.2.1.2, Bump clockseq on clock regression
+ if (dt < 0 && options.clockseq === undefined) {
+ clockseq = clockseq + 1 & 0x3fff;
+ }
+
+ // Reset nsecs if clock regresses (new clockseq) or we've moved onto a new
+ // time interval
+ if ((dt < 0 || msecs > _lastMSecs) && options.nsecs === undefined) {
+ nsecs = 0;
+ }
+
+ // Per 4.2.1.2 Throw error if too many uuids are requested
+ if (nsecs >= 10000) {
+ throw new Error('uuid.v1(): Can\'t create more than 10M uuids/sec');
+ }
+
+ _lastMSecs = msecs;
+ _lastNSecs = nsecs;
+ _clockseq = clockseq;
+
+ // Per 4.1.4 - Convert from unix epoch to Gregorian epoch
+ msecs += 12219292800000;
+
+ // `time_low`
+ var tl = ((msecs & 0xfffffff) * 10000 + nsecs) % 0x100000000;
+ b[i++] = tl >>> 24 & 0xff;
+ b[i++] = tl >>> 16 & 0xff;
+ b[i++] = tl >>> 8 & 0xff;
+ b[i++] = tl & 0xff;
+
+ // `time_mid`
+ var tmh = (msecs / 0x100000000 * 10000) & 0xfffffff;
+ b[i++] = tmh >>> 8 & 0xff;
+ b[i++] = tmh & 0xff;
+
+ // `time_high_and_version`
+ b[i++] = tmh >>> 24 & 0xf | 0x10; // include version
+ b[i++] = tmh >>> 16 & 0xff;
+
+ // `clock_seq_hi_and_reserved` (Per 4.2.2 - include variant)
+ b[i++] = clockseq >>> 8 | 0x80;
+
+ // `clock_seq_low`
+ b[i++] = clockseq & 0xff;
+
+ // `node`
+ for (var n = 0; n < 6; ++n) {
+ b[i + n] = node[n];
+ }
+
+ return buf ? buf : bytesToUuid(b);
+}
+
+module.exports = v1;
+
+},{"./lib/bytesToUuid":10,"./lib/rng":11}],13:[function(require,module,exports){
+var rng = require('./lib/rng');
+var bytesToUuid = require('./lib/bytesToUuid');
+
+function v4(options, buf, offset) {
+ var i = buf && offset || 0;
+
+ if (typeof(options) == 'string') {
+ buf = options === 'binary' ? new Array(16) : null;
+ options = null;
+ }
+ options = options || {};
+
+ var rnds = options.random || (options.rng || rng)();
+
+ // Per 4.4, set bits for version and `clock_seq_hi_and_reserved`
+ rnds[6] = (rnds[6] & 0x0f) | 0x40;
+ rnds[8] = (rnds[8] & 0x3f) | 0x80;
+
+ // Copy bytes to buffer, if provided
+ if (buf) {
+ for (var ii = 0; ii < 16; ++ii) {
+ buf[i + ii] = rnds[ii];
+ }
+ }
+
+ return buf || bytesToUuid(rnds);
+}
+
+module.exports = v4;
+
+},{"./lib/bytesToUuid":10,"./lib/rng":11}],14:[function(require,module,exports){
+/*
+WildEmitter.js is a slim little event emitter by @henrikjoreteg largely based
+on @visionmedia's Emitter from UI Kit.
+
+Why? I wanted it standalone.
+
+I also wanted support for wildcard emitters like this:
+
+emitter.on('*', function (eventName, other, event, payloads) {
+
+});
+
+emitter.on('somenamespace*', function (eventName, payloads) {
+
+});
+
+Please note that callbacks triggered by wildcard registered events also get
+the event name as the first argument.
+*/
+
+module.exports = WildEmitter;
+
+function WildEmitter() { }
+
+WildEmitter.mixin = function (constructor) {
+ var prototype = constructor.prototype || constructor;
+
+ prototype.isWildEmitter= true;
+
+ // Listen on the given `event` with `fn`. Store a group name if present.
+ prototype.on = function (event, groupName, fn) {
+ this.callbacks = this.callbacks || {};
+ var hasGroup = (arguments.length === 3),
+ group = hasGroup ? arguments[1] : undefined,
+ func = hasGroup ? arguments[2] : arguments[1];
+ func._groupName = group;
+ (this.callbacks[event] = this.callbacks[event] || []).push(func);
+ return this;
+ };
+
+ // Adds an `event` listener that will be invoked a single
+ // time then automatically removed.
+ prototype.once = function (event, groupName, fn) {
+ var self = this,
+ hasGroup = (arguments.length === 3),
+ group = hasGroup ? arguments[1] : undefined,
+ func = hasGroup ? arguments[2] : arguments[1];
+ function on() {
+ self.off(event, on);
+ func.apply(this, arguments);
+ }
+ this.on(event, group, on);
+ return this;
+ };
+
+ // Unbinds an entire group
+ prototype.releaseGroup = function (groupName) {
+ this.callbacks = this.callbacks || {};
+ var item, i, len, handlers;
+ for (item in this.callbacks) {
+ handlers = this.callbacks[item];
+ for (i = 0, len = handlers.length; i < len; i++) {
+ if (handlers[i]._groupName === groupName) {
+ //console.log('removing');
+ // remove it and shorten the array we're looping through
+ handlers.splice(i, 1);
+ i--;
+ len--;
+ }
+ }
+ }
+ return this;
+ };
+
+ // Remove the given callback for `event` or all
+ // registered callbacks.
+ prototype.off = function (event, fn) {
+ this.callbacks = this.callbacks || {};
+ var callbacks = this.callbacks[event],
+ i;
+
+ if (!callbacks) return this;
+
+ // remove all handlers
+ if (arguments.length === 1) {
+ delete this.callbacks[event];
+ return this;
+ }
+
+ // remove specific handler
+ i = callbacks.indexOf(fn);
+ callbacks.splice(i, 1);
+ if (callbacks.length === 0) {
+ delete this.callbacks[event];
+ }
+ return this;
+ };
+
+ /// Emit `event` with the given args.
+ // also calls any `*` handlers
+ prototype.emit = function (event) {
+ this.callbacks = this.callbacks || {};
+ var args = [].slice.call(arguments, 1),
+ callbacks = this.callbacks[event],
+ specialCallbacks = this.getWildcardCallbacks(event),
+ i,
+ len,
+ item,
+ listeners;
+
+ if (callbacks) {
+ listeners = callbacks.slice();
+ for (i = 0, len = listeners.length; i < len; ++i) {
+ if (!listeners[i]) {
+ break;
+ }
+ listeners[i].apply(this, args);
+ }
+ }
+
+ if (specialCallbacks) {
+ len = specialCallbacks.length;
+ listeners = specialCallbacks.slice();
+ for (i = 0, len = listeners.length; i < len; ++i) {
+ if (!listeners[i]) {
+ break;
+ }
+ listeners[i].apply(this, [event].concat(args));
+ }
+ }
+
+ return this;
+ };
+
+ // Helper for for finding special wildcard event handlers that match the event
+ prototype.getWildcardCallbacks = function (eventName) {
+ this.callbacks = this.callbacks || {};
+ var item,
+ split,
+ result = [];
+
+ for (item in this.callbacks) {
+ split = item.split('*');
+ if (item === '*' || (split.length === 2 && eventName.slice(0, split[0].length) === split[0])) {
+ result = result.concat(this.callbacks[item]);
+ }
+ }
+ return result;
+ };
+
+};
+
+WildEmitter.mixin(WildEmitter);
+
+},{}],15:[function(require,module,exports){
+/*!
+ * EventEmitter v5.2.5 - git.io/ee
+ * Unlicense - http://unlicense.org/
+ * Oliver Caldwell - http://oli.me.uk/
+ * @preserve
+ */
+
+;(function (exports) {
+ 'use strict';
+
+ /**
+ * Class for managing events.
+ * Can be extended to provide event functionality in other classes.
+ *
+ * @class EventEmitter Manages event registering and emitting.
+ */
+ function EventEmitter() {}
+
+ // Shortcuts to improve speed and size
+ var proto = EventEmitter.prototype;
+ var originalGlobalValue = exports.EventEmitter;
+
+ /**
+ * Finds the index of the listener for the event in its storage array.
+ *
+ * @param {Function[]} listeners Array of listeners to search through.
+ * @param {Function} listener Method to look for.
+ * @return {Number} Index of the specified listener, -1 if not found
+ * @api private
+ */
+ function indexOfListener(listeners, listener) {
+ var i = listeners.length;
+ while (i--) {
+ if (listeners[i].listener === listener) {
+ return i;
+ }
+ }
+
+ return -1;
+ }
+
+ /**
+ * Alias a method while keeping the context correct, to allow for overwriting of target method.
+ *
+ * @param {String} name The name of the target method.
+ * @return {Function} The aliased method
+ * @api private
+ */
+ function alias(name) {
+ return function aliasClosure() {
+ return this[name].apply(this, arguments);
+ };
+ }
+
+ /**
+ * Returns the listener array for the specified event.
+ * Will initialise the event object and listener arrays if required.
+ * Will return an object if you use a regex search. The object contains keys for each matched event. So /ba[rz]/ might return an object containing bar and baz. But only if you have either defined them with defineEvent or added some listeners to them.
+ * Each property in the object response is an array of listener functions.
+ *
+ * @param {String|RegExp} evt Name of the event to return the listeners from.
+ * @return {Function[]|Object} All listener functions for the event.
+ */
+ proto.getListeners = function getListeners(evt) {
+ var events = this._getEvents();
+ var response;
+ var key;
+
+ // Return a concatenated array of all matching events if
+ // the selector is a regular expression.
+ if (evt instanceof RegExp) {
+ response = {};
+ for (key in events) {
+ if (events.hasOwnProperty(key) && evt.test(key)) {
+ response[key] = events[key];
+ }
+ }
+ }
+ else {
+ response = events[evt] || (events[evt] = []);
+ }
+
+ return response;
+ };
+
+ /**
+ * Takes a list of listener objects and flattens it into a list of listener functions.
+ *
+ * @param {Object[]} listeners Raw listener objects.
+ * @return {Function[]} Just the listener functions.
+ */
+ proto.flattenListeners = function flattenListeners(listeners) {
+ var flatListeners = [];
+ var i;
+
+ for (i = 0; i < listeners.length; i += 1) {
+ flatListeners.push(listeners[i].listener);
+ }
+
+ return flatListeners;
+ };
+
+ /**
+ * Fetches the requested listeners via getListeners but will always return the results inside an object. This is mainly for internal use but others may find it useful.
+ *
+ * @param {String|RegExp} evt Name of the event to return the listeners from.
+ * @return {Object} All listener functions for an event in an object.
+ */
+ proto.getListenersAsObject = function getListenersAsObject(evt) {
+ var listeners = this.getListeners(evt);
+ var response;
+
+ if (listeners instanceof Array) {
+ response = {};
+ response[evt] = listeners;
+ }
+
+ return response || listeners;
+ };
+
+ function isValidListener (listener) {
+ if (typeof listener === 'function' || listener instanceof RegExp) {
+ return true
+ } else if (listener && typeof listener === 'object') {
+ return isValidListener(listener.listener)
+ } else {
+ return false
+ }
+ }
+
+ /**
+ * Adds a listener function to the specified event.
+ * The listener will not be added if it is a duplicate.
+ * If the listener returns true then it will be removed after it is called.
+ * If you pass a regular expression as the event name then the listener will be added to all events that match it.
+ *
+ * @param {String|RegExp} evt Name of the event to attach the listener to.
+ * @param {Function} listener Method to be called when the event is emitted. If the function returns true then it will be removed after calling.
+ * @return {Object} Current instance of EventEmitter for chaining.
+ */
+ proto.addListener = function addListener(evt, listener) {
+ if (!isValidListener(listener)) {
+ throw new TypeError('listener must be a function');
+ }
+
+ var listeners = this.getListenersAsObject(evt);
+ var listenerIsWrapped = typeof listener === 'object';
+ var key;
+
+ for (key in listeners) {
+ if (listeners.hasOwnProperty(key) && indexOfListener(listeners[key], listener) === -1) {
+ listeners[key].push(listenerIsWrapped ? listener : {
+ listener: listener,
+ once: false
+ });
+ }
+ }
+
+ return this;
+ };
+
+ /**
+ * Alias of addListener
+ */
+ proto.on = alias('addListener');
+
+ /**
+ * Semi-alias of addListener. It will add a listener that will be
+ * automatically removed after its first execution.
+ *
+ * @param {String|RegExp} evt Name of the event to attach the listener to.
+ * @param {Function} listener Method to be called when the event is emitted. If the function returns true then it will be removed after calling.
+ * @return {Object} Current instance of EventEmitter for chaining.
+ */
+ proto.addOnceListener = function addOnceListener(evt, listener) {
+ return this.addListener(evt, {
+ listener: listener,
+ once: true
+ });
+ };
+
+ /**
+ * Alias of addOnceListener.
+ */
+ proto.once = alias('addOnceListener');
+
+ /**
+ * Defines an event name. This is required if you want to use a regex to add a listener to multiple events at once. If you don't do this then how do you expect it to know what event to add to? Should it just add to every possible match for a regex? No. That is scary and bad.
+ * You need to tell it what event names should be matched by a regex.
+ *
+ * @param {String} evt Name of the event to create.
+ * @return {Object} Current instance of EventEmitter for chaining.
+ */
+ proto.defineEvent = function defineEvent(evt) {
+ this.getListeners(evt);
+ return this;
+ };
+
+ /**
+ * Uses defineEvent to define multiple events.
+ *
+ * @param {String[]} evts An array of event names to define.
+ * @return {Object} Current instance of EventEmitter for chaining.
+ */
+ proto.defineEvents = function defineEvents(evts) {
+ for (var i = 0; i < evts.length; i += 1) {
+ this.defineEvent(evts[i]);
+ }
+ return this;
+ };
+
+ /**
+ * Removes a listener function from the specified event.
+ * When passed a regular expression as the event name, it will remove the listener from all events that match it.
+ *
+ * @param {String|RegExp} evt Name of the event to remove the listener from.
+ * @param {Function} listener Method to remove from the event.
+ * @return {Object} Current instance of EventEmitter for chaining.
+ */
+ proto.removeListener = function removeListener(evt, listener) {
+ var listeners = this.getListenersAsObject(evt);
+ var index;
+ var key;
+
+ for (key in listeners) {
+ if (listeners.hasOwnProperty(key)) {
+ index = indexOfListener(listeners[key], listener);
+
+ if (index !== -1) {
+ listeners[key].splice(index, 1);
+ }
+ }
+ }
+
+ return this;
+ };
+
+ /**
+ * Alias of removeListener
+ */
+ proto.off = alias('removeListener');
+
+ /**
+ * Adds listeners in bulk using the manipulateListeners method.
+ * If you pass an object as the first argument you can add to multiple events at once. The object should contain key value pairs of events and listeners or listener arrays. You can also pass it an event name and an array of listeners to be added.
+ * You can also pass it a regular expression to add the array of listeners to all events that match it.
+ * Yeah, this function does quite a bit. That's probably a bad thing.
+ *
+ * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to add to multiple events at once.
+ * @param {Function[]} [listeners] An optional array of listener functions to add.
+ * @return {Object} Current instance of EventEmitter for chaining.
+ */
+ proto.addListeners = function addListeners(evt, listeners) {
+ // Pass through to manipulateListeners
+ return this.manipulateListeners(false, evt, listeners);
+ };
+
+ /**
+ * Removes listeners in bulk using the manipulateListeners method.
+ * If you pass an object as the first argument you can remove from multiple events at once. The object should contain key value pairs of events and listeners or listener arrays.
+ * You can also pass it an event name and an array of listeners to be removed.
+ * You can also pass it a regular expression to remove the listeners from all events that match it.
+ *
+ * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to remove from multiple events at once.
+ * @param {Function[]} [listeners] An optional array of listener functions to remove.
+ * @return {Object} Current instance of EventEmitter for chaining.
+ */
+ proto.removeListeners = function removeListeners(evt, listeners) {
+ // Pass through to manipulateListeners
+ return this.manipulateListeners(true, evt, listeners);
+ };
+
+ /**
+ * Edits listeners in bulk. The addListeners and removeListeners methods both use this to do their job. You should really use those instead, this is a little lower level.
+ * The first argument will determine if the listeners are removed (true) or added (false).
+ * If you pass an object as the second argument you can add/remove from multiple events at once. The object should contain key value pairs of events and listeners or listener arrays.
+ * You can also pass it an event name and an array of listeners to be added/removed.
+ * You can also pass it a regular expression to manipulate the listeners of all events that match it.
+ *
+ * @param {Boolean} remove True if you want to remove listeners, false if you want to add.
+ * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to add/remove from multiple events at once.
+ * @param {Function[]} [listeners] An optional array of listener functions to add/remove.
+ * @return {Object} Current instance of EventEmitter for chaining.
+ */
+ proto.manipulateListeners = function manipulateListeners(remove, evt, listeners) {
+ var i;
+ var value;
+ var single = remove ? this.removeListener : this.addListener;
+ var multiple = remove ? this.removeListeners : this.addListeners;
+
+ // If evt is an object then pass each of its properties to this method
+ if (typeof evt === 'object' && !(evt instanceof RegExp)) {
+ for (i in evt) {
+ if (evt.hasOwnProperty(i) && (value = evt[i])) {
+ // Pass the single listener straight through to the singular method
+ if (typeof value === 'function') {
+ single.call(this, i, value);
+ }
+ else {
+ // Otherwise pass back to the multiple function
+ multiple.call(this, i, value);
+ }
+ }
+ }
+ }
+ else {
+ // So evt must be a string
+ // And listeners must be an array of listeners
+ // Loop over it and pass each one to the multiple method
+ i = listeners.length;
+ while (i--) {
+ single.call(this, evt, listeners[i]);
+ }
+ }
+
+ return this;
+ };
+
+ /**
+ * Removes all listeners from a specified event.
+ * If you do not specify an event then all listeners will be removed.
+ * That means every event will be emptied.
+ * You can also pass a regex to remove all events that match it.
+ *
+ * @param {String|RegExp} [evt] Optional name of the event to remove all listeners for. Will remove from every event if not passed.
+ * @return {Object} Current instance of EventEmitter for chaining.
+ */
+ proto.removeEvent = function removeEvent(evt) {
+ var type = typeof evt;
+ var events = this._getEvents();
+ var key;
+
+ // Remove different things depending on the state of evt
+ if (type === 'string') {
+ // Remove all listeners for the specified event
+ delete events[evt];
+ }
+ else if (evt instanceof RegExp) {
+ // Remove all events matching the regex.
+ for (key in events) {
+ if (events.hasOwnProperty(key) && evt.test(key)) {
+ delete events[key];
+ }
+ }
+ }
+ else {
+ // Remove all listeners in all events
+ delete this._events;
+ }
+
+ return this;
+ };
+
+ /**
+ * Alias of removeEvent.
+ *
+ * Added to mirror the node API.
+ */
+ proto.removeAllListeners = alias('removeEvent');
+
+ /**
+ * Emits an event of your choice.
+ * When emitted, every listener attached to that event will be executed.
+ * If you pass the optional argument array then those arguments will be passed to every listener upon execution.
+ * Because it uses `apply`, your array of arguments will be passed as if you wrote them out separately.
+ * So they will not arrive within the array on the other side, they will be separate.
+ * You can also pass a regular expression to emit to all events that match it.
+ *
+ * @param {String|RegExp} evt Name of the event to emit and execute listeners for.
+ * @param {Array} [args] Optional array of arguments to be passed to each listener.
+ * @return {Object} Current instance of EventEmitter for chaining.
+ */
+ proto.emitEvent = function emitEvent(evt, args) {
+ var listenersMap = this.getListenersAsObject(evt);
+ var listeners;
+ var listener;
+ var i;
+ var key;
+ var response;
+
+ for (key in listenersMap) {
+ if (listenersMap.hasOwnProperty(key)) {
+ listeners = listenersMap[key].slice(0);
+
+ for (i = 0; i < listeners.length; i++) {
+ // If the listener returns true then it shall be removed from the event
+ // The function is executed either with a basic call or an apply if there is an args array
+ listener = listeners[i];
+
+ if (listener.once === true) {
+ this.removeListener(evt, listener.listener);
+ }
+
+ response = listener.listener.apply(this, args || []);
+
+ if (response === this._getOnceReturnValue()) {
+ this.removeListener(evt, listener.listener);
+ }
+ }
+ }
+ }
+
+ return this;
+ };
+
+ /**
+ * Alias of emitEvent
+ */
+ proto.trigger = alias('emitEvent');
+
+ /**
+ * Subtly different from emitEvent in that it will pass its arguments on to the listeners, as opposed to taking a single array of arguments to pass on.
+ * As with emitEvent, you can pass a regex in place of the event name to emit to all events that match it.
+ *
+ * @param {String|RegExp} evt Name of the event to emit and execute listeners for.
+ * @param {...*} Optional additional arguments to be passed to each listener.
+ * @return {Object} Current instance of EventEmitter for chaining.
+ */
+ proto.emit = function emit(evt) {
+ var args = Array.prototype.slice.call(arguments, 1);
+ return this.emitEvent(evt, args);
+ };
+
+ /**
+ * Sets the current value to check against when executing listeners. If a
+ * listeners return value matches the one set here then it will be removed
+ * after execution. This value defaults to true.
+ *
+ * @param {*} value The new value to check for when executing listeners.
+ * @return {Object} Current instance of EventEmitter for chaining.
+ */
+ proto.setOnceReturnValue = function setOnceReturnValue(value) {
+ this._onceReturnValue = value;
+ return this;
+ };
+
+ /**
+ * Fetches the current value to check against when executing listeners. If
+ * the listeners return value matches this one then it should be removed
+ * automatically. It will return true by default.
+ *
+ * @return {*|Boolean} The current value to check for or the default, true.
+ * @api private
+ */
+ proto._getOnceReturnValue = function _getOnceReturnValue() {
+ if (this.hasOwnProperty('_onceReturnValue')) {
+ return this._onceReturnValue;
+ }
+ else {
+ return true;
+ }
+ };
+
+ /**
+ * Fetches the events object and creates one if required.
+ *
+ * @return {Object} The events storage object.
+ * @api private
+ */
+ proto._getEvents = function _getEvents() {
+ return this._events || (this._events = {});
+ };
+
+ /**
+ * Reverts the global {@link EventEmitter} to its previous value and returns a reference to this version.
+ *
+ * @return {Function} Non conflicting EventEmitter class.
+ */
+ EventEmitter.noConflict = function noConflict() {
+ exports.EventEmitter = originalGlobalValue;
+ return EventEmitter;
+ };
+
+ // Expose the class either via AMD, CommonJS or the global object
+ if (typeof define === 'function' && define.amd) {
+ define(function () {
+ return EventEmitter;
+ });
+ }
+ else if (typeof module === 'object' && module.exports){
+ module.exports = EventEmitter;
+ }
+ else {
+ exports.EventEmitter = EventEmitter;
+ }
+}(typeof window !== 'undefined' ? window : this || {}));
+
+},{}],16:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+var OpenVidu_1 = require("./OpenVidu/OpenVidu");
+if (window) {
+ window['OpenVidu'] = OpenVidu_1.OpenVidu;
+}
+
+},{"./OpenVidu/OpenVidu":19}],17:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+var Stream_1 = require("./Stream");
+var Connection = (function () {
+ function Connection(session, opts) {
+ this.session = session;
+ this.disposed = false;
+ var msg = "'Connection' created ";
+ if (!!opts) {
+ msg += "(remote) with 'connectionId' [" + opts.id + ']';
+ }
+ else {
+ msg += '(local)';
+ }
+ console.info(msg);
+ this.options = opts;
+ if (!!opts) {
+ this.connectionId = opts.id;
+ if (opts.metadata) {
+ this.data = opts.metadata;
+ }
+ if (opts.streams) {
+ this.initRemoteStreams(opts.streams);
+ }
+ }
+ this.creationTime = new Date().getTime();
+ }
+ Connection.prototype.sendIceCandidate = function (candidate) {
+ console.debug((!!this.stream.outboundStreamOpts ? 'Local' : 'Remote'), 'candidate for', this.connectionId, JSON.stringify(candidate));
+ this.session.openvidu.sendRequest('onIceCandidate', {
+ endpointName: this.connectionId,
+ candidate: candidate.candidate,
+ sdpMid: candidate.sdpMid,
+ sdpMLineIndex: candidate.sdpMLineIndex
+ }, function (error, response) {
+ if (error) {
+ console.error('Error sending ICE candidate: '
+ + JSON.stringify(error));
+ }
+ });
+ };
+ Connection.prototype.initRemoteStreams = function (options) {
+ var _this = this;
+ options.forEach(function (opts) {
+ var streamOptions = {
+ id: opts.id,
+ connection: _this,
+ hasAudio: opts.hasAudio,
+ hasVideo: opts.hasVideo,
+ audioActive: opts.audioActive,
+ videoActive: opts.videoActive,
+ typeOfVideo: opts.typeOfVideo,
+ frameRate: opts.frameRate,
+ videoDimensions: !!opts.videoDimensions ? JSON.parse(opts.videoDimensions) : undefined
+ };
+ var stream = new Stream_1.Stream(_this.session, streamOptions);
+ _this.addStream(stream);
+ });
+ console.info("Remote 'Connection' with 'connectionId' [" + this.connectionId + '] is now configured for receiving Streams with options: ', this.stream.inboundStreamOpts);
+ };
+ Connection.prototype.addStream = function (stream) {
+ stream.connection = this;
+ this.stream = stream;
+ };
+ Connection.prototype.removeStream = function (streamId) {
+ delete this.stream;
+ };
+ Connection.prototype.dispose = function () {
+ if (!!this.stream) {
+ delete this.stream;
+ }
+ this.disposed = true;
+ };
+ return Connection;
+}());
+exports.Connection = Connection;
+
+},{"./Stream":22}],18:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+var LocalRecorderState_1 = require("../OpenViduInternal/Enums/LocalRecorderState");
+var LocalRecorder = (function () {
+ function LocalRecorder(stream) {
+ this.stream = stream;
+ this.chunks = [];
+ this.count = 0;
+ this.connectionId = (!!this.stream.connection) ? this.stream.connection.connectionId : 'default-connection';
+ this.id = this.stream.streamId + '_' + this.connectionId + '_localrecord';
+ this.state = LocalRecorderState_1.LocalRecorderState.READY;
+ }
+ LocalRecorder.prototype.record = function () {
+ var _this = this;
+ return new Promise(function (resolve, reject) {
+ try {
+ if (typeof MediaRecorder === 'undefined') {
+ console.error('MediaRecorder not supported on your browser. See compatibility in https://caniuse.com/#search=MediaRecorder');
+ throw (Error('MediaRecorder not supported on your browser. See compatibility in https://caniuse.com/#search=MediaRecorder'));
+ }
+ if (_this.state !== LocalRecorderState_1.LocalRecorderState.READY) {
+ throw (Error('\'LocalRecord.record()\' needs \'LocalRecord.state\' to be \'READY\' (current value: \'' + _this.state + '\'). Call \'LocalRecorder.clean()\' or init a new LocalRecorder before'));
+ }
+ console.log("Starting local recording of stream '" + _this.stream.streamId + "' of connection '" + _this.connectionId + "'");
+ if (typeof MediaRecorder.isTypeSupported === 'function') {
+ var options = void 0;
+ if (MediaRecorder.isTypeSupported('video/webm;codecs=vp9')) {
+ options = { mimeType: 'video/webm;codecs=vp9' };
+ }
+ else if (MediaRecorder.isTypeSupported('video/webm;codecs=h264')) {
+ options = { mimeType: 'video/webm;codecs=h264' };
+ }
+ else if (MediaRecorder.isTypeSupported('video/webm;codecs=vp8')) {
+ options = { mimeType: 'video/webm;codecs=vp8' };
+ }
+ console.log('Using mimeType ' + options.mimeType);
+ _this.mediaRecorder = new MediaRecorder(_this.stream.getMediaStream(), options);
+ }
+ else {
+ console.warn('isTypeSupported is not supported, using default codecs for browser');
+ _this.mediaRecorder = new MediaRecorder(_this.stream.getMediaStream());
+ }
+ _this.mediaRecorder.start(10);
+ }
+ catch (err) {
+ reject(err);
+ }
+ _this.mediaRecorder.ondataavailable = function (e) {
+ _this.chunks.push(e.data);
+ };
+ _this.mediaRecorder.onerror = function (e) {
+ console.error('MediaRecorder error: ', e);
+ };
+ _this.mediaRecorder.onstart = function () {
+ console.log('MediaRecorder started (state=' + _this.mediaRecorder.state + ')');
+ };
+ _this.mediaRecorder.onstop = function () {
+ _this.onStopDefault();
+ };
+ _this.mediaRecorder.onpause = function () {
+ console.log('MediaRecorder paused (state=' + _this.mediaRecorder.state + ')');
+ };
+ _this.mediaRecorder.onresume = function () {
+ console.log('MediaRecorder resumed (state=' + _this.mediaRecorder.state + ')');
+ };
+ _this.mediaRecorder.onwarning = function (e) {
+ console.log('MediaRecorder warning: ' + e);
+ };
+ _this.state = LocalRecorderState_1.LocalRecorderState.RECORDING;
+ resolve();
+ });
+ };
+ LocalRecorder.prototype.stop = function () {
+ var _this = this;
+ return new Promise(function (resolve, reject) {
+ try {
+ if (_this.state === LocalRecorderState_1.LocalRecorderState.READY || _this.state === LocalRecorderState_1.LocalRecorderState.FINISHED) {
+ throw (Error('\'LocalRecord.stop()\' needs \'LocalRecord.state\' to be \'RECORDING\' or \'PAUSED\' (current value: \'' + _this.state + '\'). Call \'LocalRecorder.start()\' before'));
+ }
+ _this.mediaRecorder.onstop = function () {
+ _this.onStopDefault();
+ resolve();
+ };
+ _this.mediaRecorder.stop();
+ }
+ catch (e) {
+ reject(e);
+ }
+ });
+ };
+ LocalRecorder.prototype.pause = function () {
+ var _this = this;
+ return new Promise(function (resolve, reject) {
+ try {
+ if (_this.state !== LocalRecorderState_1.LocalRecorderState.RECORDING) {
+ reject(Error('\'LocalRecord.pause()\' needs \'LocalRecord.state\' to be \'RECORDING\' (current value: \'' + _this.state + '\'). Call \'LocalRecorder.start()\' or \'LocalRecorder.resume()\' before'));
+ }
+ _this.mediaRecorder.pause();
+ _this.state = LocalRecorderState_1.LocalRecorderState.PAUSED;
+ }
+ catch (error) {
+ reject(error);
+ }
+ });
+ };
+ LocalRecorder.prototype.resume = function () {
+ var _this = this;
+ return new Promise(function (resolve, reject) {
+ try {
+ if (_this.state !== LocalRecorderState_1.LocalRecorderState.PAUSED) {
+ throw (Error('\'LocalRecord.resume()\' needs \'LocalRecord.state\' to be \'PAUSED\' (current value: \'' + _this.state + '\'). Call \'LocalRecorder.pause()\' before'));
+ }
+ _this.mediaRecorder.resume();
+ _this.state = LocalRecorderState_1.LocalRecorderState.RECORDING;
+ }
+ catch (error) {
+ reject(error);
+ }
+ });
+ };
+ LocalRecorder.prototype.preview = function (parentElement) {
+ if (this.state !== LocalRecorderState_1.LocalRecorderState.FINISHED) {
+ throw (Error('\'LocalRecord.preview()\' needs \'LocalRecord.state\' to be \'FINISHED\' (current value: \'' + this.state + '\'). Call \'LocalRecorder.stop()\' before'));
+ }
+ this.videoPreview = document.createElement('video');
+ this.videoPreview.id = this.id;
+ this.videoPreview.autoplay = true;
+ if (typeof parentElement === 'string') {
+ this.htmlParentElementId = parentElement;
+ var parentElementDom = document.getElementById(parentElement);
+ if (parentElementDom) {
+ this.videoPreview = parentElementDom.appendChild(this.videoPreview);
+ }
+ }
+ else {
+ this.htmlParentElementId = parentElement.id;
+ this.videoPreview = parentElement.appendChild(this.videoPreview);
+ }
+ this.videoPreview.src = this.videoPreviewSrc;
+ return this.videoPreview;
+ };
+ LocalRecorder.prototype.clean = function () {
+ var _this = this;
+ var f = function () {
+ delete _this.blob;
+ _this.chunks = [];
+ _this.count = 0;
+ delete _this.mediaRecorder;
+ _this.state = LocalRecorderState_1.LocalRecorderState.READY;
+ };
+ if (this.state === LocalRecorderState_1.LocalRecorderState.RECORDING || this.state === LocalRecorderState_1.LocalRecorderState.PAUSED) {
+ this.stop().then(function () { return f(); }).catch(function () { return f(); });
+ }
+ else {
+ f();
+ }
+ };
+ LocalRecorder.prototype.download = function () {
+ if (this.state !== LocalRecorderState_1.LocalRecorderState.FINISHED) {
+ throw (Error('\'LocalRecord.download()\' needs \'LocalRecord.state\' to be \'FINISHED\' (current value: \'' + this.state + '\'). Call \'LocalRecorder.stop()\' before'));
+ }
+ else {
+ var a = document.createElement('a');
+ a.style.display = 'none';
+ document.body.appendChild(a);
+ var url = window.URL.createObjectURL(this.blob);
+ a.href = url;
+ a.download = this.id + '.webm';
+ a.click();
+ window.URL.revokeObjectURL(url);
+ document.body.removeChild(a);
+ }
+ };
+ LocalRecorder.prototype.getBlob = function () {
+ if (this.state !== LocalRecorderState_1.LocalRecorderState.FINISHED) {
+ throw (Error('Call \'LocalRecord.stop()\' before getting Blob file'));
+ }
+ else {
+ return this.blob;
+ }
+ };
+ LocalRecorder.prototype.uploadAsBinary = function (endpoint, headers) {
+ var _this = this;
+ return new Promise(function (resolve, reject) {
+ if (_this.state !== LocalRecorderState_1.LocalRecorderState.FINISHED) {
+ reject(Error('\'LocalRecord.uploadAsBinary()\' needs \'LocalRecord.state\' to be \'FINISHED\' (current value: \'' + _this.state + '\'). Call \'LocalRecorder.stop()\' before'));
+ }
+ else {
+ var http_1 = new XMLHttpRequest();
+ http_1.open('POST', endpoint, true);
+ if (typeof headers === 'object') {
+ for (var _i = 0, _a = Object.keys(headers); _i < _a.length; _i++) {
+ var key = _a[_i];
+ http_1.setRequestHeader(key, headers[key]);
+ }
+ }
+ http_1.onreadystatechange = function () {
+ if (http_1.readyState === 4) {
+ if (http_1.status.toString().charAt(0) === '2') {
+ resolve(http_1.responseText);
+ }
+ else {
+ reject(http_1.status);
+ }
+ }
+ };
+ http_1.send(_this.blob);
+ }
+ });
+ };
+ LocalRecorder.prototype.uploadAsMultipartfile = function (endpoint, headers) {
+ var _this = this;
+ return new Promise(function (resolve, reject) {
+ if (_this.state !== LocalRecorderState_1.LocalRecorderState.FINISHED) {
+ reject(Error('\'LocalRecord.uploadAsMultipartfile()\' needs \'LocalRecord.state\' to be \'FINISHED\' (current value: \'' + _this.state + '\'). Call \'LocalRecorder.stop()\' before'));
+ }
+ else {
+ var http_2 = new XMLHttpRequest();
+ http_2.open('POST', endpoint, true);
+ if (typeof headers === 'object') {
+ for (var _i = 0, _a = Object.keys(headers); _i < _a.length; _i++) {
+ var key = _a[_i];
+ http_2.setRequestHeader(key, headers[key]);
+ }
+ }
+ var sendable = new FormData();
+ sendable.append('file', _this.blob, _this.id + '.webm');
+ http_2.onreadystatechange = function () {
+ if (http_2.readyState === 4) {
+ if (http_2.status.toString().charAt(0) === '2') {
+ resolve(http_2.responseText);
+ }
+ else {
+ reject(http_2.status);
+ }
+ }
+ };
+ http_2.send(sendable);
+ }
+ });
+ };
+ LocalRecorder.prototype.onStopDefault = function () {
+ console.log('MediaRecorder stopped (state=' + this.mediaRecorder.state + ')');
+ this.blob = new Blob(this.chunks, { type: 'video/webm' });
+ this.chunks = [];
+ this.videoPreviewSrc = window.URL.createObjectURL(this.blob);
+ this.state = LocalRecorderState_1.LocalRecorderState.FINISHED;
+ };
+ return LocalRecorder;
+}());
+exports.LocalRecorder = LocalRecorder;
+
+},{"../OpenViduInternal/Enums/LocalRecorderState":25}],19:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+var LocalRecorder_1 = require("./LocalRecorder");
+var Publisher_1 = require("./Publisher");
+var Session_1 = require("./Session");
+var StreamPropertyChangedEvent_1 = require("../OpenViduInternal/Events/StreamPropertyChangedEvent");
+var OpenViduError_1 = require("../OpenViduInternal/Enums/OpenViduError");
+var VideoInsertMode_1 = require("../OpenViduInternal/Enums/VideoInsertMode");
+var screenSharingAuto = require("../OpenViduInternal/ScreenSharing/Screen-Capturing-Auto");
+var screenSharing = require("../OpenViduInternal/ScreenSharing/Screen-Capturing");
+var RpcBuilder = require("../OpenViduInternal/KurentoUtils/kurento-jsonrpc");
+var platform = require("platform");
+var OpenVidu = (function () {
+ function OpenVidu() {
+ var _this = this;
+ this.publishers = [];
+ this.secret = '';
+ this.recorder = false;
+ this.advancedConfiguration = {};
+ console.info("'OpenVidu' initialized");
+ if (platform.name.toLowerCase().indexOf('mobile') !== -1) {
+ window.onorientationchange = function () {
+ _this.publishers.forEach(function (publisher) {
+ if (!!publisher.stream && !!publisher.stream.hasVideo && !!publisher.stream.streamManager.videos[0]) {
+ var attempts_1 = 0;
+ var oldWidth_1 = publisher.stream.videoDimensions.width;
+ var oldHeight_1 = publisher.stream.videoDimensions.height;
+ var firefoxSettings_1 = publisher.stream.getMediaStream().getVideoTracks()[0].getSettings();
+ var newWidth_1 = (platform.name.toLowerCase().indexOf('firefox') !== -1) ? firefoxSettings_1.width : publisher.videoReference.videoWidth;
+ var newHeight_1 = (platform.name.toLowerCase().indexOf('firefox') !== -1) ? firefoxSettings_1.height : publisher.videoReference.videoHeight;
+ var repeatUntilChange_1 = setInterval(function () {
+ firefoxSettings_1 = publisher.stream.getMediaStream().getVideoTracks()[0].getSettings();
+ newWidth_1 = (platform.name.toLowerCase().indexOf('firefox') !== -1) ? firefoxSettings_1.width : publisher.videoReference.videoWidth;
+ newHeight_1 = (platform.name.toLowerCase().indexOf('firefox') !== -1) ? firefoxSettings_1.height : publisher.videoReference.videoHeight;
+ sendStreamPropertyChangedEvent_1(oldWidth_1, oldHeight_1, newWidth_1, newHeight_1);
+ }, 100);
+ var sendStreamPropertyChangedEvent_1 = function (oldWidth, oldHeight, newWidth, newHeight) {
+ attempts_1++;
+ if (attempts_1 > 4) {
+ clearTimeout(repeatUntilChange_1);
+ }
+ if (newWidth !== oldWidth || newHeight !== oldHeight) {
+ publisher.stream.videoDimensions = {
+ width: newWidth || 0,
+ height: newHeight || 0
+ };
+ _this.sendRequest('streamPropertyChanged', {
+ streamId: publisher.stream.streamId,
+ property: 'videoDimensions',
+ newValue: JSON.stringify(publisher.stream.videoDimensions),
+ reason: 'deviceRotated'
+ }, function (error, response) {
+ if (error) {
+ console.error("Error sending 'streamPropertyChanged' event", error);
+ }
+ else {
+ _this.session.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent_1.StreamPropertyChangedEvent(_this.session, publisher.stream, 'videoDimensions', publisher.stream.videoDimensions, { width: oldWidth, height: oldHeight }, 'deviceRotated')]);
+ publisher.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent_1.StreamPropertyChangedEvent(publisher, publisher.stream, 'videoDimensions', publisher.stream.videoDimensions, { width: oldWidth, height: oldHeight }, 'deviceRotated')]);
+ }
+ });
+ clearTimeout(repeatUntilChange_1);
+ }
+ };
+ }
+ });
+ };
+ }
+ }
+ OpenVidu.prototype.initSession = function () {
+ this.session = new Session_1.Session(this);
+ return this.session;
+ };
+ OpenVidu.prototype.initPublisher = function (targetElement, param2, param3) {
+ var properties;
+ if (!!param2 && (typeof param2 !== 'function')) {
+ properties = param2;
+ properties = {
+ audioSource: (typeof properties.audioSource !== 'undefined') ? properties.audioSource : undefined,
+ frameRate: this.isMediaStreamTrack(properties.videoSource) ? undefined : ((typeof properties.frameRate !== 'undefined') ? properties.frameRate : undefined),
+ insertMode: (typeof properties.insertMode !== 'undefined') ? ((typeof properties.insertMode === 'string') ? VideoInsertMode_1.VideoInsertMode[properties.insertMode] : properties.insertMode) : VideoInsertMode_1.VideoInsertMode.APPEND,
+ mirror: (typeof properties.mirror !== 'undefined') ? properties.mirror : true,
+ publishAudio: (typeof properties.publishAudio !== 'undefined') ? properties.publishAudio : true,
+ publishVideo: (typeof properties.publishVideo !== 'undefined') ? properties.publishVideo : true,
+ resolution: this.isMediaStreamTrack(properties.videoSource) ? undefined : ((typeof properties.resolution !== 'undefined') ? properties.resolution : '640x480'),
+ videoSource: (typeof properties.videoSource !== 'undefined') ? properties.videoSource : undefined
+ };
+ }
+ else {
+ properties = {
+ insertMode: VideoInsertMode_1.VideoInsertMode.APPEND,
+ mirror: true,
+ publishAudio: true,
+ publishVideo: true,
+ resolution: '640x480'
+ };
+ }
+ var publisher = new Publisher_1.Publisher(targetElement, properties, this);
+ var completionHandler;
+ if (!!param2 && (typeof param2 === 'function')) {
+ completionHandler = param2;
+ }
+ else if (!!param3) {
+ completionHandler = param3;
+ }
+ publisher.initialize()
+ .then(function () {
+ if (completionHandler !== undefined) {
+ completionHandler(undefined);
+ }
+ publisher.emitEvent('accessAllowed', []);
+ }).catch(function (error) {
+ if (completionHandler !== undefined) {
+ completionHandler(error);
+ }
+ publisher.emitEvent('accessDenied', []);
+ });
+ this.publishers.push(publisher);
+ return publisher;
+ };
+ OpenVidu.prototype.initPublisherAsync = function (targetElement, properties) {
+ var _this = this;
+ return new Promise(function (resolve, reject) {
+ var publisher;
+ var callback = function (error) {
+ if (!!error) {
+ reject(error);
+ }
+ else {
+ resolve(publisher);
+ }
+ };
+ if (!!properties) {
+ publisher = _this.initPublisher(targetElement, properties, callback);
+ }
+ else {
+ publisher = _this.initPublisher(targetElement, callback);
+ }
+ });
+ };
+ OpenVidu.prototype.initLocalRecorder = function (stream) {
+ return new LocalRecorder_1.LocalRecorder(stream);
+ };
+ OpenVidu.prototype.checkSystemRequirements = function () {
+ var browser = platform.name;
+ var version = platform.version;
+ if ((browser !== 'Chrome') && (browser !== 'Chrome Mobile') &&
+ (browser !== 'Firefox') && (browser !== 'Firefox Mobile') && (browser !== 'Firefox for iOS') &&
+ (browser !== 'Opera') && (browser !== 'Opera Mobile') &&
+ (browser !== 'Safari')) {
+ return 0;
+ }
+ else {
+ return 1;
+ }
+ };
+ OpenVidu.prototype.getDevices = function () {
+ return new Promise(function (resolve, reject) {
+ navigator.mediaDevices.enumerateDevices().then(function (deviceInfos) {
+ var devices = [];
+ deviceInfos.forEach(function (deviceInfo) {
+ if (deviceInfo.kind === 'audioinput' || deviceInfo.kind === 'videoinput') {
+ devices.push({
+ kind: deviceInfo.kind,
+ deviceId: deviceInfo.deviceId,
+ label: deviceInfo.label
+ });
+ }
+ });
+ resolve(devices);
+ }).catch(function (error) {
+ console.error('Error getting devices', error);
+ reject(error);
+ });
+ });
+ };
+ OpenVidu.prototype.getUserMedia = function (options) {
+ var _this = this;
+ return new Promise(function (resolve, reject) {
+ _this.generateMediaConstraints(options)
+ .then(function (constraints) {
+ navigator.mediaDevices.getUserMedia(constraints)
+ .then(function (mediaStream) {
+ resolve(mediaStream);
+ })
+ .catch(function (error) {
+ var errorName;
+ var errorMessage = error.toString();
+ if (!(options.videoSource === 'screen')) {
+ errorName = OpenViduError_1.OpenViduErrorName.DEVICE_ACCESS_DENIED;
+ }
+ else {
+ errorName = OpenViduError_1.OpenViduErrorName.SCREEN_CAPTURE_DENIED;
+ }
+ reject(new OpenViduError_1.OpenViduError(errorName, errorMessage));
+ });
+ })
+ .catch(function (error) {
+ reject(error);
+ });
+ });
+ };
+ OpenVidu.prototype.enableProdMode = function () {
+ console.log = function () { };
+ console.debug = function () { };
+ console.info = function () { };
+ console.warn = function () { };
+ };
+ OpenVidu.prototype.setAdvancedConfiguration = function (configuration) {
+ this.advancedConfiguration = configuration;
+ };
+ OpenVidu.prototype.generateMediaConstraints = function (publisherProperties) {
+ var _this = this;
+ return new Promise(function (resolve, reject) {
+ var audio, video;
+ if (publisherProperties.audioSource === null || publisherProperties.audioSource === false) {
+ audio = false;
+ }
+ else if (publisherProperties.audioSource === undefined) {
+ audio = true;
+ }
+ else {
+ audio = publisherProperties.audioSource;
+ }
+ if (publisherProperties.videoSource === null || publisherProperties.videoSource === false) {
+ video = false;
+ }
+ else {
+ video = {
+ height: {
+ ideal: 480
+ },
+ width: {
+ ideal: 640
+ }
+ };
+ }
+ var mediaConstraints = {
+ audio: audio,
+ video: video
+ };
+ if (typeof mediaConstraints.audio === 'string') {
+ mediaConstraints.audio = { deviceId: { exact: mediaConstraints.audio } };
+ }
+ if (mediaConstraints.video) {
+ if (!!publisherProperties.resolution) {
+ var widthAndHeight = publisherProperties.resolution.toLowerCase().split('x');
+ var width = Number(widthAndHeight[0]);
+ var height = Number(widthAndHeight[1]);
+ mediaConstraints.video.width.ideal = width;
+ mediaConstraints.video.height.ideal = height;
+ }
+ if (!!publisherProperties.frameRate) {
+ mediaConstraints.video.frameRate = { ideal: publisherProperties.frameRate };
+ }
+ if (!!publisherProperties.videoSource && typeof publisherProperties.videoSource === 'string') {
+ if (publisherProperties.videoSource === 'screen') {
+ if (platform.name !== 'Chrome' && platform.name.indexOf('Firefox') === -1) {
+ var error = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_SHARING_NOT_SUPPORTED, 'You can only screen share in desktop Chrome and Firefox. Detected browser: ' + platform.name);
+ console.error(error);
+ reject(error);
+ }
+ else {
+ if (!!_this.advancedConfiguration.screenShareChromeExtension && !(platform.name.indexOf('Firefox') !== -1)) {
+ screenSharing.getScreenConstraints(function (error, screenConstraints) {
+ if (!!error || !!screenConstraints.mandatory && screenConstraints.mandatory.chromeMediaSource === 'screen') {
+ if (error === 'permission-denied' || error === 'PermissionDeniedError') {
+ var error_1 = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_CAPTURE_DENIED, 'You must allow access to one window of your desktop');
+ console.error(error_1);
+ reject(error_1);
+ }
+ else {
+ var extensionId = _this.advancedConfiguration.screenShareChromeExtension.split('/').pop().trim();
+ screenSharing.getChromeExtensionStatus(extensionId, function (status) {
+ if (status === 'installed-disabled') {
+ var error_2 = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_EXTENSION_DISABLED, 'You must enable the screen extension');
+ console.error(error_2);
+ reject(error_2);
+ }
+ if (status === 'not-installed') {
+ var error_3 = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_EXTENSION_NOT_INSTALLED, _this.advancedConfiguration.screenShareChromeExtension);
+ console.error(error_3);
+ reject(error_3);
+ }
+ });
+ }
+ }
+ else {
+ mediaConstraints.video = screenConstraints;
+ resolve(mediaConstraints);
+ }
+ });
+ }
+ else {
+ screenSharingAuto.getScreenId(function (error, sourceId, screenConstraints) {
+ if (!!error) {
+ if (error === 'not-installed') {
+ var extensionUrl = !!_this.advancedConfiguration.screenShareChromeExtension ? _this.advancedConfiguration.screenShareChromeExtension :
+ 'https://chrome.google.com/webstore/detail/openvidu-screensharing/lfcgfepafnobdloecchnfaclibenjold';
+ var error_4 = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_EXTENSION_NOT_INSTALLED, extensionUrl);
+ console.error(error_4);
+ reject(error_4);
+ }
+ else if (error === 'installed-disabled') {
+ var error_5 = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_EXTENSION_DISABLED, 'You must enable the screen extension');
+ console.error(error_5);
+ reject(error_5);
+ }
+ else if (error === 'permission-denied') {
+ var error_6 = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_CAPTURE_DENIED, 'You must allow access to one window of your desktop');
+ console.error(error_6);
+ reject(error_6);
+ }
+ }
+ else {
+ mediaConstraints.video = screenConstraints.video;
+ resolve(mediaConstraints);
+ }
+ });
+ }
+ publisherProperties.videoSource = 'screen';
+ }
+ }
+ else {
+ mediaConstraints.video['deviceId'] = { exact: publisherProperties.videoSource };
+ resolve(mediaConstraints);
+ }
+ }
+ else {
+ resolve(mediaConstraints);
+ }
+ }
+ else {
+ resolve(mediaConstraints);
+ }
+ });
+ };
+ OpenVidu.prototype.startWs = function (onConnectSucces) {
+ var config = {
+ heartbeat: 5000,
+ sendCloseMessage: false,
+ ws: {
+ uri: this.wsUri,
+ useSockJS: false,
+ onconnected: onConnectSucces,
+ ondisconnect: this.disconnectCallback.bind(this),
+ onreconnecting: this.reconnectingCallback.bind(this),
+ onreconnected: this.reconnectedCallback.bind(this)
+ },
+ rpc: {
+ requestTimeout: 10000,
+ participantJoined: this.session.onParticipantJoined.bind(this.session),
+ participantPublished: this.session.onParticipantPublished.bind(this.session),
+ participantUnpublished: this.session.onParticipantUnpublished.bind(this.session),
+ participantLeft: this.session.onParticipantLeft.bind(this.session),
+ participantEvicted: this.session.onParticipantEvicted.bind(this.session),
+ recordingStarted: this.session.onRecordingStarted.bind(this.session),
+ recordingStopped: this.session.onRecordingStopped.bind(this.session),
+ sendMessage: this.session.onNewMessage.bind(this.session),
+ streamPropertyChanged: this.session.onStreamPropertyChanged.bind(this.session),
+ iceCandidate: this.session.recvIceCandidate.bind(this.session),
+ mediaError: this.session.onMediaError.bind(this.session)
+ }
+ };
+ this.jsonRpcClient = new RpcBuilder.clients.JsonRpcClient(config);
+ };
+ OpenVidu.prototype.closeWs = function () {
+ this.jsonRpcClient.close();
+ };
+ OpenVidu.prototype.sendRequest = function (method, params, callback) {
+ if (params && params instanceof Function) {
+ callback = params;
+ params = {};
+ }
+ console.debug('Sending request: {method:"' + method + '", params: ' + JSON.stringify(params) + '}');
+ this.jsonRpcClient.send(method, params, callback);
+ };
+ OpenVidu.prototype.isMediaStreamTrack = function (mediaSource) {
+ var is = (!!mediaSource &&
+ mediaSource.enabled !== undefined && typeof mediaSource.enabled === 'boolean' &&
+ mediaSource.id !== undefined && typeof mediaSource.id === 'string' &&
+ mediaSource.kind !== undefined && typeof mediaSource.kind === 'string' &&
+ mediaSource.label !== undefined && typeof mediaSource.label === 'string' &&
+ mediaSource.muted !== undefined && typeof mediaSource.muted === 'boolean' &&
+ mediaSource.readyState !== undefined && typeof mediaSource.readyState === 'string');
+ return is;
+ };
+ OpenVidu.prototype.getWsUri = function () {
+ return this.wsUri;
+ };
+ OpenVidu.prototype.getSecret = function () {
+ return this.secret;
+ };
+ OpenVidu.prototype.getRecorder = function () {
+ return this.recorder;
+ };
+ OpenVidu.prototype.disconnectCallback = function () {
+ console.warn('Websocket connection lost');
+ if (this.isRoomAvailable()) {
+ this.session.onLostConnection();
+ }
+ else {
+ alert('Connection error. Please reload page.');
+ }
+ };
+ OpenVidu.prototype.reconnectingCallback = function () {
+ console.warn('Websocket connection lost (reconnecting)');
+ if (this.isRoomAvailable()) {
+ this.session.onLostConnection();
+ }
+ else {
+ alert('Connection error. Please reload page.');
+ }
+ };
+ OpenVidu.prototype.reconnectedCallback = function () {
+ console.warn('Websocket reconnected');
+ if (this.isRoomAvailable()) {
+ this.session.onRecoveredConnection();
+ }
+ else {
+ alert('Connection error. Please reload page.');
+ }
+ };
+ OpenVidu.prototype.isRoomAvailable = function () {
+ if (this.session !== undefined && this.session instanceof Session_1.Session) {
+ return true;
+ }
+ else {
+ console.warn('Session instance not found');
+ return false;
+ }
+ };
+ return OpenVidu;
+}());
+exports.OpenVidu = OpenVidu;
+
+},{"../OpenViduInternal/Enums/OpenViduError":26,"../OpenViduInternal/Enums/VideoInsertMode":27,"../OpenViduInternal/Events/StreamPropertyChangedEvent":36,"../OpenViduInternal/KurentoUtils/kurento-jsonrpc":43,"../OpenViduInternal/ScreenSharing/Screen-Capturing":48,"../OpenViduInternal/ScreenSharing/Screen-Capturing-Auto":47,"./LocalRecorder":18,"./Publisher":20,"./Session":21,"platform":8}],20:[function(require,module,exports){
+"use strict";
+var __extends = (this && this.__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 __());
+ };
+})();
+Object.defineProperty(exports, "__esModule", { value: true });
+var Session_1 = require("./Session");
+var Stream_1 = require("./Stream");
+var StreamManager_1 = require("./StreamManager");
+var StreamEvent_1 = require("../OpenViduInternal/Events/StreamEvent");
+var StreamPropertyChangedEvent_1 = require("../OpenViduInternal/Events/StreamPropertyChangedEvent");
+var VideoElementEvent_1 = require("../OpenViduInternal/Events/VideoElementEvent");
+var OpenViduError_1 = require("../OpenViduInternal/Enums/OpenViduError");
+var platform = require("platform");
+var Publisher = (function (_super) {
+ __extends(Publisher, _super);
+ function Publisher(targEl, properties, openvidu) {
+ var _this = _super.call(this, new Stream_1.Stream((!!openvidu.session) ? openvidu.session : new Session_1.Session(openvidu), { publisherProperties: properties, mediaConstraints: {} }), targEl) || this;
+ _this.accessAllowed = false;
+ _this.isSubscribedToRemote = false;
+ _this.accessDenied = false;
+ _this.properties = properties;
+ _this.openvidu = openvidu;
+ _this.stream.ee.on('local-stream-destroyed', function (reason) {
+ _this.stream.isLocalStreamPublished = false;
+ var streamEvent = new StreamEvent_1.StreamEvent(true, _this, 'streamDestroyed', _this.stream, reason);
+ _this.emitEvent('streamDestroyed', [streamEvent]);
+ streamEvent.callDefaultBehavior();
+ });
+ return _this;
+ }
+ Publisher.prototype.publishAudio = function (value) {
+ var _this = this;
+ if (this.stream.audioActive !== value) {
+ this.stream.getMediaStream().getAudioTracks().forEach(function (track) {
+ track.enabled = value;
+ });
+ this.session.openvidu.sendRequest('streamPropertyChanged', {
+ streamId: this.stream.streamId,
+ property: 'audioActive',
+ newValue: value,
+ reason: 'publishAudio'
+ }, function (error, response) {
+ if (error) {
+ console.error("Error sending 'streamPropertyChanged' event", error);
+ }
+ else {
+ _this.session.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent_1.StreamPropertyChangedEvent(_this.session, _this.stream, 'audioActive', value, !value, 'publishAudio')]);
+ _this.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent_1.StreamPropertyChangedEvent(_this, _this.stream, 'audioActive', value, !value, 'publishAudio')]);
+ }
+ });
+ this.stream.audioActive = value;
+ console.info("'Publisher' has " + (value ? 'published' : 'unpublished') + ' its audio stream');
+ }
+ };
+ Publisher.prototype.publishVideo = function (value) {
+ var _this = this;
+ if (this.stream.videoActive !== value) {
+ this.stream.getMediaStream().getVideoTracks().forEach(function (track) {
+ track.enabled = value;
+ });
+ this.session.openvidu.sendRequest('streamPropertyChanged', {
+ streamId: this.stream.streamId,
+ property: 'videoActive',
+ newValue: value,
+ reason: 'publishVideo'
+ }, function (error, response) {
+ if (error) {
+ console.error("Error sending 'streamPropertyChanged' event", error);
+ }
+ else {
+ _this.session.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent_1.StreamPropertyChangedEvent(_this.session, _this.stream, 'videoActive', value, !value, 'publishVideo')]);
+ _this.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent_1.StreamPropertyChangedEvent(_this, _this.stream, 'videoActive', value, !value, 'publishVideo')]);
+ }
+ });
+ this.stream.videoActive = value;
+ console.info("'Publisher' has " + (value ? 'published' : 'unpublished') + ' its video stream');
+ }
+ };
+ Publisher.prototype.subscribeToRemote = function (value) {
+ value = (value !== undefined) ? value : true;
+ this.isSubscribedToRemote = value;
+ this.stream.subscribeToMyRemote(value);
+ };
+ Publisher.prototype.on = function (type, handler) {
+ var _this = this;
+ _super.prototype.on.call(this, type, handler);
+ if (type === 'streamCreated') {
+ if (!!this.stream && this.stream.isLocalStreamPublished) {
+ this.emitEvent('streamCreated', [new StreamEvent_1.StreamEvent(false, this, 'streamCreated', this.stream, '')]);
+ }
+ else {
+ this.stream.ee.on('stream-created-by-publisher', function () {
+ _this.emitEvent('streamCreated', [new StreamEvent_1.StreamEvent(false, _this, 'streamCreated', _this.stream, '')]);
+ });
+ }
+ }
+ if (type === 'remoteVideoPlaying') {
+ if (this.stream.displayMyRemote() && this.videos[0] && this.videos[0].video &&
+ this.videos[0].video.currentTime > 0 &&
+ this.videos[0].video.paused === false &&
+ this.videos[0].video.ended === false &&
+ this.videos[0].video.readyState === 4) {
+ this.emitEvent('remoteVideoPlaying', [new VideoElementEvent_1.VideoElementEvent(this.videos[0].video, this, 'remoteVideoPlaying')]);
+ }
+ }
+ if (type === 'accessAllowed') {
+ if (this.accessAllowed) {
+ this.emitEvent('accessAllowed', []);
+ }
+ }
+ if (type === 'accessDenied') {
+ if (this.accessDenied) {
+ this.emitEvent('accessDenied', []);
+ }
+ }
+ return this;
+ };
+ Publisher.prototype.once = function (type, handler) {
+ var _this = this;
+ _super.prototype.once.call(this, type, handler);
+ if (type === 'streamCreated') {
+ if (!!this.stream && this.stream.isLocalStreamPublished) {
+ this.emitEvent('streamCreated', [new StreamEvent_1.StreamEvent(false, this, 'streamCreated', this.stream, '')]);
+ }
+ else {
+ this.stream.ee.once('stream-created-by-publisher', function () {
+ _this.emitEvent('streamCreated', [new StreamEvent_1.StreamEvent(false, _this, 'streamCreated', _this.stream, '')]);
+ });
+ }
+ }
+ if (type === 'remoteVideoPlaying') {
+ if (this.stream.displayMyRemote() && this.videos[0] && this.videos[0].video &&
+ this.videos[0].video.currentTime > 0 &&
+ this.videos[0].video.paused === false &&
+ this.videos[0].video.ended === false &&
+ this.videos[0].video.readyState === 4) {
+ this.emitEvent('remoteVideoPlaying', [new VideoElementEvent_1.VideoElementEvent(this.videos[0].video, this, 'remoteVideoPlaying')]);
+ }
+ }
+ if (type === 'accessAllowed') {
+ if (this.accessAllowed) {
+ this.emitEvent('accessAllowed', []);
+ }
+ }
+ if (type === 'accessDenied') {
+ if (this.accessDenied) {
+ this.emitEvent('accessDenied', []);
+ }
+ }
+ return this;
+ };
+ Publisher.prototype.initialize = function () {
+ var _this = this;
+ return new Promise(function (resolve, reject) {
+ var errorCallback = function (openViduError) {
+ _this.accessDenied = true;
+ _this.accessAllowed = false;
+ reject(openViduError);
+ };
+ var successCallback = function (mediaStream) {
+ _this.accessAllowed = true;
+ _this.accessDenied = false;
+ if (_this.openvidu.isMediaStreamTrack(_this.properties.audioSource)) {
+ mediaStream.removeTrack(mediaStream.getAudioTracks()[0]);
+ mediaStream.addTrack(_this.properties.audioSource);
+ }
+ if (_this.openvidu.isMediaStreamTrack(_this.properties.videoSource)) {
+ mediaStream.removeTrack(mediaStream.getVideoTracks()[0]);
+ mediaStream.addTrack(_this.properties.videoSource);
+ }
+ if (!!mediaStream.getAudioTracks()[0]) {
+ var enabled = (_this.stream.audioActive !== undefined && _this.stream.audioActive !== null) ? _this.stream.audioActive : !!_this.stream.outboundStreamOpts.publisherProperties.publishAudio;
+ mediaStream.getAudioTracks()[0].enabled = enabled;
+ }
+ if (!!mediaStream.getVideoTracks()[0]) {
+ var enabled = (_this.stream.videoActive !== undefined && _this.stream.videoActive !== null) ? _this.stream.videoActive : !!_this.stream.outboundStreamOpts.publisherProperties.publishVideo;
+ mediaStream.getVideoTracks()[0].enabled = enabled;
+ }
+ _this.videoReference = document.createElement('video');
+ _this.videoReference.srcObject = mediaStream;
+ _this.stream.setMediaStream(mediaStream);
+ if (!_this.stream.displayMyRemote()) {
+ _this.stream.updateMediaStreamInVideos();
+ }
+ if (!!_this.firstVideoElement) {
+ _this.createVideoElement(_this.firstVideoElement.targetElement, _this.properties.insertMode);
+ }
+ delete _this.firstVideoElement;
+ if (_this.stream.isSendVideo()) {
+ if (!_this.stream.isSendScreen()) {
+ var _a = mediaStream.getVideoTracks()[0].getSettings(), width = _a.width, height = _a.height;
+ if (platform.name.toLowerCase().indexOf('mobile') !== -1 && (window.innerHeight > window.innerWidth)) {
+ _this.stream.videoDimensions = {
+ width: height || 0,
+ height: width || 0
+ };
+ }
+ else {
+ _this.stream.videoDimensions = {
+ width: width || 0,
+ height: height || 0
+ };
+ }
+ _this.stream.isLocalStreamReadyToPublish = true;
+ _this.stream.ee.emitEvent('stream-ready-to-publish', []);
+ }
+ else {
+ _this.videoReference.onloadedmetadata = function () {
+ _this.stream.videoDimensions = {
+ width: _this.videoReference.videoWidth,
+ height: _this.videoReference.videoHeight
+ };
+ _this.screenShareResizeInterval = setInterval(function () {
+ var firefoxSettings = mediaStream.getVideoTracks()[0].getSettings();
+ var newWidth = (platform.name === 'Chrome') ? _this.videoReference.videoWidth : firefoxSettings.width;
+ var newHeight = (platform.name === 'Chrome') ? _this.videoReference.videoHeight : firefoxSettings.height;
+ if (_this.stream.isLocalStreamPublished &&
+ (newWidth !== _this.stream.videoDimensions.width ||
+ newHeight !== _this.stream.videoDimensions.height)) {
+ var oldValue_1 = { width: _this.stream.videoDimensions.width, height: _this.stream.videoDimensions.height };
+ _this.stream.videoDimensions = {
+ width: newWidth || 0,
+ height: newHeight || 0
+ };
+ _this.session.openvidu.sendRequest('streamPropertyChanged', {
+ streamId: _this.stream.streamId,
+ property: 'videoDimensions',
+ newValue: JSON.stringify(_this.stream.videoDimensions),
+ reason: 'screenResized'
+ }, function (error, response) {
+ if (error) {
+ console.error("Error sending 'streamPropertyChanged' event", error);
+ }
+ else {
+ _this.session.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent_1.StreamPropertyChangedEvent(_this.session, _this.stream, 'videoDimensions', _this.stream.videoDimensions, oldValue_1, 'screenResized')]);
+ _this.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent_1.StreamPropertyChangedEvent(_this, _this.stream, 'videoDimensions', _this.stream.videoDimensions, oldValue_1, 'screenResized')]);
+ }
+ });
+ }
+ }, 500);
+ _this.stream.isLocalStreamReadyToPublish = true;
+ _this.stream.ee.emitEvent('stream-ready-to-publish', []);
+ };
+ }
+ }
+ else {
+ _this.stream.isLocalStreamReadyToPublish = true;
+ _this.stream.ee.emitEvent('stream-ready-to-publish', []);
+ }
+ resolve();
+ };
+ _this.openvidu.generateMediaConstraints(_this.properties)
+ .then(function (constraints) {
+ var outboundStreamOptions = {
+ mediaConstraints: constraints,
+ publisherProperties: _this.properties
+ };
+ _this.stream.setOutboundStreamOptions(outboundStreamOptions);
+ var constraintsAux = {};
+ var timeForDialogEvent = 1250;
+ if (_this.stream.isSendVideo() || _this.stream.isSendAudio()) {
+ var definedAudioConstraint_1 = ((constraints.audio === undefined) ? true : constraints.audio);
+ constraintsAux.audio = _this.stream.isSendScreen() ? false : definedAudioConstraint_1;
+ constraintsAux.video = constraints.video;
+ var startTime_1 = Date.now();
+ _this.setPermissionDialogTimer(timeForDialogEvent);
+ navigator.mediaDevices.getUserMedia(constraintsAux)
+ .then(function (mediaStream) {
+ _this.clearPermissionDialogTimer(startTime_1, timeForDialogEvent);
+ if (_this.stream.isSendScreen() && _this.stream.isSendAudio()) {
+ constraintsAux.audio = definedAudioConstraint_1;
+ constraintsAux.video = false;
+ startTime_1 = Date.now();
+ _this.setPermissionDialogTimer(timeForDialogEvent);
+ navigator.mediaDevices.getUserMedia(constraintsAux)
+ .then(function (audioOnlyStream) {
+ _this.clearPermissionDialogTimer(startTime_1, timeForDialogEvent);
+ mediaStream.addTrack(audioOnlyStream.getAudioTracks()[0]);
+ successCallback(mediaStream);
+ })
+ .catch(function (error) {
+ _this.clearPermissionDialogTimer(startTime_1, timeForDialogEvent);
+ var errorName, errorMessage;
+ switch (error.name.toLowerCase()) {
+ case 'notfounderror':
+ errorName = OpenViduError_1.OpenViduErrorName.INPUT_AUDIO_DEVICE_NOT_FOUND;
+ errorMessage = error.toString();
+ errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage));
+ break;
+ case 'notallowederror':
+ errorName = OpenViduError_1.OpenViduErrorName.DEVICE_ACCESS_DENIED;
+ errorMessage = error.toString();
+ errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage));
+ break;
+ case 'overconstrainederror':
+ if (error.constraint.toLowerCase() === 'deviceid') {
+ errorName = OpenViduError_1.OpenViduErrorName.INPUT_AUDIO_DEVICE_NOT_FOUND;
+ errorMessage = "Audio input device with deviceId '" + constraints.video.deviceId.exact + "' not found";
+ }
+ else {
+ errorName = OpenViduError_1.OpenViduErrorName.PUBLISHER_PROPERTIES_ERROR;
+ errorMessage = "Audio input device doesn't support the value passed for constraint '" + error.constraint + "'";
+ }
+ errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage));
+ break;
+ }
+ });
+ }
+ else {
+ successCallback(mediaStream);
+ }
+ })
+ .catch(function (error) {
+ _this.clearPermissionDialogTimer(startTime_1, timeForDialogEvent);
+ var errorName, errorMessage;
+ switch (error.name.toLowerCase()) {
+ case 'notfounderror':
+ navigator.mediaDevices.getUserMedia({
+ audio: false,
+ video: constraints.video
+ })
+ .then(function (mediaStream) {
+ mediaStream.getVideoTracks().forEach(function (track) {
+ track.stop();
+ });
+ errorName = OpenViduError_1.OpenViduErrorName.INPUT_AUDIO_DEVICE_NOT_FOUND;
+ errorMessage = error.toString();
+ errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage));
+ }).catch(function (e) {
+ errorName = OpenViduError_1.OpenViduErrorName.INPUT_VIDEO_DEVICE_NOT_FOUND;
+ errorMessage = error.toString();
+ errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage));
+ });
+ break;
+ case 'notallowederror':
+ errorName = _this.stream.isSendScreen() ? OpenViduError_1.OpenViduErrorName.SCREEN_CAPTURE_DENIED : OpenViduError_1.OpenViduErrorName.DEVICE_ACCESS_DENIED;
+ errorMessage = error.toString();
+ errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage));
+ break;
+ case 'overconstrainederror':
+ navigator.mediaDevices.getUserMedia({
+ audio: false,
+ video: constraints.video
+ })
+ .then(function (mediaStream) {
+ mediaStream.getVideoTracks().forEach(function (track) {
+ track.stop();
+ });
+ if (error.constraint.toLowerCase() === 'deviceid') {
+ errorName = OpenViduError_1.OpenViduErrorName.INPUT_AUDIO_DEVICE_NOT_FOUND;
+ errorMessage = "Audio input device with deviceId '" + constraints.audio.deviceId.exact + "' not found";
+ }
+ else {
+ errorName = OpenViduError_1.OpenViduErrorName.PUBLISHER_PROPERTIES_ERROR;
+ errorMessage = "Audio input device doesn't support the value passed for constraint '" + error.constraint + "'";
+ }
+ errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage));
+ }).catch(function (e) {
+ if (error.constraint.toLowerCase() === 'deviceid') {
+ errorName = OpenViduError_1.OpenViduErrorName.INPUT_VIDEO_DEVICE_NOT_FOUND;
+ errorMessage = "Video input device with deviceId '" + constraints.video.deviceId.exact + "' not found";
+ }
+ else {
+ errorName = OpenViduError_1.OpenViduErrorName.PUBLISHER_PROPERTIES_ERROR;
+ errorMessage = "Video input device doesn't support the value passed for constraint '" + error.constraint + "'";
+ }
+ errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage));
+ });
+ break;
+ }
+ });
+ }
+ else {
+ reject(new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.NO_INPUT_SOURCE_SET, "Properties 'audioSource' and 'videoSource' cannot be set to false or null at the same time when calling 'OpenVidu.initPublisher'"));
+ }
+ })
+ .catch(function (error) {
+ errorCallback(error);
+ });
+ });
+ };
+ Publisher.prototype.reestablishStreamPlayingEvent = function () {
+ if (this.ee.getListeners('streamPlaying').length > 0) {
+ this.addPlayEventToFirstVideo();
+ }
+ };
+ Publisher.prototype.setPermissionDialogTimer = function (waitTime) {
+ var _this = this;
+ this.permissionDialogTimeout = setTimeout(function () {
+ _this.emitEvent('accessDialogOpened', []);
+ }, waitTime);
+ };
+ Publisher.prototype.clearPermissionDialogTimer = function (startTime, waitTime) {
+ clearTimeout(this.permissionDialogTimeout);
+ if ((Date.now() - startTime) > waitTime) {
+ this.emitEvent('accessDialogClosed', []);
+ }
+ };
+ return Publisher;
+}(StreamManager_1.StreamManager));
+exports.Publisher = Publisher;
+
+},{"../OpenViduInternal/Enums/OpenViduError":26,"../OpenViduInternal/Events/StreamEvent":34,"../OpenViduInternal/Events/StreamPropertyChangedEvent":36,"../OpenViduInternal/Events/VideoElementEvent":37,"./Session":21,"./Stream":22,"./StreamManager":23,"platform":8}],21:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+var Connection_1 = require("./Connection");
+var Subscriber_1 = require("./Subscriber");
+var ConnectionEvent_1 = require("../OpenViduInternal/Events/ConnectionEvent");
+var RecordingEvent_1 = require("../OpenViduInternal/Events/RecordingEvent");
+var SessionDisconnectedEvent_1 = require("../OpenViduInternal/Events/SessionDisconnectedEvent");
+var SignalEvent_1 = require("../OpenViduInternal/Events/SignalEvent");
+var StreamEvent_1 = require("../OpenViduInternal/Events/StreamEvent");
+var StreamPropertyChangedEvent_1 = require("../OpenViduInternal/Events/StreamPropertyChangedEvent");
+var OpenViduError_1 = require("../OpenViduInternal/Enums/OpenViduError");
+var VideoInsertMode_1 = require("../OpenViduInternal/Enums/VideoInsertMode");
+var platform = require("platform");
+var EventEmitter = require("wolfy87-eventemitter");
+var Session = (function () {
+ function Session(openvidu) {
+ this.streamManagers = [];
+ this.remoteStreamsCreated = {};
+ this.remoteConnections = {};
+ this.speakingEventsEnabled = false;
+ this.ee = new EventEmitter();
+ this.openvidu = openvidu;
+ }
+ Session.prototype.connect = function (token, metadata) {
+ var _this = this;
+ return new Promise(function (resolve, reject) {
+ _this.processToken(token);
+ if (_this.openvidu.checkSystemRequirements()) {
+ _this.options = {
+ sessionId: _this.sessionId,
+ participantId: token,
+ metadata: !!metadata ? _this.stringClientMetadata(metadata) : ''
+ };
+ _this.connectAux(token).then(function () {
+ resolve();
+ }).catch(function (error) {
+ reject(error);
+ });
+ }
+ else {
+ reject(new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.BROWSER_NOT_SUPPORTED, 'Browser ' + platform.name + ' ' + platform.version + ' is not supported in OpenVidu'));
+ }
+ });
+ };
+ Session.prototype.disconnect = function () {
+ this.leave(false, 'disconnect');
+ };
+ Session.prototype.subscribe = function (stream, targetElement, param3, param4) {
+ var properties = {};
+ if (!!param3 && typeof param3 !== 'function') {
+ properties = {
+ insertMode: (typeof param3.insertMode !== 'undefined') ? ((typeof param3.insertMode === 'string') ? VideoInsertMode_1.VideoInsertMode[param3.insertMode] : properties.insertMode) : VideoInsertMode_1.VideoInsertMode.APPEND,
+ subscribeToAudio: (typeof param3.subscribeToAudio !== 'undefined') ? param3.subscribeToAudio : true,
+ subscribeToVideo: (typeof param3.subscribeToVideo !== 'undefined') ? param3.subscribeToVideo : true
+ };
+ }
+ else {
+ properties = {
+ insertMode: VideoInsertMode_1.VideoInsertMode.APPEND,
+ subscribeToAudio: true,
+ subscribeToVideo: true
+ };
+ }
+ var completionHandler;
+ if (!!param3 && (typeof param3 === 'function')) {
+ completionHandler = param3;
+ }
+ else if (!!param4) {
+ completionHandler = param4;
+ }
+ console.info('Subscribing to ' + stream.connection.connectionId);
+ stream.subscribe()
+ .then(function () {
+ console.info('Subscribed correctly to ' + stream.connection.connectionId);
+ if (completionHandler !== undefined) {
+ completionHandler(undefined);
+ }
+ })
+ .catch(function (error) {
+ if (completionHandler !== undefined) {
+ completionHandler(error);
+ }
+ });
+ var subscriber = new Subscriber_1.Subscriber(stream, targetElement, properties);
+ if (!!subscriber.targetElement) {
+ stream.streamManager.createVideoElement(subscriber.targetElement, properties.insertMode);
+ }
+ return subscriber;
+ };
+ Session.prototype.subscribeAsync = function (stream, targetElement, properties) {
+ var _this = this;
+ return new Promise(function (resolve, reject) {
+ var subscriber;
+ var callback = function (error) {
+ if (!!error) {
+ reject(error);
+ }
+ else {
+ resolve(subscriber);
+ }
+ };
+ if (!!properties) {
+ subscriber = _this.subscribe(stream, targetElement, properties, callback);
+ }
+ else {
+ subscriber = _this.subscribe(stream, targetElement, callback);
+ }
+ });
+ };
+ Session.prototype.unsubscribe = function (subscriber) {
+ var connectionId = subscriber.stream.connection.connectionId;
+ console.info('Unsubscribing from ' + connectionId);
+ this.openvidu.sendRequest('unsubscribeFromVideo', { sender: subscriber.stream.connection.connectionId }, function (error, response) {
+ if (error) {
+ console.error('Error unsubscribing from ' + connectionId, error);
+ }
+ else {
+ console.info('Unsubscribed correctly from ' + connectionId);
+ }
+ subscriber.stream.disposeWebRtcPeer();
+ subscriber.stream.disposeMediaStream();
+ });
+ subscriber.stream.streamManager.removeAllVideos();
+ };
+ Session.prototype.publish = function (publisher) {
+ var _this = this;
+ return new Promise(function (resolve, reject) {
+ publisher.session = _this;
+ publisher.stream.session = _this;
+ if (!publisher.stream.publishedOnce) {
+ _this.connection.addStream(publisher.stream);
+ publisher.stream.publish()
+ .then(function () {
+ resolve();
+ })
+ .catch(function (error) {
+ reject(error);
+ });
+ }
+ else {
+ publisher.initialize()
+ .then(function () {
+ _this.connection.addStream(publisher.stream);
+ publisher.reestablishStreamPlayingEvent();
+ publisher.stream.publish()
+ .then(function () {
+ resolve();
+ })
+ .catch(function (error) {
+ reject(error);
+ });
+ }).catch(function (error) {
+ reject(error);
+ });
+ }
+ });
+ };
+ Session.prototype.unpublish = function (publisher) {
+ var stream = publisher.stream;
+ if (!stream.connection) {
+ console.error('The associated Connection object of this Publisher is null', stream);
+ return;
+ }
+ else if (stream.connection !== this.connection) {
+ console.error('The associated Connection object of this Publisher is not your local Connection.' +
+ "Only moderators can force unpublish on remote Streams via 'forceUnpublish' method", stream);
+ return;
+ }
+ else {
+ console.info('Unpublishing local media (' + stream.connection.connectionId + ')');
+ this.openvidu.sendRequest('unpublishVideo', function (error, response) {
+ if (error) {
+ console.error(error);
+ }
+ else {
+ console.info('Media unpublished correctly');
+ }
+ });
+ stream.disposeWebRtcPeer();
+ delete stream.connection.stream;
+ var streamEvent = new StreamEvent_1.StreamEvent(true, publisher, 'streamDestroyed', publisher.stream, 'unpublish');
+ publisher.emitEvent('streamDestroyed', [streamEvent]);
+ streamEvent.callDefaultBehavior();
+ }
+ };
+ Session.prototype.forceDisconnect = function (connection) {
+ var _this = this;
+ return new Promise(function (resolve, reject) {
+ console.info('Forcing disconnect for connection ' + connection.connectionId);
+ _this.openvidu.sendRequest('forceDisconnect', { connectionId: connection.connectionId }, function (error, response) {
+ if (error) {
+ console.error('Error forcing disconnect for Connection ' + connection.connectionId, error);
+ if (error.code === 401) {
+ reject(new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.OPENVIDU_PERMISSION_DENIED, "You don't have permissions to force a disconnection"));
+ }
+ else {
+ reject(error);
+ }
+ }
+ else {
+ console.info('Forcing disconnect correctly for Connection ' + connection.connectionId);
+ resolve();
+ }
+ });
+ });
+ };
+ Session.prototype.forceUnpublish = function (stream) {
+ var _this = this;
+ return new Promise(function (resolve, reject) {
+ console.info('Forcing unpublish for stream ' + stream.streamId);
+ _this.openvidu.sendRequest('forceUnpublish', { streamId: stream.streamId }, function (error, response) {
+ if (error) {
+ console.error('Error forcing unpublish for Stream ' + stream.streamId, error);
+ if (error.code === 401) {
+ reject(new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.OPENVIDU_PERMISSION_DENIED, "You don't have permissions to force an unpublishing"));
+ }
+ else {
+ reject(error);
+ }
+ }
+ else {
+ console.info('Forcing unpublish correctly for Stream ' + stream.streamId);
+ resolve();
+ }
+ });
+ });
+ };
+ Session.prototype.signal = function (signal) {
+ var _this = this;
+ return new Promise(function (resolve, reject) {
+ var signalMessage = {};
+ if (signal.to && signal.to.length > 0) {
+ var connectionIds_1 = [];
+ signal.to.forEach(function (connection) {
+ connectionIds_1.push(connection.connectionId);
+ });
+ signalMessage['to'] = connectionIds_1;
+ }
+ else {
+ signalMessage['to'] = [];
+ }
+ signalMessage['data'] = signal.data ? signal.data : '';
+ signalMessage['type'] = signal.type ? signal.type : '';
+ _this.openvidu.sendRequest('sendMessage', {
+ message: JSON.stringify(signalMessage)
+ }, function (error, response) {
+ if (!!error) {
+ reject(error);
+ }
+ else {
+ resolve();
+ }
+ });
+ });
+ };
+ Session.prototype.on = function (type, handler) {
+ this.ee.on(type, function (event) {
+ if (event) {
+ console.info("Event '" + type + "' triggered by 'Session'", event);
+ }
+ else {
+ console.info("Event '" + type + "' triggered by 'Session'");
+ }
+ handler(event);
+ });
+ if (type === 'publisherStartSpeaking' || type === 'publisherStopSpeaking') {
+ this.speakingEventsEnabled = true;
+ for (var connectionId in this.remoteConnections) {
+ var str = this.remoteConnections[connectionId].stream;
+ if (!!str && !str.speechEvent && str.hasAudio) {
+ str.enableSpeakingEvents();
+ }
+ }
+ }
+ return this;
+ };
+ Session.prototype.once = function (type, handler) {
+ this.ee.once(type, function (event) {
+ if (event) {
+ console.info("Event '" + type + "' triggered by 'Session'", event);
+ }
+ else {
+ console.info("Event '" + type + "' triggered by 'Session'");
+ }
+ handler(event);
+ });
+ if (type === 'publisherStartSpeaking' || type === 'publisherStopSpeaking') {
+ this.speakingEventsEnabled = true;
+ for (var connectionId in this.remoteConnections) {
+ var str = this.remoteConnections[connectionId].stream;
+ if (!!str && !str.speechEvent && str.hasAudio) {
+ str.enableOnceSpeakingEvents();
+ }
+ }
+ }
+ return this;
+ };
+ Session.prototype.off = function (type, handler) {
+ if (!handler) {
+ this.ee.removeAllListeners(type);
+ }
+ else {
+ this.ee.off(type, handler);
+ }
+ if (type === 'publisherStartSpeaking' || type === 'publisherStopSpeaking') {
+ this.speakingEventsEnabled = false;
+ for (var connectionId in this.remoteConnections) {
+ var str = this.remoteConnections[connectionId].stream;
+ if (!!str && !!str.speechEvent) {
+ str.disableSpeakingEvents();
+ }
+ }
+ }
+ return this;
+ };
+ Session.prototype.onParticipantJoined = function (response) {
+ var _this = this;
+ this.getConnection(response.id, '')
+ .then(function (connection) {
+ console.warn('Connection ' + response.id + ' already exists in connections list');
+ })
+ .catch(function (openViduError) {
+ var connection = new Connection_1.Connection(_this, response);
+ _this.remoteConnections[response.id] = connection;
+ _this.ee.emitEvent('connectionCreated', [new ConnectionEvent_1.ConnectionEvent(false, _this, 'connectionCreated', connection, '')]);
+ });
+ };
+ Session.prototype.onParticipantLeft = function (msg) {
+ var _this = this;
+ this.getRemoteConnection(msg.connectionId, 'Remote connection ' + msg.connectionId + " unknown when 'onParticipantLeft'. " +
+ 'Existing remote connections: ' + JSON.stringify(Object.keys(this.remoteConnections)))
+ .then(function (connection) {
+ if (!!connection.stream) {
+ var stream = connection.stream;
+ var streamEvent = new StreamEvent_1.StreamEvent(true, _this, 'streamDestroyed', stream, msg.reason);
+ _this.ee.emitEvent('streamDestroyed', [streamEvent]);
+ streamEvent.callDefaultBehavior();
+ delete _this.remoteStreamsCreated[stream.streamId];
+ }
+ delete _this.remoteConnections[connection.connectionId];
+ _this.ee.emitEvent('connectionDestroyed', [new ConnectionEvent_1.ConnectionEvent(false, _this, 'connectionDestroyed', connection, msg.reason)]);
+ })
+ .catch(function (openViduError) {
+ console.error(openViduError);
+ });
+ };
+ Session.prototype.onParticipantPublished = function (response) {
+ var _this = this;
+ var afterConnectionFound = function (connection) {
+ _this.remoteConnections[connection.connectionId] = connection;
+ if (!_this.remoteStreamsCreated[connection.stream.streamId]) {
+ _this.ee.emitEvent('streamCreated', [new StreamEvent_1.StreamEvent(false, _this, 'streamCreated', connection.stream, '')]);
+ }
+ _this.remoteStreamsCreated[connection.stream.streamId] = true;
+ };
+ var connection;
+ this.getRemoteConnection(response.id, "Remote connection '" + response.id + "' unknown when 'onParticipantPublished'. " +
+ 'Existing remote connections: ' + JSON.stringify(Object.keys(this.remoteConnections)))
+ .then(function (con) {
+ connection = con;
+ response.metadata = con.data;
+ connection.options = response;
+ connection.initRemoteStreams(response.streams);
+ afterConnectionFound(connection);
+ })
+ .catch(function (openViduError) {
+ connection = new Connection_1.Connection(_this, response);
+ afterConnectionFound(connection);
+ });
+ };
+ Session.prototype.onParticipantUnpublished = function (msg) {
+ var _this = this;
+ if (msg.connectionId === this.connection.connectionId) {
+ this.stopPublisherStream(msg.reason);
+ }
+ else {
+ this.getRemoteConnection(msg.connectionId, "Remote connection '" + msg.connectionId + "' unknown when 'onParticipantUnpublished'. " +
+ 'Existing remote connections: ' + JSON.stringify(Object.keys(this.remoteConnections)))
+ .then(function (connection) {
+ var streamEvent = new StreamEvent_1.StreamEvent(true, _this, 'streamDestroyed', connection.stream, msg.reason);
+ _this.ee.emitEvent('streamDestroyed', [streamEvent]);
+ streamEvent.callDefaultBehavior();
+ var streamId = connection.stream.streamId;
+ delete _this.remoteStreamsCreated[streamId];
+ connection.removeStream(streamId);
+ })
+ .catch(function (openViduError) {
+ console.error(openViduError);
+ });
+ }
+ };
+ Session.prototype.onParticipantEvicted = function (msg) {
+ if (msg.connectionId === this.connection.connectionId) {
+ if (!!this.sessionId && !this.connection.disposed) {
+ this.leave(true, msg.reason);
+ }
+ }
+ };
+ Session.prototype.onNewMessage = function (msg) {
+ var _this = this;
+ console.info('New signal: ' + JSON.stringify(msg));
+ this.getConnection(msg.from, "Connection '" + msg.from + "' unknow when 'onNewMessage'. Existing remote connections: "
+ + JSON.stringify(Object.keys(this.remoteConnections)) + '. Existing local connection: ' + this.connection.connectionId)
+ .then(function (connection) {
+ _this.ee.emitEvent('signal', [new SignalEvent_1.SignalEvent(_this, msg.type, msg.data, connection)]);
+ _this.ee.emitEvent('signal:' + msg.type, [new SignalEvent_1.SignalEvent(_this, msg.type, msg.data, connection)]);
+ })
+ .catch(function (openViduError) {
+ console.error(openViduError);
+ });
+ };
+ Session.prototype.onStreamPropertyChanged = function (msg) {
+ var _this = this;
+ this.getRemoteConnection(msg.connectionId, 'Remote connection ' + msg.connectionId + " unknown when 'onStreamPropertyChanged'. " +
+ 'Existing remote connections: ' + JSON.stringify(Object.keys(this.remoteConnections)))
+ .then(function (connection) {
+ if (!!connection.stream && connection.stream.streamId === msg.streamId) {
+ var stream = connection.stream;
+ var oldValue = void 0;
+ switch (msg.property) {
+ case 'audioActive':
+ oldValue = stream.audioActive;
+ msg.newValue = msg.newValue === 'true';
+ stream.audioActive = msg.newValue;
+ break;
+ case 'videoActive':
+ oldValue = stream.videoActive;
+ msg.newValue = msg.newValue === 'true';
+ stream.videoActive = msg.newValue;
+ break;
+ case 'videoDimensions':
+ oldValue = stream.videoDimensions;
+ msg.newValue = JSON.parse(JSON.parse(msg.newValue));
+ stream.videoDimensions = msg.newValue;
+ break;
+ }
+ _this.ee.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent_1.StreamPropertyChangedEvent(_this, stream, msg.property, msg.newValue, oldValue, msg.reason)]);
+ stream.streamManager.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent_1.StreamPropertyChangedEvent(stream.streamManager, stream, msg.property, msg.newValue, oldValue, msg.reason)]);
+ }
+ else {
+ console.error("No stream with streamId '" + msg.streamId + "' found for connection '" + msg.connectionId + "' on 'streamPropertyChanged' event");
+ }
+ })
+ .catch(function (openViduError) {
+ console.error(openViduError);
+ });
+ };
+ Session.prototype.recvIceCandidate = function (msg) {
+ var candidate = {
+ candidate: msg.candidate,
+ sdpMid: msg.sdpMid,
+ sdpMLineIndex: msg.sdpMLineIndex,
+ toJSON: function () {
+ return { candidate: msg.candidate };
+ }
+ };
+ this.getConnection(msg.endpointName, 'Connection not found for endpoint ' + msg.endpointName + '. Ice candidate will be ignored: ' + candidate)
+ .then(function (connection) {
+ var stream = connection.stream;
+ stream.getWebRtcPeer().addIceCandidate(candidate).catch(function (error) {
+ console.error('Error adding candidate for ' + stream.streamId
+ + ' stream of endpoint ' + msg.endpointName + ': ' + error);
+ });
+ })
+ .catch(function (openViduError) {
+ console.error(openViduError);
+ });
+ };
+ Session.prototype.onSessionClosed = function (msg) {
+ console.info('Session closed: ' + JSON.stringify(msg));
+ var s = msg.sessionId;
+ if (s !== undefined) {
+ this.ee.emitEvent('session-closed', [{
+ session: s
+ }]);
+ }
+ else {
+ console.warn('Session undefined on session closed', msg);
+ }
+ };
+ Session.prototype.onLostConnection = function () {
+ console.warn('Lost connection in Session ' + this.sessionId);
+ if (!!this.sessionId && !this.connection.disposed) {
+ this.leave(true, 'networkDisconnect');
+ }
+ };
+ Session.prototype.onRecoveredConnection = function () {
+ console.warn('Recovered connection in Session ' + this.sessionId);
+ this.ee.emitEvent('connectionRecovered', []);
+ };
+ Session.prototype.onMediaError = function (params) {
+ console.error('Media error: ' + JSON.stringify(params));
+ var err = params.error;
+ if (err) {
+ this.ee.emitEvent('error-media', [{
+ error: err
+ }]);
+ }
+ else {
+ console.warn('Received undefined media error. Params:', params);
+ }
+ };
+ Session.prototype.onRecordingStarted = function (response) {
+ this.ee.emitEvent('recordingStarted', [new RecordingEvent_1.RecordingEvent(this, 'recordingStarted', response.id, response.name)]);
+ };
+ Session.prototype.onRecordingStopped = function (response) {
+ this.ee.emitEvent('recordingStopped', [new RecordingEvent_1.RecordingEvent(this, 'recordingStopped', response.id, response.name)]);
+ };
+ Session.prototype.emitEvent = function (type, eventArray) {
+ this.ee.emitEvent(type, eventArray);
+ };
+ Session.prototype.leave = function (forced, reason) {
+ var _this = this;
+ forced = !!forced;
+ console.info('Leaving Session (forced=' + forced + ')');
+ if (!!this.connection) {
+ if (!this.connection.disposed && !forced) {
+ this.openvidu.sendRequest('leaveRoom', function (error, response) {
+ if (error) {
+ console.error(error);
+ }
+ _this.openvidu.closeWs();
+ });
+ }
+ else {
+ this.openvidu.closeWs();
+ }
+ this.stopPublisherStream(reason);
+ if (!this.connection.disposed) {
+ var sessionDisconnectEvent = new SessionDisconnectedEvent_1.SessionDisconnectedEvent(this, reason);
+ this.ee.emitEvent('sessionDisconnected', [sessionDisconnectEvent]);
+ sessionDisconnectEvent.callDefaultBehavior();
+ }
+ }
+ else {
+ console.warn('You were not connected to the session ' + this.sessionId);
+ }
+ };
+ Session.prototype.connectAux = function (token) {
+ var _this = this;
+ return new Promise(function (resolve, reject) {
+ _this.openvidu.startWs(function (error) {
+ if (!!error) {
+ reject(error);
+ }
+ else {
+ var joinParams = {
+ token: (!!token) ? token : '',
+ session: _this.sessionId,
+ metadata: !!_this.options.metadata ? _this.options.metadata : '',
+ secret: _this.openvidu.getSecret(),
+ recorder: _this.openvidu.getRecorder(),
+ };
+ _this.openvidu.sendRequest('joinRoom', joinParams, function (error, response) {
+ if (!!error) {
+ reject(error);
+ }
+ else {
+ _this.capabilities = {
+ subscribe: true,
+ publish: _this.openvidu.role !== 'SUBSCRIBER',
+ forceUnpublish: _this.openvidu.role === 'MODERATOR',
+ forceDisconnect: _this.openvidu.role === 'MODERATOR'
+ };
+ _this.connection = new Connection_1.Connection(_this);
+ _this.connection.connectionId = response.id;
+ _this.connection.data = response.metadata;
+ var events_1 = {
+ connections: new Array(),
+ streams: new Array()
+ };
+ var existingParticipants = response.value;
+ existingParticipants.forEach(function (participant) {
+ var connection = new Connection_1.Connection(_this, participant);
+ _this.remoteConnections[connection.connectionId] = connection;
+ events_1.connections.push(connection);
+ if (!!connection.stream) {
+ _this.remoteStreamsCreated[connection.stream.streamId] = true;
+ events_1.streams.push(connection.stream);
+ }
+ });
+ _this.ee.emitEvent('connectionCreated', [new ConnectionEvent_1.ConnectionEvent(false, _this, 'connectionCreated', _this.connection, '')]);
+ events_1.connections.forEach(function (connection) {
+ _this.ee.emitEvent('connectionCreated', [new ConnectionEvent_1.ConnectionEvent(false, _this, 'connectionCreated', connection, '')]);
+ });
+ events_1.streams.forEach(function (stream) {
+ _this.ee.emitEvent('streamCreated', [new StreamEvent_1.StreamEvent(false, _this, 'streamCreated', stream, '')]);
+ });
+ resolve();
+ }
+ });
+ }
+ });
+ });
+ };
+ Session.prototype.stopPublisherStream = function (reason) {
+ if (!!this.connection.stream) {
+ this.connection.stream.disposeWebRtcPeer();
+ if (this.connection.stream.isLocalStreamPublished) {
+ this.connection.stream.ee.emitEvent('local-stream-destroyed', [reason]);
+ }
+ }
+ };
+ Session.prototype.stringClientMetadata = function (metadata) {
+ if (typeof metadata !== 'string') {
+ return JSON.stringify(metadata);
+ }
+ else {
+ return metadata;
+ }
+ };
+ Session.prototype.getConnection = function (connectionId, errorMessage) {
+ var _this = this;
+ return new Promise(function (resolve, reject) {
+ var connection = _this.remoteConnections[connectionId];
+ if (!!connection) {
+ resolve(connection);
+ }
+ else {
+ if (_this.connection.connectionId === connectionId) {
+ resolve(_this.connection);
+ }
+ else {
+ reject(new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.GENERIC_ERROR, errorMessage));
+ }
+ }
+ });
+ };
+ Session.prototype.getRemoteConnection = function (connectionId, errorMessage) {
+ var _this = this;
+ return new Promise(function (resolve, reject) {
+ var connection = _this.remoteConnections[connectionId];
+ if (!!connection) {
+ resolve(connection);
+ }
+ else {
+ reject(new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.GENERIC_ERROR, errorMessage));
+ }
+ });
+ };
+ Session.prototype.processToken = function (token) {
+ var url = new URL(token);
+ this.sessionId = url.searchParams.get('sessionId');
+ var secret = url.searchParams.get('secret');
+ var recorder = url.searchParams.get('recorder');
+ var turnUsername = url.searchParams.get('turnUsername');
+ var turnCredential = url.searchParams.get('turnCredential');
+ var role = url.searchParams.get('role');
+ if (!!secret) {
+ this.openvidu.secret = secret;
+ }
+ if (!!recorder) {
+ this.openvidu.recorder = true;
+ }
+ if (!!turnUsername && !!turnCredential) {
+ var stunUrl = 'stun:' + url.hostname + ':3478';
+ var turnUrl1 = 'turn:' + url.hostname + ':3478';
+ var turnUrl2 = turnUrl1 + '?transport=tcp';
+ this.openvidu.iceServers = [
+ { urls: [stunUrl] },
+ { urls: [turnUrl1, turnUrl2], username: turnUsername, credential: turnCredential }
+ ];
+ console.log('TURN temp credentials [' + turnUsername + ':' + turnCredential + ']');
+ }
+ if (!!role) {
+ this.openvidu.role = role;
+ }
+ this.openvidu.wsUri = 'wss://' + url.host + '/openvidu';
+ };
+ return Session;
+}());
+exports.Session = Session;
+
+},{"../OpenViduInternal/Enums/OpenViduError":26,"../OpenViduInternal/Enums/VideoInsertMode":27,"../OpenViduInternal/Events/ConnectionEvent":28,"../OpenViduInternal/Events/RecordingEvent":31,"../OpenViduInternal/Events/SessionDisconnectedEvent":32,"../OpenViduInternal/Events/SignalEvent":33,"../OpenViduInternal/Events/StreamEvent":34,"../OpenViduInternal/Events/StreamPropertyChangedEvent":36,"./Connection":17,"./Subscriber":24,"platform":8,"wolfy87-eventemitter":15}],22:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+var WebRtcPeer_1 = require("../OpenViduInternal/WebRtcPeer/WebRtcPeer");
+var WebRtcStats_1 = require("../OpenViduInternal/WebRtcStats/WebRtcStats");
+var PublisherSpeakingEvent_1 = require("../OpenViduInternal/Events/PublisherSpeakingEvent");
+var EventEmitter = require("wolfy87-eventemitter");
+var hark = require("hark");
+var OpenViduError_1 = require("../OpenViduInternal/Enums/OpenViduError");
+var Stream = (function () {
+ function Stream(session, options) {
+ var _this = this;
+ this.ee = new EventEmitter();
+ this.isSubscribeToRemote = false;
+ this.isLocalStreamReadyToPublish = false;
+ this.isLocalStreamPublished = false;
+ this.publishedOnce = false;
+ this.session = session;
+ if (options.hasOwnProperty('id')) {
+ this.inboundStreamOpts = options;
+ this.streamId = this.inboundStreamOpts.id;
+ this.hasAudio = this.inboundStreamOpts.hasAudio;
+ this.hasVideo = this.inboundStreamOpts.hasVideo;
+ if (this.hasAudio) {
+ this.audioActive = this.inboundStreamOpts.audioActive;
+ }
+ if (this.hasVideo) {
+ this.videoActive = this.inboundStreamOpts.videoActive;
+ this.typeOfVideo = (!this.inboundStreamOpts.typeOfVideo) ? undefined : this.inboundStreamOpts.typeOfVideo;
+ this.frameRate = (this.inboundStreamOpts.frameRate === -1) ? undefined : this.inboundStreamOpts.frameRate;
+ this.videoDimensions = this.inboundStreamOpts.videoDimensions;
+ }
+ }
+ else {
+ this.outboundStreamOpts = options;
+ this.hasAudio = this.isSendAudio();
+ this.hasVideo = this.isSendVideo();
+ if (this.hasAudio) {
+ this.audioActive = !!this.outboundStreamOpts.publisherProperties.publishAudio;
+ }
+ if (this.hasVideo) {
+ this.videoActive = !!this.outboundStreamOpts.publisherProperties.publishVideo;
+ this.frameRate = this.outboundStreamOpts.publisherProperties.frameRate;
+ if (this.outboundStreamOpts.publisherProperties.videoSource instanceof MediaStreamTrack) {
+ this.typeOfVideo = 'CUSTOM';
+ }
+ else {
+ this.typeOfVideo = this.isSendScreen() ? 'SCREEN' : 'CAMERA';
+ }
+ }
+ }
+ this.ee.on('mediastream-updated', function () {
+ _this.streamManager.updateMediaStream(_this.mediaStream);
+ console.debug('Video srcObject [' + _this.mediaStream + '] updated in stream [' + _this.streamId + ']');
+ });
+ }
+ Stream.prototype.getMediaStream = function () {
+ return this.mediaStream;
+ };
+ Stream.prototype.setMediaStream = function (mediaStream) {
+ this.mediaStream = mediaStream;
+ };
+ Stream.prototype.updateMediaStreamInVideos = function () {
+ this.ee.emitEvent('mediastream-updated');
+ };
+ Stream.prototype.getWebRtcPeer = function () {
+ return this.webRtcPeer;
+ };
+ Stream.prototype.getRTCPeerConnection = function () {
+ return this.webRtcPeer.pc;
+ };
+ Stream.prototype.subscribeToMyRemote = function (value) {
+ this.isSubscribeToRemote = value;
+ };
+ Stream.prototype.setOutboundStreamOptions = function (outboundStreamOpts) {
+ this.outboundStreamOpts = outboundStreamOpts;
+ };
+ Stream.prototype.subscribe = function () {
+ var _this = this;
+ return new Promise(function (resolve, reject) {
+ _this.initWebRtcPeerReceive()
+ .then(function () {
+ resolve();
+ })
+ .catch(function (error) {
+ reject(error);
+ });
+ });
+ };
+ Stream.prototype.publish = function () {
+ var _this = this;
+ return new Promise(function (resolve, reject) {
+ if (_this.isLocalStreamReadyToPublish) {
+ _this.initWebRtcPeerSend()
+ .then(function () {
+ resolve();
+ })
+ .catch(function (error) {
+ reject(error);
+ });
+ }
+ else {
+ _this.ee.once('stream-ready-to-publish', function () {
+ _this.publish()
+ .then(function () {
+ resolve();
+ })
+ .catch(function (error) {
+ reject(error);
+ });
+ });
+ }
+ });
+ };
+ Stream.prototype.disposeWebRtcPeer = function () {
+ if (this.webRtcPeer) {
+ this.webRtcPeer.dispose();
+ }
+ if (this.speechEvent) {
+ this.speechEvent.stop();
+ }
+ this.stopWebRtcStats();
+ console.info((!!this.outboundStreamOpts ? 'Outbound ' : 'Inbound ') + "WebRTCPeer from 'Stream' with id [" + this.streamId + '] is now closed');
+ };
+ Stream.prototype.disposeMediaStream = function () {
+ if (this.mediaStream) {
+ this.mediaStream.getAudioTracks().forEach(function (track) {
+ track.stop();
+ });
+ this.mediaStream.getVideoTracks().forEach(function (track) {
+ track.stop();
+ });
+ delete this.mediaStream;
+ }
+ console.info((!!this.outboundStreamOpts ? 'Local ' : 'Remote ') + "MediaStream from 'Stream' with id [" + this.streamId + '] is now disposed');
+ };
+ Stream.prototype.displayMyRemote = function () {
+ return this.isSubscribeToRemote;
+ };
+ Stream.prototype.isSendAudio = function () {
+ return (!!this.outboundStreamOpts &&
+ this.outboundStreamOpts.publisherProperties.audioSource !== null &&
+ this.outboundStreamOpts.publisherProperties.audioSource !== false);
+ };
+ Stream.prototype.isSendVideo = function () {
+ return (!!this.outboundStreamOpts &&
+ this.outboundStreamOpts.publisherProperties.videoSource !== null &&
+ this.outboundStreamOpts.publisherProperties.videoSource !== false);
+ };
+ Stream.prototype.isSendScreen = function () {
+ return (!!this.outboundStreamOpts &&
+ this.outboundStreamOpts.publisherProperties.videoSource === 'screen');
+ };
+ Stream.prototype.setSpeechEventIfNotExists = function () {
+ if (!this.speechEvent) {
+ var harkOptions = this.session.openvidu.advancedConfiguration.publisherSpeakingEventsOptions || {};
+ harkOptions.interval = (typeof harkOptions.interval === 'number') ? harkOptions.interval : 50;
+ harkOptions.threshold = (typeof harkOptions.threshold === 'number') ? harkOptions.threshold : -50;
+ this.speechEvent = hark(this.mediaStream, harkOptions);
+ }
+ };
+ Stream.prototype.enableSpeakingEvents = function () {
+ var _this = this;
+ this.setSpeechEventIfNotExists();
+ this.speechEvent.on('speaking', function () {
+ _this.session.emitEvent('publisherStartSpeaking', [new PublisherSpeakingEvent_1.PublisherSpeakingEvent(_this.session, 'publisherStartSpeaking', _this.connection, _this.streamId)]);
+ });
+ this.speechEvent.on('stopped_speaking', function () {
+ _this.session.emitEvent('publisherStopSpeaking', [new PublisherSpeakingEvent_1.PublisherSpeakingEvent(_this.session, 'publisherStopSpeaking', _this.connection, _this.streamId)]);
+ });
+ };
+ Stream.prototype.enableOnceSpeakingEvents = function () {
+ var _this = this;
+ this.setSpeechEventIfNotExists();
+ this.speechEvent.on('speaking', function () {
+ _this.session.emitEvent('publisherStartSpeaking', [new PublisherSpeakingEvent_1.PublisherSpeakingEvent(_this.session, 'publisherStartSpeaking', _this.connection, _this.streamId)]);
+ _this.disableSpeakingEvents();
+ });
+ this.speechEvent.on('stopped_speaking', function () {
+ _this.session.emitEvent('publisherStopSpeaking', [new PublisherSpeakingEvent_1.PublisherSpeakingEvent(_this.session, 'publisherStopSpeaking', _this.connection, _this.streamId)]);
+ _this.disableSpeakingEvents();
+ });
+ };
+ Stream.prototype.disableSpeakingEvents = function () {
+ this.speechEvent.stop();
+ this.speechEvent = undefined;
+ };
+ Stream.prototype.isLocal = function () {
+ return (!this.inboundStreamOpts && !!this.outboundStreamOpts);
+ };
+ Stream.prototype.getSelectedIceCandidate = function () {
+ var _this = this;
+ return new Promise(function (resolve, reject) {
+ _this.webRtcStats.getSelectedIceCandidateInfo()
+ .then(function (report) { return resolve(report); })
+ .catch(function (error) { return reject(error); });
+ });
+ };
+ Stream.prototype.getRemoteIceCandidateList = function () {
+ return this.webRtcPeer.remoteCandidatesQueue;
+ };
+ Stream.prototype.getLocalIceCandidateList = function () {
+ return this.webRtcPeer.localCandidatesQueue;
+ };
+ Stream.prototype.initWebRtcPeerSend = function () {
+ var _this = this;
+ return new Promise(function (resolve, reject) {
+ var userMediaConstraints = {
+ audio: _this.isSendAudio(),
+ video: _this.isSendVideo()
+ };
+ var options = {
+ mediaStream: _this.mediaStream,
+ mediaConstraints: userMediaConstraints,
+ onicecandidate: _this.connection.sendIceCandidate.bind(_this.connection),
+ iceServers: _this.getIceServersConf(),
+ simulcast: false
+ };
+ var successCallback = function (sdpOfferParam) {
+ console.debug('Sending SDP offer to publish as '
+ + _this.streamId, sdpOfferParam);
+ var typeOfVideo = '';
+ if (_this.isSendVideo()) {
+ typeOfVideo = _this.outboundStreamOpts.publisherProperties.videoSource instanceof MediaStreamTrack ? 'CUSTOM' : (_this.isSendScreen() ? 'SCREEN' : 'CAMERA');
+ }
+ _this.session.openvidu.sendRequest('publishVideo', {
+ sdpOffer: sdpOfferParam,
+ doLoopback: _this.displayMyRemote() || false,
+ hasAudio: _this.isSendAudio(),
+ hasVideo: _this.isSendVideo(),
+ audioActive: _this.audioActive,
+ videoActive: _this.videoActive,
+ typeOfVideo: typeOfVideo,
+ frameRate: !!_this.frameRate ? _this.frameRate : -1,
+ videoDimensions: JSON.stringify(_this.videoDimensions)
+ }, function (error, response) {
+ if (error) {
+ if (error.code === 401) {
+ reject(new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.OPENVIDU_PERMISSION_DENIED, "You don't have permissions to publish"));
+ }
+ else {
+ reject('Error on publishVideo: ' + JSON.stringify(error));
+ }
+ }
+ else {
+ _this.webRtcPeer.processAnswer(response.sdpAnswer)
+ .then(function () {
+ _this.streamId = response.id;
+ _this.isLocalStreamPublished = true;
+ _this.publishedOnce = true;
+ if (_this.displayMyRemote()) {
+ _this.remotePeerSuccessfullyEstablished();
+ }
+ _this.ee.emitEvent('stream-created-by-publisher');
+ _this.initWebRtcStats();
+ resolve();
+ })
+ .catch(function (error) {
+ reject(error);
+ });
+ console.info("'Publisher' successfully published to session");
+ }
+ });
+ };
+ if (_this.displayMyRemote()) {
+ _this.webRtcPeer = new WebRtcPeer_1.WebRtcPeerSendrecv(options);
+ }
+ else {
+ _this.webRtcPeer = new WebRtcPeer_1.WebRtcPeerSendonly(options);
+ }
+ _this.webRtcPeer.generateOffer().then(function (offer) {
+ successCallback(offer);
+ }).catch(function (error) {
+ reject(new Error('(publish) SDP offer error: ' + JSON.stringify(error)));
+ });
+ });
+ };
+ Stream.prototype.initWebRtcPeerReceive = function () {
+ var _this = this;
+ return new Promise(function (resolve, reject) {
+ var offerConstraints = {
+ audio: _this.inboundStreamOpts.hasAudio,
+ video: _this.inboundStreamOpts.hasVideo
+ };
+ console.debug("'Session.subscribe(Stream)' called. Constraints of generate SDP offer", offerConstraints);
+ var options = {
+ onicecandidate: _this.connection.sendIceCandidate.bind(_this.connection),
+ mediaConstraints: offerConstraints,
+ iceServers: _this.getIceServersConf(),
+ simulcast: false
+ };
+ var successCallback = function (sdpOfferParam) {
+ console.debug('Sending SDP offer to subscribe to '
+ + _this.streamId, sdpOfferParam);
+ _this.session.openvidu.sendRequest('receiveVideoFrom', {
+ sender: _this.streamId,
+ sdpOffer: sdpOfferParam
+ }, function (error, response) {
+ if (error) {
+ reject(new Error('Error on recvVideoFrom: ' + JSON.stringify(error)));
+ }
+ else {
+ _this.webRtcPeer.processAnswer(response.sdpAnswer).then(function () {
+ _this.remotePeerSuccessfullyEstablished();
+ _this.initWebRtcStats();
+ resolve();
+ }).catch(function (error) {
+ reject(error);
+ });
+ }
+ });
+ };
+ _this.webRtcPeer = new WebRtcPeer_1.WebRtcPeerRecvonly(options);
+ _this.webRtcPeer.generateOffer()
+ .then(function (offer) {
+ successCallback(offer);
+ })
+ .catch(function (error) {
+ reject(new Error('(subscribe) SDP offer error: ' + JSON.stringify(error)));
+ });
+ });
+ };
+ Stream.prototype.remotePeerSuccessfullyEstablished = function () {
+ this.mediaStream = this.webRtcPeer.pc.getRemoteStreams()[0];
+ console.debug('Peer remote stream', this.mediaStream);
+ if (!!this.mediaStream) {
+ this.ee.emitEvent('mediastream-updated');
+ if (!this.displayMyRemote() && !!this.mediaStream.getAudioTracks()[0] && this.session.speakingEventsEnabled) {
+ this.enableSpeakingEvents();
+ }
+ }
+ };
+ Stream.prototype.initWebRtcStats = function () {
+ this.webRtcStats = new WebRtcStats_1.WebRtcStats(this);
+ this.webRtcStats.initWebRtcStats();
+ };
+ Stream.prototype.stopWebRtcStats = function () {
+ if (!!this.webRtcStats && this.webRtcStats.isEnabled()) {
+ this.webRtcStats.stopWebRtcStats();
+ }
+ };
+ Stream.prototype.getIceServersConf = function () {
+ var returnValue;
+ if (!!this.session.openvidu.advancedConfiguration.iceServers) {
+ returnValue = this.session.openvidu.advancedConfiguration.iceServers === 'freeice' ?
+ undefined :
+ this.session.openvidu.advancedConfiguration.iceServers;
+ }
+ else if (this.session.openvidu.iceServers) {
+ returnValue = this.session.openvidu.iceServers;
+ }
+ else {
+ returnValue = undefined;
+ }
+ return returnValue;
+ };
+ return Stream;
+}());
+exports.Stream = Stream;
+
+},{"../OpenViduInternal/Enums/OpenViduError":26,"../OpenViduInternal/Events/PublisherSpeakingEvent":30,"../OpenViduInternal/WebRtcPeer/WebRtcPeer":49,"../OpenViduInternal/WebRtcStats/WebRtcStats":50,"hark":5,"wolfy87-eventemitter":15}],23:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+var StreamManagerEvent_1 = require("../OpenViduInternal/Events/StreamManagerEvent");
+var VideoElementEvent_1 = require("../OpenViduInternal/Events/VideoElementEvent");
+var VideoInsertMode_1 = require("../OpenViduInternal/Enums/VideoInsertMode");
+var EventEmitter = require("wolfy87-eventemitter");
+var StreamManager = (function () {
+ function StreamManager(stream, targetElement) {
+ var _this = this;
+ this.videos = [];
+ this.lazyLaunchVideoElementCreatedEvent = false;
+ this.ee = new EventEmitter();
+ this.stream = stream;
+ this.stream.streamManager = this;
+ this.remote = !this.stream.isLocal();
+ if (!!targetElement) {
+ var targEl = void 0;
+ if (typeof targetElement === 'string') {
+ targEl = document.getElementById(targetElement);
+ }
+ else if (targetElement instanceof HTMLElement) {
+ targEl = targetElement;
+ }
+ if (!!targEl) {
+ this.firstVideoElement = {
+ targetElement: targEl,
+ video: document.createElement('video'),
+ id: ''
+ };
+ this.targetElement = targEl;
+ this.element = targEl;
+ }
+ }
+ this.canPlayListener = function () {
+ if (_this.stream.isLocal()) {
+ if (!_this.stream.displayMyRemote()) {
+ console.info("Your local 'Stream' with id [" + _this.stream.streamId + '] video is now playing');
+ _this.ee.emitEvent('videoPlaying', [new VideoElementEvent_1.VideoElementEvent(_this.videos[0].video, _this, 'videoPlaying')]);
+ }
+ else {
+ console.info("Your own remote 'Stream' with id [" + _this.stream.streamId + '] video is now playing');
+ _this.ee.emitEvent('remoteVideoPlaying', [new VideoElementEvent_1.VideoElementEvent(_this.videos[0].video, _this, 'remoteVideoPlaying')]);
+ }
+ }
+ else {
+ console.info("Remote 'Stream' with id [" + _this.stream.streamId + '] video is now playing');
+ _this.ee.emitEvent('videoPlaying', [new VideoElementEvent_1.VideoElementEvent(_this.videos[0].video, _this, 'videoPlaying')]);
+ }
+ _this.ee.emitEvent('streamPlaying', [new StreamManagerEvent_1.StreamManagerEvent(_this)]);
+ };
+ }
+ StreamManager.prototype.on = function (type, handler) {
+ var _this = this;
+ this.ee.on(type, function (event) {
+ if (event) {
+ console.info("Event '" + type + "' triggered by '" + (_this.remote ? 'Subscriber' : 'Publisher') + "'", event);
+ }
+ else {
+ console.info("Event '" + type + "' triggered by '" + (_this.remote ? 'Subscriber' : 'Publisher') + "'");
+ }
+ handler(event);
+ });
+ if (type === 'videoElementCreated') {
+ if (!!this.stream && this.lazyLaunchVideoElementCreatedEvent) {
+ this.ee.emitEvent('videoElementCreated', [new VideoElementEvent_1.VideoElementEvent(this.videos[0].video, this, 'videoElementCreated')]);
+ this.lazyLaunchVideoElementCreatedEvent = false;
+ }
+ }
+ if (type === 'streamPlaying' || type === 'videoPlaying') {
+ if (this.videos[0] && this.videos[0].video &&
+ this.videos[0].video.currentTime > 0 &&
+ this.videos[0].video.paused === false &&
+ this.videos[0].video.ended === false &&
+ this.videos[0].video.readyState === 4) {
+ this.ee.emitEvent('streamPlaying', [new StreamManagerEvent_1.StreamManagerEvent(this)]);
+ this.ee.emitEvent('videoPlaying', [new VideoElementEvent_1.VideoElementEvent(this.videos[0].video, this, 'videoPlaying')]);
+ }
+ }
+ return this;
+ };
+ StreamManager.prototype.once = function (type, handler) {
+ this.ee.once(type, function (event) {
+ if (event) {
+ console.info("Event '" + type + "' triggered once", event);
+ }
+ else {
+ console.info("Event '" + type + "' triggered once");
+ }
+ handler(event);
+ });
+ if (type === 'videoElementCreated') {
+ if (!!this.stream && this.lazyLaunchVideoElementCreatedEvent) {
+ this.ee.emitEvent('videoElementCreated', [new VideoElementEvent_1.VideoElementEvent(this.videos[0].video, this, 'videoElementCreated')]);
+ }
+ }
+ if (type === 'streamPlaying' || type === 'videoPlaying') {
+ if (this.videos[0] && this.videos[0].video &&
+ this.videos[0].video.currentTime > 0 &&
+ this.videos[0].video.paused === false &&
+ this.videos[0].video.ended === false &&
+ this.videos[0].video.readyState === 4) {
+ this.ee.emitEvent('streamPlaying', [new StreamManagerEvent_1.StreamManagerEvent(this)]);
+ this.ee.emitEvent('videoPlaying', [new VideoElementEvent_1.VideoElementEvent(this.videos[0].video, this, 'videoPlaying')]);
+ }
+ }
+ return this;
+ };
+ StreamManager.prototype.off = function (type, handler) {
+ if (!handler) {
+ this.ee.removeAllListeners(type);
+ }
+ else {
+ this.ee.off(type, handler);
+ }
+ return this;
+ };
+ StreamManager.prototype.addVideoElement = function (video) {
+ this.initializeVideoProperties(video);
+ for (var _i = 0, _a = this.videos; _i < _a.length; _i++) {
+ var v = _a[_i];
+ if (v.video === video) {
+ return 0;
+ }
+ }
+ var returnNumber = 1;
+ for (var _b = 0, _c = this.stream.session.streamManagers; _b < _c.length; _b++) {
+ var streamManager = _c[_b];
+ if (streamManager.disassociateVideo(video)) {
+ returnNumber = -1;
+ break;
+ }
+ }
+ this.stream.session.streamManagers.forEach(function (streamManager) {
+ streamManager.disassociateVideo(video);
+ });
+ this.pushNewStreamManagerVideo({
+ video: video,
+ id: video.id
+ });
+ console.info('New video element associated to ', this);
+ return returnNumber;
+ };
+ StreamManager.prototype.createVideoElement = function (targetElement, insertMode) {
+ var targEl;
+ if (typeof targetElement === 'string') {
+ targEl = document.getElementById(targEl);
+ if (!targEl) {
+ throw new Error("The provided 'targetElement' couldn't be resolved to any HTML element: " + targetElement);
+ }
+ }
+ else if (targetElement instanceof HTMLElement) {
+ targEl = targetElement;
+ }
+ else {
+ throw new Error("The provided 'targetElement' couldn't be resolved to any HTML element: " + targetElement);
+ }
+ var video = document.createElement('video');
+ this.initializeVideoProperties(video);
+ var insMode = !!insertMode ? insertMode : VideoInsertMode_1.VideoInsertMode.APPEND;
+ switch (insMode) {
+ case VideoInsertMode_1.VideoInsertMode.AFTER:
+ targEl.parentNode.insertBefore(video, targEl.nextSibling);
+ break;
+ case VideoInsertMode_1.VideoInsertMode.APPEND:
+ targEl.appendChild(video);
+ break;
+ case VideoInsertMode_1.VideoInsertMode.BEFORE:
+ targEl.parentNode.insertBefore(video, targEl);
+ break;
+ case VideoInsertMode_1.VideoInsertMode.PREPEND:
+ targEl.insertBefore(video, targEl.childNodes[0]);
+ break;
+ case VideoInsertMode_1.VideoInsertMode.REPLACE:
+ targEl.parentNode.replaceChild(video, targEl);
+ break;
+ default:
+ insMode = VideoInsertMode_1.VideoInsertMode.APPEND;
+ targEl.appendChild(video);
+ break;
+ }
+ var v = {
+ targetElement: targEl,
+ video: video,
+ insertMode: insMode,
+ id: video.id
+ };
+ this.pushNewStreamManagerVideo(v);
+ this.ee.emitEvent('videoElementCreated', [new VideoElementEvent_1.VideoElementEvent(v.video, this, 'videoElementCreated')]);
+ this.lazyLaunchVideoElementCreatedEvent = !!this.firstVideoElement;
+ return video;
+ };
+ StreamManager.prototype.initializeVideoProperties = function (video) {
+ if (!(this.stream.isLocal() && this.stream.displayMyRemote())) {
+ video.srcObject = this.stream.getMediaStream();
+ }
+ video.autoplay = true;
+ video.controls = false;
+ if (!video.id) {
+ video.id = (this.remote ? 'remote-' : 'local-') + 'video-' + this.stream.streamId;
+ if (!this.id && !!this.targetElement) {
+ this.id = video.id;
+ }
+ }
+ if (!this.remote && !this.stream.displayMyRemote()) {
+ video.muted = true;
+ if (this.stream.outboundStreamOpts.publisherProperties.mirror) {
+ this.mirrorVideo(video);
+ }
+ }
+ };
+ StreamManager.prototype.removeAllVideos = function () {
+ var _this = this;
+ for (var i = this.stream.session.streamManagers.length - 1; i >= 0; --i) {
+ if (this.stream.session.streamManagers[i] === this) {
+ this.stream.session.streamManagers.splice(i, 1);
+ }
+ }
+ this.videos.forEach(function (streamManagerVideo) {
+ streamManagerVideo.video.removeEventListener('canplay', _this.canPlayListener);
+ if (!!streamManagerVideo.targetElement) {
+ streamManagerVideo.video.parentNode.removeChild(streamManagerVideo.video);
+ _this.ee.emitEvent('videoElementDestroyed', [new VideoElementEvent_1.VideoElementEvent(streamManagerVideo.video, _this, 'videoElementDestroyed')]);
+ }
+ streamManagerVideo.video.srcObject = null;
+ _this.videos.filter(function (v) { return !v.targetElement; });
+ });
+ };
+ StreamManager.prototype.disassociateVideo = function (video) {
+ var disassociated = false;
+ for (var i = 0; i < this.videos.length; i++) {
+ if (this.videos[i].video === video) {
+ this.videos.splice(i, 1);
+ disassociated = true;
+ console.info('Video element disassociated from ', this);
+ break;
+ }
+ }
+ return disassociated;
+ };
+ StreamManager.prototype.addPlayEventToFirstVideo = function () {
+ if ((!!this.videos[0]) && (!!this.videos[0].video) && (this.videos[0].video.oncanplay === null)) {
+ this.videos[0].video.addEventListener('canplay', this.canPlayListener);
+ }
+ };
+ StreamManager.prototype.updateMediaStream = function (mediaStream) {
+ this.videos.forEach(function (streamManagerVideo) {
+ streamManagerVideo.video.srcObject = mediaStream;
+ });
+ };
+ StreamManager.prototype.emitEvent = function (type, eventArray) {
+ this.ee.emitEvent(type, eventArray);
+ };
+ StreamManager.prototype.pushNewStreamManagerVideo = function (streamManagerVideo) {
+ this.videos.push(streamManagerVideo);
+ this.addPlayEventToFirstVideo();
+ if (this.stream.session.streamManagers.indexOf(this) === -1) {
+ this.stream.session.streamManagers.push(this);
+ }
+ };
+ StreamManager.prototype.mirrorVideo = function (video) {
+ video.style.transform = 'rotateY(180deg)';
+ video.style.webkitTransform = 'rotateY(180deg)';
+ };
+ return StreamManager;
+}());
+exports.StreamManager = StreamManager;
+
+},{"../OpenViduInternal/Enums/VideoInsertMode":27,"../OpenViduInternal/Events/StreamManagerEvent":35,"../OpenViduInternal/Events/VideoElementEvent":37,"wolfy87-eventemitter":15}],24:[function(require,module,exports){
+"use strict";
+var __extends = (this && this.__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 __());
+ };
+})();
+Object.defineProperty(exports, "__esModule", { value: true });
+var StreamManager_1 = require("./StreamManager");
+var Subscriber = (function (_super) {
+ __extends(Subscriber, _super);
+ function Subscriber(stream, targEl, properties) {
+ var _this = _super.call(this, stream, targEl) || this;
+ _this.element = _this.targetElement;
+ _this.stream = stream;
+ _this.properties = properties;
+ return _this;
+ }
+ Subscriber.prototype.subscribeToAudio = function (value) {
+ this.stream.getMediaStream().getAudioTracks().forEach(function (track) {
+ track.enabled = value;
+ });
+ console.info("'Subscriber' has " + (value ? 'subscribed to' : 'unsubscribed from') + ' its audio stream');
+ return this;
+ };
+ Subscriber.prototype.subscribeToVideo = function (value) {
+ this.stream.getMediaStream().getVideoTracks().forEach(function (track) {
+ track.enabled = value;
+ });
+ console.info("'Subscriber' has " + (value ? 'subscribed to' : 'unsubscribed from') + ' its video stream');
+ return this;
+ };
+ return Subscriber;
+}(StreamManager_1.StreamManager));
+exports.Subscriber = Subscriber;
+
+},{"./StreamManager":23}],25:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+var LocalRecorderState;
+(function (LocalRecorderState) {
+ LocalRecorderState["READY"] = "READY";
+ LocalRecorderState["RECORDING"] = "RECORDING";
+ LocalRecorderState["PAUSED"] = "PAUSED";
+ LocalRecorderState["FINISHED"] = "FINISHED";
+})(LocalRecorderState = exports.LocalRecorderState || (exports.LocalRecorderState = {}));
+
+},{}],26:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+var OpenViduErrorName;
+(function (OpenViduErrorName) {
+ OpenViduErrorName["BROWSER_NOT_SUPPORTED"] = "BROWSER_NOT_SUPPORTED";
+ OpenViduErrorName["DEVICE_ACCESS_DENIED"] = "DEVICE_ACCESS_DENIED";
+ OpenViduErrorName["SCREEN_CAPTURE_DENIED"] = "SCREEN_CAPTURE_DENIED";
+ OpenViduErrorName["SCREEN_SHARING_NOT_SUPPORTED"] = "SCREEN_SHARING_NOT_SUPPORTED";
+ OpenViduErrorName["SCREEN_EXTENSION_NOT_INSTALLED"] = "SCREEN_EXTENSION_NOT_INSTALLED";
+ OpenViduErrorName["SCREEN_EXTENSION_DISABLED"] = "SCREEN_EXTENSION_DISABLED";
+ OpenViduErrorName["INPUT_VIDEO_DEVICE_NOT_FOUND"] = "INPUT_VIDEO_DEVICE_NOT_FOUND";
+ OpenViduErrorName["INPUT_AUDIO_DEVICE_NOT_FOUND"] = "INPUT_AUDIO_DEVICE_NOT_FOUND";
+ OpenViduErrorName["NO_INPUT_SOURCE_SET"] = "NO_INPUT_SOURCE_SET";
+ OpenViduErrorName["PUBLISHER_PROPERTIES_ERROR"] = "PUBLISHER_PROPERTIES_ERROR";
+ OpenViduErrorName["OPENVIDU_PERMISSION_DENIED"] = "OPENVIDU_PERMISSION_DENIED";
+ OpenViduErrorName["OPENVIDU_NOT_CONNECTED"] = "OPENVIDU_NOT_CONNECTED";
+ OpenViduErrorName["GENERIC_ERROR"] = "GENERIC_ERROR";
+})(OpenViduErrorName = exports.OpenViduErrorName || (exports.OpenViduErrorName = {}));
+var OpenViduError = (function () {
+ function OpenViduError(name, message) {
+ this.name = name;
+ this.message = message;
+ }
+ return OpenViduError;
+}());
+exports.OpenViduError = OpenViduError;
+
+},{}],27:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+var VideoInsertMode;
+(function (VideoInsertMode) {
+ VideoInsertMode["AFTER"] = "AFTER";
+ VideoInsertMode["APPEND"] = "APPEND";
+ VideoInsertMode["BEFORE"] = "BEFORE";
+ VideoInsertMode["PREPEND"] = "PREPEND";
+ VideoInsertMode["REPLACE"] = "REPLACE";
+})(VideoInsertMode = exports.VideoInsertMode || (exports.VideoInsertMode = {}));
+
+},{}],28:[function(require,module,exports){
+"use strict";
+var __extends = (this && this.__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 __());
+ };
+})();
+Object.defineProperty(exports, "__esModule", { value: true });
+var Event_1 = require("./Event");
+var ConnectionEvent = (function (_super) {
+ __extends(ConnectionEvent, _super);
+ function ConnectionEvent(cancelable, target, type, connection, reason) {
+ var _this = _super.call(this, cancelable, target, type) || this;
+ _this.connection = connection;
+ _this.reason = reason;
+ return _this;
+ }
+ ConnectionEvent.prototype.callDefaultBehavior = function () { };
+ return ConnectionEvent;
+}(Event_1.Event));
+exports.ConnectionEvent = ConnectionEvent;
+
+},{"./Event":29}],29:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+var Event = (function () {
+ function Event(cancelable, target, type) {
+ this.hasBeenPrevented = false;
+ this.cancelable = cancelable;
+ this.target = target;
+ this.type = type;
+ }
+ Event.prototype.isDefaultPrevented = function () {
+ return this.hasBeenPrevented;
+ };
+ Event.prototype.preventDefault = function () {
+ this.callDefaultBehavior = function () { };
+ this.hasBeenPrevented = true;
+ };
+ return Event;
+}());
+exports.Event = Event;
+
+},{}],30:[function(require,module,exports){
+"use strict";
+var __extends = (this && this.__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 __());
+ };
+})();
+Object.defineProperty(exports, "__esModule", { value: true });
+var Event_1 = require("./Event");
+var PublisherSpeakingEvent = (function (_super) {
+ __extends(PublisherSpeakingEvent, _super);
+ function PublisherSpeakingEvent(target, type, connection, streamId) {
+ var _this = _super.call(this, false, target, type) || this;
+ _this.type = type;
+ _this.connection = connection;
+ _this.streamId = streamId;
+ return _this;
+ }
+ PublisherSpeakingEvent.prototype.callDefaultBehavior = function () { };
+ return PublisherSpeakingEvent;
+}(Event_1.Event));
+exports.PublisherSpeakingEvent = PublisherSpeakingEvent;
+
+},{"./Event":29}],31:[function(require,module,exports){
+"use strict";
+var __extends = (this && this.__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 __());
+ };
+})();
+Object.defineProperty(exports, "__esModule", { value: true });
+var Event_1 = require("./Event");
+var RecordingEvent = (function (_super) {
+ __extends(RecordingEvent, _super);
+ function RecordingEvent(target, type, id, name) {
+ var _this = _super.call(this, false, target, type) || this;
+ _this.id = id;
+ if (name !== id) {
+ _this.name = name;
+ }
+ return _this;
+ }
+ RecordingEvent.prototype.callDefaultBehavior = function () { };
+ return RecordingEvent;
+}(Event_1.Event));
+exports.RecordingEvent = RecordingEvent;
+
+},{"./Event":29}],32:[function(require,module,exports){
+"use strict";
+var __extends = (this && this.__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 __());
+ };
+})();
+Object.defineProperty(exports, "__esModule", { value: true });
+var Event_1 = require("./Event");
+var SessionDisconnectedEvent = (function (_super) {
+ __extends(SessionDisconnectedEvent, _super);
+ function SessionDisconnectedEvent(target, reason) {
+ var _this = _super.call(this, true, target, 'sessionDisconnected') || this;
+ _this.reason = reason;
+ return _this;
+ }
+ SessionDisconnectedEvent.prototype.callDefaultBehavior = function () {
+ console.info("Calling default behavior upon '" + this.type + "' event dispatched by 'Session'");
+ var session = this.target;
+ for (var connectionId in session.remoteConnections) {
+ if (!!session.remoteConnections[connectionId].stream) {
+ session.remoteConnections[connectionId].stream.disposeWebRtcPeer();
+ session.remoteConnections[connectionId].stream.disposeMediaStream();
+ if (session.remoteConnections[connectionId].stream.streamManager) {
+ session.remoteConnections[connectionId].stream.streamManager.removeAllVideos();
+ }
+ delete session.remoteStreamsCreated[session.remoteConnections[connectionId].stream.streamId];
+ session.remoteConnections[connectionId].dispose();
+ }
+ delete session.remoteConnections[connectionId];
+ }
+ };
+ return SessionDisconnectedEvent;
+}(Event_1.Event));
+exports.SessionDisconnectedEvent = SessionDisconnectedEvent;
+
+},{"./Event":29}],33:[function(require,module,exports){
+"use strict";
+var __extends = (this && this.__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 __());
+ };
+})();
+Object.defineProperty(exports, "__esModule", { value: true });
+var Event_1 = require("./Event");
+var SignalEvent = (function (_super) {
+ __extends(SignalEvent, _super);
+ function SignalEvent(target, type, data, from) {
+ var _this = _super.call(this, false, target, type) || this;
+ _this.type = type;
+ _this.data = data;
+ _this.from = from;
+ return _this;
+ }
+ SignalEvent.prototype.callDefaultBehavior = function () { };
+ return SignalEvent;
+}(Event_1.Event));
+exports.SignalEvent = SignalEvent;
+
+},{"./Event":29}],34:[function(require,module,exports){
+"use strict";
+var __extends = (this && this.__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 __());
+ };
+})();
+Object.defineProperty(exports, "__esModule", { value: true });
+var Event_1 = require("./Event");
+var Publisher_1 = require("../../OpenVidu/Publisher");
+var Session_1 = require("../../OpenVidu/Session");
+var StreamEvent = (function (_super) {
+ __extends(StreamEvent, _super);
+ function StreamEvent(cancelable, target, type, stream, reason) {
+ var _this = _super.call(this, cancelable, target, type) || this;
+ _this.stream = stream;
+ _this.reason = reason;
+ return _this;
+ }
+ StreamEvent.prototype.callDefaultBehavior = function () {
+ if (this.type === 'streamDestroyed') {
+ if (this.target instanceof Session_1.Session) {
+ console.info("Calling default behavior upon '" + this.type + "' event dispatched by 'Session'");
+ this.stream.disposeWebRtcPeer();
+ }
+ else if (this.target instanceof Publisher_1.Publisher) {
+ console.info("Calling default behavior upon '" + this.type + "' event dispatched by 'Publisher'");
+ clearInterval(this.target.screenShareResizeInterval);
+ this.stream.isLocalStreamReadyToPublish = false;
+ var openviduPublishers = this.target.openvidu.publishers;
+ for (var i = 0; i < openviduPublishers.length; i++) {
+ if (openviduPublishers[i] === this.target) {
+ openviduPublishers.splice(i, 1);
+ break;
+ }
+ }
+ }
+ this.stream.disposeMediaStream();
+ if (this.stream.streamManager)
+ this.stream.streamManager.removeAllVideos();
+ delete this.stream.session.remoteStreamsCreated[this.stream.streamId];
+ var remoteConnection = this.stream.session.remoteConnections[this.stream.connection.connectionId];
+ if (!!remoteConnection && !!remoteConnection.options) {
+ var streamOptionsServer = remoteConnection.options.streams;
+ for (var i = streamOptionsServer.length - 1; i >= 0; --i) {
+ if (streamOptionsServer[i].id === this.stream.streamId) {
+ streamOptionsServer.splice(i, 1);
+ }
+ }
+ }
+ }
+ };
+ return StreamEvent;
+}(Event_1.Event));
+exports.StreamEvent = StreamEvent;
+
+},{"../../OpenVidu/Publisher":20,"../../OpenVidu/Session":21,"./Event":29}],35:[function(require,module,exports){
+"use strict";
+var __extends = (this && this.__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 __());
+ };
+})();
+Object.defineProperty(exports, "__esModule", { value: true });
+var Event_1 = require("./Event");
+var StreamManagerEvent = (function (_super) {
+ __extends(StreamManagerEvent, _super);
+ function StreamManagerEvent(target) {
+ return _super.call(this, false, target, 'streamPlaying') || this;
+ }
+ StreamManagerEvent.prototype.callDefaultBehavior = function () { };
+ return StreamManagerEvent;
+}(Event_1.Event));
+exports.StreamManagerEvent = StreamManagerEvent;
+
+},{"./Event":29}],36:[function(require,module,exports){
+"use strict";
+var __extends = (this && this.__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 __());
+ };
+})();
+Object.defineProperty(exports, "__esModule", { value: true });
+var Event_1 = require("./Event");
+var StreamPropertyChangedEvent = (function (_super) {
+ __extends(StreamPropertyChangedEvent, _super);
+ function StreamPropertyChangedEvent(target, stream, changedProperty, newValue, oldValue, reason) {
+ var _this = _super.call(this, false, target, 'streamPropertyChanged') || this;
+ _this.stream = stream;
+ _this.changedProperty = changedProperty;
+ _this.newValue = newValue;
+ _this.oldValue = oldValue;
+ _this.reason = reason;
+ return _this;
+ }
+ StreamPropertyChangedEvent.prototype.callDefaultBehavior = function () { };
+ return StreamPropertyChangedEvent;
+}(Event_1.Event));
+exports.StreamPropertyChangedEvent = StreamPropertyChangedEvent;
+
+},{"./Event":29}],37:[function(require,module,exports){
+"use strict";
+var __extends = (this && this.__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 __());
+ };
+})();
+Object.defineProperty(exports, "__esModule", { value: true });
+var Event_1 = require("./Event");
+var VideoElementEvent = (function (_super) {
+ __extends(VideoElementEvent, _super);
+ function VideoElementEvent(element, target, type) {
+ var _this = _super.call(this, false, target, type) || this;
+ _this.element = element;
+ return _this;
+ }
+ VideoElementEvent.prototype.callDefaultBehavior = function () { };
+ return VideoElementEvent;
+}(Event_1.Event));
+exports.VideoElementEvent = VideoElementEvent;
+
+},{"./Event":29}],38:[function(require,module,exports){
+function Mapper() {
+ var sources = {};
+ this.forEach = function (callback) {
+ for (var key in sources) {
+ var source = sources[key];
+ for (var key2 in source)
+ callback(source[key2]);
+ }
+ ;
+ };
+ this.get = function (id, source) {
+ var ids = sources[source];
+ if (ids == undefined)
+ return undefined;
+ return ids[id];
+ };
+ this.remove = function (id, source) {
+ var ids = sources[source];
+ if (ids == undefined)
+ return;
+ delete ids[id];
+ for (var i in ids) {
+ return false;
+ }
+ delete sources[source];
+ };
+ this.set = function (value, id, source) {
+ if (value == undefined)
+ return this.remove(id, source);
+ var ids = sources[source];
+ if (ids == undefined)
+ sources[source] = ids = {};
+ ids[id] = value;
+ };
+}
+;
+Mapper.prototype.pop = function (id, source) {
+ var value = this.get(id, source);
+ if (value == undefined)
+ return undefined;
+ this.remove(id, source);
+ return value;
+};
+module.exports = Mapper;
+
+},{}],39:[function(require,module,exports){
+var JsonRpcClient = require('./jsonrpcclient');
+exports.JsonRpcClient = JsonRpcClient;
+
+},{"./jsonrpcclient":40}],40:[function(require,module,exports){
+var RpcBuilder = require('../');
+var WebSocketWithReconnection = require('./transports/webSocketWithReconnection');
+Date.now = Date.now || function () {
+ return +new Date;
+};
+var PING_INTERVAL = 5000;
+var RECONNECTING = 'RECONNECTING';
+var CONNECTED = 'CONNECTED';
+var DISCONNECTED = 'DISCONNECTED';
+var Logger = console;
+function JsonRpcClient(configuration) {
+ var self = this;
+ var wsConfig = configuration.ws;
+ var notReconnectIfNumLessThan = -1;
+ var pingNextNum = 0;
+ var enabledPings = true;
+ var pingPongStarted = false;
+ var pingInterval;
+ var status = DISCONNECTED;
+ var onreconnecting = wsConfig.onreconnecting;
+ var onreconnected = wsConfig.onreconnected;
+ var onconnected = wsConfig.onconnected;
+ var onerror = wsConfig.onerror;
+ configuration.rpc.pull = function (params, request) {
+ request.reply(null, "push");
+ };
+ wsConfig.onreconnecting = function () {
+ Logger.debug("--------- ONRECONNECTING -----------");
+ if (status === RECONNECTING) {
+ Logger.error("Websocket already in RECONNECTING state when receiving a new ONRECONNECTING message. Ignoring it");
+ return;
+ }
+ status = RECONNECTING;
+ if (onreconnecting) {
+ onreconnecting();
+ }
+ };
+ wsConfig.onreconnected = function () {
+ Logger.debug("--------- ONRECONNECTED -----------");
+ if (status === CONNECTED) {
+ Logger.error("Websocket already in CONNECTED state when receiving a new ONRECONNECTED message. Ignoring it");
+ return;
+ }
+ status = CONNECTED;
+ enabledPings = true;
+ updateNotReconnectIfLessThan();
+ usePing();
+ if (onreconnected) {
+ onreconnected();
+ }
+ };
+ wsConfig.onconnected = function () {
+ Logger.debug("--------- ONCONNECTED -----------");
+ if (status === CONNECTED) {
+ Logger.error("Websocket already in CONNECTED state when receiving a new ONCONNECTED message. Ignoring it");
+ return;
+ }
+ status = CONNECTED;
+ enabledPings = true;
+ usePing();
+ if (onconnected) {
+ onconnected();
+ }
+ };
+ wsConfig.onerror = function (error) {
+ Logger.debug("--------- ONERROR -----------");
+ status = DISCONNECTED;
+ if (onerror) {
+ onerror(error);
+ }
+ };
+ var ws = new WebSocketWithReconnection(wsConfig);
+ Logger.debug('Connecting websocket to URI: ' + wsConfig.uri);
+ var rpcBuilderOptions = {
+ request_timeout: configuration.rpc.requestTimeout,
+ ping_request_timeout: configuration.rpc.heartbeatRequestTimeout
+ };
+ var rpc = new RpcBuilder(RpcBuilder.packers.JsonRPC, rpcBuilderOptions, ws, function (request) {
+ Logger.debug('Received request: ' + JSON.stringify(request));
+ try {
+ var func = configuration.rpc[request.method];
+ if (func === undefined) {
+ Logger.error("Method " + request.method + " not registered in client");
+ }
+ else {
+ func(request.params, request);
+ }
+ }
+ catch (err) {
+ Logger.error('Exception processing request: ' + JSON.stringify(request));
+ Logger.error(err);
+ }
+ });
+ this.send = function (method, params, callback) {
+ if (method !== 'ping') {
+ Logger.debug('Request: method:' + method + " params:" + JSON.stringify(params));
+ }
+ var requestTime = Date.now();
+ rpc.encode(method, params, function (error, result) {
+ if (error) {
+ try {
+ Logger.error("ERROR:" + error.message + " in Request: method:" +
+ method + " params:" + JSON.stringify(params) + " request:" +
+ error.request);
+ if (error.data) {
+ Logger.error("ERROR DATA:" + JSON.stringify(error.data));
+ }
+ }
+ catch (e) { }
+ error.requestTime = requestTime;
+ }
+ if (callback) {
+ if (result != undefined && result.value !== 'pong') {
+ Logger.debug('Response: ' + JSON.stringify(result));
+ }
+ callback(error, result);
+ }
+ });
+ };
+ function updateNotReconnectIfLessThan() {
+ Logger.debug("notReconnectIfNumLessThan = " + pingNextNum + ' (old=' +
+ notReconnectIfNumLessThan + ')');
+ notReconnectIfNumLessThan = pingNextNum;
+ }
+ function sendPing() {
+ if (enabledPings) {
+ var params = null;
+ if (pingNextNum == 0 || pingNextNum == notReconnectIfNumLessThan) {
+ params = {
+ interval: configuration.heartbeat || PING_INTERVAL
+ };
+ }
+ pingNextNum++;
+ self.send('ping', params, (function (pingNum) {
+ return function (error, result) {
+ if (error) {
+ Logger.debug("Error in ping request #" + pingNum + " (" +
+ error.message + ")");
+ if (pingNum > notReconnectIfNumLessThan) {
+ enabledPings = false;
+ updateNotReconnectIfLessThan();
+ Logger.debug("Server did not respond to ping message #" +
+ pingNum + ". Reconnecting... ");
+ ws.reconnectWs();
+ }
+ }
+ };
+ })(pingNextNum));
+ }
+ else {
+ Logger.debug("Trying to send ping, but ping is not enabled");
+ }
+ }
+ function usePing() {
+ if (!pingPongStarted) {
+ Logger.debug("Starting ping (if configured)");
+ pingPongStarted = true;
+ if (configuration.heartbeat != undefined) {
+ pingInterval = setInterval(sendPing, configuration.heartbeat);
+ sendPing();
+ }
+ }
+ }
+ this.close = function () {
+ Logger.debug("Closing jsonRpcClient explicitly by client");
+ if (pingInterval != undefined) {
+ Logger.debug("Clearing ping interval");
+ clearInterval(pingInterval);
+ }
+ pingPongStarted = false;
+ enabledPings = false;
+ if (configuration.sendCloseMessage) {
+ Logger.debug("Sending close message");
+ this.send('closeSession', null, function (error, result) {
+ if (error) {
+ Logger.error("Error sending close message: " + JSON.stringify(error));
+ }
+ ws.close();
+ });
+ }
+ else {
+ ws.close();
+ }
+ };
+ this.forceClose = function (millis) {
+ ws.forceClose(millis);
+ };
+ this.reconnect = function () {
+ ws.reconnectWs();
+ };
+}
+module.exports = JsonRpcClient;
+
+},{"../":43,"./transports/webSocketWithReconnection":42}],41:[function(require,module,exports){
+var WebSocketWithReconnection = require('./webSocketWithReconnection');
+exports.WebSocketWithReconnection = WebSocketWithReconnection;
+
+},{"./webSocketWithReconnection":42}],42:[function(require,module,exports){
+(function (global){
+"use strict";
+var BrowserWebSocket = global.WebSocket || global.MozWebSocket;
+var Logger = console;
+var MAX_RETRIES = 2000;
+var RETRY_TIME_MS = 3000;
+var CONNECTING = 0;
+var OPEN = 1;
+var CLOSING = 2;
+var CLOSED = 3;
+function WebSocketWithReconnection(config) {
+ var closing = false;
+ var registerMessageHandler;
+ var wsUri = config.uri;
+ var useSockJS = config.useSockJS;
+ var reconnecting = false;
+ var forcingDisconnection = false;
+ var ws;
+ if (useSockJS) {
+ ws = new SockJS(wsUri);
+ }
+ else {
+ ws = new WebSocket(wsUri);
+ }
+ ws.onopen = function () {
+ logConnected(ws, wsUri);
+ if (config.onconnected) {
+ config.onconnected();
+ }
+ };
+ ws.onerror = function (error) {
+ Logger.error("Could not connect to " + wsUri + " (invoking onerror if defined)", error);
+ if (config.onerror) {
+ config.onerror(error);
+ }
+ };
+ function logConnected(ws, wsUri) {
+ try {
+ Logger.debug("WebSocket connected to " + wsUri);
+ }
+ catch (e) {
+ Logger.error(e);
+ }
+ }
+ var reconnectionOnClose = function () {
+ if (ws.readyState === CLOSED) {
+ if (closing) {
+ Logger.debug("Connection closed by user");
+ }
+ else {
+ Logger.debug("Connection closed unexpectecly. Reconnecting...");
+ reconnectToSameUri(MAX_RETRIES, 1);
+ }
+ }
+ else {
+ Logger.debug("Close callback from previous websocket. Ignoring it");
+ }
+ };
+ ws.onclose = reconnectionOnClose;
+ function reconnectToSameUri(maxRetries, numRetries) {
+ Logger.debug("reconnectToSameUri (attempt #" + numRetries + ", max=" + maxRetries + ")");
+ if (numRetries === 1) {
+ if (reconnecting) {
+ Logger.warn("Trying to reconnectToNewUri when reconnecting... Ignoring this reconnection.");
+ return;
+ }
+ else {
+ reconnecting = true;
+ }
+ if (config.onreconnecting) {
+ config.onreconnecting();
+ }
+ }
+ if (forcingDisconnection) {
+ reconnectToNewUri(maxRetries, numRetries, wsUri);
+ }
+ else {
+ if (config.newWsUriOnReconnection) {
+ config.newWsUriOnReconnection(function (error, newWsUri) {
+ if (error) {
+ Logger.debug(error);
+ setTimeout(function () {
+ reconnectToSameUri(maxRetries, numRetries + 1);
+ }, RETRY_TIME_MS);
+ }
+ else {
+ reconnectToNewUri(maxRetries, numRetries, newWsUri);
+ }
+ });
+ }
+ else {
+ reconnectToNewUri(maxRetries, numRetries, wsUri);
+ }
+ }
+ }
+ function reconnectToNewUri(maxRetries, numRetries, reconnectWsUri) {
+ Logger.debug("Reconnection attempt #" + numRetries);
+ ws.close();
+ wsUri = reconnectWsUri || wsUri;
+ var newWs;
+ if (useSockJS) {
+ newWs = new SockJS(wsUri);
+ }
+ else {
+ newWs = new WebSocket(wsUri);
+ }
+ newWs.onopen = function () {
+ Logger.debug("Reconnected after " + numRetries + " attempts...");
+ logConnected(newWs, wsUri);
+ reconnecting = false;
+ registerMessageHandler();
+ if (config.onreconnected()) {
+ config.onreconnected();
+ }
+ newWs.onclose = reconnectionOnClose;
+ };
+ var onErrorOrClose = function (error) {
+ Logger.warn("Reconnection error: ", error);
+ if (numRetries === maxRetries) {
+ if (config.ondisconnect) {
+ config.ondisconnect();
+ }
+ }
+ else {
+ setTimeout(function () {
+ reconnectToSameUri(maxRetries, numRetries + 1);
+ }, RETRY_TIME_MS);
+ }
+ };
+ newWs.onerror = onErrorOrClose;
+ ws = newWs;
+ }
+ this.close = function () {
+ closing = true;
+ ws.close();
+ };
+ this.forceClose = function (millis) {
+ Logger.debug("Testing: Force WebSocket close");
+ if (millis) {
+ Logger.debug("Testing: Change wsUri for " + millis + " millis to simulate net failure");
+ var goodWsUri = wsUri;
+ wsUri = "wss://21.234.12.34.4:443/";
+ forcingDisconnection = true;
+ setTimeout(function () {
+ Logger.debug("Testing: Recover good wsUri " + goodWsUri);
+ wsUri = goodWsUri;
+ forcingDisconnection = false;
+ }, millis);
+ }
+ ws.close();
+ };
+ this.reconnectWs = function () {
+ Logger.debug("reconnectWs");
+ reconnectToSameUri(MAX_RETRIES, 1);
+ };
+ this.send = function (message) {
+ ws.send(message);
+ };
+ this.addEventListener = function (type, callback) {
+ registerMessageHandler = function () {
+ ws.addEventListener(type, callback);
+ };
+ registerMessageHandler();
+ };
+}
+module.exports = WebSocketWithReconnection;
+
+}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
+
+},{}],43:[function(require,module,exports){
+var defineProperty_IE8 = false;
+if (Object.defineProperty) {
+ try {
+ Object.defineProperty({}, "x", {});
+ }
+ catch (e) {
+ defineProperty_IE8 = true;
+ }
+}
+if (!Function.prototype.bind) {
+ Function.prototype.bind = function (oThis) {
+ if (typeof this !== 'function') {
+ throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable');
+ }
+ var aArgs = Array.prototype.slice.call(arguments, 1), fToBind = this, fNOP = function () { }, fBound = function () {
+ return fToBind.apply(this instanceof fNOP && oThis
+ ? this
+ : oThis, aArgs.concat(Array.prototype.slice.call(arguments)));
+ };
+ fNOP.prototype = this.prototype;
+ fBound.prototype = new fNOP();
+ return fBound;
+ };
+}
+var EventEmitter = require('events').EventEmitter;
+var inherits = require('inherits');
+var packers = require('./packers');
+var Mapper = require('./Mapper');
+var BASE_TIMEOUT = 5000;
+function unifyResponseMethods(responseMethods) {
+ if (!responseMethods)
+ return {};
+ for (var key in responseMethods) {
+ var value = responseMethods[key];
+ if (typeof value == 'string')
+ responseMethods[key] =
+ {
+ response: value
+ };
+ }
+ ;
+ return responseMethods;
+}
+;
+function unifyTransport(transport) {
+ if (!transport)
+ return;
+ if (transport instanceof Function)
+ return { send: transport };
+ if (transport.send instanceof Function)
+ return transport;
+ if (transport.postMessage instanceof Function) {
+ transport.send = transport.postMessage;
+ return transport;
+ }
+ if (transport.write instanceof Function) {
+ transport.send = transport.write;
+ return transport;
+ }
+ if (transport.onmessage !== undefined)
+ return;
+ if (transport.pause instanceof Function)
+ return;
+ throw new SyntaxError("Transport is not a function nor a valid object");
+}
+;
+function RpcNotification(method, params) {
+ if (defineProperty_IE8) {
+ this.method = method;
+ this.params = params;
+ }
+ else {
+ Object.defineProperty(this, 'method', { value: method, enumerable: true });
+ Object.defineProperty(this, 'params', { value: params, enumerable: true });
+ }
+}
+;
+function RpcBuilder(packer, options, transport, onRequest) {
+ var self = this;
+ if (!packer)
+ throw new SyntaxError('Packer is not defined');
+ if (!packer.pack || !packer.unpack)
+ throw new SyntaxError('Packer is invalid');
+ var responseMethods = unifyResponseMethods(packer.responseMethods);
+ if (options instanceof Function) {
+ if (transport != undefined)
+ throw new SyntaxError("There can't be parameters after onRequest");
+ onRequest = options;
+ transport = undefined;
+ options = undefined;
+ }
+ ;
+ if (options && options.send instanceof Function) {
+ if (transport && !(transport instanceof Function))
+ throw new SyntaxError("Only a function can be after transport");
+ onRequest = transport;
+ transport = options;
+ options = undefined;
+ }
+ ;
+ if (transport instanceof Function) {
+ if (onRequest != undefined)
+ throw new SyntaxError("There can't be parameters after onRequest");
+ onRequest = transport;
+ transport = undefined;
+ }
+ ;
+ if (transport && transport.send instanceof Function)
+ if (onRequest && !(onRequest instanceof Function))
+ throw new SyntaxError("Only a function can be after transport");
+ options = options || {};
+ EventEmitter.call(this);
+ if (onRequest)
+ this.on('request', onRequest);
+ if (defineProperty_IE8)
+ this.peerID = options.peerID;
+ else
+ Object.defineProperty(this, 'peerID', { value: options.peerID });
+ var max_retries = options.max_retries || 0;
+ function transportMessage(event) {
+ self.decode(event.data || event);
+ }
+ ;
+ this.getTransport = function () {
+ return transport;
+ };
+ this.setTransport = function (value) {
+ if (transport) {
+ if (transport.removeEventListener)
+ transport.removeEventListener('message', transportMessage);
+ else if (transport.removeListener)
+ transport.removeListener('data', transportMessage);
+ }
+ ;
+ if (value) {
+ if (value.addEventListener)
+ value.addEventListener('message', transportMessage);
+ else if (value.addListener)
+ value.addListener('data', transportMessage);
+ }
+ ;
+ transport = unifyTransport(value);
+ };
+ if (!defineProperty_IE8)
+ Object.defineProperty(this, 'transport', {
+ get: this.getTransport.bind(this),
+ set: this.setTransport.bind(this)
+ });
+ this.setTransport(transport);
+ var request_timeout = options.request_timeout || BASE_TIMEOUT;
+ var ping_request_timeout = options.ping_request_timeout || request_timeout;
+ var response_timeout = options.response_timeout || BASE_TIMEOUT;
+ var duplicates_timeout = options.duplicates_timeout || BASE_TIMEOUT;
+ var requestID = 0;
+ var requests = new Mapper();
+ var responses = new Mapper();
+ var processedResponses = new Mapper();
+ var message2Key = {};
+ function storeResponse(message, id, dest) {
+ var response = {
+ message: message,
+ timeout: setTimeout(function () {
+ responses.remove(id, dest);
+ }, response_timeout)
+ };
+ responses.set(response, id, dest);
+ }
+ ;
+ function storeProcessedResponse(ack, from) {
+ var timeout = setTimeout(function () {
+ processedResponses.remove(ack, from);
+ }, duplicates_timeout);
+ processedResponses.set(timeout, ack, from);
+ }
+ ;
+ function RpcRequest(method, params, id, from, transport) {
+ RpcNotification.call(this, method, params);
+ this.getTransport = function () {
+ return transport;
+ };
+ this.setTransport = function (value) {
+ transport = unifyTransport(value);
+ };
+ if (!defineProperty_IE8)
+ Object.defineProperty(this, 'transport', {
+ get: this.getTransport.bind(this),
+ set: this.setTransport.bind(this)
+ });
+ var response = responses.get(id, from);
+ if (!(transport || self.getTransport())) {
+ if (defineProperty_IE8)
+ this.duplicated = Boolean(response);
+ else
+ Object.defineProperty(this, 'duplicated', {
+ value: Boolean(response)
+ });
+ }
+ var responseMethod = responseMethods[method];
+ this.pack = packer.pack.bind(packer, this, id);
+ this.reply = function (error, result, transport) {
+ if (error instanceof Function || error && error.send instanceof Function) {
+ if (result != undefined)
+ throw new SyntaxError("There can't be parameters after callback");
+ transport = error;
+ result = null;
+ error = undefined;
+ }
+ else if (result instanceof Function
+ || result && result.send instanceof Function) {
+ if (transport != undefined)
+ throw new SyntaxError("There can't be parameters after callback");
+ transport = result;
+ result = null;
+ }
+ ;
+ transport = unifyTransport(transport);
+ if (response)
+ clearTimeout(response.timeout);
+ if (from != undefined) {
+ if (error)
+ error.dest = from;
+ if (result)
+ result.dest = from;
+ }
+ ;
+ var message;
+ if (error || result != undefined) {
+ if (self.peerID != undefined) {
+ if (error)
+ error.from = self.peerID;
+ else
+ result.from = self.peerID;
+ }
+ if (responseMethod) {
+ if (responseMethod.error == undefined && error)
+ message =
+ {
+ error: error
+ };
+ else {
+ var method = error
+ ? responseMethod.error
+ : responseMethod.response;
+ message =
+ {
+ method: method,
+ params: error || result
+ };
+ }
+ }
+ else
+ message =
+ {
+ error: error,
+ result: result
+ };
+ message = packer.pack(message, id);
+ }
+ else if (response)
+ message = response.message;
+ else
+ message = packer.pack({ result: null }, id);
+ storeResponse(message, id, from);
+ transport = transport || this.getTransport() || self.getTransport();
+ if (transport)
+ return transport.send(message);
+ return message;
+ };
+ }
+ ;
+ inherits(RpcRequest, RpcNotification);
+ function cancel(message) {
+ var key = message2Key[message];
+ if (!key)
+ return;
+ delete message2Key[message];
+ var request = requests.pop(key.id, key.dest);
+ if (!request)
+ return;
+ clearTimeout(request.timeout);
+ storeProcessedResponse(key.id, key.dest);
+ }
+ ;
+ this.cancel = function (message) {
+ if (message)
+ return cancel(message);
+ for (var message in message2Key)
+ cancel(message);
+ };
+ this.close = function () {
+ var transport = this.getTransport();
+ if (transport && transport.close)
+ transport.close();
+ this.cancel();
+ processedResponses.forEach(clearTimeout);
+ responses.forEach(function (response) {
+ clearTimeout(response.timeout);
+ });
+ };
+ this.encode = function (method, params, dest, transport, callback) {
+ if (params instanceof Function) {
+ if (dest != undefined)
+ throw new SyntaxError("There can't be parameters after callback");
+ callback = params;
+ transport = undefined;
+ dest = undefined;
+ params = undefined;
+ }
+ else if (dest instanceof Function) {
+ if (transport != undefined)
+ throw new SyntaxError("There can't be parameters after callback");
+ callback = dest;
+ transport = undefined;
+ dest = undefined;
+ }
+ else if (transport instanceof Function) {
+ if (callback != undefined)
+ throw new SyntaxError("There can't be parameters after callback");
+ callback = transport;
+ transport = undefined;
+ }
+ ;
+ if (self.peerID != undefined) {
+ params = params || {};
+ params.from = self.peerID;
+ }
+ ;
+ if (dest != undefined) {
+ params = params || {};
+ params.dest = dest;
+ }
+ ;
+ var message = {
+ method: method,
+ params: params
+ };
+ if (callback) {
+ var id = requestID++;
+ var retried = 0;
+ message = packer.pack(message, id);
+ function dispatchCallback(error, result) {
+ self.cancel(message);
+ callback(error, result);
+ }
+ ;
+ var request = {
+ message: message,
+ callback: dispatchCallback,
+ responseMethods: responseMethods[method] || {}
+ };
+ var encode_transport = unifyTransport(transport);
+ function sendRequest(transport) {
+ var rt = (method === 'ping' ? ping_request_timeout : request_timeout);
+ request.timeout = setTimeout(timeout, rt * Math.pow(2, retried++));
+ message2Key[message] = { id: id, dest: dest };
+ requests.set(request, id, dest);
+ transport = transport || encode_transport || self.getTransport();
+ if (transport)
+ return transport.send(message);
+ return message;
+ }
+ ;
+ function retry(transport) {
+ transport = unifyTransport(transport);
+ console.warn(retried + ' retry for request message:', message);
+ var timeout = processedResponses.pop(id, dest);
+ clearTimeout(timeout);
+ return sendRequest(transport);
+ }
+ ;
+ function timeout() {
+ if (retried < max_retries)
+ return retry(transport);
+ var error = new Error('Request has timed out');
+ error.request = message;
+ error.retry = retry;
+ dispatchCallback(error);
+ }
+ ;
+ return sendRequest(transport);
+ }
+ ;
+ message = packer.pack(message);
+ transport = transport || this.getTransport();
+ if (transport)
+ return transport.send(message);
+ return message;
+ };
+ this.decode = function (message, transport) {
+ if (!message)
+ throw new TypeError("Message is not defined");
+ try {
+ message = packer.unpack(message);
+ }
+ catch (e) {
+ return console.debug(e, message);
+ }
+ ;
+ var id = message.id;
+ var ack = message.ack;
+ var method = message.method;
+ var params = message.params || {};
+ var from = params.from;
+ var dest = params.dest;
+ if (self.peerID != undefined && from == self.peerID)
+ return;
+ if (id == undefined && ack == undefined) {
+ var notification = new RpcNotification(method, params);
+ if (self.emit('request', notification))
+ return;
+ return notification;
+ }
+ ;
+ function processRequest() {
+ transport = unifyTransport(transport) || self.getTransport();
+ if (transport) {
+ var response = responses.get(id, from);
+ if (response)
+ return transport.send(response.message);
+ }
+ ;
+ var idAck = (id != undefined) ? id : ack;
+ var request = new RpcRequest(method, params, idAck, from, transport);
+ if (self.emit('request', request))
+ return;
+ return request;
+ }
+ ;
+ function processResponse(request, error, result) {
+ request.callback(error, result);
+ }
+ ;
+ function duplicatedResponse(timeout) {
+ console.warn("Response already processed", message);
+ clearTimeout(timeout);
+ storeProcessedResponse(ack, from);
+ }
+ ;
+ if (method) {
+ if (dest == undefined || dest == self.peerID) {
+ var request = requests.get(ack, from);
+ if (request) {
+ var responseMethods = request.responseMethods;
+ if (method == responseMethods.error)
+ return processResponse(request, params);
+ if (method == responseMethods.response)
+ return processResponse(request, null, params);
+ return processRequest();
+ }
+ var processed = processedResponses.get(ack, from);
+ if (processed)
+ return duplicatedResponse(processed);
+ }
+ return processRequest();
+ }
+ ;
+ var error = message.error;
+ var result = message.result;
+ if (error && error.dest && error.dest != self.peerID)
+ return;
+ if (result && result.dest && result.dest != self.peerID)
+ return;
+ var request = requests.get(ack, from);
+ if (!request) {
+ var processed = processedResponses.get(ack, from);
+ if (processed)
+ return duplicatedResponse(processed);
+ return console.warn("No callback was defined for this message", message);
+ }
+ ;
+ processResponse(request, error, result);
+ };
+}
+;
+inherits(RpcBuilder, EventEmitter);
+RpcBuilder.RpcNotification = RpcNotification;
+module.exports = RpcBuilder;
+var clients = require('./clients');
+var transports = require('./clients/transports');
+RpcBuilder.clients = clients;
+RpcBuilder.clients.transports = transports;
+RpcBuilder.packers = packers;
+
+},{"./Mapper":38,"./clients":39,"./clients/transports":41,"./packers":46,"events":1,"inherits":6}],44:[function(require,module,exports){
+function pack(message, id) {
+ var result = {
+ jsonrpc: "2.0"
+ };
+ if (message.method) {
+ result.method = message.method;
+ if (message.params)
+ result.params = message.params;
+ if (id != undefined)
+ result.id = id;
+ }
+ else if (id != undefined) {
+ if (message.error) {
+ if (message.result !== undefined)
+ throw new TypeError("Both result and error are defined");
+ result.error = message.error;
+ }
+ else if (message.result !== undefined)
+ result.result = message.result;
+ else
+ throw new TypeError("No result or error is defined");
+ result.id = id;
+ }
+ ;
+ return JSON.stringify(result);
+}
+;
+function unpack(message) {
+ var result = message;
+ if (typeof message === 'string' || message instanceof String) {
+ result = JSON.parse(message);
+ }
+ var version = result.jsonrpc;
+ if (version !== '2.0')
+ throw new TypeError("Invalid JsonRPC version '" + version + "': " + message);
+ if (result.method == undefined) {
+ if (result.id == undefined)
+ throw new TypeError("Invalid message: " + message);
+ var result_defined = result.result !== undefined;
+ var error_defined = result.error !== undefined;
+ if (result_defined && error_defined)
+ throw new TypeError("Both result and error are defined: " + message);
+ if (!result_defined && !error_defined)
+ throw new TypeError("No result or error is defined: " + message);
+ result.ack = result.id;
+ delete result.id;
+ }
+ return result;
+}
+;
+exports.pack = pack;
+exports.unpack = unpack;
+
+},{}],45:[function(require,module,exports){
+function pack(message) {
+ throw new TypeError("Not yet implemented");
+}
+;
+function unpack(message) {
+ throw new TypeError("Not yet implemented");
+}
+;
+exports.pack = pack;
+exports.unpack = unpack;
+
+},{}],46:[function(require,module,exports){
+var JsonRPC = require('./JsonRPC');
+var XmlRPC = require('./XmlRPC');
+exports.JsonRPC = JsonRPC;
+exports.XmlRPC = XmlRPC;
+
+},{"./JsonRPC":44,"./XmlRPC":45}],47:[function(require,module,exports){
+window.getScreenId = function (callback, custom_parameter) {
+ if (navigator.userAgent.indexOf('Edge') !== -1 && (!!navigator.msSaveOrOpenBlob || !!navigator.msSaveBlob)) {
+ callback({
+ video: true
+ });
+ return;
+ }
+ if (!!navigator.mozGetUserMedia) {
+ callback(null, 'firefox', {
+ video: {
+ mozMediaSource: 'window',
+ mediaSource: 'window'
+ }
+ });
+ return;
+ }
+ window.addEventListener('message', onIFrameCallback);
+ function onIFrameCallback(event) {
+ if (!event.data)
+ return;
+ if (event.data.chromeMediaSourceId) {
+ if (event.data.chromeMediaSourceId === 'PermissionDeniedError') {
+ callback('permission-denied');
+ }
+ else {
+ callback(null, event.data.chromeMediaSourceId, getScreenConstraints(null, event.data.chromeMediaSourceId, event.data.canRequestAudioTrack));
+ }
+ window.removeEventListener('message', onIFrameCallback);
+ }
+ if (event.data.chromeExtensionStatus) {
+ callback(event.data.chromeExtensionStatus, null, getScreenConstraints(event.data.chromeExtensionStatus));
+ window.removeEventListener('message', onIFrameCallback);
+ }
+ }
+ if (!custom_parameter) {
+ setTimeout(postGetSourceIdMessage, 100);
+ }
+ else {
+ setTimeout(function () {
+ postGetSourceIdMessage(custom_parameter);
+ }, 100);
+ }
+};
+function getScreenConstraints(error, sourceId, canRequestAudioTrack) {
+ var screen_constraints = {
+ audio: false,
+ video: {
+ mandatory: {
+ chromeMediaSource: error ? 'screen' : 'desktop',
+ maxWidth: window.screen.width > 1920 ? window.screen.width : 1920,
+ maxHeight: window.screen.height > 1080 ? window.screen.height : 1080
+ },
+ optional: []
+ }
+ };
+ if (!!canRequestAudioTrack) {
+ screen_constraints.audio = {
+ mandatory: {
+ chromeMediaSource: error ? 'screen' : 'desktop',
+ },
+ optional: []
+ };
+ }
+ if (sourceId) {
+ screen_constraints.video.mandatory.chromeMediaSourceId = sourceId;
+ if (screen_constraints.audio && screen_constraints.audio.mandatory) {
+ screen_constraints.audio.mandatory.chromeMediaSourceId = sourceId;
+ }
+ }
+ return screen_constraints;
+}
+function postGetSourceIdMessage(custom_parameter) {
+ if (!iframe) {
+ loadIFrame(function () {
+ postGetSourceIdMessage(custom_parameter);
+ });
+ return;
+ }
+ if (!iframe.isLoaded) {
+ setTimeout(function () {
+ postGetSourceIdMessage(custom_parameter);
+ }, 100);
+ return;
+ }
+ if (!custom_parameter) {
+ iframe.contentWindow.postMessage({
+ captureSourceId: true
+ }, '*');
+ }
+ else if (!!custom_parameter.forEach) {
+ iframe.contentWindow.postMessage({
+ captureCustomSourceId: custom_parameter
+ }, '*');
+ }
+ else {
+ iframe.contentWindow.postMessage({
+ captureSourceIdWithAudio: true
+ }, '*');
+ }
+}
+var iframe;
+window.getScreenConstraints = function (callback) {
+ loadIFrame(function () {
+ getScreenId(function (error, sourceId, screen_constraints) {
+ if (!screen_constraints) {
+ screen_constraints = {
+ video: true
+ };
+ }
+ callback(error, screen_constraints.video);
+ });
+ });
+};
+function loadIFrame(loadCallback) {
+ if (iframe) {
+ loadCallback();
+ return;
+ }
+ iframe = document.createElement('iframe');
+ iframe.onload = function () {
+ iframe.isLoaded = true;
+ loadCallback();
+ };
+ iframe.src = 'https://openvidu.github.io/openvidu-screen-sharing-chrome-extension/';
+ iframe.style.display = 'none';
+ (document.body || document.documentElement).appendChild(iframe);
+}
+window.getChromeExtensionStatus = function (callback) {
+ if (!!navigator.mozGetUserMedia) {
+ callback('installed-enabled');
+ return;
+ }
+ window.addEventListener('message', onIFrameCallback);
+ function onIFrameCallback(event) {
+ if (!event.data)
+ return;
+ if (event.data.chromeExtensionStatus) {
+ callback(event.data.chromeExtensionStatus);
+ window.removeEventListener('message', onIFrameCallback);
+ }
+ }
+ setTimeout(postGetChromeExtensionStatusMessage, 100);
+};
+function postGetChromeExtensionStatusMessage() {
+ if (!iframe) {
+ loadIFrame(postGetChromeExtensionStatusMessage);
+ return;
+ }
+ if (!iframe.isLoaded) {
+ setTimeout(postGetChromeExtensionStatusMessage, 100);
+ return;
+ }
+ iframe.contentWindow.postMessage({
+ getChromeExtensionStatus: true
+ }, '*');
+}
+exports.getScreenId = getScreenId;
+
+},{}],48:[function(require,module,exports){
+var chromeMediaSource = 'screen';
+var sourceId;
+var screenCallback;
+var isFirefox = typeof window.InstallTrigger !== 'undefined';
+var isOpera = !!window.opera || navigator.userAgent.indexOf(' OPR/') >= 0;
+var isChrome = !!window.chrome && !isOpera;
+window.addEventListener('message', function (event) {
+ if (event.origin != window.location.origin) {
+ return;
+ }
+ onMessageCallback(event.data);
+});
+function onMessageCallback(data) {
+ if (data == 'PermissionDeniedError') {
+ if (screenCallback)
+ return screenCallback('PermissionDeniedError');
+ else
+ throw new Error('PermissionDeniedError');
+ }
+ if (data == 'rtcmulticonnection-extension-loaded') {
+ chromeMediaSource = 'desktop';
+ }
+ if (data.sourceId && screenCallback) {
+ screenCallback(sourceId = data.sourceId, data.canRequestAudioTrack === true);
+ }
+}
+function isChromeExtensionAvailable(callback) {
+ if (!callback)
+ return;
+ if (chromeMediaSource == 'desktop')
+ return callback(true);
+ window.postMessage('are-you-there', '*');
+ setTimeout(function () {
+ if (chromeMediaSource == 'screen') {
+ callback(false);
+ }
+ else
+ callback(true);
+ }, 2000);
+}
+function getSourceId(callback) {
+ if (!callback)
+ throw '"callback" parameter is mandatory.';
+ if (sourceId)
+ return callback(sourceId);
+ screenCallback = callback;
+ window.postMessage('get-sourceId', '*');
+}
+function getCustomSourceId(arr, callback) {
+ if (!arr || !arr.forEach)
+ throw '"arr" parameter is mandatory and it must be an array.';
+ if (!callback)
+ throw '"callback" parameter is mandatory.';
+ if (sourceId)
+ return callback(sourceId);
+ screenCallback = callback;
+ window.postMessage({
+ 'get-custom-sourceId': arr
+ }, '*');
+}
+function getSourceIdWithAudio(callback) {
+ if (!callback)
+ throw '"callback" parameter is mandatory.';
+ if (sourceId)
+ return callback(sourceId);
+ screenCallback = callback;
+ window.postMessage('audio-plus-tab', '*');
+}
+function getChromeExtensionStatus(extensionid, callback) {
+ if (isFirefox)
+ return callback('not-chrome');
+ if (arguments.length != 2) {
+ callback = extensionid;
+ extensionid = 'lfcgfepafnobdloecchnfaclibenjold';
+ }
+ var image = document.createElement('img');
+ image.src = 'chrome-extension://' + extensionid + '/icon.png';
+ image.onload = function () {
+ chromeMediaSource = 'screen';
+ window.postMessage('are-you-there', '*');
+ setTimeout(function () {
+ if (chromeMediaSource == 'screen') {
+ callback('installed-disabled');
+ }
+ else
+ callback('installed-enabled');
+ }, 2000);
+ };
+ image.onerror = function () {
+ callback('not-installed');
+ };
+}
+function getScreenConstraintsWithAudio(callback) {
+ getScreenConstraints(callback, true);
+}
+function getScreenConstraints(callback, captureSourceIdWithAudio) {
+ sourceId = '';
+ var firefoxScreenConstraints = {
+ mozMediaSource: 'window',
+ mediaSource: 'window'
+ };
+ if (isFirefox)
+ return callback(null, firefoxScreenConstraints);
+ var screen_constraints = {
+ mandatory: {
+ chromeMediaSource: chromeMediaSource,
+ maxWidth: screen.width > 1920 ? screen.width : 1920,
+ maxHeight: screen.height > 1080 ? screen.height : 1080
+ },
+ optional: []
+ };
+ if (chromeMediaSource == 'desktop' && !sourceId) {
+ if (captureSourceIdWithAudio) {
+ getSourceIdWithAudio(function (sourceId, canRequestAudioTrack) {
+ screen_constraints.mandatory.chromeMediaSourceId = sourceId;
+ if (canRequestAudioTrack) {
+ screen_constraints.canRequestAudioTrack = true;
+ }
+ callback(sourceId == 'PermissionDeniedError' ? sourceId : null, screen_constraints);
+ });
+ }
+ else {
+ getSourceId(function (sourceId) {
+ screen_constraints.mandatory.chromeMediaSourceId = sourceId;
+ callback(sourceId == 'PermissionDeniedError' ? sourceId : null, screen_constraints);
+ });
+ }
+ return;
+ }
+ if (chromeMediaSource == 'desktop') {
+ screen_constraints.mandatory.chromeMediaSourceId = sourceId;
+ }
+ callback(null, screen_constraints);
+}
+exports.getScreenConstraints = getScreenConstraints;
+exports.getScreenConstraintsWithAudio = getScreenConstraintsWithAudio;
+exports.isChromeExtensionAvailable = isChromeExtensionAvailable;
+exports.getChromeExtensionStatus = getChromeExtensionStatus;
+exports.getSourceId = getSourceId;
+
+},{}],49:[function(require,module,exports){
+"use strict";
+var __extends = (this && this.__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 __());
+ };
+})();
+Object.defineProperty(exports, "__esModule", { value: true });
+var freeice = require("freeice");
+var uuid = require("uuid");
+var platform = require("platform");
+var WebRtcPeer = (function () {
+ function WebRtcPeer(configuration) {
+ var _this = this;
+ this.configuration = configuration;
+ this.remoteCandidatesQueue = [];
+ this.localCandidatesQueue = [];
+ this.iceCandidateList = [];
+ this.candidategatheringdone = false;
+ this.configuration.iceServers = (!!this.configuration.iceServers && this.configuration.iceServers.length > 0) ? this.configuration.iceServers : freeice();
+ this.pc = new RTCPeerConnection({ iceServers: this.configuration.iceServers });
+ this.id = !!configuration.id ? configuration.id : uuid.v4();
+ this.pc.onicecandidate = function (event) {
+ var candidate = event.candidate;
+ if (candidate) {
+ _this.localCandidatesQueue.push({ candidate: candidate.candidate });
+ _this.candidategatheringdone = false;
+ _this.configuration.onicecandidate(event.candidate);
+ }
+ else if (!_this.candidategatheringdone) {
+ _this.candidategatheringdone = true;
+ }
+ };
+ this.pc.onsignalingstatechange = function () {
+ if (_this.pc.signalingState === 'stable') {
+ while (_this.iceCandidateList.length > 0) {
+ _this.pc.addIceCandidate(_this.iceCandidateList.shift());
+ }
+ }
+ };
+ this.start();
+ }
+ WebRtcPeer.prototype.start = function () {
+ var _this = this;
+ return new Promise(function (resolve, reject) {
+ if (_this.pc.signalingState === 'closed') {
+ reject('The peer connection object is in "closed" state. This is most likely due to an invocation of the dispose method before accepting in the dialogue');
+ }
+ if (!!_this.configuration.mediaStream) {
+ _this.pc.addStream(_this.configuration.mediaStream);
+ }
+ if (_this.configuration.mode === 'sendonly' &&
+ (platform.name === 'Chrome' && platform.version.toString().substring(0, 2) === '39')) {
+ _this.configuration.mode = 'sendrecv';
+ }
+ resolve();
+ });
+ };
+ WebRtcPeer.prototype.dispose = function () {
+ var _this = this;
+ console.debug('Disposing WebRtcPeer');
+ try {
+ if (this.pc) {
+ if (this.pc.signalingState === 'closed') {
+ return;
+ }
+ this.remoteCandidatesQueue = [];
+ this.localCandidatesQueue = [];
+ this.pc.getLocalStreams().forEach(function (str) {
+ _this.streamStop(str);
+ });
+ this.pc.close();
+ }
+ }
+ catch (err) {
+ console.warn('Exception disposing webrtc peer ' + err);
+ }
+ };
+ WebRtcPeer.prototype.generateOffer = function () {
+ var _this = this;
+ return new Promise(function (resolve, reject) {
+ var offerAudio, offerVideo = true;
+ if (!!_this.configuration.mediaConstraints) {
+ offerAudio = (typeof _this.configuration.mediaConstraints.audio === 'boolean') ?
+ _this.configuration.mediaConstraints.audio : true;
+ offerVideo = (typeof _this.configuration.mediaConstraints.video === 'boolean') ?
+ _this.configuration.mediaConstraints.video : true;
+ }
+ var constraints = {
+ offerToReceiveAudio: +(_this.configuration.mode !== 'sendonly' && offerAudio),
+ offerToReceiveVideo: +(_this.configuration.mode !== 'sendonly' && offerVideo)
+ };
+ console.debug('RTCPeerConnection constraints: ' + JSON.stringify(constraints));
+ _this.pc.createOffer(constraints).then(function (offer) {
+ console.debug('Created SDP offer');
+ return _this.pc.setLocalDescription(offer);
+ }).then(function () {
+ var localDescription = _this.pc.localDescription;
+ if (!!localDescription) {
+ console.debug('Local description set', localDescription.sdp);
+ resolve(localDescription.sdp);
+ }
+ else {
+ reject('Local description is not defined');
+ }
+ }).catch(function (error) { return reject(error); });
+ });
+ };
+ WebRtcPeer.prototype.processOffer = function (sdpOffer) {
+ var _this = this;
+ return new Promise(function (resolve, reject) {
+ var offer = {
+ type: 'offer',
+ sdp: sdpOffer
+ };
+ console.debug('SDP offer received, setting remote description');
+ if (_this.pc.signalingState === 'closed') {
+ reject('PeerConnection is closed');
+ }
+ _this.pc.setRemoteDescription(offer)
+ .then(function () {
+ return _this.pc.createAnswer();
+ }).then(function (answer) {
+ console.debug('Created SDP answer');
+ return _this.pc.setLocalDescription(answer);
+ }).then(function () {
+ var localDescription = _this.pc.localDescription;
+ if (!!localDescription) {
+ console.debug('Local description set', localDescription.sdp);
+ resolve(localDescription.sdp);
+ }
+ else {
+ reject('Local description is not defined');
+ }
+ }).catch(function (error) { return reject(error); });
+ });
+ };
+ WebRtcPeer.prototype.processAnswer = function (sdpAnswer) {
+ var _this = this;
+ return new Promise(function (resolve, reject) {
+ var answer = {
+ type: 'answer',
+ sdp: sdpAnswer
+ };
+ console.debug('SDP answer received, setting remote description');
+ if (_this.pc.signalingState === 'closed') {
+ reject('RTCPeerConnection is closed');
+ }
+ _this.pc.setRemoteDescription(answer).then(function () { return resolve(); }).catch(function (error) { return reject(error); });
+ });
+ };
+ WebRtcPeer.prototype.addIceCandidate = function (iceCandidate) {
+ var _this = this;
+ return new Promise(function (resolve, reject) {
+ console.debug('Remote ICE candidate received', iceCandidate);
+ _this.remoteCandidatesQueue.push(iceCandidate);
+ switch (_this.pc.signalingState) {
+ case 'closed':
+ reject(new Error('PeerConnection object is closed'));
+ break;
+ case 'stable':
+ if (!!_this.pc.remoteDescription) {
+ _this.pc.addIceCandidate(iceCandidate).then(function () { return resolve(); }).catch(function (error) { return reject(error); });
+ }
+ break;
+ default:
+ _this.iceCandidateList.push(iceCandidate);
+ resolve();
+ }
+ });
+ };
+ WebRtcPeer.prototype.streamStop = function (stream) {
+ stream.getTracks().forEach(function (track) {
+ track.stop();
+ stream.removeTrack(track);
+ });
+ };
+ return WebRtcPeer;
+}());
+exports.WebRtcPeer = WebRtcPeer;
+var WebRtcPeerRecvonly = (function (_super) {
+ __extends(WebRtcPeerRecvonly, _super);
+ function WebRtcPeerRecvonly(configuration) {
+ var _this = this;
+ configuration.mode = 'recvonly';
+ _this = _super.call(this, configuration) || this;
+ return _this;
+ }
+ return WebRtcPeerRecvonly;
+}(WebRtcPeer));
+exports.WebRtcPeerRecvonly = WebRtcPeerRecvonly;
+var WebRtcPeerSendonly = (function (_super) {
+ __extends(WebRtcPeerSendonly, _super);
+ function WebRtcPeerSendonly(configuration) {
+ var _this = this;
+ configuration.mode = 'sendonly';
+ _this = _super.call(this, configuration) || this;
+ return _this;
+ }
+ return WebRtcPeerSendonly;
+}(WebRtcPeer));
+exports.WebRtcPeerSendonly = WebRtcPeerSendonly;
+var WebRtcPeerSendrecv = (function (_super) {
+ __extends(WebRtcPeerSendrecv, _super);
+ function WebRtcPeerSendrecv(configuration) {
+ var _this = this;
+ configuration.mode = 'sendrecv';
+ _this = _super.call(this, configuration) || this;
+ return _this;
+ }
+ return WebRtcPeerSendrecv;
+}(WebRtcPeer));
+exports.WebRtcPeerSendrecv = WebRtcPeerSendrecv;
+
+},{"freeice":2,"platform":8,"uuid":9}],50:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+var platform = require("platform");
+var WebRtcStats = (function () {
+ function WebRtcStats(stream) {
+ this.stream = stream;
+ this.webRtcStatsEnabled = false;
+ this.statsInterval = 1;
+ this.stats = {
+ inbound: {
+ audio: {
+ bytesReceived: 0,
+ packetsReceived: 0,
+ packetsLost: 0
+ },
+ video: {
+ bytesReceived: 0,
+ packetsReceived: 0,
+ packetsLost: 0,
+ framesDecoded: 0,
+ nackCount: 0
+ }
+ },
+ outbound: {
+ audio: {
+ bytesSent: 0,
+ packetsSent: 0,
+ },
+ video: {
+ bytesSent: 0,
+ packetsSent: 0,
+ framesEncoded: 0,
+ nackCount: 0
+ }
+ }
+ };
+ }
+ WebRtcStats.prototype.isEnabled = function () {
+ return this.webRtcStatsEnabled;
+ };
+ WebRtcStats.prototype.initWebRtcStats = function () {
+ var _this = this;
+ var elastestInstrumentation = localStorage.getItem('elastest-instrumentation');
+ if (elastestInstrumentation) {
+ console.warn('WebRtc stats enabled for stream ' + this.stream.streamId + ' of connection ' + this.stream.connection.connectionId);
+ this.webRtcStatsEnabled = true;
+ var instrumentation_1 = JSON.parse(elastestInstrumentation);
+ this.statsInterval = instrumentation_1.webrtc.interval;
+ console.warn('localStorage item: ' + JSON.stringify(instrumentation_1));
+ this.webRtcStatsIntervalId = setInterval(function () {
+ _this.sendStatsToHttpEndpoint(instrumentation_1);
+ }, this.statsInterval * 1000);
+ return;
+ }
+ console.debug('WebRtc stats not enabled');
+ };
+ WebRtcStats.prototype.stopWebRtcStats = function () {
+ if (this.webRtcStatsEnabled) {
+ clearInterval(this.webRtcStatsIntervalId);
+ console.warn('WebRtc stats stopped for disposed stream ' + this.stream.streamId + ' of connection ' + this.stream.connection.connectionId);
+ }
+ };
+ WebRtcStats.prototype.getSelectedIceCandidateInfo = function () {
+ var _this = this;
+ return new Promise(function (resolve, reject) {
+ _this.getStatsAgnostic(_this.stream.getRTCPeerConnection(), function (stats) {
+ if ((platform.name.indexOf('Chrome') !== -1) || (platform.name.indexOf('Opera') !== -1)) {
+ var localCandidateId = void 0, remoteCandidateId = void 0, googCandidatePair = void 0;
+ var localCandidates = {};
+ var remoteCandidates = {};
+ for (var key in stats) {
+ var stat = stats[key];
+ if (stat.type === 'localcandidate') {
+ localCandidates[stat.id] = stat;
+ }
+ else if (stat.type === 'remotecandidate') {
+ remoteCandidates[stat.id] = stat;
+ }
+ else if (stat.type === 'googCandidatePair' && (stat.googActiveConnection === 'true')) {
+ googCandidatePair = stat;
+ localCandidateId = stat.localCandidateId;
+ remoteCandidateId = stat.remoteCandidateId;
+ }
+ }
+ var finalLocalCandidate_1 = localCandidates[localCandidateId];
+ if (!!finalLocalCandidate_1) {
+ var candList = _this.stream.getLocalIceCandidateList();
+ var cand = candList.filter(function (c) {
+ return (!!c.candidate &&
+ c.candidate.indexOf(finalLocalCandidate_1.ipAddress) >= 0 &&
+ c.candidate.indexOf(finalLocalCandidate_1.portNumber) >= 0 &&
+ c.candidate.indexOf(finalLocalCandidate_1.priority) >= 0);
+ });
+ finalLocalCandidate_1.raw = !!cand[0] ? cand[0].candidate : 'ERROR: Cannot find local candidate in list of sent ICE candidates';
+ }
+ else {
+ finalLocalCandidate_1 = 'ERROR: No active local ICE candidate. Probably ICE-TCP is being used';
+ }
+ var finalRemoteCandidate_1 = remoteCandidates[remoteCandidateId];
+ if (!!finalRemoteCandidate_1) {
+ var candList = _this.stream.getRemoteIceCandidateList();
+ var cand = candList.filter(function (c) {
+ return (!!c.candidate &&
+ c.candidate.indexOf(finalRemoteCandidate_1.ipAddress) >= 0 &&
+ c.candidate.indexOf(finalRemoteCandidate_1.portNumber) >= 0 &&
+ c.candidate.indexOf(finalRemoteCandidate_1.priority) >= 0);
+ });
+ finalRemoteCandidate_1.raw = !!cand[0] ? cand[0].candidate : 'ERROR: Cannot find remote candidate in list of received ICE candidates';
+ }
+ else {
+ finalRemoteCandidate_1 = 'ERROR: No active remote ICE candidate. Probably ICE-TCP is being used';
+ }
+ resolve({
+ googCandidatePair: googCandidatePair,
+ localCandidate: finalLocalCandidate_1,
+ remoteCandidate: finalRemoteCandidate_1
+ });
+ }
+ else {
+ reject('Selected ICE candidate info only available for Chrome');
+ }
+ }, function (error) {
+ reject(error);
+ });
+ });
+ };
+ WebRtcStats.prototype.sendStatsToHttpEndpoint = function (instrumentation) {
+ var _this = this;
+ var sendPost = function (json) {
+ var http = new XMLHttpRequest();
+ var url = instrumentation.webrtc.httpEndpoint;
+ http.open('POST', url, true);
+ http.setRequestHeader('Content-type', 'application/json');
+ http.onreadystatechange = function () {
+ if (http.readyState === 4 && http.status === 200) {
+ console.log('WebRtc stats successfully sent to ' + url + ' for stream ' + _this.stream.streamId + ' of connection ' + _this.stream.connection.connectionId);
+ }
+ };
+ http.send(json);
+ };
+ var f = function (stats) {
+ if (platform.name.indexOf('Firefox') !== -1) {
+ stats.forEach(function (stat) {
+ var json = {};
+ if ((stat.type === 'inbound-rtp') &&
+ (stat.nackCount !== null &&
+ stat.isRemote === false &&
+ stat.id.startsWith('inbound') &&
+ stat.remoteId.startsWith('inbound'))) {
+ var metricId = 'webrtc_inbound_' + stat.mediaType + '_' + stat.ssrc;
+ var jit = stat.jitter * 1000;
+ var metrics = {
+ bytesReceived: (stat.bytesReceived - _this.stats.inbound[stat.mediaType].bytesReceived) / _this.statsInterval,
+ jitter: jit,
+ packetsReceived: (stat.packetsReceived - _this.stats.inbound[stat.mediaType].packetsReceived) / _this.statsInterval,
+ packetsLost: (stat.packetsLost - _this.stats.inbound[stat.mediaType].packetsLost) / _this.statsInterval
+ };
+ var units = {
+ bytesReceived: 'bytes',
+ jitter: 'ms',
+ packetsReceived: 'packets',
+ packetsLost: 'packets'
+ };
+ if (stat.mediaType === 'video') {
+ metrics['framesDecoded'] = (stat.framesDecoded - _this.stats.inbound.video.framesDecoded) / _this.statsInterval;
+ metrics['nackCount'] = (stat.nackCount - _this.stats.inbound.video.nackCount) / _this.statsInterval;
+ units['framesDecoded'] = 'frames';
+ units['nackCount'] = 'packets';
+ _this.stats.inbound.video.framesDecoded = stat.framesDecoded;
+ _this.stats.inbound.video.nackCount = stat.nackCount;
+ }
+ _this.stats.inbound[stat.mediaType].bytesReceived = stat.bytesReceived;
+ _this.stats.inbound[stat.mediaType].packetsReceived = stat.packetsReceived;
+ _this.stats.inbound[stat.mediaType].packetsLost = stat.packetsLost;
+ json = {
+ '@timestamp': new Date(stat.timestamp).toISOString(),
+ 'exec': instrumentation.exec,
+ 'component': instrumentation.component,
+ 'stream': 'webRtc',
+ 'type': metricId,
+ 'stream_type': 'composed_metrics',
+ 'units': units
+ };
+ json[metricId] = metrics;
+ sendPost(JSON.stringify(json));
+ }
+ else if ((stat.type === 'outbound-rtp') &&
+ (stat.isRemote === false &&
+ stat.id.toLowerCase().includes('outbound'))) {
+ var metricId = 'webrtc_outbound_' + stat.mediaType + '_' + stat.ssrc;
+ var metrics = {
+ bytesSent: (stat.bytesSent - _this.stats.outbound[stat.mediaType].bytesSent) / _this.statsInterval,
+ packetsSent: (stat.packetsSent - _this.stats.outbound[stat.mediaType].packetsSent) / _this.statsInterval
+ };
+ var units = {
+ bytesSent: 'bytes',
+ packetsSent: 'packets'
+ };
+ if (stat.mediaType === 'video') {
+ metrics['framesEncoded'] = (stat.framesEncoded - _this.stats.outbound.video.framesEncoded) / _this.statsInterval;
+ units['framesEncoded'] = 'frames';
+ _this.stats.outbound.video.framesEncoded = stat.framesEncoded;
+ }
+ _this.stats.outbound[stat.mediaType].bytesSent = stat.bytesSent;
+ _this.stats.outbound[stat.mediaType].packetsSent = stat.packetsSent;
+ json = {
+ '@timestamp': new Date(stat.timestamp).toISOString(),
+ 'exec': instrumentation.exec,
+ 'component': instrumentation.component,
+ 'stream': 'webRtc',
+ 'type': metricId,
+ 'stream_type': 'composed_metrics',
+ 'units': units
+ };
+ json[metricId] = metrics;
+ sendPost(JSON.stringify(json));
+ }
+ });
+ }
+ else if ((platform.name.indexOf('Chrome') !== -1) || (platform.name.indexOf('Opera') !== -1)) {
+ for (var _i = 0, _a = Object.keys(stats); _i < _a.length; _i++) {
+ var key = _a[_i];
+ var stat = stats[key];
+ if (stat.type === 'ssrc') {
+ var json = {};
+ if ('bytesReceived' in stat && ((stat.mediaType === 'audio' && 'audioOutputLevel' in stat) ||
+ (stat.mediaType === 'video' && 'qpSum' in stat))) {
+ var metricId = 'webrtc_inbound_' + stat.mediaType + '_' + stat.ssrc;
+ var metrics = {
+ bytesReceived: (stat.bytesReceived - _this.stats.inbound[stat.mediaType].bytesReceived) / _this.statsInterval,
+ jitter: stat.googJitterBufferMs,
+ packetsReceived: (stat.packetsReceived - _this.stats.inbound[stat.mediaType].packetsReceived) / _this.statsInterval,
+ packetsLost: (stat.packetsLost - _this.stats.inbound[stat.mediaType].packetsLost) / _this.statsInterval
+ };
+ var units = {
+ bytesReceived: 'bytes',
+ jitter: 'ms',
+ packetsReceived: 'packets',
+ packetsLost: 'packets'
+ };
+ if (stat.mediaType === 'video') {
+ metrics['framesDecoded'] = (stat.framesDecoded - _this.stats.inbound.video.framesDecoded) / _this.statsInterval;
+ metrics['nackCount'] = (stat.googNacksSent - _this.stats.inbound.video.nackCount) / _this.statsInterval;
+ units['framesDecoded'] = 'frames';
+ units['nackCount'] = 'packets';
+ _this.stats.inbound.video.framesDecoded = stat.framesDecoded;
+ _this.stats.inbound.video.nackCount = stat.googNacksSent;
+ }
+ _this.stats.inbound[stat.mediaType].bytesReceived = stat.bytesReceived;
+ _this.stats.inbound[stat.mediaType].packetsReceived = stat.packetsReceived;
+ _this.stats.inbound[stat.mediaType].packetsLost = stat.packetsLost;
+ json = {
+ '@timestamp': new Date(stat.timestamp).toISOString(),
+ 'exec': instrumentation.exec,
+ 'component': instrumentation.component,
+ 'stream': 'webRtc',
+ 'type': metricId,
+ 'stream_type': 'composed_metrics',
+ 'units': units
+ };
+ json[metricId] = metrics;
+ sendPost(JSON.stringify(json));
+ }
+ else if ('bytesSent' in stat) {
+ var metricId = 'webrtc_outbound_' + stat.mediaType + '_' + stat.ssrc;
+ var metrics = {
+ bytesSent: (stat.bytesSent - _this.stats.outbound[stat.mediaType].bytesSent) / _this.statsInterval,
+ packetsSent: (stat.packetsSent - _this.stats.outbound[stat.mediaType].packetsSent) / _this.statsInterval
+ };
+ var units = {
+ bytesSent: 'bytes',
+ packetsSent: 'packets'
+ };
+ if (stat.mediaType === 'video') {
+ metrics['framesEncoded'] = (stat.framesEncoded - _this.stats.outbound.video.framesEncoded) / _this.statsInterval;
+ units['framesEncoded'] = 'frames';
+ _this.stats.outbound.video.framesEncoded = stat.framesEncoded;
+ }
+ _this.stats.outbound[stat.mediaType].bytesSent = stat.bytesSent;
+ _this.stats.outbound[stat.mediaType].packetsSent = stat.packetsSent;
+ json = {
+ '@timestamp': new Date(stat.timestamp).toISOString(),
+ 'exec': instrumentation.exec,
+ 'component': instrumentation.component,
+ 'stream': 'webRtc',
+ 'type': metricId,
+ 'stream_type': 'composed_metrics',
+ 'units': units
+ };
+ json[metricId] = metrics;
+ sendPost(JSON.stringify(json));
+ }
+ }
+ }
+ }
+ };
+ this.getStatsAgnostic(this.stream.getRTCPeerConnection(), f, function (error) { console.log(error); });
+ };
+ WebRtcStats.prototype.standardizeReport = function (response) {
+ console.log(response);
+ var standardReport = {};
+ if (platform.name.indexOf('Firefox') !== -1) {
+ Object.keys(response).forEach(function (key) {
+ console.log(response[key]);
+ });
+ return response;
+ }
+ response.result().forEach(function (report) {
+ var standardStats = {
+ id: report.id,
+ timestamp: report.timestamp,
+ type: report.type
+ };
+ report.names().forEach(function (name) {
+ standardStats[name] = report.stat(name);
+ });
+ standardReport[standardStats.id] = standardStats;
+ });
+ return standardReport;
+ };
+ WebRtcStats.prototype.getStatsAgnostic = function (pc, successCb, failureCb) {
+ var _this = this;
+ if (platform.name.indexOf('Firefox') !== -1) {
+ return pc.getStats(null).then(function (response) {
+ var report = _this.standardizeReport(response);
+ successCb(report);
+ }).catch(failureCb);
+ }
+ else if ((platform.name.indexOf('Chrome') !== -1) || (platform.name.indexOf('Opera') !== -1)) {
+ return pc.getStats(function (response) {
+ var report = _this.standardizeReport(response);
+ successCb(report);
+ }, null, failureCb);
+ }
+ };
+ return WebRtcStats;
+}());
+exports.WebRtcStats = WebRtcStats;
+
+},{"platform":8}]},{},[16])
+//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL25vZGVfbW9kdWxlcy9icm93c2VyLXBhY2svX3ByZWx1ZGUuanMiLCIuLi9ub2RlX21vZHVsZXMvZXZlbnRzL2V2ZW50cy5qcyIsIi4uL25vZGVfbW9kdWxlcy9mcmVlaWNlL2luZGV4LmpzIiwiLi4vbm9kZV9tb2R1bGVzL2ZyZWVpY2Uvc3R1bi5qc29uIiwiLi4vbm9kZV9tb2R1bGVzL2ZyZWVpY2UvdHVybi5qc29uIiwiLi4vbm9kZV9tb2R1bGVzL2hhcmsvaGFyay5qcyIsIi4uL25vZGVfbW9kdWxlcy9pbmhlcml0cy9pbmhlcml0c19icm93c2VyLmpzIiwiLi4vbm9kZV9tb2R1bGVzL25vcm1hbGljZS9pbmRleC5qcyIsIi4uL25vZGVfbW9kdWxlcy9wbGF0Zm9ybS9wbGF0Zm9ybS5qcyIsIi4uL25vZGVfbW9kdWxlcy91dWlkL2luZGV4LmpzIiwiLi4vbm9kZV9tb2R1bGVzL3V1aWQvbGliL2J5dGVzVG9VdWlkLmpzIiwiLi4vbm9kZV9tb2R1bGVzL3V1aWQvbGliL3JuZy1icm93c2VyLmpzIiwiLi4vbm9kZV9tb2R1bGVzL3V1aWQvdjEuanMiLCIuLi9ub2RlX21vZHVsZXMvdXVpZC92NC5qcyIsIi4uL25vZGVfbW9kdWxlcy93aWxkZW1pdHRlci93aWxkZW1pdHRlci5qcyIsIi4uL25vZGVfbW9kdWxlcy93b2xmeTg3LWV2ZW50ZW1pdHRlci9FdmVudEVtaXR0ZXIuanMiLCJNYWluLnRzIiwiT3BlblZpZHUvQ29ubmVjdGlvbi50cyIsIk9wZW5WaWR1L0xvY2FsUmVjb3JkZXIudHMiLCJPcGVuVmlkdS9PcGVuVmlkdS50cyIsIk9wZW5WaWR1L1B1Ymxpc2hlci50cyIsIk9wZW5WaWR1L1Nlc3Npb24udHMiLCJPcGVuVmlkdS9TdHJlYW0udHMiLCJPcGVuVmlkdS9TdHJlYW1NYW5hZ2VyLnRzIiwiT3BlblZpZHUvU3Vic2NyaWJlci50cyIsIk9wZW5WaWR1SW50ZXJuYWwvRW51bXMvTG9jYWxSZWNvcmRlclN0YXRlLnRzIiwiT3BlblZpZHVJbnRlcm5hbC9FbnVtcy9PcGVuVmlkdUVycm9yLnRzIiwiT3BlblZpZHVJbnRlcm5hbC9FbnVtcy9WaWRlb0luc2VydE1vZGUudHMiLCJPcGVuVmlkdUludGVybmFsL0V2ZW50cy9Db25uZWN0aW9uRXZlbnQudHMiLCJPcGVuVmlkdUludGVybmFsL0V2ZW50cy9FdmVudC50cyIsIk9wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1B1Ymxpc2hlclNwZWFraW5nRXZlbnQudHMiLCJPcGVuVmlkdUludGVybmFsL0V2ZW50cy9SZWNvcmRpbmdFdmVudC50cyIsIk9wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1Nlc3Npb25EaXNjb25uZWN0ZWRFdmVudC50cyIsIk9wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1NpZ25hbEV2ZW50LnRzIiwiT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvU3RyZWFtRXZlbnQudHMiLCJPcGVuVmlkdUludGVybmFsL0V2ZW50cy9TdHJlYW1NYW5hZ2VyRXZlbnQudHMiLCJPcGVuVmlkdUludGVybmFsL0V2ZW50cy9TdHJlYW1Qcm9wZXJ0eUNoYW5nZWRFdmVudC50cyIsIk9wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1ZpZGVvRWxlbWVudEV2ZW50LnRzIiwiT3BlblZpZHVJbnRlcm5hbC9LdXJlbnRvVXRpbHMva3VyZW50by1qc29ucnBjL01hcHBlci5qcyIsIk9wZW5WaWR1SW50ZXJuYWwvS3VyZW50b1V0aWxzL2t1cmVudG8tanNvbnJwYy9jbGllbnRzL2luZGV4LmpzIiwiT3BlblZpZHVJbnRlcm5hbC9LdXJlbnRvVXRpbHMva3VyZW50by1qc29ucnBjL2NsaWVudHMvanNvbnJwY2NsaWVudC5qcyIsIk9wZW5WaWR1SW50ZXJuYWwvS3VyZW50b1V0aWxzL2t1cmVudG8tanNvbnJwYy9jbGllbnRzL3RyYW5zcG9ydHMvaW5kZXguanMiLCJPcGVuVmlkdUludGVybmFsL0t1cmVudG9VdGlscy9rdXJlbnRvLWpzb25ycGMvY2xpZW50cy90cmFuc3BvcnRzL3dlYlNvY2tldFdpdGhSZWNvbm5lY3Rpb24uanMiLCJPcGVuVmlkdUludGVybmFsL0t1cmVudG9VdGlscy9rdXJlbnRvLWpzb25ycGMvaW5kZXguanMiLCJPcGVuVmlkdUludGVybmFsL0t1cmVudG9VdGlscy9rdXJlbnRvLWpzb25ycGMvcGFja2Vycy9Kc29uUlBDLmpzIiwiT3BlblZpZHVJbnRlcm5hbC9LdXJlbnRvVXRpbHMva3VyZW50by1qc29ucnBjL3BhY2tlcnMvWG1sUlBDLmpzIiwiT3BlblZpZHVJbnRlcm5hbC9LdXJlbnRvVXRpbHMva3VyZW50by1qc29ucnBjL3BhY2tlcnMvaW5kZXguanMiLCJPcGVuVmlkdUludGVybmFsL1NjcmVlblNoYXJpbmcvU2NyZWVuLUNhcHR1cmluZy1BdXRvLmpzIiwiT3BlblZpZHVJbnRlcm5hbC9TY3JlZW5TaGFyaW5nL1NjcmVlbi1DYXB0dXJpbmcuanMiLCJPcGVuVmlkdUludGVybmFsL1dlYlJ0Y1BlZXIvV2ViUnRjUGVlci50cyIsIk9wZW5WaWR1SW50ZXJuYWwvV2ViUnRjU3RhdHMvV2ViUnRjU3RhdHMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7QUNBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzNnQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDekdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDaEJBO0FBQ0E7O0FDREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2xKQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdkJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUM1REE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7O0FDanNDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDUkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDeEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbENBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDN0dBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM3QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDekpBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7O0FDdGVBLGdEQUErQztBQUUvQyxJQUFJLE1BQU0s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bigpe2Z1bmN0aW9uIHIoZSxuLHQpe2Z1bmN0aW9uIG8oaSxmKXtpZighbltpXSl7aWYoIWVbaV0pe3ZhciBjPVwiZnVuY3Rpb25cIj09dHlwZW9mIHJlcXVpcmUmJnJlcXVpcmU7aWYoIWYmJmMpcmV0dXJuIGMoaSwhMCk7aWYodSlyZXR1cm4gdShpLCEwKTt2YXIgYT1uZXcgRXJyb3IoXCJDYW5ub3QgZmluZCBtb2R1bGUgJ1wiK2krXCInXCIpO3Rocm93IGEuY29kZT1cIk1PRFVMRV9OT1RfRk9VTkRcIixhfXZhciBwPW5baV09e2V4cG9ydHM6e319O2VbaV1bMF0uY2FsbChwLmV4cG9ydHMsZnVuY3Rpb24ocil7dmFyIG49ZVtpXVsxXVtyXTtyZXR1cm4gbyhufHxyKX0scCxwLmV4cG9ydHMscixlLG4sdCl9cmV0dXJuIG5baV0uZXhwb3J0c31mb3IodmFyIHU9XCJmdW5jdGlvblwiPT10eXBlb2YgcmVxdWlyZSYmcmVxdWlyZSxpPTA7aTx0Lmxlbmd0aDtpKyspbyh0W2ldKTtyZXR1cm4gb31yZXR1cm4gcn0pKCkiLCIvLyBDb3B5cmlnaHQgSm95ZW50LCBJbmMuIGFuZCBvdGhlciBOb2RlIGNvbnRyaWJ1dG9ycy5cbi8vXG4vLyBQZXJtaXNzaW9uIGlzIGhlcmVieSBncmFudGVkLCBmcmVlIG9mIGNoYXJnZSwgdG8gYW55IHBlcnNvbiBvYnRhaW5pbmcgYVxuLy8gY29weSBvZiB0aGlzIHNvZnR3YXJlIGFuZCBhc3NvY2lhdGVkIGRvY3VtZW50YXRpb24gZmlsZXMgKHRoZVxuLy8gXCJTb2Z0d2FyZVwiKSwgdG8gZGVhbCBpbiB0aGUgU29mdHdhcmUgd2l0aG91dCByZXN0cmljdGlvbiwgaW5jbHVkaW5nXG4vLyB3aXRob3V0IGxpbWl0YXRpb24gdGhlIHJpZ2h0cyB0byB1c2UsIGNvcHksIG1vZGlmeSwgbWVyZ2UsIHB1Ymxpc2gsXG4vLyBkaXN0cmlidXRlLCBzdWJsaWNlbnNlLCBhbmQvb3Igc2VsbCBjb3BpZXMgb2YgdGhlIFNvZnR3YXJlLCBhbmQgdG8gcGVybWl0XG4vLyBwZXJzb25zIHRvIHdob20gdGhlIFNvZnR3YXJlIGlzIGZ1cm5pc2hlZCB0byBkbyBzbywgc3ViamVjdCB0byB0aGVcbi8vIGZvbGxvd2luZyBjb25kaXRpb25zOlxuLy9cbi8vIFRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlIGFuZCB0aGlzIHBlcm1pc3Npb24gbm90aWNlIHNoYWxsIGJlIGluY2x1ZGVkXG4vLyBpbiBhbGwgY29waWVzIG9yIHN1YnN0YW50aWFsIHBvcnRpb25zIG9mIHRoZSBTb2Z0d2FyZS5cbi8vXG4vLyBUSEUgU09GVFdBUkUgSVMgUFJPVklERUQgXCJBUyBJU1wiLCBXSVRIT1VUIFdBUlJBTlRZIE9GIEFOWSBLSU5ELCBFWFBSRVNTXG4vLyBPUiBJTVBMSUVELCBJTkNMVURJTkcgQlVUIE5PVCBMSU1JVEVEIFRPIFRIRSBXQVJSQU5USUVTIE9GXG4vLyBNRVJDSEFOVEFCSUxJVFksIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFORCBOT05JTkZSSU5HRU1FTlQuIElOXG4vLyBOTyBFVkVOVCBTSEFMTCBUSEUgQVVUSE9SUyBPUiBDT1BZUklHSFQgSE9MREVSUyBCRSBMSUFCTEUgRk9SIEFOWSBDTEFJTSxcbi8vIERBTUFHRVMgT1IgT1RIRVIgTElBQklMSVRZLCBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgVE9SVCBPUlxuLy8gT1RIRVJXSVNFLCBBUklTSU5HIEZST00sIE9VVCBPRiBPUiBJTiBDT05ORUNUSU9OIFdJVEggVEhFIFNPRlRXQVJFIE9SIFRIRVxuLy8gVVNFIE9SIE9USEVSIERFQUxJTkdTIElOIFRIRSBTT0ZUV0FSRS5cblxudmFyIG9iamVjdENyZWF0ZSA9IE9iamVjdC5jcmVhdGUgfHwgb2JqZWN0Q3JlYXRlUG9seWZpbGxcbnZhciBvYmplY3RLZXlzID0gT2JqZWN0LmtleXMgfHwgb2JqZWN0S2V5c1BvbHlmaWxsXG52YXIgYmluZCA9IEZ1bmN0aW9uLnByb3RvdHlwZS5iaW5kIHx8IGZ1bmN0aW9uQmluZFBvbHlmaWxsXG5cbmZ1bmN0aW9uIEV2ZW50RW1pdHRlcigpIHtcbiAgaWYgKCF0aGlzLl9ldmVudHMgfHwgIU9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbCh0aGlzLCAnX2V2ZW50cycpKSB7XG4gICAgdGhpcy5fZXZlbnRzID0gb2JqZWN0Q3JlYXRlKG51bGwpO1xuICAgIHRoaXMuX2V2ZW50c0NvdW50ID0gMDtcbiAgfVxuXG4gIHRoaXMuX21heExpc3RlbmVycyA9IHRoaXMuX21heExpc3RlbmVycyB8fCB1bmRlZmluZWQ7XG59XG5tb2R1bGUuZXhwb3J0cyA9IEV2ZW50RW1pdHRlcjtcblxuLy8gQmFja3dhcmRzLWNvbXBhdCB3aXRoIG5vZGUgMC4xMC54XG5FdmVudEVtaXR0ZXIuRXZlbnRFbWl0dGVyID0gRXZlbnRFbWl0dGVyO1xuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLl9ldmVudHMgPSB1bmRlZmluZWQ7XG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLl9tYXhMaXN0ZW5lcnMgPSB1bmRlZmluZWQ7XG5cbi8vIEJ5IGRlZmF1bHQgRXZlbnRFbWl0dGVycyB3aWxsIHByaW50IGEgd2FybmluZyBpZiBtb3JlIHRoYW4gMTAgbGlzdGVuZXJzIGFyZVxuLy8gYWRkZWQgdG8gaXQuIFRoaXMgaXMgYSB1c2VmdWwgZGVmYXVsdCB3aGljaCBoZWxwcyBmaW5kaW5nIG1lbW9yeSBsZWFrcy5cbnZhciBkZWZhdWx0TWF4TGlzdGVuZXJzID0gMTA7XG5cbnZhciBoYXNEZWZpbmVQcm9wZXJ0eTtcbnRyeSB7XG4gIHZhciBvID0ge307XG4gIGlmIChPYmplY3QuZGVmaW5lUHJvcGVydHkpIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShvLCAneCcsIHsgdmFsdWU6IDAgfSk7XG4gIGhhc0RlZmluZVByb3BlcnR5ID0gby54ID09PSAwO1xufSBjYXRjaCAoZXJyKSB7IGhhc0RlZmluZVByb3BlcnR5ID0gZmFsc2UgfVxuaWYgKGhhc0RlZmluZVByb3BlcnR5KSB7XG4gIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShFdmVudEVtaXR0ZXIsICdkZWZhdWx0TWF4TGlzdGVuZXJzJywge1xuICAgIGVudW1lcmFibGU6IHRydWUsXG4gICAgZ2V0OiBmdW5jdGlvbigpIHtcbiAgICAgIHJldHVybiBkZWZhdWx0TWF4TGlzdGVuZXJzO1xuICAgIH0sXG4gICAgc2V0OiBmdW5jdGlvbihhcmcpIHtcbiAgICAgIC8vIGNoZWNrIHdoZXRoZXIgdGhlIGlucHV0IGlzIGEgcG9zaXRpdmUgbnVtYmVyICh3aG9zZSB2YWx1ZSBpcyB6ZXJvIG9yXG4gICAgICAvLyBncmVhdGVyIGFuZCBub3QgYSBOYU4pLlxuICAgICAgaWYgKHR5cGVvZiBhcmcgIT09ICdudW1iZXInIHx8IGFyZyA8IDAgfHwgYXJnICE9PSBhcmcpXG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ1wiZGVmYXVsdE1heExpc3RlbmVyc1wiIG11c3QgYmUgYSBwb3NpdGl2ZSBudW1iZXInKTtcbiAgICAgIGRlZmF1bHRNYXhMaXN0ZW5lcnMgPSBhcmc7XG4gICAgfVxuICB9KTtcbn0gZWxzZSB7XG4gIEV2ZW50RW1pdHRlci5kZWZhdWx0TWF4TGlzdGVuZXJzID0gZGVmYXVsdE1heExpc3RlbmVycztcbn1cblxuLy8gT2J2aW91c2x5IG5vdCBhbGwgRW1pdHRlcnMgc2hvdWxkIGJlIGxpbWl0ZWQgdG8gMTAuIFRoaXMgZnVuY3Rpb24gYWxsb3dzXG4vLyB0aGF0IHRvIGJlIGluY3JlYXNlZC4gU2V0IHRvIHplcm8gZm9yIHVubGltaXRlZC5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUuc2V0TWF4TGlzdGVuZXJzID0gZnVuY3Rpb24gc2V0TWF4TGlzdGVuZXJzKG4pIHtcbiAgaWYgKHR5cGVvZiBuICE9PSAnbnVtYmVyJyB8fCBuIDwgMCB8fCBpc05hTihuKSlcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdcIm5cIiBhcmd1bWVudCBtdXN0IGJlIGEgcG9zaXRpdmUgbnVtYmVyJyk7XG4gIHRoaXMuX21heExpc3RlbmVycyA9IG47XG4gIHJldHVybiB0aGlzO1xufTtcblxuZnVuY3Rpb24gJGdldE1heExpc3RlbmVycyh0aGF0KSB7XG4gIGlmICh0aGF0Ll9tYXhMaXN0ZW5lcnMgPT09IHVuZGVmaW5lZClcbiAgICByZXR1cm4gRXZlbnRFbWl0dGVyLmRlZmF1bHRNYXhMaXN0ZW5lcnM7XG4gIHJldHVybiB0aGF0Ll9tYXhMaXN0ZW5lcnM7XG59XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUuZ2V0TWF4TGlzdGVuZXJzID0gZnVuY3Rpb24gZ2V0TWF4TGlzdGVuZXJzKCkge1xuICByZXR1cm4gJGdldE1heExpc3RlbmVycyh0aGlzKTtcbn07XG5cbi8vIFRoZXNlIHN0YW5kYWxvbmUgZW1pdCogZnVuY3Rpb25zIGFyZSB1c2VkIHRvIG9wdGltaXplIGNhbGxpbmcgb2YgZXZlbnRcbi8vIGhhbmRsZXJzIGZvciBmYXN0IGNhc2VzIGJlY2F1c2UgZW1pdCgpIGl0c2VsZiBvZnRlbiBoYXMgYSB2YXJpYWJsZSBudW1iZXIgb2Zcbi8vIGFyZ3VtZW50cyBhbmQgY2FuIGJlIGRlb3B0aW1pemVkIGJlY2F1c2Ugb2YgdGhhdC4gVGhlc2UgZnVuY3Rpb25zIGFsd2F5cyBoYXZlXG4vLyB0aGUgc2FtZSBudW1iZXIgb2YgYXJndW1lbnRzIGFuZCB0aHVzIGRvIG5vdCBnZXQgZGVvcHRpbWl6ZWQsIHNvIHRoZSBjb2RlXG4vLyBpbnNpZGUgdGhlbSBjYW4gZXhlY3V0ZSBmYXN0ZXIuXG5mdW5jdGlvbiBlbWl0Tm9uZShoYW5kbGVyLCBpc0ZuLCBzZWxmKSB7XG4gIGlmIChpc0ZuKVxuICAgIGhhbmRsZXIuY2FsbChzZWxmKTtcbiAgZWxzZSB7XG4gICAgdmFyIGxlbiA9IGhhbmRsZXIubGVuZ3RoO1xuICAgIHZhciBsaXN0ZW5lcnMgPSBhcnJheUNsb25lKGhhbmRsZXIsIGxlbik7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW47ICsraSlcbiAgICAgIGxpc3RlbmVyc1tpXS5jYWxsKHNlbGYpO1xuICB9XG59XG5mdW5jdGlvbiBlbWl0T25lKGhhbmRsZXIsIGlzRm4sIHNlbGYsIGFyZzEpIHtcbiAgaWYgKGlzRm4pXG4gICAgaGFuZGxlci5jYWxsKHNlbGYsIGFyZzEpO1xuICBlbHNlIHtcbiAgICB2YXIgbGVuID0gaGFuZGxlci5sZW5ndGg7XG4gICAgdmFyIGxpc3RlbmVycyA9IGFycmF5Q2xvbmUoaGFuZGxlciwgbGVuKTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgKytpKVxuICAgICAgbGlzdGVuZXJzW2ldLmNhbGwoc2VsZiwgYXJnMSk7XG4gIH1cbn1cbmZ1bmN0aW9uIGVtaXRUd28oaGFuZGxlciwgaXNGbiwgc2VsZiwgYXJnMSwgYXJnMikge1xuICBpZiAoaXNGbilcbiAgICBoYW5kbGVyLmNhbGwoc2VsZiwgYXJnMSwgYXJnMik7XG4gIGVsc2Uge1xuICAgIHZhciBsZW4gPSBoYW5kbGVyLmxlbmd0aDtcbiAgICB2YXIgbGlzdGVuZXJzID0gYXJyYXlDbG9uZShoYW5kbGVyLCBsZW4pO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuOyArK2kpXG4gICAgICBsaXN0ZW5lcnNbaV0uY2FsbChzZWxmLCBhcmcxLCBhcmcyKTtcbiAgfVxufVxuZnVuY3Rpb24gZW1pdFRocmVlKGhhbmRsZXIsIGlzRm4sIHNlbGYsIGFyZzEsIGFyZzIsIGFyZzMpIHtcbiAgaWYgKGlzRm4pXG4gICAgaGFuZGxlci5jYWxsKHNlbGYsIGFyZzEsIGFyZzIsIGFyZzMpO1xuICBlbHNlIHtcbiAgICB2YXIgbGVuID0gaGFuZGxlci5sZW5ndGg7XG4gICAgdmFyIGxpc3RlbmVycyA9IGFycmF5Q2xvbmUoaGFuZGxlciwgbGVuKTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgKytpKVxuICAgICAgbGlzdGVuZXJzW2ldLmNhbGwoc2VsZiwgYXJnMSwgYXJnMiwgYXJnMyk7XG4gIH1cbn1cblxuZnVuY3Rpb24gZW1pdE1hbnkoaGFuZGxlciwgaXNGbiwgc2VsZiwgYXJncykge1xuICBpZiAoaXNGbilcbiAgICBoYW5kbGVyLmFwcGx5KHNlbGYsIGFyZ3MpO1xuICBlbHNlIHtcbiAgICB2YXIgbGVuID0gaGFuZGxlci5sZW5ndGg7XG4gICAgdmFyIGxpc3RlbmVycyA9IGFycmF5Q2xvbmUoaGFuZGxlciwgbGVuKTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgKytpKVxuICAgICAgbGlzdGVuZXJzW2ldLmFwcGx5KHNlbGYsIGFyZ3MpO1xuICB9XG59XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUuZW1pdCA9IGZ1bmN0aW9uIGVtaXQodHlwZSkge1xuICB2YXIgZXIsIGhhbmRsZXIsIGxlbiwgYXJncywgaSwgZXZlbnRzO1xuICB2YXIgZG9FcnJvciA9ICh0eXBlID09PSAnZXJyb3InKTtcblxuICBldmVudHMgPSB0aGlzLl9ldmVudHM7XG4gIGlmIChldmVudHMpXG4gICAgZG9FcnJvciA9IChkb0Vycm9yICYmIGV2ZW50cy5lcnJvciA9PSBudWxsKTtcbiAgZWxzZSBpZiAoIWRvRXJyb3IpXG4gICAgcmV0dXJuIGZhbHNlO1xuXG4gIC8vIElmIHRoZXJlIGlzIG5vICdlcnJvcicgZXZlbnQgbGlzdGVuZXIgdGhlbiB0aHJvdy5cbiAgaWYgKGRvRXJyb3IpIHtcbiAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA+IDEpXG4gICAgICBlciA9IGFyZ3VtZW50c1sxXTtcbiAgICBpZiAoZXIgaW5zdGFuY2VvZiBFcnJvcikge1xuICAgICAgdGhyb3cgZXI7IC8vIFVuaGFuZGxlZCAnZXJyb3InIGV2ZW50XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIEF0IGxlYXN0IGdpdmUgc29tZSBraW5kIG9mIGNvbnRleHQgdG8gdGhlIHVzZXJcbiAgICAgIHZhciBlcnIgPSBuZXcgRXJyb3IoJ1VuaGFuZGxlZCBcImVycm9yXCIgZXZlbnQuICgnICsgZXIgKyAnKScpO1xuICAgICAgZXJyLmNvbnRleHQgPSBlcjtcbiAgICAgIHRocm93IGVycjtcbiAgICB9XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgaGFuZGxlciA9IGV2ZW50c1t0eXBlXTtcblxuICBpZiAoIWhhbmRsZXIpXG4gICAgcmV0dXJuIGZhbHNlO1xuXG4gIHZhciBpc0ZuID0gdHlwZW9mIGhhbmRsZXIgPT09ICdmdW5jdGlvbic7XG4gIGxlbiA9IGFyZ3VtZW50cy5sZW5ndGg7XG4gIHN3aXRjaCAobGVuKSB7XG4gICAgICAvLyBmYXN0IGNhc2VzXG4gICAgY2FzZSAxOlxuICAgICAgZW1pdE5vbmUoaGFuZGxlciwgaXNGbiwgdGhpcyk7XG4gICAgICBicmVhaztcbiAgICBjYXNlIDI6XG4gICAgICBlbWl0T25lKGhhbmRsZXIsIGlzRm4sIHRoaXMsIGFyZ3VtZW50c1sxXSk7XG4gICAgICBicmVhaztcbiAgICBjYXNlIDM6XG4gICAgICBlbWl0VHdvKGhhbmRsZXIsIGlzRm4sIHRoaXMsIGFyZ3VtZW50c1sxXSwgYXJndW1lbnRzWzJdKTtcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgNDpcbiAgICAgIGVtaXRUaHJlZShoYW5kbGVyLCBpc0ZuLCB0aGlzLCBhcmd1bWVudHNbMV0sIGFyZ3VtZW50c1syXSwgYXJndW1lbnRzWzNdKTtcbiAgICAgIGJyZWFrO1xuICAgICAgLy8gc2xvd2VyXG4gICAgZGVmYXVsdDpcbiAgICAgIGFyZ3MgPSBuZXcgQXJyYXkobGVuIC0gMSk7XG4gICAgICBmb3IgKGkgPSAxOyBpIDwgbGVuOyBpKyspXG4gICAgICAgIGFyZ3NbaSAtIDFdID0gYXJndW1lbnRzW2ldO1xuICAgICAgZW1pdE1hbnkoaGFuZGxlciwgaXNGbiwgdGhpcywgYXJncyk7XG4gIH1cblxuICByZXR1cm4gdHJ1ZTtcbn07XG5cbmZ1bmN0aW9uIF9hZGRMaXN0ZW5lcih0YXJnZXQsIHR5cGUsIGxpc3RlbmVyLCBwcmVwZW5kKSB7XG4gIHZhciBtO1xuICB2YXIgZXZlbnRzO1xuICB2YXIgZXhpc3Rpbmc7XG5cbiAgaWYgKHR5cGVvZiBsaXN0ZW5lciAhPT0gJ2Z1bmN0aW9uJylcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdcImxpc3RlbmVyXCIgYXJndW1lbnQgbXVzdCBiZSBhIGZ1bmN0aW9uJyk7XG5cbiAgZXZlbnRzID0gdGFyZ2V0Ll9ldmVudHM7XG4gIGlmICghZXZlbnRzKSB7XG4gICAgZXZlbnRzID0gdGFyZ2V0Ll9ldmVudHMgPSBvYmplY3RDcmVhdGUobnVsbCk7XG4gICAgdGFyZ2V0Ll9ldmVudHNDb3VudCA9IDA7XG4gIH0gZWxzZSB7XG4gICAgLy8gVG8gYXZvaWQgcmVjdXJzaW9uIGluIHRoZSBjYXNlIHRoYXQgdHlwZSA9PT0gXCJuZXdMaXN0ZW5lclwiISBCZWZvcmVcbiAgICAvLyBhZGRpbmcgaXQgdG8gdGhlIGxpc3RlbmVycywgZmlyc3QgZW1pdCBcIm5ld0xpc3RlbmVyXCIuXG4gICAgaWYgKGV2ZW50cy5uZXdMaXN0ZW5lcikge1xuICAgICAgdGFyZ2V0LmVtaXQoJ25ld0xpc3RlbmVyJywgdHlwZSxcbiAgICAgICAgICBsaXN0ZW5lci5saXN0ZW5lciA/IGxpc3RlbmVyLmxpc3RlbmVyIDogbGlzdGVuZXIpO1xuXG4gICAgICAvLyBSZS1hc3NpZ24gYGV2ZW50c2AgYmVjYXVzZSBhIG5ld0xpc3RlbmVyIGhhbmRsZXIgY291bGQgaGF2ZSBjYXVzZWQgdGhlXG4gICAgICAvLyB0aGlzLl9ldmVudHMgdG8gYmUgYXNzaWduZWQgdG8gYSBuZXcgb2JqZWN0XG4gICAgICBldmVudHMgPSB0YXJnZXQuX2V2ZW50cztcbiAgICB9XG4gICAgZXhpc3RpbmcgPSBldmVudHNbdHlwZV07XG4gIH1cblxuICBpZiAoIWV4aXN0aW5nKSB7XG4gICAgLy8gT3B0aW1pemUgdGhlIGNhc2Ugb2Ygb25lIGxpc3RlbmVyLiBEb24ndCBuZWVkIHRoZSBleHRyYSBhcnJheSBvYmplY3QuXG4gICAgZXhpc3RpbmcgPSBldmVudHNbdHlwZV0gPSBsaXN0ZW5lcjtcbiAgICArK3RhcmdldC5fZXZlbnRzQ291bnQ7XG4gIH0gZWxzZSB7XG4gICAgaWYgKHR5cGVvZiBleGlzdGluZyA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgLy8gQWRkaW5nIHRoZSBzZWNvbmQgZWxlbWVudCwgbmVlZCB0byBjaGFuZ2UgdG8gYXJyYXkuXG4gICAgICBleGlzdGluZyA9IGV2ZW50c1t0eXBlXSA9XG4gICAgICAgICAgcHJlcGVuZCA/IFtsaXN0ZW5lciwgZXhpc3RpbmddIDogW2V4aXN0aW5nLCBsaXN0ZW5lcl07XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIElmIHdlJ3ZlIGFscmVhZHkgZ290IGFuIGFycmF5LCBqdXN0IGFwcGVuZC5cbiAgICAgIGlmIChwcmVwZW5kKSB7XG4gICAgICAgIGV4aXN0aW5nLnVuc2hpZnQobGlzdGVuZXIpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgZXhpc3RpbmcucHVzaChsaXN0ZW5lcik7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gQ2hlY2sgZm9yIGxpc3RlbmVyIGxlYWtcbiAgICBpZiAoIWV4aXN0aW5nLndhcm5lZCkge1xuICAgICAgbSA9ICRnZXRNYXhMaXN0ZW5lcnModGFyZ2V0KTtcbiAgICAgIGlmIChtICYmIG0gPiAwICYmIGV4aXN0aW5nLmxlbmd0aCA+IG0pIHtcbiAgICAgICAgZXhpc3Rpbmcud2FybmVkID0gdHJ1ZTtcbiAgICAgICAgdmFyIHcgPSBuZXcgRXJyb3IoJ1Bvc3NpYmxlIEV2ZW50RW1pdHRlciBtZW1vcnkgbGVhayBkZXRlY3RlZC4gJyArXG4gICAgICAgICAgICBleGlzdGluZy5sZW5ndGggKyAnIFwiJyArIFN0cmluZyh0eXBlKSArICdcIiBsaXN0ZW5lcnMgJyArXG4gICAgICAgICAgICAnYWRkZWQuIFVzZSBlbWl0dGVyLnNldE1heExpc3RlbmVycygpIHRvICcgK1xuICAgICAgICAgICAgJ2luY3JlYXNlIGxpbWl0LicpO1xuICAgICAgICB3Lm5hbWUgPSAnTWF4TGlzdGVuZXJzRXhjZWVkZWRXYXJuaW5nJztcbiAgICAgICAgdy5lbWl0dGVyID0gdGFyZ2V0O1xuICAgICAgICB3LnR5cGUgPSB0eXBlO1xuICAgICAgICB3LmNvdW50ID0gZXhpc3RpbmcubGVuZ3RoO1xuICAgICAgICBpZiAodHlwZW9mIGNvbnNvbGUgPT09ICdvYmplY3QnICYmIGNvbnNvbGUud2Fybikge1xuICAgICAgICAgIGNvbnNvbGUud2FybignJXM6ICVzJywgdy5uYW1lLCB3Lm1lc3NhZ2UpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHRhcmdldDtcbn1cblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5hZGRMaXN0ZW5lciA9IGZ1bmN0aW9uIGFkZExpc3RlbmVyKHR5cGUsIGxpc3RlbmVyKSB7XG4gIHJldHVybiBfYWRkTGlzdGVuZXIodGhpcywgdHlwZSwgbGlzdGVuZXIsIGZhbHNlKTtcbn07XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUub24gPSBFdmVudEVtaXR0ZXIucHJvdG90eXBlLmFkZExpc3RlbmVyO1xuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLnByZXBlbmRMaXN0ZW5lciA9XG4gICAgZnVuY3Rpb24gcHJlcGVuZExpc3RlbmVyKHR5cGUsIGxpc3RlbmVyKSB7XG4gICAgICByZXR1cm4gX2FkZExpc3RlbmVyKHRoaXMsIHR5cGUsIGxpc3RlbmVyLCB0cnVlKTtcbiAgICB9O1xuXG5mdW5jdGlvbiBvbmNlV3JhcHBlcigpIHtcbiAgaWYgKCF0aGlzLmZpcmVkKSB7XG4gICAgdGhpcy50YXJnZXQucmVtb3ZlTGlzdGVuZXIodGhpcy50eXBlLCB0aGlzLndyYXBGbik7XG4gICAgdGhpcy5maXJlZCA9IHRydWU7XG4gICAgc3dpdGNoIChhcmd1bWVudHMubGVuZ3RoKSB7XG4gICAgICBjYXNlIDA6XG4gICAgICAgIHJldHVybiB0aGlzLmxpc3RlbmVyLmNhbGwodGhpcy50YXJnZXQpO1xuICAgICAgY2FzZSAxOlxuICAgICAgICByZXR1cm4gdGhpcy5saXN0ZW5lci5jYWxsKHRoaXMudGFyZ2V0LCBhcmd1bWVudHNbMF0pO1xuICAgICAgY2FzZSAyOlxuICAgICAgICByZXR1cm4gdGhpcy5saXN0ZW5lci5jYWxsKHRoaXMudGFyZ2V0LCBhcmd1bWVudHNbMF0sIGFyZ3VtZW50c1sxXSk7XG4gICAgICBjYXNlIDM6XG4gICAgICAgIHJldHVybiB0aGlzLmxpc3RlbmVyLmNhbGwodGhpcy50YXJnZXQsIGFyZ3VtZW50c1swXSwgYXJndW1lbnRzWzFdLFxuICAgICAgICAgICAgYXJndW1lbnRzWzJdKTtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHZhciBhcmdzID0gbmV3IEFycmF5KGFyZ3VtZW50cy5sZW5ndGgpO1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGFyZ3MubGVuZ3RoOyArK2kpXG4gICAgICAgICAgYXJnc1tpXSA9IGFyZ3VtZW50c1tpXTtcbiAgICAgICAgdGhpcy5saXN0ZW5lci5hcHBseSh0aGlzLnRhcmdldCwgYXJncyk7XG4gICAgfVxuICB9XG59XG5cbmZ1bmN0aW9uIF9vbmNlV3JhcCh0YXJnZXQsIHR5cGUsIGxpc3RlbmVyKSB7XG4gIHZhciBzdGF0ZSA9IHsgZmlyZWQ6IGZhbHNlLCB3cmFwRm46IHVuZGVmaW5lZCwgdGFyZ2V0OiB0YXJnZXQsIHR5cGU6IHR5cGUsIGxpc3RlbmVyOiBsaXN0ZW5lciB9O1xuICB2YXIgd3JhcHBlZCA9IGJpbmQuY2FsbChvbmNlV3JhcHBlciwgc3RhdGUpO1xuICB3cmFwcGVkLmxpc3RlbmVyID0gbGlzdGVuZXI7XG4gIHN0YXRlLndyYXBGbiA9IHdyYXBwZWQ7XG4gIHJldHVybiB3cmFwcGVkO1xufVxuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLm9uY2UgPSBmdW5jdGlvbiBvbmNlKHR5cGUsIGxpc3RlbmVyKSB7XG4gIGlmICh0eXBlb2YgbGlzdGVuZXIgIT09ICdmdW5jdGlvbicpXG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcignXCJsaXN0ZW5lclwiIGFyZ3VtZW50IG11c3QgYmUgYSBmdW5jdGlvbicpO1xuICB0aGlzLm9uKHR5cGUsIF9vbmNlV3JhcCh0aGlzLCB0eXBlLCBsaXN0ZW5lcikpO1xuICByZXR1cm4gdGhpcztcbn07XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUucHJlcGVuZE9uY2VMaXN0ZW5lciA9XG4gICAgZnVuY3Rpb24gcHJlcGVuZE9uY2VMaXN0ZW5lcih0eXBlLCBsaXN0ZW5lcikge1xuICAgICAgaWYgKHR5cGVvZiBsaXN0ZW5lciAhPT0gJ2Z1bmN0aW9uJylcbiAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignXCJsaXN0ZW5lclwiIGFyZ3VtZW50IG11c3QgYmUgYSBmdW5jdGlvbicpO1xuICAgICAgdGhpcy5wcmVwZW5kTGlzdGVuZXIodHlwZSwgX29uY2VXcmFwKHRoaXMsIHR5cGUsIGxpc3RlbmVyKSk7XG4gICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuXG4vLyBFbWl0cyBhICdyZW1vdmVMaXN0ZW5lcicgZXZlbnQgaWYgYW5kIG9ubHkgaWYgdGhlIGxpc3RlbmVyIHdhcyByZW1vdmVkLlxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5yZW1vdmVMaXN0ZW5lciA9XG4gICAgZnVuY3Rpb24gcmVtb3ZlTGlzdGVuZXIodHlwZSwgbGlzdGVuZXIpIHtcbiAgICAgIHZhciBsaXN0LCBldmVudHMsIHBvc2l0aW9uLCBpLCBvcmlnaW5hbExpc3RlbmVyO1xuXG4gICAgICBpZiAodHlwZW9mIGxpc3RlbmVyICE9PSAnZnVuY3Rpb24nKVxuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdcImxpc3RlbmVyXCIgYXJndW1lbnQgbXVzdCBiZSBhIGZ1bmN0aW9uJyk7XG5cbiAgICAgIGV2ZW50cyA9IHRoaXMuX2V2ZW50cztcbiAgICAgIGlmICghZXZlbnRzKVxuICAgICAgICByZXR1cm4gdGhpcztcblxuICAgICAgbGlzdCA9IGV2ZW50c1t0eXBlXTtcbiAgICAgIGlmICghbGlzdClcbiAgICAgICAgcmV0dXJuIHRoaXM7XG5cbiAgICAgIGlmIChsaXN0ID09PSBsaXN0ZW5lciB8fCBsaXN0Lmxpc3RlbmVyID09PSBsaXN0ZW5lcikge1xuICAgICAgICBpZiAoLS10aGlzLl9ldmVudHNDb3VudCA9PT0gMClcbiAgICAgICAgICB0aGlzLl9ldmVudHMgPSBvYmplY3RDcmVhdGUobnVsbCk7XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgIGRlbGV0ZSBldmVudHNbdHlwZV07XG4gICAgICAgICAgaWYgKGV2ZW50cy5yZW1vdmVMaXN0ZW5lcilcbiAgICAgICAgICAgIHRoaXMuZW1pdCgncmVtb3ZlTGlzdGVuZXInLCB0eXBlLCBsaXN0Lmxpc3RlbmVyIHx8IGxpc3RlbmVyKTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIGlmICh0eXBlb2YgbGlzdCAhPT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICBwb3NpdGlvbiA9IC0xO1xuXG4gICAgICAgIGZvciAoaSA9IGxpc3QubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgICAgICBpZiAobGlzdFtpXSA9PT0gbGlzdGVuZXIgfHwgbGlzdFtpXS5saXN0ZW5lciA9PT0gbGlzdGVuZXIpIHtcbiAgICAgICAgICAgIG9yaWdpbmFsTGlzdGVuZXIgPSBsaXN0W2ldLmxpc3RlbmVyO1xuICAgICAgICAgICAgcG9zaXRpb24gPSBpO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHBvc2l0aW9uIDwgMClcbiAgICAgICAgICByZXR1cm4gdGhpcztcblxuICAgICAgICBpZiAocG9zaXRpb24gPT09IDApXG4gICAgICAgICAgbGlzdC5zaGlmdCgpO1xuICAgICAgICBlbHNlXG4gICAgICAgICAgc3BsaWNlT25lKGxpc3QsIHBvc2l0aW9uKTtcblxuICAgICAgICBpZiAobGlzdC5sZW5ndGggPT09IDEpXG4gICAgICAgICAgZXZlbnRzW3R5cGVdID0gbGlzdFswXTtcblxuICAgICAgICBpZiAoZXZlbnRzLnJlbW92ZUxpc3RlbmVyKVxuICAgICAgICAgIHRoaXMuZW1pdCgncmVtb3ZlTGlzdGVuZXInLCB0eXBlLCBvcmlnaW5hbExpc3RlbmVyIHx8IGxpc3RlbmVyKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5yZW1vdmVBbGxMaXN0ZW5lcnMgPVxuICAgIGZ1bmN0aW9uIHJlbW92ZUFsbExpc3RlbmVycyh0eXBlKSB7XG4gICAgICB2YXIgbGlzdGVuZXJzLCBldmVudHMsIGk7XG5cbiAgICAgIGV2ZW50cyA9IHRoaXMuX2V2ZW50cztcbiAgICAgIGlmICghZXZlbnRzKVxuICAgICAgICByZXR1cm4gdGhpcztcblxuICAgICAgLy8gbm90IGxpc3RlbmluZyBmb3IgcmVtb3ZlTGlzdGVuZXIsIG5vIG5lZWQgdG8gZW1pdFxuICAgICAgaWYgKCFldmVudHMucmVtb3ZlTGlzdGVuZXIpIHtcbiAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICB0aGlzLl9ldmVudHMgPSBvYmplY3RDcmVhdGUobnVsbCk7XG4gICAgICAgICAgdGhpcy5fZXZlbnRzQ291bnQgPSAwO1xuICAgICAgICB9IGVsc2UgaWYgKGV2ZW50c1t0eXBlXSkge1xuICAgICAgICAgIGlmICgtLXRoaXMuX2V2ZW50c0NvdW50ID09PSAwKVxuICAgICAgICAgICAgdGhpcy5fZXZlbnRzID0gb2JqZWN0Q3JlYXRlKG51bGwpO1xuICAgICAgICAgIGVsc2VcbiAgICAgICAgICAgIGRlbGV0ZSBldmVudHNbdHlwZV07XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICB9XG5cbiAgICAgIC8vIGVtaXQgcmVtb3ZlTGlzdGVuZXIgZm9yIGFsbCBsaXN0ZW5lcnMgb24gYWxsIGV2ZW50c1xuICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgdmFyIGtleXMgPSBvYmplY3RLZXlzKGV2ZW50cyk7XG4gICAgICAgIHZhciBrZXk7XG4gICAgICAgIGZvciAoaSA9IDA7IGkgPCBrZXlzLmxlbmd0aDsgKytpKSB7XG4gICAgICAgICAga2V5ID0ga2V5c1tpXTtcbiAgICAgICAgICBpZiAoa2V5ID09PSAncmVtb3ZlTGlzdGVuZXInKSBjb250aW51ZTtcbiAgICAgICAgICB0aGlzLnJlbW92ZUFsbExpc3RlbmVycyhrZXkpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMucmVtb3ZlQWxsTGlzdGVuZXJzKCdyZW1vdmVMaXN0ZW5lcicpO1xuICAgICAgICB0aGlzLl9ldmVudHMgPSBvYmplY3RDcmVhdGUobnVsbCk7XG4gICAgICAgIHRoaXMuX2V2ZW50c0NvdW50ID0gMDtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICB9XG5cbiAgICAgIGxpc3RlbmVycyA9IGV2ZW50c1t0eXBlXTtcblxuICAgICAgaWYgKHR5cGVvZiBsaXN0ZW5lcnMgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgdGhpcy5yZW1vdmVMaXN0ZW5lcih0eXBlLCBsaXN0ZW5lcnMpO1xuICAgICAgfSBlbHNlIGlmIChsaXN0ZW5lcnMpIHtcbiAgICAgICAgLy8gTElGTyBvcmRlclxuICAgICAgICBmb3IgKGkgPSBsaXN0ZW5lcnMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgICAgICB0aGlzLnJlbW92ZUxpc3RlbmVyKHR5cGUsIGxpc3RlbmVyc1tpXSk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcblxuZnVuY3Rpb24gX2xpc3RlbmVycyh0YXJnZXQsIHR5cGUsIHVud3JhcCkge1xuICB2YXIgZXZlbnRzID0gdGFyZ2V0Ll9ldmVudHM7XG5cbiAgaWYgKCFldmVudHMpXG4gICAgcmV0dXJuIFtdO1xuXG4gIHZhciBldmxpc3RlbmVyID0gZXZlbnRzW3R5cGVdO1xuICBpZiAoIWV2bGlzdGVuZXIpXG4gICAgcmV0dXJuIFtdO1xuXG4gIGlmICh0eXBlb2YgZXZsaXN0ZW5lciA9PT0gJ2Z1bmN0aW9uJylcbiAgICByZXR1cm4gdW53cmFwID8gW2V2bGlzdGVuZXIubGlzdGVuZXIgfHwgZXZsaXN0ZW5lcl0gOiBbZXZsaXN0ZW5lcl07XG5cbiAgcmV0dXJuIHVud3JhcCA/IHVud3JhcExpc3RlbmVycyhldmxpc3RlbmVyKSA6IGFycmF5Q2xvbmUoZXZsaXN0ZW5lciwgZXZsaXN0ZW5lci5sZW5ndGgpO1xufVxuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLmxpc3RlbmVycyA9IGZ1bmN0aW9uIGxpc3RlbmVycyh0eXBlKSB7XG4gIHJldHVybiBfbGlzdGVuZXJzKHRoaXMsIHR5cGUsIHRydWUpO1xufTtcblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5yYXdMaXN0ZW5lcnMgPSBmdW5jdGlvbiByYXdMaXN0ZW5lcnModHlwZSkge1xuICByZXR1cm4gX2xpc3RlbmVycyh0aGlzLCB0eXBlLCBmYWxzZSk7XG59O1xuXG5FdmVudEVtaXR0ZXIubGlzdGVuZXJDb3VudCA9IGZ1bmN0aW9uKGVtaXR0ZXIsIHR5cGUpIHtcbiAgaWYgKHR5cGVvZiBlbWl0dGVyLmxpc3RlbmVyQ291bnQgPT09ICdmdW5jdGlvbicpIHtcbiAgICByZXR1cm4gZW1pdHRlci5saXN0ZW5lckNvdW50KHR5cGUpO1xuICB9IGVsc2Uge1xuICAgIHJldHVybiBsaXN0ZW5lckNvdW50LmNhbGwoZW1pdHRlciwgdHlwZSk7XG4gIH1cbn07XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUubGlzdGVuZXJDb3VudCA9IGxpc3RlbmVyQ291bnQ7XG5mdW5jdGlvbiBsaXN0ZW5lckNvdW50KHR5cGUpIHtcbiAgdmFyIGV2ZW50cyA9IHRoaXMuX2V2ZW50cztcblxuICBpZiAoZXZlbnRzKSB7XG4gICAgdmFyIGV2bGlzdGVuZXIgPSBldmVudHNbdHlwZV07XG5cbiAgICBpZiAodHlwZW9mIGV2bGlzdGVuZXIgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgIHJldHVybiAxO1xuICAgIH0gZWxzZSBpZiAoZXZsaXN0ZW5lcikge1xuICAgICAgcmV0dXJuIGV2bGlzdGVuZXIubGVuZ3RoO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiAwO1xufVxuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLmV2ZW50TmFtZXMgPSBmdW5jdGlvbiBldmVudE5hbWVzKCkge1xuICByZXR1cm4gdGhpcy5fZXZlbnRzQ291bnQgPiAwID8gUmVmbGVjdC5vd25LZXlzKHRoaXMuX2V2ZW50cykgOiBbXTtcbn07XG5cbi8vIEFib3V0IDEuNXggZmFzdGVyIHRoYW4gdGhlIHR3by1hcmcgdmVyc2lvbiBvZiBBcnJheSNzcGxpY2UoKS5cbmZ1bmN0aW9uIHNwbGljZU9uZShsaXN0LCBpbmRleCkge1xuICBmb3IgKHZhciBpID0gaW5kZXgsIGsgPSBpICsgMSwgbiA9IGxpc3QubGVuZ3RoOyBrIDwgbjsgaSArPSAxLCBrICs9IDEpXG4gICAgbGlzdFtpXSA9IGxpc3Rba107XG4gIGxpc3QucG9wKCk7XG59XG5cbmZ1bmN0aW9uIGFycmF5Q2xvbmUoYXJyLCBuKSB7XG4gIHZhciBjb3B5ID0gbmV3IEFycmF5KG4pO1xuICBmb3IgKHZhciBpID0gMDsgaSA8IG47ICsraSlcbiAgICBjb3B5W2ldID0gYXJyW2ldO1xuICByZXR1cm4gY29weTtcbn1cblxuZnVuY3Rpb24gdW53cmFwTGlzdGVuZXJzKGFycikge1xuICB2YXIgcmV0ID0gbmV3IEFycmF5KGFyci5sZW5ndGgpO1xuICBmb3IgKHZhciBpID0gMDsgaSA8IHJldC5sZW5ndGg7ICsraSkge1xuICAgIHJldFtpXSA9IGFycltpXS5saXN0ZW5lciB8fCBhcnJbaV07XG4gIH1cbiAgcmV0dXJuIHJldDtcbn1cblxuZnVuY3Rpb24gb2JqZWN0Q3JlYXRlUG9seWZpbGwocHJvdG8pIHtcbiAgdmFyIEYgPSBmdW5jdGlvbigpIHt9O1xuICBGLnByb3RvdHlwZSA9IHByb3RvO1xuICByZXR1cm4gbmV3IEY7XG59XG5mdW5jdGlvbiBvYmplY3RLZXlzUG9seWZpbGwob2JqKSB7XG4gIHZhciBrZXlzID0gW107XG4gIGZvciAodmFyIGsgaW4gb2JqKSBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKG9iaiwgaykpIHtcbiAgICBrZXlzLnB1c2goayk7XG4gIH1cbiAgcmV0dXJuIGs7XG59XG5mdW5jdGlvbiBmdW5jdGlvbkJpbmRQb2x5ZmlsbChjb250ZXh0KSB7XG4gIHZhciBmbiA9IHRoaXM7XG4gIHJldHVybiBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIGZuLmFwcGx5KGNvbnRleHQsIGFyZ3VtZW50cyk7XG4gIH07XG59XG4iLCIvKiBqc2hpbnQgbm9kZTogdHJ1ZSAqL1xuJ3VzZSBzdHJpY3QnO1xuXG52YXIgbm9ybWFsaWNlID0gcmVxdWlyZSgnbm9ybWFsaWNlJyk7XG5cbi8qKlxuICAjIGZyZWVpY2VcblxuICBUaGUgYGZyZWVpY2VgIG1vZHVsZSBpcyBhIHNpbXBsZSB3YXkgb2YgZ2V0dGluZyByYW5kb20gU1RVTiBvciBUVVJOIHNlcnZlclxuICBmb3IgeW91ciBXZWJSVEMgYXBwbGljYXRpb24uICBUaGUgbGlzdCBvZiBzZXJ2ZXJzIChqdXN0IFNUVU4gYXQgdGhpcyBzdGFnZSlcbiAgd2VyZSBzb3VyY2VkIGZyb20gdGhpcyBbZ2lzdF0oaHR0cHM6Ly9naXN0LmdpdGh1Yi5jb20venppdW5pLzM3NDE5MzMpLlxuXG4gICMjIEV4YW1wbGUgVXNlXG5cbiAgVGhlIGZvbGxvd2luZyBkZW1vbnN0cmF0ZXMgaG93IHlvdSBjYW4gdXNlIGBmcmVlaWNlYCB3aXRoXG4gIFtydGMtcXVpY2tjb25uZWN0XShodHRwczovL2dpdGh1Yi5jb20vcnRjLWlvL3J0Yy1xdWlja2Nvbm5lY3QpOlxuXG4gIDw8PCBleGFtcGxlcy9xdWlja2Nvbm5lY3QuanNcblxuICBBcyB0aGUgYGZyZWVpY2VgIG1vZHVsZSBnZW5lcmF0ZXMgaWNlIHNlcnZlcnMgaW4gYSBsaXN0IGNvbXBsaWFudCB3aXRoIHRoZVxuICBXZWJSVEMgc3BlYyB5b3Ugd2lsbCBiZSBhYmxlIHRvIHVzZSBpdCB3aXRoIHJhdyBgUlRDUGVlckNvbm5lY3Rpb25gXG4gIGNvbnN0cnVjdG9ycyBhbmQgb3RoZXIgV2ViUlRDIGxpYnJhcmllcy5cblxuICAjIyBIZXksIGRvbid0IHVzZSBteSBTVFVOL1RVUk4gc2VydmVyIVxuXG4gIElmIGZvciBzb21lIHJlYXNvbiB5b3VyIGZyZWUgU1RVTiBvciBUVVJOIHNlcnZlciBlbmRzIHVwIGluIHRoZVxuICBsaXN0IG9mIHNlcnZlcnMgKFtzdHVuXShodHRwczovL2dpdGh1Yi5jb20vRGFtb25PZWhsbWFuL2ZyZWVpY2UvYmxvYi9tYXN0ZXIvc3R1bi5qc29uKSBvclxuICBbdHVybl0oaHR0cHM6Ly9naXRodWIuY29tL0RhbW9uT2VobG1hbi9mcmVlaWNlL2Jsb2IvbWFzdGVyL3R1cm4uanNvbikpXG4gIHRoYXQgaXMgdXNlZCBpbiB0aGlzIG1vZHVsZSwgeW91IGNhbiBmZWVsXG4gIGZyZWUgdG8gb3BlbiBhbiBpc3N1ZSBvbiB0aGlzIHJlcG9zaXRvcnkgYW5kIHRob3NlIHNlcnZlcnMgd2lsbCBiZSByZW1vdmVkXG4gIHdpdGhpbiAyNCBob3VycyAob3Igc29vbmVyKS4gIFRoaXMgaXMgdGhlIHF1aWNrZXN0IGFuZCBwcm9iYWJseSB0aGUgbW9zdFxuICBwb2xpdGUgd2F5IHRvIGhhdmUgc29tZXRoaW5nIHJlbW92ZWQgKGFuZCBwcm92aWRlcyB1cyBzb21lIHZpc2liaWxpdHlcbiAgaWYgc29tZW9uZSBvcGVucyBhIHB1bGwgcmVxdWVzdCByZXF1ZXN0aW5nIHRoYXQgYSBzZXJ2ZXIgaXMgYWRkZWQpLlxuXG4gICMjIFBsZWFzZSBhZGQgbXkgc2VydmVyIVxuXG4gIElmIHlvdSBoYXZlIGEgc2VydmVyIHRoYXQgeW91IHdpc2ggdG8gYWRkIHRvIHRoZSBsaXN0LCB0aGF0J3MgYXdlc29tZSEgSSdtXG4gIHN1cmUgSSBzcGVhayBvbiBiZWhhbGYgb2YgYSB3aG9sZSBwaWxlIG9mIFdlYlJUQyBkZXZlbG9wZXJzIHdobyBzYXkgdGhhbmtzLlxuICBUbyBnZXQgaXQgaW50byB0aGUgbGlzdCwgZmVlbCBmcmVlIHRvIGVpdGhlciBvcGVuIGEgcHVsbCByZXF1ZXN0IG9yIGlmIHlvdVxuICBmaW5kIHRoYXQgcHJvY2VzcyBhIGJpdCBkYXVudGluZyB0aGVuIGp1c3QgY3JlYXRlIGFuIGlzc3VlIHJlcXVlc3RpbmdcbiAgdGhlIGFkZGl0aW9uIG9mIHRoZSBzZXJ2ZXIgKG1ha2Ugc3VyZSB5b3UgcHJvdmlkZSBhbGwgdGhlIGRldGFpbHMsIGFuZCBpZlxuICB5b3UgaGF2ZSBhIFRlcm1zIG9mIFNlcnZpY2UgdGhlbiBpbmNsdWRpbmcgdGhhdCBpbiB0aGUgUFIvaXNzdWUgd291bGQgYmVcbiAgYXdlc29tZSkuXG5cbiAgIyMgSSBrbm93IG9mIGEgZnJlZSBzZXJ2ZXIsIGNhbiBJIGFkZCBpdD9cblxuICBTdXJlLCBpZiB5b3UgZG8geW91ciBob21ld29yayBhbmQgbWFrZSBzdXJlIGl0IGlzIG9rIHRvIHVzZSAoSSdtIGN1cnJlbnRseVxuICBpbiB0aGUgcHJvY2VzcyBvZiByZXZpZXdpbmcgdGhlIHRlcm1zIG9mIHRob3NlIFNUVU4gc2VydmVycyBpbmNsdWRlZCBmcm9tXG4gIHRoZSBvcmlnaW5hbCBsaXN0KS4gIElmIGl0J3Mgb2sgdG8gZ28sIHRoZW4gcGxlYXNlIHNlZSB0aGUgcHJldmlvdXMgZW50cnlcbiAgZm9yIGhvdyB0byBhZGQgaXQuXG5cbiAgIyMgQ3VycmVudCBMaXN0IG9mIFNlcnZlcnNcblxuICAqIGN1cnJlbnQgYXMgYXQgdGhlIHRpbWUgb2YgbGFzdCBgUkVBRE1FLm1kYCBmaWxlIGdlbmVyYXRpb25cblxuICAjIyMgU1RVTlxuXG4gIDw8PCBzdHVuLmpzb25cblxuICAjIyMgVFVSTlxuXG4gIDw8PCB0dXJuLmpzb25cblxuKiovXG5cbnZhciBmcmVlaWNlID0gbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihvcHRzKSB7XG4gIC8vIGlmIGEgbGlzdCBvZiBzZXJ2ZXJzIGhhcyBiZWVuIHByb3ZpZGVkLCB0aGVuIHVzZSBpdCBpbnN0ZWFkIG9mIGRlZmF1bHRzXG4gIHZhciBzZXJ2ZXJzID0ge1xuICAgIHN0dW46IChvcHRzIHx8IHt9KS5zdHVuIHx8IHJlcXVpcmUoJy4vc3R1bi5qc29uJyksXG4gICAgdHVybjogKG9wdHMgfHwge30pLnR1cm4gfHwgcmVxdWlyZSgnLi90dXJuLmpzb24nKVxuICB9O1xuXG4gIHZhciBzdHVuQ291bnQgPSAob3B0cyB8fCB7fSkuc3R1bkNvdW50IHx8IDI7XG4gIHZhciB0dXJuQ291bnQgPSAob3B0cyB8fCB7fSkudHVybkNvdW50IHx8IDA7XG4gIHZhciBzZWxlY3RlZDtcblxuICBmdW5jdGlvbiBnZXRTZXJ2ZXJzKHR5cGUsIGNvdW50KSB7XG4gICAgdmFyIG91dCA9IFtdO1xuICAgIHZhciBpbnB1dCA9IFtdLmNvbmNhdChzZXJ2ZXJzW3R5cGVdKTtcbiAgICB2YXIgaWR4O1xuXG4gICAgd2hpbGUgKGlucHV0Lmxlbmd0aCAmJiBvdXQubGVuZ3RoIDwgY291bnQpIHtcbiAgICAgIGlkeCA9IChNYXRoLnJhbmRvbSgpICogaW5wdXQubGVuZ3RoKSB8IDA7XG4gICAgICBvdXQgPSBvdXQuY29uY2F0KGlucHV0LnNwbGljZShpZHgsIDEpKTtcbiAgICB9XG5cbiAgICByZXR1cm4gb3V0Lm1hcChmdW5jdGlvbih1cmwpIHtcbiAgICAgICAgLy9JZiBpdCdzIGEgbm90IGEgc3RyaW5nLCBkb24ndCB0cnkgdG8gXCJub3JtYWxpY2VcIiBpdCBvdGhlcndpc2UgdXNpbmcgdHlwZTp1cmwgd2lsbCBzY3JldyBpdCB1cFxuICAgICAgICBpZiAoKHR5cGVvZiB1cmwgIT09ICdzdHJpbmcnKSAmJiAoISAodXJsIGluc3RhbmNlb2YgU3RyaW5nKSkpIHtcbiAgICAgICAgICAgIHJldHVybiB1cmw7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gbm9ybWFsaWNlKHR5cGUgKyAnOicgKyB1cmwpO1xuICAgICAgICB9XG4gICAgfSk7XG4gIH1cblxuICAvLyBhZGQgc3R1biBzZXJ2ZXJzXG4gIHNlbGVjdGVkID0gW10uY29uY2F0KGdldFNlcnZlcnMoJ3N0dW4nLCBzdHVuQ291bnQpKTtcblxuICBpZiAodHVybkNvdW50KSB7XG4gICAgc2VsZWN0ZWQgPSBzZWxlY3RlZC5jb25jYXQoZ2V0U2VydmVycygndHVybicsIHR1cm5Db3VudCkpO1xuICB9XG5cbiAgcmV0dXJuIHNlbGVjdGVkO1xufTtcbiIsIm1vZHVsZS5leHBvcnRzPVtcbiAgXCJzdHVuLmwuZ29vZ2xlLmNvbToxOTMwMlwiLFxuICBcInN0dW4xLmwuZ29vZ2xlLmNvbToxOTMwMlwiLFxuICBcInN0dW4yLmwuZ29vZ2xlLmNvbToxOTMwMlwiLFxuICBcInN0dW4zLmwuZ29vZ2xlLmNvbToxOTMwMlwiLFxuICBcInN0dW40LmwuZ29vZ2xlLmNvbToxOTMwMlwiLFxuICBcInN0dW4uZWtpZ2EubmV0XCIsXG4gIFwic3R1bi5pZGVhc2lwLmNvbVwiLFxuICBcInN0dW4uc2NobHVuZC5kZVwiLFxuICBcInN0dW4uc3R1bnByb3RvY29sLm9yZzozNDc4XCIsXG4gIFwic3R1bi52b2lwYXJvdW5kLmNvbVwiLFxuICBcInN0dW4udm9pcGJ1c3Rlci5jb21cIixcbiAgXCJzdHVuLnZvaXBzdHVudC5jb21cIixcbiAgXCJzdHVuLnZveGdyYXRpYS5vcmdcIixcbiAgXCJzdHVuLnNlcnZpY2VzLm1vemlsbGEuY29tXCJcbl1cbiIsIm1vZHVsZS5leHBvcnRzPVtdXG4iLCJ2YXIgV2lsZEVtaXR0ZXIgPSByZXF1aXJlKCd3aWxkZW1pdHRlcicpO1xuXG5mdW5jdGlvbiBnZXRNYXhWb2x1bWUgKGFuYWx5c2VyLCBmZnRCaW5zKSB7XG4gIHZhciBtYXhWb2x1bWUgPSAtSW5maW5pdHk7XG4gIGFuYWx5c2VyLmdldEZsb2F0RnJlcXVlbmN5RGF0YShmZnRCaW5zKTtcblxuICBmb3IodmFyIGk9NCwgaWk9ZmZ0Qmlucy5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7XG4gICAgaWYgKGZmdEJpbnNbaV0gPiBtYXhWb2x1bWUgJiYgZmZ0Qmluc1tpXSA8IDApIHtcbiAgICAgIG1heFZvbHVtZSA9IGZmdEJpbnNbaV07XG4gICAgfVxuICB9O1xuXG4gIHJldHVybiBtYXhWb2x1bWU7XG59XG5cblxudmFyIGF1ZGlvQ29udGV4dFR5cGU7XG5pZiAodHlwZW9mIHdpbmRvdyAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgYXVkaW9Db250ZXh0VHlwZSA9IHdpbmRvdy5BdWRpb0NvbnRleHQgfHwgd2luZG93LndlYmtpdEF1ZGlvQ29udGV4dDtcbn1cbi8vIHVzZSBhIHNpbmdsZSBhdWRpbyBjb250ZXh0IGR1ZSB0byBoYXJkd2FyZSBsaW1pdHNcbnZhciBhdWRpb0NvbnRleHQgPSBudWxsO1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihzdHJlYW0sIG9wdGlvbnMpIHtcbiAgdmFyIGhhcmtlciA9IG5ldyBXaWxkRW1pdHRlcigpO1xuXG5cbiAgLy8gbWFrZSBpdCBub3QgYnJlYWsgaW4gbm9uLXN1cHBvcnRlZCBicm93c2Vyc1xuICBpZiAoIWF1ZGlvQ29udGV4dFR5cGUpIHJldHVybiBoYXJrZXI7XG5cbiAgLy9Db25maWdcbiAgdmFyIG9wdGlvbnMgPSBvcHRpb25zIHx8IHt9LFxuICAgICAgc21vb3RoaW5nID0gKG9wdGlvbnMuc21vb3RoaW5nIHx8IDAuMSksXG4gICAgICBpbnRlcnZhbCA9IChvcHRpb25zLmludGVydmFsIHx8IDUwKSxcbiAgICAgIHRocmVzaG9sZCA9IG9wdGlvbnMudGhyZXNob2xkLFxuICAgICAgcGxheSA9IG9wdGlvbnMucGxheSxcbiAgICAgIGhpc3RvcnkgPSBvcHRpb25zLmhpc3RvcnkgfHwgMTAsXG4gICAgICBydW5uaW5nID0gdHJ1ZTtcblxuICAvL1NldHVwIEF1ZGlvIENvbnRleHRcbiAgaWYgKCFhdWRpb0NvbnRleHQpIHtcbiAgICBhdWRpb0NvbnRleHQgPSBuZXcgYXVkaW9Db250ZXh0VHlwZSgpO1xuICB9XG4gIHZhciBzb3VyY2VOb2RlLCBmZnRCaW5zLCBhbmFseXNlcjtcblxuICBhbmFseXNlciA9IGF1ZGlvQ29udGV4dC5jcmVhdGVBbmFseXNlcigpO1xuICBhbmFseXNlci5mZnRTaXplID0gNTEyO1xuICBhbmFseXNlci5zbW9vdGhpbmdUaW1lQ29uc3RhbnQgPSBzbW9vdGhpbmc7XG4gIGZmdEJpbnMgPSBuZXcgRmxvYXQzMkFycmF5KGFuYWx5c2VyLmZyZXF1ZW5jeUJpbkNvdW50KTtcblxuICBpZiAoc3RyZWFtLmpxdWVyeSkgc3RyZWFtID0gc3RyZWFtWzBdO1xuICBpZiAoc3RyZWFtIGluc3RhbmNlb2YgSFRNTEF1ZGlvRWxlbWVudCB8fCBzdHJlYW0gaW5zdGFuY2VvZiBIVE1MVmlkZW9FbGVtZW50KSB7XG4gICAgLy9BdWRpbyBUYWdcbiAgICBzb3VyY2VOb2RlID0gYXVkaW9Db250ZXh0LmNyZWF0ZU1lZGlhRWxlbWVudFNvdXJjZShzdHJlYW0pO1xuICAgIGlmICh0eXBlb2YgcGxheSA9PT0gJ3VuZGVmaW5lZCcpIHBsYXkgPSB0cnVlO1xuICAgIHRocmVzaG9sZCA9IHRocmVzaG9sZCB8fCAtNTA7XG4gIH0gZWxzZSB7XG4gICAgLy9XZWJSVEMgU3RyZWFtXG4gICAgc291cmNlTm9kZSA9IGF1ZGlvQ29udGV4dC5jcmVhdGVNZWRpYVN0cmVhbVNvdXJjZShzdHJlYW0pO1xuICAgIHRocmVzaG9sZCA9IHRocmVzaG9sZCB8fCAtNTA7XG4gIH1cblxuICBzb3VyY2VOb2RlLmNvbm5lY3QoYW5hbHlzZXIpO1xuICBpZiAocGxheSkgYW5hbHlzZXIuY29ubmVjdChhdWRpb0NvbnRleHQuZGVzdGluYXRpb24pO1xuXG4gIGhhcmtlci5zcGVha2luZyA9IGZhbHNlO1xuXG4gIGhhcmtlci5zdXNwZW5kID0gZnVuY3Rpb24oKSB7XG4gICAgYXVkaW9Db250ZXh0LnN1c3BlbmQoKTtcbiAgfVxuICBoYXJrZXIucmVzdW1lID0gZnVuY3Rpb24oKSB7XG4gICAgYXVkaW9Db250ZXh0LnJlc3VtZSgpO1xuICB9XG4gIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShoYXJrZXIsICdzdGF0ZScsIHsgZ2V0OiBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gYXVkaW9Db250ZXh0LnN0YXRlO1xuICB9fSk7XG4gIGF1ZGlvQ29udGV4dC5vbnN0YXRlY2hhbmdlID0gZnVuY3Rpb24oKSB7XG4gICAgaGFya2VyLmVtaXQoJ3N0YXRlX2NoYW5nZScsIGF1ZGlvQ29udGV4dC5zdGF0ZSk7XG4gIH1cblxuICBoYXJrZXIuc2V0VGhyZXNob2xkID0gZnVuY3Rpb24odCkge1xuICAgIHRocmVzaG9sZCA9IHQ7XG4gIH07XG5cbiAgaGFya2VyLnNldEludGVydmFsID0gZnVuY3Rpb24oaSkge1xuICAgIGludGVydmFsID0gaTtcbiAgfTtcblxuICBoYXJrZXIuc3RvcCA9IGZ1bmN0aW9uKCkge1xuICAgIHJ1bm5pbmcgPSBmYWxzZTtcbiAgICBoYXJrZXIuZW1pdCgndm9sdW1lX2NoYW5nZScsIC0xMDAsIHRocmVzaG9sZCk7XG4gICAgaWYgKGhhcmtlci5zcGVha2luZykge1xuICAgICAgaGFya2VyLnNwZWFraW5nID0gZmFsc2U7XG4gICAgICBoYXJrZXIuZW1pdCgnc3RvcHBlZF9zcGVha2luZycpO1xuICAgIH1cbiAgICBhbmFseXNlci5kaXNjb25uZWN0KCk7XG4gICAgc291cmNlTm9kZS5kaXNjb25uZWN0KCk7XG4gIH07XG4gIGhhcmtlci5zcGVha2luZ0hpc3RvcnkgPSBbXTtcbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBoaXN0b3J5OyBpKyspIHtcbiAgICAgIGhhcmtlci5zcGVha2luZ0hpc3RvcnkucHVzaCgwKTtcbiAgfVxuXG4gIC8vIFBvbGwgdGhlIGFuYWx5c2VyIG5vZGUgdG8gZGV0ZXJtaW5lIGlmIHNwZWFraW5nXG4gIC8vIGFuZCBlbWl0IGV2ZW50cyBpZiBjaGFuZ2VkXG4gIHZhciBsb29wZXIgPSBmdW5jdGlvbigpIHtcbiAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uKCkge1xuXG4gICAgICAvL2NoZWNrIGlmIHN0b3AgaGFzIGJlZW4gY2FsbGVkXG4gICAgICBpZighcnVubmluZykge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIHZhciBjdXJyZW50Vm9sdW1lID0gZ2V0TWF4Vm9sdW1lKGFuYWx5c2VyLCBmZnRCaW5zKTtcblxuICAgICAgaGFya2VyLmVtaXQoJ3ZvbHVtZV9jaGFuZ2UnLCBjdXJyZW50Vm9sdW1lLCB0aHJlc2hvbGQpO1xuXG4gICAgICB2YXIgaGlzdG9yeSA9IDA7XG4gICAgICBpZiAoY3VycmVudFZvbHVtZSA+IHRocmVzaG9sZCAmJiAhaGFya2VyLnNwZWFraW5nKSB7XG4gICAgICAgIC8vIHRyaWdnZXIgcXVpY2tseSwgc2hvcnQgaGlzdG9yeVxuICAgICAgICBmb3IgKHZhciBpID0gaGFya2VyLnNwZWFraW5nSGlzdG9yeS5sZW5ndGggLSAzOyBpIDwgaGFya2VyLnNwZWFraW5nSGlzdG9yeS5sZW5ndGg7IGkrKykge1xuICAgICAgICAgIGhpc3RvcnkgKz0gaGFya2VyLnNwZWFraW5nSGlzdG9yeVtpXTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoaGlzdG9yeSA+PSAyKSB7XG4gICAgICAgICAgaGFya2VyLnNwZWFraW5nID0gdHJ1ZTtcbiAgICAgICAgICBoYXJrZXIuZW1pdCgnc3BlYWtpbmcnKTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIGlmIChjdXJyZW50Vm9sdW1lIDwgdGhyZXNob2xkICYmIGhhcmtlci5zcGVha2luZykge1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGhhcmtlci5zcGVha2luZ0hpc3RvcnkubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICBoaXN0b3J5ICs9IGhhcmtlci5zcGVha2luZ0hpc3RvcnlbaV07XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGhpc3RvcnkgPT0gMCkge1xuICAgICAgICAgIGhhcmtlci5zcGVha2luZyA9IGZhbHNlO1xuICAgICAgICAgIGhhcmtlci5lbWl0KCdzdG9wcGVkX3NwZWFraW5nJyk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGhhcmtlci5zcGVha2luZ0hpc3Rvcnkuc2hpZnQoKTtcbiAgICAgIGhhcmtlci5zcGVha2luZ0hpc3RvcnkucHVzaCgwICsgKGN1cnJlbnRWb2x1bWUgPiB0aHJlc2hvbGQpKTtcblxuICAgICAgbG9vcGVyKCk7XG4gICAgfSwgaW50ZXJ2YWwpO1xuICB9O1xuICBsb29wZXIoKTtcblxuXG4gIHJldHVybiBoYXJrZXI7XG59XG4iLCJpZiAodHlwZW9mIE9iamVjdC5jcmVhdGUgPT09ICdmdW5jdGlvbicpIHtcbiAgLy8gaW1wbGVtZW50YXRpb24gZnJvbSBzdGFuZGFyZCBub2RlLmpzICd1dGlsJyBtb2R1bGVcbiAgbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBpbmhlcml0cyhjdG9yLCBzdXBlckN0b3IpIHtcbiAgICBjdG9yLnN1cGVyXyA9IHN1cGVyQ3RvclxuICAgIGN0b3IucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShzdXBlckN0b3IucHJvdG90eXBlLCB7XG4gICAgICBjb25zdHJ1Y3Rvcjoge1xuICAgICAgICB2YWx1ZTogY3RvcixcbiAgICAgICAgZW51bWVyYWJsZTogZmFsc2UsXG4gICAgICAgIHdyaXRhYmxlOiB0cnVlLFxuICAgICAgICBjb25maWd1cmFibGU6IHRydWVcbiAgICAgIH1cbiAgICB9KTtcbiAgfTtcbn0gZWxzZSB7XG4gIC8vIG9sZCBzY2hvb2wgc2hpbSBmb3Igb2xkIGJyb3dzZXJzXG4gIG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gaW5oZXJpdHMoY3Rvciwgc3VwZXJDdG9yKSB7XG4gICAgY3Rvci5zdXBlcl8gPSBzdXBlckN0b3JcbiAgICB2YXIgVGVtcEN0b3IgPSBmdW5jdGlvbiAoKSB7fVxuICAgIFRlbXBDdG9yLnByb3RvdHlwZSA9IHN1cGVyQ3Rvci5wcm90b3R5cGVcbiAgICBjdG9yLnByb3RvdHlwZSA9IG5ldyBUZW1wQ3RvcigpXG4gICAgY3Rvci5wcm90b3R5cGUuY29uc3RydWN0b3IgPSBjdG9yXG4gIH1cbn1cbiIsIi8qKlxuICAjIG5vcm1hbGljZVxuXG4gIE5vcm1hbGl6ZSBhbiBpY2Ugc2VydmVyIGNvbmZpZ3VyYXRpb24gb2JqZWN0IChvciBwbGFpbiBvbGQgc3RyaW5nKSBpbnRvIGEgZm9ybWF0XG4gIHRoYXQgaXMgdXNhYmxlIGluIGFsbCBicm93c2VycyBzdXBwb3J0aW5nIFdlYlJUQy4gIFByaW1hcmlseSB0aGlzIG1vZHVsZSBpcyBkZXNpZ25lZFxuICB0byBoZWxwIHdpdGggdGhlIHRyYW5zaXRpb24gb2YgdGhlIGB1cmxgIGF0dHJpYnV0ZSBvZiB0aGUgY29uZmlndXJhdGlvbiBvYmplY3QgdG9cbiAgdGhlIGB1cmxzYCBhdHRyaWJ1dGUuXG5cbiAgIyMgRXhhbXBsZSBVc2FnZVxuXG4gIDw8PCBleGFtcGxlcy9zaW1wbGUuanNcblxuKiovXG5cbnZhciBwcm90b2NvbHMgPSBbXG4gICdzdHVuOicsXG4gICd0dXJuOidcbl07XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24oaW5wdXQpIHtcbiAgdmFyIHVybCA9IChpbnB1dCB8fCB7fSkudXJsIHx8IGlucHV0O1xuICB2YXIgcHJvdG9jb2w7XG4gIHZhciBwYXJ0cztcbiAgdmFyIG91dHB1dCA9IHt9O1xuXG4gIC8vIGlmIHdlIGRvbid0IGhhdmUgYSBzdHJpbmcgdXJsLCB0aGVuIGFsbG93IHRoZSBpbnB1dCB0byBwYXNzdGhyb3VnaFxuICBpZiAodHlwZW9mIHVybCAhPSAnc3RyaW5nJyAmJiAoISAodXJsIGluc3RhbmNlb2YgU3RyaW5nKSkpIHtcbiAgICByZXR1cm4gaW5wdXQ7XG4gIH1cblxuICAvLyB0cmltIHRoZSB1cmwgc3RyaW5nLCBhbmQgY29udmVydCB0byBhbiBhcnJheVxuICB1cmwgPSB1cmwudHJpbSgpO1xuXG4gIC8vIGlmIHRoZSBwcm90b2NvbCBpcyBub3Qga25vd24sIHRoZW4gcGFzc3Rocm91Z2hcbiAgcHJvdG9jb2wgPSBwcm90b2NvbHNbcHJvdG9jb2xzLmluZGV4T2YodXJsLnNsaWNlKDAsIDUpKV07XG4gIGlmICghIHByb3RvY29sKSB7XG4gICAgcmV0dXJuIGlucHV0O1xuICB9XG5cbiAgLy8gbm93IGxldCdzIGF0dGFjayB0aGUgcmVtYWluaW5nIHVybCBwYXJ0c1xuICB1cmwgPSB1cmwuc2xpY2UoNSk7XG4gIHBhcnRzID0gdXJsLnNwbGl0KCdAJyk7XG5cbiAgb3V0cHV0LnVzZXJuYW1lID0gaW5wdXQudXNlcm5hbWU7XG4gIG91dHB1dC5jcmVkZW50aWFsID0gaW5wdXQuY3JlZGVudGlhbDtcbiAgLy8gaWYgd2UgaGF2ZSBhbiBhdXRoZW50aWNhdGlvbiBwYXJ0LCB0aGVuIHNldCB0aGUgY3JlZGVudGlhbHNcbiAgaWYgKHBhcnRzLmxlbmd0aCA+IDEpIHtcbiAgICB1cmwgPSBwYXJ0c1sxXTtcbiAgICBwYXJ0cyA9IHBhcnRzWzBdLnNwbGl0KCc6Jyk7XG5cbiAgICAvLyBhZGQgdGhlIG91dHB1dCBjcmVkZW50aWFsIGFuZCB1c2VybmFtZVxuICAgIG91dHB1dC51c2VybmFtZSA9IHBhcnRzWzBdO1xuICAgIG91dHB1dC5jcmVkZW50aWFsID0gKGlucHV0IHx8IHt9KS5jcmVkZW50aWFsIHx8IHBhcnRzWzFdIHx8ICcnO1xuICB9XG5cbiAgb3V0cHV0LnVybCA9IHByb3RvY29sICsgdXJsO1xuICBvdXRwdXQudXJscyA9IFsgb3V0cHV0LnVybCBdO1xuXG4gIHJldHVybiBvdXRwdXQ7XG59O1xuIiwiLyohXG4gKiBQbGF0Zm9ybS5qcyA8aHR0cHM6Ly9tdGhzLmJlL3BsYXRmb3JtPlxuICogQ29weXJpZ2h0IDIwMTQtMjAxOCBCZW5qYW1pbiBUYW4gPGh0dHBzOi8vYm5qbW50NG4ubm93LnNoLz5cbiAqIENvcHlyaWdodCAyMDExLTIwMTMgSm9obi1EYXZpZCBEYWx0b24gPGh0dHA6Ly9hbGx5b3VjYW5sZWV0LmNvbS8+XG4gKiBBdmFpbGFibGUgdW5kZXIgTUlUIGxpY2Vuc2UgPGh0dHBzOi8vbXRocy5iZS9taXQ+XG4gKi9cbjsoZnVuY3Rpb24oKSB7XG4gICd1c2Ugc3RyaWN0JztcblxuICAvKiogVXNlZCB0byBkZXRlcm1pbmUgaWYgdmFsdWVzIGFyZSBvZiB0aGUgbGFuZ3VhZ2UgdHlwZSBgT2JqZWN0YC4gKi9cbiAgdmFyIG9iamVjdFR5cGVzID0ge1xuICAgICdmdW5jdGlvbic6IHRydWUsXG4gICAgJ29iamVjdCc6IHRydWVcbiAgfTtcblxuICAvKiogVXNlZCBhcyBhIHJlZmVyZW5jZSB0byB0aGUgZ2xvYmFsIG9iamVjdC4gKi9cbiAgdmFyIHJvb3QgPSAob2JqZWN0VHlwZXNbdHlwZW9mIHdpbmRvd10gJiYgd2luZG93KSB8fCB0aGlzO1xuXG4gIC8qKiBCYWNrdXAgcG9zc2libGUgZ2xvYmFsIG9iamVjdC4gKi9cbiAgdmFyIG9sZFJvb3QgPSByb290O1xuXG4gIC8qKiBEZXRlY3QgZnJlZSB2YXJpYWJsZSBgZXhwb3J0c2AuICovXG4gIHZhciBmcmVlRXhwb3J0cyA9IG9iamVjdFR5cGVzW3R5cGVvZiBleHBvcnRzXSAmJiBleHBvcnRzO1xuXG4gIC8qKiBEZXRlY3QgZnJlZSB2YXJpYWJsZSBgbW9kdWxlYC4gKi9cbiAgdmFyIGZyZWVNb2R1bGUgPSBvYmplY3RUeXBlc1t0eXBlb2YgbW9kdWxlXSAmJiBtb2R1bGUgJiYgIW1vZHVsZS5ub2RlVHlwZSAmJiBtb2R1bGU7XG5cbiAgLyoqIERldGVjdCBmcmVlIHZhcmlhYmxlIGBnbG9iYWxgIGZyb20gTm9kZS5qcyBvciBCcm93c2VyaWZpZWQgY29kZSBhbmQgdXNlIGl0IGFzIGByb290YC4gKi9cbiAgdmFyIGZyZWVHbG9iYWwgPSBmcmVlRXhwb3J0cyAmJiBmcmVlTW9kdWxlICYmIHR5cGVvZiBnbG9iYWwgPT0gJ29iamVjdCcgJiYgZ2xvYmFsO1xuICBpZiAoZnJlZUdsb2JhbCAmJiAoZnJlZUdsb2JhbC5nbG9iYWwgPT09IGZyZWVHbG9iYWwgfHwgZnJlZUdsb2JhbC53aW5kb3cgPT09IGZyZWVHbG9iYWwgfHwgZnJlZUdsb2JhbC5zZWxmID09PSBmcmVlR2xvYmFsKSkge1xuICAgIHJvb3QgPSBmcmVlR2xvYmFsO1xuICB9XG5cbiAgLyoqXG4gICAqIFVzZWQgYXMgdGhlIG1heGltdW0gbGVuZ3RoIG9mIGFuIGFycmF5LWxpa2Ugb2JqZWN0LlxuICAgKiBTZWUgdGhlIFtFUzYgc3BlY10oaHR0cDovL3Blb3BsZS5tb3ppbGxhLm9yZy9+am9yZW5kb3JmZi9lczYtZHJhZnQuaHRtbCNzZWMtdG9sZW5ndGgpXG4gICAqIGZvciBtb3JlIGRldGFpbHMuXG4gICAqL1xuICB2YXIgbWF4U2FmZUludGVnZXIgPSBNYXRoLnBvdygyLCA1MykgLSAxO1xuXG4gIC8qKiBSZWd1bGFyIGV4cHJlc3Npb24gdG8gZGV0ZWN0IE9wZXJhLiAqL1xuICB2YXIgcmVPcGVyYSA9IC9cXGJPcGVyYS87XG5cbiAgLyoqIFBvc3NpYmxlIGdsb2JhbCBvYmplY3QuICovXG4gIHZhciB0aGlzQmluZGluZyA9IHRoaXM7XG5cbiAgLyoqIFVzZWQgZm9yIG5hdGl2ZSBtZXRob2QgcmVmZXJlbmNlcy4gKi9cbiAgdmFyIG9iamVjdFByb3RvID0gT2JqZWN0LnByb3RvdHlwZTtcblxuICAvKiogVXNlZCB0byBjaGVjayBmb3Igb3duIHByb3BlcnRpZXMgb2YgYW4gb2JqZWN0LiAqL1xuICB2YXIgaGFzT3duUHJvcGVydHkgPSBvYmplY3RQcm90by5oYXNPd25Qcm9wZXJ0eTtcblxuICAvKiogVXNlZCB0byByZXNvbHZlIHRoZSBpbnRlcm5hbCBgW1tDbGFzc11dYCBvZiB2YWx1ZXMuICovXG4gIHZhciB0b1N0cmluZyA9IG9iamVjdFByb3RvLnRvU3RyaW5nO1xuXG4gIC8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuXG4gIC8qKlxuICAgKiBDYXBpdGFsaXplcyBhIHN0cmluZyB2YWx1ZS5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtzdHJpbmd9IHN0cmluZyBUaGUgc3RyaW5nIHRvIGNhcGl0YWxpemUuXG4gICAqIEByZXR1cm5zIHtzdHJpbmd9IFRoZSBjYXBpdGFsaXplZCBzdHJpbmcuXG4gICAqL1xuICBmdW5jdGlvbiBjYXBpdGFsaXplKHN0cmluZykge1xuICAgIHN0cmluZyA9IFN0cmluZyhzdHJpbmcpO1xuICAgIHJldHVybiBzdHJpbmcuY2hhckF0KDApLnRvVXBwZXJDYXNlKCkgKyBzdHJpbmcuc2xpY2UoMSk7XG4gIH1cblxuICAvKipcbiAgICogQSB1dGlsaXR5IGZ1bmN0aW9uIHRvIGNsZWFuIHVwIHRoZSBPUyBuYW1lLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gb3MgVGhlIE9TIG5hbWUgdG8gY2xlYW4gdXAuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbcGF0dGVybl0gQSBgUmVnRXhwYCBwYXR0ZXJuIG1hdGNoaW5nIHRoZSBPUyBuYW1lLlxuICAgKiBAcGFyYW0ge3N0cmluZ30gW2xhYmVsXSBBIGxhYmVsIGZvciB0aGUgT1MuXG4gICAqL1xuICBmdW5jdGlvbiBjbGVhbnVwT1Mob3MsIHBhdHRlcm4sIGxhYmVsKSB7XG4gICAgLy8gUGxhdGZvcm0gdG9rZW5zIGFyZSBkZWZpbmVkIGF0OlxuICAgIC8vIGh0dHA6Ly9tc2RuLm1pY3Jvc29mdC5jb20vZW4tdXMvbGlicmFyeS9tczUzNzUwMyhWUy44NSkuYXNweFxuICAgIC8vIGh0dHA6Ly93ZWIuYXJjaGl2ZS5vcmcvd2ViLzIwMDgxMTIyMDUzOTUwL2h0dHA6Ly9tc2RuLm1pY3Jvc29mdC5jb20vZW4tdXMvbGlicmFyeS9tczUzNzUwMyhWUy44NSkuYXNweFxuICAgIHZhciBkYXRhID0ge1xuICAgICAgJzEwLjAnOiAnMTAnLFxuICAgICAgJzYuNCc6ICAnMTAgVGVjaG5pY2FsIFByZXZpZXcnLFxuICAgICAgJzYuMyc6ICAnOC4xJyxcbiAgICAgICc2LjInOiAgJzgnLFxuICAgICAgJzYuMSc6ICAnU2VydmVyIDIwMDggUjIgLyA3JyxcbiAgICAgICc2LjAnOiAgJ1NlcnZlciAyMDA4IC8gVmlzdGEnLFxuICAgICAgJzUuMic6ICAnU2VydmVyIDIwMDMgLyBYUCA2NC1iaXQnLFxuICAgICAgJzUuMSc6ICAnWFAnLFxuICAgICAgJzUuMDEnOiAnMjAwMCBTUDEnLFxuICAgICAgJzUuMCc6ICAnMjAwMCcsXG4gICAgICAnNC4wJzogICdOVCcsXG4gICAgICAnNC45MCc6ICdNRSdcbiAgICB9O1xuICAgIC8vIERldGVjdCBXaW5kb3dzIHZlcnNpb24gZnJvbSBwbGF0Zm9ybSB0b2tlbnMuXG4gICAgaWYgKHBhdHRlcm4gJiYgbGFiZWwgJiYgL15XaW4vaS50ZXN0KG9zKSAmJiAhL15XaW5kb3dzIFBob25lIC9pLnRlc3Qob3MpICYmXG4gICAgICAgIChkYXRhID0gZGF0YVsvW1xcZC5dKyQvLmV4ZWMob3MpXSkpIHtcbiAgICAgIG9zID0gJ1dpbmRvd3MgJyArIGRhdGE7XG4gICAgfVxuICAgIC8vIENvcnJlY3QgY2hhcmFjdGVyIGNhc2UgYW5kIGNsZWFudXAgc3RyaW5nLlxuICAgIG9zID0gU3RyaW5nKG9zKTtcblxuICAgIGlmIChwYXR0ZXJuICYmIGxhYmVsKSB7XG4gICAgICBvcyA9IG9zLnJlcGxhY2UoUmVnRXhwKHBhdHRlcm4sICdpJyksIGxhYmVsKTtcbiAgICB9XG5cbiAgICBvcyA9IGZvcm1hdChcbiAgICAgIG9zLnJlcGxhY2UoLyBjZSQvaSwgJyBDRScpXG4gICAgICAgIC5yZXBsYWNlKC9cXGJocHcvaSwgJ3dlYicpXG4gICAgICAgIC5yZXBsYWNlKC9cXGJNYWNpbnRvc2hcXGIvLCAnTWFjIE9TJylcbiAgICAgICAgLnJlcGxhY2UoL19Qb3dlclBDXFxiL2ksICcgT1MnKVxuICAgICAgICAucmVwbGFjZSgvXFxiKE9TIFgpIFteIFxcZF0rL2ksICckMScpXG4gICAgICAgIC5yZXBsYWNlKC9cXGJNYWMgKE9TIFgpXFxiLywgJyQxJylcbiAgICAgICAgLnJlcGxhY2UoL1xcLyhcXGQpLywgJyAkMScpXG4gICAgICAgIC5yZXBsYWNlKC9fL2csICcuJylcbiAgICAgICAgLnJlcGxhY2UoLyg/OiBCZVBDfFsgLl0qZmNbIFxcZC5dKykkL2ksICcnKVxuICAgICAgICAucmVwbGFjZSgvXFxieDg2XFwuNjRcXGIvZ2ksICd4ODZfNjQnKVxuICAgICAgICAucmVwbGFjZSgvXFxiKFdpbmRvd3MgUGhvbmUpIE9TXFxiLywgJyQxJylcbiAgICAgICAgLnJlcGxhY2UoL1xcYihDaHJvbWUgT1MgXFx3KykgW1xcZC5dK1xcYi8sICckMScpXG4gICAgICAgIC5zcGxpdCgnIG9uICcpWzBdXG4gICAgKTtcblxuICAgIHJldHVybiBvcztcbiAgfVxuXG4gIC8qKlxuICAgKiBBbiBpdGVyYXRpb24gdXRpbGl0eSBmb3IgYXJyYXlzIGFuZCBvYmplY3RzLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge0FycmF5fE9iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gaXRlcmF0ZSBvdmVyLlxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBjYWxsYmFjayBUaGUgZnVuY3Rpb24gY2FsbGVkIHBlciBpdGVyYXRpb24uXG4gICAqL1xuICBmdW5jdGlvbiBlYWNoKG9iamVjdCwgY2FsbGJhY2spIHtcbiAgICB2YXIgaW5kZXggPSAtMSxcbiAgICAgICAgbGVuZ3RoID0gb2JqZWN0ID8gb2JqZWN0Lmxlbmd0aCA6IDA7XG5cbiAgICBpZiAodHlwZW9mIGxlbmd0aCA9PSAnbnVtYmVyJyAmJiBsZW5ndGggPiAtMSAmJiBsZW5ndGggPD0gbWF4U2FmZUludGVnZXIpIHtcbiAgICAgIHdoaWxlICgrK2luZGV4IDwgbGVuZ3RoKSB7XG4gICAgICAgIGNhbGxiYWNrKG9iamVjdFtpbmRleF0sIGluZGV4LCBvYmplY3QpO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBmb3JPd24ob2JqZWN0LCBjYWxsYmFjayk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFRyaW0gYW5kIGNvbmRpdGlvbmFsbHkgY2FwaXRhbGl6ZSBzdHJpbmcgdmFsdWVzLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gc3RyaW5nIFRoZSBzdHJpbmcgdG8gZm9ybWF0LlxuICAgKiBAcmV0dXJucyB7c3RyaW5nfSBUaGUgZm9ybWF0dGVkIHN0cmluZy5cbiAgICovXG4gIGZ1bmN0aW9uIGZvcm1hdChzdHJpbmcpIHtcbiAgICBzdHJpbmcgPSB0cmltKHN0cmluZyk7XG4gICAgcmV0dXJuIC9eKD86d2ViT1N8aSg/Ok9TfFApKS8udGVzdChzdHJpbmcpXG4gICAgICA/IHN0cmluZ1xuICAgICAgOiBjYXBpdGFsaXplKHN0cmluZyk7XG4gIH1cblxuICAvKipcbiAgICogSXRlcmF0ZXMgb3ZlciBhbiBvYmplY3QncyBvd24gcHJvcGVydGllcywgZXhlY3V0aW5nIHRoZSBgY2FsbGJhY2tgIGZvciBlYWNoLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gaXRlcmF0ZSBvdmVyLlxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBjYWxsYmFjayBUaGUgZnVuY3Rpb24gZXhlY3V0ZWQgcGVyIG93biBwcm9wZXJ0eS5cbiAgICovXG4gIGZ1bmN0aW9uIGZvck93bihvYmplY3QsIGNhbGxiYWNrKSB7XG4gICAgZm9yICh2YXIga2V5IGluIG9iamVjdCkge1xuICAgICAgaWYgKGhhc093blByb3BlcnR5LmNhbGwob2JqZWN0LCBrZXkpKSB7XG4gICAgICAgIGNhbGxiYWNrKG9iamVjdFtrZXldLCBrZXksIG9iamVjdCk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEdldHMgdGhlIGludGVybmFsIGBbW0NsYXNzXV1gIG9mIGEgdmFsdWUuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlLlxuICAgKiBAcmV0dXJucyB7c3RyaW5nfSBUaGUgYFtbQ2xhc3NdXWAuXG4gICAqL1xuICBmdW5jdGlvbiBnZXRDbGFzc09mKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlID09IG51bGxcbiAgICAgID8gY2FwaXRhbGl6ZSh2YWx1ZSlcbiAgICAgIDogdG9TdHJpbmcuY2FsbCh2YWx1ZSkuc2xpY2UoOCwgLTEpO1xuICB9XG5cbiAgLyoqXG4gICAqIEhvc3Qgb2JqZWN0cyBjYW4gcmV0dXJuIHR5cGUgdmFsdWVzIHRoYXQgYXJlIGRpZmZlcmVudCBmcm9tIHRoZWlyIGFjdHVhbFxuICAgKiBkYXRhIHR5cGUuIFRoZSBvYmplY3RzIHdlIGFyZSBjb25jZXJuZWQgd2l0aCB1c3VhbGx5IHJldHVybiBub24tcHJpbWl0aXZlXG4gICAqIHR5cGVzIG9mIFwib2JqZWN0XCIsIFwiZnVuY3Rpb25cIiwgb3IgXCJ1bmtub3duXCIuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7Kn0gb2JqZWN0IFRoZSBvd25lciBvZiB0aGUgcHJvcGVydHkuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBwcm9wZXJ0eSBUaGUgcHJvcGVydHkgdG8gY2hlY2suXG4gICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiB0aGUgcHJvcGVydHkgdmFsdWUgaXMgYSBub24tcHJpbWl0aXZlLCBlbHNlIGBmYWxzZWAuXG4gICAqL1xuICBmdW5jdGlvbiBpc0hvc3RUeXBlKG9iamVjdCwgcHJvcGVydHkpIHtcbiAgICB2YXIgdHlwZSA9IG9iamVjdCAhPSBudWxsID8gdHlwZW9mIG9iamVjdFtwcm9wZXJ0eV0gOiAnbnVtYmVyJztcbiAgICByZXR1cm4gIS9eKD86Ym9vbGVhbnxudW1iZXJ8c3RyaW5nfHVuZGVmaW5lZCkkLy50ZXN0KHR5cGUpICYmXG4gICAgICAodHlwZSA9PSAnb2JqZWN0JyA/ICEhb2JqZWN0W3Byb3BlcnR5XSA6IHRydWUpO1xuICB9XG5cbiAgLyoqXG4gICAqIFByZXBhcmVzIGEgc3RyaW5nIGZvciB1c2UgaW4gYSBgUmVnRXhwYCBieSBtYWtpbmcgaHlwaGVucyBhbmQgc3BhY2VzIG9wdGlvbmFsLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gc3RyaW5nIFRoZSBzdHJpbmcgdG8gcXVhbGlmeS5cbiAgICogQHJldHVybnMge3N0cmluZ30gVGhlIHF1YWxpZmllZCBzdHJpbmcuXG4gICAqL1xuICBmdW5jdGlvbiBxdWFsaWZ5KHN0cmluZykge1xuICAgIHJldHVybiBTdHJpbmcoc3RyaW5nKS5yZXBsYWNlKC8oWyAtXSkoPyEkKS9nLCAnJDE/Jyk7XG4gIH1cblxuICAvKipcbiAgICogQSBiYXJlLWJvbmVzIGBBcnJheSNyZWR1Y2VgIGxpa2UgdXRpbGl0eSBmdW5jdGlvbi5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIGl0ZXJhdGUgb3Zlci5cbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gY2FsbGJhY2sgVGhlIGZ1bmN0aW9uIGNhbGxlZCBwZXIgaXRlcmF0aW9uLlxuICAgKiBAcmV0dXJucyB7Kn0gVGhlIGFjY3VtdWxhdGVkIHJlc3VsdC5cbiAgICovXG4gIGZ1bmN0aW9uIHJlZHVjZShhcnJheSwgY2FsbGJhY2spIHtcbiAgICB2YXIgYWNjdW11bGF0b3IgPSBudWxsO1xuICAgIGVhY2goYXJyYXksIGZ1bmN0aW9uKHZhbHVlLCBpbmRleCkge1xuICAgICAgYWNjdW11bGF0b3IgPSBjYWxsYmFjayhhY2N1bXVsYXRvciwgdmFsdWUsIGluZGV4LCBhcnJheSk7XG4gICAgfSk7XG4gICAgcmV0dXJuIGFjY3VtdWxhdG9yO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlbW92ZXMgbGVhZGluZyBhbmQgdHJhaWxpbmcgd2hpdGVzcGFjZSBmcm9tIGEgc3RyaW5nLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gc3RyaW5nIFRoZSBzdHJpbmcgdG8gdHJpbS5cbiAgICogQHJldHVybnMge3N0cmluZ30gVGhlIHRyaW1tZWQgc3RyaW5nLlxuICAgKi9cbiAgZnVuY3Rpb24gdHJpbShzdHJpbmcpIHtcbiAgICByZXR1cm4gU3RyaW5nKHN0cmluZykucmVwbGFjZSgvXiArfCArJC9nLCAnJyk7XG4gIH1cblxuICAvKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cblxuICAvKipcbiAgICogQ3JlYXRlcyBhIG5ldyBwbGF0Zm9ybSBvYmplY3QuXG4gICAqXG4gICAqIEBtZW1iZXJPZiBwbGF0Zm9ybVxuICAgKiBAcGFyYW0ge09iamVjdHxzdHJpbmd9IFt1YT1uYXZpZ2F0b3IudXNlckFnZW50XSBUaGUgdXNlciBhZ2VudCBzdHJpbmcgb3JcbiAgICogIGNvbnRleHQgb2JqZWN0LlxuICAgKiBAcmV0dXJucyB7T2JqZWN0fSBBIHBsYXRmb3JtIG9iamVjdC5cbiAgICovXG4gIGZ1bmN0aW9uIHBhcnNlKHVhKSB7XG5cbiAgICAvKiogVGhlIGVudmlyb25tZW50IGNvbnRleHQgb2JqZWN0LiAqL1xuICAgIHZhciBjb250ZXh0ID0gcm9vdDtcblxuICAgIC8qKiBVc2VkIHRvIGZsYWcgd2hlbiBhIGN1c3RvbSBjb250ZXh0IGlzIHByb3ZpZGVkLiAqL1xuICAgIHZhciBpc0N1c3RvbUNvbnRleHQgPSB1YSAmJiB0eXBlb2YgdWEgPT0gJ29iamVjdCcgJiYgZ2V0Q2xhc3NPZih1YSkgIT0gJ1N0cmluZyc7XG5cbiAgICAvLyBKdWdnbGUgYXJndW1lbnRzLlxuICAgIGlmIChpc0N1c3RvbUNvbnRleHQpIHtcbiAgICAgIGNvbnRleHQgPSB1YTtcbiAgICAgIHVhID0gbnVsbDtcbiAgICB9XG5cbiAgICAvKiogQnJvd3NlciBuYXZpZ2F0b3Igb2JqZWN0LiAqL1xuICAgIHZhciBuYXYgPSBjb250ZXh0Lm5hdmlnYXRvciB8fCB7fTtcblxuICAgIC8qKiBCcm93c2VyIHVzZXIgYWdlbnQgc3RyaW5nLiAqL1xuICAgIHZhciB1c2VyQWdlbnQgPSBuYXYudXNlckFnZW50IHx8ICcnO1xuXG4gICAgdWEgfHwgKHVhID0gdXNlckFnZW50KTtcblxuICAgIC8qKiBVc2VkIHRvIGZsYWcgd2hlbiBgdGhpc0JpbmRpbmdgIGlzIHRoZSBbTW9kdWxlU2NvcGVdLiAqL1xuICAgIHZhciBpc01vZHVsZVNjb3BlID0gaXNDdXN0b21Db250ZXh0IHx8IHRoaXNCaW5kaW5nID09IG9sZFJvb3Q7XG5cbiAgICAvKiogVXNlZCB0byBkZXRlY3QgaWYgYnJvd3NlciBpcyBsaWtlIENocm9tZS4gKi9cbiAgICB2YXIgbGlrZUNocm9tZSA9IGlzQ3VzdG9tQ29udGV4dFxuICAgICAgPyAhIW5hdi5saWtlQ2hyb21lXG4gICAgICA6IC9cXGJDaHJvbWVcXGIvLnRlc3QodWEpICYmICEvaW50ZXJuYWx8XFxuL2kudGVzdCh0b1N0cmluZy50b1N0cmluZygpKTtcblxuICAgIC8qKiBJbnRlcm5hbCBgW1tDbGFzc11dYCB2YWx1ZSBzaG9ydGN1dHMuICovXG4gICAgdmFyIG9iamVjdENsYXNzID0gJ09iamVjdCcsXG4gICAgICAgIGFpclJ1bnRpbWVDbGFzcyA9IGlzQ3VzdG9tQ29udGV4dCA/IG9iamVjdENsYXNzIDogJ1NjcmlwdEJyaWRnaW5nUHJveHlPYmplY3QnLFxuICAgICAgICBlbnZpcm9DbGFzcyA9IGlzQ3VzdG9tQ29udGV4dCA/IG9iamVjdENsYXNzIDogJ0Vudmlyb25tZW50JyxcbiAgICAgICAgamF2YUNsYXNzID0gKGlzQ3VzdG9tQ29udGV4dCAmJiBjb250ZXh0LmphdmEpID8gJ0phdmFQYWNrYWdlJyA6IGdldENsYXNzT2YoY29udGV4dC5qYXZhKSxcbiAgICAgICAgcGhhbnRvbUNsYXNzID0gaXNDdXN0b21Db250ZXh0ID8gb2JqZWN0Q2xhc3MgOiAnUnVudGltZU9iamVjdCc7XG5cbiAgICAvKiogRGV0ZWN0IEphdmEgZW52aXJvbm1lbnRzLiAqL1xuICAgIHZhciBqYXZhID0gL1xcYkphdmEvLnRlc3QoamF2YUNsYXNzKSAmJiBjb250ZXh0LmphdmE7XG5cbiAgICAvKiogRGV0ZWN0IFJoaW5vLiAqL1xuICAgIHZhciByaGlubyA9IGphdmEgJiYgZ2V0Q2xhc3NPZihjb250ZXh0LmVudmlyb25tZW50KSA9PSBlbnZpcm9DbGFzcztcblxuICAgIC8qKiBBIGNoYXJhY3RlciB0byByZXByZXNlbnQgYWxwaGEuICovXG4gICAgdmFyIGFscGhhID0gamF2YSA/ICdhJyA6ICdcXHUwM2IxJztcblxuICAgIC8qKiBBIGNoYXJhY3RlciB0byByZXByZXNlbnQgYmV0YS4gKi9cbiAgICB2YXIgYmV0YSA9IGphdmEgPyAnYicgOiAnXFx1MDNiMic7XG5cbiAgICAvKiogQnJvd3NlciBkb2N1bWVudCBvYmplY3QuICovXG4gICAgdmFyIGRvYyA9IGNvbnRleHQuZG9jdW1lbnQgfHwge307XG5cbiAgICAvKipcbiAgICAgKiBEZXRlY3QgT3BlcmEgYnJvd3NlciAoUHJlc3RvLWJhc2VkKS5cbiAgICAgKiBodHRwOi8vd3d3Lmhvd3RvY3JlYXRlLmNvLnVrL29wZXJhU3R1ZmYvb3BlcmFPYmplY3QuaHRtbFxuICAgICAqIGh0dHA6Ly9kZXYub3BlcmEuY29tL2FydGljbGVzL3ZpZXcvb3BlcmEtbWluaS13ZWItY29udGVudC1hdXRob3JpbmctZ3VpZGVsaW5lcy8jb3BlcmFtaW5pXG4gICAgICovXG4gICAgdmFyIG9wZXJhID0gY29udGV4dC5vcGVyYW1pbmkgfHwgY29udGV4dC5vcGVyYTtcblxuICAgIC8qKiBPcGVyYSBgW1tDbGFzc11dYC4gKi9cbiAgICB2YXIgb3BlcmFDbGFzcyA9IHJlT3BlcmEudGVzdChvcGVyYUNsYXNzID0gKGlzQ3VzdG9tQ29udGV4dCAmJiBvcGVyYSkgPyBvcGVyYVsnW1tDbGFzc11dJ10gOiBnZXRDbGFzc09mKG9wZXJhKSlcbiAgICAgID8gb3BlcmFDbGFzc1xuICAgICAgOiAob3BlcmEgPSBudWxsKTtcblxuICAgIC8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cblxuICAgIC8qKiBUZW1wb3JhcnkgdmFyaWFibGUgdXNlZCBvdmVyIHRoZSBzY3JpcHQncyBsaWZldGltZS4gKi9cbiAgICB2YXIgZGF0YTtcblxuICAgIC8qKiBUaGUgQ1BVIGFyY2hpdGVjdHVyZS4gKi9cbiAgICB2YXIgYXJjaCA9IHVhO1xuXG4gICAgLyoqIFBsYXRmb3JtIGRlc2NyaXB0aW9uIGFycmF5LiAqL1xuICAgIHZhciBkZXNjcmlwdGlvbiA9IFtdO1xuXG4gICAgLyoqIFBsYXRmb3JtIGFscGhhL2JldGEgaW5kaWNhdG9yLiAqL1xuICAgIHZhciBwcmVyZWxlYXNlID0gbnVsbDtcblxuICAgIC8qKiBBIGZsYWcgdG8gaW5kaWNhdGUgdGhhdCBlbnZpcm9ubWVudCBmZWF0dXJlcyBzaG91bGQgYmUgdXNlZCB0byByZXNvbHZlIHRoZSBwbGF0Zm9ybS4gKi9cbiAgICB2YXIgdXNlRmVhdHVyZXMgPSB1YSA9PSB1c2VyQWdlbnQ7XG5cbiAgICAvKiogVGhlIGJyb3dzZXIvZW52aXJvbm1lbnQgdmVyc2lvbi4gKi9cbiAgICB2YXIgdmVyc2lvbiA9IHVzZUZlYXR1cmVzICYmIG9wZXJhICYmIHR5cGVvZiBvcGVyYS52ZXJzaW9uID09ICdmdW5jdGlvbicgJiYgb3BlcmEudmVyc2lvbigpO1xuXG4gICAgLyoqIEEgZmxhZyB0byBpbmRpY2F0ZSBpZiB0aGUgT1MgZW5kcyB3aXRoIFwiLyBWZXJzaW9uXCIgKi9cbiAgICB2YXIgaXNTcGVjaWFsQ2FzZWRPUztcblxuICAgIC8qIERldGVjdGFibGUgbGF5b3V0IGVuZ2luZXMgKG9yZGVyIGlzIGltcG9ydGFudCkuICovXG4gICAgdmFyIGxheW91dCA9IGdldExheW91dChbXG4gICAgICB7ICdsYWJlbCc6ICdFZGdlSFRNTCcsICdwYXR0ZXJuJzogJ0VkZ2UnIH0sXG4gICAgICAnVHJpZGVudCcsXG4gICAgICB7ICdsYWJlbCc6ICdXZWJLaXQnLCAncGF0dGVybic6ICdBcHBsZVdlYktpdCcgfSxcbiAgICAgICdpQ2FiJyxcbiAgICAgICdQcmVzdG8nLFxuICAgICAgJ05ldEZyb250JyxcbiAgICAgICdUYXNtYW4nLFxuICAgICAgJ0tIVE1MJyxcbiAgICAgICdHZWNrbydcbiAgICBdKTtcblxuICAgIC8qIERldGVjdGFibGUgYnJvd3NlciBuYW1lcyAob3JkZXIgaXMgaW1wb3J0YW50KS4gKi9cbiAgICB2YXIgbmFtZSA9IGdldE5hbWUoW1xuICAgICAgJ0Fkb2JlIEFJUicsXG4gICAgICAnQXJvcmEnLFxuICAgICAgJ0F2YW50IEJyb3dzZXInLFxuICAgICAgJ0JyZWFjaCcsXG4gICAgICAnQ2FtaW5vJyxcbiAgICAgICdFbGVjdHJvbicsXG4gICAgICAnRXBpcGhhbnknLFxuICAgICAgJ0Zlbm5lYycsXG4gICAgICAnRmxvY2snLFxuICAgICAgJ0dhbGVvbicsXG4gICAgICAnR3JlZW5Ccm93c2VyJyxcbiAgICAgICdpQ2FiJyxcbiAgICAgICdJY2V3ZWFzZWwnLFxuICAgICAgJ0stTWVsZW9uJyxcbiAgICAgICdLb25xdWVyb3InLFxuICAgICAgJ0x1bmFzY2FwZScsXG4gICAgICAnTWF4dGhvbicsXG4gICAgICB7ICdsYWJlbCc6ICdNaWNyb3NvZnQgRWRnZScsICdwYXR0ZXJuJzogJ0VkZ2UnIH0sXG4gICAgICAnTWlkb3JpJyxcbiAgICAgICdOb29rIEJyb3dzZXInLFxuICAgICAgJ1BhbGVNb29uJyxcbiAgICAgICdQaGFudG9tSlMnLFxuICAgICAgJ1JhdmVuJyxcbiAgICAgICdSZWtvbnEnLFxuICAgICAgJ1JvY2tNZWx0JyxcbiAgICAgIHsgJ2xhYmVsJzogJ1NhbXN1bmcgSW50ZXJuZXQnLCAncGF0dGVybic6ICdTYW1zdW5nQnJvd3NlcicgfSxcbiAgICAgICdTZWFNb25rZXknLFxuICAgICAgeyAnbGFiZWwnOiAnU2lsaycsICdwYXR0ZXJuJzogJyg/OkNsb3VkOXxTaWxrLUFjY2VsZXJhdGVkKScgfSxcbiAgICAgICdTbGVpcG5pcicsXG4gICAgICAnU2xpbUJyb3dzZXInLFxuICAgICAgeyAnbGFiZWwnOiAnU1JXYXJlIElyb24nLCAncGF0dGVybic6ICdJcm9uJyB9LFxuICAgICAgJ1N1bnJpc2UnLFxuICAgICAgJ1N3aWZ0Zm94JyxcbiAgICAgICdXYXRlcmZveCcsXG4gICAgICAnV2ViUG9zaXRpdmUnLFxuICAgICAgJ09wZXJhIE1pbmknLFxuICAgICAgeyAnbGFiZWwnOiAnT3BlcmEgTWluaScsICdwYXR0ZXJuJzogJ09QaU9TJyB9LFxuICAgICAgJ09wZXJhJyxcbiAgICAgIHsgJ2xhYmVsJzogJ09wZXJhJywgJ3BhdHRlcm4nOiAnT1BSJyB9LFxuICAgICAgJ0Nocm9tZScsXG4gICAgICB7ICdsYWJlbCc6ICdDaHJvbWUgTW9iaWxlJywgJ3BhdHRlcm4nOiAnKD86Q3JpT1N8Q3JNbyknIH0sXG4gICAgICB7ICdsYWJlbCc6ICdGaXJlZm94JywgJ3BhdHRlcm4nOiAnKD86RmlyZWZveHxNaW5lZmllbGQpJyB9LFxuICAgICAgeyAnbGFiZWwnOiAnRmlyZWZveCBmb3IgaU9TJywgJ3BhdHRlcm4nOiAnRnhpT1MnIH0sXG4gICAgICB7ICdsYWJlbCc6ICdJRScsICdwYXR0ZXJuJzogJ0lFTW9iaWxlJyB9LFxuICAgICAgeyAnbGFiZWwnOiAnSUUnLCAncGF0dGVybic6ICdNU0lFJyB9LFxuICAgICAgJ1NhZmFyaSdcbiAgICBdKTtcblxuICAgIC8qIERldGVjdGFibGUgcHJvZHVjdHMgKG9yZGVyIGlzIGltcG9ydGFudCkuICovXG4gICAgdmFyIHByb2R1Y3QgPSBnZXRQcm9kdWN0KFtcbiAgICAgIHsgJ2xhYmVsJzogJ0JsYWNrQmVycnknLCAncGF0dGVybic6ICdCQjEwJyB9LFxuICAgICAgJ0JsYWNrQmVycnknLFxuICAgICAgeyAnbGFiZWwnOiAnR2FsYXh5IFMnLCAncGF0dGVybic6ICdHVC1JOTAwMCcgfSxcbiAgICAgIHsgJ2xhYmVsJzogJ0dhbGF4eSBTMicsICdwYXR0ZXJuJzogJ0dULUk5MTAwJyB9LFxuICAgICAgeyAnbGFiZWwnOiAnR2FsYXh5IFMzJywgJ3BhdHRlcm4nOiAnR1QtSTkzMDAnIH0sXG4gICAgICB7ICdsYWJlbCc6ICdHYWxheHkgUzQnLCAncGF0dGVybic6ICdHVC1JOTUwMCcgfSxcbiAgICAgIHsgJ2xhYmVsJzogJ0dhbGF4eSBTNScsICdwYXR0ZXJuJzogJ1NNLUc5MDAnIH0sXG4gICAgICB7ICdsYWJlbCc6ICdHYWxheHkgUzYnLCAncGF0dGVybic6ICdTTS1HOTIwJyB9LFxuICAgICAgeyAnbGFiZWwnOiAnR2FsYXh5IFM2IEVkZ2UnLCAncGF0dGVybic6ICdTTS1HOTI1JyB9LFxuICAgICAgeyAnbGFiZWwnOiAnR2FsYXh5IFM3JywgJ3BhdHRlcm4nOiAnU00tRzkzMCcgfSxcbiAgICAgIHsgJ2xhYmVsJzogJ0dhbGF4eSBTNyBFZGdlJywgJ3BhdHRlcm4nOiAnU00tRzkzNScgfSxcbiAgICAgICdHb29nbGUgVFYnLFxuICAgICAgJ0x1bWlhJyxcbiAgICAgICdpUGFkJyxcbiAgICAgICdpUG9kJyxcbiAgICAgICdpUGhvbmUnLFxuICAgICAgJ0tpbmRsZScsXG4gICAgICB7ICdsYWJlbCc6ICdLaW5kbGUgRmlyZScsICdwYXR0ZXJuJzogJyg/OkNsb3VkOXxTaWxrLUFjY2VsZXJhdGVkKScgfSxcbiAgICAgICdOZXh1cycsXG4gICAgICAnTm9vaycsXG4gICAgICAnUGxheUJvb2snLFxuICAgICAgJ1BsYXlTdGF0aW9uIFZpdGEnLFxuICAgICAgJ1BsYXlTdGF0aW9uJyxcbiAgICAgICdUb3VjaFBhZCcsXG4gICAgICAnVHJhbnNmb3JtZXInLFxuICAgICAgeyAnbGFiZWwnOiAnV2lpIFUnLCAncGF0dGVybic6ICdXaWlVJyB9LFxuICAgICAgJ1dpaScsXG4gICAgICAnWGJveCBPbmUnLFxuICAgICAgeyAnbGFiZWwnOiAnWGJveCAzNjAnLCAncGF0dGVybic6ICdYYm94JyB9LFxuICAgICAgJ1hvb20nXG4gICAgXSk7XG5cbiAgICAvKiBEZXRlY3RhYmxlIG1hbnVmYWN0dXJlcnMuICovXG4gICAgdmFyIG1hbnVmYWN0dXJlciA9IGdldE1hbnVmYWN0dXJlcih7XG4gICAgICAnQXBwbGUnOiB7ICdpUGFkJzogMSwgJ2lQaG9uZSc6IDEsICdpUG9kJzogMSB9LFxuICAgICAgJ0FyY2hvcyc6IHt9LFxuICAgICAgJ0FtYXpvbic6IHsgJ0tpbmRsZSc6IDEsICdLaW5kbGUgRmlyZSc6IDEgfSxcbiAgICAgICdBc3VzJzogeyAnVHJhbnNmb3JtZXInOiAxIH0sXG4gICAgICAnQmFybmVzICYgTm9ibGUnOiB7ICdOb29rJzogMSB9LFxuICAgICAgJ0JsYWNrQmVycnknOiB7ICdQbGF5Qm9vayc6IDEgfSxcbiAgICAgICdHb29nbGUnOiB7ICdHb29nbGUgVFYnOiAxLCAnTmV4dXMnOiAxIH0sXG4gICAgICAnSFAnOiB7ICdUb3VjaFBhZCc6IDEgfSxcbiAgICAgICdIVEMnOiB7fSxcbiAgICAgICdMRyc6IHt9LFxuICAgICAgJ01pY3Jvc29mdCc6IHsgJ1hib3gnOiAxLCAnWGJveCBPbmUnOiAxIH0sXG4gICAgICAnTW90b3JvbGEnOiB7ICdYb29tJzogMSB9LFxuICAgICAgJ05pbnRlbmRvJzogeyAnV2lpIFUnOiAxLCAgJ1dpaSc6IDEgfSxcbiAgICAgICdOb2tpYSc6IHsgJ0x1bWlhJzogMSB9LFxuICAgICAgJ1NhbXN1bmcnOiB7ICdHYWxheHkgUyc6IDEsICdHYWxheHkgUzInOiAxLCAnR2FsYXh5IFMzJzogMSwgJ0dhbGF4eSBTNCc6IDEgfSxcbiAgICAgICdTb255JzogeyAnUGxheVN0YXRpb24nOiAxLCAnUGxheVN0YXRpb24gVml0YSc6IDEgfVxuICAgIH0pO1xuXG4gICAgLyogRGV0ZWN0YWJsZSBvcGVyYXRpbmcgc3lzdGVtcyAob3JkZXIgaXMgaW1wb3J0YW50KS4gKi9cbiAgICB2YXIgb3MgPSBnZXRPUyhbXG4gICAgICAnV2luZG93cyBQaG9uZScsXG4gICAgICAnQW5kcm9pZCcsXG4gICAgICAnQ2VudE9TJyxcbiAgICAgIHsgJ2xhYmVsJzogJ0Nocm9tZSBPUycsICdwYXR0ZXJuJzogJ0NyT1MnIH0sXG4gICAgICAnRGViaWFuJyxcbiAgICAgICdGZWRvcmEnLFxuICAgICAgJ0ZyZWVCU0QnLFxuICAgICAgJ0dlbnRvbycsXG4gICAgICAnSGFpa3UnLFxuICAgICAgJ0t1YnVudHUnLFxuICAgICAgJ0xpbnV4IE1pbnQnLFxuICAgICAgJ09wZW5CU0QnLFxuICAgICAgJ1JlZCBIYXQnLFxuICAgICAgJ1N1U0UnLFxuICAgICAgJ1VidW50dScsXG4gICAgICAnWHVidW50dScsXG4gICAgICAnQ3lnd2luJyxcbiAgICAgICdTeW1iaWFuIE9TJyxcbiAgICAgICdocHdPUycsXG4gICAgICAnd2ViT1MgJyxcbiAgICAgICd3ZWJPUycsXG4gICAgICAnVGFibGV0IE9TJyxcbiAgICAgICdUaXplbicsXG4gICAgICAnTGludXgnLFxuICAgICAgJ01hYyBPUyBYJyxcbiAgICAgICdNYWNpbnRvc2gnLFxuICAgICAgJ01hYycsXG4gICAgICAnV2luZG93cyA5ODsnLFxuICAgICAgJ1dpbmRvd3MgJ1xuICAgIF0pO1xuXG4gICAgLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuXG4gICAgLyoqXG4gICAgICogUGlja3MgdGhlIGxheW91dCBlbmdpbmUgZnJvbSBhbiBhcnJheSBvZiBndWVzc2VzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBndWVzc2VzIEFuIGFycmF5IG9mIGd1ZXNzZXMuXG4gICAgICogQHJldHVybnMge251bGx8c3RyaW5nfSBUaGUgZGV0ZWN0ZWQgbGF5b3V0IGVuZ2luZS5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBnZXRMYXlvdXQoZ3Vlc3Nlcykge1xuICAgICAgcmV0dXJuIHJlZHVjZShndWVzc2VzLCBmdW5jdGlvbihyZXN1bHQsIGd1ZXNzKSB7XG4gICAgICAgIHJldHVybiByZXN1bHQgfHwgUmVnRXhwKCdcXFxcYicgKyAoXG4gICAgICAgICAgZ3Vlc3MucGF0dGVybiB8fCBxdWFsaWZ5KGd1ZXNzKVxuICAgICAgICApICsgJ1xcXFxiJywgJ2knKS5leGVjKHVhKSAmJiAoZ3Vlc3MubGFiZWwgfHwgZ3Vlc3MpO1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUGlja3MgdGhlIG1hbnVmYWN0dXJlciBmcm9tIGFuIGFycmF5IG9mIGd1ZXNzZXMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGd1ZXNzZXMgQW4gb2JqZWN0IG9mIGd1ZXNzZXMuXG4gICAgICogQHJldHVybnMge251bGx8c3RyaW5nfSBUaGUgZGV0ZWN0ZWQgbWFudWZhY3R1cmVyLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGdldE1hbnVmYWN0dXJlcihndWVzc2VzKSB7XG4gICAgICByZXR1cm4gcmVkdWNlKGd1ZXNzZXMsIGZ1bmN0aW9uKHJlc3VsdCwgdmFsdWUsIGtleSkge1xuICAgICAgICAvLyBMb29rdXAgdGhlIG1hbnVmYWN0dXJlciBieSBwcm9kdWN0IG9yIHNjYW4gdGhlIFVBIGZvciB0aGUgbWFudWZhY3R1cmVyLlxuICAgICAgICByZXR1cm4gcmVzdWx0IHx8IChcbiAgICAgICAgICB2YWx1ZVtwcm9kdWN0XSB8fFxuICAgICAgICAgIHZhbHVlWy9eW2Etel0rKD86ICtbYS16XStcXGIpKi9pLmV4ZWMocHJvZHVjdCldIHx8XG4gICAgICAgICAgUmVnRXhwKCdcXFxcYicgKyBxdWFsaWZ5KGtleSkgKyAnKD86XFxcXGJ8XFxcXHcqXFxcXGQpJywgJ2knKS5leGVjKHVhKVxuICAgICAgICApICYmIGtleTtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFBpY2tzIHRoZSBicm93c2VyIG5hbWUgZnJvbSBhbiBhcnJheSBvZiBndWVzc2VzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBndWVzc2VzIEFuIGFycmF5IG9mIGd1ZXNzZXMuXG4gICAgICogQHJldHVybnMge251bGx8c3RyaW5nfSBUaGUgZGV0ZWN0ZWQgYnJvd3NlciBuYW1lLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGdldE5hbWUoZ3Vlc3Nlcykge1xuICAgICAgcmV0dXJuIHJlZHVjZShndWVzc2VzLCBmdW5jdGlvbihyZXN1bHQsIGd1ZXNzKSB7XG4gICAgICAgIHJldHVybiByZXN1bHQgfHwgUmVnRXhwKCdcXFxcYicgKyAoXG4gICAgICAgICAgZ3Vlc3MucGF0dGVybiB8fCBxdWFsaWZ5KGd1ZXNzKVxuICAgICAgICApICsgJ1xcXFxiJywgJ2knKS5leGVjKHVhKSAmJiAoZ3Vlc3MubGFiZWwgfHwgZ3Vlc3MpO1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUGlja3MgdGhlIE9TIG5hbWUgZnJvbSBhbiBhcnJheSBvZiBndWVzc2VzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBndWVzc2VzIEFuIGFycmF5IG9mIGd1ZXNzZXMuXG4gICAgICogQHJldHVybnMge251bGx8c3RyaW5nfSBUaGUgZGV0ZWN0ZWQgT1MgbmFtZS5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBnZXRPUyhndWVzc2VzKSB7XG4gICAgICByZXR1cm4gcmVkdWNlKGd1ZXNzZXMsIGZ1bmN0aW9uKHJlc3VsdCwgZ3Vlc3MpIHtcbiAgICAgICAgdmFyIHBhdHRlcm4gPSBndWVzcy5wYXR0ZXJuIHx8IHF1YWxpZnkoZ3Vlc3MpO1xuICAgICAgICBpZiAoIXJlc3VsdCAmJiAocmVzdWx0ID1cbiAgICAgICAgICAgICAgUmVnRXhwKCdcXFxcYicgKyBwYXR0ZXJuICsgJyg/Oi9bXFxcXGQuXSt8WyBcXFxcdy5dKiknLCAnaScpLmV4ZWModWEpXG4gICAgICAgICAgICApKSB7XG4gICAgICAgICAgcmVzdWx0ID0gY2xlYW51cE9TKHJlc3VsdCwgcGF0dGVybiwgZ3Vlc3MubGFiZWwgfHwgZ3Vlc3MpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBQaWNrcyB0aGUgcHJvZHVjdCBuYW1lIGZyb20gYW4gYXJyYXkgb2YgZ3Vlc3Nlcy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtBcnJheX0gZ3Vlc3NlcyBBbiBhcnJheSBvZiBndWVzc2VzLlxuICAgICAqIEByZXR1cm5zIHtudWxsfHN0cmluZ30gVGhlIGRldGVjdGVkIHByb2R1Y3QgbmFtZS5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBnZXRQcm9kdWN0KGd1ZXNzZXMpIHtcbiAgICAgIHJldHVybiByZWR1Y2UoZ3Vlc3NlcywgZnVuY3Rpb24ocmVzdWx0LCBndWVzcykge1xuICAgICAgICB2YXIgcGF0dGVybiA9IGd1ZXNzLnBhdHRlcm4gfHwgcXVhbGlmeShndWVzcyk7XG4gICAgICAgIGlmICghcmVzdWx0ICYmIChyZXN1bHQgPVxuICAgICAgICAgICAgICBSZWdFeHAoJ1xcXFxiJyArIHBhdHRlcm4gKyAnICpcXFxcZCtbLlxcXFx3X10qJywgJ2knKS5leGVjKHVhKSB8fFxuICAgICAgICAgICAgICBSZWdFeHAoJ1xcXFxiJyArIHBhdHRlcm4gKyAnICpcXFxcdystW1xcXFx3XSonLCAnaScpLmV4ZWModWEpIHx8XG4gICAgICAgICAgICAgIFJlZ0V4cCgnXFxcXGInICsgcGF0dGVybiArICcoPzo7ICooPzpbYS16XStbXy1dKT9bYS16XStcXFxcZCt8W14gKCk7LV0qKScsICdpJykuZXhlYyh1YSlcbiAgICAgICAgICAgICkpIHtcbiAgICAgICAgICAvLyBTcGxpdCBieSBmb3J3YXJkIHNsYXNoIGFuZCBhcHBlbmQgcHJvZHVjdCB2ZXJzaW9uIGlmIG5lZWRlZC5cbiAgICAgICAgICBpZiAoKHJlc3VsdCA9IFN0cmluZygoZ3Vlc3MubGFiZWwgJiYgIVJlZ0V4cChwYXR0ZXJuLCAnaScpLnRlc3QoZ3Vlc3MubGFiZWwpKSA/IGd1ZXNzLmxhYmVsIDogcmVzdWx0KS5zcGxpdCgnLycpKVsxXSAmJiAhL1tcXGQuXSsvLnRlc3QocmVzdWx0WzBdKSkge1xuICAgICAgICAgICAgcmVzdWx0WzBdICs9ICcgJyArIHJlc3VsdFsxXTtcbiAgICAgICAgICB9XG4gICAgICAgICAgLy8gQ29ycmVjdCBjaGFyYWN0ZXIgY2FzZSBhbmQgY2xlYW51cCBzdHJpbmcuXG4gICAgICAgICAgZ3Vlc3MgPSBndWVzcy5sYWJlbCB8fCBndWVzcztcbiAgICAgICAgICByZXN1bHQgPSBmb3JtYXQocmVzdWx0WzBdXG4gICAgICAgICAgICAucmVwbGFjZShSZWdFeHAocGF0dGVybiwgJ2knKSwgZ3Vlc3MpXG4gICAgICAgICAgICAucmVwbGFjZShSZWdFeHAoJzsgKig/OicgKyBndWVzcyArICdbXy1dKT8nLCAnaScpLCAnICcpXG4gICAgICAgICAgICAucmVwbGFjZShSZWdFeHAoJygnICsgZ3Vlc3MgKyAnKVstXy5dPyhcXFxcdyknLCAnaScpLCAnJDEgJDInKSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlc29sdmVzIHRoZSB2ZXJzaW9uIHVzaW5nIGFuIGFycmF5IG9mIFVBIHBhdHRlcm5zLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBwYXR0ZXJucyBBbiBhcnJheSBvZiBVQSBwYXR0ZXJucy5cbiAgICAgKiBAcmV0dXJucyB7bnVsbHxzdHJpbmd9IFRoZSBkZXRlY3RlZCB2ZXJzaW9uLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGdldFZlcnNpb24ocGF0dGVybnMpIHtcbiAgICAgIHJldHVybiByZWR1Y2UocGF0dGVybnMsIGZ1bmN0aW9uKHJlc3VsdCwgcGF0dGVybikge1xuICAgICAgICByZXR1cm4gcmVzdWx0IHx8IChSZWdFeHAocGF0dGVybiArXG4gICAgICAgICAgJyg/Oi1bXFxcXGQuXSsvfCg/OiBmb3IgW1xcXFx3LV0rKT9bIC8tXSkoW1xcXFxkLl0rW14gKCk7L18tXSopJywgJ2knKS5leGVjKHVhKSB8fCAwKVsxXSB8fCBudWxsO1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyBgcGxhdGZvcm0uZGVzY3JpcHRpb25gIHdoZW4gdGhlIHBsYXRmb3JtIG9iamVjdCBpcyBjb2VyY2VkIHRvIGEgc3RyaW5nLlxuICAgICAqXG4gICAgICogQG5hbWUgdG9TdHJpbmdcbiAgICAgKiBAbWVtYmVyT2YgcGxhdGZvcm1cbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfSBSZXR1cm5zIGBwbGF0Zm9ybS5kZXNjcmlwdGlvbmAgaWYgYXZhaWxhYmxlLCBlbHNlIGFuIGVtcHR5IHN0cmluZy5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiB0b1N0cmluZ1BsYXRmb3JtKCkge1xuICAgICAgcmV0dXJuIHRoaXMuZGVzY3JpcHRpb24gfHwgJyc7XG4gICAgfVxuXG4gICAgLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuXG4gICAgLy8gQ29udmVydCBsYXlvdXQgdG8gYW4gYXJyYXkgc28gd2UgY2FuIGFkZCBleHRyYSBkZXRhaWxzLlxuICAgIGxheW91dCAmJiAobGF5b3V0ID0gW2xheW91dF0pO1xuXG4gICAgLy8gRGV0ZWN0IHByb2R1Y3QgbmFtZXMgdGhhdCBjb250YWluIHRoZWlyIG1hbnVmYWN0dXJlcidzIG5hbWUuXG4gICAgaWYgKG1hbnVmYWN0dXJlciAmJiAhcHJvZHVjdCkge1xuICAgICAgcHJvZHVjdCA9IGdldFByb2R1Y3QoW21hbnVmYWN0dXJlcl0pO1xuICAgIH1cbiAgICAvLyBDbGVhbiB1cCBHb29nbGUgVFYuXG4gICAgaWYgKChkYXRhID0gL1xcYkdvb2dsZSBUVlxcYi8uZXhlYyhwcm9kdWN0KSkpIHtcbiAgICAgIHByb2R1Y3QgPSBkYXRhWzBdO1xuICAgIH1cbiAgICAvLyBEZXRlY3Qgc2ltdWxhdG9ycy5cbiAgICBpZiAoL1xcYlNpbXVsYXRvclxcYi9pLnRlc3QodWEpKSB7XG4gICAgICBwcm9kdWN0ID0gKHByb2R1Y3QgPyBwcm9kdWN0ICsgJyAnIDogJycpICsgJ1NpbXVsYXRvcic7XG4gICAgfVxuICAgIC8vIERldGVjdCBPcGVyYSBNaW5pIDgrIHJ1bm5pbmcgaW4gVHVyYm8vVW5jb21wcmVzc2VkIG1vZGUgb24gaU9TLlxuICAgIGlmIChuYW1lID09ICdPcGVyYSBNaW5pJyAmJiAvXFxiT1BpT1NcXGIvLnRlc3QodWEpKSB7XG4gICAgICBkZXNjcmlwdGlvbi5wdXNoKCdydW5uaW5nIGluIFR1cmJvL1VuY29tcHJlc3NlZCBtb2RlJyk7XG4gICAgfVxuICAgIC8vIERldGVjdCBJRSBNb2JpbGUgMTEuXG4gICAgaWYgKG5hbWUgPT0gJ0lFJyAmJiAvXFxibGlrZSBpUGhvbmUgT1NcXGIvLnRlc3QodWEpKSB7XG4gICAgICBkYXRhID0gcGFyc2UodWEucmVwbGFjZSgvbGlrZSBpUGhvbmUgT1MvLCAnJykpO1xuICAgICAgbWFudWZhY3R1cmVyID0gZGF0YS5tYW51ZmFjdHVyZXI7XG4gICAgICBwcm9kdWN0ID0gZGF0YS5wcm9kdWN0O1xuICAgIH1cbiAgICAvLyBEZXRlY3QgaU9TLlxuICAgIGVsc2UgaWYgKC9eaVAvLnRlc3QocHJvZHVjdCkpIHtcbiAgICAgIG5hbWUgfHwgKG5hbWUgPSAnU2FmYXJpJyk7XG4gICAgICBvcyA9ICdpT1MnICsgKChkYXRhID0gLyBPUyAoW1xcZF9dKykvaS5leGVjKHVhKSlcbiAgICAgICAgPyAnICcgKyBkYXRhWzFdLnJlcGxhY2UoL18vZywgJy4nKVxuICAgICAgICA6ICcnKTtcbiAgICB9XG4gICAgLy8gRGV0ZWN0IEt1YnVudHUuXG4gICAgZWxzZSBpZiAobmFtZSA9PSAnS29ucXVlcm9yJyAmJiAhL2J1bnR1L2kudGVzdChvcykpIHtcbiAgICAgIG9zID0gJ0t1YnVudHUnO1xuICAgIH1cbiAgICAvLyBEZXRlY3QgQW5kcm9pZCBicm93c2Vycy5cbiAgICBlbHNlIGlmICgobWFudWZhY3R1cmVyICYmIG1hbnVmYWN0dXJlciAhPSAnR29vZ2xlJyAmJlxuICAgICAgICAoKC9DaHJvbWUvLnRlc3QobmFtZSkgJiYgIS9cXGJNb2JpbGUgU2FmYXJpXFxiL2kudGVzdCh1YSkpIHx8IC9cXGJWaXRhXFxiLy50ZXN0KHByb2R1Y3QpKSkgfHxcbiAgICAgICAgKC9cXGJBbmRyb2lkXFxiLy50ZXN0KG9zKSAmJiAvXkNocm9tZS8udGVzdChuYW1lKSAmJiAvXFxiVmVyc2lvblxcLy9pLnRlc3QodWEpKSkge1xuICAgICAgbmFtZSA9ICdBbmRyb2lkIEJyb3dzZXInO1xuICAgICAgb3MgPSAvXFxiQW5kcm9pZFxcYi8udGVzdChvcykgPyBvcyA6ICdBbmRyb2lkJztcbiAgICB9XG4gICAgLy8gRGV0ZWN0IFNpbGsgZGVza3RvcC9hY2NlbGVyYXRlZCBtb2Rlcy5cbiAgICBlbHNlIGlmIChuYW1lID09ICdTaWxrJykge1xuICAgICAgaWYgKCEvXFxiTW9iaS9pLnRlc3QodWEpKSB7XG4gICAgICAgIG9zID0gJ0FuZHJvaWQnO1xuICAgICAgICBkZXNjcmlwdGlvbi51bnNoaWZ0KCdkZXNrdG9wIG1vZGUnKTtcbiAgICAgIH1cbiAgICAgIGlmICgvQWNjZWxlcmF0ZWQgKj0gKnRydWUvaS50ZXN0KHVhKSkge1xuICAgICAgICBkZXNjcmlwdGlvbi51bnNoaWZ0KCdhY2NlbGVyYXRlZCcpO1xuICAgICAgfVxuICAgIH1cbiAgICAvLyBEZXRlY3QgUGFsZU1vb24gaWRlbnRpZnlpbmcgYXMgRmlyZWZveC5cbiAgICBlbHNlIGlmIChuYW1lID09ICdQYWxlTW9vbicgJiYgKGRhdGEgPSAvXFxiRmlyZWZveFxcLyhbXFxkLl0rKVxcYi8uZXhlYyh1YSkpKSB7XG4gICAgICBkZXNjcmlwdGlvbi5wdXNoKCdpZGVudGlmeWluZyBhcyBGaXJlZm94ICcgKyBkYXRhWzFdKTtcbiAgICB9XG4gICAgLy8gRGV0ZWN0IEZpcmVmb3ggT1MgYW5kIHByb2R1Y3RzIHJ1bm5pbmcgRmlyZWZveC5cbiAgICBlbHNlIGlmIChuYW1lID09ICdGaXJlZm94JyAmJiAoZGF0YSA9IC9cXGIoTW9iaWxlfFRhYmxldHxUVilcXGIvaS5leGVjKHVhKSkpIHtcbiAgICAgIG9zIHx8IChvcyA9ICdGaXJlZm94IE9TJyk7XG4gICAgICBwcm9kdWN0IHx8IChwcm9kdWN0ID0gZGF0YVsxXSk7XG4gICAgfVxuICAgIC8vIERldGVjdCBmYWxzZSBwb3NpdGl2ZXMgZm9yIEZpcmVmb3gvU2FmYXJpLlxuICAgIGVsc2UgaWYgKCFuYW1lIHx8IChkYXRhID0gIS9cXGJNaW5lZmllbGRcXGIvaS50ZXN0KHVhKSAmJiAvXFxiKD86RmlyZWZveHxTYWZhcmkpXFxiLy5leGVjKG5hbWUpKSkge1xuICAgICAgLy8gRXNjYXBlIHRoZSBgL2AgZm9yIEZpcmVmb3ggMS5cbiAgICAgIGlmIChuYW1lICYmICFwcm9kdWN0ICYmIC9bXFwvLF18XlteKF0rP1xcKS8udGVzdCh1YS5zbGljZSh1YS5pbmRleE9mKGRhdGEgKyAnLycpICsgOCkpKSB7XG4gICAgICAgIC8vIENsZWFyIG5hbWUgb2YgZmFsc2UgcG9zaXRpdmVzLlxuICAgICAgICBuYW1lID0gbnVsbDtcbiAgICAgIH1cbiAgICAgIC8vIFJlYXNzaWduIGEgZ2VuZXJpYyBuYW1lLlxuICAgICAgaWYgKChkYXRhID0gcHJvZHVjdCB8fCBtYW51ZmFjdHVyZXIgfHwgb3MpICYmXG4gICAgICAgICAgKHByb2R1Y3QgfHwgbWFudWZhY3R1cmVyIHx8IC9cXGIoPzpBbmRyb2lkfFN5bWJpYW4gT1N8VGFibGV0IE9TfHdlYk9TKVxcYi8udGVzdChvcykpKSB7XG4gICAgICAgIG5hbWUgPSAvW2Etel0rKD86IEhhdCk/L2kuZXhlYygvXFxiQW5kcm9pZFxcYi8udGVzdChvcykgPyBvcyA6IGRhdGEpICsgJyBCcm93c2VyJztcbiAgICAgIH1cbiAgICB9XG4gICAgLy8gQWRkIENocm9tZSB2ZXJzaW9uIHRvIGRlc2NyaXB0aW9uIGZvciBFbGVjdHJvbi5cbiAgICBlbHNlIGlmIChuYW1lID09ICdFbGVjdHJvbicgJiYgKGRhdGEgPSAoL1xcYkNocm9tZVxcLyhbXFxkLl0rKVxcYi8uZXhlYyh1YSkgfHwgMClbMV0pKSB7XG4gICAgICBkZXNjcmlwdGlvbi5wdXNoKCdDaHJvbWl1bSAnICsgZGF0YSk7XG4gICAgfVxuICAgIC8vIERldGVjdCBub24tT3BlcmEgKFByZXN0by1iYXNlZCkgdmVyc2lvbnMgKG9yZGVyIGlzIGltcG9ydGFudCkuXG4gICAgaWYgKCF2ZXJzaW9uKSB7XG4gICAgICB2ZXJzaW9uID0gZ2V0VmVyc2lvbihbXG4gICAgICAgICcoPzpDbG91ZDl8Q3JpT1N8Q3JNb3xFZGdlfEZ4aU9TfElFTW9iaWxlfElyb258T3BlcmEgP01pbml8T1BpT1N8T1BSfFJhdmVufFNhbXN1bmdCcm93c2VyfFNpbGsoPyEvW1xcXFxkLl0rJCkpJyxcbiAgICAgICAgJ1ZlcnNpb24nLFxuICAgICAgICBxdWFsaWZ5KG5hbWUpLFxuICAgICAgICAnKD86RmlyZWZveHxNaW5lZmllbGR8TmV0RnJvbnQpJ1xuICAgICAgXSk7XG4gICAgfVxuICAgIC8vIERldGVjdCBzdHViYm9ybiBsYXlvdXQgZW5naW5lcy5cbiAgICBpZiAoKGRhdGEgPVxuICAgICAgICAgIGxheW91dCA9PSAnaUNhYicgJiYgcGFyc2VGbG9hdCh2ZXJzaW9uKSA+IDMgJiYgJ1dlYktpdCcgfHxcbiAgICAgICAgICAvXFxiT3BlcmFcXGIvLnRlc3QobmFtZSkgJiYgKC9cXGJPUFJcXGIvLnRlc3QodWEpID8gJ0JsaW5rJyA6ICdQcmVzdG8nKSB8fFxuICAgICAgICAgIC9cXGIoPzpNaWRvcml8Tm9va3xTYWZhcmkpXFxiL2kudGVzdCh1YSkgJiYgIS9eKD86VHJpZGVudHxFZGdlSFRNTCkkLy50ZXN0KGxheW91dCkgJiYgJ1dlYktpdCcgfHxcbiAgICAgICAgICAhbGF5b3V0ICYmIC9cXGJNU0lFXFxiL2kudGVzdCh1YSkgJiYgKG9zID09ICdNYWMgT1MnID8gJ1Rhc21hbicgOiAnVHJpZGVudCcpIHx8XG4gICAgICAgICAgbGF5b3V0ID09ICdXZWJLaXQnICYmIC9cXGJQbGF5U3RhdGlvblxcYig/ISBWaXRhXFxiKS9pLnRlc3QobmFtZSkgJiYgJ05ldEZyb250J1xuICAgICAgICApKSB7XG4gICAgICBsYXlvdXQgPSBbZGF0YV07XG4gICAgfVxuICAgIC8vIERldGVjdCBXaW5kb3dzIFBob25lIDcgZGVza3RvcCBtb2RlLlxuICAgIGlmIChuYW1lID09ICdJRScgJiYgKGRhdGEgPSAoLzsgKig/OlhCTFdQfFp1bmVXUCkoXFxkKykvaS5leGVjKHVhKSB8fCAwKVsxXSkpIHtcbiAgICAgIG5hbWUgKz0gJyBNb2JpbGUnO1xuICAgICAgb3MgPSAnV2luZG93cyBQaG9uZSAnICsgKC9cXCskLy50ZXN0KGRhdGEpID8gZGF0YSA6IGRhdGEgKyAnLngnKTtcbiAgICAgIGRlc2NyaXB0aW9uLnVuc2hpZnQoJ2Rlc2t0b3AgbW9kZScpO1xuICAgIH1cbiAgICAvLyBEZXRlY3QgV2luZG93cyBQaG9uZSA4LnggZGVza3RvcCBtb2RlLlxuICAgIGVsc2UgaWYgKC9cXGJXUERlc2t0b3BcXGIvaS50ZXN0KHVhKSkge1xuICAgICAgbmFtZSA9ICdJRSBNb2JpbGUnO1xuICAgICAgb3MgPSAnV2luZG93cyBQaG9uZSA4LngnO1xuICAgICAgZGVzY3JpcHRpb24udW5zaGlmdCgnZGVza3RvcCBtb2RlJyk7XG4gICAgICB2ZXJzaW9uIHx8ICh2ZXJzaW9uID0gKC9cXGJydjooW1xcZC5dKykvLmV4ZWModWEpIHx8IDApWzFdKTtcbiAgICB9XG4gICAgLy8gRGV0ZWN0IElFIDExIGlkZW50aWZ5aW5nIGFzIG90aGVyIGJyb3dzZXJzLlxuICAgIGVsc2UgaWYgKG5hbWUgIT0gJ0lFJyAmJiBsYXlvdXQgPT0gJ1RyaWRlbnQnICYmIChkYXRhID0gL1xcYnJ2OihbXFxkLl0rKS8uZXhlYyh1YSkpKSB7XG4gICAgICBpZiAobmFtZSkge1xuICAgICAgICBkZXNjcmlwdGlvbi5wdXNoKCdpZGVudGlmeWluZyBhcyAnICsgbmFtZSArICh2ZXJzaW9uID8gJyAnICsgdmVyc2lvbiA6ICcnKSk7XG4gICAgICB9XG4gICAgICBuYW1lID0gJ0lFJztcbiAgICAgIHZlcnNpb24gPSBkYXRhWzFdO1xuICAgIH1cbiAgICAvLyBMZXZlcmFnZSBlbnZpcm9ubWVudCBmZWF0dXJlcy5cbiAgICBpZiAodXNlRmVhdHVyZXMpIHtcbiAgICAgIC8vIERldGVjdCBzZXJ2ZXItc2lkZSBlbnZpcm9ubWVudHMuXG4gICAgICAvLyBSaGlubyBoYXMgYSBnbG9iYWwgZnVuY3Rpb24gd2hpbGUgb3RoZXJzIGhhdmUgYSBnbG9iYWwgb2JqZWN0LlxuICAgICAgaWYgKGlzSG9zdFR5cGUoY29udGV4dCwgJ2dsb2JhbCcpKSB7XG4gICAgICAgIGlmIChqYXZhKSB7XG4gICAgICAgICAgZGF0YSA9IGphdmEubGFuZy5TeXN0ZW07XG4gICAgICAgICAgYXJjaCA9IGRhdGEuZ2V0UHJvcGVydHkoJ29zLmFyY2gnKTtcbiAgICAgICAgICBvcyA9IG9zIHx8IGRhdGEuZ2V0UHJvcGVydHkoJ29zLm5hbWUnKSArICcgJyArIGRhdGEuZ2V0UHJvcGVydHkoJ29zLnZlcnNpb24nKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAocmhpbm8pIHtcbiAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgdmVyc2lvbiA9IGNvbnRleHQucmVxdWlyZSgncmluZ28vZW5naW5lJykudmVyc2lvbi5qb2luKCcuJyk7XG4gICAgICAgICAgICBuYW1lID0gJ1JpbmdvSlMnO1xuICAgICAgICAgIH0gY2F0Y2goZSkge1xuICAgICAgICAgICAgaWYgKChkYXRhID0gY29udGV4dC5zeXN0ZW0pICYmIGRhdGEuZ2xvYmFsLnN5c3RlbSA9PSBjb250ZXh0LnN5c3RlbSkge1xuICAgICAgICAgICAgICBuYW1lID0gJ05hcndoYWwnO1xuICAgICAgICAgICAgICBvcyB8fCAob3MgPSBkYXRhWzBdLm9zIHx8IG51bGwpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoIW5hbWUpIHtcbiAgICAgICAgICAgIG5hbWUgPSAnUmhpbm8nO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmIChcbiAgICAgICAgICB0eXBlb2YgY29udGV4dC5wcm9jZXNzID09ICdvYmplY3QnICYmICFjb250ZXh0LnByb2Nlc3MuYnJvd3NlciAmJlxuICAgICAgICAgIChkYXRhID0gY29udGV4dC5wcm9jZXNzKVxuICAgICAgICApIHtcbiAgICAgICAgICBpZiAodHlwZW9mIGRhdGEudmVyc2lvbnMgPT0gJ29iamVjdCcpIHtcbiAgICAgICAgICAgIGlmICh0eXBlb2YgZGF0YS52ZXJzaW9ucy5lbGVjdHJvbiA9PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgICBkZXNjcmlwdGlvbi5wdXNoKCdOb2RlICcgKyBkYXRhLnZlcnNpb25zLm5vZGUpO1xuICAgICAgICAgICAgICBuYW1lID0gJ0VsZWN0cm9uJztcbiAgICAgICAgICAgICAgdmVyc2lvbiA9IGRhdGEudmVyc2lvbnMuZWxlY3Ryb247XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHR5cGVvZiBkYXRhLnZlcnNpb25zLm53ID09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAgIGRlc2NyaXB0aW9uLnB1c2goJ0Nocm9taXVtICcgKyB2ZXJzaW9uLCAnTm9kZSAnICsgZGF0YS52ZXJzaW9ucy5ub2RlKTtcbiAgICAgICAgICAgICAgbmFtZSA9ICdOVy5qcyc7XG4gICAgICAgICAgICAgIHZlcnNpb24gPSBkYXRhLnZlcnNpb25zLm53O1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoIW5hbWUpIHtcbiAgICAgICAgICAgIG5hbWUgPSAnTm9kZS5qcyc7XG4gICAgICAgICAgICBhcmNoID0gZGF0YS5hcmNoO1xuICAgICAgICAgICAgb3MgPSBkYXRhLnBsYXRmb3JtO1xuICAgICAgICAgICAgdmVyc2lvbiA9IC9bXFxkLl0rLy5leGVjKGRhdGEudmVyc2lvbik7XG4gICAgICAgICAgICB2ZXJzaW9uID0gdmVyc2lvbiA/IHZlcnNpb25bMF0gOiBudWxsO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgLy8gRGV0ZWN0IEFkb2JlIEFJUi5cbiAgICAgIGVsc2UgaWYgKGdldENsYXNzT2YoKGRhdGEgPSBjb250ZXh0LnJ1bnRpbWUpKSA9PSBhaXJSdW50aW1lQ2xhc3MpIHtcbiAgICAgICAgbmFtZSA9ICdBZG9iZSBBSVInO1xuICAgICAgICBvcyA9IGRhdGEuZmxhc2guc3lzdGVtLkNhcGFiaWxpdGllcy5vcztcbiAgICAgIH1cbiAgICAgIC8vIERldGVjdCBQaGFudG9tSlMuXG4gICAgICBlbHNlIGlmIChnZXRDbGFzc09mKChkYXRhID0gY29udGV4dC5waGFudG9tKSkgPT0gcGhhbnRvbUNsYXNzKSB7XG4gICAgICAgIG5hbWUgPSAnUGhhbnRvbUpTJztcbiAgICAgICAgdmVyc2lvbiA9IChkYXRhID0gZGF0YS52ZXJzaW9uIHx8IG51bGwpICYmIChkYXRhLm1ham9yICsgJy4nICsgZGF0YS5taW5vciArICcuJyArIGRhdGEucGF0Y2gpO1xuICAgICAgfVxuICAgICAgLy8gRGV0ZWN0IElFIGNvbXBhdGliaWxpdHkgbW9kZXMuXG4gICAgICBlbHNlIGlmICh0eXBlb2YgZG9jLmRvY3VtZW50TW9kZSA9PSAnbnVtYmVyJyAmJiAoZGF0YSA9IC9cXGJUcmlkZW50XFwvKFxcZCspL2kuZXhlYyh1YSkpKSB7XG4gICAgICAgIC8vIFdlJ3JlIGluIGNvbXBhdGliaWxpdHkgbW9kZSB3aGVuIHRoZSBUcmlkZW50IHZlcnNpb24gKyA0IGRvZXNuJ3RcbiAgICAgICAgLy8gZXF1YWwgdGhlIGRvY3VtZW50IG1vZGUuXG4gICAgICAgIHZlcnNpb24gPSBbdmVyc2lvbiwgZG9jLmRvY3VtZW50TW9kZV07XG4gICAgICAgIGlmICgoZGF0YSA9ICtkYXRhWzFdICsgNCkgIT0gdmVyc2lvblsxXSkge1xuICAgICAgICAgIGRlc2NyaXB0aW9uLnB1c2goJ0lFICcgKyB2ZXJzaW9uWzFdICsgJyBtb2RlJyk7XG4gICAgICAgICAgbGF5b3V0ICYmIChsYXlvdXRbMV0gPSAnJyk7XG4gICAgICAgICAgdmVyc2lvblsxXSA9IGRhdGE7XG4gICAgICAgIH1cbiAgICAgICAgdmVyc2lvbiA9IG5hbWUgPT0gJ0lFJyA/IFN0cmluZyh2ZXJzaW9uWzFdLnRvRml4ZWQoMSkpIDogdmVyc2lvblswXTtcbiAgICAgIH1cbiAgICAgIC8vIERldGVjdCBJRSAxMSBtYXNraW5nIGFzIG90aGVyIGJyb3dzZXJzLlxuICAgICAgZWxzZSBpZiAodHlwZW9mIGRvYy5kb2N1bWVudE1vZGUgPT0gJ251bWJlcicgJiYgL14oPzpDaHJvbWV8RmlyZWZveClcXGIvLnRlc3QobmFtZSkpIHtcbiAgICAgICAgZGVzY3JpcHRpb24ucHVzaCgnbWFza2luZyBhcyAnICsgbmFtZSArICcgJyArIHZlcnNpb24pO1xuICAgICAgICBuYW1lID0gJ0lFJztcbiAgICAgICAgdmVyc2lvbiA9ICcxMS4wJztcbiAgICAgICAgbGF5b3V0ID0gWydUcmlkZW50J107XG4gICAgICAgIG9zID0gJ1dpbmRvd3MnO1xuICAgICAgfVxuICAgICAgb3MgPSBvcyAmJiBmb3JtYXQob3MpO1xuICAgIH1cbiAgICAvLyBEZXRlY3QgcHJlcmVsZWFzZSBwaGFzZXMuXG4gICAgaWYgKHZlcnNpb24gJiYgKGRhdGEgPVxuICAgICAgICAgIC8oPzpbYWJdfGRwfHByZXxbYWJdXFxkK3ByZSkoPzpcXGQrXFwrPyk/JC9pLmV4ZWModmVyc2lvbikgfHxcbiAgICAgICAgICAvKD86YWxwaGF8YmV0YSkoPzogP1xcZCk/L2kuZXhlYyh1YSArICc7JyArICh1c2VGZWF0dXJlcyAmJiBuYXYuYXBwTWlub3JWZXJzaW9uKSkgfHxcbiAgICAgICAgICAvXFxiTWluZWZpZWxkXFxiL2kudGVzdCh1YSkgJiYgJ2EnXG4gICAgICAgICkpIHtcbiAgICAgIHByZXJlbGVhc2UgPSAvYi9pLnRlc3QoZGF0YSkgPyAnYmV0YScgOiAnYWxwaGEnO1xuICAgICAgdmVyc2lvbiA9IHZlcnNpb24ucmVwbGFjZShSZWdFeHAoZGF0YSArICdcXFxcKz8kJyksICcnKSArXG4gICAgICAgIChwcmVyZWxlYXNlID09ICdiZXRhJyA/IGJldGEgOiBhbHBoYSkgKyAoL1xcZCtcXCs/Ly5leGVjKGRhdGEpIHx8ICcnKTtcbiAgICB9XG4gICAgLy8gRGV0ZWN0IEZpcmVmb3ggTW9iaWxlLlxuICAgIGlmIChuYW1lID09ICdGZW5uZWMnIHx8IG5hbWUgPT0gJ0ZpcmVmb3gnICYmIC9cXGIoPzpBbmRyb2lkfEZpcmVmb3ggT1MpXFxiLy50ZXN0KG9zKSkge1xuICAgICAgbmFtZSA9ICdGaXJlZm94IE1vYmlsZSc7XG4gICAgfVxuICAgIC8vIE9ic2N1cmUgTWF4dGhvbidzIHVucmVsaWFibGUgdmVyc2lvbi5cbiAgICBlbHNlIGlmIChuYW1lID09ICdNYXh0aG9uJyAmJiB2ZXJzaW9uKSB7XG4gICAgICB2ZXJzaW9uID0gdmVyc2lvbi5yZXBsYWNlKC9cXC5bXFxkLl0rLywgJy54Jyk7XG4gICAgfVxuICAgIC8vIERldGVjdCBYYm94IDM2MCBhbmQgWGJveCBPbmUuXG4gICAgZWxzZSBpZiAoL1xcYlhib3hcXGIvaS50ZXN0KHByb2R1Y3QpKSB7XG4gICAgICBpZiAocHJvZHVjdCA9PSAnWGJveCAzNjAnKSB7XG4gICAgICAgIG9zID0gbnVsbDtcbiAgICAgIH1cbiAgICAgIGlmIChwcm9kdWN0ID09ICdYYm94IDM2MCcgJiYgL1xcYklFTW9iaWxlXFxiLy50ZXN0KHVhKSkge1xuICAgICAgICBkZXNjcmlwdGlvbi51bnNoaWZ0KCdtb2JpbGUgbW9kZScpO1xuICAgICAgfVxuICAgIH1cbiAgICAvLyBBZGQgbW9iaWxlIHBvc3RmaXguXG4gICAgZWxzZSBpZiAoKC9eKD86Q2hyb21lfElFfE9wZXJhKSQvLnRlc3QobmFtZSkgfHwgbmFtZSAmJiAhcHJvZHVjdCAmJiAhL0Jyb3dzZXJ8TW9iaS8udGVzdChuYW1lKSkgJiZcbiAgICAgICAgKG9zID09ICdXaW5kb3dzIENFJyB8fCAvTW9iaS9pLnRlc3QodWEpKSkge1xuICAgICAgbmFtZSArPSAnIE1vYmlsZSc7XG4gICAgfVxuICAgIC8vIERldGVjdCBJRSBwbGF0Zm9ybSBwcmV2aWV3LlxuICAgIGVsc2UgaWYgKG5hbWUgPT0gJ0lFJyAmJiB1c2VGZWF0dXJlcykge1xuICAgICAgdHJ5IHtcbiAgICAgICAgaWYgKGNvbnRleHQuZXh0ZXJuYWwgPT09IG51bGwpIHtcbiAgICAgICAgICBkZXNjcmlwdGlvbi51bnNoaWZ0KCdwbGF0Zm9ybSBwcmV2aWV3Jyk7XG4gICAgICAgIH1cbiAgICAgIH0gY2F0Y2goZSkge1xuICAgICAgICBkZXNjcmlwdGlvbi51bnNoaWZ0KCdlbWJlZGRlZCcpO1xuICAgICAgfVxuICAgIH1cbiAgICAvLyBEZXRlY3QgQmxhY2tCZXJyeSBPUyB2ZXJzaW9uLlxuICAgIC8vIGh0dHA6Ly9kb2NzLmJsYWNrYmVycnkuY29tL2VuL2RldmVsb3BlcnMvZGVsaXZlcmFibGVzLzE4MTY5L0hUVFBfaGVhZGVyc19zZW50X2J5X0JCX0Jyb3dzZXJfMTIzNDkxMV8xMS5qc3BcbiAgICBlbHNlIGlmICgoL1xcYkJsYWNrQmVycnlcXGIvLnRlc3QocHJvZHVjdCkgfHwgL1xcYkJCMTBcXGIvLnRlc3QodWEpKSAmJiAoZGF0YSA9XG4gICAgICAgICAgKFJlZ0V4cChwcm9kdWN0LnJlcGxhY2UoLyArL2csICcgKicpICsgJy8oWy5cXFxcZF0rKScsICdpJykuZXhlYyh1YSkgfHwgMClbMV0gfHxcbiAgICAgICAgICB2ZXJzaW9uXG4gICAgICAgICkpIHtcbiAgICAgIGRhdGEgPSBbZGF0YSwgL0JCMTAvLnRlc3QodWEpXTtcbiAgICAgIG9zID0gKGRhdGFbMV0gPyAocHJvZHVjdCA9IG51bGwsIG1hbnVmYWN0dXJlciA9ICdCbGFja0JlcnJ5JykgOiAnRGV2aWNlIFNvZnR3YXJlJykgKyAnICcgKyBkYXRhWzBdO1xuICAgICAgdmVyc2lvbiA9IG51bGw7XG4gICAgfVxuICAgIC8vIERldGVjdCBPcGVyYSBpZGVudGlmeWluZy9tYXNraW5nIGl0c2VsZiBhcyBhbm90aGVyIGJyb3dzZXIuXG4gICAgLy8gaHR0cDovL3d3dy5vcGVyYS5jb20vc3VwcG9ydC9rYi92aWV3Lzg0My9cbiAgICBlbHNlIGlmICh0aGlzICE9IGZvck93biAmJiBwcm9kdWN0ICE9ICdXaWknICYmIChcbiAgICAgICAgICAodXNlRmVhdHVyZXMgJiYgb3BlcmEpIHx8XG4gICAgICAgICAgKC9PcGVyYS8udGVzdChuYW1lKSAmJiAvXFxiKD86TVNJRXxGaXJlZm94KVxcYi9pLnRlc3QodWEpKSB8fFxuICAgICAgICAgIChuYW1lID09ICdGaXJlZm94JyAmJiAvXFxiT1MgWCAoPzpcXGQrXFwuKXsyLH0vLnRlc3Qob3MpKSB8fFxuICAgICAgICAgIChuYW1lID09ICdJRScgJiYgKFxuICAgICAgICAgICAgKG9zICYmICEvXldpbi8udGVzdChvcykgJiYgdmVyc2lvbiA+IDUuNSkgfHxcbiAgICAgICAgICAgIC9cXGJXaW5kb3dzIFhQXFxiLy50ZXN0KG9zKSAmJiB2ZXJzaW9uID4gOCB8fFxuICAgICAgICAgICAgdmVyc2lvbiA9PSA4ICYmICEvXFxiVHJpZGVudFxcYi8udGVzdCh1YSlcbiAgICAgICAgICApKVxuICAgICAgICApICYmICFyZU9wZXJhLnRlc3QoKGRhdGEgPSBwYXJzZS5jYWxsKGZvck93biwgdWEucmVwbGFjZShyZU9wZXJhLCAnJykgKyAnOycpKSkgJiYgZGF0YS5uYW1lKSB7XG4gICAgICAvLyBXaGVuIFwiaWRlbnRpZnlpbmdcIiwgdGhlIFVBIGNvbnRhaW5zIGJvdGggT3BlcmEgYW5kIHRoZSBvdGhlciBicm93c2VyJ3MgbmFtZS5cbiAgICAgIGRhdGEgPSAnaW5nIGFzICcgKyBkYXRhLm5hbWUgKyAoKGRhdGEgPSBkYXRhLnZlcnNpb24pID8gJyAnICsgZGF0YSA6ICcnKTtcbiAgICAgIGlmIChyZU9wZXJhLnRlc3QobmFtZSkpIHtcbiAgICAgICAgaWYgKC9cXGJJRVxcYi8udGVzdChkYXRhKSAmJiBvcyA9PSAnTWFjIE9TJykge1xuICAgICAgICAgIG9zID0gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICBkYXRhID0gJ2lkZW50aWZ5JyArIGRhdGE7XG4gICAgICB9XG4gICAgICAvLyBXaGVuIFwibWFza2luZ1wiLCB0aGUgVUEgY29udGFpbnMgb25seSB0aGUgb3RoZXIgYnJvd3NlcidzIG5hbWUuXG4gICAgICBlbHNlIHtcbiAgICAgICAgZGF0YSA9ICdtYXNrJyArIGRhdGE7XG4gICAgICAgIGlmIChvcGVyYUNsYXNzKSB7XG4gICAgICAgICAgbmFtZSA9IGZvcm1hdChvcGVyYUNsYXNzLnJlcGxhY2UoLyhbYS16XSkoW0EtWl0pL2csICckMSAkMicpKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBuYW1lID0gJ09wZXJhJztcbiAgICAgICAgfVxuICAgICAgICBpZiAoL1xcYklFXFxiLy50ZXN0KGRhdGEpKSB7XG4gICAgICAgICAgb3MgPSBudWxsO1xuICAgICAgICB9XG4gICAgICAgIGlmICghdXNlRmVhdHVyZXMpIHtcbiAgICAgICAgICB2ZXJzaW9uID0gbnVsbDtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgbGF5b3V0ID0gWydQcmVzdG8nXTtcbiAgICAgIGRlc2NyaXB0aW9uLnB1c2goZGF0YSk7XG4gICAgfVxuICAgIC8vIERldGVjdCBXZWJLaXQgTmlnaHRseSBhbmQgYXBwcm94aW1hdGUgQ2hyb21lL1NhZmFyaSB2ZXJzaW9ucy5cbiAgICBpZiAoKGRhdGEgPSAoL1xcYkFwcGxlV2ViS2l0XFwvKFtcXGQuXStcXCs/KS9pLmV4ZWModWEpIHx8IDApWzFdKSkge1xuICAgICAgLy8gQ29ycmVjdCBidWlsZCBudW1iZXIgZm9yIG51bWVyaWMgY29tcGFyaXNvbi5cbiAgICAgIC8vIChlLmcuIFwiNTMyLjVcIiBiZWNvbWVzIFwiNTMyLjA1XCIpXG4gICAgICBkYXRhID0gW3BhcnNlRmxvYXQoZGF0YS5yZXBsYWNlKC9cXC4oXFxkKSQvLCAnLjAkMScpKSwgZGF0YV07XG4gICAgICAvLyBOaWdodGx5IGJ1aWxkcyBhcmUgcG9zdGZpeGVkIHdpdGggYSBcIitcIi5cbiAgICAgIGlmIChuYW1lID09ICdTYWZhcmknICYmIGRhdGFbMV0uc2xpY2UoLTEpID09ICcrJykge1xuICAgICAgICBuYW1lID0gJ1dlYktpdCBOaWdodGx5JztcbiAgICAgICAgcHJlcmVsZWFzZSA9ICdhbHBoYSc7XG4gICAgICAgIHZlcnNpb24gPSBkYXRhWzFdLnNsaWNlKDAsIC0xKTtcbiAgICAgIH1cbiAgICAgIC8vIENsZWFyIGluY29ycmVjdCBicm93c2VyIHZlcnNpb25zLlxuICAgICAgZWxzZSBpZiAodmVyc2lvbiA9PSBkYXRhWzFdIHx8XG4gICAgICAgICAgdmVyc2lvbiA9PSAoZGF0YVsyXSA9ICgvXFxiU2FmYXJpXFwvKFtcXGQuXStcXCs/KS9pLmV4ZWModWEpIHx8IDApWzFdKSkge1xuICAgICAgICB2ZXJzaW9uID0gbnVsbDtcbiAgICAgIH1cbiAgICAgIC8vIFVzZSB0aGUgZnVsbCBDaHJvbWUgdmVyc2lvbiB3aGVuIGF2YWlsYWJsZS5cbiAgICAgIGRhdGFbMV0gPSAoL1xcYkNocm9tZVxcLyhbXFxkLl0rKS9pLmV4ZWModWEpIHx8IDApWzFdO1xuICAgICAgLy8gRGV0ZWN0IEJsaW5rIGxheW91dCBlbmdpbmUuXG4gICAgICBpZiAoZGF0YVswXSA9PSA1MzcuMzYgJiYgZGF0YVsyXSA9PSA1MzcuMzYgJiYgcGFyc2VGbG9hdChkYXRhWzFdKSA+PSAyOCAmJiBsYXlvdXQgPT0gJ1dlYktpdCcpIHtcbiAgICAgICAgbGF5b3V0ID0gWydCbGluayddO1xuICAgICAgfVxuICAgICAgLy8gRGV0ZWN0IEphdmFTY3JpcHRDb3JlLlxuICAgICAgLy8gaHR0cDovL3N0YWNrb3ZlcmZsb3cuY29tL3F1ZXN0aW9ucy82NzY4NDc0L2hvdy1jYW4taS1kZXRlY3Qtd2hpY2gtamF2YXNjcmlwdC1lbmdpbmUtdjgtb3ItanNjLWlzLXVzZWQtYXQtcnVudGltZS1pbi1hbmRyb2lcbiAgICAgIGlmICghdXNlRmVhdHVyZXMgfHwgKCFsaWtlQ2hyb21lICYmICFkYXRhWzFdKSkge1xuICAgICAgICBsYXlvdXQgJiYgKGxheW91dFsxXSA9ICdsaWtlIFNhZmFyaScpO1xuICAgICAgICBkYXRhID0gKGRhdGEgPSBkYXRhWzBdLCBkYXRhIDwgNDAwID8gMSA6IGRhdGEgPCA1MDAgPyAyIDogZGF0YSA8IDUyNiA/IDMgOiBkYXRhIDwgNTMzID8gNCA6IGRhdGEgPCA1MzQgPyAnNCsnIDogZGF0YSA8IDUzNSA/IDUgOiBkYXRhIDwgNTM3ID8gNiA6IGRhdGEgPCA1MzggPyA3IDogZGF0YSA8IDYwMSA/IDggOiAnOCcpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbGF5b3V0ICYmIChsYXlvdXRbMV0gPSAnbGlrZSBDaHJvbWUnKTtcbiAgICAgICAgZGF0YSA9IGRhdGFbMV0gfHwgKGRhdGEgPSBkYXRhWzBdLCBkYXRhIDwgNTMwID8gMSA6IGRhdGEgPCA1MzIgPyAyIDogZGF0YSA8IDUzMi4wNSA/IDMgOiBkYXRhIDwgNTMzID8gNCA6IGRhdGEgPCA1MzQuMDMgPyA1IDogZGF0YSA8IDUzNC4wNyA/IDYgOiBkYXRhIDwgNTM0LjEwID8gNyA6IGRhdGEgPCA1MzQuMTMgPyA4IDogZGF0YSA8IDUzNC4xNiA/IDkgOiBkYXRhIDwgNTM0LjI0ID8gMTAgOiBkYXRhIDwgNTM0LjMwID8gMTEgOiBkYXRhIDwgNTM1LjAxID8gMTIgOiBkYXRhIDwgNTM1LjAyID8gJzEzKycgOiBkYXRhIDwgNTM1LjA3ID8gMTUgOiBkYXRhIDwgNTM1LjExID8gMTYgOiBkYXRhIDwgNTM1LjE5ID8gMTcgOiBkYXRhIDwgNTM2LjA1ID8gMTggOiBkYXRhIDwgNTM2LjEwID8gMTkgOiBkYXRhIDwgNTM3LjAxID8gMjAgOiBkYXRhIDwgNTM3LjExID8gJzIxKycgOiBkYXRhIDwgNTM3LjEzID8gMjMgOiBkYXRhIDwgNTM3LjE4ID8gMjQgOiBkYXRhIDwgNTM3LjI0ID8gMjUgOiBkYXRhIDwgNTM3LjM2ID8gMjYgOiBsYXlvdXQgIT0gJ0JsaW5rJyA/ICcyNycgOiAnMjgnKTtcbiAgICAgIH1cbiAgICAgIC8vIEFkZCB0aGUgcG9zdGZpeCBvZiBcIi54XCIgb3IgXCIrXCIgZm9yIGFwcHJveGltYXRlIHZlcnNpb25zLlxuICAgICAgbGF5b3V0ICYmIChsYXlvdXRbMV0gKz0gJyAnICsgKGRhdGEgKz0gdHlwZW9mIGRhdGEgPT0gJ251bWJlcicgPyAnLngnIDogL1suK10vLnRlc3QoZGF0YSkgPyAnJyA6ICcrJykpO1xuICAgICAgLy8gT2JzY3VyZSB2ZXJzaW9uIGZvciBzb21lIFNhZmFyaSAxLTIgcmVsZWFzZXMuXG4gICAgICBpZiAobmFtZSA9PSAnU2FmYXJpJyAmJiAoIXZlcnNpb24gfHwgcGFyc2VJbnQodmVyc2lvbikgPiA0NSkpIHtcbiAgICAgICAgdmVyc2lvbiA9IGRhdGE7XG4gICAgICB9XG4gICAgfVxuICAgIC8vIERldGVjdCBPcGVyYSBkZXNrdG9wIG1vZGVzLlxuICAgIGlmIChuYW1lID09ICdPcGVyYScgJiYgIChkYXRhID0gL1xcYnpib3Z8enZhdiQvLmV4ZWMob3MpKSkge1xuICAgICAgbmFtZSArPSAnICc7XG4gICAgICBkZXNjcmlwdGlvbi51bnNoaWZ0KCdkZXNrdG9wIG1vZGUnKTtcbiAgICAgIGlmIChkYXRhID09ICd6dmF2Jykge1xuICAgICAgICBuYW1lICs9ICdNaW5pJztcbiAgICAgICAgdmVyc2lvbiA9IG51bGw7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBuYW1lICs9ICdNb2JpbGUnO1xuICAgICAgfVxuICAgICAgb3MgPSBvcy5yZXBsYWNlKFJlZ0V4cCgnIConICsgZGF0YSArICckJyksICcnKTtcbiAgICB9XG4gICAgLy8gRGV0ZWN0IENocm9tZSBkZXNrdG9wIG1vZGUuXG4gICAgZWxzZSBpZiAobmFtZSA9PSAnU2FmYXJpJyAmJiAvXFxiQ2hyb21lXFxiLy5leGVjKGxheW91dCAmJiBsYXlvdXRbMV0pKSB7XG4gICAgICBkZXNjcmlwdGlvbi51bnNoaWZ0KCdkZXNrdG9wIG1vZGUnKTtcbiAgICAgIG5hbWUgPSAnQ2hyb21lIE1vYmlsZSc7XG4gICAgICB2ZXJzaW9uID0gbnVsbDtcblxuICAgICAgaWYgKC9cXGJPUyBYXFxiLy50ZXN0KG9zKSkge1xuICAgICAgICBtYW51ZmFjdHVyZXIgPSAnQXBwbGUnO1xuICAgICAgICBvcyA9ICdpT1MgNC4zKyc7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBvcyA9IG51bGw7XG4gICAgICB9XG4gICAgfVxuICAgIC8vIFN0cmlwIGluY29ycmVjdCBPUyB2ZXJzaW9ucy5cbiAgICBpZiAodmVyc2lvbiAmJiB2ZXJzaW9uLmluZGV4T2YoKGRhdGEgPSAvW1xcZC5dKyQvLmV4ZWMob3MpKSkgPT0gMCAmJlxuICAgICAgICB1YS5pbmRleE9mKCcvJyArIGRhdGEgKyAnLScpID4gLTEpIHtcbiAgICAgIG9zID0gdHJpbShvcy5yZXBsYWNlKGRhdGEsICcnKSk7XG4gICAgfVxuICAgIC8vIEFkZCBsYXlvdXQgZW5naW5lLlxuICAgIGlmIChsYXlvdXQgJiYgIS9cXGIoPzpBdmFudHxOb29rKVxcYi8udGVzdChuYW1lKSAmJiAoXG4gICAgICAgIC9Ccm93c2VyfEx1bmFzY2FwZXxNYXh0aG9uLy50ZXN0KG5hbWUpIHx8XG4gICAgICAgIG5hbWUgIT0gJ1NhZmFyaScgJiYgL15pT1MvLnRlc3Qob3MpICYmIC9cXGJTYWZhcmlcXGIvLnRlc3QobGF5b3V0WzFdKSB8fFxuICAgICAgICAvXig/OkFkb2JlfEFyb3JhfEJyZWFjaHxNaWRvcml8T3BlcmF8UGhhbnRvbXxSZWtvbnF8Um9ja3xTYW1zdW5nIEludGVybmV0fFNsZWlwbmlyfFdlYikvLnRlc3QobmFtZSkgJiYgbGF5b3V0WzFdKSkge1xuICAgICAgLy8gRG9uJ3QgYWRkIGxheW91dCBkZXRhaWxzIHRvIGRlc2NyaXB0aW9uIGlmIHRoZXkgYXJlIGZhbHNleS5cbiAgICAgIChkYXRhID0gbGF5b3V0W2xheW91dC5sZW5ndGggLSAxXSkgJiYgZGVzY3JpcHRpb24ucHVzaChkYXRhKTtcbiAgICB9XG4gICAgLy8gQ29tYmluZSBjb250ZXh0dWFsIGluZm9ybWF0aW9uLlxuICAgIGlmIChkZXNjcmlwdGlvbi5sZW5ndGgpIHtcbiAgICAgIGRlc2NyaXB0aW9uID0gWycoJyArIGRlc2NyaXB0aW9uLmpvaW4oJzsgJykgKyAnKSddO1xuICAgIH1cbiAgICAvLyBBcHBlbmQgbWFudWZhY3R1cmVyIHRvIGRlc2NyaXB0aW9uLlxuICAgIGlmIChtYW51ZmFjdHVyZXIgJiYgcHJvZHVjdCAmJiBwcm9kdWN0LmluZGV4T2YobWFudWZhY3R1cmVyKSA8IDApIHtcbiAgICAgIGRlc2NyaXB0aW9uLnB1c2goJ29uICcgKyBtYW51ZmFjdHVyZXIpO1xuICAgIH1cbiAgICAvLyBBcHBlbmQgcHJvZHVjdCB0byBkZXNjcmlwdGlvbi5cbiAgICBpZiAocHJvZHVjdCkge1xuICAgICAgZGVzY3JpcHRpb24ucHVzaCgoL15vbiAvLnRlc3QoZGVzY3JpcHRpb25bZGVzY3JpcHRpb24ubGVuZ3RoIC0gMV0pID8gJycgOiAnb24gJykgKyBwcm9kdWN0KTtcbiAgICB9XG4gICAgLy8gUGFyc2UgdGhlIE9TIGludG8gYW4gb2JqZWN0LlxuICAgIGlmIChvcykge1xuICAgICAgZGF0YSA9IC8gKFtcXGQuK10rKSQvLmV4ZWMob3MpO1xuICAgICAgaXNTcGVjaWFsQ2FzZWRPUyA9IGRhdGEgJiYgb3MuY2hhckF0KG9zLmxlbmd0aCAtIGRhdGFbMF0ubGVuZ3RoIC0gMSkgPT0gJy8nO1xuICAgICAgb3MgPSB7XG4gICAgICAgICdhcmNoaXRlY3R1cmUnOiAzMixcbiAgICAgICAgJ2ZhbWlseSc6IChkYXRhICYmICFpc1NwZWNpYWxDYXNlZE9TKSA/IG9zLnJlcGxhY2UoZGF0YVswXSwgJycpIDogb3MsXG4gICAgICAgICd2ZXJzaW9uJzogZGF0YSA/IGRhdGFbMV0gOiBudWxsLFxuICAgICAgICAndG9TdHJpbmcnOiBmdW5jdGlvbigpIHtcbiAgICAgICAgICB2YXIgdmVyc2lvbiA9IHRoaXMudmVyc2lvbjtcbiAgICAgICAgICByZXR1cm4gdGhpcy5mYW1pbHkgKyAoKHZlcnNpb24gJiYgIWlzU3BlY2lhbENhc2VkT1MpID8gJyAnICsgdmVyc2lvbiA6ICcnKSArICh0aGlzLmFyY2hpdGVjdHVyZSA9PSA2NCA/ICcgNjQtYml0JyA6ICcnKTtcbiAgICAgICAgfVxuICAgICAgfTtcbiAgICB9XG4gICAgLy8gQWRkIGJyb3dzZXIvT1MgYXJjaGl0ZWN0dXJlLlxuICAgIGlmICgoZGF0YSA9IC9cXGIoPzpBTUR8SUF8V2lufFdPV3x4ODZffHgpNjRcXGIvaS5leGVjKGFyY2gpKSAmJiAhL1xcYmk2ODZcXGIvaS50ZXN0KGFyY2gpKSB7XG4gICAgICBpZiAob3MpIHtcbiAgICAgICAgb3MuYXJjaGl0ZWN0dXJlID0gNjQ7XG4gICAgICAgIG9zLmZhbWlseSA9IG9zLmZhbWlseS5yZXBsYWNlKFJlZ0V4cCgnIConICsgZGF0YSksICcnKTtcbiAgICAgIH1cbiAgICAgIGlmIChcbiAgICAgICAgICBuYW1lICYmICgvXFxiV09XNjRcXGIvaS50ZXN0KHVhKSB8fFxuICAgICAgICAgICh1c2VGZWF0dXJlcyAmJiAvXFx3KD86ODZ8MzIpJC8udGVzdChuYXYuY3B1Q2xhc3MgfHwgbmF2LnBsYXRmb3JtKSAmJiAhL1xcYldpbjY0OyB4NjRcXGIvaS50ZXN0KHVhKSkpXG4gICAgICApIHtcbiAgICAgICAgZGVzY3JpcHRpb24udW5zaGlmdCgnMzItYml0Jyk7XG4gICAgICB9XG4gICAgfVxuICAgIC8vIENocm9tZSAzOSBhbmQgYWJvdmUgb24gT1MgWCBpcyBhbHdheXMgNjQtYml0LlxuICAgIGVsc2UgaWYgKFxuICAgICAgICBvcyAmJiAvXk9TIFgvLnRlc3Qob3MuZmFtaWx5KSAmJlxuICAgICAgICBuYW1lID09ICdDaHJvbWUnICYmIHBhcnNlRmxvYXQodmVyc2lvbikgPj0gMzlcbiAgICApIHtcbiAgICAgIG9zLmFyY2hpdGVjdHVyZSA9IDY0O1xuICAgIH1cblxuICAgIHVhIHx8ICh1YSA9IG51bGwpO1xuXG4gICAgLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuXG4gICAgLyoqXG4gICAgICogVGhlIHBsYXRmb3JtIG9iamVjdC5cbiAgICAgKlxuICAgICAqIEBuYW1lIHBsYXRmb3JtXG4gICAgICogQHR5cGUgT2JqZWN0XG4gICAgICovXG4gICAgdmFyIHBsYXRmb3JtID0ge307XG5cbiAgICAvKipcbiAgICAgKiBUaGUgcGxhdGZvcm0gZGVzY3JpcHRpb24uXG4gICAgICpcbiAgICAgKiBAbWVtYmVyT2YgcGxhdGZvcm1cbiAgICAgKiBAdHlwZSBzdHJpbmd8bnVsbFxuICAgICAqL1xuICAgIHBsYXRmb3JtLmRlc2NyaXB0aW9uID0gdWE7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgbmFtZSBvZiB0aGUgYnJvd3NlcidzIGxheW91dCBlbmdpbmUuXG4gICAgICpcbiAgICAgKiBUaGUgbGlzdCBvZiBjb21tb24gbGF5b3V0IGVuZ2luZXMgaW5jbHVkZTpcbiAgICAgKiBcIkJsaW5rXCIsIFwiRWRnZUhUTUxcIiwgXCJHZWNrb1wiLCBcIlRyaWRlbnRcIiBhbmQgXCJXZWJLaXRcIlxuICAgICAqXG4gICAgICogQG1lbWJlck9mIHBsYXRmb3JtXG4gICAgICogQHR5cGUgc3RyaW5nfG51bGxcbiAgICAgKi9cbiAgICBwbGF0Zm9ybS5sYXlvdXQgPSBsYXlvdXQgJiYgbGF5b3V0WzBdO1xuXG4gICAgLyoqXG4gICAgICogVGhlIG5hbWUgb2YgdGhlIHByb2R1Y3QncyBtYW51ZmFjdHVyZXIuXG4gICAgICpcbiAgICAgKiBUaGUgbGlzdCBvZiBtYW51ZmFjdHVyZXJzIGluY2x1ZGU6XG4gICAgICogXCJBcHBsZVwiLCBcIkFyY2hvc1wiLCBcIkFtYXpvblwiLCBcIkFzdXNcIiwgXCJCYXJuZXMgJiBOb2JsZVwiLCBcIkJsYWNrQmVycnlcIixcbiAgICAgKiBcIkdvb2dsZVwiLCBcIkhQXCIsIFwiSFRDXCIsIFwiTEdcIiwgXCJNaWNyb3NvZnRcIiwgXCJNb3Rvcm9sYVwiLCBcIk5pbnRlbmRvXCIsXG4gICAgICogXCJOb2tpYVwiLCBcIlNhbXN1bmdcIiBhbmQgXCJTb255XCJcbiAgICAgKlxuICAgICAqIEBtZW1iZXJPZiBwbGF0Zm9ybVxuICAgICAqIEB0eXBlIHN0cmluZ3xudWxsXG4gICAgICovXG4gICAgcGxhdGZvcm0ubWFudWZhY3R1cmVyID0gbWFudWZhY3R1cmVyO1xuXG4gICAgLyoqXG4gICAgICogVGhlIG5hbWUgb2YgdGhlIGJyb3dzZXIvZW52aXJvbm1lbnQuXG4gICAgICpcbiAgICAgKiBUaGUgbGlzdCBvZiBjb21tb24gYnJvd3NlciBuYW1lcyBpbmNsdWRlOlxuICAgICAqIFwiQ2hyb21lXCIsIFwiRWxlY3Ryb25cIiwgXCJGaXJlZm94XCIsIFwiRmlyZWZveCBmb3IgaU9TXCIsIFwiSUVcIixcbiAgICAgKiBcIk1pY3Jvc29mdCBFZGdlXCIsIFwiUGhhbnRvbUpTXCIsIFwiU2FmYXJpXCIsIFwiU2VhTW9ua2V5XCIsIFwiU2lsa1wiLFxuICAgICAqIFwiT3BlcmEgTWluaVwiIGFuZCBcIk9wZXJhXCJcbiAgICAgKlxuICAgICAqIE1vYmlsZSB2ZXJzaW9ucyBvZiBzb21lIGJyb3dzZXJzIGhhdmUgXCJNb2JpbGVcIiBhcHBlbmRlZCB0byB0aGVpciBuYW1lOlxuICAgICAqIGVnLiBcIkNocm9tZSBNb2JpbGVcIiwgXCJGaXJlZm94IE1vYmlsZVwiLCBcIklFIE1vYmlsZVwiIGFuZCBcIk9wZXJhIE1vYmlsZVwiXG4gICAgICpcbiAgICAgKiBAbWVtYmVyT2YgcGxhdGZvcm1cbiAgICAgKiBAdHlwZSBzdHJpbmd8bnVsbFxuICAgICAqL1xuICAgIHBsYXRmb3JtLm5hbWUgPSBuYW1lO1xuXG4gICAgLyoqXG4gICAgICogVGhlIGFscGhhL2JldGEgcmVsZWFzZSBpbmRpY2F0b3IuXG4gICAgICpcbiAgICAgKiBAbWVtYmVyT2YgcGxhdGZvcm1cbiAgICAgKiBAdHlwZSBzdHJpbmd8bnVsbFxuICAgICAqL1xuICAgIHBsYXRmb3JtLnByZXJlbGVhc2UgPSBwcmVyZWxlYXNlO1xuXG4gICAgLyoqXG4gICAgICogVGhlIG5hbWUgb2YgdGhlIHByb2R1Y3QgaG9zdGluZyB0aGUgYnJvd3Nlci5cbiAgICAgKlxuICAgICAqIFRoZSBsaXN0IG9mIGNvbW1vbiBwcm9kdWN0cyBpbmNsdWRlOlxuICAgICAqXG4gICAgICogXCJCbGFja0JlcnJ5XCIsIFwiR2FsYXh5IFM0XCIsIFwiTHVtaWFcIiwgXCJpUGFkXCIsIFwiaVBvZFwiLCBcImlQaG9uZVwiLCBcIktpbmRsZVwiLFxuICAgICAqIFwiS2luZGxlIEZpcmVcIiwgXCJOZXh1c1wiLCBcIk5vb2tcIiwgXCJQbGF5Qm9va1wiLCBcIlRvdWNoUGFkXCIgYW5kIFwiVHJhbnNmb3JtZXJcIlxuICAgICAqXG4gICAgICogQG1lbWJlck9mIHBsYXRmb3JtXG4gICAgICogQHR5cGUgc3RyaW5nfG51bGxcbiAgICAgKi9cbiAgICBwbGF0Zm9ybS5wcm9kdWN0ID0gcHJvZHVjdDtcblxuICAgIC8qKlxuICAgICAqIFRoZSBicm93c2VyJ3MgdXNlciBhZ2VudCBzdHJpbmcuXG4gICAgICpcbiAgICAgKiBAbWVtYmVyT2YgcGxhdGZvcm1cbiAgICAgKiBAdHlwZSBzdHJpbmd8bnVsbFxuICAgICAqL1xuICAgIHBsYXRmb3JtLnVhID0gdWE7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYnJvd3Nlci9lbnZpcm9ubWVudCB2ZXJzaW9uLlxuICAgICAqXG4gICAgICogQG1lbWJlck9mIHBsYXRmb3JtXG4gICAgICogQHR5cGUgc3RyaW5nfG51bGxcbiAgICAgKi9cbiAgICBwbGF0Zm9ybS52ZXJzaW9uID0gbmFtZSAmJiB2ZXJzaW9uO1xuXG4gICAgLyoqXG4gICAgICogVGhlIG5hbWUgb2YgdGhlIG9wZXJhdGluZyBzeXN0ZW0uXG4gICAgICpcbiAgICAgKiBAbWVtYmVyT2YgcGxhdGZvcm1cbiAgICAgKiBAdHlwZSBPYmplY3RcbiAgICAgKi9cbiAgICBwbGF0Zm9ybS5vcyA9IG9zIHx8IHtcblxuICAgICAgLyoqXG4gICAgICAgKiBUaGUgQ1BVIGFyY2hpdGVjdHVyZSB0aGUgT1MgaXMgYnVpbHQgZm9yLlxuICAgICAgICpcbiAgICAgICAqIEBtZW1iZXJPZiBwbGF0Zm9ybS5vc1xuICAgICAgICogQHR5cGUgbnVtYmVyfG51bGxcbiAgICAgICAqL1xuICAgICAgJ2FyY2hpdGVjdHVyZSc6IG51bGwsXG5cbiAgICAgIC8qKlxuICAgICAgICogVGhlIGZhbWlseSBvZiB0aGUgT1MuXG4gICAgICAgKlxuICAgICAgICogQ29tbW9uIHZhbHVlcyBpbmNsdWRlOlxuICAgICAgICogXCJXaW5kb3dzXCIsIFwiV2luZG93cyBTZXJ2ZXIgMjAwOCBSMiAvIDdcIiwgXCJXaW5kb3dzIFNlcnZlciAyMDA4IC8gVmlzdGFcIixcbiAgICAgICAqIFwiV2luZG93cyBYUFwiLCBcIk9TIFhcIiwgXCJVYnVudHVcIiwgXCJEZWJpYW5cIiwgXCJGZWRvcmFcIiwgXCJSZWQgSGF0XCIsIFwiU3VTRVwiLFxuICAgICAgICogXCJBbmRyb2lkXCIsIFwiaU9TXCIgYW5kIFwiV2luZG93cyBQaG9uZVwiXG4gICAgICAgKlxuICAgICAgICogQG1lbWJlck9mIHBsYXRmb3JtLm9zXG4gICAgICAgKiBAdHlwZSBzdHJpbmd8bnVsbFxuICAgICAgICovXG4gICAgICAnZmFtaWx5JzogbnVsbCxcblxuICAgICAgLyoqXG4gICAgICAgKiBUaGUgdmVyc2lvbiBvZiB0aGUgT1MuXG4gICAgICAgKlxuICAgICAgICogQG1lbWJlck9mIHBsYXRmb3JtLm9zXG4gICAgICAgKiBAdHlwZSBzdHJpbmd8bnVsbFxuICAgICAgICovXG4gICAgICAndmVyc2lvbic6IG51bGwsXG5cbiAgICAgIC8qKlxuICAgICAgICogUmV0dXJucyB0aGUgT1Mgc3RyaW5nLlxuICAgICAgICpcbiAgICAgICAqIEBtZW1iZXJPZiBwbGF0Zm9ybS5vc1xuICAgICAgICogQHJldHVybnMge3N0cmluZ30gVGhlIE9TIHN0cmluZy5cbiAgICAgICAqL1xuICAgICAgJ3RvU3RyaW5nJzogZnVuY3Rpb24oKSB7IHJldHVybiAnbnVsbCc7IH1cbiAgICB9O1xuXG4gICAgcGxhdGZvcm0ucGFyc2UgPSBwYXJzZTtcbiAgICBwbGF0Zm9ybS50b1N0cmluZyA9IHRvU3RyaW5nUGxhdGZvcm07XG5cbiAgICBpZiAocGxhdGZvcm0udmVyc2lvbikge1xuICAgICAgZGVzY3JpcHRpb24udW5zaGlmdCh2ZXJzaW9uKTtcbiAgICB9XG4gICAgaWYgKHBsYXRmb3JtLm5hbWUpIHtcbiAgICAgIGRlc2NyaXB0aW9uLnVuc2hpZnQobmFtZSk7XG4gICAgfVxuICAgIGlmIChvcyAmJiBuYW1lICYmICEob3MgPT0gU3RyaW5nKG9zKS5zcGxpdCgnICcpWzBdICYmIChvcyA9PSBuYW1lLnNwbGl0KCcgJylbMF0gfHwgcHJvZHVjdCkpKSB7XG4gICAgICBkZXNjcmlwdGlvbi5wdXNoKHByb2R1Y3QgPyAnKCcgKyBvcyArICcpJyA6ICdvbiAnICsgb3MpO1xuICAgIH1cbiAgICBpZiAoZGVzY3JpcHRpb24ubGVuZ3RoKSB7XG4gICAgICBwbGF0Zm9ybS5kZXNjcmlwdGlvbiA9IGRlc2NyaXB0aW9uLmpvaW4oJyAnKTtcbiAgICB9XG4gICAgcmV0dXJuIHBsYXRmb3JtO1xuICB9XG5cbiAgLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG5cbiAgLy8gRXhwb3J0IHBsYXRmb3JtLlxuICB2YXIgcGxhdGZvcm0gPSBwYXJzZSgpO1xuXG4gIC8vIFNvbWUgQU1EIGJ1aWxkIG9wdGltaXplcnMsIGxpa2Ugci5qcywgY2hlY2sgZm9yIGNvbmRpdGlvbiBwYXR0ZXJucyBsaWtlIHRoZSBmb2xsb3dpbmc6XG4gIGlmICh0eXBlb2YgZGVmaW5lID09ICdmdW5jdGlvbicgJiYgdHlwZW9mIGRlZmluZS5hbWQgPT0gJ29iamVjdCcgJiYgZGVmaW5lLmFtZCkge1xuICAgIC8vIEV4cG9zZSBwbGF0Zm9ybSBvbiB0aGUgZ2xvYmFsIG9iamVjdCB0byBwcmV2ZW50IGVycm9ycyB3aGVuIHBsYXRmb3JtIGlzXG4gICAgLy8gbG9hZGVkIGJ5IGEgc2NyaXB0IHRhZyBpbiB0aGUgcHJlc2VuY2Ugb2YgYW4gQU1EIGxvYWRlci5cbiAgICAvLyBTZWUgaHR0cDovL3JlcXVpcmVqcy5vcmcvZG9jcy9lcnJvcnMuaHRtbCNtaXNtYXRjaCBmb3IgbW9yZSBkZXRhaWxzLlxuICAgIHJvb3QucGxhdGZvcm0gPSBwbGF0Zm9ybTtcblxuICAgIC8vIERlZmluZSBhcyBhbiBhbm9ueW1vdXMgbW9kdWxlIHNvIHBsYXRmb3JtIGNhbiBiZSBhbGlhc2VkIHRocm91Z2ggcGF0aCBtYXBwaW5nLlxuICAgIGRlZmluZShmdW5jdGlvbigpIHtcbiAgICAgIHJldHVybiBwbGF0Zm9ybTtcbiAgICB9KTtcbiAgfVxuICAvLyBDaGVjayBmb3IgYGV4cG9ydHNgIGFmdGVyIGBkZWZpbmVgIGluIGNhc2UgYSBidWlsZCBvcHRpbWl6ZXIgYWRkcyBhbiBgZXhwb3J0c2Agb2JqZWN0LlxuICBlbHNlIGlmIChmcmVlRXhwb3J0cyAmJiBmcmVlTW9kdWxlKSB7XG4gICAgLy8gRXhwb3J0IGZvciBDb21tb25KUyBzdXBwb3J0LlxuICAgIGZvck93bihwbGF0Zm9ybSwgZnVuY3Rpb24odmFsdWUsIGtleSkge1xuICAgICAgZnJlZUV4cG9ydHNba2V5XSA9IHZhbHVlO1xuICAgIH0pO1xuICB9XG4gIGVsc2Uge1xuICAgIC8vIEV4cG9ydCB0byB0aGUgZ2xvYmFsIG9iamVjdC5cbiAgICByb290LnBsYXRmb3JtID0gcGxhdGZvcm07XG4gIH1cbn0uY2FsbCh0aGlzKSk7XG4iLCJ2YXIgdjEgPSByZXF1aXJlKCcuL3YxJyk7XG52YXIgdjQgPSByZXF1aXJlKCcuL3Y0Jyk7XG5cbnZhciB1dWlkID0gdjQ7XG51dWlkLnYxID0gdjE7XG51dWlkLnY0ID0gdjQ7XG5cbm1vZHVsZS5leHBvcnRzID0gdXVpZDtcbiIsIi8qKlxuICogQ29udmVydCBhcnJheSBvZiAxNiBieXRlIHZhbHVlcyB0byBVVUlEIHN0cmluZyBmb3JtYXQgb2YgdGhlIGZvcm06XG4gKiBYWFhYWFhYWC1YWFhYLVhYWFgtWFhYWC1YWFhYWFhYWFhYWFhcbiAqL1xudmFyIGJ5dGVUb0hleCA9IFtdO1xuZm9yICh2YXIgaSA9IDA7IGkgPCAyNTY7ICsraSkge1xuICBieXRlVG9IZXhbaV0gPSAoaSArIDB4MTAwKS50b1N0cmluZygxNikuc3Vic3RyKDEpO1xufVxuXG5mdW5jdGlvbiBieXRlc1RvVXVpZChidWYsIG9mZnNldCkge1xuICB2YXIgaSA9IG9mZnNldCB8fCAwO1xuICB2YXIgYnRoID0gYnl0ZVRvSGV4O1xuICAvLyBqb2luIHVzZWQgdG8gZml4IG1lbW9yeSBpc3N1ZSBjYXVzZWQgYnkgY29uY2F0ZW5hdGlvbjogaHR0cHM6Ly9idWdzLmNocm9taXVtLm9yZy9wL3Y4L2lzc3Vlcy9kZXRhaWw/aWQ9MzE3NSNjNFxuICByZXR1cm4gKFtidGhbYnVmW2krK11dLCBidGhbYnVmW2krK11dLCBcblx0YnRoW2J1ZltpKytdXSwgYnRoW2J1ZltpKytdXSwgJy0nLFxuXHRidGhbYnVmW2krK11dLCBidGhbYnVmW2krK11dLCAnLScsXG5cdGJ0aFtidWZbaSsrXV0sIGJ0aFtidWZbaSsrXV0sICctJyxcblx0YnRoW2J1ZltpKytdXSwgYnRoW2J1ZltpKytdXSwgJy0nLFxuXHRidGhbYnVmW2krK11dLCBidGhbYnVmW2krK11dLFxuXHRidGhbYnVmW2krK11dLCBidGhbYnVmW2krK11dLFxuXHRidGhbYnVmW2krK11dLCBidGhbYnVmW2krK11dXSkuam9pbignJyk7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gYnl0ZXNUb1V1aWQ7XG4iLCIvLyBVbmlxdWUgSUQgY3JlYXRpb24gcmVxdWlyZXMgYSBoaWdoIHF1YWxpdHkgcmFuZG9tICMgZ2VuZXJhdG9yLiAgSW4gdGhlXG4vLyBicm93c2VyIHRoaXMgaXMgYSBsaXR0bGUgY29tcGxpY2F0ZWQgZHVlIHRvIHVua25vd24gcXVhbGl0eSBvZiBNYXRoLnJhbmRvbSgpXG4vLyBhbmQgaW5jb25zaXN0ZW50IHN1cHBvcnQgZm9yIHRoZSBgY3J5cHRvYCBBUEkuICBXZSBkbyB0aGUgYmVzdCB3ZSBjYW4gdmlhXG4vLyBmZWF0dXJlLWRldGVjdGlvblxuXG4vLyBnZXRSYW5kb21WYWx1ZXMgbmVlZHMgdG8gYmUgaW52b2tlZCBpbiBhIGNvbnRleHQgd2hlcmUgXCJ0aGlzXCIgaXMgYSBDcnlwdG9cbi8vIGltcGxlbWVudGF0aW9uLiBBbHNvLCBmaW5kIHRoZSBjb21wbGV0ZSBpbXBsZW1lbnRhdGlvbiBvZiBjcnlwdG8gb24gSUUxMS5cbnZhciBnZXRSYW5kb21WYWx1ZXMgPSAodHlwZW9mKGNyeXB0bykgIT0gJ3VuZGVmaW5lZCcgJiYgY3J5cHRvLmdldFJhbmRvbVZhbHVlcyAmJiBjcnlwdG8uZ2V0UmFuZG9tVmFsdWVzLmJpbmQoY3J5cHRvKSkgfHxcbiAgICAgICAgICAgICAgICAgICAgICAodHlwZW9mKG1zQ3J5cHRvKSAhPSAndW5kZWZpbmVkJyAmJiB0eXBlb2Ygd2luZG93Lm1zQ3J5cHRvLmdldFJhbmRvbVZhbHVlcyA9PSAnZnVuY3Rpb24nICYmIG1zQ3J5cHRvLmdldFJhbmRvbVZhbHVlcy5iaW5kKG1zQ3J5cHRvKSk7XG5cbmlmIChnZXRSYW5kb21WYWx1ZXMpIHtcbiAgLy8gV0hBVFdHIGNyeXB0byBSTkcgLSBodHRwOi8vd2lraS53aGF0d2cub3JnL3dpa2kvQ3J5cHRvXG4gIHZhciBybmRzOCA9IG5ldyBVaW50OEFycmF5KDE2KTsgLy8gZXNsaW50LWRpc2FibGUtbGluZSBuby11bmRlZlxuXG4gIG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gd2hhdHdnUk5HKCkge1xuICAgIGdldFJhbmRvbVZhbHVlcyhybmRzOCk7XG4gICAgcmV0dXJuIHJuZHM4O1xuICB9O1xufSBlbHNlIHtcbiAgLy8gTWF0aC5yYW5kb20oKS1iYXNlZCAoUk5HKVxuICAvL1xuICAvLyBJZiBhbGwgZWxzZSBmYWlscywgdXNlIE1hdGgucmFuZG9tKCkuICBJdCdzIGZhc3QsIGJ1dCBpcyBvZiB1bnNwZWNpZmllZFxuICAvLyBxdWFsaXR5LlxuICB2YXIgcm5kcyA9IG5ldyBBcnJheSgxNik7XG5cbiAgbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBtYXRoUk5HKCkge1xuICAgIGZvciAodmFyIGkgPSAwLCByOyBpIDwgMTY7IGkrKykge1xuICAgICAgaWYgKChpICYgMHgwMykgPT09IDApIHIgPSBNYXRoLnJhbmRvbSgpICogMHgxMDAwMDAwMDA7XG4gICAgICBybmRzW2ldID0gciA+Pj4gKChpICYgMHgwMykgPDwgMykgJiAweGZmO1xuICAgIH1cblxuICAgIHJldHVybiBybmRzO1xuICB9O1xufVxuIiwidmFyIHJuZyA9IHJlcXVpcmUoJy4vbGliL3JuZycpO1xudmFyIGJ5dGVzVG9VdWlkID0gcmVxdWlyZSgnLi9saWIvYnl0ZXNUb1V1aWQnKTtcblxuLy8gKipgdjEoKWAgLSBHZW5lcmF0ZSB0aW1lLWJhc2VkIFVVSUQqKlxuLy9cbi8vIEluc3BpcmVkIGJ5IGh0dHBzOi8vZ2l0aHViLmNvbS9MaW9zSy9VVUlELmpzXG4vLyBhbmQgaHR0cDovL2RvY3MucHl0aG9uLm9yZy9saWJyYXJ5L3V1aWQuaHRtbFxuXG52YXIgX25vZGVJZDtcbnZhciBfY2xvY2tzZXE7XG5cbi8vIFByZXZpb3VzIHV1aWQgY3JlYXRpb24gdGltZVxudmFyIF9sYXN0TVNlY3MgPSAwO1xudmFyIF9sYXN0TlNlY3MgPSAwO1xuXG4vLyBTZWUgaHR0cHM6Ly9naXRodWIuY29tL2Jyb29mYS9ub2RlLXV1aWQgZm9yIEFQSSBkZXRhaWxzXG5mdW5jdGlvbiB2MShvcHRpb25zLCBidWYsIG9mZnNldCkge1xuICB2YXIgaSA9IGJ1ZiAmJiBvZmZzZXQgfHwgMDtcbiAgdmFyIGIgPSBidWYgfHwgW107XG5cbiAgb3B0aW9ucyA9IG9wdGlvbnMgfHwge307XG4gIHZhciBub2RlID0gb3B0aW9ucy5ub2RlIHx8IF9ub2RlSWQ7XG4gIHZhciBjbG9ja3NlcSA9IG9wdGlvbnMuY2xvY2tzZXEgIT09IHVuZGVmaW5lZCA/IG9wdGlvbnMuY2xvY2tzZXEgOiBfY2xvY2tzZXE7XG5cbiAgLy8gbm9kZSBhbmQgY2xvY2tzZXEgbmVlZCB0byBiZSBpbml0aWFsaXplZCB0byByYW5kb20gdmFsdWVzIGlmIHRoZXkncmUgbm90XG4gIC8vIHNwZWNpZmllZC4gIFdlIGRvIHRoaXMgbGF6aWx5IHRvIG1pbmltaXplIGlzc3VlcyByZWxhdGVkIHRvIGluc3VmZmljaWVudFxuICAvLyBzeXN0ZW0gZW50cm9weS4gIFNlZSAjMTg5XG4gIGlmIChub2RlID09IG51bGwgfHwgY2xvY2tzZXEgPT0gbnVsbCkge1xuICAgIHZhciBzZWVkQnl0ZXMgPSBybmcoKTtcbiAgICBpZiAobm9kZSA9PSBudWxsKSB7XG4gICAgICAvLyBQZXIgNC41LCBjcmVhdGUgYW5kIDQ4LWJpdCBub2RlIGlkLCAoNDcgcmFuZG9tIGJpdHMgKyBtdWx0aWNhc3QgYml0ID0gMSlcbiAgICAgIG5vZGUgPSBfbm9kZUlkID0gW1xuICAgICAgICBzZWVkQnl0ZXNbMF0gfCAweDAxLFxuICAgICAgICBzZWVkQnl0ZXNbMV0sIHNlZWRCeXRlc1syXSwgc2VlZEJ5dGVzWzNdLCBzZWVkQnl0ZXNbNF0sIHNlZWRCeXRlc1s1XVxuICAgICAgXTtcbiAgICB9XG4gICAgaWYgKGNsb2Nrc2VxID09IG51bGwpIHtcbiAgICAgIC8vIFBlciA0LjIuMiwgcmFuZG9taXplICgxNCBiaXQpIGNsb2Nrc2VxXG4gICAgICBjbG9ja3NlcSA9IF9jbG9ja3NlcSA9IChzZWVkQnl0ZXNbNl0gPDwgOCB8IHNlZWRCeXRlc1s3XSkgJiAweDNmZmY7XG4gICAgfVxuICB9XG5cbiAgLy8gVVVJRCB0aW1lc3RhbXBzIGFyZSAxMDAgbmFuby1zZWNvbmQgdW5pdHMgc2luY2UgdGhlIEdyZWdvcmlhbiBlcG9jaCxcbiAgLy8gKDE1ODItMTAtMTUgMDA6MDApLiAgSlNOdW1iZXJzIGFyZW4ndCBwcmVjaXNlIGVub3VnaCBmb3IgdGhpcywgc29cbiAgLy8gdGltZSBpcyBoYW5kbGVkIGludGVybmFsbHkgYXMgJ21zZWNzJyAoaW50ZWdlciBtaWxsaXNlY29uZHMpIGFuZCAnbnNlY3MnXG4gIC8vICgxMDAtbmFub3NlY29uZHMgb2Zmc2V0IGZyb20gbXNlY3MpIHNpbmNlIHVuaXggZXBvY2gsIDE5NzAtMDEtMDEgMDA6MDAuXG4gIHZhciBtc2VjcyA9IG9wdGlvbnMubXNlY3MgIT09IHVuZGVmaW5lZCA/IG9wdGlvbnMubXNlY3MgOiBuZXcgRGF0ZSgpLmdldFRpbWUoKTtcblxuICAvLyBQZXIgNC4yLjEuMiwgdXNlIGNvdW50IG9mIHV1aWQncyBnZW5lcmF0ZWQgZHVyaW5nIHRoZSBjdXJyZW50IGNsb2NrXG4gIC8vIGN5Y2xlIHRvIHNpbXVsYXRlIGhpZ2hlciByZXNvbHV0aW9uIGNsb2NrXG4gIHZhciBuc2VjcyA9IG9wdGlvbnMubnNlY3MgIT09IHVuZGVmaW5lZCA/IG9wdGlvbnMubnNlY3MgOiBfbGFzdE5TZWNzICsgMTtcblxuICAvLyBUaW1lIHNpbmNlIGxhc3QgdXVpZCBjcmVhdGlvbiAoaW4gbXNlY3MpXG4gIHZhciBkdCA9IChtc2VjcyAtIF9sYXN0TVNlY3MpICsgKG5zZWNzIC0gX2xhc3ROU2VjcykvMTAwMDA7XG5cbiAgLy8gUGVyIDQuMi4xLjIsIEJ1bXAgY2xvY2tzZXEgb24gY2xvY2sgcmVncmVzc2lvblxuICBpZiAoZHQgPCAwICYmIG9wdGlvbnMuY2xvY2tzZXEgPT09IHVuZGVmaW5lZCkge1xuICAgIGNsb2Nrc2VxID0gY2xvY2tzZXEgKyAxICYgMHgzZmZmO1xuICB9XG5cbiAgLy8gUmVzZXQgbnNlY3MgaWYgY2xvY2sgcmVncmVzc2VzIChuZXcgY2xvY2tzZXEpIG9yIHdlJ3ZlIG1vdmVkIG9udG8gYSBuZXdcbiAgLy8gdGltZSBpbnRlcnZhbFxuICBpZiAoKGR0IDwgMCB8fCBtc2VjcyA+IF9sYXN0TVNlY3MpICYmIG9wdGlvbnMubnNlY3MgPT09IHVuZGVmaW5lZCkge1xuICAgIG5zZWNzID0gMDtcbiAgfVxuXG4gIC8vIFBlciA0LjIuMS4yIFRocm93IGVycm9yIGlmIHRvbyBtYW55IHV1aWRzIGFyZSByZXF1ZXN0ZWRcbiAgaWYgKG5zZWNzID49IDEwMDAwKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCd1dWlkLnYxKCk6IENhblxcJ3QgY3JlYXRlIG1vcmUgdGhhbiAxME0gdXVpZHMvc2VjJyk7XG4gIH1cblxuICBfbGFzdE1TZWNzID0gbXNlY3M7XG4gIF9sYXN0TlNlY3MgPSBuc2VjcztcbiAgX2Nsb2Nrc2VxID0gY2xvY2tzZXE7XG5cbiAgLy8gUGVyIDQuMS40IC0gQ29udmVydCBmcm9tIHVuaXggZXBvY2ggdG8gR3JlZ29yaWFuIGVwb2NoXG4gIG1zZWNzICs9IDEyMjE5MjkyODAwMDAwO1xuXG4gIC8vIGB0aW1lX2xvd2BcbiAgdmFyIHRsID0gKChtc2VjcyAmIDB4ZmZmZmZmZikgKiAxMDAwMCArIG5zZWNzKSAlIDB4MTAwMDAwMDAwO1xuICBiW2krK10gPSB0bCA+Pj4gMjQgJiAweGZmO1xuICBiW2krK10gPSB0bCA+Pj4gMTYgJiAweGZmO1xuICBiW2krK10gPSB0bCA+Pj4gOCAmIDB4ZmY7XG4gIGJbaSsrXSA9IHRsICYgMHhmZjtcblxuICAvLyBgdGltZV9taWRgXG4gIHZhciB0bWggPSAobXNlY3MgLyAweDEwMDAwMDAwMCAqIDEwMDAwKSAmIDB4ZmZmZmZmZjtcbiAgYltpKytdID0gdG1oID4+PiA4ICYgMHhmZjtcbiAgYltpKytdID0gdG1oICYgMHhmZjtcblxuICAvLyBgdGltZV9oaWdoX2FuZF92ZXJzaW9uYFxuICBiW2krK10gPSB0bWggPj4+IDI0ICYgMHhmIHwgMHgxMDsgLy8gaW5jbHVkZSB2ZXJzaW9uXG4gIGJbaSsrXSA9IHRtaCA+Pj4gMTYgJiAweGZmO1xuXG4gIC8vIGBjbG9ja19zZXFfaGlfYW5kX3Jlc2VydmVkYCAoUGVyIDQuMi4yIC0gaW5jbHVkZSB2YXJpYW50KVxuICBiW2krK10gPSBjbG9ja3NlcSA+Pj4gOCB8IDB4ODA7XG5cbiAgLy8gYGNsb2NrX3NlcV9sb3dgXG4gIGJbaSsrXSA9IGNsb2Nrc2VxICYgMHhmZjtcblxuICAvLyBgbm9kZWBcbiAgZm9yICh2YXIgbiA9IDA7IG4gPCA2OyArK24pIHtcbiAgICBiW2kgKyBuXSA9IG5vZGVbbl07XG4gIH1cblxuICByZXR1cm4gYnVmID8gYnVmIDogYnl0ZXNUb1V1aWQoYik7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gdjE7XG4iLCJ2YXIgcm5nID0gcmVxdWlyZSgnLi9saWIvcm5nJyk7XG52YXIgYnl0ZXNUb1V1aWQgPSByZXF1aXJlKCcuL2xpYi9ieXRlc1RvVXVpZCcpO1xuXG5mdW5jdGlvbiB2NChvcHRpb25zLCBidWYsIG9mZnNldCkge1xuICB2YXIgaSA9IGJ1ZiAmJiBvZmZzZXQgfHwgMDtcblxuICBpZiAodHlwZW9mKG9wdGlvbnMpID09ICdzdHJpbmcnKSB7XG4gICAgYnVmID0gb3B0aW9ucyA9PT0gJ2JpbmFyeScgPyBuZXcgQXJyYXkoMTYpIDogbnVsbDtcbiAgICBvcHRpb25zID0gbnVsbDtcbiAgfVxuICBvcHRpb25zID0gb3B0aW9ucyB8fCB7fTtcblxuICB2YXIgcm5kcyA9IG9wdGlvbnMucmFuZG9tIHx8IChvcHRpb25zLnJuZyB8fCBybmcpKCk7XG5cbiAgLy8gUGVyIDQuNCwgc2V0IGJpdHMgZm9yIHZlcnNpb24gYW5kIGBjbG9ja19zZXFfaGlfYW5kX3Jlc2VydmVkYFxuICBybmRzWzZdID0gKHJuZHNbNl0gJiAweDBmKSB8IDB4NDA7XG4gIHJuZHNbOF0gPSAocm5kc1s4XSAmIDB4M2YpIHwgMHg4MDtcblxuICAvLyBDb3B5IGJ5dGVzIHRvIGJ1ZmZlciwgaWYgcHJvdmlkZWRcbiAgaWYgKGJ1Zikge1xuICAgIGZvciAodmFyIGlpID0gMDsgaWkgPCAxNjsgKytpaSkge1xuICAgICAgYnVmW2kgKyBpaV0gPSBybmRzW2lpXTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gYnVmIHx8IGJ5dGVzVG9VdWlkKHJuZHMpO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHY0O1xuIiwiLypcclxuV2lsZEVtaXR0ZXIuanMgaXMgYSBzbGltIGxpdHRsZSBldmVudCBlbWl0dGVyIGJ5IEBoZW5yaWtqb3JldGVnIGxhcmdlbHkgYmFzZWRcclxub24gQHZpc2lvbm1lZGlhJ3MgRW1pdHRlciBmcm9tIFVJIEtpdC5cclxuXHJcbldoeT8gSSB3YW50ZWQgaXQgc3RhbmRhbG9uZS5cclxuXHJcbkkgYWxzbyB3YW50ZWQgc3VwcG9ydCBmb3Igd2lsZGNhcmQgZW1pdHRlcnMgbGlrZSB0aGlzOlxyXG5cclxuZW1pdHRlci5vbignKicsIGZ1bmN0aW9uIChldmVudE5hbWUsIG90aGVyLCBldmVudCwgcGF5bG9hZHMpIHtcclxuXHJcbn0pO1xyXG5cclxuZW1pdHRlci5vbignc29tZW5hbWVzcGFjZSonLCBmdW5jdGlvbiAoZXZlbnROYW1lLCBwYXlsb2Fkcykge1xyXG5cclxufSk7XHJcblxyXG5QbGVhc2Ugbm90ZSB0aGF0IGNhbGxiYWNrcyB0cmlnZ2VyZWQgYnkgd2lsZGNhcmQgcmVnaXN0ZXJlZCBldmVudHMgYWxzbyBnZXRcclxudGhlIGV2ZW50IG5hbWUgYXMgdGhlIGZpcnN0IGFyZ3VtZW50LlxyXG4qL1xyXG5cclxubW9kdWxlLmV4cG9ydHMgPSBXaWxkRW1pdHRlcjtcclxuXHJcbmZ1bmN0aW9uIFdpbGRFbWl0dGVyKCkgeyB9XHJcblxyXG5XaWxkRW1pdHRlci5taXhpbiA9IGZ1bmN0aW9uIChjb25zdHJ1Y3Rvcikge1xyXG4gICAgdmFyIHByb3RvdHlwZSA9IGNvbnN0cnVjdG9yLnByb3RvdHlwZSB8fCBjb25zdHJ1Y3RvcjtcclxuXHJcbiAgICBwcm90b3R5cGUuaXNXaWxkRW1pdHRlcj0gdHJ1ZTtcclxuXHJcbiAgICAvLyBMaXN0ZW4gb24gdGhlIGdpdmVuIGBldmVudGAgd2l0aCBgZm5gLiBTdG9yZSBhIGdyb3VwIG5hbWUgaWYgcHJlc2VudC5cclxuICAgIHByb3RvdHlwZS5vbiA9IGZ1bmN0aW9uIChldmVudCwgZ3JvdXBOYW1lLCBmbikge1xyXG4gICAgICAgIHRoaXMuY2FsbGJhY2tzID0gdGhpcy5jYWxsYmFja3MgfHwge307XHJcbiAgICAgICAgdmFyIGhhc0dyb3VwID0gKGFyZ3VtZW50cy5sZW5ndGggPT09IDMpLFxyXG4gICAgICAgICAgICBncm91cCA9IGhhc0dyb3VwID8gYXJndW1lbnRzWzFdIDogdW5kZWZpbmVkLFxyXG4gICAgICAgICAgICBmdW5jID0gaGFzR3JvdXAgPyBhcmd1bWVudHNbMl0gOiBhcmd1bWVudHNbMV07XHJcbiAgICAgICAgZnVuYy5fZ3JvdXBOYW1lID0gZ3JvdXA7XHJcbiAgICAgICAgKHRoaXMuY2FsbGJhY2tzW2V2ZW50XSA9IHRoaXMuY2FsbGJhY2tzW2V2ZW50XSB8fCBbXSkucHVzaChmdW5jKTtcclxuICAgICAgICByZXR1cm4gdGhpcztcclxuICAgIH07XHJcblxyXG4gICAgLy8gQWRkcyBhbiBgZXZlbnRgIGxpc3RlbmVyIHRoYXQgd2lsbCBiZSBpbnZva2VkIGEgc2luZ2xlXHJcbiAgICAvLyB0aW1lIHRoZW4gYXV0b21hdGljYWxseSByZW1vdmVkLlxyXG4gICAgcHJvdG90eXBlLm9uY2UgPSBmdW5jdGlvbiAoZXZlbnQsIGdyb3VwTmFtZSwgZm4pIHtcclxuICAgICAgICB2YXIgc2VsZiA9IHRoaXMsXHJcbiAgICAgICAgICAgIGhhc0dyb3VwID0gKGFyZ3VtZW50cy5sZW5ndGggPT09IDMpLFxyXG4gICAgICAgICAgICBncm91cCA9IGhhc0dyb3VwID8gYXJndW1lbnRzWzFdIDogdW5kZWZpbmVkLFxyXG4gICAgICAgICAgICBmdW5jID0gaGFzR3JvdXAgPyBhcmd1bWVudHNbMl0gOiBhcmd1bWVudHNbMV07XHJcbiAgICAgICAgZnVuY3Rpb24gb24oKSB7XHJcbiAgICAgICAgICAgIHNlbGYub2ZmKGV2ZW50LCBvbik7XHJcbiAgICAgICAgICAgIGZ1bmMuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgdGhpcy5vbihldmVudCwgZ3JvdXAsIG9uKTtcclxuICAgICAgICByZXR1cm4gdGhpcztcclxuICAgIH07XHJcblxyXG4gICAgLy8gVW5iaW5kcyBhbiBlbnRpcmUgZ3JvdXBcclxuICAgIHByb3RvdHlwZS5yZWxlYXNlR3JvdXAgPSBmdW5jdGlvbiAoZ3JvdXBOYW1lKSB7XHJcbiAgICAgICAgdGhpcy5jYWxsYmFja3MgPSB0aGlzLmNhbGxiYWNrcyB8fCB7fTtcclxuICAgICAgICB2YXIgaXRlbSwgaSwgbGVuLCBoYW5kbGVycztcclxuICAgICAgICBmb3IgKGl0ZW0gaW4gdGhpcy5jYWxsYmFja3MpIHtcclxuICAgICAgICAgICAgaGFuZGxlcnMgPSB0aGlzLmNhbGxiYWNrc1tpdGVtXTtcclxuICAgICAgICAgICAgZm9yIChpID0gMCwgbGVuID0gaGFuZGxlcnMubGVuZ3RoOyBpIDwgbGVuOyBpKyspIHtcclxuICAgICAgICAgICAgICAgIGlmIChoYW5kbGVyc1tpXS5fZ3JvdXBOYW1lID09PSBncm91cE5hbWUpIHtcclxuICAgICAgICAgICAgICAgICAgICAvL2NvbnNvbGUubG9nKCdyZW1vdmluZycpO1xyXG4gICAgICAgICAgICAgICAgICAgIC8vIHJlbW92ZSBpdCBhbmQgc2hvcnRlbiB0aGUgYXJyYXkgd2UncmUgbG9vcGluZyB0aHJvdWdoXHJcbiAgICAgICAgICAgICAgICAgICAgaGFuZGxlcnMuc3BsaWNlKGksIDEpO1xyXG4gICAgICAgICAgICAgICAgICAgIGktLTtcclxuICAgICAgICAgICAgICAgICAgICBsZW4tLTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgICAgICByZXR1cm4gdGhpcztcclxuICAgIH07XHJcblxyXG4gICAgLy8gUmVtb3ZlIHRoZSBnaXZlbiBjYWxsYmFjayBmb3IgYGV2ZW50YCBvciBhbGxcclxuICAgIC8vIHJlZ2lzdGVyZWQgY2FsbGJhY2tzLlxyXG4gICAgcHJvdG90eXBlLm9mZiA9IGZ1bmN0aW9uIChldmVudCwgZm4pIHtcclxuICAgICAgICB0aGlzLmNhbGxiYWNrcyA9IHRoaXMuY2FsbGJhY2tzIHx8IHt9O1xyXG4gICAgICAgIHZhciBjYWxsYmFja3MgPSB0aGlzLmNhbGxiYWNrc1tldmVudF0sXHJcbiAgICAgICAgICAgIGk7XHJcblxyXG4gICAgICAgIGlmICghY2FsbGJhY2tzKSByZXR1cm4gdGhpcztcclxuXHJcbiAgICAgICAgLy8gcmVtb3ZlIGFsbCBoYW5kbGVyc1xyXG4gICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAxKSB7XHJcbiAgICAgICAgICAgIGRlbGV0ZSB0aGlzLmNhbGxiYWNrc1tldmVudF07XHJcbiAgICAgICAgICAgIHJldHVybiB0aGlzO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgLy8gcmVtb3ZlIHNwZWNpZmljIGhhbmRsZXJcclxuICAgICAgICBpID0gY2FsbGJhY2tzLmluZGV4T2YoZm4pO1xyXG4gICAgICAgIGNhbGxiYWNrcy5zcGxpY2UoaSwgMSk7XHJcbiAgICAgICAgaWYgKGNhbGxiYWNrcy5sZW5ndGggPT09IDApIHtcclxuICAgICAgICAgICAgZGVsZXRlIHRoaXMuY2FsbGJhY2tzW2V2ZW50XTtcclxuICAgICAgICB9XHJcbiAgICAgICAgcmV0dXJuIHRoaXM7XHJcbiAgICB9O1xyXG5cclxuICAgIC8vLyBFbWl0IGBldmVudGAgd2l0aCB0aGUgZ2l2ZW4gYXJncy5cclxuICAgIC8vIGFsc28gY2FsbHMgYW55IGAqYCBoYW5kbGVyc1xyXG4gICAgcHJvdG90eXBlLmVtaXQgPSBmdW5jdGlvbiAoZXZlbnQpIHtcclxuICAgICAgICB0aGlzLmNhbGxiYWNrcyA9IHRoaXMuY2FsbGJhY2tzIHx8IHt9O1xyXG4gICAgICAgIHZhciBhcmdzID0gW10uc2xpY2UuY2FsbChhcmd1bWVudHMsIDEpLFxyXG4gICAgICAgICAgICBjYWxsYmFja3MgPSB0aGlzLmNhbGxiYWNrc1tldmVudF0sXHJcbiAgICAgICAgICAgIHNwZWNpYWxDYWxsYmFja3MgPSB0aGlzLmdldFdpbGRjYXJkQ2FsbGJhY2tzKGV2ZW50KSxcclxuICAgICAgICAgICAgaSxcclxuICAgICAgICAgICAgbGVuLFxyXG4gICAgICAgICAgICBpdGVtLFxyXG4gICAgICAgICAgICBsaXN0ZW5lcnM7XHJcblxyXG4gICAgICAgIGlmIChjYWxsYmFja3MpIHtcclxuICAgICAgICAgICAgbGlzdGVuZXJzID0gY2FsbGJhY2tzLnNsaWNlKCk7XHJcbiAgICAgICAgICAgIGZvciAoaSA9IDAsIGxlbiA9IGxpc3RlbmVycy5sZW5ndGg7IGkgPCBsZW47ICsraSkge1xyXG4gICAgICAgICAgICAgICAgaWYgKCFsaXN0ZW5lcnNbaV0pIHtcclxuICAgICAgICAgICAgICAgICAgICBicmVhaztcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIGxpc3RlbmVyc1tpXS5hcHBseSh0aGlzLCBhcmdzKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgaWYgKHNwZWNpYWxDYWxsYmFja3MpIHtcclxuICAgICAgICAgICAgbGVuID0gc3BlY2lhbENhbGxiYWNrcy5sZW5ndGg7XHJcbiAgICAgICAgICAgIGxpc3RlbmVycyA9IHNwZWNpYWxDYWxsYmFja3Muc2xpY2UoKTtcclxuICAgICAgICAgICAgZm9yIChpID0gMCwgbGVuID0gbGlzdGVuZXJzLmxlbmd0aDsgaSA8IGxlbjsgKytpKSB7XHJcbiAgICAgICAgICAgICAgICBpZiAoIWxpc3RlbmVyc1tpXSkge1xyXG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgbGlzdGVuZXJzW2ldLmFwcGx5KHRoaXMsIFtldmVudF0uY29uY2F0KGFyZ3MpKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgcmV0dXJuIHRoaXM7XHJcbiAgICB9O1xyXG5cclxuICAgIC8vIEhlbHBlciBmb3IgZm9yIGZpbmRpbmcgc3BlY2lhbCB3aWxkY2FyZCBldmVudCBoYW5kbGVycyB0aGF0IG1hdGNoIHRoZSBldmVudFxyXG4gICAgcHJvdG90eXBlLmdldFdpbGRjYXJkQ2FsbGJhY2tzID0gZnVuY3Rpb24gKGV2ZW50TmFtZSkge1xyXG4gICAgICAgIHRoaXMuY2FsbGJhY2tzID0gdGhpcy5jYWxsYmFja3MgfHwge307XHJcbiAgICAgICAgdmFyIGl0ZW0sXHJcbiAgICAgICAgICAgIHNwbGl0LFxyXG4gICAgICAgICAgICByZXN1bHQgPSBbXTtcclxuXHJcbiAgICAgICAgZm9yIChpdGVtIGluIHRoaXMuY2FsbGJhY2tzKSB7XHJcbiAgICAgICAgICAgIHNwbGl0ID0gaXRlbS5zcGxpdCgnKicpO1xyXG4gICAgICAgICAgICBpZiAoaXRlbSA9PT0gJyonIHx8IChzcGxpdC5sZW5ndGggPT09IDIgJiYgZXZlbnROYW1lLnNsaWNlKDAsIHNwbGl0WzBdLmxlbmd0aCkgPT09IHNwbGl0WzBdKSkge1xyXG4gICAgICAgICAgICAgICAgcmVzdWx0ID0gcmVzdWx0LmNvbmNhdCh0aGlzLmNhbGxiYWNrc1tpdGVtXSk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcclxuICAgIH07XHJcblxyXG59O1xyXG5cclxuV2lsZEVtaXR0ZXIubWl4aW4oV2lsZEVtaXR0ZXIpO1xyXG4iLCIvKiFcbiAqIEV2ZW50RW1pdHRlciB2NS4yLjUgLSBnaXQuaW8vZWVcbiAqIFVubGljZW5zZSAtIGh0dHA6Ly91bmxpY2Vuc2Uub3JnL1xuICogT2xpdmVyIENhbGR3ZWxsIC0gaHR0cDovL29saS5tZS51ay9cbiAqIEBwcmVzZXJ2ZVxuICovXG5cbjsoZnVuY3Rpb24gKGV4cG9ydHMpIHtcbiAgICAndXNlIHN0cmljdCc7XG5cbiAgICAvKipcbiAgICAgKiBDbGFzcyBmb3IgbWFuYWdpbmcgZXZlbnRzLlxuICAgICAqIENhbiBiZSBleHRlbmRlZCB0byBwcm92aWRlIGV2ZW50IGZ1bmN0aW9uYWxpdHkgaW4gb3RoZXIgY2xhc3Nlcy5cbiAgICAgKlxuICAgICAqIEBjbGFzcyBFdmVudEVtaXR0ZXIgTWFuYWdlcyBldmVudCByZWdpc3RlcmluZyBhbmQgZW1pdHRpbmcuXG4gICAgICovXG4gICAgZnVuY3Rpb24gRXZlbnRFbWl0dGVyKCkge31cblxuICAgIC8vIFNob3J0Y3V0cyB0byBpbXByb3ZlIHNwZWVkIGFuZCBzaXplXG4gICAgdmFyIHByb3RvID0gRXZlbnRFbWl0dGVyLnByb3RvdHlwZTtcbiAgICB2YXIgb3JpZ2luYWxHbG9iYWxWYWx1ZSA9IGV4cG9ydHMuRXZlbnRFbWl0dGVyO1xuXG4gICAgLyoqXG4gICAgICogRmluZHMgdGhlIGluZGV4IG9mIHRoZSBsaXN0ZW5lciBmb3IgdGhlIGV2ZW50IGluIGl0cyBzdG9yYWdlIGFycmF5LlxuICAgICAqXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbltdfSBsaXN0ZW5lcnMgQXJyYXkgb2YgbGlzdGVuZXJzIHRvIHNlYXJjaCB0aHJvdWdoLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGxpc3RlbmVyIE1ldGhvZCB0byBsb29rIGZvci5cbiAgICAgKiBAcmV0dXJuIHtOdW1iZXJ9IEluZGV4IG9mIHRoZSBzcGVjaWZpZWQgbGlzdGVuZXIsIC0xIGlmIG5vdCBmb3VuZFxuICAgICAqIEBhcGkgcHJpdmF0ZVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGluZGV4T2ZMaXN0ZW5lcihsaXN0ZW5lcnMsIGxpc3RlbmVyKSB7XG4gICAgICAgIHZhciBpID0gbGlzdGVuZXJzLmxlbmd0aDtcbiAgICAgICAgd2hpbGUgKGktLSkge1xuICAgICAgICAgICAgaWYgKGxpc3RlbmVyc1tpXS5saXN0ZW5lciA9PT0gbGlzdGVuZXIpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiAtMTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBBbGlhcyBhIG1ldGhvZCB3aGlsZSBrZWVwaW5nIHRoZSBjb250ZXh0IGNvcnJlY3QsIHRvIGFsbG93IGZvciBvdmVyd3JpdGluZyBvZiB0YXJnZXQgbWV0aG9kLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtTdHJpbmd9IG5hbWUgVGhlIG5hbWUgb2YgdGhlIHRhcmdldCBtZXRob2QuXG4gICAgICogQHJldHVybiB7RnVuY3Rpb259IFRoZSBhbGlhc2VkIG1ldGhvZFxuICAgICAqIEBhcGkgcHJpdmF0ZVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGFsaWFzKG5hbWUpIHtcbiAgICAgICAgcmV0dXJuIGZ1bmN0aW9uIGFsaWFzQ2xvc3VyZSgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzW25hbWVdLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyB0aGUgbGlzdGVuZXIgYXJyYXkgZm9yIHRoZSBzcGVjaWZpZWQgZXZlbnQuXG4gICAgICogV2lsbCBpbml0aWFsaXNlIHRoZSBldmVudCBvYmplY3QgYW5kIGxpc3RlbmVyIGFycmF5cyBpZiByZXF1aXJlZC5cbiAgICAgKiBXaWxsIHJldHVybiBhbiBvYmplY3QgaWYgeW91IHVzZSBhIHJlZ2V4IHNlYXJjaC4gVGhlIG9iamVjdCBjb250YWlucyBrZXlzIGZvciBlYWNoIG1hdGNoZWQgZXZlbnQuIFNvIC9iYVtyel0vIG1pZ2h0IHJldHVybiBhbiBvYmplY3QgY29udGFpbmluZyBiYXIgYW5kIGJhei4gQnV0IG9ubHkgaWYgeW91IGhhdmUgZWl0aGVyIGRlZmluZWQgdGhlbSB3aXRoIGRlZmluZUV2ZW50IG9yIGFkZGVkIHNvbWUgbGlzdGVuZXJzIHRvIHRoZW0uXG4gICAgICogRWFjaCBwcm9wZXJ0eSBpbiB0aGUgb2JqZWN0IHJlc3BvbnNlIGlzIGFuIGFycmF5IG9mIGxpc3RlbmVyIGZ1bmN0aW9ucy5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfFJlZ0V4cH0gZXZ0IE5hbWUgb2YgdGhlIGV2ZW50IHRvIHJldHVybiB0aGUgbGlzdGVuZXJzIGZyb20uXG4gICAgICogQHJldHVybiB7RnVuY3Rpb25bXXxPYmplY3R9IEFsbCBsaXN0ZW5lciBmdW5jdGlvbnMgZm9yIHRoZSBldmVudC5cbiAgICAgKi9cbiAgICBwcm90by5nZXRMaXN0ZW5lcnMgPSBmdW5jdGlvbiBnZXRMaXN0ZW5lcnMoZXZ0KSB7XG4gICAgICAgIHZhciBldmVudHMgPSB0aGlzLl9nZXRFdmVudHMoKTtcbiAgICAgICAgdmFyIHJlc3BvbnNlO1xuICAgICAgICB2YXIga2V5O1xuXG4gICAgICAgIC8vIFJldHVybiBhIGNvbmNhdGVuYXRlZCBhcnJheSBvZiBhbGwgbWF0Y2hpbmcgZXZlbnRzIGlmXG4gICAgICAgIC8vIHRoZSBzZWxlY3RvciBpcyBhIHJlZ3VsYXIgZXhwcmVzc2lvbi5cbiAgICAgICAgaWYgKGV2dCBpbnN0YW5jZW9mIFJlZ0V4cCkge1xuICAgICAgICAgICAgcmVzcG9uc2UgPSB7fTtcbiAgICAgICAgICAgIGZvciAoa2V5IGluIGV2ZW50cykge1xuICAgICAgICAgICAgICAgIGlmIChldmVudHMuaGFzT3duUHJvcGVydHkoa2V5KSAmJiBldnQudGVzdChrZXkpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc3BvbnNlW2tleV0gPSBldmVudHNba2V5XTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICByZXNwb25zZSA9IGV2ZW50c1tldnRdIHx8IChldmVudHNbZXZ0XSA9IFtdKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiByZXNwb25zZTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogVGFrZXMgYSBsaXN0IG9mIGxpc3RlbmVyIG9iamVjdHMgYW5kIGZsYXR0ZW5zIGl0IGludG8gYSBsaXN0IG9mIGxpc3RlbmVyIGZ1bmN0aW9ucy5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7T2JqZWN0W119IGxpc3RlbmVycyBSYXcgbGlzdGVuZXIgb2JqZWN0cy5cbiAgICAgKiBAcmV0dXJuIHtGdW5jdGlvbltdfSBKdXN0IHRoZSBsaXN0ZW5lciBmdW5jdGlvbnMuXG4gICAgICovXG4gICAgcHJvdG8uZmxhdHRlbkxpc3RlbmVycyA9IGZ1bmN0aW9uIGZsYXR0ZW5MaXN0ZW5lcnMobGlzdGVuZXJzKSB7XG4gICAgICAgIHZhciBmbGF0TGlzdGVuZXJzID0gW107XG4gICAgICAgIHZhciBpO1xuXG4gICAgICAgIGZvciAoaSA9IDA7IGkgPCBsaXN0ZW5lcnMubGVuZ3RoOyBpICs9IDEpIHtcbiAgICAgICAgICAgIGZsYXRMaXN0ZW5lcnMucHVzaChsaXN0ZW5lcnNbaV0ubGlzdGVuZXIpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGZsYXRMaXN0ZW5lcnM7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEZldGNoZXMgdGhlIHJlcXVlc3RlZCBsaXN0ZW5lcnMgdmlhIGdldExpc3RlbmVycyBidXQgd2lsbCBhbHdheXMgcmV0dXJuIHRoZSByZXN1bHRzIGluc2lkZSBhbiBvYmplY3QuIFRoaXMgaXMgbWFpbmx5IGZvciBpbnRlcm5hbCB1c2UgYnV0IG90aGVycyBtYXkgZmluZCBpdCB1c2VmdWwuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1N0cmluZ3xSZWdFeHB9IGV2dCBOYW1lIG9mIHRoZSBldmVudCB0byByZXR1cm4gdGhlIGxpc3RlbmVycyBmcm9tLlxuICAgICAqIEByZXR1cm4ge09iamVjdH0gQWxsIGxpc3RlbmVyIGZ1bmN0aW9ucyBmb3IgYW4gZXZlbnQgaW4gYW4gb2JqZWN0LlxuICAgICAqL1xuICAgIHByb3RvLmdldExpc3RlbmVyc0FzT2JqZWN0ID0gZnVuY3Rpb24gZ2V0TGlzdGVuZXJzQXNPYmplY3QoZXZ0KSB7XG4gICAgICAgIHZhciBsaXN0ZW5lcnMgPSB0aGlzLmdldExpc3RlbmVycyhldnQpO1xuICAgICAgICB2YXIgcmVzcG9uc2U7XG5cbiAgICAgICAgaWYgKGxpc3RlbmVycyBpbnN0YW5jZW9mIEFycmF5KSB7XG4gICAgICAgICAgICByZXNwb25zZSA9IHt9O1xuICAgICAgICAgICAgcmVzcG9uc2VbZXZ0XSA9IGxpc3RlbmVycztcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiByZXNwb25zZSB8fCBsaXN0ZW5lcnM7XG4gICAgfTtcblxuICAgIGZ1bmN0aW9uIGlzVmFsaWRMaXN0ZW5lciAobGlzdGVuZXIpIHtcbiAgICAgICAgaWYgKHR5cGVvZiBsaXN0ZW5lciA9PT0gJ2Z1bmN0aW9uJyB8fCBsaXN0ZW5lciBpbnN0YW5jZW9mIFJlZ0V4cCkge1xuICAgICAgICAgICAgcmV0dXJuIHRydWVcbiAgICAgICAgfSBlbHNlIGlmIChsaXN0ZW5lciAmJiB0eXBlb2YgbGlzdGVuZXIgPT09ICdvYmplY3QnKSB7XG4gICAgICAgICAgICByZXR1cm4gaXNWYWxpZExpc3RlbmVyKGxpc3RlbmVyLmxpc3RlbmVyKVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlXG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBBZGRzIGEgbGlzdGVuZXIgZnVuY3Rpb24gdG8gdGhlIHNwZWNpZmllZCBldmVudC5cbiAgICAgKiBUaGUgbGlzdGVuZXIgd2lsbCBub3QgYmUgYWRkZWQgaWYgaXQgaXMgYSBkdXBsaWNhdGUuXG4gICAgICogSWYgdGhlIGxpc3RlbmVyIHJldHVybnMgdHJ1ZSB0aGVuIGl0IHdpbGwgYmUgcmVtb3ZlZCBhZnRlciBpdCBpcyBjYWxsZWQuXG4gICAgICogSWYgeW91IHBhc3MgYSByZWd1bGFyIGV4cHJlc3Npb24gYXMgdGhlIGV2ZW50IG5hbWUgdGhlbiB0aGUgbGlzdGVuZXIgd2lsbCBiZSBhZGRlZCB0byBhbGwgZXZlbnRzIHRoYXQgbWF0Y2ggaXQuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1N0cmluZ3xSZWdFeHB9IGV2dCBOYW1lIG9mIHRoZSBldmVudCB0byBhdHRhY2ggdGhlIGxpc3RlbmVyIHRvLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGxpc3RlbmVyIE1ldGhvZCB0byBiZSBjYWxsZWQgd2hlbiB0aGUgZXZlbnQgaXMgZW1pdHRlZC4gSWYgdGhlIGZ1bmN0aW9uIHJldHVybnMgdHJ1ZSB0aGVuIGl0IHdpbGwgYmUgcmVtb3ZlZCBhZnRlciBjYWxsaW5nLlxuICAgICAqIEByZXR1cm4ge09iamVjdH0gQ3VycmVudCBpbnN0YW5jZSBvZiBFdmVudEVtaXR0ZXIgZm9yIGNoYWluaW5nLlxuICAgICAqL1xuICAgIHByb3RvLmFkZExpc3RlbmVyID0gZnVuY3Rpb24gYWRkTGlzdGVuZXIoZXZ0LCBsaXN0ZW5lcikge1xuICAgICAgICBpZiAoIWlzVmFsaWRMaXN0ZW5lcihsaXN0ZW5lcikpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2xpc3RlbmVyIG11c3QgYmUgYSBmdW5jdGlvbicpO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIGxpc3RlbmVycyA9IHRoaXMuZ2V0TGlzdGVuZXJzQXNPYmplY3QoZXZ0KTtcbiAgICAgICAgdmFyIGxpc3RlbmVySXNXcmFwcGVkID0gdHlwZW9mIGxpc3RlbmVyID09PSAnb2JqZWN0JztcbiAgICAgICAgdmFyIGtleTtcblxuICAgICAgICBmb3IgKGtleSBpbiBsaXN0ZW5lcnMpIHtcbiAgICAgICAgICAgIGlmIChsaXN0ZW5lcnMuaGFzT3duUHJvcGVydHkoa2V5KSAmJiBpbmRleE9mTGlzdGVuZXIobGlzdGVuZXJzW2tleV0sIGxpc3RlbmVyKSA9PT0gLTEpIHtcbiAgICAgICAgICAgICAgICBsaXN0ZW5lcnNba2V5XS5wdXNoKGxpc3RlbmVySXNXcmFwcGVkID8gbGlzdGVuZXIgOiB7XG4gICAgICAgICAgICAgICAgICAgIGxpc3RlbmVyOiBsaXN0ZW5lcixcbiAgICAgICAgICAgICAgICAgICAgb25jZTogZmFsc2VcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBBbGlhcyBvZiBhZGRMaXN0ZW5lclxuICAgICAqL1xuICAgIHByb3RvLm9uID0gYWxpYXMoJ2FkZExpc3RlbmVyJyk7XG5cbiAgICAvKipcbiAgICAgKiBTZW1pLWFsaWFzIG9mIGFkZExpc3RlbmVyLiBJdCB3aWxsIGFkZCBhIGxpc3RlbmVyIHRoYXQgd2lsbCBiZVxuICAgICAqIGF1dG9tYXRpY2FsbHkgcmVtb3ZlZCBhZnRlciBpdHMgZmlyc3QgZXhlY3V0aW9uLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtTdHJpbmd8UmVnRXhwfSBldnQgTmFtZSBvZiB0aGUgZXZlbnQgdG8gYXR0YWNoIHRoZSBsaXN0ZW5lciB0by5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBsaXN0ZW5lciBNZXRob2QgdG8gYmUgY2FsbGVkIHdoZW4gdGhlIGV2ZW50IGlzIGVtaXR0ZWQuIElmIHRoZSBmdW5jdGlvbiByZXR1cm5zIHRydWUgdGhlbiBpdCB3aWxsIGJlIHJlbW92ZWQgYWZ0ZXIgY2FsbGluZy5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEN1cnJlbnQgaW5zdGFuY2Ugb2YgRXZlbnRFbWl0dGVyIGZvciBjaGFpbmluZy5cbiAgICAgKi9cbiAgICBwcm90by5hZGRPbmNlTGlzdGVuZXIgPSBmdW5jdGlvbiBhZGRPbmNlTGlzdGVuZXIoZXZ0LCBsaXN0ZW5lcikge1xuICAgICAgICByZXR1cm4gdGhpcy5hZGRMaXN0ZW5lcihldnQsIHtcbiAgICAgICAgICAgIGxpc3RlbmVyOiBsaXN0ZW5lcixcbiAgICAgICAgICAgIG9uY2U6IHRydWVcbiAgICAgICAgfSk7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEFsaWFzIG9mIGFkZE9uY2VMaXN0ZW5lci5cbiAgICAgKi9cbiAgICBwcm90by5vbmNlID0gYWxpYXMoJ2FkZE9uY2VMaXN0ZW5lcicpO1xuXG4gICAgLyoqXG4gICAgICogRGVmaW5lcyBhbiBldmVudCBuYW1lLiBUaGlzIGlzIHJlcXVpcmVkIGlmIHlvdSB3YW50IHRvIHVzZSBhIHJlZ2V4IHRvIGFkZCBhIGxpc3RlbmVyIHRvIG11bHRpcGxlIGV2ZW50cyBhdCBvbmNlLiBJZiB5b3UgZG9uJ3QgZG8gdGhpcyB0aGVuIGhvdyBkbyB5b3UgZXhwZWN0IGl0IHRvIGtub3cgd2hhdCBldmVudCB0byBhZGQgdG8/IFNob3VsZCBpdCBqdXN0IGFkZCB0byBldmVyeSBwb3NzaWJsZSBtYXRjaCBmb3IgYSByZWdleD8gTm8uIFRoYXQgaXMgc2NhcnkgYW5kIGJhZC5cbiAgICAgKiBZb3UgbmVlZCB0byB0ZWxsIGl0IHdoYXQgZXZlbnQgbmFtZXMgc2hvdWxkIGJlIG1hdGNoZWQgYnkgYSByZWdleC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfSBldnQgTmFtZSBvZiB0aGUgZXZlbnQgdG8gY3JlYXRlLlxuICAgICAqIEByZXR1cm4ge09iamVjdH0gQ3VycmVudCBpbnN0YW5jZSBvZiBFdmVudEVtaXR0ZXIgZm9yIGNoYWluaW5nLlxuICAgICAqL1xuICAgIHByb3RvLmRlZmluZUV2ZW50ID0gZnVuY3Rpb24gZGVmaW5lRXZlbnQoZXZ0KSB7XG4gICAgICAgIHRoaXMuZ2V0TGlzdGVuZXJzKGV2dCk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBVc2VzIGRlZmluZUV2ZW50IHRvIGRlZmluZSBtdWx0aXBsZSBldmVudHMuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1N0cmluZ1tdfSBldnRzIEFuIGFycmF5IG9mIGV2ZW50IG5hbWVzIHRvIGRlZmluZS5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEN1cnJlbnQgaW5zdGFuY2Ugb2YgRXZlbnRFbWl0dGVyIGZvciBjaGFpbmluZy5cbiAgICAgKi9cbiAgICBwcm90by5kZWZpbmVFdmVudHMgPSBmdW5jdGlvbiBkZWZpbmVFdmVudHMoZXZ0cykge1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGV2dHMubGVuZ3RoOyBpICs9IDEpIHtcbiAgICAgICAgICAgIHRoaXMuZGVmaW5lRXZlbnQoZXZ0c1tpXSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIFJlbW92ZXMgYSBsaXN0ZW5lciBmdW5jdGlvbiBmcm9tIHRoZSBzcGVjaWZpZWQgZXZlbnQuXG4gICAgICogV2hlbiBwYXNzZWQgYSByZWd1bGFyIGV4cHJlc3Npb24gYXMgdGhlIGV2ZW50IG5hbWUsIGl0IHdpbGwgcmVtb3ZlIHRoZSBsaXN0ZW5lciBmcm9tIGFsbCBldmVudHMgdGhhdCBtYXRjaCBpdC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfFJlZ0V4cH0gZXZ0IE5hbWUgb2YgdGhlIGV2ZW50IHRvIHJlbW92ZSB0aGUgbGlzdGVuZXIgZnJvbS5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBsaXN0ZW5lciBNZXRob2QgdG8gcmVtb3ZlIGZyb20gdGhlIGV2ZW50LlxuICAgICAqIEByZXR1cm4ge09iamVjdH0gQ3VycmVudCBpbnN0YW5jZSBvZiBFdmVudEVtaXR0ZXIgZm9yIGNoYWluaW5nLlxuICAgICAqL1xuICAgIHByb3RvLnJlbW92ZUxpc3RlbmVyID0gZnVuY3Rpb24gcmVtb3ZlTGlzdGVuZXIoZXZ0LCBsaXN0ZW5lcikge1xuICAgICAgICB2YXIgbGlzdGVuZXJzID0gdGhpcy5nZXRMaXN0ZW5lcnNBc09iamVjdChldnQpO1xuICAgICAgICB2YXIgaW5kZXg7XG4gICAgICAgIHZhciBrZXk7XG5cbiAgICAgICAgZm9yIChrZXkgaW4gbGlzdGVuZXJzKSB7XG4gICAgICAgICAgICBpZiAobGlzdGVuZXJzLmhhc093blByb3BlcnR5KGtleSkpIHtcbiAgICAgICAgICAgICAgICBpbmRleCA9IGluZGV4T2ZMaXN0ZW5lcihsaXN0ZW5lcnNba2V5XSwgbGlzdGVuZXIpO1xuXG4gICAgICAgICAgICAgICAgaWYgKGluZGV4ICE9PSAtMSkge1xuICAgICAgICAgICAgICAgICAgICBsaXN0ZW5lcnNba2V5XS5zcGxpY2UoaW5kZXgsIDEpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBBbGlhcyBvZiByZW1vdmVMaXN0ZW5lclxuICAgICAqL1xuICAgIHByb3RvLm9mZiA9IGFsaWFzKCdyZW1vdmVMaXN0ZW5lcicpO1xuXG4gICAgLyoqXG4gICAgICogQWRkcyBsaXN0ZW5lcnMgaW4gYnVsayB1c2luZyB0aGUgbWFuaXB1bGF0ZUxpc3RlbmVycyBtZXRob2QuXG4gICAgICogSWYgeW91IHBhc3MgYW4gb2JqZWN0IGFzIHRoZSBmaXJzdCBhcmd1bWVudCB5b3UgY2FuIGFkZCB0byBtdWx0aXBsZSBldmVudHMgYXQgb25jZS4gVGhlIG9iamVjdCBzaG91bGQgY29udGFpbiBrZXkgdmFsdWUgcGFpcnMgb2YgZXZlbnRzIGFuZCBsaXN0ZW5lcnMgb3IgbGlzdGVuZXIgYXJyYXlzLiBZb3UgY2FuIGFsc28gcGFzcyBpdCBhbiBldmVudCBuYW1lIGFuZCBhbiBhcnJheSBvZiBsaXN0ZW5lcnMgdG8gYmUgYWRkZWQuXG4gICAgICogWW91IGNhbiBhbHNvIHBhc3MgaXQgYSByZWd1bGFyIGV4cHJlc3Npb24gdG8gYWRkIHRoZSBhcnJheSBvZiBsaXN0ZW5lcnMgdG8gYWxsIGV2ZW50cyB0aGF0IG1hdGNoIGl0LlxuICAgICAqIFllYWgsIHRoaXMgZnVuY3Rpb24gZG9lcyBxdWl0ZSBhIGJpdC4gVGhhdCdzIHByb2JhYmx5IGEgYmFkIHRoaW5nLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtTdHJpbmd8T2JqZWN0fFJlZ0V4cH0gZXZ0IEFuIGV2ZW50IG5hbWUgaWYgeW91IHdpbGwgcGFzcyBhbiBhcnJheSBvZiBsaXN0ZW5lcnMgbmV4dC4gQW4gb2JqZWN0IGlmIHlvdSB3aXNoIHRvIGFkZCB0byBtdWx0aXBsZSBldmVudHMgYXQgb25jZS5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9uW119IFtsaXN0ZW5lcnNdIEFuIG9wdGlvbmFsIGFycmF5IG9mIGxpc3RlbmVyIGZ1bmN0aW9ucyB0byBhZGQuXG4gICAgICogQHJldHVybiB7T2JqZWN0fSBDdXJyZW50IGluc3RhbmNlIG9mIEV2ZW50RW1pdHRlciBmb3IgY2hhaW5pbmcuXG4gICAgICovXG4gICAgcHJvdG8uYWRkTGlzdGVuZXJzID0gZnVuY3Rpb24gYWRkTGlzdGVuZXJzKGV2dCwgbGlzdGVuZXJzKSB7XG4gICAgICAgIC8vIFBhc3MgdGhyb3VnaCB0byBtYW5pcHVsYXRlTGlzdGVuZXJzXG4gICAgICAgIHJldHVybiB0aGlzLm1hbmlwdWxhdGVMaXN0ZW5lcnMoZmFsc2UsIGV2dCwgbGlzdGVuZXJzKTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlcyBsaXN0ZW5lcnMgaW4gYnVsayB1c2luZyB0aGUgbWFuaXB1bGF0ZUxpc3RlbmVycyBtZXRob2QuXG4gICAgICogSWYgeW91IHBhc3MgYW4gb2JqZWN0IGFzIHRoZSBmaXJzdCBhcmd1bWVudCB5b3UgY2FuIHJlbW92ZSBmcm9tIG11bHRpcGxlIGV2ZW50cyBhdCBvbmNlLiBUaGUgb2JqZWN0IHNob3VsZCBjb250YWluIGtleSB2YWx1ZSBwYWlycyBvZiBldmVudHMgYW5kIGxpc3RlbmVycyBvciBsaXN0ZW5lciBhcnJheXMuXG4gICAgICogWW91IGNhbiBhbHNvIHBhc3MgaXQgYW4gZXZlbnQgbmFtZSBhbmQgYW4gYXJyYXkgb2YgbGlzdGVuZXJzIHRvIGJlIHJlbW92ZWQuXG4gICAgICogWW91IGNhbiBhbHNvIHBhc3MgaXQgYSByZWd1bGFyIGV4cHJlc3Npb24gdG8gcmVtb3ZlIHRoZSBsaXN0ZW5lcnMgZnJvbSBhbGwgZXZlbnRzIHRoYXQgbWF0Y2ggaXQuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1N0cmluZ3xPYmplY3R8UmVnRXhwfSBldnQgQW4gZXZlbnQgbmFtZSBpZiB5b3Ugd2lsbCBwYXNzIGFuIGFycmF5IG9mIGxpc3RlbmVycyBuZXh0LiBBbiBvYmplY3QgaWYgeW91IHdpc2ggdG8gcmVtb3ZlIGZyb20gbXVsdGlwbGUgZXZlbnRzIGF0IG9uY2UuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbltdfSBbbGlzdGVuZXJzXSBBbiBvcHRpb25hbCBhcnJheSBvZiBsaXN0ZW5lciBmdW5jdGlvbnMgdG8gcmVtb3ZlLlxuICAgICAqIEByZXR1cm4ge09iamVjdH0gQ3VycmVudCBpbnN0YW5jZSBvZiBFdmVudEVtaXR0ZXIgZm9yIGNoYWluaW5nLlxuICAgICAqL1xuICAgIHByb3RvLnJlbW92ZUxpc3RlbmVycyA9IGZ1bmN0aW9uIHJlbW92ZUxpc3RlbmVycyhldnQsIGxpc3RlbmVycykge1xuICAgICAgICAvLyBQYXNzIHRocm91Z2ggdG8gbWFuaXB1bGF0ZUxpc3RlbmVyc1xuICAgICAgICByZXR1cm4gdGhpcy5tYW5pcHVsYXRlTGlzdGVuZXJzKHRydWUsIGV2dCwgbGlzdGVuZXJzKTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogRWRpdHMgbGlzdGVuZXJzIGluIGJ1bGsuIFRoZSBhZGRMaXN0ZW5lcnMgYW5kIHJlbW92ZUxpc3RlbmVycyBtZXRob2RzIGJvdGggdXNlIHRoaXMgdG8gZG8gdGhlaXIgam9iLiBZb3Ugc2hvdWxkIHJlYWxseSB1c2UgdGhvc2UgaW5zdGVhZCwgdGhpcyBpcyBhIGxpdHRsZSBsb3dlciBsZXZlbC5cbiAgICAgKiBUaGUgZmlyc3QgYXJndW1lbnQgd2lsbCBkZXRlcm1pbmUgaWYgdGhlIGxpc3RlbmVycyBhcmUgcmVtb3ZlZCAodHJ1ZSkgb3IgYWRkZWQgKGZhbHNlKS5cbiAgICAgKiBJZiB5b3UgcGFzcyBhbiBvYmplY3QgYXMgdGhlIHNlY29uZCBhcmd1bWVudCB5b3UgY2FuIGFkZC9yZW1vdmUgZnJvbSBtdWx0aXBsZSBldmVudHMgYXQgb25jZS4gVGhlIG9iamVjdCBzaG91bGQgY29udGFpbiBrZXkgdmFsdWUgcGFpcnMgb2YgZXZlbnRzIGFuZCBsaXN0ZW5lcnMgb3IgbGlzdGVuZXIgYXJyYXlzLlxuICAgICAqIFlvdSBjYW4gYWxzbyBwYXNzIGl0IGFuIGV2ZW50IG5hbWUgYW5kIGFuIGFycmF5IG9mIGxpc3RlbmVycyB0byBiZSBhZGRlZC9yZW1vdmVkLlxuICAgICAqIFlvdSBjYW4gYWxzbyBwYXNzIGl0IGEgcmVndWxhciBleHByZXNzaW9uIHRvIG1hbmlwdWxhdGUgdGhlIGxpc3RlbmVycyBvZiBhbGwgZXZlbnRzIHRoYXQgbWF0Y2ggaXQuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0Jvb2xlYW59IHJlbW92ZSBUcnVlIGlmIHlvdSB3YW50IHRvIHJlbW92ZSBsaXN0ZW5lcnMsIGZhbHNlIGlmIHlvdSB3YW50IHRvIGFkZC5cbiAgICAgKiBAcGFyYW0ge1N0cmluZ3xPYmplY3R8UmVnRXhwfSBldnQgQW4gZXZlbnQgbmFtZSBpZiB5b3Ugd2lsbCBwYXNzIGFuIGFycmF5IG9mIGxpc3RlbmVycyBuZXh0LiBBbiBvYmplY3QgaWYgeW91IHdpc2ggdG8gYWRkL3JlbW92ZSBmcm9tIG11bHRpcGxlIGV2ZW50cyBhdCBvbmNlLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb25bXX0gW2xpc3RlbmVyc10gQW4gb3B0aW9uYWwgYXJyYXkgb2YgbGlzdGVuZXIgZnVuY3Rpb25zIHRvIGFkZC9yZW1vdmUuXG4gICAgICogQHJldHVybiB7T2JqZWN0fSBDdXJyZW50IGluc3RhbmNlIG9mIEV2ZW50RW1pdHRlciBmb3IgY2hhaW5pbmcuXG4gICAgICovXG4gICAgcHJvdG8ubWFuaXB1bGF0ZUxpc3RlbmVycyA9IGZ1bmN0aW9uIG1hbmlwdWxhdGVMaXN0ZW5lcnMocmVtb3ZlLCBldnQsIGxpc3RlbmVycykge1xuICAgICAgICB2YXIgaTtcbiAgICAgICAgdmFyIHZhbHVlO1xuICAgICAgICB2YXIgc2luZ2xlID0gcmVtb3ZlID8gdGhpcy5yZW1vdmVMaXN0ZW5lciA6IHRoaXMuYWRkTGlzdGVuZXI7XG4gICAgICAgIHZhciBtdWx0aXBsZSA9IHJlbW92ZSA/IHRoaXMucmVtb3ZlTGlzdGVuZXJzIDogdGhpcy5hZGRMaXN0ZW5lcnM7XG5cbiAgICAgICAgLy8gSWYgZXZ0IGlzIGFuIG9iamVjdCB0aGVuIHBhc3MgZWFjaCBvZiBpdHMgcHJvcGVydGllcyB0byB0aGlzIG1ldGhvZFxuICAgICAgICBpZiAodHlwZW9mIGV2dCA9PT0gJ29iamVjdCcgJiYgIShldnQgaW5zdGFuY2VvZiBSZWdFeHApKSB7XG4gICAgICAgICAgICBmb3IgKGkgaW4gZXZ0KSB7XG4gICAgICAgICAgICAgICAgaWYgKGV2dC5oYXNPd25Qcm9wZXJ0eShpKSAmJiAodmFsdWUgPSBldnRbaV0pKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIFBhc3MgdGhlIHNpbmdsZSBsaXN0ZW5lciBzdHJhaWdodCB0aHJvdWdoIHRvIHRoZSBzaW5ndWxhciBtZXRob2RcbiAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgc2luZ2xlLmNhbGwodGhpcywgaSwgdmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gT3RoZXJ3aXNlIHBhc3MgYmFjayB0byB0aGUgbXVsdGlwbGUgZnVuY3Rpb25cbiAgICAgICAgICAgICAgICAgICAgICAgIG11bHRpcGxlLmNhbGwodGhpcywgaSwgdmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgLy8gU28gZXZ0IG11c3QgYmUgYSBzdHJpbmdcbiAgICAgICAgICAgIC8vIEFuZCBsaXN0ZW5lcnMgbXVzdCBiZSBhbiBhcnJheSBvZiBsaXN0ZW5lcnNcbiAgICAgICAgICAgIC8vIExvb3Agb3ZlciBpdCBhbmQgcGFzcyBlYWNoIG9uZSB0byB0aGUgbXVsdGlwbGUgbWV0aG9kXG4gICAgICAgICAgICBpID0gbGlzdGVuZXJzLmxlbmd0aDtcbiAgICAgICAgICAgIHdoaWxlIChpLS0pIHtcbiAgICAgICAgICAgICAgICBzaW5nbGUuY2FsbCh0aGlzLCBldnQsIGxpc3RlbmVyc1tpXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlcyBhbGwgbGlzdGVuZXJzIGZyb20gYSBzcGVjaWZpZWQgZXZlbnQuXG4gICAgICogSWYgeW91IGRvIG5vdCBzcGVjaWZ5IGFuIGV2ZW50IHRoZW4gYWxsIGxpc3RlbmVycyB3aWxsIGJlIHJlbW92ZWQuXG4gICAgICogVGhhdCBtZWFucyBldmVyeSBldmVudCB3aWxsIGJlIGVtcHRpZWQuXG4gICAgICogWW91IGNhbiBhbHNvIHBhc3MgYSByZWdleCB0byByZW1vdmUgYWxsIGV2ZW50cyB0aGF0IG1hdGNoIGl0LlxuICAgICAqXG4gICAgICogQHBhcmFtIHtTdHJpbmd8UmVnRXhwfSBbZXZ0XSBPcHRpb25hbCBuYW1lIG9mIHRoZSBldmVudCB0byByZW1vdmUgYWxsIGxpc3RlbmVycyBmb3IuIFdpbGwgcmVtb3ZlIGZyb20gZXZlcnkgZXZlbnQgaWYgbm90IHBhc3NlZC5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEN1cnJlbnQgaW5zdGFuY2Ugb2YgRXZlbnRFbWl0dGVyIGZvciBjaGFpbmluZy5cbiAgICAgKi9cbiAgICBwcm90by5yZW1vdmVFdmVudCA9IGZ1bmN0aW9uIHJlbW92ZUV2ZW50KGV2dCkge1xuICAgICAgICB2YXIgdHlwZSA9IHR5cGVvZiBldnQ7XG4gICAgICAgIHZhciBldmVudHMgPSB0aGlzLl9nZXRFdmVudHMoKTtcbiAgICAgICAgdmFyIGtleTtcblxuICAgICAgICAvLyBSZW1vdmUgZGlmZmVyZW50IHRoaW5ncyBkZXBlbmRpbmcgb24gdGhlIHN0YXRlIG9mIGV2dFxuICAgICAgICBpZiAodHlwZSA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgIC8vIFJlbW92ZSBhbGwgbGlzdGVuZXJzIGZvciB0aGUgc3BlY2lmaWVkIGV2ZW50XG4gICAgICAgICAgICBkZWxldGUgZXZlbnRzW2V2dF07XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAoZXZ0IGluc3RhbmNlb2YgUmVnRXhwKSB7XG4gICAgICAgICAgICAvLyBSZW1vdmUgYWxsIGV2ZW50cyBtYXRjaGluZyB0aGUgcmVnZXguXG4gICAgICAgICAgICBmb3IgKGtleSBpbiBldmVudHMpIHtcbiAgICAgICAgICAgICAgICBpZiAoZXZlbnRzLmhhc093blByb3BlcnR5KGtleSkgJiYgZXZ0LnRlc3Qoa2V5KSkge1xuICAgICAgICAgICAgICAgICAgICBkZWxldGUgZXZlbnRzW2tleV07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgLy8gUmVtb3ZlIGFsbCBsaXN0ZW5lcnMgaW4gYWxsIGV2ZW50c1xuICAgICAgICAgICAgZGVsZXRlIHRoaXMuX2V2ZW50cztcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBBbGlhcyBvZiByZW1vdmVFdmVudC5cbiAgICAgKlxuICAgICAqIEFkZGVkIHRvIG1pcnJvciB0aGUgbm9kZSBBUEkuXG4gICAgICovXG4gICAgcHJvdG8ucmVtb3ZlQWxsTGlzdGVuZXJzID0gYWxpYXMoJ3JlbW92ZUV2ZW50Jyk7XG5cbiAgICAvKipcbiAgICAgKiBFbWl0cyBhbiBldmVudCBvZiB5b3VyIGNob2ljZS5cbiAgICAgKiBXaGVuIGVtaXR0ZWQsIGV2ZXJ5IGxpc3RlbmVyIGF0dGFjaGVkIHRvIHRoYXQgZXZlbnQgd2lsbCBiZSBleGVjdXRlZC5cbiAgICAgKiBJZiB5b3UgcGFzcyB0aGUgb3B0aW9uYWwgYXJndW1lbnQgYXJyYXkgdGhlbiB0aG9zZSBhcmd1bWVudHMgd2lsbCBiZSBwYXNzZWQgdG8gZXZlcnkgbGlzdGVuZXIgdXBvbiBleGVjdXRpb24uXG4gICAgICogQmVjYXVzZSBpdCB1c2VzIGBhcHBseWAsIHlvdXIgYXJyYXkgb2YgYXJndW1lbnRzIHdpbGwgYmUgcGFzc2VkIGFzIGlmIHlvdSB3cm90ZSB0aGVtIG91dCBzZXBhcmF0ZWx5LlxuICAgICAqIFNvIHRoZXkgd2lsbCBub3QgYXJyaXZlIHdpdGhpbiB0aGUgYXJyYXkgb24gdGhlIG90aGVyIHNpZGUsIHRoZXkgd2lsbCBiZSBzZXBhcmF0ZS5cbiAgICAgKiBZb3UgY2FuIGFsc28gcGFzcyBhIHJlZ3VsYXIgZXhwcmVzc2lvbiB0byBlbWl0IHRvIGFsbCBldmVudHMgdGhhdCBtYXRjaCBpdC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfFJlZ0V4cH0gZXZ0IE5hbWUgb2YgdGhlIGV2ZW50IHRvIGVtaXQgYW5kIGV4ZWN1dGUgbGlzdGVuZXJzIGZvci5cbiAgICAgKiBAcGFyYW0ge0FycmF5fSBbYXJnc10gT3B0aW9uYWwgYXJyYXkgb2YgYXJndW1lbnRzIHRvIGJlIHBhc3NlZCB0byBlYWNoIGxpc3RlbmVyLlxuICAgICAqIEByZXR1cm4ge09iamVjdH0gQ3VycmVudCBpbnN0YW5jZSBvZiBFdmVudEVtaXR0ZXIgZm9yIGNoYWluaW5nLlxuICAgICAqL1xuICAgIHByb3RvLmVtaXRFdmVudCA9IGZ1bmN0aW9uIGVtaXRFdmVudChldnQsIGFyZ3MpIHtcbiAgICAgICAgdmFyIGxpc3RlbmVyc01hcCA9IHRoaXMuZ2V0TGlzdGVuZXJzQXNPYmplY3QoZXZ0KTtcbiAgICAgICAgdmFyIGxpc3RlbmVycztcbiAgICAgICAgdmFyIGxpc3RlbmVyO1xuICAgICAgICB2YXIgaTtcbiAgICAgICAgdmFyIGtleTtcbiAgICAgICAgdmFyIHJlc3BvbnNlO1xuXG4gICAgICAgIGZvciAoa2V5IGluIGxpc3RlbmVyc01hcCkge1xuICAgICAgICAgICAgaWYgKGxpc3RlbmVyc01hcC5oYXNPd25Qcm9wZXJ0eShrZXkpKSB7XG4gICAgICAgICAgICAgICAgbGlzdGVuZXJzID0gbGlzdGVuZXJzTWFwW2tleV0uc2xpY2UoMCk7XG5cbiAgICAgICAgICAgICAgICBmb3IgKGkgPSAwOyBpIDwgbGlzdGVuZXJzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIElmIHRoZSBsaXN0ZW5lciByZXR1cm5zIHRydWUgdGhlbiBpdCBzaGFsbCBiZSByZW1vdmVkIGZyb20gdGhlIGV2ZW50XG4gICAgICAgICAgICAgICAgICAgIC8vIFRoZSBmdW5jdGlvbiBpcyBleGVjdXRlZCBlaXRoZXIgd2l0aCBhIGJhc2ljIGNhbGwgb3IgYW4gYXBwbHkgaWYgdGhlcmUgaXMgYW4gYXJncyBhcnJheVxuICAgICAgICAgICAgICAgICAgICBsaXN0ZW5lciA9IGxpc3RlbmVyc1tpXTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAobGlzdGVuZXIub25jZSA9PT0gdHJ1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5yZW1vdmVMaXN0ZW5lcihldnQsIGxpc3RlbmVyLmxpc3RlbmVyKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHJlc3BvbnNlID0gbGlzdGVuZXIubGlzdGVuZXIuYXBwbHkodGhpcywgYXJncyB8fCBbXSk7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKHJlc3BvbnNlID09PSB0aGlzLl9nZXRPbmNlUmV0dXJuVmFsdWUoKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5yZW1vdmVMaXN0ZW5lcihldnQsIGxpc3RlbmVyLmxpc3RlbmVyKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBBbGlhcyBvZiBlbWl0RXZlbnRcbiAgICAgKi9cbiAgICBwcm90by50cmlnZ2VyID0gYWxpYXMoJ2VtaXRFdmVudCcpO1xuXG4gICAgLyoqXG4gICAgICogU3VidGx5IGRpZmZlcmVudCBmcm9tIGVtaXRFdmVudCBpbiB0aGF0IGl0IHdpbGwgcGFzcyBpdHMgYXJndW1lbnRzIG9uIHRvIHRoZSBsaXN0ZW5lcnMsIGFzIG9wcG9zZWQgdG8gdGFraW5nIGEgc2luZ2xlIGFycmF5IG9mIGFyZ3VtZW50cyB0byBwYXNzIG9uLlxuICAgICAqIEFzIHdpdGggZW1pdEV2ZW50LCB5b3UgY2FuIHBhc3MgYSByZWdleCBpbiBwbGFjZSBvZiB0aGUgZXZlbnQgbmFtZSB0byBlbWl0IHRvIGFsbCBldmVudHMgdGhhdCBtYXRjaCBpdC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfFJlZ0V4cH0gZXZ0IE5hbWUgb2YgdGhlIGV2ZW50IHRvIGVtaXQgYW5kIGV4ZWN1dGUgbGlzdGVuZXJzIGZvci5cbiAgICAgKiBAcGFyYW0gey4uLip9IE9wdGlvbmFsIGFkZGl0aW9uYWwgYXJndW1lbnRzIHRvIGJlIHBhc3NlZCB0byBlYWNoIGxpc3RlbmVyLlxuICAgICAqIEByZXR1cm4ge09iamVjdH0gQ3VycmVudCBpbnN0YW5jZSBvZiBFdmVudEVtaXR0ZXIgZm9yIGNoYWluaW5nLlxuICAgICAqL1xuICAgIHByb3RvLmVtaXQgPSBmdW5jdGlvbiBlbWl0KGV2dCkge1xuICAgICAgICB2YXIgYXJncyA9IEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3VtZW50cywgMSk7XG4gICAgICAgIHJldHVybiB0aGlzLmVtaXRFdmVudChldnQsIGFyZ3MpO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBTZXRzIHRoZSBjdXJyZW50IHZhbHVlIHRvIGNoZWNrIGFnYWluc3Qgd2hlbiBleGVjdXRpbmcgbGlzdGVuZXJzLiBJZiBhXG4gICAgICogbGlzdGVuZXJzIHJldHVybiB2YWx1ZSBtYXRjaGVzIHRoZSBvbmUgc2V0IGhlcmUgdGhlbiBpdCB3aWxsIGJlIHJlbW92ZWRcbiAgICAgKiBhZnRlciBleGVjdXRpb24uIFRoaXMgdmFsdWUgZGVmYXVsdHMgdG8gdHJ1ZS5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIG5ldyB2YWx1ZSB0byBjaGVjayBmb3Igd2hlbiBleGVjdXRpbmcgbGlzdGVuZXJzLlxuICAgICAqIEByZXR1cm4ge09iamVjdH0gQ3VycmVudCBpbnN0YW5jZSBvZiBFdmVudEVtaXR0ZXIgZm9yIGNoYWluaW5nLlxuICAgICAqL1xuICAgIHByb3RvLnNldE9uY2VSZXR1cm5WYWx1ZSA9IGZ1bmN0aW9uIHNldE9uY2VSZXR1cm5WYWx1ZSh2YWx1ZSkge1xuICAgICAgICB0aGlzLl9vbmNlUmV0dXJuVmFsdWUgPSB2YWx1ZTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEZldGNoZXMgdGhlIGN1cnJlbnQgdmFsdWUgdG8gY2hlY2sgYWdhaW5zdCB3aGVuIGV4ZWN1dGluZyBsaXN0ZW5lcnMuIElmXG4gICAgICogdGhlIGxpc3RlbmVycyByZXR1cm4gdmFsdWUgbWF0Y2hlcyB0aGlzIG9uZSB0aGVuIGl0IHNob3VsZCBiZSByZW1vdmVkXG4gICAgICogYXV0b21hdGljYWxseS4gSXQgd2lsbCByZXR1cm4gdHJ1ZSBieSBkZWZhdWx0LlxuICAgICAqXG4gICAgICogQHJldHVybiB7KnxCb29sZWFufSBUaGUgY3VycmVudCB2YWx1ZSB0byBjaGVjayBmb3Igb3IgdGhlIGRlZmF1bHQsIHRydWUuXG4gICAgICogQGFwaSBwcml2YXRlXG4gICAgICovXG4gICAgcHJvdG8uX2dldE9uY2VSZXR1cm5WYWx1ZSA9IGZ1bmN0aW9uIF9nZXRPbmNlUmV0dXJuVmFsdWUoKSB7XG4gICAgICAgIGlmICh0aGlzLmhhc093blByb3BlcnR5KCdfb25jZVJldHVyblZhbHVlJykpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLl9vbmNlUmV0dXJuVmFsdWU7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBGZXRjaGVzIHRoZSBldmVudHMgb2JqZWN0IGFuZCBjcmVhdGVzIG9uZSBpZiByZXF1aXJlZC5cbiAgICAgKlxuICAgICAqIEByZXR1cm4ge09iamVjdH0gVGhlIGV2ZW50cyBzdG9yYWdlIG9iamVjdC5cbiAgICAgKiBAYXBpIHByaXZhdGVcbiAgICAgKi9cbiAgICBwcm90by5fZ2V0RXZlbnRzID0gZnVuY3Rpb24gX2dldEV2ZW50cygpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2V2ZW50cyB8fCAodGhpcy5fZXZlbnRzID0ge30pO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBSZXZlcnRzIHRoZSBnbG9iYWwge0BsaW5rIEV2ZW50RW1pdHRlcn0gdG8gaXRzIHByZXZpb3VzIHZhbHVlIGFuZCByZXR1cm5zIGEgcmVmZXJlbmNlIHRvIHRoaXMgdmVyc2lvbi5cbiAgICAgKlxuICAgICAqIEByZXR1cm4ge0Z1bmN0aW9ufSBOb24gY29uZmxpY3RpbmcgRXZlbnRFbWl0dGVyIGNsYXNzLlxuICAgICAqL1xuICAgIEV2ZW50RW1pdHRlci5ub0NvbmZsaWN0ID0gZnVuY3Rpb24gbm9Db25mbGljdCgpIHtcbiAgICAgICAgZXhwb3J0cy5FdmVudEVtaXR0ZXIgPSBvcmlnaW5hbEdsb2JhbFZhbHVlO1xuICAgICAgICByZXR1cm4gRXZlbnRFbWl0dGVyO1xuICAgIH07XG5cbiAgICAvLyBFeHBvc2UgdGhlIGNsYXNzIGVpdGhlciB2aWEgQU1ELCBDb21tb25KUyBvciB0aGUgZ2xvYmFsIG9iamVjdFxuICAgIGlmICh0eXBlb2YgZGVmaW5lID09PSAnZnVuY3Rpb24nICYmIGRlZmluZS5hbWQpIHtcbiAgICAgICAgZGVmaW5lKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiBFdmVudEVtaXR0ZXI7XG4gICAgICAgIH0pO1xuICAgIH1cbiAgICBlbHNlIGlmICh0eXBlb2YgbW9kdWxlID09PSAnb2JqZWN0JyAmJiBtb2R1bGUuZXhwb3J0cyl7XG4gICAgICAgIG1vZHVsZS5leHBvcnRzID0gRXZlbnRFbWl0dGVyO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgZXhwb3J0cy5FdmVudEVtaXR0ZXIgPSBFdmVudEVtaXR0ZXI7XG4gICAgfVxufSh0eXBlb2Ygd2luZG93ICE9PSAndW5kZWZpbmVkJyA/IHdpbmRvdyA6IHRoaXMgfHwge30pKTtcbiIsImltcG9ydCB7IE9wZW5WaWR1IH0gZnJvbSAnLi9PcGVuVmlkdS9PcGVuVmlkdSc7XG5cbmlmICh3aW5kb3cpIHtcbiAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6bm8tc3RyaW5nLWxpdGVyYWxcbiAgICB3aW5kb3dbJ09wZW5WaWR1J10gPSBPcGVuVmlkdTtcbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IFNlc3Npb24gfSBmcm9tICcuL1Nlc3Npb24nO1xuaW1wb3J0IHsgU3RyZWFtIH0gZnJvbSAnLi9TdHJlYW0nO1xuaW1wb3J0IHsgQ29ubmVjdGlvbk9wdGlvbnMgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHJpdmF0ZS9Db25uZWN0aW9uT3B0aW9ucyc7XG5pbXBvcnQgeyBJbmJvdW5kU3RyZWFtT3B0aW9ucyB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvSW50ZXJmYWNlcy9Qcml2YXRlL0luYm91bmRTdHJlYW1PcHRpb25zJztcbmltcG9ydCB7IFN0cmVhbU9wdGlvbnNTZXJ2ZXIgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHJpdmF0ZS9TdHJlYW1PcHRpb25zU2VydmVyJztcblxuXG4vKipcbiAqIFJlcHJlc2VudHMgZWFjaCBvbmUgb2YgdGhlIHVzZXIncyBjb25uZWN0aW9uIHRvIHRoZSBzZXNzaW9uICh0aGUgbG9jYWwgb25lIGFuZCBvdGhlciB1c2VyJ3MgY29ubmVjdGlvbnMpLlxuICogVGhlcmVmb3JlIGVhY2ggW1tTZXNzaW9uXV0gYW5kIFtbU3RyZWFtXV0gb2JqZWN0IGhhcyBhbiBhdHRyaWJ1dGUgb2YgdHlwZSBDb25uZWN0aW9uXG4gKi9cbmV4cG9ydCBjbGFzcyBDb25uZWN0aW9uIHtcblxuICAgIC8qKlxuICAgICAqIFVuaXF1ZSBpZGVudGlmaWVyIG9mIHRoZSBjb25uZWN0aW9uXG4gICAgICovXG4gICAgY29ubmVjdGlvbklkOiBzdHJpbmc7XG5cbiAgICAvKipcbiAgICAgKiBUaW1lIHdoZW4gdGhpcyBjb25uZWN0aW9uIHdhcyBjcmVhdGVkIChVVEMgbWlsbGlzZWNvbmRzKVxuICAgICAqL1xuICAgIGNyZWF0aW9uVGltZTogbnVtYmVyO1xuXG4gICAgLyoqXG4gICAgICogRGF0YSBhc3NvY2lhdGVkIHRvIHRoaXMgY29ubmVjdGlvbiAoYW5kIHRoZXJlZm9yZSB0byBjZXJ0YWluIHVzZXIpLiBUaGlzIGlzIGFuIGltcG9ydGFudCBmaWVsZDpcbiAgICAgKiBpdCBhbGxvd3MgeW91IHRvIGJyb2FkY2FzdCBhbGwgdGhlIGluZm9ybWF0aW9uIHlvdSB3YW50IGZvciBlYWNoIHVzZXIgKGEgdXNlcm5hbWUsIGZvciBleGFtcGxlKVxuICAgICAqL1xuICAgIGRhdGE6IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBzdHJlYW06IFN0cmVhbTtcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvcHRpb25zOiBDb25uZWN0aW9uT3B0aW9ucyB8IHVuZGVmaW5lZDtcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBkaXNwb3NlZCA9IGZhbHNlO1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHByaXZhdGUgc2Vzc2lvbjogU2Vzc2lvbiwgb3B0cz86IENvbm5lY3Rpb25PcHRpb25zKSB7XG5cbiAgICAgICAgbGV0IG1zZyA9IFwiJ0Nvbm5lY3Rpb24nIGNyZWF0ZWQgXCI7XG4gICAgICAgIGlmICghIW9wdHMpIHtcbiAgICAgICAgICAgIG1zZyArPSBcIihyZW1vdGUpIHdpdGggJ2Nvbm5lY3Rpb25JZCcgW1wiICsgb3B0cy5pZCArICddJztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIG1zZyArPSAnKGxvY2FsKSc7XG4gICAgICAgIH1cbiAgICAgICAgY29uc29sZS5pbmZvKG1zZyk7XG5cbiAgICAgICAgdGhpcy5vcHRpb25zID0gb3B0cztcblxuICAgICAgICBpZiAoISFvcHRzKSB7XG4gICAgICAgICAgICAvLyBDb25uZWN0aW9uIGlzIHJlbW90ZVxuICAgICAgICAgICAgdGhpcy5jb25uZWN0aW9uSWQgPSBvcHRzLmlkO1xuICAgICAgICAgICAgaWYgKG9wdHMubWV0YWRhdGEpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmRhdGEgPSBvcHRzLm1ldGFkYXRhO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG9wdHMuc3RyZWFtcykge1xuICAgICAgICAgICAgICAgIHRoaXMuaW5pdFJlbW90ZVN0cmVhbXMob3B0cy5zdHJlYW1zKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuY3JlYXRpb25UaW1lID0gbmV3IERhdGUoKS5nZXRUaW1lKCk7XG4gICAgfVxuXG5cbiAgICAvKiBIaWRkZW4gbWV0aG9kcyAqL1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHNlbmRJY2VDYW5kaWRhdGUoY2FuZGlkYXRlOiBSVENJY2VDYW5kaWRhdGUpOiB2b2lkIHtcblxuICAgICAgICBjb25zb2xlLmRlYnVnKCghIXRoaXMuc3RyZWFtLm91dGJvdW5kU3RyZWFtT3B0cyA/ICdMb2NhbCcgOiAnUmVtb3RlJyksICdjYW5kaWRhdGUgZm9yJyxcbiAgICAgICAgICAgIHRoaXMuY29ubmVjdGlvbklkLCBKU09OLnN0cmluZ2lmeShjYW5kaWRhdGUpKTtcblxuICAgICAgICB0aGlzLnNlc3Npb24ub3BlbnZpZHUuc2VuZFJlcXVlc3QoJ29uSWNlQ2FuZGlkYXRlJywge1xuICAgICAgICAgICAgZW5kcG9pbnROYW1lOiB0aGlzLmNvbm5lY3Rpb25JZCxcbiAgICAgICAgICAgIGNhbmRpZGF0ZTogY2FuZGlkYXRlLmNhbmRpZGF0ZSxcbiAgICAgICAgICAgIHNkcE1pZDogY2FuZGlkYXRlLnNkcE1pZCxcbiAgICAgICAgICAgIHNkcE1MaW5lSW5kZXg6IGNhbmRpZGF0ZS5zZHBNTGluZUluZGV4XG4gICAgICAgIH0sIChlcnJvciwgcmVzcG9uc2UpID0+IHtcbiAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ0Vycm9yIHNlbmRpbmcgSUNFIGNhbmRpZGF0ZTogJ1xuICAgICAgICAgICAgICAgICAgICArIEpTT04uc3RyaW5naWZ5KGVycm9yKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBpbml0UmVtb3RlU3RyZWFtcyhvcHRpb25zOiBTdHJlYW1PcHRpb25zU2VydmVyW10pOiB2b2lkIHtcblxuICAgICAgICAvLyBUaGlzIGlzIHJlYWR5IGZvciBzdXBwb3J0aW5nIG11bHRpcGxlIHN0cmVhbXMgcGVyIENvbm5lY3Rpb24gb2JqZWN0LiBSaWdodCBub3cgdGhlIGxvb3Agd2lsbCBhbHdheXMgcnVuIGp1c3Qgb25jZVxuICAgICAgICAvLyB0aGlzLnN0cmVhbSBzaG91bGQgYWxzbyBiZSByZXBsYWNlZCBieSBhIGNvbGxlY3Rpb24gb2Ygc3RyZWFtcyB0byBzdXBwb3J0IG11bHRpcGxlIHN0cmVhbXMgcGVyIENvbm5lY3Rpb25cbiAgICAgICAgb3B0aW9ucy5mb3JFYWNoKG9wdHMgPT4ge1xuICAgICAgICAgICAgY29uc3Qgc3RyZWFtT3B0aW9uczogSW5ib3VuZFN0cmVhbU9wdGlvbnMgPSB7XG4gICAgICAgICAgICAgICAgaWQ6IG9wdHMuaWQsXG4gICAgICAgICAgICAgICAgY29ubmVjdGlvbjogdGhpcyxcbiAgICAgICAgICAgICAgICBoYXNBdWRpbzogb3B0cy5oYXNBdWRpbyxcbiAgICAgICAgICAgICAgICBoYXNWaWRlbzogb3B0cy5oYXNWaWRlbyxcbiAgICAgICAgICAgICAgICBhdWRpb0FjdGl2ZTogb3B0cy5hdWRpb0FjdGl2ZSxcbiAgICAgICAgICAgICAgICB2aWRlb0FjdGl2ZTogb3B0cy52aWRlb0FjdGl2ZSxcbiAgICAgICAgICAgICAgICB0eXBlT2ZWaWRlbzogb3B0cy50eXBlT2ZWaWRlbyxcbiAgICAgICAgICAgICAgICBmcmFtZVJhdGU6IG9wdHMuZnJhbWVSYXRlLFxuICAgICAgICAgICAgICAgIHZpZGVvRGltZW5zaW9uczogISFvcHRzLnZpZGVvRGltZW5zaW9ucyA/IEpTT04ucGFyc2Uob3B0cy52aWRlb0RpbWVuc2lvbnMpIDogdW5kZWZpbmVkXG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgY29uc3Qgc3RyZWFtID0gbmV3IFN0cmVhbSh0aGlzLnNlc3Npb24sIHN0cmVhbU9wdGlvbnMpO1xuXG4gICAgICAgICAgICB0aGlzLmFkZFN0cmVhbShzdHJlYW0pO1xuICAgICAgICB9KTtcblxuICAgICAgICBjb25zb2xlLmluZm8oXCJSZW1vdGUgJ0Nvbm5lY3Rpb24nIHdpdGggJ2Nvbm5lY3Rpb25JZCcgW1wiICsgdGhpcy5jb25uZWN0aW9uSWQgKyAnXSBpcyBub3cgY29uZmlndXJlZCBmb3IgcmVjZWl2aW5nIFN0cmVhbXMgd2l0aCBvcHRpb25zOiAnLCB0aGlzLnN0cmVhbS5pbmJvdW5kU3RyZWFtT3B0cyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGFkZFN0cmVhbShzdHJlYW06IFN0cmVhbSk6IHZvaWQge1xuICAgICAgICBzdHJlYW0uY29ubmVjdGlvbiA9IHRoaXM7XG4gICAgICAgIHRoaXMuc3RyZWFtID0gc3RyZWFtO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICByZW1vdmVTdHJlYW0oc3RyZWFtSWQ6IHN0cmluZyk6IHZvaWQge1xuICAgICAgICBkZWxldGUgdGhpcy5zdHJlYW07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGRpc3Bvc2UoKTogdm9pZCB7XG4gICAgICAgIGlmICghIXRoaXMuc3RyZWFtKSB7XG4gICAgICAgICAgICBkZWxldGUgdGhpcy5zdHJlYW07XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5kaXNwb3NlZCA9IHRydWU7XG4gICAgfVxuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBTdHJlYW0gfSBmcm9tICcuL1N0cmVhbSc7XG5pbXBvcnQgeyBMb2NhbFJlY29yZGVyU3RhdGUgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0VudW1zL0xvY2FsUmVjb3JkZXJTdGF0ZSc7XG5cbi8qKlxuICogQGhpZGRlblxuICovXG5kZWNsYXJlIHZhciBNZWRpYVJlY29yZGVyOiBhbnk7XG5cblxuLyoqXG4gKiBFYXN5IHJlY29yZGluZyBvZiBbW1N0cmVhbV1dIG9iamVjdHMgc3RyYWlnaHRhd2F5IGZyb20gdGhlIGJyb3dzZXIuIEluaXRpYWxpemVkIHdpdGggW1tPcGVuVmlkdS5pbml0TG9jYWxSZWNvcmRlcl1dIG1ldGhvZFxuICpcbiAqID4gV0FSTklORzogUGVyZm9ybWluZyBicm93c2VyIGxvY2FsIHJlY29yZGluZyBvZiAqKnJlbW90ZSBzdHJlYW1zKiogbWF5IGNhdXNlIHNvbWUgdHJvdWJsZXMuIEEgbG9uZyB3YWl0aW5nIHRpbWUgbWF5IGJlIHJlcXVpcmVkIGFmdGVyIGNhbGxpbmcgX0xvY2FsUmVjb3JkZXIuc3RvcCgpXyBpbiB0aGlzIGNhc2VcbiAqL1xuZXhwb3J0IGNsYXNzIExvY2FsUmVjb3JkZXIge1xuXG4gICAgc3RhdGU6IExvY2FsUmVjb3JkZXJTdGF0ZTtcblxuICAgIHByaXZhdGUgY29ubmVjdGlvbklkOiBzdHJpbmc7XG4gICAgcHJpdmF0ZSBtZWRpYVJlY29yZGVyOiBhbnk7XG4gICAgcHJpdmF0ZSBjaHVua3M6IGFueVtdID0gW107XG4gICAgcHJpdmF0ZSBibG9iOiBCbG9iO1xuICAgIHByaXZhdGUgY291bnQgPSAwO1xuICAgIHByaXZhdGUgaWQ6IHN0cmluZztcbiAgICBwcml2YXRlIHZpZGVvUHJldmlld1NyYzogc3RyaW5nO1xuICAgIHByaXZhdGUgaHRtbFBhcmVudEVsZW1lbnRJZDogc3RyaW5nO1xuICAgIHByaXZhdGUgdmlkZW9QcmV2aWV3OiBIVE1MVmlkZW9FbGVtZW50O1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHByaXZhdGUgc3RyZWFtOiBTdHJlYW0pIHtcbiAgICAgICAgdGhpcy5jb25uZWN0aW9uSWQgPSAoISF0aGlzLnN0cmVhbS5jb25uZWN0aW9uKSA/IHRoaXMuc3RyZWFtLmNvbm5lY3Rpb24uY29ubmVjdGlvbklkIDogJ2RlZmF1bHQtY29ubmVjdGlvbic7XG4gICAgICAgIHRoaXMuaWQgPSB0aGlzLnN0cmVhbS5zdHJlYW1JZCArICdfJyArIHRoaXMuY29ubmVjdGlvbklkICsgJ19sb2NhbHJlY29yZCc7XG4gICAgICAgIHRoaXMuc3RhdGUgPSBMb2NhbFJlY29yZGVyU3RhdGUuUkVBRFk7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBTdGFydHMgdGhlIHJlY29yZGluZyBvZiB0aGUgU3RyZWFtLiBbW3N0YXRlXV0gcHJvcGVydHkgbXVzdCBiZSBgUkVBRFlgLiBBZnRlciBtZXRob2Qgc3VjY2VlZHMgaXMgc2V0IHRvIGBSRUNPUkRJTkdgXG4gICAgICogQHJldHVybnMgQSBQcm9taXNlICh0byB3aGljaCB5b3UgY2FuIG9wdGlvbmFsbHkgc3Vic2NyaWJlIHRvKSB0aGF0IGlzIHJlc29sdmVkIGlmIHRoZSByZWNvcmRpbmcgc3VjY2Vzc2Z1bGx5IHN0YXJ0ZWQgYW5kIHJlamVjdGVkIHdpdGggYW4gRXJyb3Igb2JqZWN0IGlmIG5vdFxuICAgICAqL1xuICAgIHJlY29yZCgpOiBQcm9taXNlPGFueT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuXG4gICAgICAgICAgICB0cnkge1xuXG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBNZWRpYVJlY29yZGVyID09PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKCdNZWRpYVJlY29yZGVyIG5vdCBzdXBwb3J0ZWQgb24geW91ciBicm93c2VyLiBTZWUgY29tcGF0aWJpbGl0eSBpbiBodHRwczovL2Nhbml1c2UuY29tLyNzZWFyY2g9TWVkaWFSZWNvcmRlcicpO1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyAoRXJyb3IoJ01lZGlhUmVjb3JkZXIgbm90IHN1cHBvcnRlZCBvbiB5b3VyIGJyb3dzZXIuIFNlZSBjb21wYXRpYmlsaXR5IGluIGh0dHBzOi8vY2FuaXVzZS5jb20vI3NlYXJjaD1NZWRpYVJlY29yZGVyJykpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAodGhpcy5zdGF0ZSAhPT0gTG9jYWxSZWNvcmRlclN0YXRlLlJFQURZKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IChFcnJvcignXFwnTG9jYWxSZWNvcmQucmVjb3JkKClcXCcgbmVlZHMgXFwnTG9jYWxSZWNvcmQuc3RhdGVcXCcgdG8gYmUgXFwnUkVBRFlcXCcgKGN1cnJlbnQgdmFsdWU6IFxcJycgKyB0aGlzLnN0YXRlICsgJ1xcJykuIENhbGwgXFwnTG9jYWxSZWNvcmRlci5jbGVhbigpXFwnIG9yIGluaXQgYSBuZXcgTG9jYWxSZWNvcmRlciBiZWZvcmUnKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKFwiU3RhcnRpbmcgbG9jYWwgcmVjb3JkaW5nIG9mIHN0cmVhbSAnXCIgKyB0aGlzLnN0cmVhbS5zdHJlYW1JZCArIFwiJyBvZiBjb25uZWN0aW9uICdcIiArIHRoaXMuY29ubmVjdGlvbklkICsgXCInXCIpO1xuXG5cbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIE1lZGlhUmVjb3JkZXIuaXNUeXBlU3VwcG9ydGVkID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICAgICAgICAgIGxldCBvcHRpb25zO1xuICAgICAgICAgICAgICAgICAgICBpZiAoTWVkaWFSZWNvcmRlci5pc1R5cGVTdXBwb3J0ZWQoJ3ZpZGVvL3dlYm07Y29kZWNzPXZwOScpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBvcHRpb25zID0geyBtaW1lVHlwZTogJ3ZpZGVvL3dlYm07Y29kZWNzPXZwOScgfTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChNZWRpYVJlY29yZGVyLmlzVHlwZVN1cHBvcnRlZCgndmlkZW8vd2VibTtjb2RlY3M9aDI2NCcpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBvcHRpb25zID0geyBtaW1lVHlwZTogJ3ZpZGVvL3dlYm07Y29kZWNzPWgyNjQnIH07XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoTWVkaWFSZWNvcmRlci5pc1R5cGVTdXBwb3J0ZWQoJ3ZpZGVvL3dlYm07Y29kZWNzPXZwOCcpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBvcHRpb25zID0geyBtaW1lVHlwZTogJ3ZpZGVvL3dlYm07Y29kZWNzPXZwOCcgfTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmxvZygnVXNpbmcgbWltZVR5cGUgJyArIG9wdGlvbnMubWltZVR5cGUpO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLm1lZGlhUmVjb3JkZXIgPSBuZXcgTWVkaWFSZWNvcmRlcih0aGlzLnN0cmVhbS5nZXRNZWRpYVN0cmVhbSgpLCBvcHRpb25zKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLndhcm4oJ2lzVHlwZVN1cHBvcnRlZCBpcyBub3Qgc3VwcG9ydGVkLCB1c2luZyBkZWZhdWx0IGNvZGVjcyBmb3IgYnJvd3NlcicpO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLm1lZGlhUmVjb3JkZXIgPSBuZXcgTWVkaWFSZWNvcmRlcih0aGlzLnN0cmVhbS5nZXRNZWRpYVN0cmVhbSgpKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB0aGlzLm1lZGlhUmVjb3JkZXIuc3RhcnQoMTApO1xuXG4gICAgICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAgICAgICByZWplY3QoZXJyKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5tZWRpYVJlY29yZGVyLm9uZGF0YWF2YWlsYWJsZSA9IChlKSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5jaHVua3MucHVzaChlLmRhdGEpO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgdGhpcy5tZWRpYVJlY29yZGVyLm9uZXJyb3IgPSAoZSkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ01lZGlhUmVjb3JkZXIgZXJyb3I6ICcsIGUpO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgdGhpcy5tZWRpYVJlY29yZGVyLm9uc3RhcnQgPSAoKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5sb2coJ01lZGlhUmVjb3JkZXIgc3RhcnRlZCAoc3RhdGU9JyArIHRoaXMubWVkaWFSZWNvcmRlci5zdGF0ZSArICcpJyk7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICB0aGlzLm1lZGlhUmVjb3JkZXIub25zdG9wID0gKCkgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMub25TdG9wRGVmYXVsdCgpO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgdGhpcy5tZWRpYVJlY29yZGVyLm9ucGF1c2UgPSAoKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5sb2coJ01lZGlhUmVjb3JkZXIgcGF1c2VkIChzdGF0ZT0nICsgdGhpcy5tZWRpYVJlY29yZGVyLnN0YXRlICsgJyknKTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIHRoaXMubWVkaWFSZWNvcmRlci5vbnJlc3VtZSA9ICgpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmxvZygnTWVkaWFSZWNvcmRlciByZXN1bWVkIChzdGF0ZT0nICsgdGhpcy5tZWRpYVJlY29yZGVyLnN0YXRlICsgJyknKTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIHRoaXMubWVkaWFSZWNvcmRlci5vbndhcm5pbmcgPSAoZSkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKCdNZWRpYVJlY29yZGVyIHdhcm5pbmc6ICcgKyBlKTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIHRoaXMuc3RhdGUgPSBMb2NhbFJlY29yZGVyU3RhdGUuUkVDT1JESU5HO1xuICAgICAgICAgICAgcmVzb2x2ZSgpO1xuXG4gICAgICAgIH0pO1xuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogRW5kcyB0aGUgcmVjb3JkaW5nIG9mIHRoZSBTdHJlYW0uIFtbc3RhdGVdXSBwcm9wZXJ0eSBtdXN0IGJlIGBSRUNPUkRJTkdgIG9yIGBQQVVTRURgLiBBZnRlciBtZXRob2Qgc3VjY2VlZHMgaXMgc2V0IHRvIGBGSU5JU0hFRGBcbiAgICAgKiBAcmV0dXJucyBBIFByb21pc2UgKHRvIHdoaWNoIHlvdSBjYW4gb3B0aW9uYWxseSBzdWJzY3JpYmUgdG8pIHRoYXQgaXMgcmVzb2x2ZWQgaWYgdGhlIHJlY29yZGluZyBzdWNjZXNzZnVsbHkgc3RvcHBlZCBhbmQgcmVqZWN0ZWQgd2l0aCBhbiBFcnJvciBvYmplY3QgaWYgbm90XG4gICAgICovXG4gICAgc3RvcCgpOiBQcm9taXNlPGFueT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5zdGF0ZSA9PT0gTG9jYWxSZWNvcmRlclN0YXRlLlJFQURZIHx8IHRoaXMuc3RhdGUgPT09IExvY2FsUmVjb3JkZXJTdGF0ZS5GSU5JU0hFRCkge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyAoRXJyb3IoJ1xcJ0xvY2FsUmVjb3JkLnN0b3AoKVxcJyBuZWVkcyBcXCdMb2NhbFJlY29yZC5zdGF0ZVxcJyB0byBiZSBcXCdSRUNPUkRJTkdcXCcgb3IgXFwnUEFVU0VEXFwnIChjdXJyZW50IHZhbHVlOiBcXCcnICsgdGhpcy5zdGF0ZSArICdcXCcpLiBDYWxsIFxcJ0xvY2FsUmVjb3JkZXIuc3RhcnQoKVxcJyBiZWZvcmUnKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRoaXMubWVkaWFSZWNvcmRlci5vbnN0b3AgPSAoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMub25TdG9wRGVmYXVsdCgpO1xuICAgICAgICAgICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB0aGlzLm1lZGlhUmVjb3JkZXIuc3RvcCgpO1xuICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICAgIHJlamVjdChlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBQYXVzZXMgdGhlIHJlY29yZGluZyBvZiB0aGUgU3RyZWFtLiBbW3N0YXRlXV0gcHJvcGVydHkgbXVzdCBiZSBgUkVDT1JESU5HYC4gQWZ0ZXIgbWV0aG9kIHN1Y2NlZWRzIGlzIHNldCB0byBgUEFVU0VEYFxuICAgICAqIEByZXR1cm5zIEEgUHJvbWlzZSAodG8gd2hpY2ggeW91IGNhbiBvcHRpb25hbGx5IHN1YnNjcmliZSB0bykgdGhhdCBpcyByZXNvbHZlZCBpZiB0aGUgcmVjb3JkaW5nIHdhcyBzdWNjZXNzZnVsbHkgcGF1c2VkIGFuZCByZWplY3RlZCB3aXRoIGFuIEVycm9yIG9iamVjdCBpZiBub3RcbiAgICAgKi9cbiAgICBwYXVzZSgpOiBQcm9taXNlPGFueT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5zdGF0ZSAhPT0gTG9jYWxSZWNvcmRlclN0YXRlLlJFQ09SRElORykge1xuICAgICAgICAgICAgICAgICAgICByZWplY3QoRXJyb3IoJ1xcJ0xvY2FsUmVjb3JkLnBhdXNlKClcXCcgbmVlZHMgXFwnTG9jYWxSZWNvcmQuc3RhdGVcXCcgdG8gYmUgXFwnUkVDT1JESU5HXFwnIChjdXJyZW50IHZhbHVlOiBcXCcnICsgdGhpcy5zdGF0ZSArICdcXCcpLiBDYWxsIFxcJ0xvY2FsUmVjb3JkZXIuc3RhcnQoKVxcJyBvciBcXCdMb2NhbFJlY29yZGVyLnJlc3VtZSgpXFwnIGJlZm9yZScpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhpcy5tZWRpYVJlY29yZGVyLnBhdXNlKCk7XG4gICAgICAgICAgICAgICAgdGhpcy5zdGF0ZSA9IExvY2FsUmVjb3JkZXJTdGF0ZS5QQVVTRUQ7XG4gICAgICAgICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlc3VtZXMgdGhlIHJlY29yZGluZyBvZiB0aGUgU3RyZWFtLiBbW3N0YXRlXV0gcHJvcGVydHkgbXVzdCBiZSBgUEFVU0VEYC4gQWZ0ZXIgbWV0aG9kIHN1Y2NlZWRzIGlzIHNldCB0byBgUkVDT1JESU5HYFxuICAgICAqIEByZXR1cm5zIEEgUHJvbWlzZSAodG8gd2hpY2ggeW91IGNhbiBvcHRpb25hbGx5IHN1YnNjcmliZSB0bykgdGhhdCBpcyByZXNvbHZlZCBpZiB0aGUgcmVjb3JkaW5nIHdhcyBzdWNjZXNzZnVsbHkgcmVzdW1lZCBhbmQgcmVqZWN0ZWQgd2l0aCBhbiBFcnJvciBvYmplY3QgaWYgbm90XG4gICAgICovXG4gICAgcmVzdW1lKCk6IFByb21pc2U8YW55PiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLnN0YXRlICE9PSBMb2NhbFJlY29yZGVyU3RhdGUuUEFVU0VEKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IChFcnJvcignXFwnTG9jYWxSZWNvcmQucmVzdW1lKClcXCcgbmVlZHMgXFwnTG9jYWxSZWNvcmQuc3RhdGVcXCcgdG8gYmUgXFwnUEFVU0VEXFwnIChjdXJyZW50IHZhbHVlOiBcXCcnICsgdGhpcy5zdGF0ZSArICdcXCcpLiBDYWxsIFxcJ0xvY2FsUmVjb3JkZXIucGF1c2UoKVxcJyBiZWZvcmUnKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRoaXMubWVkaWFSZWNvcmRlci5yZXN1bWUoKTtcbiAgICAgICAgICAgICAgICB0aGlzLnN0YXRlID0gTG9jYWxSZWNvcmRlclN0YXRlLlJFQ09SRElORztcbiAgICAgICAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBQcmV2aWV3cyB0aGUgcmVjb3JkaW5nLCBhcHBlbmRpbmcgYSBuZXcgSFRNTFZpZGVvRWxlbWVudCB0byBlbGVtZW50IHdpdGggaWQgYHBhcmVudElkYC4gW1tzdGF0ZV1dIHByb3BlcnR5IG11c3QgYmUgYEZJTklTSEVEYFxuICAgICAqL1xuICAgIHByZXZpZXcocGFyZW50RWxlbWVudCk6IEhUTUxWaWRlb0VsZW1lbnQge1xuXG4gICAgICAgIGlmICh0aGlzLnN0YXRlICE9PSBMb2NhbFJlY29yZGVyU3RhdGUuRklOSVNIRUQpIHtcbiAgICAgICAgICAgIHRocm93IChFcnJvcignXFwnTG9jYWxSZWNvcmQucHJldmlldygpXFwnIG5lZWRzIFxcJ0xvY2FsUmVjb3JkLnN0YXRlXFwnIHRvIGJlIFxcJ0ZJTklTSEVEXFwnIChjdXJyZW50IHZhbHVlOiBcXCcnICsgdGhpcy5zdGF0ZSArICdcXCcpLiBDYWxsIFxcJ0xvY2FsUmVjb3JkZXIuc3RvcCgpXFwnIGJlZm9yZScpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMudmlkZW9QcmV2aWV3ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgndmlkZW8nKTtcblxuICAgICAgICB0aGlzLnZpZGVvUHJldmlldy5pZCA9IHRoaXMuaWQ7XG4gICAgICAgIHRoaXMudmlkZW9QcmV2aWV3LmF1dG9wbGF5ID0gdHJ1ZTtcblxuICAgICAgICBpZiAodHlwZW9mIHBhcmVudEVsZW1lbnQgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICB0aGlzLmh0bWxQYXJlbnRFbGVtZW50SWQgPSBwYXJlbnRFbGVtZW50O1xuXG4gICAgICAgICAgICBjb25zdCBwYXJlbnRFbGVtZW50RG9tID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQocGFyZW50RWxlbWVudCk7XG4gICAgICAgICAgICBpZiAocGFyZW50RWxlbWVudERvbSkge1xuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9QcmV2aWV3ID0gcGFyZW50RWxlbWVudERvbS5hcHBlbmRDaGlsZCh0aGlzLnZpZGVvUHJldmlldyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLmh0bWxQYXJlbnRFbGVtZW50SWQgPSBwYXJlbnRFbGVtZW50LmlkO1xuICAgICAgICAgICAgdGhpcy52aWRlb1ByZXZpZXcgPSBwYXJlbnRFbGVtZW50LmFwcGVuZENoaWxkKHRoaXMudmlkZW9QcmV2aWV3KTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMudmlkZW9QcmV2aWV3LnNyYyA9IHRoaXMudmlkZW9QcmV2aWV3U3JjO1xuXG4gICAgICAgIHJldHVybiB0aGlzLnZpZGVvUHJldmlldztcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIEdyYWNlZnVsbHkgc3RvcHMgYW5kIGNsZWFucyB0aGUgY3VycmVudCByZWNvcmRpbmcgKFdBUk5JTkc6IGl0IGlzIGNvbXBsZXRlbHkgZGlzbWlzc2VkKS4gU2V0cyBbW3N0YXRlXV0gdG8gYFJFQURZYCBzbyB0aGUgcmVjb3JkaW5nIGNhbiBzdGFydCBhZ2FpblxuICAgICAqL1xuICAgIGNsZWFuKCk6IHZvaWQge1xuICAgICAgICBjb25zdCBmID0gKCkgPT4ge1xuICAgICAgICAgICAgZGVsZXRlIHRoaXMuYmxvYjtcbiAgICAgICAgICAgIHRoaXMuY2h1bmtzID0gW107XG4gICAgICAgICAgICB0aGlzLmNvdW50ID0gMDtcbiAgICAgICAgICAgIGRlbGV0ZSB0aGlzLm1lZGlhUmVjb3JkZXI7XG4gICAgICAgICAgICB0aGlzLnN0YXRlID0gTG9jYWxSZWNvcmRlclN0YXRlLlJFQURZO1xuICAgICAgICB9O1xuICAgICAgICBpZiAodGhpcy5zdGF0ZSA9PT0gTG9jYWxSZWNvcmRlclN0YXRlLlJFQ09SRElORyB8fCB0aGlzLnN0YXRlID09PSBMb2NhbFJlY29yZGVyU3RhdGUuUEFVU0VEKSB7XG4gICAgICAgICAgICB0aGlzLnN0b3AoKS50aGVuKCgpID0+IGYoKSkuY2F0Y2goKCkgPT4gZigpKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGYoKTtcbiAgICAgICAgfVxuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogRG93bmxvYWRzIHRoZSByZWNvcmRlZCB2aWRlbyB0aHJvdWdoIHRoZSBicm93c2VyLiBbW3N0YXRlXV0gcHJvcGVydHkgbXVzdCBiZSBgRklOSVNIRURgXG4gICAgICovXG4gICAgZG93bmxvYWQoKTogdm9pZCB7XG4gICAgICAgIGlmICh0aGlzLnN0YXRlICE9PSBMb2NhbFJlY29yZGVyU3RhdGUuRklOSVNIRUQpIHtcbiAgICAgICAgICAgIHRocm93IChFcnJvcignXFwnTG9jYWxSZWNvcmQuZG93bmxvYWQoKVxcJyBuZWVkcyBcXCdMb2NhbFJlY29yZC5zdGF0ZVxcJyB0byBiZSBcXCdGSU5JU0hFRFxcJyAoY3VycmVudCB2YWx1ZTogXFwnJyArIHRoaXMuc3RhdGUgKyAnXFwnKS4gQ2FsbCBcXCdMb2NhbFJlY29yZGVyLnN0b3AoKVxcJyBiZWZvcmUnKSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjb25zdCBhOiBIVE1MQW5jaG9yRWxlbWVudCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2EnKTtcbiAgICAgICAgICAgIGEuc3R5bGUuZGlzcGxheSA9ICdub25lJztcbiAgICAgICAgICAgIGRvY3VtZW50LmJvZHkuYXBwZW5kQ2hpbGQoYSk7XG5cbiAgICAgICAgICAgIGNvbnN0IHVybCA9IHdpbmRvdy5VUkwuY3JlYXRlT2JqZWN0VVJMKHRoaXMuYmxvYik7XG4gICAgICAgICAgICBhLmhyZWYgPSB1cmw7XG4gICAgICAgICAgICBhLmRvd25sb2FkID0gdGhpcy5pZCArICcud2VibSc7XG4gICAgICAgICAgICBhLmNsaWNrKCk7XG4gICAgICAgICAgICB3aW5kb3cuVVJMLnJldm9rZU9iamVjdFVSTCh1cmwpO1xuXG4gICAgICAgICAgICBkb2N1bWVudC5ib2R5LnJlbW92ZUNoaWxkKGEpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0cyB0aGUgcmF3IEJsb2IgZmlsZS4gTWV0aG9kcyBwcmV2aWV3LCBkb3dubG9hZCwgdXBsb2FkQXNCaW5hcnkgYW5kIHVwbG9hZEFzTXVsdGlwYXJ0ZmlsZSB1c2UgdGhpcyBzYW1lIGZpbGUgdG8gcGVyZm9ybSB0aGVpciBzcGVjaWZpYyBhY3Rpb25zLiBbW3N0YXRlXV0gcHJvcGVydHkgbXVzdCBiZSBgRklOSVNIRURgXG4gICAgICovXG4gICAgZ2V0QmxvYigpOiBCbG9iIHtcbiAgICAgICAgaWYgKHRoaXMuc3RhdGUgIT09IExvY2FsUmVjb3JkZXJTdGF0ZS5GSU5JU0hFRCkge1xuICAgICAgICAgICAgdGhyb3cgKEVycm9yKCdDYWxsIFxcJ0xvY2FsUmVjb3JkLnN0b3AoKVxcJyBiZWZvcmUgZ2V0dGluZyBCbG9iIGZpbGUnKSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5ibG9iO1xuICAgICAgICB9XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBVcGxvYWRzIHRoZSByZWNvcmRlZCB2aWRlbyBhcyBhIGJpbmFyeSBmaWxlIHBlcmZvcm1pbmcgYW4gSFRUUC9QT1NUIG9wZXJhdGlvbiB0byBVUkwgYGVuZHBvaW50YC4gW1tzdGF0ZV1dIHByb3BlcnR5IG11c3QgYmUgYEZJTklTSEVEYC4gT3B0aW9uYWwgSFRUUCBoZWFkZXJzIGNhbiBiZSBwYXNzZWQgYXMgc2Vjb25kIHBhcmFtZXRlci4gRm9yIGV4YW1wbGU6XG4gICAgICogYGBgXG4gICAgICogdmFyIGhlYWRlcnMgPSB7XG4gICAgICogIFwiQ29va2llXCI6IFwiJFZlcnNpb249MTsgU2tpbj1uZXc7XCIsXG4gICAgICogIFwiQXV0aG9yaXphdGlvblwiOlwiQmFzaWMgUVd4aFpHcGJqcHVJSE5sY3RaUT09XCJcbiAgICAgKiB9XG4gICAgICogYGBgXG4gICAgICogQHJldHVybnMgQSBQcm9taXNlICh0byB3aGljaCB5b3UgY2FuIG9wdGlvbmFsbHkgc3Vic2NyaWJlIHRvKSB0aGF0IGlzIHJlc29sdmVkIHdpdGggdGhlIGBodHRwLnJlc3BvbnNlVGV4dGAgZnJvbSBzZXJ2ZXIgaWYgdGhlIG9wZXJhdGlvbiB3YXMgc3VjY2Vzc2Z1bCBhbmQgcmVqZWN0ZWQgd2l0aCB0aGUgZmFpbGVkIGBodHRwLnN0YXR1c2AgaWYgbm90XG4gICAgICovXG4gICAgdXBsb2FkQXNCaW5hcnkoZW5kcG9pbnQ6IHN0cmluZywgaGVhZGVycz86IGFueSk6IFByb21pc2U8YW55PiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICBpZiAodGhpcy5zdGF0ZSAhPT0gTG9jYWxSZWNvcmRlclN0YXRlLkZJTklTSEVEKSB7XG4gICAgICAgICAgICAgICAgcmVqZWN0KEVycm9yKCdcXCdMb2NhbFJlY29yZC51cGxvYWRBc0JpbmFyeSgpXFwnIG5lZWRzIFxcJ0xvY2FsUmVjb3JkLnN0YXRlXFwnIHRvIGJlIFxcJ0ZJTklTSEVEXFwnIChjdXJyZW50IHZhbHVlOiBcXCcnICsgdGhpcy5zdGF0ZSArICdcXCcpLiBDYWxsIFxcJ0xvY2FsUmVjb3JkZXIuc3RvcCgpXFwnIGJlZm9yZScpKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY29uc3QgaHR0cCA9IG5ldyBYTUxIdHRwUmVxdWVzdCgpO1xuICAgICAgICAgICAgICAgIGh0dHAub3BlbignUE9TVCcsIGVuZHBvaW50LCB0cnVlKTtcblxuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgaGVhZGVycyA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgICAgICAgICAgICAgZm9yIChjb25zdCBrZXkgb2YgT2JqZWN0LmtleXMoaGVhZGVycykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGh0dHAuc2V0UmVxdWVzdEhlYWRlcihrZXksIGhlYWRlcnNba2V5XSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBodHRwLm9ucmVhZHlzdGF0ZWNoYW5nZSA9ICgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGh0dHAucmVhZHlTdGF0ZSA9PT0gNCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGh0dHAuc3RhdHVzLnRvU3RyaW5nKCkuY2hhckF0KDApID09PSAnMicpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBTdWNjZXNzIHJlc3BvbnNlIGZyb20gc2VydmVyIChIVFRQIHN0YXR1cyBzdGFuZGFyZDogMlhYIGlzIHN1Y2Nlc3MpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZShodHRwLnJlc3BvbnNlVGV4dCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChodHRwLnN0YXR1cyk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIGh0dHAuc2VuZCh0aGlzLmJsb2IpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFVwbG9hZHMgdGhlIHJlY29yZGVkIHZpZGVvIGFzIGEgbXVsdGlwYXJ0IGZpbGUgcGVyZm9ybWluZyBhbiBIVFRQL1BPU1Qgb3BlcmF0aW9uIHRvIFVSTCBgZW5kcG9pbnRgLiBbW3N0YXRlXV0gcHJvcGVydHkgbXVzdCBiZSBgRklOSVNIRURgLiBPcHRpb25hbCBIVFRQIGhlYWRlcnMgY2FuIGJlIHBhc3NlZCBhcyBzZWNvbmQgcGFyYW1ldGVyLiBGb3IgZXhhbXBsZTpcbiAgICAgKiBgYGBcbiAgICAgKiB2YXIgaGVhZGVycyA9IHtcbiAgICAgKiAgXCJDb29raWVcIjogXCIkVmVyc2lvbj0xOyBTa2luPW5ldztcIixcbiAgICAgKiAgXCJBdXRob3JpemF0aW9uXCI6XCJCYXNpYyBRV3hoWkdwYmpwdUlITmxjdFpRPT1cIlxuICAgICAqIH1cbiAgICAgKiBgYGBcbiAgICAgKiBAcmV0dXJucyBBIFByb21pc2UgKHRvIHdoaWNoIHlvdSBjYW4gb3B0aW9uYWxseSBzdWJzY3JpYmUgdG8pIHRoYXQgaXMgcmVzb2x2ZWQgd2l0aCB0aGUgYGh0dHAucmVzcG9uc2VUZXh0YCBmcm9tIHNlcnZlciBpZiB0aGUgb3BlcmF0aW9uIHdhcyBzdWNjZXNzZnVsIGFuZCByZWplY3RlZCB3aXRoIHRoZSBmYWlsZWQgYGh0dHAuc3RhdHVzYCBpZiBub3Q6XG4gICAgICovXG4gICAgdXBsb2FkQXNNdWx0aXBhcnRmaWxlKGVuZHBvaW50OiBzdHJpbmcsIGhlYWRlcnM/OiBhbnkpOiBQcm9taXNlPGFueT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgaWYgKHRoaXMuc3RhdGUgIT09IExvY2FsUmVjb3JkZXJTdGF0ZS5GSU5JU0hFRCkge1xuICAgICAgICAgICAgICAgIHJlamVjdChFcnJvcignXFwnTG9jYWxSZWNvcmQudXBsb2FkQXNNdWx0aXBhcnRmaWxlKClcXCcgbmVlZHMgXFwnTG9jYWxSZWNvcmQuc3RhdGVcXCcgdG8gYmUgXFwnRklOSVNIRURcXCcgKGN1cnJlbnQgdmFsdWU6IFxcJycgKyB0aGlzLnN0YXRlICsgJ1xcJykuIENhbGwgXFwnTG9jYWxSZWNvcmRlci5zdG9wKClcXCcgYmVmb3JlJykpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBjb25zdCBodHRwID0gbmV3IFhNTEh0dHBSZXF1ZXN0KCk7XG4gICAgICAgICAgICAgICAgaHR0cC5vcGVuKCdQT1NUJywgZW5kcG9pbnQsIHRydWUpO1xuXG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBoZWFkZXJzID09PSAnb2JqZWN0Jykge1xuICAgICAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IGtleSBvZiBPYmplY3Qua2V5cyhoZWFkZXJzKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaHR0cC5zZXRSZXF1ZXN0SGVhZGVyKGtleSwgaGVhZGVyc1trZXldKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGNvbnN0IHNlbmRhYmxlID0gbmV3IEZvcm1EYXRhKCk7XG4gICAgICAgICAgICAgICAgc2VuZGFibGUuYXBwZW5kKCdmaWxlJywgdGhpcy5ibG9iLCB0aGlzLmlkICsgJy53ZWJtJyk7XG5cbiAgICAgICAgICAgICAgICBodHRwLm9ucmVhZHlzdGF0ZWNoYW5nZSA9ICgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGh0dHAucmVhZHlTdGF0ZSA9PT0gNCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGh0dHAuc3RhdHVzLnRvU3RyaW5nKCkuY2hhckF0KDApID09PSAnMicpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBTdWNjZXNzIHJlc3BvbnNlIGZyb20gc2VydmVyIChIVFRQIHN0YXR1cyBzdGFuZGFyZDogMlhYIGlzIHN1Y2Nlc3MpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZShodHRwLnJlc3BvbnNlVGV4dCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChodHRwLnN0YXR1cyk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICAgICAgaHR0cC5zZW5kKHNlbmRhYmxlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG5cbiAgICAvKiBQcml2YXRlIG1ldGhvZHMgKi9cblxuICAgIHByaXZhdGUgb25TdG9wRGVmYXVsdCgpOiB2b2lkIHtcbiAgICAgICAgY29uc29sZS5sb2coJ01lZGlhUmVjb3JkZXIgc3RvcHBlZCAgKHN0YXRlPScgKyB0aGlzLm1lZGlhUmVjb3JkZXIuc3RhdGUgKyAnKScpO1xuXG4gICAgICAgIHRoaXMuYmxvYiA9IG5ldyBCbG9iKHRoaXMuY2h1bmtzLCB7IHR5cGU6ICd2aWRlby93ZWJtJyB9KTtcbiAgICAgICAgdGhpcy5jaHVua3MgPSBbXTtcblxuICAgICAgICB0aGlzLnZpZGVvUHJldmlld1NyYyA9IHdpbmRvdy5VUkwuY3JlYXRlT2JqZWN0VVJMKHRoaXMuYmxvYik7XG5cbiAgICAgICAgdGhpcy5zdGF0ZSA9IExvY2FsUmVjb3JkZXJTdGF0ZS5GSU5JU0hFRDtcbiAgICB9XG5cbn1cbiIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTctMjAxOCBPcGVuVmlkdSAoaHR0cHM6Ly9vcGVudmlkdS5pby8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuaW1wb3J0IHsgTG9jYWxSZWNvcmRlciB9IGZyb20gJy4vTG9jYWxSZWNvcmRlcic7XG5pbXBvcnQgeyBQdWJsaXNoZXIgfSBmcm9tICcuL1B1Ymxpc2hlcic7XG5pbXBvcnQgeyBTZXNzaW9uIH0gZnJvbSAnLi9TZXNzaW9uJztcbmltcG9ydCB7IFN0cmVhbSB9IGZyb20gJy4vU3RyZWFtJztcbmltcG9ydCB7IFN0cmVhbVByb3BlcnR5Q2hhbmdlZEV2ZW50IH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvU3RyZWFtUHJvcGVydHlDaGFuZ2VkRXZlbnQnO1xuaW1wb3J0IHsgRGV2aWNlIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9JbnRlcmZhY2VzL1B1YmxpYy9EZXZpY2UnO1xuaW1wb3J0IHsgT3BlblZpZHVBZHZhbmNlZENvbmZpZ3VyYXRpb24gfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHVibGljL09wZW5WaWR1QWR2YW5jZWRDb25maWd1cmF0aW9uJztcbmltcG9ydCB7IFB1Ymxpc2hlclByb3BlcnRpZXMgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHVibGljL1B1Ymxpc2hlclByb3BlcnRpZXMnO1xuaW1wb3J0IHsgT3BlblZpZHVFcnJvciwgT3BlblZpZHVFcnJvck5hbWUgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0VudW1zL09wZW5WaWR1RXJyb3InO1xuaW1wb3J0IHsgVmlkZW9JbnNlcnRNb2RlIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FbnVtcy9WaWRlb0luc2VydE1vZGUnO1xuXG5pbXBvcnQgKiBhcyBzY3JlZW5TaGFyaW5nQXV0byBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL1NjcmVlblNoYXJpbmcvU2NyZWVuLUNhcHR1cmluZy1BdXRvJztcbmltcG9ydCAqIGFzIHNjcmVlblNoYXJpbmcgZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9TY3JlZW5TaGFyaW5nL1NjcmVlbi1DYXB0dXJpbmcnO1xuXG5pbXBvcnQgUnBjQnVpbGRlciA9IHJlcXVpcmUoJy4uL09wZW5WaWR1SW50ZXJuYWwvS3VyZW50b1V0aWxzL2t1cmVudG8tanNvbnJwYycpO1xuaW1wb3J0IHBsYXRmb3JtID0gcmVxdWlyZSgncGxhdGZvcm0nKTtcblxuXG4vKipcbiAqIEVudHJ5cG9pbnQgb2YgT3BlblZpZHUgQnJvd3NlciBsaWJyYXJ5LlxuICogVXNlIGl0IHRvIGluaXRpYWxpemUgb2JqZWN0cyBvZiB0eXBlIFtbU2Vzc2lvbl1dLCBbW1B1Ymxpc2hlcl1dIGFuZCBbW0xvY2FsUmVjb3JkZXJdXVxuICovXG5leHBvcnQgY2xhc3MgT3BlblZpZHUge1xuXG4gIHByaXZhdGUganNvblJwY0NsaWVudDogYW55O1xuXG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICBzZXNzaW9uOiBTZXNzaW9uO1xuICAvKipcbiAgICogQGhpZGRlblxuICAgKi9cbiAgcHVibGlzaGVyczogUHVibGlzaGVyW10gPSBbXTtcbiAgLyoqXG4gICAqIEBoaWRkZW5cbiAgICovXG4gIHdzVXJpOiBzdHJpbmc7XG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICBzZWNyZXQgPSAnJztcbiAgLyoqXG4gICAqIEBoaWRkZW5cbiAgICovXG4gIHJlY29yZGVyID0gZmFsc2U7XG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICBpY2VTZXJ2ZXJzOiBSVENJY2VTZXJ2ZXJbXTtcbiAgLyoqXG4gICAqIEBoaWRkZW5cbiAgICovXG4gIHJvbGU6IHN0cmluZztcbiAgLyoqXG4gICAqIEBoaWRkZW5cbiAgICovXG4gIGFkdmFuY2VkQ29uZmlndXJhdGlvbjogT3BlblZpZHVBZHZhbmNlZENvbmZpZ3VyYXRpb24gPSB7fTtcblxuICBjb25zdHJ1Y3RvcigpIHtcbiAgICBjb25zb2xlLmluZm8oXCInT3BlblZpZHUnIGluaXRpYWxpemVkXCIpO1xuXG4gICAgaWYgKHBsYXRmb3JtLm5hbWUhIS50b0xvd2VyQ2FzZSgpLmluZGV4T2YoJ21vYmlsZScpICE9PSAtMSkge1xuICAgICAgLy8gTGlzdGVuIHRvIG9yaWVudGF0aW9uY2hhbmdlIG9ubHkgb24gbW9iaWxlIGJyb3dzZXJzXG4gICAgICAoPGFueT53aW5kb3cpLm9ub3JpZW50YXRpb25jaGFuZ2UgPSAoKSA9PiB7XG4gICAgICAgIHRoaXMucHVibGlzaGVycy5mb3JFYWNoKHB1Ymxpc2hlciA9PiB7XG4gICAgICAgICAgaWYgKCEhcHVibGlzaGVyLnN0cmVhbSAmJiAhIXB1Ymxpc2hlci5zdHJlYW0uaGFzVmlkZW8gJiYgISFwdWJsaXNoZXIuc3RyZWFtLnN0cmVhbU1hbmFnZXIudmlkZW9zWzBdKSB7XG5cbiAgICAgICAgICAgIGxldCBhdHRlbXB0cyA9IDA7XG5cbiAgICAgICAgICAgIGNvbnN0IG9sZFdpZHRoID0gcHVibGlzaGVyLnN0cmVhbS52aWRlb0RpbWVuc2lvbnMud2lkdGg7XG4gICAgICAgICAgICBjb25zdCBvbGRIZWlnaHQgPSBwdWJsaXNoZXIuc3RyZWFtLnZpZGVvRGltZW5zaW9ucy5oZWlnaHQ7XG4gICAgICAgICAgICAvLyBOZXcgcmVzb2x1dGlvbiBnb3QgZnJvbSBkaWZmZXJlbnQgcGxhY2VzIGZvciBDaHJvbWUgYW5kIEZpcmVmb3guIENocm9tZSBuZWVkcyBhIHZpZGVvV2lkdGggYW5kIHZpZGVvSGVpZ2h0IG9mIGEgdmlkZW9FbGVtZW50LlxuICAgICAgICAgICAgLy8gRmlyZWZveCBuZWVkcyBnZXRTZXR0aW5ncyBmcm9tIHRoZSB2aWRlb1RyYWNrXG4gICAgICAgICAgICBsZXQgZmlyZWZveFNldHRpbmdzID0gcHVibGlzaGVyLnN0cmVhbS5nZXRNZWRpYVN0cmVhbSgpLmdldFZpZGVvVHJhY2tzKClbMF0uZ2V0U2V0dGluZ3MoKTtcbiAgICAgICAgICAgIGxldCBuZXdXaWR0aCA9IChwbGF0Zm9ybS5uYW1lISEudG9Mb3dlckNhc2UoKS5pbmRleE9mKCdmaXJlZm94JykgIT09IC0xKSA/IGZpcmVmb3hTZXR0aW5ncy53aWR0aCA6IHB1Ymxpc2hlci52aWRlb1JlZmVyZW5jZS52aWRlb1dpZHRoO1xuICAgICAgICAgICAgbGV0IG5ld0hlaWdodCA9IChwbGF0Zm9ybS5uYW1lISEudG9Mb3dlckNhc2UoKS5pbmRleE9mKCdmaXJlZm94JykgIT09IC0xKSA/IGZpcmVmb3hTZXR0aW5ncy5oZWlnaHQgOiBwdWJsaXNoZXIudmlkZW9SZWZlcmVuY2UudmlkZW9IZWlnaHQ7XG5cbiAgICAgICAgICAgIGNvbnN0IHJlcGVhdFVudGlsQ2hhbmdlID0gc2V0SW50ZXJ2YWwoKCkgPT4ge1xuICAgICAgICAgICAgICBmaXJlZm94U2V0dGluZ3MgPSBwdWJsaXNoZXIuc3RyZWFtLmdldE1lZGlhU3RyZWFtKCkuZ2V0VmlkZW9UcmFja3MoKVswXS5nZXRTZXR0aW5ncygpO1xuICAgICAgICAgICAgICBuZXdXaWR0aCA9IChwbGF0Zm9ybS5uYW1lISEudG9Mb3dlckNhc2UoKS5pbmRleE9mKCdmaXJlZm94JykgIT09IC0xKSA/IGZpcmVmb3hTZXR0aW5ncy53aWR0aCA6IHB1Ymxpc2hlci52aWRlb1JlZmVyZW5jZS52aWRlb1dpZHRoO1xuICAgICAgICAgICAgICBuZXdIZWlnaHQgPSAocGxhdGZvcm0ubmFtZSEhLnRvTG93ZXJDYXNlKCkuaW5kZXhPZignZmlyZWZveCcpICE9PSAtMSkgPyBmaXJlZm94U2V0dGluZ3MuaGVpZ2h0IDogcHVibGlzaGVyLnZpZGVvUmVmZXJlbmNlLnZpZGVvSGVpZ2h0O1xuICAgICAgICAgICAgICBzZW5kU3RyZWFtUHJvcGVydHlDaGFuZ2VkRXZlbnQob2xkV2lkdGgsIG9sZEhlaWdodCwgbmV3V2lkdGgsIG5ld0hlaWdodCk7XG4gICAgICAgICAgICB9LCAxMDApO1xuXG4gICAgICAgICAgICBjb25zdCBzZW5kU3RyZWFtUHJvcGVydHlDaGFuZ2VkRXZlbnQgPSAob2xkV2lkdGgsIG9sZEhlaWdodCwgbmV3V2lkdGgsIG5ld0hlaWdodCkgPT4ge1xuICAgICAgICAgICAgICBhdHRlbXB0cysrO1xuICAgICAgICAgICAgICBpZiAoYXR0ZW1wdHMgPiA0KSB7XG4gICAgICAgICAgICAgICAgY2xlYXJUaW1lb3V0KHJlcGVhdFVudGlsQ2hhbmdlKTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICBpZiAobmV3V2lkdGggIT09IG9sZFdpZHRoIHx8IG5ld0hlaWdodCAhPT0gb2xkSGVpZ2h0KSB7XG4gICAgICAgICAgICAgICAgcHVibGlzaGVyLnN0cmVhbS52aWRlb0RpbWVuc2lvbnMgPSB7XG4gICAgICAgICAgICAgICAgICB3aWR0aDogbmV3V2lkdGggfHwgMCxcbiAgICAgICAgICAgICAgICAgIGhlaWdodDogbmV3SGVpZ2h0IHx8IDBcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIHRoaXMuc2VuZFJlcXVlc3QoXG4gICAgICAgICAgICAgICAgICAnc3RyZWFtUHJvcGVydHlDaGFuZ2VkJyxcbiAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgc3RyZWFtSWQ6IHB1Ymxpc2hlci5zdHJlYW0uc3RyZWFtSWQsXG4gICAgICAgICAgICAgICAgICAgIHByb3BlcnR5OiAndmlkZW9EaW1lbnNpb25zJyxcbiAgICAgICAgICAgICAgICAgICAgbmV3VmFsdWU6IEpTT04uc3RyaW5naWZ5KHB1Ymxpc2hlci5zdHJlYW0udmlkZW9EaW1lbnNpb25zKSxcbiAgICAgICAgICAgICAgICAgICAgcmVhc29uOiAnZGV2aWNlUm90YXRlZCdcbiAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAoZXJyb3IsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoXCJFcnJvciBzZW5kaW5nICdzdHJlYW1Qcm9wZXJ0eUNoYW5nZWQnIGV2ZW50XCIsIGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICB0aGlzLnNlc3Npb24uZW1pdEV2ZW50KCdzdHJlYW1Qcm9wZXJ0eUNoYW5nZWQnLCBbbmV3IFN0cmVhbVByb3BlcnR5Q2hhbmdlZEV2ZW50KHRoaXMuc2Vzc2lvbiwgcHVibGlzaGVyLnN0cmVhbSwgJ3ZpZGVvRGltZW5zaW9ucycsIHB1Ymxpc2hlci5zdHJlYW0udmlkZW9EaW1lbnNpb25zLCB7IHdpZHRoOiBvbGRXaWR0aCwgaGVpZ2h0OiBvbGRIZWlnaHQgfSwgJ2RldmljZVJvdGF0ZWQnKV0pO1xuICAgICAgICAgICAgICAgICAgICAgIHB1Ymxpc2hlci5lbWl0RXZlbnQoJ3N0cmVhbVByb3BlcnR5Q2hhbmdlZCcsIFtuZXcgU3RyZWFtUHJvcGVydHlDaGFuZ2VkRXZlbnQocHVibGlzaGVyLCBwdWJsaXNoZXIuc3RyZWFtLCAndmlkZW9EaW1lbnNpb25zJywgcHVibGlzaGVyLnN0cmVhbS52aWRlb0RpbWVuc2lvbnMsIHsgd2lkdGg6IG9sZFdpZHRoLCBoZWlnaHQ6IG9sZEhlaWdodCB9LCAnZGV2aWNlUm90YXRlZCcpXSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIGNsZWFyVGltZW91dChyZXBlYXRVbnRpbENoYW5nZSk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH07XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgIH07XG4gICAgfVxuICB9XG5cblxuICAvKipcbiAgICogUmV0dXJucyBuZXcgc2Vzc2lvblxuICAgKi9cbiAgaW5pdFNlc3Npb24oKTogU2Vzc2lvbiB7XG4gICAgdGhpcy5zZXNzaW9uID0gbmV3IFNlc3Npb24odGhpcyk7XG4gICAgcmV0dXJuIHRoaXMuc2Vzc2lvbjtcbiAgfVxuXG5cbiAgaW5pdFB1Ymxpc2hlcih0YXJnZXRFbGVtZW50OiBzdHJpbmcgfCBIVE1MRWxlbWVudCk6IFB1Ymxpc2hlcjtcbiAgaW5pdFB1Ymxpc2hlcih0YXJnZXRFbGVtZW50OiBzdHJpbmcgfCBIVE1MRWxlbWVudCwgcHJvcGVydGllczogUHVibGlzaGVyUHJvcGVydGllcyk6IFB1Ymxpc2hlcjtcbiAgaW5pdFB1Ymxpc2hlcih0YXJnZXRFbGVtZW50OiBzdHJpbmcgfCBIVE1MRWxlbWVudCwgY29tcGxldGlvbkhhbmRsZXI6IChlcnJvcjogRXJyb3IgfCB1bmRlZmluZWQpID0+IHZvaWQpOiBQdWJsaXNoZXI7XG4gIGluaXRQdWJsaXNoZXIodGFyZ2V0RWxlbWVudDogc3RyaW5nIHwgSFRNTEVsZW1lbnQsIHByb3BlcnRpZXM6IFB1Ymxpc2hlclByb3BlcnRpZXMsIGNvbXBsZXRpb25IYW5kbGVyOiAoZXJyb3I6IEVycm9yIHwgdW5kZWZpbmVkKSA9PiB2b2lkKTogUHVibGlzaGVyO1xuXG4gIC8qKlxuICAgKiBSZXR1cm5zIGEgbmV3IHB1Ymxpc2hlclxuICAgKlxuICAgKiAjIyMjIEV2ZW50cyBkaXNwYXRjaGVkXG4gICAqXG4gICAqIFRoZSBbW1B1Ymxpc2hlcl1dIG9iamVjdCB3aWxsIGRpc3BhdGNoIGFuIGBhY2Nlc3NEaWFsb2dPcGVuZWRgIGV2ZW50LCBvbmx5IGlmIHRoZSBwb3AtdXAgc2hvd24gYnkgdGhlIGJyb3dzZXIgdG8gcmVxdWVzdCBwZXJtaXNzaW9ucyBmb3IgdGhlIGNhbWVyYSBpcyBvcGVuZWQuIFlvdSBjYW4gdXNlIHRoaXMgZXZlbnQgdG8gYWxlcnQgdGhlIHVzZXIgYWJvdXQgZ3JhbnRpbmcgcGVybWlzc2lvbnNcbiAgICogZm9yIHlvdXIgd2Vic2l0ZS4gQW4gYGFjY2Vzc0RpYWxvZ0Nsb3NlZGAgZXZlbnQgd2lsbCBhbHNvIGJlIGRpc3BhdGNoZWQgYWZ0ZXIgdXNlciBjbGlja3Mgb24gXCJBbGxvd1wiIG9yIFwiQmxvY2tcIiBpbiB0aGUgcG9wLXVwLlxuICAgKlxuICAgKiBUaGUgW1tQdWJsaXNoZXJdXSBvYmplY3Qgd2lsbCBkaXNwYXRjaCBhbiBgYWNjZXNzQWxsb3dlZGAgb3IgYGFjY2Vzc0RlbmllZGAgZXZlbnQgb25jZSBpdCBoYXMgYmVlbiBncmFudGVkIGFjY2VzcyB0byB0aGUgcmVxdWVzdGVkIGlucHV0IGRldmljZXMgb3Igbm90LlxuICAgKlxuICAgKiBUaGUgW1tQdWJsaXNoZXJdXSBvYmplY3Qgd2lsbCBkaXNwYXRjaCBhIGB2aWRlb0VsZW1lbnRDcmVhdGVkYCBldmVudCBvbmNlIGEgSFRNTCB2aWRlbyBlbGVtZW50IGhhcyBiZWVuIGFkZGVkIHRvIERPTSAob25seSBpZiB5b3VcbiAgICogW2xldCBPcGVuVmlkdSB0YWtlIGNhcmUgb2YgdGhlIHZpZGVvIHBsYXllcnNdKC9kb2NzL2hvdy1kby1pL21hbmFnZS12aWRlb3MvI2xldC1vcGVudmlkdS10YWtlLWNhcmUtb2YtdGhlLXZpZGVvLXBsYXllcnMpKS4gU2VlIFtbVmlkZW9FbGVtZW50RXZlbnRdXSB0byBsZWFybiBtb3JlLlxuICAgKlxuICAgKiBUaGUgW1tQdWJsaXNoZXJdXSBvYmplY3Qgd2lsbCBkaXNwYXRjaCBhIGBzdHJlYW1QbGF5aW5nYCBldmVudCBvbmNlIHRoZSBsb2NhbCBzdHJlYW1zIHN0YXJ0cyBwbGF5aW5nLiBTZWUgW1tTdHJlYW1NYW5hZ2VyRXZlbnRdXSB0byBsZWFybiBtb3JlLlxuICAgKlxuICAgKiBAcGFyYW0gdGFyZ2V0RWxlbWVudCAgSFRNTCBET00gZWxlbWVudCAob3IgaXRzIGBpZGAgYXR0cmlidXRlKSBpbiB3aGljaCB0aGUgdmlkZW8gZWxlbWVudCBvZiB0aGUgUHVibGlzaGVyIHdpbGwgYmUgaW5zZXJ0ZWQgKHNlZSBbW1B1Ymxpc2hlclByb3BlcnRpZXMuaW5zZXJ0TW9kZV1dKS4gSWYgKm51bGwqIG9yICp1bmRlZmluZWQqIG5vIGRlZmF1bHQgdmlkZW8gd2lsbCBiZSBjcmVhdGVkIGZvciB0aGlzIFB1Ymxpc2hlci5cbiAgICogWW91IGNhbiBhbHdheXMgY2FsbCBtZXRob2QgW1tQdWJsaXNoZXIuYWRkVmlkZW9FbGVtZW50XV0gb3IgW1tQdWJsaXNoZXIuY3JlYXRlVmlkZW9FbGVtZW50XV0gdG8gbWFuYWdlIHRoZSB2aWRlbyBlbGVtZW50cyBvbiB5b3VyIG93biAoc2VlIFtNYW5hZ2UgdmlkZW8gcGxheWVyc10oL2RvY3MvaG93LWRvLWkvbWFuYWdlLXZpZGVvcykgc2VjdGlvbilcbiAgICogQHBhcmFtIGNvbXBsZXRpb25IYW5kbGVyIGBlcnJvcmAgcGFyYW1ldGVyIGlzIG51bGwgaWYgYGluaXRQdWJsaXNoZXJgIHN1Y2NlZWRzLCBhbmQgaXMgZGVmaW5lZCBpZiBpdCBmYWlscy5cbiAgICogICAgICAgICAgICAgICAgICAgICAgICAgIGBjb21wbGV0aW9uSGFuZGxlcmAgZnVuY3Rpb24gaXMgY2FsbGVkIGJlZm9yZSB0aGUgUHVibGlzaGVyIGRpc3BhdGNoZXMgYW4gYGFjY2Vzc0FsbG93ZWRgIG9yIGFuIGBhY2Nlc3NEZW5pZWRgIGV2ZW50XG4gICAqL1xuICBpbml0UHVibGlzaGVyKHRhcmdldEVsZW1lbnQ6IHN0cmluZyB8IEhUTUxFbGVtZW50LCBwYXJhbTI/LCBwYXJhbTM/KTogUHVibGlzaGVyIHtcblxuICAgIGxldCBwcm9wZXJ0aWVzOiBQdWJsaXNoZXJQcm9wZXJ0aWVzO1xuXG4gICAgaWYgKCEhcGFyYW0yICYmICh0eXBlb2YgcGFyYW0yICE9PSAnZnVuY3Rpb24nKSkge1xuXG4gICAgICAvLyBNYXRjaGVzICdpbml0UHVibGlzaGVyKHRhcmdldEVsZW1lbnQsIHByb3BlcnRpZXMpJyBvciAnaW5pdFB1Ymxpc2hlcih0YXJnZXRFbGVtZW50LCBwcm9wZXJ0aWVzLCBjb21wbGV0aW9uSGFuZGxlciknXG5cbiAgICAgIHByb3BlcnRpZXMgPSAoPFB1Ymxpc2hlclByb3BlcnRpZXM+cGFyYW0yKTtcblxuICAgICAgcHJvcGVydGllcyA9IHtcbiAgICAgICAgYXVkaW9Tb3VyY2U6ICh0eXBlb2YgcHJvcGVydGllcy5hdWRpb1NvdXJjZSAhPT0gJ3VuZGVmaW5lZCcpID8gcHJvcGVydGllcy5hdWRpb1NvdXJjZSA6IHVuZGVmaW5lZCxcbiAgICAgICAgZnJhbWVSYXRlOiB0aGlzLmlzTWVkaWFTdHJlYW1UcmFjayhwcm9wZXJ0aWVzLnZpZGVvU291cmNlKSA/IHVuZGVmaW5lZCA6ICgodHlwZW9mIHByb3BlcnRpZXMuZnJhbWVSYXRlICE9PSAndW5kZWZpbmVkJykgPyBwcm9wZXJ0aWVzLmZyYW1lUmF0ZSA6IHVuZGVmaW5lZCksXG4gICAgICAgIGluc2VydE1vZGU6ICh0eXBlb2YgcHJvcGVydGllcy5pbnNlcnRNb2RlICE9PSAndW5kZWZpbmVkJykgPyAoKHR5cGVvZiBwcm9wZXJ0aWVzLmluc2VydE1vZGUgPT09ICdzdHJpbmcnKSA/IFZpZGVvSW5zZXJ0TW9kZVtwcm9wZXJ0aWVzLmluc2VydE1vZGVdIDogcHJvcGVydGllcy5pbnNlcnRNb2RlKSA6IFZpZGVvSW5zZXJ0TW9kZS5BUFBFTkQsXG4gICAgICAgIG1pcnJvcjogKHR5cGVvZiBwcm9wZXJ0aWVzLm1pcnJvciAhPT0gJ3VuZGVmaW5lZCcpID8gcHJvcGVydGllcy5taXJyb3IgOiB0cnVlLFxuICAgICAgICBwdWJsaXNoQXVkaW86ICh0eXBlb2YgcHJvcGVydGllcy5wdWJsaXNoQXVkaW8gIT09ICd1bmRlZmluZWQnKSA/IHByb3BlcnRpZXMucHVibGlzaEF1ZGlvIDogdHJ1ZSxcbiAgICAgICAgcHVibGlzaFZpZGVvOiAodHlwZW9mIHByb3BlcnRpZXMucHVibGlzaFZpZGVvICE9PSAndW5kZWZpbmVkJykgPyBwcm9wZXJ0aWVzLnB1Ymxpc2hWaWRlbyA6IHRydWUsXG4gICAgICAgIHJlc29sdXRpb246IHRoaXMuaXNNZWRpYVN0cmVhbVRyYWNrKHByb3BlcnRpZXMudmlkZW9Tb3VyY2UpID8gdW5kZWZpbmVkIDogKCh0eXBlb2YgcHJvcGVydGllcy5yZXNvbHV0aW9uICE9PSAndW5kZWZpbmVkJykgPyBwcm9wZXJ0aWVzLnJlc29sdXRpb24gOiAnNjQweDQ4MCcpLFxuICAgICAgICB2aWRlb1NvdXJjZTogKHR5cGVvZiBwcm9wZXJ0aWVzLnZpZGVvU291cmNlICE9PSAndW5kZWZpbmVkJykgPyBwcm9wZXJ0aWVzLnZpZGVvU291cmNlIDogdW5kZWZpbmVkXG4gICAgICB9O1xuICAgIH0gZWxzZSB7XG5cbiAgICAgIC8vIE1hdGNoZXMgJ2luaXRQdWJsaXNoZXIodGFyZ2V0RWxlbWVudCknIG9yICdpbml0UHVibGlzaGVyKHRhcmdldEVsZW1lbnQsIGNvbXBsZXRpb25IYW5kbGVyKSdcblxuICAgICAgcHJvcGVydGllcyA9IHtcbiAgICAgICAgaW5zZXJ0TW9kZTogVmlkZW9JbnNlcnRNb2RlLkFQUEVORCxcbiAgICAgICAgbWlycm9yOiB0cnVlLFxuICAgICAgICBwdWJsaXNoQXVkaW86IHRydWUsXG4gICAgICAgIHB1Ymxpc2hWaWRlbzogdHJ1ZSxcbiAgICAgICAgcmVzb2x1dGlvbjogJzY0MHg0ODAnXG4gICAgICB9O1xuICAgIH1cblxuICAgIGNvbnN0IHB1Ymxpc2hlcjogUHVibGlzaGVyID0gbmV3IFB1Ymxpc2hlcih0YXJnZXRFbGVtZW50LCBwcm9wZXJ0aWVzLCB0aGlzKTtcblxuICAgIGxldCBjb21wbGV0aW9uSGFuZGxlcjogKGVycm9yOiBFcnJvciB8IHVuZGVmaW5lZCkgPT4gdm9pZDtcbiAgICBpZiAoISFwYXJhbTIgJiYgKHR5cGVvZiBwYXJhbTIgPT09ICdmdW5jdGlvbicpKSB7XG4gICAgICBjb21wbGV0aW9uSGFuZGxlciA9IHBhcmFtMjtcbiAgICB9IGVsc2UgaWYgKCEhcGFyYW0zKSB7XG4gICAgICBjb21wbGV0aW9uSGFuZGxlciA9IHBhcmFtMztcbiAgICB9XG5cbiAgICBwdWJsaXNoZXIuaW5pdGlhbGl6ZSgpXG4gICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgIGlmIChjb21wbGV0aW9uSGFuZGxlciAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgY29tcGxldGlvbkhhbmRsZXIodW5kZWZpbmVkKTtcbiAgICAgICAgfVxuICAgICAgICBwdWJsaXNoZXIuZW1pdEV2ZW50KCdhY2Nlc3NBbGxvd2VkJywgW10pO1xuICAgICAgfSkuY2F0Y2goKGVycm9yKSA9PiB7XG4gICAgICAgIGlmIChjb21wbGV0aW9uSGFuZGxlciAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgY29tcGxldGlvbkhhbmRsZXIoZXJyb3IpO1xuICAgICAgICB9XG4gICAgICAgIHB1Ymxpc2hlci5lbWl0RXZlbnQoJ2FjY2Vzc0RlbmllZCcsIFtdKTtcbiAgICAgIH0pO1xuXG4gICAgdGhpcy5wdWJsaXNoZXJzLnB1c2gocHVibGlzaGVyKTtcbiAgICByZXR1cm4gcHVibGlzaGVyO1xuICB9XG5cblxuICAvKipcbiAgICogUHJvbWlzaWZpZWQgdmVyc2lvbiBvZiBbW09wZW5WaWR1LmluaXRQdWJsaXNoZXJdXVxuICAgKlxuICAgKiA+IFdBUk5JTkc6IGV2ZW50cyBgYWNjZXNzRGlhbG9nT3BlbmVkYCBhbmQgYGFjY2Vzc0RpYWxvZ0Nsb3NlZGAgd2lsbCBub3QgYmUgZGlzcGF0Y2hlZCBpZiB1c2luZyB0aGlzIG1ldGhvZCBpbnN0ZWFkIG9mIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dXG4gICAqL1xuICBpbml0UHVibGlzaGVyQXN5bmModGFyZ2V0RWxlbWVudDogc3RyaW5nIHwgSFRNTEVsZW1lbnQpOiBQcm9taXNlPFB1Ymxpc2hlcj47XG4gIGluaXRQdWJsaXNoZXJBc3luYyh0YXJnZXRFbGVtZW50OiBzdHJpbmcgfCBIVE1MRWxlbWVudCwgcHJvcGVydGllczogUHVibGlzaGVyUHJvcGVydGllcyk6IFByb21pc2U8UHVibGlzaGVyPjtcblxuICBpbml0UHVibGlzaGVyQXN5bmModGFyZ2V0RWxlbWVudDogc3RyaW5nIHwgSFRNTEVsZW1lbnQsIHByb3BlcnRpZXM/OiBQdWJsaXNoZXJQcm9wZXJ0aWVzKTogUHJvbWlzZTxQdWJsaXNoZXI+IHtcbiAgICByZXR1cm4gbmV3IFByb21pc2U8UHVibGlzaGVyPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG5cbiAgICAgIGxldCBwdWJsaXNoZXI6IFB1Ymxpc2hlcjtcblxuICAgICAgY29uc3QgY2FsbGJhY2sgPSAoZXJyb3I6IEVycm9yKSA9PiB7XG4gICAgICAgIGlmICghIWVycm9yKSB7XG4gICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICByZXNvbHZlKHB1Ymxpc2hlcik7XG4gICAgICAgIH1cbiAgICAgIH07XG5cbiAgICAgIGlmICghIXByb3BlcnRpZXMpIHtcbiAgICAgICAgcHVibGlzaGVyID0gdGhpcy5pbml0UHVibGlzaGVyKHRhcmdldEVsZW1lbnQsIHByb3BlcnRpZXMsIGNhbGxiYWNrKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHB1Ymxpc2hlciA9IHRoaXMuaW5pdFB1Ymxpc2hlcih0YXJnZXRFbGVtZW50LCBjYWxsYmFjayk7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIGEgbmV3IGxvY2FsIHJlY29yZGVyIGZvciByZWNvcmRpbmcgc3RyZWFtcyBzdHJhaWdodCBhd2F5IGZyb20gdGhlIGJyb3dzZXJcbiAgICogQHBhcmFtIHN0cmVhbSAgU3RyZWFtIHRvIHJlY29yZFxuICAgKi9cbiAgaW5pdExvY2FsUmVjb3JkZXIoc3RyZWFtOiBTdHJlYW0pOiBMb2NhbFJlY29yZGVyIHtcbiAgICByZXR1cm4gbmV3IExvY2FsUmVjb3JkZXIoc3RyZWFtKTtcbiAgfVxuXG5cbiAgLyoqXG4gICAqIENoZWNrcyBpZiB0aGUgYnJvd3NlciBzdXBwb3J0cyBPcGVuVmlkdVxuICAgKiBAcmV0dXJucyAxIGlmIHRoZSBicm93c2VyIHN1cHBvcnRzIE9wZW5WaWR1LCAwIG90aGVyd2lzZVxuICAgKi9cbiAgY2hlY2tTeXN0ZW1SZXF1aXJlbWVudHMoKTogbnVtYmVyIHtcbiAgICBjb25zdCBicm93c2VyID0gcGxhdGZvcm0ubmFtZTtcbiAgICBjb25zdCB2ZXJzaW9uID0gcGxhdGZvcm0udmVyc2lvbjtcblxuICAgIGlmICgoYnJvd3NlciAhPT0gJ0Nocm9tZScpICYmIChicm93c2VyICE9PSAnQ2hyb21lIE1vYmlsZScpICYmXG4gICAgICAoYnJvd3NlciAhPT0gJ0ZpcmVmb3gnKSAmJiAoYnJvd3NlciAhPT0gJ0ZpcmVmb3ggTW9iaWxlJykgJiYgKGJyb3dzZXIgIT09ICdGaXJlZm94IGZvciBpT1MnKSAmJlxuICAgICAgKGJyb3dzZXIgIT09ICdPcGVyYScpICYmIChicm93c2VyICE9PSAnT3BlcmEgTW9iaWxlJykgJiZcbiAgICAgIChicm93c2VyICE9PSAnU2FmYXJpJykpIHtcbiAgICAgIHJldHVybiAwO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gMTtcbiAgICB9XG4gIH1cblxuXG4gIC8qKlxuICAgKiBDb2xsZWN0cyBpbmZvcm1hdGlvbiBhYm91dCB0aGUgbWVkaWEgaW5wdXQgZGV2aWNlcyBhdmFpbGFibGUgb24gdGhlIHN5c3RlbS4gWW91IGNhbiBwYXNzIHByb3BlcnR5IGBkZXZpY2VJZGAgb2YgYSBbW0RldmljZV1dIG9iamVjdCBhcyB2YWx1ZSBvZiBgYXVkaW9Tb3VyY2VgIG9yIGB2aWRlb1NvdXJjZWAgcHJvcGVydGllcyBpbiBbW2luaXRQdWJsaXNoZXJdXSBtZXRob2RcbiAgICovXG4gIGdldERldmljZXMoKTogUHJvbWlzZTxEZXZpY2VbXT4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZTxEZXZpY2VbXT4oKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgbmF2aWdhdG9yLm1lZGlhRGV2aWNlcy5lbnVtZXJhdGVEZXZpY2VzKCkudGhlbigoZGV2aWNlSW5mb3MpID0+IHtcbiAgICAgICAgY29uc3QgZGV2aWNlczogRGV2aWNlW10gPSBbXTtcbiAgICAgICAgZGV2aWNlSW5mb3MuZm9yRWFjaChkZXZpY2VJbmZvID0+IHtcbiAgICAgICAgICBpZiAoZGV2aWNlSW5mby5raW5kID09PSAnYXVkaW9pbnB1dCcgfHwgZGV2aWNlSW5mby5raW5kID09PSAndmlkZW9pbnB1dCcpIHtcbiAgICAgICAgICAgIGRldmljZXMucHVzaCh7XG4gICAgICAgICAgICAgIGtpbmQ6IGRldmljZUluZm8ua2luZCxcbiAgICAgICAgICAgICAgZGV2aWNlSWQ6IGRldmljZUluZm8uZGV2aWNlSWQsXG4gICAgICAgICAgICAgIGxhYmVsOiBkZXZpY2VJbmZvLmxhYmVsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICByZXNvbHZlKGRldmljZXMpO1xuICAgICAgfSkuY2F0Y2goKGVycm9yKSA9PiB7XG4gICAgICAgIGNvbnNvbGUuZXJyb3IoJ0Vycm9yIGdldHRpbmcgZGV2aWNlcycsIGVycm9yKTtcbiAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9XG5cblxuICAvKipcbiAgICogR2V0IGEgTWVkaWFTdHJlYW0gb2JqZWN0IHRoYXQgeW91IGNhbiBjdXN0b21pemUgYmVmb3JlIGNhbGxpbmcgW1tpbml0UHVibGlzaGVyXV0gKHBhc3MgX01lZGlhU3RyZWFtVHJhY2tfIHByb3BlcnR5IG9mIHRoZSBfTWVkaWFTdHJlYW1fIHZhbHVlIHJlc29sdmVkIGJ5IHRoZSBQcm9taXNlIGFzIGBhdWRpb1NvdXJjZWAgb3IgYHZpZGVvU291cmNlYCBwcm9wZXJ0aWVzIGluIFtbaW5pdFB1Ymxpc2hlcl1dKVxuICAgKlxuICAgKiBQYXJhbWV0ZXIgYG9wdGlvbnNgIGlzIHRoZSBzYW1lIGFzIGluIFtbaW5pdFB1Ymxpc2hlcl1dIHNlY29uZCBwYXJhbWV0ZXIgKG9mIHR5cGUgW1tQdWJsaXNoZXJQcm9wZXJ0aWVzXV0pLCBidXQgb25seSB0aGUgZm9sbG93aW5nIHByb3BlcnRpZXMgd2lsbCBiZSBhcHBsaWVkOiBgYXVkaW9Tb3VyY2VgLCBgdmlkZW9Tb3VyY2VgLCBgZnJhbWVSYXRlYCwgYHJlc29sdXRpb25gXG4gICAqXG4gICAqIFRvIGN1c3RvbWl6ZSB0aGUgUHVibGlzaGVyJ3MgdmlkZW8sIHRoZSBBUEkgZm9yIEhUTUxDYW52YXNFbGVtZW50IGlzIHZlcnkgdXNlZnVsLiBGb3IgZXhhbXBsZSwgdG8gZ2V0IGEgYmxhY2stYW5kLXdoaXRlIHZpZGVvIGF0IDEwIGZwcyBhbmQgSEQgcmVzb2x1dGlvbiB3aXRoIG5vIHNvdW5kOlxuICAgKiBgYGBcbiAgICogdmFyIE9WID0gbmV3IE9wZW5WaWR1KCk7XG4gICAqIHZhciBGUkFNRV9SQVRFID0gMTA7XG4gICAqXG4gICAqIE9WLmdldFVzZXJNZWRpYSh7XG4gICAqICAgIGF1ZGlvU291cmNlOiBmYWxzZTtcbiAgICogICAgdmlkZW9Tb3VyY2U6IHVuZGVmaW5lZCxcbiAgICogICAgcmVzb2x1dGlvbjogJzEyODB4NzIwJyxcbiAgICogICAgZnJhbWVSYXRlOiBGUkFNRV9SQVRFXG4gICAqIH0pXG4gICAqIC50aGVuKG1lZGlhU3RyZWFtID0+IHtcbiAgICpcbiAgICogICAgdmFyIHZpZGVvVHJhY2sgPSBtZWRpYVN0cmVhbS5nZXRWaWRlb1RyYWNrcygpWzBdO1xuICAgKiAgICB2YXIgdmlkZW8gPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCd2aWRlbycpO1xuICAgKiAgICB2aWRlby5zcmNPYmplY3QgPSBuZXcgTWVkaWFTdHJlYW0oW3ZpZGVvVHJhY2tdKTtcbiAgICpcbiAgICogICAgdmFyIGNhbnZhcyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2NhbnZhcycpO1xuICAgKiAgICB2YXIgY3R4ID0gY2FudmFzLmdldENvbnRleHQoJzJkJyk7XG4gICAqICAgIGN0eC5maWx0ZXIgPSAnZ3JheXNjYWxlKDEwMCUpJztcbiAgICpcbiAgICogICAgdmlkZW8uYWRkRXZlbnRMaXN0ZW5lcigncGxheScsICgpID0+IHtcbiAgICogICAgICB2YXIgbG9vcCA9ICgpID0+IHtcbiAgICogICAgICAgIGlmICghdmlkZW8ucGF1c2VkICYmICF2aWRlby5lbmRlZCkge1xuICAgKiAgICAgICAgICBjdHguZHJhd0ltYWdlKHZpZGVvLCAwLCAwLCAzMDAsIDE3MCk7XG4gICAqICAgICAgICAgIHNldFRpbWVvdXQobG9vcCwgMTAwMC8gRlJBTUVfUkFURSk7IC8vIERyYXdpbmcgYXQgMTAgZnBzXG4gICAqICAgICAgICB9XG4gICAqICAgICAgfTtcbiAgICogICAgICBsb29wKCk7XG4gICAqICAgIH0pO1xuICAgKiAgICB2aWRlby5wbGF5KCk7XG4gICAqXG4gICAqICAgIHZhciBncmF5VmlkZW9UcmFjayA9IGNhbnZhcy5jYXB0dXJlU3RyZWFtKEZSQU1FX1JBVEUpLmdldFZpZGVvVHJhY2tzKClbMF07XG4gICAqICAgIHZhciBwdWJsaXNoZXIgPSB0aGlzLk9WLmluaXRQdWJsaXNoZXIoXG4gICAqICAgICAgbXlIdG1sVGFyZ2V0LFxuICAgKiAgICAgIHtcbiAgICogICAgICAgIGF1ZGlvU291cmNlOiBmYWxzZSxcbiAgICogICAgICAgIHZpZGVvU291cmNlOiBncmF5VmlkZW9UcmFja1xuICAgKiAgICAgIH0pO1xuICAgKiB9KTtcbiAgICogYGBgXG4gICAqL1xuICBnZXRVc2VyTWVkaWEob3B0aW9uczogUHVibGlzaGVyUHJvcGVydGllcyk6IFByb21pc2U8TWVkaWFTdHJlYW0+IHtcbiAgICByZXR1cm4gbmV3IFByb21pc2U8TWVkaWFTdHJlYW0+KChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIHRoaXMuZ2VuZXJhdGVNZWRpYUNvbnN0cmFpbnRzKG9wdGlvbnMpXG4gICAgICAgIC50aGVuKGNvbnN0cmFpbnRzID0+IHtcbiAgICAgICAgICBuYXZpZ2F0b3IubWVkaWFEZXZpY2VzLmdldFVzZXJNZWRpYShjb25zdHJhaW50cylcbiAgICAgICAgICAgIC50aGVuKG1lZGlhU3RyZWFtID0+IHtcbiAgICAgICAgICAgICAgcmVzb2x2ZShtZWRpYVN0cmVhbSk7XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICAgICAgbGV0IGVycm9yTmFtZTogT3BlblZpZHVFcnJvck5hbWU7XG4gICAgICAgICAgICAgIGNvbnN0IGVycm9yTWVzc2FnZSA9IGVycm9yLnRvU3RyaW5nKCk7XG4gICAgICAgICAgICAgIGlmICghKG9wdGlvbnMudmlkZW9Tb3VyY2UgPT09ICdzY3JlZW4nKSkge1xuICAgICAgICAgICAgICAgIGVycm9yTmFtZSA9IE9wZW5WaWR1RXJyb3JOYW1lLkRFVklDRV9BQ0NFU1NfREVOSUVEO1xuICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGVycm9yTmFtZSA9IE9wZW5WaWR1RXJyb3JOYW1lLlNDUkVFTl9DQVBUVVJFX0RFTklFRDtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICByZWplY3QobmV3IE9wZW5WaWR1RXJyb3IoZXJyb3JOYW1lLCBlcnJvck1lc3NhZ2UpKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KVxuICAgICAgICAuY2F0Y2goKGVycm9yOiBPcGVuVmlkdUVycm9yKSA9PiB7XG4gICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgfSk7XG4gICAgfSk7XG4gIH1cblxuXG4gIC8qIHRzbGludDpkaXNhYmxlOm5vLWVtcHR5ICovXG4gIC8qKlxuICAgKiBEaXNhYmxlIGFsbCBsb2dnaW5nIGV4Y2VwdCBlcnJvciBsZXZlbFxuICAgKi9cbiAgZW5hYmxlUHJvZE1vZGUoKTogdm9pZCB7XG4gICAgY29uc29sZS5sb2cgPSAoKSA9PiB7IH07XG4gICAgY29uc29sZS5kZWJ1ZyA9ICgpID0+IHsgfTtcbiAgICBjb25zb2xlLmluZm8gPSAoKSA9PiB7IH07XG4gICAgY29uc29sZS53YXJuID0gKCkgPT4geyB9O1xuICB9XG4gIC8qIHRzbGludDplbmFibGU6bm8tZW1wdHkgKi9cblxuXG4gIC8qKlxuICAgKiBTZXQgT3BlblZpZHUgYWR2YW5jZWQgY29uZmlndXJhdGlvbiBvcHRpb25zLiBDdXJyZW50bHkgYGNvbmZpZ3VyYXRpb25gIGlzIGFuIG9iamVjdCB3aXRoIHRoZSBmb2xsb3dpbmcgb3B0aW9uYWwgcHJvcGVydGllcyAoc2VlIFtbT3BlblZpZHVBZHZhbmNlZENvbmZpZ3VyYXRpb25dXSBmb3IgbW9yZSBkZXRhaWxzKTpcbiAgICogLSBgaWNlU2VydmVyc2A6IHNldCBjdXN0b20gU1RVTi9UVVJOIHNlcnZlcnMgdG8gYmUgdXNlZCBieSBPcGVuVmlkdSBCcm93c2VyXG4gICAqIC0gYHNjcmVlblNoYXJlQ2hyb21lRXh0ZW5zaW9uYDogdXJsIHRvIGEgY3VzdG9tIHNjcmVlbiBzaGFyZSBleHRlbnNpb24gZm9yIENocm9tZSB0byBiZSB1c2VkIGluc3RlYWQgb2YgdGhlIGRlZmF1bHQgb25lLCBiYXNlZCBvbiBvdXJzIFtodHRwczovL2dpdGh1Yi5jb20vT3BlblZpZHUvb3BlbnZpZHUtc2NyZWVuLXNoYXJpbmctY2hyb21lLWV4dGVuc2lvbl0oaHR0cHM6Ly9naXRodWIuY29tL09wZW5WaWR1L29wZW52aWR1LXNjcmVlbi1zaGFyaW5nLWNocm9tZS1leHRlbnNpb24pXG4gICAqIC0gYHB1Ymxpc2hlclNwZWFraW5nRXZlbnRzT3B0aW9uc2A6IGN1c3RvbSBjb25maWd1cmF0aW9uIGZvciB0aGUgW1tQdWJsaXNoZXJTcGVha2luZ0V2ZW50XV0gZmVhdHVyZVxuICAgKi9cbiAgc2V0QWR2YW5jZWRDb25maWd1cmF0aW9uKGNvbmZpZ3VyYXRpb246IE9wZW5WaWR1QWR2YW5jZWRDb25maWd1cmF0aW9uKTogdm9pZCB7XG4gICAgdGhpcy5hZHZhbmNlZENvbmZpZ3VyYXRpb24gPSBjb25maWd1cmF0aW9uO1xuICB9XG5cblxuICAvKiBIaWRkZW4gbWV0aG9kcyAqL1xuXG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICBnZW5lcmF0ZU1lZGlhQ29uc3RyYWludHMocHVibGlzaGVyUHJvcGVydGllczogUHVibGlzaGVyUHJvcGVydGllcyk6IFByb21pc2U8TWVkaWFTdHJlYW1Db25zdHJhaW50cz4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZTxNZWRpYVN0cmVhbUNvbnN0cmFpbnRzPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICBsZXQgYXVkaW8sIHZpZGVvO1xuXG4gICAgICBpZiAocHVibGlzaGVyUHJvcGVydGllcy5hdWRpb1NvdXJjZSA9PT0gbnVsbCB8fCBwdWJsaXNoZXJQcm9wZXJ0aWVzLmF1ZGlvU291cmNlID09PSBmYWxzZSkge1xuICAgICAgICBhdWRpbyA9IGZhbHNlO1xuICAgICAgfSBlbHNlIGlmIChwdWJsaXNoZXJQcm9wZXJ0aWVzLmF1ZGlvU291cmNlID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgYXVkaW8gPSB0cnVlO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgYXVkaW8gPSBwdWJsaXNoZXJQcm9wZXJ0aWVzLmF1ZGlvU291cmNlO1xuICAgICAgfVxuXG4gICAgICBpZiAocHVibGlzaGVyUHJvcGVydGllcy52aWRlb1NvdXJjZSA9PT0gbnVsbCB8fCBwdWJsaXNoZXJQcm9wZXJ0aWVzLnZpZGVvU291cmNlID09PSBmYWxzZSkge1xuICAgICAgICB2aWRlbyA9IGZhbHNlO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdmlkZW8gPSB7XG4gICAgICAgICAgaGVpZ2h0OiB7XG4gICAgICAgICAgICBpZGVhbDogNDgwXG4gICAgICAgICAgfSxcbiAgICAgICAgICB3aWR0aDoge1xuICAgICAgICAgICAgaWRlYWw6IDY0MFxuICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgbWVkaWFDb25zdHJhaW50czogTWVkaWFTdHJlYW1Db25zdHJhaW50cyA9IHtcbiAgICAgICAgYXVkaW8sXG4gICAgICAgIHZpZGVvXG4gICAgICB9O1xuXG4gICAgICBpZiAodHlwZW9mIG1lZGlhQ29uc3RyYWludHMuYXVkaW8gPT09ICdzdHJpbmcnKSB7XG4gICAgICAgIG1lZGlhQ29uc3RyYWludHMuYXVkaW8gPSB7IGRldmljZUlkOiB7IGV4YWN0OiBtZWRpYUNvbnN0cmFpbnRzLmF1ZGlvIH0gfTtcbiAgICAgIH1cblxuICAgICAgaWYgKG1lZGlhQ29uc3RyYWludHMudmlkZW8pIHtcblxuICAgICAgICBpZiAoISFwdWJsaXNoZXJQcm9wZXJ0aWVzLnJlc29sdXRpb24pIHtcbiAgICAgICAgICBjb25zdCB3aWR0aEFuZEhlaWdodCA9IHB1Ymxpc2hlclByb3BlcnRpZXMucmVzb2x1dGlvbi50b0xvd2VyQ2FzZSgpLnNwbGl0KCd4Jyk7XG4gICAgICAgICAgY29uc3Qgd2lkdGggPSBOdW1iZXIod2lkdGhBbmRIZWlnaHRbMF0pO1xuICAgICAgICAgIGNvbnN0IGhlaWdodCA9IE51bWJlcih3aWR0aEFuZEhlaWdodFsxXSk7XG4gICAgICAgICAgKG1lZGlhQ29uc3RyYWludHMudmlkZW8gYXMgYW55KS53aWR0aC5pZGVhbCA9IHdpZHRoO1xuICAgICAgICAgIChtZWRpYUNvbnN0cmFpbnRzLnZpZGVvIGFzIGFueSkuaGVpZ2h0LmlkZWFsID0gaGVpZ2h0O1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCEhcHVibGlzaGVyUHJvcGVydGllcy5mcmFtZVJhdGUpIHtcbiAgICAgICAgICAobWVkaWFDb25zdHJhaW50cy52aWRlbyBhcyBhbnkpLmZyYW1lUmF0ZSA9IHsgaWRlYWw6IHB1Ymxpc2hlclByb3BlcnRpZXMuZnJhbWVSYXRlIH07XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoISFwdWJsaXNoZXJQcm9wZXJ0aWVzLnZpZGVvU291cmNlICYmIHR5cGVvZiBwdWJsaXNoZXJQcm9wZXJ0aWVzLnZpZGVvU291cmNlID09PSAnc3RyaW5nJykge1xuXG4gICAgICAgICAgaWYgKHB1Ymxpc2hlclByb3BlcnRpZXMudmlkZW9Tb3VyY2UgPT09ICdzY3JlZW4nKSB7XG5cbiAgICAgICAgICAgIGlmIChwbGF0Zm9ybS5uYW1lICE9PSAnQ2hyb21lJyAmJiBwbGF0Zm9ybS5uYW1lIS5pbmRleE9mKCdGaXJlZm94JykgPT09IC0xKSB7XG4gICAgICAgICAgICAgIGNvbnN0IGVycm9yID0gbmV3IE9wZW5WaWR1RXJyb3IoT3BlblZpZHVFcnJvck5hbWUuU0NSRUVOX1NIQVJJTkdfTk9UX1NVUFBPUlRFRCwgJ1lvdSBjYW4gb25seSBzY3JlZW4gc2hhcmUgaW4gZGVza3RvcCBDaHJvbWUgYW5kIEZpcmVmb3guIERldGVjdGVkIGJyb3dzZXI6ICcgKyBwbGF0Zm9ybS5uYW1lKTtcbiAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihlcnJvcik7XG4gICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICB9IGVsc2Uge1xuXG4gICAgICAgICAgICAgIGlmICghIXRoaXMuYWR2YW5jZWRDb25maWd1cmF0aW9uLnNjcmVlblNoYXJlQ2hyb21lRXh0ZW5zaW9uICYmICEocGxhdGZvcm0ubmFtZSEuaW5kZXhPZignRmlyZWZveCcpICE9PSAtMSkpIHtcblxuICAgICAgICAgICAgICAgIC8vIEN1c3RvbSBzY3JlZW4gc2hhcmluZyBleHRlbnNpb24gZm9yIENocm9tZVxuXG4gICAgICAgICAgICAgICAgc2NyZWVuU2hhcmluZy5nZXRTY3JlZW5Db25zdHJhaW50cygoZXJyb3IsIHNjcmVlbkNvbnN0cmFpbnRzKSA9PiB7XG4gICAgICAgICAgICAgICAgICBpZiAoISFlcnJvciB8fCAhIXNjcmVlbkNvbnN0cmFpbnRzLm1hbmRhdG9yeSAmJiBzY3JlZW5Db25zdHJhaW50cy5tYW5kYXRvcnkuY2hyb21lTWVkaWFTb3VyY2UgPT09ICdzY3JlZW4nKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnJvciA9PT0gJ3Blcm1pc3Npb24tZGVuaWVkJyB8fCBlcnJvciA9PT0gJ1Blcm1pc3Npb25EZW5pZWRFcnJvcicpIHtcbiAgICAgICAgICAgICAgICAgICAgICBjb25zdCBlcnJvciA9IG5ldyBPcGVuVmlkdUVycm9yKE9wZW5WaWR1RXJyb3JOYW1lLlNDUkVFTl9DQVBUVVJFX0RFTklFRCwgJ1lvdSBtdXN0IGFsbG93IGFjY2VzcyB0byBvbmUgd2luZG93IG9mIHlvdXIgZGVza3RvcCcpO1xuICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgY29uc3QgZXh0ZW5zaW9uSWQgPSB0aGlzLmFkdmFuY2VkQ29uZmlndXJhdGlvbi5zY3JlZW5TaGFyZUNocm9tZUV4dGVuc2lvbiEuc3BsaXQoJy8nKS5wb3AoKSEhLnRyaW0oKTtcbiAgICAgICAgICAgICAgICAgICAgICBzY3JlZW5TaGFyaW5nLmdldENocm9tZUV4dGVuc2lvblN0YXR1cyhleHRlbnNpb25JZCwgKHN0YXR1cykgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHN0YXR1cyA9PT0gJ2luc3RhbGxlZC1kaXNhYmxlZCcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZXJyb3IgPSBuZXcgT3BlblZpZHVFcnJvcihPcGVuVmlkdUVycm9yTmFtZS5TQ1JFRU5fRVhURU5TSU9OX0RJU0FCTEVELCAnWW91IG11c3QgZW5hYmxlIHRoZSBzY3JlZW4gZXh0ZW5zaW9uJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHN0YXR1cyA9PT0gJ25vdC1pbnN0YWxsZWQnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGVycm9yID0gbmV3IE9wZW5WaWR1RXJyb3IoT3BlblZpZHVFcnJvck5hbWUuU0NSRUVOX0VYVEVOU0lPTl9OT1RfSU5TVEFMTEVELCAoPHN0cmluZz50aGlzLmFkdmFuY2VkQ29uZmlndXJhdGlvbi5zY3JlZW5TaGFyZUNocm9tZUV4dGVuc2lvbikpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgbWVkaWFDb25zdHJhaW50cy52aWRlbyA9IHNjcmVlbkNvbnN0cmFpbnRzO1xuICAgICAgICAgICAgICAgICAgICByZXNvbHZlKG1lZGlhQ29uc3RyYWludHMpO1xuICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICB9IGVsc2Uge1xuXG4gICAgICAgICAgICAgICAgLy8gRGVmYXVsdCBzY3JlZW4gc2hhcmluZyBleHRlbnNpb24gZm9yIENocm9tZVxuXG4gICAgICAgICAgICAgICAgc2NyZWVuU2hhcmluZ0F1dG8uZ2V0U2NyZWVuSWQoKGVycm9yLCBzb3VyY2VJZCwgc2NyZWVuQ29uc3RyYWludHMpID0+IHtcbiAgICAgICAgICAgICAgICAgIGlmICghIWVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnJvciA9PT0gJ25vdC1pbnN0YWxsZWQnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgY29uc3QgZXh0ZW5zaW9uVXJsID0gISF0aGlzLmFkdmFuY2VkQ29uZmlndXJhdGlvbi5zY3JlZW5TaGFyZUNocm9tZUV4dGVuc2lvbiA/IHRoaXMuYWR2YW5jZWRDb25maWd1cmF0aW9uLnNjcmVlblNoYXJlQ2hyb21lRXh0ZW5zaW9uIDpcbiAgICAgICAgICAgICAgICAgICAgICAgICdodHRwczovL2Nocm9tZS5nb29nbGUuY29tL3dlYnN0b3JlL2RldGFpbC9vcGVudmlkdS1zY3JlZW5zaGFyaW5nL2xmY2dmZXBhZm5vYmRsb2VjY2huZmFjbGliZW5qb2xkJztcbiAgICAgICAgICAgICAgICAgICAgICBjb25zdCBlcnJvciA9IG5ldyBPcGVuVmlkdUVycm9yKE9wZW5WaWR1RXJyb3JOYW1lLlNDUkVFTl9FWFRFTlNJT05fTk9UX0lOU1RBTExFRCwgZXh0ZW5zaW9uVXJsKTtcbiAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGVycm9yID09PSAnaW5zdGFsbGVkLWRpc2FibGVkJykge1xuICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGVycm9yID0gbmV3IE9wZW5WaWR1RXJyb3IoT3BlblZpZHVFcnJvck5hbWUuU0NSRUVOX0VYVEVOU0lPTl9ESVNBQkxFRCwgJ1lvdSBtdXN0IGVuYWJsZSB0aGUgc2NyZWVuIGV4dGVuc2lvbicpO1xuICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoZXJyb3IgPT09ICdwZXJtaXNzaW9uLWRlbmllZCcpIHtcbiAgICAgICAgICAgICAgICAgICAgICBjb25zdCBlcnJvciA9IG5ldyBPcGVuVmlkdUVycm9yKE9wZW5WaWR1RXJyb3JOYW1lLlNDUkVFTl9DQVBUVVJFX0RFTklFRCwgJ1lvdSBtdXN0IGFsbG93IGFjY2VzcyB0byBvbmUgd2luZG93IG9mIHlvdXIgZGVza3RvcCcpO1xuICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIG1lZGlhQ29uc3RyYWludHMudmlkZW8gPSBzY3JlZW5Db25zdHJhaW50cy52aWRlbztcbiAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZShtZWRpYUNvbnN0cmFpbnRzKTtcbiAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgIHB1Ymxpc2hlclByb3BlcnRpZXMudmlkZW9Tb3VyY2UgPSAnc2NyZWVuJztcblxuICAgICAgICAgICAgfVxuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6bm8tc3RyaW5nLWxpdGVyYWxcbiAgICAgICAgICAgIG1lZGlhQ29uc3RyYWludHMudmlkZW9bJ2RldmljZUlkJ10gPSB7IGV4YWN0OiBwdWJsaXNoZXJQcm9wZXJ0aWVzLnZpZGVvU291cmNlIH07XG4gICAgICAgICAgICByZXNvbHZlKG1lZGlhQ29uc3RyYWludHMpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICByZXNvbHZlKG1lZGlhQ29uc3RyYWludHMpO1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXNvbHZlKG1lZGlhQ29uc3RyYWludHMpO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIEBoaWRkZW5cbiAgICovXG4gIHN0YXJ0V3Mob25Db25uZWN0U3VjY2VzOiAoZXJyb3I6IEVycm9yKSA9PiB2b2lkKTogdm9pZCB7XG4gICAgY29uc3QgY29uZmlnID0ge1xuICAgICAgaGVhcnRiZWF0OiA1MDAwLFxuICAgICAgc2VuZENsb3NlTWVzc2FnZTogZmFsc2UsXG4gICAgICB3czoge1xuICAgICAgICB1cmk6IHRoaXMud3NVcmksXG4gICAgICAgIHVzZVNvY2tKUzogZmFsc2UsXG4gICAgICAgIG9uY29ubmVjdGVkOiBvbkNvbm5lY3RTdWNjZXMsXG4gICAgICAgIG9uZGlzY29ubmVjdDogdGhpcy5kaXNjb25uZWN0Q2FsbGJhY2suYmluZCh0aGlzKSxcbiAgICAgICAgb25yZWNvbm5lY3Rpbmc6IHRoaXMucmVjb25uZWN0aW5nQ2FsbGJhY2suYmluZCh0aGlzKSxcbiAgICAgICAgb25yZWNvbm5lY3RlZDogdGhpcy5yZWNvbm5lY3RlZENhbGxiYWNrLmJpbmQodGhpcylcbiAgICAgIH0sXG4gICAgICBycGM6IHtcbiAgICAgICAgcmVxdWVzdFRpbWVvdXQ6IDEwMDAwLFxuICAgICAgICBwYXJ0aWNpcGFudEpvaW5lZDogdGhpcy5zZXNzaW9uLm9uUGFydGljaXBhbnRKb2luZWQuYmluZCh0aGlzLnNlc3Npb24pLFxuICAgICAgICBwYXJ0aWNpcGFudFB1Ymxpc2hlZDogdGhpcy5zZXNzaW9uLm9uUGFydGljaXBhbnRQdWJsaXNoZWQuYmluZCh0aGlzLnNlc3Npb24pLFxuICAgICAgICBwYXJ0aWNpcGFudFVucHVibGlzaGVkOiB0aGlzLnNlc3Npb24ub25QYXJ0aWNpcGFudFVucHVibGlzaGVkLmJpbmQodGhpcy5zZXNzaW9uKSxcbiAgICAgICAgcGFydGljaXBhbnRMZWZ0OiB0aGlzLnNlc3Npb24ub25QYXJ0aWNpcGFudExlZnQuYmluZCh0aGlzLnNlc3Npb24pLFxuICAgICAgICBwYXJ0aWNpcGFudEV2aWN0ZWQ6IHRoaXMuc2Vzc2lvbi5vblBhcnRpY2lwYW50RXZpY3RlZC5iaW5kKHRoaXMuc2Vzc2lvbiksXG4gICAgICAgIHJlY29yZGluZ1N0YXJ0ZWQ6IHRoaXMuc2Vzc2lvbi5vblJlY29yZGluZ1N0YXJ0ZWQuYmluZCh0aGlzLnNlc3Npb24pLFxuICAgICAgICByZWNvcmRpbmdTdG9wcGVkOiB0aGlzLnNlc3Npb24ub25SZWNvcmRpbmdTdG9wcGVkLmJpbmQodGhpcy5zZXNzaW9uKSxcbiAgICAgICAgc2VuZE1lc3NhZ2U6IHRoaXMuc2Vzc2lvbi5vbk5ld01lc3NhZ2UuYmluZCh0aGlzLnNlc3Npb24pLFxuICAgICAgICBzdHJlYW1Qcm9wZXJ0eUNoYW5nZWQ6IHRoaXMuc2Vzc2lvbi5vblN0cmVhbVByb3BlcnR5Q2hhbmdlZC5iaW5kKHRoaXMuc2Vzc2lvbiksXG4gICAgICAgIGljZUNhbmRpZGF0ZTogdGhpcy5zZXNzaW9uLnJlY3ZJY2VDYW5kaWRhdGUuYmluZCh0aGlzLnNlc3Npb24pLFxuICAgICAgICBtZWRpYUVycm9yOiB0aGlzLnNlc3Npb24ub25NZWRpYUVycm9yLmJpbmQodGhpcy5zZXNzaW9uKVxuICAgICAgfVxuICAgIH07XG4gICAgdGhpcy5qc29uUnBjQ2xpZW50ID0gbmV3IFJwY0J1aWxkZXIuY2xpZW50cy5Kc29uUnBjQ2xpZW50KGNvbmZpZyk7XG4gIH1cblxuICAvKipcbiAgICogQGhpZGRlblxuICAgKi9cbiAgY2xvc2VXcygpOiB2b2lkIHtcbiAgICB0aGlzLmpzb25ScGNDbGllbnQuY2xvc2UoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICBzZW5kUmVxdWVzdChtZXRob2Q6IHN0cmluZywgcGFyYW1zOiBhbnksIGNhbGxiYWNrPyk6IHZvaWQge1xuICAgIGlmIChwYXJhbXMgJiYgcGFyYW1zIGluc3RhbmNlb2YgRnVuY3Rpb24pIHtcbiAgICAgIGNhbGxiYWNrID0gcGFyYW1zO1xuICAgICAgcGFyYW1zID0ge307XG4gICAgfVxuICAgIGNvbnNvbGUuZGVidWcoJ1NlbmRpbmcgcmVxdWVzdDoge21ldGhvZDpcIicgKyBtZXRob2QgKyAnXCIsIHBhcmFtczogJyArIEpTT04uc3RyaW5naWZ5KHBhcmFtcykgKyAnfScpO1xuICAgIHRoaXMuanNvblJwY0NsaWVudC5zZW5kKG1ldGhvZCwgcGFyYW1zLCBjYWxsYmFjayk7XG4gIH1cblxuICAvKipcbiAgICogQGhpZGRlblxuICAgKi9cbiAgaXNNZWRpYVN0cmVhbVRyYWNrKG1lZGlhU291cmNlOiBhbnkpOiBib29sZWFuIHtcbiAgICBjb25zdCBpcyA9ICghIW1lZGlhU291cmNlICYmXG4gICAgICBtZWRpYVNvdXJjZS5lbmFibGVkICE9PSB1bmRlZmluZWQgJiYgdHlwZW9mIG1lZGlhU291cmNlLmVuYWJsZWQgPT09ICdib29sZWFuJyAmJlxuICAgICAgbWVkaWFTb3VyY2UuaWQgIT09IHVuZGVmaW5lZCAmJiB0eXBlb2YgbWVkaWFTb3VyY2UuaWQgPT09ICdzdHJpbmcnICYmXG4gICAgICBtZWRpYVNvdXJjZS5raW5kICE9PSB1bmRlZmluZWQgJiYgdHlwZW9mIG1lZGlhU291cmNlLmtpbmQgPT09ICdzdHJpbmcnICYmXG4gICAgICBtZWRpYVNvdXJjZS5sYWJlbCAhPT0gdW5kZWZpbmVkICYmIHR5cGVvZiBtZWRpYVNvdXJjZS5sYWJlbCA9PT0gJ3N0cmluZycgJiZcbiAgICAgIG1lZGlhU291cmNlLm11dGVkICE9PSB1bmRlZmluZWQgJiYgdHlwZW9mIG1lZGlhU291cmNlLm11dGVkID09PSAnYm9vbGVhbicgJiZcbiAgICAgIG1lZGlhU291cmNlLnJlYWR5U3RhdGUgIT09IHVuZGVmaW5lZCAmJiB0eXBlb2YgbWVkaWFTb3VyY2UucmVhZHlTdGF0ZSA9PT0gJ3N0cmluZycpO1xuICAgIHJldHVybiBpcztcbiAgfVxuXG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICBnZXRXc1VyaSgpOiBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLndzVXJpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBoaWRkZW5cbiAgICovXG4gIGdldFNlY3JldCgpOiBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLnNlY3JldDtcbiAgfVxuXG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICBnZXRSZWNvcmRlcigpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5yZWNvcmRlcjtcbiAgfVxuXG5cbiAgLyogUHJpdmF0ZSBtZXRob2RzICovXG5cbiAgcHJpdmF0ZSBkaXNjb25uZWN0Q2FsbGJhY2soKTogdm9pZCB7XG4gICAgY29uc29sZS53YXJuKCdXZWJzb2NrZXQgY29ubmVjdGlvbiBsb3N0Jyk7XG4gICAgaWYgKHRoaXMuaXNSb29tQXZhaWxhYmxlKCkpIHtcbiAgICAgIHRoaXMuc2Vzc2lvbi5vbkxvc3RDb25uZWN0aW9uKCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGFsZXJ0KCdDb25uZWN0aW9uIGVycm9yLiBQbGVhc2UgcmVsb2FkIHBhZ2UuJyk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSByZWNvbm5lY3RpbmdDYWxsYmFjaygpOiB2b2lkIHtcbiAgICBjb25zb2xlLndhcm4oJ1dlYnNvY2tldCBjb25uZWN0aW9uIGxvc3QgKHJlY29ubmVjdGluZyknKTtcbiAgICBpZiAodGhpcy5pc1Jvb21BdmFpbGFibGUoKSkge1xuICAgICAgdGhpcy5zZXNzaW9uLm9uTG9zdENvbm5lY3Rpb24oKTtcbiAgICB9IGVsc2Uge1xuICAgICAgYWxlcnQoJ0Nvbm5lY3Rpb24gZXJyb3IuIFBsZWFzZSByZWxvYWQgcGFnZS4nKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIHJlY29ubmVjdGVkQ2FsbGJhY2soKTogdm9pZCB7XG4gICAgY29uc29sZS53YXJuKCdXZWJzb2NrZXQgcmVjb25uZWN0ZWQnKTtcbiAgICBpZiAodGhpcy5pc1Jvb21BdmFpbGFibGUoKSkge1xuICAgICAgdGhpcy5zZXNzaW9uLm9uUmVjb3ZlcmVkQ29ubmVjdGlvbigpO1xuICAgIH0gZWxzZSB7XG4gICAgICBhbGVydCgnQ29ubmVjdGlvbiBlcnJvci4gUGxlYXNlIHJlbG9hZCBwYWdlLicpO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgaXNSb29tQXZhaWxhYmxlKCk6IGJvb2xlYW4ge1xuICAgIGlmICh0aGlzLnNlc3Npb24gIT09IHVuZGVmaW5lZCAmJiB0aGlzLnNlc3Npb24gaW5zdGFuY2VvZiBTZXNzaW9uKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9IGVsc2Uge1xuICAgICAgY29uc29sZS53YXJuKCdTZXNzaW9uIGluc3RhbmNlIG5vdCBmb3VuZCcpO1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfVxuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBPcGVuVmlkdSB9IGZyb20gJy4vT3BlblZpZHUnO1xuaW1wb3J0IHsgU2Vzc2lvbiB9IGZyb20gJy4vU2Vzc2lvbic7XG5pbXBvcnQgeyBTdHJlYW0gfSBmcm9tICcuL1N0cmVhbSc7XG5pbXBvcnQgeyBTdHJlYW1NYW5hZ2VyIH0gZnJvbSAnLi9TdHJlYW1NYW5hZ2VyJztcbmltcG9ydCB7IEV2ZW50RGlzcGF0Y2hlciB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvSW50ZXJmYWNlcy9QdWJsaWMvRXZlbnREaXNwYXRjaGVyJztcbmltcG9ydCB7IFB1Ymxpc2hlclByb3BlcnRpZXMgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHVibGljL1B1Ymxpc2hlclByb3BlcnRpZXMnO1xuaW1wb3J0IHsgRXZlbnQgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0V2ZW50cy9FdmVudCc7XG5pbXBvcnQgeyBTdHJlYW1FdmVudCB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1N0cmVhbUV2ZW50JztcbmltcG9ydCB7IFN0cmVhbVByb3BlcnR5Q2hhbmdlZEV2ZW50IH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvU3RyZWFtUHJvcGVydHlDaGFuZ2VkRXZlbnQnO1xuaW1wb3J0IHsgVmlkZW9FbGVtZW50RXZlbnQgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0V2ZW50cy9WaWRlb0VsZW1lbnRFdmVudCc7XG5pbXBvcnQgeyBPcGVuVmlkdUVycm9yLCBPcGVuVmlkdUVycm9yTmFtZSB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRW51bXMvT3BlblZpZHVFcnJvcic7XG5pbXBvcnQgeyBWaWRlb0luc2VydE1vZGUgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0VudW1zL1ZpZGVvSW5zZXJ0TW9kZSc7XG5cbmltcG9ydCBwbGF0Zm9ybSA9IHJlcXVpcmUoJ3BsYXRmb3JtJyk7XG5cblxuLyoqXG4gKiBQYWNrcyBsb2NhbCBtZWRpYSBzdHJlYW1zLiBQYXJ0aWNpcGFudHMgY2FuIHB1Ymxpc2ggaXQgdG8gYSBzZXNzaW9uLiBJbml0aWFsaXplZCB3aXRoIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dIG1ldGhvZFxuICovXG5leHBvcnQgY2xhc3MgUHVibGlzaGVyIGV4dGVuZHMgU3RyZWFtTWFuYWdlciB7XG5cbiAgICAvKipcbiAgICAgKiBXaGV0aGVyIHRoZSBQdWJsaXNoZXIgaGFzIGJlZW4gZ3JhbnRlZCBhY2Nlc3MgdG8gdGhlIHJlcXVlc3RlZCBpbnB1dCBkZXZpY2VzIG9yIG5vdFxuICAgICAqL1xuICAgIGFjY2Vzc0FsbG93ZWQgPSBmYWxzZTtcblxuICAgIC8qKlxuICAgICAqIFdoZXRoZXIgeW91IGhhdmUgY2FsbGVkIFtbUHVibGlzaGVyLnN1YnNjcmliZVRvUmVtb3RlXV0gd2l0aCB2YWx1ZSBgdHJ1ZWAgb3IgYGZhbHNlYCAoKmZhbHNlKiBieSBkZWZhdWx0KVxuICAgICAqL1xuICAgIGlzU3Vic2NyaWJlZFRvUmVtb3RlID0gZmFsc2U7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgW1tTZXNzaW9uXV0gdG8gd2hpY2ggdGhlIFB1Ymxpc2hlciBiZWxvbmdzXG4gICAgICovXG4gICAgc2Vzc2lvbjogU2Vzc2lvbjsgLy8gSW5pdGlhbGl6ZWQgYnkgU2Vzc2lvbi5wdWJsaXNoKFB1Ymxpc2hlcilcblxuICAgIHByaXZhdGUgYWNjZXNzRGVuaWVkID0gZmFsc2U7XG4gICAgcHJpdmF0ZSBwcm9wZXJ0aWVzOiBQdWJsaXNoZXJQcm9wZXJ0aWVzO1xuICAgIHByaXZhdGUgcGVybWlzc2lvbkRpYWxvZ1RpbWVvdXQ6IE5vZGVKUy5UaW1lcjtcblxuICAgIC8qKlxuICAgICAqIGhpZGRlblxuICAgICAqL1xuICAgIG9wZW52aWR1OiBPcGVuVmlkdTtcbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgdmlkZW9SZWZlcmVuY2U6IEhUTUxWaWRlb0VsZW1lbnQ7XG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHNjcmVlblNoYXJlUmVzaXplSW50ZXJ2YWw6IE5vZGVKUy5UaW1lcjtcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3Rvcih0YXJnRWw6IHN0cmluZyB8IEhUTUxFbGVtZW50LCBwcm9wZXJ0aWVzOiBQdWJsaXNoZXJQcm9wZXJ0aWVzLCBvcGVudmlkdTogT3BlblZpZHUpIHtcbiAgICAgICAgc3VwZXIobmV3IFN0cmVhbSgoISFvcGVudmlkdS5zZXNzaW9uKSA/IG9wZW52aWR1LnNlc3Npb24gOiBuZXcgU2Vzc2lvbihvcGVudmlkdSksIHsgcHVibGlzaGVyUHJvcGVydGllczogcHJvcGVydGllcywgbWVkaWFDb25zdHJhaW50czoge30gfSksIHRhcmdFbCk7XG4gICAgICAgIHRoaXMucHJvcGVydGllcyA9IHByb3BlcnRpZXM7XG4gICAgICAgIHRoaXMub3BlbnZpZHUgPSBvcGVudmlkdTtcblxuICAgICAgICB0aGlzLnN0cmVhbS5lZS5vbignbG9jYWwtc3RyZWFtLWRlc3Ryb3llZCcsIChyZWFzb246IHN0cmluZykgPT4ge1xuICAgICAgICAgICAgdGhpcy5zdHJlYW0uaXNMb2NhbFN0cmVhbVB1Ymxpc2hlZCA9IGZhbHNlO1xuICAgICAgICAgICAgY29uc3Qgc3RyZWFtRXZlbnQgPSBuZXcgU3RyZWFtRXZlbnQodHJ1ZSwgdGhpcywgJ3N0cmVhbURlc3Ryb3llZCcsIHRoaXMuc3RyZWFtLCByZWFzb24pO1xuICAgICAgICAgICAgdGhpcy5lbWl0RXZlbnQoJ3N0cmVhbURlc3Ryb3llZCcsIFtzdHJlYW1FdmVudF0pO1xuICAgICAgICAgICAgc3RyZWFtRXZlbnQuY2FsbERlZmF1bHRCZWhhdmlvcigpO1xuICAgICAgICB9KTtcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFB1Ymxpc2ggb3IgdW5wdWJsaXNoIHRoZSBhdWRpbyBzdHJlYW0gKGlmIGF2YWlsYWJsZSkuIENhbGxpbmcgdGhpcyBtZXRob2QgdHdpY2UgaW4gYSByb3cgcGFzc2luZyBzYW1lIHZhbHVlIHdpbGwgaGF2ZSBubyBlZmZlY3RcbiAgICAgKlxuICAgICAqICMjIyMgRXZlbnRzIGRpc3BhdGNoZWRcbiAgICAgKlxuICAgICAqIFRoZSBbW1Nlc3Npb25dXSBvYmplY3Qgb2YgdGhlIGxvY2FsIHBhcnRpY2lwYW50IHdpbGwgZGlzcGF0Y2ggYSBgc3RyZWFtUHJvcGVydHlDaGFuZ2VkYCBldmVudCB3aXRoIGBjaGFuZ2VkUHJvcGVydHlgIHNldCB0byBgXCJhdWRpb0FjdGl2ZVwiYCBhbmQgYHJlYXNvbmAgc2V0IHRvIGBcInB1Ymxpc2hBdWRpb1wiYFxuICAgICAqIFRoZSBbW1B1Ymxpc2hlcl1dIG9iamVjdCBvZiB0aGUgbG9jYWwgcGFydGljaXBhbnQgd2lsbCBhbHNvIGRpc3BhdGNoIHRoZSBleGFjdCBzYW1lIGV2ZW50XG4gICAgICpcbiAgICAgKiBUaGUgW1tTZXNzaW9uXV0gb2JqZWN0IG9mIGV2ZXJ5IG90aGVyIHBhcnRpY2lwYW50IGNvbm5lY3RlZCB0byB0aGUgc2Vzc2lvbiB3aWxsIGRpc3BhdGNoIGEgYHN0cmVhbVByb3BlcnR5Q2hhbmdlZGAgZXZlbnQgd2l0aCBgY2hhbmdlZFByb3BlcnR5YCBzZXQgdG8gYFwiYXVkaW9BY3RpdmVcImAgYW5kIGByZWFzb25gIHNldCB0byBgXCJwdWJsaXNoQXVkaW9cImBcbiAgICAgKiBUaGUgcmVzcGVjdGl2ZSBbW1N1YnNjcmliZXJdXSBvYmplY3Qgb2YgZXZlcnkgb3RoZXIgcGFydGljaXBhbnQgcmVjZWl2aW5nIHRoaXMgUHVibGlzaGVyJ3Mgc3RyZWFtIHdpbGwgYWxzbyBkaXNwYXRjaCB0aGUgZXhhY3Qgc2FtZSBldmVudFxuICAgICAqXG4gICAgICogU2VlIFtbU3RyZWFtUHJvcGVydHlDaGFuZ2VkRXZlbnRdXSB0byBsZWFybiBtb3JlLlxuICAgICAqXG4gICAgICogQHBhcmFtIHZhbHVlIGB0cnVlYCB0byBwdWJsaXNoIHRoZSBhdWRpbyBzdHJlYW0sIGBmYWxzZWAgdG8gdW5wdWJsaXNoIGl0XG4gICAgICovXG4gICAgcHVibGlzaEF1ZGlvKHZhbHVlOiBib29sZWFuKTogdm9pZCB7XG4gICAgICAgIGlmICh0aGlzLnN0cmVhbS5hdWRpb0FjdGl2ZSAhPT0gdmFsdWUpIHtcbiAgICAgICAgICAgIHRoaXMuc3RyZWFtLmdldE1lZGlhU3RyZWFtKCkuZ2V0QXVkaW9UcmFja3MoKS5mb3JFYWNoKCh0cmFjaykgPT4ge1xuICAgICAgICAgICAgICAgIHRyYWNrLmVuYWJsZWQgPSB2YWx1ZTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgdGhpcy5zZXNzaW9uLm9wZW52aWR1LnNlbmRSZXF1ZXN0KFxuICAgICAgICAgICAgICAgICdzdHJlYW1Qcm9wZXJ0eUNoYW5nZWQnLFxuICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgc3RyZWFtSWQ6IHRoaXMuc3RyZWFtLnN0cmVhbUlkLFxuICAgICAgICAgICAgICAgICAgICBwcm9wZXJ0eTogJ2F1ZGlvQWN0aXZlJyxcbiAgICAgICAgICAgICAgICAgICAgbmV3VmFsdWU6IHZhbHVlLFxuICAgICAgICAgICAgICAgICAgICByZWFzb246ICdwdWJsaXNoQXVkaW8nXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAoZXJyb3IsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihcIkVycm9yIHNlbmRpbmcgJ3N0cmVhbVByb3BlcnR5Q2hhbmdlZCcgZXZlbnRcIiwgZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXNzaW9uLmVtaXRFdmVudCgnc3RyZWFtUHJvcGVydHlDaGFuZ2VkJywgW25ldyBTdHJlYW1Qcm9wZXJ0eUNoYW5nZWRFdmVudCh0aGlzLnNlc3Npb24sIHRoaXMuc3RyZWFtLCAnYXVkaW9BY3RpdmUnLCB2YWx1ZSwgIXZhbHVlLCAncHVibGlzaEF1ZGlvJyldKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZW1pdEV2ZW50KCdzdHJlYW1Qcm9wZXJ0eUNoYW5nZWQnLCBbbmV3IFN0cmVhbVByb3BlcnR5Q2hhbmdlZEV2ZW50KHRoaXMsIHRoaXMuc3RyZWFtLCAnYXVkaW9BY3RpdmUnLCB2YWx1ZSwgIXZhbHVlLCAncHVibGlzaEF1ZGlvJyldKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgdGhpcy5zdHJlYW0uYXVkaW9BY3RpdmUgPSB2YWx1ZTtcbiAgICAgICAgICAgIGNvbnNvbGUuaW5mbyhcIidQdWJsaXNoZXInIGhhcyBcIiArICh2YWx1ZSA/ICdwdWJsaXNoZWQnIDogJ3VucHVibGlzaGVkJykgKyAnIGl0cyBhdWRpbyBzdHJlYW0nKTtcbiAgICAgICAgfVxuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogUHVibGlzaCBvciB1bnB1Ymxpc2ggdGhlIHZpZGVvIHN0cmVhbSAoaWYgYXZhaWxhYmxlKS4gQ2FsbGluZyB0aGlzIG1ldGhvZCB0d2ljZSBpbiBhIHJvdyBwYXNzaW5nIHNhbWUgdmFsdWUgd2lsbCBoYXZlIG5vIGVmZmVjdFxuICAgICAqXG4gICAgICogIyMjIyBFdmVudHMgZGlzcGF0Y2hlZFxuICAgICAqXG4gICAgICogVGhlIFtbU2Vzc2lvbl1dIG9iamVjdCBvZiB0aGUgbG9jYWwgcGFydGljaXBhbnQgd2lsbCBkaXNwYXRjaCBhIGBzdHJlYW1Qcm9wZXJ0eUNoYW5nZWRgIGV2ZW50IHdpdGggYGNoYW5nZWRQcm9wZXJ0eWAgc2V0IHRvIGBcInZpZGVvQWN0aXZlXCJgIGFuZCBgcmVhc29uYCBzZXQgdG8gYFwicHVibGlzaFZpZGVvXCJgXG4gICAgICogVGhlIFtbUHVibGlzaGVyXV0gb2JqZWN0IG9mIHRoZSBsb2NhbCBwYXJ0aWNpcGFudCB3aWxsIGFsc28gZGlzcGF0Y2ggdGhlIGV4YWN0IHNhbWUgZXZlbnRcbiAgICAgKlxuICAgICAqIFRoZSBbW1Nlc3Npb25dXSBvYmplY3Qgb2YgZXZlcnkgb3RoZXIgcGFydGljaXBhbnQgY29ubmVjdGVkIHRvIHRoZSBzZXNzaW9uIHdpbGwgZGlzcGF0Y2ggYSBgc3RyZWFtUHJvcGVydHlDaGFuZ2VkYCBldmVudCB3aXRoIGBjaGFuZ2VkUHJvcGVydHlgIHNldCB0byBgXCJ2aWRlb0FjdGl2ZVwiYCBhbmQgYHJlYXNvbmAgc2V0IHRvIGBcInB1Ymxpc2hWaWRlb1wiYFxuICAgICAqIFRoZSByZXNwZWN0aXZlIFtbU3Vic2NyaWJlcl1dIG9iamVjdCBvZiBldmVyeSBvdGhlciBwYXJ0aWNpcGFudCByZWNlaXZpbmcgdGhpcyBQdWJsaXNoZXIncyBzdHJlYW0gd2lsbCBhbHNvIGRpc3BhdGNoIHRoZSBleGFjdCBzYW1lIGV2ZW50XG4gICAgICpcbiAgICAgKiBTZWUgW1tTdHJlYW1Qcm9wZXJ0eUNoYW5nZWRFdmVudF1dIHRvIGxlYXJuIG1vcmUuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gdmFsdWUgYHRydWVgIHRvIHB1Ymxpc2ggdGhlIHZpZGVvIHN0cmVhbSwgYGZhbHNlYCB0byB1bnB1Ymxpc2ggaXRcbiAgICAgKi9cbiAgICBwdWJsaXNoVmlkZW8odmFsdWU6IGJvb2xlYW4pOiB2b2lkIHtcbiAgICAgICAgaWYgKHRoaXMuc3RyZWFtLnZpZGVvQWN0aXZlICE9PSB2YWx1ZSkge1xuICAgICAgICAgICAgdGhpcy5zdHJlYW0uZ2V0TWVkaWFTdHJlYW0oKS5nZXRWaWRlb1RyYWNrcygpLmZvckVhY2goKHRyYWNrKSA9PiB7XG4gICAgICAgICAgICAgICAgdHJhY2suZW5hYmxlZCA9IHZhbHVlO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB0aGlzLnNlc3Npb24ub3BlbnZpZHUuc2VuZFJlcXVlc3QoXG4gICAgICAgICAgICAgICAgJ3N0cmVhbVByb3BlcnR5Q2hhbmdlZCcsXG4gICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICBzdHJlYW1JZDogdGhpcy5zdHJlYW0uc3RyZWFtSWQsXG4gICAgICAgICAgICAgICAgICAgIHByb3BlcnR5OiAndmlkZW9BY3RpdmUnLFxuICAgICAgICAgICAgICAgICAgICBuZXdWYWx1ZTogdmFsdWUsXG4gICAgICAgICAgICAgICAgICAgIHJlYXNvbjogJ3B1Ymxpc2hWaWRlbydcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIChlcnJvciwgcmVzcG9uc2UpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKFwiRXJyb3Igc2VuZGluZyAnc3RyZWFtUHJvcGVydHlDaGFuZ2VkJyBldmVudFwiLCBlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnNlc3Npb24uZW1pdEV2ZW50KCdzdHJlYW1Qcm9wZXJ0eUNoYW5nZWQnLCBbbmV3IFN0cmVhbVByb3BlcnR5Q2hhbmdlZEV2ZW50KHRoaXMuc2Vzc2lvbiwgdGhpcy5zdHJlYW0sICd2aWRlb0FjdGl2ZScsIHZhbHVlLCAhdmFsdWUsICdwdWJsaXNoVmlkZW8nKV0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5lbWl0RXZlbnQoJ3N0cmVhbVByb3BlcnR5Q2hhbmdlZCcsIFtuZXcgU3RyZWFtUHJvcGVydHlDaGFuZ2VkRXZlbnQodGhpcywgdGhpcy5zdHJlYW0sICd2aWRlb0FjdGl2ZScsIHZhbHVlLCAhdmFsdWUsICdwdWJsaXNoVmlkZW8nKV0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB0aGlzLnN0cmVhbS52aWRlb0FjdGl2ZSA9IHZhbHVlO1xuICAgICAgICAgICAgY29uc29sZS5pbmZvKFwiJ1B1Ymxpc2hlcicgaGFzIFwiICsgKHZhbHVlID8gJ3B1Ymxpc2hlZCcgOiAndW5wdWJsaXNoZWQnKSArICcgaXRzIHZpZGVvIHN0cmVhbScpO1xuICAgICAgICB9XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBDYWxsIHRoaXMgbWV0aG9kIGJlZm9yZSBbW1Nlc3Npb24ucHVibGlzaF1dIGlmIHlvdSBwcmVmZXIgdG8gc3Vic2NyaWJlIHRvIHlvdXIgUHVibGlzaGVyJ3MgcmVtb3RlIHN0cmVhbSBpbnN0ZWFkIG9mIHVzaW5nIHRoZSBsb2NhbCBzdHJlYW0sIGFzIGFueSBvdGhlciB1c2VyIHdvdWxkIGRvLlxuICAgICAqL1xuICAgIHN1YnNjcmliZVRvUmVtb3RlKHZhbHVlPzogYm9vbGVhbik6IHZvaWQge1xuICAgICAgICB2YWx1ZSA9ICh2YWx1ZSAhPT0gdW5kZWZpbmVkKSA/IHZhbHVlIDogdHJ1ZTtcbiAgICAgICAgdGhpcy5pc1N1YnNjcmliZWRUb1JlbW90ZSA9IHZhbHVlO1xuICAgICAgICB0aGlzLnN0cmVhbS5zdWJzY3JpYmVUb015UmVtb3RlKHZhbHVlKTtcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFNlZSBbW0V2ZW50RGlzcGF0Y2hlci5vbl1dXG4gICAgICovXG4gICAgb24odHlwZTogc3RyaW5nLCBoYW5kbGVyOiAoZXZlbnQ6IEV2ZW50KSA9PiB2b2lkKTogRXZlbnREaXNwYXRjaGVyIHtcbiAgICAgICAgc3VwZXIub24odHlwZSwgaGFuZGxlcik7XG4gICAgICAgIGlmICh0eXBlID09PSAnc3RyZWFtQ3JlYXRlZCcpIHtcbiAgICAgICAgICAgIGlmICghIXRoaXMuc3RyZWFtICYmIHRoaXMuc3RyZWFtLmlzTG9jYWxTdHJlYW1QdWJsaXNoZWQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVtaXRFdmVudCgnc3RyZWFtQ3JlYXRlZCcsIFtuZXcgU3RyZWFtRXZlbnQoZmFsc2UsIHRoaXMsICdzdHJlYW1DcmVhdGVkJywgdGhpcy5zdHJlYW0sICcnKV0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbS5lZS5vbignc3RyZWFtLWNyZWF0ZWQtYnktcHVibGlzaGVyJywgKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmVtaXRFdmVudCgnc3RyZWFtQ3JlYXRlZCcsIFtuZXcgU3RyZWFtRXZlbnQoZmFsc2UsIHRoaXMsICdzdHJlYW1DcmVhdGVkJywgdGhpcy5zdHJlYW0sICcnKV0pO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmICh0eXBlID09PSAncmVtb3RlVmlkZW9QbGF5aW5nJykge1xuICAgICAgICAgICAgaWYgKHRoaXMuc3RyZWFtLmRpc3BsYXlNeVJlbW90ZSgpICYmIHRoaXMudmlkZW9zWzBdICYmIHRoaXMudmlkZW9zWzBdLnZpZGVvICYmXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8uY3VycmVudFRpbWUgPiAwICYmXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8ucGF1c2VkID09PSBmYWxzZSAmJlxuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9zWzBdLnZpZGVvLmVuZGVkID09PSBmYWxzZSAmJlxuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9zWzBdLnZpZGVvLnJlYWR5U3RhdGUgPT09IDQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVtaXRFdmVudCgncmVtb3RlVmlkZW9QbGF5aW5nJywgW25ldyBWaWRlb0VsZW1lbnRFdmVudCh0aGlzLnZpZGVvc1swXS52aWRlbywgdGhpcywgJ3JlbW90ZVZpZGVvUGxheWluZycpXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHR5cGUgPT09ICdhY2Nlc3NBbGxvd2VkJykge1xuICAgICAgICAgICAgaWYgKHRoaXMuYWNjZXNzQWxsb3dlZCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZW1pdEV2ZW50KCdhY2Nlc3NBbGxvd2VkJywgW10pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmICh0eXBlID09PSAnYWNjZXNzRGVuaWVkJykge1xuICAgICAgICAgICAgaWYgKHRoaXMuYWNjZXNzRGVuaWVkKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5lbWl0RXZlbnQoJ2FjY2Vzc0RlbmllZCcsIFtdKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFNlZSBbW0V2ZW50RGlzcGF0Y2hlci5vbmNlXV1cbiAgICAgKi9cbiAgICBvbmNlKHR5cGU6IHN0cmluZywgaGFuZGxlcjogKGV2ZW50OiBFdmVudCkgPT4gdm9pZCk6IFB1Ymxpc2hlciB7XG4gICAgICAgIHN1cGVyLm9uY2UodHlwZSwgaGFuZGxlcik7XG4gICAgICAgIGlmICh0eXBlID09PSAnc3RyZWFtQ3JlYXRlZCcpIHtcbiAgICAgICAgICAgIGlmICghIXRoaXMuc3RyZWFtICYmIHRoaXMuc3RyZWFtLmlzTG9jYWxTdHJlYW1QdWJsaXNoZWQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVtaXRFdmVudCgnc3RyZWFtQ3JlYXRlZCcsIFtuZXcgU3RyZWFtRXZlbnQoZmFsc2UsIHRoaXMsICdzdHJlYW1DcmVhdGVkJywgdGhpcy5zdHJlYW0sICcnKV0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbS5lZS5vbmNlKCdzdHJlYW0tY3JlYXRlZC1ieS1wdWJsaXNoZXInLCAoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZW1pdEV2ZW50KCdzdHJlYW1DcmVhdGVkJywgW25ldyBTdHJlYW1FdmVudChmYWxzZSwgdGhpcywgJ3N0cmVhbUNyZWF0ZWQnLCB0aGlzLnN0cmVhbSwgJycpXSk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHR5cGUgPT09ICdyZW1vdGVWaWRlb1BsYXlpbmcnKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5zdHJlYW0uZGlzcGxheU15UmVtb3RlKCkgJiYgdGhpcy52aWRlb3NbMF0gJiYgdGhpcy52aWRlb3NbMF0udmlkZW8gJiZcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvc1swXS52aWRlby5jdXJyZW50VGltZSA+IDAgJiZcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvc1swXS52aWRlby5wYXVzZWQgPT09IGZhbHNlICYmXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8uZW5kZWQgPT09IGZhbHNlICYmXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8ucmVhZHlTdGF0ZSA9PT0gNCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZW1pdEV2ZW50KCdyZW1vdGVWaWRlb1BsYXlpbmcnLCBbbmV3IFZpZGVvRWxlbWVudEV2ZW50KHRoaXMudmlkZW9zWzBdLnZpZGVvLCB0aGlzLCAncmVtb3RlVmlkZW9QbGF5aW5nJyldKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAodHlwZSA9PT0gJ2FjY2Vzc0FsbG93ZWQnKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5hY2Nlc3NBbGxvd2VkKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5lbWl0RXZlbnQoJ2FjY2Vzc0FsbG93ZWQnLCBbXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHR5cGUgPT09ICdhY2Nlc3NEZW5pZWQnKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5hY2Nlc3NEZW5pZWQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVtaXRFdmVudCgnYWNjZXNzRGVuaWVkJywgW10pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuXG4gICAgLyogSGlkZGVuIG1ldGhvZHMgKi9cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBpbml0aWFsaXplKCk6IFByb21pc2U8YW55PiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG5cbiAgICAgICAgICAgIGNvbnN0IGVycm9yQ2FsbGJhY2sgPSAob3BlblZpZHVFcnJvcjogT3BlblZpZHVFcnJvcikgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuYWNjZXNzRGVuaWVkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB0aGlzLmFjY2Vzc0FsbG93ZWQgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICByZWplY3Qob3BlblZpZHVFcnJvcik7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICBjb25zdCBzdWNjZXNzQ2FsbGJhY2sgPSAobWVkaWFTdHJlYW06IE1lZGlhU3RyZWFtKSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5hY2Nlc3NBbGxvd2VkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB0aGlzLmFjY2Vzc0RlbmllZCA9IGZhbHNlO1xuXG4gICAgICAgICAgICAgICAgaWYgKHRoaXMub3BlbnZpZHUuaXNNZWRpYVN0cmVhbVRyYWNrKHRoaXMucHJvcGVydGllcy5hdWRpb1NvdXJjZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgbWVkaWFTdHJlYW0ucmVtb3ZlVHJhY2sobWVkaWFTdHJlYW0uZ2V0QXVkaW9UcmFja3MoKVswXSk7XG4gICAgICAgICAgICAgICAgICAgIG1lZGlhU3RyZWFtLmFkZFRyYWNrKCg8TWVkaWFTdHJlYW1UcmFjaz50aGlzLnByb3BlcnRpZXMuYXVkaW9Tb3VyY2UpKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAodGhpcy5vcGVudmlkdS5pc01lZGlhU3RyZWFtVHJhY2sodGhpcy5wcm9wZXJ0aWVzLnZpZGVvU291cmNlKSkge1xuICAgICAgICAgICAgICAgICAgICBtZWRpYVN0cmVhbS5yZW1vdmVUcmFjayhtZWRpYVN0cmVhbS5nZXRWaWRlb1RyYWNrcygpWzBdKTtcbiAgICAgICAgICAgICAgICAgICAgbWVkaWFTdHJlYW0uYWRkVHJhY2soKDxNZWRpYVN0cmVhbVRyYWNrPnRoaXMucHJvcGVydGllcy52aWRlb1NvdXJjZSkpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIEFwcGx5IFB1Ymxpc2hlclByb3BlcnRpZXMucHVibGlzaEF1ZGlvIGFuZCBQdWJsaXNoZXJQcm9wZXJ0aWVzLnB1Ymxpc2hWaWRlb1xuICAgICAgICAgICAgICAgIGlmICghIW1lZGlhU3RyZWFtLmdldEF1ZGlvVHJhY2tzKClbMF0pIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgZW5hYmxlZCA9ICh0aGlzLnN0cmVhbS5hdWRpb0FjdGl2ZSAhPT0gdW5kZWZpbmVkICYmIHRoaXMuc3RyZWFtLmF1ZGlvQWN0aXZlICE9PSBudWxsKSA/IHRoaXMuc3RyZWFtLmF1ZGlvQWN0aXZlIDogISF0aGlzLnN0cmVhbS5vdXRib3VuZFN0cmVhbU9wdHMucHVibGlzaGVyUHJvcGVydGllcy5wdWJsaXNoQXVkaW87XG4gICAgICAgICAgICAgICAgICAgIG1lZGlhU3RyZWFtLmdldEF1ZGlvVHJhY2tzKClbMF0uZW5hYmxlZCA9IGVuYWJsZWQ7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmICghIW1lZGlhU3RyZWFtLmdldFZpZGVvVHJhY2tzKClbMF0pIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgZW5hYmxlZCA9ICh0aGlzLnN0cmVhbS52aWRlb0FjdGl2ZSAhPT0gdW5kZWZpbmVkICYmIHRoaXMuc3RyZWFtLnZpZGVvQWN0aXZlICE9PSBudWxsKSA/IHRoaXMuc3RyZWFtLnZpZGVvQWN0aXZlIDogISF0aGlzLnN0cmVhbS5vdXRib3VuZFN0cmVhbU9wdHMucHVibGlzaGVyUHJvcGVydGllcy5wdWJsaXNoVmlkZW87XG4gICAgICAgICAgICAgICAgICAgIG1lZGlhU3RyZWFtLmdldFZpZGVvVHJhY2tzKClbMF0uZW5hYmxlZCA9IGVuYWJsZWQ7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb1JlZmVyZW5jZSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3ZpZGVvJyk7XG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb1JlZmVyZW5jZS5zcmNPYmplY3QgPSBtZWRpYVN0cmVhbTtcblxuICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtLnNldE1lZGlhU3RyZWFtKG1lZGlhU3RyZWFtKTtcbiAgICAgICAgICAgICAgICBpZiAoIXRoaXMuc3RyZWFtLmRpc3BsYXlNeVJlbW90ZSgpKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIFdoZW4gd2UgYXJlIHN1YnNjcmliZWQgdG8gb3VyIHJlbW90ZSB3ZSBkb24ndCBzdGlsbCBzZXQgdGhlIE1lZGlhU3RyZWFtIG9iamVjdCBpbiB0aGUgdmlkZW8gZWxlbWVudHMgdG9cbiAgICAgICAgICAgICAgICAgICAgLy8gYXZvaWQgZWFybHkgJ3N0cmVhbVBsYXlpbmcnIGV2ZW50XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtLnVwZGF0ZU1lZGlhU3RyZWFtSW5WaWRlb3MoKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoISF0aGlzLmZpcnN0VmlkZW9FbGVtZW50KSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuY3JlYXRlVmlkZW9FbGVtZW50KHRoaXMuZmlyc3RWaWRlb0VsZW1lbnQudGFyZ2V0RWxlbWVudCwgPFZpZGVvSW5zZXJ0TW9kZT50aGlzLnByb3BlcnRpZXMuaW5zZXJ0TW9kZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGRlbGV0ZSB0aGlzLmZpcnN0VmlkZW9FbGVtZW50O1xuXG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuc3RyZWFtLmlzU2VuZFZpZGVvKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCF0aGlzLnN0cmVhbS5pc1NlbmRTY3JlZW4oKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gV2l0aCBubyBzY3JlZW4gc2hhcmUsIHZpZGVvIGRpbWVuc2lvbiBjYW4gYmUgc2V0IGRpcmVjdGx5IGZyb20gTWVkaWFTdHJlYW0gKGdldFNldHRpbmdzKVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gT3JpZW50YXRpb24gbXVzdCBiZSBjaGVja2VkIGZvciBtb2JpbGUgZGV2aWNlcyAod2lkdGggYW5kIGhlaWdodCBhcmUgcmV2ZXJzZWQpXG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB7IHdpZHRoLCBoZWlnaHQgfSA9IG1lZGlhU3RyZWFtLmdldFZpZGVvVHJhY2tzKClbMF0uZ2V0U2V0dGluZ3MoKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHBsYXRmb3JtLm5hbWUhIS50b0xvd2VyQ2FzZSgpLmluZGV4T2YoJ21vYmlsZScpICE9PSAtMSAmJiAod2luZG93LmlubmVySGVpZ2h0ID4gd2luZG93LmlubmVyV2lkdGgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gTW9iaWxlIHBvcnRyYWl0IG1vZGVcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbS52aWRlb0RpbWVuc2lvbnMgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdpZHRoOiBoZWlnaHQgfHwgMCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaGVpZ2h0OiB3aWR0aCB8fCAwXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdHJlYW0udmlkZW9EaW1lbnNpb25zID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3aWR0aDogd2lkdGggfHwgMCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaGVpZ2h0OiBoZWlnaHQgfHwgMFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbS5pc0xvY2FsU3RyZWFtUmVhZHlUb1B1Ymxpc2ggPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdHJlYW0uZWUuZW1pdEV2ZW50KCdzdHJlYW0tcmVhZHktdG8tcHVibGlzaCcsIFtdKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIFdpdGggc2NyZWVuIHNoYXJlLCB2aWRlbyBkaW1lbnNpb24gbXVzdCBiZSBnb3QgZnJvbSBhIHZpZGVvIGVsZW1lbnQgKG9ubG9hZGVkbWV0YWRhdGEgZXZlbnQpXG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnZpZGVvUmVmZXJlbmNlLm9ubG9hZGVkbWV0YWRhdGEgPSAoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdHJlYW0udmlkZW9EaW1lbnNpb25zID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3aWR0aDogdGhpcy52aWRlb1JlZmVyZW5jZS52aWRlb1dpZHRoLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBoZWlnaHQ6IHRoaXMudmlkZW9SZWZlcmVuY2UudmlkZW9IZWlnaHRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc2NyZWVuU2hhcmVSZXNpemVJbnRlcnZhbCA9IHNldEludGVydmFsKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZmlyZWZveFNldHRpbmdzID0gbWVkaWFTdHJlYW0uZ2V0VmlkZW9UcmFja3MoKVswXS5nZXRTZXR0aW5ncygpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBuZXdXaWR0aCA9IChwbGF0Zm9ybS5uYW1lID09PSAnQ2hyb21lJykgPyB0aGlzLnZpZGVvUmVmZXJlbmNlLnZpZGVvV2lkdGggOiBmaXJlZm94U2V0dGluZ3Mud2lkdGg7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG5ld0hlaWdodCA9IChwbGF0Zm9ybS5uYW1lID09PSAnQ2hyb21lJykgPyB0aGlzLnZpZGVvUmVmZXJlbmNlLnZpZGVvSGVpZ2h0IDogZmlyZWZveFNldHRpbmdzLmhlaWdodDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuc3RyZWFtLmlzTG9jYWxTdHJlYW1QdWJsaXNoZWQgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChuZXdXaWR0aCAhPT0gdGhpcy5zdHJlYW0udmlkZW9EaW1lbnNpb25zLndpZHRoIHx8XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3SGVpZ2h0ICE9PSB0aGlzLnN0cmVhbS52aWRlb0RpbWVuc2lvbnMuaGVpZ2h0KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3Qgb2xkVmFsdWUgPSB7IHdpZHRoOiB0aGlzLnN0cmVhbS52aWRlb0RpbWVuc2lvbnMud2lkdGgsIGhlaWdodDogdGhpcy5zdHJlYW0udmlkZW9EaW1lbnNpb25zLmhlaWdodCB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdHJlYW0udmlkZW9EaW1lbnNpb25zID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdpZHRoOiBuZXdXaWR0aCB8fCAwLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhlaWdodDogbmV3SGVpZ2h0IHx8IDBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnNlc3Npb24ub3BlbnZpZHUuc2VuZFJlcXVlc3QoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ3N0cmVhbVByb3BlcnR5Q2hhbmdlZCcsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJlYW1JZDogdGhpcy5zdHJlYW0uc3RyZWFtSWQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByb3BlcnR5OiAndmlkZW9EaW1lbnNpb25zJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3VmFsdWU6IEpTT04uc3RyaW5naWZ5KHRoaXMuc3RyZWFtLnZpZGVvRGltZW5zaW9ucyksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlYXNvbjogJ3NjcmVlblJlc2l6ZWQnXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoZXJyb3IsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihcIkVycm9yIHNlbmRpbmcgJ3N0cmVhbVByb3BlcnR5Q2hhbmdlZCcgZXZlbnRcIiwgZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXNzaW9uLmVtaXRFdmVudCgnc3RyZWFtUHJvcGVydHlDaGFuZ2VkJywgW25ldyBTdHJlYW1Qcm9wZXJ0eUNoYW5nZWRFdmVudCh0aGlzLnNlc3Npb24sIHRoaXMuc3RyZWFtLCAndmlkZW9EaW1lbnNpb25zJywgdGhpcy5zdHJlYW0udmlkZW9EaW1lbnNpb25zLCBvbGRWYWx1ZSwgJ3NjcmVlblJlc2l6ZWQnKV0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5lbWl0RXZlbnQoJ3N0cmVhbVByb3BlcnR5Q2hhbmdlZCcsIFtuZXcgU3RyZWFtUHJvcGVydHlDaGFuZ2VkRXZlbnQodGhpcywgdGhpcy5zdHJlYW0sICd2aWRlb0RpbWVuc2lvbnMnLCB0aGlzLnN0cmVhbS52aWRlb0RpbWVuc2lvbnMsIG9sZFZhbHVlLCAnc2NyZWVuUmVzaXplZCcpXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0sIDUwMCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdHJlYW0uaXNMb2NhbFN0cmVhbVJlYWR5VG9QdWJsaXNoID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbS5lZS5lbWl0RXZlbnQoJ3N0cmVhbS1yZWFkeS10by1wdWJsaXNoJywgW10pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtLmlzTG9jYWxTdHJlYW1SZWFkeVRvUHVibGlzaCA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtLmVlLmVtaXRFdmVudCgnc3RyZWFtLXJlYWR5LXRvLXB1Ymxpc2gnLCBbXSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIHRoaXMub3BlbnZpZHUuZ2VuZXJhdGVNZWRpYUNvbnN0cmFpbnRzKHRoaXMucHJvcGVydGllcylcbiAgICAgICAgICAgICAgICAudGhlbihjb25zdHJhaW50cyA9PiB7XG5cbiAgICAgICAgICAgICAgICAgICAgY29uc3Qgb3V0Ym91bmRTdHJlYW1PcHRpb25zID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgbWVkaWFDb25zdHJhaW50czogY29uc3RyYWludHMsXG4gICAgICAgICAgICAgICAgICAgICAgICBwdWJsaXNoZXJQcm9wZXJ0aWVzOiB0aGlzLnByb3BlcnRpZXNcbiAgICAgICAgICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbS5zZXRPdXRib3VuZFN0cmVhbU9wdGlvbnMob3V0Ym91bmRTdHJlYW1PcHRpb25zKTtcblxuICAgICAgICAgICAgICAgICAgICBjb25zdCBjb25zdHJhaW50c0F1eDogTWVkaWFTdHJlYW1Db25zdHJhaW50cyA9IHt9O1xuICAgICAgICAgICAgICAgICAgICBjb25zdCB0aW1lRm9yRGlhbG9nRXZlbnQgPSAxMjUwO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLnN0cmVhbS5pc1NlbmRWaWRlbygpIHx8IHRoaXMuc3RyZWFtLmlzU2VuZEF1ZGlvKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGRlZmluZWRBdWRpb0NvbnN0cmFpbnQgPSAoKGNvbnN0cmFpbnRzLmF1ZGlvID09PSB1bmRlZmluZWQpID8gdHJ1ZSA6IGNvbnN0cmFpbnRzLmF1ZGlvKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0cmFpbnRzQXV4LmF1ZGlvID0gdGhpcy5zdHJlYW0uaXNTZW5kU2NyZWVuKCkgPyBmYWxzZSA6IGRlZmluZWRBdWRpb0NvbnN0cmFpbnQ7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdHJhaW50c0F1eC52aWRlbyA9IGNvbnN0cmFpbnRzLnZpZGVvO1xuICAgICAgICAgICAgICAgICAgICAgICAgbGV0IHN0YXJ0VGltZSA9IERhdGUubm93KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnNldFBlcm1pc3Npb25EaWFsb2dUaW1lcih0aW1lRm9yRGlhbG9nRXZlbnQpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBuYXZpZ2F0b3IubWVkaWFEZXZpY2VzLmdldFVzZXJNZWRpYShjb25zdHJhaW50c0F1eClcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAudGhlbihtZWRpYVN0cmVhbSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY2xlYXJQZXJtaXNzaW9uRGlhbG9nVGltZXIoc3RhcnRUaW1lLCB0aW1lRm9yRGlhbG9nRXZlbnQpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLnN0cmVhbS5pc1NlbmRTY3JlZW4oKSAmJiB0aGlzLnN0cmVhbS5pc1NlbmRBdWRpbygpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBXaGVuIGdldHRpbmcgZGVza3RvcCBhcyB1c2VyIG1lZGlhIGF1ZGlvIGNvbnN0cmFpbnQgbXVzdCBiZSBmYWxzZS4gTm93IHdlIGNhbiBhc2sgZm9yIGl0IGlmIHJlcXVpcmVkXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdHJhaW50c0F1eC5hdWRpbyA9IGRlZmluZWRBdWRpb0NvbnN0cmFpbnQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdHJhaW50c0F1eC52aWRlbyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhcnRUaW1lID0gRGF0ZS5ub3coKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc2V0UGVybWlzc2lvbkRpYWxvZ1RpbWVyKHRpbWVGb3JEaWFsb2dFdmVudCk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hdmlnYXRvci5tZWRpYURldmljZXMuZ2V0VXNlck1lZGlhKGNvbnN0cmFpbnRzQXV4KVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC50aGVuKGF1ZGlvT25seVN0cmVhbSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY2xlYXJQZXJtaXNzaW9uRGlhbG9nVGltZXIoc3RhcnRUaW1lLCB0aW1lRm9yRGlhbG9nRXZlbnQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZWRpYVN0cmVhbS5hZGRUcmFjayhhdWRpb09ubHlTdHJlYW0uZ2V0QXVkaW9UcmFja3MoKVswXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN1Y2Nlc3NDYWxsYmFjayhtZWRpYVN0cmVhbSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNsZWFyUGVybWlzc2lvbkRpYWxvZ1RpbWVyKHN0YXJ0VGltZSwgdGltZUZvckRpYWxvZ0V2ZW50KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGVycm9yTmFtZSwgZXJyb3JNZXNzYWdlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzd2l0Y2ggKGVycm9yLm5hbWUudG9Mb3dlckNhc2UoKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAnbm90Zm91bmRlcnJvcic6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JOYW1lID0gT3BlblZpZHVFcnJvck5hbWUuSU5QVVRfQVVESU9fREVWSUNFX05PVF9GT1VORDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck1lc3NhZ2UgPSBlcnJvci50b1N0cmluZygpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yQ2FsbGJhY2sobmV3IE9wZW5WaWR1RXJyb3IoZXJyb3JOYW1lLCBlcnJvck1lc3NhZ2UpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJ25vdGFsbG93ZWRlcnJvcic6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JOYW1lID0gT3BlblZpZHVFcnJvck5hbWUuREVWSUNFX0FDQ0VTU19ERU5JRUQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JNZXNzYWdlID0gZXJyb3IudG9TdHJpbmcoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvckNhbGxiYWNrKG5ldyBPcGVuVmlkdUVycm9yKGVycm9yTmFtZSwgZXJyb3JNZXNzYWdlKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlICdvdmVyY29uc3RyYWluZWRlcnJvcic6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yLmNvbnN0cmFpbnQudG9Mb3dlckNhc2UoKSA9PT0gJ2RldmljZWlkJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck5hbWUgPSBPcGVuVmlkdUVycm9yTmFtZS5JTlBVVF9BVURJT19ERVZJQ0VfTk9UX0ZPVU5EO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck1lc3NhZ2UgPSBcIkF1ZGlvIGlucHV0IGRldmljZSB3aXRoIGRldmljZUlkICdcIiArICg8Q29uc3RyYWluRE9NU3RyaW5nUGFyYW1ldGVycz4oPE1lZGlhVHJhY2tDb25zdHJhaW50cz5jb25zdHJhaW50cy52aWRlbykuZGV2aWNlSWQhISkuZXhhY3QgKyBcIicgbm90IGZvdW5kXCI7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JOYW1lID0gT3BlblZpZHVFcnJvck5hbWUuUFVCTElTSEVSX1BST1BFUlRJRVNfRVJST1I7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yTWVzc2FnZSA9IFwiQXVkaW8gaW5wdXQgZGV2aWNlIGRvZXNuJ3Qgc3VwcG9ydCB0aGUgdmFsdWUgcGFzc2VkIGZvciBjb25zdHJhaW50ICdcIiArIGVycm9yLmNvbnN0cmFpbnQgKyBcIidcIjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JDYWxsYmFjayhuZXcgT3BlblZpZHVFcnJvcihlcnJvck5hbWUsIGVycm9yTWVzc2FnZSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdWNjZXNzQ2FsbGJhY2sobWVkaWFTdHJlYW0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNsZWFyUGVybWlzc2lvbkRpYWxvZ1RpbWVyKHN0YXJ0VGltZSwgdGltZUZvckRpYWxvZ0V2ZW50KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGVycm9yTmFtZSwgZXJyb3JNZXNzYWdlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzd2l0Y2ggKGVycm9yLm5hbWUudG9Mb3dlckNhc2UoKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAnbm90Zm91bmRlcnJvcic6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmF2aWdhdG9yLm1lZGlhRGV2aWNlcy5nZXRVc2VyTWVkaWEoe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhdWRpbzogZmFsc2UsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZpZGVvOiBjb25zdHJhaW50cy52aWRlb1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC50aGVuKG1lZGlhU3RyZWFtID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1lZGlhU3RyZWFtLmdldFZpZGVvVHJhY2tzKCkuZm9yRWFjaCgodHJhY2spID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cmFjay5zdG9wKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yTmFtZSA9IE9wZW5WaWR1RXJyb3JOYW1lLklOUFVUX0FVRElPX0RFVklDRV9OT1RfRk9VTkQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck1lc3NhZ2UgPSBlcnJvci50b1N0cmluZygpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JDYWxsYmFjayhuZXcgT3BlblZpZHVFcnJvcihlcnJvck5hbWUsIGVycm9yTWVzc2FnZSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KS5jYXRjaChlID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yTmFtZSA9IE9wZW5WaWR1RXJyb3JOYW1lLklOUFVUX1ZJREVPX0RFVklDRV9OT1RfRk9VTkQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck1lc3NhZ2UgPSBlcnJvci50b1N0cmluZygpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JDYWxsYmFjayhuZXcgT3BlblZpZHVFcnJvcihlcnJvck5hbWUsIGVycm9yTWVzc2FnZSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJ25vdGFsbG93ZWRlcnJvcic6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JOYW1lID0gdGhpcy5zdHJlYW0uaXNTZW5kU2NyZWVuKCkgPyBPcGVuVmlkdUVycm9yTmFtZS5TQ1JFRU5fQ0FQVFVSRV9ERU5JRUQgOiBPcGVuVmlkdUVycm9yTmFtZS5ERVZJQ0VfQUNDRVNTX0RFTklFRDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck1lc3NhZ2UgPSBlcnJvci50b1N0cmluZygpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yQ2FsbGJhY2sobmV3IE9wZW5WaWR1RXJyb3IoZXJyb3JOYW1lLCBlcnJvck1lc3NhZ2UpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJ292ZXJjb25zdHJhaW5lZGVycm9yJzpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYXZpZ2F0b3IubWVkaWFEZXZpY2VzLmdldFVzZXJNZWRpYSh7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGF1ZGlvOiBmYWxzZSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmlkZW86IGNvbnN0cmFpbnRzLnZpZGVvXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLnRoZW4obWVkaWFTdHJlYW0gPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWVkaWFTdHJlYW0uZ2V0VmlkZW9UcmFja3MoKS5mb3JFYWNoKCh0cmFjaykgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRyYWNrLnN0b3AoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yLmNvbnN0cmFpbnQudG9Mb3dlckNhc2UoKSA9PT0gJ2RldmljZWlkJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yTmFtZSA9IE9wZW5WaWR1RXJyb3JOYW1lLklOUFVUX0FVRElPX0RFVklDRV9OT1RfRk9VTkQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JNZXNzYWdlID0gXCJBdWRpbyBpbnB1dCBkZXZpY2Ugd2l0aCBkZXZpY2VJZCAnXCIgKyAoPENvbnN0cmFpbkRPTVN0cmluZ1BhcmFtZXRlcnM+KDxNZWRpYVRyYWNrQ29uc3RyYWludHM+Y29uc3RyYWludHMuYXVkaW8pLmRldmljZUlkISEpLmV4YWN0ICsgXCInIG5vdCBmb3VuZFwiO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck5hbWUgPSBPcGVuVmlkdUVycm9yTmFtZS5QVUJMSVNIRVJfUFJPUEVSVElFU19FUlJPUjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck1lc3NhZ2UgPSBcIkF1ZGlvIGlucHV0IGRldmljZSBkb2Vzbid0IHN1cHBvcnQgdGhlIHZhbHVlIHBhc3NlZCBmb3IgY29uc3RyYWludCAnXCIgKyBlcnJvci5jb25zdHJhaW50ICsgXCInXCI7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvckNhbGxiYWNrKG5ldyBPcGVuVmlkdUVycm9yKGVycm9yTmFtZSwgZXJyb3JNZXNzYWdlKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pLmNhdGNoKGUgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yLmNvbnN0cmFpbnQudG9Mb3dlckNhc2UoKSA9PT0gJ2RldmljZWlkJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yTmFtZSA9IE9wZW5WaWR1RXJyb3JOYW1lLklOUFVUX1ZJREVPX0RFVklDRV9OT1RfRk9VTkQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JNZXNzYWdlID0gXCJWaWRlbyBpbnB1dCBkZXZpY2Ugd2l0aCBkZXZpY2VJZCAnXCIgKyAoPENvbnN0cmFpbkRPTVN0cmluZ1BhcmFtZXRlcnM+KDxNZWRpYVRyYWNrQ29uc3RyYWludHM+Y29uc3RyYWludHMudmlkZW8pLmRldmljZUlkISEpLmV4YWN0ICsgXCInIG5vdCBmb3VuZFwiO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck5hbWUgPSBPcGVuVmlkdUVycm9yTmFtZS5QVUJMSVNIRVJfUFJPUEVSVElFU19FUlJPUjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck1lc3NhZ2UgPSBcIlZpZGVvIGlucHV0IGRldmljZSBkb2Vzbid0IHN1cHBvcnQgdGhlIHZhbHVlIHBhc3NlZCBmb3IgY29uc3RyYWludCAnXCIgKyBlcnJvci5jb25zdHJhaW50ICsgXCInXCI7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvckNhbGxiYWNrKG5ldyBPcGVuVmlkdUVycm9yKGVycm9yTmFtZSwgZXJyb3JNZXNzYWdlKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZWplY3QobmV3IE9wZW5WaWR1RXJyb3IoT3BlblZpZHVFcnJvck5hbWUuTk9fSU5QVVRfU09VUkNFX1NFVCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBcIlByb3BlcnRpZXMgJ2F1ZGlvU291cmNlJyBhbmQgJ3ZpZGVvU291cmNlJyBjYW5ub3QgYmUgc2V0IHRvIGZhbHNlIG9yIG51bGwgYXQgdGhlIHNhbWUgdGltZSB3aGVuIGNhbGxpbmcgJ09wZW5WaWR1LmluaXRQdWJsaXNoZXInXCIpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgLmNhdGNoKChlcnJvcjogT3BlblZpZHVFcnJvcikgPT4ge1xuICAgICAgICAgICAgICAgICAgICBlcnJvckNhbGxiYWNrKGVycm9yKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHJlZXN0YWJsaXNoU3RyZWFtUGxheWluZ0V2ZW50KCkge1xuICAgICAgICBpZiAodGhpcy5lZS5nZXRMaXN0ZW5lcnMoJ3N0cmVhbVBsYXlpbmcnKS5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICB0aGlzLmFkZFBsYXlFdmVudFRvRmlyc3RWaWRlbygpO1xuICAgICAgICB9XG4gICAgfVxuXG5cbiAgICAvKiBQcml2YXRlIG1ldGhvZHMgKi9cblxuICAgIHByaXZhdGUgc2V0UGVybWlzc2lvbkRpYWxvZ1RpbWVyKHdhaXRUaW1lOiBudW1iZXIpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5wZXJtaXNzaW9uRGlhbG9nVGltZW91dCA9IHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5lbWl0RXZlbnQoJ2FjY2Vzc0RpYWxvZ09wZW5lZCcsIFtdKTtcbiAgICAgICAgfSwgd2FpdFRpbWUpO1xuICAgIH1cblxuICAgIHByaXZhdGUgY2xlYXJQZXJtaXNzaW9uRGlhbG9nVGltZXIoc3RhcnRUaW1lOiBudW1iZXIsIHdhaXRUaW1lOiBudW1iZXIpOiB2b2lkIHtcbiAgICAgICAgY2xlYXJUaW1lb3V0KHRoaXMucGVybWlzc2lvbkRpYWxvZ1RpbWVvdXQpO1xuICAgICAgICBpZiAoKERhdGUubm93KCkgLSBzdGFydFRpbWUpID4gd2FpdFRpbWUpIHtcbiAgICAgICAgICAgIC8vIFBlcm1pc3Npb24gZGlhbG9nIHdhcyBzaG93biBhbmQgbm93IGlzIGNsb3NlZFxuICAgICAgICAgICAgdGhpcy5lbWl0RXZlbnQoJ2FjY2Vzc0RpYWxvZ0Nsb3NlZCcsIFtdKTtcbiAgICAgICAgfVxuICAgIH1cblxufSIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTctMjAxOCBPcGVuVmlkdSAoaHR0cHM6Ly9vcGVudmlkdS5pby8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuaW1wb3J0IHsgQ29ubmVjdGlvbiB9IGZyb20gJy4vQ29ubmVjdGlvbic7XG5pbXBvcnQgeyBPcGVuVmlkdSB9IGZyb20gJy4vT3BlblZpZHUnO1xuaW1wb3J0IHsgUHVibGlzaGVyIH0gZnJvbSAnLi9QdWJsaXNoZXInO1xuaW1wb3J0IHsgU3RyZWFtIH0gZnJvbSAnLi9TdHJlYW0nO1xuaW1wb3J0IHsgU3RyZWFtTWFuYWdlciB9IGZyb20gJy4vU3RyZWFtTWFuYWdlcic7XG5pbXBvcnQgeyBTdWJzY3JpYmVyIH0gZnJvbSAnLi9TdWJzY3JpYmVyJztcbmltcG9ydCB7IENhcGFiaWxpdGllcyB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvSW50ZXJmYWNlcy9QdWJsaWMvQ2FwYWJpbGl0aWVzJztcbmltcG9ydCB7IEV2ZW50RGlzcGF0Y2hlciB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvSW50ZXJmYWNlcy9QdWJsaWMvRXZlbnREaXNwYXRjaGVyJztcbmltcG9ydCB7IFNpZ25hbE9wdGlvbnMgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHVibGljL1NpZ25hbE9wdGlvbnMnO1xuaW1wb3J0IHsgU3Vic2NyaWJlclByb3BlcnRpZXMgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHVibGljL1N1YnNjcmliZXJQcm9wZXJ0aWVzJztcbmltcG9ydCB7IENvbm5lY3Rpb25PcHRpb25zIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9JbnRlcmZhY2VzL1ByaXZhdGUvQ29ubmVjdGlvbk9wdGlvbnMnO1xuaW1wb3J0IHsgT2JqTWFwIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9JbnRlcmZhY2VzL1ByaXZhdGUvT2JqTWFwJztcbmltcG9ydCB7IFNlc3Npb25PcHRpb25zIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9JbnRlcmZhY2VzL1ByaXZhdGUvU2Vzc2lvbk9wdGlvbnMnO1xuaW1wb3J0IHsgQ29ubmVjdGlvbkV2ZW50IH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvQ29ubmVjdGlvbkV2ZW50JztcbmltcG9ydCB7IFB1Ymxpc2hlclNwZWFraW5nRXZlbnQgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0V2ZW50cy9QdWJsaXNoZXJTcGVha2luZ0V2ZW50JztcbmltcG9ydCB7IFJlY29yZGluZ0V2ZW50IH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvUmVjb3JkaW5nRXZlbnQnO1xuaW1wb3J0IHsgU2Vzc2lvbkRpc2Nvbm5lY3RlZEV2ZW50IH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvU2Vzc2lvbkRpc2Nvbm5lY3RlZEV2ZW50JztcbmltcG9ydCB7IFNpZ25hbEV2ZW50IH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvU2lnbmFsRXZlbnQnO1xuaW1wb3J0IHsgU3RyZWFtRXZlbnQgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0V2ZW50cy9TdHJlYW1FdmVudCc7XG5pbXBvcnQgeyBTdHJlYW1Qcm9wZXJ0eUNoYW5nZWRFdmVudCB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1N0cmVhbVByb3BlcnR5Q2hhbmdlZEV2ZW50JztcbmltcG9ydCB7IE9wZW5WaWR1RXJyb3IsIE9wZW5WaWR1RXJyb3JOYW1lIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FbnVtcy9PcGVuVmlkdUVycm9yJztcbmltcG9ydCB7IFZpZGVvSW5zZXJ0TW9kZSB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRW51bXMvVmlkZW9JbnNlcnRNb2RlJztcblxuaW1wb3J0IHBsYXRmb3JtID0gcmVxdWlyZSgncGxhdGZvcm0nKTtcbmltcG9ydCBFdmVudEVtaXR0ZXIgPSByZXF1aXJlKCd3b2xmeTg3LWV2ZW50ZW1pdHRlcicpO1xuXG5cbi8qKlxuICogUmVwcmVzZW50cyBhIHZpZGVvIGNhbGwuIEl0IGNhbiBhbHNvIGJlIHNlZW4gYXMgYSB2aWRlb2NvbmZlcmVuY2Ugcm9vbSB3aGVyZSBtdWx0aXBsZSB1c2VycyBjYW4gY29ubmVjdC5cbiAqIFBhcnRpY2lwYW50cyB3aG8gcHVibGlzaCB0aGVpciB2aWRlb3MgdG8gYSBzZXNzaW9uIGNhbiBiZSBzZWVuIGJ5IHRoZSByZXN0IG9mIHVzZXJzIGNvbm5lY3RlZCB0byB0aGF0IHNwZWNpZmljIHNlc3Npb24uXG4gKiBJbml0aWFsaXplZCB3aXRoIFtbT3BlblZpZHUuaW5pdFNlc3Npb25dXSBtZXRob2RcbiAqL1xuZXhwb3J0IGNsYXNzIFNlc3Npb24gaW1wbGVtZW50cyBFdmVudERpc3BhdGNoZXIge1xuXG4gICAgLyoqXG4gICAgICogTG9jYWwgY29ubmVjdGlvbiB0byB0aGUgU2Vzc2lvbi4gVGhpcyBvYmplY3QgaXMgZGVmaW5lZCBvbmx5IGFmdGVyIFtbU2Vzc2lvbi5jb25uZWN0XV0gaGFzIGJlZW4gc3VjY2Vzc2Z1bGx5IGV4ZWN1dGVkLCBhbmQgY2FuIGJlIHJldHJpZXZlZCBzdWJzY3JpYmluZyB0byBgY29ubmVjdGlvbkNyZWF0ZWRgIGV2ZW50XG4gICAgICovXG4gICAgY29ubmVjdGlvbjogQ29ubmVjdGlvbjtcblxuICAgIC8qKlxuICAgICAqIFVuaXF1ZSBpZGVudGlmaWVyIG9mIHRoZSBTZXNzaW9uXG4gICAgICovXG4gICAgc2Vzc2lvbklkOiBzdHJpbmc7XG5cbiAgICAvKipcbiAgICAgKiBDb2xsZWN0aW9uIG9mIGFsbCBTdHJlYW1NYW5hZ2VycyBvZiB0aGlzIFNlc3Npb24gKFtbUHVibGlzaGVyXV0gYW5kIFtbU3Vic2NyaWJlcl1dKVxuICAgICAqL1xuICAgIHN0cmVhbU1hbmFnZXJzOiBTdHJlYW1NYW5hZ2VyW10gPSBbXTtcblxuICAgIC8qKlxuICAgICAqIE9iamVjdCBkZWZpbmluZyB0aGUgbWV0aG9kcyB0aGF0IHRoZSBjbGllbnQgaXMgYWJsZSB0byBjYWxsLiBUaGVzZSBhcmUgZGVmaW5lZCBieSB0aGUgcm9sZSBvZiB0aGUgdG9rZW4gdXNlZCB0byBjb25uZWN0IHRvIHRoZSBTZXNzaW9uLlxuICAgICAqIFRoaXMgb2JqZWN0IGlzIG9ubHkgZGVmaW5lZCBhZnRlciBbW1Nlc3Npb24uY29ubmVjdF1dIGhhcyBiZWVuIHN1Y2Nlc3NmdWxseSByZXNvbHZlZFxuICAgICAqL1xuICAgIGNhcGFiaWxpdGllczogQ2FwYWJpbGl0aWVzO1xuXG4gICAgLy8gVGhpcyBtYXAgaXMgb25seSB1c2VkIHRvIGF2b2lkIHJhY2UgY29uZGl0aW9uIGJldHdlZW4gJ2pvaW5Sb29tJyByZXNwb25zZSBhbmQgJ29uUGFydGljaXBhbnRQdWJsaXNoZWQnIG5vdGlmaWNhdGlvblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICByZW1vdGVTdHJlYW1zQ3JlYXRlZDogT2JqTWFwPGJvb2xlYW4+ID0ge307XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgcmVtb3RlQ29ubmVjdGlvbnM6IE9iak1hcDxDb25uZWN0aW9uPiA9IHt9O1xuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvcGVudmlkdTogT3BlblZpZHU7XG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIG9wdGlvbnM6IFNlc3Npb25PcHRpb25zO1xuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBzcGVha2luZ0V2ZW50c0VuYWJsZWQgPSBmYWxzZTtcblxuICAgIHByaXZhdGUgZWUgPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgY29uc3RydWN0b3Iob3BlbnZpZHU6IE9wZW5WaWR1KSB7XG4gICAgICAgIHRoaXMub3BlbnZpZHUgPSBvcGVudmlkdTtcbiAgICB9XG5cbiAgICBjb25uZWN0KHRva2VuOiBzdHJpbmcpOiBQcm9taXNlPGFueT47XG4gICAgY29ubmVjdCh0b2tlbjogc3RyaW5nLCBtZXRhZGF0YTogYW55KTogUHJvbWlzZTxhbnk+O1xuXG4gICAgLyoqXG4gICAgICogQ29ubmVjdHMgdG8gdGhlIHNlc3Npb24gdXNpbmcgYHRva2VuYC4gUGFyYW1ldGVyIGBtZXRhZGF0YWAgYWxsb3dzIHlvdSB0byBwYXNzIGV4dHJhIGRhdGEgdG8gc2hhcmUgd2l0aCBvdGhlciB1c2VycyB3aGVuXG4gICAgICogdGhleSByZWNlaXZlIGBzdHJlYW1DcmVhdGVkYCBldmVudC4gVGhlIHN0cnVjdHVyZSBvZiBgbWV0YWRhdGFgIHN0cmluZyBpcyB1cCB0byB5b3UgKG1heWJlIHNvbWUgc3RhbmRhcml6ZWQgZm9ybWF0XG4gICAgICogYXMgSlNPTiBvciBYTUwgaXMgYSBnb29kIGlkZWEpLCB0aGUgb25seSByZXN0cmljdGlvbiBpcyBhIG1heGltdW0gbGVuZ3RoIG9mIDEwMDAwIGNoYXJzLlxuICAgICAqXG4gICAgICogVGhpcyBtZXRhZGF0YSBpcyBub3QgY29uc2lkZXJlZCBzZWN1cmUsIGFzIGl0IGlzIGdlbmVyYXRlZCBpbiB0aGUgY2xpZW50IHNpZGUuIFRvIHBhc3Mgc2VjdXJpemVkIGRhdGEsIGFkZCBpdCBhcyBhIHBhcmFtZXRlciBpbiB0aGVcbiAgICAgKiB0b2tlbiBnZW5lcmF0aW9uIG9wZXJhdGlvbiAodGhyb3VnaCB0aGUgQVBJIFJFU1QsIG9wZW52aWR1LWphdmEtY2xpZW50IG9yIG9wZW52aWR1LW5vZGUtY2xpZW50KS5cbiAgICAgKlxuICAgICAqIE9ubHkgYWZ0ZXIgdGhlIHJldHVybmVkIFByb21pc2UgaXMgc3VjY2Vzc2Z1bGx5IHJlc29sdmVkIFtbU2Vzc2lvbi5jb25uZWN0aW9uXV0gb2JqZWN0IHdpbGwgYmUgYXZhaWxhYmxlIGFuZCBwcm9wZXJseSBkZWZpbmVkLlxuICAgICAqXG4gICAgICogIyMjIyBFdmVudHMgZGlzcGF0Y2hlZFxuICAgICAqXG4gICAgICogVGhlIFtbU2Vzc2lvbl1dIG9iamVjdCBvZiB0aGUgbG9jYWwgcGFydGljaXBhbnQgd2lsbCBmaXJzdCBkaXNwYXRjaCBvbmUgb3IgbW9yZSBgY29ubmVjdGlvbkNyZWF0ZWRgIGV2ZW50cyB1cG9uIHN1Y2Nlc3NmdWwgdGVybWluYXRpb24gb2YgdGhpcyBtZXRob2Q6XG4gICAgICogLSBGaXJzdCBvbmUgZm9yIHlvdXIgb3duIGxvY2FsIENvbm5lY3Rpb24gb2JqZWN0LCBzbyB5b3UgY2FuIHJldHJpZXZlIFtbU2Vzc2lvbi5jb25uZWN0aW9uXV0gcHJvcGVydHkuXG4gICAgICogLSBUaGVuIG9uZSBmb3IgZWFjaCByZW1vdGUgQ29ubmVjdGlvbiBwcmV2aW91c2x5IGNvbm5lY3RlZCB0byB0aGUgU2Vzc2lvbiwgaWYgYW55LiBBbnkgb3RoZXIgcmVtb3RlIHVzZXIgY29ubmVjdGluZyB0byB0aGUgU2Vzc2lvbiBhZnRlciB5b3UgaGF2ZVxuICAgICAqIHN1Y2Nlc3NmdWxseSBjb25uZWN0ZWQgd2lsbCBhbHNvIGRpc3BhdGNoIGEgYGNvbm5lY3Rpb25DcmVhdGVkYCBldmVudCB3aGVuIHRoZXkgZG8gc28uXG4gICAgICpcbiAgICAgKiBUaGUgW1tTZXNzaW9uXV0gb2JqZWN0IG9mIHRoZSBsb2NhbCBwYXJ0aWNpcGFudCB3aWxsIGFsc28gZGlzcGF0Y2ggYSBgc3RyZWFtQ3JlYXRlZGAgZXZlbnQgZm9yIGVhY2ggcmVtb3RlIGFjdGl2ZSBbW1B1Ymxpc2hlcl1dIHRoYXQgd2FzIGFscmVhZHkgc3RyZWFtaW5nXG4gICAgICogd2hlbiBjb25uZWN0aW5nLCBqdXN0IGFmdGVyIGRpc3BhdGNoaW5nIGFsbCByZW1vdGUgYGNvbm5lY3Rpb25DcmVhdGVkYCBldmVudHMuXG4gICAgICpcbiAgICAgKiBUaGUgW1tTZXNzaW9uXV0gb2JqZWN0IG9mIGV2ZXJ5IG90aGVyIHBhcnRpY2lwYW50IGNvbm5lY3RlZCB0byB0aGUgc2Vzc2lvbiB3aWxsIGRpc3BhdGNoIGEgYGNvbm5lY3Rpb25DcmVhdGVkYCBldmVudC5cbiAgICAgKlxuICAgICAqIFNlZSBbW0Nvbm5lY3Rpb25FdmVudF1dIGFuZCBbW1N0cmVhbUV2ZW50XV0gdG8gbGVhcm4gbW9yZS5cbiAgICAgKlxuICAgICAqIEByZXR1cm5zIEEgUHJvbWlzZSB0byB3aGljaCB5b3UgbXVzdCBzdWJzY3JpYmUgdGhhdCBpcyByZXNvbHZlZCBpZiB0aGUgdGhlIGNvbm5lY3Rpb24gdG8gdGhlIFNlc3Npb24gd2FzIHN1Y2Nlc3NmdWwgYW5kIHJlamVjdGVkIHdpdGggYW4gRXJyb3Igb2JqZWN0IGlmIG5vdFxuICAgICAqXG4gICAgICovXG4gICAgY29ubmVjdCh0b2tlbjogc3RyaW5nLCBtZXRhZGF0YT86IGFueSk6IFByb21pc2U8YW55PiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG5cbiAgICAgICAgICAgIHRoaXMucHJvY2Vzc1Rva2VuKHRva2VuKTtcblxuICAgICAgICAgICAgaWYgKHRoaXMub3BlbnZpZHUuY2hlY2tTeXN0ZW1SZXF1aXJlbWVudHMoKSkge1xuICAgICAgICAgICAgICAgIC8vIEVhcmx5IGNvbmZpZ3VyYXRpb24gdG8gZGVhY3RpdmF0ZSBhdXRvbWF0aWMgc3Vic2NyaXB0aW9uIHRvIHN0cmVhbXNcbiAgICAgICAgICAgICAgICB0aGlzLm9wdGlvbnMgPSB7XG4gICAgICAgICAgICAgICAgICAgIHNlc3Npb25JZDogdGhpcy5zZXNzaW9uSWQsXG4gICAgICAgICAgICAgICAgICAgIHBhcnRpY2lwYW50SWQ6IHRva2VuLFxuICAgICAgICAgICAgICAgICAgICBtZXRhZGF0YTogISFtZXRhZGF0YSA/IHRoaXMuc3RyaW5nQ2xpZW50TWV0YWRhdGEobWV0YWRhdGEpIDogJydcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIHRoaXMuY29ubmVjdEF1eCh0b2tlbikudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICB9KS5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJlamVjdChuZXcgT3BlblZpZHVFcnJvcihPcGVuVmlkdUVycm9yTmFtZS5CUk9XU0VSX05PVF9TVVBQT1JURUQsICdCcm93c2VyICcgKyBwbGF0Zm9ybS5uYW1lICsgJyAnICsgcGxhdGZvcm0udmVyc2lvbiArICcgaXMgbm90IHN1cHBvcnRlZCBpbiBPcGVuVmlkdScpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogTGVhdmVzIHRoZSBzZXNzaW9uLCBkZXN0cm95aW5nIGFsbCBzdHJlYW1zIGFuZCBkZWxldGluZyB0aGUgdXNlciBhcyBhIHBhcnRpY2lwYW50LlxuICAgICAqXG4gICAgICogIyMjIyBFdmVudHMgZGlzcGF0Y2hlZFxuICAgICAqXG4gICAgICogVGhlIFtbU2Vzc2lvbl1dIG9iamVjdCBvZiB0aGUgbG9jYWwgcGFydGljaXBhbnQgd2lsbCBkaXNwYXRjaCBhIGBzZXNzaW9uRGlzY29ubmVjdGVkYCBldmVudC5cbiAgICAgKiBUaGlzIGV2ZW50IHdpbGwgYXV0b21hdGljYWxseSB1bnN1YnNjcmliZSB0aGUgbGVhdmluZyBwYXJ0aWNpcGFudCBmcm9tIGV2ZXJ5IFN1YnNjcmliZXIgb2JqZWN0IG9mIHRoZSBzZXNzaW9uICh0aGlzIGluY2x1ZGVzIGNsb3NpbmcgdGhlIFdlYlJUQ1BlZXIgY29ubmVjdGlvbiBhbmQgZGlzcG9zaW5nIGFsbCBNZWRpYVN0cmVhbVRyYWNrcylcbiAgICAgKiBhbmQgYWxzbyBkZWxldGVzIGFueSBIVE1MIHZpZGVvIGVsZW1lbnQgYXNzb2NpYXRlZCB0byBlYWNoIFN1YnNjcmliZXIgKG9ubHkgdGhvc2UgW2NyZWF0ZWQgYnkgT3BlblZpZHUgQnJvd3Nlcl0oL2RvY3MvaG93LWRvLWkvbWFuYWdlLXZpZGVvcy8jbGV0LW9wZW52aWR1LXRha2UtY2FyZS1vZi10aGUtdmlkZW8tcGxheWVycykpLlxuICAgICAqIEZvciBldmVyeSB2aWRlbyByZW1vdmVkLCBlYWNoIFN1YnNjcmliZXIgb2JqZWN0IHdpbGwgZGlzcGF0Y2ggYSBgdmlkZW9FbGVtZW50RGVzdHJveWVkYCBldmVudC5cbiAgICAgKiBDYWxsIGBldmVudC5wcmV2ZW50RGVmYXVsdCgpYCB1cG9uIGV2ZW50IGBzZXNzaW9uRGlzY29ubmVjdGVkYCB0byBhdm9pZCB0aGlzIGJlaGF2aW9yIGFuZCB0YWtlIGNhcmUgb2YgZGlzcG9zaW5nIGFuZCBjbGVhbmluZyBhbGwgdGhlIFN1YnNjcmliZXIgb2JqZWN0cyB5b3Vyc2VsZi5cbiAgICAgKiBTZWUgW1tTZXNzaW9uRGlzY29ubmVjdGVkRXZlbnRdXSBhbmQgW1tWaWRlb0VsZW1lbnRFdmVudF1dIHRvIGxlYXJuIG1vcmUgdG8gbGVhcm4gbW9yZS5cbiAgICAgKlxuICAgICAqIFRoZSBbW1B1Ymxpc2hlcl1dIG9iamVjdCBvZiB0aGUgbG9jYWwgcGFydGljaXBhbnQgd2lsbCBkaXNwYXRjaCBhIGBzdHJlYW1EZXN0cm95ZWRgIGV2ZW50IGlmIHRoZXJlIGlzIGEgW1tQdWJsaXNoZXJdXSBvYmplY3QgcHVibGlzaGluZyB0byB0aGUgc2Vzc2lvbi5cbiAgICAgKiBUaGlzIGV2ZW50IHdpbGwgYXV0b21hdGljYWxseSBzdG9wIGFsbCBtZWRpYSB0cmFja3MgYW5kIGRlbGV0ZSBhbnkgSFRNTCB2aWRlbyBlbGVtZW50IGFzc29jaWF0ZWQgdG8gaXQgKG9ubHkgdGhvc2UgW2NyZWF0ZWQgYnkgT3BlblZpZHUgQnJvd3Nlcl0oL2RvY3MvaG93LWRvLWkvbWFuYWdlLXZpZGVvcy8jbGV0LW9wZW52aWR1LXRha2UtY2FyZS1vZi10aGUtdmlkZW8tcGxheWVycykpLlxuICAgICAqIEZvciBldmVyeSB2aWRlbyByZW1vdmVkLCB0aGUgUHVibGlzaGVyIG9iamVjdCB3aWxsIGRpc3BhdGNoIGEgYHZpZGVvRWxlbWVudERlc3Ryb3llZGAgZXZlbnQuXG4gICAgICogQ2FsbCBgZXZlbnQucHJldmVudERlZmF1bHQoKWAgdXBvbiBldmVudCBgc3RyZWFtRGVzdHJveWVkYCBpZiB5b3Ugd2FudCB0byBjbGVhbiB0aGUgUHVibGlzaGVyIG9iamVjdCBvbiB5b3VyIG93biBvciByZS1wdWJsaXNoIGl0IGluIGEgZGlmZmVyZW50IFNlc3Npb24gKHRvIGRvIHNvIGl0IGlzIGEgbWFuZGF0b3J5IHJlcXVpcmVtZW50IHRvIGNhbGwgYFNlc3Npb24udW5wdWJsaXNoKClgXG4gICAgICogb3IvYW5kIGBTZXNzaW9uLmRpc2Nvbm5lY3QoKWAgaW4gdGhlIHByZXZpb3VzIHNlc3Npb24pLiBTZWUgW1tTdHJlYW1FdmVudF1dIGFuZCBbW1ZpZGVvRWxlbWVudEV2ZW50XV0gdG8gbGVhcm4gbW9yZS5cbiAgICAgKlxuICAgICAqIFRoZSBbW1Nlc3Npb25dXSBvYmplY3Qgb2YgZXZlcnkgb3RoZXIgcGFydGljaXBhbnQgY29ubmVjdGVkIHRvIHRoZSBzZXNzaW9uIHdpbGwgZGlzcGF0Y2ggYSBgc3RyZWFtRGVzdHJveWVkYCBldmVudCBpZiB0aGUgZGlzY29ubmVjdGVkIHBhcnRpY2lwYW50IHdhcyBwdWJsaXNoaW5nLlxuICAgICAqIFRoaXMgZXZlbnQgd2lsbCBhdXRvbWF0aWNhbGx5IHVuc3Vic2NyaWJlIHRoZSBTdWJzY3JpYmVyIG9iamVjdCBmcm9tIHRoZSBzZXNzaW9uICh0aGlzIGluY2x1ZGVzIGNsb3NpbmcgdGhlIFdlYlJUQ1BlZXIgY29ubmVjdGlvbiBhbmQgZGlzcG9zaW5nIGFsbCBNZWRpYVN0cmVhbVRyYWNrcylcbiAgICAgKiBhbmQgYWxzbyBkZWxldGVzIGFueSBIVE1MIHZpZGVvIGVsZW1lbnQgYXNzb2NpYXRlZCB0byB0aGF0IFN1YnNjcmliZXIgKG9ubHkgdGhvc2UgW2NyZWF0ZWQgYnkgT3BlblZpZHUgQnJvd3Nlcl0oL2RvY3MvaG93LWRvLWkvbWFuYWdlLXZpZGVvcy8jbGV0LW9wZW52aWR1LXRha2UtY2FyZS1vZi10aGUtdmlkZW8tcGxheWVycykpLlxuICAgICAqIEZvciBldmVyeSB2aWRlbyByZW1vdmVkLCB0aGUgU3Vic2NyaWJlciBvYmplY3Qgd2lsbCBkaXNwYXRjaCBhIGB2aWRlb0VsZW1lbnREZXN0cm95ZWRgIGV2ZW50LlxuICAgICAqIENhbGwgYGV2ZW50LnByZXZlbnREZWZhdWx0KClgIHVwb24gZXZlbnQgYHN0cmVhbURlc3Ryb3llZGAgdG8gYXZvaWQgdGhpcyBkZWZhdWx0IGJlaGF2aW9yIGFuZCB0YWtlIGNhcmUgb2YgZGlzcG9zaW5nIGFuZCBjbGVhbmluZyB0aGUgU3Vic2NyaWJlciBvYmplY3QgeW91cnNlbGYuXG4gICAgICogU2VlIFtbU3RyZWFtRXZlbnRdXSBhbmQgW1tWaWRlb0VsZW1lbnRFdmVudF1dIHRvIGxlYXJuIG1vcmUuXG4gICAgICpcbiAgICAgKiBUaGUgW1tTZXNzaW9uXV0gb2JqZWN0IG9mIGV2ZXJ5IG90aGVyIHBhcnRpY2lwYW50IGNvbm5lY3RlZCB0byB0aGUgc2Vzc2lvbiB3aWxsIGRpc3BhdGNoIGEgYGNvbm5lY3Rpb25EZXN0cm95ZWRgIGV2ZW50IGluIGFueSBjYXNlLiBTZWUgW1tDb25uZWN0aW9uRXZlbnRdXSB0byBsZWFybiBtb3JlLlxuICAgICAqL1xuICAgIGRpc2Nvbm5lY3QoKTogdm9pZCB7XG4gICAgICAgIHRoaXMubGVhdmUoZmFsc2UsICdkaXNjb25uZWN0Jyk7XG4gICAgfVxuXG4gICAgc3Vic2NyaWJlKHN0cmVhbTogU3RyZWFtLCB0YXJnZXRFbGVtZW50OiBzdHJpbmcgfCBIVE1MRWxlbWVudCk6IFN1YnNjcmliZXI7XG4gICAgc3Vic2NyaWJlKHN0cmVhbTogU3RyZWFtLCB0YXJnZXRFbGVtZW50OiBzdHJpbmcgfCBIVE1MRWxlbWVudCwgcHJvcGVydGllczogU3Vic2NyaWJlclByb3BlcnRpZXMpOiBTdWJzY3JpYmVyO1xuICAgIHN1YnNjcmliZShzdHJlYW06IFN0cmVhbSwgdGFyZ2V0RWxlbWVudDogc3RyaW5nIHwgSFRNTEVsZW1lbnQsIGNvbXBsZXRpb25IYW5kbGVyOiAoZXJyb3I6IEVycm9yIHwgdW5kZWZpbmVkKSA9PiB2b2lkKTogU3Vic2NyaWJlcjtcbiAgICBzdWJzY3JpYmUoc3RyZWFtOiBTdHJlYW0sIHRhcmdldEVsZW1lbnQ6IHN0cmluZyB8IEhUTUxFbGVtZW50LCBwcm9wZXJ0aWVzOiBTdWJzY3JpYmVyUHJvcGVydGllcywgY29tcGxldGlvbkhhbmRsZXI6IChlcnJvcjogRXJyb3IgfCB1bmRlZmluZWQpID0+IHZvaWQpOiBTdWJzY3JpYmVyO1xuXG4gICAgLyoqXG4gICAgICogU3Vic2NyaWJlcyB0byBhIGBzdHJlYW1gLCBhZGRpbmcgYSBuZXcgSFRNTCB2aWRlbyBlbGVtZW50IHRvIERPTSB3aXRoIGBzdWJzY3JpYmVyUHJvcGVydGllc2Agc2V0dGluZ3MuIFRoaXMgbWV0aG9kIGlzIHVzdWFsbHkgY2FsbGVkIGluIHRoZSBjYWxsYmFjayBvZiBgc3RyZWFtQ3JlYXRlZGAgZXZlbnQuXG4gICAgICpcbiAgICAgKiAjIyMjIEV2ZW50cyBkaXNwYXRjaGVkXG4gICAgICpcbiAgICAgKiBUaGUgW1tTdWJzY3JpYmVyXV0gb2JqZWN0IHdpbGwgZGlzcGF0Y2ggYSBgdmlkZW9FbGVtZW50Q3JlYXRlZGAgZXZlbnQgb25jZSB0aGUgSFRNTCB2aWRlbyBlbGVtZW50IGhhcyBiZWVuIGFkZGVkIHRvIERPTSAob25seSBpZiB5b3VcbiAgICAgKiBbbGV0IE9wZW5WaWR1IHRha2UgY2FyZSBvZiB0aGUgdmlkZW8gcGxheWVyc10oL2RvY3MvaG93LWRvLWkvbWFuYWdlLXZpZGVvcy8jbGV0LW9wZW52aWR1LXRha2UtY2FyZS1vZi10aGUtdmlkZW8tcGxheWVycykpLiBTZWUgW1tWaWRlb0VsZW1lbnRFdmVudF1dIHRvIGxlYXJuIG1vcmUuXG4gICAgICpcbiAgICAgKiBUaGUgW1tTdWJzY3JpYmVyXV0gb2JqZWN0IHdpbGwgZGlzcGF0Y2ggYSBgc3RyZWFtUGxheWluZ2AgZXZlbnQgb25jZSB0aGUgcmVtb3RlIHN0cmVhbSBzdGFydHMgcGxheWluZy4gU2VlIFtbU3RyZWFtTWFuYWdlckV2ZW50XV0gdG8gbGVhcm4gbW9yZS5cbiAgICAgKlxuICAgICAqIEBwYXJhbSBzdHJlYW0gU3RyZWFtIG9iamVjdCB0byBzdWJzY3JpYmUgdG9cbiAgICAgKiBAcGFyYW0gdGFyZ2V0RWxlbWVudCBIVE1MIERPTSBlbGVtZW50IChvciBpdHMgYGlkYCBhdHRyaWJ1dGUpIGluIHdoaWNoIHRoZSB2aWRlbyBlbGVtZW50IG9mIHRoZSBTdWJzY3JpYmVyIHdpbGwgYmUgaW5zZXJ0ZWQgKHNlZSBbW1N1YnNjcmliZXJQcm9wZXJ0aWVzLmluc2VydE1vZGVdXSkuIElmICpudWxsKiBvciAqdW5kZWZpbmVkKiBubyBkZWZhdWx0IHZpZGVvIHdpbGwgYmUgY3JlYXRlZCBmb3IgdGhpcyBTdWJzY3JpYmVyLlxuICAgICAqIFlvdSBjYW4gYWx3YXlzIGNhbGwgbWV0aG9kIFtbU3Vic2NyaWJlci5hZGRWaWRlb0VsZW1lbnRdXSBvciBbW1N1YnNjcmliZXIuY3JlYXRlVmlkZW9FbGVtZW50XV0gdG8gbWFuYWdlIHRoZSB2aWRlbyBlbGVtZW50cyBvbiB5b3VyIG93biAoc2VlIFtNYW5hZ2UgdmlkZW8gcGxheWVyc10oL2RvY3MvaG93LWRvLWkvbWFuYWdlLXZpZGVvcykgc2VjdGlvbilcbiAgICAgKiBAcGFyYW0gY29tcGxldGlvbkhhbmRsZXIgYGVycm9yYCBwYXJhbWV0ZXIgaXMgbnVsbCBpZiBgc3Vic2NyaWJlYCBzdWNjZWVkcywgYW5kIGlzIGRlZmluZWQgaWYgaXQgZmFpbHMuXG4gICAgICovXG4gICAgc3Vic2NyaWJlKHN0cmVhbTogU3RyZWFtLCB0YXJnZXRFbGVtZW50OiBzdHJpbmcgfCBIVE1MRWxlbWVudCwgcGFyYW0zPzogKChlcnJvcjogRXJyb3IgfCB1bmRlZmluZWQpID0+IHZvaWQpIHwgU3Vic2NyaWJlclByb3BlcnRpZXMsIHBhcmFtND86ICgoZXJyb3I6IEVycm9yIHwgdW5kZWZpbmVkKSA9PiB2b2lkKSk6IFN1YnNjcmliZXIge1xuICAgICAgICBsZXQgcHJvcGVydGllczogU3Vic2NyaWJlclByb3BlcnRpZXMgPSB7fTtcbiAgICAgICAgaWYgKCEhcGFyYW0zICYmIHR5cGVvZiBwYXJhbTMgIT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgIHByb3BlcnRpZXMgPSB7XG4gICAgICAgICAgICAgICAgaW5zZXJ0TW9kZTogKHR5cGVvZiBwYXJhbTMuaW5zZXJ0TW9kZSAhPT0gJ3VuZGVmaW5lZCcpID8gKCh0eXBlb2YgcGFyYW0zLmluc2VydE1vZGUgPT09ICdzdHJpbmcnKSA/IFZpZGVvSW5zZXJ0TW9kZVtwYXJhbTMuaW5zZXJ0TW9kZV0gOiBwcm9wZXJ0aWVzLmluc2VydE1vZGUpIDogVmlkZW9JbnNlcnRNb2RlLkFQUEVORCxcbiAgICAgICAgICAgICAgICBzdWJzY3JpYmVUb0F1ZGlvOiAodHlwZW9mIHBhcmFtMy5zdWJzY3JpYmVUb0F1ZGlvICE9PSAndW5kZWZpbmVkJykgPyBwYXJhbTMuc3Vic2NyaWJlVG9BdWRpbyA6IHRydWUsXG4gICAgICAgICAgICAgICAgc3Vic2NyaWJlVG9WaWRlbzogKHR5cGVvZiBwYXJhbTMuc3Vic2NyaWJlVG9WaWRlbyAhPT0gJ3VuZGVmaW5lZCcpID8gcGFyYW0zLnN1YnNjcmliZVRvVmlkZW8gOiB0cnVlXG4gICAgICAgICAgICB9O1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcHJvcGVydGllcyA9IHtcbiAgICAgICAgICAgICAgICBpbnNlcnRNb2RlOiBWaWRlb0luc2VydE1vZGUuQVBQRU5ELFxuICAgICAgICAgICAgICAgIHN1YnNjcmliZVRvQXVkaW86IHRydWUsXG4gICAgICAgICAgICAgICAgc3Vic2NyaWJlVG9WaWRlbzogdHJ1ZVxuICAgICAgICAgICAgfTtcbiAgICAgICAgfVxuXG4gICAgICAgIGxldCBjb21wbGV0aW9uSGFuZGxlcjogKGVycm9yOiBFcnJvciB8IHVuZGVmaW5lZCkgPT4gdm9pZDtcbiAgICAgICAgaWYgKCEhcGFyYW0zICYmICh0eXBlb2YgcGFyYW0zID09PSAnZnVuY3Rpb24nKSkge1xuICAgICAgICAgICAgY29tcGxldGlvbkhhbmRsZXIgPSBwYXJhbTM7XG4gICAgICAgIH0gZWxzZSBpZiAoISFwYXJhbTQpIHtcbiAgICAgICAgICAgIGNvbXBsZXRpb25IYW5kbGVyID0gcGFyYW00O1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc29sZS5pbmZvKCdTdWJzY3JpYmluZyB0byAnICsgc3RyZWFtLmNvbm5lY3Rpb24uY29ubmVjdGlvbklkKTtcblxuICAgICAgICBzdHJlYW0uc3Vic2NyaWJlKClcbiAgICAgICAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oJ1N1YnNjcmliZWQgY29ycmVjdGx5IHRvICcgKyBzdHJlYW0uY29ubmVjdGlvbi5jb25uZWN0aW9uSWQpO1xuICAgICAgICAgICAgICAgIGlmIChjb21wbGV0aW9uSGFuZGxlciAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbXBsZXRpb25IYW5kbGVyKHVuZGVmaW5lZCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKGNvbXBsZXRpb25IYW5kbGVyICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgY29tcGxldGlvbkhhbmRsZXIoZXJyb3IpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICBjb25zdCBzdWJzY3JpYmVyID0gbmV3IFN1YnNjcmliZXIoc3RyZWFtLCB0YXJnZXRFbGVtZW50LCBwcm9wZXJ0aWVzKTtcbiAgICAgICAgaWYgKCEhc3Vic2NyaWJlci50YXJnZXRFbGVtZW50KSB7XG4gICAgICAgICAgICBzdHJlYW0uc3RyZWFtTWFuYWdlci5jcmVhdGVWaWRlb0VsZW1lbnQoc3Vic2NyaWJlci50YXJnZXRFbGVtZW50LCA8VmlkZW9JbnNlcnRNb2RlPnByb3BlcnRpZXMuaW5zZXJ0TW9kZSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHN1YnNjcmliZXI7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBQcm9taXNpZmllZCB2ZXJzaW9uIG9mIFtbU2Vzc2lvbi5zdWJzY3JpYmVdXVxuICAgICAqL1xuICAgIHN1YnNjcmliZUFzeW5jKHN0cmVhbTogU3RyZWFtLCB0YXJnZXRFbGVtZW50OiBzdHJpbmcgfCBIVE1MRWxlbWVudCk6IFByb21pc2U8U3Vic2NyaWJlcj47XG4gICAgc3Vic2NyaWJlQXN5bmMoc3RyZWFtOiBTdHJlYW0sIHRhcmdldEVsZW1lbnQ6IHN0cmluZyB8IEhUTUxFbGVtZW50LCBwcm9wZXJ0aWVzOiBTdWJzY3JpYmVyUHJvcGVydGllcyk6IFByb21pc2U8U3Vic2NyaWJlcj47XG5cbiAgICBzdWJzY3JpYmVBc3luYyhzdHJlYW06IFN0cmVhbSwgdGFyZ2V0RWxlbWVudDogc3RyaW5nIHwgSFRNTEVsZW1lbnQsIHByb3BlcnRpZXM/OiBTdWJzY3JpYmVyUHJvcGVydGllcyk6IFByb21pc2U8U3Vic2NyaWJlcj4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2U8U3Vic2NyaWJlcj4oKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuXG4gICAgICAgICAgICBsZXQgc3Vic2NyaWJlcjogU3Vic2NyaWJlcjtcblxuICAgICAgICAgICAgY29uc3QgY2FsbGJhY2sgPSAoZXJyb3I6IEVycm9yKSA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKCEhZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICByZXNvbHZlKHN1YnNjcmliZXIpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIGlmICghIXByb3BlcnRpZXMpIHtcbiAgICAgICAgICAgICAgICBzdWJzY3JpYmVyID0gdGhpcy5zdWJzY3JpYmUoc3RyZWFtLCB0YXJnZXRFbGVtZW50LCBwcm9wZXJ0aWVzLCBjYWxsYmFjayk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHN1YnNjcmliZXIgPSB0aGlzLnN1YnNjcmliZShzdHJlYW0sIHRhcmdldEVsZW1lbnQsIGNhbGxiYWNrKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICB9KTtcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFVuc3Vic2NyaWJlcyBmcm9tIGBzdWJzY3JpYmVyYCwgYXV0b21hdGljYWxseSByZW1vdmluZyBpdHMgYXNzb2NpYXRlZCBIVE1MIHZpZGVvIGVsZW1lbnRzLlxuICAgICAqXG4gICAgICogIyMjIyBFdmVudHMgZGlzcGF0Y2hlZFxuICAgICAqXG4gICAgICogVGhlIFtbU3Vic2NyaWJlcl1dIG9iamVjdCB3aWxsIGRpc3BhdGNoIGEgYHZpZGVvRWxlbWVudERlc3Ryb3llZGAgZXZlbnQgZm9yIGVhY2ggdmlkZW8gYXNzb2NpYXRlZCB0byBpdCB0aGF0IHdhcyByZW1vdmVkIGZyb20gRE9NLlxuICAgICAqIE9ubHkgdmlkZW9zIFtjcmVhdGVkIGJ5IE9wZW5WaWR1IEJyb3dzZXJdKC9kb2NzL2hvdy1kby1pL21hbmFnZS12aWRlb3MvI2xldC1vcGVudmlkdS10YWtlLWNhcmUtb2YtdGhlLXZpZGVvLXBsYXllcnMpKSB3aWxsIGJlIGF1dG9tYXRpY2FsbHkgcmVtb3ZlZFxuICAgICAqXG4gICAgICogU2VlIFtbVmlkZW9FbGVtZW50RXZlbnRdXSB0byBsZWFybiBtb3JlXG4gICAgICovXG4gICAgdW5zdWJzY3JpYmUoc3Vic2NyaWJlcjogU3Vic2NyaWJlcik6IHZvaWQge1xuICAgICAgICBjb25zdCBjb25uZWN0aW9uSWQgPSBzdWJzY3JpYmVyLnN0cmVhbS5jb25uZWN0aW9uLmNvbm5lY3Rpb25JZDtcblxuICAgICAgICBjb25zb2xlLmluZm8oJ1Vuc3Vic2NyaWJpbmcgZnJvbSAnICsgY29ubmVjdGlvbklkKTtcblxuICAgICAgICB0aGlzLm9wZW52aWR1LnNlbmRSZXF1ZXN0KFxuICAgICAgICAgICAgJ3Vuc3Vic2NyaWJlRnJvbVZpZGVvJyxcbiAgICAgICAgICAgIHsgc2VuZGVyOiBzdWJzY3JpYmVyLnN0cmVhbS5jb25uZWN0aW9uLmNvbm5lY3Rpb25JZCB9LFxuICAgICAgICAgICAgKGVycm9yLCByZXNwb25zZSkgPT4ge1xuICAgICAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKCdFcnJvciB1bnN1YnNjcmliaW5nIGZyb20gJyArIGNvbm5lY3Rpb25JZCwgZXJyb3IpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbygnVW5zdWJzY3JpYmVkIGNvcnJlY3RseSBmcm9tICcgKyBjb25uZWN0aW9uSWQpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBzdWJzY3JpYmVyLnN0cmVhbS5kaXNwb3NlV2ViUnRjUGVlcigpO1xuICAgICAgICAgICAgICAgIHN1YnNjcmliZXIuc3RyZWFtLmRpc3Bvc2VNZWRpYVN0cmVhbSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICApO1xuICAgICAgICBzdWJzY3JpYmVyLnN0cmVhbS5zdHJlYW1NYW5hZ2VyLnJlbW92ZUFsbFZpZGVvcygpO1xuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogUHVibGlzaGVzIHRvIHRoZSBTZXNzaW9uIHRoZSBQdWJsaXNoZXIgb2JqZWN0XG4gICAgICpcbiAgICAgKiAjIyMjIEV2ZW50cyBkaXNwYXRjaGVkXG4gICAgICpcbiAgICAgKiBUaGUgbG9jYWwgW1tQdWJsaXNoZXJdXSBvYmplY3Qgd2lsbCBkaXNwYXRjaCBhIGBzdHJlYW1DcmVhdGVkYCBldmVudCB1cG9uIHN1Y2Nlc3NmdWwgdGVybWluYXRpb24gb2YgdGhpcyBtZXRob2QuIFNlZSBbW1N0cmVhbUV2ZW50XV0gdG8gbGVhcm4gbW9yZS5cbiAgICAgKlxuICAgICAqIFRoZSBsb2NhbCBbW1B1Ymxpc2hlcl1dIG9iamVjdCB3aWxsIGRpc3BhdGNoIGEgYHN0cmVhbVBsYXlpbmdgIG9uY2UgdGhlIG1lZGlhIHN0cmVhbSBzdGFydHMgcGxheWluZy4gU2VlIFtbU3RyZWFtTWFuYWdlckV2ZW50XV0gdG8gbGVhcm4gbW9yZS5cbiAgICAgKlxuICAgICAqIFRoZSBbW1Nlc3Npb25dXSBvYmplY3Qgb2YgZXZlcnkgb3RoZXIgcGFydGljaXBhbnQgY29ubmVjdGVkIHRvIHRoZSBzZXNzaW9uIHdpbGwgZGlzcGF0Y2ggYSBgc3RyZWFtQ3JlYXRlZGAgZXZlbnQgc28gdGhleSBjYW4gc3Vic2NyaWJlIHRvIGl0LiBTZWUgW1tTdHJlYW1FdmVudF1dIHRvIGxlYXJuIG1vcmUuXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyBBIFByb21pc2UgKHRvIHdoaWNoIHlvdSBjYW4gb3B0aW9uYWxseSBzdWJzY3JpYmUgdG8pIHRoYXQgaXMgcmVzb2x2ZWQgb25seSBhZnRlciB0aGUgcHVibGlzaGVyIHdhcyBzdWNjZXNzZnVsbHkgcHVibGlzaGVkIGFuZCByZWplY3RlZCB3aXRoIGFuIEVycm9yIG9iamVjdCBpZiBub3RcbiAgICAgKi9cbiAgICBwdWJsaXNoKHB1Ymxpc2hlcjogUHVibGlzaGVyKTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIHB1Ymxpc2hlci5zZXNzaW9uID0gdGhpcztcbiAgICAgICAgICAgIHB1Ymxpc2hlci5zdHJlYW0uc2Vzc2lvbiA9IHRoaXM7XG5cbiAgICAgICAgICAgIGlmICghcHVibGlzaGVyLnN0cmVhbS5wdWJsaXNoZWRPbmNlKSB7XG4gICAgICAgICAgICAgICAgLy8gJ1Nlc3Npb24udW5wdWJsaXNoKFB1Ymxpc2hlciknIGhhcyBOT1QgYmVlbiBjYWxsZWRcbiAgICAgICAgICAgICAgICB0aGlzLmNvbm5lY3Rpb24uYWRkU3RyZWFtKHB1Ymxpc2hlci5zdHJlYW0pO1xuICAgICAgICAgICAgICAgIHB1Ymxpc2hlci5zdHJlYW0ucHVibGlzaCgpXG4gICAgICAgICAgICAgICAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAvLyAnU2Vzc2lvbi51bnB1Ymxpc2goUHVibGlzaGVyKScgaGFzIGJlZW4gY2FsbGVkLiBNdXN0IGluaXRpYWxpemUgYWdhaW4gUHVibGlzaGVyXG4gICAgICAgICAgICAgICAgcHVibGlzaGVyLmluaXRpYWxpemUoKVxuICAgICAgICAgICAgICAgICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbm5lY3Rpb24uYWRkU3RyZWFtKHB1Ymxpc2hlci5zdHJlYW0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgcHVibGlzaGVyLnJlZXN0YWJsaXNoU3RyZWFtUGxheWluZ0V2ZW50KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBwdWJsaXNoZXIuc3RyZWFtLnB1Ymxpc2goKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgfSkuY2F0Y2goKGVycm9yKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBVbnB1Ymxpc2hlcyBmcm9tIHRoZSBTZXNzaW9uIHRoZSBQdWJsaXNoZXIgb2JqZWN0LlxuICAgICAqXG4gICAgICogIyMjIyBFdmVudHMgZGlzcGF0Y2hlZFxuICAgICAqXG4gICAgICogVGhlIFtbUHVibGlzaGVyXV0gb2JqZWN0IG9mIHRoZSBsb2NhbCBwYXJ0aWNpcGFudCB3aWxsIGRpc3BhdGNoIGEgYHN0cmVhbURlc3Ryb3llZGAgZXZlbnQuXG4gICAgICogVGhpcyBldmVudCB3aWxsIGF1dG9tYXRpY2FsbHkgc3RvcCBhbGwgbWVkaWEgdHJhY2tzIGFuZCBkZWxldGUgYW55IEhUTUwgdmlkZW8gZWxlbWVudCBhc3NvY2lhdGVkIHRvIHRoaXMgUHVibGlzaGVyXG4gICAgICogKG9ubHkgdGhvc2UgdmlkZW9zIFtjcmVhdGVkIGJ5IE9wZW5WaWR1IEJyb3dzZXJdKC9kb2NzL2hvdy1kby1pL21hbmFnZS12aWRlb3MvI2xldC1vcGVudmlkdS10YWtlLWNhcmUtb2YtdGhlLXZpZGVvLXBsYXllcnMpKS5cbiAgICAgKiBGb3IgZXZlcnkgdmlkZW8gcmVtb3ZlZCwgdGhlIFB1Ymxpc2hlciBvYmplY3Qgd2lsbCBkaXNwYXRjaCBhIGB2aWRlb0VsZW1lbnREZXN0cm95ZWRgIGV2ZW50LlxuICAgICAqIENhbGwgYGV2ZW50LnByZXZlbnREZWZhdWx0KClgIHVwb24gZXZlbnQgYHN0cmVhbURlc3Ryb3llZGAgaWYgeW91IHdhbnQgdG8gY2xlYW4gdGhlIFB1Ymxpc2hlciBvYmplY3Qgb24geW91ciBvd24gb3IgcmUtcHVibGlzaCBpdCBpbiBhIGRpZmZlcmVudCBTZXNzaW9uLlxuICAgICAqXG4gICAgICogVGhlIFtbU2Vzc2lvbl1dIG9iamVjdCBvZiBldmVyeSBvdGhlciBwYXJ0aWNpcGFudCBjb25uZWN0ZWQgdG8gdGhlIHNlc3Npb24gd2lsbCBkaXNwYXRjaCBhIGBzdHJlYW1EZXN0cm95ZWRgIGV2ZW50LlxuICAgICAqIFRoaXMgZXZlbnQgd2lsbCBhdXRvbWF0aWNhbGx5IHVuc3Vic2NyaWJlIHRoZSBTdWJzY3JpYmVyIG9iamVjdCBmcm9tIHRoZSBzZXNzaW9uICh0aGlzIGluY2x1ZGVzIGNsb3NpbmcgdGhlIFdlYlJUQ1BlZXIgY29ubmVjdGlvbiBhbmQgZGlzcG9zaW5nIGFsbCBNZWRpYVN0cmVhbVRyYWNrcykgYW5kXG4gICAgICogZGVsZXRlIGFueSBIVE1MIHZpZGVvIGVsZW1lbnQgYXNzb2NpYXRlZCB0byBpdCAob25seSB0aG9zZSBbY3JlYXRlZCBieSBPcGVuVmlkdSBCcm93c2VyXSgvZG9jcy9ob3ctZG8taS9tYW5hZ2UtdmlkZW9zLyNsZXQtb3BlbnZpZHUtdGFrZS1jYXJlLW9mLXRoZS12aWRlby1wbGF5ZXJzKSkuXG4gICAgICogRm9yIGV2ZXJ5IHZpZGVvIHJlbW92ZWQsIHRoZSBTdWJzY3JpYmVyIG9iamVjdCB3aWxsIGRpc3BhdGNoIGEgYHZpZGVvRWxlbWVudERlc3Ryb3llZGAgZXZlbnQuXG4gICAgICogQ2FsbCBgZXZlbnQucHJldmVudERlZmF1bHQoKWAgdXBvbiBldmVudCBgc3RyZWFtRGVzdHJveWVkYCB0byBhdm9pZCB0aGlzIGRlZmF1bHQgYmVoYXZpb3IgYW5kIHRha2UgY2FyZSBvZiBkaXNwb3NpbmcgYW5kIGNsZWFuaW5nIHRoZSBTdWJzY3JpYmVyIG9iamVjdCBvbiB5b3VyIG93bi5cbiAgICAgKlxuICAgICAqIFNlZSBbW1N0cmVhbUV2ZW50XV0gYW5kIFtbVmlkZW9FbGVtZW50RXZlbnRdXSB0byBsZWFybiBtb3JlLlxuICAgICAqL1xuICAgIHVucHVibGlzaChwdWJsaXNoZXI6IFB1Ymxpc2hlcik6IHZvaWQge1xuXG4gICAgICAgIGNvbnN0IHN0cmVhbSA9IHB1Ymxpc2hlci5zdHJlYW07XG5cbiAgICAgICAgaWYgKCFzdHJlYW0uY29ubmVjdGlvbikge1xuICAgICAgICAgICAgY29uc29sZS5lcnJvcignVGhlIGFzc29jaWF0ZWQgQ29ubmVjdGlvbiBvYmplY3Qgb2YgdGhpcyBQdWJsaXNoZXIgaXMgbnVsbCcsIHN0cmVhbSk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH0gZWxzZSBpZiAoc3RyZWFtLmNvbm5lY3Rpb24gIT09IHRoaXMuY29ubmVjdGlvbikge1xuICAgICAgICAgICAgY29uc29sZS5lcnJvcignVGhlIGFzc29jaWF0ZWQgQ29ubmVjdGlvbiBvYmplY3Qgb2YgdGhpcyBQdWJsaXNoZXIgaXMgbm90IHlvdXIgbG9jYWwgQ29ubmVjdGlvbi4nICtcbiAgICAgICAgICAgICAgICBcIk9ubHkgbW9kZXJhdG9ycyBjYW4gZm9yY2UgdW5wdWJsaXNoIG9uIHJlbW90ZSBTdHJlYW1zIHZpYSAnZm9yY2VVbnB1Ymxpc2gnIG1ldGhvZFwiLCBzdHJlYW0pO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9IGVsc2Uge1xuXG4gICAgICAgICAgICBjb25zb2xlLmluZm8oJ1VucHVibGlzaGluZyBsb2NhbCBtZWRpYSAoJyArIHN0cmVhbS5jb25uZWN0aW9uLmNvbm5lY3Rpb25JZCArICcpJyk7XG5cbiAgICAgICAgICAgIHRoaXMub3BlbnZpZHUuc2VuZFJlcXVlc3QoJ3VucHVibGlzaFZpZGVvJywgKGVycm9yLCByZXNwb25zZSkgPT4ge1xuICAgICAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKGVycm9yKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oJ01lZGlhIHVucHVibGlzaGVkIGNvcnJlY3RseScpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICBzdHJlYW0uZGlzcG9zZVdlYlJ0Y1BlZXIoKTtcbiAgICAgICAgICAgIGRlbGV0ZSBzdHJlYW0uY29ubmVjdGlvbi5zdHJlYW07XG5cbiAgICAgICAgICAgIGNvbnN0IHN0cmVhbUV2ZW50ID0gbmV3IFN0cmVhbUV2ZW50KHRydWUsIHB1Ymxpc2hlciwgJ3N0cmVhbURlc3Ryb3llZCcsIHB1Ymxpc2hlci5zdHJlYW0sICd1bnB1Ymxpc2gnKTtcbiAgICAgICAgICAgIHB1Ymxpc2hlci5lbWl0RXZlbnQoJ3N0cmVhbURlc3Ryb3llZCcsIFtzdHJlYW1FdmVudF0pO1xuICAgICAgICAgICAgc3RyZWFtRXZlbnQuY2FsbERlZmF1bHRCZWhhdmlvcigpO1xuICAgICAgICB9XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBGb3JjZXMgc29tZSB1c2VyIHRvIGxlYXZlIHRoZSBzZXNzaW9uXG4gICAgICpcbiAgICAgKiAjIyMjIEV2ZW50cyBkaXNwYXRjaGVkXG4gICAgICpcbiAgICAgKiBUaGUgYmVoYXZpb3IgaXMgdGhlIHNhbWUgYXMgd2hlbiBzb21lIHVzZXIgY2FsbHMgW1tTZXNzaW9uLmRpc2Nvbm5lY3RdXSwgYnV0IGByZWFzb25gIHByb3BlcnR5IGluIGFsbCBldmVudHMgd2lsbCBiZSBgXCJmb3JjZURpc2Nvbm5lY3RCeVVzZXJcImAuXG4gICAgICpcbiAgICAgKiBUaGUgW1tTZXNzaW9uXV0gb2JqZWN0IG9mIGV2ZXJ5IHBhcnRpY2lwYW50IHdpbGwgZGlzcGF0Y2ggYSBgc3RyZWFtRGVzdHJveWVkYCBldmVudCBpZiB0aGUgZXZpY3RlZCB1c2VyIHdhcyBwdWJsaXNoaW5nIGEgc3RyZWFtLCB3aXRoIHByb3BlcnR5IGByZWFzb25gIHNldCB0byBgXCJmb3JjZURpc2Nvbm5lY3RCeVVzZXJcImAuXG4gICAgICogVGhlIFtbU2Vzc2lvbl1dIG9iamVjdCBvZiBldmVyeSBwYXJ0aWNpcGFudCBleGNlcHQgdGhlIGV2aWN0ZWQgb25lIHdpbGwgZGlzcGF0Y2ggYSBgY29ubmVjdGlvbkRlc3Ryb3llZGAgZXZlbnQgZm9yIHRoZSBldmljdGVkIHVzZXIsIHdpdGggcHJvcGVydHkgYHJlYXNvbmAgc2V0IHRvIGBcImZvcmNlRGlzY29ubmVjdEJ5VXNlclwiYC5cbiAgICAgKlxuICAgICAqIElmIGFueSwgdGhlIFtbUHVibGlzaGVyXV0gb2JqZWN0IG9mIHRoZSBldmljdGVkIHBhcnRpY2lwYW50IHdpbGwgYWxzbyBkaXNwYXRjaCBhIGBzdHJlYW1EZXN0cm95ZWRgIGV2ZW50IHdpdGggcHJvcGVydHkgYHJlYXNvbmAgc2V0IHRvIGBcImZvcmNlRGlzY29ubmVjdEJ5VXNlclwiYC5cbiAgICAgKiBUaGUgW1tTZXNzaW9uXV0gb2JqZWN0IG9mIHRoZSBldmljdGVkIHBhcnRpY2lwYW50IHdpbGwgZGlzcGF0Y2ggYSBgc2Vzc2lvbkRpc2Nvbm5lY3RlZGAgZXZlbnQgd2l0aCBwcm9wZXJ0eSBgcmVhc29uYCBzZXQgdG8gYFwiZm9yY2VEaXNjb25uZWN0QnlVc2VyXCJgLlxuICAgICAqXG4gICAgICogU2VlIFtbU3RyZWFtRXZlbnRdXSwgW1tDb25uZWN0aW9uRXZlbnRdXSBhbmQgW1tTZXNzaW9uRGlzY29ubmVjdGVkRXZlbnRdXSB0byBsZWFybiBtb3JlLlxuICAgICAqXG4gICAgICogQHJldHVybnMgQSBQcm9taXNlICh0byB3aGljaCB5b3UgY2FuIG9wdGlvbmFsbHkgc3Vic2NyaWJlIHRvKSB0aGF0IGlzIHJlc29sdmVkIG9ubHkgYWZ0ZXIgdGhlIHBhcnRpY2lwYW50IGhhcyBiZWVuIHN1Y2Nlc3NmdWxseSBldmljdGVkIGZyb20gdGhlIHNlc3Npb24gYW5kIHJlamVjdGVkIHdpdGggYW4gRXJyb3Igb2JqZWN0IGlmIG5vdFxuICAgICAqL1xuICAgIGZvcmNlRGlzY29ubmVjdChjb25uZWN0aW9uOiBDb25uZWN0aW9uKTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIGNvbnNvbGUuaW5mbygnRm9yY2luZyBkaXNjb25uZWN0IGZvciBjb25uZWN0aW9uICcgKyBjb25uZWN0aW9uLmNvbm5lY3Rpb25JZCk7XG4gICAgICAgICAgICB0aGlzLm9wZW52aWR1LnNlbmRSZXF1ZXN0KFxuICAgICAgICAgICAgICAgICdmb3JjZURpc2Nvbm5lY3QnLFxuICAgICAgICAgICAgICAgIHsgY29ubmVjdGlvbklkOiBjb25uZWN0aW9uLmNvbm5lY3Rpb25JZCB9LFxuICAgICAgICAgICAgICAgIChlcnJvciwgcmVzcG9uc2UpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKCdFcnJvciBmb3JjaW5nIGRpc2Nvbm5lY3QgZm9yIENvbm5lY3Rpb24gJyArIGNvbm5lY3Rpb24uY29ubmVjdGlvbklkLCBlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZXJyb3IuY29kZSA9PT0gNDAxKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KG5ldyBPcGVuVmlkdUVycm9yKE9wZW5WaWR1RXJyb3JOYW1lLk9QRU5WSURVX1BFUk1JU1NJT05fREVOSUVELCBcIllvdSBkb24ndCBoYXZlIHBlcm1pc3Npb25zIHRvIGZvcmNlIGEgZGlzY29ubmVjdGlvblwiKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oJ0ZvcmNpbmcgZGlzY29ubmVjdCBjb3JyZWN0bHkgZm9yIENvbm5lY3Rpb24gJyArIGNvbm5lY3Rpb24uY29ubmVjdGlvbklkKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogRm9yY2VzIHNvbWUgdXNlciB0byB1bnB1Ymxpc2ggYSBTdHJlYW1cbiAgICAgKlxuICAgICAqICMjIyMgRXZlbnRzIGRpc3BhdGNoZWRcbiAgICAgKlxuICAgICAqIFRoZSBiZWhhdmlvciBpcyB0aGUgc2FtZSBhcyB3aGVuIHNvbWUgdXNlciBjYWxscyBbW1Nlc3Npb24udW5wdWJsaXNoXV0sIGJ1dCBgcmVhc29uYCBwcm9wZXJ0eSBpbiBhbGwgZXZlbnRzIHdpbGwgYmUgYFwiZm9yY2VVbnB1Ymxpc2hCeVVzZXJcImBcbiAgICAgKlxuICAgICAqIFRoZSBbW1Nlc3Npb25dXSBvYmplY3Qgb2YgZXZlcnkgcGFydGljaXBhbnQgd2lsbCBkaXNwYXRjaCBhIGBzdHJlYW1EZXN0cm95ZWRgIGV2ZW50IHdpdGggcHJvcGVydHkgYHJlYXNvbmAgc2V0IHRvIGBcImZvcmNlRGlzY29ubmVjdEJ5VXNlclwiYFxuICAgICAqXG4gICAgICogVGhlIFtbUHVibGlzaGVyXV0gb2JqZWN0IG9mIHRoZSBhZmZlY3RlZCBwYXJ0aWNpcGFudCB3aWxsIGFsc28gZGlzcGF0Y2ggYSBgc3RyZWFtRGVzdHJveWVkYCBldmVudCB3aXRoIHByb3BlcnR5IGByZWFzb25gIHNldCB0byBgXCJmb3JjZURpc2Nvbm5lY3RCeVVzZXJcImBcbiAgICAgKlxuICAgICAqIFNlZSBbW1N0cmVhbUV2ZW50XV0gdG8gbGVhcm4gbW9yZS5cbiAgICAgKlxuICAgICAqIEByZXR1cm5zIEEgUHJvbWlzZSAodG8gd2hpY2ggeW91IGNhbiBvcHRpb25hbGx5IHN1YnNjcmliZSB0bykgdGhhdCBpcyByZXNvbHZlZCBvbmx5IGFmdGVyIHRoZSByZW1vdGUgU3RyZWFtIGhhcyBiZWVuIHN1Y2Nlc3NmdWxseSB1bnB1Ymxpc2hlZCBmcm9tIHRoZSBzZXNzaW9uIGFuZCByZWplY3RlZCB3aXRoIGFuIEVycm9yIG9iamVjdCBpZiBub3RcbiAgICAgKi9cbiAgICBmb3JjZVVucHVibGlzaChzdHJlYW06IFN0cmVhbSk6IFByb21pc2U8YW55PiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICBjb25zb2xlLmluZm8oJ0ZvcmNpbmcgdW5wdWJsaXNoIGZvciBzdHJlYW0gJyArIHN0cmVhbS5zdHJlYW1JZCk7XG4gICAgICAgICAgICB0aGlzLm9wZW52aWR1LnNlbmRSZXF1ZXN0KFxuICAgICAgICAgICAgICAgICdmb3JjZVVucHVibGlzaCcsXG4gICAgICAgICAgICAgICAgeyBzdHJlYW1JZDogc3RyZWFtLnN0cmVhbUlkIH0sXG4gICAgICAgICAgICAgICAgKGVycm9yLCByZXNwb25zZSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBpZiAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ0Vycm9yIGZvcmNpbmcgdW5wdWJsaXNoIGZvciBTdHJlYW0gJyArIHN0cmVhbS5zdHJlYW1JZCwgZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yLmNvZGUgPT09IDQwMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChuZXcgT3BlblZpZHVFcnJvcihPcGVuVmlkdUVycm9yTmFtZS5PUEVOVklEVV9QRVJNSVNTSU9OX0RFTklFRCwgXCJZb3UgZG9uJ3QgaGF2ZSBwZXJtaXNzaW9ucyB0byBmb3JjZSBhbiB1bnB1Ymxpc2hpbmdcIikpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5pbmZvKCdGb3JjaW5nIHVucHVibGlzaCBjb3JyZWN0bHkgZm9yIFN0cmVhbSAnICsgc3RyZWFtLnN0cmVhbUlkKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogU2VuZHMgb25lIHNpZ25hbC4gYHNpZ25hbGAgb2JqZWN0IGhhcyB0aGUgZm9sbG93aW5nIG9wdGlvbmFsIHByb3BlcnRpZXM6XG4gICAgICogYGBganNvblxuICAgICAqIHtkYXRhOnN0cmluZywgdG86Q29ubmVjdGlvbltdLCB0eXBlOnN0cmluZ31cbiAgICAgKiBgYGBcbiAgICAgKiBBbGwgdXNlcnMgc3Vic2NyaWJlZCB0byB0aGF0IHNpZ25hbCAoYHNlc3Npb24ub24oJ3NpZ25hbDp0eXBlJywgLi4uKWAgb3IgYHNlc3Npb24ub24oJ3NpZ25hbCcsIC4uLilgIGZvciBhbGwgc2lnbmFscykgYW5kIHdob3NlIENvbm5lY3Rpb24gb2JqZWN0cyBhcmUgaW4gYHRvYCBhcnJheSB3aWxsIHJlY2VpdmUgaXQuIFRoZWlyIGxvY2FsXG4gICAgICogU2Vzc2lvbiBvYmplY3RzIHdpbGwgZGlzcGF0Y2ggYSBgc2lnbmFsYCBvciBgc2lnbmFsOnR5cGVgIGV2ZW50LiBTZWUgW1tTaWduYWxFdmVudF1dIHRvIGxlYXJuIG1vcmUuXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyBBIFByb21pc2UgKHRvIHdoaWNoIHlvdSBjYW4gb3B0aW9uYWxseSBzdWJzY3JpYmUgdG8pIHRoYXQgaXMgcmVzb2x2ZWQgaWYgdGhlIG1lc3NhZ2Ugc3VjY2Vzc2Z1bGx5IHJlYWNoZWQgb3BlbnZpZHUtc2VydmVyIGFuZCByZWplY3RlZCB3aXRoIGFuIEVycm9yIG9iamVjdCBpZiBub3QuIF9UaGlzIGRvZXNuJ3RcbiAgICAgKiBtZWFuIHRoYXQgb3BlbnZpZHUtc2VydmVyIGNvdWxkIHJlc2VuZCB0aGUgbWVzc2FnZSB0byBhbGwgdGhlIGxpc3RlZCByZWNlaXZlcnMuX1xuICAgICAqL1xuICAgIC8qIHRzbGludDpkaXNhYmxlOm5vLXN0cmluZy1saXRlcmFsICovXG4gICAgc2lnbmFsKHNpZ25hbDogU2lnbmFsT3B0aW9ucyk6IFByb21pc2U8YW55PiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG5cbiAgICAgICAgICAgIGNvbnN0IHNpZ25hbE1lc3NhZ2UgPSB7fTtcblxuICAgICAgICAgICAgaWYgKHNpZ25hbC50byAmJiBzaWduYWwudG8ubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgICAgIGNvbnN0IGNvbm5lY3Rpb25JZHM6IHN0cmluZ1tdID0gW107XG5cbiAgICAgICAgICAgICAgICBzaWduYWwudG8uZm9yRWFjaChjb25uZWN0aW9uID0+IHtcbiAgICAgICAgICAgICAgICAgICAgY29ubmVjdGlvbklkcy5wdXNoKGNvbm5lY3Rpb24uY29ubmVjdGlvbklkKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICBzaWduYWxNZXNzYWdlWyd0byddID0gY29ubmVjdGlvbklkcztcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgc2lnbmFsTWVzc2FnZVsndG8nXSA9IFtdO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBzaWduYWxNZXNzYWdlWydkYXRhJ10gPSBzaWduYWwuZGF0YSA/IHNpZ25hbC5kYXRhIDogJyc7XG4gICAgICAgICAgICBzaWduYWxNZXNzYWdlWyd0eXBlJ10gPSBzaWduYWwudHlwZSA/IHNpZ25hbC50eXBlIDogJyc7XG5cbiAgICAgICAgICAgIHRoaXMub3BlbnZpZHUuc2VuZFJlcXVlc3QoJ3NlbmRNZXNzYWdlJywge1xuICAgICAgICAgICAgICAgIG1lc3NhZ2U6IEpTT04uc3RyaW5naWZ5KHNpZ25hbE1lc3NhZ2UpXG4gICAgICAgICAgICB9LCAoZXJyb3IsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKCEhZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgIH1cbiAgICAvKiB0c2xpbnQ6ZW5hYmxlOm5vLXN0cmluZy1saXRlcmFsICovXG5cblxuICAgIC8qKlxuICAgICAqIFNlZSBbW0V2ZW50RGlzcGF0Y2hlci5vbl1dXG4gICAgICovXG4gICAgb24odHlwZTogc3RyaW5nLCBoYW5kbGVyOiAoZXZlbnQ6IFNlc3Npb25EaXNjb25uZWN0ZWRFdmVudCB8IFNpZ25hbEV2ZW50IHwgU3RyZWFtRXZlbnQgfCBDb25uZWN0aW9uRXZlbnQgfCBQdWJsaXNoZXJTcGVha2luZ0V2ZW50IHwgUmVjb3JkaW5nRXZlbnQpID0+IHZvaWQpOiBFdmVudERpc3BhdGNoZXIge1xuXG4gICAgICAgIHRoaXMuZWUub24odHlwZSwgZXZlbnQgPT4ge1xuICAgICAgICAgICAgaWYgKGV2ZW50KSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5pbmZvKFwiRXZlbnQgJ1wiICsgdHlwZSArIFwiJyB0cmlnZ2VyZWQgYnkgJ1Nlc3Npb24nXCIsIGV2ZW50KTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5pbmZvKFwiRXZlbnQgJ1wiICsgdHlwZSArIFwiJyB0cmlnZ2VyZWQgYnkgJ1Nlc3Npb24nXCIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaGFuZGxlcihldmVudCk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGlmICh0eXBlID09PSAncHVibGlzaGVyU3RhcnRTcGVha2luZycgfHwgdHlwZSA9PT0gJ3B1Ymxpc2hlclN0b3BTcGVha2luZycpIHtcbiAgICAgICAgICAgIHRoaXMuc3BlYWtpbmdFdmVudHNFbmFibGVkID0gdHJ1ZTtcbiAgICAgICAgICAgIC8vIElmIHRoZXJlIGFyZSBhbHJlYWR5IGF2YWlsYWJsZSByZW1vdGUgc3RyZWFtcywgZW5hYmxlIGhhcmsgJ3NwZWFraW5nJyBldmVudCBpbiBhbGwgb2YgdGhlbVxuICAgICAgICAgICAgZm9yIChjb25zdCBjb25uZWN0aW9uSWQgaW4gdGhpcy5yZW1vdGVDb25uZWN0aW9ucykge1xuICAgICAgICAgICAgICAgIGNvbnN0IHN0ciA9IHRoaXMucmVtb3RlQ29ubmVjdGlvbnNbY29ubmVjdGlvbklkXS5zdHJlYW07XG4gICAgICAgICAgICAgICAgaWYgKCEhc3RyICYmICFzdHIuc3BlZWNoRXZlbnQgJiYgc3RyLmhhc0F1ZGlvKSB7XG4gICAgICAgICAgICAgICAgICAgIHN0ci5lbmFibGVTcGVha2luZ0V2ZW50cygpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogU2VlIFtbRXZlbnREaXNwYXRjaGVyLm9uY2VdXVxuICAgICAqL1xuICAgIG9uY2UodHlwZTogc3RyaW5nLCBoYW5kbGVyOiAoZXZlbnQ6IFNlc3Npb25EaXNjb25uZWN0ZWRFdmVudCB8IFNpZ25hbEV2ZW50IHwgU3RyZWFtRXZlbnQgfCBDb25uZWN0aW9uRXZlbnQgfCBQdWJsaXNoZXJTcGVha2luZ0V2ZW50IHwgUmVjb3JkaW5nRXZlbnQpID0+IHZvaWQpOiBTZXNzaW9uIHtcblxuICAgICAgICB0aGlzLmVlLm9uY2UodHlwZSwgZXZlbnQgPT4ge1xuICAgICAgICAgICAgaWYgKGV2ZW50KSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5pbmZvKFwiRXZlbnQgJ1wiICsgdHlwZSArIFwiJyB0cmlnZ2VyZWQgYnkgJ1Nlc3Npb24nXCIsIGV2ZW50KTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5pbmZvKFwiRXZlbnQgJ1wiICsgdHlwZSArIFwiJyB0cmlnZ2VyZWQgYnkgJ1Nlc3Npb24nXCIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaGFuZGxlcihldmVudCk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGlmICh0eXBlID09PSAncHVibGlzaGVyU3RhcnRTcGVha2luZycgfHwgdHlwZSA9PT0gJ3B1Ymxpc2hlclN0b3BTcGVha2luZycpIHtcbiAgICAgICAgICAgIHRoaXMuc3BlYWtpbmdFdmVudHNFbmFibGVkID0gdHJ1ZTtcbiAgICAgICAgICAgIC8vIElmIHRoZXJlIGFyZSBhbHJlYWR5IGF2YWlsYWJsZSByZW1vdGUgc3RyZWFtcywgZW5hYmxlIGhhcmsgaW4gYWxsIG9mIHRoZW1cbiAgICAgICAgICAgIGZvciAoY29uc3QgY29ubmVjdGlvbklkIGluIHRoaXMucmVtb3RlQ29ubmVjdGlvbnMpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBzdHIgPSB0aGlzLnJlbW90ZUNvbm5lY3Rpb25zW2Nvbm5lY3Rpb25JZF0uc3RyZWFtO1xuICAgICAgICAgICAgICAgIGlmICghIXN0ciAmJiAhc3RyLnNwZWVjaEV2ZW50ICYmIHN0ci5oYXNBdWRpbykge1xuICAgICAgICAgICAgICAgICAgICBzdHIuZW5hYmxlT25jZVNwZWFraW5nRXZlbnRzKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBTZWUgW1tFdmVudERpc3BhdGNoZXIub2ZmXV1cbiAgICAgKi9cbiAgICBvZmYodHlwZTogc3RyaW5nLCBoYW5kbGVyPzogKGV2ZW50OiBTZXNzaW9uRGlzY29ubmVjdGVkRXZlbnQgfCBTaWduYWxFdmVudCB8IFN0cmVhbUV2ZW50IHwgQ29ubmVjdGlvbkV2ZW50IHwgUHVibGlzaGVyU3BlYWtpbmdFdmVudCB8IFJlY29yZGluZ0V2ZW50KSA9PiB2b2lkKTogU2Vzc2lvbiB7XG5cbiAgICAgICAgaWYgKCFoYW5kbGVyKSB7XG4gICAgICAgICAgICB0aGlzLmVlLnJlbW92ZUFsbExpc3RlbmVycyh0eXBlKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuZWUub2ZmKHR5cGUsIGhhbmRsZXIpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHR5cGUgPT09ICdwdWJsaXNoZXJTdGFydFNwZWFraW5nJyB8fCB0eXBlID09PSAncHVibGlzaGVyU3RvcFNwZWFraW5nJykge1xuICAgICAgICAgICAgdGhpcy5zcGVha2luZ0V2ZW50c0VuYWJsZWQgPSBmYWxzZTtcblxuICAgICAgICAgICAgLy8gSWYgdGhlcmUgYXJlIGFscmVhZHkgYXZhaWxhYmxlIHJlbW90ZSBzdHJlYW1zLCBkaXNhYmxhZSBoYXJrIGluIGFsbCBvZiB0aGVtXG4gICAgICAgICAgICBmb3IgKGNvbnN0IGNvbm5lY3Rpb25JZCBpbiB0aGlzLnJlbW90ZUNvbm5lY3Rpb25zKSB7XG4gICAgICAgICAgICAgICAgY29uc3Qgc3RyID0gdGhpcy5yZW1vdGVDb25uZWN0aW9uc1tjb25uZWN0aW9uSWRdLnN0cmVhbTtcbiAgICAgICAgICAgICAgICBpZiAoISFzdHIgJiYgISFzdHIuc3BlZWNoRXZlbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgc3RyLmRpc2FibGVTcGVha2luZ0V2ZW50cygpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cblxuICAgIC8qIEhpZGRlbiBtZXRob2RzICovXG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgb25QYXJ0aWNpcGFudEpvaW5lZChyZXNwb25zZTogQ29ubmVjdGlvbk9wdGlvbnMpOiB2b2lkIHtcbiAgICAgICAgLy8gQ29ubmVjdGlvbiBzaG91bGRuJ3QgZXhpc3RcbiAgICAgICAgdGhpcy5nZXRDb25uZWN0aW9uKHJlc3BvbnNlLmlkLCAnJylcblxuICAgICAgICAgICAgLnRoZW4oY29ubmVjdGlvbiA9PiB7XG4gICAgICAgICAgICAgICAgY29uc29sZS53YXJuKCdDb25uZWN0aW9uICcgKyByZXNwb25zZS5pZCArICcgYWxyZWFkeSBleGlzdHMgaW4gY29ubmVjdGlvbnMgbGlzdCcpO1xuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIC5jYXRjaChvcGVuVmlkdUVycm9yID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCBjb25uZWN0aW9uID0gbmV3IENvbm5lY3Rpb24odGhpcywgcmVzcG9uc2UpO1xuICAgICAgICAgICAgICAgIHRoaXMucmVtb3RlQ29ubmVjdGlvbnNbcmVzcG9uc2UuaWRdID0gY29ubmVjdGlvbjtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnY29ubmVjdGlvbkNyZWF0ZWQnLCBbbmV3IENvbm5lY3Rpb25FdmVudChmYWxzZSwgdGhpcywgJ2Nvbm5lY3Rpb25DcmVhdGVkJywgY29ubmVjdGlvbiwgJycpXSk7XG4gICAgICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgb25QYXJ0aWNpcGFudExlZnQobXNnKTogdm9pZCB7XG4gICAgICAgIHRoaXMuZ2V0UmVtb3RlQ29ubmVjdGlvbihtc2cuY29ubmVjdGlvbklkLCAnUmVtb3RlIGNvbm5lY3Rpb24gJyArIG1zZy5jb25uZWN0aW9uSWQgKyBcIiB1bmtub3duIHdoZW4gJ29uUGFydGljaXBhbnRMZWZ0Jy4gXCIgK1xuICAgICAgICAgICAgJ0V4aXN0aW5nIHJlbW90ZSBjb25uZWN0aW9uczogJyArIEpTT04uc3RyaW5naWZ5KE9iamVjdC5rZXlzKHRoaXMucmVtb3RlQ29ubmVjdGlvbnMpKSlcblxuICAgICAgICAgICAgLnRoZW4oY29ubmVjdGlvbiA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKCEhY29ubmVjdGlvbi5zdHJlYW0pIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3Qgc3RyZWFtID0gY29ubmVjdGlvbi5zdHJlYW07XG5cbiAgICAgICAgICAgICAgICAgICAgY29uc3Qgc3RyZWFtRXZlbnQgPSBuZXcgU3RyZWFtRXZlbnQodHJ1ZSwgdGhpcywgJ3N0cmVhbURlc3Ryb3llZCcsIHN0cmVhbSwgbXNnLnJlYXNvbik7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdzdHJlYW1EZXN0cm95ZWQnLCBbc3RyZWFtRXZlbnRdKTtcbiAgICAgICAgICAgICAgICAgICAgc3RyZWFtRXZlbnQuY2FsbERlZmF1bHRCZWhhdmlvcigpO1xuXG4gICAgICAgICAgICAgICAgICAgIGRlbGV0ZSB0aGlzLnJlbW90ZVN0cmVhbXNDcmVhdGVkW3N0cmVhbS5zdHJlYW1JZF07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGRlbGV0ZSB0aGlzLnJlbW90ZUNvbm5lY3Rpb25zW2Nvbm5lY3Rpb24uY29ubmVjdGlvbklkXTtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnY29ubmVjdGlvbkRlc3Ryb3llZCcsIFtuZXcgQ29ubmVjdGlvbkV2ZW50KGZhbHNlLCB0aGlzLCAnY29ubmVjdGlvbkRlc3Ryb3llZCcsIGNvbm5lY3Rpb24sIG1zZy5yZWFzb24pXSk7XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLmNhdGNoKG9wZW5WaWR1RXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3Iob3BlblZpZHVFcnJvcik7XG4gICAgICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgb25QYXJ0aWNpcGFudFB1Ymxpc2hlZChyZXNwb25zZTogQ29ubmVjdGlvbk9wdGlvbnMpOiB2b2lkIHtcblxuICAgICAgICBjb25zdCBhZnRlckNvbm5lY3Rpb25Gb3VuZCA9IChjb25uZWN0aW9uKSA9PiB7XG4gICAgICAgICAgICB0aGlzLnJlbW90ZUNvbm5lY3Rpb25zW2Nvbm5lY3Rpb24uY29ubmVjdGlvbklkXSA9IGNvbm5lY3Rpb247XG5cbiAgICAgICAgICAgIGlmICghdGhpcy5yZW1vdGVTdHJlYW1zQ3JlYXRlZFtjb25uZWN0aW9uLnN0cmVhbS5zdHJlYW1JZF0pIHtcbiAgICAgICAgICAgICAgICAvLyBBdm9pZCByYWNlIGNvbmRpdGlvbiBiZXR3ZWVuIHN0cmVhbS5zdWJzY3JpYmUoKSBpbiBcIm9uUGFydGljaXBhbnRQdWJsaXNoZWRcIiBhbmQgaW4gXCJqb2luUm9vbVwiIHJwYyBjYWxsYmFja1xuICAgICAgICAgICAgICAgIC8vIFRoaXMgY29uZGl0aW9uIGlzIGZhbHNlIGlmIG9wZW52aWR1LXNlcnZlciBzZW5kcyBcInBhcnRpY2lwYW50UHVibGlzaGVkXCIgZXZlbnQgdG8gYSBzdWJzY3JpYmVyIHBhcnRpY2lwYW50IHRoYXQgaGFzXG4gICAgICAgICAgICAgICAgLy8gYWxyZWFkeSBzdWJzY3JpYmVkIHRvIGNlcnRhaW4gc3RyZWFtIGluIHRoZSBjYWxsYmFjayBvZiBcImpvaW5Sb29tXCIgbWV0aG9kXG5cbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnc3RyZWFtQ3JlYXRlZCcsIFtuZXcgU3RyZWFtRXZlbnQoZmFsc2UsIHRoaXMsICdzdHJlYW1DcmVhdGVkJywgY29ubmVjdGlvbi5zdHJlYW0sICcnKV0pO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLnJlbW90ZVN0cmVhbXNDcmVhdGVkW2Nvbm5lY3Rpb24uc3RyZWFtLnN0cmVhbUlkXSA9IHRydWU7XG4gICAgICAgIH07XG5cbiAgICAgICAgLy8gR2V0IHRoZSBleGlzdGluZyBDb25uZWN0aW9uIGNyZWF0ZWQgb24gJ29uUGFydGljaXBhbnRKb2luZWQnIGZvclxuICAgICAgICAvLyBleGlzdGluZyBwYXJ0aWNpcGFudHMgb3IgY3JlYXRlIGEgbmV3IG9uZSBmb3IgbmV3IHBhcnRpY2lwYW50c1xuICAgICAgICBsZXQgY29ubmVjdGlvbjogQ29ubmVjdGlvbjtcbiAgICAgICAgdGhpcy5nZXRSZW1vdGVDb25uZWN0aW9uKHJlc3BvbnNlLmlkLCBcIlJlbW90ZSBjb25uZWN0aW9uICdcIiArIHJlc3BvbnNlLmlkICsgXCInIHVua25vd24gd2hlbiAnb25QYXJ0aWNpcGFudFB1Ymxpc2hlZCcuIFwiICtcbiAgICAgICAgICAgICdFeGlzdGluZyByZW1vdGUgY29ubmVjdGlvbnM6ICcgKyBKU09OLnN0cmluZ2lmeShPYmplY3Qua2V5cyh0aGlzLnJlbW90ZUNvbm5lY3Rpb25zKSkpXG5cbiAgICAgICAgICAgIC50aGVuKGNvbiA9PiB7XG4gICAgICAgICAgICAgICAgLy8gVXBkYXRlIGV4aXN0aW5nIENvbm5lY3Rpb25cbiAgICAgICAgICAgICAgICBjb25uZWN0aW9uID0gY29uO1xuICAgICAgICAgICAgICAgIHJlc3BvbnNlLm1ldGFkYXRhID0gY29uLmRhdGE7XG4gICAgICAgICAgICAgICAgY29ubmVjdGlvbi5vcHRpb25zID0gcmVzcG9uc2U7XG4gICAgICAgICAgICAgICAgY29ubmVjdGlvbi5pbml0UmVtb3RlU3RyZWFtcyhyZXNwb25zZS5zdHJlYW1zKTtcbiAgICAgICAgICAgICAgICBhZnRlckNvbm5lY3Rpb25Gb3VuZChjb25uZWN0aW9uKTtcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAuY2F0Y2gob3BlblZpZHVFcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgLy8gQ3JlYXRlIG5ldyBDb25uZWN0aW9uXG4gICAgICAgICAgICAgICAgY29ubmVjdGlvbiA9IG5ldyBDb25uZWN0aW9uKHRoaXMsIHJlc3BvbnNlKTtcbiAgICAgICAgICAgICAgICBhZnRlckNvbm5lY3Rpb25Gb3VuZChjb25uZWN0aW9uKTtcbiAgICAgICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvblBhcnRpY2lwYW50VW5wdWJsaXNoZWQobXNnKTogdm9pZCB7XG4gICAgICAgIGlmIChtc2cuY29ubmVjdGlvbklkID09PSB0aGlzLmNvbm5lY3Rpb24uY29ubmVjdGlvbklkKSB7XG4gICAgICAgICAgICAvLyBZb3VyIHN0cmVhbSBoYXMgYmVlbiBmb3JjZWRseSB1bnB1Ymxpc2hlZCBmcm9tIHRoZSBzZXNzaW9uXG4gICAgICAgICAgICB0aGlzLnN0b3BQdWJsaXNoZXJTdHJlYW0obXNnLnJlYXNvbik7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLmdldFJlbW90ZUNvbm5lY3Rpb24obXNnLmNvbm5lY3Rpb25JZCwgXCJSZW1vdGUgY29ubmVjdGlvbiAnXCIgKyBtc2cuY29ubmVjdGlvbklkICsgXCInIHVua25vd24gd2hlbiAnb25QYXJ0aWNpcGFudFVucHVibGlzaGVkJy4gXCIgK1xuICAgICAgICAgICAgICAgICdFeGlzdGluZyByZW1vdGUgY29ubmVjdGlvbnM6ICcgKyBKU09OLnN0cmluZ2lmeShPYmplY3Qua2V5cyh0aGlzLnJlbW90ZUNvbm5lY3Rpb25zKSkpXG5cbiAgICAgICAgICAgICAgICAudGhlbihjb25uZWN0aW9uID0+IHtcblxuICAgICAgICAgICAgICAgICAgICBjb25zdCBzdHJlYW1FdmVudCA9IG5ldyBTdHJlYW1FdmVudCh0cnVlLCB0aGlzLCAnc3RyZWFtRGVzdHJveWVkJywgY29ubmVjdGlvbi5zdHJlYW0sIG1zZy5yZWFzb24pO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnc3RyZWFtRGVzdHJveWVkJywgW3N0cmVhbUV2ZW50XSk7XG4gICAgICAgICAgICAgICAgICAgIHN0cmVhbUV2ZW50LmNhbGxEZWZhdWx0QmVoYXZpb3IoKTtcblxuICAgICAgICAgICAgICAgICAgICAvLyBEZWxldGluZyB0aGUgcmVtb3RlIHN0cmVhbVxuICAgICAgICAgICAgICAgICAgICBjb25zdCBzdHJlYW1JZDogc3RyaW5nID0gY29ubmVjdGlvbi5zdHJlYW0uc3RyZWFtSWQ7XG4gICAgICAgICAgICAgICAgICAgIGRlbGV0ZSB0aGlzLnJlbW90ZVN0cmVhbXNDcmVhdGVkW3N0cmVhbUlkXTtcbiAgICAgICAgICAgICAgICAgICAgY29ubmVjdGlvbi5yZW1vdmVTdHJlYW0oc3RyZWFtSWQpO1xuICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgLmNhdGNoKG9wZW5WaWR1RXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKG9wZW5WaWR1RXJyb3IpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIG9uUGFydGljaXBhbnRFdmljdGVkKG1zZyk6IHZvaWQge1xuICAgICAgICBpZiAobXNnLmNvbm5lY3Rpb25JZCA9PT0gdGhpcy5jb25uZWN0aW9uLmNvbm5lY3Rpb25JZCkge1xuICAgICAgICAgICAgLy8gWW91IGhhdmUgYmVlbiBldmljdGVkIGZyb20gdGhlIHNlc3Npb25cbiAgICAgICAgICAgIGlmICghIXRoaXMuc2Vzc2lvbklkICYmICF0aGlzLmNvbm5lY3Rpb24uZGlzcG9zZWQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmxlYXZlKHRydWUsIG1zZy5yZWFzb24pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIG9uTmV3TWVzc2FnZShtc2cpOiB2b2lkIHtcblxuICAgICAgICBjb25zb2xlLmluZm8oJ05ldyBzaWduYWw6ICcgKyBKU09OLnN0cmluZ2lmeShtc2cpKTtcblxuICAgICAgICB0aGlzLmdldENvbm5lY3Rpb24obXNnLmZyb20sIFwiQ29ubmVjdGlvbiAnXCIgKyBtc2cuZnJvbSArIFwiJyB1bmtub3cgd2hlbiAnb25OZXdNZXNzYWdlJy4gRXhpc3RpbmcgcmVtb3RlIGNvbm5lY3Rpb25zOiBcIlxuICAgICAgICAgICAgKyBKU09OLnN0cmluZ2lmeShPYmplY3Qua2V5cyh0aGlzLnJlbW90ZUNvbm5lY3Rpb25zKSkgKyAnLiBFeGlzdGluZyBsb2NhbCBjb25uZWN0aW9uOiAnICsgdGhpcy5jb25uZWN0aW9uLmNvbm5lY3Rpb25JZClcblxuICAgICAgICAgICAgLnRoZW4oY29ubmVjdGlvbiA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3NpZ25hbCcsIFtuZXcgU2lnbmFsRXZlbnQodGhpcywgbXNnLnR5cGUsIG1zZy5kYXRhLCBjb25uZWN0aW9uKV0pO1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdzaWduYWw6JyArIG1zZy50eXBlLCBbbmV3IFNpZ25hbEV2ZW50KHRoaXMsIG1zZy50eXBlLCBtc2cuZGF0YSwgY29ubmVjdGlvbildKTtcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAuY2F0Y2gob3BlblZpZHVFcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihvcGVuVmlkdUVycm9yKTtcbiAgICAgICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvblN0cmVhbVByb3BlcnR5Q2hhbmdlZChtc2cpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5nZXRSZW1vdGVDb25uZWN0aW9uKG1zZy5jb25uZWN0aW9uSWQsICdSZW1vdGUgY29ubmVjdGlvbiAnICsgbXNnLmNvbm5lY3Rpb25JZCArIFwiIHVua25vd24gd2hlbiAnb25TdHJlYW1Qcm9wZXJ0eUNoYW5nZWQnLiBcIiArXG4gICAgICAgICAgICAnRXhpc3RpbmcgcmVtb3RlIGNvbm5lY3Rpb25zOiAnICsgSlNPTi5zdHJpbmdpZnkoT2JqZWN0LmtleXModGhpcy5yZW1vdGVDb25uZWN0aW9ucykpKVxuXG4gICAgICAgICAgICAudGhlbihjb25uZWN0aW9uID0+IHtcbiAgICAgICAgICAgICAgICBpZiAoISFjb25uZWN0aW9uLnN0cmVhbSAmJiBjb25uZWN0aW9uLnN0cmVhbS5zdHJlYW1JZCA9PT0gbXNnLnN0cmVhbUlkKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHN0cmVhbSA9IGNvbm5lY3Rpb24uc3RyZWFtO1xuICAgICAgICAgICAgICAgICAgICBsZXQgb2xkVmFsdWU7XG4gICAgICAgICAgICAgICAgICAgIHN3aXRjaCAobXNnLnByb3BlcnR5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlICdhdWRpb0FjdGl2ZSc6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgb2xkVmFsdWUgPSBzdHJlYW0uYXVkaW9BY3RpdmU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbXNnLm5ld1ZhbHVlID0gbXNnLm5ld1ZhbHVlID09PSAndHJ1ZSc7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyZWFtLmF1ZGlvQWN0aXZlID0gbXNnLm5ld1ZhbHVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAndmlkZW9BY3RpdmUnOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9sZFZhbHVlID0gc3RyZWFtLnZpZGVvQWN0aXZlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1zZy5uZXdWYWx1ZSA9IG1zZy5uZXdWYWx1ZSA9PT0gJ3RydWUnO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cmVhbS52aWRlb0FjdGl2ZSA9IG1zZy5uZXdWYWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJ3ZpZGVvRGltZW5zaW9ucyc6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgb2xkVmFsdWUgPSBzdHJlYW0udmlkZW9EaW1lbnNpb25zO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1zZy5uZXdWYWx1ZSA9IEpTT04ucGFyc2UoSlNPTi5wYXJzZShtc2cubmV3VmFsdWUpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJlYW0udmlkZW9EaW1lbnNpb25zID0gbXNnLm5ld1ZhbHVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3N0cmVhbVByb3BlcnR5Q2hhbmdlZCcsIFtuZXcgU3RyZWFtUHJvcGVydHlDaGFuZ2VkRXZlbnQodGhpcywgc3RyZWFtLCBtc2cucHJvcGVydHksIG1zZy5uZXdWYWx1ZSwgb2xkVmFsdWUsIG1zZy5yZWFzb24pXSk7XG4gICAgICAgICAgICAgICAgICAgIHN0cmVhbS5zdHJlYW1NYW5hZ2VyLmVtaXRFdmVudCgnc3RyZWFtUHJvcGVydHlDaGFuZ2VkJywgW25ldyBTdHJlYW1Qcm9wZXJ0eUNoYW5nZWRFdmVudChzdHJlYW0uc3RyZWFtTWFuYWdlciwgc3RyZWFtLCBtc2cucHJvcGVydHksIG1zZy5uZXdWYWx1ZSwgb2xkVmFsdWUsIG1zZy5yZWFzb24pXSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihcIk5vIHN0cmVhbSB3aXRoIHN0cmVhbUlkICdcIiArIG1zZy5zdHJlYW1JZCArIFwiJyBmb3VuZCBmb3IgY29ubmVjdGlvbiAnXCIgKyBtc2cuY29ubmVjdGlvbklkICsgXCInIG9uICdzdHJlYW1Qcm9wZXJ0eUNoYW5nZWQnIGV2ZW50XCIpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAuY2F0Y2gob3BlblZpZHVFcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihvcGVuVmlkdUVycm9yKTtcbiAgICAgICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICByZWN2SWNlQ2FuZGlkYXRlKG1zZyk6IHZvaWQge1xuICAgICAgICBjb25zdCBjYW5kaWRhdGUgPSB7XG4gICAgICAgICAgICBjYW5kaWRhdGU6IG1zZy5jYW5kaWRhdGUsXG4gICAgICAgICAgICBzZHBNaWQ6IG1zZy5zZHBNaWQsXG4gICAgICAgICAgICBzZHBNTGluZUluZGV4OiBtc2cuc2RwTUxpbmVJbmRleCxcbiAgICAgICAgICAgIHRvSlNPTjogKCkgPT4ge1xuICAgICAgICAgICAgICAgIHJldHVybiB7IGNhbmRpZGF0ZTogbXNnLmNhbmRpZGF0ZSB9O1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICB0aGlzLmdldENvbm5lY3Rpb24obXNnLmVuZHBvaW50TmFtZSwgJ0Nvbm5lY3Rpb24gbm90IGZvdW5kIGZvciBlbmRwb2ludCAnICsgbXNnLmVuZHBvaW50TmFtZSArICcuIEljZSBjYW5kaWRhdGUgd2lsbCBiZSBpZ25vcmVkOiAnICsgY2FuZGlkYXRlKVxuICAgICAgICAgICAgLnRoZW4oY29ubmVjdGlvbiA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3Qgc3RyZWFtID0gY29ubmVjdGlvbi5zdHJlYW07XG4gICAgICAgICAgICAgICAgc3RyZWFtLmdldFdlYlJ0Y1BlZXIoKS5hZGRJY2VDYW5kaWRhdGUoY2FuZGlkYXRlKS5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ0Vycm9yIGFkZGluZyBjYW5kaWRhdGUgZm9yICcgKyBzdHJlYW0uc3RyZWFtSWRcbiAgICAgICAgICAgICAgICAgICAgICAgICsgJyBzdHJlYW0gb2YgZW5kcG9pbnQgJyArIG1zZy5lbmRwb2ludE5hbWUgKyAnOiAnICsgZXJyb3IpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIC5jYXRjaChvcGVuVmlkdUVycm9yID0+IHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKG9wZW5WaWR1RXJyb3IpO1xuICAgICAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIG9uU2Vzc2lvbkNsb3NlZChtc2cpOiB2b2lkIHtcbiAgICAgICAgY29uc29sZS5pbmZvKCdTZXNzaW9uIGNsb3NlZDogJyArIEpTT04uc3RyaW5naWZ5KG1zZykpO1xuICAgICAgICBjb25zdCBzID0gbXNnLnNlc3Npb25JZDtcbiAgICAgICAgaWYgKHMgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3Nlc3Npb24tY2xvc2VkJywgW3tcbiAgICAgICAgICAgICAgICBzZXNzaW9uOiBzXG4gICAgICAgICAgICB9XSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjb25zb2xlLndhcm4oJ1Nlc3Npb24gdW5kZWZpbmVkIG9uIHNlc3Npb24gY2xvc2VkJywgbXNnKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvbkxvc3RDb25uZWN0aW9uKCk6IHZvaWQge1xuXG4gICAgICAgIC8qaWYgKCF0aGlzLmNvbm5lY3Rpb24pIHtcblxuICAgICAgICAgICAgY29uc29sZS53YXJuKCdOb3QgY29ubmVjdGVkIHRvIHNlc3Npb246IGlmIHlvdSBhcmUgbm90IGRlYnVnZ2luZywgdGhpcyBpcyBwcm9iYWJseSBhIGNlcnRpZmljYXRlIGVycm9yJyk7XG5cbiAgICAgICAgICAgIGNvbnN0IHVybCA9ICdodHRwczovLycgKyB0aGlzLm9wZW52aWR1LmdldFdzVXJpKCkuc3BsaXQoJ3dzczovLycpWzFdLnNwbGl0KCcvb3BlbnZpZHUnKVswXTtcbiAgICAgICAgICAgIGlmICh3aW5kb3cuY29uZmlybSgnSWYgeW91IGFyZSBub3QgZGVidWdnaW5nLCB0aGlzIGlzIHByb2JhYmx5IGEgY2VydGlmaWNhdGUgZXJyb3IgYXQgXFxcIicgKyB1cmwgKyAnXFxcIlxcblxcbkNsaWNrIE9LIHRvIG5hdmlnYXRlIGFuZCBhY2NlcHQgaXQnKSkge1xuICAgICAgICAgICAgICAgIGxvY2F0aW9uLmFzc2lnbih1cmwgKyAnL2FjY2VwdC1jZXJ0aWZpY2F0ZScpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9Ki9cblxuICAgICAgICBjb25zb2xlLndhcm4oJ0xvc3QgY29ubmVjdGlvbiBpbiBTZXNzaW9uICcgKyB0aGlzLnNlc3Npb25JZCk7XG4gICAgICAgIGlmICghIXRoaXMuc2Vzc2lvbklkICYmICF0aGlzLmNvbm5lY3Rpb24uZGlzcG9zZWQpIHtcbiAgICAgICAgICAgIHRoaXMubGVhdmUodHJ1ZSwgJ25ldHdvcmtEaXNjb25uZWN0Jyk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgb25SZWNvdmVyZWRDb25uZWN0aW9uKCk6IHZvaWQge1xuICAgICAgICBjb25zb2xlLndhcm4oJ1JlY292ZXJlZCBjb25uZWN0aW9uIGluIFNlc3Npb24gJyArIHRoaXMuc2Vzc2lvbklkKTtcbiAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ2Nvbm5lY3Rpb25SZWNvdmVyZWQnLCBbXSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIG9uTWVkaWFFcnJvcihwYXJhbXMpOiB2b2lkIHtcblxuICAgICAgICBjb25zb2xlLmVycm9yKCdNZWRpYSBlcnJvcjogJyArIEpTT04uc3RyaW5naWZ5KHBhcmFtcykpO1xuICAgICAgICBjb25zdCBlcnIgPSBwYXJhbXMuZXJyb3I7XG4gICAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdlcnJvci1tZWRpYScsIFt7XG4gICAgICAgICAgICAgICAgZXJyb3I6IGVyclxuICAgICAgICAgICAgfV0pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY29uc29sZS53YXJuKCdSZWNlaXZlZCB1bmRlZmluZWQgbWVkaWEgZXJyb3IuIFBhcmFtczonLCBwYXJhbXMpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIG9uUmVjb3JkaW5nU3RhcnRlZChyZXNwb25zZSk6IHZvaWQge1xuICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgncmVjb3JkaW5nU3RhcnRlZCcsIFtuZXcgUmVjb3JkaW5nRXZlbnQodGhpcywgJ3JlY29yZGluZ1N0YXJ0ZWQnLCByZXNwb25zZS5pZCwgcmVzcG9uc2UubmFtZSldKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgb25SZWNvcmRpbmdTdG9wcGVkKHJlc3BvbnNlKTogdm9pZCB7XG4gICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdyZWNvcmRpbmdTdG9wcGVkJywgW25ldyBSZWNvcmRpbmdFdmVudCh0aGlzLCAncmVjb3JkaW5nU3RvcHBlZCcsIHJlc3BvbnNlLmlkLCByZXNwb25zZS5uYW1lKV0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBlbWl0RXZlbnQodHlwZTogc3RyaW5nLCBldmVudEFycmF5OiBhbnlbXSk6IHZvaWQge1xuICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCh0eXBlLCBldmVudEFycmF5KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgbGVhdmUoZm9yY2VkOiBib29sZWFuLCByZWFzb246IHN0cmluZyk6IHZvaWQge1xuXG4gICAgICAgIGZvcmNlZCA9ICEhZm9yY2VkO1xuICAgICAgICBjb25zb2xlLmluZm8oJ0xlYXZpbmcgU2Vzc2lvbiAoZm9yY2VkPScgKyBmb3JjZWQgKyAnKScpO1xuXG4gICAgICAgIGlmICghIXRoaXMuY29ubmVjdGlvbikge1xuICAgICAgICAgICAgaWYgKCF0aGlzLmNvbm5lY3Rpb24uZGlzcG9zZWQgJiYgIWZvcmNlZCkge1xuICAgICAgICAgICAgICAgIHRoaXMub3BlbnZpZHUuc2VuZFJlcXVlc3QoJ2xlYXZlUm9vbScsIChlcnJvciwgcmVzcG9uc2UpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB0aGlzLm9wZW52aWR1LmNsb3NlV3MoKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy5vcGVudmlkdS5jbG9zZVdzKCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMuc3RvcFB1Ymxpc2hlclN0cmVhbShyZWFzb24pO1xuXG4gICAgICAgICAgICBpZiAoIXRoaXMuY29ubmVjdGlvbi5kaXNwb3NlZCkge1xuICAgICAgICAgICAgICAgIC8vIE1ha2UgU2Vzc2lvbiBvYmplY3QgZGlzcGF0Y2ggJ3Nlc3Npb25EaXNjb25uZWN0ZWQnIGV2ZW50IChpZiBpdCBpcyBub3QgYWxyZWFkeSBkaXNwb3NlZClcbiAgICAgICAgICAgICAgICBjb25zdCBzZXNzaW9uRGlzY29ubmVjdEV2ZW50ID0gbmV3IFNlc3Npb25EaXNjb25uZWN0ZWRFdmVudCh0aGlzLCByZWFzb24pO1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdzZXNzaW9uRGlzY29ubmVjdGVkJywgW3Nlc3Npb25EaXNjb25uZWN0RXZlbnRdKTtcbiAgICAgICAgICAgICAgICBzZXNzaW9uRGlzY29ubmVjdEV2ZW50LmNhbGxEZWZhdWx0QmVoYXZpb3IoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvbnNvbGUud2FybignWW91IHdlcmUgbm90IGNvbm5lY3RlZCB0byB0aGUgc2Vzc2lvbiAnICsgdGhpcy5zZXNzaW9uSWQpO1xuICAgICAgICB9XG4gICAgfVxuXG5cbiAgICAvKiBQcml2YXRlIG1ldGhvZHMgKi9cblxuICAgIHByaXZhdGUgY29ubmVjdEF1eCh0b2tlbjogc3RyaW5nKTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIHRoaXMub3BlbnZpZHUuc3RhcnRXcygoZXJyb3IpID0+IHtcbiAgICAgICAgICAgICAgICBpZiAoISFlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG5cbiAgICAgICAgICAgICAgICAgICAgY29uc3Qgam9pblBhcmFtcyA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRva2VuOiAoISF0b2tlbikgPyB0b2tlbiA6ICcnLFxuICAgICAgICAgICAgICAgICAgICAgICAgc2Vzc2lvbjogdGhpcy5zZXNzaW9uSWQsXG4gICAgICAgICAgICAgICAgICAgICAgICBtZXRhZGF0YTogISF0aGlzLm9wdGlvbnMubWV0YWRhdGEgPyB0aGlzLm9wdGlvbnMubWV0YWRhdGEgOiAnJyxcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlY3JldDogdGhpcy5vcGVudmlkdS5nZXRTZWNyZXQoKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlY29yZGVyOiB0aGlzLm9wZW52aWR1LmdldFJlY29yZGVyKCksXG4gICAgICAgICAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgICAgICAgICAgdGhpcy5vcGVudmlkdS5zZW5kUmVxdWVzdCgnam9pblJvb20nLCBqb2luUGFyYW1zLCAoZXJyb3IsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoISFlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gSW5pdGlhbGl6ZSBjYXBhYmlsaXRpZXMgb2JqZWN0IHdpdGggdGhlIHJvbGVcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNhcGFiaWxpdGllcyA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3Vic2NyaWJlOiB0cnVlLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwdWJsaXNoOiB0aGlzLm9wZW52aWR1LnJvbGUgIT09ICdTVUJTQ1JJQkVSJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yY2VVbnB1Ymxpc2g6IHRoaXMub3BlbnZpZHUucm9sZSA9PT0gJ01PREVSQVRPUicsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvcmNlRGlzY29ubmVjdDogdGhpcy5vcGVudmlkdS5yb2xlID09PSAnTU9ERVJBVE9SJ1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBJbml0aWFsaXplIGxvY2FsIENvbm5lY3Rpb24gb2JqZWN0IHdpdGggdmFsdWVzIHJldHVybmVkIGJ5IG9wZW52aWR1LXNlcnZlclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY29ubmVjdGlvbiA9IG5ldyBDb25uZWN0aW9uKHRoaXMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY29ubmVjdGlvbi5jb25uZWN0aW9uSWQgPSByZXNwb25zZS5pZDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbm5lY3Rpb24uZGF0YSA9IHJlc3BvbnNlLm1ldGFkYXRhO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gSW5pdGlhbGl6ZSByZW1vdGUgQ29ubmVjdGlvbnMgd2l0aCB2YWx1ZSByZXR1cm5lZCBieSBvcGVudmlkdS1zZXJ2ZXJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBldmVudHMgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbm5lY3Rpb25zOiBuZXcgQXJyYXk8Q29ubmVjdGlvbj4oKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyZWFtczogbmV3IEFycmF5PFN0cmVhbT4oKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZXhpc3RpbmdQYXJ0aWNpcGFudHM6IENvbm5lY3Rpb25PcHRpb25zW10gPSByZXNwb25zZS52YWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBleGlzdGluZ1BhcnRpY2lwYW50cy5mb3JFYWNoKHBhcnRpY2lwYW50ID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgY29ubmVjdGlvbiA9IG5ldyBDb25uZWN0aW9uKHRoaXMsIHBhcnRpY2lwYW50KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5yZW1vdGVDb25uZWN0aW9uc1tjb25uZWN0aW9uLmNvbm5lY3Rpb25JZF0gPSBjb25uZWN0aW9uO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBldmVudHMuY29ubmVjdGlvbnMucHVzaChjb25uZWN0aW9uKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCEhY29ubmVjdGlvbi5zdHJlYW0pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucmVtb3RlU3RyZWFtc0NyZWF0ZWRbY29ubmVjdGlvbi5zdHJlYW0uc3RyZWFtSWRdID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV2ZW50cy5zdHJlYW1zLnB1c2goY29ubmVjdGlvbi5zdHJlYW0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBPd24gJ2Nvbm5lY3Rpb25DcmVhdGVkJyBldmVudFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdjb25uZWN0aW9uQ3JlYXRlZCcsIFtuZXcgQ29ubmVjdGlvbkV2ZW50KGZhbHNlLCB0aGlzLCAnY29ubmVjdGlvbkNyZWF0ZWQnLCB0aGlzLmNvbm5lY3Rpb24sICcnKV0pO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gT25lICdjb25uZWN0aW9uQ3JlYXRlZCcgZXZlbnQgZm9yIGVhY2ggZXhpc3RpbmcgY29ubmVjdGlvbiBpbiB0aGUgc2Vzc2lvblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV2ZW50cy5jb25uZWN0aW9ucy5mb3JFYWNoKGNvbm5lY3Rpb24gPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnY29ubmVjdGlvbkNyZWF0ZWQnLCBbbmV3IENvbm5lY3Rpb25FdmVudChmYWxzZSwgdGhpcywgJ2Nvbm5lY3Rpb25DcmVhdGVkJywgY29ubmVjdGlvbiwgJycpXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBPbmUgJ3N0cmVhbUNyZWF0ZWQnIGV2ZW50IGZvciBlYWNoIGFjdGl2ZSBzdHJlYW0gaW4gdGhlIHNlc3Npb25cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBldmVudHMuc3RyZWFtcy5mb3JFYWNoKHN0cmVhbSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdzdHJlYW1DcmVhdGVkJywgW25ldyBTdHJlYW1FdmVudChmYWxzZSwgdGhpcywgJ3N0cmVhbUNyZWF0ZWQnLCBzdHJlYW0sICcnKV0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBzdG9wUHVibGlzaGVyU3RyZWFtKHJlYXNvbjogc3RyaW5nKSB7XG4gICAgICAgIGlmICghIXRoaXMuY29ubmVjdGlvbi5zdHJlYW0pIHtcbiAgICAgICAgICAgIC8vIERpc3Bvc2UgUHVibGlzaGVyJ3MgIGxvY2FsIHN0cmVhbVxuICAgICAgICAgICAgdGhpcy5jb25uZWN0aW9uLnN0cmVhbS5kaXNwb3NlV2ViUnRjUGVlcigpO1xuICAgICAgICAgICAgaWYgKHRoaXMuY29ubmVjdGlvbi5zdHJlYW0uaXNMb2NhbFN0cmVhbVB1Ymxpc2hlZCkge1xuICAgICAgICAgICAgICAgIC8vIE1ha2UgUHVibGlzaGVyIG9iamVjdCBkaXNwYXRjaCAnc3RyZWFtRGVzdHJveWVkJyBldmVudCBpZiB0aGUgU3RyZWFtIHdhcyBwdWJsaXNoZWRcbiAgICAgICAgICAgICAgICB0aGlzLmNvbm5lY3Rpb24uc3RyZWFtLmVlLmVtaXRFdmVudCgnbG9jYWwtc3RyZWFtLWRlc3Ryb3llZCcsIFtyZWFzb25dKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgc3RyaW5nQ2xpZW50TWV0YWRhdGEobWV0YWRhdGE6IGFueSk6IHN0cmluZyB7XG4gICAgICAgIGlmICh0eXBlb2YgbWV0YWRhdGEgIT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkobWV0YWRhdGEpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIG1ldGFkYXRhO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBnZXRDb25uZWN0aW9uKGNvbm5lY3Rpb25JZDogc3RyaW5nLCBlcnJvck1lc3NhZ2U6IHN0cmluZyk6IFByb21pc2U8Q29ubmVjdGlvbj4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2U8Q29ubmVjdGlvbj4oKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgY29uc3QgY29ubmVjdGlvbiA9IHRoaXMucmVtb3RlQ29ubmVjdGlvbnNbY29ubmVjdGlvbklkXTtcbiAgICAgICAgICAgIGlmICghIWNvbm5lY3Rpb24pIHtcbiAgICAgICAgICAgICAgICAvLyBSZXNvbHZlIHJlbW90ZSBjb25uZWN0aW9uXG4gICAgICAgICAgICAgICAgcmVzb2x2ZShjb25uZWN0aW9uKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuY29ubmVjdGlvbi5jb25uZWN0aW9uSWQgPT09IGNvbm5lY3Rpb25JZCkge1xuICAgICAgICAgICAgICAgICAgICAvLyBSZXNvbHZlIGxvY2FsIGNvbm5lY3Rpb25cbiAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSh0aGlzLmNvbm5lY3Rpb24pO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIENvbm5lY3Rpb24gbm90IGZvdW5kLiBSZWplY3Qgd2l0aCBPcGVuVmlkdUVycm9yXG4gICAgICAgICAgICAgICAgICAgIHJlamVjdChuZXcgT3BlblZpZHVFcnJvcihPcGVuVmlkdUVycm9yTmFtZS5HRU5FUklDX0VSUk9SLCBlcnJvck1lc3NhZ2UpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIHByaXZhdGUgZ2V0UmVtb3RlQ29ubmVjdGlvbihjb25uZWN0aW9uSWQ6IHN0cmluZywgZXJyb3JNZXNzYWdlOiBzdHJpbmcpOiBQcm9taXNlPENvbm5lY3Rpb24+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlPENvbm5lY3Rpb24+KChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGNvbm5lY3Rpb24gPSB0aGlzLnJlbW90ZUNvbm5lY3Rpb25zW2Nvbm5lY3Rpb25JZF07XG4gICAgICAgICAgICBpZiAoISFjb25uZWN0aW9uKSB7XG4gICAgICAgICAgICAgICAgLy8gUmVzb2x2ZSByZW1vdGUgY29ubmVjdGlvblxuICAgICAgICAgICAgICAgIHJlc29sdmUoY29ubmVjdGlvbik7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIC8vIFJlbW90ZSBjb25uZWN0aW9uIG5vdCBmb3VuZC4gUmVqZWN0IHdpdGggT3BlblZpZHVFcnJvclxuICAgICAgICAgICAgICAgIHJlamVjdChuZXcgT3BlblZpZHVFcnJvcihPcGVuVmlkdUVycm9yTmFtZS5HRU5FUklDX0VSUk9SLCBlcnJvck1lc3NhZ2UpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBwcm9jZXNzVG9rZW4odG9rZW46IHN0cmluZyk6IHZvaWQge1xuICAgICAgICBjb25zdCB1cmwgPSBuZXcgVVJMKHRva2VuKTtcbiAgICAgICAgdGhpcy5zZXNzaW9uSWQgPSA8c3RyaW5nPnVybC5zZWFyY2hQYXJhbXMuZ2V0KCdzZXNzaW9uSWQnKTtcbiAgICAgICAgY29uc3Qgc2VjcmV0ID0gdXJsLnNlYXJjaFBhcmFtcy5nZXQoJ3NlY3JldCcpO1xuICAgICAgICBjb25zdCByZWNvcmRlciA9IHVybC5zZWFyY2hQYXJhbXMuZ2V0KCdyZWNvcmRlcicpO1xuICAgICAgICBjb25zdCB0dXJuVXNlcm5hbWUgPSB1cmwuc2VhcmNoUGFyYW1zLmdldCgndHVyblVzZXJuYW1lJyk7XG4gICAgICAgIGNvbnN0IHR1cm5DcmVkZW50aWFsID0gdXJsLnNlYXJjaFBhcmFtcy5nZXQoJ3R1cm5DcmVkZW50aWFsJyk7XG4gICAgICAgIGNvbnN0IHJvbGUgPSB1cmwuc2VhcmNoUGFyYW1zLmdldCgncm9sZScpO1xuXG4gICAgICAgIGlmICghIXNlY3JldCkge1xuICAgICAgICAgICAgdGhpcy5vcGVudmlkdS5zZWNyZXQgPSBzZWNyZXQ7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCEhcmVjb3JkZXIpIHtcbiAgICAgICAgICAgIHRoaXMub3BlbnZpZHUucmVjb3JkZXIgPSB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIGlmICghIXR1cm5Vc2VybmFtZSAmJiAhIXR1cm5DcmVkZW50aWFsKSB7XG4gICAgICAgICAgICBjb25zdCBzdHVuVXJsID0gJ3N0dW46JyArIHVybC5ob3N0bmFtZSArICc6MzQ3OCc7XG4gICAgICAgICAgICBjb25zdCB0dXJuVXJsMSA9ICd0dXJuOicgKyB1cmwuaG9zdG5hbWUgKyAnOjM0NzgnO1xuICAgICAgICAgICAgY29uc3QgdHVyblVybDIgPSB0dXJuVXJsMSArICc/dHJhbnNwb3J0PXRjcCc7XG4gICAgICAgICAgICB0aGlzLm9wZW52aWR1LmljZVNlcnZlcnMgPSBbXG4gICAgICAgICAgICAgICAgeyB1cmxzOiBbc3R1blVybF0gfSxcbiAgICAgICAgICAgICAgICB7IHVybHM6IFt0dXJuVXJsMSwgdHVyblVybDJdLCB1c2VybmFtZTogdHVyblVzZXJuYW1lLCBjcmVkZW50aWFsOiB0dXJuQ3JlZGVudGlhbCB9XG4gICAgICAgICAgICBdO1xuICAgICAgICAgICAgY29uc29sZS5sb2coJ1RVUk4gdGVtcCBjcmVkZW50aWFscyBbJyArIHR1cm5Vc2VybmFtZSArICc6JyArIHR1cm5DcmVkZW50aWFsICsgJ10nKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoISFyb2xlKSB7XG4gICAgICAgICAgICB0aGlzLm9wZW52aWR1LnJvbGUgPSByb2xlO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5vcGVudmlkdS53c1VyaSA9ICd3c3M6Ly8nICsgdXJsLmhvc3QgKyAnL29wZW52aWR1JztcbiAgICB9XG5cbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IENvbm5lY3Rpb24gfSBmcm9tICcuL0Nvbm5lY3Rpb24nO1xuaW1wb3J0IHsgU2Vzc2lvbiB9IGZyb20gJy4vU2Vzc2lvbic7XG5pbXBvcnQgeyBTdHJlYW1NYW5hZ2VyIH0gZnJvbSAnLi9TdHJlYW1NYW5hZ2VyJztcbmltcG9ydCB7IEluYm91bmRTdHJlYW1PcHRpb25zIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9JbnRlcmZhY2VzL1ByaXZhdGUvSW5ib3VuZFN0cmVhbU9wdGlvbnMnO1xuaW1wb3J0IHsgT3V0Ym91bmRTdHJlYW1PcHRpb25zIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9JbnRlcmZhY2VzL1ByaXZhdGUvT3V0Ym91bmRTdHJlYW1PcHRpb25zJztcbmltcG9ydCB7IFdlYlJ0Y1BlZXIsIFdlYlJ0Y1BlZXJTZW5kb25seSwgV2ViUnRjUGVlclJlY3Zvbmx5LCBXZWJSdGNQZWVyU2VuZHJlY3YgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL1dlYlJ0Y1BlZXIvV2ViUnRjUGVlcic7XG5pbXBvcnQgeyBXZWJSdGNTdGF0cyB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvV2ViUnRjU3RhdHMvV2ViUnRjU3RhdHMnO1xuaW1wb3J0IHsgUHVibGlzaGVyU3BlYWtpbmdFdmVudCB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1B1Ymxpc2hlclNwZWFraW5nRXZlbnQnO1xuXG5pbXBvcnQgRXZlbnRFbWl0dGVyID0gcmVxdWlyZSgnd29sZnk4Ny1ldmVudGVtaXR0ZXInKTtcbmltcG9ydCBoYXJrID0gcmVxdWlyZSgnaGFyaycpO1xuaW1wb3J0IHsgT3BlblZpZHVFcnJvciwgT3BlblZpZHVFcnJvck5hbWUgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0VudW1zL09wZW5WaWR1RXJyb3InO1xuXG5cbi8qKlxuICogUmVwcmVzZW50cyBlYWNoIG9uZSBvZiB0aGUgbWVkaWEgc3RyZWFtcyBhdmFpbGFibGUgaW4gT3BlblZpZHUgU2VydmVyIGZvciBjZXJ0YWluIHNlc3Npb24uXG4gKiBFYWNoIFtbUHVibGlzaGVyXV0gYW5kIFtbU3Vic2NyaWJlcl1dIGhhcyBhbiBhdHRyaWJ1dGUgb2YgdHlwZSBTdHJlYW0sIGFzIHRoZXkgZ2l2ZSBhY2Nlc3NcbiAqIHRvIG9uZSBvZiB0aGVtIChzZW5kaW5nIGFuZCByZWNlaXZpbmcgaXQsIHJlc3BlY3RpdmVseSlcbiAqL1xuZXhwb3J0IGNsYXNzIFN0cmVhbSB7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgQ29ubmVjdGlvbiBvYmplY3QgdGhhdCBpcyBwdWJsaXNoaW5nIHRoZSBzdHJlYW1cbiAgICAgKi9cbiAgICBjb25uZWN0aW9uOiBDb25uZWN0aW9uO1xuXG4gICAgLyoqXG4gICAgICogRnJhbWUgcmF0ZSBvZiB0aGUgdmlkZW8gaW4gZnJhbWVzIHBlciBzZWNvbmQuIFRoaXMgcHJvcGVydHkgaXMgb25seSBkZWZpbmVkIGlmIHRoZSBbW1B1Ymxpc2hlcl1dIG9mXG4gICAgICogdGhlIHN0cmVhbSB3YXMgaW5pdGlhbGl6ZWQgcGFzc2luZyBhIF9mcmFtZVJhdGVfIHByb3BlcnR5IG9uIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dIG1ldGhvZFxuICAgICAqL1xuICAgIGZyYW1lUmF0ZT86IG51bWJlcjtcblxuICAgIC8qKlxuICAgICAqIFdoZXRoZXIgdGhlIHN0cmVhbSBoYXMgYSB2aWRlbyB0cmFjayBvciBub3RcbiAgICAgKi9cbiAgICBoYXNWaWRlbzogYm9vbGVhbjtcblxuICAgIC8qKlxuICAgICAqIFdoZXRoZXIgdGhlIHN0cmVhbSBoYXMgYW4gYXVkaW8gdHJhY2sgb3Igbm90XG4gICAgICovXG4gICAgaGFzQXVkaW86IGJvb2xlYW47XG5cbiAgICAvKipcbiAgICAgKiBXaGV0aGVyIHRoZSBzdHJlYW0gaGFzIHRoZSB2aWRlbyB0cmFjayBtdXRlZCBvciB1bm11dGVkLiBJZiBbW2hhc1ZpZGVvXV0gaXMgZmFsc2UsIHRoaXMgcHJvcGVydHkgaXMgdW5kZWZpbmVkLlxuICAgICAqXG4gICAgICogVGhpcyBwcm9wZXJ0eSBtYXkgY2hhbmdlIGlmIHRoZSBQdWJsaXNoZXIgcHVibGlzaGluZyB0aGUgc3RyZWFtIGNhbGxzIFtbUHVibGlzaGVyLnB1Ymxpc2hWaWRlb11dLiBXaGVuZXZlciB0aGlzIGhhcHBlbnMgYSBbW1N0cmVhbVByb3BlcnR5Q2hhbmdlZEV2ZW50XV0gd2lsbCBiZSBkaXNwYXRjaGVkXG4gICAgICogYnkgdGhlIFNlc3Npb24gb2JqZWN0IGFzIHdlbGwgYXMgYnkgdGhlIGFmZmVjdGVkIFN1YnNjcmliZXIvUHVibGlzaGVyIG9iamVjdFxuICAgICAqL1xuICAgIHZpZGVvQWN0aXZlOiBib29sZWFuO1xuXG4gICAgLyoqXG4gICAgICogV2hldGhlciB0aGUgc3RyZWFtIGhhcyB0aGUgYXVkaW8gdHJhY2sgbXV0ZWQgb3IgdW5tdXRlZC4gSWYgW1toYXNBdWRpb11dIGlzIGZhbHNlLCB0aGlzIHByb3BlcnR5IGlzIHVuZGVmaW5lZFxuICAgICAqXG4gICAgICogVGhpcyBwcm9wZXJ0eSBtYXkgY2hhbmdlIGlmIHRoZSBQdWJsaXNoZXIgcHVibGlzaGluZyB0aGUgc3RyZWFtIGNhbGxzIFtbUHVibGlzaGVyLnB1Ymxpc2hBdWRpb11dLiBXaGVuZXZlciB0aGlzIGhhcHBlbnMgYSBbW1N0cmVhbVByb3BlcnR5Q2hhbmdlZEV2ZW50XV0gd2lsbCBiZSBkaXNwYXRjaGVkXG4gICAgICogYnkgdGhlIFNlc3Npb24gb2JqZWN0IGFzIHdlbGwgYXMgYnkgdGhlIGFmZmVjdGVkIFN1YnNjcmliZXIvUHVibGlzaGVyIG9iamVjdFxuICAgICAqL1xuICAgIGF1ZGlvQWN0aXZlOiBib29sZWFuO1xuXG4gICAgLyoqXG4gICAgICogVW5pcXVlIGlkZW50aWZpZXIgb2YgdGhlIHN0cmVhbVxuICAgICAqL1xuICAgIHN0cmVhbUlkOiBzdHJpbmc7XG5cbiAgICAvKipcbiAgICAgKiBgXCJDQU1FUkFcImAsIGBcIlNDUkVFTlwiYCBvciBgXCJDVVNUT01cImAgKHRoZSBsYXR0ZXIgd2hlbiBbW1B1Ymxpc2hlclByb3BlcnRpZXMudmlkZW9Tb3VyY2VdXSBpcyBhIE1lZGlhU3RyZWFtVHJhY2sgd2hlbiBjYWxsaW5nIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dKS5cbiAgICAgKiBJZiBbW2hhc1ZpZGVvXV0gaXMgZmFsc2UsIHRoaXMgcHJvcGVydHkgaXMgdW5kZWZpbmVkXG4gICAgICovXG4gICAgdHlwZU9mVmlkZW8/OiBzdHJpbmc7XG5cbiAgICAvKipcbiAgICAgKiBTdHJlYW1NYW5hZ2VyIG9iamVjdCAoW1tQdWJsaXNoZXJdXSBvciBbW1N1YnNjcmliZXJdXSkgaW4gY2hhcmdlIG9mIGRpc3BsYXlpbmcgdGhpcyBzdHJlYW0gaW4gdGhlIERPTVxuICAgICAqL1xuICAgIHN0cmVhbU1hbmFnZXI6IFN0cmVhbU1hbmFnZXI7XG5cbiAgICAvKipcbiAgICAgKiBXaWR0aCBhbmQgaGVpZ2h0IGluIHBpeGVscyBvZiB0aGUgZW5jb2RlZCB2aWRlbyBzdHJlYW0uIElmIFtbaGFzVmlkZW9dXSBpcyBmYWxzZSwgdGhpcyBwcm9wZXJ0eSBpcyB1bmRlZmluZWRcbiAgICAgKlxuICAgICAqIFRoaXMgcHJvcGVydHkgbWF5IGNoYW5nZSBpZiB0aGUgUHVibGlzaGVyIHRoYXQgaXMgcHVibGlzaGluZzpcbiAgICAgKiAtIElmIGl0IGlzIGEgbW9iaWxlIGRldmljZSwgd2hlbmV2ZXIgdGhlIHVzZXIgcm90YXRlcyB0aGUgZGV2aWNlLlxuICAgICAqIC0gSWYgaXQgaXMgc2NyZWVuLXNoYXJpbmcsIHdoZW5ldmVyIHRoZSB1c2VyIGNoYW5nZXMgdGhlIHNpemUgb2YgdGhlIGNhcHR1cmVkIHdpbmRvdy5cbiAgICAgKlxuICAgICAqIFdoZW5ldmVyIHRoaXMgaGFwcGVucyBhIFtbU3RyZWFtUHJvcGVydHlDaGFuZ2VkRXZlbnRdXSB3aWxsIGJlIGRpc3BhdGNoZWQgYnkgdGhlIFNlc3Npb24gb2JqZWN0IGFzIHdlbGwgYXMgYnkgdGhlIGFmZmVjdGVkIFN1YnNjcmliZXIvUHVibGlzaGVyIG9iamVjdFxuICAgICAqL1xuICAgIHZpZGVvRGltZW5zaW9uczogeyB3aWR0aDogbnVtYmVyLCBoZWlnaHQ6IG51bWJlciB9O1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGVlID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuXG4gICAgcHJpdmF0ZSB3ZWJSdGNQZWVyOiBXZWJSdGNQZWVyO1xuICAgIHByaXZhdGUgbWVkaWFTdHJlYW06IE1lZGlhU3RyZWFtO1xuICAgIHByaXZhdGUgd2ViUnRjU3RhdHM6IFdlYlJ0Y1N0YXRzO1xuXG4gICAgcHJpdmF0ZSBpc1N1YnNjcmliZVRvUmVtb3RlID0gZmFsc2U7XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgaXNMb2NhbFN0cmVhbVJlYWR5VG9QdWJsaXNoID0gZmFsc2U7XG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGlzTG9jYWxTdHJlYW1QdWJsaXNoZWQgPSBmYWxzZTtcbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgcHVibGlzaGVkT25jZSA9IGZhbHNlO1xuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBzZXNzaW9uOiBTZXNzaW9uO1xuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBpbmJvdW5kU3RyZWFtT3B0czogSW5ib3VuZFN0cmVhbU9wdGlvbnM7XG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIG91dGJvdW5kU3RyZWFtT3B0czogT3V0Ym91bmRTdHJlYW1PcHRpb25zO1xuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBzcGVlY2hFdmVudDogYW55O1xuXG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgY29uc3RydWN0b3Ioc2Vzc2lvbjogU2Vzc2lvbiwgb3B0aW9uczogSW5ib3VuZFN0cmVhbU9wdGlvbnMgfCBPdXRib3VuZFN0cmVhbU9wdGlvbnMgfCB7fSkge1xuXG4gICAgICAgIHRoaXMuc2Vzc2lvbiA9IHNlc3Npb247XG5cbiAgICAgICAgaWYgKG9wdGlvbnMuaGFzT3duUHJvcGVydHkoJ2lkJykpIHtcbiAgICAgICAgICAgIC8vIEluYm91bmRTdHJlYW1PcHRpb25zOiBzdHJlYW0gYmVsb25ncyB0byBhIFN1YnNjcmliZXJcbiAgICAgICAgICAgIHRoaXMuaW5ib3VuZFN0cmVhbU9wdHMgPSA8SW5ib3VuZFN0cmVhbU9wdGlvbnM+b3B0aW9ucztcbiAgICAgICAgICAgIHRoaXMuc3RyZWFtSWQgPSB0aGlzLmluYm91bmRTdHJlYW1PcHRzLmlkO1xuICAgICAgICAgICAgdGhpcy5oYXNBdWRpbyA9IHRoaXMuaW5ib3VuZFN0cmVhbU9wdHMuaGFzQXVkaW87XG4gICAgICAgICAgICB0aGlzLmhhc1ZpZGVvID0gdGhpcy5pbmJvdW5kU3RyZWFtT3B0cy5oYXNWaWRlbztcbiAgICAgICAgICAgIGlmICh0aGlzLmhhc0F1ZGlvKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5hdWRpb0FjdGl2ZSA9IHRoaXMuaW5ib3VuZFN0cmVhbU9wdHMuYXVkaW9BY3RpdmU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodGhpcy5oYXNWaWRlbykge1xuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9BY3RpdmUgPSB0aGlzLmluYm91bmRTdHJlYW1PcHRzLnZpZGVvQWN0aXZlO1xuICAgICAgICAgICAgICAgIHRoaXMudHlwZU9mVmlkZW8gPSAoIXRoaXMuaW5ib3VuZFN0cmVhbU9wdHMudHlwZU9mVmlkZW8pID8gdW5kZWZpbmVkIDogdGhpcy5pbmJvdW5kU3RyZWFtT3B0cy50eXBlT2ZWaWRlbztcbiAgICAgICAgICAgICAgICB0aGlzLmZyYW1lUmF0ZSA9ICh0aGlzLmluYm91bmRTdHJlYW1PcHRzLmZyYW1lUmF0ZSA9PT0gLTEpID8gdW5kZWZpbmVkIDogdGhpcy5pbmJvdW5kU3RyZWFtT3B0cy5mcmFtZVJhdGU7XG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb0RpbWVuc2lvbnMgPSB0aGlzLmluYm91bmRTdHJlYW1PcHRzLnZpZGVvRGltZW5zaW9ucztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIE91dGJvdW5kU3RyZWFtT3B0aW9uczogc3RyZWFtIGJlbG9uZ3MgdG8gYSBQdWJsaXNoZXJcbiAgICAgICAgICAgIHRoaXMub3V0Ym91bmRTdHJlYW1PcHRzID0gPE91dGJvdW5kU3RyZWFtT3B0aW9ucz5vcHRpb25zO1xuXG4gICAgICAgICAgICB0aGlzLmhhc0F1ZGlvID0gdGhpcy5pc1NlbmRBdWRpbygpO1xuICAgICAgICAgICAgdGhpcy5oYXNWaWRlbyA9IHRoaXMuaXNTZW5kVmlkZW8oKTtcblxuICAgICAgICAgICAgaWYgKHRoaXMuaGFzQXVkaW8pIHtcbiAgICAgICAgICAgICAgICB0aGlzLmF1ZGlvQWN0aXZlID0gISF0aGlzLm91dGJvdW5kU3RyZWFtT3B0cy5wdWJsaXNoZXJQcm9wZXJ0aWVzLnB1Ymxpc2hBdWRpbztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0aGlzLmhhc1ZpZGVvKSB7XG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb0FjdGl2ZSA9ICEhdGhpcy5vdXRib3VuZFN0cmVhbU9wdHMucHVibGlzaGVyUHJvcGVydGllcy5wdWJsaXNoVmlkZW87XG4gICAgICAgICAgICAgICAgdGhpcy5mcmFtZVJhdGUgPSB0aGlzLm91dGJvdW5kU3RyZWFtT3B0cy5wdWJsaXNoZXJQcm9wZXJ0aWVzLmZyYW1lUmF0ZTtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5vdXRib3VuZFN0cmVhbU9wdHMucHVibGlzaGVyUHJvcGVydGllcy52aWRlb1NvdXJjZSBpbnN0YW5jZW9mIE1lZGlhU3RyZWFtVHJhY2spIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy50eXBlT2ZWaWRlbyA9ICdDVVNUT00nO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMudHlwZU9mVmlkZW8gPSB0aGlzLmlzU2VuZFNjcmVlbigpID8gJ1NDUkVFTicgOiAnQ0FNRVJBJztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLmVlLm9uKCdtZWRpYXN0cmVhbS11cGRhdGVkJywgKCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5zdHJlYW1NYW5hZ2VyLnVwZGF0ZU1lZGlhU3RyZWFtKHRoaXMubWVkaWFTdHJlYW0pO1xuICAgICAgICAgICAgY29uc29sZS5kZWJ1ZygnVmlkZW8gc3JjT2JqZWN0IFsnICsgdGhpcy5tZWRpYVN0cmVhbSArICddIHVwZGF0ZWQgaW4gc3RyZWFtIFsnICsgdGhpcy5zdHJlYW1JZCArICddJyk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuXG4gICAgLyogSGlkZGVuIG1ldGhvZHMgKi9cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBnZXRNZWRpYVN0cmVhbSgpOiBNZWRpYVN0cmVhbSB7XG4gICAgICAgIHJldHVybiB0aGlzLm1lZGlhU3RyZWFtO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBzZXRNZWRpYVN0cmVhbShtZWRpYVN0cmVhbTogTWVkaWFTdHJlYW0pOiB2b2lkIHtcbiAgICAgICAgdGhpcy5tZWRpYVN0cmVhbSA9IG1lZGlhU3RyZWFtO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICB1cGRhdGVNZWRpYVN0cmVhbUluVmlkZW9zKCkge1xuICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnbWVkaWFzdHJlYW0tdXBkYXRlZCcpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBnZXRXZWJSdGNQZWVyKCk6IFdlYlJ0Y1BlZXIge1xuICAgICAgICByZXR1cm4gdGhpcy53ZWJSdGNQZWVyO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBnZXRSVENQZWVyQ29ubmVjdGlvbigpOiBSVENQZWVyQ29ubmVjdGlvbiB7XG4gICAgICAgIHJldHVybiB0aGlzLndlYlJ0Y1BlZXIucGM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHN1YnNjcmliZVRvTXlSZW1vdGUodmFsdWU6IGJvb2xlYW4pOiB2b2lkIHtcbiAgICAgICAgdGhpcy5pc1N1YnNjcmliZVRvUmVtb3RlID0gdmFsdWU7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHNldE91dGJvdW5kU3RyZWFtT3B0aW9ucyhvdXRib3VuZFN0cmVhbU9wdHM6IE91dGJvdW5kU3RyZWFtT3B0aW9ucyk6IHZvaWQge1xuICAgICAgICB0aGlzLm91dGJvdW5kU3RyZWFtT3B0cyA9IG91dGJvdW5kU3RyZWFtT3B0cztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgc3Vic2NyaWJlKCk6IFByb21pc2U8YW55PiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICB0aGlzLmluaXRXZWJSdGNQZWVyUmVjZWl2ZSgpXG4gICAgICAgICAgICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgcHVibGlzaCgpOiBQcm9taXNlPGFueT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgaWYgKHRoaXMuaXNMb2NhbFN0cmVhbVJlYWR5VG9QdWJsaXNoKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5pbml0V2ViUnRjUGVlclNlbmQoKVxuICAgICAgICAgICAgICAgICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy5lZS5vbmNlKCdzdHJlYW0tcmVhZHktdG8tcHVibGlzaCcsICgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5wdWJsaXNoKClcbiAgICAgICAgICAgICAgICAgICAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgICAgICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBkaXNwb3NlV2ViUnRjUGVlcigpOiB2b2lkIHtcbiAgICAgICAgaWYgKHRoaXMud2ViUnRjUGVlcikge1xuICAgICAgICAgICAgdGhpcy53ZWJSdGNQZWVyLmRpc3Bvc2UoKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5zcGVlY2hFdmVudCkge1xuICAgICAgICAgICAgdGhpcy5zcGVlY2hFdmVudC5zdG9wKCk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLnN0b3BXZWJSdGNTdGF0cygpO1xuXG4gICAgICAgIGNvbnNvbGUuaW5mbygoISF0aGlzLm91dGJvdW5kU3RyZWFtT3B0cyA/ICdPdXRib3VuZCAnIDogJ0luYm91bmQgJykgKyBcIldlYlJUQ1BlZXIgZnJvbSAnU3RyZWFtJyB3aXRoIGlkIFtcIiArIHRoaXMuc3RyZWFtSWQgKyAnXSBpcyBub3cgY2xvc2VkJyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGRpc3Bvc2VNZWRpYVN0cmVhbSgpOiB2b2lkIHtcbiAgICAgICAgaWYgKHRoaXMubWVkaWFTdHJlYW0pIHtcbiAgICAgICAgICAgIHRoaXMubWVkaWFTdHJlYW0uZ2V0QXVkaW9UcmFja3MoKS5mb3JFYWNoKCh0cmFjaykgPT4ge1xuICAgICAgICAgICAgICAgIHRyYWNrLnN0b3AoKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgdGhpcy5tZWRpYVN0cmVhbS5nZXRWaWRlb1RyYWNrcygpLmZvckVhY2goKHRyYWNrKSA9PiB7XG4gICAgICAgICAgICAgICAgdHJhY2suc3RvcCgpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBkZWxldGUgdGhpcy5tZWRpYVN0cmVhbTtcbiAgICAgICAgfVxuICAgICAgICBjb25zb2xlLmluZm8oKCEhdGhpcy5vdXRib3VuZFN0cmVhbU9wdHMgPyAnTG9jYWwgJyA6ICdSZW1vdGUgJykgKyBcIk1lZGlhU3RyZWFtIGZyb20gJ1N0cmVhbScgd2l0aCBpZCBbXCIgKyB0aGlzLnN0cmVhbUlkICsgJ10gaXMgbm93IGRpc3Bvc2VkJyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGRpc3BsYXlNeVJlbW90ZSgpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuaXNTdWJzY3JpYmVUb1JlbW90ZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgaXNTZW5kQXVkaW8oKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiAoISF0aGlzLm91dGJvdW5kU3RyZWFtT3B0cyAmJlxuICAgICAgICAgICAgdGhpcy5vdXRib3VuZFN0cmVhbU9wdHMucHVibGlzaGVyUHJvcGVydGllcy5hdWRpb1NvdXJjZSAhPT0gbnVsbCAmJlxuICAgICAgICAgICAgdGhpcy5vdXRib3VuZFN0cmVhbU9wdHMucHVibGlzaGVyUHJvcGVydGllcy5hdWRpb1NvdXJjZSAhPT0gZmFsc2UpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBpc1NlbmRWaWRlbygpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuICghIXRoaXMub3V0Ym91bmRTdHJlYW1PcHRzICYmXG4gICAgICAgICAgICB0aGlzLm91dGJvdW5kU3RyZWFtT3B0cy5wdWJsaXNoZXJQcm9wZXJ0aWVzLnZpZGVvU291cmNlICE9PSBudWxsICYmXG4gICAgICAgICAgICB0aGlzLm91dGJvdW5kU3RyZWFtT3B0cy5wdWJsaXNoZXJQcm9wZXJ0aWVzLnZpZGVvU291cmNlICE9PSBmYWxzZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGlzU2VuZFNjcmVlbigpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuICghIXRoaXMub3V0Ym91bmRTdHJlYW1PcHRzICYmXG4gICAgICAgICAgICB0aGlzLm91dGJvdW5kU3RyZWFtT3B0cy5wdWJsaXNoZXJQcm9wZXJ0aWVzLnZpZGVvU291cmNlID09PSAnc2NyZWVuJyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHNldFNwZWVjaEV2ZW50SWZOb3RFeGlzdHMoKTogdm9pZCB7XG4gICAgICAgIGlmICghdGhpcy5zcGVlY2hFdmVudCkge1xuICAgICAgICAgICAgY29uc3QgaGFya09wdGlvbnMgPSB0aGlzLnNlc3Npb24ub3BlbnZpZHUuYWR2YW5jZWRDb25maWd1cmF0aW9uLnB1Ymxpc2hlclNwZWFraW5nRXZlbnRzT3B0aW9ucyB8fCB7fTtcbiAgICAgICAgICAgIGhhcmtPcHRpb25zLmludGVydmFsID0gKHR5cGVvZiBoYXJrT3B0aW9ucy5pbnRlcnZhbCA9PT0gJ251bWJlcicpID8gaGFya09wdGlvbnMuaW50ZXJ2YWwgOiA1MDtcbiAgICAgICAgICAgIGhhcmtPcHRpb25zLnRocmVzaG9sZCA9ICh0eXBlb2YgaGFya09wdGlvbnMudGhyZXNob2xkID09PSAnbnVtYmVyJykgPyBoYXJrT3B0aW9ucy50aHJlc2hvbGQgOiAtNTA7XG5cbiAgICAgICAgICAgIHRoaXMuc3BlZWNoRXZlbnQgPSBoYXJrKHRoaXMubWVkaWFTdHJlYW0sIGhhcmtPcHRpb25zKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBlbmFibGVTcGVha2luZ0V2ZW50cygpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5zZXRTcGVlY2hFdmVudElmTm90RXhpc3RzKCk7XG4gICAgICAgIHRoaXMuc3BlZWNoRXZlbnQub24oJ3NwZWFraW5nJywgKCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5zZXNzaW9uLmVtaXRFdmVudCgncHVibGlzaGVyU3RhcnRTcGVha2luZycsIFtuZXcgUHVibGlzaGVyU3BlYWtpbmdFdmVudCh0aGlzLnNlc3Npb24sICdwdWJsaXNoZXJTdGFydFNwZWFraW5nJywgdGhpcy5jb25uZWN0aW9uLCB0aGlzLnN0cmVhbUlkKV0pO1xuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy5zcGVlY2hFdmVudC5vbignc3RvcHBlZF9zcGVha2luZycsICgpID0+IHtcbiAgICAgICAgICAgIHRoaXMuc2Vzc2lvbi5lbWl0RXZlbnQoJ3B1Ymxpc2hlclN0b3BTcGVha2luZycsIFtuZXcgUHVibGlzaGVyU3BlYWtpbmdFdmVudCh0aGlzLnNlc3Npb24sICdwdWJsaXNoZXJTdG9wU3BlYWtpbmcnLCB0aGlzLmNvbm5lY3Rpb24sIHRoaXMuc3RyZWFtSWQpXSk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBlbmFibGVPbmNlU3BlYWtpbmdFdmVudHMoKTogdm9pZCB7XG4gICAgICAgIHRoaXMuc2V0U3BlZWNoRXZlbnRJZk5vdEV4aXN0cygpO1xuICAgICAgICB0aGlzLnNwZWVjaEV2ZW50Lm9uKCdzcGVha2luZycsICgpID0+IHtcbiAgICAgICAgICAgIHRoaXMuc2Vzc2lvbi5lbWl0RXZlbnQoJ3B1Ymxpc2hlclN0YXJ0U3BlYWtpbmcnLCBbbmV3IFB1Ymxpc2hlclNwZWFraW5nRXZlbnQodGhpcy5zZXNzaW9uLCAncHVibGlzaGVyU3RhcnRTcGVha2luZycsIHRoaXMuY29ubmVjdGlvbiwgdGhpcy5zdHJlYW1JZCldKTtcbiAgICAgICAgICAgIHRoaXMuZGlzYWJsZVNwZWFraW5nRXZlbnRzKCk7XG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLnNwZWVjaEV2ZW50Lm9uKCdzdG9wcGVkX3NwZWFraW5nJywgKCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5zZXNzaW9uLmVtaXRFdmVudCgncHVibGlzaGVyU3RvcFNwZWFraW5nJywgW25ldyBQdWJsaXNoZXJTcGVha2luZ0V2ZW50KHRoaXMuc2Vzc2lvbiwgJ3B1Ymxpc2hlclN0b3BTcGVha2luZycsIHRoaXMuY29ubmVjdGlvbiwgdGhpcy5zdHJlYW1JZCldKTtcbiAgICAgICAgICAgIHRoaXMuZGlzYWJsZVNwZWFraW5nRXZlbnRzKCk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBkaXNhYmxlU3BlYWtpbmdFdmVudHMoKTogdm9pZCB7XG4gICAgICAgIHRoaXMuc3BlZWNoRXZlbnQuc3RvcCgpO1xuICAgICAgICB0aGlzLnNwZWVjaEV2ZW50ID0gdW5kZWZpbmVkO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBpc0xvY2FsKCk6IGJvb2xlYW4ge1xuICAgICAgICAvLyBpbmJvdW5kIG9wdGlvbnMgdW5kZWZpbmVkIGFuZCBvdXRib3VuZCBvcHRpb25zIGRlZmluZWRcbiAgICAgICAgcmV0dXJuICghdGhpcy5pbmJvdW5kU3RyZWFtT3B0cyAmJiAhIXRoaXMub3V0Ym91bmRTdHJlYW1PcHRzKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgZ2V0U2VsZWN0ZWRJY2VDYW5kaWRhdGUoKTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIHRoaXMud2ViUnRjU3RhdHMuZ2V0U2VsZWN0ZWRJY2VDYW5kaWRhdGVJbmZvKClcbiAgICAgICAgICAgICAgICAudGhlbihyZXBvcnQgPT4gcmVzb2x2ZShyZXBvcnQpKVxuICAgICAgICAgICAgICAgIC5jYXRjaChlcnJvciA9PiByZWplY3QoZXJyb3IpKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGdldFJlbW90ZUljZUNhbmRpZGF0ZUxpc3QoKTogUlRDSWNlQ2FuZGlkYXRlW10ge1xuICAgICAgICByZXR1cm4gdGhpcy53ZWJSdGNQZWVyLnJlbW90ZUNhbmRpZGF0ZXNRdWV1ZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgZ2V0TG9jYWxJY2VDYW5kaWRhdGVMaXN0KCk6IFJUQ0ljZUNhbmRpZGF0ZVtdIHtcbiAgICAgICAgcmV0dXJuIHRoaXMud2ViUnRjUGVlci5sb2NhbENhbmRpZGF0ZXNRdWV1ZTtcbiAgICB9XG5cbiAgICAvKiBQcml2YXRlIG1ldGhvZHMgKi9cblxuICAgIHByaXZhdGUgaW5pdFdlYlJ0Y1BlZXJTZW5kKCk6IFByb21pc2U8YW55PiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG5cbiAgICAgICAgICAgIGNvbnN0IHVzZXJNZWRpYUNvbnN0cmFpbnRzID0ge1xuICAgICAgICAgICAgICAgIGF1ZGlvOiB0aGlzLmlzU2VuZEF1ZGlvKCksXG4gICAgICAgICAgICAgICAgdmlkZW86IHRoaXMuaXNTZW5kVmlkZW8oKVxuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgY29uc3Qgb3B0aW9ucyA9IHtcbiAgICAgICAgICAgICAgICBtZWRpYVN0cmVhbTogdGhpcy5tZWRpYVN0cmVhbSxcbiAgICAgICAgICAgICAgICBtZWRpYUNvbnN0cmFpbnRzOiB1c2VyTWVkaWFDb25zdHJhaW50cyxcbiAgICAgICAgICAgICAgICBvbmljZWNhbmRpZGF0ZTogdGhpcy5jb25uZWN0aW9uLnNlbmRJY2VDYW5kaWRhdGUuYmluZCh0aGlzLmNvbm5lY3Rpb24pLFxuICAgICAgICAgICAgICAgIGljZVNlcnZlcnM6IHRoaXMuZ2V0SWNlU2VydmVyc0NvbmYoKSxcbiAgICAgICAgICAgICAgICBzaW11bGNhc3Q6IGZhbHNlXG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICBjb25zdCBzdWNjZXNzQ2FsbGJhY2sgPSAoc2RwT2ZmZXJQYXJhbSkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuZGVidWcoJ1NlbmRpbmcgU0RQIG9mZmVyIHRvIHB1Ymxpc2ggYXMgJ1xuICAgICAgICAgICAgICAgICAgICArIHRoaXMuc3RyZWFtSWQsIHNkcE9mZmVyUGFyYW0pO1xuXG4gICAgICAgICAgICAgICAgbGV0IHR5cGVPZlZpZGVvID0gJyc7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuaXNTZW5kVmlkZW8oKSkge1xuICAgICAgICAgICAgICAgICAgICB0eXBlT2ZWaWRlbyA9IHRoaXMub3V0Ym91bmRTdHJlYW1PcHRzLnB1Ymxpc2hlclByb3BlcnRpZXMudmlkZW9Tb3VyY2UgaW5zdGFuY2VvZiBNZWRpYVN0cmVhbVRyYWNrID8gJ0NVU1RPTScgOiAodGhpcy5pc1NlbmRTY3JlZW4oKSA/ICdTQ1JFRU4nIDogJ0NBTUVSQScpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMuc2Vzc2lvbi5vcGVudmlkdS5zZW5kUmVxdWVzdCgncHVibGlzaFZpZGVvJywge1xuICAgICAgICAgICAgICAgICAgICBzZHBPZmZlcjogc2RwT2ZmZXJQYXJhbSxcbiAgICAgICAgICAgICAgICAgICAgZG9Mb29wYmFjazogdGhpcy5kaXNwbGF5TXlSZW1vdGUoKSB8fCBmYWxzZSxcbiAgICAgICAgICAgICAgICAgICAgaGFzQXVkaW86IHRoaXMuaXNTZW5kQXVkaW8oKSxcbiAgICAgICAgICAgICAgICAgICAgaGFzVmlkZW86IHRoaXMuaXNTZW5kVmlkZW8oKSxcbiAgICAgICAgICAgICAgICAgICAgYXVkaW9BY3RpdmU6IHRoaXMuYXVkaW9BY3RpdmUsXG4gICAgICAgICAgICAgICAgICAgIHZpZGVvQWN0aXZlOiB0aGlzLnZpZGVvQWN0aXZlLFxuICAgICAgICAgICAgICAgICAgICB0eXBlT2ZWaWRlbyxcbiAgICAgICAgICAgICAgICAgICAgZnJhbWVSYXRlOiAhIXRoaXMuZnJhbWVSYXRlID8gdGhpcy5mcmFtZVJhdGUgOiAtMSxcbiAgICAgICAgICAgICAgICAgICAgdmlkZW9EaW1lbnNpb25zOiBKU09OLnN0cmluZ2lmeSh0aGlzLnZpZGVvRGltZW5zaW9ucylcbiAgICAgICAgICAgICAgICB9LCAoZXJyb3IsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yLmNvZGUgPT09IDQwMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChuZXcgT3BlblZpZHVFcnJvcihPcGVuVmlkdUVycm9yTmFtZS5PUEVOVklEVV9QRVJNSVNTSU9OX0RFTklFRCwgXCJZb3UgZG9uJ3QgaGF2ZSBwZXJtaXNzaW9ucyB0byBwdWJsaXNoXCIpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KCdFcnJvciBvbiBwdWJsaXNoVmlkZW86ICcgKyBKU09OLnN0cmluZ2lmeShlcnJvcikpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy53ZWJSdGNQZWVyLnByb2Nlc3NBbnN3ZXIocmVzcG9uc2Uuc2RwQW5zd2VyKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdHJlYW1JZCA9IHJlc3BvbnNlLmlkO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmlzTG9jYWxTdHJlYW1QdWJsaXNoZWQgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnB1Ymxpc2hlZE9uY2UgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5kaXNwbGF5TXlSZW1vdGUoKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5yZW1vdGVQZWVyU3VjY2Vzc2Z1bGx5RXN0YWJsaXNoZWQoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnc3RyZWFtLWNyZWF0ZWQtYnktcHVibGlzaGVyJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuaW5pdFdlYlJ0Y1N0YXRzKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oXCInUHVibGlzaGVyJyBzdWNjZXNzZnVsbHkgcHVibGlzaGVkIHRvIHNlc3Npb25cIik7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIGlmICh0aGlzLmRpc3BsYXlNeVJlbW90ZSgpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy53ZWJSdGNQZWVyID0gbmV3IFdlYlJ0Y1BlZXJTZW5kcmVjdihvcHRpb25zKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy53ZWJSdGNQZWVyID0gbmV3IFdlYlJ0Y1BlZXJTZW5kb25seShvcHRpb25zKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMud2ViUnRjUGVlci5nZW5lcmF0ZU9mZmVyKCkudGhlbihvZmZlciA9PiB7XG4gICAgICAgICAgICAgICAgc3VjY2Vzc0NhbGxiYWNrKG9mZmVyKTtcbiAgICAgICAgICAgIH0pLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICAgICAgICByZWplY3QobmV3IEVycm9yKCcocHVibGlzaCkgU0RQIG9mZmVyIGVycm9yOiAnICsgSlNPTi5zdHJpbmdpZnkoZXJyb3IpKSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBpbml0V2ViUnRjUGVlclJlY2VpdmUoKTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcblxuICAgICAgICAgICAgY29uc3Qgb2ZmZXJDb25zdHJhaW50cyA9IHtcbiAgICAgICAgICAgICAgICBhdWRpbzogdGhpcy5pbmJvdW5kU3RyZWFtT3B0cy5oYXNBdWRpbyxcbiAgICAgICAgICAgICAgICB2aWRlbzogdGhpcy5pbmJvdW5kU3RyZWFtT3B0cy5oYXNWaWRlb1xuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGNvbnNvbGUuZGVidWcoXCInU2Vzc2lvbi5zdWJzY3JpYmUoU3RyZWFtKScgY2FsbGVkLiBDb25zdHJhaW50cyBvZiBnZW5lcmF0ZSBTRFAgb2ZmZXJcIixcbiAgICAgICAgICAgICAgICBvZmZlckNvbnN0cmFpbnRzKTtcbiAgICAgICAgICAgIGNvbnN0IG9wdGlvbnMgPSB7XG4gICAgICAgICAgICAgICAgb25pY2VjYW5kaWRhdGU6IHRoaXMuY29ubmVjdGlvbi5zZW5kSWNlQ2FuZGlkYXRlLmJpbmQodGhpcy5jb25uZWN0aW9uKSxcbiAgICAgICAgICAgICAgICBtZWRpYUNvbnN0cmFpbnRzOiBvZmZlckNvbnN0cmFpbnRzLFxuICAgICAgICAgICAgICAgIGljZVNlcnZlcnM6IHRoaXMuZ2V0SWNlU2VydmVyc0NvbmYoKSxcbiAgICAgICAgICAgICAgICBzaW11bGNhc3Q6IGZhbHNlXG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICBjb25zdCBzdWNjZXNzQ2FsbGJhY2sgPSAoc2RwT2ZmZXJQYXJhbSkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuZGVidWcoJ1NlbmRpbmcgU0RQIG9mZmVyIHRvIHN1YnNjcmliZSB0byAnXG4gICAgICAgICAgICAgICAgICAgICsgdGhpcy5zdHJlYW1JZCwgc2RwT2ZmZXJQYXJhbSk7XG4gICAgICAgICAgICAgICAgdGhpcy5zZXNzaW9uLm9wZW52aWR1LnNlbmRSZXF1ZXN0KCdyZWNlaXZlVmlkZW9Gcm9tJywge1xuICAgICAgICAgICAgICAgICAgICBzZW5kZXI6IHRoaXMuc3RyZWFtSWQsXG4gICAgICAgICAgICAgICAgICAgIHNkcE9mZmVyOiBzZHBPZmZlclBhcmFtXG4gICAgICAgICAgICAgICAgfSwgKGVycm9yLCByZXNwb25zZSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBpZiAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChuZXcgRXJyb3IoJ0Vycm9yIG9uIHJlY3ZWaWRlb0Zyb206ICcgKyBKU09OLnN0cmluZ2lmeShlcnJvcikpKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMud2ViUnRjUGVlci5wcm9jZXNzQW5zd2VyKHJlc3BvbnNlLnNkcEFuc3dlcikudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5yZW1vdGVQZWVyU3VjY2Vzc2Z1bGx5RXN0YWJsaXNoZWQoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmluaXRXZWJSdGNTdGF0cygpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIHRoaXMud2ViUnRjUGVlciA9IG5ldyBXZWJSdGNQZWVyUmVjdm9ubHkob3B0aW9ucyk7XG4gICAgICAgICAgICB0aGlzLndlYlJ0Y1BlZXIuZ2VuZXJhdGVPZmZlcigpXG4gICAgICAgICAgICAgICAgLnRoZW4ob2ZmZXIgPT4ge1xuICAgICAgICAgICAgICAgICAgICBzdWNjZXNzQ2FsbGJhY2sob2ZmZXIpO1xuICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICAgICAgICAgICAgcmVqZWN0KG5ldyBFcnJvcignKHN1YnNjcmliZSkgU0RQIG9mZmVyIGVycm9yOiAnICsgSlNPTi5zdHJpbmdpZnkoZXJyb3IpKSk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIHByaXZhdGUgcmVtb3RlUGVlclN1Y2Nlc3NmdWxseUVzdGFibGlzaGVkKCk6IHZvaWQge1xuICAgICAgICB0aGlzLm1lZGlhU3RyZWFtID0gdGhpcy53ZWJSdGNQZWVyLnBjLmdldFJlbW90ZVN0cmVhbXMoKVswXTtcbiAgICAgICAgY29uc29sZS5kZWJ1ZygnUGVlciByZW1vdGUgc3RyZWFtJywgdGhpcy5tZWRpYVN0cmVhbSk7XG5cbiAgICAgICAgaWYgKCEhdGhpcy5tZWRpYVN0cmVhbSkge1xuICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ21lZGlhc3RyZWFtLXVwZGF0ZWQnKTtcbiAgICAgICAgICAgIGlmICghdGhpcy5kaXNwbGF5TXlSZW1vdGUoKSAmJiAhIXRoaXMubWVkaWFTdHJlYW0uZ2V0QXVkaW9UcmFja3MoKVswXSAmJiB0aGlzLnNlc3Npb24uc3BlYWtpbmdFdmVudHNFbmFibGVkKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5lbmFibGVTcGVha2luZ0V2ZW50cygpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBpbml0V2ViUnRjU3RhdHMoKTogdm9pZCB7XG4gICAgICAgIHRoaXMud2ViUnRjU3RhdHMgPSBuZXcgV2ViUnRjU3RhdHModGhpcyk7XG4gICAgICAgIHRoaXMud2ViUnRjU3RhdHMuaW5pdFdlYlJ0Y1N0YXRzKCk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBzdG9wV2ViUnRjU3RhdHMoKTogdm9pZCB7XG4gICAgICAgIGlmICghIXRoaXMud2ViUnRjU3RhdHMgJiYgdGhpcy53ZWJSdGNTdGF0cy5pc0VuYWJsZWQoKSkge1xuICAgICAgICAgICAgdGhpcy53ZWJSdGNTdGF0cy5zdG9wV2ViUnRjU3RhdHMoKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgZ2V0SWNlU2VydmVyc0NvbmYoKTogUlRDSWNlU2VydmVyW10gfCB1bmRlZmluZWQge1xuICAgICAgICBsZXQgcmV0dXJuVmFsdWU7XG4gICAgICAgIGlmICghIXRoaXMuc2Vzc2lvbi5vcGVudmlkdS5hZHZhbmNlZENvbmZpZ3VyYXRpb24uaWNlU2VydmVycykge1xuICAgICAgICAgICAgcmV0dXJuVmFsdWUgPSB0aGlzLnNlc3Npb24ub3BlbnZpZHUuYWR2YW5jZWRDb25maWd1cmF0aW9uLmljZVNlcnZlcnMgPT09ICdmcmVlaWNlJyA/XG4gICAgICAgICAgICAgICAgdW5kZWZpbmVkIDpcbiAgICAgICAgICAgICAgICB0aGlzLnNlc3Npb24ub3BlbnZpZHUuYWR2YW5jZWRDb25maWd1cmF0aW9uLmljZVNlcnZlcnM7XG4gICAgICAgIH0gZWxzZSBpZiAodGhpcy5zZXNzaW9uLm9wZW52aWR1LmljZVNlcnZlcnMpIHtcbiAgICAgICAgICAgIHJldHVyblZhbHVlID0gdGhpcy5zZXNzaW9uLm9wZW52aWR1LmljZVNlcnZlcnM7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm5WYWx1ZSA9IHVuZGVmaW5lZDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcmV0dXJuVmFsdWU7XG4gICAgfVxuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBTdHJlYW0gfSBmcm9tICcuL1N0cmVhbSc7XG5pbXBvcnQgeyBFdmVudERpc3BhdGNoZXIgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHVibGljL0V2ZW50RGlzcGF0Y2hlcic7XG5pbXBvcnQgeyBTdHJlYW1NYW5hZ2VyVmlkZW8gfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHVibGljL1N0cmVhbU1hbmFnZXJWaWRlbyc7XG5pbXBvcnQgeyBFdmVudCB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL0V2ZW50JztcbmltcG9ydCB7IFN0cmVhbU1hbmFnZXJFdmVudCB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1N0cmVhbU1hbmFnZXJFdmVudCc7XG5pbXBvcnQgeyBWaWRlb0VsZW1lbnRFdmVudCB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1ZpZGVvRWxlbWVudEV2ZW50JztcbmltcG9ydCB7IFZpZGVvSW5zZXJ0TW9kZSB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRW51bXMvVmlkZW9JbnNlcnRNb2RlJztcblxuaW1wb3J0IEV2ZW50RW1pdHRlciA9IHJlcXVpcmUoJ3dvbGZ5ODctZXZlbnRlbWl0dGVyJyk7XG5cblxuLyoqXG4gKiBJbnRlcmZhY2UgaW4gY2hhcmdlIG9mIGRpc3BsYXlpbmcgdGhlIG1lZGlhIHN0cmVhbXMgaW4gdGhlIEhUTUwgRE9NLiBUaGlzIHdyYXBzIGFueSBbW1B1Ymxpc2hlcl1dIGFuZCBbW1N1YnNjcmliZXJdXSBvYmplY3QuXG4gKiBZb3UgY2FuIGluc2VydCBhcyBtYW55IHZpZGVvIHBsYXllcnMgZm8gdGhlIHNhbWUgU3RyZWFtIGFzIHlvdSB3YW50IGJ5IGNhbGxpbmcgW1tTdHJlYW1NYW5hZ2VyLmFkZFZpZGVvRWxlbWVudF1dIG9yXG4gKiBbW1N0cmVhbU1hbmFnZXIuY3JlYXRlVmlkZW9FbGVtZW50XV0uXG4gKlxuICogVGhlIHVzZSBvZiBTdHJlYW1NYW5hZ2VyIHdyYXBwZXIgaXMgcGFydGljdWxhcmx5IHVzZWZ1bCB3aGVuIHlvdSBkb24ndCBuZWVkIHRvIGRpZmZlcmVudGlhdGUgYmV0d2VlbiBQdWJsaXNoZXIgb3IgU3Vic2NyaWJlciBzdHJlYW1zIG9yIGp1c3RcbiAqIHdhbnQgdG8gZGlyZWN0bHkgbWFuYWdlIHlvdXIgb3duIHZpZGVvIGVsZW1lbnRzIChldmVuIG1vcmUgdGhhbiBvbmUgdmlkZW8gZWxlbWVudCBwZXIgU3RyZWFtKS4gVGhpcyBzY2VuYXJpbyBpcyBwcmV0dHkgY29tbW9uIGluXG4gKiBkZWNsYXJhdGl2ZSwgTVZDIGZyb250ZW5kIGZyYW1ld29ya3Mgc3VjaCBhcyBBbmd1bGFyLCBSZWFjdCBvciBWdWUuanNcbiAqL1xuZXhwb3J0IGNsYXNzIFN0cmVhbU1hbmFnZXIgaW1wbGVtZW50cyBFdmVudERpc3BhdGNoZXIge1xuXG4gICAgLyoqXG4gICAgICogVGhlIFN0cmVhbSByZXByZXNlbnRlZCBpbiB0aGUgRE9NIGJ5IHRoZSBQdWJsaXNoZXIvU3Vic2NyaWJlclxuICAgICAqL1xuICAgIHN0cmVhbTogU3RyZWFtO1xuXG4gICAgLyoqXG4gICAgICogQWxsIHRoZSB2aWRlb3MgZGlzcGxheWluZyB0aGUgU3RyZWFtIG9mIHRoaXMgUHVibGlzaGVyL1N1YnNjcmliZXJcbiAgICAgKi9cbiAgICB2aWRlb3M6IFN0cmVhbU1hbmFnZXJWaWRlb1tdID0gW107XG5cbiAgICAvKipcbiAgICAgKiBXaGV0aGVyIHRoZSBTdHJlYW0gcmVwcmVzZW50ZWQgaW4gdGhlIERPTSBpcyBsb2NhbCBvciByZW1vdGVcbiAgICAgKiAtIGBmYWxzZWAgZm9yIFtbUHVibGlzaGVyXV1cbiAgICAgKiAtIGB0cnVlYCBmb3IgW1tTdWJzY3JpYmVyXV1cbiAgICAgKi9cbiAgICByZW1vdGU6IGJvb2xlYW47XG5cbiAgICAvKipcbiAgICAgKiBUaGUgRE9NIEhUTUxFbGVtZW50IGFzc2lnbmVkIGFzIHRhcmdldCBlbGVtZW50IHdoZW4gY3JlYXRpbmcgdGhlIHZpZGVvIGZvciB0aGUgUHVibGlzaGVyL1N1YnNjcmliZXIuIFRoaXMgcHJvcGVydHkgaXMgb25seSBkZWZpbmVkIGlmOlxuICAgICAqIC0gW1tQdWJsaXNoZXJdXSBoYXMgYmVlbiBpbml0aWFsaXplZCBieSBjYWxsaW5nIG1ldGhvZCBbW09wZW5WaWR1LmluaXRQdWJsaXNoZXJdXSB3aXRoIGEgdmFsaWQgYHRhcmdldEVsZW1lbnRgIHBhcmFtZXRlclxuICAgICAqIC0gW1tTdWJzY3JpYmVyXV0gaGFzIGJlZW4gaW5pdGlhbGl6ZWQgYnkgY2FsbGluZyBtZXRob2QgW1tTZXNzaW9uLnN1YnNjcmliZV1dIHdpdGggYSB2YWxpZCBgdGFyZ2V0RWxlbWVudGAgcGFyYW1ldGVyXG4gICAgICovXG4gICAgdGFyZ2V0RWxlbWVudDogSFRNTEVsZW1lbnQ7XG5cbiAgICAvKipcbiAgICAgKiBgaWRgIGF0dHJpYnV0ZSBvZiB0aGUgRE9NIHZpZGVvIGVsZW1lbnQgZGlzcGxheWluZyB0aGUgUHVibGlzaGVyL1N1YnNjcmliZXIncyBzdHJlYW0uIFRoaXMgcHJvcGVydHkgaXMgb25seSBkZWZpbmVkIGlmOlxuICAgICAqIC0gW1tQdWJsaXNoZXJdXSBoYXMgYmVlbiBpbml0aWFsaXplZCBieSBjYWxsaW5nIG1ldGhvZCBbW09wZW5WaWR1LmluaXRQdWJsaXNoZXJdXSB3aXRoIGEgdmFsaWQgYHRhcmdldEVsZW1lbnRgIHBhcmFtZXRlclxuICAgICAqIC0gW1tTdWJzY3JpYmVyXV0gaGFzIGJlZW4gaW5pdGlhbGl6ZWQgYnkgY2FsbGluZyBtZXRob2QgW1tTZXNzaW9uLnN1YnNjcmliZV1dIHdpdGggYSB2YWxpZCBgdGFyZ2V0RWxlbWVudGAgcGFyYW1ldGVyXG4gICAgICovXG4gICAgaWQ6IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBmaXJzdFZpZGVvRWxlbWVudDogU3RyZWFtTWFuYWdlclZpZGVvO1xuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBsYXp5TGF1bmNoVmlkZW9FbGVtZW50Q3JlYXRlZEV2ZW50ID0gZmFsc2U7XG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGVsZW1lbnQ6IEhUTUxFbGVtZW50O1xuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgZWUgPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHByb3RlY3RlZCBjYW5QbGF5TGlzdGVuZXI6IEV2ZW50TGlzdGVuZXJPckV2ZW50TGlzdGVuZXJPYmplY3Q7XG5cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3RvcihzdHJlYW06IFN0cmVhbSwgdGFyZ2V0RWxlbWVudD86IEhUTUxFbGVtZW50IHwgc3RyaW5nKSB7XG4gICAgICAgIHRoaXMuc3RyZWFtID0gc3RyZWFtO1xuICAgICAgICB0aGlzLnN0cmVhbS5zdHJlYW1NYW5hZ2VyID0gdGhpcztcbiAgICAgICAgdGhpcy5yZW1vdGUgPSAhdGhpcy5zdHJlYW0uaXNMb2NhbCgpO1xuXG4gICAgICAgIGlmICghIXRhcmdldEVsZW1lbnQpIHtcbiAgICAgICAgICAgIGxldCB0YXJnRWw7XG4gICAgICAgICAgICBpZiAodHlwZW9mIHRhcmdldEVsZW1lbnQgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAgICAgdGFyZ0VsID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQodGFyZ2V0RWxlbWVudCk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHRhcmdldEVsZW1lbnQgaW5zdGFuY2VvZiBIVE1MRWxlbWVudCkge1xuICAgICAgICAgICAgICAgIHRhcmdFbCA9IHRhcmdldEVsZW1lbnQ7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICghIXRhcmdFbCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZmlyc3RWaWRlb0VsZW1lbnQgPSB7XG4gICAgICAgICAgICAgICAgICAgIHRhcmdldEVsZW1lbnQ6IHRhcmdFbCxcbiAgICAgICAgICAgICAgICAgICAgdmlkZW86IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3ZpZGVvJyksXG4gICAgICAgICAgICAgICAgICAgIGlkOiAnJ1xuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgdGhpcy50YXJnZXRFbGVtZW50ID0gdGFyZ0VsO1xuICAgICAgICAgICAgICAgIHRoaXMuZWxlbWVudCA9IHRhcmdFbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICB0aGlzLmNhblBsYXlMaXN0ZW5lciA9ICgpID0+IHtcbiAgICAgICAgICAgIGlmICh0aGlzLnN0cmVhbS5pc0xvY2FsKCkpIHtcbiAgICAgICAgICAgICAgICBpZiAoIXRoaXMuc3RyZWFtLmRpc3BsYXlNeVJlbW90ZSgpKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbyhcIllvdXIgbG9jYWwgJ1N0cmVhbScgd2l0aCBpZCBbXCIgKyB0aGlzLnN0cmVhbS5zdHJlYW1JZCArICddIHZpZGVvIGlzIG5vdyBwbGF5aW5nJyk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCd2aWRlb1BsYXlpbmcnLCBbbmV3IFZpZGVvRWxlbWVudEV2ZW50KHRoaXMudmlkZW9zWzBdLnZpZGVvLCB0aGlzLCAndmlkZW9QbGF5aW5nJyldKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oXCJZb3VyIG93biByZW1vdGUgJ1N0cmVhbScgd2l0aCBpZCBbXCIgKyB0aGlzLnN0cmVhbS5zdHJlYW1JZCArICddIHZpZGVvIGlzIG5vdyBwbGF5aW5nJyk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdyZW1vdGVWaWRlb1BsYXlpbmcnLCBbbmV3IFZpZGVvRWxlbWVudEV2ZW50KHRoaXMudmlkZW9zWzBdLnZpZGVvLCB0aGlzLCAncmVtb3RlVmlkZW9QbGF5aW5nJyldKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbyhcIlJlbW90ZSAnU3RyZWFtJyB3aXRoIGlkIFtcIiArIHRoaXMuc3RyZWFtLnN0cmVhbUlkICsgJ10gdmlkZW8gaXMgbm93IHBsYXlpbmcnKTtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgndmlkZW9QbGF5aW5nJywgW25ldyBWaWRlb0VsZW1lbnRFdmVudCh0aGlzLnZpZGVvc1swXS52aWRlbywgdGhpcywgJ3ZpZGVvUGxheWluZycpXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnc3RyZWFtUGxheWluZycsIFtuZXcgU3RyZWFtTWFuYWdlckV2ZW50KHRoaXMpXSk7XG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2VlIFtbRXZlbnREaXNwYXRjaGVyLm9uXV1cbiAgICAgKi9cbiAgICBvbih0eXBlOiBzdHJpbmcsIGhhbmRsZXI6IChldmVudDogRXZlbnQpID0+IHZvaWQpOiBFdmVudERpc3BhdGNoZXIge1xuICAgICAgICB0aGlzLmVlLm9uKHR5cGUsIGV2ZW50ID0+IHtcbiAgICAgICAgICAgIGlmIChldmVudCkge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbyhcIkV2ZW50ICdcIiArIHR5cGUgKyBcIicgdHJpZ2dlcmVkIGJ5ICdcIiArICh0aGlzLnJlbW90ZSA/ICdTdWJzY3JpYmVyJyA6ICdQdWJsaXNoZXInKSArIFwiJ1wiLCBldmVudCk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbyhcIkV2ZW50ICdcIiArIHR5cGUgKyBcIicgdHJpZ2dlcmVkIGJ5ICdcIiArICh0aGlzLnJlbW90ZSA/ICdTdWJzY3JpYmVyJyA6ICdQdWJsaXNoZXInKSArIFwiJ1wiKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGhhbmRsZXIoZXZlbnQpO1xuICAgICAgICB9KTtcbiAgICAgICAgaWYgKHR5cGUgPT09ICd2aWRlb0VsZW1lbnRDcmVhdGVkJykge1xuICAgICAgICAgICAgaWYgKCEhdGhpcy5zdHJlYW0gJiYgdGhpcy5sYXp5TGF1bmNoVmlkZW9FbGVtZW50Q3JlYXRlZEV2ZW50KSB7XG4gICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3ZpZGVvRWxlbWVudENyZWF0ZWQnLCBbbmV3IFZpZGVvRWxlbWVudEV2ZW50KHRoaXMudmlkZW9zWzBdLnZpZGVvLCB0aGlzLCAndmlkZW9FbGVtZW50Q3JlYXRlZCcpXSk7XG4gICAgICAgICAgICAgICAgdGhpcy5sYXp5TGF1bmNoVmlkZW9FbGVtZW50Q3JlYXRlZEV2ZW50ID0gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHR5cGUgPT09ICdzdHJlYW1QbGF5aW5nJyB8fCB0eXBlID09PSAndmlkZW9QbGF5aW5nJykge1xuICAgICAgICAgICAgaWYgKHRoaXMudmlkZW9zWzBdICYmIHRoaXMudmlkZW9zWzBdLnZpZGVvICYmXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8uY3VycmVudFRpbWUgPiAwICYmXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8ucGF1c2VkID09PSBmYWxzZSAmJlxuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9zWzBdLnZpZGVvLmVuZGVkID09PSBmYWxzZSAmJlxuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9zWzBdLnZpZGVvLnJlYWR5U3RhdGUgPT09IDQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnc3RyZWFtUGxheWluZycsIFtuZXcgU3RyZWFtTWFuYWdlckV2ZW50KHRoaXMpXSk7XG4gICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3ZpZGVvUGxheWluZycsIFtuZXcgVmlkZW9FbGVtZW50RXZlbnQodGhpcy52aWRlb3NbMF0udmlkZW8sIHRoaXMsICd2aWRlb1BsYXlpbmcnKV0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNlZSBbW0V2ZW50RGlzcGF0Y2hlci5vbmNlXV1cbiAgICAgKi9cbiAgICBvbmNlKHR5cGU6IHN0cmluZywgaGFuZGxlcjogKGV2ZW50OiBFdmVudCkgPT4gdm9pZCk6IFN0cmVhbU1hbmFnZXIge1xuICAgICAgICB0aGlzLmVlLm9uY2UodHlwZSwgZXZlbnQgPT4ge1xuICAgICAgICAgICAgaWYgKGV2ZW50KSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5pbmZvKFwiRXZlbnQgJ1wiICsgdHlwZSArIFwiJyB0cmlnZ2VyZWQgb25jZVwiLCBldmVudCk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbyhcIkV2ZW50ICdcIiArIHR5cGUgKyBcIicgdHJpZ2dlcmVkIG9uY2VcIik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBoYW5kbGVyKGV2ZW50KTtcbiAgICAgICAgfSk7XG4gICAgICAgIGlmICh0eXBlID09PSAndmlkZW9FbGVtZW50Q3JlYXRlZCcpIHtcbiAgICAgICAgICAgIGlmICghIXRoaXMuc3RyZWFtICYmIHRoaXMubGF6eUxhdW5jaFZpZGVvRWxlbWVudENyZWF0ZWRFdmVudCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCd2aWRlb0VsZW1lbnRDcmVhdGVkJywgW25ldyBWaWRlb0VsZW1lbnRFdmVudCh0aGlzLnZpZGVvc1swXS52aWRlbywgdGhpcywgJ3ZpZGVvRWxlbWVudENyZWF0ZWQnKV0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmICh0eXBlID09PSAnc3RyZWFtUGxheWluZycgfHwgdHlwZSA9PT0gJ3ZpZGVvUGxheWluZycpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLnZpZGVvc1swXSAmJiB0aGlzLnZpZGVvc1swXS52aWRlbyAmJlxuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9zWzBdLnZpZGVvLmN1cnJlbnRUaW1lID4gMCAmJlxuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9zWzBdLnZpZGVvLnBhdXNlZCA9PT0gZmFsc2UgJiZcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvc1swXS52aWRlby5lbmRlZCA9PT0gZmFsc2UgJiZcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvc1swXS52aWRlby5yZWFkeVN0YXRlID09PSA0KSB7XG4gICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3N0cmVhbVBsYXlpbmcnLCBbbmV3IFN0cmVhbU1hbmFnZXJFdmVudCh0aGlzKV0pO1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCd2aWRlb1BsYXlpbmcnLCBbbmV3IFZpZGVvRWxlbWVudEV2ZW50KHRoaXMudmlkZW9zWzBdLnZpZGVvLCB0aGlzLCAndmlkZW9QbGF5aW5nJyldKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZWUgW1tFdmVudERpc3BhdGNoZXIub2ZmXV1cbiAgICAgKi9cbiAgICBvZmYodHlwZTogc3RyaW5nLCBoYW5kbGVyPzogKGV2ZW50OiBFdmVudCkgPT4gdm9pZCk6IFN0cmVhbU1hbmFnZXIge1xuICAgICAgICBpZiAoIWhhbmRsZXIpIHtcbiAgICAgICAgICAgIHRoaXMuZWUucmVtb3ZlQWxsTGlzdGVuZXJzKHR5cGUpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5lZS5vZmYodHlwZSwgaGFuZGxlcik7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogTWFrZXMgYHZpZGVvYCBlbGVtZW50IHBhcmFtZXRlciBkaXNwbGF5IHRoaXMgW1tzdHJlYW1dXS4gVGhpcyBpcyB1c2VmdWwgd2hlbiB5b3UgYXJlXG4gICAgICogW21hbmFnaW5nIHRoZSB2aWRlbyBlbGVtZW50cyBvbiB5b3VyIG93bl0oL2RvY3MvaG93LWRvLWkvbWFuYWdlLXZpZGVvcy8jeW91LXRha2UtY2FyZS1vZi10aGUtdmlkZW8tcGxheWVycylcbiAgICAgKlxuICAgICAqIENhbGxpbmcgdGhpcyBtZXRob2Qgd2l0aCBhIHZpZGVvIGFscmVhZHkgYWRkZWQgdG8gb3RoZXIgUHVibGlzaGVyL1N1YnNjcmliZXIgd2lsbCBjYXVzZSB0aGUgdmlkZW8gZWxlbWVudCB0byBiZVxuICAgICAqIGRpc2Fzc29jaWF0ZWQgZnJvbSB0aGF0IHByZXZpb3VzIFB1Ymxpc2hlci9TdWJzY3JpYmVyIGFuZCB0byBiZSBhc3NvY2lhdGVkIHRvIHRoaXMgb25lLlxuICAgICAqXG4gICAgICogQHJldHVybnMgMSBpZiB0aGUgdmlkZW8gd2Fzbid0IGFzc29jaWF0ZWQgdG8gYW55IG90aGVyIFB1Ymxpc2hlci9TdWJzY3JpYmVyIGFuZCBoYXMgYmVlbiBzdWNjZXNzZnVsbHkgYWRkZWQgdG8gdGhpcyBvbmUuXG4gICAgICogMCBpZiB0aGUgdmlkZW8gd2FzIGFscmVhZHkgYWRkZWQgdG8gdGhpcyBQdWJsaXNoZXIvU3Vic2NyaWJlci4gLTEgaWYgdGhlIHZpZGVvIHdhcyBwcmV2aW91c2x5IGFzc29jaWF0ZWQgdG8gYW55IG90aGVyXG4gICAgICogUHVibGlzaGVyL1N1YnNjcmliZXIgYW5kIGhhcyBiZWVuIHN1Y2Nlc3NmdWxseSBkaXNhc3NvY2lhdGVkIGZyb20gdGhhdCBvbmUgYW5kIHByb3Blcmx5IGFkZGVkIHRvIHRoaXMgb25lLlxuICAgICAqL1xuICAgIGFkZFZpZGVvRWxlbWVudCh2aWRlbzogSFRNTFZpZGVvRWxlbWVudCk6IG51bWJlciB7XG5cbiAgICAgICAgdGhpcy5pbml0aWFsaXplVmlkZW9Qcm9wZXJ0aWVzKHZpZGVvKTtcblxuICAgICAgICAvLyBJZiB0aGUgdmlkZW8gZWxlbWVudCBpcyBhbHJlYWR5IHBhcnQgb2YgdGhpcyBTdHJlYW1NYW5hZ2VyIGRvIG5vdGhpbmdcbiAgICAgICAgZm9yIChjb25zdCB2IG9mIHRoaXMudmlkZW9zKSB7XG4gICAgICAgICAgICBpZiAodi52aWRlbyA9PT0gdmlkZW8pIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gMDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGxldCByZXR1cm5OdW1iZXIgPSAxO1xuXG4gICAgICAgIGZvciAoY29uc3Qgc3RyZWFtTWFuYWdlciBvZiB0aGlzLnN0cmVhbS5zZXNzaW9uLnN0cmVhbU1hbmFnZXJzKSB7XG4gICAgICAgICAgICBpZiAoc3RyZWFtTWFuYWdlci5kaXNhc3NvY2lhdGVWaWRlbyh2aWRlbykpIHtcbiAgICAgICAgICAgICAgICByZXR1cm5OdW1iZXIgPSAtMTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuc3RyZWFtLnNlc3Npb24uc3RyZWFtTWFuYWdlcnMuZm9yRWFjaChzdHJlYW1NYW5hZ2VyID0+IHtcbiAgICAgICAgICAgIHN0cmVhbU1hbmFnZXIuZGlzYXNzb2NpYXRlVmlkZW8odmlkZW8pO1xuICAgICAgICB9KTtcblxuICAgICAgICB0aGlzLnB1c2hOZXdTdHJlYW1NYW5hZ2VyVmlkZW8oe1xuICAgICAgICAgICAgdmlkZW8sXG4gICAgICAgICAgICBpZDogdmlkZW8uaWRcbiAgICAgICAgfSk7XG5cbiAgICAgICAgY29uc29sZS5pbmZvKCdOZXcgdmlkZW8gZWxlbWVudCBhc3NvY2lhdGVkIHRvICcsIHRoaXMpO1xuXG4gICAgICAgIHJldHVybiByZXR1cm5OdW1iZXI7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIG5ldyB2aWRlbyBlbGVtZW50IGRpc3BsYXlpbmcgdGhpcyBbW3N0cmVhbV1dLiBUaGlzIGFsbG93cyB5b3UgdG8gaGF2ZSBtdWx0aXBsZSB2aWRlbyBlbGVtZW50cyBkaXNwbGF5aW5nIHRoZSBzYW1lIG1lZGlhIHN0cmVhbS5cbiAgICAgKlxuICAgICAqICMjIyMgRXZlbnRzIGRpc3BhdGNoZWRcbiAgICAgKlxuICAgICAqIFRoZSBQdWJsaXNoZXIvU3Vic2NyaWJlciBvYmplY3Qgd2lsbCBkaXNwYXRjaCBhIGB2aWRlb0VsZW1lbnRDcmVhdGVkYCBldmVudCBvbmNlIHRoZSBIVE1MIHZpZGVvIGVsZW1lbnQgaGFzIGJlZW4gYWRkZWQgdG8gRE9NLiBTZWUgW1tWaWRlb0VsZW1lbnRFdmVudF1dXG4gICAgICpcbiAgICAgKiBAcGFyYW0gdGFyZ2V0RWxlbWVudCBIVE1MIERPTSBlbGVtZW50IChvciBpdHMgYGlkYCBhdHRyaWJ1dGUpIGluIHdoaWNoIHRoZSB2aWRlbyBlbGVtZW50IG9mIHRoZSBQdWJsaXNoZXIvU3Vic2NyaWJlciB3aWxsIGJlIGluc2VydGVkXG4gICAgICogQHBhcmFtIGluc2VydE1vZGUgSG93IHRoZSB2aWRlbyBlbGVtZW50IHdpbGwgYmUgaW5zZXJ0ZWQgYWNjb3JkaW5nbHkgdG8gYHRhcmdldEVsZW1ldGBcbiAgICAgKi9cbiAgICBjcmVhdGVWaWRlb0VsZW1lbnQodGFyZ2V0RWxlbWVudD86IHN0cmluZyB8IEhUTUxFbGVtZW50LCBpbnNlcnRNb2RlPzogVmlkZW9JbnNlcnRNb2RlKTogSFRNTFZpZGVvRWxlbWVudCB7XG4gICAgICAgIGxldCB0YXJnRWw7XG4gICAgICAgIGlmICh0eXBlb2YgdGFyZ2V0RWxlbWVudCA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgIHRhcmdFbCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKHRhcmdFbCk7XG4gICAgICAgICAgICBpZiAoIXRhcmdFbCkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIlRoZSBwcm92aWRlZCAndGFyZ2V0RWxlbWVudCcgY291bGRuJ3QgYmUgcmVzb2x2ZWQgdG8gYW55IEhUTUwgZWxlbWVudDogXCIgKyB0YXJnZXRFbGVtZW50KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIGlmICh0YXJnZXRFbGVtZW50IGluc3RhbmNlb2YgSFRNTEVsZW1lbnQpIHtcbiAgICAgICAgICAgIHRhcmdFbCA9IHRhcmdldEVsZW1lbnQ7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJUaGUgcHJvdmlkZWQgJ3RhcmdldEVsZW1lbnQnIGNvdWxkbid0IGJlIHJlc29sdmVkIHRvIGFueSBIVE1MIGVsZW1lbnQ6IFwiICsgdGFyZ2V0RWxlbWVudCk7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCB2aWRlbyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3ZpZGVvJyk7XG4gICAgICAgIHRoaXMuaW5pdGlhbGl6ZVZpZGVvUHJvcGVydGllcyh2aWRlbyk7XG5cbiAgICAgICAgbGV0IGluc01vZGUgPSAhIWluc2VydE1vZGUgPyBpbnNlcnRNb2RlIDogVmlkZW9JbnNlcnRNb2RlLkFQUEVORDtcbiAgICAgICAgc3dpdGNoIChpbnNNb2RlKSB7XG4gICAgICAgICAgICBjYXNlIFZpZGVvSW5zZXJ0TW9kZS5BRlRFUjpcbiAgICAgICAgICAgICAgICB0YXJnRWwucGFyZW50Tm9kZSEhLmluc2VydEJlZm9yZSh2aWRlbywgdGFyZ0VsLm5leHRTaWJsaW5nKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgVmlkZW9JbnNlcnRNb2RlLkFQUEVORDpcbiAgICAgICAgICAgICAgICB0YXJnRWwuYXBwZW5kQ2hpbGQodmlkZW8pO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBWaWRlb0luc2VydE1vZGUuQkVGT1JFOlxuICAgICAgICAgICAgICAgIHRhcmdFbC5wYXJlbnROb2RlISEuaW5zZXJ0QmVmb3JlKHZpZGVvLCB0YXJnRWwpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBWaWRlb0luc2VydE1vZGUuUFJFUEVORDpcbiAgICAgICAgICAgICAgICB0YXJnRWwuaW5zZXJ0QmVmb3JlKHZpZGVvLCB0YXJnRWwuY2hpbGROb2Rlc1swXSk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIFZpZGVvSW5zZXJ0TW9kZS5SRVBMQUNFOlxuICAgICAgICAgICAgICAgIHRhcmdFbC5wYXJlbnROb2RlISEucmVwbGFjZUNoaWxkKHZpZGVvLCB0YXJnRWwpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICBpbnNNb2RlID0gVmlkZW9JbnNlcnRNb2RlLkFQUEVORDtcbiAgICAgICAgICAgICAgICB0YXJnRWwuYXBwZW5kQ2hpbGQodmlkZW8pO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgdjogU3RyZWFtTWFuYWdlclZpZGVvID0ge1xuICAgICAgICAgICAgdGFyZ2V0RWxlbWVudDogdGFyZ0VsLFxuICAgICAgICAgICAgdmlkZW8sXG4gICAgICAgICAgICBpbnNlcnRNb2RlOiBpbnNNb2RlLFxuICAgICAgICAgICAgaWQ6IHZpZGVvLmlkXG4gICAgICAgIH07XG4gICAgICAgIHRoaXMucHVzaE5ld1N0cmVhbU1hbmFnZXJWaWRlbyh2KTtcblxuICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgndmlkZW9FbGVtZW50Q3JlYXRlZCcsIFtuZXcgVmlkZW9FbGVtZW50RXZlbnQodi52aWRlbywgdGhpcywgJ3ZpZGVvRWxlbWVudENyZWF0ZWQnKV0pO1xuXG4gICAgICAgIHRoaXMubGF6eUxhdW5jaFZpZGVvRWxlbWVudENyZWF0ZWRFdmVudCA9ICEhdGhpcy5maXJzdFZpZGVvRWxlbWVudDtcblxuICAgICAgICByZXR1cm4gdmlkZW87XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGluaXRpYWxpemVWaWRlb1Byb3BlcnRpZXModmlkZW86IEhUTUxWaWRlb0VsZW1lbnQpOiB2b2lkIHtcbiAgICAgICAgaWYgKCEodGhpcy5zdHJlYW0uaXNMb2NhbCgpICYmIHRoaXMuc3RyZWFtLmRpc3BsYXlNeVJlbW90ZSgpKSkge1xuICAgICAgICAgICAgLy8gQXZvaWQgc2V0dGluZyB0aGUgTWVkaWFTdHJlYW0gaW50byB0aGUgc3JjT2JqZWN0IGlmIHJlbW90ZSBzdWJzY3JpcHRpb24gYmVmb3JlIHB1Ymxpc2hpbmdcbiAgICAgICAgICAgIHZpZGVvLnNyY09iamVjdCA9IHRoaXMuc3RyZWFtLmdldE1lZGlhU3RyZWFtKCk7XG4gICAgICAgIH1cbiAgICAgICAgdmlkZW8uYXV0b3BsYXkgPSB0cnVlO1xuICAgICAgICB2aWRlby5jb250cm9scyA9IGZhbHNlO1xuICAgICAgICBpZiAoIXZpZGVvLmlkKSB7XG4gICAgICAgICAgICB2aWRlby5pZCA9ICh0aGlzLnJlbW90ZSA/ICdyZW1vdGUtJyA6ICdsb2NhbC0nKSArICd2aWRlby0nICsgdGhpcy5zdHJlYW0uc3RyZWFtSWQ7XG4gICAgICAgICAgICAvLyBERVBSRUNBVEVEIHByb3BlcnR5OiBhc3NpZ24gb25jZSB0aGUgcHJvcGVydHkgaWQgaWYgdGhlIHVzZXIgcHJvdmlkZWQgYSB2YWxpZCB0YXJnZXRFbGVtZW50XG4gICAgICAgICAgICBpZiAoIXRoaXMuaWQgJiYgISF0aGlzLnRhcmdldEVsZW1lbnQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmlkID0gdmlkZW8uaWQ7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCF0aGlzLnJlbW90ZSAmJiAhdGhpcy5zdHJlYW0uZGlzcGxheU15UmVtb3RlKCkpIHtcbiAgICAgICAgICAgIHZpZGVvLm11dGVkID0gdHJ1ZTtcbiAgICAgICAgICAgIGlmICh0aGlzLnN0cmVhbS5vdXRib3VuZFN0cmVhbU9wdHMucHVibGlzaGVyUHJvcGVydGllcy5taXJyb3IpIHtcbiAgICAgICAgICAgICAgICB0aGlzLm1pcnJvclZpZGVvKHZpZGVvKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICByZW1vdmVBbGxWaWRlb3MoKTogdm9pZCB7XG4gICAgICAgIGZvciAobGV0IGkgPSB0aGlzLnN0cmVhbS5zZXNzaW9uLnN0cmVhbU1hbmFnZXJzLmxlbmd0aCAtIDE7IGkgPj0gMDsgLS1pKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5zdHJlYW0uc2Vzc2lvbi5zdHJlYW1NYW5hZ2Vyc1tpXSA9PT0gdGhpcykge1xuICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtLnNlc3Npb24uc3RyZWFtTWFuYWdlcnMuc3BsaWNlKGksIDEpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy52aWRlb3MuZm9yRWFjaChzdHJlYW1NYW5hZ2VyVmlkZW8gPT4ge1xuICAgICAgICAgICAgLy8gUmVtb3ZlIG9uY2FucGxheSBldmVudCBsaXN0ZW5lciAob25seSBPcGVuVmlkdSBicm93c2VyIG9uZSwgbm90IHRoZSB1c2VyIG9uZXMpXG4gICAgICAgICAgICBzdHJlYW1NYW5hZ2VyVmlkZW8udmlkZW8ucmVtb3ZlRXZlbnRMaXN0ZW5lcignY2FucGxheScsIHRoaXMuY2FuUGxheUxpc3RlbmVyKTtcbiAgICAgICAgICAgIGlmICghIXN0cmVhbU1hbmFnZXJWaWRlby50YXJnZXRFbGVtZW50KSB7XG4gICAgICAgICAgICAgICAgLy8gT25seSByZW1vdmUgZnJvbSBET00gdmlkZW9zIGNyZWF0ZWQgYnkgT3BlblZpZHUgQnJvd3NlciAodGhvc2UgZ2VuZXJhdGVkIGJ5IHBhc3NpbmcgYSB2YWxpZCB0YXJnZXRFbGVtZW50IGluIE9wZW5WaWR1LmluaXRQdWJsaXNoZXJcbiAgICAgICAgICAgICAgICAvLyBhbmQgU2Vzc2lvbi5zdWJzY3JpYmUgb3IgdGhvc2UgY3JlYXRlZCBieSBTdHJlYW1NYW5hZ2VyLmNyZWF0ZVZpZGVvRWxlbWVudCkuIEFsbCB0aGlzIHZpZGVvcyB0cmlnZ2VyZWQgYSB2aWRlb0VsZW1lbnRDcmVhdGVkIGV2ZW50XG4gICAgICAgICAgICAgICAgc3RyZWFtTWFuYWdlclZpZGVvLnZpZGVvLnBhcmVudE5vZGUhLnJlbW92ZUNoaWxkKHN0cmVhbU1hbmFnZXJWaWRlby52aWRlbyk7XG4gICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3ZpZGVvRWxlbWVudERlc3Ryb3llZCcsIFtuZXcgVmlkZW9FbGVtZW50RXZlbnQoc3RyZWFtTWFuYWdlclZpZGVvLnZpZGVvLCB0aGlzLCAndmlkZW9FbGVtZW50RGVzdHJveWVkJyldKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIFJlbW92ZSBzcmNPYmplY3QgZnJvbSB0aGUgdmlkZW9cbiAgICAgICAgICAgIHN0cmVhbU1hbmFnZXJWaWRlby52aWRlby5zcmNPYmplY3QgPSBudWxsO1xuICAgICAgICAgICAgLy8gUmVtb3ZlIGZyb20gY29sbGVjdGlvbiBvZiB2aWRlb3MgZXZlcnkgdmlkZW8gbWFuYWdlZCBieSBPcGVuVmlkdSBCcm93c2VyXG4gICAgICAgICAgICB0aGlzLnZpZGVvcy5maWx0ZXIodiA9PiAhdi50YXJnZXRFbGVtZW50KTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGRpc2Fzc29jaWF0ZVZpZGVvKHZpZGVvOiBIVE1MVmlkZW9FbGVtZW50KTogYm9vbGVhbiB7XG4gICAgICAgIGxldCBkaXNhc3NvY2lhdGVkID0gZmFsc2U7XG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy52aWRlb3MubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGlmICh0aGlzLnZpZGVvc1tpXS52aWRlbyA9PT0gdmlkZW8pIHtcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvcy5zcGxpY2UoaSwgMSk7XG4gICAgICAgICAgICAgICAgZGlzYXNzb2NpYXRlZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgY29uc29sZS5pbmZvKCdWaWRlbyBlbGVtZW50IGRpc2Fzc29jaWF0ZWQgZnJvbSAnLCB0aGlzKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZGlzYXNzb2NpYXRlZDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgYWRkUGxheUV2ZW50VG9GaXJzdFZpZGVvKCkge1xuICAgICAgICBpZiAoKCEhdGhpcy52aWRlb3NbMF0pICYmICghIXRoaXMudmlkZW9zWzBdLnZpZGVvKSAmJiAodGhpcy52aWRlb3NbMF0udmlkZW8ub25jYW5wbGF5ID09PSBudWxsKSkge1xuICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8uYWRkRXZlbnRMaXN0ZW5lcignY2FucGxheScsIHRoaXMuY2FuUGxheUxpc3RlbmVyKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICB1cGRhdGVNZWRpYVN0cmVhbShtZWRpYVN0cmVhbTogTWVkaWFTdHJlYW0pIHtcbiAgICAgICAgdGhpcy52aWRlb3MuZm9yRWFjaChzdHJlYW1NYW5hZ2VyVmlkZW8gPT4ge1xuICAgICAgICAgICAgc3RyZWFtTWFuYWdlclZpZGVvLnZpZGVvLnNyY09iamVjdCA9IG1lZGlhU3RyZWFtO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgZW1pdEV2ZW50KHR5cGU6IHN0cmluZywgZXZlbnRBcnJheTogYW55W10pOiB2b2lkIHtcbiAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQodHlwZSwgZXZlbnRBcnJheSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBwdXNoTmV3U3RyZWFtTWFuYWdlclZpZGVvKHN0cmVhbU1hbmFnZXJWaWRlbzogU3RyZWFtTWFuYWdlclZpZGVvKSB7XG4gICAgICAgIHRoaXMudmlkZW9zLnB1c2goc3RyZWFtTWFuYWdlclZpZGVvKTtcbiAgICAgICAgdGhpcy5hZGRQbGF5RXZlbnRUb0ZpcnN0VmlkZW8oKTtcbiAgICAgICAgaWYgKHRoaXMuc3RyZWFtLnNlc3Npb24uc3RyZWFtTWFuYWdlcnMuaW5kZXhPZih0aGlzKSA9PT0gLTEpIHtcbiAgICAgICAgICAgIHRoaXMuc3RyZWFtLnNlc3Npb24uc3RyZWFtTWFuYWdlcnMucHVzaCh0aGlzKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgbWlycm9yVmlkZW8odmlkZW8pOiB2b2lkIHtcbiAgICAgICAgdmlkZW8uc3R5bGUudHJhbnNmb3JtID0gJ3JvdGF0ZVkoMTgwZGVnKSc7XG4gICAgICAgIHZpZGVvLnN0eWxlLndlYmtpdFRyYW5zZm9ybSA9ICdyb3RhdGVZKDE4MGRlZyknO1xuICAgIH1cblxufSIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTctMjAxOCBPcGVuVmlkdSAoaHR0cHM6Ly9vcGVudmlkdS5pby8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuaW1wb3J0IHsgU3RyZWFtIH0gZnJvbSAnLi9TdHJlYW0nO1xuaW1wb3J0IHsgU3RyZWFtTWFuYWdlciB9IGZyb20gJy4vU3RyZWFtTWFuYWdlcic7XG5pbXBvcnQgeyBTdWJzY3JpYmVyUHJvcGVydGllcyB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvSW50ZXJmYWNlcy9QdWJsaWMvU3Vic2NyaWJlclByb3BlcnRpZXMnO1xuXG5cbi8qKlxuICogUGFja3MgcmVtb3RlIG1lZGlhIHN0cmVhbXMuIFBhcnRpY2lwYW50cyBhdXRvbWF0aWNhbGx5IHJlY2VpdmUgdGhlbSB3aGVuIG90aGVycyBwdWJsaXNoIHRoZWlyIHN0cmVhbXMuIEluaXRpYWxpemVkIHdpdGggW1tTZXNzaW9uLnN1YnNjcmliZV1dIG1ldGhvZFxuICovXG5leHBvcnQgY2xhc3MgU3Vic2NyaWJlciBleHRlbmRzIFN0cmVhbU1hbmFnZXIge1xuXG4gICAgcHJpdmF0ZSBwcm9wZXJ0aWVzOiBTdWJzY3JpYmVyUHJvcGVydGllcztcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3RvcihzdHJlYW06IFN0cmVhbSwgdGFyZ0VsOiBzdHJpbmcgfCBIVE1MRWxlbWVudCwgcHJvcGVydGllczogU3Vic2NyaWJlclByb3BlcnRpZXMpIHtcbiAgICAgICAgc3VwZXIoc3RyZWFtLCB0YXJnRWwpO1xuICAgICAgICB0aGlzLmVsZW1lbnQgPSB0aGlzLnRhcmdldEVsZW1lbnQ7XG4gICAgICAgIHRoaXMuc3RyZWFtID0gc3RyZWFtO1xuICAgICAgICB0aGlzLnByb3BlcnRpZXMgPSBwcm9wZXJ0aWVzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFN1YnNjcmliZSBvciB1bnN1YnNjcmliZSBmcm9tIHRoZSBhdWRpbyBzdHJlYW0gKGlmIGF2YWlsYWJsZSkuIENhbGxpbmcgdGhpcyBtZXRob2QgdHdpY2UgaW4gYSByb3cgcGFzc2luZyBzYW1lIHZhbHVlIHdpbGwgaGF2ZSBubyBlZmZlY3RcbiAgICAgKiBAcGFyYW0gdmFsdWUgYHRydWVgIHRvIHN1YnNjcmliZSB0byB0aGUgYXVkaW8gc3RyZWFtLCBgZmFsc2VgIHRvIHVuc3Vic2NyaWJlIGZyb20gaXRcbiAgICAgKi9cbiAgICBzdWJzY3JpYmVUb0F1ZGlvKHZhbHVlOiBib29sZWFuKTogU3Vic2NyaWJlciB7XG4gICAgICAgIHRoaXMuc3RyZWFtLmdldE1lZGlhU3RyZWFtKCkuZ2V0QXVkaW9UcmFja3MoKS5mb3JFYWNoKCh0cmFjaykgPT4ge1xuICAgICAgICAgICAgdHJhY2suZW5hYmxlZCA9IHZhbHVlO1xuICAgICAgICB9KTtcbiAgICAgICAgY29uc29sZS5pbmZvKFwiJ1N1YnNjcmliZXInIGhhcyBcIiArICh2YWx1ZSA/ICdzdWJzY3JpYmVkIHRvJyA6ICd1bnN1YnNjcmliZWQgZnJvbScpICsgJyBpdHMgYXVkaW8gc3RyZWFtJyk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFN1YnNjcmliZSBvciB1bnN1YnNjcmliZSBmcm9tIHRoZSB2aWRlbyBzdHJlYW0gKGlmIGF2YWlsYWJsZSkuIENhbGxpbmcgdGhpcyBtZXRob2QgdHdpY2UgaW4gYSByb3cgcGFzc2luZyBzYW1lIHZhbHVlIHdpbGwgaGF2ZSBubyBlZmZlY3RcbiAgICAgKiBAcGFyYW0gdmFsdWUgYHRydWVgIHRvIHN1YnNjcmliZSB0byB0aGUgdmlkZW8gc3RyZWFtLCBgZmFsc2VgIHRvIHVuc3Vic2NyaWJlIGZyb20gaXRcbiAgICAgKi9cbiAgICBzdWJzY3JpYmVUb1ZpZGVvKHZhbHVlOiBib29sZWFuKTogU3Vic2NyaWJlciB7XG4gICAgICAgIHRoaXMuc3RyZWFtLmdldE1lZGlhU3RyZWFtKCkuZ2V0VmlkZW9UcmFja3MoKS5mb3JFYWNoKCh0cmFjaykgPT4ge1xuICAgICAgICAgICAgdHJhY2suZW5hYmxlZCA9IHZhbHVlO1xuICAgICAgICB9KTtcbiAgICAgICAgY29uc29sZS5pbmZvKFwiJ1N1YnNjcmliZXInIGhhcyBcIiArICh2YWx1ZSA/ICdzdWJzY3JpYmVkIHRvJyA6ICd1bnN1YnNjcmliZWQgZnJvbScpICsgJyBpdHMgdmlkZW8gc3RyZWFtJyk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxufSIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTctMjAxOCBPcGVuVmlkdSAoaHR0cHM6Ly9vcGVudmlkdS5pby8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuZXhwb3J0IGVudW0gTG9jYWxSZWNvcmRlclN0YXRlIHtcbiAgICBSRUFEWSA9ICdSRUFEWScsXG4gICAgUkVDT1JESU5HID0gJ1JFQ09SRElORycsXG4gICAgUEFVU0VEID0gJ1BBVVNFRCcsXG4gICAgRklOSVNIRUQgPSAnRklOSVNIRUQnXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG4vKipcbiAqIERlZmluZXMgcHJvcGVydHkgW1tPcGVuVmlkdUVycm9yLm5hbWVdXVxuICovXG5leHBvcnQgZW51bSBPcGVuVmlkdUVycm9yTmFtZSB7XG5cbiAgICAvKipcbiAgICAgKiBCcm93c2VyIGlzIG5vdCBzdXBwb3J0ZWQgYnkgT3BlblZpZHUuXG4gICAgICogUmV0dXJuZWQgdXBvbiB1bnN1Y2Nlc3NmdWwgW1tTZXNzaW9uLmNvbm5lY3RdXVxuICAgICAqL1xuICAgIEJST1dTRVJfTk9UX1NVUFBPUlRFRCA9ICdCUk9XU0VSX05PVF9TVVBQT1JURUQnLFxuXG4gICAgLyoqXG4gICAgICogVGhlIHVzZXIgaGFzbid0IGdyYW50ZWQgcGVybWlzc2lvbnMgdG8gdGhlIHJlcXVpcmVkIGlucHV0IGRldmljZSB3aGVuIHRoZSBicm93c2VyIGFza2VkIGZvciB0aGVtLlxuICAgICAqIFJldHVybmVkIHVwb24gdW5zdWNjZXNzZnVsIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dIG9yIFtbT3BlblZpZHUuZ2V0VXNlck1lZGlhXV1cbiAgICAgKi9cbiAgICBERVZJQ0VfQUNDRVNTX0RFTklFRCA9ICdERVZJQ0VfQUNDRVNTX0RFTklFRCcsXG5cbiAgICAvKipcbiAgICAgKiBUaGUgdXNlciBoYXNuJ3QgZ3JhbnRlZCBwZXJtaXNzaW9ucyB0byBjYXB0dXJlIHNvbWUgZGVza3RvcCBzY3JlZW4gd2hlbiB0aGUgYnJvd3NlciBhc2tlZCBmb3IgdGhlbS5cbiAgICAgKiBSZXR1cm5lZCB1cG9uIHVuc3VjY2Vzc2Z1bCBbW09wZW5WaWR1LmluaXRQdWJsaXNoZXJdXSBvciBbW09wZW5WaWR1LmdldFVzZXJNZWRpYV1dXG4gICAgICovXG4gICAgU0NSRUVOX0NBUFRVUkVfREVOSUVEID0gJ1NDUkVFTl9DQVBUVVJFX0RFTklFRCcsXG5cbiAgICAvKipcbiAgICAgKiBCcm93c2VyIGRvZXMgbm90IHN1cHBvcnQgc2NyZWVuIHNoYXJpbmcuXG4gICAgICogUmV0dXJuZWQgdXBvbiB1bnN1Y2Nlc3NmdWwgW1tPcGVuVmlkdS5pbml0UHVibGlzaGVyXV1cbiAgICAgKi9cbiAgICBTQ1JFRU5fU0hBUklOR19OT1RfU1VQUE9SVEVEID0gJ1NDUkVFTl9TSEFSSU5HX05PVF9TVVBQT1JURUQnLFxuXG4gICAgLyoqXG4gICAgICogT25seSBmb3IgQ2hyb21lLCB0aGVyZSdzIG5vIHNjcmVlbiBzaGFyaW5nIGV4dGVuc2lvbiBpbnN0YWxsZWRcbiAgICAgKiBSZXR1cm5lZCB1cG9uIHVuc3VjY2Vzc2Z1bCBbW09wZW5WaWR1LmluaXRQdWJsaXNoZXJdXVxuICAgICAqL1xuICAgIFNDUkVFTl9FWFRFTlNJT05fTk9UX0lOU1RBTExFRCA9ICdTQ1JFRU5fRVhURU5TSU9OX05PVF9JTlNUQUxMRUQnLFxuXG4gICAgLyoqXG4gICAgICogT25seSBmb3IgQ2hyb21lLCB0aGUgc2NyZWVuIHNoYXJpbmcgZXh0ZW5zaW9uIGlzIGluc3RhbGxlZCBidXQgaXMgZGlzYWJsZWRcbiAgICAgKiBSZXR1cm5lZCB1cG9uIHVuc3VjY2Vzc2Z1bCBbW09wZW5WaWR1LmluaXRQdWJsaXNoZXJdXVxuICAgICAqL1xuICAgIFNDUkVFTl9FWFRFTlNJT05fRElTQUJMRUQgPSAnU0NSRUVOX0VYVEVOU0lPTl9ESVNBQkxFRCcsXG5cbiAgICAvKipcbiAgICAgKiBObyB2aWRlbyBpbnB1dCBkZXZpY2UgZm91bmQgd2l0aCB0aGUgcHJvdmlkZWQgZGV2aWNlSWQgKHByb3BlcnR5IFtbUHVibGlzaGVyUHJvcGVydGllcy52aWRlb1NvdXJjZV1dKVxuICAgICAqIFJldHVybmVkIHVwb24gdW5zdWNjZXNzZnVsIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dXG4gICAgICovXG4gICAgSU5QVVRfVklERU9fREVWSUNFX05PVF9GT1VORCA9ICdJTlBVVF9WSURFT19ERVZJQ0VfTk9UX0ZPVU5EJyxcblxuICAgIC8qKlxuICAgICAqIE5vIGF1ZGlvIGlucHV0IGRldmljZSBmb3VuZCB3aXRoIHRoZSBwcm92aWRlZCBkZXZpY2VJZCAocHJvcGVydHkgW1tQdWJsaXNoZXJQcm9wZXJ0aWVzLmF1ZGlvU291cmNlXV0pXG4gICAgICogUmV0dXJuZWQgdXBvbiB1bnN1Y2Nlc3NmdWwgW1tPcGVuVmlkdS5pbml0UHVibGlzaGVyXV1cbiAgICAgKi9cbiAgICBJTlBVVF9BVURJT19ERVZJQ0VfTk9UX0ZPVU5EID0gJ0lOUFVUX0FVRElPX0RFVklDRV9OT1RfRk9VTkQnLFxuXG4gICAgLyoqXG4gICAgICogTWV0aG9kIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dIGhhcyBiZWVuIGNhbGxlZCB3aXRoIHByb3BlcnRpZXMgYHZpZGVvU291cmNlYCBhbmQgYGF1ZGlvU291cmNlYCBvZlxuICAgICAqIFtbUHVibGlzaGVyUHJvcGVydGllc11dIHBhcmFtZXRlciBib3RoIHNldCB0byAqZmFsc2UqIG9yICpudWxsKlxuICAgICAqL1xuICAgIE5PX0lOUFVUX1NPVVJDRV9TRVQgPSAnTk9fSU5QVVRfU09VUkNFX1NFVCcsXG5cbiAgICAvKipcbiAgICAgKiBTb21lIG1lZGlhIHByb3BlcnR5IG9mIFtbUHVibGlzaGVyUHJvcGVydGllc11dIHN1Y2ggYXMgYGZyYW1lUmF0ZWAgb3IgYHJlc29sdXRpb25gIGlzIG5vdCBzdXBwb3J0ZWRcbiAgICAgKiBieSB0aGUgaW5wdXQgZGV2aWNlcyAod2hlbmV2ZXIgaXQgaXMgcG9zc2libGUgdGhleSBhcmUgYXV0b21hdGljYWxseSBhZGp1c3RlZCB0byB0aGUgbW9zdCBzaW1pbGFyIHZhbHVlKS5cbiAgICAgKiBSZXR1cm5lZCB1cG9uIHVuc3VjY2Vzc2Z1bCBbW09wZW5WaWR1LmluaXRQdWJsaXNoZXJdXVxuICAgICAqL1xuICAgIFBVQkxJU0hFUl9QUk9QRVJUSUVTX0VSUk9SID0gJ1BVQkxJU0hFUl9QUk9QRVJUSUVTX0VSUk9SJyxcblxuICAgIC8qKlxuICAgICAqIFRoZSBjbGllbnQgdHJpZWQgdG8gY2FsbCBhIG1ldGhvZCB3aXRob3V0IHRoZSByZXF1aXJlZCBwZXJtaXNzaW9ucy4gVGhpcyBjYW4gb2NjdXIgZm9yIG1ldGhvZHMgW1tTZXNzaW9uLnB1Ymxpc2hdXSxcbiAgICAgKiBbW1Nlc3Npb24uZm9yY2VVbnB1Ymxpc2hdXSBhbmQgW1tTZXNzaW9uLmZvcmNlRGlzY29ubmVjdF1dXG4gICAgICovXG4gICAgT1BFTlZJRFVfUEVSTUlTU0lPTl9ERU5JRUQgPSAnT1BFTlZJRFVfUEVSTUlTU0lPTl9ERU5JRUQnLFxuXG4gICAgLyoqXG4gICAgICogX05vdCBpbiB1c2UgeWV0X1xuICAgICAqL1xuICAgIE9QRU5WSURVX05PVF9DT05ORUNURUQgPSAnT1BFTlZJRFVfTk9UX0NPTk5FQ1RFRCcsXG5cbiAgICAvKipcbiAgICAgKiBfTm90IGluIHVzZSB5ZXRfXG4gICAgICovXG4gICAgR0VORVJJQ19FUlJPUiA9ICdHRU5FUklDX0VSUk9SJ1xufVxuXG4vKipcbiAqIFNpbXBsZSBvYmplY3QgdG8gaWRlbnRpZnkgcnVudGltZSBlcnJvcnMgb24gdGhlIGNsaWVudCBzaWRlXG4gKi9cbmV4cG9ydCBjbGFzcyBPcGVuVmlkdUVycm9yIHtcblxuICAgIG5hbWU6IE9wZW5WaWR1RXJyb3JOYW1lO1xuICAgIG1lc3NhZ2U6IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3RvcihuYW1lOiBPcGVuVmlkdUVycm9yTmFtZSwgbWVzc2FnZTogc3RyaW5nKSB7XG4gICAgICAgIHRoaXMubmFtZSA9IG5hbWU7XG4gICAgICAgIHRoaXMubWVzc2FnZSA9IG1lc3NhZ2U7XG4gICAgfVxuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG4vKipcbiAqIEhvdyB0aGUgdmlkZW8gd2lsbCBiZSBpbnNlcnRlZCBpbiB0aGUgRE9NIGZvciBQdWJsaXNoZXJzIGFuZCBTdWJzY3JpYmVycy4gU2VlIFtbUHVibGlzaGVyUHJvcGVydGllcy5pbnNlcnRNb2RlXV0gYW5kIFtbU3Vic2NyaWJlclByb3BlcnRpZXMuaW5zZXJ0TW9kZV1dXG4gKi9cbmV4cG9ydCBlbnVtIFZpZGVvSW5zZXJ0TW9kZSB7XG5cbiAgICAvKipcbiAgICAgKiBWaWRlbyBpbnNlcnRlZCBhZnRlciB0aGUgdGFyZ2V0IGVsZW1lbnQgKGFzIG5leHQgc2libGluZylcbiAgICAgKi9cbiAgICBBRlRFUiA9ICdBRlRFUicsXG4gICAgLyoqXG4gICAgICogVmlkZW8gaW5zZXJ0ZWQgYXMgbGFzdCBjaGlsZCBvZiB0aGUgdGFyZ2V0IGVsZW1lbnRcbiAgICAgKi9cbiAgICBBUFBFTkQgPSAnQVBQRU5EJyxcbiAgICAvKipcbiAgICAgKiBWaWRlbyBpbnNlcnRlZCBiZWZvcmUgdGhlIHRhcmdldCBlbGVtZW50IChhcyBwcmV2aW91cyBzaWJsaW5nKVxuICAgICAqL1xuICAgIEJFRk9SRSA9ICdCRUZPUkUnLFxuICAgIC8qKlxuICAgICAqIFZpZGVvIGluc2VydGVkIGFzIGZpcnN0IGNoaWxkIG9mIHRoZSB0YXJnZXQgZWxlbWVudFxuICAgICAqL1xuICAgIFBSRVBFTkQgPSAnUFJFUEVORCcsXG4gICAgLyoqXG4gICAgICogVmlkZW8gcmVwbGFjZXMgdGFyZ2V0IGVsZW1lbnRcbiAgICAgKi9cbiAgICBSRVBMQUNFID0gJ1JFUExBQ0UnXG5cbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IEV2ZW50IH0gZnJvbSAnLi9FdmVudCc7XG5pbXBvcnQgeyBDb25uZWN0aW9uIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvQ29ubmVjdGlvbic7XG5pbXBvcnQgeyBTZXNzaW9uIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvU2Vzc2lvbic7XG5cblxuLyoqXG4gKiBEZWZpbmVzIHRoZSBmb2xsb3dpbmcgZXZlbnRzOlxuICogLSBgY29ubmVjdGlvbkNyZWF0ZWRgOiBkaXNwYXRjaGVkIGJ5IFtbU2Vzc2lvbl1dXG4gKiAtIGBjb25uZWN0aW9uRGVzdHJveWVkYDogZGlzcGF0Y2hlZCBieSBbW1Nlc3Npb25dXVxuICovXG5leHBvcnQgY2xhc3MgQ29ubmVjdGlvbkV2ZW50IGV4dGVuZHMgRXZlbnQge1xuXG4gICAgLyoqXG4gICAgICogQ29ubmVjdGlvbiBvYmplY3QgdGhhdCB3YXMgY3JlYXRlZCBvciBkZXN0cm95ZWRcbiAgICAgKi9cbiAgICBjb25uZWN0aW9uOiBDb25uZWN0aW9uO1xuXG4gICAgLyoqXG4gICAgICogRm9yICdjb25uZWN0aW9uRGVzdHJveWVkJyBldmVudDpcbiAgICAgKiAtIFwiZGlzY29ubmVjdFwiOiB0aGUgcmVtb3RlIHVzZXIgaGFzIGNhbGxlZCBgU2Vzc2lvbi5kaXNjb25uZWN0KClgXG4gICAgICogLSBcImZvcmNlRGlzY29ubmVjdEJ5VXNlclwiOiB0aGUgcmVtb3RlIHVzZXIgaGFzIGJlZW4gZXZpY3RlZCBmcm9tIHRoZSBTZXNzaW9uIGJ5IG90aGVyIHVzZXIgY2FsbGluZyBgU2Vzc2lvbi5mb3JjZURpc2Nvbm5lY3QoKWBcbiAgICAgKiAtIFwiZm9yY2VEaXNjb25uZWN0QnlTZXJ2ZXJcIjogdGhlIHJlbW90ZSB1c2VyIGhhcyBiZWVuIGV2aWN0ZWQgZnJvbSB0aGUgU2Vzc2lvbiBieSB0aGUgYXBwbGljYXRpb25cbiAgICAgKiAtIFwic2Vzc2lvbkNsb3NlZEJ5U2VydmVyXCI6IHRoZSBTZXNzaW9uIGhhcyBiZWVuIGNsb3NlZCBieSB0aGUgYXBwbGljYXRpb25cbiAgICAgKiAtIFwibmV0d29ya0Rpc2Nvbm5lY3RcIjogdGhlIHJlbW90ZSB1c2VyIG5ldHdvcmsgY29ubmVjdGlvbiBoYXMgZHJvcHBlZFxuICAgICAqXG4gICAgICogRm9yICdjb25uZWN0aW9uQ3JlYXRlZCcgZW1wdHkgc3RyaW5nXG4gICAgICovXG4gICAgcmVhc29uOiBzdHJpbmc7XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgY29uc3RydWN0b3IoY2FuY2VsYWJsZTogYm9vbGVhbiwgdGFyZ2V0OiBTZXNzaW9uLCB0eXBlOiBzdHJpbmcsIGNvbm5lY3Rpb246IENvbm5lY3Rpb24sIHJlYXNvbjogc3RyaW5nKSB7XG4gICAgICAgIHN1cGVyKGNhbmNlbGFibGUsIHRhcmdldCwgdHlwZSk7XG4gICAgICAgIHRoaXMuY29ubmVjdGlvbiA9IGNvbm5lY3Rpb247XG4gICAgICAgIHRoaXMucmVhc29uID0gcmVhc29uO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6bm8tZW1wdHlcbiAgICBjYWxsRGVmYXVsdEJlaGF2aW9yKCkgeyB9XG5cbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IFN0cmVhbU1hbmFnZXIgfSBmcm9tICcuLi8uLi9PcGVuVmlkdS9TdHJlYW1NYW5hZ2VyJztcbmltcG9ydCB7IFNlc3Npb24gfSBmcm9tICcuLi8uLi9PcGVuVmlkdS9TZXNzaW9uJztcblxuZXhwb3J0IGFic3RyYWN0IGNsYXNzIEV2ZW50IHtcblxuICAgIC8qKlxuICAgICAqIFdoZXRoZXIgdGhlIGV2ZW50IGhhcyBhIGRlZmF1bHQgYmVoYXZpb3IgdGhhdCBtYXkgYmUgcHJldmVudGVkIGJ5IGNhbGxpbmcgW1tFdmVudC5wcmV2ZW50RGVmYXVsdF1dXG4gICAgICovXG4gICAgY2FuY2VsYWJsZTogYm9vbGVhbjtcblxuICAgIC8qKlxuICAgICAqIFRoZSBvYmplY3QgdGhhdCBkaXNwYXRjaGVkIHRoZSBldmVudFxuICAgICAqL1xuICAgIHRhcmdldDogU2Vzc2lvbiB8IFN0cmVhbU1hbmFnZXI7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgdHlwZSBvZiBldmVudC4gVGhpcyBpcyB0aGUgc2FtZSBzdHJpbmcgeW91IHBhc3MgYXMgZmlyc3QgcGFyYW1ldGVyIHdoZW4gY2FsbGluZyBtZXRob2QgYG9uKClgIG9mIGFueSBvYmplY3QgaW1wbGVtZW50aW5nIFtbRXZlbnREaXNwYXRjaGVyXV0gaW50ZXJmYWNlXG4gICAgICovXG4gICAgdHlwZTogc3RyaW5nO1xuXG4gICAgcHJpdmF0ZSBoYXNCZWVuUHJldmVudGVkID0gZmFsc2U7XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgY29uc3RydWN0b3IoY2FuY2VsYWJsZTogYm9vbGVhbiwgdGFyZ2V0OiBTZXNzaW9uIHwgU3RyZWFtTWFuYWdlciwgdHlwZTogc3RyaW5nKSB7XG4gICAgICAgIHRoaXMuY2FuY2VsYWJsZSA9IGNhbmNlbGFibGU7XG4gICAgICAgIHRoaXMudGFyZ2V0ID0gdGFyZ2V0O1xuICAgICAgICB0aGlzLnR5cGUgPSB0eXBlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFdoZXRoZXIgdGhlIGRlZmF1bHQgYmVhaGl2b3VyIG9mIHRoZSBldmVudCBoYXMgYmVlbiBwcmV2ZW50ZWQgb3Igbm90LiBDYWxsIFtbRXZlbnQucHJldmVudERlZmF1bHRdXSB0byBwcmV2ZW50IGl0XG4gICAgICovXG4gICAgaXNEZWZhdWx0UHJldmVudGVkKCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gdGhpcy5oYXNCZWVuUHJldmVudGVkO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFByZXZlbnRzIHRoZSBkZWZhdWx0IGJlaGF2aW9yIG9mIHRoZSBldmVudC4gVGhlIGZvbGxvd2luZyBldmVudHMgaGF2ZSBhIGRlZmF1bHQgYmVoYXZpb3I6XG4gICAgICpcbiAgICAgKiAtIGBzZXNzaW9uRGlzY29ubmVjdGVkYDogZGlzcGF0Y2hlZCBieSBbW1Nlc3Npb25dXSBvYmplY3QsIGF1dG9tYXRpY2FsbHkgdW5zdWJzY3JpYmVzIHRoZSBsZWF2aW5nIHBhcnRpY2lwYW50IGZyb20gZXZlcnkgU3Vic2NyaWJlciBvYmplY3Qgb2YgdGhlIHNlc3Npb24gKHRoaXMgaW5jbHVkZXMgY2xvc2luZyB0aGUgV2ViUlRDUGVlciBjb25uZWN0aW9uIGFuZCBkaXNwb3NpbmcgYWxsIE1lZGlhU3RyZWFtVHJhY2tzKVxuICAgICAqIGFuZCBhbHNvIGRlbGV0ZXMgYW55IEhUTUwgdmlkZW8gZWxlbWVudCBhc3NvY2lhdGVkIHRvIGVhY2ggU3Vic2NyaWJlciAob25seSB0aG9zZSBjcmVhdGVkIGJ5IE9wZW5WaWR1IEJyb3dzZXIsIGVpdGhlciBieSBwYXNzaW5nIGEgdmFsaWQgcGFyYW1ldGVyIGFzIGB0YXJnZXRFbGVtZW50YCBpbiBtZXRob2QgW1tTZXNzaW9uLnN1YnNjcmliZV1dIG9yXG4gICAgICogYnkgY2FsbGluZyBbW1N1YnNjcmliZXIuY3JlYXRlVmlkZW9FbGVtZW50XV0pLiBGb3IgZXZlcnkgdmlkZW8gcmVtb3ZlZCwgZWFjaCBTdWJzY3JpYmVyIG9iamVjdCB3aWxsIGFsc28gZGlzcGF0Y2ggYSBgdmlkZW9FbGVtZW50RGVzdHJveWVkYCBldmVudC5cbiAgICAgKlxuICAgICAqIC0gYHN0cmVhbURlc3Ryb3llZGA6XG4gICAgICogICAtIElmIGRpc3BhdGNoZWQgYnkgYSBbW1B1Ymxpc2hlcl1dICgqeW91KiBoYXZlIHVucHVibGlzaGVkKTogYXV0b21hdGljYWxseSBzdG9wcyBhbGwgbWVkaWEgdHJhY2tzIGFuZCBkZWxldGVzIGFueSBIVE1MIHZpZGVvIGVsZW1lbnQgYXNzb2NpYXRlZCB0byBpdCAob25seSB0aG9zZSBjcmVhdGVkIGJ5IE9wZW5WaWR1IEJyb3dzZXIsIGVpdGhlciBieSBwYXNzaW5nIGEgdmFsaWQgcGFyYW1ldGVyIGFzIGB0YXJnZXRFbGVtZW50YFxuICAgICAqIGluIG1ldGhvZCBbW09wZW5WaWR1LmluaXRQdWJsaXNoZXJdXSBvciBieSBjYWxsaW5nIFtbUHVibGlzaGVyLmNyZWF0ZVZpZGVvRWxlbWVudF1dKS4gRm9yIGV2ZXJ5IHZpZGVvIHJlbW92ZWQsIHRoZSBQdWJsaXNoZXIgb2JqZWN0IHdpbGwgYWxzbyBkaXNwYXRjaCBhIGB2aWRlb0VsZW1lbnREZXN0cm95ZWRgIGV2ZW50LlxuICAgICAqICAgLSBJZiBkaXNwYXRjaGVkIGJ5IFtbU2Vzc2lvbl1dICgqb3RoZXIgdXNlciogaGFzIHVucHVibGlzaGVkKTogYXV0b21hdGljYWxseSB1bnN1YnNjcmliZXMgdGhlIHByb3BlciBTdWJzY3JpYmVyIG9iamVjdCBmcm9tIHRoZSBzZXNzaW9uICh0aGlzIGluY2x1ZGVzIGNsb3NpbmcgdGhlIFdlYlJUQ1BlZXIgY29ubmVjdGlvbiBhbmQgZGlzcG9zaW5nIGFsbCBNZWRpYVN0cmVhbVRyYWNrcylcbiAgICAgKiBhbmQgYWxzbyBkZWxldGVzIGFueSBIVE1MIHZpZGVvIGVsZW1lbnQgYXNzb2NpYXRlZCB0byB0aGF0IFN1YnNjcmliZXIgKG9ubHkgdGhvc2UgY3JlYXRlZCBieSBPcGVuVmlkdSBCcm93c2VyLCBlaXRoZXIgYnkgcGFzc2luZyBhIHZhbGlkIHBhcmFtZXRlciBhcyBgdGFyZ2V0RWxlbWVudGAgaW4gbWV0aG9kIFtbU2Vzc2lvbi5zdWJzY3JpYmVdXSBvclxuICAgICAqIGJ5IGNhbGxpbmcgW1tTdWJzY3JpYmVyLmNyZWF0ZVZpZGVvRWxlbWVudF1dKS4gRm9yIGV2ZXJ5IHZpZGVvIHJlbW92ZWQsIHRoZSBTdWJzY3JpYmVyIG9iamVjdCB3aWxsIGFsc28gZGlzcGF0Y2ggYSBgdmlkZW9FbGVtZW50RGVzdHJveWVkYCBldmVudC5cbiAgICAgKi9cbiAgICBwcmV2ZW50RGVmYXVsdCgpIHtcbiAgICAgICAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lOm5vLWVtcHR5XG4gICAgICAgIHRoaXMuY2FsbERlZmF1bHRCZWhhdmlvciA9ICgpID0+IHsgfTtcbiAgICAgICAgdGhpcy5oYXNCZWVuUHJldmVudGVkID0gdHJ1ZTtcbiAgICB9XG5cbiAgICBwcm90ZWN0ZWQgYWJzdHJhY3QgY2FsbERlZmF1bHRCZWhhdmlvcigpO1xuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBFdmVudCB9IGZyb20gJy4vRXZlbnQnO1xuaW1wb3J0IHsgQ29ubmVjdGlvbiB9IGZyb20gJy4uLy4uL09wZW5WaWR1L0Nvbm5lY3Rpb24nO1xuaW1wb3J0IHsgU2Vzc2lvbiB9IGZyb20gJy4uLy4uJztcblxuXG4vKipcbiAqIERlZmluZXMgdGhlIGZvbGxvd2luZyBldmVudHM6XG4gKiAtIGBwdWJsaXNoZXJTdGFydFNwZWFraW5nYDogZGlzcGF0Y2hlZCBieSBbW1Nlc3Npb25dXVxuICogLSBgcHVibGlzaGVyU3RvcFNwZWFraW5nYDogZGlzcGF0Y2hlZCBieSBbW1Nlc3Npb25dXVxuICpcbiAqIE1vcmUgaW5mb3JtYXRpb246XG4gKiAtIFRoaXMgZXZlbnRzIHdpbGwgb25seSBiZSB0cmlnZ2VyZWQgZm9yICoqcmVtb3RlIHN0cmVhbXMgdGhhdCBoYXZlIGF1ZGlvIHRyYWNrcyoqIChbW1N0cmVhbS5oYXNBdWRpb11dIG11c3QgYmUgdHJ1ZSlcbiAqIC0gQm90aCBldmVudHMgc2hhcmUgdGhlIHNhbWUgbGlmZWN5Y2xlLiBUaGF0IG1lYW5zIHRoYXQgeW91IGNhbiBzdWJzY3JpYmUgdG8gb25seSBvbmUgb2YgdGhlbSBpZiB5b3Ugd2FudCwgYnV0IGlmIHlvdSBjYWxsIGBTZXNzaW9uLm9mZigncHVibGlzaGVyU3RvcFNwZWFraW5nJylgLFxuICoga2VlcCBpbiBtaW5kIHRoYXQgdGhpcyB3aWxsIGFsc28gaW50ZXJuYWxseSByZW1vdmUgYW55ICdwdWJsaXNoZXJTdGFydFNwZWFraW5nJyBldmVudFxuICogLSBZb3UgY2FuIGZ1cnRoZXIgY29uZmlndXJlIGhvdyB0aGUgZXZlbnRzIGFyZSBkaXNwYXRjaGVkIGJ5IHNldHRpbmcgcHJvcGVydHkgYHB1Ymxpc2hlclNwZWFraW5nRXZlbnRzT3B0aW9uc2AgaW4gdGhlIGNhbGwgb2YgW1tPcGVuVmlkdS5zZXRBZHZhbmNlZENvbmZpZ3VyYXRpb25dXVxuICovXG5leHBvcnQgY2xhc3MgUHVibGlzaGVyU3BlYWtpbmdFdmVudCBleHRlbmRzIEV2ZW50IHtcblxuICAgIC8qKlxuICAgICAqIFRoZSBjbGllbnQgdGhhdCBzdGFydGVkIG9yIHN0b3BwZWQgc3BlYWtpbmdcbiAgICAgKi9cbiAgICBjb25uZWN0aW9uOiBDb25uZWN0aW9uO1xuXG4gICAgLyoqXG4gICAgICogVGhlIHN0cmVhbUlkIG9mIHRoZSBTdHJlYW0gYWZmZWN0ZWQgYnkgdGhlIHNwZWFraW5nIGV2ZW50XG4gICAgICovXG4gICAgc3RyZWFtSWQ6IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3Rvcih0YXJnZXQ6IFNlc3Npb24sIHR5cGU6IHN0cmluZywgY29ubmVjdGlvbjogQ29ubmVjdGlvbiwgc3RyZWFtSWQ6IHN0cmluZykge1xuICAgICAgICBzdXBlcihmYWxzZSwgdGFyZ2V0LCB0eXBlKTtcbiAgICAgICAgdGhpcy50eXBlID0gdHlwZTtcbiAgICAgICAgdGhpcy5jb25uZWN0aW9uID0gY29ubmVjdGlvbjtcbiAgICAgICAgdGhpcy5zdHJlYW1JZCA9IHN0cmVhbUlkO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6bm8tZW1wdHlcbiAgICBjYWxsRGVmYXVsdEJlaGF2aW9yKCkgeyB9XG5cbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IEV2ZW50IH0gZnJvbSAnLi9FdmVudCc7XG5pbXBvcnQgeyBTZXNzaW9uIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvU2Vzc2lvbic7XG5cblxuLyoqXG4gKiBEZWZpbmVzIHRoZSBmb2xsb3dpbmcgZXZlbnRzOlxuICogLSBgcmVjb3JkaW5nU3RhcnRlZGA6IGRpc3BhdGNoZWQgYnkgW1tTZXNzaW9uXV1cbiAqIC0gYHJlY29yZGluZ1N0b3BwZWRgOiBkaXNwYXRjaGVkIGJ5IFtbU2Vzc2lvbl1dXG4gKi9cbmV4cG9ydCBjbGFzcyBSZWNvcmRpbmdFdmVudCBleHRlbmRzIEV2ZW50IHtcblxuICAgIC8qKlxuICAgICAqIFRoZSByZWNvcmRpbmcgSUQgZ2VuZXJhdGVkIGluIG9wZW52aWR1LXNlcnZlclxuICAgICAqL1xuICAgIGlkOiBzdHJpbmc7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgcmVjb3JkaW5nIG5hbWUgeW91IHN1cHBsaWVkIHRvIG9wZW52aWR1LXNlcnZlci4gRm9yIGV4YW1wbGUsIHRvIG5hbWUgeW91ciByZWNvcmRpbmcgZmlsZSBNWV9SRUNPUkRJTkc6XG4gICAgICogLSBXaXRoICoqQVBJIFJFU1QqKjogUE9TVCB0byBgL2FwaS9yZWNvcmRpbmdzL3N0YXJ0YCBwYXNzaW5nIEpTT04gYm9keSBge1wic2Vzc2lvblwiOlwic2Vzc2lvbklkXCIsXCJuYW1lXCI6XCJNWV9SRUNPUkRJTkdcIn1gXG4gICAgICogLSBXaXRoICoqb3BlbnZpZHUtamF2YS1jbGllbnQqKjogYE9wZW5WaWR1LnN0YXJ0UmVjb3JkaW5nKHNlc3Npb25JZCwgXCJNWV9SRUNPUkRJTkdcIilgIG9yIGBPcGVuVmlkdS5zdGFydFJlY29yZGluZyhzZXNzaW9uSWQsIG5ldyBSZWNvcmRpbmdQcm9wZXJ0aWVzLkJ1aWxkZXIoKS5uYW1lKFwiTVlfUkVDT1JESU5HXCIpLmJ1aWxkKCkpYFxuICAgICAqIC0gV2l0aCAqKm9wZW52aWR1LW5vZGUtY2xpZW50Kio6IGBPcGVuVmlkdS5zdGFydFJlY29yZGluZyhzZXNzaW9uSWQsIFwiTVlfUkVDT1JESU5HXCIpYCBvciBgT3BlblZpZHUuc3RhcnRSZWNvcmRpbmcoc2Vzc2lvbklkLCB7bmFtZTogXCJNWV9SRUNPUkRJTkdcIn0pYFxuICAgICAqXG4gICAgICogSWYgbm8gbmFtZSBpcyBzdXBwbGllZCwgdGhpcyBwcm9wZXJ0eSB3aWxsIGJlIHVuZGVmaW5lZCBhbmQgdGhlIHJlY29yZGVkIGZpbGUgd2lsbCBiZSBuYW1lZCBhZnRlciBwcm9wZXJ0eSBbW2lkXV1cbiAgICAgKi9cbiAgICBuYW1lPzogc3RyaW5nO1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHRhcmdldDogU2Vzc2lvbiwgdHlwZTogc3RyaW5nLCBpZDogc3RyaW5nLCBuYW1lOiBzdHJpbmcpIHtcbiAgICAgICAgc3VwZXIoZmFsc2UsIHRhcmdldCwgdHlwZSk7XG4gICAgICAgIHRoaXMuaWQgPSBpZDtcbiAgICAgICAgaWYgKG5hbWUgIT09IGlkKSB7XG4gICAgICAgICAgICB0aGlzLm5hbWUgPSBuYW1lO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZTpuby1lbXB0eVxuICAgIGNhbGxEZWZhdWx0QmVoYXZpb3IoKSB7IH1cblxufSIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTctMjAxOCBPcGVuVmlkdSAoaHR0cHM6Ly9vcGVudmlkdS5pby8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuaW1wb3J0IHsgRXZlbnQgfSBmcm9tICcuL0V2ZW50JztcbmltcG9ydCB7IFNlc3Npb24gfSBmcm9tICcuLi8uLi9PcGVuVmlkdS9TZXNzaW9uJztcblxuXG4vKipcbiAqIERlZmluZXMgZXZlbnQgYHNlc3Npb25EaXNjb25uZWN0ZWRgIGRpc3BhdGNoZWQgYnkgW1tTZXNzaW9uXV1cbiAqL1xuZXhwb3J0IGNsYXNzIFNlc3Npb25EaXNjb25uZWN0ZWRFdmVudCBleHRlbmRzIEV2ZW50IHtcblxuICAgIC8qKlxuICAgICAqIC0gXCJkaXNjb25uZWN0XCI6IHlvdSBoYXZlIGNhbGxlZCBgU2Vzc2lvbi5kaXNjb25uZWN0KClgXG4gICAgICogLSBcImZvcmNlRGlzY29ubmVjdEJ5VXNlclwiOiB5b3UgaGF2ZSBiZWVuIGV2aWN0ZWQgZnJvbSB0aGUgU2Vzc2lvbiBieSBvdGhlciB1c2VyIGNhbGxpbmcgYFNlc3Npb24uZm9yY2VEaXNjb25uZWN0KClgXG4gICAgICogLSBcImZvcmNlRGlzY29ubmVjdEJ5U2VydmVyXCI6IHlvdSBoYXZlIGJlZW4gZXZpY3RlZCBmcm9tIHRoZSBTZXNzaW9uIGJ5IHRoZSBhcHBsaWNhdGlvblxuICAgICAqIC0gXCJzZXNzaW9uQ2xvc2VkQnlTZXJ2ZXJcIjogdGhlIFNlc3Npb24gaGFzIGJlZW4gY2xvc2VkIGJ5IHRoZSBhcHBsaWNhdGlvblxuICAgICAqIC0gXCJuZXR3b3JrRGlzY29ubmVjdFwiOiB5b3VyIG5ldHdvcmsgY29ubmVjdGlvbiBoYXMgZHJvcHBlZFxuICAgICAqL1xuICAgIHJlYXNvbjogc3RyaW5nO1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHRhcmdldDogU2Vzc2lvbiwgcmVhc29uOiBzdHJpbmcpIHtcbiAgICAgICAgc3VwZXIodHJ1ZSwgdGFyZ2V0LCAnc2Vzc2lvbkRpc2Nvbm5lY3RlZCcpO1xuICAgICAgICB0aGlzLnJlYXNvbiA9IHJlYXNvbjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgY2FsbERlZmF1bHRCZWhhdmlvcigpIHtcblxuICAgICAgICBjb25zb2xlLmluZm8oXCJDYWxsaW5nIGRlZmF1bHQgYmVoYXZpb3IgdXBvbiAnXCIgKyB0aGlzLnR5cGUgKyBcIicgZXZlbnQgZGlzcGF0Y2hlZCBieSAnU2Vzc2lvbidcIik7XG5cbiAgICAgICAgY29uc3Qgc2Vzc2lvbiA9IDxTZXNzaW9uPnRoaXMudGFyZ2V0O1xuXG4gICAgICAgIC8vIERpc3Bvc2UgYW5kIGRlbGV0ZSBhbGwgcmVtb3RlIENvbm5lY3Rpb25zXG4gICAgICAgIGZvciAoY29uc3QgY29ubmVjdGlvbklkIGluIHNlc3Npb24ucmVtb3RlQ29ubmVjdGlvbnMpIHtcbiAgICAgICAgICAgIGlmICghIXNlc3Npb24ucmVtb3RlQ29ubmVjdGlvbnNbY29ubmVjdGlvbklkXS5zdHJlYW0pIHtcbiAgICAgICAgICAgICAgICBzZXNzaW9uLnJlbW90ZUNvbm5lY3Rpb25zW2Nvbm5lY3Rpb25JZF0uc3RyZWFtLmRpc3Bvc2VXZWJSdGNQZWVyKCk7XG4gICAgICAgICAgICAgICAgc2Vzc2lvbi5yZW1vdGVDb25uZWN0aW9uc1tjb25uZWN0aW9uSWRdLnN0cmVhbS5kaXNwb3NlTWVkaWFTdHJlYW0oKTtcbiAgICAgICAgICAgICAgICBpZiAoc2Vzc2lvbi5yZW1vdGVDb25uZWN0aW9uc1tjb25uZWN0aW9uSWRdLnN0cmVhbS5zdHJlYW1NYW5hZ2VyKSB7XG4gICAgICAgICAgICAgICAgICAgIHNlc3Npb24ucmVtb3RlQ29ubmVjdGlvbnNbY29ubmVjdGlvbklkXS5zdHJlYW0uc3RyZWFtTWFuYWdlci5yZW1vdmVBbGxWaWRlb3MoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZGVsZXRlIHNlc3Npb24ucmVtb3RlU3RyZWFtc0NyZWF0ZWRbc2Vzc2lvbi5yZW1vdGVDb25uZWN0aW9uc1tjb25uZWN0aW9uSWRdLnN0cmVhbS5zdHJlYW1JZF07XG4gICAgICAgICAgICAgICAgc2Vzc2lvbi5yZW1vdGVDb25uZWN0aW9uc1tjb25uZWN0aW9uSWRdLmRpc3Bvc2UoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGRlbGV0ZSBzZXNzaW9uLnJlbW90ZUNvbm5lY3Rpb25zW2Nvbm5lY3Rpb25JZF07XG4gICAgICAgIH1cbiAgICB9XG5cbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IEV2ZW50IH0gZnJvbSAnLi9FdmVudCc7XG5pbXBvcnQgeyBDb25uZWN0aW9uIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvQ29ubmVjdGlvbic7XG5pbXBvcnQgeyBTZXNzaW9uIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvU2Vzc2lvbic7XG5cblxuLyoqXG4gKiBEZWZpbmVzIHRoZSBmb2xsb3dpbmcgZXZlbnRzOlxuICogLSBgc2lnbmFsYDogZGlzcGF0Y2hlZCBieSBbW1Nlc3Npb25dXVxuICogLSBgc2lnbmFsOlRZUEVgOiBkaXNwYXRjaGVkIGJ5IFtbU2Vzc2lvbl1dXG4gKi9cbmV4cG9ydCBjbGFzcyBTaWduYWxFdmVudCBleHRlbmRzIEV2ZW50IHtcblxuICAgIC8qKlxuICAgICAqIFRoZSB0eXBlIG9mIHNpZ25hbCAoY2FuIGJlIGVtcHR5KS5cbiAgICAgKlxuICAgICAqIFRoZSBjbGllbnQgbXVzdCBiZSBzdWJzY3JpYmVkIHRvIGBTZXNzaW9uLm9uKCdzaWduYWw6dHlwZScsIGZ1bmN0aW9uKHNpZ25hbEV2ZW50KSB7Li4ufSlgIHRvIHJlY2VpdmUgdGhpcyBvYmplY3QgaW4gdGhlIGNhbGxiYWNrLlxuICAgICAqXG4gICAgICogU3Vic2NyaWJpbmcgdG8gYFNlc3Npb24ub24oJ3NpZ25hbCcsIGZ1bmN0aW9uKHNpZ25hbEV2ZW50KSB7Li4ufSlgIHdpbGwgdHJpZ2dlciBhbGwgdHlwZXMgb2Ygc2lnbmFscy5cbiAgICAgKi9cbiAgICB0eXBlOiBzdHJpbmc7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgbWVzc2FnZSBvZiB0aGUgc2lnbmFsIChjYW4gYmUgZW10cHkpXG4gICAgICovXG4gICAgZGF0YTogc3RyaW5nO1xuXG4gICAgLyoqXG4gICAgICogVGhlIGNsaWVudCB0aGF0IHNlbnQgdGhlIHNpZ25hbFxuICAgICAqL1xuICAgIGZyb206IENvbm5lY3Rpb247XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgY29uc3RydWN0b3IodGFyZ2V0OiBTZXNzaW9uLCB0eXBlOiBzdHJpbmcsIGRhdGE6IHN0cmluZywgZnJvbTogQ29ubmVjdGlvbikge1xuICAgICAgICBzdXBlcihmYWxzZSwgdGFyZ2V0LCB0eXBlKTtcbiAgICAgICAgdGhpcy50eXBlID0gdHlwZTtcbiAgICAgICAgdGhpcy5kYXRhID0gZGF0YTtcbiAgICAgICAgdGhpcy5mcm9tID0gZnJvbTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lOm5vLWVtcHR5XG4gICAgY2FsbERlZmF1bHRCZWhhdmlvcigpIHsgfVxuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBFdmVudCB9IGZyb20gJy4vRXZlbnQnO1xuaW1wb3J0IHsgUHVibGlzaGVyIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvUHVibGlzaGVyJztcbmltcG9ydCB7IFNlc3Npb24gfSBmcm9tICcuLi8uLi9PcGVuVmlkdS9TZXNzaW9uJztcbmltcG9ydCB7IFN0cmVhbSB9IGZyb20gJy4uLy4uL09wZW5WaWR1L1N0cmVhbSc7XG5cblxuLyoqXG4gKiBEZWZpbmVzIHRoZSBmb2xsb3dpbmcgZXZlbnRzOlxuICogLSBgc3RyZWFtQ3JlYXRlZGA6IGRpc3BhdGNoZWQgYnkgW1tTZXNzaW9uXV0gYW5kIFtbUHVibGlzaGVyXV1cbiAqIC0gYHN0cmVhbURlc3Ryb3llZGA6IGRpc3BhdGNoZWQgYnkgW1tTZXNzaW9uXV0gYW5kIFtbUHVibGlzaGVyXV1cbiAqL1xuZXhwb3J0IGNsYXNzIFN0cmVhbUV2ZW50IGV4dGVuZHMgRXZlbnQge1xuXG4gICAgLyoqXG4gICAgICogU3RyZWFtIG9iamVjdCB0aGF0IHdhcyBjcmVhdGVkIG9yIGRlc3Ryb3llZFxuICAgICAqL1xuICAgIHN0cmVhbTogU3RyZWFtO1xuXG4gICAgLyoqXG4gICAgICogRm9yICdzdHJlYW1EZXN0cm95ZWQnIGV2ZW50OlxuICAgICAqIC0gXCJ1bnB1Ymxpc2hcIjogbWV0aG9kIGBTZXNzaW9uLnVucHVibGlzaCgpYCBoYXMgYmVlbiBjYWxsZWRcbiAgICAgKiAtIFwiZGlzY29ubmVjdFwiOiBtZXRob2QgYFNlc3Npb24uZGlzY29ubmVjdCgpYCBoYXMgYmVlbiBjYWxsZWRcbiAgICAgKiAtIFwiZm9yY2VVbnB1Ymxpc2hCeVVzZXJcIjogc29tZSB1c2VyIGhhcyBjYWxsZWQgYFNlc3Npb24uZm9yY2VVbnB1Ymxpc2goKWAgb3ZlciB0aGUgU3RyZWFtXG4gICAgICogLSBcImZvcmNlRGlzY29ubmVjdEJ5VXNlclwiOiBzb21lIHVzZXIgaGFzIGNhbGxlZCBgU2Vzc2lvbi5mb3JjZURpc2Nvbm5lY3QoKWAgb3ZlciB0aGUgU3RyZWFtXG4gICAgICogLSBcImZvcmNlVW5wdWJsaXNoQnlTZXJ2ZXJcIjogdGhlIHVzZXIncyBzdHJlYW0gaGFzIGJlZW4gdW5wdWJsaXNoZWQgZnJvbSB0aGUgU2Vzc2lvbiBieSB0aGUgYXBwbGljYXRpb25cbiAgICAgKiAtIFwiZm9yY2VEaXNjb25uZWN0QnlTZXJ2ZXJcIjogdGhlIHVzZXIgaGFzIGJlZW4gZXZpY3RlZCBmcm9tIHRoZSBTZXNzaW9uIGJ5IHRoZSBhcHBsaWNhdGlvblxuICAgICAqIC0gXCJzZXNzaW9uQ2xvc2VkQnlTZXJ2ZXJcIjogdGhlIFNlc3Npb24gaGFzIGJlZW4gY2xvc2VkIGJ5IHRoZSBhcHBsaWNhdGlvblxuICAgICAqIC0gXCJuZXR3b3JrRGlzY29ubmVjdFwiOiB0aGUgdXNlcidzIG5ldHdvcmsgY29ubmVjdGlvbiBoYXMgZHJvcHBlZFxuICAgICAqXG4gICAgICogRm9yICdzdHJlYW1DcmVhdGVkJyBlbXB0eSBzdHJpbmdcbiAgICAgKi9cbiAgICByZWFzb246IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3RvcihjYW5jZWxhYmxlOiBib29sZWFuLCB0YXJnZXQ6IFNlc3Npb24gfCBQdWJsaXNoZXIsIHR5cGU6IHN0cmluZywgc3RyZWFtOiBTdHJlYW0sIHJlYXNvbjogc3RyaW5nKSB7XG4gICAgICAgIHN1cGVyKGNhbmNlbGFibGUsIHRhcmdldCwgdHlwZSk7XG4gICAgICAgIHRoaXMuc3RyZWFtID0gc3RyZWFtO1xuICAgICAgICB0aGlzLnJlYXNvbiA9IHJlYXNvbjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgY2FsbERlZmF1bHRCZWhhdmlvcigpIHtcbiAgICAgICAgaWYgKHRoaXMudHlwZSA9PT0gJ3N0cmVhbURlc3Ryb3llZCcpIHtcblxuICAgICAgICAgICAgaWYgKHRoaXMudGFyZ2V0IGluc3RhbmNlb2YgU2Vzc2lvbikge1xuICAgICAgICAgICAgICAgIC8vIFJlbW90ZSBTdHJlYW1cbiAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oXCJDYWxsaW5nIGRlZmF1bHQgYmVoYXZpb3IgdXBvbiAnXCIgKyB0aGlzLnR5cGUgKyBcIicgZXZlbnQgZGlzcGF0Y2hlZCBieSAnU2Vzc2lvbidcIik7XG4gICAgICAgICAgICAgICAgdGhpcy5zdHJlYW0uZGlzcG9zZVdlYlJ0Y1BlZXIoKTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAodGhpcy50YXJnZXQgaW5zdGFuY2VvZiBQdWJsaXNoZXIpIHtcbiAgICAgICAgICAgICAgICAvLyBMb2NhbCBTdHJlYW1cbiAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oXCJDYWxsaW5nIGRlZmF1bHQgYmVoYXZpb3IgdXBvbiAnXCIgKyB0aGlzLnR5cGUgKyBcIicgZXZlbnQgZGlzcGF0Y2hlZCBieSAnUHVibGlzaGVyJ1wiKTtcbiAgICAgICAgICAgICAgICBjbGVhckludGVydmFsKCg8UHVibGlzaGVyPnRoaXMudGFyZ2V0KS5zY3JlZW5TaGFyZVJlc2l6ZUludGVydmFsKTtcbiAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbS5pc0xvY2FsU3RyZWFtUmVhZHlUb1B1Ymxpc2ggPSBmYWxzZTtcblxuICAgICAgICAgICAgICAgIC8vIERlbGV0ZSBQdWJsaXNoZXIgb2JqZWN0IGZyb20gT3BlblZpZHUgcHVibGlzaGVycyBhcnJheVxuICAgICAgICAgICAgICAgIGNvbnN0IG9wZW52aWR1UHVibGlzaGVycyA9ICg8UHVibGlzaGVyPnRoaXMudGFyZ2V0KS5vcGVudmlkdS5wdWJsaXNoZXJzO1xuICAgICAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgb3BlbnZpZHVQdWJsaXNoZXJzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChvcGVudmlkdVB1Ymxpc2hlcnNbaV0gPT09ICg8UHVibGlzaGVyPnRoaXMudGFyZ2V0KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgb3BlbnZpZHVQdWJsaXNoZXJzLnNwbGljZShpLCAxKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBEaXNwb3NlIHRoZSBNZWRpYVN0cmVhbSBsb2NhbCBvYmplY3RcbiAgICAgICAgICAgIHRoaXMuc3RyZWFtLmRpc3Bvc2VNZWRpYVN0cmVhbSgpO1xuXG4gICAgICAgICAgICAvLyBSZW1vdmUgZnJvbSBET00gYWxsIHZpZGVvIGVsZW1lbnRzIGFzc29jaWF0ZWQgdG8gdGhpcyBTdHJlYW0sIGlmIHRoZXJlJ3MgYSBTdHJlYW1NYW5hZ2VyIGRlZmluZWRcbiAgICAgICAgICAgIC8vIChtZXRob2QgU2Vzc2lvbi5zdWJzY3JpYmUgbXVzdCBoYXZlIGJlZW4gY2FsbGVkKVxuICAgICAgICAgICAgaWYgKHRoaXMuc3RyZWFtLnN0cmVhbU1hbmFnZXIpIHRoaXMuc3RyZWFtLnN0cmVhbU1hbmFnZXIucmVtb3ZlQWxsVmlkZW9zKCk7XG5cbiAgICAgICAgICAgIC8vIERlbGV0ZSBzdHJlYW0gZnJvbSBTZXNzaW9uLnJlbW90ZVN0cmVhbXNDcmVhdGVkIG1hcFxuICAgICAgICAgICAgZGVsZXRlIHRoaXMuc3RyZWFtLnNlc3Npb24ucmVtb3RlU3RyZWFtc0NyZWF0ZWRbdGhpcy5zdHJlYW0uc3RyZWFtSWRdO1xuXG4gICAgICAgICAgICAvLyBEZWxldGUgU3RyZWFtT3B0aW9uc1NlcnZlciBmcm9tIHJlbW90ZSBDb25uZWN0aW9uXG4gICAgICAgICAgICBjb25zdCByZW1vdGVDb25uZWN0aW9uID0gdGhpcy5zdHJlYW0uc2Vzc2lvbi5yZW1vdGVDb25uZWN0aW9uc1t0aGlzLnN0cmVhbS5jb25uZWN0aW9uLmNvbm5lY3Rpb25JZF07XG4gICAgICAgICAgICBpZiAoISFyZW1vdGVDb25uZWN0aW9uICYmICEhcmVtb3RlQ29ubmVjdGlvbi5vcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgY29uc3Qgc3RyZWFtT3B0aW9uc1NlcnZlciA9IHJlbW90ZUNvbm5lY3Rpb24ub3B0aW9ucy5zdHJlYW1zO1xuICAgICAgICAgICAgICAgIGZvciAobGV0IGkgPSBzdHJlYW1PcHRpb25zU2VydmVyLmxlbmd0aCAtIDE7IGkgPj0gMDsgLS1pKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChzdHJlYW1PcHRpb25zU2VydmVyW2ldLmlkID09PSB0aGlzLnN0cmVhbS5zdHJlYW1JZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgc3RyZWFtT3B0aW9uc1NlcnZlci5zcGxpY2UoaSwgMSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgfVxuICAgIH1cblxufSIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTctMjAxOCBPcGVuVmlkdSAoaHR0cHM6Ly9vcGVudmlkdS5pby8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuaW1wb3J0IHsgRXZlbnQgfSBmcm9tICcuL0V2ZW50JztcbmltcG9ydCB7IFN0cmVhbU1hbmFnZXIgfSBmcm9tICcuLi8uLi9PcGVuVmlkdS9TdHJlYW1NYW5hZ2VyJztcblxuLyoqXG4gKiBEZWZpbmVzIHRoZSBmb2xsb3dpbmcgZXZlbnRzOlxuICogLSBgc3RyZWFtUGxheWluZ2A6IGRpc3BhdGNoZWQgYnkgW1tTdHJlYW1NYW5hZ2VyXV0gKFtbUHVibGlzaGVyXV0gYW5kIFtbU3Vic2NyaWJlcl1dKVxuICovXG5leHBvcnQgY2xhc3MgU3RyZWFtTWFuYWdlckV2ZW50IGV4dGVuZHMgRXZlbnQge1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHRhcmdldDogU3RyZWFtTWFuYWdlcikge1xuICAgICAgICBzdXBlcihmYWxzZSwgdGFyZ2V0LCAnc3RyZWFtUGxheWluZycpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6bm8tZW1wdHlcbiAgICBjYWxsRGVmYXVsdEJlaGF2aW9yKCkgeyB9XG5cbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IEV2ZW50IH0gZnJvbSAnLi9FdmVudCc7XG5pbXBvcnQgeyBTZXNzaW9uIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvU2Vzc2lvbic7XG5pbXBvcnQgeyBTdHJlYW0gfSBmcm9tICcuLi8uLi9PcGVuVmlkdS9TdHJlYW0nO1xuaW1wb3J0IHsgU3RyZWFtTWFuYWdlciB9IGZyb20gJy4uLy4uL09wZW5WaWR1L1N0cmVhbU1hbmFnZXInO1xuXG4vKipcbiAqIERlZmluZXMgZXZlbnQgYHN0cmVhbVByb3BlcnR5Q2hhbmdlZGAgZGlzcGF0Y2hlZCBieSBbW1Nlc3Npb25dXSBhcyB3ZWxsIGFzIGJ5IFtbU3RyZWFtTWFuYWdlcl1dIChbW1B1Ymxpc2hlcl1dIGFuZCBbW1N1YnNjcmliZXJdXSkuXG4gKiBUaGlzIGV2ZW50IGlzIGZpcmVkIHdoZW4gYW55IHJlbW90ZSBzdHJlYW0gKG93bmVkIGJ5IGEgU3Vic2NyaWJlcikgb3IgbG9jYWwgc3RyZWFtIChvd25lZCBieSBhIFB1Ymxpc2hlcikgdW5kZXJnb2VzXG4gKiBhbnkgY2hhbmdlIGluIGFueSBvZiBpdHMgbXV0YWJsZSBwcm9wZXJ0aWVzIChzZWUgW1tjaGFuZ2VkUHJvcGVydHldXSkuXG4gKi9cbmV4cG9ydCBjbGFzcyBTdHJlYW1Qcm9wZXJ0eUNoYW5nZWRFdmVudCBleHRlbmRzIEV2ZW50IHtcblxuICAgIC8qKlxuICAgICAqIFRoZSBTdHJlYW0gd2hvc2UgcHJvcGVydHkgaGFzIGNoYW5nZWQuIFlvdSBjYW4gYWx3YXlzIGlkZW50aWZ5IHRoZSB1c2VyIHB1Ymxpc2hpbmcgdGhlIGNoYW5nZWQgc3RyZWFtIGJ5IGNvbnN1bHRpbmcgcHJvcGVydHkgW1tTdHJlYW0uY29ubmVjdGlvbl1dXG4gICAgICovXG4gICAgc3RyZWFtOiBTdHJlYW07XG5cbiAgICAvKipcbiAgICAgKiBUaGUgcHJvcGVydHkgb2YgdGhlIHN0cmVhbSB0aGF0IGNoYW5nZWQuIFRoaXMgdmFsdWUgaXMgZWl0aGVyIGBcInZpZGVvQWN0aXZlXCJgLCBgXCJhdWRpb0FjdGl2ZVwiYCBvciBgXCJ2aWRlb0RpbWVuc2lvbnNcImBcbiAgICAgKi9cbiAgICBjaGFuZ2VkUHJvcGVydHk6IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIENhdXNlIG9mIHRoZSBjaGFuZ2Ugb24gdGhlIHN0cmVhbSdzIHByb3BlcnR5OlxuICAgICAqIC0gRm9yIGB2aWRlb0FjdGl2ZWA6IGBcInB1Ymxpc2hWaWRlb1wiYFxuICAgICAqIC0gRm9yIGBhdWRpb0FjdGl2ZWA6IGBcInB1Ymxpc2hBdWRpb1wiYFxuICAgICAqIC0gRm9yIGB2aWRlb0RpbWVuc2lvbnNgOiBgXCJkZXZpY2VSb3RhdGVkXCJgIG9yIGBcInNjcmVlblJlc2l6ZWRcImBcbiAgICAgKi9cbiAgICByZWFzb246IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIE5ldyB2YWx1ZSBvZiB0aGUgcHJvcGVydHkgKGFmdGVyIGNoYW5nZSwgY3VycmVudCB2YWx1ZSlcbiAgICAgKi9cbiAgICBuZXdWYWx1ZTogT2JqZWN0O1xuXG4gICAgLyoqXG4gICAgICogUHJldmlvdXMgdmFsdWUgb2YgdGhlIHByb3BlcnR5IChiZWZvcmUgY2hhbmdlKVxuICAgICAqL1xuICAgIG9sZFZhbHVlOiBPYmplY3Q7XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgY29uc3RydWN0b3IodGFyZ2V0OiBTZXNzaW9uIHwgU3RyZWFtTWFuYWdlciwgc3RyZWFtOiBTdHJlYW0sIGNoYW5nZWRQcm9wZXJ0eTogc3RyaW5nLCBuZXdWYWx1ZTogT2JqZWN0LCBvbGRWYWx1ZTogT2JqZWN0LCByZWFzb246IHN0cmluZykge1xuICAgICAgICBzdXBlcihmYWxzZSwgdGFyZ2V0LCAnc3RyZWFtUHJvcGVydHlDaGFuZ2VkJyk7XG4gICAgICAgIHRoaXMuc3RyZWFtID0gc3RyZWFtO1xuICAgICAgICB0aGlzLmNoYW5nZWRQcm9wZXJ0eSA9IGNoYW5nZWRQcm9wZXJ0eTtcbiAgICAgICAgdGhpcy5uZXdWYWx1ZSA9IG5ld1ZhbHVlO1xuICAgICAgICB0aGlzLm9sZFZhbHVlID0gb2xkVmFsdWU7XG4gICAgICAgIHRoaXMucmVhc29uID0gcmVhc29uO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6bm8tZW1wdHlcbiAgICBjYWxsRGVmYXVsdEJlaGF2aW9yKCkgeyB9XG5cbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IEV2ZW50IH0gZnJvbSAnLi9FdmVudCc7XG5pbXBvcnQgeyBTdHJlYW1NYW5hZ2VyIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvU3RyZWFtTWFuYWdlcic7XG5cblxuLyoqXG4gKiBEZWZpbmVzIHRoZSBmb2xsb3dpbmcgZXZlbnRzOlxuICogLSBgdmlkZW9FbGVtZW50Q3JlYXRlZGA6IGRpc3BhdGNoZWQgYnkgW1tQdWJsaXNoZXJdXSBhbmQgW1tTdWJzY3JpYmVyXV0gd2hlbmV2ZXIgYSBuZXcgSFRNTCB2aWRlbyBlbGVtZW50IGhhcyBiZWVuIGluc2VydGVkIGludG8gRE9NIGJ5IE9wZW5WaWR1IEJyb3dzZXIgbGlicmFyeS4gU2VlXG4gKiBbTWFuYWdlIHZpZGVvIHBsYXllcnNdKC9kb2NzL2hvdy1kby1pL21hbmFnZS12aWRlb3MpIHNlY3Rpb24uXG4gKiAtIGB2aWRlb0VsZW1lbnREZXN0cm95ZWRgOiBkaXNwYXRjaGVkIGJ5IFtbUHVibGlzaGVyXV0gYW5kIFtbU3Vic2NyaWJlcl1dIHdoZW5ldmVyIGFuIEhUTUwgdmlkZW8gZWxlbWVudCBoYXMgYmVlbiByZW1vdmVkIGZyb20gRE9NIGJ5IE9wZW5WaWR1IEJyb3dzZXIgbGlicmFyeS5cbiAqL1xuZXhwb3J0IGNsYXNzIFZpZGVvRWxlbWVudEV2ZW50IGV4dGVuZHMgRXZlbnQge1xuXG4gICAgLyoqXG4gICAgICogVmlkZW8gZWxlbWVudCB0aGF0IHdhcyBjcmVhdGVkIG9yIGRlc3Ryb3llZFxuICAgICAqL1xuICAgIGVsZW1lbnQ6IEhUTUxWaWRlb0VsZW1lbnQ7XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgY29uc3RydWN0b3IoZWxlbWVudDogSFRNTFZpZGVvRWxlbWVudCwgdGFyZ2V0OiBTdHJlYW1NYW5hZ2VyLCB0eXBlOiBzdHJpbmcpIHtcbiAgICAgICAgc3VwZXIoZmFsc2UsIHRhcmdldCwgdHlwZSk7XG4gICAgICAgIHRoaXMuZWxlbWVudCA9IGVsZW1lbnQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZTpuby1lbXB0eVxuICAgIGNhbGxEZWZhdWx0QmVoYXZpb3IoKSB7IH1cblxufSIsImZ1bmN0aW9uIE1hcHBlcigpXG57XG4gIHZhciBzb3VyY2VzID0ge307XG5cblxuICB0aGlzLmZvckVhY2ggPSBmdW5jdGlvbihjYWxsYmFjaylcbiAge1xuICAgIGZvcih2YXIga2V5IGluIHNvdXJjZXMpXG4gICAge1xuICAgICAgdmFyIHNvdXJjZSA9IHNvdXJjZXNba2V5XTtcblxuICAgICAgZm9yKHZhciBrZXkyIGluIHNvdXJjZSlcbiAgICAgICAgY2FsbGJhY2soc291cmNlW2tleTJdKTtcbiAgICB9O1xuICB9O1xuXG4gIHRoaXMuZ2V0ID0gZnVuY3Rpb24oaWQsIHNvdXJjZSlcbiAge1xuICAgIHZhciBpZHMgPSBzb3VyY2VzW3NvdXJjZV07XG4gICAgaWYoaWRzID09IHVuZGVmaW5lZClcbiAgICAgIHJldHVybiB1bmRlZmluZWQ7XG5cbiAgICByZXR1cm4gaWRzW2lkXTtcbiAgfTtcblxuICB0aGlzLnJlbW92ZSA9IGZ1bmN0aW9uKGlkLCBzb3VyY2UpXG4gIHtcbiAgICB2YXIgaWRzID0gc291cmNlc1tzb3VyY2VdO1xuICAgIGlmKGlkcyA9PSB1bmRlZmluZWQpXG4gICAgICByZXR1cm47XG5cbiAgICBkZWxldGUgaWRzW2lkXTtcblxuICAgIC8vIENoZWNrIGl0J3MgZW1wdHlcbiAgICBmb3IodmFyIGkgaW4gaWRzKXtyZXR1cm4gZmFsc2V9XG5cbiAgICBkZWxldGUgc291cmNlc1tzb3VyY2VdO1xuICB9O1xuXG4gIHRoaXMuc2V0ID0gZnVuY3Rpb24odmFsdWUsIGlkLCBzb3VyY2UpXG4gIHtcbiAgICBpZih2YWx1ZSA9PSB1bmRlZmluZWQpXG4gICAgICByZXR1cm4gdGhpcy5yZW1vdmUoaWQsIHNvdXJjZSk7XG5cbiAgICB2YXIgaWRzID0gc291cmNlc1tzb3VyY2VdO1xuICAgIGlmKGlkcyA9PSB1bmRlZmluZWQpXG4gICAgICBzb3VyY2VzW3NvdXJjZV0gPSBpZHMgPSB7fTtcblxuICAgIGlkc1tpZF0gPSB2YWx1ZTtcbiAgfTtcbn07XG5cblxuTWFwcGVyLnByb3RvdHlwZS5wb3AgPSBmdW5jdGlvbihpZCwgc291cmNlKVxue1xuICB2YXIgdmFsdWUgPSB0aGlzLmdldChpZCwgc291cmNlKTtcbiAgaWYodmFsdWUgPT0gdW5kZWZpbmVkKVxuICAgIHJldHVybiB1bmRlZmluZWQ7XG5cbiAgdGhpcy5yZW1vdmUoaWQsIHNvdXJjZSk7XG5cbiAgcmV0dXJuIHZhbHVlO1xufTtcblxuXG5tb2R1bGUuZXhwb3J0cyA9IE1hcHBlcjtcbiIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTQgS3VyZW50byAoaHR0cDovL2t1cmVudG8ub3JnLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG52YXIgSnNvblJwY0NsaWVudCAgPSByZXF1aXJlKCcuL2pzb25ycGNjbGllbnQnKTtcblxuXG5leHBvcnRzLkpzb25ScGNDbGllbnQgID0gSnNvblJwY0NsaWVudDsiLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE0IEt1cmVudG8gKGh0dHA6Ly9rdXJlbnRvLm9yZy8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxudmFyIFJwY0J1aWxkZXIgPSByZXF1aXJlKCcuLi8nKTtcbnZhciBXZWJTb2NrZXRXaXRoUmVjb25uZWN0aW9uID0gcmVxdWlyZSgnLi90cmFuc3BvcnRzL3dlYlNvY2tldFdpdGhSZWNvbm5lY3Rpb24nKTtcblxuRGF0ZS5ub3cgPSBEYXRlLm5vdyB8fCBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gK25ldyBEYXRlO1xufTtcblxudmFyIFBJTkdfSU5URVJWQUwgPSA1MDAwO1xuXG52YXIgUkVDT05ORUNUSU5HID0gJ1JFQ09OTkVDVElORyc7XG52YXIgQ09OTkVDVEVEID0gJ0NPTk5FQ1RFRCc7XG52YXIgRElTQ09OTkVDVEVEID0gJ0RJU0NPTk5FQ1RFRCc7XG5cbnZhciBMb2dnZXIgPSBjb25zb2xlO1xuXG4vKipcbiAqXG4gKiBoZWFydGJlYXQ6IGludGVydmFsIGluIG1zIGZvciBlYWNoIGhlYXJ0YmVhdCBtZXNzYWdlLFxuICogc2VuZENsb3NlTWVzc2FnZSA6IHRydWUgLyBmYWxzZSwgYmVmb3JlIGNsb3NpbmcgdGhlIGNvbm5lY3Rpb24sIGl0IHNlbmRzIGEgY2xvc2VTZXNzaW9uIG1lc3NhZ2VcbiAqIDxwcmU+XG4gKiB3cyA6IHtcbiAqIFx0dXJpIDogVVJJIHRvIGNvbm50ZWN0IHRvLFxuICogIHVzZVNvY2tKUyA6IHRydWUgKHVzZSBTb2NrSlMpIC8gZmFsc2UgKHVzZSBXZWJTb2NrZXQpIGJ5IGRlZmF1bHQsXG4gKiBcdG9uY29ubmVjdGVkIDogY2FsbGJhY2sgbWV0aG9kIHRvIGludm9rZSB3aGVuIGNvbm5lY3Rpb24gaXMgc3VjY2Vzc2Z1bCxcbiAqIFx0b25kaXNjb25uZWN0IDogY2FsbGJhY2sgbWV0aG9kIHRvIGludm9rZSB3aGVuIHRoZSBjb25uZWN0aW9uIGlzIGxvc3QsXG4gKiBcdG9ucmVjb25uZWN0aW5nIDogY2FsbGJhY2sgbWV0aG9kIHRvIGludm9rZSB3aGVuIHRoZSBjbGllbnQgaXMgcmVjb25uZWN0aW5nLFxuICogXHRvbnJlY29ubmVjdGVkIDogY2FsbGJhY2sgbWV0aG9kIHRvIGludm9rZSB3aGVuIHRoZSBjbGllbnQgc3VjY2Vzc2Z1bGx5IHJlY29ubmVjdHMsXG4gKiBcdG9uZXJyb3IgOiBjYWxsYmFjayBtZXRob2QgdG8gaW52b2tlIHdoZW4gdGhlcmUgaXMgYW4gZXJyb3JcbiAqIH0sXG4gKiBycGMgOiB7XG4gKiBcdHJlcXVlc3RUaW1lb3V0IDogdGltZW91dCBmb3IgYSByZXF1ZXN0LFxuICogXHRzZXNzaW9uU3RhdHVzQ2hhbmdlZDogY2FsbGJhY2sgbWV0aG9kIGZvciBjaGFuZ2VzIGluIHNlc3Npb24gc3RhdHVzLFxuICogXHRtZWRpYVJlbmVnb3RpYXRpb246IG1lZGlhUmVuZWdvdGlhdGlvblxuICogfVxuICogPC9wcmU+XG4gKi9cbmZ1bmN0aW9uIEpzb25ScGNDbGllbnQoY29uZmlndXJhdGlvbikge1xuXG4gICAgdmFyIHNlbGYgPSB0aGlzO1xuXG4gICAgdmFyIHdzQ29uZmlnID0gY29uZmlndXJhdGlvbi53cztcblxuICAgIHZhciBub3RSZWNvbm5lY3RJZk51bUxlc3NUaGFuID0gLTE7XG5cbiAgICB2YXIgcGluZ05leHROdW0gPSAwO1xuICAgIHZhciBlbmFibGVkUGluZ3MgPSB0cnVlO1xuICAgIHZhciBwaW5nUG9uZ1N0YXJ0ZWQgPSBmYWxzZTtcbiAgICB2YXIgcGluZ0ludGVydmFsO1xuXG4gICAgdmFyIHN0YXR1cyA9IERJU0NPTk5FQ1RFRDtcblxuICAgIHZhciBvbnJlY29ubmVjdGluZyA9IHdzQ29uZmlnLm9ucmVjb25uZWN0aW5nO1xuICAgIHZhciBvbnJlY29ubmVjdGVkID0gd3NDb25maWcub25yZWNvbm5lY3RlZDtcbiAgICB2YXIgb25jb25uZWN0ZWQgPSB3c0NvbmZpZy5vbmNvbm5lY3RlZDtcbiAgICB2YXIgb25lcnJvciA9IHdzQ29uZmlnLm9uZXJyb3I7XG5cbiAgICBjb25maWd1cmF0aW9uLnJwYy5wdWxsID0gZnVuY3Rpb24ocGFyYW1zLCByZXF1ZXN0KSB7XG4gICAgICAgIHJlcXVlc3QucmVwbHkobnVsbCwgXCJwdXNoXCIpO1xuICAgIH1cblxuICAgIHdzQ29uZmlnLm9ucmVjb25uZWN0aW5nID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIExvZ2dlci5kZWJ1ZyhcIi0tLS0tLS0tLSBPTlJFQ09OTkVDVElORyAtLS0tLS0tLS0tLVwiKTtcbiAgICAgICAgaWYgKHN0YXR1cyA9PT0gUkVDT05ORUNUSU5HKSB7XG4gICAgICAgICAgICBMb2dnZXIuZXJyb3IoXCJXZWJzb2NrZXQgYWxyZWFkeSBpbiBSRUNPTk5FQ1RJTkcgc3RhdGUgd2hlbiByZWNlaXZpbmcgYSBuZXcgT05SRUNPTk5FQ1RJTkcgbWVzc2FnZS4gSWdub3JpbmcgaXRcIik7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBzdGF0dXMgPSBSRUNPTk5FQ1RJTkc7XG4gICAgICAgIGlmIChvbnJlY29ubmVjdGluZykge1xuICAgICAgICAgICAgb25yZWNvbm5lY3RpbmcoKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHdzQ29uZmlnLm9ucmVjb25uZWN0ZWQgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgTG9nZ2VyLmRlYnVnKFwiLS0tLS0tLS0tIE9OUkVDT05ORUNURUQgLS0tLS0tLS0tLS1cIik7XG4gICAgICAgIGlmIChzdGF0dXMgPT09IENPTk5FQ1RFRCkge1xuICAgICAgICAgICAgTG9nZ2VyLmVycm9yKFwiV2Vic29ja2V0IGFscmVhZHkgaW4gQ09OTkVDVEVEIHN0YXRlIHdoZW4gcmVjZWl2aW5nIGEgbmV3IE9OUkVDT05ORUNURUQgbWVzc2FnZS4gSWdub3JpbmcgaXRcIik7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgc3RhdHVzID0gQ09OTkVDVEVEO1xuXG4gICAgICAgIGVuYWJsZWRQaW5ncyA9IHRydWU7XG4gICAgICAgIHVwZGF0ZU5vdFJlY29ubmVjdElmTGVzc1RoYW4oKTtcbiAgICAgICAgdXNlUGluZygpO1xuXG4gICAgICAgIGlmIChvbnJlY29ubmVjdGVkKSB7XG4gICAgICAgICAgICBvbnJlY29ubmVjdGVkKCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB3c0NvbmZpZy5vbmNvbm5lY3RlZCA9IGZ1bmN0aW9uKCkge1xuICAgICAgICBMb2dnZXIuZGVidWcoXCItLS0tLS0tLS0gT05DT05ORUNURUQgLS0tLS0tLS0tLS1cIik7XG4gICAgICAgIGlmIChzdGF0dXMgPT09IENPTk5FQ1RFRCkge1xuICAgICAgICAgICAgTG9nZ2VyLmVycm9yKFwiV2Vic29ja2V0IGFscmVhZHkgaW4gQ09OTkVDVEVEIHN0YXRlIHdoZW4gcmVjZWl2aW5nIGEgbmV3IE9OQ09OTkVDVEVEIG1lc3NhZ2UuIElnbm9yaW5nIGl0XCIpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHN0YXR1cyA9IENPTk5FQ1RFRDtcblxuICAgICAgICBlbmFibGVkUGluZ3MgPSB0cnVlO1xuICAgICAgICB1c2VQaW5nKCk7XG5cbiAgICAgICAgaWYgKG9uY29ubmVjdGVkKSB7XG4gICAgICAgICAgICBvbmNvbm5lY3RlZCgpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgd3NDb25maWcub25lcnJvciA9IGZ1bmN0aW9uKGVycm9yKSB7XG4gICAgICAgIExvZ2dlci5kZWJ1ZyhcIi0tLS0tLS0tLSBPTkVSUk9SIC0tLS0tLS0tLS0tXCIpO1xuXG4gICAgICAgIHN0YXR1cyA9IERJU0NPTk5FQ1RFRDtcblxuICAgICAgICBpZiAob25lcnJvcikge1xuICAgICAgICAgICAgb25lcnJvcihlcnJvcik7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB2YXIgd3MgPSBuZXcgV2ViU29ja2V0V2l0aFJlY29ubmVjdGlvbih3c0NvbmZpZyk7XG5cbiAgICBMb2dnZXIuZGVidWcoJ0Nvbm5lY3Rpbmcgd2Vic29ja2V0IHRvIFVSSTogJyArIHdzQ29uZmlnLnVyaSk7XG5cbiAgICB2YXIgcnBjQnVpbGRlck9wdGlvbnMgPSB7XG4gICAgICAgIHJlcXVlc3RfdGltZW91dDogY29uZmlndXJhdGlvbi5ycGMucmVxdWVzdFRpbWVvdXQsXG4gICAgICAgIHBpbmdfcmVxdWVzdF90aW1lb3V0OiBjb25maWd1cmF0aW9uLnJwYy5oZWFydGJlYXRSZXF1ZXN0VGltZW91dFxuICAgIH07XG5cbiAgICB2YXIgcnBjID0gbmV3IFJwY0J1aWxkZXIoUnBjQnVpbGRlci5wYWNrZXJzLkpzb25SUEMsIHJwY0J1aWxkZXJPcHRpb25zLCB3cyxcbiAgICAgICAgZnVuY3Rpb24ocmVxdWVzdCkge1xuXG4gICAgICAgICAgICBMb2dnZXIuZGVidWcoJ1JlY2VpdmVkIHJlcXVlc3Q6ICcgKyBKU09OLnN0cmluZ2lmeShyZXF1ZXN0KSk7XG5cbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgdmFyIGZ1bmMgPSBjb25maWd1cmF0aW9uLnJwY1tyZXF1ZXN0Lm1ldGhvZF07XG5cbiAgICAgICAgICAgICAgICBpZiAoZnVuYyA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgIExvZ2dlci5lcnJvcihcIk1ldGhvZCBcIiArIHJlcXVlc3QubWV0aG9kICsgXCIgbm90IHJlZ2lzdGVyZWQgaW4gY2xpZW50XCIpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGZ1bmMocmVxdWVzdC5wYXJhbXMsIHJlcXVlc3QpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgICAgIExvZ2dlci5lcnJvcignRXhjZXB0aW9uIHByb2Nlc3NpbmcgcmVxdWVzdDogJyArIEpTT04uc3RyaW5naWZ5KHJlcXVlc3QpKTtcbiAgICAgICAgICAgICAgICBMb2dnZXIuZXJyb3IoZXJyKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG5cbiAgICB0aGlzLnNlbmQgPSBmdW5jdGlvbihtZXRob2QsIHBhcmFtcywgY2FsbGJhY2spIHtcbiAgICAgICAgaWYgKG1ldGhvZCAhPT0gJ3BpbmcnKSB7XG4gICAgICAgICAgICBMb2dnZXIuZGVidWcoJ1JlcXVlc3Q6IG1ldGhvZDonICsgbWV0aG9kICsgXCIgcGFyYW1zOlwiICsgSlNPTi5zdHJpbmdpZnkocGFyYW1zKSk7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgcmVxdWVzdFRpbWUgPSBEYXRlLm5vdygpO1xuXG4gICAgICAgIHJwYy5lbmNvZGUobWV0aG9kLCBwYXJhbXMsIGZ1bmN0aW9uKGVycm9yLCByZXN1bHQpIHtcbiAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgIExvZ2dlci5lcnJvcihcIkVSUk9SOlwiICsgZXJyb3IubWVzc2FnZSArIFwiIGluIFJlcXVlc3Q6IG1ldGhvZDpcIiArXG4gICAgICAgICAgICAgICAgICAgICAgICBtZXRob2QgKyBcIiBwYXJhbXM6XCIgKyBKU09OLnN0cmluZ2lmeShwYXJhbXMpICsgXCIgcmVxdWVzdDpcIiArXG4gICAgICAgICAgICAgICAgICAgICAgICBlcnJvci5yZXF1ZXN0KTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yLmRhdGEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIExvZ2dlci5lcnJvcihcIkVSUk9SIERBVEE6XCIgKyBKU09OLnN0cmluZ2lmeShlcnJvci5kYXRhKSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGNhdGNoIChlKSB7fVxuICAgICAgICAgICAgICAgIGVycm9yLnJlcXVlc3RUaW1lID0gcmVxdWVzdFRpbWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoY2FsbGJhY2spIHtcbiAgICAgICAgICAgICAgICBpZiAocmVzdWx0ICE9IHVuZGVmaW5lZCAmJiByZXN1bHQudmFsdWUgIT09ICdwb25nJykge1xuICAgICAgICAgICAgICAgICAgICBMb2dnZXIuZGVidWcoJ1Jlc3BvbnNlOiAnICsgSlNPTi5zdHJpbmdpZnkocmVzdWx0KSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNhbGxiYWNrKGVycm9yLCByZXN1bHQpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiB1cGRhdGVOb3RSZWNvbm5lY3RJZkxlc3NUaGFuKCkge1xuICAgICAgICBMb2dnZXIuZGVidWcoXCJub3RSZWNvbm5lY3RJZk51bUxlc3NUaGFuID0gXCIgKyBwaW5nTmV4dE51bSArICcgKG9sZD0nICtcbiAgICAgICAgICAgIG5vdFJlY29ubmVjdElmTnVtTGVzc1RoYW4gKyAnKScpO1xuICAgICAgICBub3RSZWNvbm5lY3RJZk51bUxlc3NUaGFuID0gcGluZ05leHROdW07XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gc2VuZFBpbmcoKSB7XG4gICAgICAgIGlmIChlbmFibGVkUGluZ3MpIHtcbiAgICAgICAgICAgIHZhciBwYXJhbXMgPSBudWxsO1xuICAgICAgICAgICAgaWYgKHBpbmdOZXh0TnVtID09IDAgfHwgcGluZ05leHROdW0gPT0gbm90UmVjb25uZWN0SWZOdW1MZXNzVGhhbikge1xuICAgICAgICAgICAgICAgIHBhcmFtcyA9IHtcbiAgICAgICAgICAgICAgICAgICAgaW50ZXJ2YWw6IGNvbmZpZ3VyYXRpb24uaGVhcnRiZWF0IHx8IFBJTkdfSU5URVJWQUxcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcGluZ05leHROdW0rKztcblxuICAgICAgICAgICAgc2VsZi5zZW5kKCdwaW5nJywgcGFyYW1zLCAoZnVuY3Rpb24ocGluZ051bSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmdW5jdGlvbihlcnJvciwgcmVzdWx0KSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFwiRXJyb3IgaW4gcGluZyByZXF1ZXN0ICNcIiArIHBpbmdOdW0gKyBcIiAoXCIgK1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yLm1lc3NhZ2UgKyBcIilcIik7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocGluZ051bSA+IG5vdFJlY29ubmVjdElmTnVtTGVzc1RoYW4pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbmFibGVkUGluZ3MgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB1cGRhdGVOb3RSZWNvbm5lY3RJZkxlc3NUaGFuKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFwiU2VydmVyIGRpZCBub3QgcmVzcG9uZCB0byBwaW5nIG1lc3NhZ2UgI1wiICtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGluZ051bSArIFwiLiBSZWNvbm5lY3RpbmcuLi4gXCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdzLnJlY29ubmVjdFdzKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KShwaW5nTmV4dE51bSkpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFwiVHJ5aW5nIHRvIHNlbmQgcGluZywgYnV0IHBpbmcgaXMgbm90IGVuYWJsZWRcIik7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKlxuICAgICogSWYgY29uZmlndXJhdGlvbi5oZWFyYmVhdCBoYXMgYW55IHZhbHVlLCB0aGUgcGluZy1wb25nIHdpbGwgd29yayB3aXRoIHRoZSBpbnRlcnZhbFxuICAgICogb2YgY29uZmlndXJhdGlvbi5oZWFyYmVhdFxuICAgICovXG4gICAgZnVuY3Rpb24gdXNlUGluZygpIHtcbiAgICAgICAgaWYgKCFwaW5nUG9uZ1N0YXJ0ZWQpIHtcbiAgICAgICAgICAgIExvZ2dlci5kZWJ1ZyhcIlN0YXJ0aW5nIHBpbmcgKGlmIGNvbmZpZ3VyZWQpXCIpXG4gICAgICAgICAgICBwaW5nUG9uZ1N0YXJ0ZWQgPSB0cnVlO1xuXG4gICAgICAgICAgICBpZiAoY29uZmlndXJhdGlvbi5oZWFydGJlYXQgIT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgcGluZ0ludGVydmFsID0gc2V0SW50ZXJ2YWwoc2VuZFBpbmcsIGNvbmZpZ3VyYXRpb24uaGVhcnRiZWF0KTtcbiAgICAgICAgICAgICAgICBzZW5kUGluZygpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgdGhpcy5jbG9zZSA9IGZ1bmN0aW9uKCkge1xuICAgICAgICBMb2dnZXIuZGVidWcoXCJDbG9zaW5nIGpzb25ScGNDbGllbnQgZXhwbGljaXRseSBieSBjbGllbnRcIik7XG5cbiAgICAgICAgaWYgKHBpbmdJbnRlcnZhbCAhPSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIExvZ2dlci5kZWJ1ZyhcIkNsZWFyaW5nIHBpbmcgaW50ZXJ2YWxcIik7XG4gICAgICAgICAgICBjbGVhckludGVydmFsKHBpbmdJbnRlcnZhbCk7XG4gICAgICAgIH1cbiAgICAgICAgcGluZ1BvbmdTdGFydGVkID0gZmFsc2U7XG4gICAgICAgIGVuYWJsZWRQaW5ncyA9IGZhbHNlO1xuXG4gICAgICAgIGlmIChjb25maWd1cmF0aW9uLnNlbmRDbG9zZU1lc3NhZ2UpIHtcbiAgICAgICAgICAgIExvZ2dlci5kZWJ1ZyhcIlNlbmRpbmcgY2xvc2UgbWVzc2FnZVwiKVxuICAgICAgICAgICAgdGhpcy5zZW5kKCdjbG9zZVNlc3Npb24nLCBudWxsLCBmdW5jdGlvbihlcnJvciwgcmVzdWx0KSB7XG4gICAgICAgICAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgIExvZ2dlci5lcnJvcihcIkVycm9yIHNlbmRpbmcgY2xvc2UgbWVzc2FnZTogXCIgKyBKU09OLnN0cmluZ2lmeShlcnJvcikpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB3cy5jbG9zZSgpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0gZWxzZSB7XG5cdFx0XHR3cy5jbG9zZSgpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gVGhpcyBtZXRob2QgaXMgb25seSBmb3IgdGVzdGluZ1xuICAgIHRoaXMuZm9yY2VDbG9zZSA9IGZ1bmN0aW9uKG1pbGxpcykge1xuICAgICAgICB3cy5mb3JjZUNsb3NlKG1pbGxpcyk7XG4gICAgfVxuXG4gICAgdGhpcy5yZWNvbm5lY3QgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgd3MucmVjb25uZWN0V3MoKTtcbiAgICB9XG59XG5cblxubW9kdWxlLmV4cG9ydHMgPSBKc29uUnBjQ2xpZW50O1xuIiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNCBLdXJlbnRvIChodHRwOi8va3VyZW50by5vcmcvKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbnZhciBXZWJTb2NrZXRXaXRoUmVjb25uZWN0aW9uICA9IHJlcXVpcmUoJy4vd2ViU29ja2V0V2l0aFJlY29ubmVjdGlvbicpO1xuXG5cbmV4cG9ydHMuV2ViU29ja2V0V2l0aFJlY29ubmVjdGlvbiAgPSBXZWJTb2NrZXRXaXRoUmVjb25uZWN0aW9uOyIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTMtMjAxNSBLdXJlbnRvIChodHRwOi8va3VyZW50by5vcmcvKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuXCJ1c2Ugc3RyaWN0XCI7XG5cbnZhciBCcm93c2VyV2ViU29ja2V0ID0gZ2xvYmFsLldlYlNvY2tldCB8fCBnbG9iYWwuTW96V2ViU29ja2V0O1xuXG52YXIgTG9nZ2VyID0gY29uc29sZTtcblxuLyoqXG4gKiBHZXQgZWl0aGVyIHRoZSBgV2ViU29ja2V0YCBvciBgTW96V2ViU29ja2V0YCBnbG9iYWxzXG4gKiBpbiB0aGUgYnJvd3NlciBvciB0cnkgdG8gcmVzb2x2ZSBXZWJTb2NrZXQtY29tcGF0aWJsZVxuICogaW50ZXJmYWNlIGV4cG9zZWQgYnkgYHdzYCBmb3IgTm9kZS1saWtlIGVudmlyb25tZW50LlxuICovXG5cbi8qdmFyIFdlYlNvY2tldCA9IEJyb3dzZXJXZWJTb2NrZXQ7XG5pZiAoIVdlYlNvY2tldCAmJiB0eXBlb2Ygd2luZG93ID09PSAndW5kZWZpbmVkJykge1xuICAgIHRyeSB7XG4gICAgICAgIFdlYlNvY2tldCA9IHJlcXVpcmUoJ3dzJyk7XG4gICAgfSBjYXRjaCAoZSkgeyB9XG59Ki9cblxuLy92YXIgU29ja0pTID0gcmVxdWlyZSgnc29ja2pzLWNsaWVudCcpO1xuXG52YXIgTUFYX1JFVFJJRVMgPSAyMDAwOyAvLyBGb3JldmVyLi4uXG52YXIgUkVUUllfVElNRV9NUyA9IDMwMDA7IC8vIEZJWE1FOiBJbXBsZW1lbnQgZXhwb25lbnRpYWwgd2FpdCB0aW1lcy4uLlxuXG52YXIgQ09OTkVDVElORyA9IDA7XG52YXIgT1BFTiA9IDE7XG52YXIgQ0xPU0lORyA9IDI7XG52YXIgQ0xPU0VEID0gMztcblxuLypcbmNvbmZpZyA9IHtcblx0XHR1cmkgOiB3c1VyaSxcblx0XHR1c2VTb2NrSlMgOiB0cnVlICh1c2UgU29ja0pTKSAvIGZhbHNlICh1c2UgV2ViU29ja2V0KSBieSBkZWZhdWx0LFxuXHRcdG9uY29ubmVjdGVkIDogY2FsbGJhY2sgbWV0aG9kIHRvIGludm9rZSB3aGVuIGNvbm5lY3Rpb24gaXMgc3VjY2Vzc2Z1bCxcblx0XHRvbmRpc2Nvbm5lY3QgOiBjYWxsYmFjayBtZXRob2QgdG8gaW52b2tlIHdoZW4gdGhlIGNvbm5lY3Rpb24gaXMgbG9zdCxcblx0XHRvbnJlY29ubmVjdGluZyA6IGNhbGxiYWNrIG1ldGhvZCB0byBpbnZva2Ugd2hlbiB0aGUgY2xpZW50IGlzIHJlY29ubmVjdGluZyxcblx0XHRvbnJlY29ubmVjdGVkIDogY2FsbGJhY2sgbWV0aG9kIHRvIGludm9rZSB3aGVuIHRoZSBjbGllbnQgc3VjY2Vzc2Z1bGx5IHJlY29ubmVjdHMsXG5cdH07XG4qL1xuZnVuY3Rpb24gV2ViU29ja2V0V2l0aFJlY29ubmVjdGlvbihjb25maWcpIHtcblxuICAgIHZhciBjbG9zaW5nID0gZmFsc2U7XG4gICAgdmFyIHJlZ2lzdGVyTWVzc2FnZUhhbmRsZXI7XG4gICAgdmFyIHdzVXJpID0gY29uZmlnLnVyaTtcbiAgICB2YXIgdXNlU29ja0pTID0gY29uZmlnLnVzZVNvY2tKUztcbiAgICB2YXIgcmVjb25uZWN0aW5nID0gZmFsc2U7XG5cbiAgICB2YXIgZm9yY2luZ0Rpc2Nvbm5lY3Rpb24gPSBmYWxzZTtcblxuICAgIHZhciB3cztcblxuICAgIGlmICh1c2VTb2NrSlMpIHtcbiAgICAgICAgd3MgPSBuZXcgU29ja0pTKHdzVXJpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICB3cyA9IG5ldyBXZWJTb2NrZXQod3NVcmkpO1xuICAgIH1cblxuICAgIHdzLm9ub3BlbiA9IGZ1bmN0aW9uKCkge1xuICAgICAgICBsb2dDb25uZWN0ZWQod3MsIHdzVXJpKTtcbiAgICAgICAgaWYgKGNvbmZpZy5vbmNvbm5lY3RlZCkge1xuICAgICAgICAgICAgY29uZmlnLm9uY29ubmVjdGVkKCk7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgd3Mub25lcnJvciA9IGZ1bmN0aW9uKGVycm9yKSB7XG4gICAgICAgIExvZ2dlci5lcnJvcihcIkNvdWxkIG5vdCBjb25uZWN0IHRvIFwiICsgd3NVcmkgKyBcIiAoaW52b2tpbmcgb25lcnJvciBpZiBkZWZpbmVkKVwiLCBlcnJvcik7XG4gICAgICAgIGlmIChjb25maWcub25lcnJvcikge1xuICAgICAgICAgICAgY29uZmlnLm9uZXJyb3IoZXJyb3IpO1xuICAgICAgICB9XG4gICAgfTtcblxuICAgIGZ1bmN0aW9uIGxvZ0Nvbm5lY3RlZCh3cywgd3NVcmkpIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIExvZ2dlci5kZWJ1ZyhcIldlYlNvY2tldCBjb25uZWN0ZWQgdG8gXCIgKyB3c1VyaSk7XG4gICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgIExvZ2dlci5lcnJvcihlKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHZhciByZWNvbm5lY3Rpb25PbkNsb3NlID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIGlmICh3cy5yZWFkeVN0YXRlID09PSBDTE9TRUQpIHtcbiAgICAgICAgICAgIGlmIChjbG9zaW5nKSB7XG4gICAgICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFwiQ29ubmVjdGlvbiBjbG9zZWQgYnkgdXNlclwiKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFwiQ29ubmVjdGlvbiBjbG9zZWQgdW5leHBlY3RlY2x5LiBSZWNvbm5lY3RpbmcuLi5cIik7XG4gICAgICAgICAgICAgICAgcmVjb25uZWN0VG9TYW1lVXJpKE1BWF9SRVRSSUVTLCAxKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIExvZ2dlci5kZWJ1ZyhcIkNsb3NlIGNhbGxiYWNrIGZyb20gcHJldmlvdXMgd2Vic29ja2V0LiBJZ25vcmluZyBpdFwiKTtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICB3cy5vbmNsb3NlID0gcmVjb25uZWN0aW9uT25DbG9zZTtcblxuICAgIGZ1bmN0aW9uIHJlY29ubmVjdFRvU2FtZVVyaShtYXhSZXRyaWVzLCBudW1SZXRyaWVzKSB7XG4gICAgICAgIExvZ2dlci5kZWJ1ZyhcInJlY29ubmVjdFRvU2FtZVVyaSAoYXR0ZW1wdCAjXCIgKyBudW1SZXRyaWVzICsgXCIsIG1heD1cIiArIG1heFJldHJpZXMgKyBcIilcIik7XG5cbiAgICAgICAgaWYgKG51bVJldHJpZXMgPT09IDEpIHtcbiAgICAgICAgICAgIGlmIChyZWNvbm5lY3RpbmcpIHtcbiAgICAgICAgICAgICAgICBMb2dnZXIud2FybihcIlRyeWluZyB0byByZWNvbm5lY3RUb05ld1VyaSB3aGVuIHJlY29ubmVjdGluZy4uLiBJZ25vcmluZyB0aGlzIHJlY29ubmVjdGlvbi5cIilcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJlY29ubmVjdGluZyA9IHRydWU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChjb25maWcub25yZWNvbm5lY3RpbmcpIHtcbiAgICAgICAgICAgICAgICBjb25maWcub25yZWNvbm5lY3RpbmcoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChmb3JjaW5nRGlzY29ubmVjdGlvbikge1xuICAgICAgICAgICAgcmVjb25uZWN0VG9OZXdVcmkobWF4UmV0cmllcywgbnVtUmV0cmllcywgd3NVcmkpO1xuXG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBpZiAoY29uZmlnLm5ld1dzVXJpT25SZWNvbm5lY3Rpb24pIHtcbiAgICAgICAgICAgICAgICBjb25maWcubmV3V3NVcmlPblJlY29ubmVjdGlvbihmdW5jdGlvbihlcnJvciwgbmV3V3NVcmkpIHtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIExvZ2dlci5kZWJ1ZyhlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlY29ubmVjdFRvU2FtZVVyaShtYXhSZXRyaWVzLCBudW1SZXRyaWVzICsgMSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9LCBSRVRSWV9USU1FX01TKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlY29ubmVjdFRvTmV3VXJpKG1heFJldHJpZXMsIG51bVJldHJpZXMsIG5ld1dzVXJpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJlY29ubmVjdFRvTmV3VXJpKG1heFJldHJpZXMsIG51bVJldHJpZXMsIHdzVXJpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIFRPRE8gVGVzdCByZXRyaWVzLiBIb3cgdG8gZm9yY2Ugbm90IGNvbm5lY3Rpb24/XG4gICAgZnVuY3Rpb24gcmVjb25uZWN0VG9OZXdVcmkobWF4UmV0cmllcywgbnVtUmV0cmllcywgcmVjb25uZWN0V3NVcmkpIHtcbiAgICAgICAgTG9nZ2VyLmRlYnVnKFwiUmVjb25uZWN0aW9uIGF0dGVtcHQgI1wiICsgbnVtUmV0cmllcyk7XG5cbiAgICAgICAgd3MuY2xvc2UoKTtcblxuICAgICAgICB3c1VyaSA9IHJlY29ubmVjdFdzVXJpIHx8IHdzVXJpO1xuXG4gICAgICAgIHZhciBuZXdXcztcbiAgICAgICAgaWYgKHVzZVNvY2tKUykge1xuICAgICAgICAgICAgbmV3V3MgPSBuZXcgU29ja0pTKHdzVXJpKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIG5ld1dzID0gbmV3IFdlYlNvY2tldCh3c1VyaSk7XG4gICAgICAgIH1cblxuICAgICAgICBuZXdXcy5vbm9wZW4gPSBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIExvZ2dlci5kZWJ1ZyhcIlJlY29ubmVjdGVkIGFmdGVyIFwiICsgbnVtUmV0cmllcyArIFwiIGF0dGVtcHRzLi4uXCIpO1xuICAgICAgICAgICAgbG9nQ29ubmVjdGVkKG5ld1dzLCB3c1VyaSk7XG4gICAgICAgICAgICByZWNvbm5lY3RpbmcgPSBmYWxzZTtcbiAgICAgICAgICAgIHJlZ2lzdGVyTWVzc2FnZUhhbmRsZXIoKTtcbiAgICAgICAgICAgIGlmIChjb25maWcub25yZWNvbm5lY3RlZCgpKSB7XG4gICAgICAgICAgICAgICAgY29uZmlnLm9ucmVjb25uZWN0ZWQoKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgbmV3V3Mub25jbG9zZSA9IHJlY29ubmVjdGlvbk9uQ2xvc2U7XG4gICAgICAgIH07XG5cbiAgICAgICAgdmFyIG9uRXJyb3JPckNsb3NlID0gZnVuY3Rpb24oZXJyb3IpIHtcbiAgICAgICAgICAgIExvZ2dlci53YXJuKFwiUmVjb25uZWN0aW9uIGVycm9yOiBcIiwgZXJyb3IpO1xuXG4gICAgICAgICAgICBpZiAobnVtUmV0cmllcyA9PT0gbWF4UmV0cmllcykge1xuICAgICAgICAgICAgICAgIGlmIChjb25maWcub25kaXNjb25uZWN0KSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbmZpZy5vbmRpc2Nvbm5lY3QoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlY29ubmVjdFRvU2FtZVVyaShtYXhSZXRyaWVzLCBudW1SZXRyaWVzICsgMSk7XG4gICAgICAgICAgICAgICAgfSwgUkVUUllfVElNRV9NUyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG5cbiAgICAgICAgbmV3V3Mub25lcnJvciA9IG9uRXJyb3JPckNsb3NlO1xuXG4gICAgICAgIHdzID0gbmV3V3M7XG4gICAgfVxuXG4gICAgdGhpcy5jbG9zZSA9IGZ1bmN0aW9uKCkge1xuICAgICAgICBjbG9zaW5nID0gdHJ1ZTtcbiAgICAgICAgd3MuY2xvc2UoKTtcbiAgICB9O1xuXG5cbiAgICAvLyBUaGlzIG1ldGhvZCBpcyBvbmx5IGZvciB0ZXN0aW5nXG4gICAgdGhpcy5mb3JjZUNsb3NlID0gZnVuY3Rpb24obWlsbGlzKSB7XG4gICAgICAgIExvZ2dlci5kZWJ1ZyhcIlRlc3Rpbmc6IEZvcmNlIFdlYlNvY2tldCBjbG9zZVwiKTtcblxuICAgICAgICBpZiAobWlsbGlzKSB7XG4gICAgICAgICAgICBMb2dnZXIuZGVidWcoXCJUZXN0aW5nOiBDaGFuZ2Ugd3NVcmkgZm9yIFwiICsgbWlsbGlzICsgXCIgbWlsbGlzIHRvIHNpbXVsYXRlIG5ldCBmYWlsdXJlXCIpO1xuICAgICAgICAgICAgdmFyIGdvb2RXc1VyaSA9IHdzVXJpO1xuICAgICAgICAgICAgd3NVcmkgPSBcIndzczovLzIxLjIzNC4xMi4zNC40OjQ0My9cIjtcblxuICAgICAgICAgICAgZm9yY2luZ0Rpc2Nvbm5lY3Rpb24gPSB0cnVlO1xuXG4gICAgICAgICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgIExvZ2dlci5kZWJ1ZyhcIlRlc3Rpbmc6IFJlY292ZXIgZ29vZCB3c1VyaSBcIiArIGdvb2RXc1VyaSk7XG4gICAgICAgICAgICAgICAgd3NVcmkgPSBnb29kV3NVcmk7XG5cbiAgICAgICAgICAgICAgICBmb3JjaW5nRGlzY29ubmVjdGlvbiA9IGZhbHNlO1xuXG4gICAgICAgICAgICB9LCBtaWxsaXMpO1xuICAgICAgICB9XG5cbiAgICAgICAgd3MuY2xvc2UoKTtcbiAgICB9O1xuXG4gICAgdGhpcy5yZWNvbm5lY3RXcyA9IGZ1bmN0aW9uKCkge1xuICAgICAgICBMb2dnZXIuZGVidWcoXCJyZWNvbm5lY3RXc1wiKTtcbiAgICAgICAgcmVjb25uZWN0VG9TYW1lVXJpKE1BWF9SRVRSSUVTLCAxKTtcbiAgICB9O1xuXG4gICAgdGhpcy5zZW5kID0gZnVuY3Rpb24obWVzc2FnZSkge1xuICAgICAgICB3cy5zZW5kKG1lc3NhZ2UpO1xuICAgIH07XG5cbiAgICB0aGlzLmFkZEV2ZW50TGlzdGVuZXIgPSBmdW5jdGlvbih0eXBlLCBjYWxsYmFjaykge1xuICAgICAgICByZWdpc3Rlck1lc3NhZ2VIYW5kbGVyID0gZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICB3cy5hZGRFdmVudExpc3RlbmVyKHR5cGUsIGNhbGxiYWNrKTtcbiAgICAgICAgfTtcblxuICAgICAgICByZWdpc3Rlck1lc3NhZ2VIYW5kbGVyKCk7XG4gICAgfTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBXZWJTb2NrZXRXaXRoUmVjb25uZWN0aW9uO1xuIiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNCBLdXJlbnRvIChodHRwOi8va3VyZW50by5vcmcvKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cblxudmFyIGRlZmluZVByb3BlcnR5X0lFOCA9IGZhbHNlXG5pZihPYmplY3QuZGVmaW5lUHJvcGVydHkpXG57XG4gIHRyeVxuICB7XG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHt9LCBcInhcIiwge30pO1xuICB9XG4gIGNhdGNoKGUpXG4gIHtcbiAgICBkZWZpbmVQcm9wZXJ0eV9JRTggPSB0cnVlXG4gIH1cbn1cblxuLy8gaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvSmF2YVNjcmlwdC9SZWZlcmVuY2UvR2xvYmFsX09iamVjdHMvRnVuY3Rpb24vYmluZFxuaWYgKCFGdW5jdGlvbi5wcm90b3R5cGUuYmluZCkge1xuICBGdW5jdGlvbi5wcm90b3R5cGUuYmluZCA9IGZ1bmN0aW9uKG9UaGlzKSB7XG4gICAgaWYgKHR5cGVvZiB0aGlzICE9PSAnZnVuY3Rpb24nKSB7XG4gICAgICAvLyBjbG9zZXN0IHRoaW5nIHBvc3NpYmxlIHRvIHRoZSBFQ01BU2NyaXB0IDVcbiAgICAgIC8vIGludGVybmFsIElzQ2FsbGFibGUgZnVuY3Rpb25cbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ0Z1bmN0aW9uLnByb3RvdHlwZS5iaW5kIC0gd2hhdCBpcyB0cnlpbmcgdG8gYmUgYm91bmQgaXMgbm90IGNhbGxhYmxlJyk7XG4gICAgfVxuXG4gICAgdmFyIGFBcmdzICAgPSBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMsIDEpLFxuICAgICAgICBmVG9CaW5kID0gdGhpcyxcbiAgICAgICAgZk5PUCAgICA9IGZ1bmN0aW9uKCkge30sXG4gICAgICAgIGZCb3VuZCAgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgICByZXR1cm4gZlRvQmluZC5hcHBseSh0aGlzIGluc3RhbmNlb2YgZk5PUCAmJiBvVGhpc1xuICAgICAgICAgICAgICAgICA/IHRoaXNcbiAgICAgICAgICAgICAgICAgOiBvVGhpcyxcbiAgICAgICAgICAgICAgICAgYUFyZ3MuY29uY2F0KEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3VtZW50cykpKTtcbiAgICAgICAgfTtcblxuICAgIGZOT1AucHJvdG90eXBlID0gdGhpcy5wcm90b3R5cGU7XG4gICAgZkJvdW5kLnByb3RvdHlwZSA9IG5ldyBmTk9QKCk7XG5cbiAgICByZXR1cm4gZkJvdW5kO1xuICB9O1xufVxuXG5cbnZhciBFdmVudEVtaXR0ZXIgPSByZXF1aXJlKCdldmVudHMnKS5FdmVudEVtaXR0ZXI7XG5cbnZhciBpbmhlcml0cyA9IHJlcXVpcmUoJ2luaGVyaXRzJyk7XG5cbnZhciBwYWNrZXJzID0gcmVxdWlyZSgnLi9wYWNrZXJzJyk7XG52YXIgTWFwcGVyID0gcmVxdWlyZSgnLi9NYXBwZXInKTtcblxuXG52YXIgQkFTRV9USU1FT1VUID0gNTAwMDtcblxuXG5mdW5jdGlvbiB1bmlmeVJlc3BvbnNlTWV0aG9kcyhyZXNwb25zZU1ldGhvZHMpXG57XG4gIGlmKCFyZXNwb25zZU1ldGhvZHMpIHJldHVybiB7fTtcblxuICBmb3IodmFyIGtleSBpbiByZXNwb25zZU1ldGhvZHMpXG4gIHtcbiAgICB2YXIgdmFsdWUgPSByZXNwb25zZU1ldGhvZHNba2V5XTtcblxuICAgIGlmKHR5cGVvZiB2YWx1ZSA9PSAnc3RyaW5nJylcbiAgICAgIHJlc3BvbnNlTWV0aG9kc1trZXldID1cbiAgICAgIHtcbiAgICAgICAgcmVzcG9uc2U6IHZhbHVlXG4gICAgICB9XG4gIH07XG5cbiAgcmV0dXJuIHJlc3BvbnNlTWV0aG9kcztcbn07XG5cbmZ1bmN0aW9uIHVuaWZ5VHJhbnNwb3J0KHRyYW5zcG9ydClcbntcbiAgaWYoIXRyYW5zcG9ydCkgcmV0dXJuO1xuXG4gIC8vIFRyYW5zcG9ydCBhcyBhIGZ1bmN0aW9uXG4gIGlmKHRyYW5zcG9ydCBpbnN0YW5jZW9mIEZ1bmN0aW9uKVxuICAgIHJldHVybiB7c2VuZDogdHJhbnNwb3J0fTtcblxuICAvLyBXZWJTb2NrZXQgJiBEYXRhQ2hhbm5lbFxuICBpZih0cmFuc3BvcnQuc2VuZCBpbnN0YW5jZW9mIEZ1bmN0aW9uKVxuICAgIHJldHVybiB0cmFuc3BvcnQ7XG5cbiAgLy8gTWVzc2FnZSBBUEkgKEludGVyLXdpbmRvdyAmIFdlYldvcmtlcilcbiAgaWYodHJhbnNwb3J0LnBvc3RNZXNzYWdlIGluc3RhbmNlb2YgRnVuY3Rpb24pXG4gIHtcbiAgICB0cmFuc3BvcnQuc2VuZCA9IHRyYW5zcG9ydC5wb3N0TWVzc2FnZTtcbiAgICByZXR1cm4gdHJhbnNwb3J0O1xuICB9XG5cbiAgLy8gU3RyZWFtIEFQSVxuICBpZih0cmFuc3BvcnQud3JpdGUgaW5zdGFuY2VvZiBGdW5jdGlvbilcbiAge1xuICAgIHRyYW5zcG9ydC5zZW5kID0gdHJhbnNwb3J0LndyaXRlO1xuICAgIHJldHVybiB0cmFuc3BvcnQ7XG4gIH1cblxuICAvLyBUcmFuc3BvcnRzIHRoYXQgb25seSBjYW4gcmVjZWl2ZSBtZXNzYWdlcywgYnV0IG5vdCBzZW5kXG4gIGlmKHRyYW5zcG9ydC5vbm1lc3NhZ2UgIT09IHVuZGVmaW5lZCkgcmV0dXJuO1xuICBpZih0cmFuc3BvcnQucGF1c2UgaW5zdGFuY2VvZiBGdW5jdGlvbikgcmV0dXJuO1xuXG4gIHRocm93IG5ldyBTeW50YXhFcnJvcihcIlRyYW5zcG9ydCBpcyBub3QgYSBmdW5jdGlvbiBub3IgYSB2YWxpZCBvYmplY3RcIik7XG59O1xuXG5cbi8qKlxuICogUmVwcmVzZW50YXRpb24gb2YgYSBSUEMgbm90aWZpY2F0aW9uXG4gKlxuICogQGNsYXNzXG4gKlxuICogQGNvbnN0cnVjdG9yXG4gKlxuICogQHBhcmFtIHtTdHJpbmd9IG1ldGhvZCAtbWV0aG9kIG9mIHRoZSBub3RpZmljYXRpb25cbiAqIEBwYXJhbSBwYXJhbXMgLSBwYXJhbWV0ZXJzIG9mIHRoZSBub3RpZmljYXRpb25cbiAqL1xuZnVuY3Rpb24gUnBjTm90aWZpY2F0aW9uKG1ldGhvZCwgcGFyYW1zKVxue1xuICBpZihkZWZpbmVQcm9wZXJ0eV9JRTgpXG4gIHtcbiAgICB0aGlzLm1ldGhvZCA9IG1ldGhvZFxuICAgIHRoaXMucGFyYW1zID0gcGFyYW1zXG4gIH1cbiAgZWxzZVxuICB7XG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRoaXMsICdtZXRob2QnLCB7dmFsdWU6IG1ldGhvZCwgZW51bWVyYWJsZTogdHJ1ZX0pO1xuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0aGlzLCAncGFyYW1zJywge3ZhbHVlOiBwYXJhbXMsIGVudW1lcmFibGU6IHRydWV9KTtcbiAgfVxufTtcblxuXG4vKipcbiAqIEBjbGFzc1xuICpcbiAqIEBjb25zdHJ1Y3RvclxuICpcbiAqIEBwYXJhbSB7b2JqZWN0fSBwYWNrZXJcbiAqXG4gKiBAcGFyYW0ge29iamVjdH0gW29wdGlvbnNdXG4gKlxuICogQHBhcmFtIHtvYmplY3R9IFt0cmFuc3BvcnRdXG4gKlxuICogQHBhcmFtIHtGdW5jdGlvbn0gW29uUmVxdWVzdF1cbiAqL1xuZnVuY3Rpb24gUnBjQnVpbGRlcihwYWNrZXIsIG9wdGlvbnMsIHRyYW5zcG9ydCwgb25SZXF1ZXN0KVxue1xuICB2YXIgc2VsZiA9IHRoaXM7XG5cbiAgaWYoIXBhY2tlcilcbiAgICB0aHJvdyBuZXcgU3ludGF4RXJyb3IoJ1BhY2tlciBpcyBub3QgZGVmaW5lZCcpO1xuXG4gIGlmKCFwYWNrZXIucGFjayB8fCAhcGFja2VyLnVucGFjaylcbiAgICB0aHJvdyBuZXcgU3ludGF4RXJyb3IoJ1BhY2tlciBpcyBpbnZhbGlkJyk7XG5cbiAgdmFyIHJlc3BvbnNlTWV0aG9kcyA9IHVuaWZ5UmVzcG9uc2VNZXRob2RzKHBhY2tlci5yZXNwb25zZU1ldGhvZHMpO1xuXG5cbiAgaWYob3B0aW9ucyBpbnN0YW5jZW9mIEZ1bmN0aW9uKVxuICB7XG4gICAgaWYodHJhbnNwb3J0ICE9IHVuZGVmaW5lZClcbiAgICAgIHRocm93IG5ldyBTeW50YXhFcnJvcihcIlRoZXJlIGNhbid0IGJlIHBhcmFtZXRlcnMgYWZ0ZXIgb25SZXF1ZXN0XCIpO1xuXG4gICAgb25SZXF1ZXN0ID0gb3B0aW9ucztcbiAgICB0cmFuc3BvcnQgPSB1bmRlZmluZWQ7XG4gICAgb3B0aW9ucyAgID0gdW5kZWZpbmVkO1xuICB9O1xuXG4gIGlmKG9wdGlvbnMgJiYgb3B0aW9ucy5zZW5kIGluc3RhbmNlb2YgRnVuY3Rpb24pXG4gIHtcbiAgICBpZih0cmFuc3BvcnQgJiYgISh0cmFuc3BvcnQgaW5zdGFuY2VvZiBGdW5jdGlvbikpXG4gICAgICB0aHJvdyBuZXcgU3ludGF4RXJyb3IoXCJPbmx5IGEgZnVuY3Rpb24gY2FuIGJlIGFmdGVyIHRyYW5zcG9ydFwiKTtcblxuICAgIG9uUmVxdWVzdCA9IHRyYW5zcG9ydDtcbiAgICB0cmFuc3BvcnQgPSBvcHRpb25zO1xuICAgIG9wdGlvbnMgICA9IHVuZGVmaW5lZDtcbiAgfTtcblxuICBpZih0cmFuc3BvcnQgaW5zdGFuY2VvZiBGdW5jdGlvbilcbiAge1xuICAgIGlmKG9uUmVxdWVzdCAhPSB1bmRlZmluZWQpXG4gICAgICB0aHJvdyBuZXcgU3ludGF4RXJyb3IoXCJUaGVyZSBjYW4ndCBiZSBwYXJhbWV0ZXJzIGFmdGVyIG9uUmVxdWVzdFwiKTtcblxuICAgIG9uUmVxdWVzdCA9IHRyYW5zcG9ydDtcbiAgICB0cmFuc3BvcnQgPSB1bmRlZmluZWQ7XG4gIH07XG5cbiAgaWYodHJhbnNwb3J0ICYmIHRyYW5zcG9ydC5zZW5kIGluc3RhbmNlb2YgRnVuY3Rpb24pXG4gICAgaWYob25SZXF1ZXN0ICYmICEob25SZXF1ZXN0IGluc3RhbmNlb2YgRnVuY3Rpb24pKVxuICAgICAgdGhyb3cgbmV3IFN5bnRheEVycm9yKFwiT25seSBhIGZ1bmN0aW9uIGNhbiBiZSBhZnRlciB0cmFuc3BvcnRcIik7XG5cbiAgb3B0aW9ucyA9IG9wdGlvbnMgfHwge307XG5cblxuICBFdmVudEVtaXR0ZXIuY2FsbCh0aGlzKTtcblxuICBpZihvblJlcXVlc3QpXG4gICAgdGhpcy5vbigncmVxdWVzdCcsIG9uUmVxdWVzdCk7XG5cblxuICBpZihkZWZpbmVQcm9wZXJ0eV9JRTgpXG4gICAgdGhpcy5wZWVySUQgPSBvcHRpb25zLnBlZXJJRFxuICBlbHNlXG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRoaXMsICdwZWVySUQnLCB7dmFsdWU6IG9wdGlvbnMucGVlcklEfSk7XG5cbiAgdmFyIG1heF9yZXRyaWVzID0gb3B0aW9ucy5tYXhfcmV0cmllcyB8fCAwO1xuXG5cbiAgZnVuY3Rpb24gdHJhbnNwb3J0TWVzc2FnZShldmVudClcbiAge1xuICAgIHNlbGYuZGVjb2RlKGV2ZW50LmRhdGEgfHwgZXZlbnQpO1xuICB9O1xuXG4gIHRoaXMuZ2V0VHJhbnNwb3J0ID0gZnVuY3Rpb24oKVxuICB7XG4gICAgcmV0dXJuIHRyYW5zcG9ydDtcbiAgfVxuICB0aGlzLnNldFRyYW5zcG9ydCA9IGZ1bmN0aW9uKHZhbHVlKVxuICB7XG4gICAgLy8gUmVtb3ZlIGxpc3RlbmVyIGZyb20gb2xkIHRyYW5zcG9ydFxuICAgIGlmKHRyYW5zcG9ydClcbiAgICB7XG4gICAgICAvLyBXM0MgdHJhbnNwb3J0c1xuICAgICAgaWYodHJhbnNwb3J0LnJlbW92ZUV2ZW50TGlzdGVuZXIpXG4gICAgICAgIHRyYW5zcG9ydC5yZW1vdmVFdmVudExpc3RlbmVyKCdtZXNzYWdlJywgdHJhbnNwb3J0TWVzc2FnZSk7XG5cbiAgICAgIC8vIE5vZGUuanMgU3RyZWFtcyBBUElcbiAgICAgIGVsc2UgaWYodHJhbnNwb3J0LnJlbW92ZUxpc3RlbmVyKVxuICAgICAgICB0cmFuc3BvcnQucmVtb3ZlTGlzdGVuZXIoJ2RhdGEnLCB0cmFuc3BvcnRNZXNzYWdlKTtcbiAgICB9O1xuXG4gICAgLy8gU2V0IGxpc3RlbmVyIG9uIG5ldyB0cmFuc3BvcnRcbiAgICBpZih2YWx1ZSlcbiAgICB7XG4gICAgICAvLyBXM0MgdHJhbnNwb3J0c1xuICAgICAgaWYodmFsdWUuYWRkRXZlbnRMaXN0ZW5lcilcbiAgICAgICAgdmFsdWUuYWRkRXZlbnRMaXN0ZW5lcignbWVzc2FnZScsIHRyYW5zcG9ydE1lc3NhZ2UpO1xuXG4gICAgICAvLyBOb2RlLmpzIFN0cmVhbXMgQVBJXG4gICAgICBlbHNlIGlmKHZhbHVlLmFkZExpc3RlbmVyKVxuICAgICAgICB2YWx1ZS5hZGRMaXN0ZW5lcignZGF0YScsIHRyYW5zcG9ydE1lc3NhZ2UpO1xuICAgIH07XG5cbiAgICB0cmFuc3BvcnQgPSB1bmlmeVRyYW5zcG9ydCh2YWx1ZSk7XG4gIH1cblxuICBpZighZGVmaW5lUHJvcGVydHlfSUU4KVxuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0aGlzLCAndHJhbnNwb3J0JyxcbiAgICB7XG4gICAgICBnZXQ6IHRoaXMuZ2V0VHJhbnNwb3J0LmJpbmQodGhpcyksXG4gICAgICBzZXQ6IHRoaXMuc2V0VHJhbnNwb3J0LmJpbmQodGhpcylcbiAgICB9KVxuXG4gIHRoaXMuc2V0VHJhbnNwb3J0KHRyYW5zcG9ydCk7XG5cblxuICB2YXIgcmVxdWVzdF90aW1lb3V0ICAgICAgPSBvcHRpb25zLnJlcXVlc3RfdGltZW91dCAgICAgIHx8IEJBU0VfVElNRU9VVDtcbiAgdmFyIHBpbmdfcmVxdWVzdF90aW1lb3V0ID0gb3B0aW9ucy5waW5nX3JlcXVlc3RfdGltZW91dCB8fCByZXF1ZXN0X3RpbWVvdXQ7XG4gIHZhciByZXNwb25zZV90aW1lb3V0ICAgICA9IG9wdGlvbnMucmVzcG9uc2VfdGltZW91dCAgICAgfHwgQkFTRV9USU1FT1VUO1xuICB2YXIgZHVwbGljYXRlc190aW1lb3V0ICAgPSBvcHRpb25zLmR1cGxpY2F0ZXNfdGltZW91dCAgIHx8IEJBU0VfVElNRU9VVDtcblxuXG4gIHZhciByZXF1ZXN0SUQgPSAwO1xuXG4gIHZhciByZXF1ZXN0cyAgPSBuZXcgTWFwcGVyKCk7XG4gIHZhciByZXNwb25zZXMgPSBuZXcgTWFwcGVyKCk7XG4gIHZhciBwcm9jZXNzZWRSZXNwb25zZXMgPSBuZXcgTWFwcGVyKCk7XG5cbiAgdmFyIG1lc3NhZ2UyS2V5ID0ge307XG5cblxuICAvKipcbiAgICogU3RvcmUgdGhlIHJlc3BvbnNlIHRvIHByZXZlbnQgdG8gcHJvY2VzcyBkdXBsaWNhdGUgcmVxdWVzdCBsYXRlclxuICAgKi9cbiAgZnVuY3Rpb24gc3RvcmVSZXNwb25zZShtZXNzYWdlLCBpZCwgZGVzdClcbiAge1xuICAgIHZhciByZXNwb25zZSA9XG4gICAge1xuICAgICAgbWVzc2FnZTogbWVzc2FnZSxcbiAgICAgIC8qKiBUaW1lb3V0IHRvIGF1dG8tY2xlYW4gb2xkIHJlc3BvbnNlcyAqL1xuICAgICAgdGltZW91dDogc2V0VGltZW91dChmdW5jdGlvbigpXG4gICAgICB7XG4gICAgICAgIHJlc3BvbnNlcy5yZW1vdmUoaWQsIGRlc3QpO1xuICAgICAgfSxcbiAgICAgIHJlc3BvbnNlX3RpbWVvdXQpXG4gICAgfTtcblxuICAgIHJlc3BvbnNlcy5zZXQocmVzcG9uc2UsIGlkLCBkZXN0KTtcbiAgfTtcblxuICAvKipcbiAgICogU3RvcmUgdGhlIHJlc3BvbnNlIHRvIGlnbm9yZSBkdXBsaWNhdGVkIG1lc3NhZ2VzIGxhdGVyXG4gICAqL1xuICBmdW5jdGlvbiBzdG9yZVByb2Nlc3NlZFJlc3BvbnNlKGFjaywgZnJvbSlcbiAge1xuICAgIHZhciB0aW1lb3V0ID0gc2V0VGltZW91dChmdW5jdGlvbigpXG4gICAge1xuICAgICAgcHJvY2Vzc2VkUmVzcG9uc2VzLnJlbW92ZShhY2ssIGZyb20pO1xuICAgIH0sXG4gICAgZHVwbGljYXRlc190aW1lb3V0KTtcblxuICAgIHByb2Nlc3NlZFJlc3BvbnNlcy5zZXQodGltZW91dCwgYWNrLCBmcm9tKTtcbiAgfTtcblxuXG4gIC8qKlxuICAgKiBSZXByZXNlbnRhdGlvbiBvZiBhIFJQQyByZXF1ZXN0XG4gICAqXG4gICAqIEBjbGFzc1xuICAgKiBAZXh0ZW5kcyBScGNOb3RpZmljYXRpb25cbiAgICpcbiAgICogQGNvbnN0cnVjdG9yXG4gICAqXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBtZXRob2QgLW1ldGhvZCBvZiB0aGUgbm90aWZpY2F0aW9uXG4gICAqIEBwYXJhbSBwYXJhbXMgLSBwYXJhbWV0ZXJzIG9mIHRoZSBub3RpZmljYXRpb25cbiAgICogQHBhcmFtIHtJbnRlZ2VyfSBpZCAtIGlkZW50aWZpZXIgb2YgdGhlIHJlcXVlc3RcbiAgICogQHBhcmFtIFtmcm9tXSAtIHNvdXJjZSBvZiB0aGUgbm90aWZpY2F0aW9uXG4gICAqL1xuICBmdW5jdGlvbiBScGNSZXF1ZXN0KG1ldGhvZCwgcGFyYW1zLCBpZCwgZnJvbSwgdHJhbnNwb3J0KVxuICB7XG4gICAgUnBjTm90aWZpY2F0aW9uLmNhbGwodGhpcywgbWV0aG9kLCBwYXJhbXMpO1xuXG4gICAgdGhpcy5nZXRUcmFuc3BvcnQgPSBmdW5jdGlvbigpXG4gICAge1xuICAgICAgcmV0dXJuIHRyYW5zcG9ydDtcbiAgICB9XG4gICAgdGhpcy5zZXRUcmFuc3BvcnQgPSBmdW5jdGlvbih2YWx1ZSlcbiAgICB7XG4gICAgICB0cmFuc3BvcnQgPSB1bmlmeVRyYW5zcG9ydCh2YWx1ZSk7XG4gICAgfVxuXG4gICAgaWYoIWRlZmluZVByb3BlcnR5X0lFOClcbiAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0aGlzLCAndHJhbnNwb3J0JyxcbiAgICAgIHtcbiAgICAgICAgZ2V0OiB0aGlzLmdldFRyYW5zcG9ydC5iaW5kKHRoaXMpLFxuICAgICAgICBzZXQ6IHRoaXMuc2V0VHJhbnNwb3J0LmJpbmQodGhpcylcbiAgICAgIH0pXG5cbiAgICB2YXIgcmVzcG9uc2UgPSByZXNwb25zZXMuZ2V0KGlkLCBmcm9tKTtcblxuICAgIC8qKlxuICAgICAqIEBjb25zdGFudCB7Qm9vbGVhbn0gZHVwbGljYXRlZFxuICAgICAqL1xuICAgIGlmKCEodHJhbnNwb3J0IHx8IHNlbGYuZ2V0VHJhbnNwb3J0KCkpKVxuICAgIHtcbiAgICAgIGlmKGRlZmluZVByb3BlcnR5X0lFOClcbiAgICAgICAgdGhpcy5kdXBsaWNhdGVkID0gQm9vbGVhbihyZXNwb25zZSlcbiAgICAgIGVsc2VcbiAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRoaXMsICdkdXBsaWNhdGVkJyxcbiAgICAgICAge1xuICAgICAgICAgIHZhbHVlOiBCb29sZWFuKHJlc3BvbnNlKVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICB2YXIgcmVzcG9uc2VNZXRob2QgPSByZXNwb25zZU1ldGhvZHNbbWV0aG9kXTtcblxuICAgIHRoaXMucGFjayA9IHBhY2tlci5wYWNrLmJpbmQocGFja2VyLCB0aGlzLCBpZClcblxuICAgIC8qKlxuICAgICAqIEdlbmVyYXRlIGEgcmVzcG9uc2UgdG8gdGhpcyByZXF1ZXN0XG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0Vycm9yfSBbZXJyb3JdXG4gICAgICogQHBhcmFtIHsqfSBbcmVzdWx0XVxuICAgICAqXG4gICAgICogQHJldHVybnMge3N0cmluZ31cbiAgICAgKi9cbiAgICB0aGlzLnJlcGx5ID0gZnVuY3Rpb24oZXJyb3IsIHJlc3VsdCwgdHJhbnNwb3J0KVxuICAgIHtcbiAgICAgIC8vIEZpeCBvcHRpb25hbCBwYXJhbWV0ZXJzXG4gICAgICBpZihlcnJvciBpbnN0YW5jZW9mIEZ1bmN0aW9uIHx8IGVycm9yICYmIGVycm9yLnNlbmQgaW5zdGFuY2VvZiBGdW5jdGlvbilcbiAgICAgIHtcbiAgICAgICAgaWYocmVzdWx0ICE9IHVuZGVmaW5lZClcbiAgICAgICAgICB0aHJvdyBuZXcgU3ludGF4RXJyb3IoXCJUaGVyZSBjYW4ndCBiZSBwYXJhbWV0ZXJzIGFmdGVyIGNhbGxiYWNrXCIpO1xuXG4gICAgICAgIHRyYW5zcG9ydCA9IGVycm9yO1xuICAgICAgICByZXN1bHQgPSBudWxsO1xuICAgICAgICBlcnJvciA9IHVuZGVmaW5lZDtcbiAgICAgIH1cblxuICAgICAgZWxzZSBpZihyZXN1bHQgaW5zdGFuY2VvZiBGdW5jdGlvblxuICAgICAgfHwgcmVzdWx0ICYmIHJlc3VsdC5zZW5kIGluc3RhbmNlb2YgRnVuY3Rpb24pXG4gICAgICB7XG4gICAgICAgIGlmKHRyYW5zcG9ydCAhPSB1bmRlZmluZWQpXG4gICAgICAgICAgdGhyb3cgbmV3IFN5bnRheEVycm9yKFwiVGhlcmUgY2FuJ3QgYmUgcGFyYW1ldGVycyBhZnRlciBjYWxsYmFja1wiKTtcblxuICAgICAgICB0cmFuc3BvcnQgPSByZXN1bHQ7XG4gICAgICAgIHJlc3VsdCA9IG51bGw7XG4gICAgICB9O1xuXG4gICAgICB0cmFuc3BvcnQgPSB1bmlmeVRyYW5zcG9ydCh0cmFuc3BvcnQpO1xuXG4gICAgICAvLyBEdXBsaWNhdGVkIHJlcXVlc3QsIHJlbW92ZSBvbGQgcmVzcG9uc2UgdGltZW91dFxuICAgICAgaWYocmVzcG9uc2UpXG4gICAgICAgIGNsZWFyVGltZW91dChyZXNwb25zZS50aW1lb3V0KTtcblxuICAgICAgaWYoZnJvbSAhPSB1bmRlZmluZWQpXG4gICAgICB7XG4gICAgICAgIGlmKGVycm9yKVxuICAgICAgICAgIGVycm9yLmRlc3QgPSBmcm9tO1xuXG4gICAgICAgIGlmKHJlc3VsdClcbiAgICAgICAgICByZXN1bHQuZGVzdCA9IGZyb207XG4gICAgICB9O1xuXG4gICAgICB2YXIgbWVzc2FnZTtcblxuICAgICAgLy8gTmV3IHJlcXVlc3Qgb3Igb3ZlcnJpZGVuIG9uZSwgY3JlYXRlIG5ldyByZXNwb25zZSB3aXRoIHByb3ZpZGVkIGRhdGFcbiAgICAgIGlmKGVycm9yIHx8IHJlc3VsdCAhPSB1bmRlZmluZWQpXG4gICAgICB7XG4gICAgICAgIGlmKHNlbGYucGVlcklEICE9IHVuZGVmaW5lZClcbiAgICAgICAge1xuICAgICAgICAgIGlmKGVycm9yKVxuICAgICAgICAgICAgZXJyb3IuZnJvbSA9IHNlbGYucGVlcklEO1xuICAgICAgICAgIGVsc2VcbiAgICAgICAgICAgIHJlc3VsdC5mcm9tID0gc2VsZi5wZWVySUQ7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBQcm90b2NvbCBpbmRpY2F0ZXMgdGhhdCByZXNwb25zZXMgaGFzIG93biByZXF1ZXN0IG1ldGhvZHNcbiAgICAgICAgaWYocmVzcG9uc2VNZXRob2QpXG4gICAgICAgIHtcbiAgICAgICAgICBpZihyZXNwb25zZU1ldGhvZC5lcnJvciA9PSB1bmRlZmluZWQgJiYgZXJyb3IpXG4gICAgICAgICAgICBtZXNzYWdlID1cbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgZXJyb3I6IGVycm9yXG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgZWxzZVxuICAgICAgICAgIHtcbiAgICAgICAgICAgIHZhciBtZXRob2QgPSBlcnJvclxuICAgICAgICAgICAgICAgICAgICAgICA/IHJlc3BvbnNlTWV0aG9kLmVycm9yXG4gICAgICAgICAgICAgICAgICAgICAgIDogcmVzcG9uc2VNZXRob2QucmVzcG9uc2U7XG5cbiAgICAgICAgICAgIG1lc3NhZ2UgPVxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICBtZXRob2Q6IG1ldGhvZCxcbiAgICAgICAgICAgICAgcGFyYW1zOiBlcnJvciB8fCByZXN1bHRcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGVsc2VcbiAgICAgICAgICBtZXNzYWdlID1cbiAgICAgICAgICB7XG4gICAgICAgICAgICBlcnJvcjogIGVycm9yLFxuICAgICAgICAgICAgcmVzdWx0OiByZXN1bHRcbiAgICAgICAgICB9O1xuXG4gICAgICAgIG1lc3NhZ2UgPSBwYWNrZXIucGFjayhtZXNzYWdlLCBpZCk7XG4gICAgICB9XG5cbiAgICAgIC8vIER1cGxpY2F0ZSAmIG5vdC1vdmVycmlkZW4gcmVxdWVzdCwgcmUtc2VuZCBvbGQgcmVzcG9uc2VcbiAgICAgIGVsc2UgaWYocmVzcG9uc2UpXG4gICAgICAgIG1lc3NhZ2UgPSByZXNwb25zZS5tZXNzYWdlO1xuXG4gICAgICAvLyBOZXcgZW1wdHkgcmVwbHksIHJlc3BvbnNlIG51bGwgdmFsdWVcbiAgICAgIGVsc2VcbiAgICAgICAgbWVzc2FnZSA9IHBhY2tlci5wYWNrKHtyZXN1bHQ6IG51bGx9LCBpZCk7XG5cbiAgICAgIC8vIFN0b3JlIHRoZSByZXNwb25zZSB0byBwcmV2ZW50IHRvIHByb2Nlc3MgYSBkdXBsaWNhdGVkIHJlcXVlc3QgbGF0ZXJcbiAgICAgIHN0b3JlUmVzcG9uc2UobWVzc2FnZSwgaWQsIGZyb20pO1xuXG4gICAgICAvLyBSZXR1cm4gdGhlIHN0b3JlZCByZXNwb25zZSBzbyBpdCBjYW4gYmUgZGlyZWN0bHkgc2VuZCBiYWNrXG4gICAgICB0cmFuc3BvcnQgPSB0cmFuc3BvcnQgfHwgdGhpcy5nZXRUcmFuc3BvcnQoKSB8fCBzZWxmLmdldFRyYW5zcG9ydCgpO1xuXG4gICAgICBpZih0cmFuc3BvcnQpXG4gICAgICAgIHJldHVybiB0cmFuc3BvcnQuc2VuZChtZXNzYWdlKTtcblxuICAgICAgcmV0dXJuIG1lc3NhZ2U7XG4gICAgfVxuICB9O1xuICBpbmhlcml0cyhScGNSZXF1ZXN0LCBScGNOb3RpZmljYXRpb24pO1xuXG5cbiAgZnVuY3Rpb24gY2FuY2VsKG1lc3NhZ2UpXG4gIHtcbiAgICB2YXIga2V5ID0gbWVzc2FnZTJLZXlbbWVzc2FnZV07XG4gICAgaWYoIWtleSkgcmV0dXJuO1xuXG4gICAgZGVsZXRlIG1lc3NhZ2UyS2V5W21lc3NhZ2VdO1xuXG4gICAgdmFyIHJlcXVlc3QgPSByZXF1ZXN0cy5wb3Aoa2V5LmlkLCBrZXkuZGVzdCk7XG4gICAgaWYoIXJlcXVlc3QpIHJldHVybjtcblxuICAgIGNsZWFyVGltZW91dChyZXF1ZXN0LnRpbWVvdXQpO1xuXG4gICAgLy8gU3RhcnQgZHVwbGljYXRlZCByZXNwb25zZXMgdGltZW91dFxuICAgIHN0b3JlUHJvY2Vzc2VkUmVzcG9uc2Uoa2V5LmlkLCBrZXkuZGVzdCk7XG4gIH07XG5cbiAgLyoqXG4gICAqIEFsbG93IHRvIGNhbmNlbCBhIHJlcXVlc3QgYW5kIGRvbid0IHdhaXQgZm9yIGEgcmVzcG9uc2VcbiAgICpcbiAgICogSWYgYG1lc3NhZ2VgIGlzIG5vdCBnaXZlbiwgY2FuY2VsIGFsbCB0aGUgcmVxdWVzdFxuICAgKi9cbiAgdGhpcy5jYW5jZWwgPSBmdW5jdGlvbihtZXNzYWdlKVxuICB7XG4gICAgaWYobWVzc2FnZSkgcmV0dXJuIGNhbmNlbChtZXNzYWdlKTtcblxuICAgIGZvcih2YXIgbWVzc2FnZSBpbiBtZXNzYWdlMktleSlcbiAgICAgIGNhbmNlbChtZXNzYWdlKTtcbiAgfTtcblxuXG4gIHRoaXMuY2xvc2UgPSBmdW5jdGlvbigpXG4gIHtcbiAgICAvLyBQcmV2ZW50IHRvIHJlY2VpdmUgbmV3IG1lc3NhZ2VzXG4gICAgdmFyIHRyYW5zcG9ydCA9IHRoaXMuZ2V0VHJhbnNwb3J0KCk7XG4gICAgaWYodHJhbnNwb3J0ICYmIHRyYW5zcG9ydC5jbG9zZSlcbiAgICAgICB0cmFuc3BvcnQuY2xvc2UoKTtcblxuICAgIC8vIFJlcXVlc3QgJiBwcm9jZXNzZWQgcmVzcG9uc2VzXG4gICAgdGhpcy5jYW5jZWwoKTtcblxuICAgIHByb2Nlc3NlZFJlc3BvbnNlcy5mb3JFYWNoKGNsZWFyVGltZW91dCk7XG5cbiAgICAvLyBSZXNwb25zZXNcbiAgICByZXNwb25zZXMuZm9yRWFjaChmdW5jdGlvbihyZXNwb25zZSlcbiAgICB7XG4gICAgICBjbGVhclRpbWVvdXQocmVzcG9uc2UudGltZW91dCk7XG4gICAgfSk7XG4gIH07XG5cblxuICAvKipcbiAgICogR2VuZXJhdGVzIGFuZCBlbmNvZGUgYSBKc29uUlBDIDIuMCBtZXNzYWdlXG4gICAqXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBtZXRob2QgLW1ldGhvZCBvZiB0aGUgbm90aWZpY2F0aW9uXG4gICAqIEBwYXJhbSBwYXJhbXMgLSBwYXJhbWV0ZXJzIG9mIHRoZSBub3RpZmljYXRpb25cbiAgICogQHBhcmFtIFtkZXN0XSAtIGRlc3RpbmF0aW9uIG9mIHRoZSBub3RpZmljYXRpb25cbiAgICogQHBhcmFtIHtvYmplY3R9IFt0cmFuc3BvcnRdIC0gdHJhbnNwb3J0IHdoZXJlIHRvIHNlbmQgdGhlIG1lc3NhZ2VcbiAgICogQHBhcmFtIFtjYWxsYmFja10gLSBmdW5jdGlvbiBjYWxsZWQgd2hlbiBhIHJlc3BvbnNlIHRvIHRoaXMgcmVxdWVzdCBpc1xuICAgKiAgIHJlY2VpdmVkLiBJZiBub3QgZGVmaW5lZCwgYSBub3RpZmljYXRpb24gd2lsbCBiZSBzZW5kIGluc3RlYWRcbiAgICpcbiAgICogQHJldHVybnMge3N0cmluZ30gQSByYXcgSnNvblJQQyAyLjAgcmVxdWVzdCBvciBub3RpZmljYXRpb24gc3RyaW5nXG4gICAqL1xuICB0aGlzLmVuY29kZSA9IGZ1bmN0aW9uKG1ldGhvZCwgcGFyYW1zLCBkZXN0LCB0cmFuc3BvcnQsIGNhbGxiYWNrKVxuICB7XG4gICAgLy8gRml4IG9wdGlvbmFsIHBhcmFtZXRlcnNcbiAgICBpZihwYXJhbXMgaW5zdGFuY2VvZiBGdW5jdGlvbilcbiAgICB7XG4gICAgICBpZihkZXN0ICE9IHVuZGVmaW5lZClcbiAgICAgICAgdGhyb3cgbmV3IFN5bnRheEVycm9yKFwiVGhlcmUgY2FuJ3QgYmUgcGFyYW1ldGVycyBhZnRlciBjYWxsYmFja1wiKTtcblxuICAgICAgY2FsbGJhY2sgID0gcGFyYW1zO1xuICAgICAgdHJhbnNwb3J0ID0gdW5kZWZpbmVkO1xuICAgICAgZGVzdCAgICAgID0gdW5kZWZpbmVkO1xuICAgICAgcGFyYW1zICAgID0gdW5kZWZpbmVkO1xuICAgIH1cblxuICAgIGVsc2UgaWYoZGVzdCBpbnN0YW5jZW9mIEZ1bmN0aW9uKVxuICAgIHtcbiAgICAgIGlmKHRyYW5zcG9ydCAhPSB1bmRlZmluZWQpXG4gICAgICAgIHRocm93IG5ldyBTeW50YXhFcnJvcihcIlRoZXJlIGNhbid0IGJlIHBhcmFtZXRlcnMgYWZ0ZXIgY2FsbGJhY2tcIik7XG5cbiAgICAgIGNhbGxiYWNrICA9IGRlc3Q7XG4gICAgICB0cmFuc3BvcnQgPSB1bmRlZmluZWQ7XG4gICAgICBkZXN0ICAgICAgPSB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgZWxzZSBpZih0cmFuc3BvcnQgaW5zdGFuY2VvZiBGdW5jdGlvbilcbiAgICB7XG4gICAgICBpZihjYWxsYmFjayAhPSB1bmRlZmluZWQpXG4gICAgICAgIHRocm93IG5ldyBTeW50YXhFcnJvcihcIlRoZXJlIGNhbid0IGJlIHBhcmFtZXRlcnMgYWZ0ZXIgY2FsbGJhY2tcIik7XG5cbiAgICAgIGNhbGxiYWNrICA9IHRyYW5zcG9ydDtcbiAgICAgIHRyYW5zcG9ydCA9IHVuZGVmaW5lZDtcbiAgICB9O1xuXG4gICAgaWYoc2VsZi5wZWVySUQgIT0gdW5kZWZpbmVkKVxuICAgIHtcbiAgICAgIHBhcmFtcyA9IHBhcmFtcyB8fCB7fTtcblxuICAgICAgcGFyYW1zLmZyb20gPSBzZWxmLnBlZXJJRDtcbiAgICB9O1xuXG4gICAgaWYoZGVzdCAhPSB1bmRlZmluZWQpXG4gICAge1xuICAgICAgcGFyYW1zID0gcGFyYW1zIHx8IHt9O1xuXG4gICAgICBwYXJhbXMuZGVzdCA9IGRlc3Q7XG4gICAgfTtcblxuICAgIC8vIEVuY29kZSBtZXNzYWdlXG4gICAgdmFyIG1lc3NhZ2UgPVxuICAgIHtcbiAgICAgIG1ldGhvZDogbWV0aG9kLFxuICAgICAgcGFyYW1zOiBwYXJhbXNcbiAgICB9O1xuXG4gICAgaWYoY2FsbGJhY2spXG4gICAge1xuICAgICAgdmFyIGlkID0gcmVxdWVzdElEKys7XG4gICAgICB2YXIgcmV0cmllZCA9IDA7XG5cbiAgICAgIG1lc3NhZ2UgPSBwYWNrZXIucGFjayhtZXNzYWdlLCBpZCk7XG5cbiAgICAgIGZ1bmN0aW9uIGRpc3BhdGNoQ2FsbGJhY2soZXJyb3IsIHJlc3VsdClcbiAgICAgIHtcbiAgICAgICAgc2VsZi5jYW5jZWwobWVzc2FnZSk7XG5cbiAgICAgICAgY2FsbGJhY2soZXJyb3IsIHJlc3VsdCk7XG4gICAgICB9O1xuXG4gICAgICB2YXIgcmVxdWVzdCA9XG4gICAgICB7XG4gICAgICAgIG1lc3NhZ2U6ICAgICAgICAgbWVzc2FnZSxcbiAgICAgICAgY2FsbGJhY2s6ICAgICAgICBkaXNwYXRjaENhbGxiYWNrLFxuICAgICAgICByZXNwb25zZU1ldGhvZHM6IHJlc3BvbnNlTWV0aG9kc1ttZXRob2RdIHx8IHt9XG4gICAgICB9O1xuXG4gICAgICB2YXIgZW5jb2RlX3RyYW5zcG9ydCA9IHVuaWZ5VHJhbnNwb3J0KHRyYW5zcG9ydCk7XG5cbiAgICAgIGZ1bmN0aW9uIHNlbmRSZXF1ZXN0KHRyYW5zcG9ydClcbiAgICAgIHtcbiAgICAgICAgdmFyIHJ0ID0gKG1ldGhvZCA9PT0gJ3BpbmcnID8gcGluZ19yZXF1ZXN0X3RpbWVvdXQgOiByZXF1ZXN0X3RpbWVvdXQpO1xuICAgICAgICByZXF1ZXN0LnRpbWVvdXQgPSBzZXRUaW1lb3V0KHRpbWVvdXQsIHJ0Kk1hdGgucG93KDIsIHJldHJpZWQrKykpO1xuICAgICAgICBtZXNzYWdlMktleVttZXNzYWdlXSA9IHtpZDogaWQsIGRlc3Q6IGRlc3R9O1xuICAgICAgICByZXF1ZXN0cy5zZXQocmVxdWVzdCwgaWQsIGRlc3QpO1xuXG4gICAgICAgIHRyYW5zcG9ydCA9IHRyYW5zcG9ydCB8fCBlbmNvZGVfdHJhbnNwb3J0IHx8IHNlbGYuZ2V0VHJhbnNwb3J0KCk7XG4gICAgICAgIGlmKHRyYW5zcG9ydClcbiAgICAgICAgICByZXR1cm4gdHJhbnNwb3J0LnNlbmQobWVzc2FnZSk7XG5cbiAgICAgICAgcmV0dXJuIG1lc3NhZ2U7XG4gICAgICB9O1xuXG4gICAgICBmdW5jdGlvbiByZXRyeSh0cmFuc3BvcnQpXG4gICAgICB7XG4gICAgICAgIHRyYW5zcG9ydCA9IHVuaWZ5VHJhbnNwb3J0KHRyYW5zcG9ydCk7XG5cbiAgICAgICAgY29uc29sZS53YXJuKHJldHJpZWQrJyByZXRyeSBmb3IgcmVxdWVzdCBtZXNzYWdlOicsbWVzc2FnZSk7XG5cbiAgICAgICAgdmFyIHRpbWVvdXQgPSBwcm9jZXNzZWRSZXNwb25zZXMucG9wKGlkLCBkZXN0KTtcbiAgICAgICAgY2xlYXJUaW1lb3V0KHRpbWVvdXQpO1xuXG4gICAgICAgIHJldHVybiBzZW5kUmVxdWVzdCh0cmFuc3BvcnQpO1xuICAgICAgfTtcblxuICAgICAgZnVuY3Rpb24gdGltZW91dCgpXG4gICAgICB7XG4gICAgICAgIGlmKHJldHJpZWQgPCBtYXhfcmV0cmllcylcbiAgICAgICAgICByZXR1cm4gcmV0cnkodHJhbnNwb3J0KTtcblxuICAgICAgICB2YXIgZXJyb3IgPSBuZXcgRXJyb3IoJ1JlcXVlc3QgaGFzIHRpbWVkIG91dCcpO1xuICAgICAgICAgICAgZXJyb3IucmVxdWVzdCA9IG1lc3NhZ2U7XG5cbiAgICAgICAgZXJyb3IucmV0cnkgPSByZXRyeTtcblxuICAgICAgICBkaXNwYXRjaENhbGxiYWNrKGVycm9yKVxuICAgICAgfTtcblxuICAgICAgcmV0dXJuIHNlbmRSZXF1ZXN0KHRyYW5zcG9ydCk7XG4gICAgfTtcblxuICAgIC8vIFJldHVybiB0aGUgcGFja2VkIG1lc3NhZ2VcbiAgICBtZXNzYWdlID0gcGFja2VyLnBhY2sobWVzc2FnZSk7XG5cbiAgICB0cmFuc3BvcnQgPSB0cmFuc3BvcnQgfHwgdGhpcy5nZXRUcmFuc3BvcnQoKTtcbiAgICBpZih0cmFuc3BvcnQpXG4gICAgICByZXR1cm4gdHJhbnNwb3J0LnNlbmQobWVzc2FnZSk7XG5cbiAgICByZXR1cm4gbWVzc2FnZTtcbiAgfTtcblxuICAvKipcbiAgICogRGVjb2RlIGFuZCBwcm9jZXNzIGEgSnNvblJQQyAyLjAgbWVzc2FnZVxuICAgKlxuICAgKiBAcGFyYW0ge3N0cmluZ30gbWVzc2FnZSAtIHN0cmluZyB3aXRoIHRoZSBjb250ZW50IG9mIHRoZSBtZXNzYWdlXG4gICAqXG4gICAqIEByZXR1cm5zIHtScGNOb3RpZmljYXRpb258UnBjUmVxdWVzdHx1bmRlZmluZWR9IC0gdGhlIHJlcHJlc2VudGF0aW9uIG9mIHRoZVxuICAgKiAgIG5vdGlmaWNhdGlvbiBvciB0aGUgcmVxdWVzdC4gSWYgYSByZXNwb25zZSB3YXMgcHJvY2Vzc2VkLCBpdCB3aWxsIHJldHVyblxuICAgKiAgIGB1bmRlZmluZWRgIHRvIG5vdGlmeSB0aGF0IGl0IHdhcyBwcm9jZXNzZWRcbiAgICpcbiAgICogQHRocm93cyB7VHlwZUVycm9yfSAtIE1lc3NhZ2UgaXMgbm90IGRlZmluZWRcbiAgICovXG4gIHRoaXMuZGVjb2RlID0gZnVuY3Rpb24obWVzc2FnZSwgdHJhbnNwb3J0KVxuICB7XG4gICAgaWYoIW1lc3NhZ2UpXG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiTWVzc2FnZSBpcyBub3QgZGVmaW5lZFwiKTtcblxuICAgIHRyeVxuICAgIHtcbiAgICAgIG1lc3NhZ2UgPSBwYWNrZXIudW5wYWNrKG1lc3NhZ2UpO1xuICAgIH1cbiAgICBjYXRjaChlKVxuICAgIHtcbiAgICAgIC8vIElnbm9yZSBpbnZhbGlkIG1lc3NhZ2VzXG4gICAgICByZXR1cm4gY29uc29sZS5kZWJ1ZyhlLCBtZXNzYWdlKTtcbiAgICB9O1xuXG4gICAgdmFyIGlkICAgICA9IG1lc3NhZ2UuaWQ7XG4gICAgdmFyIGFjayAgICA9IG1lc3NhZ2UuYWNrO1xuICAgIHZhciBtZXRob2QgPSBtZXNzYWdlLm1ldGhvZDtcbiAgICB2YXIgcGFyYW1zID0gbWVzc2FnZS5wYXJhbXMgfHwge307XG5cbiAgICB2YXIgZnJvbSA9IHBhcmFtcy5mcm9tO1xuICAgIHZhciBkZXN0ID0gcGFyYW1zLmRlc3Q7XG5cbiAgICAvLyBJZ25vcmUgbWVzc2FnZXMgc2VuZCBieSB1c1xuICAgIGlmKHNlbGYucGVlcklEICE9IHVuZGVmaW5lZCAmJiBmcm9tID09IHNlbGYucGVlcklEKSByZXR1cm47XG5cbiAgICAvLyBOb3RpZmljYXRpb25cbiAgICBpZihpZCA9PSB1bmRlZmluZWQgJiYgYWNrID09IHVuZGVmaW5lZClcbiAgICB7XG4gICAgICB2YXIgbm90aWZpY2F0aW9uID0gbmV3IFJwY05vdGlmaWNhdGlvbihtZXRob2QsIHBhcmFtcyk7XG5cbiAgICAgIGlmKHNlbGYuZW1pdCgncmVxdWVzdCcsIG5vdGlmaWNhdGlvbikpIHJldHVybjtcbiAgICAgIHJldHVybiBub3RpZmljYXRpb247XG4gICAgfTtcblxuXG4gICAgZnVuY3Rpb24gcHJvY2Vzc1JlcXVlc3QoKVxuICAgIHtcbiAgICAgIC8vIElmIHdlIGhhdmUgYSB0cmFuc3BvcnQgYW5kIGl0J3MgYSBkdXBsaWNhdGVkIHJlcXVlc3QsIHJlcGx5IGlubWVkaWF0bHlcbiAgICAgIHRyYW5zcG9ydCA9IHVuaWZ5VHJhbnNwb3J0KHRyYW5zcG9ydCkgfHwgc2VsZi5nZXRUcmFuc3BvcnQoKTtcbiAgICAgIGlmKHRyYW5zcG9ydClcbiAgICAgIHtcbiAgICAgICAgdmFyIHJlc3BvbnNlID0gcmVzcG9uc2VzLmdldChpZCwgZnJvbSk7XG4gICAgICAgIGlmKHJlc3BvbnNlKVxuICAgICAgICAgIHJldHVybiB0cmFuc3BvcnQuc2VuZChyZXNwb25zZS5tZXNzYWdlKTtcbiAgICAgIH07XG5cbiAgICAgIHZhciBpZEFjayA9IChpZCAhPSB1bmRlZmluZWQpID8gaWQgOiBhY2s7XG4gICAgICB2YXIgcmVxdWVzdCA9IG5ldyBScGNSZXF1ZXN0KG1ldGhvZCwgcGFyYW1zLCBpZEFjaywgZnJvbSwgdHJhbnNwb3J0KTtcblxuICAgICAgaWYoc2VsZi5lbWl0KCdyZXF1ZXN0JywgcmVxdWVzdCkpIHJldHVybjtcbiAgICAgIHJldHVybiByZXF1ZXN0O1xuICAgIH07XG5cbiAgICBmdW5jdGlvbiBwcm9jZXNzUmVzcG9uc2UocmVxdWVzdCwgZXJyb3IsIHJlc3VsdClcbiAgICB7XG4gICAgICByZXF1ZXN0LmNhbGxiYWNrKGVycm9yLCByZXN1bHQpO1xuICAgIH07XG5cbiAgICBmdW5jdGlvbiBkdXBsaWNhdGVkUmVzcG9uc2UodGltZW91dClcbiAgICB7XG4gICAgICBjb25zb2xlLndhcm4oXCJSZXNwb25zZSBhbHJlYWR5IHByb2Nlc3NlZFwiLCBtZXNzYWdlKTtcblxuICAgICAgLy8gVXBkYXRlIGR1cGxpY2F0ZWQgcmVzcG9uc2VzIHRpbWVvdXRcbiAgICAgIGNsZWFyVGltZW91dCh0aW1lb3V0KTtcbiAgICAgIHN0b3JlUHJvY2Vzc2VkUmVzcG9uc2UoYWNrLCBmcm9tKTtcbiAgICB9O1xuXG5cbiAgICAvLyBSZXF1ZXN0LCBvciByZXNwb25zZSB3aXRoIG93biBtZXRob2RcbiAgICBpZihtZXRob2QpXG4gICAge1xuICAgICAgLy8gQ2hlY2sgaWYgaXQncyBhIHJlc3BvbnNlIHdpdGggb3duIG1ldGhvZFxuICAgICAgaWYoZGVzdCA9PSB1bmRlZmluZWQgfHwgZGVzdCA9PSBzZWxmLnBlZXJJRClcbiAgICAgIHtcbiAgICAgICAgdmFyIHJlcXVlc3QgPSByZXF1ZXN0cy5nZXQoYWNrLCBmcm9tKTtcbiAgICAgICAgaWYocmVxdWVzdClcbiAgICAgICAge1xuICAgICAgICAgIHZhciByZXNwb25zZU1ldGhvZHMgPSByZXF1ZXN0LnJlc3BvbnNlTWV0aG9kcztcblxuICAgICAgICAgIGlmKG1ldGhvZCA9PSByZXNwb25zZU1ldGhvZHMuZXJyb3IpXG4gICAgICAgICAgICByZXR1cm4gcHJvY2Vzc1Jlc3BvbnNlKHJlcXVlc3QsIHBhcmFtcyk7XG5cbiAgICAgICAgICBpZihtZXRob2QgPT0gcmVzcG9uc2VNZXRob2RzLnJlc3BvbnNlKVxuICAgICAgICAgICAgcmV0dXJuIHByb2Nlc3NSZXNwb25zZShyZXF1ZXN0LCBudWxsLCBwYXJhbXMpO1xuXG4gICAgICAgICAgcmV0dXJuIHByb2Nlc3NSZXF1ZXN0KCk7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgcHJvY2Vzc2VkID0gcHJvY2Vzc2VkUmVzcG9uc2VzLmdldChhY2ssIGZyb20pO1xuICAgICAgICBpZihwcm9jZXNzZWQpXG4gICAgICAgICAgcmV0dXJuIGR1cGxpY2F0ZWRSZXNwb25zZShwcm9jZXNzZWQpO1xuICAgICAgfVxuXG4gICAgICAvLyBSZXF1ZXN0XG4gICAgICByZXR1cm4gcHJvY2Vzc1JlcXVlc3QoKTtcbiAgICB9O1xuXG4gICAgdmFyIGVycm9yICA9IG1lc3NhZ2UuZXJyb3I7XG4gICAgdmFyIHJlc3VsdCA9IG1lc3NhZ2UucmVzdWx0O1xuXG4gICAgLy8gSWdub3JlIHJlc3BvbnNlcyBub3Qgc2VuZCB0byB1c1xuICAgIGlmKGVycm9yICAmJiBlcnJvci5kZXN0ICAmJiBlcnJvci5kZXN0ICAhPSBzZWxmLnBlZXJJRCkgcmV0dXJuO1xuICAgIGlmKHJlc3VsdCAmJiByZXN1bHQuZGVzdCAmJiByZXN1bHQuZGVzdCAhPSBzZWxmLnBlZXJJRCkgcmV0dXJuO1xuXG4gICAgLy8gUmVzcG9uc2VcbiAgICB2YXIgcmVxdWVzdCA9IHJlcXVlc3RzLmdldChhY2ssIGZyb20pO1xuICAgIGlmKCFyZXF1ZXN0KVxuICAgIHtcbiAgICAgIHZhciBwcm9jZXNzZWQgPSBwcm9jZXNzZWRSZXNwb25zZXMuZ2V0KGFjaywgZnJvbSk7XG4gICAgICBpZihwcm9jZXNzZWQpXG4gICAgICAgIHJldHVybiBkdXBsaWNhdGVkUmVzcG9uc2UocHJvY2Vzc2VkKTtcblxuICAgICAgcmV0dXJuIGNvbnNvbGUud2FybihcIk5vIGNhbGxiYWNrIHdhcyBkZWZpbmVkIGZvciB0aGlzIG1lc3NhZ2VcIiwgbWVzc2FnZSk7XG4gICAgfTtcblxuICAgIC8vIFByb2Nlc3MgcmVzcG9uc2VcbiAgICBwcm9jZXNzUmVzcG9uc2UocmVxdWVzdCwgZXJyb3IsIHJlc3VsdCk7XG4gIH07XG59O1xuaW5oZXJpdHMoUnBjQnVpbGRlciwgRXZlbnRFbWl0dGVyKTtcblxuXG5ScGNCdWlsZGVyLlJwY05vdGlmaWNhdGlvbiA9IFJwY05vdGlmaWNhdGlvbjtcblxuXG5tb2R1bGUuZXhwb3J0cyA9IFJwY0J1aWxkZXI7XG5cbnZhciBjbGllbnRzID0gcmVxdWlyZSgnLi9jbGllbnRzJyk7XG52YXIgdHJhbnNwb3J0cyA9IHJlcXVpcmUoJy4vY2xpZW50cy90cmFuc3BvcnRzJyk7XG5cblJwY0J1aWxkZXIuY2xpZW50cyA9IGNsaWVudHM7XG5ScGNCdWlsZGVyLmNsaWVudHMudHJhbnNwb3J0cyA9IHRyYW5zcG9ydHM7XG5ScGNCdWlsZGVyLnBhY2tlcnMgPSBwYWNrZXJzO1xuIiwiLyoqXG4gKiBKc29uUlBDIDIuMCBwYWNrZXJcbiAqL1xuXG4vKipcbiAqIFBhY2sgYSBKc29uUlBDIDIuMCBtZXNzYWdlXG4gKlxuICogQHBhcmFtIHtPYmplY3R9IG1lc3NhZ2UgLSBvYmplY3QgdG8gYmUgcGFja2FnZWQuIEl0IHJlcXVpcmVzIHRvIGhhdmUgYWxsIHRoZVxuICogICBmaWVsZHMgbmVlZGVkIGJ5IHRoZSBKc29uUlBDIDIuMCBtZXNzYWdlIHRoYXQgaXQncyBnb2luZyB0byBiZSBnZW5lcmF0ZWRcbiAqXG4gKiBAcmV0dXJuIHtTdHJpbmd9IC0gdGhlIHN0cmluZ2lmaWVkIEpzb25SUEMgMi4wIG1lc3NhZ2VcbiAqL1xuZnVuY3Rpb24gcGFjayhtZXNzYWdlLCBpZClcbntcbiAgdmFyIHJlc3VsdCA9XG4gIHtcbiAgICBqc29ucnBjOiBcIjIuMFwiXG4gIH07XG5cbiAgLy8gUmVxdWVzdFxuICBpZihtZXNzYWdlLm1ldGhvZClcbiAge1xuICAgIHJlc3VsdC5tZXRob2QgPSBtZXNzYWdlLm1ldGhvZDtcblxuICAgIGlmKG1lc3NhZ2UucGFyYW1zKVxuICAgICAgcmVzdWx0LnBhcmFtcyA9IG1lc3NhZ2UucGFyYW1zO1xuXG4gICAgLy8gUmVxdWVzdCBpcyBhIG5vdGlmaWNhdGlvblxuICAgIGlmKGlkICE9IHVuZGVmaW5lZClcbiAgICAgIHJlc3VsdC5pZCA9IGlkO1xuICB9XG5cbiAgLy8gUmVzcG9uc2VcbiAgZWxzZSBpZihpZCAhPSB1bmRlZmluZWQpXG4gIHtcbiAgICBpZihtZXNzYWdlLmVycm9yKVxuICAgIHtcbiAgICAgIGlmKG1lc3NhZ2UucmVzdWx0ICE9PSB1bmRlZmluZWQpXG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJCb3RoIHJlc3VsdCBhbmQgZXJyb3IgYXJlIGRlZmluZWRcIik7XG5cbiAgICAgIHJlc3VsdC5lcnJvciA9IG1lc3NhZ2UuZXJyb3I7XG4gICAgfVxuICAgIGVsc2UgaWYobWVzc2FnZS5yZXN1bHQgIT09IHVuZGVmaW5lZClcbiAgICAgIHJlc3VsdC5yZXN1bHQgPSBtZXNzYWdlLnJlc3VsdDtcbiAgICBlbHNlXG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiTm8gcmVzdWx0IG9yIGVycm9yIGlzIGRlZmluZWRcIik7XG5cbiAgICByZXN1bHQuaWQgPSBpZDtcbiAgfTtcblxuICByZXR1cm4gSlNPTi5zdHJpbmdpZnkocmVzdWx0KTtcbn07XG5cbi8qKlxuICogVW5wYWNrIGEgSnNvblJQQyAyLjAgbWVzc2FnZVxuICpcbiAqIEBwYXJhbSB7U3RyaW5nfSBtZXNzYWdlIC0gc3RyaW5nIHdpdGggdGhlIGNvbnRlbnQgb2YgdGhlIEpzb25SUEMgMi4wIG1lc3NhZ2VcbiAqXG4gKiBAdGhyb3dzIHtUeXBlRXJyb3J9IC0gSW52YWxpZCBKc29uUlBDIHZlcnNpb25cbiAqXG4gKiBAcmV0dXJuIHtPYmplY3R9IC0gb2JqZWN0IGZpbGxlZCB3aXRoIHRoZSBKc29uUlBDIDIuMCBtZXNzYWdlIGNvbnRlbnRcbiAqL1xuZnVuY3Rpb24gdW5wYWNrKG1lc3NhZ2UpXG57XG4gIHZhciByZXN1bHQgPSBtZXNzYWdlO1xuXG4gIGlmKHR5cGVvZiBtZXNzYWdlID09PSAnc3RyaW5nJyB8fCBtZXNzYWdlIGluc3RhbmNlb2YgU3RyaW5nKSB7XG4gICAgcmVzdWx0ID0gSlNPTi5wYXJzZShtZXNzYWdlKTtcbiAgfVxuXG4gIC8vIENoZWNrIGlmIGl0J3MgYSB2YWxpZCBtZXNzYWdlXG5cbiAgdmFyIHZlcnNpb24gPSByZXN1bHQuanNvbnJwYztcbiAgaWYodmVyc2lvbiAhPT0gJzIuMCcpXG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkludmFsaWQgSnNvblJQQyB2ZXJzaW9uICdcIiArIHZlcnNpb24gKyBcIic6IFwiICsgbWVzc2FnZSk7XG5cbiAgLy8gUmVzcG9uc2VcbiAgaWYocmVzdWx0Lm1ldGhvZCA9PSB1bmRlZmluZWQpXG4gIHtcbiAgICBpZihyZXN1bHQuaWQgPT0gdW5kZWZpbmVkKVxuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkludmFsaWQgbWVzc2FnZTogXCIrbWVzc2FnZSk7XG5cbiAgICB2YXIgcmVzdWx0X2RlZmluZWQgPSByZXN1bHQucmVzdWx0ICE9PSB1bmRlZmluZWQ7XG4gICAgdmFyIGVycm9yX2RlZmluZWQgID0gcmVzdWx0LmVycm9yICAhPT0gdW5kZWZpbmVkO1xuXG4gICAgLy8gQ2hlY2sgb25seSByZXN1bHQgb3IgZXJyb3IgaXMgZGVmaW5lZCwgbm90IGJvdGggb3Igbm9uZVxuICAgIGlmKHJlc3VsdF9kZWZpbmVkICYmIGVycm9yX2RlZmluZWQpXG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQm90aCByZXN1bHQgYW5kIGVycm9yIGFyZSBkZWZpbmVkOiBcIittZXNzYWdlKTtcblxuICAgIGlmKCFyZXN1bHRfZGVmaW5lZCAmJiAhZXJyb3JfZGVmaW5lZClcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJObyByZXN1bHQgb3IgZXJyb3IgaXMgZGVmaW5lZDogXCIrbWVzc2FnZSk7XG5cbiAgICByZXN1bHQuYWNrID0gcmVzdWx0LmlkO1xuICAgIGRlbGV0ZSByZXN1bHQuaWQ7XG4gIH1cblxuICAvLyBSZXR1cm4gdW5wYWNrZWQgbWVzc2FnZVxuICByZXR1cm4gcmVzdWx0O1xufTtcblxuXG5leHBvcnRzLnBhY2sgICA9IHBhY2s7XG5leHBvcnRzLnVucGFjayA9IHVucGFjaztcbiIsImZ1bmN0aW9uIHBhY2sobWVzc2FnZSlcbntcbiAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIk5vdCB5ZXQgaW1wbGVtZW50ZWRcIik7XG59O1xuXG5mdW5jdGlvbiB1bnBhY2sobWVzc2FnZSlcbntcbiAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIk5vdCB5ZXQgaW1wbGVtZW50ZWRcIik7XG59O1xuXG5cbmV4cG9ydHMucGFjayAgID0gcGFjaztcbmV4cG9ydHMudW5wYWNrID0gdW5wYWNrO1xuIiwidmFyIEpzb25SUEMgPSByZXF1aXJlKCcuL0pzb25SUEMnKTtcbnZhciBYbWxSUEMgID0gcmVxdWlyZSgnLi9YbWxSUEMnKTtcblxuXG5leHBvcnRzLkpzb25SUEMgPSBKc29uUlBDO1xuZXhwb3J0cy5YbWxSUEMgID0gWG1sUlBDO1xuIiwiLy8gTGFzdCB0aW1lIHVwZGF0ZWQgb24gSnVuZSAwOCwgMjAxOFxuXG4vLyBMYXRlc3QgZmlsZSBjYW4gYmUgZm91bmQgaGVyZTogaHR0cHM6Ly9jZG4ud2VicnRjLWV4cGVyaW1lbnQuY29tL2dldFNjcmVlbklkLmpzXG5cbi8vIE11YXogS2hhbiAgICAgICAgIC0gd3d3Lk11YXpLaGFuLmNvbVxuLy8gTUlUIExpY2Vuc2UgICAgICAgLSB3d3cuV2ViUlRDLUV4cGVyaW1lbnQuY29tL2xpY2VuY2Vcbi8vIERvY3VtZW50YXRpb24gICAgIC0gaHR0cHM6Ly9naXRodWIuY29tL211YXota2hhbi9nZXRTY3JlZW5JZC5cblxuLy8gX19fX19fX19fX19fX19cbi8vIGdldFNjcmVlbklkLmpzXG5cbi8qXG5nZXRTY3JlZW5JZChmdW5jdGlvbiAoZXJyb3IsIHNvdXJjZUlkLCBzY3JlZW5fY29uc3RyYWludHMpIHtcbiAgICAvLyBlcnJvciAgICA9PSBudWxsIHx8ICdwZXJtaXNzaW9uLWRlbmllZCcgfHwgJ25vdC1pbnN0YWxsZWQnIHx8ICdpbnN0YWxsZWQtZGlzYWJsZWQnIHx8ICdub3QtY2hyb21lJ1xuICAgIC8vIHNvdXJjZUlkID09IG51bGwgfHwgJ3N0cmluZycgfHwgJ2ZpcmVmb3gnXG4gICAgXG4gICAgaWYobWljcm9zb2Z0RWRnZSkge1xuICAgICAgICBuYXZpZ2F0b3IuZ2V0RGlzcGxheU1lZGlhKHNjcmVlbl9jb25zdHJhaW50cykudGhlbihvblN1Y2Nlc3MsIG9uRmFpbHVyZSk7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICBuYXZpZ2F0b3IubWVkaWFEZXZpY2VzLmdldFVzZXJNZWRpYShzY3JlZW5fY29uc3RyYWludHMpLnRoZW4ob25TdWNjZXNzKWNhdGNoKG9uRmFpbHVyZSk7XG4gICAgfVxufSwgJ3Bhc3Mgc2Vjb25kIHBhcmFtZXRlciBvbmx5IGlmIHlvdSB3YW50IHN5c3RlbSBhdWRpbycpO1xuKi9cblxud2luZG93LmdldFNjcmVlbklkID0gZnVuY3Rpb24gKGNhbGxiYWNrLCBjdXN0b21fcGFyYW1ldGVyKSB7XG4gICAgaWYgKG5hdmlnYXRvci51c2VyQWdlbnQuaW5kZXhPZignRWRnZScpICE9PSAtMSAmJiAoISFuYXZpZ2F0b3IubXNTYXZlT3JPcGVuQmxvYiB8fCAhIW5hdmlnYXRvci5tc1NhdmVCbG9iKSkge1xuICAgICAgICAvLyBtaWNyb3NvZnQgZWRnZSA9PiBuYXZpZ2F0b3IuZ2V0RGlzcGxheU1lZGlhKHNjcmVlbl9jb25zdHJhaW50cykudGhlbihvblN1Y2Nlc3MsIG9uRmFpbHVyZSk7XG4gICAgICAgIGNhbGxiYWNrKHtcbiAgICAgICAgICAgIHZpZGVvOiB0cnVlXG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gZm9yIEZpcmVmb3g6XG4gICAgLy8gc291cmNlSWQgPT0gJ2ZpcmVmb3gnXG4gICAgLy8gc2NyZWVuX2NvbnN0cmFpbnRzID0gey4uLn1cbiAgICBpZiAoISFuYXZpZ2F0b3IubW96R2V0VXNlck1lZGlhKSB7XG4gICAgICAgIGNhbGxiYWNrKG51bGwsICdmaXJlZm94Jywge1xuICAgICAgICAgICAgdmlkZW86IHtcbiAgICAgICAgICAgICAgICBtb3pNZWRpYVNvdXJjZTogJ3dpbmRvdycsXG4gICAgICAgICAgICAgICAgbWVkaWFTb3VyY2U6ICd3aW5kb3cnXG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ21lc3NhZ2UnLCBvbklGcmFtZUNhbGxiYWNrKTtcblxuICAgIGZ1bmN0aW9uIG9uSUZyYW1lQ2FsbGJhY2soZXZlbnQpIHtcbiAgICAgICAgaWYgKCFldmVudC5kYXRhKSByZXR1cm47XG5cbiAgICAgICAgaWYgKGV2ZW50LmRhdGEuY2hyb21lTWVkaWFTb3VyY2VJZCkge1xuICAgICAgICAgICAgaWYgKGV2ZW50LmRhdGEuY2hyb21lTWVkaWFTb3VyY2VJZCA9PT0gJ1Blcm1pc3Npb25EZW5pZWRFcnJvcicpIHtcbiAgICAgICAgICAgICAgICBjYWxsYmFjaygncGVybWlzc2lvbi1kZW5pZWQnKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY2FsbGJhY2sobnVsbCwgZXZlbnQuZGF0YS5jaHJvbWVNZWRpYVNvdXJjZUlkLCBnZXRTY3JlZW5Db25zdHJhaW50cyhudWxsLCBldmVudC5kYXRhLmNocm9tZU1lZGlhU291cmNlSWQsIGV2ZW50LmRhdGEuY2FuUmVxdWVzdEF1ZGlvVHJhY2spKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gdGhpcyBldmVudCBsaXN0ZW5lciBpcyBubyBtb3JlIG5lZWRlZFxuICAgICAgICAgICAgd2luZG93LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ21lc3NhZ2UnLCBvbklGcmFtZUNhbGxiYWNrKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChldmVudC5kYXRhLmNocm9tZUV4dGVuc2lvblN0YXR1cykge1xuICAgICAgICAgICAgY2FsbGJhY2soZXZlbnQuZGF0YS5jaHJvbWVFeHRlbnNpb25TdGF0dXMsIG51bGwsIGdldFNjcmVlbkNvbnN0cmFpbnRzKGV2ZW50LmRhdGEuY2hyb21lRXh0ZW5zaW9uU3RhdHVzKSk7XG5cbiAgICAgICAgICAgIC8vIHRoaXMgZXZlbnQgbGlzdGVuZXIgaXMgbm8gbW9yZSBuZWVkZWRcbiAgICAgICAgICAgIHdpbmRvdy5yZW1vdmVFdmVudExpc3RlbmVyKCdtZXNzYWdlJywgb25JRnJhbWVDYWxsYmFjayk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoIWN1c3RvbV9wYXJhbWV0ZXIpIHtcbiAgICAgICAgc2V0VGltZW91dChwb3N0R2V0U291cmNlSWRNZXNzYWdlLCAxMDApO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBwb3N0R2V0U291cmNlSWRNZXNzYWdlKGN1c3RvbV9wYXJhbWV0ZXIpO1xuICAgICAgICB9LCAxMDApO1xuICAgIH1cbn07XG5cbmZ1bmN0aW9uIGdldFNjcmVlbkNvbnN0cmFpbnRzKGVycm9yLCBzb3VyY2VJZCwgY2FuUmVxdWVzdEF1ZGlvVHJhY2spIHtcbiAgICB2YXIgc2NyZWVuX2NvbnN0cmFpbnRzID0ge1xuICAgICAgICBhdWRpbzogZmFsc2UsXG4gICAgICAgIHZpZGVvOiB7XG4gICAgICAgICAgICBtYW5kYXRvcnk6IHtcbiAgICAgICAgICAgICAgICBjaHJvbWVNZWRpYVNvdXJjZTogZXJyb3IgPyAnc2NyZWVuJyA6ICdkZXNrdG9wJyxcbiAgICAgICAgICAgICAgICBtYXhXaWR0aDogd2luZG93LnNjcmVlbi53aWR0aCA+IDE5MjAgPyB3aW5kb3cuc2NyZWVuLndpZHRoIDogMTkyMCxcbiAgICAgICAgICAgICAgICBtYXhIZWlnaHQ6IHdpbmRvdy5zY3JlZW4uaGVpZ2h0ID4gMTA4MCA/IHdpbmRvdy5zY3JlZW4uaGVpZ2h0IDogMTA4MFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIG9wdGlvbmFsOiBbXVxuICAgICAgICB9XG4gICAgfTtcblxuICAgIGlmICghIWNhblJlcXVlc3RBdWRpb1RyYWNrKSB7XG4gICAgICAgIHNjcmVlbl9jb25zdHJhaW50cy5hdWRpbyA9IHtcbiAgICAgICAgICAgIG1hbmRhdG9yeToge1xuICAgICAgICAgICAgICAgIGNocm9tZU1lZGlhU291cmNlOiBlcnJvciA/ICdzY3JlZW4nIDogJ2Rlc2t0b3AnLFxuICAgICAgICAgICAgICAgIC8vIGVjaG9DYW5jZWxsYXRpb246IHRydWVcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBvcHRpb25hbDogW11cbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICBpZiAoc291cmNlSWQpIHtcbiAgICAgICAgc2NyZWVuX2NvbnN0cmFpbnRzLnZpZGVvLm1hbmRhdG9yeS5jaHJvbWVNZWRpYVNvdXJjZUlkID0gc291cmNlSWQ7XG5cbiAgICAgICAgaWYgKHNjcmVlbl9jb25zdHJhaW50cy5hdWRpbyAmJiBzY3JlZW5fY29uc3RyYWludHMuYXVkaW8ubWFuZGF0b3J5KSB7XG4gICAgICAgICAgICBzY3JlZW5fY29uc3RyYWludHMuYXVkaW8ubWFuZGF0b3J5LmNocm9tZU1lZGlhU291cmNlSWQgPSBzb3VyY2VJZDtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBzY3JlZW5fY29uc3RyYWludHM7XG59XG5cbmZ1bmN0aW9uIHBvc3RHZXRTb3VyY2VJZE1lc3NhZ2UoY3VzdG9tX3BhcmFtZXRlcikge1xuICAgIGlmICghaWZyYW1lKSB7XG4gICAgICAgIGxvYWRJRnJhbWUoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcG9zdEdldFNvdXJjZUlkTWVzc2FnZShjdXN0b21fcGFyYW1ldGVyKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAoIWlmcmFtZS5pc0xvYWRlZCkge1xuICAgICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHBvc3RHZXRTb3VyY2VJZE1lc3NhZ2UoY3VzdG9tX3BhcmFtZXRlcik7XG4gICAgICAgIH0sIDEwMCk7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAoIWN1c3RvbV9wYXJhbWV0ZXIpIHtcbiAgICAgICAgaWZyYW1lLmNvbnRlbnRXaW5kb3cucG9zdE1lc3NhZ2Uoe1xuICAgICAgICAgICAgY2FwdHVyZVNvdXJjZUlkOiB0cnVlXG4gICAgICAgIH0sICcqJyk7XG4gICAgfVxuICAgIGVsc2UgaWYgKCEhY3VzdG9tX3BhcmFtZXRlci5mb3JFYWNoKSB7XG4gICAgICAgIGlmcmFtZS5jb250ZW50V2luZG93LnBvc3RNZXNzYWdlKHtcbiAgICAgICAgICAgIGNhcHR1cmVDdXN0b21Tb3VyY2VJZDogY3VzdG9tX3BhcmFtZXRlclxuICAgICAgICB9LCAnKicpO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgaWZyYW1lLmNvbnRlbnRXaW5kb3cucG9zdE1lc3NhZ2Uoe1xuICAgICAgICAgICAgY2FwdHVyZVNvdXJjZUlkV2l0aEF1ZGlvOiB0cnVlXG4gICAgICAgIH0sICcqJyk7XG4gICAgfVxufVxuXG52YXIgaWZyYW1lO1xuXG4vLyB0aGlzIGZ1bmN0aW9uIGlzIHVzZWQgaW4gUlRDTXVsdGlDb25uZWN0aW9uIHYzXG53aW5kb3cuZ2V0U2NyZWVuQ29uc3RyYWludHMgPSBmdW5jdGlvbiAoY2FsbGJhY2spIHtcbiAgICBsb2FkSUZyYW1lKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgZ2V0U2NyZWVuSWQoZnVuY3Rpb24gKGVycm9yLCBzb3VyY2VJZCwgc2NyZWVuX2NvbnN0cmFpbnRzKSB7XG4gICAgICAgICAgICBpZiAoIXNjcmVlbl9jb25zdHJhaW50cykge1xuICAgICAgICAgICAgICAgIHNjcmVlbl9jb25zdHJhaW50cyA9IHtcbiAgICAgICAgICAgICAgICAgICAgdmlkZW86IHRydWVcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBjYWxsYmFjayhlcnJvciwgc2NyZWVuX2NvbnN0cmFpbnRzLnZpZGVvKTtcbiAgICAgICAgfSk7XG4gICAgfSk7XG59O1xuXG5mdW5jdGlvbiBsb2FkSUZyYW1lKGxvYWRDYWxsYmFjaykge1xuICAgIGlmIChpZnJhbWUpIHtcbiAgICAgICAgbG9hZENhbGxiYWNrKCk7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZnJhbWUgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdpZnJhbWUnKTtcbiAgICBpZnJhbWUub25sb2FkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZnJhbWUuaXNMb2FkZWQgPSB0cnVlO1xuICAgICAgICBsb2FkQ2FsbGJhY2soKTtcbiAgICB9O1xuICAgIGlmcmFtZS5zcmMgPSAnaHR0cHM6Ly9vcGVudmlkdS5naXRodWIuaW8vb3BlbnZpZHUtc2NyZWVuLXNoYXJpbmctY2hyb21lLWV4dGVuc2lvbi8nO1xuICAgIGlmcmFtZS5zdHlsZS5kaXNwbGF5ID0gJ25vbmUnO1xuICAgIChkb2N1bWVudC5ib2R5IHx8IGRvY3VtZW50LmRvY3VtZW50RWxlbWVudCkuYXBwZW5kQ2hpbGQoaWZyYW1lKTtcbn1cblxud2luZG93LmdldENocm9tZUV4dGVuc2lvblN0YXR1cyA9IGZ1bmN0aW9uIChjYWxsYmFjaykge1xuICAgIC8vIGZvciBGaXJlZm94OlxuICAgIGlmICghIW5hdmlnYXRvci5tb3pHZXRVc2VyTWVkaWEpIHtcbiAgICAgICAgY2FsbGJhY2soJ2luc3RhbGxlZC1lbmFibGVkJyk7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcignbWVzc2FnZScsIG9uSUZyYW1lQ2FsbGJhY2spO1xuXG4gICAgZnVuY3Rpb24gb25JRnJhbWVDYWxsYmFjayhldmVudCkge1xuICAgICAgICBpZiAoIWV2ZW50LmRhdGEpIHJldHVybjtcblxuICAgICAgICBpZiAoZXZlbnQuZGF0YS5jaHJvbWVFeHRlbnNpb25TdGF0dXMpIHtcbiAgICAgICAgICAgIGNhbGxiYWNrKGV2ZW50LmRhdGEuY2hyb21lRXh0ZW5zaW9uU3RhdHVzKTtcblxuICAgICAgICAgICAgLy8gdGhpcyBldmVudCBsaXN0ZW5lciBpcyBubyBtb3JlIG5lZWRlZFxuICAgICAgICAgICAgd2luZG93LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ21lc3NhZ2UnLCBvbklGcmFtZUNhbGxiYWNrKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHNldFRpbWVvdXQocG9zdEdldENocm9tZUV4dGVuc2lvblN0YXR1c01lc3NhZ2UsIDEwMCk7XG59O1xuXG5mdW5jdGlvbiBwb3N0R2V0Q2hyb21lRXh0ZW5zaW9uU3RhdHVzTWVzc2FnZSgpIHtcbiAgICBpZiAoIWlmcmFtZSkge1xuICAgICAgICBsb2FkSUZyYW1lKHBvc3RHZXRDaHJvbWVFeHRlbnNpb25TdGF0dXNNZXNzYWdlKTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmICghaWZyYW1lLmlzTG9hZGVkKSB7XG4gICAgICAgIHNldFRpbWVvdXQocG9zdEdldENocm9tZUV4dGVuc2lvblN0YXR1c01lc3NhZ2UsIDEwMCk7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZnJhbWUuY29udGVudFdpbmRvdy5wb3N0TWVzc2FnZSh7XG4gICAgICAgIGdldENocm9tZUV4dGVuc2lvblN0YXR1czogdHJ1ZVxuICAgIH0sICcqJyk7XG59XG5cbmV4cG9ydHMuZ2V0U2NyZWVuSWQgPSBnZXRTY3JlZW5JZDsiLCIvLyBnbG9iYWwgdmFyaWFibGVzXG52YXIgY2hyb21lTWVkaWFTb3VyY2UgPSAnc2NyZWVuJztcbnZhciBzb3VyY2VJZDtcbnZhciBzY3JlZW5DYWxsYmFjaztcbnZhciBpc0ZpcmVmb3ggPSB0eXBlb2Ygd2luZG93Lkluc3RhbGxUcmlnZ2VyICE9PSAndW5kZWZpbmVkJztcbnZhciBpc09wZXJhID0gISF3aW5kb3cub3BlcmEgfHwgbmF2aWdhdG9yLnVzZXJBZ2VudC5pbmRleE9mKCcgT1BSLycpID49IDA7XG52YXIgaXNDaHJvbWUgPSAhIXdpbmRvdy5jaHJvbWUgJiYgIWlzT3BlcmE7XG5cbndpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdtZXNzYWdlJywgZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgaWYgKGV2ZW50Lm9yaWdpbiAhPSB3aW5kb3cubG9jYXRpb24ub3JpZ2luKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgb25NZXNzYWdlQ2FsbGJhY2soZXZlbnQuZGF0YSk7XG59KTtcblxuLy8gYW5kIHRoZSBmdW5jdGlvbiB0aGF0IGhhbmRsZXMgcmVjZWl2ZWQgbWVzc2FnZXNcbmZ1bmN0aW9uIG9uTWVzc2FnZUNhbGxiYWNrKGRhdGEpIHtcbiAgICAvLyBcImNhbmNlbFwiIGJ1dHRvbiBpcyBjbGlja2VkXG4gICAgaWYgKGRhdGEgPT0gJ1Blcm1pc3Npb25EZW5pZWRFcnJvcicpIHtcbiAgICAgICAgaWYgKHNjcmVlbkNhbGxiYWNrKVxuICAgICAgICAgICAgcmV0dXJuIHNjcmVlbkNhbGxiYWNrKCdQZXJtaXNzaW9uRGVuaWVkRXJyb3InKTtcbiAgICAgICAgZWxzZVxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdQZXJtaXNzaW9uRGVuaWVkRXJyb3InKTtcbiAgICB9XG4gICAgLy8gZXh0ZW5zaW9uIG5vdGlmaWVkIGhpcyBwcmVzZW5jZVxuICAgIGlmIChkYXRhID09ICdydGNtdWx0aWNvbm5lY3Rpb24tZXh0ZW5zaW9uLWxvYWRlZCcpIHtcbiAgICAgICAgY2hyb21lTWVkaWFTb3VyY2UgPSAnZGVza3RvcCc7XG4gICAgfVxuICAgIC8vIGV4dGVuc2lvbiBzaGFyZWQgdGVtcCBzb3VyY2VJZFxuICAgIGlmIChkYXRhLnNvdXJjZUlkICYmIHNjcmVlbkNhbGxiYWNrKSB7XG4gICAgICAgIHNjcmVlbkNhbGxiYWNrKHNvdXJjZUlkID0gZGF0YS5zb3VyY2VJZCwgZGF0YS5jYW5SZXF1ZXN0QXVkaW9UcmFjayA9PT0gdHJ1ZSk7XG4gICAgfVxufVxuXG4vLyB0aGlzIG1ldGhvZCBjYW4gYmUgdXNlZCB0byBjaGVjayBpZiBjaHJvbWUgZXh0ZW5zaW9uIGlzIGluc3RhbGxlZCAmIGVuYWJsZWQuXG5mdW5jdGlvbiBpc0Nocm9tZUV4dGVuc2lvbkF2YWlsYWJsZShjYWxsYmFjaykge1xuICAgIGlmICghY2FsbGJhY2spIHJldHVybjtcbiAgICBpZiAoY2hyb21lTWVkaWFTb3VyY2UgPT0gJ2Rlc2t0b3AnKSByZXR1cm4gY2FsbGJhY2sodHJ1ZSk7XG5cbiAgICAvLyBhc2sgZXh0ZW5zaW9uIGlmIGl0IGlzIGF2YWlsYWJsZVxuICAgIHdpbmRvdy5wb3N0TWVzc2FnZSgnYXJlLXlvdS10aGVyZScsICcqJyk7XG4gICAgc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmIChjaHJvbWVNZWRpYVNvdXJjZSA9PSAnc2NyZWVuJykge1xuICAgICAgICAgICAgY2FsbGJhY2soZmFsc2UpO1xuICAgICAgICB9IGVsc2UgY2FsbGJhY2sodHJ1ZSk7XG4gICAgfSwgMjAwMCk7XG59XG5cbi8vIHRoaXMgZnVuY3Rpb24gY2FuIGJlIHVzZWQgdG8gZ2V0IFwic291cmNlLWlkXCIgZnJvbSB0aGUgZXh0ZW5zaW9uXG5mdW5jdGlvbiBnZXRTb3VyY2VJZChjYWxsYmFjaykge1xuICAgIGlmICghY2FsbGJhY2spXG4gICAgICAgIHRocm93ICdcImNhbGxiYWNrXCIgcGFyYW1ldGVyIGlzIG1hbmRhdG9yeS4nO1xuICAgIGlmIChzb3VyY2VJZClcbiAgICAgICAgcmV0dXJuIGNhbGxiYWNrKHNvdXJjZUlkKTtcbiAgICBzY3JlZW5DYWxsYmFjayA9IGNhbGxiYWNrO1xuICAgIHdpbmRvdy5wb3N0TWVzc2FnZSgnZ2V0LXNvdXJjZUlkJywgJyonKTtcbn1cblxuLy8gdGhpcyBmdW5jdGlvbiBjYW4gYmUgdXNlZCB0byBnZXQgXCJzb3VyY2UtaWRcIiBmcm9tIHRoZSBleHRlbnNpb25cbmZ1bmN0aW9uIGdldEN1c3RvbVNvdXJjZUlkKGFyciwgY2FsbGJhY2spIHtcbiAgICBpZiAoIWFyciB8fCAhYXJyLmZvckVhY2gpIHRocm93ICdcImFyclwiIHBhcmFtZXRlciBpcyBtYW5kYXRvcnkgYW5kIGl0IG11c3QgYmUgYW4gYXJyYXkuJztcbiAgICBpZiAoIWNhbGxiYWNrKSB0aHJvdyAnXCJjYWxsYmFja1wiIHBhcmFtZXRlciBpcyBtYW5kYXRvcnkuJztcblxuICAgIGlmIChzb3VyY2VJZCkgcmV0dXJuIGNhbGxiYWNrKHNvdXJjZUlkKTtcblxuICAgIHNjcmVlbkNhbGxiYWNrID0gY2FsbGJhY2s7XG4gICAgd2luZG93LnBvc3RNZXNzYWdlKHtcbiAgICAgICAgJ2dldC1jdXN0b20tc291cmNlSWQnOiBhcnJcbiAgICB9LCAnKicpO1xufVxuXG4vLyB0aGlzIGZ1bmN0aW9uIGNhbiBiZSB1c2VkIHRvIGdldCBcInNvdXJjZS1pZFwiIGZyb20gdGhlIGV4dGVuc2lvblxuZnVuY3Rpb24gZ2V0U291cmNlSWRXaXRoQXVkaW8oY2FsbGJhY2spIHtcbiAgICBpZiAoIWNhbGxiYWNrKSB0aHJvdyAnXCJjYWxsYmFja1wiIHBhcmFtZXRlciBpcyBtYW5kYXRvcnkuJztcbiAgICBpZiAoc291cmNlSWQpIHJldHVybiBjYWxsYmFjayhzb3VyY2VJZCk7XG5cbiAgICBzY3JlZW5DYWxsYmFjayA9IGNhbGxiYWNrO1xuICAgIHdpbmRvdy5wb3N0TWVzc2FnZSgnYXVkaW8tcGx1cy10YWInLCAnKicpO1xufVxuXG5mdW5jdGlvbiBnZXRDaHJvbWVFeHRlbnNpb25TdGF0dXMoZXh0ZW5zaW9uaWQsIGNhbGxiYWNrKSB7XG4gICAgaWYgKGlzRmlyZWZveClcbiAgICAgICAgcmV0dXJuIGNhbGxiYWNrKCdub3QtY2hyb21lJyk7XG4gICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggIT0gMikge1xuICAgICAgICBjYWxsYmFjayA9IGV4dGVuc2lvbmlkO1xuICAgICAgICBleHRlbnNpb25pZCA9ICdsZmNnZmVwYWZub2JkbG9lY2NobmZhY2xpYmVuam9sZCc7IC8vIGRlZmF1bHQgZXh0ZW5zaW9uLWlkXG4gICAgfVxuICAgIHZhciBpbWFnZSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2ltZycpO1xuICAgIGltYWdlLnNyYyA9ICdjaHJvbWUtZXh0ZW5zaW9uOi8vJyArIGV4dGVuc2lvbmlkICsgJy9pY29uLnBuZyc7XG4gICAgaW1hZ2Uub25sb2FkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBjaHJvbWVNZWRpYVNvdXJjZSA9ICdzY3JlZW4nO1xuICAgICAgICB3aW5kb3cucG9zdE1lc3NhZ2UoJ2FyZS15b3UtdGhlcmUnLCAnKicpO1xuICAgICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIGlmIChjaHJvbWVNZWRpYVNvdXJjZSA9PSAnc2NyZWVuJykge1xuICAgICAgICAgICAgICAgIGNhbGxiYWNrKCdpbnN0YWxsZWQtZGlzYWJsZWQnKTtcbiAgICAgICAgICAgIH0gZWxzZVxuICAgICAgICAgICAgICAgIGNhbGxiYWNrKCdpbnN0YWxsZWQtZW5hYmxlZCcpO1xuICAgICAgICB9LCAyMDAwKTtcbiAgICB9O1xuICAgIGltYWdlLm9uZXJyb3IgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGNhbGxiYWNrKCdub3QtaW5zdGFsbGVkJyk7XG4gICAgfTtcbn1cblxuZnVuY3Rpb24gZ2V0U2NyZWVuQ29uc3RyYWludHNXaXRoQXVkaW8oY2FsbGJhY2spIHtcbiAgICBnZXRTY3JlZW5Db25zdHJhaW50cyhjYWxsYmFjaywgdHJ1ZSk7XG59XG5cbi8vIHRoaXMgZnVuY3Rpb24gZXhwbGFpbnMgaG93IHRvIHVzZSBhYm92ZSBtZXRob2RzL29iamVjdHNcbmZ1bmN0aW9uIGdldFNjcmVlbkNvbnN0cmFpbnRzKGNhbGxiYWNrLCBjYXB0dXJlU291cmNlSWRXaXRoQXVkaW8pIHtcbiAgICBzb3VyY2VJZCA9ICcnO1xuICAgIHZhciBmaXJlZm94U2NyZWVuQ29uc3RyYWludHMgPSB7XG4gICAgICAgIG1vek1lZGlhU291cmNlOiAnd2luZG93JyxcbiAgICAgICAgbWVkaWFTb3VyY2U6ICd3aW5kb3cnXG4gICAgfTtcbiAgICBpZiAoaXNGaXJlZm94KVxuICAgICAgICByZXR1cm4gY2FsbGJhY2sobnVsbCwgZmlyZWZveFNjcmVlbkNvbnN0cmFpbnRzKTtcbiAgICAvLyB0aGlzIHN0YXRlbWVudCBkZWZpbmVzIGdldFVzZXJNZWRpYSBjb25zdHJhaW50c1xuICAgIC8vIHRoYXQgd2lsbCBiZSB1c2VkIHRvIGNhcHR1cmUgY29udGVudCBvZiBzY3JlZW5cbiAgICB2YXIgc2NyZWVuX2NvbnN0cmFpbnRzID0ge1xuICAgICAgICBtYW5kYXRvcnk6IHtcbiAgICAgICAgICAgIGNocm9tZU1lZGlhU291cmNlOiBjaHJvbWVNZWRpYVNvdXJjZSxcbiAgICAgICAgICAgIG1heFdpZHRoOiBzY3JlZW4ud2lkdGggPiAxOTIwID8gc2NyZWVuLndpZHRoIDogMTkyMCxcbiAgICAgICAgICAgIG1heEhlaWdodDogc2NyZWVuLmhlaWdodCA+IDEwODAgPyBzY3JlZW4uaGVpZ2h0IDogMTA4MFxuICAgICAgICB9LFxuICAgICAgICBvcHRpb25hbDogW11cbiAgICB9O1xuICAgIC8vIHRoaXMgc3RhdGVtZW50IHZlcmlmaWVzIGNocm9tZSBleHRlbnNpb24gYXZhaWxhYmlsaXR5XG4gICAgLy8gaWYgaW5zdGFsbGVkIGFuZCBhdmFpbGFibGUgdGhlbiBpdCB3aWxsIGludm9rZSBleHRlbnNpb24gQVBJXG4gICAgLy8gb3RoZXJ3aXNlIGl0IHdpbGwgZmFsbGJhY2sgdG8gY29tbWFuZC1saW5lIGJhc2VkIHNjcmVlbiBjYXB0dXJpbmcgQVBJXG4gICAgaWYgKGNocm9tZU1lZGlhU291cmNlID09ICdkZXNrdG9wJyAmJiAhc291cmNlSWQpIHtcbiAgICAgICAgaWYgKGNhcHR1cmVTb3VyY2VJZFdpdGhBdWRpbykge1xuICAgICAgICAgICAgZ2V0U291cmNlSWRXaXRoQXVkaW8oZnVuY3Rpb24gKHNvdXJjZUlkLCBjYW5SZXF1ZXN0QXVkaW9UcmFjaykge1xuICAgICAgICAgICAgICAgIHNjcmVlbl9jb25zdHJhaW50cy5tYW5kYXRvcnkuY2hyb21lTWVkaWFTb3VyY2VJZCA9IHNvdXJjZUlkO1xuXG4gICAgICAgICAgICAgICAgaWYgKGNhblJlcXVlc3RBdWRpb1RyYWNrKSB7XG4gICAgICAgICAgICAgICAgICAgIHNjcmVlbl9jb25zdHJhaW50cy5jYW5SZXF1ZXN0QXVkaW9UcmFjayA9IHRydWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNhbGxiYWNrKHNvdXJjZUlkID09ICdQZXJtaXNzaW9uRGVuaWVkRXJyb3InID8gc291cmNlSWQgOiBudWxsLCBzY3JlZW5fY29uc3RyYWludHMpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBnZXRTb3VyY2VJZChmdW5jdGlvbiAoc291cmNlSWQpIHtcbiAgICAgICAgICAgICAgICBzY3JlZW5fY29uc3RyYWludHMubWFuZGF0b3J5LmNocm9tZU1lZGlhU291cmNlSWQgPSBzb3VyY2VJZDtcbiAgICAgICAgICAgICAgICBjYWxsYmFjayhzb3VyY2VJZCA9PSAnUGVybWlzc2lvbkRlbmllZEVycm9yJyA/IHNvdXJjZUlkIDogbnVsbCwgc2NyZWVuX2NvbnN0cmFpbnRzKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyB0aGlzIHN0YXRlbWVudCBzZXRzIGdldHMgJ3NvdXJjZUlkXCIgYW5kIHNldHMgXCJjaHJvbWVNZWRpYVNvdXJjZUlkXCIgXG4gICAgaWYgKGNocm9tZU1lZGlhU291cmNlID09ICdkZXNrdG9wJykge1xuICAgICAgICBzY3JlZW5fY29uc3RyYWludHMubWFuZGF0b3J5LmNocm9tZU1lZGlhU291cmNlSWQgPSBzb3VyY2VJZDtcbiAgICB9XG5cbiAgICAvLyBub3cgaW52b2tpbmcgbmF0aXZlIGdldFVzZXJNZWRpYSBBUElcbiAgICBjYWxsYmFjayhudWxsLCBzY3JlZW5fY29uc3RyYWludHMpO1xufVxuXG5leHBvcnRzLmdldFNjcmVlbkNvbnN0cmFpbnRzID0gZ2V0U2NyZWVuQ29uc3RyYWludHM7XG5leHBvcnRzLmdldFNjcmVlbkNvbnN0cmFpbnRzV2l0aEF1ZGlvID0gZ2V0U2NyZWVuQ29uc3RyYWludHNXaXRoQXVkaW87XG5leHBvcnRzLmlzQ2hyb21lRXh0ZW5zaW9uQXZhaWxhYmxlID0gaXNDaHJvbWVFeHRlbnNpb25BdmFpbGFibGU7XG5leHBvcnRzLmdldENocm9tZUV4dGVuc2lvblN0YXR1cyA9IGdldENocm9tZUV4dGVuc2lvblN0YXR1cztcbmV4cG9ydHMuZ2V0U291cmNlSWQgPSBnZXRTb3VyY2VJZDsiLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCBmcmVlaWNlID0gcmVxdWlyZSgnZnJlZWljZScpO1xuaW1wb3J0IHV1aWQgPSByZXF1aXJlKCd1dWlkJyk7XG5pbXBvcnQgcGxhdGZvcm0gPSByZXF1aXJlKCdwbGF0Zm9ybScpO1xuXG5cbmV4cG9ydCBpbnRlcmZhY2UgV2ViUnRjUGVlckNvbmZpZ3VyYXRpb24ge1xuICAgIG1lZGlhQ29uc3RyYWludHM6IHtcbiAgICAgICAgYXVkaW86IGJvb2xlYW4sXG4gICAgICAgIHZpZGVvOiBib29sZWFuXG4gICAgfTtcbiAgICBzaW11bGNhc3Q6IGJvb2xlYW47XG4gICAgb25pY2VjYW5kaWRhdGU6IChldmVudCkgPT4gdm9pZDtcbiAgICBpY2VTZXJ2ZXJzOiBSVENJY2VTZXJ2ZXJbXSB8IHVuZGVmaW5lZDtcbiAgICBtZWRpYVN0cmVhbT86IE1lZGlhU3RyZWFtO1xuICAgIG1vZGU/OiBzdHJpbmc7IC8vIHNlbmRvbmx5LCByZWNvbmx5LCBzZW5kcmVjdlxuICAgIGlkPzogc3RyaW5nO1xufVxuXG5leHBvcnQgY2xhc3MgV2ViUnRjUGVlciB7XG5cbiAgICBwYzogUlRDUGVlckNvbm5lY3Rpb247XG4gICAgaWQ6IHN0cmluZztcbiAgICByZW1vdGVDYW5kaWRhdGVzUXVldWU6IFJUQ0ljZUNhbmRpZGF0ZVtdID0gW107XG4gICAgbG9jYWxDYW5kaWRhdGVzUXVldWU6IFJUQ0ljZUNhbmRpZGF0ZVtdID0gW107XG5cbiAgICBpY2VDYW5kaWRhdGVMaXN0OiBSVENJY2VDYW5kaWRhdGVbXSA9IFtdO1xuXG4gICAgcHJpdmF0ZSBjYW5kaWRhdGVnYXRoZXJpbmdkb25lID0gZmFsc2U7XG5cbiAgICBjb25zdHJ1Y3Rvcihwcml2YXRlIGNvbmZpZ3VyYXRpb246IFdlYlJ0Y1BlZXJDb25maWd1cmF0aW9uKSB7XG4gICAgICAgIHRoaXMuY29uZmlndXJhdGlvbi5pY2VTZXJ2ZXJzID0gKCEhdGhpcy5jb25maWd1cmF0aW9uLmljZVNlcnZlcnMgJiYgdGhpcy5jb25maWd1cmF0aW9uLmljZVNlcnZlcnMubGVuZ3RoID4gMCkgPyB0aGlzLmNvbmZpZ3VyYXRpb24uaWNlU2VydmVycyA6IGZyZWVpY2UoKTtcblxuICAgICAgICB0aGlzLnBjID0gbmV3IFJUQ1BlZXJDb25uZWN0aW9uKHsgaWNlU2VydmVyczogdGhpcy5jb25maWd1cmF0aW9uLmljZVNlcnZlcnMgfSk7XG4gICAgICAgIHRoaXMuaWQgPSAhIWNvbmZpZ3VyYXRpb24uaWQgPyBjb25maWd1cmF0aW9uLmlkIDogdXVpZC52NCgpO1xuXG4gICAgICAgIHRoaXMucGMub25pY2VjYW5kaWRhdGUgPSBldmVudCA9PiB7XG4gICAgICAgICAgICBjb25zdCBjYW5kaWRhdGU6IFJUQ0ljZUNhbmRpZGF0ZSA9IGV2ZW50LmNhbmRpZGF0ZTtcbiAgICAgICAgICAgIGlmIChjYW5kaWRhdGUpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmxvY2FsQ2FuZGlkYXRlc1F1ZXVlLnB1c2goPFJUQ0ljZUNhbmRpZGF0ZT57IGNhbmRpZGF0ZTogY2FuZGlkYXRlLmNhbmRpZGF0ZSB9KTtcbiAgICAgICAgICAgICAgICB0aGlzLmNhbmRpZGF0ZWdhdGhlcmluZ2RvbmUgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB0aGlzLmNvbmZpZ3VyYXRpb24ub25pY2VjYW5kaWRhdGUoZXZlbnQuY2FuZGlkYXRlKTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoIXRoaXMuY2FuZGlkYXRlZ2F0aGVyaW5nZG9uZSkge1xuICAgICAgICAgICAgICAgIHRoaXMuY2FuZGlkYXRlZ2F0aGVyaW5nZG9uZSA9IHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG5cbiAgICAgICAgdGhpcy5wYy5vbnNpZ25hbGluZ3N0YXRlY2hhbmdlID0gKCkgPT4ge1xuICAgICAgICAgICAgaWYgKHRoaXMucGMuc2lnbmFsaW5nU3RhdGUgPT09ICdzdGFibGUnKSB7XG4gICAgICAgICAgICAgICAgd2hpbGUgKHRoaXMuaWNlQ2FuZGlkYXRlTGlzdC5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMucGMuYWRkSWNlQ2FuZGlkYXRlKDxSVENJY2VDYW5kaWRhdGU+dGhpcy5pY2VDYW5kaWRhdGVMaXN0LnNoaWZ0KCkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcblxuICAgICAgICB0aGlzLnN0YXJ0KCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhpcyBmdW5jdGlvbiBjcmVhdGVzIHRoZSBSVENQZWVyQ29ubmVjdGlvbiBvYmplY3QgdGFraW5nIGludG8gYWNjb3VudCB0aGVcbiAgICAgKiBwcm9wZXJ0aWVzIHJlY2VpdmVkIGluIHRoZSBjb25zdHJ1Y3Rvci4gSXQgc3RhcnRzIHRoZSBTRFAgbmVnb3RpYXRpb25cbiAgICAgKiBwcm9jZXNzOiBnZW5lcmF0ZXMgdGhlIFNEUCBvZmZlciBhbmQgaW52b2tlcyB0aGUgb25zZHBvZmZlciBjYWxsYmFjay4gVGhpc1xuICAgICAqIGNhbGxiYWNrIGlzIGV4cGVjdGVkIHRvIHNlbmQgdGhlIFNEUCBvZmZlciwgaW4gb3JkZXIgdG8gb2J0YWluIGFuIFNEUFxuICAgICAqIGFuc3dlciBmcm9tIGFub3RoZXIgcGVlci5cbiAgICAgKi9cbiAgICBzdGFydCgpOiBQcm9taXNlPGFueT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgaWYgKHRoaXMucGMuc2lnbmFsaW5nU3RhdGUgPT09ICdjbG9zZWQnKSB7XG4gICAgICAgICAgICAgICAgcmVqZWN0KCdUaGUgcGVlciBjb25uZWN0aW9uIG9iamVjdCBpcyBpbiBcImNsb3NlZFwiIHN0YXRlLiBUaGlzIGlzIG1vc3QgbGlrZWx5IGR1ZSB0byBhbiBpbnZvY2F0aW9uIG9mIHRoZSBkaXNwb3NlIG1ldGhvZCBiZWZvcmUgYWNjZXB0aW5nIGluIHRoZSBkaWFsb2d1ZScpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCEhdGhpcy5jb25maWd1cmF0aW9uLm1lZGlhU3RyZWFtKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5wYy5hZGRTdHJlYW0odGhpcy5jb25maWd1cmF0aW9uLm1lZGlhU3RyZWFtKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gW0hhY2tdIGh0dHBzOi8vY29kZS5nb29nbGUuY29tL3AvY2hyb21pdW0vaXNzdWVzL2RldGFpbD9pZD00NDM1NThcbiAgICAgICAgICAgIGlmICh0aGlzLmNvbmZpZ3VyYXRpb24ubW9kZSA9PT0gJ3NlbmRvbmx5JyAmJlxuICAgICAgICAgICAgICAgIChwbGF0Zm9ybS5uYW1lID09PSAnQ2hyb21lJyAmJiBwbGF0Zm9ybS52ZXJzaW9uIS50b1N0cmluZygpLnN1YnN0cmluZygwLCAyKSA9PT0gJzM5JykpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmNvbmZpZ3VyYXRpb24ubW9kZSA9ICdzZW5kcmVjdic7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhpcyBtZXRob2QgZnJlZXMgdGhlIHJlc291cmNlcyB1c2VkIGJ5IFdlYlJ0Y1BlZXJcbiAgICAgKi9cbiAgICBkaXNwb3NlKCkge1xuICAgICAgICBjb25zb2xlLmRlYnVnKCdEaXNwb3NpbmcgV2ViUnRjUGVlcicpO1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgaWYgKHRoaXMucGMpIHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5wYy5zaWduYWxpbmdTdGF0ZSA9PT0gJ2Nsb3NlZCcpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLnJlbW90ZUNhbmRpZGF0ZXNRdWV1ZSA9IFtdO1xuICAgICAgICAgICAgICAgIHRoaXMubG9jYWxDYW5kaWRhdGVzUXVldWUgPSBbXTtcblxuICAgICAgICAgICAgICAgIHRoaXMucGMuZ2V0TG9jYWxTdHJlYW1zKCkuZm9yRWFjaChzdHIgPT4ge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbVN0b3Aoc3RyKTtcbiAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAgIC8vIEZJWE1FIFRoaXMgaXMgbm90IHlldCBpbXBsZW1lbnRlZCBpbiBmaXJlZm94XG4gICAgICAgICAgICAgICAgLy8gaWYodmlkZW9TdHJlYW0pIHBjLnJlbW92ZVN0cmVhbSh2aWRlb1N0cmVhbSk7XG4gICAgICAgICAgICAgICAgLy8gaWYoYXVkaW9TdHJlYW0pIHBjLnJlbW92ZVN0cmVhbShhdWRpb1N0cmVhbSk7XG5cbiAgICAgICAgICAgICAgICB0aGlzLnBjLmNsb3NlKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgY29uc29sZS53YXJuKCdFeGNlcHRpb24gZGlzcG9zaW5nIHdlYnJ0YyBwZWVyICcgKyBlcnIpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogMSkgRnVuY3Rpb24gdGhhdCBjcmVhdGVzIGFuIG9mZmVyLCBzZXRzIGl0IGFzIGxvY2FsIGRlc2NyaXB0aW9uIGFuZCByZXR1cm5zIHRoZSBvZmZlciBwYXJhbVxuICAgICAqIHRvIHNlbmQgdG8gT3BlblZpZHUgU2VydmVyICh3aWxsIGJlIHRoZSByZW1vdGUgZGVzY3JpcHRpb24gb2Ygb3RoZXIgcGVlcilcbiAgICAgKi9cbiAgICBnZW5lcmF0ZU9mZmVyKCk6IFByb21pc2U8c3RyaW5nPiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICBsZXQgb2ZmZXJBdWRpbywgb2ZmZXJWaWRlbyA9IHRydWU7XG5cbiAgICAgICAgICAgIC8vIENvbnN0cmFpbnRzIG11c3QgaGF2ZSBib3RoIGJsb2Nrc1xuICAgICAgICAgICAgaWYgKCEhdGhpcy5jb25maWd1cmF0aW9uLm1lZGlhQ29uc3RyYWludHMpIHtcbiAgICAgICAgICAgICAgICBvZmZlckF1ZGlvID0gKHR5cGVvZiB0aGlzLmNvbmZpZ3VyYXRpb24ubWVkaWFDb25zdHJhaW50cy5hdWRpbyA9PT0gJ2Jvb2xlYW4nKSA/XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuY29uZmlndXJhdGlvbi5tZWRpYUNvbnN0cmFpbnRzLmF1ZGlvIDogdHJ1ZTtcbiAgICAgICAgICAgICAgICBvZmZlclZpZGVvID0gKHR5cGVvZiB0aGlzLmNvbmZpZ3VyYXRpb24ubWVkaWFDb25zdHJhaW50cy52aWRlbyA9PT0gJ2Jvb2xlYW4nKSA/XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuY29uZmlndXJhdGlvbi5tZWRpYUNvbnN0cmFpbnRzLnZpZGVvIDogdHJ1ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgY29uc3QgY29uc3RyYWludHM6IFJUQ09mZmVyT3B0aW9ucyA9IHtcbiAgICAgICAgICAgICAgICBvZmZlclRvUmVjZWl2ZUF1ZGlvOiArICh0aGlzLmNvbmZpZ3VyYXRpb24ubW9kZSAhPT0gJ3NlbmRvbmx5JyAmJiBvZmZlckF1ZGlvKSxcbiAgICAgICAgICAgICAgICBvZmZlclRvUmVjZWl2ZVZpZGVvOiArICh0aGlzLmNvbmZpZ3VyYXRpb24ubW9kZSAhPT0gJ3NlbmRvbmx5JyAmJiBvZmZlclZpZGVvKVxuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgY29uc29sZS5kZWJ1ZygnUlRDUGVlckNvbm5lY3Rpb24gY29uc3RyYWludHM6ICcgKyBKU09OLnN0cmluZ2lmeShjb25zdHJhaW50cykpO1xuXG4gICAgICAgICAgICB0aGlzLnBjLmNyZWF0ZU9mZmVyKGNvbnN0cmFpbnRzKS50aGVuKG9mZmVyID0+IHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmRlYnVnKCdDcmVhdGVkIFNEUCBvZmZlcicpO1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLnBjLnNldExvY2FsRGVzY3JpcHRpb24ob2ZmZXIpO1xuICAgICAgICAgICAgfSkudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3QgbG9jYWxEZXNjcmlwdGlvbiA9IHRoaXMucGMubG9jYWxEZXNjcmlwdGlvbjtcbiAgICAgICAgICAgICAgICBpZiAoISFsb2NhbERlc2NyaXB0aW9uKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZGVidWcoJ0xvY2FsIGRlc2NyaXB0aW9uIHNldCcsIGxvY2FsRGVzY3JpcHRpb24uc2RwKTtcbiAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSg8c3RyaW5nPmxvY2FsRGVzY3JpcHRpb24uc2RwKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICByZWplY3QoJ0xvY2FsIGRlc2NyaXB0aW9uIGlzIG5vdCBkZWZpbmVkJyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSkuY2F0Y2goZXJyb3IgPT4gcmVqZWN0KGVycm9yKSk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIDIpIEZ1bmN0aW9uIHRvIGludm9rZSB3aGVuIGEgU0RQIG9mZmVyIGlzIHJlY2VpdmVkLiBTZXRzIGl0IGFzIHJlbW90ZSBkZXNjcmlwdGlvbixcbiAgICAgKiBnZW5lcmF0ZXMgYW5kIGFuc3dlciBhbmQgcmV0dXJucyBpdCB0byBzZW5kIGl0IHRvIE9wZW5WaWR1IFNlcnZlclxuICAgICAqL1xuICAgIHByb2Nlc3NPZmZlcihzZHBPZmZlcjogc3RyaW5nKTogUHJvbWlzZTxDb25zdHJhaW5ET01TdHJpbmc+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IG9mZmVyOiBSVENTZXNzaW9uRGVzY3JpcHRpb25Jbml0ID0ge1xuICAgICAgICAgICAgICAgIHR5cGU6ICdvZmZlcicsXG4gICAgICAgICAgICAgICAgc2RwOiBzZHBPZmZlclxuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgY29uc29sZS5kZWJ1ZygnU0RQIG9mZmVyIHJlY2VpdmVkLCBzZXR0aW5nIHJlbW90ZSBkZXNjcmlwdGlvbicpO1xuXG4gICAgICAgICAgICBpZiAodGhpcy5wYy5zaWduYWxpbmdTdGF0ZSA9PT0gJ2Nsb3NlZCcpIHtcbiAgICAgICAgICAgICAgICByZWplY3QoJ1BlZXJDb25uZWN0aW9uIGlzIGNsb3NlZCcpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLnBjLnNldFJlbW90ZURlc2NyaXB0aW9uKG9mZmVyKVxuICAgICAgICAgICAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMucGMuY3JlYXRlQW5zd2VyKCk7XG4gICAgICAgICAgICAgICAgfSkudGhlbihhbnN3ZXIgPT4ge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmRlYnVnKCdDcmVhdGVkIFNEUCBhbnN3ZXInKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMucGMuc2V0TG9jYWxEZXNjcmlwdGlvbihhbnN3ZXIpO1xuICAgICAgICAgICAgICAgIH0pLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBsb2NhbERlc2NyaXB0aW9uID0gdGhpcy5wYy5sb2NhbERlc2NyaXB0aW9uO1xuICAgICAgICAgICAgICAgICAgICBpZiAoISFsb2NhbERlc2NyaXB0aW9uKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmRlYnVnKCdMb2NhbCBkZXNjcmlwdGlvbiBzZXQnLCBsb2NhbERlc2NyaXB0aW9uLnNkcCk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXNvbHZlKDxzdHJpbmc+bG9jYWxEZXNjcmlwdGlvbi5zZHApO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KCdMb2NhbCBkZXNjcmlwdGlvbiBpcyBub3QgZGVmaW5lZCcpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSkuY2F0Y2goZXJyb3IgPT4gcmVqZWN0KGVycm9yKSk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIDMpIEZ1bmN0aW9uIGludm9rZWQgd2hlbiBhIFNEUCBhbnN3ZXIgaXMgcmVjZWl2ZWQuIEZpbmFsIHN0ZXAgaW4gU0RQIG5lZ290aWF0aW9uLCB0aGUgcGVlclxuICAgICAqIGp1c3QgbmVlZHMgdG8gc2V0IHRoZSBhbnN3ZXIgYXMgaXRzIHJlbW90ZSBkZXNjcmlwdGlvblxuICAgICAqL1xuICAgIHByb2Nlc3NBbnN3ZXIoc2RwQW5zd2VyOiBzdHJpbmcpOiBQcm9taXNlPHN0cmluZz4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuXG4gICAgICAgICAgICBjb25zdCBhbnN3ZXI6IFJUQ1Nlc3Npb25EZXNjcmlwdGlvbkluaXQgPSB7XG4gICAgICAgICAgICAgICAgdHlwZTogJ2Fuc3dlcicsXG4gICAgICAgICAgICAgICAgc2RwOiBzZHBBbnN3ZXJcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIGNvbnNvbGUuZGVidWcoJ1NEUCBhbnN3ZXIgcmVjZWl2ZWQsIHNldHRpbmcgcmVtb3RlIGRlc2NyaXB0aW9uJyk7XG5cbiAgICAgICAgICAgIGlmICh0aGlzLnBjLnNpZ25hbGluZ1N0YXRlID09PSAnY2xvc2VkJykge1xuICAgICAgICAgICAgICAgIHJlamVjdCgnUlRDUGVlckNvbm5lY3Rpb24gaXMgY2xvc2VkJyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMucGMuc2V0UmVtb3RlRGVzY3JpcHRpb24oYW5zd2VyKS50aGVuKCgpID0+IHJlc29sdmUoKSkuY2F0Y2goZXJyb3IgPT4gcmVqZWN0KGVycm9yKSk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENhbGxiYWNrIGZ1bmN0aW9uIGludm9rZWQgd2hlbiBhbiBJQ0UgY2FuZGlkYXRlIGlzIHJlY2VpdmVkXG4gICAgICovXG4gICAgYWRkSWNlQ2FuZGlkYXRlKGljZUNhbmRpZGF0ZTogUlRDSWNlQ2FuZGlkYXRlKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICBjb25zb2xlLmRlYnVnKCdSZW1vdGUgSUNFIGNhbmRpZGF0ZSByZWNlaXZlZCcsIGljZUNhbmRpZGF0ZSk7XG4gICAgICAgICAgICB0aGlzLnJlbW90ZUNhbmRpZGF0ZXNRdWV1ZS5wdXNoKGljZUNhbmRpZGF0ZSk7XG4gICAgICAgICAgICBzd2l0Y2ggKHRoaXMucGMuc2lnbmFsaW5nU3RhdGUpIHtcbiAgICAgICAgICAgICAgICBjYXNlICdjbG9zZWQnOlxuICAgICAgICAgICAgICAgICAgICByZWplY3QobmV3IEVycm9yKCdQZWVyQ29ubmVjdGlvbiBvYmplY3QgaXMgY2xvc2VkJykpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlICdzdGFibGUnOlxuICAgICAgICAgICAgICAgICAgICBpZiAoISF0aGlzLnBjLnJlbW90ZURlc2NyaXB0aW9uKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnBjLmFkZEljZUNhbmRpZGF0ZShpY2VDYW5kaWRhdGUpLnRoZW4oKCkgPT4gcmVzb2x2ZSgpKS5jYXRjaChlcnJvciA9PiByZWplY3QoZXJyb3IpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICB0aGlzLmljZUNhbmRpZGF0ZUxpc3QucHVzaChpY2VDYW5kaWRhdGUpO1xuICAgICAgICAgICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIHByaXZhdGUgc3RyZWFtU3RvcChzdHJlYW06IE1lZGlhU3RyZWFtKTogdm9pZCB7XG4gICAgICAgIHN0cmVhbS5nZXRUcmFja3MoKS5mb3JFYWNoKHRyYWNrID0+IHtcbiAgICAgICAgICAgIHRyYWNrLnN0b3AoKTtcbiAgICAgICAgICAgIHN0cmVhbS5yZW1vdmVUcmFjayh0cmFjayk7XG4gICAgICAgIH0pO1xuICAgIH1cbn1cblxuXG5leHBvcnQgY2xhc3MgV2ViUnRjUGVlclJlY3Zvbmx5IGV4dGVuZHMgV2ViUnRjUGVlciB7XG4gICAgY29uc3RydWN0b3IoY29uZmlndXJhdGlvbjogV2ViUnRjUGVlckNvbmZpZ3VyYXRpb24pIHtcbiAgICAgICAgY29uZmlndXJhdGlvbi5tb2RlID0gJ3JlY3Zvbmx5JztcbiAgICAgICAgc3VwZXIoY29uZmlndXJhdGlvbik7XG4gICAgfVxufVxuXG5leHBvcnQgY2xhc3MgV2ViUnRjUGVlclNlbmRvbmx5IGV4dGVuZHMgV2ViUnRjUGVlciB7XG4gICAgY29uc3RydWN0b3IoY29uZmlndXJhdGlvbjogV2ViUnRjUGVlckNvbmZpZ3VyYXRpb24pIHtcbiAgICAgICAgY29uZmlndXJhdGlvbi5tb2RlID0gJ3NlbmRvbmx5JztcbiAgICAgICAgc3VwZXIoY29uZmlndXJhdGlvbik7XG4gICAgfVxufVxuXG5leHBvcnQgY2xhc3MgV2ViUnRjUGVlclNlbmRyZWN2IGV4dGVuZHMgV2ViUnRjUGVlciB7XG4gICAgY29uc3RydWN0b3IoY29uZmlndXJhdGlvbjogV2ViUnRjUGVlckNvbmZpZ3VyYXRpb24pIHtcbiAgICAgICAgY29uZmlndXJhdGlvbi5tb2RlID0gJ3NlbmRyZWN2JztcbiAgICAgICAgc3VwZXIoY29uZmlndXJhdGlvbik7XG4gICAgfVxufSIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTctMjAxOCBPcGVuVmlkdSAoaHR0cHM6Ly9vcGVudmlkdS5pby8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuLy8gdHNsaW50OmRpc2FibGU6bm8tc3RyaW5nLWxpdGVyYWxcblxuaW1wb3J0IHsgU3RyZWFtIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvU3RyZWFtJztcbmltcG9ydCBwbGF0Zm9ybSA9IHJlcXVpcmUoJ3BsYXRmb3JtJyk7XG5cbmV4cG9ydCBjbGFzcyBXZWJSdGNTdGF0cyB7XG5cbiAgICBwcml2YXRlIHdlYlJ0Y1N0YXRzRW5hYmxlZCA9IGZhbHNlO1xuICAgIHByaXZhdGUgd2ViUnRjU3RhdHNJbnRlcnZhbElkOiBOb2RlSlMuVGltZXI7XG4gICAgcHJpdmF0ZSBzdGF0c0ludGVydmFsID0gMTtcbiAgICBwcml2YXRlIHN0YXRzOiBhbnkgPSB7XG4gICAgICAgIGluYm91bmQ6IHtcbiAgICAgICAgICAgIGF1ZGlvOiB7XG4gICAgICAgICAgICAgICAgYnl0ZXNSZWNlaXZlZDogMCxcbiAgICAgICAgICAgICAgICBwYWNrZXRzUmVjZWl2ZWQ6IDAsXG4gICAgICAgICAgICAgICAgcGFja2V0c0xvc3Q6IDBcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB2aWRlbzoge1xuICAgICAgICAgICAgICAgIGJ5dGVzUmVjZWl2ZWQ6IDAsXG4gICAgICAgICAgICAgICAgcGFja2V0c1JlY2VpdmVkOiAwLFxuICAgICAgICAgICAgICAgIHBhY2tldHNMb3N0OiAwLFxuICAgICAgICAgICAgICAgIGZyYW1lc0RlY29kZWQ6IDAsXG4gICAgICAgICAgICAgICAgbmFja0NvdW50OiAwXG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIG91dGJvdW5kOiB7XG4gICAgICAgICAgICBhdWRpbzoge1xuICAgICAgICAgICAgICAgIGJ5dGVzU2VudDogMCxcbiAgICAgICAgICAgICAgICBwYWNrZXRzU2VudDogMCxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB2aWRlbzoge1xuICAgICAgICAgICAgICAgIGJ5dGVzU2VudDogMCxcbiAgICAgICAgICAgICAgICBwYWNrZXRzU2VudDogMCxcbiAgICAgICAgICAgICAgICBmcmFtZXNFbmNvZGVkOiAwLFxuICAgICAgICAgICAgICAgIG5hY2tDb3VudDogMFxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfTtcblxuICAgIGNvbnN0cnVjdG9yKHByaXZhdGUgc3RyZWFtOiBTdHJlYW0pIHsgfVxuXG4gICAgcHVibGljIGlzRW5hYmxlZCgpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuIHRoaXMud2ViUnRjU3RhdHNFbmFibGVkO1xuICAgIH1cblxuICAgIHB1YmxpYyBpbml0V2ViUnRjU3RhdHMoKTogdm9pZCB7XG5cbiAgICAgICAgY29uc3QgZWxhc3Rlc3RJbnN0cnVtZW50YXRpb24gPSBsb2NhbFN0b3JhZ2UuZ2V0SXRlbSgnZWxhc3Rlc3QtaW5zdHJ1bWVudGF0aW9uJyk7XG5cbiAgICAgICAgaWYgKGVsYXN0ZXN0SW5zdHJ1bWVudGF0aW9uKSB7XG4gICAgICAgICAgICAvLyBFbGFzVGVzdCBpbnN0cnVtZW50YXRpb24gb2JqZWN0IGZvdW5kIGluIGxvY2FsIHN0b3JhZ2VcblxuICAgICAgICAgICAgY29uc29sZS53YXJuKCdXZWJSdGMgc3RhdHMgZW5hYmxlZCBmb3Igc3RyZWFtICcgKyB0aGlzLnN0cmVhbS5zdHJlYW1JZCArICcgb2YgY29ubmVjdGlvbiAnICsgdGhpcy5zdHJlYW0uY29ubmVjdGlvbi5jb25uZWN0aW9uSWQpO1xuXG4gICAgICAgICAgICB0aGlzLndlYlJ0Y1N0YXRzRW5hYmxlZCA9IHRydWU7XG5cbiAgICAgICAgICAgIGNvbnN0IGluc3RydW1lbnRhdGlvbiA9IEpTT04ucGFyc2UoZWxhc3Rlc3RJbnN0cnVtZW50YXRpb24pO1xuICAgICAgICAgICAgdGhpcy5zdGF0c0ludGVydmFsID0gaW5zdHJ1bWVudGF0aW9uLndlYnJ0Yy5pbnRlcnZhbDsgIC8vIEludGVydmFsIGluIHNlY29uZHNcblxuICAgICAgICAgICAgY29uc29sZS53YXJuKCdsb2NhbFN0b3JhZ2UgaXRlbTogJyArIEpTT04uc3RyaW5naWZ5KGluc3RydW1lbnRhdGlvbikpO1xuXG4gICAgICAgICAgICB0aGlzLndlYlJ0Y1N0YXRzSW50ZXJ2YWxJZCA9IHNldEludGVydmFsKCgpID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLnNlbmRTdGF0c1RvSHR0cEVuZHBvaW50KGluc3RydW1lbnRhdGlvbik7XG4gICAgICAgICAgICB9LCB0aGlzLnN0YXRzSW50ZXJ2YWwgKiAxMDAwKTtcblxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc29sZS5kZWJ1ZygnV2ViUnRjIHN0YXRzIG5vdCBlbmFibGVkJyk7XG4gICAgfVxuXG4gICAgcHVibGljIHN0b3BXZWJSdGNTdGF0cygpIHtcbiAgICAgICAgaWYgKHRoaXMud2ViUnRjU3RhdHNFbmFibGVkKSB7XG4gICAgICAgICAgICBjbGVhckludGVydmFsKHRoaXMud2ViUnRjU3RhdHNJbnRlcnZhbElkKTtcbiAgICAgICAgICAgIGNvbnNvbGUud2FybignV2ViUnRjIHN0YXRzIHN0b3BwZWQgZm9yIGRpc3Bvc2VkIHN0cmVhbSAnICsgdGhpcy5zdHJlYW0uc3RyZWFtSWQgKyAnIG9mIGNvbm5lY3Rpb24gJyArIHRoaXMuc3RyZWFtLmNvbm5lY3Rpb24uY29ubmVjdGlvbklkKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHB1YmxpYyBnZXRTZWxlY3RlZEljZUNhbmRpZGF0ZUluZm8oKTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIHRoaXMuZ2V0U3RhdHNBZ25vc3RpYyh0aGlzLnN0cmVhbS5nZXRSVENQZWVyQ29ubmVjdGlvbigpLFxuICAgICAgICAgICAgICAgIChzdGF0cykgPT4ge1xuICAgICAgICAgICAgICAgICAgICBpZiAoKHBsYXRmb3JtLm5hbWUhLmluZGV4T2YoJ0Nocm9tZScpICE9PSAtMSkgfHwgKHBsYXRmb3JtLm5hbWUhLmluZGV4T2YoJ09wZXJhJykgIT09IC0xKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGxvY2FsQ2FuZGlkYXRlSWQsIHJlbW90ZUNhbmRpZGF0ZUlkLCBnb29nQ2FuZGlkYXRlUGFpcjtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGxvY2FsQ2FuZGlkYXRlcyA9IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgcmVtb3RlQ2FuZGlkYXRlcyA9IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChjb25zdCBrZXkgaW4gc3RhdHMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBzdGF0ID0gc3RhdHNba2V5XTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoc3RhdC50eXBlID09PSAnbG9jYWxjYW5kaWRhdGUnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxvY2FsQ2FuZGlkYXRlc1tzdGF0LmlkXSA9IHN0YXQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChzdGF0LnR5cGUgPT09ICdyZW1vdGVjYW5kaWRhdGUnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlbW90ZUNhbmRpZGF0ZXNbc3RhdC5pZF0gPSBzdGF0O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoc3RhdC50eXBlID09PSAnZ29vZ0NhbmRpZGF0ZVBhaXInICYmIChzdGF0Lmdvb2dBY3RpdmVDb25uZWN0aW9uID09PSAndHJ1ZScpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdvb2dDYW5kaWRhdGVQYWlyID0gc3RhdDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbG9jYWxDYW5kaWRhdGVJZCA9IHN0YXQubG9jYWxDYW5kaWRhdGVJZDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3RlQ2FuZGlkYXRlSWQgPSBzdGF0LnJlbW90ZUNhbmRpZGF0ZUlkO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBmaW5hbExvY2FsQ2FuZGlkYXRlID0gbG9jYWxDYW5kaWRhdGVzW2xvY2FsQ2FuZGlkYXRlSWRdO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCEhZmluYWxMb2NhbENhbmRpZGF0ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGNhbmRMaXN0ID0gdGhpcy5zdHJlYW0uZ2V0TG9jYWxJY2VDYW5kaWRhdGVMaXN0KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgY2FuZCA9IGNhbmRMaXN0LmZpbHRlcigoYzogUlRDSWNlQ2FuZGlkYXRlKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAoISFjLmNhbmRpZGF0ZSAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5jYW5kaWRhdGUuaW5kZXhPZihmaW5hbExvY2FsQ2FuZGlkYXRlLmlwQWRkcmVzcykgPj0gMCAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5jYW5kaWRhdGUuaW5kZXhPZihmaW5hbExvY2FsQ2FuZGlkYXRlLnBvcnROdW1iZXIpID49IDAgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuY2FuZGlkYXRlLmluZGV4T2YoZmluYWxMb2NhbENhbmRpZGF0ZS5wcmlvcml0eSkgPj0gMCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZmluYWxMb2NhbENhbmRpZGF0ZS5yYXcgPSAhIWNhbmRbMF0gPyBjYW5kWzBdLmNhbmRpZGF0ZSA6ICdFUlJPUjogQ2Fubm90IGZpbmQgbG9jYWwgY2FuZGlkYXRlIGluIGxpc3Qgb2Ygc2VudCBJQ0UgY2FuZGlkYXRlcyc7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbmFsTG9jYWxDYW5kaWRhdGUgPSAnRVJST1I6IE5vIGFjdGl2ZSBsb2NhbCBJQ0UgY2FuZGlkYXRlLiBQcm9iYWJseSBJQ0UtVENQIGlzIGJlaW5nIHVzZWQnO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICBsZXQgZmluYWxSZW1vdGVDYW5kaWRhdGUgPSByZW1vdGVDYW5kaWRhdGVzW3JlbW90ZUNhbmRpZGF0ZUlkXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghIWZpbmFsUmVtb3RlQ2FuZGlkYXRlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgY2FuZExpc3QgPSB0aGlzLnN0cmVhbS5nZXRSZW1vdGVJY2VDYW5kaWRhdGVMaXN0KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgY2FuZCA9IGNhbmRMaXN0LmZpbHRlcigoYzogUlRDSWNlQ2FuZGlkYXRlKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAoISFjLmNhbmRpZGF0ZSAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5jYW5kaWRhdGUuaW5kZXhPZihmaW5hbFJlbW90ZUNhbmRpZGF0ZS5pcEFkZHJlc3MpID49IDAgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuY2FuZGlkYXRlLmluZGV4T2YoZmluYWxSZW1vdGVDYW5kaWRhdGUucG9ydE51bWJlcikgPj0gMCAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5jYW5kaWRhdGUuaW5kZXhPZihmaW5hbFJlbW90ZUNhbmRpZGF0ZS5wcmlvcml0eSkgPj0gMCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZmluYWxSZW1vdGVDYW5kaWRhdGUucmF3ID0gISFjYW5kWzBdID8gY2FuZFswXS5jYW5kaWRhdGUgOiAnRVJST1I6IENhbm5vdCBmaW5kIHJlbW90ZSBjYW5kaWRhdGUgaW4gbGlzdCBvZiByZWNlaXZlZCBJQ0UgY2FuZGlkYXRlcyc7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbmFsUmVtb3RlQ2FuZGlkYXRlID0gJ0VSUk9SOiBObyBhY3RpdmUgcmVtb3RlIElDRSBjYW5kaWRhdGUuIFByb2JhYmx5IElDRS1UQ1AgaXMgYmVpbmcgdXNlZCc7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdvb2dDYW5kaWRhdGVQYWlyLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxvY2FsQ2FuZGlkYXRlOiBmaW5hbExvY2FsQ2FuZGlkYXRlLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlbW90ZUNhbmRpZGF0ZTogZmluYWxSZW1vdGVDYW5kaWRhdGVcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KCdTZWxlY3RlZCBJQ0UgY2FuZGlkYXRlIGluZm8gb25seSBhdmFpbGFibGUgZm9yIENocm9tZScpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAoZXJyb3IpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBzZW5kU3RhdHNUb0h0dHBFbmRwb2ludChpbnN0cnVtZW50YXRpb24pOiB2b2lkIHtcblxuICAgICAgICBjb25zdCBzZW5kUG9zdCA9IChqc29uKSA9PiB7XG4gICAgICAgICAgICBjb25zdCBodHRwOiBYTUxIdHRwUmVxdWVzdCA9IG5ldyBYTUxIdHRwUmVxdWVzdCgpO1xuICAgICAgICAgICAgY29uc3QgdXJsOiBzdHJpbmcgPSBpbnN0cnVtZW50YXRpb24ud2VicnRjLmh0dHBFbmRwb2ludDtcbiAgICAgICAgICAgIGh0dHAub3BlbignUE9TVCcsIHVybCwgdHJ1ZSk7XG5cbiAgICAgICAgICAgIGh0dHAuc2V0UmVxdWVzdEhlYWRlcignQ29udGVudC10eXBlJywgJ2FwcGxpY2F0aW9uL2pzb24nKTtcblxuICAgICAgICAgICAgaHR0cC5vbnJlYWR5c3RhdGVjaGFuZ2UgPSAoKSA9PiB7IC8vIENhbGwgYSBmdW5jdGlvbiB3aGVuIHRoZSBzdGF0ZSBjaGFuZ2VzLlxuICAgICAgICAgICAgICAgIGlmIChodHRwLnJlYWR5U3RhdGUgPT09IDQgJiYgaHR0cC5zdGF0dXMgPT09IDIwMCkge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmxvZygnV2ViUnRjIHN0YXRzIHN1Y2Nlc3NmdWxseSBzZW50IHRvICcgKyB1cmwgKyAnIGZvciBzdHJlYW0gJyArIHRoaXMuc3RyZWFtLnN0cmVhbUlkICsgJyBvZiBjb25uZWN0aW9uICcgKyB0aGlzLnN0cmVhbS5jb25uZWN0aW9uLmNvbm5lY3Rpb25JZCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGh0dHAuc2VuZChqc29uKTtcbiAgICAgICAgfTtcblxuICAgICAgICBjb25zdCBmID0gKHN0YXRzKSA9PiB7XG5cbiAgICAgICAgICAgIGlmIChwbGF0Zm9ybS5uYW1lIS5pbmRleE9mKCdGaXJlZm94JykgIT09IC0xKSB7XG4gICAgICAgICAgICAgICAgc3RhdHMuZm9yRWFjaCgoc3RhdCkgPT4ge1xuXG4gICAgICAgICAgICAgICAgICAgIGxldCBqc29uID0ge307XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKChzdGF0LnR5cGUgPT09ICdpbmJvdW5kLXJ0cCcpICYmXG4gICAgICAgICAgICAgICAgICAgICAgICAoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gQXZvaWQgZmlyZWZveCBlbXB0eSBvdXRib3VuZC1ydHAgc3RhdGlzdGljc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0YXQubmFja0NvdW50ICE9PSBudWxsICYmXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhdC5pc1JlbW90ZSA9PT0gZmFsc2UgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGF0LmlkLnN0YXJ0c1dpdGgoJ2luYm91bmQnKSAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0YXQucmVtb3RlSWQuc3RhcnRzV2l0aCgnaW5ib3VuZCcpXG4gICAgICAgICAgICAgICAgICAgICAgICApKSB7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG1ldHJpY0lkID0gJ3dlYnJ0Y19pbmJvdW5kXycgKyBzdGF0Lm1lZGlhVHlwZSArICdfJyArIHN0YXQuc3NyYztcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGppdCA9IHN0YXQuaml0dGVyICogMTAwMDtcblxuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgbWV0cmljcyA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBieXRlc1JlY2VpdmVkOiAoc3RhdC5ieXRlc1JlY2VpdmVkIC0gdGhpcy5zdGF0cy5pbmJvdW5kW3N0YXQubWVkaWFUeXBlXS5ieXRlc1JlY2VpdmVkKSAvIHRoaXMuc3RhdHNJbnRlcnZhbCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBqaXR0ZXI6IGppdCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYWNrZXRzUmVjZWl2ZWQ6IChzdGF0LnBhY2tldHNSZWNlaXZlZCAtIHRoaXMuc3RhdHMuaW5ib3VuZFtzdGF0Lm1lZGlhVHlwZV0ucGFja2V0c1JlY2VpdmVkKSAvIHRoaXMuc3RhdHNJbnRlcnZhbCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYWNrZXRzTG9zdDogKHN0YXQucGFja2V0c0xvc3QgLSB0aGlzLnN0YXRzLmluYm91bmRbc3RhdC5tZWRpYVR5cGVdLnBhY2tldHNMb3N0KSAvIHRoaXMuc3RhdHNJbnRlcnZhbFxuICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHVuaXRzID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ5dGVzUmVjZWl2ZWQ6ICdieXRlcycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaml0dGVyOiAnbXMnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhY2tldHNSZWNlaXZlZDogJ3BhY2tldHMnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhY2tldHNMb3N0OiAncGFja2V0cydcbiAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoc3RhdC5tZWRpYVR5cGUgPT09ICd2aWRlbycpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXRyaWNzWydmcmFtZXNEZWNvZGVkJ10gPSAoc3RhdC5mcmFtZXNEZWNvZGVkIC0gdGhpcy5zdGF0cy5pbmJvdW5kLnZpZGVvLmZyYW1lc0RlY29kZWQpIC8gdGhpcy5zdGF0c0ludGVydmFsO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1ldHJpY3NbJ25hY2tDb3VudCddID0gKHN0YXQubmFja0NvdW50IC0gdGhpcy5zdGF0cy5pbmJvdW5kLnZpZGVvLm5hY2tDb3VudCkgLyB0aGlzLnN0YXRzSW50ZXJ2YWw7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdW5pdHNbJ2ZyYW1lc0RlY29kZWQnXSA9ICdmcmFtZXMnO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVuaXRzWyduYWNrQ291bnQnXSA9ICdwYWNrZXRzJztcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdHMuaW5ib3VuZC52aWRlby5mcmFtZXNEZWNvZGVkID0gc3RhdC5mcmFtZXNEZWNvZGVkO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdHMuaW5ib3VuZC52aWRlby5uYWNrQ291bnQgPSBzdGF0Lm5hY2tDb3VudDtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0cy5pbmJvdW5kW3N0YXQubWVkaWFUeXBlXS5ieXRlc1JlY2VpdmVkID0gc3RhdC5ieXRlc1JlY2VpdmVkO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0cy5pbmJvdW5kW3N0YXQubWVkaWFUeXBlXS5wYWNrZXRzUmVjZWl2ZWQgPSBzdGF0LnBhY2tldHNSZWNlaXZlZDtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdHMuaW5ib3VuZFtzdGF0Lm1lZGlhVHlwZV0ucGFja2V0c0xvc3QgPSBzdGF0LnBhY2tldHNMb3N0O1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBqc29uID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICdAdGltZXN0YW1wJzogbmV3IERhdGUoc3RhdC50aW1lc3RhbXApLnRvSVNPU3RyaW5nKCksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJ2V4ZWMnOiBpbnN0cnVtZW50YXRpb24uZXhlYyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAnY29tcG9uZW50JzogaW5zdHJ1bWVudGF0aW9uLmNvbXBvbmVudCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAnc3RyZWFtJzogJ3dlYlJ0YycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJ3R5cGUnOiBtZXRyaWNJZCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAnc3RyZWFtX3R5cGUnOiAnY29tcG9zZWRfbWV0cmljcycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJ3VuaXRzJzogdW5pdHNcbiAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICBqc29uW21ldHJpY0lkXSA9IG1ldHJpY3M7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIHNlbmRQb3N0KEpTT04uc3RyaW5naWZ5KGpzb24pKTtcblxuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKChzdGF0LnR5cGUgPT09ICdvdXRib3VuZC1ydHAnKSAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEF2b2lkIGZpcmVmb3ggZW1wdHkgaW5ib3VuZC1ydHAgc3RhdGlzdGljc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0YXQuaXNSZW1vdGUgPT09IGZhbHNlICYmXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhdC5pZC50b0xvd2VyQ2FzZSgpLmluY2x1ZGVzKCdvdXRib3VuZCcpXG4gICAgICAgICAgICAgICAgICAgICAgICApKSB7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG1ldHJpY0lkID0gJ3dlYnJ0Y19vdXRib3VuZF8nICsgc3RhdC5tZWRpYVR5cGUgKyAnXycgKyBzdGF0LnNzcmM7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG1ldHJpY3MgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnl0ZXNTZW50OiAoc3RhdC5ieXRlc1NlbnQgLSB0aGlzLnN0YXRzLm91dGJvdW5kW3N0YXQubWVkaWFUeXBlXS5ieXRlc1NlbnQpIC8gdGhpcy5zdGF0c0ludGVydmFsLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhY2tldHNTZW50OiAoc3RhdC5wYWNrZXRzU2VudCAtIHRoaXMuc3RhdHMub3V0Ym91bmRbc3RhdC5tZWRpYVR5cGVdLnBhY2tldHNTZW50KSAvIHRoaXMuc3RhdHNJbnRlcnZhbFxuICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHVuaXRzID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ5dGVzU2VudDogJ2J5dGVzJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYWNrZXRzU2VudDogJ3BhY2tldHMnXG4gICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHN0YXQubWVkaWFUeXBlID09PSAndmlkZW8nKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbWV0cmljc1snZnJhbWVzRW5jb2RlZCddID0gKHN0YXQuZnJhbWVzRW5jb2RlZCAtIHRoaXMuc3RhdHMub3V0Ym91bmQudmlkZW8uZnJhbWVzRW5jb2RlZCkgLyB0aGlzLnN0YXRzSW50ZXJ2YWw7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdW5pdHNbJ2ZyYW1lc0VuY29kZWQnXSA9ICdmcmFtZXMnO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0cy5vdXRib3VuZC52aWRlby5mcmFtZXNFbmNvZGVkID0gc3RhdC5mcmFtZXNFbmNvZGVkO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXRzLm91dGJvdW5kW3N0YXQubWVkaWFUeXBlXS5ieXRlc1NlbnQgPSBzdGF0LmJ5dGVzU2VudDtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdHMub3V0Ym91bmRbc3RhdC5tZWRpYVR5cGVdLnBhY2tldHNTZW50ID0gc3RhdC5wYWNrZXRzU2VudDtcblxuICAgICAgICAgICAgICAgICAgICAgICAganNvbiA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAnQHRpbWVzdGFtcCc6IG5ldyBEYXRlKHN0YXQudGltZXN0YW1wKS50b0lTT1N0cmluZygpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICdleGVjJzogaW5zdHJ1bWVudGF0aW9uLmV4ZWMsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJ2NvbXBvbmVudCc6IGluc3RydW1lbnRhdGlvbi5jb21wb25lbnQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJ3N0cmVhbSc6ICd3ZWJSdGMnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICd0eXBlJzogbWV0cmljSWQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJ3N0cmVhbV90eXBlJzogJ2NvbXBvc2VkX21ldHJpY3MnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICd1bml0cyc6IHVuaXRzXG4gICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAganNvblttZXRyaWNJZF0gPSBtZXRyaWNzO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBzZW5kUG9zdChKU09OLnN0cmluZ2lmeShqc29uKSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoKHBsYXRmb3JtLm5hbWUhLmluZGV4T2YoJ0Nocm9tZScpICE9PSAtMSkgfHwgKHBsYXRmb3JtLm5hbWUhLmluZGV4T2YoJ09wZXJhJykgIT09IC0xKSkge1xuICAgICAgICAgICAgICAgIGZvciAoY29uc3Qga2V5IG9mIE9iamVjdC5rZXlzKHN0YXRzKSkge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBzdGF0ID0gc3RhdHNba2V5XTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHN0YXQudHlwZSA9PT0gJ3NzcmMnKSB7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBqc29uID0ge307XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICgnYnl0ZXNSZWNlaXZlZCcgaW4gc3RhdCAmJiAoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKHN0YXQubWVkaWFUeXBlID09PSAnYXVkaW8nICYmICdhdWRpb091dHB1dExldmVsJyBpbiBzdGF0KSB8fFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIChzdGF0Lm1lZGlhVHlwZSA9PT0gJ3ZpZGVvJyAmJiAncXBTdW0nIGluIHN0YXQpXG4gICAgICAgICAgICAgICAgICAgICAgICApKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaW5ib3VuZC1ydHBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBtZXRyaWNJZCA9ICd3ZWJydGNfaW5ib3VuZF8nICsgc3RhdC5tZWRpYVR5cGUgKyAnXycgKyBzdGF0LnNzcmM7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBtZXRyaWNzID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBieXRlc1JlY2VpdmVkOiAoc3RhdC5ieXRlc1JlY2VpdmVkIC0gdGhpcy5zdGF0cy5pbmJvdW5kW3N0YXQubWVkaWFUeXBlXS5ieXRlc1JlY2VpdmVkKSAvIHRoaXMuc3RhdHNJbnRlcnZhbCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaml0dGVyOiBzdGF0Lmdvb2dKaXR0ZXJCdWZmZXJNcyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFja2V0c1JlY2VpdmVkOiAoc3RhdC5wYWNrZXRzUmVjZWl2ZWQgLSB0aGlzLnN0YXRzLmluYm91bmRbc3RhdC5tZWRpYVR5cGVdLnBhY2tldHNSZWNlaXZlZCkgLyB0aGlzLnN0YXRzSW50ZXJ2YWwsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhY2tldHNMb3N0OiAoc3RhdC5wYWNrZXRzTG9zdCAtIHRoaXMuc3RhdHMuaW5ib3VuZFtzdGF0Lm1lZGlhVHlwZV0ucGFja2V0c0xvc3QpIC8gdGhpcy5zdGF0c0ludGVydmFsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB1bml0cyA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnl0ZXNSZWNlaXZlZDogJ2J5dGVzJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaml0dGVyOiAnbXMnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYWNrZXRzUmVjZWl2ZWQ6ICdwYWNrZXRzJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFja2V0c0xvc3Q6ICdwYWNrZXRzJ1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHN0YXQubWVkaWFUeXBlID09PSAndmlkZW8nKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1ldHJpY3NbJ2ZyYW1lc0RlY29kZWQnXSA9IChzdGF0LmZyYW1lc0RlY29kZWQgLSB0aGlzLnN0YXRzLmluYm91bmQudmlkZW8uZnJhbWVzRGVjb2RlZCkgLyB0aGlzLnN0YXRzSW50ZXJ2YWw7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1ldHJpY3NbJ25hY2tDb3VudCddID0gKHN0YXQuZ29vZ05hY2tzU2VudCAtIHRoaXMuc3RhdHMuaW5ib3VuZC52aWRlby5uYWNrQ291bnQpIC8gdGhpcy5zdGF0c0ludGVydmFsO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1bml0c1snZnJhbWVzRGVjb2RlZCddID0gJ2ZyYW1lcyc7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVuaXRzWyduYWNrQ291bnQnXSA9ICdwYWNrZXRzJztcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXRzLmluYm91bmQudmlkZW8uZnJhbWVzRGVjb2RlZCA9IHN0YXQuZnJhbWVzRGVjb2RlZDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0cy5pbmJvdW5kLnZpZGVvLm5hY2tDb3VudCA9IHN0YXQuZ29vZ05hY2tzU2VudDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXRzLmluYm91bmRbc3RhdC5tZWRpYVR5cGVdLmJ5dGVzUmVjZWl2ZWQgPSBzdGF0LmJ5dGVzUmVjZWl2ZWQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0cy5pbmJvdW5kW3N0YXQubWVkaWFUeXBlXS5wYWNrZXRzUmVjZWl2ZWQgPSBzdGF0LnBhY2tldHNSZWNlaXZlZDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXRzLmluYm91bmRbc3RhdC5tZWRpYVR5cGVdLnBhY2tldHNMb3N0ID0gc3RhdC5wYWNrZXRzTG9zdDtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGpzb24gPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdAdGltZXN0YW1wJzogbmV3IERhdGUoc3RhdC50aW1lc3RhbXApLnRvSVNPU3RyaW5nKCksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdleGVjJzogaW5zdHJ1bWVudGF0aW9uLmV4ZWMsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdjb21wb25lbnQnOiBpbnN0cnVtZW50YXRpb24uY29tcG9uZW50LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnc3RyZWFtJzogJ3dlYlJ0YycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICd0eXBlJzogbWV0cmljSWQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdzdHJlYW1fdHlwZSc6ICdjb21wb3NlZF9tZXRyaWNzJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ3VuaXRzJzogdW5pdHNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGpzb25bbWV0cmljSWRdID0gbWV0cmljcztcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbmRQb3N0KEpTT04uc3RyaW5naWZ5KGpzb24pKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoJ2J5dGVzU2VudCcgaW4gc3RhdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIG91dGJvdW5kLXJ0cFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG1ldHJpY0lkID0gJ3dlYnJ0Y19vdXRib3VuZF8nICsgc3RhdC5tZWRpYVR5cGUgKyAnXycgKyBzdGF0LnNzcmM7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBtZXRyaWNzID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBieXRlc1NlbnQ6IChzdGF0LmJ5dGVzU2VudCAtIHRoaXMuc3RhdHMub3V0Ym91bmRbc3RhdC5tZWRpYVR5cGVdLmJ5dGVzU2VudCkgLyB0aGlzLnN0YXRzSW50ZXJ2YWwsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhY2tldHNTZW50OiAoc3RhdC5wYWNrZXRzU2VudCAtIHRoaXMuc3RhdHMub3V0Ym91bmRbc3RhdC5tZWRpYVR5cGVdLnBhY2tldHNTZW50KSAvIHRoaXMuc3RhdHNJbnRlcnZhbFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgdW5pdHMgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ5dGVzU2VudDogJ2J5dGVzJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFja2V0c1NlbnQ6ICdwYWNrZXRzJ1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHN0YXQubWVkaWFUeXBlID09PSAndmlkZW8nKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1ldHJpY3NbJ2ZyYW1lc0VuY29kZWQnXSA9IChzdGF0LmZyYW1lc0VuY29kZWQgLSB0aGlzLnN0YXRzLm91dGJvdW5kLnZpZGVvLmZyYW1lc0VuY29kZWQpIC8gdGhpcy5zdGF0c0ludGVydmFsO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1bml0c1snZnJhbWVzRW5jb2RlZCddID0gJ2ZyYW1lcyc7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0cy5vdXRib3VuZC52aWRlby5mcmFtZXNFbmNvZGVkID0gc3RhdC5mcmFtZXNFbmNvZGVkO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdHMub3V0Ym91bmRbc3RhdC5tZWRpYVR5cGVdLmJ5dGVzU2VudCA9IHN0YXQuYnl0ZXNTZW50O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdHMub3V0Ym91bmRbc3RhdC5tZWRpYVR5cGVdLnBhY2tldHNTZW50ID0gc3RhdC5wYWNrZXRzU2VudDtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGpzb24gPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdAdGltZXN0YW1wJzogbmV3IERhdGUoc3RhdC50aW1lc3RhbXApLnRvSVNPU3RyaW5nKCksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdleGVjJzogaW5zdHJ1bWVudGF0aW9uLmV4ZWMsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdjb21wb25lbnQnOiBpbnN0cnVtZW50YXRpb24uY29tcG9uZW50LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnc3RyZWFtJzogJ3dlYlJ0YycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICd0eXBlJzogbWV0cmljSWQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdzdHJlYW1fdHlwZSc6ICdjb21wb3NlZF9tZXRyaWNzJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ3VuaXRzJzogdW5pdHNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGpzb25bbWV0cmljSWRdID0gbWV0cmljcztcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbmRQb3N0KEpTT04uc3RyaW5naWZ5KGpzb24pKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcblxuICAgICAgICB0aGlzLmdldFN0YXRzQWdub3N0aWModGhpcy5zdHJlYW0uZ2V0UlRDUGVlckNvbm5lY3Rpb24oKSwgZiwgKGVycm9yKSA9PiB7IGNvbnNvbGUubG9nKGVycm9yKTsgfSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBzdGFuZGFyZGl6ZVJlcG9ydChyZXNwb25zZSkge1xuICAgICAgICBjb25zb2xlLmxvZyhyZXNwb25zZSk7XG4gICAgICAgIGNvbnN0IHN0YW5kYXJkUmVwb3J0ID0ge307XG5cbiAgICAgICAgaWYgKHBsYXRmb3JtLm5hbWUhLmluZGV4T2YoJ0ZpcmVmb3gnKSAhPT0gLTEpIHtcbiAgICAgICAgICAgIE9iamVjdC5rZXlzKHJlc3BvbnNlKS5mb3JFYWNoKGtleSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5sb2cocmVzcG9uc2Vba2V5XSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHJldHVybiByZXNwb25zZTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJlc3BvbnNlLnJlc3VsdCgpLmZvckVhY2gocmVwb3J0ID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHN0YW5kYXJkU3RhdHMgPSB7XG4gICAgICAgICAgICAgICAgaWQ6IHJlcG9ydC5pZCxcbiAgICAgICAgICAgICAgICB0aW1lc3RhbXA6IHJlcG9ydC50aW1lc3RhbXAsXG4gICAgICAgICAgICAgICAgdHlwZTogcmVwb3J0LnR5cGVcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICByZXBvcnQubmFtZXMoKS5mb3JFYWNoKChuYW1lKSA9PiB7XG4gICAgICAgICAgICAgICAgc3RhbmRhcmRTdGF0c1tuYW1lXSA9IHJlcG9ydC5zdGF0KG5hbWUpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBzdGFuZGFyZFJlcG9ydFtzdGFuZGFyZFN0YXRzLmlkXSA9IHN0YW5kYXJkU3RhdHM7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHJldHVybiBzdGFuZGFyZFJlcG9ydDtcbiAgICB9XG5cbiAgICBwcml2YXRlIGdldFN0YXRzQWdub3N0aWMocGMsIHN1Y2Nlc3NDYiwgZmFpbHVyZUNiKSB7XG4gICAgICAgIGlmIChwbGF0Zm9ybS5uYW1lIS5pbmRleE9mKCdGaXJlZm94JykgIT09IC0xKSB7XG4gICAgICAgICAgICAvLyBnZXRTdGF0cyB0YWtlcyBhcmdzIGluIGRpZmZlcmVudCBvcmRlciBpbiBDaHJvbWUgYW5kIEZpcmVmb3hcbiAgICAgICAgICAgIHJldHVybiBwYy5nZXRTdGF0cyhudWxsKS50aGVuKHJlc3BvbnNlID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCByZXBvcnQgPSB0aGlzLnN0YW5kYXJkaXplUmVwb3J0KHJlc3BvbnNlKTtcbiAgICAgICAgICAgICAgICBzdWNjZXNzQ2IocmVwb3J0KTtcbiAgICAgICAgICAgIH0pLmNhdGNoKGZhaWx1cmVDYik7XG4gICAgICAgIH0gZWxzZSBpZiAoKHBsYXRmb3JtLm5hbWUhLmluZGV4T2YoJ0Nocm9tZScpICE9PSAtMSkgfHwgKHBsYXRmb3JtLm5hbWUhLmluZGV4T2YoJ09wZXJhJykgIT09IC0xKSkge1xuICAgICAgICAgICAgLy8gSW4gQ2hyb21lLCB0aGUgZmlyc3QgdHdvIGFyZ3VtZW50cyBhcmUgcmV2ZXJzZWRcbiAgICAgICAgICAgIHJldHVybiBwYy5nZXRTdGF0cygocmVzcG9uc2UpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCByZXBvcnQgPSB0aGlzLnN0YW5kYXJkaXplUmVwb3J0KHJlc3BvbnNlKTtcbiAgICAgICAgICAgICAgICBzdWNjZXNzQ2IocmVwb3J0KTtcbiAgICAgICAgICAgIH0sIG51bGwsIGZhaWx1cmVDYik7XG4gICAgICAgIH1cbiAgICB9XG5cbn0iXX0=
diff --git a/openvidu-mvc-node/views/session.ejs b/openvidu-mvc-node/views/session.ejs
index 00f1607f7..9414f4be2 100644
--- a/openvidu-mvc-node/views/session.ejs
+++ b/openvidu-mvc-node/views/session.ejs
@@ -14,7 +14,7 @@
-
+
diff --git a/openvidu-recording-java/pom.xml b/openvidu-recording-java/pom.xml
index 3b418d2df..2c1b029ac 100644
--- a/openvidu-recording-java/pom.xml
+++ b/openvidu-recording-java/pom.xml
@@ -95,7 +95,7 @@
io.openvidu
openvidu-java-client
- 2.3.0
+ 2.4.0
diff --git a/openvidu-recording-java/src/main/resources/static/index.html b/openvidu-recording-java/src/main/resources/static/index.html
index 621ec2613..8b3539b9c 100644
--- a/openvidu-recording-java/src/main/resources/static/index.html
+++ b/openvidu-recording-java/src/main/resources/static/index.html
@@ -17,7 +17,7 @@
-
+
+
-
-
+
+
diff --git a/openvidu-webcomponent/web/openvidu-webcomponent-2.3.0.css b/openvidu-webcomponent/web/openvidu-webcomponent-2.3.0.css
deleted file mode 100644
index a5bae68be..000000000
--- a/openvidu-webcomponent/web/openvidu-webcomponent-2.3.0.css
+++ /dev/null
@@ -1 +0,0 @@
-.mat-elevation-z0{box-shadow:0 0 0 0 rgba(0,0,0,.2),0 0 0 0 rgba(0,0,0,.14),0 0 0 0 rgba(0,0,0,.12)}.mat-elevation-z1{box-shadow:0 2px 1px -1px rgba(0,0,0,.2),0 1px 1px 0 rgba(0,0,0,.14),0 1px 3px 0 rgba(0,0,0,.12)}.mat-elevation-z2{box-shadow:0 3px 1px -2px rgba(0,0,0,.2),0 2px 2px 0 rgba(0,0,0,.14),0 1px 5px 0 rgba(0,0,0,.12)}.mat-elevation-z3{box-shadow:0 3px 3px -2px rgba(0,0,0,.2),0 3px 4px 0 rgba(0,0,0,.14),0 1px 8px 0 rgba(0,0,0,.12)}.mat-elevation-z4{box-shadow:0 2px 4px -1px rgba(0,0,0,.2),0 4px 5px 0 rgba(0,0,0,.14),0 1px 10px 0 rgba(0,0,0,.12)}.mat-elevation-z5{box-shadow:0 3px 5px -1px rgba(0,0,0,.2),0 5px 8px 0 rgba(0,0,0,.14),0 1px 14px 0 rgba(0,0,0,.12)}.mat-elevation-z6{box-shadow:0 3px 5px -1px rgba(0,0,0,.2),0 6px 10px 0 rgba(0,0,0,.14),0 1px 18px 0 rgba(0,0,0,.12)}.mat-elevation-z7{box-shadow:0 4px 5px -2px rgba(0,0,0,.2),0 7px 10px 1px rgba(0,0,0,.14),0 2px 16px 1px rgba(0,0,0,.12)}.mat-elevation-z8{box-shadow:0 5px 5px -3px rgba(0,0,0,.2),0 8px 10px 1px rgba(0,0,0,.14),0 3px 14px 2px rgba(0,0,0,.12)}.mat-elevation-z9{box-shadow:0 5px 6px -3px rgba(0,0,0,.2),0 9px 12px 1px rgba(0,0,0,.14),0 3px 16px 2px rgba(0,0,0,.12)}.mat-elevation-z10{box-shadow:0 6px 6px -3px rgba(0,0,0,.2),0 10px 14px 1px rgba(0,0,0,.14),0 4px 18px 3px rgba(0,0,0,.12)}.mat-elevation-z11{box-shadow:0 6px 7px -4px rgba(0,0,0,.2),0 11px 15px 1px rgba(0,0,0,.14),0 4px 20px 3px rgba(0,0,0,.12)}.mat-elevation-z12{box-shadow:0 7px 8px -4px rgba(0,0,0,.2),0 12px 17px 2px rgba(0,0,0,.14),0 5px 22px 4px rgba(0,0,0,.12)}.mat-elevation-z13{box-shadow:0 7px 8px -4px rgba(0,0,0,.2),0 13px 19px 2px rgba(0,0,0,.14),0 5px 24px 4px rgba(0,0,0,.12)}.mat-elevation-z14{box-shadow:0 7px 9px -4px rgba(0,0,0,.2),0 14px 21px 2px rgba(0,0,0,.14),0 5px 26px 4px rgba(0,0,0,.12)}.mat-elevation-z15{box-shadow:0 8px 9px -5px rgba(0,0,0,.2),0 15px 22px 2px rgba(0,0,0,.14),0 6px 28px 5px rgba(0,0,0,.12)}.mat-elevation-z16{box-shadow:0 8px 10px -5px rgba(0,0,0,.2),0 16px 24px 2px rgba(0,0,0,.14),0 6px 30px 5px rgba(0,0,0,.12)}.mat-elevation-z17{box-shadow:0 8px 11px -5px rgba(0,0,0,.2),0 17px 26px 2px rgba(0,0,0,.14),0 6px 32px 5px rgba(0,0,0,.12)}.mat-elevation-z18{box-shadow:0 9px 11px -5px rgba(0,0,0,.2),0 18px 28px 2px rgba(0,0,0,.14),0 7px 34px 6px rgba(0,0,0,.12)}.mat-elevation-z19{box-shadow:0 9px 12px -6px rgba(0,0,0,.2),0 19px 29px 2px rgba(0,0,0,.14),0 7px 36px 6px rgba(0,0,0,.12)}.mat-elevation-z20{box-shadow:0 10px 13px -6px rgba(0,0,0,.2),0 20px 31px 3px rgba(0,0,0,.14),0 8px 38px 7px rgba(0,0,0,.12)}.mat-elevation-z21{box-shadow:0 10px 13px -6px rgba(0,0,0,.2),0 21px 33px 3px rgba(0,0,0,.14),0 8px 40px 7px rgba(0,0,0,.12)}.mat-elevation-z22{box-shadow:0 10px 14px -6px rgba(0,0,0,.2),0 22px 35px 3px rgba(0,0,0,.14),0 8px 42px 7px rgba(0,0,0,.12)}.mat-elevation-z23{box-shadow:0 11px 14px -7px rgba(0,0,0,.2),0 23px 36px 3px rgba(0,0,0,.14),0 9px 44px 8px rgba(0,0,0,.12)}.mat-elevation-z24{box-shadow:0 11px 15px -7px rgba(0,0,0,.2),0 24px 38px 3px rgba(0,0,0,.14),0 9px 46px 8px rgba(0,0,0,.12)}.mat-badge-content{font-weight:600;font-size:12px;font-family:Roboto,"Helvetica Neue",sans-serif}.mat-badge-small .mat-badge-content{font-size:6px}.mat-badge-large .mat-badge-content{font-size:24px}.mat-h1,.mat-headline,.mat-typography h1{font:400 24px/32px Roboto,"Helvetica Neue",sans-serif;margin:0 0 16px}.mat-h2,.mat-title,.mat-typography h2{font:500 20px/32px Roboto,"Helvetica Neue",sans-serif;margin:0 0 16px}.mat-h3,.mat-subheading-2,.mat-typography h3{font:400 16px/28px Roboto,"Helvetica Neue",sans-serif;margin:0 0 16px}.mat-h4,.mat-subheading-1,.mat-typography h4{font:400 15px/24px Roboto,"Helvetica Neue",sans-serif;margin:0 0 16px}.mat-h5,.mat-typography h5{font:400 11.62px/20px Roboto,"Helvetica Neue",sans-serif;margin:0 0 12px}.mat-h6,.mat-typography h6{font:400 9.38px/20px Roboto,"Helvetica Neue",sans-serif;margin:0 0 12px}.mat-body-2,.mat-body-strong{font:500 14px/24px Roboto,"Helvetica Neue",sans-serif}.mat-body,.mat-body-1,.mat-typography{font:400 14px/20px Roboto,"Helvetica Neue",sans-serif}.mat-body p,.mat-body-1 p,.mat-typography p{margin:0 0 12px}.mat-caption,.mat-small{font:400 12px/20px Roboto,"Helvetica Neue",sans-serif}.mat-display-4,.mat-typography .mat-display-4{font:300 112px/112px Roboto,"Helvetica Neue",sans-serif;margin:0 0 56px;letter-spacing:-.05em}.mat-display-3,.mat-typography .mat-display-3{font:400 56px/56px Roboto,"Helvetica Neue",sans-serif;margin:0 0 64px;letter-spacing:-.02em}.mat-display-2,.mat-typography .mat-display-2{font:400 45px/48px Roboto,"Helvetica Neue",sans-serif;margin:0 0 64px;letter-spacing:-.005em}.mat-display-1,.mat-typography .mat-display-1{font:400 34px/40px Roboto,"Helvetica Neue",sans-serif;margin:0 0 64px}.mat-bottom-sheet-container{font-family:Roboto,"Helvetica Neue",sans-serif;font-size:16px;font-weight:400}.mat-button,.mat-fab,.mat-flat-button,.mat-icon-button,.mat-mini-fab,.mat-raised-button,.mat-stroked-button{font-family:Roboto,"Helvetica Neue",sans-serif;font-size:14px;font-weight:500}.mat-button-toggle,.mat-card{font-family:Roboto,"Helvetica Neue",sans-serif}.mat-card-title{font-size:24px;font-weight:400}.mat-card-content,.mat-card-header .mat-card-title,.mat-card-subtitle{font-size:14px}.mat-checkbox{font-family:Roboto,"Helvetica Neue",sans-serif}.mat-checkbox-layout .mat-checkbox-label{line-height:24px}.mat-chip{font-size:13px;line-height:18px}.mat-chip .mat-chip-remove.mat-icon,.mat-chip .mat-chip-trailing-icon.mat-icon{font-size:18px}.mat-table{font-family:Roboto,"Helvetica Neue",sans-serif}.mat-header-cell{font-size:12px;font-weight:500}.mat-cell,.mat-footer-cell{font-size:14px}.mat-calendar{font-family:Roboto,"Helvetica Neue",sans-serif}.mat-calendar-body{font-size:13px}.mat-calendar-body-label,.mat-calendar-period-button{font-size:14px;font-weight:500}.mat-calendar-table-header th{font-size:11px;font-weight:400}.mat-dialog-title{font:500 20px/32px Roboto,"Helvetica Neue",sans-serif}.mat-expansion-panel-header{font-family:Roboto,"Helvetica Neue",sans-serif;font-size:15px;font-weight:400}.mat-expansion-panel-content{font:400 14px/20px Roboto,"Helvetica Neue",sans-serif}.mat-form-field{font-size:inherit;font-weight:400;line-height:1.125;font-family:Roboto,"Helvetica Neue",sans-serif}.mat-form-field-wrapper{padding-bottom:1.34375em}.mat-form-field-prefix .mat-icon,.mat-form-field-suffix .mat-icon{font-size:150%;line-height:1.125}.mat-form-field-prefix .mat-icon-button,.mat-form-field-suffix .mat-icon-button{height:1.5em;width:1.5em}.mat-form-field-prefix .mat-icon-button .mat-icon,.mat-form-field-suffix .mat-icon-button .mat-icon{height:1.125em;line-height:1.125}.mat-form-field-infix{padding:.5em 0;border-top:.84375em solid transparent}.mat-form-field-can-float .mat-input-server:focus+.mat-form-field-label-wrapper .mat-form-field-label,.mat-form-field-can-float.mat-form-field-should-float .mat-form-field-label{-webkit-transform:translateY(-1.34375em) scale(.75);transform:translateY(-1.34375em) scale(.75);width:133.33333%}.mat-form-field-can-float .mat-input-server[label]:not(:label-shown)+.mat-form-field-label-wrapper .mat-form-field-label{-webkit-transform:translateY(-1.34374em) scale(.75);transform:translateY(-1.34374em) scale(.75);width:133.33334%}.mat-form-field-label-wrapper{top:-.84375em;padding-top:.84375em}.mat-form-field-label{top:1.34375em}.mat-form-field-underline{bottom:1.34375em}.mat-form-field-subscript-wrapper{font-size:75%;margin-top:.66667em;top:calc(100% - 1.79167em)}.mat-form-field-appearance-legacy .mat-form-field-wrapper{padding-bottom:1.25em}.mat-form-field-appearance-legacy .mat-form-field-infix{padding:.4375em 0}.mat-form-field-appearance-legacy.mat-form-field-can-float .mat-input-server:focus+.mat-form-field-label-wrapper .mat-form-field-label,.mat-form-field-appearance-legacy.mat-form-field-can-float.mat-form-field-should-float .mat-form-field-label{-webkit-transform:translateY(-1.28125em) scale(.75) perspective(100px) translateZ(.001px);transform:translateY(-1.28125em) scale(.75) perspective(100px) translateZ(.001px);-ms-transform:translateY(-1.28125em) scale(.75);width:133.33333%}.mat-form-field-appearance-legacy.mat-form-field-can-float .mat-form-field-autofill-control:-webkit-autofill+.mat-form-field-label-wrapper .mat-form-field-label{-webkit-transform:translateY(-1.28125em) scale(.75) perspective(100px) translateZ(.00101px);transform:translateY(-1.28125em) scale(.75) perspective(100px) translateZ(.00101px);-ms-transform:translateY(-1.28124em) scale(.75);width:133.33334%}.mat-form-field-appearance-legacy.mat-form-field-can-float .mat-input-server[label]:not(:label-shown)+.mat-form-field-label-wrapper .mat-form-field-label{-webkit-transform:translateY(-1.28125em) scale(.75) perspective(100px) translateZ(.00102px);transform:translateY(-1.28125em) scale(.75) perspective(100px) translateZ(.00102px);-ms-transform:translateY(-1.28123em) scale(.75);width:133.33335%}.mat-form-field-appearance-legacy .mat-form-field-label{top:1.28125em}.mat-form-field-appearance-legacy .mat-form-field-underline{bottom:1.25em}.mat-form-field-appearance-legacy .mat-form-field-subscript-wrapper{margin-top:.54167em;top:calc(100% - 1.66667em)}.mat-form-field-appearance-fill .mat-form-field-infix{padding:.25em 0 .75em}.mat-form-field-appearance-fill .mat-form-field-label{top:1.09375em;margin-top:-.5em}.mat-form-field-appearance-fill.mat-form-field-can-float .mat-input-server:focus+.mat-form-field-label-wrapper .mat-form-field-label,.mat-form-field-appearance-fill.mat-form-field-can-float.mat-form-field-should-float .mat-form-field-label{-webkit-transform:translateY(-.59375em) scale(.75);transform:translateY(-.59375em) scale(.75);width:133.33333%}.mat-form-field-appearance-fill.mat-form-field-can-float .mat-input-server[label]:not(:label-shown)+.mat-form-field-label-wrapper .mat-form-field-label{-webkit-transform:translateY(-.59374em) scale(.75);transform:translateY(-.59374em) scale(.75);width:133.33334%}.mat-form-field-appearance-outline .mat-form-field-infix{padding:1em 0}.mat-form-field-appearance-outline .mat-form-field-label{top:1.84375em;margin-top:-.25em}.mat-form-field-appearance-outline.mat-form-field-can-float .mat-input-server:focus+.mat-form-field-label-wrapper .mat-form-field-label,.mat-form-field-appearance-outline.mat-form-field-can-float.mat-form-field-should-float .mat-form-field-label{-webkit-transform:translateY(-1.59375em) scale(.75);transform:translateY(-1.59375em) scale(.75);width:133.33333%}.mat-form-field-appearance-outline.mat-form-field-can-float .mat-input-server[label]:not(:label-shown)+.mat-form-field-label-wrapper .mat-form-field-label{-webkit-transform:translateY(-1.59374em) scale(.75);transform:translateY(-1.59374em) scale(.75);width:133.33334%}.mat-grid-tile-footer,.mat-grid-tile-header{font-size:14px}.mat-grid-tile-footer .mat-line,.mat-grid-tile-header .mat-line{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;display:block;box-sizing:border-box}.mat-grid-tile-footer .mat-line:nth-child(n+2),.mat-grid-tile-header .mat-line:nth-child(n+2){font-size:12px}input.mat-input-element{margin-top:-.0625em}.mat-menu-item{font-family:Roboto,"Helvetica Neue",sans-serif;font-size:16px;font-weight:400}.mat-paginator,.mat-paginator-page-size .mat-select-trigger{font-family:Roboto,"Helvetica Neue",sans-serif;font-size:12px}.mat-radio-button,.mat-select{font-family:Roboto,"Helvetica Neue",sans-serif}.mat-select-trigger{height:1.125em}.mat-slide-toggle-content{font:400 14px/20px Roboto,"Helvetica Neue",sans-serif}.mat-slider-thumb-label-text{font-family:Roboto,"Helvetica Neue",sans-serif;font-size:12px;font-weight:500}.mat-stepper-horizontal,.mat-stepper-vertical{font-family:Roboto,"Helvetica Neue",sans-serif}.mat-step-label{font-size:14px;font-weight:400}.mat-step-label-selected{font-size:14px;font-weight:500}.mat-tab-group{font-family:Roboto,"Helvetica Neue",sans-serif}.mat-tab-label,.mat-tab-link{font-family:Roboto,"Helvetica Neue",sans-serif;font-size:14px;font-weight:500}.mat-toolbar,.mat-toolbar h1,.mat-toolbar h2,.mat-toolbar h3,.mat-toolbar h4,.mat-toolbar h5,.mat-toolbar h6{font:500 20px/32px Roboto,"Helvetica Neue",sans-serif;margin:0}.mat-tooltip{font-family:Roboto,"Helvetica Neue",sans-serif;font-size:10px;padding-top:6px;padding-bottom:6px}.mat-tooltip-handset{font-size:14px;padding-top:9px;padding-bottom:9px}.mat-list-item,.mat-list-option{font-family:Roboto,"Helvetica Neue",sans-serif}.mat-list .mat-list-item,.mat-nav-list .mat-list-item,.mat-selection-list .mat-list-item{font-size:16px}.mat-list .mat-list-item .mat-line,.mat-nav-list .mat-list-item .mat-line,.mat-selection-list .mat-list-item .mat-line{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;display:block;box-sizing:border-box}.mat-list .mat-list-item .mat-line:nth-child(n+2),.mat-nav-list .mat-list-item .mat-line:nth-child(n+2),.mat-selection-list .mat-list-item .mat-line:nth-child(n+2){font-size:14px}.mat-list .mat-list-option,.mat-nav-list .mat-list-option,.mat-selection-list .mat-list-option{font-size:16px}.mat-list .mat-list-option .mat-line,.mat-nav-list .mat-list-option .mat-line,.mat-selection-list .mat-list-option .mat-line{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;display:block;box-sizing:border-box}.mat-list .mat-list-option .mat-line:nth-child(n+2),.mat-nav-list .mat-list-option .mat-line:nth-child(n+2),.mat-selection-list .mat-list-option .mat-line:nth-child(n+2){font-size:14px}.mat-list[dense] .mat-list-item,.mat-nav-list[dense] .mat-list-item,.mat-selection-list[dense] .mat-list-item{font-size:12px}.mat-list[dense] .mat-list-item .mat-line,.mat-nav-list[dense] .mat-list-item .mat-line,.mat-selection-list[dense] .mat-list-item .mat-line{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;display:block;box-sizing:border-box}.mat-list[dense] .mat-list-item .mat-line:nth-child(n+2),.mat-list[dense] .mat-list-option,.mat-nav-list[dense] .mat-list-item .mat-line:nth-child(n+2),.mat-nav-list[dense] .mat-list-option,.mat-selection-list[dense] .mat-list-item .mat-line:nth-child(n+2),.mat-selection-list[dense] .mat-list-option{font-size:12px}.mat-list[dense] .mat-list-option .mat-line,.mat-nav-list[dense] .mat-list-option .mat-line,.mat-selection-list[dense] .mat-list-option .mat-line{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;display:block;box-sizing:border-box}.mat-list[dense] .mat-list-option .mat-line:nth-child(n+2),.mat-nav-list[dense] .mat-list-option .mat-line:nth-child(n+2),.mat-selection-list[dense] .mat-list-option .mat-line:nth-child(n+2){font-size:12px}.mat-list[dense] .mat-subheader,.mat-nav-list[dense] .mat-subheader,.mat-selection-list[dense] .mat-subheader{font-family:Roboto,"Helvetica Neue",sans-serif;font-size:12px;font-weight:500}.mat-option{font-family:Roboto,"Helvetica Neue",sans-serif;font-size:16px;color:rgba(0,0,0,.87)}.mat-optgroup-label{font:500 14px/24px Roboto,"Helvetica Neue",sans-serif;color:rgba(0,0,0,.54)}.mat-simple-snackbar{font-family:Roboto,"Helvetica Neue",sans-serif;font-size:14px}.mat-simple-snackbar-action{line-height:1;font-family:inherit;font-size:inherit;font-weight:500}.mat-ripple{overflow:hidden}@media screen and (-ms-high-contrast:active){.mat-ripple{display:none}}.mat-ripple.mat-ripple-unbounded{overflow:visible}.mat-ripple-element{position:absolute;border-radius:50%;pointer-events:none;transition:opacity,-webkit-transform 0s cubic-bezier(0,0,.2,1);transition:opacity,transform 0s cubic-bezier(0,0,.2,1);transition:opacity,transform 0s cubic-bezier(0,0,.2,1),-webkit-transform 0s cubic-bezier(0,0,.2,1);-webkit-transform:scale(0);transform:scale(0)}.cdk-visually-hidden{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px;outline:0;-webkit-appearance:none;-moz-appearance:none}.cdk-global-overlay-wrapper,.cdk-overlay-container{pointer-events:none;top:0;left:0;height:100%;width:100%}.cdk-overlay-container{position:fixed;z-index:1000}.cdk-overlay-container:empty{display:none}.cdk-global-overlay-wrapper{display:flex;position:absolute;z-index:1000}.cdk-overlay-pane{position:absolute;pointer-events:auto;box-sizing:border-box;z-index:1000;display:flex;max-width:100%;max-height:100%}.cdk-overlay-backdrop{position:absolute;top:0;bottom:0;left:0;right:0;z-index:1000;pointer-events:auto;-webkit-tap-highlight-color:transparent;transition:opacity .4s cubic-bezier(.25,.8,.25,1);opacity:0}.cdk-overlay-backdrop.cdk-overlay-backdrop-showing{opacity:1}@media screen and (-ms-high-contrast:active){.cdk-overlay-backdrop.cdk-overlay-backdrop-showing{opacity:.6}.mat-badge-small .mat-badge-content{outline:solid 1px;border-radius:0}}.cdk-overlay-dark-backdrop{background:rgba(0,0,0,.288)}.cdk-overlay-transparent-backdrop,.cdk-overlay-transparent-backdrop.cdk-overlay-backdrop-showing{opacity:0}.cdk-overlay-connected-position-bounding-box{position:absolute;z-index:1000;display:flex;flex-direction:column;min-width:1px;min-height:1px}.cdk-global-scrollblock{position:fixed;width:100%;overflow-y:scroll}.cdk-text-field-autofill-monitored:-webkit-autofill{-webkit-animation-name:cdk-text-field-autofill-start;animation-name:cdk-text-field-autofill-start}.cdk-text-field-autofill-monitored:not(:-webkit-autofill){-webkit-animation-name:cdk-text-field-autofill-end;animation-name:cdk-text-field-autofill-end}textarea.cdk-textarea-autosize{resize:none}textarea.cdk-textarea-autosize-measuring{height:auto!important;overflow:hidden!important;padding:2px 0!important;box-sizing:content-box!important}.mat-ripple-element{background-color:rgba(0,0,0,.1)}.mat-option.mat-selected:not(.mat-option-multiple):not(.mat-option-disabled),.mat-option:focus:not(.mat-option-disabled),.mat-option:hover:not(.mat-option-disabled){background:rgba(0,0,0,.04)}.mat-option.mat-active{background:rgba(0,0,0,.04);color:rgba(0,0,0,.87)}.mat-option.mat-option-disabled{color:rgba(0,0,0,.38)}.mat-primary .mat-option.mat-selected:not(.mat-option-disabled){color:#3f51b5}.mat-accent .mat-option.mat-selected:not(.mat-option-disabled){color:#ff4081}.mat-warn .mat-option.mat-selected:not(.mat-option-disabled){color:#f44336}.mat-optgroup-disabled .mat-optgroup-label{color:rgba(0,0,0,.38)}.mat-pseudo-checkbox{color:rgba(0,0,0,.54)}.mat-pseudo-checkbox::after{color:#fafafa}.mat-accent .mat-pseudo-checkbox-checked,.mat-accent .mat-pseudo-checkbox-indeterminate,.mat-pseudo-checkbox-checked,.mat-pseudo-checkbox-indeterminate{background:#ff4081}.mat-primary .mat-pseudo-checkbox-checked,.mat-primary .mat-pseudo-checkbox-indeterminate{background:#3f51b5}.mat-warn .mat-pseudo-checkbox-checked,.mat-warn .mat-pseudo-checkbox-indeterminate{background:#f44336}.mat-pseudo-checkbox-checked.mat-pseudo-checkbox-disabled,.mat-pseudo-checkbox-indeterminate.mat-pseudo-checkbox-disabled{background:#b0b0b0}.mat-app-background{background-color:#fafafa;color:rgba(0,0,0,.87)}.mat-theme-loaded-marker{display:none}.mat-autocomplete-panel{background:#fff;color:rgba(0,0,0,.87)}.mat-autocomplete-panel .mat-option.mat-selected:not(.mat-active):not(:hover){background:#fff}.mat-autocomplete-panel .mat-option.mat-selected:not(.mat-active):not(:hover):not(.mat-option-disabled){color:rgba(0,0,0,.87)}.mat-badge-accent .mat-badge-content{background:#ff4081;color:#fff}.mat-badge-warn .mat-badge-content{color:#fff;background:#f44336}.mat-badge{position:relative}.mat-badge-hidden .mat-badge-content{display:none}.mat-badge-content{color:#fff;background:#3f51b5;position:absolute;text-align:center;display:inline-block;border-radius:50%;transition:-webkit-transform .2s ease-in-out;transition:transform .2s ease-in-out;transition:transform .2s ease-in-out,-webkit-transform .2s ease-in-out;-webkit-transform:scale(.6);transform:scale(.6);overflow:hidden;white-space:nowrap;text-overflow:ellipsis;pointer-events:none}.mat-badge-content.mat-badge-active{-webkit-transform:none;transform:none}.mat-badge-small .mat-badge-content{width:16px;height:16px;line-height:16px}.mat-badge-small.mat-badge-above .mat-badge-content{top:-8px}.mat-badge-small.mat-badge-below .mat-badge-content{bottom:-8px}.mat-badge-small.mat-badge-before{margin-left:16px}.mat-badge-small.mat-badge-before .mat-badge-content{left:-16px}[dir=rtl] .mat-badge-small.mat-badge-before{margin-left:0;margin-right:16px}[dir=rtl] .mat-badge-small.mat-badge-before .mat-badge-content{left:auto;right:-16px}.mat-badge-small.mat-badge-after{margin-right:16px}.mat-badge-small.mat-badge-after .mat-badge-content{right:-16px}[dir=rtl] .mat-badge-small.mat-badge-after{margin-right:0;margin-left:16px}[dir=rtl] .mat-badge-small.mat-badge-after .mat-badge-content{right:auto;left:-16px}.mat-badge-small.mat-badge-overlap.mat-badge-before{margin-left:8px}.mat-badge-small.mat-badge-overlap.mat-badge-before .mat-badge-content{left:-8px}[dir=rtl] .mat-badge-small.mat-badge-overlap.mat-badge-before{margin-left:0;margin-right:8px}[dir=rtl] .mat-badge-small.mat-badge-overlap.mat-badge-before .mat-badge-content{left:auto;right:-8px}.mat-badge-small.mat-badge-overlap.mat-badge-after{margin-right:8px}.mat-badge-small.mat-badge-overlap.mat-badge-after .mat-badge-content{right:-8px}[dir=rtl] .mat-badge-small.mat-badge-overlap.mat-badge-after{margin-right:0;margin-left:16px}[dir=rtl] .mat-badge-small.mat-badge-overlap.mat-badge-after .mat-badge-content{right:auto;left:-8px}.mat-badge-medium .mat-badge-content{width:22px;height:22px;line-height:22px}.mat-badge-medium.mat-badge-above .mat-badge-content{top:-11px}.mat-badge-medium.mat-badge-below .mat-badge-content{bottom:-11px}.mat-badge-medium.mat-badge-before{margin-left:22px}.mat-badge-medium.mat-badge-before .mat-badge-content{left:-22px}[dir=rtl] .mat-badge-medium.mat-badge-before{margin-left:0;margin-right:22px}[dir=rtl] .mat-badge-medium.mat-badge-before .mat-badge-content{left:auto;right:-22px}.mat-badge-medium.mat-badge-after{margin-right:22px}.mat-badge-medium.mat-badge-after .mat-badge-content{right:-22px}[dir=rtl] .mat-badge-medium.mat-badge-after{margin-right:0;margin-left:22px}[dir=rtl] .mat-badge-medium.mat-badge-after .mat-badge-content{right:auto;left:-22px}.mat-badge-medium.mat-badge-overlap.mat-badge-before{margin-left:11px}.mat-badge-medium.mat-badge-overlap.mat-badge-before .mat-badge-content{left:-11px}[dir=rtl] .mat-badge-medium.mat-badge-overlap.mat-badge-before{margin-left:0;margin-right:11px}[dir=rtl] .mat-badge-medium.mat-badge-overlap.mat-badge-before .mat-badge-content{left:auto;right:-11px}.mat-badge-medium.mat-badge-overlap.mat-badge-after{margin-right:11px}.mat-badge-medium.mat-badge-overlap.mat-badge-after .mat-badge-content{right:-11px}[dir=rtl] .mat-badge-medium.mat-badge-overlap.mat-badge-after{margin-right:0;margin-left:22px}[dir=rtl] .mat-badge-medium.mat-badge-overlap.mat-badge-after .mat-badge-content{right:auto;left:-11px}.mat-badge-large .mat-badge-content{width:28px;height:28px;line-height:28px}@media screen and (-ms-high-contrast:active){.mat-badge-large .mat-badge-content,.mat-badge-medium .mat-badge-content{outline:solid 1px;border-radius:0}}.mat-badge-large.mat-badge-above .mat-badge-content{top:-14px}.mat-badge-large.mat-badge-below .mat-badge-content{bottom:-14px}.mat-badge-large.mat-badge-before{margin-left:28px}.mat-badge-large.mat-badge-before .mat-badge-content{left:-28px}[dir=rtl] .mat-badge-large.mat-badge-before{margin-left:0;margin-right:28px}[dir=rtl] .mat-badge-large.mat-badge-before .mat-badge-content{left:auto;right:-28px}.mat-badge-large.mat-badge-after{margin-right:28px}.mat-badge-large.mat-badge-after .mat-badge-content{right:-28px}[dir=rtl] .mat-badge-large.mat-badge-after{margin-right:0;margin-left:28px}[dir=rtl] .mat-badge-large.mat-badge-after .mat-badge-content{right:auto;left:-28px}.mat-badge-large.mat-badge-overlap.mat-badge-before{margin-left:14px}.mat-badge-large.mat-badge-overlap.mat-badge-before .mat-badge-content{left:-14px}[dir=rtl] .mat-badge-large.mat-badge-overlap.mat-badge-before{margin-left:0;margin-right:14px}[dir=rtl] .mat-badge-large.mat-badge-overlap.mat-badge-before .mat-badge-content{left:auto;right:-14px}.mat-badge-large.mat-badge-overlap.mat-badge-after{margin-right:14px}.mat-badge-large.mat-badge-overlap.mat-badge-after .mat-badge-content{right:-14px}[dir=rtl] .mat-badge-large.mat-badge-overlap.mat-badge-after{margin-right:0;margin-left:28px}[dir=rtl] .mat-badge-large.mat-badge-overlap.mat-badge-after .mat-badge-content{right:auto;left:-14px}.mat-bottom-sheet-container{background:#fff;color:rgba(0,0,0,.87)}.mat-button,.mat-icon-button,.mat-stroked-button{color:inherit;background:0 0}.mat-button.mat-primary,.mat-icon-button.mat-primary,.mat-stroked-button.mat-primary{color:#3f51b5}.mat-button.mat-accent,.mat-icon-button.mat-accent,.mat-stroked-button.mat-accent{color:#ff4081}.mat-button.mat-warn,.mat-icon-button.mat-warn,.mat-stroked-button.mat-warn{color:#f44336}.mat-button.mat-accent[disabled],.mat-button.mat-primary[disabled],.mat-button.mat-warn[disabled],.mat-button[disabled][disabled],.mat-icon-button.mat-accent[disabled],.mat-icon-button.mat-primary[disabled],.mat-icon-button.mat-warn[disabled],.mat-icon-button[disabled][disabled],.mat-stroked-button.mat-accent[disabled],.mat-stroked-button.mat-primary[disabled],.mat-stroked-button.mat-warn[disabled],.mat-stroked-button[disabled][disabled]{color:rgba(0,0,0,.26)}.mat-button.mat-primary .mat-button-focus-overlay,.mat-icon-button.mat-primary .mat-button-focus-overlay,.mat-stroked-button.mat-primary .mat-button-focus-overlay{background-color:rgba(63,81,181,.12)}.mat-button.mat-accent .mat-button-focus-overlay,.mat-icon-button.mat-accent .mat-button-focus-overlay,.mat-stroked-button.mat-accent .mat-button-focus-overlay{background-color:rgba(255,64,129,.12)}.mat-button.mat-warn .mat-button-focus-overlay,.mat-icon-button.mat-warn .mat-button-focus-overlay,.mat-stroked-button.mat-warn .mat-button-focus-overlay{background-color:rgba(244,67,54,.12)}.mat-button[disabled] .mat-button-focus-overlay,.mat-icon-button[disabled] .mat-button-focus-overlay,.mat-stroked-button[disabled] .mat-button-focus-overlay{background-color:transparent}.mat-button.mat-primary .mat-ripple-element,.mat-icon-button.mat-primary .mat-ripple-element,.mat-stroked-button.mat-primary .mat-ripple-element{background-color:rgba(63,81,181,.1)}.mat-button.mat-accent .mat-ripple-element,.mat-icon-button.mat-accent .mat-ripple-element,.mat-stroked-button.mat-accent .mat-ripple-element{background-color:rgba(255,64,129,.1)}.mat-button.mat-warn .mat-ripple-element,.mat-icon-button.mat-warn .mat-ripple-element,.mat-stroked-button.mat-warn .mat-ripple-element{background-color:rgba(244,67,54,.1)}.mat-fab,.mat-flat-button,.mat-mini-fab,.mat-raised-button{color:rgba(0,0,0,.87);background-color:#fff}.mat-fab.mat-accent,.mat-fab.mat-primary,.mat-fab.mat-warn,.mat-flat-button.mat-accent,.mat-flat-button.mat-primary,.mat-flat-button.mat-warn,.mat-mini-fab.mat-accent,.mat-mini-fab.mat-primary,.mat-mini-fab.mat-warn,.mat-raised-button.mat-accent,.mat-raised-button.mat-primary,.mat-raised-button.mat-warn{color:#fff}.mat-fab.mat-accent[disabled],.mat-fab.mat-primary[disabled],.mat-fab.mat-warn[disabled],.mat-fab[disabled][disabled],.mat-flat-button.mat-accent[disabled],.mat-flat-button.mat-primary[disabled],.mat-flat-button.mat-warn[disabled],.mat-flat-button[disabled][disabled],.mat-mini-fab.mat-accent[disabled],.mat-mini-fab.mat-primary[disabled],.mat-mini-fab.mat-warn[disabled],.mat-mini-fab[disabled][disabled],.mat-raised-button.mat-accent[disabled],.mat-raised-button.mat-primary[disabled],.mat-raised-button.mat-warn[disabled],.mat-raised-button[disabled][disabled]{color:rgba(0,0,0,.26);background-color:rgba(0,0,0,.12)}.mat-fab.mat-primary,.mat-flat-button.mat-primary,.mat-mini-fab.mat-primary,.mat-raised-button.mat-primary{background-color:#3f51b5}.mat-fab.mat-accent,.mat-flat-button.mat-accent,.mat-mini-fab.mat-accent,.mat-raised-button.mat-accent{background-color:#ff4081}.mat-fab.mat-warn,.mat-flat-button.mat-warn,.mat-mini-fab.mat-warn,.mat-raised-button.mat-warn{background-color:#f44336}.mat-fab.mat-accent .mat-ripple-element,.mat-fab.mat-primary .mat-ripple-element,.mat-fab.mat-warn .mat-ripple-element,.mat-flat-button.mat-accent .mat-ripple-element,.mat-flat-button.mat-primary .mat-ripple-element,.mat-flat-button.mat-warn .mat-ripple-element,.mat-mini-fab.mat-accent .mat-ripple-element,.mat-mini-fab.mat-primary .mat-ripple-element,.mat-mini-fab.mat-warn .mat-ripple-element,.mat-raised-button.mat-accent .mat-ripple-element,.mat-raised-button.mat-primary .mat-ripple-element,.mat-raised-button.mat-warn .mat-ripple-element{background-color:rgba(255,255,255,.1)}.mat-icon-button.mat-primary .mat-ripple-element{background-color:rgba(63,81,181,.2)}.mat-icon-button.mat-accent .mat-ripple-element{background-color:rgba(255,64,129,.2)}.mat-icon-button.mat-warn .mat-ripple-element{background-color:rgba(244,67,54,.2)}.mat-button-toggle{color:rgba(0,0,0,.38)}.mat-button-toggle .mat-button-toggle-focus-overlay{background-color:rgba(0,0,0,.12)}.mat-button-toggle-checked{background-color:#e0e0e0;color:rgba(0,0,0,.54)}.mat-button-toggle-disabled{background-color:#eee;color:rgba(0,0,0,.26)}.mat-button-toggle-disabled.mat-button-toggle-checked{background-color:#bdbdbd}.mat-card{background:#fff;color:rgba(0,0,0,.87)}.mat-card-subtitle{color:rgba(0,0,0,.54)}.mat-checkbox-frame{border-color:rgba(0,0,0,.54)}.mat-checkbox-checkmark{fill:#fafafa}.mat-checkbox-checkmark-path{stroke:#fafafa!important}.mat-checkbox-mixedmark{background-color:#fafafa}.mat-checkbox-checked.mat-primary .mat-checkbox-background,.mat-checkbox-indeterminate.mat-primary .mat-checkbox-background{background-color:#3f51b5}.mat-checkbox-checked.mat-accent .mat-checkbox-background,.mat-checkbox-indeterminate.mat-accent .mat-checkbox-background{background-color:#ff4081}.mat-checkbox-checked.mat-warn .mat-checkbox-background,.mat-checkbox-indeterminate.mat-warn .mat-checkbox-background{background-color:#f44336}.mat-checkbox-disabled.mat-checkbox-checked .mat-checkbox-background,.mat-checkbox-disabled.mat-checkbox-indeterminate .mat-checkbox-background{background-color:#b0b0b0}.mat-checkbox-disabled:not(.mat-checkbox-checked) .mat-checkbox-frame{border-color:#b0b0b0}.mat-checkbox-disabled .mat-checkbox-label{color:#b0b0b0}.mat-checkbox:not(.mat-checkbox-disabled).mat-primary .mat-checkbox-ripple .mat-ripple-element{background-color:rgba(63,81,181,.26)}.mat-checkbox:not(.mat-checkbox-disabled).mat-accent .mat-checkbox-ripple .mat-ripple-element{background-color:rgba(255,64,129,.26)}.mat-checkbox:not(.mat-checkbox-disabled).mat-warn .mat-checkbox-ripple .mat-ripple-element{background-color:rgba(244,67,54,.26)}.mat-chip.mat-standard-chip{background-color:#e0e0e0;color:rgba(0,0,0,.87)}.mat-chip.mat-standard-chip .mat-chip-remove{color:rgba(0,0,0,.87);opacity:.4}.mat-chip.mat-standard-chip .mat-chip-remove:hover{opacity:.54}.mat-chip.mat-standard-chip.mat-chip-selected.mat-primary{background-color:#3f51b5;color:#fff}.mat-chip.mat-standard-chip.mat-chip-selected.mat-primary .mat-chip-remove{color:#fff;opacity:.4}.mat-chip.mat-standard-chip.mat-chip-selected.mat-primary .mat-chip-remove:hover{opacity:.54}.mat-chip.mat-standard-chip.mat-chip-selected.mat-warn{background-color:#f44336;color:#fff}.mat-chip.mat-standard-chip.mat-chip-selected.mat-warn .mat-chip-remove{color:#fff;opacity:.4}.mat-chip.mat-standard-chip.mat-chip-selected.mat-warn .mat-chip-remove:hover{opacity:.54}.mat-chip.mat-standard-chip.mat-chip-selected.mat-accent{background-color:#ff4081;color:#fff}.mat-chip.mat-standard-chip.mat-chip-selected.mat-accent .mat-chip-remove{color:#fff;opacity:.4}.mat-chip.mat-standard-chip.mat-chip-selected.mat-accent .mat-chip-remove:hover{opacity:.54}.mat-table{background:#fff}mat-footer-row,mat-header-row,mat-row,td.mat-cell,td.mat-footer-cell,th.mat-header-cell{border-bottom-color:rgba(0,0,0,.12)}.mat-header-cell{color:rgba(0,0,0,.54)}.mat-cell,.mat-footer-cell{color:rgba(0,0,0,.87)}.mat-calendar-arrow{border-top-color:rgba(0,0,0,.54)}.mat-datepicker-popup .mat-calendar-next-button,.mat-datepicker-popup .mat-calendar-previous-button,.mat-datepicker-toggle{color:rgba(0,0,0,.54)}.mat-calendar-table-header{color:rgba(0,0,0,.38)}.mat-calendar-table-header-divider::after{background:rgba(0,0,0,.12)}.mat-calendar-body-label{color:rgba(0,0,0,.54)}.mat-calendar-body-cell-content{color:rgba(0,0,0,.87);border-color:transparent}.mat-calendar-body-disabled>.mat-calendar-body-cell-content:not(.mat-calendar-body-selected){color:rgba(0,0,0,.38)}.cdk-keyboard-focused .mat-calendar-body-active>.mat-calendar-body-cell-content:not(.mat-calendar-body-selected),.cdk-program-focused .mat-calendar-body-active>.mat-calendar-body-cell-content:not(.mat-calendar-body-selected),.mat-calendar-body-cell:not(.mat-calendar-body-disabled):hover>.mat-calendar-body-cell-content:not(.mat-calendar-body-selected){background-color:rgba(0,0,0,.04)}.mat-calendar-body-today:not(.mat-calendar-body-selected){border-color:rgba(0,0,0,.38)}.mat-calendar-body-disabled>.mat-calendar-body-today:not(.mat-calendar-body-selected){border-color:rgba(0,0,0,.18)}.mat-calendar-body-selected{background-color:#3f51b5;color:#fff}.mat-calendar-body-disabled>.mat-calendar-body-selected{background-color:rgba(63,81,181,.4)}.mat-calendar-body-today.mat-calendar-body-selected{box-shadow:inset 0 0 0 1px #fff}.mat-datepicker-content{background-color:#fff;color:rgba(0,0,0,.87)}.mat-datepicker-content.mat-accent .mat-calendar-body-selected{background-color:#ff4081;color:#fff}.mat-datepicker-content.mat-accent .mat-calendar-body-disabled>.mat-calendar-body-selected{background-color:rgba(255,64,129,.4)}.mat-datepicker-content.mat-accent .mat-calendar-body-today.mat-calendar-body-selected{box-shadow:inset 0 0 0 1px #fff}.mat-datepicker-content.mat-warn .mat-calendar-body-selected{background-color:#f44336;color:#fff}.mat-datepicker-content.mat-warn .mat-calendar-body-disabled>.mat-calendar-body-selected{background-color:rgba(244,67,54,.4)}.mat-datepicker-content.mat-warn .mat-calendar-body-today.mat-calendar-body-selected{box-shadow:inset 0 0 0 1px #fff}.mat-datepicker-toggle-active{color:#3f51b5}.mat-datepicker-toggle-active.mat-accent{color:#ff4081}.mat-datepicker-toggle-active.mat-warn{color:#f44336}.mat-dialog-container{background:#fff;color:rgba(0,0,0,.87)}.mat-divider{border-top-color:rgba(0,0,0,.12)}.mat-divider-vertical{border-right-color:rgba(0,0,0,.12)}.mat-expansion-panel{background:#fff;color:rgba(0,0,0,.87)}.mat-action-row{border-top-color:rgba(0,0,0,.12)}.mat-expansion-panel:not(.mat-expanded) .mat-expansion-panel-header:not([aria-disabled=true]).cdk-keyboard-focused,.mat-expansion-panel:not(.mat-expanded) .mat-expansion-panel-header:not([aria-disabled=true]).cdk-program-focused,.mat-expansion-panel:not(.mat-expanded) .mat-expansion-panel-header:not([aria-disabled=true]):hover{background:rgba(0,0,0,.04)}.mat-expansion-panel-header-title{color:rgba(0,0,0,.87)}.mat-expansion-indicator::after,.mat-expansion-panel-header-description{color:rgba(0,0,0,.54)}.mat-expansion-panel-header[aria-disabled=true]{color:rgba(0,0,0,.26)}.mat-expansion-panel-header[aria-disabled=true] .mat-expansion-panel-header-description,.mat-expansion-panel-header[aria-disabled=true] .mat-expansion-panel-header-title{color:inherit}.mat-form-field-label,.mat-hint{color:rgba(0,0,0,.6)}.mat-form-field.mat-focused .mat-form-field-label{color:#3f51b5}.mat-form-field.mat-focused .mat-form-field-label.mat-accent{color:#ff4081}.mat-form-field.mat-focused .mat-form-field-label.mat-warn{color:#f44336}.mat-focused .mat-form-field-required-marker{color:#ff4081}.mat-form-field-ripple{background-color:rgba(0,0,0,.87)}.mat-form-field.mat-focused .mat-form-field-ripple{background-color:#3f51b5}.mat-form-field.mat-focused .mat-form-field-ripple.mat-accent{background-color:#ff4081}.mat-form-field.mat-focused .mat-form-field-ripple.mat-warn{background-color:#f44336}.mat-form-field.mat-form-field-invalid .mat-form-field-label,.mat-form-field.mat-form-field-invalid .mat-form-field-label .mat-form-field-required-marker,.mat-form-field.mat-form-field-invalid .mat-form-field-label.mat-accent{color:#f44336}.mat-form-field.mat-form-field-invalid .mat-form-field-ripple{background-color:#f44336}.mat-error{color:#f44336}.mat-form-field-appearance-legacy .mat-form-field-label,.mat-form-field-appearance-legacy .mat-hint{color:rgba(0,0,0,.54)}.mat-form-field-appearance-legacy .mat-form-field-underline{background-color:rgba(0,0,0,.42)}.mat-form-field-appearance-legacy.mat-form-field-disabled .mat-form-field-underline{background-image:linear-gradient(to right,rgba(0,0,0,.42) 0,rgba(0,0,0,.42) 33%,transparent 0);background-size:4px 100%;background-repeat:repeat-x}.mat-form-field-appearance-standard .mat-form-field-underline{background-color:rgba(0,0,0,.42)}.mat-form-field-appearance-standard.mat-form-field-disabled .mat-form-field-underline{background-image:linear-gradient(to right,rgba(0,0,0,.42) 0,rgba(0,0,0,.42) 33%,transparent 0);background-size:4px 100%;background-repeat:repeat-x}.mat-form-field-appearance-fill .mat-form-field-flex{background-color:rgba(0,0,0,.04)}.mat-form-field-appearance-fill.mat-form-field-disabled .mat-form-field-flex{background-color:rgba(0,0,0,.02)}.mat-form-field-appearance-fill .mat-form-field-underline::before{background-color:rgba(0,0,0,.42)}.mat-form-field-appearance-fill.mat-form-field-disabled .mat-form-field-label{color:rgba(0,0,0,.38)}.mat-form-field-appearance-fill.mat-form-field-disabled .mat-form-field-underline::before{background-color:transparent}.mat-form-field-appearance-outline .mat-form-field-outline{bottom:1.34375em;color:rgba(0,0,0,.12)}.mat-form-field-appearance-outline .mat-form-field-outline-thick{color:rgba(0,0,0,.87)}.mat-form-field-appearance-outline.mat-focused .mat-form-field-outline-thick{color:#3f51b5}.mat-form-field-appearance-outline.mat-focused.mat-accent .mat-form-field-outline-thick{color:#ff4081}.mat-form-field-appearance-outline.mat-focused.mat-warn .mat-form-field-outline-thick,.mat-form-field-appearance-outline.mat-form-field-invalid.mat-form-field-invalid .mat-form-field-outline-thick{color:#f44336}.mat-form-field-appearance-outline.mat-form-field-disabled .mat-form-field-label{color:rgba(0,0,0,.38)}.mat-form-field-appearance-outline.mat-form-field-disabled .mat-form-field-outline{color:rgba(0,0,0,.06)}.mat-icon.mat-primary{color:#3f51b5}.mat-icon.mat-accent{color:#ff4081}.mat-icon.mat-warn{color:#f44336}.mat-input-element:disabled{color:rgba(0,0,0,.38)}.mat-input-element{caret-color:#3f51b5}.mat-input-element::-ms-input-placeholder{color:rgba(0,0,0,.42)}.mat-input-element::placeholder{color:rgba(0,0,0,.42)}.mat-input-element::-moz-placeholder{color:rgba(0,0,0,.42)}.mat-input-element::-webkit-input-placeholder{color:rgba(0,0,0,.42)}.mat-input-element:-ms-input-placeholder{color:rgba(0,0,0,.42)}.mat-accent .mat-input-element{caret-color:#ff4081}.mat-form-field-invalid .mat-input-element,.mat-warn .mat-input-element{caret-color:#f44336}.mat-list .mat-list-item,.mat-list .mat-list-option,.mat-nav-list .mat-list-item,.mat-nav-list .mat-list-option,.mat-selection-list .mat-list-item,.mat-selection-list .mat-list-option{color:rgba(0,0,0,.87)}.mat-list .mat-subheader,.mat-nav-list .mat-subheader,.mat-selection-list .mat-subheader{font-family:Roboto,"Helvetica Neue",sans-serif;font-size:14px;font-weight:500;color:rgba(0,0,0,.54)}.mat-list-item-disabled{background-color:#eee}.mat-list-option.mat-list-item-focus,.mat-list-option:hover,.mat-nav-list .mat-list-item.mat-list-item-focus,.mat-nav-list .mat-list-item:hover{background:rgba(0,0,0,.04)}.mat-menu-panel{background:#fff}.mat-menu-item{background:0 0;color:rgba(0,0,0,.87)}.mat-menu-item[disabled],.mat-menu-item[disabled]::after{color:rgba(0,0,0,.38)}.mat-menu-item .mat-icon:not([color]),.mat-menu-item-submenu-trigger::after{color:rgba(0,0,0,.54)}.mat-menu-item-highlighted:not([disabled]),.mat-menu-item.cdk-keyboard-focused:not([disabled]),.mat-menu-item.cdk-program-focused:not([disabled]),.mat-menu-item:hover:not([disabled]){background:rgba(0,0,0,.04)}.mat-paginator{background:#fff}.mat-paginator,.mat-paginator-page-size .mat-select-trigger{color:rgba(0,0,0,.54)}.mat-paginator-decrement,.mat-paginator-increment{border-top:2px solid rgba(0,0,0,.54);border-right:2px solid rgba(0,0,0,.54)}.mat-paginator-first,.mat-paginator-last{border-top:2px solid rgba(0,0,0,.54)}.mat-icon-button[disabled] .mat-paginator-decrement,.mat-icon-button[disabled] .mat-paginator-first,.mat-icon-button[disabled] .mat-paginator-increment,.mat-icon-button[disabled] .mat-paginator-last{border-color:rgba(0,0,0,.38)}.mat-progress-bar-background{fill:#c5cae9}.mat-progress-bar-buffer{background-color:#c5cae9}.mat-progress-bar-fill::after{background-color:#3f51b5}.mat-progress-bar.mat-accent .mat-progress-bar-background{fill:#ff80ab}.mat-progress-bar.mat-accent .mat-progress-bar-buffer{background-color:#ff80ab}.mat-progress-bar.mat-accent .mat-progress-bar-fill::after{background-color:#ff4081}.mat-progress-bar.mat-warn .mat-progress-bar-background{fill:#ffcdd2}.mat-progress-bar.mat-warn .mat-progress-bar-buffer{background-color:#ffcdd2}.mat-progress-bar.mat-warn .mat-progress-bar-fill::after{background-color:#f44336}.mat-progress-spinner circle,.mat-spinner circle{stroke:#3f51b5}.mat-progress-spinner.mat-accent circle,.mat-spinner.mat-accent circle{stroke:#ff4081}.mat-progress-spinner.mat-warn circle,.mat-spinner.mat-warn circle{stroke:#f44336}.mat-radio-outer-circle{border-color:rgba(0,0,0,.54)}.mat-radio-disabled .mat-radio-outer-circle{border-color:rgba(0,0,0,.38)}.mat-radio-disabled .mat-radio-inner-circle,.mat-radio-disabled .mat-radio-ripple .mat-ripple-element{background-color:rgba(0,0,0,.38)}.mat-radio-disabled .mat-radio-label-content{color:rgba(0,0,0,.38)}.mat-radio-button.mat-primary.mat-radio-checked .mat-radio-outer-circle{border-color:#3f51b5}.mat-radio-button.mat-primary .mat-radio-inner-circle{background-color:#3f51b5}.mat-radio-button.mat-primary .mat-radio-ripple .mat-ripple-element{background-color:rgba(63,81,181,.26)}.mat-radio-button.mat-accent.mat-radio-checked .mat-radio-outer-circle{border-color:#ff4081}.mat-radio-button.mat-accent .mat-radio-inner-circle{background-color:#ff4081}.mat-radio-button.mat-accent .mat-radio-ripple .mat-ripple-element{background-color:rgba(255,64,129,.26)}.mat-radio-button.mat-warn.mat-radio-checked .mat-radio-outer-circle{border-color:#f44336}.mat-radio-button.mat-warn .mat-radio-inner-circle{background-color:#f44336}.mat-radio-button.mat-warn .mat-radio-ripple .mat-ripple-element{background-color:rgba(244,67,54,.26)}.mat-select-content,.mat-select-panel-done-animating{background:#fff}.mat-select-value{color:rgba(0,0,0,.87)}.mat-select-placeholder{color:rgba(0,0,0,.42)}.mat-select-disabled .mat-select-value{color:rgba(0,0,0,.38)}.mat-select-arrow{color:rgba(0,0,0,.54)}.mat-select-panel .mat-option.mat-selected:not(.mat-option-multiple){background:rgba(0,0,0,.12)}.mat-form-field.mat-focused.mat-primary .mat-select-arrow{color:#3f51b5}.mat-form-field.mat-focused.mat-accent .mat-select-arrow{color:#ff4081}.mat-form-field .mat-select.mat-select-invalid .mat-select-arrow,.mat-form-field.mat-focused.mat-warn .mat-select-arrow{color:#f44336}.mat-form-field .mat-select.mat-select-disabled .mat-select-arrow{color:rgba(0,0,0,.38)}.mat-drawer-container{background-color:#fafafa;color:rgba(0,0,0,.87)}.mat-drawer{background-color:#fff;color:rgba(0,0,0,.87)}.mat-drawer.mat-drawer-push{background-color:#fff}.mat-drawer-backdrop.mat-drawer-shown{background-color:rgba(0,0,0,.6)}.mat-slide-toggle.mat-checked:not(.mat-disabled) .mat-slide-toggle-thumb{background-color:#e91e63}.mat-slide-toggle.mat-checked:not(.mat-disabled) .mat-slide-toggle-bar{background-color:rgba(233,30,99,.5)}.mat-slide-toggle:not(.mat-checked) .mat-ripple-element{background-color:rgba(0,0,0,.06)}.mat-slide-toggle .mat-ripple-element{background-color:rgba(233,30,99,.12)}.mat-slide-toggle.mat-primary.mat-checked:not(.mat-disabled) .mat-slide-toggle-thumb{background-color:#3f51b5}.mat-slide-toggle.mat-primary.mat-checked:not(.mat-disabled) .mat-slide-toggle-bar{background-color:rgba(63,81,181,.5)}.mat-slide-toggle.mat-primary:not(.mat-checked) .mat-ripple-element{background-color:rgba(0,0,0,.06)}.mat-slide-toggle.mat-primary .mat-ripple-element{background-color:rgba(63,81,181,.12)}.mat-slide-toggle.mat-warn.mat-checked:not(.mat-disabled) .mat-slide-toggle-thumb{background-color:#f44336}.mat-slide-toggle.mat-warn.mat-checked:not(.mat-disabled) .mat-slide-toggle-bar{background-color:rgba(244,67,54,.5)}.mat-slide-toggle.mat-warn:not(.mat-checked) .mat-ripple-element{background-color:rgba(0,0,0,.06)}.mat-slide-toggle.mat-warn .mat-ripple-element{background-color:rgba(244,67,54,.12)}.mat-disabled .mat-slide-toggle-thumb{background-color:#bdbdbd}.mat-disabled .mat-slide-toggle-bar{background-color:rgba(0,0,0,.1)}.mat-slide-toggle-thumb{background-color:#fafafa}.mat-slide-toggle-bar{background-color:rgba(0,0,0,.38)}.mat-slider-track-background{background-color:rgba(0,0,0,.26)}.mat-primary .mat-slider-thumb,.mat-primary .mat-slider-thumb-label,.mat-primary .mat-slider-track-fill{background-color:#3f51b5}.mat-primary .mat-slider-thumb-label-text{color:#fff}.mat-accent .mat-slider-thumb,.mat-accent .mat-slider-thumb-label,.mat-accent .mat-slider-track-fill{background-color:#ff4081}.mat-accent .mat-slider-thumb-label-text{color:#fff}.mat-warn .mat-slider-thumb,.mat-warn .mat-slider-thumb-label,.mat-warn .mat-slider-track-fill{background-color:#f44336}.mat-warn .mat-slider-thumb-label-text{color:#fff}.mat-slider-focus-ring{background-color:rgba(255,64,129,.2)}.cdk-focused .mat-slider-track-background,.mat-slider:hover .mat-slider-track-background{background-color:rgba(0,0,0,.38)}.mat-slider-disabled .mat-slider-thumb,.mat-slider-disabled .mat-slider-track-background,.mat-slider-disabled .mat-slider-track-fill,.mat-slider-disabled:hover .mat-slider-track-background{background-color:rgba(0,0,0,.26)}.mat-slider-min-value .mat-slider-focus-ring{background-color:rgba(0,0,0,.12)}.mat-slider-min-value.mat-slider-thumb-label-showing .mat-slider-thumb,.mat-slider-min-value.mat-slider-thumb-label-showing .mat-slider-thumb-label{background-color:rgba(0,0,0,.87)}.mat-slider-min-value.mat-slider-thumb-label-showing.cdk-focused .mat-slider-thumb,.mat-slider-min-value.mat-slider-thumb-label-showing.cdk-focused .mat-slider-thumb-label{background-color:rgba(0,0,0,.26)}.mat-slider-min-value:not(.mat-slider-thumb-label-showing) .mat-slider-thumb{border-color:rgba(0,0,0,.26);background-color:transparent}.mat-slider-min-value:not(.mat-slider-thumb-label-showing).cdk-focused .mat-slider-thumb,.mat-slider-min-value:not(.mat-slider-thumb-label-showing):hover .mat-slider-thumb{border-color:rgba(0,0,0,.38)}.mat-slider-min-value:not(.mat-slider-thumb-label-showing).cdk-focused.mat-slider-disabled .mat-slider-thumb,.mat-slider-min-value:not(.mat-slider-thumb-label-showing):hover.mat-slider-disabled .mat-slider-thumb{border-color:rgba(0,0,0,.26)}.mat-slider-has-ticks .mat-slider-wrapper::after{border-color:rgba(0,0,0,.7)}.mat-slider-horizontal .mat-slider-ticks{background-image:repeating-linear-gradient(to right,rgba(0,0,0,.7),rgba(0,0,0,.7) 2px,transparent 0,transparent);background-image:-moz-repeating-linear-gradient(.0001deg,rgba(0,0,0,.7),rgba(0,0,0,.7) 2px,transparent 0,transparent)}.mat-slider-vertical .mat-slider-ticks{background-image:repeating-linear-gradient(to bottom,rgba(0,0,0,.7),rgba(0,0,0,.7) 2px,transparent 0,transparent)}.mat-step-header.cdk-keyboard-focused,.mat-step-header.cdk-program-focused,.mat-step-header:hover{background-color:rgba(0,0,0,.04)}.mat-step-header .mat-step-label,.mat-step-header .mat-step-optional{color:rgba(0,0,0,.38)}.mat-step-header .mat-step-icon{background-color:#3f51b5;color:#fff}.mat-step-header .mat-step-icon-not-touched{background-color:rgba(0,0,0,.38);color:#fff}.mat-step-header .mat-step-label.mat-step-label-active{color:rgba(0,0,0,.87)}.mat-stepper-horizontal,.mat-stepper-vertical{background-color:#fff}.mat-stepper-vertical-line::before{border-left-color:rgba(0,0,0,.12)}.mat-stepper-horizontal-line{border-top-color:rgba(0,0,0,.12)}.mat-tab-header,.mat-tab-nav-bar{border-bottom:1px solid rgba(0,0,0,.12)}.mat-tab-group-inverted-header .mat-tab-header,.mat-tab-group-inverted-header .mat-tab-nav-bar{border-top:1px solid rgba(0,0,0,.12);border-bottom:none}.mat-tab-label,.mat-tab-link{color:rgba(0,0,0,.87)}.mat-tab-label.mat-tab-disabled,.mat-tab-link.mat-tab-disabled{color:rgba(0,0,0,.38)}.mat-tab-header-pagination-chevron{border-color:rgba(0,0,0,.87)}.mat-tab-header-pagination-disabled .mat-tab-header-pagination-chevron{border-color:rgba(0,0,0,.38)}.mat-tab-group[class*=mat-background-] .mat-tab-header,.mat-tab-nav-bar[class*=mat-background-]{border-bottom:none;border-top:none}.mat-tab-group.mat-primary .mat-tab-label:not(.mat-tab-disabled):focus,.mat-tab-group.mat-primary .mat-tab-link:not(.mat-tab-disabled):focus,.mat-tab-nav-bar.mat-primary .mat-tab-label:not(.mat-tab-disabled):focus,.mat-tab-nav-bar.mat-primary .mat-tab-link:not(.mat-tab-disabled):focus{background-color:rgba(197,202,233,.3)}.mat-tab-group.mat-primary .mat-ink-bar,.mat-tab-nav-bar.mat-primary .mat-ink-bar{background-color:#3f51b5}.mat-tab-group.mat-primary.mat-background-primary .mat-ink-bar,.mat-tab-nav-bar.mat-primary.mat-background-primary .mat-ink-bar{background-color:#fff}.mat-tab-group.mat-accent .mat-tab-label:not(.mat-tab-disabled):focus,.mat-tab-group.mat-accent .mat-tab-link:not(.mat-tab-disabled):focus,.mat-tab-nav-bar.mat-accent .mat-tab-label:not(.mat-tab-disabled):focus,.mat-tab-nav-bar.mat-accent .mat-tab-link:not(.mat-tab-disabled):focus{background-color:rgba(255,128,171,.3)}.mat-tab-group.mat-accent .mat-ink-bar,.mat-tab-nav-bar.mat-accent .mat-ink-bar{background-color:#ff4081}.mat-tab-group.mat-accent.mat-background-accent .mat-ink-bar,.mat-tab-nav-bar.mat-accent.mat-background-accent .mat-ink-bar{background-color:#fff}.mat-tab-group.mat-warn .mat-tab-label:not(.mat-tab-disabled):focus,.mat-tab-group.mat-warn .mat-tab-link:not(.mat-tab-disabled):focus,.mat-tab-nav-bar.mat-warn .mat-tab-label:not(.mat-tab-disabled):focus,.mat-tab-nav-bar.mat-warn .mat-tab-link:not(.mat-tab-disabled):focus{background-color:rgba(255,205,210,.3)}.mat-tab-group.mat-warn .mat-ink-bar,.mat-tab-nav-bar.mat-warn .mat-ink-bar{background-color:#f44336}.mat-tab-group.mat-warn.mat-background-warn .mat-ink-bar,.mat-tab-nav-bar.mat-warn.mat-background-warn .mat-ink-bar{background-color:#fff}.mat-tab-group.mat-background-primary .mat-tab-label:not(.mat-tab-disabled):focus,.mat-tab-group.mat-background-primary .mat-tab-link:not(.mat-tab-disabled):focus,.mat-tab-nav-bar.mat-background-primary .mat-tab-label:not(.mat-tab-disabled):focus,.mat-tab-nav-bar.mat-background-primary .mat-tab-link:not(.mat-tab-disabled):focus{background-color:rgba(197,202,233,.3)}.mat-tab-group.mat-background-primary .mat-tab-header,.mat-tab-group.mat-background-primary .mat-tab-links,.mat-tab-nav-bar.mat-background-primary .mat-tab-header,.mat-tab-nav-bar.mat-background-primary .mat-tab-links{background-color:#3f51b5}.mat-tab-group.mat-background-primary .mat-tab-label,.mat-tab-group.mat-background-primary .mat-tab-link,.mat-tab-nav-bar.mat-background-primary .mat-tab-label,.mat-tab-nav-bar.mat-background-primary .mat-tab-link{color:#fff}.mat-tab-group.mat-background-primary .mat-tab-label.mat-tab-disabled,.mat-tab-group.mat-background-primary .mat-tab-link.mat-tab-disabled,.mat-tab-nav-bar.mat-background-primary .mat-tab-label.mat-tab-disabled,.mat-tab-nav-bar.mat-background-primary .mat-tab-link.mat-tab-disabled{color:rgba(255,255,255,.4)}.mat-tab-group.mat-background-primary .mat-tab-header-pagination-chevron,.mat-tab-nav-bar.mat-background-primary .mat-tab-header-pagination-chevron{border-color:#fff}.mat-tab-group.mat-background-primary .mat-tab-header-pagination-disabled .mat-tab-header-pagination-chevron,.mat-tab-nav-bar.mat-background-primary .mat-tab-header-pagination-disabled .mat-tab-header-pagination-chevron{border-color:rgba(255,255,255,.4)}.mat-tab-group.mat-background-primary .mat-ripple-element,.mat-tab-nav-bar.mat-background-primary .mat-ripple-element{background-color:rgba(255,255,255,.12)}.mat-tab-group.mat-background-accent .mat-tab-label:not(.mat-tab-disabled):focus,.mat-tab-group.mat-background-accent .mat-tab-link:not(.mat-tab-disabled):focus,.mat-tab-nav-bar.mat-background-accent .mat-tab-label:not(.mat-tab-disabled):focus,.mat-tab-nav-bar.mat-background-accent .mat-tab-link:not(.mat-tab-disabled):focus{background-color:rgba(255,128,171,.3)}.mat-tab-group.mat-background-accent .mat-tab-header,.mat-tab-group.mat-background-accent .mat-tab-links,.mat-tab-nav-bar.mat-background-accent .mat-tab-header,.mat-tab-nav-bar.mat-background-accent .mat-tab-links{background-color:#ff4081}.mat-tab-group.mat-background-accent .mat-tab-label,.mat-tab-group.mat-background-accent .mat-tab-link,.mat-tab-nav-bar.mat-background-accent .mat-tab-label,.mat-tab-nav-bar.mat-background-accent .mat-tab-link{color:#fff}.mat-tab-group.mat-background-accent .mat-tab-label.mat-tab-disabled,.mat-tab-group.mat-background-accent .mat-tab-link.mat-tab-disabled,.mat-tab-nav-bar.mat-background-accent .mat-tab-label.mat-tab-disabled,.mat-tab-nav-bar.mat-background-accent .mat-tab-link.mat-tab-disabled{color:rgba(255,255,255,.4)}.mat-tab-group.mat-background-accent .mat-tab-header-pagination-chevron,.mat-tab-nav-bar.mat-background-accent .mat-tab-header-pagination-chevron{border-color:#fff}.mat-tab-group.mat-background-accent .mat-tab-header-pagination-disabled .mat-tab-header-pagination-chevron,.mat-tab-nav-bar.mat-background-accent .mat-tab-header-pagination-disabled .mat-tab-header-pagination-chevron{border-color:rgba(255,255,255,.4)}.mat-tab-group.mat-background-accent .mat-ripple-element,.mat-tab-nav-bar.mat-background-accent .mat-ripple-element{background-color:rgba(255,255,255,.12)}.mat-tab-group.mat-background-warn .mat-tab-label:not(.mat-tab-disabled):focus,.mat-tab-group.mat-background-warn .mat-tab-link:not(.mat-tab-disabled):focus,.mat-tab-nav-bar.mat-background-warn .mat-tab-label:not(.mat-tab-disabled):focus,.mat-tab-nav-bar.mat-background-warn .mat-tab-link:not(.mat-tab-disabled):focus{background-color:rgba(255,205,210,.3)}.mat-tab-group.mat-background-warn .mat-tab-header,.mat-tab-group.mat-background-warn .mat-tab-links,.mat-tab-nav-bar.mat-background-warn .mat-tab-header,.mat-tab-nav-bar.mat-background-warn .mat-tab-links{background-color:#f44336}.mat-tab-group.mat-background-warn .mat-tab-label,.mat-tab-group.mat-background-warn .mat-tab-link,.mat-tab-nav-bar.mat-background-warn .mat-tab-label,.mat-tab-nav-bar.mat-background-warn .mat-tab-link{color:#fff}.mat-tab-group.mat-background-warn .mat-tab-label.mat-tab-disabled,.mat-tab-group.mat-background-warn .mat-tab-link.mat-tab-disabled,.mat-tab-nav-bar.mat-background-warn .mat-tab-label.mat-tab-disabled,.mat-tab-nav-bar.mat-background-warn .mat-tab-link.mat-tab-disabled{color:rgba(255,255,255,.4)}.mat-tab-group.mat-background-warn .mat-tab-header-pagination-chevron,.mat-tab-nav-bar.mat-background-warn .mat-tab-header-pagination-chevron{border-color:#fff}.mat-tab-group.mat-background-warn .mat-tab-header-pagination-disabled .mat-tab-header-pagination-chevron,.mat-tab-nav-bar.mat-background-warn .mat-tab-header-pagination-disabled .mat-tab-header-pagination-chevron{border-color:rgba(255,255,255,.4)}.mat-tab-group.mat-background-warn .mat-ripple-element,.mat-tab-nav-bar.mat-background-warn .mat-ripple-element{background-color:rgba(255,255,255,.12)}.mat-toolbar{background:#f5f5f5;color:rgba(0,0,0,.87)}.mat-toolbar.mat-primary{background:#3f51b5;color:#fff}.mat-toolbar.mat-accent{background:#ff4081;color:#fff}.mat-toolbar.mat-warn{background:#f44336;color:#fff}.mat-toolbar .mat-focused .mat-form-field-ripple,.mat-toolbar .mat-form-field-ripple,.mat-toolbar .mat-form-field-underline{background-color:currentColor}.mat-toolbar .mat-focused .mat-form-field-label,.mat-toolbar .mat-form-field-label,.mat-toolbar .mat-form-field.mat-focused .mat-select-arrow,.mat-toolbar .mat-select-arrow,.mat-toolbar .mat-select-value{color:inherit}.mat-toolbar .mat-input-element{caret-color:currentColor}.mat-tooltip{background:rgba(97,97,97,.9)}.mat-tree{font-family:Roboto,"Helvetica Neue",sans-serif;background:#fff}.mat-tree-node{font-weight:400;font-size:14px;color:rgba(0,0,0,.87)}.mat-snack-bar-container{background:#323232;color:#fff}.mat-simple-snackbar-action{color:#ff4081}html{height:100%}body{margin:0;font-family:'Open Sans',sans-serif;height:100%}mat-button-toggle-group{box-shadow:none!important;height:inherit}@font-face{font-family:'Material Icons';font-style:normal;font-weight:400;src:url(https://fonts.gstatic.com/s/materialicons/v38/flUhRq6tzZclQEJ-Vdg-IuiaDsNc.woff2) format('woff2')}.material-icons{font-family:'Material Icons';font-weight:400;font-style:normal;font-size:24px;line-height:1;letter-spacing:normal;text-transform:none;display:inline-block;white-space:nowrap;word-wrap:normal;direction:ltr;-webkit-font-feature-settings:'liga';-webkit-font-smoothing:antialiased}
\ No newline at end of file
diff --git a/openvidu-webcomponent/web/openvidu-webcomponent-2.3.0.js b/openvidu-webcomponent/web/openvidu-webcomponent-2.3.0.js
deleted file mode 100644
index d2dad8e58..000000000
--- a/openvidu-webcomponent/web/openvidu-webcomponent-2.3.0.js
+++ /dev/null
@@ -1,4 +0,0 @@
-!function(r){function e(e){for(var t,p,c=e[0],a=e[1],f=e[2],l=0,s=[];l",this._properties=t&&t.properties||{},this._zoneDelegate=new c(this,this._parent&&this._parent._zoneDelegate,t)}return t.assertZonePatched=function(){if(e.Promise!==O.ZoneAwarePromise)throw new Error("Zone.js has detected that ZoneAwarePromise `(window|global).Promise` has been overwritten.\nMost likely cause is that a Promise polyfill has been loaded after Zone.js (Polyfilling Promise api is not necessary when zone.js is loaded. If you must load one, do so before loading zone.js.)")},Object.defineProperty(t,"root",{get:function(){for(var e=t.current;e.parent;)e=e.parent;return e},enumerable:!0,configurable:!0}),Object.defineProperty(t,"current",{get:function(){return D.zone},enumerable:!0,configurable:!0}),Object.defineProperty(t,"currentTask",{get:function(){return j},enumerable:!0,configurable:!0}),t.__load_patch=function(o,i){if(O.hasOwnProperty(o))throw Error("Already loaded patch: "+o);if(!e["__Zone_disable_"+o]){var a="Zone:"+o;n(a),O[o]=i(e,t,S),r(a,a)}},Object.defineProperty(t.prototype,"parent",{get:function(){return this._parent},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"name",{get:function(){return this._name},enumerable:!0,configurable:!0}),t.prototype.get=function(e){var t=this.getZoneWith(e);if(t)return t._properties[e]},t.prototype.getZoneWith=function(e){for(var t=this;t;){if(t._properties.hasOwnProperty(e))return t;t=t._parent}return null},t.prototype.fork=function(e){if(!e)throw new Error("ZoneSpec required!");return this._zoneDelegate.fork(this,e)},t.prototype.wrap=function(e,t){if("function"!=typeof e)throw new Error("Expecting function got: "+e);var n=this._zoneDelegate.intercept(this,e,t),r=this;return function(){return r.runGuarded(n,this,arguments,t)}},t.prototype.run=function(e,t,n,r){void 0===t&&(t=void 0),void 0===n&&(n=null),void 0===r&&(r=null),D={parent:D,zone:this};try{return this._zoneDelegate.invoke(this,e,t,n,r)}finally{D=D.parent}},t.prototype.runGuarded=function(e,t,n,r){void 0===t&&(t=null),void 0===n&&(n=null),void 0===r&&(r=null),D={parent:D,zone:this};try{try{return this._zoneDelegate.invoke(this,e,t,n,r)}catch(e){if(this._zoneDelegate.handleError(this,e))throw e}}finally{D=D.parent}},t.prototype.runTask=function(e,t,n){if(e.zone!=this)throw new Error("A task can only be run in the zone of creation! (Creation: "+(e.zone||g).name+"; Execution: "+this.name+")");if(e.state!==y||e.type!==x){var r=e.state!=k;r&&e._transitionTo(k,m),e.runCount++;var o=j;j=e,D={parent:D,zone:this};try{e.type==E&&e.data&&!e.data.isPeriodic&&(e.cancelFn=null);try{return this._zoneDelegate.invokeTask(this,e,t,n)}catch(e){if(this._zoneDelegate.handleError(this,e))throw e}}finally{e.state!==y&&e.state!==w&&(e.type==x||e.data&&e.data.isPeriodic?r&&e._transitionTo(m,k):(e.runCount=0,this._updateTaskCount(e,-1),r&&e._transitionTo(y,k,y))),D=D.parent,j=o}}},t.prototype.scheduleTask=function(e){if(e.zone&&e.zone!==this)for(var t=this;t;){if(t===e.zone)throw Error("can not reschedule task to "+this.name+" which is descendants of the original zone "+e.zone.name);t=t.parent}e._transitionTo(_,y);var n=[];e._zoneDelegates=n,e._zone=this;try{e=this._zoneDelegate.scheduleTask(this,e)}catch(t){throw e._transitionTo(w,_,y),this._zoneDelegate.handleError(this,t),t}return e._zoneDelegates===n&&this._updateTaskCount(e,1),e.state==_&&e._transitionTo(m,_),e},t.prototype.scheduleMicroTask=function(e,t,n,r){return this.scheduleTask(new u(T,e,t,n,r,null))},t.prototype.scheduleMacroTask=function(e,t,n,r,o){return this.scheduleTask(new u(E,e,t,n,r,o))},t.prototype.scheduleEventTask=function(e,t,n,r,o){return this.scheduleTask(new u(x,e,t,n,r,o))},t.prototype.cancelTask=function(e){if(e.zone!=this)throw new Error("A task can only be cancelled in the zone of creation! (Creation: "+(e.zone||g).name+"; Execution: "+this.name+")");e._transitionTo(b,m,k);try{this._zoneDelegate.cancelTask(this,e)}catch(t){throw e._transitionTo(w,b),this._zoneDelegate.handleError(this,t),t}return this._updateTaskCount(e,-1),e._transitionTo(y,b),e.runCount=0,e},t.prototype._updateTaskCount=function(e,t){var n=e._zoneDelegates;-1==t&&(e._zoneDelegates=null);for(var r=0;r0,macroTask:n.macroTask>0,eventTask:n.eventTask>0,change:e})},e}(),u=function(){function t(n,r,o,i,a,c){this._zone=null,this.runCount=0,this._zoneDelegates=null,this._state="notScheduled",this.type=n,this.source=r,this.data=i,this.scheduleFn=a,this.cancelFn=c,this.callback=o;var u=this;this.invoke=n===x&&i&&i.useG?t.invokeTask:function(){return t.invokeTask.call(e,u,this,arguments)}}return t.invokeTask=function(e,t,n){e||(e=this),Z++;try{return e.runCount++,e.zone.runTask(e,t,n)}finally{1==Z&&d(),Z--}},Object.defineProperty(t.prototype,"zone",{get:function(){return this._zone},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"state",{get:function(){return this._state},enumerable:!0,configurable:!0}),t.prototype.cancelScheduleRequest=function(){this._transitionTo(y,_)},t.prototype._transitionTo=function(e,t,n){if(this._state!==t&&this._state!==n)throw new Error(this.type+" '"+this.source+"': can not transition to '"+e+"', expecting state '"+t+"'"+(n?" or '"+n+"'":"")+", was '"+this._state+"'.");this._state=e,e==y&&(this._zoneDelegates=null)},t.prototype.toString=function(){return this.data&&void 0!==this.data.handleId?this.data.handleId:Object.prototype.toString.call(this)},t.prototype.toJSON=function(){return{type:this.type,state:this.state,source:this.source,zone:this.zone.name,runCount:this.runCount}},t}(),s=z("setTimeout"),l=z("Promise"),f=z("then"),p=[],h=!1;function v(t){0===Z&&0===p.length&&(o||e[l]&&(o=e[l].resolve(0)),o?o[f](d):e[s](d,0)),t&&p.push(t)}function d(){if(!h){for(h=!0;p.length;){var e=p;p=[];for(var t=0;t=0;n--)"function"==typeof e[n]&&(e[n]=p(e[n],t+"_"+n));return e}function b(e){return!e||!1!==e.writable&&!("function"==typeof e.get&&void 0===e.set)}var w="undefined"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope,T=!("nw"in y)&&void 0!==y.process&&"[object process]"==={}.toString.call(y.process),E=!T&&!w&&!(!d||!g.HTMLElement),x=void 0!==y.process&&"[object process]"==={}.toString.call(y.process)&&!w&&!(!d||!g.HTMLElement),O={},S=function(e){if(e=e||y.event){var t=O[e.type];t||(t=O[e.type]=v("ON_PROPERTY"+e.type));var n=(this||e.target||y)[t],r=n&&n.apply(this,arguments);return void 0==r||r||e.preventDefault(),r}};function D(n,r,o){var i=e(n,r);if(!i&&o&&e(o,r)&&(i={enumerable:!0,configurable:!0}),i&&i.configurable){delete i.writable,delete i.value;var a=i.get,c=i.set,u=r.substr(2),s=O[u];s||(s=O[u]=v("ON_PROPERTY"+u)),i.set=function(e){var t=this;t||n!==y||(t=y),t&&(t[s]&&t.removeEventListener(u,S),c&&c.apply(t,m),"function"==typeof e?(t[s]=e,t.addEventListener(u,S,!1)):t[s]=null)},i.get=function(){var e=this;if(e||n!==y||(e=y),!e)return null;var t=e[s];if(t)return t;if(a){var o=a&&a.call(this);if(o)return i.set.call(this,o),"function"==typeof e[_]&&e.removeAttribute(r),o}return null},t(n,r,i)}}function j(e,t,n){if(t)for(var r=0;r1?new c(t,n):new c(t),f=e(l,"onmessage");return f&&!1===f.configurable?(u=r(l),s=l,[i,a,"send","close"].forEach(function(e){u[e]=function(){var t=o.call(arguments);if(e===i||e===a){var n=t.length>0?t[0]:void 0;if(n){var r=Zone.__symbol__("ON_PROPERTY"+n);l[r]=u[r]}}return l[e].apply(l,t)}})):u=l,j(u,["close","error","message","open"],s),u};var u=n.WebSocket;for(var s in c)u[s]=c[s]}(0,u)}}var fe=v("unbound");Zone.__load_patch("util",function(e,t,n){n.patchOnProperties=j,n.patchMethod=z,n.bindArguments=k}),Zone.__load_patch("timers",function(e){K(e,"set","clear","Timeout"),K(e,"set","clear","Interval"),K(e,"set","clear","Immediate")}),Zone.__load_patch("requestAnimationFrame",function(e){K(e,"request","cancel","AnimationFrame"),K(e,"mozRequest","mozCancel","AnimationFrame"),K(e,"webkitRequest","webkitCancel","AnimationFrame")}),Zone.__load_patch("blocking",function(e,t){for(var n=["alert","prompt","confirm"],r=0;r=0&&"function"==typeof n[r.cbIdx]?h(r.name,n[r.cbIdx],r,i,null):e.apply(t,n)}})}()}),Zone.__load_patch("XHR",function(e,t){!function(t){var s=XMLHttpRequest.prototype,l=s[c],f=s[u];if(!l){var p=e.XMLHttpRequestEventTarget;if(p){var v=p.prototype;l=v[c],f=v[u]}}var d="readystatechange",g="scheduled";function y(e){XMLHttpRequest[i]=!1;var t=e.data,r=t.target,a=r[o];l||(l=r[c],f=r[u]),a&&f.call(r,d,a);var s=r[o]=function(){r.readyState===r.DONE&&!t.aborted&&XMLHttpRequest[i]&&e.state===g&&e.invoke()};return l.call(r,d,s),r[n]||(r[n]=e),b.apply(r,t.args),XMLHttpRequest[i]=!0,e}function _(){}function m(e){var t=e.data;return t.aborted=!0,w.apply(t.target,t.args)}var k=z(s,"open",function(){return function(e,t){return e[r]=0==t[2],e[a]=t[1],k.apply(e,t)}}),b=z(s,"send",function(){return function(e,t){return e[r]?b.apply(e,t):h("XMLHttpRequest.send",_,{target:e,url:e[a],isPeriodic:!1,delay:null,args:t,aborted:!1},y,m)}}),w=z(s,"abort",function(){return function(e){var t=e[n];if(t&&"string"==typeof t.type){if(null==t.cancelFn||t.data&&t.data.aborted)return;t.zone.cancelTask(t)}}})}();var n=v("xhrTask"),r=v("xhrSync"),o=v("xhrListener"),i=v("xhrScheduled"),a=v("xhrURL")}),Zone.__load_patch("geolocation",function(t){t.navigator&&t.navigator.geolocation&&function(t,n){for(var r=t.constructor.name,o=function(o){var i=n[o],a=t[i];if(a){if(!b(e(t,i)))return"continue";t[i]=function(e){var t=function(){return e.apply(this,k(arguments,r+"."+i))};return M(t,e),t}(a)}},i=0;i0?arguments[0]:void 0)}},{get:function(e){var t=r.getEntry(o(this,"Map"),e);return t&&t.v},set:function(e,t){return r.def(o(this,"Map"),0===e?0:e,t)}},r,!0)},"9gX7":function(e,t){e.exports=function(e,t,n,r){if(!(e instanceof t)||void 0!==r&&r in e)throw TypeError(n+": incorrect invocation!");return e}},Afnz:function(e,t,n){"use strict";var r=n("LQAc"),o=n("XKFU"),i=n("KroJ"),a=n("Mukb"),c=n("hPIQ"),u=n("QaDb"),s=n("fyDq"),l=n("OP3Y"),f=n("K0xU")("iterator"),p=!([].keys&&"next"in[].keys()),h=function(){return this};e.exports=function(e,t,n,v,d,g,y){u(n,t,v);var _,m,k,b=function(e){if(!p&&e in x)return x[e];switch(e){case"keys":case"values":return function(){return new n(this,e)}}return function(){return new n(this,e)}},w=t+" Iterator",T="values"==d,E=!1,x=e.prototype,O=x[f]||x["@@iterator"]||d&&x[d],S=O||b(d),D=d?T?b("entries"):S:void 0,j="Array"==t&&x.entries||O;if(j&&(k=l(j.call(new e)))!==Object.prototype&&k.next&&(s(k,w,!0),r||"function"==typeof k[f]||a(k,f,h)),T&&O&&"values"!==O.name&&(E=!0,S=function(){return O.call(this)}),r&&!y||!p&&!E&&x[f]||a(x,f,S),c[t]=S,c[w]=h,d)if(_={values:T?S:b("values"),keys:g?S:b("keys"),entries:D},y)for(m in _)m in x||i(x,m,_[m]);else o(o.P+o.F*(p||E),t,_);return _}},BqfV:function(e,t,n){var r=n("N6cJ"),o=n("y3w9"),i=r.get,a=r.key;r.exp({getOwnMetadata:function(e,t){return i(e,o(t),arguments.length<3?void 0:a(arguments[2]))}})},CkkT:function(e,t,n){var r=n("m0Pp"),o=n("Ymqv"),i=n("S/j/"),a=n("ne8i"),c=n("zRwo");e.exports=function(e,t){var n=1==e,u=2==e,s=3==e,l=4==e,f=6==e,p=5==e||f,h=t||c;return function(t,c,v){for(var d,g,y=i(t),_=o(y),m=r(c,v,3),k=a(_.length),b=0,w=n?h(t,k):u?h(t,0):void 0;k>b;b++)if((p||b in _)&&(g=m(d=_[b],b,y),e))if(n)w[b]=g;else if(g)switch(e){case 3:return!0;case 5:return d;case 6:return b;case 2:w.push(d)}else if(l)return!1;return f?-1:s||l?l:w}}},DVgA:function(e,t,n){var r=n("zhAb"),o=n("4R4u");e.exports=Object.keys||function(e){return r(e,o)}},EK0E:function(e,t,n){"use strict";var r,o=n("CkkT")(0),i=n("KroJ"),a=n("Z6vF"),c=n("czNK"),u=n("ZD67"),s=n("0/R4"),l=n("eeVq"),f=n("s5qY"),p=a.getWeak,h=Object.isExtensible,v=u.ufstore,d={},g=function(e){return function(){return e(this,arguments.length>0?arguments[0]:void 0)}},y={get:function(e){if(s(e)){var t=p(e);return!0===t?v(f(this,"WeakMap")).get(e):t?t[this._i]:void 0}},set:function(e,t){return u.def(f(this,"WeakMap"),e,t)}},_=e.exports=n("4LiD")("WeakMap",g,y,u,!0,!0);l(function(){return 7!=(new _).set((Object.freeze||Object)(d),7).get(d)})&&(c((r=u.getConstructor(g,"WeakMap")).prototype,y),a.NEED=!0,o(["delete","has","get","set"],function(e){var t=_.prototype,n=t[e];i(t,e,function(t,o){if(s(t)&&!h(t)){this._f||(this._f=new r);var i=this._f[e](t,o);return"set"==e?this:i}return n.call(this,t,o)})}))},EWmC:function(e,t,n){var r=n("LZWt");e.exports=Array.isArray||function(e){return"Array"==r(e)}},EemH:function(e,t,n){var r=n("UqcF"),o=n("RjD/"),i=n("aCFj"),a=n("apmT"),c=n("aagx"),u=n("xpql"),s=Object.getOwnPropertyDescriptor;t.f=n("nh4g")?s:function(e,t){if(e=i(e),t=a(t,!0),u)try{return s(e,t)}catch(e){}if(c(e,t))return o(!r.f.call(e,t),e[t])}},FJW5:function(e,t,n){var r=n("hswa"),o=n("y3w9"),i=n("DVgA");e.exports=n("nh4g")?Object.defineProperties:function(e,t){o(e);for(var n,a=i(t),c=a.length,u=0;c>u;)r.f(e,n=a[u++],t[n]);return e}},FZcq:function(e,t,n){n("49D4"),n("zq+C"),n("45Tv"),n("uAtd"),n("BqfV"),n("fN/3"),n("iW+S"),n("7Dlh"),n("Opxb"),e.exports=n("g3g5").Reflect},H6hf:function(e,t,n){var r=n("y3w9");e.exports=function(e,t,n,o){try{return o?t(r(n)[0],n[1]):t(n)}catch(t){var i=e.return;throw void 0!==i&&r(i.call(e)),t}}},"I8a+":function(e,t,n){var r=n("LZWt"),o=n("K0xU")("toStringTag"),i="Arguments"==r(function(){return arguments}());e.exports=function(e){var t,n,a;return void 0===e?"Undefined":null===e?"Null":"string"==typeof(n=function(e,t){try{return e[t]}catch(e){}}(t=Object(e),o))?n:i?r(t):"Object"==(a=r(t))&&"function"==typeof t.callee?"Arguments":a}},Iw71:function(e,t,n){var r=n("0/R4"),o=n("dyZX").document,i=r(o)&&r(o.createElement);e.exports=function(e){return i?o.createElement(e):{}}},"J+6e":function(e,t,n){var r=n("I8a+"),o=n("K0xU")("iterator"),i=n("hPIQ");e.exports=n("g3g5").getIteratorMethod=function(e){if(void 0!=e)return e[o]||e["@@iterator"]||i[r(e)]}},JiEa:function(e,t){t.f=Object.getOwnPropertySymbols},K0xU:function(e,t,n){var r=n("VTer")("wks"),o=n("ylqs"),i=n("dyZX").Symbol,a="function"==typeof i;(e.exports=function(e){return r[e]||(r[e]=a&&i[e]||(a?i:o)("Symbol."+e))}).store=r},KroJ:function(e,t,n){var r=n("dyZX"),o=n("Mukb"),i=n("aagx"),a=n("ylqs")("src"),c=Function.toString,u=(""+c).split("toString");n("g3g5").inspectSource=function(e){return c.call(e)},(e.exports=function(e,t,n,c){var s="function"==typeof n;s&&(i(n,"name")||o(n,"name",t)),e[t]!==n&&(s&&(i(n,a)||o(n,a,e[t]?""+e[t]:u.join(String(t)))),e===r?e[t]=n:c?e[t]?e[t]=n:o(e,t,n):(delete e[t],o(e,t,n)))})(Function.prototype,"toString",function(){return"function"==typeof this&&this[a]||c.call(this)})},Kuth:function(e,t,n){var r=n("y3w9"),o=n("FJW5"),i=n("4R4u"),a=n("YTvA")("IE_PROTO"),c=function(){},u=function(){var e,t=n("Iw71")("iframe"),r=i.length;for(t.style.display="none",n("+rLv").appendChild(t),t.src="javascript:",(e=t.contentWindow.document).open(),e.write("